On 27 October 2011 04:08, Kyungmin Park kmpark@infradead.org wrote:
Hi,
exynos4 tmu is already merged 3.2-rc you can find it at below message and latest git kernel http://www.spinics.net/lists/lm-sensors/msg33872.html
Thank you, Kyungmin Park
ok I will rebase my work on top of sensor Thanks for pointing this out.
On Wed, Oct 26, 2011 at 8:36 PM, Amit Daniel Kachhap amit.kachhap@linaro.org wrote:
This patch adds support for thermal sensor driver. It supports 3 trigger level. The first 2 level are warn and monitor temperature level. The third critical trigger level resets the system. The threshold change information is sent to the thermal interface layer.
Signed-off-by: SangWook Ju sw.ju@samsung.com Signed-off-by: Amit Daniel Kachhap amit.kachhap@linaro.org
arch/arm/mach-exynos4/include/mach/exynos4-tmu.h | 75 ++++ drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/thermal_exynos4/sensor/Kconfig | 14 + drivers/staging/thermal_exynos4/sensor/Makefile | 4 + .../thermal_exynos4/sensor/exynos4210_tmu.c | 465 ++++++++++++++++++++ 6 files changed, 561 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-exynos4/include/mach/exynos4-tmu.h create mode 100644 drivers/staging/thermal_exynos4/sensor/Kconfig create mode 100644 drivers/staging/thermal_exynos4/sensor/Makefile create mode 100644 drivers/staging/thermal_exynos4/sensor/exynos4210_tmu.c
diff --git a/arch/arm/mach-exynos4/include/mach/exynos4-tmu.h b/arch/arm/mach-exynos4/include/mach/exynos4-tmu.h new file mode 100644 index 0000000..dc7bf37 --- /dev/null +++ b/arch/arm/mach-exynos4/include/mach/exynos4-tmu.h @@ -0,0 +1,75 @@ +/**
- exynos4-tmu.h - definitions of exynos4 specific thermal interface
- Copyright (C) 2011 Samsung Electronics Co. ltd.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+#ifndef _EXYNOS4_TMU_H +#define _EXYNOS4_TMU_H
+/**
- tmu_data - tmu driver private structure
- @t1: colling stop temperature.
- @dc_temp: Temperature base.
- @init_threshold: Initial threshold temperature.
- @mode: Compensation mode.
- @comp_threshold: compensated threshold temperature.
- */
+struct tmu_data {
- char te1;
- char te2;
- unsigned int init_threshold;
- int mode;
- int cooling;
- unsigned int comp_threshold;
- int tmu_flag;
+};
+/**
- tmu_platform_device - tmu platform specific structure
- @id: Device id.
- @tmu_base: Memory register base.
- @dev: TMU device.
- @data: TMU driver private data structure.
- */
+struct tmu_platform_device {
- int id;
- struct platform_device *pdev;
- void __iomem *tmu_base;
- struct device *dev;
- struct tmu_data data;
- struct thermal_dev *therm_fw;
+};
+#ifdef CONFIG_PM +struct exynos4_tmu_register {
- unsigned int regval_thresh_temp;
- unsigned int regval_trig_lev0;
- unsigned int regval_trig_lev1;
- unsigned int regval_trig_lev2;
- unsigned int regval_trig_lev3;
- unsigned int regval_tmu_con0;
- unsigned int regval_int_en;
+}; +#endif
+extern void exynos4_tmu_set_platdata(struct tmu_data *pd); +extern struct tmu_platform_device *exynos4_tmu_get_platdata(void); +extern int exynos4_tmu_get_irqno(int num); +#endif /* _EXYNOS4_TMU_H */ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 2582e18..4376fed 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -148,4 +148,6 @@ source "drivers/staging/mei/Kconfig"
source "drivers/staging/nvec/Kconfig"
+source "drivers/staging/thermal_exynos4/Kconfig"
endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 50d112f..24a2943 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -65,3 +65,4 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ obj-$(CONFIG_DRM_PSB) += gma500/ obj-$(CONFIG_INTEL_MEI) += mei/ obj-$(CONFIG_MFD_NVEC) += nvec/ +obj-$(CONFIG_SAMSUNG_THERMAL_INTERFACE) += thermal_exynos4/ diff --git a/drivers/staging/thermal_exynos4/sensor/Kconfig b/drivers/staging/thermal_exynos4/sensor/Kconfig new file mode 100644 index 0000000..dcdd04b --- /dev/null +++ b/drivers/staging/thermal_exynos4/sensor/Kconfig @@ -0,0 +1,14 @@ +# +# Thermal Temp sensor configuration +#
+config SENSORS_EXYNOS4_TMU
- tristate "Samsung thermal sensor for exynos platform"
- depends on ARCH_EXYNOS4
- default n
- help
- Say Y here if you want to enable thermal sensor for samsung
- exynos platform.
- This driver can also be built as a module. If so, the module
- will be called exynos4210-tmu.
diff --git a/drivers/staging/thermal_exynos4/sensor/Makefile b/drivers/staging/thermal_exynos4/sensor/Makefile new file mode 100644 index 0000000..4cdb818 --- /dev/null +++ b/drivers/staging/thermal_exynos4/sensor/Makefile @@ -0,0 +1,4 @@ +# +# Makefile for sensor chip drivers. +# +obj-$(CONFIG_SENSORS_EXYNOS4_TMU)+= exynos4210_tmu.o diff --git a/drivers/staging/thermal_exynos4/sensor/exynos4210_tmu.c b/drivers/staging/thermal_exynos4/sensor/exynos4210_tmu.c new file mode 100644 index 0000000..b125379 --- /dev/null +++ b/drivers/staging/thermal_exynos4/sensor/exynos4210_tmu.c @@ -0,0 +1,465 @@ +/**
- exynos4210_tmu.c - exynos4 thermal sensor driver
- Copyright (C) 2011 Samsung Electronics Co. ltd.
- Author: SangWook Ju sw.ju@samsung.com
- Author: Amit Daniel Kachhap amit.kachhap@linaro.org
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+#include <linux/module.h> +#include <linux/fs.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/sysfs.h> +#include <linux/slab.h> +#include <asm/irq.h> +#include <mach/regs-tmu.h> +#include <mach/exynos4-tmu.h> +#include <mach/thermal_interface.h>
+#define INIT_THRESHOLD 80 +/*Monitor temp = INIT_THRESHOLD + TRIGGER_LEV0 = 85*/ +#define TRIGGER_LEV0 5 +/*Warning temp = INIT_THRESHOLD + TRIGGER_LEV1 = 100*/ +#define TRIGGER_LEV1 20 +/*Panic temp = INIT_THRESHOLD + TRIGGER_LEV2 = 110*/ +#define TRIGGER_LEV2 30 +#define TRIGGER_LEV3 0xFF
+#define EFUSE_MIN_VALUE 60 +#define EFUSE_AVG_VALUE 80 +#define EFUSE_MAX_VALUE 100
+#define VREF_SLOPE 0x07000F02 +#define TMU_EN 0x1 +#define TMU_DC_VALUE 25
+enum tmu_status_t {
- TMU_STATUS_NORMAL = 0,
- TMU_STATUS_MONITOR,
- TMU_STATUS_WARNING,
- TMU_STATUS_PANIC,
+};
+static struct resource *exynos4_tmu_mem; +static struct workqueue_struct *tmu_wq; +static struct delayed_work tmu_work;
+#ifdef CONFIG_PM +static struct exynos4_tmu_register tmu_register_save; +#endif
+static int irq_tmu = NO_IRQ; +static struct tmu_platform_device *tmu_dev_t;
+/**
- exynos4_tmu_readb - read a byte value from the given register.
- @tmu_dev: The tmu device structure.
- @reg: Register.
- Read a byte value from the given register.
- */
+static unsigned int exynos4_tmu_readb(struct tmu_platform_device *tmu_dev,
- unsigned int reg)
+{
- return __raw_readb(tmu_dev->tmu_base + reg);
+}
+/**
- exynos4_tmu_writeb - write a byte value to the given register.
- @tmu_dev: The tmu device structure.
- @reg: Register.
- @val: Value to write.
- write a byte value to the given register.
- */
+static void exynos4_tmu_writeb(struct tmu_platform_device *tmu_dev,
- unsigned int reg, unsigned int val)
+{
- __raw_writeb(val, tmu_dev->tmu_base + reg);
+}
+/**
- exynos4_tmu_readl - Read a long value from the given register.
- @tmu_dev: The tmu device structure.
- @reg: Register.
- Read a long value from the given register.
- */
+static unsigned int exynos4_tmu_readl(struct tmu_platform_device *tmu_dev,
- unsigned int reg)
+{
- return __raw_readl(tmu_dev->tmu_base + reg);
+}
+/**
- exynos4_tmu_writel - write a long value to the given register.
- @tmu_dev: The tmu device structure.
- @reg: Register.
- @val: Value to write.
- write a long value to the given register.
- */
+static void exynos4_tmu_writel(struct tmu_platform_device *tmu_dev,
- unsigned int reg, unsigned int val)
+{
- __raw_writel(val, tmu_dev->tmu_base + reg);
+}
+static int exynos4_tmu_current_temp(struct tmu_platform_device *tmu_dev) +{
- int temp;
- temp = exynos4_tmu_readl(tmu_dev, CURRENT_TEMP)
- - tmu_dev->data.te1 + TMU_DC_VALUE;
- return temp;
+}
+/**
- tmu_monitor - Timer handler for monitoring interrupt.
- @work: temp work.
- Timer handler for monitor/warning/panic interrupts.
+*/
+static void tmu_monitor(struct work_struct *work) +{
- exynos4_report_trigger();
- enable_irq(irq_tmu);
+}
+int exynos4_tmu_read_temp(int *temp) +{
- *temp = 0;
- if (tmu_dev_t)
- *temp = exynos4_tmu_readl(tmu_dev_t, CURRENT_TEMP)
- - tmu_dev_t->data.te1 + TMU_DC_VALUE;
- if (*temp > 0)
- return 0;
- else
- return -EINVAL;
+}
+/*
- exynos4_tmu_initialize - Initializes the TMU driver.
- @pdev: The platform device structure.
- Initialises the different registers of the temperature sensor.
- */
+static int exynos4_tmu_initialize(struct platform_device *pdev) +{
- struct tmu_platform_device *tmu_dev = platform_get_drvdata(pdev);
- unsigned int en;
- unsigned int te_temp;
- unsigned int t_new;
- en = (exynos4_tmu_readb(tmu_dev, TMU_STATUS) & 0x1);
- if (!en) {
- dev_err(&pdev->dev, "failed to start tmu drvier\n");
- return -ENOENT;
- }
- /* Temperature compensation */
- te_temp = exynos4_tmu_readl(tmu_dev, TRIMINFO);
- tmu_dev->data.te1 = te_temp & TRIM_TEMP_MASK;
- tmu_dev->data.te2 = ((te_temp >> 8) & TRIM_TEMP_MASK);
- if ((EFUSE_MIN_VALUE > tmu_dev->data.te1) ||
- (tmu_dev->data.te1 > EFUSE_MAX_VALUE) ||
- (tmu_dev->data.te2 != 0))
- tmu_dev->data.te1 = EFUSE_AVG_VALUE;
- t_new = INIT_THRESHOLD + tmu_dev->data.te1 - TMU_DC_VALUE;
- exynos4_tmu_writel(tmu_dev, THRESHOLD_TEMP, t_new);
- /* Need to initialize regsiter setting after getting parameter info */
- /* [28:23] vref [11:8] slope - Tunning parameter */
- exynos4_tmu_writel(tmu_dev, TMU_CON0, VREF_SLOPE);
- exynos4_tmu_writeb(tmu_dev, TRG_LEV0, TRIGGER_LEV0);
- exynos4_tmu_writeb(tmu_dev, TRG_LEV1, TRIGGER_LEV1);
- exynos4_tmu_writeb(tmu_dev, TRG_LEV2, TRIGGER_LEV2);
- exynos4_tmu_writeb(tmu_dev, TRG_LEV3, TRIGGER_LEV3);
- pr_info("TMU is initialized !!\n");
- pr_info("Threshold temp: %dc Monitor temp: %dc\n",
- INIT_THRESHOLD,
- INIT_THRESHOLD + exynos4_tmu_readb(tmu_dev, TRG_LEV0));
- pr_info("Warning temp: %dc Panic temp: %dc\n",
- INIT_THRESHOLD + exynos4_tmu_readb(tmu_dev, TRG_LEV1),
- INIT_THRESHOLD + exynos4_tmu_readb(tmu_dev, TRG_LEV2));
- pr_info("Cooling temp: %dc\n",
- tmu_dev->data.cooling);
+}
+/**
- exynos4_tmu_start - Triggers the TMU driver.
- @pdev: The platform device structure.
- Triggers the temperature sensor.
- */
+static void exynos4_tmu_start(struct platform_device *pdev) +{
- struct tmu_platform_device *tmu_dev = platform_get_drvdata(pdev);
- unsigned int con, cur_temp;
- exynos4_tmu_writel(tmu_dev, INTCLEAR,
- INTCLEAR0|INTCLEAR1|INTCLEAR2|INTCLEAR3);
- /* TMU core enable */
- con = exynos4_tmu_readl(tmu_dev, TMU_CON0);
- con |= TMU_EN;
- exynos4_tmu_writel(tmu_dev, TMU_CON0, con);
- /*LEV0 LEV1 LEV2 interrupt enable */
- exynos4_tmu_writel(tmu_dev, INTEN, (INTEN0|INTEN1|INTEN2));
- usleep_range(200, 1000);
- cur_temp = exynos4_tmu_current_temp(tmu_dev);
- pr_info("Current Temperature : %dc\n\n", cur_temp);
+} +/**
- exynos4_tmu_irq - IRQ handler for tmu interrupt.
- @irq: IRQ line.
- @id: void data pointer for the tmu device.
- IRQ handler for interrupt.
+*/ +static irqreturn_t exynos4_tmu_irq(int irq, void *id) +{
- struct tmu_platform_device *tmu_dev = (struct tmu_platform_device *)id;
- unsigned int status;
- disable_irq_nosync(irq);
- status = __raw_readl(tmu_dev->tmu_base + INTSTAT);
- if (status & INTSTAT0) {
- pr_info("Monitor interrupt occured!!!!\n");
- __raw_writel(INTCLEAR0, tmu_dev->tmu_base + INTCLEAR);
- tmu_dev->data.tmu_flag = TMU_STATUS_MONITOR;
- queue_delayed_work_on(0, tmu_wq, &tmu_work,
- usecs_to_jiffies(10 * 1000));
- } else if (status & INTSTAT1) {
- pr_info("Warning interrupt occured!!!!\n");
- __raw_writel(INTCLEAR1, tmu_dev->tmu_base + INTCLEAR);
- tmu_dev->data.tmu_flag = TMU_STATUS_WARNING;
- queue_delayed_work_on(0, tmu_wq, &tmu_work,
- usecs_to_jiffies(10 * 1000));
- } else if (status & INTSTAT2) {
- pr_info("Panic interrupt occured!!!!\n");
- __raw_writel(INTCLEAR2, tmu_dev->tmu_base + INTCLEAR);
- tmu_dev->data.tmu_flag = TMU_STATUS_PANIC;
- queue_delayed_work_on(0, tmu_wq, &tmu_work,
- usecs_to_jiffies(10 * 1000));
- } else {
- pr_err("%s: TMU interrupt error\n", __func__);
- return -ENODEV;
- }
- return IRQ_HANDLED;
+}
+/**
- exynos4_tmu_probe - device probe entry.
- @pdev: The device being probed.
- */
+static int __devinit exynos4_tmu_probe(struct platform_device *pdev) +{
- struct tmu_platform_device *tmu_dev = platform_get_drvdata(pdev);
- struct resource *res;
- int ret;
- pr_debug("%s: probe=%p\n", __func__, pdev);
- irq_tmu = platform_get_irq(pdev, 0);
- if (irq_tmu < 0) {
- dev_err(&pdev->dev, "no irq for thermal monitor\n");
- return -ENOENT;
- }
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "failed to get memory region resource\n");
- return -ENOENT;
- }
- exynos4_tmu_mem = request_mem_region(res->start,
- res->end-res->start+1,
- pdev->name);
- if (exynos4_tmu_mem == NULL) {
- dev_err(&pdev->dev, "failed to reserve memory region\n");
- ret = -ENOENT;
- goto err_nores;
- }
- tmu_dev->tmu_base = ioremap(res->start, (res->end - res->start) + 1);
- if (tmu_dev->tmu_base == NULL) {
- dev_err(&pdev->dev, "failed ioremap()\n");
- ret = -EINVAL;
- goto err_nomap;
- }
- tmu_dev->pdev = pdev;
- tmu_dev->dev = &pdev->dev;
- ret = request_irq(irq_tmu, exynos4_tmu_irq,
- IRQF_DISABLED, "exynos4-tmu ", tmu_dev);
- if (ret) {
- dev_err(&pdev->dev, "IRQ%d error %d\n", irq_tmu, ret);
- goto err_irq;
- }
- tmu_dev_t = tmu_dev;
- exynos4_tmu_initialize(pdev);
- if (ret)
- goto err_nores;
- exynos4_tmu_start(pdev);
- exynos4_read_sensor = exynos4_tmu_read_temp;
- return 0;
+err_irq:
- iounmap(tmu_dev->tmu_base);
+err_nomap:
- release_resource(exynos4_tmu_mem);
+err_nores:
- return ret;
+}
+/**
- exynos4_tmu_remove - device remove entry.
- @pdev: The device being removed.
- */
+static int __devinit exynos4_tmu_remove(struct platform_device *pdev) +{
- struct tmu_platform_device *tmu_dev = platform_get_drvdata(pdev);
- free_irq(irq_tmu, tmu_dev);
- iounmap(tmu_dev->tmu_base);
- release_resource(exynos4_tmu_mem);
- return 0;
+}
+#ifdef CONFIG_PM +/**
- exynos4_tmu_suspend - device suspend function.
- @pdev: The device being suspended.
- @state: suspend event message.
- */
+static int exynos4_tmu_suspend(struct platform_device *pdev, pm_message_t state) +{
- struct tmu_platform_device *tmu_dev = platform_get_drvdata(pdev);
- tmu_register_save.regval_thresh_temp =
- exynos4_tmu_readb(tmu_dev, THRESHOLD_TEMP);
- tmu_register_save.regval_trig_lev0 =
- exynos4_tmu_readb(tmu_dev, TRG_LEV0);
- tmu_register_save.regval_trig_lev1 =
- exynos4_tmu_readb(tmu_dev, TRG_LEV1);
- tmu_register_save.regval_trig_lev2 =
- exynos4_tmu_readb(tmu_dev, TRG_LEV2);
- tmu_register_save.regval_trig_lev3 =
- exynos4_tmu_readb(tmu_dev, TRG_LEV3);
- tmu_register_save.regval_tmu_con0 =
- exynos4_tmu_readl(tmu_dev, TMU_CON0);
- tmu_register_save.regval_int_en =
- exynos4_tmu_readl(tmu_dev, INTEN);
- return 0;
+}
+/**
- exynos4_tmu_resume - device resume function.
- @pdev: The device being suspended.
- */
+static int exynos4_tmu_resume(struct platform_device *pdev) +{
- struct tmu_platform_device *tmu_dev = platform_get_drvdata(pdev);
- exynos4_tmu_writeb(tmu_dev, THRESHOLD_TEMP,
- tmu_register_save.regval_thresh_temp);
- exynos4_tmu_writeb(tmu_dev, TRG_LEV0,
- tmu_register_save.regval_trig_lev0);
- exynos4_tmu_writeb(tmu_dev, TRG_LEV1,
- tmu_register_save.regval_trig_lev1);
- exynos4_tmu_writeb(tmu_dev, TRG_LEV2,
- tmu_register_save.regval_trig_lev2);
- exynos4_tmu_writeb(tmu_dev, TRG_LEV3,
- tmu_register_save.regval_trig_lev3);
- exynos4_tmu_writeb(tmu_dev, TMU_CON0,
- tmu_register_save.regval_tmu_con0);
- exynos4_tmu_writel(tmu_dev, INTEN,
- tmu_register_save.regval_int_en);
- exynos4_tmu_writel(tmu_dev, INTCLEAR,
- INTCLEAR0|INTCLEAR1|INTCLEAR2|INTCLEAR3);
- return 0;
+}
+#else +#define exynos4_tmu_suspend NULL +#define exynos4_tmu_resume NULL +#endif
+static struct platform_driver exynos4_tmu_driver = {
- .probe = exynos4_tmu_probe,
- .remove = exynos4_tmu_remove,
- .suspend = exynos4_tmu_suspend,
- .resume = exynos4_tmu_resume,
- .driver = {
- .name = "exynos4-tmu",
- .owner = THIS_MODULE,
- },
+};
+static int __init exynos4_tmu_driver_init(void) +{
- int ret = 0;
- pr_info("EXYNOS4 TMU driver is loaded.\n");
- tmu_wq = create_workqueue("tmu");
- if (!tmu_wq) {
- pr_err(" creation of tmu failed\n");
- ret = -EFAULT;
- goto out;
- }
- INIT_DELAYED_WORK_DEFERRABLE(&tmu_work, tmu_monitor);
- ret = platform_driver_register(&exynos4_tmu_driver);
- if (ret) {
- pr_err("registeration of tmu_driver failed\n");
- destroy_workqueue(tmu_wq);
- goto out;
- }
+out:
- return ret;
+}
+static void __exit exynos4_tmu_driver_exit(void) +{
- destroy_workqueue(tmu_wq);
- platform_driver_unregister(&exynos4_tmu_driver);
+}
+module_init(exynos4_tmu_driver_init); +module_exit(exynos4_tmu_driver_exit);
+MODULE_AUTHOR("Samsung Electronics"); +MODULE_DESCRIPTION("EXYNOS4 temperature sensor driver"); +MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:exynos4-tmu");
1.7.1
linaro-dev mailing list linaro-dev@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-dev