/*
 * OMAP4 system control module driver file
 *
 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
 * Author: J Keerthy <j-keerthy@ti.com>
 * Author: Moiz Sonasath <m-sonasath@ti.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <plat/omap_device.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/err.h>
#include <linux/types.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/reboot.h>
#include <plat/scm.h>
#include <linux/mfd/omap4_scm.h>
#include <linux/thermal_freq.h>
#include <linux/thermal_framework.h>

u32 omap4plus_scm_readl(struct scm *scm_ptr, u32 reg)
{
	return __raw_readl(scm_ptr->base + reg);
}
EXPORT_SYMBOL_GPL(omap4plus_scm_readl);

void omap4plus_scm_writel(struct scm *scm_ptr, u32 val, u32 reg)
{
	__raw_writel(val, scm_ptr->base + reg);
}
EXPORT_SYMBOL_GPL(omap4plus_scm_writel);


void omap4plus_scm_client_register(struct temp_sensor_hwmon *tsh_ptr,
					  int i, const char *name)
{
	int ret;

	tsh_ptr->pdev = platform_device_alloc(name, i);
	if (tsh_ptr->pdev == NULL) {
		dev_err(tsh_ptr->scm_ptr->dev, "Failed to allocate %s\n", name);
		return;
	}

	tsh_ptr->pdev->dev.parent = tsh_ptr->scm_ptr->dev;
	platform_set_drvdata(tsh_ptr->pdev, tsh_ptr);
	ret = platform_device_add(tsh_ptr->pdev);
	if (ret != 0) {
		dev_err(tsh_ptr->scm_ptr->dev, "Failed to register %s: %d\n",
			name, ret);
		platform_device_put(tsh_ptr->pdev);
		tsh_ptr->pdev = NULL;
	}
}

static irqreturn_t talert_irq_handler(int irq, void *data)
{
	struct scm *scm_ptr;
	int t_hot = 0, t_cold, temp, i;
	struct omap4460plus_temp_sensor_registers *tsr;

	scm_ptr = data;
	/* Read the status of t_hot */
	for (i = 0; i < scm_ptr->cnt; i++) {
		tsr = scm_ptr->registers[i];
		t_hot = omap4plus_scm_readl(scm_ptr, tsr->bgap_status)
		    & tsr->status_hot_mask;

		/* Read the status of t_cold */
		t_cold = omap4plus_scm_readl(scm_ptr, tsr->bgap_status)
		    & tsr->status_cold_mask;

		temp = omap4plus_scm_readl(scm_ptr, tsr->bgap_mask_ctrl);
		/*
		 * One TALERT interrupt: Two sources
		 * If the interrupt is due to t_hot then mask t_hot and
		 * and unmask t_cold else mask t_cold and unmask t_hot
		 */
		if (t_hot) {
			temp &= ~tsr->mask_hot_mask;
			temp |= tsr->mask_cold_mask;
		} else if (t_cold) {
			temp &= ~tsr->mask_cold_mask;
			temp |= tsr->mask_hot_mask;
		}

		mutex_lock(&scm_ptr->scm_mutex);
		omap4plus_scm_writel(scm_ptr, temp, tsr->bgap_mask_ctrl);
		mutex_unlock(&scm_ptr->scm_mutex);

		/* read temperature */
		temp = omap4plus_scm_readl(scm_ptr, tsr->temp_sensor_ctrl);
		temp &= tsr->bgap_dtemp_mask;

#if defined(CONFIG_THERMAL_FRAMEWORK)
		if (t_hot || t_cold) {
			/* kobject_uvent to user space threshold crossed */
			scm_ptr->therm_fw[i]->current_temp =
				adc_to_temp_conversion(scm_ptr, i, temp);
			thermal_sensor_set_temp(scm_ptr->therm_fw[i]);
			kobject_uevent(&scm_ptr->tsh_ptr[i].pdev->dev.kobj,
						KOBJ_CHANGE);
		}
#elif defined(CONFIG_THERMAL)
		scm_ptr->therm_fq->tdev->last_temperature = temp;
#endif
	}

	return IRQ_HANDLED;
}

static irqreturn_t omap4460_tshut_irq_handler(int irq, void *data)
{
	kernel_restart(NULL);

	return IRQ_HANDLED;
}

static int __devinit omap4plus_scm_probe(struct platform_device *pdev)
{
	struct omap4plus_scm_pdata *pdata = pdev->dev.platform_data;
	struct scm *scm_ptr;
	struct resource *mem;
	int ret = 0, i;

	if (!pdata) {
		dev_err(&pdev->dev, "platform data missing\n");
		return -EINVAL;
	}

	scm_ptr = kzalloc(sizeof(*scm_ptr), GFP_KERNEL);
	if (!scm_ptr) {
		dev_err(&pdev->dev, "Memory allocation failed\n");
		return -ENOMEM;
	}

	scm_ptr->tsh_ptr = kzalloc(sizeof(*scm_ptr->tsh_ptr) * pdata->cnt,
					GFP_KERNEL);
	if (!scm_ptr) {
		dev_err(&pdev->dev, "Memory allocation failed for tsh\n");
		kfree(scm_ptr);
		return -ENOMEM;
	}

	mutex_init(&scm_ptr->scm_mutex);
	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mem) {
		dev_err(&pdev->dev, "no mem resource\n");
		ret = -ENOMEM;
		goto plat_res_err;
	}

	scm_ptr->irq = platform_get_irq_byname(pdev, "thermal_alert");
	if (scm_ptr->irq < 0) {
		dev_err(&pdev->dev, "get_irq_byname failed\n");
		ret = scm_ptr->irq;
		goto plat_res_err;
	}

	scm_ptr->base = ioremap(mem->start, resource_size(mem));
	if (!scm_ptr->base) {
		dev_err(&pdev->dev, "ioremap failed\n");
		ret = -ENOMEM;
		goto plat_res_err;
	}
	scm_ptr->cnt = pdata->cnt;
	scm_ptr->rev = pdata->rev;
	scm_ptr->accurate = pdata->accurate;

	scm_ptr->dev = &pdev->dev;

	dev_set_drvdata(&pdev->dev, scm_ptr);
	scm_ptr->fclock = clk_get(&pdev->dev, "fck");
	scm_ptr->div_clk = clk_get(&pdev->dev, "div_ck");

/* Initialize temperature sensors */
	if (scm_ptr->rev == 1 && pdata->accurate) {
		ret = omap4460plus_temp_sensor_init(scm_ptr);
		if (ret)
			goto clken_err;

		ret = omap4460_tshut_init(scm_ptr);

		for (i = 0; i < pdata->cnt; i++) {
			scm_ptr->tsh_ptr[i].scm_ptr = scm_ptr;
			omap4plus_scm_client_register(&(scm_ptr->tsh_ptr[i]),
						i, "temp_sensor_hwmon");
		}

		ret = request_threaded_irq(scm_ptr->irq, NULL,
			   talert_irq_handler,
			   IRQF_TRIGGER_RISING | IRQF_ONESHOT, "TAlert",
			   scm_ptr);
		if (ret) {
			dev_err(&pdev->dev, "Request threaded irq failed.\n");
			goto req_irq_err;
		}

		ret = request_threaded_irq(gpio_to_irq(86), NULL,
						omap4460_tshut_irq_handler,
					IRQF_TRIGGER_RISING, "tshut", NULL);
		if (ret) {
			gpio_free(86);
			pr_err("request irq failed for TSHUT");
			return ret;
		}

		mutex_lock(&scm_ptr->scm_mutex);

		for (i = 0; i < pdata->cnt; i++)
			temp_sensor_unmask_interrupts(scm_ptr, i,
					scm_ptr->ts_data[i]->adc_end_val,
					scm_ptr->ts_data[i]->adc_start_val);

		mutex_unlock(&scm_ptr->scm_mutex);

		return ret;
req_irq_err:
		omap4460plus_temp_sensor_deinit(scm_ptr);
	}

clken_err:
	clk_put(scm_ptr->fclock);
	clk_put(scm_ptr->div_clk);
	iounmap(scm_ptr->base);
plat_res_err:
	dev_set_drvdata(&pdev->dev, NULL);
	mutex_destroy(&scm_ptr->scm_mutex);
	kfree(scm_ptr->tsh_ptr);
	kfree(scm_ptr);

	return ret;
}

static int __devexit omap4plus_scm_remove(struct platform_device *pdev)
{
	struct scm *scm_ptr = platform_get_drvdata(pdev);

	free_irq(scm_ptr->irq, scm_ptr);
	clk_disable(scm_ptr->fclock);
	clk_put(scm_ptr->fclock);
	clk_put(scm_ptr->div_clk);
	iounmap(scm_ptr->base);
	dev_set_drvdata(&pdev->dev, NULL);
	mutex_destroy(&scm_ptr->scm_mutex);
	kfree(scm_ptr);

	return 0;
}

static struct platform_driver omap4plus_scm_driver = {
	.probe = omap4plus_scm_probe,
	.remove = omap4plus_scm_remove,
	.driver = {
		   .name = "omap4plus_scm",
		   },
};

int __init omap4plus_scm_init(void)
{
	return platform_driver_register(&omap4plus_scm_driver);
}

module_init(omap4plus_scm_init);

static void __exit omap4plus_scm_exit(void)
{
	platform_driver_unregister(&omap4plus_scm_driver);
}

module_exit(omap4plus_scm_exit);

MODULE_DESCRIPTION("OMAP4 plus system control module Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRIVER_NAME);
MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
