All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440
@ 2013-05-07 13:00 Amit Daniel Kachhap
  2013-05-07 13:00 ` [PATCH V3 01/21] thermal: exynos: Moving exynos thermal files into samsung directory Amit Daniel Kachhap
                   ` (20 more replies)
  0 siblings, 21 replies; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:00 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

Changes in V3:
* Added proper dependency of different exynos thermal Kconfig symbols. Basically 3
 Kconfig can be enabled now and corresponds to tmu driver. exynos common part
 and exynos configuration data. This issue was raised by Rui Zhang.

Changes in V2:
* Separated SOC data from TMU driver. This is as per suggestion from Eduardo.
* Merged the new file created for exynos5440 TMU controller with the existing
 TMU controller code.
* Removed the DT parsing code as now the SOC specific data are cleanly put
 inside the data specific file.
* Even the register definations/bitfields are treated as data as there is
 some variation across SOC's.

This patchset adds TMU(Thermal management Unit) driver support for
exynos5440 platform. There are 3 instances of the TMU controllers so
necessary cleanup/re-structure is done to handle multiple thermal zone.

Patch (exynos4: Add documentation for Exynos SoC thermal bindings) from
Lukasz Majewski is already posted to mainline. Adding it here for completeness.
(http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg17817.html)

Patch (thermal: exynos: Support thermal tripping ) from Jonghwan Choi is
added here with some changes.
(https://patchwork.kernel.org/patch/1668371/)

Patch (thermal: exynos: Support for TMU regulator defined at device tree)
is a repost of my earlier patch(https://patchwork-mail1.kernel.org/patch/2510771/) 
and adds regulator support.

Patch (ARM: dts: Add device tree node for exynos5440 TMU controller) can be
merged through exynos platform maintainer as this can cause merge conflict.

All these patches are based on thermal maintainers git tree,
git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git next.

Amit Daniel Kachhap (20):
  thermal: exynos: Moving exynos thermal files into samsung directory
  thermal: exynos: Bifurcate exynos thermal common and tmu controller
    code
  thermal: exynos: Rename exynos_thermal.c to exynos_tmu.c
  thermal: exynos: Move exynos_thermal.h from include/* to driver/*
    folder
  thermal: exynos: Bifurcate exynos tmu driver and configuration data
  thermal: exynos: Add missing definations and code cleanup
  thermal: exynos: Add extra entries in the tmu platform data
  thermal: exynos: Support thermal tripping
  thermal: exynos: Move register definitions from driver file to data
    file
  thermal: exynos: Fix to clear only the generated interrupts
  thermal: exynos: Add support for instance based register/unregister
  thermal: exynos: Modify private_data to appropriate name driver_data
  thermal: exynos: Return success even if no cooling data supplied
  thermal: exynos: Make the zone handling dependent on trip count
  thermal: exynos: Add support to handle many instances of TMU
  thermal: exynos: Add features to check instead of using SOC type
  thermal: exynos: Add support for exynos5440 TMU sensor.
  Documentation: thermal: Explain the exynos thermal driver model
  thermal: exynos: Support for TMU regulator defined at device tree
  ARM: dts: Add device tree node for exynos5440 TMU controller

Lukasz Majewski (1):
  ARM: dts: thermal: exynos4: Add documentation for Exynos SoC thermal
    bindings

 .../devicetree/bindings/thermal/exynos-thermal.txt |   53 +
 Documentation/thermal/exynos_thermal               |   43 +-
 arch/arm/boot/dts/exynos5440.dtsi                  |   30 +
 drivers/thermal/Kconfig                            |   13 +-
 drivers/thermal/Makefile                           |    2 +-
 drivers/thermal/exynos_thermal.c                   | 1066 --------------------
 drivers/thermal/samsung/Kconfig                    |   28 +
 drivers/thermal/samsung/Makefile                   |    7 +
 drivers/thermal/samsung/exynos_thermal_common.c    |  401 ++++++++
 drivers/thermal/samsung/exynos_thermal_common.h    |   96 ++
 drivers/thermal/samsung/exynos_tmu.c               |  738 ++++++++++++++
 drivers/thermal/samsung/exynos_tmu.h               |  225 ++++
 drivers/thermal/samsung/exynos_tmu_data.c          |  224 ++++
 drivers/thermal/samsung/exynos_tmu_data.h          |  149 +++
 include/linux/platform_data/exynos_thermal.h       |  119 ---
 15 files changed, 1991 insertions(+), 1203 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/exynos-thermal.txt
 delete mode 100644 drivers/thermal/exynos_thermal.c
 create mode 100644 drivers/thermal/samsung/Kconfig
 create mode 100644 drivers/thermal/samsung/Makefile
 create mode 100644 drivers/thermal/samsung/exynos_thermal_common.c
 create mode 100644 drivers/thermal/samsung/exynos_thermal_common.h
 create mode 100644 drivers/thermal/samsung/exynos_tmu.c
 create mode 100644 drivers/thermal/samsung/exynos_tmu.h
 create mode 100644 drivers/thermal/samsung/exynos_tmu_data.c
 create mode 100644 drivers/thermal/samsung/exynos_tmu_data.h
 delete mode 100644 include/linux/platform_data/exynos_thermal.h


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH V3 01/21] thermal: exynos: Moving exynos thermal files into samsung directory
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
@ 2013-05-07 13:00 ` Amit Daniel Kachhap
  2013-05-07 13:07   ` [RESEND PATCH " Amit Daniel Kachhap
  2013-05-07 13:00 ` [PATCH V3 02/21] thermal: exynos: Bifurcate exynos thermal common and tmu controller code Amit Daniel Kachhap
                   ` (19 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:00 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This movement of files is done for easy maintenance and adding more
new sensor's support for exynos platform easily . This will also help in
bifurcating exynos common, sensor driver and sensor data related parts.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/Kconfig                        |   13 +++++--------
 drivers/thermal/Makefile                       |    2 +-
 drivers/thermal/samsung/Kconfig                |    9 +++++++++
 drivers/thermal/samsung/Makefile               |    4 ++++
 drivers/thermal/{ => samsung}/exynos_thermal.c |    0
 5 files changed, 19 insertions(+), 9 deletions(-)
 create mode 100644 drivers/thermal/samsung/Kconfig
 create mode 100644 drivers/thermal/samsung/Makefile
 rename drivers/thermal/{ => samsung}/exynos_thermal.c (100%)

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 5e3c025..081ddc5 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -114,14 +114,6 @@ config KIRKWOOD_THERMAL
 	  Support for the Kirkwood thermal sensor driver into the Linux thermal
 	  framework. Only kirkwood 88F6282 and 88F6283 have this sensor.
 
-config EXYNOS_THERMAL
-	tristate "Temperature sensor on Samsung EXYNOS"
-	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
-	depends on CPU_THERMAL
-	help
-	  If you say yes here you get support for TMU (Thermal Management
-	  Unit) on SAMSUNG EXYNOS series of SoC.
-
 config DOVE_THERMAL
 	tristate "Temperature sensor on Marvell Dove SoCs"
 	depends on ARCH_DOVE
@@ -169,4 +161,9 @@ config INTEL_POWERCLAMP
 	  enforce idle time which results in more package C-state residency. The
 	  user interface is exposed via generic thermal framework.
 
+menu "Exynos thermal drivers"
+depends on PLAT_SAMSUNG
+source "drivers/thermal/samsung/Kconfig"
+endmenu
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index c054d41..b3063a9 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -17,7 +17,7 @@ thermal_sys-$(CONFIG_CPU_THERMAL)	+= cpu_cooling.o
 obj-$(CONFIG_SPEAR_THERMAL)	+= spear_thermal.o
 obj-$(CONFIG_RCAR_THERMAL)	+= rcar_thermal.o
 obj-$(CONFIG_KIRKWOOD_THERMAL)  += kirkwood_thermal.o
-obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
+obj-y				+= samsung/
 obj-$(CONFIG_DOVE_THERMAL)  	+= dove_thermal.o
 obj-$(CONFIG_DB8500_THERMAL)	+= db8500_thermal.o
 obj-$(CONFIG_ARMADA_THERMAL)	+= armada_thermal.o
diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
new file mode 100644
index 0000000..2d3d9dc
--- /dev/null
+++ b/drivers/thermal/samsung/Kconfig
@@ -0,0 +1,9 @@
+config EXYNOS_THERMAL
+	tristate "Temperature sensor on Samsung EXYNOS"
+	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
+	depends on CPU_THERMAL
+	help
+	  If you say yes here you get support for TMU (Thermal Management
+	  Unit) on SAMSUNG EXYNOS series of SoC. This helps in registering
+	  the exynos thermal driver with the core thermal layer and cpu
+	  cooling API's.
diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
new file mode 100644
index 0000000..1fe6d93
--- /dev/null
+++ b/drivers/thermal/samsung/Makefile
@@ -0,0 +1,4 @@
+#
+# Samsung thermal specific Makefile
+#
+obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/samsung/exynos_thermal.c
similarity index 100%
rename from drivers/thermal/exynos_thermal.c
rename to drivers/thermal/samsung/exynos_thermal.c
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 02/21] thermal: exynos: Bifurcate exynos thermal common and tmu controller code
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
  2013-05-07 13:00 ` [PATCH V3 01/21] thermal: exynos: Moving exynos thermal files into samsung directory Amit Daniel Kachhap
@ 2013-05-07 13:00 ` Amit Daniel Kachhap
  2013-05-07 13:41   ` Zhang Rui
  2013-05-08 16:01     ` Eduardo Valentin
  2013-05-07 13:00 ` [PATCH V3 03/21] thermal: exynos: Rename exynos_thermal.c to exynos_tmu.c Amit Daniel Kachhap
                   ` (18 subsequent siblings)
  20 siblings, 2 replies; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:00 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This code bifurcates exynos thermal implementation into common and sensor
specific parts. The common thermal code interacts with core thermal layer and
core cpufreq cooling parts and is independent of SOC specific driver. This
change is needed to cleanly add support for new TMU sensors.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/Kconfig                 |   20 +-
 drivers/thermal/samsung/Makefile                |    4 +-
 drivers/thermal/samsung/exynos_thermal.c        |  421 +----------------------
 drivers/thermal/samsung/exynos_thermal_common.c |  389 +++++++++++++++++++++
 drivers/thermal/samsung/exynos_thermal_common.h |   83 +++++
 5 files changed, 498 insertions(+), 419 deletions(-)
 create mode 100644 drivers/thermal/samsung/exynos_thermal_common.c
 create mode 100644 drivers/thermal/samsung/exynos_thermal_common.h

diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
index 2d3d9dc..7857e20 100644
--- a/drivers/thermal/samsung/Kconfig
+++ b/drivers/thermal/samsung/Kconfig
@@ -1,9 +1,17 @@
 config EXYNOS_THERMAL
-	tristate "Temperature sensor on Samsung EXYNOS"
+	tristate "Exynos thermal management unit driver"
 	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
-	depends on CPU_THERMAL
 	help
-	  If you say yes here you get support for TMU (Thermal Management
-	  Unit) on SAMSUNG EXYNOS series of SoC. This helps in registering
-	  the exynos thermal driver with the core thermal layer and cpu
-	  cooling API's.
+	  If you say yes here you get support for the exynos thermal driver
+	  for exynos4 and exynos5 soc. This driver initialises the TMU, reports
+	  temperature and handles cooling action if defined. This driver uses
+	  core thermal API's.
+
+config EXYNOS_THERMAL_CORE
+	bool "Core thermal framework support for EXYNOS SOC's"
+	depends on EXYNOS_THERMAL
+	help
+	  If you say yes here you get support for EXYNOS TMU
+	  (Thermal Management Unit) common registration/unregistration
+	  functions to the core thermal layer and also to use the generic
+	  cpu cooling API's.
diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
index 1fe6d93..6227d4f 100644
--- a/drivers/thermal/samsung/Makefile
+++ b/drivers/thermal/samsung/Makefile
@@ -1,4 +1,6 @@
 #
 # Samsung thermal specific Makefile
 #
-obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
+obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_soc_thermal.o
+exynos_soc_thermal-y				:= exynos_thermal.o
+exynos_soc_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
diff --git a/drivers/thermal/samsung/exynos_thermal.c b/drivers/thermal/samsung/exynos_thermal.c
index d20ce9e..4c85945 100644
--- a/drivers/thermal/samsung/exynos_thermal.c
+++ b/drivers/thermal/samsung/exynos_thermal.c
@@ -21,23 +21,19 @@
  *
  */
 
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
 #include <linux/clk.h>
-#include <linux/workqueue.h>
-#include <linux/sysfs.h>
-#include <linux/kobject.h>
 #include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/platform_data/exynos_thermal.h>
-#include <linux/thermal.h>
-#include <linux/cpufreq.h>
-#include <linux/cpu_cooling.h>
 #include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/exynos_thermal.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include "exynos_thermal_common.h"
 
 /* Exynos generic registers */
 #define EXYNOS_TMU_REG_TRIMINFO		0x0
@@ -88,16 +84,6 @@
 #define EFUSE_MIN_VALUE 40
 #define EFUSE_MAX_VALUE 100
 
-/* In-kernel thermal framework related macros & definations */
-#define SENSOR_NAME_LEN	16
-#define MAX_TRIP_COUNT	8
-#define MAX_COOLING_DEVICE 4
-#define MAX_THRESHOLD_LEVS 4
-
-#define ACTIVE_INTERVAL 500
-#define IDLE_INTERVAL 10000
-#define MCELSIUS	1000
-
 #ifdef CONFIG_THERMAL_EMULATION
 #define EXYNOS_EMUL_TIME	0x57F0
 #define EXYNOS_EMUL_TIME_SHIFT	16
@@ -106,17 +92,6 @@
 #define EXYNOS_EMUL_ENABLE	0x1
 #endif /* CONFIG_THERMAL_EMULATION */
 
-/* CPU Zone information */
-#define PANIC_ZONE      4
-#define WARN_ZONE       3
-#define MONITOR_ZONE    2
-#define SAFE_ZONE       1
-
-#define GET_ZONE(trip) (trip + 2)
-#define GET_TRIP(zone) (zone - 2)
-
-#define EXYNOS_ZONE_COUNT	3
-
 struct exynos_tmu_data {
 	struct exynos_tmu_platform_data *pdata;
 	struct resource *mem;
@@ -129,384 +104,6 @@ struct exynos_tmu_data {
 	u8 temp_error1, temp_error2;
 };
 
-struct	thermal_trip_point_conf {
-	int trip_val[MAX_TRIP_COUNT];
-	int trip_count;
-	u8 trigger_falling;
-};
-
-struct	thermal_cooling_conf {
-	struct freq_clip_table freq_data[MAX_TRIP_COUNT];
-	int freq_clip_count;
-};
-
-struct thermal_sensor_conf {
-	char name[SENSOR_NAME_LEN];
-	int (*read_temperature)(void *data);
-	int (*write_emul_temp)(void *drv_data, unsigned long temp);
-	struct thermal_trip_point_conf trip_data;
-	struct thermal_cooling_conf cooling_data;
-	void *private_data;
-};
-
-struct exynos_thermal_zone {
-	enum thermal_device_mode mode;
-	struct thermal_zone_device *therm_dev;
-	struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
-	unsigned int cool_dev_size;
-	struct platform_device *exynos4_dev;
-	struct thermal_sensor_conf *sensor_conf;
-	bool bind;
-};
-
-static struct exynos_thermal_zone *th_zone;
-static void exynos_unregister_thermal(void);
-static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
-
-/* Get mode callback functions for thermal zone */
-static int exynos_get_mode(struct thermal_zone_device *thermal,
-			enum thermal_device_mode *mode)
-{
-	if (th_zone)
-		*mode = th_zone->mode;
-	return 0;
-}
-
-/* Set mode callback functions for thermal zone */
-static int exynos_set_mode(struct thermal_zone_device *thermal,
-			enum thermal_device_mode mode)
-{
-	if (!th_zone->therm_dev) {
-		pr_notice("thermal zone not registered\n");
-		return 0;
-	}
-
-	mutex_lock(&th_zone->therm_dev->lock);
-
-	if (mode == THERMAL_DEVICE_ENABLED &&
-		!th_zone->sensor_conf->trip_data.trigger_falling)
-		th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
-	else
-		th_zone->therm_dev->polling_delay = 0;
-
-	mutex_unlock(&th_zone->therm_dev->lock);
-
-	th_zone->mode = mode;
-	thermal_zone_device_update(th_zone->therm_dev);
-	pr_info("thermal polling set for duration=%d msec\n",
-				th_zone->therm_dev->polling_delay);
-	return 0;
-}
-
-
-/* Get trip type callback functions for thermal zone */
-static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
-				 enum thermal_trip_type *type)
-{
-	switch (GET_ZONE(trip)) {
-	case MONITOR_ZONE:
-	case WARN_ZONE:
-		*type = THERMAL_TRIP_ACTIVE;
-		break;
-	case PANIC_ZONE:
-		*type = THERMAL_TRIP_CRITICAL;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/* Get trip temperature callback functions for thermal zone */
-static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
-				unsigned long *temp)
-{
-	if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
-		return -EINVAL;
-
-	*temp = th_zone->sensor_conf->trip_data.trip_val[trip];
-	/* convert the temperature into millicelsius */
-	*temp = *temp * MCELSIUS;
-
-	return 0;
-}
-
-/* Get critical temperature callback functions for thermal zone */
-static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
-				unsigned long *temp)
-{
-	int ret;
-	/* Panic zone */
-	ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
-	return ret;
-}
-
-/* Bind callback functions for thermal zone */
-static int exynos_bind(struct thermal_zone_device *thermal,
-			struct thermal_cooling_device *cdev)
-{
-	int ret = 0, i, tab_size, level;
-	struct freq_clip_table *tab_ptr, *clip_data;
-	struct thermal_sensor_conf *data = th_zone->sensor_conf;
-
-	tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
-	tab_size = data->cooling_data.freq_clip_count;
-
-	if (tab_ptr == NULL || tab_size == 0)
-		return -EINVAL;
-
-	/* find the cooling device registered*/
-	for (i = 0; i < th_zone->cool_dev_size; i++)
-		if (cdev == th_zone->cool_dev[i])
-			break;
-
-	/* No matching cooling device */
-	if (i == th_zone->cool_dev_size)
-		return 0;
-
-	/* Bind the thermal zone to the cpufreq cooling device */
-	for (i = 0; i < tab_size; i++) {
-		clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
-		level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
-		if (level == THERMAL_CSTATE_INVALID)
-			return 0;
-		switch (GET_ZONE(i)) {
-		case MONITOR_ZONE:
-		case WARN_ZONE:
-			if (thermal_zone_bind_cooling_device(thermal, i, cdev,
-								level, 0)) {
-				pr_err("error binding cdev inst %d\n", i);
-				ret = -EINVAL;
-			}
-			th_zone->bind = true;
-			break;
-		default:
-			ret = -EINVAL;
-		}
-	}
-
-	return ret;
-}
-
-/* Unbind callback functions for thermal zone */
-static int exynos_unbind(struct thermal_zone_device *thermal,
-			struct thermal_cooling_device *cdev)
-{
-	int ret = 0, i, tab_size;
-	struct thermal_sensor_conf *data = th_zone->sensor_conf;
-
-	if (th_zone->bind == false)
-		return 0;
-
-	tab_size = data->cooling_data.freq_clip_count;
-
-	if (tab_size == 0)
-		return -EINVAL;
-
-	/* find the cooling device registered*/
-	for (i = 0; i < th_zone->cool_dev_size; i++)
-		if (cdev == th_zone->cool_dev[i])
-			break;
-
-	/* No matching cooling device */
-	if (i == th_zone->cool_dev_size)
-		return 0;
-
-	/* Bind the thermal zone to the cpufreq cooling device */
-	for (i = 0; i < tab_size; i++) {
-		switch (GET_ZONE(i)) {
-		case MONITOR_ZONE:
-		case WARN_ZONE:
-			if (thermal_zone_unbind_cooling_device(thermal, i,
-								cdev)) {
-				pr_err("error unbinding cdev inst=%d\n", i);
-				ret = -EINVAL;
-			}
-			th_zone->bind = false;
-			break;
-		default:
-			ret = -EINVAL;
-		}
-	}
-	return ret;
-}
-
-/* Get temperature callback functions for thermal zone */
-static int exynos_get_temp(struct thermal_zone_device *thermal,
-			unsigned long *temp)
-{
-	void *data;
-
-	if (!th_zone->sensor_conf) {
-		pr_info("Temperature sensor not initialised\n");
-		return -EINVAL;
-	}
-	data = th_zone->sensor_conf->private_data;
-	*temp = th_zone->sensor_conf->read_temperature(data);
-	/* convert the temperature into millicelsius */
-	*temp = *temp * MCELSIUS;
-	return 0;
-}
-
-/* Get temperature callback functions for thermal zone */
-static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
-						unsigned long temp)
-{
-	void *data;
-	int ret = -EINVAL;
-
-	if (!th_zone->sensor_conf) {
-		pr_info("Temperature sensor not initialised\n");
-		return -EINVAL;
-	}
-	data = th_zone->sensor_conf->private_data;
-	if (th_zone->sensor_conf->write_emul_temp)
-		ret = th_zone->sensor_conf->write_emul_temp(data, temp);
-	return ret;
-}
-
-/* Get the temperature trend */
-static int exynos_get_trend(struct thermal_zone_device *thermal,
-			int trip, enum thermal_trend *trend)
-{
-	int ret;
-	unsigned long trip_temp;
-
-	ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
-	if (ret < 0)
-		return ret;
-
-	if (thermal->temperature >= trip_temp)
-		*trend = THERMAL_TREND_RAISE_FULL;
-	else
-		*trend = THERMAL_TREND_DROP_FULL;
-
-	return 0;
-}
-/* Operation callback functions for thermal zone */
-static struct thermal_zone_device_ops const exynos_dev_ops = {
-	.bind = exynos_bind,
-	.unbind = exynos_unbind,
-	.get_temp = exynos_get_temp,
-	.set_emul_temp = exynos_set_emul_temp,
-	.get_trend = exynos_get_trend,
-	.get_mode = exynos_get_mode,
-	.set_mode = exynos_set_mode,
-	.get_trip_type = exynos_get_trip_type,
-	.get_trip_temp = exynos_get_trip_temp,
-	.get_crit_temp = exynos_get_crit_temp,
-};
-
-/*
- * This function may be called from interrupt based temperature sensor
- * when threshold is changed.
- */
-static void exynos_report_trigger(void)
-{
-	unsigned int i;
-	char data[10];
-	char *envp[] = { data, NULL };
-
-	if (!th_zone || !th_zone->therm_dev)
-		return;
-	if (th_zone->bind == false) {
-		for (i = 0; i < th_zone->cool_dev_size; i++) {
-			if (!th_zone->cool_dev[i])
-				continue;
-			exynos_bind(th_zone->therm_dev,
-					th_zone->cool_dev[i]);
-		}
-	}
-
-	thermal_zone_device_update(th_zone->therm_dev);
-
-	mutex_lock(&th_zone->therm_dev->lock);
-	/* Find the level for which trip happened */
-	for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
-		if (th_zone->therm_dev->last_temperature <
-			th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
-			break;
-	}
-
-	if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
-		!th_zone->sensor_conf->trip_data.trigger_falling) {
-		if (i > 0)
-			th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
-		else
-			th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
-	}
-
-	snprintf(data, sizeof(data), "%u", i);
-	kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
-	mutex_unlock(&th_zone->therm_dev->lock);
-}
-
-/* Register with the in-kernel thermal management */
-static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
-{
-	int ret;
-	struct cpumask mask_val;
-
-	if (!sensor_conf || !sensor_conf->read_temperature) {
-		pr_err("Temperature sensor not initialised\n");
-		return -EINVAL;
-	}
-
-	th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
-	if (!th_zone)
-		return -ENOMEM;
-
-	th_zone->sensor_conf = sensor_conf;
-	cpumask_set_cpu(0, &mask_val);
-	th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
-	if (IS_ERR(th_zone->cool_dev[0])) {
-		pr_err("Failed to register cpufreq cooling device\n");
-		ret = -EINVAL;
-		goto err_unregister;
-	}
-	th_zone->cool_dev_size++;
-
-	th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
-			EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
-			sensor_conf->trip_data.trigger_falling ?
-			0 : IDLE_INTERVAL);
-
-	if (IS_ERR(th_zone->therm_dev)) {
-		pr_err("Failed to register thermal zone device\n");
-		ret = PTR_ERR(th_zone->therm_dev);
-		goto err_unregister;
-	}
-	th_zone->mode = THERMAL_DEVICE_ENABLED;
-
-	pr_info("Exynos: Kernel Thermal management registered\n");
-
-	return 0;
-
-err_unregister:
-	exynos_unregister_thermal();
-	return ret;
-}
-
-/* Un-Register with the in-kernel thermal management */
-static void exynos_unregister_thermal(void)
-{
-	int i;
-
-	if (!th_zone)
-		return;
-
-	if (th_zone->therm_dev)
-		thermal_zone_device_unregister(th_zone->therm_dev);
-
-	for (i = 0; i < th_zone->cool_dev_size; i++) {
-		if (th_zone->cool_dev[i])
-			cpufreq_cooling_unregister(th_zone->cool_dev[i]);
-	}
-
-	kfree(th_zone);
-	pr_info("Exynos: Kernel Thermal management unregistered\n");
-}
-
 /*
  * TMU treats temperature as a mapped temperature code.
  * The temperature is converted differently depending on the calibration type.
diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
new file mode 100644
index 0000000..9a57606
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_thermal_common.c
@@ -0,0 +1,389 @@
+/*
+ * exynos_thermal_common.c - Samsung EXYNOS common thermal file
+ *
+ *  Copyright (C) 2013 Samsung Electronics
+ *  Amit Daniel Kachhap <amit.daniel@samsung.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/cpufreq.h>
+#include <linux/cpu_cooling.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/mutex.h>
+#include <linux/platform_data/exynos_thermal.h>
+#include <linux/slab.h>
+#include <linux/thermal.h>
+#include "exynos_thermal_common.h"
+
+struct exynos_thermal_zone {
+	enum thermal_device_mode mode;
+	struct thermal_zone_device *therm_dev;
+	struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
+	unsigned int cool_dev_size;
+	struct platform_device *exynos4_dev;
+	struct thermal_sensor_conf *sensor_conf;
+	bool bind;
+};
+
+static struct exynos_thermal_zone *th_zone;
+
+/* Get mode callback functions for thermal zone */
+static int exynos_get_mode(struct thermal_zone_device *thermal,
+			enum thermal_device_mode *mode)
+{
+	if (th_zone)
+		*mode = th_zone->mode;
+	return 0;
+}
+
+/* Set mode callback functions for thermal zone */
+static int exynos_set_mode(struct thermal_zone_device *thermal,
+			enum thermal_device_mode mode)
+{
+	if (!th_zone->therm_dev) {
+		pr_notice("thermal zone not registered\n");
+		return 0;
+	}
+
+	mutex_lock(&th_zone->therm_dev->lock);
+
+	if (mode == THERMAL_DEVICE_ENABLED &&
+		!th_zone->sensor_conf->trip_data.trigger_falling)
+		th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
+	else
+		th_zone->therm_dev->polling_delay = 0;
+
+	mutex_unlock(&th_zone->therm_dev->lock);
+
+	th_zone->mode = mode;
+	thermal_zone_device_update(th_zone->therm_dev);
+	pr_info("thermal polling set for duration=%d msec\n",
+				th_zone->therm_dev->polling_delay);
+	return 0;
+}
+
+
+/* Get trip type callback functions for thermal zone */
+static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
+				 enum thermal_trip_type *type)
+{
+	switch (GET_ZONE(trip)) {
+	case MONITOR_ZONE:
+	case WARN_ZONE:
+		*type = THERMAL_TRIP_ACTIVE;
+		break;
+	case PANIC_ZONE:
+		*type = THERMAL_TRIP_CRITICAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* Get trip temperature callback functions for thermal zone */
+static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
+				unsigned long *temp)
+{
+	if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
+		return -EINVAL;
+
+	*temp = th_zone->sensor_conf->trip_data.trip_val[trip];
+	/* convert the temperature into millicelsius */
+	*temp = *temp * MCELSIUS;
+
+	return 0;
+}
+
+/* Get critical temperature callback functions for thermal zone */
+static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
+				unsigned long *temp)
+{
+	int ret;
+	/* Panic zone */
+	ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
+	return ret;
+}
+
+/* Bind callback functions for thermal zone */
+static int exynos_bind(struct thermal_zone_device *thermal,
+			struct thermal_cooling_device *cdev)
+{
+	int ret = 0, i, tab_size, level;
+	struct freq_clip_table *tab_ptr, *clip_data;
+	struct thermal_sensor_conf *data = th_zone->sensor_conf;
+
+	tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
+	tab_size = data->cooling_data.freq_clip_count;
+
+	if (tab_ptr == NULL || tab_size == 0)
+		return -EINVAL;
+
+	/* find the cooling device registered*/
+	for (i = 0; i < th_zone->cool_dev_size; i++)
+		if (cdev == th_zone->cool_dev[i])
+			break;
+
+	/* No matching cooling device */
+	if (i == th_zone->cool_dev_size)
+		return 0;
+
+	/* Bind the thermal zone to the cpufreq cooling device */
+	for (i = 0; i < tab_size; i++) {
+		clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
+		level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
+		if (level == THERMAL_CSTATE_INVALID)
+			return 0;
+		switch (GET_ZONE(i)) {
+		case MONITOR_ZONE:
+		case WARN_ZONE:
+			if (thermal_zone_bind_cooling_device(thermal, i, cdev,
+								level, 0)) {
+				pr_err("error binding cdev inst %d\n", i);
+				ret = -EINVAL;
+			}
+			th_zone->bind = true;
+			break;
+		default:
+			ret = -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+/* Unbind callback functions for thermal zone */
+static int exynos_unbind(struct thermal_zone_device *thermal,
+			struct thermal_cooling_device *cdev)
+{
+	int ret = 0, i, tab_size;
+	struct thermal_sensor_conf *data = th_zone->sensor_conf;
+
+	if (th_zone->bind == false)
+		return 0;
+
+	tab_size = data->cooling_data.freq_clip_count;
+
+	if (tab_size == 0)
+		return -EINVAL;
+
+	/* find the cooling device registered*/
+	for (i = 0; i < th_zone->cool_dev_size; i++)
+		if (cdev == th_zone->cool_dev[i])
+			break;
+
+	/* No matching cooling device */
+	if (i == th_zone->cool_dev_size)
+		return 0;
+
+	/* Bind the thermal zone to the cpufreq cooling device */
+	for (i = 0; i < tab_size; i++) {
+		switch (GET_ZONE(i)) {
+		case MONITOR_ZONE:
+		case WARN_ZONE:
+			if (thermal_zone_unbind_cooling_device(thermal, i,
+								cdev)) {
+				pr_err("error unbinding cdev inst=%d\n", i);
+				ret = -EINVAL;
+			}
+			th_zone->bind = false;
+			break;
+		default:
+			ret = -EINVAL;
+		}
+	}
+	return ret;
+}
+
+/* Get temperature callback functions for thermal zone */
+static int exynos_get_temp(struct thermal_zone_device *thermal,
+			unsigned long *temp)
+{
+	void *data;
+
+	if (!th_zone->sensor_conf) {
+		pr_info("Temperature sensor not initialised\n");
+		return -EINVAL;
+	}
+	data = th_zone->sensor_conf->private_data;
+	*temp = th_zone->sensor_conf->read_temperature(data);
+	/* convert the temperature into millicelsius */
+	*temp = *temp * MCELSIUS;
+	return 0;
+}
+
+/* Get temperature callback functions for thermal zone */
+static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
+						unsigned long temp)
+{
+	void *data;
+	int ret = -EINVAL;
+
+	if (!th_zone->sensor_conf) {
+		pr_info("Temperature sensor not initialised\n");
+		return -EINVAL;
+	}
+	data = th_zone->sensor_conf->private_data;
+	if (th_zone->sensor_conf->write_emul_temp)
+		ret = th_zone->sensor_conf->write_emul_temp(data, temp);
+	return ret;
+}
+
+/* Get the temperature trend */
+static int exynos_get_trend(struct thermal_zone_device *thermal,
+			int trip, enum thermal_trend *trend)
+{
+	int ret;
+	unsigned long trip_temp;
+
+	ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
+	if (ret < 0)
+		return ret;
+
+	if (thermal->temperature >= trip_temp)
+		*trend = THERMAL_TREND_RAISE_FULL;
+	else
+		*trend = THERMAL_TREND_DROP_FULL;
+
+	return 0;
+}
+/* Operation callback functions for thermal zone */
+static struct thermal_zone_device_ops const exynos_dev_ops = {
+	.bind = exynos_bind,
+	.unbind = exynos_unbind,
+	.get_temp = exynos_get_temp,
+	.set_emul_temp = exynos_set_emul_temp,
+	.get_trend = exynos_get_trend,
+	.get_mode = exynos_get_mode,
+	.set_mode = exynos_set_mode,
+	.get_trip_type = exynos_get_trip_type,
+	.get_trip_temp = exynos_get_trip_temp,
+	.get_crit_temp = exynos_get_crit_temp,
+};
+
+/*
+ * This function may be called from interrupt based temperature sensor
+ * when threshold is changed.
+ */
+void exynos_report_trigger(void)
+{
+	unsigned int i;
+	char data[10];
+	char *envp[] = { data, NULL };
+
+	if (!th_zone || !th_zone->therm_dev)
+		return;
+	if (th_zone->bind == false) {
+		for (i = 0; i < th_zone->cool_dev_size; i++) {
+			if (!th_zone->cool_dev[i])
+				continue;
+			exynos_bind(th_zone->therm_dev,
+					th_zone->cool_dev[i]);
+		}
+	}
+
+	thermal_zone_device_update(th_zone->therm_dev);
+
+	mutex_lock(&th_zone->therm_dev->lock);
+	/* Find the level for which trip happened */
+	for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
+		if (th_zone->therm_dev->last_temperature <
+			th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
+			break;
+	}
+
+	if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
+		!th_zone->sensor_conf->trip_data.trigger_falling) {
+		if (i > 0)
+			th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
+		else
+			th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
+	}
+
+	snprintf(data, sizeof(data), "%u", i);
+	kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
+	mutex_unlock(&th_zone->therm_dev->lock);
+}
+
+/* Register with the in-kernel thermal management */
+int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
+{
+	int ret;
+	struct cpumask mask_val;
+
+	if (!sensor_conf || !sensor_conf->read_temperature) {
+		pr_err("Temperature sensor not initialised\n");
+		return -EINVAL;
+	}
+
+	th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
+	if (!th_zone)
+		return -ENOMEM;
+
+	th_zone->sensor_conf = sensor_conf;
+	cpumask_set_cpu(0, &mask_val);
+	th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
+	if (IS_ERR(th_zone->cool_dev[0])) {
+		pr_err("Failed to register cpufreq cooling device\n");
+		ret = -EINVAL;
+		goto err_unregister;
+	}
+	th_zone->cool_dev_size++;
+
+	th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
+			EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
+			sensor_conf->trip_data.trigger_falling ?
+			0 : IDLE_INTERVAL);
+
+	if (IS_ERR(th_zone->therm_dev)) {
+		pr_err("Failed to register thermal zone device\n");
+		ret = PTR_ERR(th_zone->therm_dev);
+		goto err_unregister;
+	}
+	th_zone->mode = THERMAL_DEVICE_ENABLED;
+
+	pr_info("Exynos: Kernel Thermal management registered\n");
+
+	return 0;
+
+err_unregister:
+	exynos_unregister_thermal();
+	return ret;
+}
+
+/* Un-Register with the in-kernel thermal management */
+void exynos_unregister_thermal(void)
+{
+	int i;
+
+	if (!th_zone)
+		return;
+
+	if (th_zone->therm_dev)
+		thermal_zone_device_unregister(th_zone->therm_dev);
+
+	for (i = 0; i < th_zone->cool_dev_size; i++) {
+		if (th_zone->cool_dev[i])
+			cpufreq_cooling_unregister(th_zone->cool_dev[i]);
+	}
+
+	kfree(th_zone);
+	pr_info("Exynos: Kernel Thermal management unregistered\n");
+}
diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
new file mode 100644
index 0000000..da2add0
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_thermal_common.h
@@ -0,0 +1,83 @@
+/*
+ * exynos_thermal_common.h - Samsung EXYNOS common header file
+ *
+ *  Copyright (C) 2013 Samsung Electronics
+ *  Amit Daniel Kachhap <amit.daniel@samsung.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _LINUX_EXYNOS_THERMAL_COMMON_H
+#define _LINUX_EXYNOS_THERMAL_COMMON_H
+
+/* In-kernel thermal framework related macros & definations */
+#define SENSOR_NAME_LEN	16
+#define MAX_TRIP_COUNT	8
+#define MAX_COOLING_DEVICE 4
+#define MAX_THRESHOLD_LEVS 4
+
+#define ACTIVE_INTERVAL 500
+#define IDLE_INTERVAL 10000
+#define MCELSIUS	1000
+
+/* CPU Zone information */
+#define PANIC_ZONE      4
+#define WARN_ZONE       3
+#define MONITOR_ZONE    2
+#define SAFE_ZONE       1
+
+#define GET_ZONE(trip) (trip + 2)
+#define GET_TRIP(zone) (zone - 2)
+
+#define EXYNOS_ZONE_COUNT	3
+
+struct	thermal_trip_point_conf {
+	int trip_val[MAX_TRIP_COUNT];
+	int trip_count;
+	u8 trigger_falling;
+};
+
+struct	thermal_cooling_conf {
+	struct freq_clip_table freq_data[MAX_TRIP_COUNT];
+	int freq_clip_count;
+};
+
+struct thermal_sensor_conf {
+	char name[SENSOR_NAME_LEN];
+	int (*read_temperature)(void *data);
+	int (*write_emul_temp)(void *drv_data, unsigned long temp);
+	struct thermal_trip_point_conf trip_data;
+	struct thermal_cooling_conf cooling_data;
+	void *private_data;
+};
+
+/*Functions used exynos based thermal sensor driver*/
+#ifdef CONFIG_EXYNOS_THERMAL_CORE
+void exynos_unregister_thermal(void);
+int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
+void exynos_report_trigger(void);
+#else
+static inline void
+exynos_unregister_thermal(void) { return; }
+
+static inline int
+exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
+
+static inline void
+exynos_report_trigger(void) { return; }
+
+#endif /* CONFIG_EXYNOS_COMMON */
+#endif /* _LINUX_EXYNOS_THERMAL_COMMON_H */
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 03/21] thermal: exynos: Rename exynos_thermal.c to exynos_tmu.c
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
  2013-05-07 13:00 ` [PATCH V3 01/21] thermal: exynos: Moving exynos thermal files into samsung directory Amit Daniel Kachhap
  2013-05-07 13:00 ` [PATCH V3 02/21] thermal: exynos: Bifurcate exynos thermal common and tmu controller code Amit Daniel Kachhap
@ 2013-05-07 13:00 ` Amit Daniel Kachhap
  2013-05-10 15:12     ` Eduardo Valentin
  2013-05-07 13:00 ` [PATCH V3 04/21] thermal: exynos: Move exynos_thermal.h from include/* to driver/* folder Amit Daniel Kachhap
                   ` (17 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:00 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch renames exynos_thermal.c to exynos_tmu.c. This change is needed as
this file now just contains exynos tmu driver related codes and thermal zone
or cpufreq cooling registration related changes are not there anymore.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/Makefile                   |    6 +++---
 .../samsung/{exynos_thermal.c => exynos_tmu.c}     |    2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)
 rename drivers/thermal/samsung/{exynos_thermal.c => exynos_tmu.c} (99%)

diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
index 6227d4f..22528d6 100644
--- a/drivers/thermal/samsung/Makefile
+++ b/drivers/thermal/samsung/Makefile
@@ -1,6 +1,6 @@
 #
 # Samsung thermal specific Makefile
 #
-obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_soc_thermal.o
-exynos_soc_thermal-y				:= exynos_thermal.o
-exynos_soc_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
+obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_thermal.o
+exynos_thermal-y				:= exynos_tmu.o
+exynos_thermal-$(CONFIG_EXYNOS_THERMAL_CORE)	+= exynos_thermal_common.o
diff --git a/drivers/thermal/samsung/exynos_thermal.c b/drivers/thermal/samsung/exynos_tmu.c
similarity index 99%
rename from drivers/thermal/samsung/exynos_thermal.c
rename to drivers/thermal/samsung/exynos_tmu.c
index 4c85945..3de3e61 100644
--- a/drivers/thermal/samsung/exynos_thermal.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -1,5 +1,5 @@
 /*
- * exynos_thermal.c - Samsung EXYNOS TMU (Thermal Management Unit)
+ * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
  *
  *  Copyright (C) 2011 Samsung Electronics
  *  Donggeun Kim <dg77.kim@samsung.com>
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 04/21] thermal: exynos: Move exynos_thermal.h from include/* to driver/* folder
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (2 preceding siblings ...)
  2013-05-07 13:00 ` [PATCH V3 03/21] thermal: exynos: Rename exynos_thermal.c to exynos_tmu.c Amit Daniel Kachhap
@ 2013-05-07 13:00 ` Amit Daniel Kachhap
  2013-05-09 13:28     ` Eduardo Valentin
  2013-05-07 13:00 ` [PATCH V3 05/21] thermal: exynos: Bifurcate exynos tmu driver and configuration data Amit Daniel Kachhap
                   ` (16 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:00 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch renames and moves  include/linux/platform_data/exynos_thermal.h to
drivers/thermal/samsung/exynos_tmu.h. This file movement is needed as exynos
SOC's are not supporting non-DT based platforms. Also the rename is needed as this
file now just contains exynos tmu driver related definations.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/exynos_thermal_common.c    |    1 -
 drivers/thermal/samsung/exynos_thermal_common.h    |   15 +++++++++++++++
 drivers/thermal/samsung/exynos_tmu.c               |    2 +-
 .../thermal/samsung/exynos_tmu.h                   |   15 ---------------
 4 files changed, 16 insertions(+), 17 deletions(-)
 rename include/linux/platform_data/exynos_thermal.h => drivers/thermal/samsung/exynos_tmu.h (88%)

diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
index 9a57606..dae5476 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.c
+++ b/drivers/thermal/samsung/exynos_thermal_common.c
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/kobject.h>
 #include <linux/mutex.h>
-#include <linux/platform_data/exynos_thermal.h>
 #include <linux/slab.h>
 #include <linux/thermal.h>
 #include "exynos_thermal_common.h"
diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
index da2add0..1c3f8b7 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.h
+++ b/drivers/thermal/samsung/exynos_thermal_common.h
@@ -44,6 +44,21 @@
 
 #define EXYNOS_ZONE_COUNT	3
 
+/**
+ * struct freq_clip_table
+ * @freq_clip_max: maximum frequency allowed for this cooling state.
+ * @temp_level: Temperature level at which the temperature clipping will
+ *	happen.
+ * @mask_val: cpumask of the allowed cpu's where the clipping will take place.
+ *
+ * This structure is required to be filled and passed to the
+ * cpufreq_cooling_unregister function.
+ */
+struct freq_clip_table {
+	unsigned int freq_clip_max;
+	unsigned int temp_level;
+	const struct cpumask *mask_val;
+};
 struct	thermal_trip_point_conf {
 	int trip_val[MAX_TRIP_COUNT];
 	int trip_count;
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 3de3e61..a02f2c9 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -30,10 +30,10 @@
 #include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
-#include <linux/platform_data/exynos_thermal.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include "exynos_thermal_common.h"
+#include "exynos_tmu.h"
 
 /* Exynos generic registers */
 #define EXYNOS_TMU_REG_TRIMINFO		0x0
diff --git a/include/linux/platform_data/exynos_thermal.h b/drivers/thermal/samsung/exynos_tmu.h
similarity index 88%
rename from include/linux/platform_data/exynos_thermal.h
rename to drivers/thermal/samsung/exynos_tmu.h
index da7e627..342fb1f 100644
--- a/include/linux/platform_data/exynos_thermal.h
+++ b/drivers/thermal/samsung/exynos_tmu.h
@@ -33,21 +33,6 @@ enum soc_type {
 	SOC_ARCH_EXYNOS4210 = 1,
 	SOC_ARCH_EXYNOS,
 };
-/**
- * struct freq_clip_table
- * @freq_clip_max: maximum frequency allowed for this cooling state.
- * @temp_level: Temperature level at which the temperature clipping will
- *	happen.
- * @mask_val: cpumask of the allowed cpu's where the clipping will take place.
- *
- * This structure is required to be filled and passed to the
- * cpufreq_cooling_unregister function.
- */
-struct freq_clip_table {
-	unsigned int freq_clip_max;
-	unsigned int temp_level;
-	const struct cpumask *mask_val;
-};
 
 /**
  * struct exynos_tmu_platform_data
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 05/21] thermal: exynos: Bifurcate exynos tmu driver and configuration data
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (3 preceding siblings ...)
  2013-05-07 13:00 ` [PATCH V3 04/21] thermal: exynos: Move exynos_thermal.h from include/* to driver/* folder Amit Daniel Kachhap
@ 2013-05-07 13:00 ` Amit Daniel Kachhap
  2013-05-09 13:39     ` Eduardo Valentin
  2013-05-07 13:00 ` [PATCH V3 06/21] thermal: exynos: Add missing definations and code cleanup Amit Daniel Kachhap
                   ` (15 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:00 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This code splits the exynos tmu driver code into SOC specific data parts.
This will simplify adding new SOC specific data to the same TMU controller.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/Kconfig                 |   13 ++++-
 drivers/thermal/samsung/Makefile                |    1 +
 drivers/thermal/samsung/exynos_thermal_common.h |    3 +-
 drivers/thermal/samsung/exynos_tmu.c            |   67 +------------------
 drivers/thermal/samsung/exynos_tmu_data.c       |   78 +++++++++++++++++++++++
 drivers/thermal/samsung/exynos_tmu_data.h       |   41 ++++++++++++
 6 files changed, 137 insertions(+), 66 deletions(-)
 create mode 100644 drivers/thermal/samsung/exynos_tmu_data.c
 create mode 100644 drivers/thermal/samsung/exynos_tmu_data.h

diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
index 7857e20..f23f533 100644
--- a/drivers/thermal/samsung/Kconfig
+++ b/drivers/thermal/samsung/Kconfig
@@ -5,7 +5,8 @@ config EXYNOS_THERMAL
 	  If you say yes here you get support for the exynos thermal driver
 	  for exynos4 and exynos5 soc. This driver initialises the TMU, reports
 	  temperature and handles cooling action if defined. This driver uses
-	  core thermal API's.
+	  core thermal API's and TMU configuration data from the supported
+	  soc's.
 
 config EXYNOS_THERMAL_CORE
 	bool "Core thermal framework support for EXYNOS SOC's"
@@ -15,3 +16,13 @@ config EXYNOS_THERMAL_CORE
 	  (Thermal Management Unit) common registration/unregistration
 	  functions to the core thermal layer and also to use the generic
 	  cpu cooling API's.
+
+config EXYNOS_THERMAL_DATA
+	bool "Temperature sensor congiguration data for EXYNOS series SOC"
+	depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250)
+	depends on EXYNOS_THERMAL
+	help
+	  If you say yes here you can enable TMU (Thermal Management Unit) on
+	  SAMSUNG EXYNOS 4210, 4412, 4414 and 5250 series of SoC. This option
+	  enables/prepares the configuration, trip and cooling data for the TMU
+	  driver.
diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
index 22528d6..c0446e8 100644
--- a/drivers/thermal/samsung/Makefile
+++ b/drivers/thermal/samsung/Makefile
@@ -4,3 +4,4 @@
 obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_thermal.o
 exynos_thermal-y				:= exynos_tmu.o
 exynos_thermal-$(CONFIG_EXYNOS_THERMAL_CORE)	+= exynos_thermal_common.o
+exynos_thermal-$(CONFIG_EXYNOS_THERMAL_DATA)	+= exynos_tmu_data.o
diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
index 1c3f8b7..3b85858 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.h
+++ b/drivers/thermal/samsung/exynos_thermal_common.h
@@ -62,7 +62,7 @@ struct freq_clip_table {
 struct	thermal_trip_point_conf {
 	int trip_val[MAX_TRIP_COUNT];
 	int trip_count;
-	u8 trigger_falling;
+	unsigned char trigger_falling;
 };
 
 struct	thermal_cooling_conf {
@@ -93,6 +93,5 @@ exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
 
 static inline void
 exynos_report_trigger(void) { return; }
-
 #endif /* CONFIG_EXYNOS_COMMON */
 #endif /* _LINUX_EXYNOS_THERMAL_COMMON_H */
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index a02f2c9..05b5068 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -34,6 +34,7 @@
 #include <linux/workqueue.h>
 #include "exynos_thermal_common.h"
 #include "exynos_tmu.h"
+#include "exynos_tmu_data.h"
 
 /* Exynos generic registers */
 #define EXYNOS_TMU_REG_TRIMINFO		0x0
@@ -385,66 +386,6 @@ static struct thermal_sensor_conf exynos_sensor_conf = {
 	.write_emul_temp	= exynos_tmu_set_emulation,
 };
 
-#if defined(CONFIG_CPU_EXYNOS4210)
-static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
-	.threshold = 80,
-	.trigger_levels[0] = 5,
-	.trigger_levels[1] = 20,
-	.trigger_levels[2] = 30,
-	.trigger_level0_en = 1,
-	.trigger_level1_en = 1,
-	.trigger_level2_en = 1,
-	.trigger_level3_en = 0,
-	.gain = 15,
-	.reference_voltage = 7,
-	.cal_type = TYPE_ONE_POINT_TRIMMING,
-	.freq_tab[0] = {
-		.freq_clip_max = 800 * 1000,
-		.temp_level = 85,
-	},
-	.freq_tab[1] = {
-		.freq_clip_max = 200 * 1000,
-		.temp_level = 100,
-	},
-	.freq_tab_count = 2,
-	.type = SOC_ARCH_EXYNOS4210,
-};
-#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
-#else
-#define EXYNOS4210_TMU_DRV_DATA (NULL)
-#endif
-
-#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
-static struct exynos_tmu_platform_data const exynos_default_tmu_data = {
-	.threshold_falling = 10,
-	.trigger_levels[0] = 85,
-	.trigger_levels[1] = 103,
-	.trigger_levels[2] = 110,
-	.trigger_level0_en = 1,
-	.trigger_level1_en = 1,
-	.trigger_level2_en = 1,
-	.trigger_level3_en = 0,
-	.gain = 8,
-	.reference_voltage = 16,
-	.noise_cancel_mode = 4,
-	.cal_type = TYPE_ONE_POINT_TRIMMING,
-	.efuse_value = 55,
-	.freq_tab[0] = {
-		.freq_clip_max = 800 * 1000,
-		.temp_level = 85,
-	},
-	.freq_tab[1] = {
-		.freq_clip_max = 200 * 1000,
-		.temp_level = 103,
-	},
-	.freq_tab_count = 2,
-	.type = SOC_ARCH_EXYNOS,
-};
-#define EXYNOS_TMU_DRV_DATA (&exynos_default_tmu_data)
-#else
-#define EXYNOS_TMU_DRV_DATA (NULL)
-#endif
-
 #ifdef CONFIG_OF
 static const struct of_device_id exynos_tmu_match[] = {
 	{
@@ -453,11 +394,11 @@ static const struct of_device_id exynos_tmu_match[] = {
 	},
 	{
 		.compatible = "samsung,exynos4412-tmu",
-		.data = (void *)EXYNOS_TMU_DRV_DATA,
+		.data = (void *)EXYNOS5250_TMU_DRV_DATA,
 	},
 	{
 		.compatible = "samsung,exynos5250-tmu",
-		.data = (void *)EXYNOS_TMU_DRV_DATA,
+		.data = (void *)EXYNOS5250_TMU_DRV_DATA,
 	},
 	{},
 };
@@ -471,7 +412,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = {
 	},
 	{
 		.name		= "exynos5250-tmu",
-		.driver_data    = (kernel_ulong_t)EXYNOS_TMU_DRV_DATA,
+		.driver_data    = (kernel_ulong_t)EXYNOS5250_TMU_DRV_DATA,
 	},
 	{ },
 };
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
new file mode 100644
index 0000000..13a60ca
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_tmu_data.c
@@ -0,0 +1,78 @@
+/*
+ * exynos_tmu_data.c - Samsung EXYNOS tmu data file
+ *
+ *  Copyright (C) 2013 Samsung Electronics
+ *  Amit Daniel Kachhap <amit.daniel@samsung.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "exynos_thermal_common.h"
+#include "exynos_tmu.h"
+
+#if defined(CONFIG_CPU_EXYNOS4210)
+struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
+	.threshold = 80,
+	.trigger_levels[0] = 5,
+	.trigger_levels[1] = 20,
+	.trigger_levels[2] = 30,
+	.trigger_level0_en = 1,
+	.trigger_level1_en = 1,
+	.trigger_level2_en = 1,
+	.trigger_level3_en = 0,
+	.gain = 15,
+	.reference_voltage = 7,
+	.cal_type = TYPE_ONE_POINT_TRIMMING,
+	.freq_tab[0] = {
+		.freq_clip_max = 800 * 1000,
+		.temp_level = 85,
+	},
+	.freq_tab[1] = {
+		.freq_clip_max = 200 * 1000,
+		.temp_level = 100,
+	},
+	.freq_tab_count = 2,
+	.type = SOC_ARCH_EXYNOS4210,
+};
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
+struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
+	.threshold_falling = 10,
+	.trigger_levels[0] = 85,
+	.trigger_levels[1] = 103,
+	.trigger_levels[2] = 110,
+	.trigger_level0_en = 1,
+	.trigger_level1_en = 1,
+	.trigger_level2_en = 1,
+	.trigger_level3_en = 0,
+	.gain = 8,
+	.reference_voltage = 16,
+	.noise_cancel_mode = 4,
+	.cal_type = TYPE_ONE_POINT_TRIMMING,
+	.efuse_value = 55,
+	.freq_tab[0] = {
+		.freq_clip_max = 800 * 1000,
+		.temp_level = 85,
+	},
+	.freq_tab[1] = {
+		.freq_clip_max = 200 * 1000,
+		.temp_level = 103,
+	},
+	.freq_tab_count = 2,
+	.type = SOC_ARCH_EXYNOS,
+};
+#endif
diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
new file mode 100644
index 0000000..5b69711
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_tmu_data.h
@@ -0,0 +1,41 @@
+/*
+ * exynos_tmu_data.h - Samsung EXYNOS tmu data header file
+ *
+ *  Copyright (C) 2013 Samsung Electronics
+ *  Amit Daniel Kachhap <amit.daniel@samsung.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _LINUX_EXYNOS_TMU_DATA_H
+#define _LINUX_EXYNOS_TMU_DATA_H
+
+#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
+extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
+#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
+#else
+#define EXYNOS4210_TMU_DRV_DATA (NULL)
+#endif
+
+#if (defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)) && \
+defined(CONFIG_EXYNOS_THERMAL_DATA)
+extern struct exynos_tmu_platform_data const exynos5250_default_tmu_data;
+#define EXYNOS5250_TMU_DRV_DATA (&exynos5250_default_tmu_data)
+#else
+#define EXYNOS5250_TMU_DRV_DATA (NULL)
+#endif
+
+#endif /*_LINUX_EXYNOS_TMU_DATA_H*/
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 06/21] thermal: exynos: Add missing definations and code cleanup
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (4 preceding siblings ...)
  2013-05-07 13:00 ` [PATCH V3 05/21] thermal: exynos: Bifurcate exynos tmu driver and configuration data Amit Daniel Kachhap
@ 2013-05-07 13:00 ` Amit Daniel Kachhap
  2013-05-09 13:52     ` Eduardo Valentin
  2013-05-07 13:00 ` [PATCH V3 07/21] thermal: exynos: Add extra entries in the tmu platform data Amit Daniel Kachhap
                   ` (14 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:00 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch adds some extra register bitfield definations and cleans
up the code to prepare for moving register macros and definations inside
the TMU data section.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/exynos_tmu.c |   62 +++++++++++++++++++++++++---------
 1 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 05b5068..a43afc4 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -47,9 +47,12 @@
 
 #define EXYNOS_TMU_TRIM_TEMP_MASK	0xff
 #define EXYNOS_TMU_GAIN_SHIFT		8
+#define EXYNOS_TMU_GAIN_MASK		0xf
 #define EXYNOS_TMU_REF_VOLTAGE_SHIFT	24
-#define EXYNOS_TMU_CORE_ON		3
-#define EXYNOS_TMU_CORE_OFF		2
+#define EXYNOS_TMU_REF_VOLTAGE_MASK	0x1f
+#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK	0xf
+#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT	8
+#define EXYNOS_TMU_CORE_EN_SHIFT	0
 #define EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET	50
 
 /* Exynos4210 specific registers */
@@ -67,6 +70,7 @@
 #define EXYNOS4210_TMU_TRIG_LEVEL1_MASK	0x10
 #define EXYNOS4210_TMU_TRIG_LEVEL2_MASK	0x100
 #define EXYNOS4210_TMU_TRIG_LEVEL3_MASK	0x1000
+#define EXYNOS4210_TMU_TRIG_LEVEL_MASK	0x1111
 #define EXYNOS4210_TMU_INTCLEAR_VAL	0x1111
 
 /* Exynos5250 and Exynos4412 specific registers */
@@ -76,17 +80,30 @@
 #define EXYNOS_EMUL_CON		0x80
 
 #define EXYNOS_TRIMINFO_RELOAD		0x1
+#define EXYNOS_TRIMINFO_SHIFT		0x0
+#define EXYNOS_TMU_RISE_INT_MASK	0x111
+#define EXYNOS_TMU_RISE_INT_SHIFT	0
+#define EXYNOS_TMU_FALL_INT_MASK	0x111
+#define EXYNOS_TMU_FALL_INT_SHIFT	12
 #define EXYNOS_TMU_CLEAR_RISE_INT	0x111
 #define EXYNOS_TMU_CLEAR_FALL_INT	(0x111 << 12)
-#define EXYNOS_MUX_ADDR_VALUE		6
-#define EXYNOS_MUX_ADDR_SHIFT		20
 #define EXYNOS_TMU_TRIP_MODE_SHIFT	13
+#define EXYNOS_TMU_TRIP_MODE_MASK	0x7
+
+#define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
+#define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
+#define EXYNOS_TMU_INTEN_RISE2_SHIFT	8
+#define EXYNOS_TMU_INTEN_RISE3_SHIFT	12
+#define EXYNOS_TMU_INTEN_FALL0_SHIFT	16
+#define EXYNOS_TMU_INTEN_FALL1_SHIFT	20
+#define EXYNOS_TMU_INTEN_FALL2_SHIFT	24
 
 #define EFUSE_MIN_VALUE 40
 #define EFUSE_MAX_VALUE 100
 
 #ifdef CONFIG_THERMAL_EMULATION
 #define EXYNOS_EMUL_TIME	0x57F0
+#define EXYNOS_EMUL_TIME_MASK	0xffff
 #define EXYNOS_EMUL_TIME_SHIFT	16
 #define EXYNOS_EMUL_DATA_SHIFT	8
 #define EXYNOS_EMUL_DATA_MASK	0xFF
@@ -265,24 +282,37 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
 	mutex_lock(&data->lock);
 	clk_enable(data->clk);
 
-	con = pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT |
-		pdata->gain << EXYNOS_TMU_GAIN_SHIFT;
+	con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
 
-	if (data->soc == SOC_ARCH_EXYNOS) {
-		con |= pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT;
-		con |= (EXYNOS_MUX_ADDR_VALUE << EXYNOS_MUX_ADDR_SHIFT);
+	if (pdata->reference_voltage) {
+		con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK <<
+				EXYNOS_TMU_REF_VOLTAGE_SHIFT);
+		con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
+	}
+
+	if (pdata->gain) {
+		con &= ~(EXYNOS_TMU_GAIN_MASK << EXYNOS_TMU_GAIN_SHIFT);
+		con |= (pdata->gain << EXYNOS_TMU_GAIN_SHIFT);
+	}
+
+	if (pdata->noise_cancel_mode) {
+		con &= ~(EXYNOS_TMU_TRIP_MODE_MASK <<
+					EXYNOS_TMU_TRIP_MODE_SHIFT);
+		con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
 	}
 
 	if (on) {
-		con |= EXYNOS_TMU_CORE_ON;
-		interrupt_en = pdata->trigger_level3_en << 12 |
-			pdata->trigger_level2_en << 8 |
-			pdata->trigger_level1_en << 4 |
-			pdata->trigger_level0_en;
+		con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
+		interrupt_en =
+		pdata->trigger_level3_en << EXYNOS_TMU_INTEN_RISE3_SHIFT |
+		pdata->trigger_level2_en << EXYNOS_TMU_INTEN_RISE2_SHIFT |
+		pdata->trigger_level1_en << EXYNOS_TMU_INTEN_RISE1_SHIFT |
+		pdata->trigger_level0_en << EXYNOS_TMU_INTEN_RISE0_SHIFT;
 		if (pdata->threshold_falling)
-			interrupt_en |= interrupt_en << 16;
+			interrupt_en |=
+				interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
 	} else {
-		con |= EXYNOS_TMU_CORE_OFF;
+		con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
 		interrupt_en = 0; /* Disable all interrupts */
 	}
 	writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 07/21] thermal: exynos: Add extra entries in the tmu platform data
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (5 preceding siblings ...)
  2013-05-07 13:00 ` [PATCH V3 06/21] thermal: exynos: Add missing definations and code cleanup Amit Daniel Kachhap
@ 2013-05-07 13:00 ` Amit Daniel Kachhap
  2013-05-07 13:00 ` [PATCH V3 08/21] thermal: exynos: Support thermal tripping Amit Daniel Kachhap
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:00 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch adds entries min_efuse_value, max_efuse_value, default_temp_offset,
trigger_type, cal_type, trim_first_point, trim_second_point and
trigger_enable in the TMU platform data structure. Also the driver is modified
to use the data passed by these new platform memebers instead of the constant
macros. All these changes helps in separating the SOC specific data part from
the TMU driver.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/exynos_tmu.c      |   43 +++++++++++------------
 drivers/thermal/samsung/exynos_tmu.h      |   52 +++++++++++++++++++----------
 drivers/thermal/samsung/exynos_tmu_data.c |   33 ++++++++++++++----
 3 files changed, 80 insertions(+), 48 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index a43afc4..77b6a37 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -53,7 +53,6 @@
 #define EXYNOS_TMU_BUF_SLOPE_SEL_MASK	0xf
 #define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT	8
 #define EXYNOS_TMU_CORE_EN_SHIFT	0
-#define EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET	50
 
 /* Exynos4210 specific registers */
 #define EXYNOS4210_TMU_REG_THRESHOLD_TEMP	0x44
@@ -98,9 +97,6 @@
 #define EXYNOS_TMU_INTEN_FALL1_SHIFT	20
 #define EXYNOS_TMU_INTEN_FALL2_SHIFT	24
 
-#define EFUSE_MIN_VALUE 40
-#define EFUSE_MAX_VALUE 100
-
 #ifdef CONFIG_THERMAL_EMULATION
 #define EXYNOS_EMUL_TIME	0x57F0
 #define EXYNOS_EMUL_TIME_MASK	0xffff
@@ -140,15 +136,16 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
 
 	switch (pdata->cal_type) {
 	case TYPE_TWO_POINT_TRIMMING:
-		temp_code = (temp - 25) *
-		    (data->temp_error2 - data->temp_error1) /
-		    (85 - 25) + data->temp_error1;
+		temp_code = (temp - pdata->first_point_trim) *
+			(data->temp_error2 - data->temp_error1) /
+			(pdata->second_point_trim - pdata->first_point_trim) +
+			data->temp_error1;
 		break;
 	case TYPE_ONE_POINT_TRIMMING:
-		temp_code = temp + data->temp_error1 - 25;
+		temp_code = temp + data->temp_error1 - pdata->first_point_trim;
 		break;
 	default:
-		temp_code = temp + EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
+		temp_code = temp + pdata->default_temp_offset;
 		break;
 	}
 out:
@@ -173,14 +170,16 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
 
 	switch (pdata->cal_type) {
 	case TYPE_TWO_POINT_TRIMMING:
-		temp = (temp_code - data->temp_error1) * (85 - 25) /
-		    (data->temp_error2 - data->temp_error1) + 25;
+		temp = (temp_code - data->temp_error1) *
+			(pdata->second_point_trim - pdata->first_point_trim) /
+			(data->temp_error2 - data->temp_error1) +
+			pdata->first_point_trim;
 		break;
 	case TYPE_ONE_POINT_TRIMMING:
-		temp = temp_code - data->temp_error1 + 25;
+		temp = temp_code - data->temp_error1 + pdata->first_point_trim;
 		break;
 	default:
-		temp = temp_code - EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
+		temp = temp_code - pdata->default_temp_offset;
 		break;
 	}
 out:
@@ -213,8 +212,8 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 	data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
 	data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
 
-	if ((EFUSE_MIN_VALUE > data->temp_error1) ||
-			(data->temp_error1 > EFUSE_MAX_VALUE) ||
+	if ((pdata->min_efuse_value > data->temp_error1) ||
+			(data->temp_error1 > pdata->max_efuse_value) ||
 			(data->temp_error2 != 0))
 		data->temp_error1 = pdata->efuse_value;
 
@@ -304,10 +303,10 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
 	if (on) {
 		con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
 		interrupt_en =
-		pdata->trigger_level3_en << EXYNOS_TMU_INTEN_RISE3_SHIFT |
-		pdata->trigger_level2_en << EXYNOS_TMU_INTEN_RISE2_SHIFT |
-		pdata->trigger_level1_en << EXYNOS_TMU_INTEN_RISE1_SHIFT |
-		pdata->trigger_level0_en << EXYNOS_TMU_INTEN_RISE0_SHIFT;
+		pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT |
+		pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT |
+		pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT |
+		pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT;
 		if (pdata->threshold_falling)
 			interrupt_en |=
 				interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
@@ -542,9 +541,9 @@ static int exynos_tmu_probe(struct platform_device *pdev)
 
 	/* Register the sensor with thermal management interface */
 	(&exynos_sensor_conf)->private_data = data;
-	exynos_sensor_conf.trip_data.trip_count = pdata->trigger_level0_en +
-			pdata->trigger_level1_en + pdata->trigger_level2_en +
-			pdata->trigger_level3_en;
+	exynos_sensor_conf.trip_data.trip_count = pdata->trigger_enable[0] +
+			pdata->trigger_enable[1] + pdata->trigger_enable[2]+
+			pdata->trigger_enable[3];
 
 	for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
 		exynos_sensor_conf.trip_data.trip_val[i] =
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
index 342fb1f..70cc518 100644
--- a/drivers/thermal/samsung/exynos_tmu.h
+++ b/drivers/thermal/samsung/exynos_tmu.h
@@ -29,6 +29,17 @@ enum calibration_type {
 	TYPE_NONE,
 };
 
+enum calibration_mode {
+	SW_MODE,
+	HW_MODE,
+};
+
+enum trigger_type {
+	THROTTLE,
+	SW_TRIP,
+	HW_TRIP,
+};
+
 enum soc_type {
 	SOC_ARCH_EXYNOS4210 = 1,
 	SOC_ARCH_EXYNOS,
@@ -54,18 +65,13 @@ enum soc_type {
  *	3: temperature for trigger_level3 interrupt
  *	   condition for trigger_level3 interrupt:
  *		current temperature > threshold + trigger_levels[3]
- * @trigger_level0_en:
- *	1 = enable trigger_level0 interrupt,
- *	0 = disable trigger_level0 interrupt
- * @trigger_level1_en:
- *	1 = enable trigger_level1 interrupt,
- *	0 = disable trigger_level1 interrupt
- * @trigger_level2_en:
- *	1 = enable trigger_level2 interrupt,
- *	0 = disable trigger_level2 interrupt
- * @trigger_level3_en:
- *	1 = enable trigger_level3 interrupt,
- *	0 = disable trigger_level3 interrupt
+ * @trigger_type: defines the type of trigger. Possible values are,
+ *	0: THROTTLE trigger type
+ *	1: SW_TRIP trigger type
+ *	2: HW_TRIP
+ * @trigger_enable[]: array to denote which trigger levels are enabled.
+ *	1 = enable trigger_level[] interrupt,
+ *	0 = disable trigger_level[] interrupt
  * @gain: gain of amplifier in the positive-TC generator block
  *	0 <= gain <= 15
  * @reference_voltage: reference voltage of amplifier
@@ -75,7 +81,13 @@ enum soc_type {
  *	000, 100, 101, 110 and 111 can be different modes
  * @type: determines the type of SOC
  * @efuse_value: platform defined fuse value
+ * @min_efuse_value: minimum valid trimming data
+ * @max_efuse_value: maximum valid trimming data
+ * @first_point_trim: temp value of the first point trimming
+ * @second_point_trim: temp value of the second point trimming
+ * @default_temp_offset: default temperature offset in case of no trimming
  * @cal_type: calibration type for temperature
+ * @cal_mode: calibration mode for temperature
  * @freq_clip_table: Table representing frequency reduction percentage.
  * @freq_tab_count: Count of the above table as frequency reduction may
  *	applicable to only some of the trigger levels.
@@ -85,18 +97,22 @@ enum soc_type {
 struct exynos_tmu_platform_data {
 	u8 threshold;
 	u8 threshold_falling;
-	u8 trigger_levels[4];
-	bool trigger_level0_en;
-	bool trigger_level1_en;
-	bool trigger_level2_en;
-	bool trigger_level3_en;
-
+	u8 trigger_levels[MAX_TRIP_COUNT];
+	enum trigger_type trigger_type[MAX_TRIP_COUNT];
+	bool trigger_enable[MAX_TRIP_COUNT];
 	u8 gain;
 	u8 reference_voltage;
 	u8 noise_cancel_mode;
+
 	u32 efuse_value;
+	u32 min_efuse_value;
+	u32 max_efuse_value;
+	u8 first_point_trim;
+	u8 second_point_trim;
+	u8 default_temp_offset;
 
 	enum calibration_type cal_type;
+	enum calibration_mode cal_mode;
 	enum soc_type type;
 	struct freq_clip_table freq_tab[4];
 	unsigned int freq_tab_count;
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
index 13a60ca..ee6a3c9 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.c
+++ b/drivers/thermal/samsung/exynos_tmu_data.c
@@ -22,6 +22,7 @@
 
 #include "exynos_thermal_common.h"
 #include "exynos_tmu.h"
+#include "exynos_tmu_data.h"
 
 #if defined(CONFIG_CPU_EXYNOS4210)
 struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
@@ -29,13 +30,21 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
 	.trigger_levels[0] = 5,
 	.trigger_levels[1] = 20,
 	.trigger_levels[2] = 30,
-	.trigger_level0_en = 1,
-	.trigger_level1_en = 1,
-	.trigger_level2_en = 1,
-	.trigger_level3_en = 0,
+	.trigger_enable[0] = 1,
+	.trigger_enable[1] = 1,
+	.trigger_enable[2] = 1,
+	.trigger_enable[3] = 0,
+	.trigger_type[0] = 0,
+	.trigger_type[1] = 0,
+	.trigger_type[2] = 1,
 	.gain = 15,
 	.reference_voltage = 7,
 	.cal_type = TYPE_ONE_POINT_TRIMMING,
+	.min_efuse_value = 40,
+	.max_efuse_value = 100,
+	.first_point_trim = 25,
+	.second_point_trim = 85,
+	.default_temp_offset = 50,
 	.freq_tab[0] = {
 		.freq_clip_max = 800 * 1000,
 		.temp_level = 85,
@@ -55,15 +64,23 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
 	.trigger_levels[0] = 85,
 	.trigger_levels[1] = 103,
 	.trigger_levels[2] = 110,
-	.trigger_level0_en = 1,
-	.trigger_level1_en = 1,
-	.trigger_level2_en = 1,
-	.trigger_level3_en = 0,
+	.trigger_enable[0] = 1,
+	.trigger_enable[1] = 1,
+	.trigger_enable[2] = 1,
+	.trigger_enable[3] = 0,
+	.trigger_type[0] = 0,
+	.trigger_type[1] = 0,
+	.trigger_type[2] = 1,
 	.gain = 8,
 	.reference_voltage = 16,
 	.noise_cancel_mode = 4,
 	.cal_type = TYPE_ONE_POINT_TRIMMING,
 	.efuse_value = 55,
+	.min_efuse_value = 40,
+	.max_efuse_value = 100,
+	.first_point_trim = 25,
+	.second_point_trim = 85,
+	.default_temp_offset = 50,
 	.freq_tab[0] = {
 		.freq_clip_max = 800 * 1000,
 		.temp_level = 85,
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 08/21] thermal: exynos: Support thermal tripping
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (6 preceding siblings ...)
  2013-05-07 13:00 ` [PATCH V3 07/21] thermal: exynos: Add extra entries in the tmu platform data Amit Daniel Kachhap
@ 2013-05-07 13:00 ` Amit Daniel Kachhap
  2013-05-07 13:00 ` [PATCH V3 09/21] thermal: exynos: Move register definitions from driver file to data file Amit Daniel Kachhap
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:00 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

TMU urgently sends active-high signal (thermal trip) to PMU, and thermal
tripping by hardware logic. Thermal tripping means that PMU cuts off the
whole power of SoC by controlling external voltage regulator.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Jonghwan Choi <jhbird.choi@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/exynos_tmu.c      |    8 +++++++-
 drivers/thermal/samsung/exynos_tmu_data.c |    2 ++
 2 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 77b6a37..23baeeb 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -88,6 +88,7 @@
 #define EXYNOS_TMU_CLEAR_FALL_INT	(0x111 << 12)
 #define EXYNOS_TMU_TRIP_MODE_SHIFT	13
 #define EXYNOS_TMU_TRIP_MODE_MASK	0x7
+#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT	12
 
 #define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
 #define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
@@ -190,7 +191,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 {
 	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 	struct exynos_tmu_platform_data *pdata = data->pdata;
-	unsigned int status, trim_info;
+	unsigned int status, trim_info, con;
 	unsigned int rising_threshold = 0, falling_threshold = 0;
 	int ret = 0, threshold_code, i, trigger_levs = 0;
 
@@ -255,6 +256,11 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 					falling_threshold |=
 						threshold_code << 8 * i;
 			}
+			if (pdata->trigger_type[i] != HW_TRIP)
+				continue;
+			con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
+			con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
+			writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
 		}
 
 		writel(rising_threshold,
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
index ee6a3c9..6b937f5 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.c
+++ b/drivers/thermal/samsung/exynos_tmu_data.c
@@ -64,6 +64,7 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
 	.trigger_levels[0] = 85,
 	.trigger_levels[1] = 103,
 	.trigger_levels[2] = 110,
+	.trigger_levels[3] = 120,
 	.trigger_enable[0] = 1,
 	.trigger_enable[1] = 1,
 	.trigger_enable[2] = 1,
@@ -71,6 +72,7 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
 	.trigger_type[0] = 0,
 	.trigger_type[1] = 0,
 	.trigger_type[2] = 1,
+	.trigger_type[3] = 2,
 	.gain = 8,
 	.reference_voltage = 16,
 	.noise_cancel_mode = 4,
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 09/21] thermal: exynos: Move register definitions from driver file to data file
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (7 preceding siblings ...)
  2013-05-07 13:00 ` [PATCH V3 08/21] thermal: exynos: Support thermal tripping Amit Daniel Kachhap
@ 2013-05-07 13:00 ` Amit Daniel Kachhap
  2013-05-09 14:32     ` Eduardo Valentin
  2013-05-07 13:01 ` [PATCH V3 10/21] thermal: exynos: Fix to clear only the generated interrupts Amit Daniel Kachhap
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:00 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch migrates the TMU register definition/bitfields to data file. This
is needed to support SoC's which use the same TMU controller but register
validity, offsets or bitfield may slightly vary across SOC's.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/exynos_tmu.c      |  177 +++++++++-------------------
 drivers/thermal/samsung/exynos_tmu.h      |   76 ++++++++++++
 drivers/thermal/samsung/exynos_tmu_data.c |   59 ++++++++++
 drivers/thermal/samsung/exynos_tmu_data.h |   68 +++++++++++
 4 files changed, 260 insertions(+), 120 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 23baeeb..97b87aa 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -36,77 +36,6 @@
 #include "exynos_tmu.h"
 #include "exynos_tmu_data.h"
 
-/* Exynos generic registers */
-#define EXYNOS_TMU_REG_TRIMINFO		0x0
-#define EXYNOS_TMU_REG_CONTROL		0x20
-#define EXYNOS_TMU_REG_STATUS		0x28
-#define EXYNOS_TMU_REG_CURRENT_TEMP	0x40
-#define EXYNOS_TMU_REG_INTEN		0x70
-#define EXYNOS_TMU_REG_INTSTAT		0x74
-#define EXYNOS_TMU_REG_INTCLEAR		0x78
-
-#define EXYNOS_TMU_TRIM_TEMP_MASK	0xff
-#define EXYNOS_TMU_GAIN_SHIFT		8
-#define EXYNOS_TMU_GAIN_MASK		0xf
-#define EXYNOS_TMU_REF_VOLTAGE_SHIFT	24
-#define EXYNOS_TMU_REF_VOLTAGE_MASK	0x1f
-#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK	0xf
-#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT	8
-#define EXYNOS_TMU_CORE_EN_SHIFT	0
-
-/* Exynos4210 specific registers */
-#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP	0x44
-#define EXYNOS4210_TMU_REG_TRIG_LEVEL0	0x50
-#define EXYNOS4210_TMU_REG_TRIG_LEVEL1	0x54
-#define EXYNOS4210_TMU_REG_TRIG_LEVEL2	0x58
-#define EXYNOS4210_TMU_REG_TRIG_LEVEL3	0x5C
-#define EXYNOS4210_TMU_REG_PAST_TEMP0	0x60
-#define EXYNOS4210_TMU_REG_PAST_TEMP1	0x64
-#define EXYNOS4210_TMU_REG_PAST_TEMP2	0x68
-#define EXYNOS4210_TMU_REG_PAST_TEMP3	0x6C
-
-#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK	0x1
-#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK	0x10
-#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK	0x100
-#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK	0x1000
-#define EXYNOS4210_TMU_TRIG_LEVEL_MASK	0x1111
-#define EXYNOS4210_TMU_INTCLEAR_VAL	0x1111
-
-/* Exynos5250 and Exynos4412 specific registers */
-#define EXYNOS_TMU_TRIMINFO_CON	0x14
-#define EXYNOS_THD_TEMP_RISE		0x50
-#define EXYNOS_THD_TEMP_FALL		0x54
-#define EXYNOS_EMUL_CON		0x80
-
-#define EXYNOS_TRIMINFO_RELOAD		0x1
-#define EXYNOS_TRIMINFO_SHIFT		0x0
-#define EXYNOS_TMU_RISE_INT_MASK	0x111
-#define EXYNOS_TMU_RISE_INT_SHIFT	0
-#define EXYNOS_TMU_FALL_INT_MASK	0x111
-#define EXYNOS_TMU_FALL_INT_SHIFT	12
-#define EXYNOS_TMU_CLEAR_RISE_INT	0x111
-#define EXYNOS_TMU_CLEAR_FALL_INT	(0x111 << 12)
-#define EXYNOS_TMU_TRIP_MODE_SHIFT	13
-#define EXYNOS_TMU_TRIP_MODE_MASK	0x7
-#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT	12
-
-#define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
-#define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
-#define EXYNOS_TMU_INTEN_RISE2_SHIFT	8
-#define EXYNOS_TMU_INTEN_RISE3_SHIFT	12
-#define EXYNOS_TMU_INTEN_FALL0_SHIFT	16
-#define EXYNOS_TMU_INTEN_FALL1_SHIFT	20
-#define EXYNOS_TMU_INTEN_FALL2_SHIFT	24
-
-#ifdef CONFIG_THERMAL_EMULATION
-#define EXYNOS_EMUL_TIME	0x57F0
-#define EXYNOS_EMUL_TIME_MASK	0xffff
-#define EXYNOS_EMUL_TIME_SHIFT	16
-#define EXYNOS_EMUL_DATA_SHIFT	8
-#define EXYNOS_EMUL_DATA_MASK	0xFF
-#define EXYNOS_EMUL_ENABLE	0x1
-#endif /* CONFIG_THERMAL_EMULATION */
-
 struct exynos_tmu_data {
 	struct exynos_tmu_platform_data *pdata;
 	struct resource *mem;
@@ -191,6 +120,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 {
 	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 	struct exynos_tmu_platform_data *pdata = data->pdata;
+	struct exynos_tmu_registers *reg = pdata->registers;
 	unsigned int status, trim_info, con;
 	unsigned int rising_threshold = 0, falling_threshold = 0;
 	int ret = 0, threshold_code, i, trigger_levs = 0;
@@ -198,20 +128,20 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 	mutex_lock(&data->lock);
 	clk_enable(data->clk);
 
-	status = readb(data->base + EXYNOS_TMU_REG_STATUS);
+	status = readb(data->base + reg->tmu_status);
 	if (!status) {
 		ret = -EBUSY;
 		goto out;
 	}
 
-	if (data->soc == SOC_ARCH_EXYNOS) {
-		__raw_writel(EXYNOS_TRIMINFO_RELOAD,
-				data->base + EXYNOS_TMU_TRIMINFO_CON);
-	}
+	if (data->soc == SOC_ARCH_EXYNOS)
+		__raw_writel(1, data->base + reg->triminfo_ctrl);
+
 	/* Save trimming info in order to perform calibration */
-	trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
-	data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
-	data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
+	trim_info = readl(data->base + reg->triminfo_data);
+	data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
+	data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
+				EXYNOS_TMU_TEMP_MASK);
 
 	if ((pdata->min_efuse_value > data->temp_error1) ||
 			(data->temp_error1 > pdata->max_efuse_value) ||
@@ -231,13 +161,12 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 			goto out;
 		}
 		writeb(threshold_code,
-			data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
+			data->base + reg->threshold_temp);
 		for (i = 0; i < trigger_levs; i++)
 			writeb(pdata->trigger_levels[i],
-			data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
+			data->base + reg->threshold_th0 + i * 4);
 
-		writel(EXYNOS4210_TMU_INTCLEAR_VAL,
-			data->base + EXYNOS_TMU_REG_INTCLEAR);
+		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
 	} else if (data->soc == SOC_ARCH_EXYNOS) {
 		/* Write temperature code for rising and falling threshold */
 		for (i = 0; i < trigger_levs; i++) {
@@ -258,18 +187,19 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 			}
 			if (pdata->trigger_type[i] != HW_TRIP)
 				continue;
-			con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
-			con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
-			writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
+			con = readl(data->base + reg->tmu_ctrl);
+			con |= (1 << reg->therm_trip_en_shift);
+			writel(con, data->base + reg->tmu_ctrl);
 		}
 
 		writel(rising_threshold,
-				data->base + EXYNOS_THD_TEMP_RISE);
+				data->base + reg->threshold_th0);
 		writel(falling_threshold,
-				data->base + EXYNOS_THD_TEMP_FALL);
+				data->base + reg->threshold_th1);
 
-		writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
-				data->base + EXYNOS_TMU_REG_INTCLEAR);
+		writel((reg->inten_rise_mask << reg->inten_rise_shift) |
+			(reg->inten_fall_mask << reg->inten_fall_shift),
+				data->base + reg->tmu_intclear);
 	}
 out:
 	clk_disable(data->clk);
@@ -282,46 +212,46 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
 {
 	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 	struct exynos_tmu_platform_data *pdata = data->pdata;
+	struct exynos_tmu_registers *reg = pdata->registers;
 	unsigned int con, interrupt_en;
 
 	mutex_lock(&data->lock);
 	clk_enable(data->clk);
 
-	con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
+	con = readl(data->base + reg->tmu_ctrl);
 
 	if (pdata->reference_voltage) {
-		con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK <<
-				EXYNOS_TMU_REF_VOLTAGE_SHIFT);
-		con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
+		con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
+		con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
 	}
 
 	if (pdata->gain) {
-		con &= ~(EXYNOS_TMU_GAIN_MASK << EXYNOS_TMU_GAIN_SHIFT);
-		con |= (pdata->gain << EXYNOS_TMU_GAIN_SHIFT);
+		con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
+		con |= (pdata->gain << reg->buf_slope_sel_shift);
 	}
 
 	if (pdata->noise_cancel_mode) {
-		con &= ~(EXYNOS_TMU_TRIP_MODE_MASK <<
-					EXYNOS_TMU_TRIP_MODE_SHIFT);
-		con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
+		con &= ~(reg->therm_trip_mode_mask <<
+					reg->therm_trip_mode_shift);
+		con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
 	}
 
 	if (on) {
-		con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
+		con |= (1 << reg->core_en_shift);
 		interrupt_en =
-		pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT |
-		pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT |
-		pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT |
-		pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT;
+			pdata->trigger_enable[3] << reg->inten_rise3_shift |
+			pdata->trigger_enable[2] << reg->inten_rise2_shift |
+			pdata->trigger_enable[1] << reg->inten_rise1_shift |
+			pdata->trigger_enable[0] << reg->inten_rise0_shift;
 		if (pdata->threshold_falling)
 			interrupt_en |=
-				interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
+				interrupt_en << reg->inten_fall0_shift;
 	} else {
-		con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
+		con &= ~(1 << reg->core_en_shift);
 		interrupt_en = 0; /* Disable all interrupts */
 	}
-	writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
-	writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
+	writel(interrupt_en, data->base + reg->tmu_inten);
+	writel(con, data->base + reg->tmu_ctrl);
 
 	clk_disable(data->clk);
 	mutex_unlock(&data->lock);
@@ -329,13 +259,15 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
 
 static int exynos_tmu_read(struct exynos_tmu_data *data)
 {
+	struct exynos_tmu_platform_data *pdata = data->pdata;
+	struct exynos_tmu_registers *reg = pdata->registers;
 	u8 temp_code;
 	int temp;
 
 	mutex_lock(&data->lock);
 	clk_enable(data->clk);
 
-	temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
+	temp_code = readb(data->base + reg->tmu_cur_temp);
 	temp = code_to_temp(data, temp_code);
 
 	clk_disable(data->clk);
@@ -348,7 +280,9 @@ static int exynos_tmu_read(struct exynos_tmu_data *data)
 static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
 {
 	struct exynos_tmu_data *data = drv_data;
-	unsigned int reg;
+	struct exynos_tmu_platform_data *pdata = data->pdata;
+	struct exynos_tmu_registers *reg = pdata->registers;
+	unsigned int val;
 	int ret = -EINVAL;
 
 	if (data->soc == SOC_ARCH_EXYNOS4210)
@@ -360,19 +294,19 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
 	mutex_lock(&data->lock);
 	clk_enable(data->clk);
 
-	reg = readl(data->base + EXYNOS_EMUL_CON);
+	val = readl(data->base + reg->emul_con);
 
 	if (temp) {
 		temp /= MCELSIUS;
 
-		reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
+		val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
 			(temp_to_code(data, temp)
-			 << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
+			 << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
 	} else {
-		reg &= ~EXYNOS_EMUL_ENABLE;
+		val &= ~EXYNOS_EMUL_ENABLE;
 	}
 
-	writel(reg, data->base + EXYNOS_EMUL_CON);
+	writel(val, data->base + reg->emul_con);
 
 	clk_disable(data->clk);
 	mutex_unlock(&data->lock);
@@ -389,17 +323,20 @@ static void exynos_tmu_work(struct work_struct *work)
 {
 	struct exynos_tmu_data *data = container_of(work,
 			struct exynos_tmu_data, irq_work);
+	struct exynos_tmu_platform_data *pdata = data->pdata;
+	struct exynos_tmu_registers *reg = pdata->registers;
 
 	exynos_report_trigger();
 	mutex_lock(&data->lock);
 	clk_enable(data->clk);
+
 	if (data->soc == SOC_ARCH_EXYNOS)
-		writel(EXYNOS_TMU_CLEAR_RISE_INT |
-				EXYNOS_TMU_CLEAR_FALL_INT,
-				data->base + EXYNOS_TMU_REG_INTCLEAR);
+		writel((reg->inten_rise_mask << reg->inten_rise_shift) |
+			(reg->inten_fall_mask << reg->inten_fall_shift),
+				data->base + reg->tmu_intclear);
 	else
-		writel(EXYNOS4210_TMU_INTCLEAR_VAL,
-				data->base + EXYNOS_TMU_REG_INTCLEAR);
+		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
+
 	clk_disable(data->clk);
 	mutex_unlock(&data->lock);
 
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
index 70cc518..1e5e492 100644
--- a/drivers/thermal/samsung/exynos_tmu.h
+++ b/drivers/thermal/samsung/exynos_tmu.h
@@ -46,6 +46,81 @@ enum soc_type {
 };
 
 /**
+ * struct exynos_tmu_register - register descriptors to access registers and
+ * bitfields. The register validity, offsets and bitfield values may vary
+ * slightly across different exynos SOC's.
+ */
+struct exynos_tmu_registers {
+	u32	triminfo_data;
+	u32	triminfo_25_shift;
+	u32	triminfo_85_shift;
+
+	u32	triminfo_ctrl;
+	u32	triminfo_reload_shift;
+
+	u32	tmu_ctrl;
+	u32	buf_vref_sel_shift;
+	u32	buf_vref_sel_mask;
+	u32	therm_trip_mode_shift;
+	u32	therm_trip_mode_mask;
+	u32	therm_trip_en_shift;
+	u32	buf_slope_sel_shift;
+	u32	buf_slope_sel_mask;
+	u32	therm_trip_tq_en_shift;
+	u32	core_en_shift;
+
+	u32	tmu_status;
+
+	u32	tmu_cur_temp;
+	u32	tmu_cur_temp_shift;
+
+	u32	threshold_temp;
+
+	u32	threshold_th0;
+	u32	threshold_th0_l0_shift;
+	u32	threshold_th0_l1_shift;
+	u32	threshold_th0_l2_shift;
+	u32	threshold_th0_l3_shift;
+
+	u32	threshold_th1;
+	u32	threshold_th1_l0_shift;
+	u32	threshold_th1_l1_shift;
+	u32	threshold_th1_l2_shift;
+	u32	threshold_th1_l3_shift;
+
+	u32	threshold_th2;
+	u32	threshold_th2_l0_shift;
+
+	u32	threshold_th3;
+	u32	threshold_th3_l0_shift;
+
+	u32	tmu_inten;
+	u32	inten_rise_shift;
+	u32	inten_rise_mask;
+	u32	inten_fall_shift;
+	u32	inten_fall_mask;
+	u32	inten_rise0_shift;
+	u32	inten_rise1_shift;
+	u32	inten_rise2_shift;
+	u32	inten_rise3_shift;
+	u32	inten_fall0_shift;
+	u32	inten_fall1_shift;
+	u32	inten_fall2_shift;
+	u32	inten_fall3_shift;
+
+	u32	tmu_intstat;
+
+	u32	tmu_intclear;
+
+	u32	tmu_evten;
+
+	u32	emul_con;
+	u32	emul_temp_shift;
+	u32	emul_time_shift;
+	u32	emul_time_mask;
+};
+
+/**
  * struct exynos_tmu_platform_data
  * @threshold: basic temperature for generating interrupt
  *	       25 <= threshold <= 125 [unit: degree Celsius]
@@ -116,5 +191,6 @@ struct exynos_tmu_platform_data {
 	enum soc_type type;
 	struct freq_clip_table freq_tab[4];
 	unsigned int freq_tab_count;
+	struct exynos_tmu_registers *registers;
 };
 #endif /* _LINUX_EXYNOS_THERMAL_H */
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
index 6b937f5..3a1ded1 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.c
+++ b/drivers/thermal/samsung/exynos_tmu_data.c
@@ -25,6 +25,28 @@
 #include "exynos_tmu_data.h"
 
 #if defined(CONFIG_CPU_EXYNOS4210)
+static struct exynos_tmu_registers exynos4210_tmu_registers = {
+	.triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
+	.triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
+	.triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
+	.tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
+	.buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
+	.buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
+	.buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
+	.buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
+	.core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
+	.tmu_status = EXYNOS_TMU_REG_STATUS,
+	.tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
+	.threshold_temp = EXYNOS4210_TMU_REG_THRESHOLD_TEMP,
+	.threshold_th0 = EXYNOS4210_TMU_REG_TRIG_LEVEL0,
+	.tmu_inten = EXYNOS_TMU_REG_INTEN,
+	.inten_rise_mask = EXYNOS4210_TMU_TRIG_LEVEL_MASK,
+	.inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
+	.inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
+	.inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
+	.inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
+	.tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
+};
 struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
 	.threshold = 80,
 	.trigger_levels[0] = 5,
@@ -55,10 +77,46 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
 	},
 	.freq_tab_count = 2,
 	.type = SOC_ARCH_EXYNOS4210,
+	.registers = &exynos4210_tmu_registers,
 };
 #endif
 
 #if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
+static struct exynos_tmu_registers exynos5250_tmu_registers = {
+	.triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
+	.triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
+	.triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
+	.triminfo_ctrl = EXYNOS_TMU_TRIMINFO_CON,
+	.triminfo_reload_shift = EXYNOS_TRIMINFO_RELOAD_SHIFT,
+	.tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
+	.buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
+	.buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
+	.therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
+	.therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
+	.therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
+	.buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
+	.buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
+	.core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
+	.tmu_status = EXYNOS_TMU_REG_STATUS,
+	.tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
+	.threshold_th0 = EXYNOS_THD_TEMP_RISE,
+	.threshold_th1 = EXYNOS_THD_TEMP_FALL,
+	.tmu_inten = EXYNOS_TMU_REG_INTEN,
+	.inten_rise_mask = EXYNOS_TMU_RISE_INT_MASK,
+	.inten_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
+	.inten_fall_mask = EXYNOS_TMU_FALL_INT_MASK,
+	.inten_fall_shift = EXYNOS_TMU_FALL_INT_SHIFT,
+	.inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
+	.inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
+	.inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
+	.inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
+	.inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
+	.tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
+	.emul_con = EXYNOS_EMUL_CON,
+	.emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
+	.emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
+	.emul_time_mask = EXYNOS_EMUL_TIME_MASK,
+};
 struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
 	.threshold_falling = 10,
 	.trigger_levels[0] = 85,
@@ -93,5 +151,6 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
 	},
 	.freq_tab_count = 2,
 	.type = SOC_ARCH_EXYNOS,
+	.registers = &exynos5250_tmu_registers,
 };
 #endif
diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
index 5b69711..0560413 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.h
+++ b/drivers/thermal/samsung/exynos_tmu_data.h
@@ -23,6 +23,74 @@
 #ifndef _LINUX_EXYNOS_TMU_DATA_H
 #define _LINUX_EXYNOS_TMU_DATA_H
 
+/* Exynos generic registers */
+#define EXYNOS_TMU_REG_TRIMINFO		0x0
+#define EXYNOS_TMU_REG_CONTROL		0x20
+#define EXYNOS_TMU_REG_STATUS		0x28
+#define EXYNOS_TMU_REG_CURRENT_TEMP	0x40
+#define EXYNOS_TMU_REG_INTEN		0x70
+#define EXYNOS_TMU_REG_INTSTAT		0x74
+#define EXYNOS_TMU_REG_INTCLEAR		0x78
+
+#define EXYNOS_TMU_TEMP_MASK		0xff
+#define EXYNOS_TMU_REF_VOLTAGE_SHIFT	24
+#define EXYNOS_TMU_REF_VOLTAGE_MASK	0x1f
+#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK	0xf
+#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT	8
+#define EXYNOS_TMU_CORE_EN_SHIFT	0
+
+/* Exynos4210 specific registers */
+#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP	0x44
+#define EXYNOS4210_TMU_REG_TRIG_LEVEL0	0x50
+#define EXYNOS4210_TMU_REG_TRIG_LEVEL1	0x54
+#define EXYNOS4210_TMU_REG_TRIG_LEVEL2	0x58
+#define EXYNOS4210_TMU_REG_TRIG_LEVEL3	0x5C
+#define EXYNOS4210_TMU_REG_PAST_TEMP0	0x60
+#define EXYNOS4210_TMU_REG_PAST_TEMP1	0x64
+#define EXYNOS4210_TMU_REG_PAST_TEMP2	0x68
+#define EXYNOS4210_TMU_REG_PAST_TEMP3	0x6C
+
+#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK	0x1
+#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK	0x10
+#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK	0x100
+#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK	0x1000
+#define EXYNOS4210_TMU_TRIG_LEVEL_MASK	0x1111
+#define EXYNOS4210_TMU_INTCLEAR_VAL	0x1111
+
+/* Exynos5250 and Exynos4412 specific registers */
+#define EXYNOS_TMU_TRIMINFO_CON	0x14
+#define EXYNOS_THD_TEMP_RISE		0x50
+#define EXYNOS_THD_TEMP_FALL		0x54
+#define EXYNOS_EMUL_CON		0x80
+
+#define EXYNOS_TRIMINFO_RELOAD_SHIFT	1
+#define EXYNOS_TRIMINFO_25_SHIFT	0
+#define EXYNOS_TRIMINFO_85_SHIFT	8
+#define EXYNOS_TMU_RISE_INT_MASK	0x111
+#define EXYNOS_TMU_RISE_INT_SHIFT	0
+#define EXYNOS_TMU_FALL_INT_MASK	0x111
+#define EXYNOS_TMU_FALL_INT_SHIFT	12
+#define EXYNOS_TMU_CLEAR_RISE_INT	0x111
+#define EXYNOS_TMU_CLEAR_FALL_INT	(0x111 << 12)
+#define EXYNOS_TMU_TRIP_MODE_SHIFT	13
+#define EXYNOS_TMU_TRIP_MODE_MASK	0x7
+#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT	12
+
+#define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
+#define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
+#define EXYNOS_TMU_INTEN_RISE2_SHIFT	8
+#define EXYNOS_TMU_INTEN_RISE3_SHIFT	12
+#define EXYNOS_TMU_INTEN_FALL0_SHIFT	16
+#define EXYNOS_TMU_INTEN_FALL1_SHIFT	20
+#define EXYNOS_TMU_INTEN_FALL2_SHIFT	24
+
+#define EXYNOS_EMUL_TIME	0x57F0
+#define EXYNOS_EMUL_TIME_MASK	0xffff
+#define EXYNOS_EMUL_TIME_SHIFT	16
+#define EXYNOS_EMUL_DATA_SHIFT	8
+#define EXYNOS_EMUL_DATA_MASK	0xFF
+#define EXYNOS_EMUL_ENABLE	0x1
+
 #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
 extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
 #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 10/21] thermal: exynos: Fix to clear only the generated interrupts
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (8 preceding siblings ...)
  2013-05-07 13:00 ` [PATCH V3 09/21] thermal: exynos: Move register definitions from driver file to data file Amit Daniel Kachhap
@ 2013-05-07 13:01 ` Amit Daniel Kachhap
  2013-05-09 14:33     ` Eduardo Valentin
  2013-05-07 13:01 ` [PATCH V3 11/21] thermal: exynos: Add support for instance based register/unregister Amit Daniel Kachhap
                   ` (10 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch uses the TMU status register to know the generated interrupts
and only clear them in the interrupt handler.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/exynos_tmu.c      |   10 ++++------
 drivers/thermal/samsung/exynos_tmu_data.c |    2 ++
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 97b87aa..082d5a2 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -325,17 +325,15 @@ static void exynos_tmu_work(struct work_struct *work)
 			struct exynos_tmu_data, irq_work);
 	struct exynos_tmu_platform_data *pdata = data->pdata;
 	struct exynos_tmu_registers *reg = pdata->registers;
+	unsigned int val_irq;
 
 	exynos_report_trigger();
 	mutex_lock(&data->lock);
 	clk_enable(data->clk);
 
-	if (data->soc == SOC_ARCH_EXYNOS)
-		writel((reg->inten_rise_mask << reg->inten_rise_shift) |
-			(reg->inten_fall_mask << reg->inten_fall_shift),
-				data->base + reg->tmu_intclear);
-	else
-		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
+	val_irq = readl(data->base + reg->tmu_intstat);
+	/* clear the interrupts */
+	writel(val_irq, data->base + reg->tmu_intclear);
 
 	clk_disable(data->clk);
 	mutex_unlock(&data->lock);
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
index 3a1ded1..7322597 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.c
+++ b/drivers/thermal/samsung/exynos_tmu_data.c
@@ -45,6 +45,7 @@ static struct exynos_tmu_registers exynos4210_tmu_registers = {
 	.inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
 	.inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
 	.inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
+	.tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
 	.tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
 };
 struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
@@ -111,6 +112,7 @@ static struct exynos_tmu_registers exynos5250_tmu_registers = {
 	.inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
 	.inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
 	.inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
+	.tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
 	.tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
 	.emul_con = EXYNOS_EMUL_CON,
 	.emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 11/21] thermal: exynos: Add support for instance based register/unregister
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (9 preceding siblings ...)
  2013-05-07 13:01 ` [PATCH V3 10/21] thermal: exynos: Fix to clear only the generated interrupts Amit Daniel Kachhap
@ 2013-05-07 13:01 ` Amit Daniel Kachhap
  2013-05-07 13:01 ` [PATCH V3 12/21] thermal: exynos: Modify private_data to appropriate name driver_data Amit Daniel Kachhap
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This code modifies the thermal driver to have multiple thermal zone
support by replacing the global thermal zone variable with device data
member of thermal_zone_device.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/exynos_thermal_common.c |   36 ++++++++++++++--------
 drivers/thermal/samsung/exynos_thermal_common.h |    9 +++--
 drivers/thermal/samsung/exynos_tmu.c            |   15 +++++----
 3 files changed, 36 insertions(+), 24 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
index dae5476..d4cd5ec 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.c
+++ b/drivers/thermal/samsung/exynos_thermal_common.c
@@ -41,12 +41,11 @@ struct exynos_thermal_zone {
 	bool bind;
 };
 
-static struct exynos_thermal_zone *th_zone;
-
 /* Get mode callback functions for thermal zone */
 static int exynos_get_mode(struct thermal_zone_device *thermal,
 			enum thermal_device_mode *mode)
 {
+	struct exynos_thermal_zone *th_zone = thermal->devdata;
 	if (th_zone)
 		*mode = th_zone->mode;
 	return 0;
@@ -56,25 +55,26 @@ static int exynos_get_mode(struct thermal_zone_device *thermal,
 static int exynos_set_mode(struct thermal_zone_device *thermal,
 			enum thermal_device_mode mode)
 {
-	if (!th_zone->therm_dev) {
+	struct exynos_thermal_zone *th_zone = thermal->devdata;
+	if (!th_zone) {
 		pr_notice("thermal zone not registered\n");
 		return 0;
 	}
 
-	mutex_lock(&th_zone->therm_dev->lock);
+	mutex_lock(&thermal->lock);
 
 	if (mode == THERMAL_DEVICE_ENABLED &&
 		!th_zone->sensor_conf->trip_data.trigger_falling)
-		th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
+		thermal->polling_delay = IDLE_INTERVAL;
 	else
-		th_zone->therm_dev->polling_delay = 0;
+		thermal->polling_delay = 0;
 
-	mutex_unlock(&th_zone->therm_dev->lock);
+	mutex_unlock(&thermal->lock);
 
 	th_zone->mode = mode;
-	thermal_zone_device_update(th_zone->therm_dev);
+	thermal_zone_device_update(thermal);
 	pr_info("thermal polling set for duration=%d msec\n",
-				th_zone->therm_dev->polling_delay);
+				thermal->polling_delay);
 	return 0;
 }
 
@@ -101,6 +101,8 @@ static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
 static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
 				unsigned long *temp)
 {
+	struct exynos_thermal_zone *th_zone = thermal->devdata;
+
 	if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
 		return -EINVAL;
 
@@ -127,6 +129,7 @@ static int exynos_bind(struct thermal_zone_device *thermal,
 {
 	int ret = 0, i, tab_size, level;
 	struct freq_clip_table *tab_ptr, *clip_data;
+	struct exynos_thermal_zone *th_zone = thermal->devdata;
 	struct thermal_sensor_conf *data = th_zone->sensor_conf;
 
 	tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
@@ -173,6 +176,7 @@ static int exynos_unbind(struct thermal_zone_device *thermal,
 			struct thermal_cooling_device *cdev)
 {
 	int ret = 0, i, tab_size;
+	struct exynos_thermal_zone *th_zone = thermal->devdata;
 	struct thermal_sensor_conf *data = th_zone->sensor_conf;
 
 	if (th_zone->bind == false)
@@ -215,6 +219,7 @@ static int exynos_unbind(struct thermal_zone_device *thermal,
 static int exynos_get_temp(struct thermal_zone_device *thermal,
 			unsigned long *temp)
 {
+	struct exynos_thermal_zone *th_zone = thermal->devdata;
 	void *data;
 
 	if (!th_zone->sensor_conf) {
@@ -234,6 +239,7 @@ static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
 {
 	void *data;
 	int ret = -EINVAL;
+	struct exynos_thermal_zone *th_zone = thermal->devdata;
 
 	if (!th_zone->sensor_conf) {
 		pr_info("Temperature sensor not initialised\n");
@@ -281,11 +287,12 @@ static struct thermal_zone_device_ops const exynos_dev_ops = {
  * This function may be called from interrupt based temperature sensor
  * when threshold is changed.
  */
-void exynos_report_trigger(void)
+void exynos_report_trigger(struct thermal_sensor_conf *conf)
 {
 	unsigned int i;
 	char data[10];
 	char *envp[] = { data, NULL };
+	struct exynos_thermal_zone *th_zone = conf->pzone_data;
 
 	if (!th_zone || !th_zone->therm_dev)
 		return;
@@ -326,6 +333,7 @@ int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
 {
 	int ret;
 	struct cpumask mask_val;
+	struct exynos_thermal_zone *th_zone;
 
 	if (!sensor_conf || !sensor_conf->read_temperature) {
 		pr_err("Temperature sensor not initialised\n");
@@ -347,7 +355,7 @@ int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
 	th_zone->cool_dev_size++;
 
 	th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
-			EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
+			EXYNOS_ZONE_COUNT, 0, th_zone, &exynos_dev_ops, NULL, 0,
 			sensor_conf->trip_data.trigger_falling ?
 			0 : IDLE_INTERVAL);
 
@@ -357,20 +365,22 @@ int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
 		goto err_unregister;
 	}
 	th_zone->mode = THERMAL_DEVICE_ENABLED;
+	sensor_conf->pzone_data = th_zone;
 
 	pr_info("Exynos: Kernel Thermal management registered\n");
 
 	return 0;
 
 err_unregister:
-	exynos_unregister_thermal();
+	exynos_unregister_thermal(sensor_conf);
 	return ret;
 }
 
 /* Un-Register with the in-kernel thermal management */
-void exynos_unregister_thermal(void)
+void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf)
 {
 	int i;
+	struct exynos_thermal_zone *th_zone = sensor_conf->pzone_data;
 
 	if (!th_zone)
 		return;
diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
index 3b85858..1105ecd 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.h
+++ b/drivers/thermal/samsung/exynos_thermal_common.h
@@ -77,21 +77,22 @@ struct thermal_sensor_conf {
 	struct thermal_trip_point_conf trip_data;
 	struct thermal_cooling_conf cooling_data;
 	void *private_data;
+	void *pzone_data;
 };
 
 /*Functions used exynos based thermal sensor driver*/
 #ifdef CONFIG_EXYNOS_THERMAL_CORE
-void exynos_unregister_thermal(void);
+void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf);
 int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
-void exynos_report_trigger(void);
+void exynos_report_trigger(struct thermal_sensor_conf *sensor_conf);
 #else
 static inline void
-exynos_unregister_thermal(void) { return; }
+exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf) { return; }
 
 static inline int
 exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
 
 static inline void
-exynos_report_trigger(void) { return; }
+exynos_report_trigger(struct thermal_sensor_conf *sensor_conf) { return; }
 #endif /* CONFIG_EXYNOS_COMMON */
 #endif /* _LINUX_EXYNOS_THERMAL_COMMON_H */
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 082d5a2..133d3f5 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -319,6 +319,12 @@ static int exynos_tmu_set_emulation(void *drv_data,	unsigned long temp)
 	{ return -EINVAL; }
 #endif/*CONFIG_THERMAL_EMULATION*/
 
+static struct thermal_sensor_conf exynos_sensor_conf = {
+	.name			= "exynos-therm",
+	.read_temperature	= (int (*)(void *))exynos_tmu_read,
+	.write_emul_temp	= exynos_tmu_set_emulation,
+};
+
 static void exynos_tmu_work(struct work_struct *work)
 {
 	struct exynos_tmu_data *data = container_of(work,
@@ -327,7 +333,7 @@ static void exynos_tmu_work(struct work_struct *work)
 	struct exynos_tmu_registers *reg = pdata->registers;
 	unsigned int val_irq;
 
-	exynos_report_trigger();
+	exynos_report_trigger(&exynos_sensor_conf);
 	mutex_lock(&data->lock);
 	clk_enable(data->clk);
 
@@ -350,11 +356,6 @@ static irqreturn_t exynos_tmu_irq(int irq, void *id)
 
 	return IRQ_HANDLED;
 }
-static struct thermal_sensor_conf exynos_sensor_conf = {
-	.name			= "exynos-therm",
-	.read_temperature	= (int (*)(void *))exynos_tmu_read,
-	.write_emul_temp	= exynos_tmu_set_emulation,
-};
 
 #ifdef CONFIG_OF
 static const struct of_device_id exynos_tmu_match[] = {
@@ -520,7 +521,7 @@ static int exynos_tmu_remove(struct platform_device *pdev)
 
 	exynos_tmu_control(pdev, false);
 
-	exynos_unregister_thermal();
+	exynos_unregister_thermal(&exynos_sensor_conf);
 
 	clk_unprepare(data->clk);
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 12/21] thermal: exynos: Modify private_data to appropriate name driver_data
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (10 preceding siblings ...)
  2013-05-07 13:01 ` [PATCH V3 11/21] thermal: exynos: Add support for instance based register/unregister Amit Daniel Kachhap
@ 2013-05-07 13:01 ` Amit Daniel Kachhap
  2013-05-07 13:01 ` [PATCH V3 13/21] thermal: exynos: Return success even if no cooling data supplied Amit Daniel Kachhap
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch renames member private_data to driver_data of the thermal
zone registration structure as this item stores the driver related
data and uses it to call the driver related callbacks.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/exynos_thermal_common.c |    4 ++--
 drivers/thermal/samsung/exynos_thermal_common.h |    2 +-
 drivers/thermal/samsung/exynos_tmu.c            |    2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
index d4cd5ec..c0e4bdb 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.c
+++ b/drivers/thermal/samsung/exynos_thermal_common.c
@@ -226,7 +226,7 @@ static int exynos_get_temp(struct thermal_zone_device *thermal,
 		pr_info("Temperature sensor not initialised\n");
 		return -EINVAL;
 	}
-	data = th_zone->sensor_conf->private_data;
+	data = th_zone->sensor_conf->driver_data;
 	*temp = th_zone->sensor_conf->read_temperature(data);
 	/* convert the temperature into millicelsius */
 	*temp = *temp * MCELSIUS;
@@ -245,7 +245,7 @@ static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
 		pr_info("Temperature sensor not initialised\n");
 		return -EINVAL;
 	}
-	data = th_zone->sensor_conf->private_data;
+	data = th_zone->sensor_conf->driver_data;
 	if (th_zone->sensor_conf->write_emul_temp)
 		ret = th_zone->sensor_conf->write_emul_temp(data, temp);
 	return ret;
diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
index 1105ecd..0acde95 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.h
+++ b/drivers/thermal/samsung/exynos_thermal_common.h
@@ -76,7 +76,7 @@ struct thermal_sensor_conf {
 	int (*write_emul_temp)(void *drv_data, unsigned long temp);
 	struct thermal_trip_point_conf trip_data;
 	struct thermal_cooling_conf cooling_data;
-	void *private_data;
+	void *driver_data;
 	void *pzone_data;
 };
 
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 133d3f5..bdf40ef 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -482,7 +482,7 @@ static int exynos_tmu_probe(struct platform_device *pdev)
 	exynos_tmu_control(pdev, true);
 
 	/* Register the sensor with thermal management interface */
-	(&exynos_sensor_conf)->private_data = data;
+	(&exynos_sensor_conf)->driver_data = data;
 	exynos_sensor_conf.trip_data.trip_count = pdata->trigger_enable[0] +
 			pdata->trigger_enable[1] + pdata->trigger_enable[2]+
 			pdata->trigger_enable[3];
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 13/21] thermal: exynos: Return success even if no cooling data supplied
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (11 preceding siblings ...)
  2013-05-07 13:01 ` [PATCH V3 12/21] thermal: exynos: Modify private_data to appropriate name driver_data Amit Daniel Kachhap
@ 2013-05-07 13:01 ` Amit Daniel Kachhap
  2013-05-07 13:01 ` [PATCH V3 14/21] thermal: exynos: Make the zone handling dependent on trip count Amit Daniel Kachhap
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch removes the error return in the bind/unbind routine
as the platform may not register any cpufreq cooling data.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/exynos_thermal_common.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
index c0e4bdb..b7ca8a4 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.c
+++ b/drivers/thermal/samsung/exynos_thermal_common.c
@@ -136,7 +136,7 @@ static int exynos_bind(struct thermal_zone_device *thermal,
 	tab_size = data->cooling_data.freq_clip_count;
 
 	if (tab_ptr == NULL || tab_size == 0)
-		return -EINVAL;
+		return 0;
 
 	/* find the cooling device registered*/
 	for (i = 0; i < th_zone->cool_dev_size; i++)
@@ -185,7 +185,7 @@ static int exynos_unbind(struct thermal_zone_device *thermal,
 	tab_size = data->cooling_data.freq_clip_count;
 
 	if (tab_size == 0)
-		return -EINVAL;
+		return 0;
 
 	/* find the cooling device registered*/
 	for (i = 0; i < th_zone->cool_dev_size; i++)
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 14/21] thermal: exynos: Make the zone handling dependent on trip count
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (12 preceding siblings ...)
  2013-05-07 13:01 ` [PATCH V3 13/21] thermal: exynos: Return success even if no cooling data supplied Amit Daniel Kachhap
@ 2013-05-07 13:01 ` Amit Daniel Kachhap
  2013-05-07 13:01 ` [PATCH V3 15/21] thermal: exynos: Add support to handle many instances of TMU Amit Daniel Kachhap
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This code simplifies the zone handling to use the trip count passed
by the TMU driver. This also helps in adding more zone support.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/exynos_thermal_common.c |   55 ++++++++++++-----------
 drivers/thermal/samsung/exynos_thermal_common.h |    2 -
 2 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
index b7ca8a4..b0dc63e 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.c
+++ b/drivers/thermal/samsung/exynos_thermal_common.c
@@ -83,17 +83,16 @@ static int exynos_set_mode(struct thermal_zone_device *thermal,
 static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
 				 enum thermal_trip_type *type)
 {
-	switch (GET_ZONE(trip)) {
-	case MONITOR_ZONE:
-	case WARN_ZONE:
-		*type = THERMAL_TRIP_ACTIVE;
-		break;
-	case PANIC_ZONE:
-		*type = THERMAL_TRIP_CRITICAL;
-		break;
-	default:
+	struct exynos_thermal_zone *th_zone = thermal->devdata;
+	int max_trip = th_zone->sensor_conf->trip_data.trip_count;
+
+	if (trip < 0 || trip >= max_trip)
 		return -EINVAL;
-	}
+	else if (trip == (max_trip - 1))
+		*type = THERMAL_TRIP_CRITICAL;
+	else
+		*type = THERMAL_TRIP_ACTIVE;
+
 	return 0;
 }
 
@@ -102,8 +101,9 @@ static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
 				unsigned long *temp)
 {
 	struct exynos_thermal_zone *th_zone = thermal->devdata;
+	int max_trip = th_zone->sensor_conf->trip_data.trip_count;
 
-	if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
+	if (trip < 0 || trip >= max_trip)
 		return -EINVAL;
 
 	*temp = th_zone->sensor_conf->trip_data.trip_val[trip];
@@ -117,10 +117,10 @@ static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
 static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
 				unsigned long *temp)
 {
-	int ret;
-	/* Panic zone */
-	ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
-	return ret;
+	struct exynos_thermal_zone *th_zone = thermal->devdata;
+	int max_trip = th_zone->sensor_conf->trip_data.trip_count;
+	/* Get the temp of highest trip*/
+	return exynos_get_trip_temp(thermal, max_trip - 1, temp);
 }
 
 /* Bind callback functions for thermal zone */
@@ -345,19 +345,22 @@ int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
 		return -ENOMEM;
 
 	th_zone->sensor_conf = sensor_conf;
-	cpumask_set_cpu(0, &mask_val);
-	th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
-	if (IS_ERR(th_zone->cool_dev[0])) {
-		pr_err("Failed to register cpufreq cooling device\n");
-		ret = -EINVAL;
-		goto err_unregister;
+	if (sensor_conf->cooling_data.freq_clip_count > 0) {
+		cpumask_set_cpu(0, &mask_val);
+		th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
+		if (IS_ERR(th_zone->cool_dev[0])) {
+			pr_err("Failed to register cpufreq cooling device\n");
+			ret = -EINVAL;
+			goto err_unregister;
+		}
+		th_zone->cool_dev_size++;
 	}
-	th_zone->cool_dev_size++;
 
-	th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
-			EXYNOS_ZONE_COUNT, 0, th_zone, &exynos_dev_ops, NULL, 0,
-			sensor_conf->trip_data.trigger_falling ?
-			0 : IDLE_INTERVAL);
+	th_zone->therm_dev = thermal_zone_device_register(
+			sensor_conf->name, sensor_conf->trip_data.trip_count,
+			0, th_zone, &exynos_dev_ops, NULL, 0,
+			sensor_conf->trip_data.trigger_falling ? 0 :
+			IDLE_INTERVAL);
 
 	if (IS_ERR(th_zone->therm_dev)) {
 		pr_err("Failed to register thermal zone device\n");
diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
index 0acde95..1dd1b9e 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.h
+++ b/drivers/thermal/samsung/exynos_thermal_common.h
@@ -42,8 +42,6 @@
 #define GET_ZONE(trip) (trip + 2)
 #define GET_TRIP(zone) (zone - 2)
 
-#define EXYNOS_ZONE_COUNT	3
-
 /**
  * struct freq_clip_table
  * @freq_clip_max: maximum frequency allowed for this cooling state.
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 15/21] thermal: exynos: Add support to handle many instances of TMU
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (13 preceding siblings ...)
  2013-05-07 13:01 ` [PATCH V3 14/21] thermal: exynos: Make the zone handling dependent on trip count Amit Daniel Kachhap
@ 2013-05-07 13:01 ` Amit Daniel Kachhap
  2013-05-09 14:53     ` Eduardo Valentin
  2013-05-07 13:01 ` [PATCH V3 16/21] thermal: exynos: Add features to check instead of using SOC type Amit Daniel Kachhap
                   ` (5 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch adds support to handle multiple instances of the TMU controllers.
This is done by removing the static structure to register with the core thermal
and creating it dynamically for each instance of the TMU controller. The
interrupt is made shared type to handle interrupts for all the TMU. Also
the identifier of the TMU controller is extracted from device tree alias.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/exynos_tmu.c |  125 +++++++++++++++++++++++-----------
 1 files changed, 84 insertions(+), 41 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index bdf40ef..94d6e8e 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -29,6 +29,8 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
@@ -36,9 +38,24 @@
 #include "exynos_tmu.h"
 #include "exynos_tmu_data.h"
 
+/**
+ * struct exynos_tmu_data : A structure to hold the private data of the TMU
+	driver
+ * @id: identifier of the one instance of the TMU controller.
+ * @pdata: pointer to the tmu platform/configuration data
+ * @base: base address of the single instance of the TMU controller.
+ * @irq: irq number of the TMU controller.
+ * @soc: id of the SOC type.
+ * @irq_work: pointer to the irq work structure.
+ * @lock: lock to implement synchronization.
+ * @clk: pointer to the clock structure.
+ * @temp_error1: fused value of the first point trim.
+ * @temp_error2: fused value of the second point trim.
+ * @reg_conf: pointer to structure to register with core thermal.
+ */
 struct exynos_tmu_data {
+	int id;
 	struct exynos_tmu_platform_data *pdata;
-	struct resource *mem;
 	void __iomem *base;
 	int irq;
 	enum soc_type soc;
@@ -46,6 +63,7 @@ struct exynos_tmu_data {
 	struct mutex lock;
 	struct clk *clk;
 	u8 temp_error1, temp_error2;
+	struct thermal_sensor_conf *reg_conf;
 };
 
 /*
@@ -319,12 +337,6 @@ static int exynos_tmu_set_emulation(void *drv_data,	unsigned long temp)
 	{ return -EINVAL; }
 #endif/*CONFIG_THERMAL_EMULATION*/
 
-static struct thermal_sensor_conf exynos_sensor_conf = {
-	.name			= "exynos-therm",
-	.read_temperature	= (int (*)(void *))exynos_tmu_read,
-	.write_emul_temp	= exynos_tmu_set_emulation,
-};
-
 static void exynos_tmu_work(struct work_struct *work)
 {
 	struct exynos_tmu_data *data = container_of(work,
@@ -333,7 +345,7 @@ static void exynos_tmu_work(struct work_struct *work)
 	struct exynos_tmu_registers *reg = pdata->registers;
 	unsigned int val_irq;
 
-	exynos_report_trigger(&exynos_sensor_conf);
+	exynos_report_trigger(data->reg_conf);
 	mutex_lock(&data->lock);
 	clk_enable(data->clk);
 
@@ -405,10 +417,42 @@ static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
 			platform_get_device_id(pdev)->driver_data;
 }
 
+static int exynos_map_dt_data(struct platform_device *pdev)
+{
+	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
+	struct resource res;
+
+	if (!data)
+		return -ENODEV;
+
+	data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
+	if (data->id < 0)
+		data->id = 0;
+
+	data->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+	if (data->irq <= 0) {
+		dev_err(&pdev->dev, "failed to get IRQ\n");
+		return -ENODEV;
+	}
+
+	if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
+		dev_err(&pdev->dev, "failed to get Resource\n");
+		return -ENODEV;
+	}
+
+	data->base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
+	if (!data->base) {
+		dev_err(&pdev->dev, "Failed to ioremap memory\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
 static int exynos_tmu_probe(struct platform_device *pdev)
 {
 	struct exynos_tmu_data *data;
 	struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
+	struct thermal_sensor_conf *sensor_conf;
 	int ret, i;
 
 	if (!pdata)
@@ -425,26 +469,17 @@ static int exynos_tmu_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	data->irq = platform_get_irq(pdev, 0);
-	if (data->irq < 0) {
-		dev_err(&pdev->dev, "Failed to get platform irq\n");
-		return data->irq;
-	}
-
-	INIT_WORK(&data->irq_work, exynos_tmu_work);
-
-	data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!data->mem) {
-		dev_err(&pdev->dev, "Failed to get platform resource\n");
-		return -ENOENT;
-	}
+	data->pdata = pdata;
+	platform_set_drvdata(pdev, data);
+	mutex_init(&data->lock);
 
-	data->base = devm_ioremap_resource(&pdev->dev, data->mem);
-	if (IS_ERR(data->base))
-		return PTR_ERR(data->base);
+	ret = exynos_map_dt_data(pdev);
+	if (ret)
+		return ret;
 
+	INIT_WORK(&data->irq_work, exynos_tmu_work);
 	ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
-		IRQF_TRIGGER_RISING, "exynos-tmu", data);
+		IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
 		return ret;
@@ -469,10 +504,6 @@ static int exynos_tmu_probe(struct platform_device *pdev)
 		goto err_clk;
 	}
 
-	data->pdata = pdata;
-	platform_set_drvdata(pdev, data);
-	mutex_init(&data->lock);
-
 	ret = exynos_tmu_initialize(pdev);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to initialize TMU\n");
@@ -481,28 +512,40 @@ static int exynos_tmu_probe(struct platform_device *pdev)
 
 	exynos_tmu_control(pdev, true);
 
-	/* Register the sensor with thermal management interface */
-	(&exynos_sensor_conf)->driver_data = data;
-	exynos_sensor_conf.trip_data.trip_count = pdata->trigger_enable[0] +
+	/* Allocate a structure to register with the exynos core thermal */
+	sensor_conf = devm_kzalloc(&pdev->dev,
+				sizeof(struct thermal_sensor_conf), GFP_KERNEL);
+	if (!sensor_conf) {
+		dev_err(&pdev->dev, "Failed to allocate registration struct\n");
+		ret = -ENOMEM;
+		goto err_clk;
+	}
+	data->reg_conf = sensor_conf;
+	sprintf(sensor_conf->name, "therm_zone%d", data->id);
+	sensor_conf->read_temperature = (int (*)(void *))exynos_tmu_read;
+	sensor_conf->write_emul_temp =
+		(int (*)(void *, unsigned long))exynos_tmu_set_emulation;
+	sensor_conf->driver_data = data;
+	sensor_conf->trip_data.trip_count = pdata->trigger_enable[0] +
 			pdata->trigger_enable[1] + pdata->trigger_enable[2]+
 			pdata->trigger_enable[3];
 
-	for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
-		exynos_sensor_conf.trip_data.trip_val[i] =
+	for (i = 0; i < sensor_conf->trip_data.trip_count; i++)
+		sensor_conf->trip_data.trip_val[i] =
 			pdata->threshold + pdata->trigger_levels[i];
 
-	exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
+	sensor_conf->trip_data.trigger_falling = pdata->threshold_falling;
 
-	exynos_sensor_conf.cooling_data.freq_clip_count =
-						pdata->freq_tab_count;
+	sensor_conf->cooling_data.freq_clip_count = pdata->freq_tab_count;
 	for (i = 0; i < pdata->freq_tab_count; i++) {
-		exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
+		sensor_conf->cooling_data.freq_data[i].freq_clip_max =
 					pdata->freq_tab[i].freq_clip_max;
-		exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
+		sensor_conf->cooling_data.freq_data[i].temp_level =
 					pdata->freq_tab[i].temp_level;
 	}
 
-	ret = exynos_register_thermal(&exynos_sensor_conf);
+	/* Register the sensor with thermal management interface */
+	ret = exynos_register_thermal(sensor_conf);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to register thermal interface\n");
 		goto err_clk;
@@ -521,7 +564,7 @@ static int exynos_tmu_remove(struct platform_device *pdev)
 
 	exynos_tmu_control(pdev, false);
 
-	exynos_unregister_thermal(&exynos_sensor_conf);
+	exynos_unregister_thermal(data->reg_conf);
 
 	clk_unprepare(data->clk);
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 16/21] thermal: exynos: Add features to check instead of using SOC type
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (14 preceding siblings ...)
  2013-05-07 13:01 ` [PATCH V3 15/21] thermal: exynos: Add support to handle many instances of TMU Amit Daniel Kachhap
@ 2013-05-07 13:01 ` Amit Daniel Kachhap
  2013-05-07 13:01 ` [PATCH V3 17/21] ARM: dts: thermal: exynos4: Add documentation for Exynos SoC thermal bindings Amit Daniel Kachhap
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch adds several features supported by TMU as bitfields.
This features varies across different SOC type and comparing
the features present in the TMU is more logical than comparing
the soc itself.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/samsung/exynos_tmu.c      |    6 +++---
 drivers/thermal/samsung/exynos_tmu.h      |   22 ++++++++++++++++++++++
 drivers/thermal/samsung/exynos_tmu_data.c |    2 ++
 3 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 94d6e8e..c1a8c5f 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -152,7 +152,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 		goto out;
 	}
 
-	if (data->soc == SOC_ARCH_EXYNOS)
+	if (TMU_SUPPORTS(pdata, TRIM_RELOAD))
 		__raw_writel(1, data->base + reg->triminfo_ctrl);
 
 	/* Save trimming info in order to perform calibration */
@@ -261,7 +261,7 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
 			pdata->trigger_enable[2] << reg->inten_rise2_shift |
 			pdata->trigger_enable[1] << reg->inten_rise1_shift |
 			pdata->trigger_enable[0] << reg->inten_rise0_shift;
-		if (pdata->threshold_falling)
+		if (TMU_SUPPORTS(pdata, FALLING_TRIP))
 			interrupt_en |=
 				interrupt_en << reg->inten_fall0_shift;
 	} else {
@@ -303,7 +303,7 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
 	unsigned int val;
 	int ret = -EINVAL;
 
-	if (data->soc == SOC_ARCH_EXYNOS4210)
+	if (!TMU_SUPPORTS(pdata, EMULATION))
 		goto out;
 
 	if (temp && temp < MCELSIUS)
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
index 1e5e492..de1c342 100644
--- a/drivers/thermal/samsung/exynos_tmu.h
+++ b/drivers/thermal/samsung/exynos_tmu.h
@@ -46,6 +46,25 @@ enum soc_type {
 };
 
 /**
+ * EXYNOS TMU supported features.
+ * TMU_SUPPORT_EMULATION - This features is used to set user defined
+ *			temperature to the TMU controller.
+ * TMU_SUPPORT_MULTI_INST - This features denotes that the soc
+ *			has many instances of TMU.
+ * TMU_SUPPORT_TRIM_RELOAD - This features shows that trimming can
+ *			be reloaded.
+ * TMU_SUPPORT_FALLING_TRIP - This features shows that interrupt can
+ *			be registered for falling trips also.
+ * TMU_SUPPORT - macro to compare the above features with the supplied.
+ */
+#define TMU_SUPPORT_EMULATION			BIT(0)
+#define TMU_SUPPORT_MULTI_INST			BIT(1)
+#define TMU_SUPPORT_TRIM_RELOAD			BIT(2)
+#define TMU_SUPPORT_FALLING_TRIP		BIT(3)
+
+#define TMU_SUPPORTS(a, b)	(a->features & TMU_SUPPORT_ ## b)
+
+/**
  * struct exynos_tmu_register - register descriptors to access registers and
  * bitfields. The register validity, offsets and bitfield values may vary
  * slightly across different exynos SOC's.
@@ -166,6 +185,8 @@ struct exynos_tmu_registers {
  * @freq_clip_table: Table representing frequency reduction percentage.
  * @freq_tab_count: Count of the above table as frequency reduction may
  *	applicable to only some of the trigger levels.
+ * @features: a bitfield value indicating the features supported in SOC like
+ *	emulation, multi instance etc
  *
  * This structure is required for configuration of exynos_tmu driver.
  */
@@ -192,5 +213,6 @@ struct exynos_tmu_platform_data {
 	struct freq_clip_table freq_tab[4];
 	unsigned int freq_tab_count;
 	struct exynos_tmu_registers *registers;
+	unsigned int features;
 };
 #endif /* _LINUX_EXYNOS_THERMAL_H */
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
index 7322597..8a587d4 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.c
+++ b/drivers/thermal/samsung/exynos_tmu_data.c
@@ -154,5 +154,7 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
 	.freq_tab_count = 2,
 	.type = SOC_ARCH_EXYNOS,
 	.registers = &exynos5250_tmu_registers,
+	.features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD |
+			TMU_SUPPORT_FALLING_TRIP),
 };
 #endif
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 17/21] ARM: dts: thermal: exynos4: Add documentation for Exynos SoC thermal bindings
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (15 preceding siblings ...)
  2013-05-07 13:01 ` [PATCH V3 16/21] thermal: exynos: Add features to check instead of using SOC type Amit Daniel Kachhap
@ 2013-05-07 13:01 ` Amit Daniel Kachhap
  2013-05-07 13:01 ` [PATCH V3 18/21] thermal: exynos: Add support for exynos5440 TMU sensor Amit Daniel Kachhap
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin, Lukasz Majewski

From: Lukasz Majewski <l.majewski@samsung.com>

Proper description for Exynos4 bindings added to Documentation/devicetree/
bindings

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 .../devicetree/bindings/thermal/exynos-thermal.txt |   25 ++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/exynos-thermal.txt

diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
new file mode 100644
index 0000000..535fd0e
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
@@ -0,0 +1,25 @@
+* Exynos Thermal Management Unit (TMU)
+
+** Required properties:
+
+- compatible : One of the following:
+	       "samsung,exynos4412-tmu"
+	       "samsung,exynos4210-tmu"
+	       "samsung,exynos5250-tmu"
+- interrupt-parent : The phandle for the interrupt controller
+- reg : Address range of the thermal registers
+- interrupts : Should contain interrupt for thermal system
+- clocks : The main clock for TMU device
+- clock-names : Thermal system clock name
+
+Example:
+
+	tmu@100C0000 {
+		compatible = "samsung,exynos4412-tmu";
+		interrupt-parent = <&combiner>;
+		reg = <0x100C0000 0x100>;
+		interrupts = <2 4>;
+		clocks = <&clock 383>;
+		clock-names = "tmu_apbif";
+		status = "disabled";
+	};
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 18/21] thermal: exynos: Add support for exynos5440 TMU sensor.
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (16 preceding siblings ...)
  2013-05-07 13:01 ` [PATCH V3 17/21] ARM: dts: thermal: exynos4: Add documentation for Exynos SoC thermal bindings Amit Daniel Kachhap
@ 2013-05-07 13:01 ` Amit Daniel Kachhap
  2013-05-09 14:47     ` Eduardo Valentin
  2013-05-07 13:01 ` [PATCH V3 19/21] Documentation: thermal: Explain the exynos thermal driver model Amit Daniel Kachhap
                   ` (2 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch modifies TMU controller to add changes needed to work with
exynos5440 platform. Also register definitions and required configuration data
are added. This sensor registers 3 instance of the tmu controller with the
thermal zone and hence reports 3 temperature output. This controller supports
upto five trip points. For critical threshold the driver uses the core driver
thermal framework for shutdown.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 .../devicetree/bindings/thermal/exynos-thermal.txt |   28 ++++-
 drivers/thermal/samsung/Kconfig                    |    4 +-
 drivers/thermal/samsung/exynos_thermal_common.c    |    2 +-
 drivers/thermal/samsung/exynos_tmu.c               |  139 +++++++++++++++++---
 drivers/thermal/samsung/exynos_tmu.h               |    7 +
 drivers/thermal/samsung/exynos_tmu_data.c          |   66 +++++++++-
 drivers/thermal/samsung/exynos_tmu_data.h          |   40 ++++++
 7 files changed, 261 insertions(+), 25 deletions(-)

diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
index 535fd0e..970eeba 100644
--- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
@@ -6,13 +6,16 @@
 	       "samsung,exynos4412-tmu"
 	       "samsung,exynos4210-tmu"
 	       "samsung,exynos5250-tmu"
+	       "samsung,exynos5440-tmu"
 - interrupt-parent : The phandle for the interrupt controller
-- reg : Address range of the thermal registers
+- reg : Address range of the thermal registers. For exynos5440-tmu which has 3
+	instances of TMU, 2 set of register has to supplied. First set belongs
+	to each instance of TMU and second set belongs to common TMU registers.
 - interrupts : Should contain interrupt for thermal system
 - clocks : The main clock for TMU device
 - clock-names : Thermal system clock name
 
-Example:
+Example 1):
 
 	tmu@100C0000 {
 		compatible = "samsung,exynos4412-tmu";
@@ -23,3 +26,24 @@ Example:
 		clock-names = "tmu_apbif";
 		status = "disabled";
 	};
+
+Example 2):
+
+	tmuctrl_0: tmuctrl@160118 {
+		compatible = "samsung,exynos5440-tmu";
+		reg = <0x160118 0x230>, <0x160368 0x10>;
+		interrupts = <0 58 0>;
+		clocks = <&clock 21>;
+		clock-names = "tmu_apbif";
+	};
+
+Note: For multi-instance tmu each instance should have an alias correctly
+numbered in "aliases" node.
+
+Example:
+
+aliases {
+	tmuctrl0 = &tmuctrl_0;
+	tmuctrl1 = &tmuctrl_1;
+	tmuctrl2 = &tmuctrl_2;
+};
diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
index f23f533..fce04f3 100644
--- a/drivers/thermal/samsung/Kconfig
+++ b/drivers/thermal/samsung/Kconfig
@@ -19,10 +19,10 @@ config EXYNOS_THERMAL_CORE
 
 config EXYNOS_THERMAL_DATA
 	bool "Temperature sensor congiguration data for EXYNOS series SOC"
-	depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250)
+	depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250 || SOC_EXYNOS5440)
 	depends on EXYNOS_THERMAL
 	help
 	  If you say yes here you can enable TMU (Thermal Management Unit) on
-	  SAMSUNG EXYNOS 4210, 4412, 4414 and 5250 series of SoC. This option
+	  SAMSUNG EXYNOS 4210, 4412, 4414, 5250 and 5440 series of SoC. This option
 	  enables/prepares the configuration, trip and cooling data for the TMU
 	  driver.
diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
index b0dc63e..de43e18 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.c
+++ b/drivers/thermal/samsung/exynos_thermal_common.c
@@ -370,7 +370,7 @@ int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
 	th_zone->mode = THERMAL_DEVICE_ENABLED;
 	sensor_conf->pzone_data = th_zone;
 
-	pr_info("Exynos: Kernel Thermal management registered\n");
+	pr_info("Exynos: Thermal zone(%s) registered\n", sensor_conf->name);
 
 	return 0;
 
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index c1a8c5f..72446c9 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -44,6 +44,7 @@
  * @id: identifier of the one instance of the TMU controller.
  * @pdata: pointer to the tmu platform/configuration data
  * @base: base address of the single instance of the TMU controller.
+ * @base_common: base address of the common registers of the TMU controller.
  * @irq: irq number of the TMU controller.
  * @soc: id of the SOC type.
  * @irq_work: pointer to the irq work structure.
@@ -57,6 +58,7 @@ struct exynos_tmu_data {
 	int id;
 	struct exynos_tmu_platform_data *pdata;
 	void __iomem *base;
+	void __iomem *base_common;
 	int irq;
 	enum soc_type soc;
 	struct work_struct irq_work;
@@ -75,6 +77,9 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
 	struct exynos_tmu_platform_data *pdata = data->pdata;
 	int temp_code;
 
+	if (pdata->cal_mode == HW_MODE)
+		return temp;
+
 	if (data->soc == SOC_ARCH_EXYNOS4210)
 		/* temp should range between 25 and 125 */
 		if (temp < 25 || temp > 125) {
@@ -109,6 +114,9 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
 	struct exynos_tmu_platform_data *pdata = data->pdata;
 	int temp;
 
+	if (pdata->cal_mode == HW_MODE)
+		return temp_code;
+
 	if (data->soc == SOC_ARCH_EXYNOS4210)
 		/* temp_code should range between 75 and 175 */
 		if (temp_code < 75 || temp_code > 175) {
@@ -139,33 +147,63 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 	struct exynos_tmu_platform_data *pdata = data->pdata;
 	struct exynos_tmu_registers *reg = pdata->registers;
-	unsigned int status, trim_info, con;
+	unsigned int status, trim_info = 0, con;
 	unsigned int rising_threshold = 0, falling_threshold = 0;
 	int ret = 0, threshold_code, i, trigger_levs = 0;
 
 	mutex_lock(&data->lock);
 	clk_enable(data->clk);
 
-	status = readb(data->base + reg->tmu_status);
-	if (!status) {
-		ret = -EBUSY;
-		goto out;
+	if (TMU_SUPPORTS(pdata, READY_STATUS)) {
+		status = readb(data->base + reg->tmu_status);
+		if (!status) {
+			ret = -EBUSY;
+			goto out;
+		}
 	}
 
 	if (TMU_SUPPORTS(pdata, TRIM_RELOAD))
 		__raw_writel(1, data->base + reg->triminfo_ctrl);
 
+	if (pdata->cal_mode == HW_MODE)
+		goto skip_calib_data;
+
 	/* Save trimming info in order to perform calibration */
-	trim_info = readl(data->base + reg->triminfo_data);
+	if (data->soc == SOC_ARCH_EXYNOS5440) {
+		/*
+		 * For exynos5440 soc triminfo value is swapped between TMU0 and
+		 * TMU2, so the below logic is needed.
+		 */
+		switch (data->id) {
+		case 0:
+			trim_info = readl(data->base +
+			EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
+			break;
+		case 1:
+			trim_info = readl(data->base + reg->triminfo_data);
+			break;
+		case 2:
+			trim_info = readl(data->base -
+			EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
+		}
+	} else {
+		trim_info = readl(data->base + reg->triminfo_data);
+	}
 	data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
 	data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
 				EXYNOS_TMU_TEMP_MASK);
 
-	if ((pdata->min_efuse_value > data->temp_error1) ||
-			(data->temp_error1 > pdata->max_efuse_value) ||
-			(data->temp_error2 != 0))
-		data->temp_error1 = pdata->efuse_value;
+	if (!data->temp_error1 ||
+		(pdata->min_efuse_value > data->temp_error1) ||
+		(data->temp_error1 > pdata->max_efuse_value))
+		data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
+
+	if (!data->temp_error2)
+		data->temp_error2 =
+			(pdata->efuse_value >> reg->triminfo_85_shift) &
+			EXYNOS_TMU_TEMP_MASK;
 
+skip_calib_data:
 	/* Count trigger levels to be enabled */
 	for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
 		if (pdata->trigger_levels[i])
@@ -185,9 +223,10 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 			data->base + reg->threshold_th0 + i * 4);
 
 		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
-	} else if (data->soc == SOC_ARCH_EXYNOS) {
+	} else if (data->soc == SOC_ARCH_EXYNOS ||
+			data->soc == SOC_ARCH_EXYNOS5440) {
 		/* Write temperature code for rising and falling threshold */
-		for (i = 0; i < trigger_levs; i++) {
+		for (i = 0; i < trigger_levs && i < 4 ; i++) {
 			threshold_code = temp_to_code(data,
 						pdata->trigger_levels[i]);
 			if (threshold_code < 0) {
@@ -218,7 +257,29 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 		writel((reg->inten_rise_mask << reg->inten_rise_shift) |
 			(reg->inten_fall_mask << reg->inten_fall_shift),
 				data->base + reg->tmu_intclear);
+
+		/* if 5th threshold limit is also present, use TH2 register */
+		i = 4;
+		if (pdata->trigger_levels[i]) {
+			threshold_code = temp_to_code(data,
+						pdata->trigger_levels[i]);
+			if (threshold_code < 0) {
+				ret = threshold_code;
+				goto out;
+			}
+			rising_threshold = threshold_code << 24;
+			writel(rising_threshold,
+				data->base + reg->threshold_th2);
+			if (pdata->trigger_type[i] == HW_TRIP) {
+				con = readl(data->base + reg->tmu_ctrl);
+				con |= (1 << reg->therm_trip_en_shift);
+				writel(con, data->base + reg->tmu_ctrl);
+			}
+		}
 	}
+	/*Clear the PMIN in the common TMU register*/
+	if (reg->tmu_pmin && !data->id)
+		writel(0, data->base_common + reg->tmu_pmin);
 out:
 	clk_disable(data->clk);
 	mutex_unlock(&data->lock);
@@ -254,6 +315,11 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
 		con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
 	}
 
+	if (pdata->cal_mode == HW_MODE) {
+		con &= ~(reg->calib_mode_mask << reg->calib_mode_shift);
+		con |= pdata->cal_type << reg->calib_mode_shift;
+	}
+
 	if (on) {
 		con |= (1 << reg->core_en_shift);
 		interrupt_en =
@@ -317,9 +383,11 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
 	if (temp) {
 		temp /= MCELSIUS;
 
-		val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
-			(temp_to_code(data, temp)
-			 << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
+		if (data->soc == SOC_ARCH_EXYNOS && reg->emul_time_shift)
+			val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift);
+
+		val |= (temp_to_code(data, temp) << reg->emul_temp_shift) |
+			EXYNOS_EMUL_ENABLE;
 	} else {
 		val &= ~EXYNOS_EMUL_ENABLE;
 	}
@@ -343,7 +411,14 @@ static void exynos_tmu_work(struct work_struct *work)
 			struct exynos_tmu_data, irq_work);
 	struct exynos_tmu_platform_data *pdata = data->pdata;
 	struct exynos_tmu_registers *reg = pdata->registers;
-	unsigned int val_irq;
+	unsigned int val_irq, val_type;
+
+	/* Find which sensor generated this interrupt */
+	if (reg->tmu_irqstatus) {
+		val_type = readl(data->base_common + reg->tmu_irqstatus);
+		if (!((val_type >> data->id) & 0x1))
+			goto out;
+	}
 
 	exynos_report_trigger(data->reg_conf);
 	mutex_lock(&data->lock);
@@ -355,7 +430,7 @@ static void exynos_tmu_work(struct work_struct *work)
 
 	clk_disable(data->clk);
 	mutex_unlock(&data->lock);
-
+out:
 	enable_irq(data->irq);
 }
 
@@ -383,6 +458,10 @@ static const struct of_device_id exynos_tmu_match[] = {
 		.compatible = "samsung,exynos5250-tmu",
 		.data = (void *)EXYNOS5250_TMU_DRV_DATA,
 	},
+	{
+		.compatible = "samsung,exynos5440-tmu",
+		.data = (void *)EXYNOS5440_TMU_DRV_DATA,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, exynos_tmu_match);
@@ -420,6 +499,7 @@ static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
 static int exynos_map_dt_data(struct platform_device *pdev)
 {
 	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
+	struct exynos_tmu_platform_data *pdata = data->pdata;
 	struct resource res;
 
 	if (!data)
@@ -436,7 +516,7 @@ static int exynos_map_dt_data(struct platform_device *pdev)
 	}
 
 	if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
-		dev_err(&pdev->dev, "failed to get Resource\n");
+		dev_err(&pdev->dev, "failed to get Resource 0\n");
 		return -ENODEV;
 	}
 
@@ -445,6 +525,26 @@ static int exynos_map_dt_data(struct platform_device *pdev)
 		dev_err(&pdev->dev, "Failed to ioremap memory\n");
 		return -ENOMEM;
 	}
+
+	/*
+	 * Check if the TMU is multi instance type and then try to map the
+	 * memory of common registers.
+	 */
+	if (!TMU_SUPPORTS(pdata, MULTI_INST))
+		return 0;
+
+	if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
+		dev_err(&pdev->dev, "failed to get Resource 1\n");
+		return -ENODEV;
+	}
+
+	data->base_common = devm_ioremap(&pdev->dev, res.start,
+					resource_size(&res));
+	if (!data->base) {
+		dev_err(&pdev->dev, "Failed to ioremap memory\n");
+		return -ENOMEM;
+	}
+
 	return 0;
 }
 
@@ -496,7 +596,8 @@ static int exynos_tmu_probe(struct platform_device *pdev)
 		return ret;
 
 	if (pdata->type == SOC_ARCH_EXYNOS ||
-				pdata->type == SOC_ARCH_EXYNOS4210)
+		pdata->type == SOC_ARCH_EXYNOS4210 ||
+		pdata->type == SOC_ARCH_EXYNOS5440)
 		data->soc = pdata->type;
 	else {
 		ret = -EINVAL;
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
index de1c342..cc6b10e 100644
--- a/drivers/thermal/samsung/exynos_tmu.h
+++ b/drivers/thermal/samsung/exynos_tmu.h
@@ -43,6 +43,7 @@ enum trigger_type {
 enum soc_type {
 	SOC_ARCH_EXYNOS4210 = 1,
 	SOC_ARCH_EXYNOS,
+	SOC_ARCH_EXYNOS5440,
 };
 
 /**
@@ -61,6 +62,7 @@ enum soc_type {
 #define TMU_SUPPORT_MULTI_INST			BIT(1)
 #define TMU_SUPPORT_TRIM_RELOAD			BIT(2)
 #define TMU_SUPPORT_FALLING_TRIP		BIT(3)
+#define TMU_SUPPORT_READY_STATUS		BIT(4)
 
 #define TMU_SUPPORTS(a, b)	(a->features & TMU_SUPPORT_ ## b)
 
@@ -85,6 +87,8 @@ struct exynos_tmu_registers {
 	u32	therm_trip_en_shift;
 	u32	buf_slope_sel_shift;
 	u32	buf_slope_sel_mask;
+	u32	calib_mode_shift;
+	u32	calib_mode_mask;
 	u32	therm_trip_tq_en_shift;
 	u32	core_en_shift;
 
@@ -137,6 +141,9 @@ struct exynos_tmu_registers {
 	u32	emul_temp_shift;
 	u32	emul_time_shift;
 	u32	emul_time_mask;
+
+	u32	tmu_irqstatus;
+	u32	tmu_pmin;
 };
 
 /**
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
index 8a587d4..25629e6 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.c
+++ b/drivers/thermal/samsung/exynos_tmu_data.c
@@ -79,6 +79,7 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
 	.freq_tab_count = 2,
 	.type = SOC_ARCH_EXYNOS4210,
 	.registers = &exynos4210_tmu_registers,
+	.features = (TMU_SUPPORT_READY_STATUS),
 };
 #endif
 
@@ -155,6 +156,69 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
 	.type = SOC_ARCH_EXYNOS,
 	.registers = &exynos5250_tmu_registers,
 	.features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD |
-			TMU_SUPPORT_FALLING_TRIP),
+			TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS),
+};
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS5440)
+static struct exynos_tmu_registers exynos5440_tmu_registers = {
+	.triminfo_data = EXYNOS5440_TMU_S0_7_TRIM,
+	.triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
+	.triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
+	.tmu_ctrl = EXYNOS5440_TMU_S0_7_CTRL,
+	.buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
+	.buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
+	.therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
+	.therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
+	.therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
+	.buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
+	.buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
+	.calib_mode_shift = EXYNOS_TMU_CALIB_MODE_SHIFT,
+	.calib_mode_mask = EXYNOS_TMU_CALIB_MODE_MASK,
+	.core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
+	.tmu_status = EXYNOS5440_TMU_S0_7_STATUS,
+	.tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP,
+	.threshold_th0 = EXYNOS5440_TMU_S0_7_TH0,
+	.threshold_th1 = EXYNOS5440_TMU_S0_7_TH1,
+	.threshold_th2 = EXYNOS5440_TMU_S0_7_TH2,
+	.tmu_inten = EXYNOS5440_TMU_S0_7_IRQEN,
+	.inten_rise_mask = EXYNOS5440_TMU_RISE_INT_MASK,
+	.inten_rise_shift = EXYNOS5440_TMU_RISE_INT_SHIFT,
+	.inten_fall_mask = EXYNOS5440_TMU_FALL_INT_MASK,
+	.inten_fall_shift = EXYNOS5440_TMU_FALL_INT_SHIFT,
+	.inten_rise0_shift = EXYNOS5440_TMU_INTEN_RISE0_SHIFT,
+	.inten_rise1_shift = EXYNOS5440_TMU_INTEN_RISE1_SHIFT,
+	.inten_rise2_shift = EXYNOS5440_TMU_INTEN_RISE2_SHIFT,
+	.inten_rise3_shift = EXYNOS5440_TMU_INTEN_RISE3_SHIFT,
+	.inten_fall0_shift = EXYNOS5440_TMU_INTEN_FALL0_SHIFT,
+	.tmu_evten = EXYNOS5440_TMU_S0_7_EVTEN,
+	.tmu_intstat = EXYNOS5440_TMU_S0_7_IRQ,
+	.tmu_intclear = EXYNOS5440_TMU_S0_7_IRQ,
+	.tmu_irqstatus = EXYNOS5440_TMU_IRQ_STATUS,
+	.emul_con = EXYNOS5440_TMU_S0_7_DEBUG,
+	.emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
+	.tmu_pmin = EXYNOS5440_TMU_PMIN,
+};
+struct exynos_tmu_platform_data const exynos5440_default_tmu_data = {
+	.trigger_levels[0] = 100,
+	.trigger_levels[4] = 105,
+	.trigger_enable[0] = 1,
+	.trigger_type[0] = 1,
+	.trigger_type[4] = 2,
+	.gain = 5,
+	.reference_voltage = 16,
+	.noise_cancel_mode = 4,
+	.cal_type = TYPE_TWO_POINT_TRIMMING,
+	.cal_mode = 0,
+	.efuse_value = 0x5b2d,
+	.min_efuse_value = 16,
+	.max_efuse_value = 76,
+	.first_point_trim = 25,
+	.second_point_trim = 70,
+	.default_temp_offset = 25,
+	.type = SOC_ARCH_EXYNOS5440,
+	.registers = &exynos5440_tmu_registers,
+	.features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP |
+			TMU_SUPPORT_MULTI_INST),
 };
 #endif
diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
index 0560413..c409f3a 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.h
+++ b/drivers/thermal/samsung/exynos_tmu_data.h
@@ -75,6 +75,8 @@
 #define EXYNOS_TMU_TRIP_MODE_SHIFT	13
 #define EXYNOS_TMU_TRIP_MODE_MASK	0x7
 #define EXYNOS_TMU_THERM_TRIP_EN_SHIFT	12
+#define EXYNOS_TMU_CALIB_MODE_SHIFT	4
+#define EXYNOS_TMU_CALIB_MODE_MASK	0x3
 
 #define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
 #define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
@@ -91,6 +93,37 @@
 #define EXYNOS_EMUL_DATA_MASK	0xFF
 #define EXYNOS_EMUL_ENABLE	0x1
 
+/*exynos5440 specific registers*/
+#define EXYNOS5440_TMU_S0_7_TRIM		0x000
+#define EXYNOS5440_TMU_S0_7_CTRL		0x020
+#define EXYNOS5440_TMU_S0_7_DEBUG		0x040
+#define EXYNOS5440_TMU_S0_7_STATUS		0x060
+#define EXYNOS5440_TMU_S0_7_TEMP		0x0f0
+#define EXYNOS5440_TMU_S0_7_TH0			0x110
+#define EXYNOS5440_TMU_S0_7_TH1			0x130
+#define EXYNOS5440_TMU_S0_7_TH2			0x150
+#define EXYNOS5440_TMU_S0_7_EVTEN		0x1F0
+#define EXYNOS5440_TMU_S0_7_IRQEN		0x210
+#define EXYNOS5440_TMU_S0_7_IRQ			0x230
+/* exynos5440 common registers */
+#define EXYNOS5440_TMU_IRQ_STATUS		0x000
+#define EXYNOS5440_TMU_PMIN			0x004
+#define EXYNOS5440_TMU_TEMP			0x008
+
+#define EXYNOS5440_EFUSE_SWAP_OFFSET		8
+#define EXYNOS5440_TMU_RISE_INT_MASK		0xf
+#define EXYNOS5440_TMU_RISE_INT_SHIFT		0
+#define EXYNOS5440_TMU_FALL_INT_MASK		0xf
+#define EXYNOS5440_TMU_FALL_INT_SHIFT		4
+#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT	0
+#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT	1
+#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT	2
+#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT	3
+#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT	4
+#define EXYNOS5440_TMU_INTEN_FALL1_SHIFT	5
+#define EXYNOS5440_TMU_INTEN_FALL2_SHIFT	6
+#define EXYNOS5440_TMU_INTEN_FALL3_SHIFT	7
+
 #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
 extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
 #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
@@ -106,4 +139,11 @@ extern struct exynos_tmu_platform_data const exynos5250_default_tmu_data;
 #define EXYNOS5250_TMU_DRV_DATA (NULL)
 #endif
 
+#if defined(CONFIG_SOC_EXYNOS5440) && defined(CONFIG_EXYNOS_THERMAL_DATA)
+extern struct exynos_tmu_platform_data const exynos5440_default_tmu_data;
+#define EXYNOS5440_TMU_DRV_DATA (&exynos5440_default_tmu_data)
+#else
+#define EXYNOS5440_TMU_DRV_DATA (NULL)
+#endif
+
 #endif /*_LINUX_EXYNOS_TMU_DATA_H*/
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 19/21] Documentation: thermal: Explain the exynos thermal driver model
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (17 preceding siblings ...)
  2013-05-07 13:01 ` [PATCH V3 18/21] thermal: exynos: Add support for exynos5440 TMU sensor Amit Daniel Kachhap
@ 2013-05-07 13:01 ` Amit Daniel Kachhap
  2013-05-07 13:01 ` [PATCH V3 20/21] thermal: exynos: Support for TMU regulator defined at device tree Amit Daniel Kachhap
  2013-05-07 13:01 ` [PATCH V3 21/21] ARM: dts: Add device tree node for exynos5440 TMU controller Amit Daniel Kachhap
  20 siblings, 0 replies; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch updates the documentation to explain the driver model
and file layout.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 Documentation/thermal/exynos_thermal |   43 ++++++++++++++++++++++++++-------
 1 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/Documentation/thermal/exynos_thermal b/Documentation/thermal/exynos_thermal
index 2b46f67..9010c44 100644
--- a/Documentation/thermal/exynos_thermal
+++ b/Documentation/thermal/exynos_thermal
@@ -1,17 +1,17 @@
-Kernel driver exynos4_tmu
+Kernel driver exynos_tmu
 =================
 
 Supported chips:
-* ARM SAMSUNG EXYNOS4 series of SoC
-  Prefix: 'exynos4-tmu'
+* ARM SAMSUNG EXYNOS4, EXYNOS5 series of SoC
   Datasheet: Not publicly available
 
 Authors: Donggeun Kim <dg77.kim@samsung.com>
+Authors: Amit Daniel <amit.daniel@samsung.com>
 
-Description
------------
+TMU controller Description:
+---------------------------
 
-This driver allows to read temperature inside SAMSUNG EXYNOS4 series of SoC.
+This driver allows to read temperature inside SAMSUNG EXYNOS4/5 series of SoC.
 
 The chip only exposes the measured 8-bit temperature code value
 through a register.
@@ -34,9 +34,9 @@ The three equations are:
   TI2: Trimming info for 85 degree Celsius (stored at TRIMINFO register)
        Temperature code measured at 85 degree Celsius which is unchanged
 
-TMU(Thermal Management Unit) in EXYNOS4 generates interrupt
+TMU(Thermal Management Unit) in EXYNOS4/5 generates interrupt
 when temperature exceeds pre-defined levels.
-The maximum number of configurable threshold is four.
+The maximum number of configurable threshold is five.
 The threshold levels are defined as follows:
   Level_0: current temperature > trigger_level_0 + threshold
   Level_1: current temperature > trigger_level_1 + threshold
@@ -47,6 +47,31 @@ The threshold levels are defined as follows:
   through the corresponding registers.
 
 When an interrupt occurs, this driver notify kernel thermal framework
-with the function exynos4_report_trigger.
+with the function exynos_report_trigger.
 Although an interrupt condition for level_0 can be set,
 it can be used to synchronize the cooling action.
+
+TMU driver description:
+-----------------------
+
+The exynos thermal driver is structured as,
+
+					Kernel Core thermal framework
+				(thermal_core.c, step_wise.c, cpu_cooling.c)
+								^
+								|
+								|
+TMU configuration data -------> TMU Driver  <------> Exynos Core thermal wrapper
+(exynos_tmu_data.c)	      (exynos_tmu.c)	   (exynos_thermal_common.c)
+(exynos_tmu_data.h)	      (exynos_tmu.h)	   (exynos_thermal_common.h)
+
+a) TMU configuration data: This consist of TMU register offsets/bitfields
+		described through structure exynos_tmu_registers. Also several
+		other platform data (struct exynos_tmu_platform_data) members
+		are used to configure the TMU.
+b) TMU driver: This component initialises the TMU controller and sets different
+		thresholds. It invokes core thermal implementation with the call
+		exynos_report_trigger.
+c) Exynos Core thermal wrapper: This provides 3 wrapper function to use the
+		Kernel core thermal framework. They are exynos_unregister_thermal,
+		exynos_register_thermal and exynos_report_trigger.
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 20/21] thermal: exynos: Support for TMU regulator defined at device tree
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (18 preceding siblings ...)
  2013-05-07 13:01 ` [PATCH V3 19/21] Documentation: thermal: Explain the exynos thermal driver model Amit Daniel Kachhap
@ 2013-05-07 13:01 ` Amit Daniel Kachhap
  2013-05-09 14:44     ` Eduardo Valentin
  2013-05-07 13:01 ` [PATCH V3 21/21] ARM: dts: Add device tree node for exynos5440 TMU controller Amit Daniel Kachhap
  20 siblings, 1 reply; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

TMU probe function now checks for a device tree defined regulator.
For compatibility reasons it is allowed to probe driver even without
this regulator defined.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 .../devicetree/bindings/thermal/exynos-thermal.txt |    4 ++++
 drivers/thermal/samsung/exynos_tmu.c               |   19 +++++++++++++++++++
 2 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
index 970eeba..ff62f7a 100644
--- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
@@ -14,6 +14,9 @@
 - interrupts : Should contain interrupt for thermal system
 - clocks : The main clock for TMU device
 - clock-names : Thermal system clock name
+- vtmu-supply: This entry is optional and provides the regulator node supplying
+		voltage to TMU. If needed this entry can be placed inside
+		board/platform specific dts file.
 
 Example 1):
 
@@ -25,6 +28,7 @@ Example 1):
 		clocks = <&clock 383>;
 		clock-names = "tmu_apbif";
 		status = "disabled";
+		vtmu-supply = <&tmu_regulator_node>;
 	};
 
 Example 2):
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 72446c9..b7c609a 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -32,6 +32,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include "exynos_thermal_common.h"
@@ -52,6 +53,7 @@
  * @clk: pointer to the clock structure.
  * @temp_error1: fused value of the first point trim.
  * @temp_error2: fused value of the second point trim.
+ * @regulator: pointer to the TMU regulator structure.
  * @reg_conf: pointer to structure to register with core thermal.
  */
 struct exynos_tmu_data {
@@ -65,6 +67,7 @@ struct exynos_tmu_data {
 	struct mutex lock;
 	struct clk *clk;
 	u8 temp_error1, temp_error2;
+	struct regulator *regulator;
 	struct thermal_sensor_conf *reg_conf;
 };
 
@@ -501,10 +504,23 @@ static int exynos_map_dt_data(struct platform_device *pdev)
 	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 	struct exynos_tmu_platform_data *pdata = data->pdata;
 	struct resource res;
+	int ret;
 
 	if (!data)
 		return -ENODEV;
 
+	/* Try enabling the regulator if found */
+	data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
+	if (!IS_ERR(data->regulator)) {
+		ret = regulator_enable(data->regulator);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to enable vtmu\n");
+			return ret;
+		}
+	} else {
+		dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
+	}
+
 	data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
 	if (data->id < 0)
 		data->id = 0;
@@ -669,6 +685,9 @@ static int exynos_tmu_remove(struct platform_device *pdev)
 
 	clk_unprepare(data->clk);
 
+	if (!IS_ERR(data->regulator))
+		regulator_disable(data->regulator);
+
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH V3 21/21] ARM: dts: Add device tree node for exynos5440 TMU controller
  2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
                   ` (19 preceding siblings ...)
  2013-05-07 13:01 ` [PATCH V3 20/21] thermal: exynos: Support for TMU regulator defined at device tree Amit Daniel Kachhap
@ 2013-05-07 13:01 ` Amit Daniel Kachhap
  20 siblings, 0 replies; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This patch adds device node for TMU controller. There are 3
instances of the controllers so 3 nodes are created.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 arch/arm/boot/dts/exynos5440.dtsi |   30 ++++++++++++++++++++++++++++++
 1 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5440.dtsi b/arch/arm/boot/dts/exynos5440.dtsi
index 9a99755..433e92e 100644
--- a/arch/arm/boot/dts/exynos5440.dtsi
+++ b/arch/arm/boot/dts/exynos5440.dtsi
@@ -16,6 +16,12 @@
 
 	interrupt-parent = <&gic>;
 
+	aliases {
+		tmuctrl0 = &tmuctrl_0;
+		tmuctrl1 = &tmuctrl_1;
+		tmuctrl2 = &tmuctrl_2;
+	};
+
 	gic:interrupt-controller@2E0000 {
 		compatible = "arm,cortex-a15-gic";
 		#interrupt-cells = <3>;
@@ -162,4 +168,28 @@
 		reg = <0x130000 0x1000>;
 		interrupts = <0 17 0>, <0 16 0>;
 	};
+
+	tmuctrl_0: tmuctrl@160118 {
+		compatible = "samsung,exynos5440-tmu";
+		reg = <0x160118 0x230>, <0x160368 0x10>;
+		interrupts = <0 58 0>;
+		clocks = <&clock 21>;
+		clock-names = "tmu_apbif";
+	};
+
+	tmuctrl_1: tmuctrl@16011C {
+		compatible = "samsung,exynos5440-tmu";
+		reg = <0x16011C 0x230>, <0x160368 0x10>;
+		interrupts = <0 58 0>;
+		clocks = <&clock 21>;
+		clock-names = "tmu_apbif";
+	};
+
+	tmuctrl_2: tmuctrl@160120 {
+		compatible = "samsung,exynos5440-tmu";
+		reg = <0x160120 0x230>, <0x160368 0x10>;
+		interrupts = <0 58 0>;
+		clocks = <&clock 21>;
+		clock-names = "tmu_apbif";
+	};
 };
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [RESEND PATCH V3 01/21] thermal: exynos: Moving exynos thermal files into samsung directory
  2013-05-07 13:00 ` [PATCH V3 01/21] thermal: exynos: Moving exynos thermal files into samsung directory Amit Daniel Kachhap
@ 2013-05-07 13:07   ` Amit Daniel Kachhap
  2013-05-08 15:49       ` Eduardo Valentin
  0 siblings, 1 reply; 67+ messages in thread
From: Amit Daniel Kachhap @ 2013-05-07 13:07 UTC (permalink / raw)
  To: linux-pm
  Cc: Zhang Rui, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

This movement of files is done for easy maintenance and adding more
new sensor's support for exynos platform easily . This will also help in
bifurcating exynos common, sensor driver and sensor data related parts.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
 drivers/thermal/Kconfig                        |   13 +++++--------
 drivers/thermal/Makefile                       |    2 +-
 drivers/thermal/samsung/Kconfig                |    9 +++++++++
 drivers/thermal/samsung/Makefile               |    4 ++++
 drivers/thermal/{ => samsung}/exynos_thermal.c |    0
 5 files changed, 19 insertions(+), 9 deletions(-)
 create mode 100644 drivers/thermal/samsung/Kconfig
 create mode 100644 drivers/thermal/samsung/Makefile
 rename drivers/thermal/{ => samsung}/exynos_thermal.c (100%)

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 5e3c025..081ddc5 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -114,14 +114,6 @@ config KIRKWOOD_THERMAL
 	  Support for the Kirkwood thermal sensor driver into the Linux thermal
 	  framework. Only kirkwood 88F6282 and 88F6283 have this sensor.
 
-config EXYNOS_THERMAL
-	tristate "Temperature sensor on Samsung EXYNOS"
-	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
-	depends on CPU_THERMAL
-	help
-	  If you say yes here you get support for TMU (Thermal Management
-	  Unit) on SAMSUNG EXYNOS series of SoC.
-
 config DOVE_THERMAL
 	tristate "Temperature sensor on Marvell Dove SoCs"
 	depends on ARCH_DOVE
@@ -169,4 +161,9 @@ config INTEL_POWERCLAMP
 	  enforce idle time which results in more package C-state residency. The
 	  user interface is exposed via generic thermal framework.
 
+menu "Samsung thermal drivers"
+depends on PLAT_SAMSUNG
+source "drivers/thermal/samsung/Kconfig"
+endmenu
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index c054d41..b3063a9 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -17,7 +17,7 @@ thermal_sys-$(CONFIG_CPU_THERMAL)	+= cpu_cooling.o
 obj-$(CONFIG_SPEAR_THERMAL)	+= spear_thermal.o
 obj-$(CONFIG_RCAR_THERMAL)	+= rcar_thermal.o
 obj-$(CONFIG_KIRKWOOD_THERMAL)  += kirkwood_thermal.o
-obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
+obj-y				+= samsung/
 obj-$(CONFIG_DOVE_THERMAL)  	+= dove_thermal.o
 obj-$(CONFIG_DB8500_THERMAL)	+= db8500_thermal.o
 obj-$(CONFIG_ARMADA_THERMAL)	+= armada_thermal.o
diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
new file mode 100644
index 0000000..2d3d9dc
--- /dev/null
+++ b/drivers/thermal/samsung/Kconfig
@@ -0,0 +1,9 @@
+config EXYNOS_THERMAL
+	tristate "Temperature sensor on Samsung EXYNOS"
+	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
+	depends on CPU_THERMAL
+	help
+	  If you say yes here you get support for TMU (Thermal Management
+	  Unit) on SAMSUNG EXYNOS series of SoC. This helps in registering
+	  the exynos thermal driver with the core thermal layer and cpu
+	  cooling API's.
diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
new file mode 100644
index 0000000..1fe6d93
--- /dev/null
+++ b/drivers/thermal/samsung/Makefile
@@ -0,0 +1,4 @@
+#
+# Samsung thermal specific Makefile
+#
+obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/samsung/exynos_thermal.c
similarity index 100%
rename from drivers/thermal/exynos_thermal.c
rename to drivers/thermal/samsung/exynos_thermal.c
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 02/21] thermal: exynos: Bifurcate exynos thermal common and tmu controller code
  2013-05-07 13:00 ` [PATCH V3 02/21] thermal: exynos: Bifurcate exynos thermal common and tmu controller code Amit Daniel Kachhap
@ 2013-05-07 13:41   ` Zhang Rui
  2013-05-08  3:49     ` amit daniel kachhap
  2013-05-08 16:01     ` Eduardo Valentin
  1 sibling, 1 reply; 67+ messages in thread
From: Zhang Rui @ 2013-05-07 13:41 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, linux-samsung-soc, linux-kernel, amit.kachhap,
	Kukjin Kim, Eduardo Valentin

On Tue, 2013-05-07 at 18:30 +0530, Amit Daniel Kachhap wrote:
> This code bifurcates exynos thermal implementation into common and sensor
> specific parts. The common thermal code interacts with core thermal layer and
> core cpufreq cooling parts and is independent of SOC specific driver. This
> change is needed to cleanly add support for new TMU sensors.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/Kconfig                 |   20 +-
>  drivers/thermal/samsung/Makefile                |    4 +-
>  drivers/thermal/samsung/exynos_thermal.c        |  421 +----------------------
>  drivers/thermal/samsung/exynos_thermal_common.c |  389 +++++++++++++++++++++
>  drivers/thermal/samsung/exynos_thermal_common.h |   83 +++++
>  5 files changed, 498 insertions(+), 419 deletions(-)
>  create mode 100644 drivers/thermal/samsung/exynos_thermal_common.c
>  create mode 100644 drivers/thermal/samsung/exynos_thermal_common.h
> 
> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
> index 2d3d9dc..7857e20 100644
> --- a/drivers/thermal/samsung/Kconfig
> +++ b/drivers/thermal/samsung/Kconfig
> @@ -1,9 +1,17 @@
>  config EXYNOS_THERMAL
> -	tristate "Temperature sensor on Samsung EXYNOS"
> +	tristate "Exynos thermal management unit driver"
>  	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
> -	depends on CPU_THERMAL
>  	help
> -	  If you say yes here you get support for TMU (Thermal Management
> -	  Unit) on SAMSUNG EXYNOS series of SoC. This helps in registering
> -	  the exynos thermal driver with the core thermal layer and cpu
> -	  cooling API's.
> +	  If you say yes here you get support for the exynos thermal driver
> +	  for exynos4 and exynos5 soc. This driver initialises the TMU, reports
> +	  temperature and handles cooling action if defined. This driver uses
> +	  core thermal API's.
> +
> +config EXYNOS_THERMAL_CORE
> +	bool "Core thermal framework support for EXYNOS SOC's"
> +	depends on EXYNOS_THERMAL
> +	help
> +	  If you say yes here you get support for EXYNOS TMU
> +	  (Thermal Management Unit) common registration/unregistration
> +	  functions to the core thermal layer and also to use the generic
> +	  cpu cooling API's.

I'm still not quite clear what you want to get there.
If EXYNOS_THERMAL=y and EXYNOS_THERMAL_CORE=n, you'll get an Exynos tmu
driver which is not shown in /sys/class/thermal/ and can not be used for
thermal management?

thanks,
rui
> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
> index 1fe6d93..6227d4f 100644
> --- a/drivers/thermal/samsung/Makefile
> +++ b/drivers/thermal/samsung/Makefile
> @@ -1,4 +1,6 @@
>  #
>  # Samsung thermal specific Makefile
>  #
> -obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
> +obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_soc_thermal.o
> +exynos_soc_thermal-y				:= exynos_thermal.o
> +exynos_soc_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
> diff --git a/drivers/thermal/samsung/exynos_thermal.c b/drivers/thermal/samsung/exynos_thermal.c
> index d20ce9e..4c85945 100644
> --- a/drivers/thermal/samsung/exynos_thermal.c
> +++ b/drivers/thermal/samsung/exynos_thermal.c
> @@ -21,23 +21,19 @@
>   *
>   */
>  
> -#include <linux/module.h>
> -#include <linux/err.h>
> -#include <linux/kernel.h>
> -#include <linux/slab.h>
> -#include <linux/platform_device.h>
> -#include <linux/interrupt.h>
>  #include <linux/clk.h>
> -#include <linux/workqueue.h>
> -#include <linux/sysfs.h>
> -#include <linux/kobject.h>
>  #include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/kobject.h>
> +#include <linux/module.h>
>  #include <linux/mutex.h>
> -#include <linux/platform_data/exynos_thermal.h>
> -#include <linux/thermal.h>
> -#include <linux/cpufreq.h>
> -#include <linux/cpu_cooling.h>
>  #include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/platform_data/exynos_thermal.h>
> +#include <linux/slab.h>
> +#include <linux/workqueue.h>
> +#include "exynos_thermal_common.h"
>  
>  /* Exynos generic registers */
>  #define EXYNOS_TMU_REG_TRIMINFO		0x0
> @@ -88,16 +84,6 @@
>  #define EFUSE_MIN_VALUE 40
>  #define EFUSE_MAX_VALUE 100
>  
> -/* In-kernel thermal framework related macros & definations */
> -#define SENSOR_NAME_LEN	16
> -#define MAX_TRIP_COUNT	8
> -#define MAX_COOLING_DEVICE 4
> -#define MAX_THRESHOLD_LEVS 4
> -
> -#define ACTIVE_INTERVAL 500
> -#define IDLE_INTERVAL 10000
> -#define MCELSIUS	1000
> -
>  #ifdef CONFIG_THERMAL_EMULATION
>  #define EXYNOS_EMUL_TIME	0x57F0
>  #define EXYNOS_EMUL_TIME_SHIFT	16
> @@ -106,17 +92,6 @@
>  #define EXYNOS_EMUL_ENABLE	0x1
>  #endif /* CONFIG_THERMAL_EMULATION */
>  
> -/* CPU Zone information */
> -#define PANIC_ZONE      4
> -#define WARN_ZONE       3
> -#define MONITOR_ZONE    2
> -#define SAFE_ZONE       1
> -
> -#define GET_ZONE(trip) (trip + 2)
> -#define GET_TRIP(zone) (zone - 2)
> -
> -#define EXYNOS_ZONE_COUNT	3
> -
>  struct exynos_tmu_data {
>  	struct exynos_tmu_platform_data *pdata;
>  	struct resource *mem;
> @@ -129,384 +104,6 @@ struct exynos_tmu_data {
>  	u8 temp_error1, temp_error2;
>  };
>  
> -struct	thermal_trip_point_conf {
> -	int trip_val[MAX_TRIP_COUNT];
> -	int trip_count;
> -	u8 trigger_falling;
> -};
> -
> -struct	thermal_cooling_conf {
> -	struct freq_clip_table freq_data[MAX_TRIP_COUNT];
> -	int freq_clip_count;
> -};
> -
> -struct thermal_sensor_conf {
> -	char name[SENSOR_NAME_LEN];
> -	int (*read_temperature)(void *data);
> -	int (*write_emul_temp)(void *drv_data, unsigned long temp);
> -	struct thermal_trip_point_conf trip_data;
> -	struct thermal_cooling_conf cooling_data;
> -	void *private_data;
> -};
> -
> -struct exynos_thermal_zone {
> -	enum thermal_device_mode mode;
> -	struct thermal_zone_device *therm_dev;
> -	struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
> -	unsigned int cool_dev_size;
> -	struct platform_device *exynos4_dev;
> -	struct thermal_sensor_conf *sensor_conf;
> -	bool bind;
> -};
> -
> -static struct exynos_thermal_zone *th_zone;
> -static void exynos_unregister_thermal(void);
> -static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
> -
> -/* Get mode callback functions for thermal zone */
> -static int exynos_get_mode(struct thermal_zone_device *thermal,
> -			enum thermal_device_mode *mode)
> -{
> -	if (th_zone)
> -		*mode = th_zone->mode;
> -	return 0;
> -}
> -
> -/* Set mode callback functions for thermal zone */
> -static int exynos_set_mode(struct thermal_zone_device *thermal,
> -			enum thermal_device_mode mode)
> -{
> -	if (!th_zone->therm_dev) {
> -		pr_notice("thermal zone not registered\n");
> -		return 0;
> -	}
> -
> -	mutex_lock(&th_zone->therm_dev->lock);
> -
> -	if (mode == THERMAL_DEVICE_ENABLED &&
> -		!th_zone->sensor_conf->trip_data.trigger_falling)
> -		th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
> -	else
> -		th_zone->therm_dev->polling_delay = 0;
> -
> -	mutex_unlock(&th_zone->therm_dev->lock);
> -
> -	th_zone->mode = mode;
> -	thermal_zone_device_update(th_zone->therm_dev);
> -	pr_info("thermal polling set for duration=%d msec\n",
> -				th_zone->therm_dev->polling_delay);
> -	return 0;
> -}
> -
> -
> -/* Get trip type callback functions for thermal zone */
> -static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
> -				 enum thermal_trip_type *type)
> -{
> -	switch (GET_ZONE(trip)) {
> -	case MONITOR_ZONE:
> -	case WARN_ZONE:
> -		*type = THERMAL_TRIP_ACTIVE;
> -		break;
> -	case PANIC_ZONE:
> -		*type = THERMAL_TRIP_CRITICAL;
> -		break;
> -	default:
> -		return -EINVAL;
> -	}
> -	return 0;
> -}
> -
> -/* Get trip temperature callback functions for thermal zone */
> -static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
> -				unsigned long *temp)
> -{
> -	if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
> -		return -EINVAL;
> -
> -	*temp = th_zone->sensor_conf->trip_data.trip_val[trip];
> -	/* convert the temperature into millicelsius */
> -	*temp = *temp * MCELSIUS;
> -
> -	return 0;
> -}
> -
> -/* Get critical temperature callback functions for thermal zone */
> -static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
> -				unsigned long *temp)
> -{
> -	int ret;
> -	/* Panic zone */
> -	ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
> -	return ret;
> -}
> -
> -/* Bind callback functions for thermal zone */
> -static int exynos_bind(struct thermal_zone_device *thermal,
> -			struct thermal_cooling_device *cdev)
> -{
> -	int ret = 0, i, tab_size, level;
> -	struct freq_clip_table *tab_ptr, *clip_data;
> -	struct thermal_sensor_conf *data = th_zone->sensor_conf;
> -
> -	tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
> -	tab_size = data->cooling_data.freq_clip_count;
> -
> -	if (tab_ptr == NULL || tab_size == 0)
> -		return -EINVAL;
> -
> -	/* find the cooling device registered*/
> -	for (i = 0; i < th_zone->cool_dev_size; i++)
> -		if (cdev == th_zone->cool_dev[i])
> -			break;
> -
> -	/* No matching cooling device */
> -	if (i == th_zone->cool_dev_size)
> -		return 0;
> -
> -	/* Bind the thermal zone to the cpufreq cooling device */
> -	for (i = 0; i < tab_size; i++) {
> -		clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
> -		level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
> -		if (level == THERMAL_CSTATE_INVALID)
> -			return 0;
> -		switch (GET_ZONE(i)) {
> -		case MONITOR_ZONE:
> -		case WARN_ZONE:
> -			if (thermal_zone_bind_cooling_device(thermal, i, cdev,
> -								level, 0)) {
> -				pr_err("error binding cdev inst %d\n", i);
> -				ret = -EINVAL;
> -			}
> -			th_zone->bind = true;
> -			break;
> -		default:
> -			ret = -EINVAL;
> -		}
> -	}
> -
> -	return ret;
> -}
> -
> -/* Unbind callback functions for thermal zone */
> -static int exynos_unbind(struct thermal_zone_device *thermal,
> -			struct thermal_cooling_device *cdev)
> -{
> -	int ret = 0, i, tab_size;
> -	struct thermal_sensor_conf *data = th_zone->sensor_conf;
> -
> -	if (th_zone->bind == false)
> -		return 0;
> -
> -	tab_size = data->cooling_data.freq_clip_count;
> -
> -	if (tab_size == 0)
> -		return -EINVAL;
> -
> -	/* find the cooling device registered*/
> -	for (i = 0; i < th_zone->cool_dev_size; i++)
> -		if (cdev == th_zone->cool_dev[i])
> -			break;
> -
> -	/* No matching cooling device */
> -	if (i == th_zone->cool_dev_size)
> -		return 0;
> -
> -	/* Bind the thermal zone to the cpufreq cooling device */
> -	for (i = 0; i < tab_size; i++) {
> -		switch (GET_ZONE(i)) {
> -		case MONITOR_ZONE:
> -		case WARN_ZONE:
> -			if (thermal_zone_unbind_cooling_device(thermal, i,
> -								cdev)) {
> -				pr_err("error unbinding cdev inst=%d\n", i);
> -				ret = -EINVAL;
> -			}
> -			th_zone->bind = false;
> -			break;
> -		default:
> -			ret = -EINVAL;
> -		}
> -	}
> -	return ret;
> -}
> -
> -/* Get temperature callback functions for thermal zone */
> -static int exynos_get_temp(struct thermal_zone_device *thermal,
> -			unsigned long *temp)
> -{
> -	void *data;
> -
> -	if (!th_zone->sensor_conf) {
> -		pr_info("Temperature sensor not initialised\n");
> -		return -EINVAL;
> -	}
> -	data = th_zone->sensor_conf->private_data;
> -	*temp = th_zone->sensor_conf->read_temperature(data);
> -	/* convert the temperature into millicelsius */
> -	*temp = *temp * MCELSIUS;
> -	return 0;
> -}
> -
> -/* Get temperature callback functions for thermal zone */
> -static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
> -						unsigned long temp)
> -{
> -	void *data;
> -	int ret = -EINVAL;
> -
> -	if (!th_zone->sensor_conf) {
> -		pr_info("Temperature sensor not initialised\n");
> -		return -EINVAL;
> -	}
> -	data = th_zone->sensor_conf->private_data;
> -	if (th_zone->sensor_conf->write_emul_temp)
> -		ret = th_zone->sensor_conf->write_emul_temp(data, temp);
> -	return ret;
> -}
> -
> -/* Get the temperature trend */
> -static int exynos_get_trend(struct thermal_zone_device *thermal,
> -			int trip, enum thermal_trend *trend)
> -{
> -	int ret;
> -	unsigned long trip_temp;
> -
> -	ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
> -	if (ret < 0)
> -		return ret;
> -
> -	if (thermal->temperature >= trip_temp)
> -		*trend = THERMAL_TREND_RAISE_FULL;
> -	else
> -		*trend = THERMAL_TREND_DROP_FULL;
> -
> -	return 0;
> -}
> -/* Operation callback functions for thermal zone */
> -static struct thermal_zone_device_ops const exynos_dev_ops = {
> -	.bind = exynos_bind,
> -	.unbind = exynos_unbind,
> -	.get_temp = exynos_get_temp,
> -	.set_emul_temp = exynos_set_emul_temp,
> -	.get_trend = exynos_get_trend,
> -	.get_mode = exynos_get_mode,
> -	.set_mode = exynos_set_mode,
> -	.get_trip_type = exynos_get_trip_type,
> -	.get_trip_temp = exynos_get_trip_temp,
> -	.get_crit_temp = exynos_get_crit_temp,
> -};
> -
> -/*
> - * This function may be called from interrupt based temperature sensor
> - * when threshold is changed.
> - */
> -static void exynos_report_trigger(void)
> -{
> -	unsigned int i;
> -	char data[10];
> -	char *envp[] = { data, NULL };
> -
> -	if (!th_zone || !th_zone->therm_dev)
> -		return;
> -	if (th_zone->bind == false) {
> -		for (i = 0; i < th_zone->cool_dev_size; i++) {
> -			if (!th_zone->cool_dev[i])
> -				continue;
> -			exynos_bind(th_zone->therm_dev,
> -					th_zone->cool_dev[i]);
> -		}
> -	}
> -
> -	thermal_zone_device_update(th_zone->therm_dev);
> -
> -	mutex_lock(&th_zone->therm_dev->lock);
> -	/* Find the level for which trip happened */
> -	for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
> -		if (th_zone->therm_dev->last_temperature <
> -			th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
> -			break;
> -	}
> -
> -	if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
> -		!th_zone->sensor_conf->trip_data.trigger_falling) {
> -		if (i > 0)
> -			th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
> -		else
> -			th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
> -	}
> -
> -	snprintf(data, sizeof(data), "%u", i);
> -	kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
> -	mutex_unlock(&th_zone->therm_dev->lock);
> -}
> -
> -/* Register with the in-kernel thermal management */
> -static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
> -{
> -	int ret;
> -	struct cpumask mask_val;
> -
> -	if (!sensor_conf || !sensor_conf->read_temperature) {
> -		pr_err("Temperature sensor not initialised\n");
> -		return -EINVAL;
> -	}
> -
> -	th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
> -	if (!th_zone)
> -		return -ENOMEM;
> -
> -	th_zone->sensor_conf = sensor_conf;
> -	cpumask_set_cpu(0, &mask_val);
> -	th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
> -	if (IS_ERR(th_zone->cool_dev[0])) {
> -		pr_err("Failed to register cpufreq cooling device\n");
> -		ret = -EINVAL;
> -		goto err_unregister;
> -	}
> -	th_zone->cool_dev_size++;
> -
> -	th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
> -			EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
> -			sensor_conf->trip_data.trigger_falling ?
> -			0 : IDLE_INTERVAL);
> -
> -	if (IS_ERR(th_zone->therm_dev)) {
> -		pr_err("Failed to register thermal zone device\n");
> -		ret = PTR_ERR(th_zone->therm_dev);
> -		goto err_unregister;
> -	}
> -	th_zone->mode = THERMAL_DEVICE_ENABLED;
> -
> -	pr_info("Exynos: Kernel Thermal management registered\n");
> -
> -	return 0;
> -
> -err_unregister:
> -	exynos_unregister_thermal();
> -	return ret;
> -}
> -
> -/* Un-Register with the in-kernel thermal management */
> -static void exynos_unregister_thermal(void)
> -{
> -	int i;
> -
> -	if (!th_zone)
> -		return;
> -
> -	if (th_zone->therm_dev)
> -		thermal_zone_device_unregister(th_zone->therm_dev);
> -
> -	for (i = 0; i < th_zone->cool_dev_size; i++) {
> -		if (th_zone->cool_dev[i])
> -			cpufreq_cooling_unregister(th_zone->cool_dev[i]);
> -	}
> -
> -	kfree(th_zone);
> -	pr_info("Exynos: Kernel Thermal management unregistered\n");
> -}
> -
>  /*
>   * TMU treats temperature as a mapped temperature code.
>   * The temperature is converted differently depending on the calibration type.
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
> new file mode 100644
> index 0000000..9a57606
> --- /dev/null
> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
> @@ -0,0 +1,389 @@
> +/*
> + * exynos_thermal_common.c - Samsung EXYNOS common thermal file
> + *
> + *  Copyright (C) 2013 Samsung Electronics
> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
> + *
> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#include <linux/cpufreq.h>
> +#include <linux/cpu_cooling.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/kobject.h>
> +#include <linux/mutex.h>
> +#include <linux/platform_data/exynos_thermal.h>
> +#include <linux/slab.h>
> +#include <linux/thermal.h>
> +#include "exynos_thermal_common.h"
> +
> +struct exynos_thermal_zone {
> +	enum thermal_device_mode mode;
> +	struct thermal_zone_device *therm_dev;
> +	struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
> +	unsigned int cool_dev_size;
> +	struct platform_device *exynos4_dev;
> +	struct thermal_sensor_conf *sensor_conf;
> +	bool bind;
> +};
> +
> +static struct exynos_thermal_zone *th_zone;
> +
> +/* Get mode callback functions for thermal zone */
> +static int exynos_get_mode(struct thermal_zone_device *thermal,
> +			enum thermal_device_mode *mode)
> +{
> +	if (th_zone)
> +		*mode = th_zone->mode;
> +	return 0;
> +}
> +
> +/* Set mode callback functions for thermal zone */
> +static int exynos_set_mode(struct thermal_zone_device *thermal,
> +			enum thermal_device_mode mode)
> +{
> +	if (!th_zone->therm_dev) {
> +		pr_notice("thermal zone not registered\n");
> +		return 0;
> +	}
> +
> +	mutex_lock(&th_zone->therm_dev->lock);
> +
> +	if (mode == THERMAL_DEVICE_ENABLED &&
> +		!th_zone->sensor_conf->trip_data.trigger_falling)
> +		th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
> +	else
> +		th_zone->therm_dev->polling_delay = 0;
> +
> +	mutex_unlock(&th_zone->therm_dev->lock);
> +
> +	th_zone->mode = mode;
> +	thermal_zone_device_update(th_zone->therm_dev);
> +	pr_info("thermal polling set for duration=%d msec\n",
> +				th_zone->therm_dev->polling_delay);
> +	return 0;
> +}
> +
> +
> +/* Get trip type callback functions for thermal zone */
> +static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
> +				 enum thermal_trip_type *type)
> +{
> +	switch (GET_ZONE(trip)) {
> +	case MONITOR_ZONE:
> +	case WARN_ZONE:
> +		*type = THERMAL_TRIP_ACTIVE;
> +		break;
> +	case PANIC_ZONE:
> +		*type = THERMAL_TRIP_CRITICAL;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	return 0;
> +}
> +
> +/* Get trip temperature callback functions for thermal zone */
> +static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
> +				unsigned long *temp)
> +{
> +	if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
> +		return -EINVAL;
> +
> +	*temp = th_zone->sensor_conf->trip_data.trip_val[trip];
> +	/* convert the temperature into millicelsius */
> +	*temp = *temp * MCELSIUS;
> +
> +	return 0;
> +}
> +
> +/* Get critical temperature callback functions for thermal zone */
> +static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
> +				unsigned long *temp)
> +{
> +	int ret;
> +	/* Panic zone */
> +	ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
> +	return ret;
> +}
> +
> +/* Bind callback functions for thermal zone */
> +static int exynos_bind(struct thermal_zone_device *thermal,
> +			struct thermal_cooling_device *cdev)
> +{
> +	int ret = 0, i, tab_size, level;
> +	struct freq_clip_table *tab_ptr, *clip_data;
> +	struct thermal_sensor_conf *data = th_zone->sensor_conf;
> +
> +	tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
> +	tab_size = data->cooling_data.freq_clip_count;
> +
> +	if (tab_ptr == NULL || tab_size == 0)
> +		return -EINVAL;
> +
> +	/* find the cooling device registered*/
> +	for (i = 0; i < th_zone->cool_dev_size; i++)
> +		if (cdev == th_zone->cool_dev[i])
> +			break;
> +
> +	/* No matching cooling device */
> +	if (i == th_zone->cool_dev_size)
> +		return 0;
> +
> +	/* Bind the thermal zone to the cpufreq cooling device */
> +	for (i = 0; i < tab_size; i++) {
> +		clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
> +		level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
> +		if (level == THERMAL_CSTATE_INVALID)
> +			return 0;
> +		switch (GET_ZONE(i)) {
> +		case MONITOR_ZONE:
> +		case WARN_ZONE:
> +			if (thermal_zone_bind_cooling_device(thermal, i, cdev,
> +								level, 0)) {
> +				pr_err("error binding cdev inst %d\n", i);
> +				ret = -EINVAL;
> +			}
> +			th_zone->bind = true;
> +			break;
> +		default:
> +			ret = -EINVAL;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +/* Unbind callback functions for thermal zone */
> +static int exynos_unbind(struct thermal_zone_device *thermal,
> +			struct thermal_cooling_device *cdev)
> +{
> +	int ret = 0, i, tab_size;
> +	struct thermal_sensor_conf *data = th_zone->sensor_conf;
> +
> +	if (th_zone->bind == false)
> +		return 0;
> +
> +	tab_size = data->cooling_data.freq_clip_count;
> +
> +	if (tab_size == 0)
> +		return -EINVAL;
> +
> +	/* find the cooling device registered*/
> +	for (i = 0; i < th_zone->cool_dev_size; i++)
> +		if (cdev == th_zone->cool_dev[i])
> +			break;
> +
> +	/* No matching cooling device */
> +	if (i == th_zone->cool_dev_size)
> +		return 0;
> +
> +	/* Bind the thermal zone to the cpufreq cooling device */
> +	for (i = 0; i < tab_size; i++) {
> +		switch (GET_ZONE(i)) {
> +		case MONITOR_ZONE:
> +		case WARN_ZONE:
> +			if (thermal_zone_unbind_cooling_device(thermal, i,
> +								cdev)) {
> +				pr_err("error unbinding cdev inst=%d\n", i);
> +				ret = -EINVAL;
> +			}
> +			th_zone->bind = false;
> +			break;
> +		default:
> +			ret = -EINVAL;
> +		}
> +	}
> +	return ret;
> +}
> +
> +/* Get temperature callback functions for thermal zone */
> +static int exynos_get_temp(struct thermal_zone_device *thermal,
> +			unsigned long *temp)
> +{
> +	void *data;
> +
> +	if (!th_zone->sensor_conf) {
> +		pr_info("Temperature sensor not initialised\n");
> +		return -EINVAL;
> +	}
> +	data = th_zone->sensor_conf->private_data;
> +	*temp = th_zone->sensor_conf->read_temperature(data);
> +	/* convert the temperature into millicelsius */
> +	*temp = *temp * MCELSIUS;
> +	return 0;
> +}
> +
> +/* Get temperature callback functions for thermal zone */
> +static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
> +						unsigned long temp)
> +{
> +	void *data;
> +	int ret = -EINVAL;
> +
> +	if (!th_zone->sensor_conf) {
> +		pr_info("Temperature sensor not initialised\n");
> +		return -EINVAL;
> +	}
> +	data = th_zone->sensor_conf->private_data;
> +	if (th_zone->sensor_conf->write_emul_temp)
> +		ret = th_zone->sensor_conf->write_emul_temp(data, temp);
> +	return ret;
> +}
> +
> +/* Get the temperature trend */
> +static int exynos_get_trend(struct thermal_zone_device *thermal,
> +			int trip, enum thermal_trend *trend)
> +{
> +	int ret;
> +	unsigned long trip_temp;
> +
> +	ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (thermal->temperature >= trip_temp)
> +		*trend = THERMAL_TREND_RAISE_FULL;
> +	else
> +		*trend = THERMAL_TREND_DROP_FULL;
> +
> +	return 0;
> +}
> +/* Operation callback functions for thermal zone */
> +static struct thermal_zone_device_ops const exynos_dev_ops = {
> +	.bind = exynos_bind,
> +	.unbind = exynos_unbind,
> +	.get_temp = exynos_get_temp,
> +	.set_emul_temp = exynos_set_emul_temp,
> +	.get_trend = exynos_get_trend,
> +	.get_mode = exynos_get_mode,
> +	.set_mode = exynos_set_mode,
> +	.get_trip_type = exynos_get_trip_type,
> +	.get_trip_temp = exynos_get_trip_temp,
> +	.get_crit_temp = exynos_get_crit_temp,
> +};
> +
> +/*
> + * This function may be called from interrupt based temperature sensor
> + * when threshold is changed.
> + */
> +void exynos_report_trigger(void)
> +{
> +	unsigned int i;
> +	char data[10];
> +	char *envp[] = { data, NULL };
> +
> +	if (!th_zone || !th_zone->therm_dev)
> +		return;
> +	if (th_zone->bind == false) {
> +		for (i = 0; i < th_zone->cool_dev_size; i++) {
> +			if (!th_zone->cool_dev[i])
> +				continue;
> +			exynos_bind(th_zone->therm_dev,
> +					th_zone->cool_dev[i]);
> +		}
> +	}
> +
> +	thermal_zone_device_update(th_zone->therm_dev);
> +
> +	mutex_lock(&th_zone->therm_dev->lock);
> +	/* Find the level for which trip happened */
> +	for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
> +		if (th_zone->therm_dev->last_temperature <
> +			th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
> +			break;
> +	}
> +
> +	if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
> +		!th_zone->sensor_conf->trip_data.trigger_falling) {
> +		if (i > 0)
> +			th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
> +		else
> +			th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
> +	}
> +
> +	snprintf(data, sizeof(data), "%u", i);
> +	kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
> +	mutex_unlock(&th_zone->therm_dev->lock);
> +}
> +
> +/* Register with the in-kernel thermal management */
> +int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
> +{
> +	int ret;
> +	struct cpumask mask_val;
> +
> +	if (!sensor_conf || !sensor_conf->read_temperature) {
> +		pr_err("Temperature sensor not initialised\n");
> +		return -EINVAL;
> +	}
> +
> +	th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
> +	if (!th_zone)
> +		return -ENOMEM;
> +
> +	th_zone->sensor_conf = sensor_conf;
> +	cpumask_set_cpu(0, &mask_val);
> +	th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
> +	if (IS_ERR(th_zone->cool_dev[0])) {
> +		pr_err("Failed to register cpufreq cooling device\n");
> +		ret = -EINVAL;
> +		goto err_unregister;
> +	}
> +	th_zone->cool_dev_size++;
> +
> +	th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
> +			EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
> +			sensor_conf->trip_data.trigger_falling ?
> +			0 : IDLE_INTERVAL);
> +
> +	if (IS_ERR(th_zone->therm_dev)) {
> +		pr_err("Failed to register thermal zone device\n");
> +		ret = PTR_ERR(th_zone->therm_dev);
> +		goto err_unregister;
> +	}
> +	th_zone->mode = THERMAL_DEVICE_ENABLED;
> +
> +	pr_info("Exynos: Kernel Thermal management registered\n");
> +
> +	return 0;
> +
> +err_unregister:
> +	exynos_unregister_thermal();
> +	return ret;
> +}
> +
> +/* Un-Register with the in-kernel thermal management */
> +void exynos_unregister_thermal(void)
> +{
> +	int i;
> +
> +	if (!th_zone)
> +		return;
> +
> +	if (th_zone->therm_dev)
> +		thermal_zone_device_unregister(th_zone->therm_dev);
> +
> +	for (i = 0; i < th_zone->cool_dev_size; i++) {
> +		if (th_zone->cool_dev[i])
> +			cpufreq_cooling_unregister(th_zone->cool_dev[i]);
> +	}
> +
> +	kfree(th_zone);
> +	pr_info("Exynos: Kernel Thermal management unregistered\n");
> +}
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
> new file mode 100644
> index 0000000..da2add0
> --- /dev/null
> +++ b/drivers/thermal/samsung/exynos_thermal_common.h
> @@ -0,0 +1,83 @@
> +/*
> + * exynos_thermal_common.h - Samsung EXYNOS common header file
> + *
> + *  Copyright (C) 2013 Samsung Electronics
> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
> + *
> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#ifndef _LINUX_EXYNOS_THERMAL_COMMON_H
> +#define _LINUX_EXYNOS_THERMAL_COMMON_H
> +
> +/* In-kernel thermal framework related macros & definations */
> +#define SENSOR_NAME_LEN	16
> +#define MAX_TRIP_COUNT	8
> +#define MAX_COOLING_DEVICE 4
> +#define MAX_THRESHOLD_LEVS 4
> +
> +#define ACTIVE_INTERVAL 500
> +#define IDLE_INTERVAL 10000
> +#define MCELSIUS	1000
> +
> +/* CPU Zone information */
> +#define PANIC_ZONE      4
> +#define WARN_ZONE       3
> +#define MONITOR_ZONE    2
> +#define SAFE_ZONE       1
> +
> +#define GET_ZONE(trip) (trip + 2)
> +#define GET_TRIP(zone) (zone - 2)
> +
> +#define EXYNOS_ZONE_COUNT	3
> +
> +struct	thermal_trip_point_conf {
> +	int trip_val[MAX_TRIP_COUNT];
> +	int trip_count;
> +	u8 trigger_falling;
> +};
> +
> +struct	thermal_cooling_conf {
> +	struct freq_clip_table freq_data[MAX_TRIP_COUNT];
> +	int freq_clip_count;
> +};
> +
> +struct thermal_sensor_conf {
> +	char name[SENSOR_NAME_LEN];
> +	int (*read_temperature)(void *data);
> +	int (*write_emul_temp)(void *drv_data, unsigned long temp);
> +	struct thermal_trip_point_conf trip_data;
> +	struct thermal_cooling_conf cooling_data;
> +	void *private_data;
> +};
> +
> +/*Functions used exynos based thermal sensor driver*/
> +#ifdef CONFIG_EXYNOS_THERMAL_CORE
> +void exynos_unregister_thermal(void);
> +int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
> +void exynos_report_trigger(void);
> +#else
> +static inline void
> +exynos_unregister_thermal(void) { return; }
> +
> +static inline int
> +exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
> +
> +static inline void
> +exynos_report_trigger(void) { return; }
> +
> +#endif /* CONFIG_EXYNOS_COMMON */
> +#endif /* _LINUX_EXYNOS_THERMAL_COMMON_H */



^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 02/21] thermal: exynos: Bifurcate exynos thermal common and tmu controller code
  2013-05-07 13:41   ` Zhang Rui
@ 2013-05-08  3:49     ` amit daniel kachhap
  0 siblings, 0 replies; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-08  3:49 UTC (permalink / raw)
  To: Zhang Rui
  Cc: linux-pm, linux-samsung-soc, linux-kernel, Kukjin Kim, Eduardo Valentin

Hi Rui,

On Tue, May 7, 2013 at 7:11 PM, Zhang Rui <rui.zhang@intel.com> wrote:
> On Tue, 2013-05-07 at 18:30 +0530, Amit Daniel Kachhap wrote:
>> This code bifurcates exynos thermal implementation into common and sensor
>> specific parts. The common thermal code interacts with core thermal layer and
>> core cpufreq cooling parts and is independent of SOC specific driver. This
>> change is needed to cleanly add support for new TMU sensors.
>>
>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>> ---
>>  drivers/thermal/samsung/Kconfig                 |   20 +-
>>  drivers/thermal/samsung/Makefile                |    4 +-
>>  drivers/thermal/samsung/exynos_thermal.c        |  421 +----------------------
>>  drivers/thermal/samsung/exynos_thermal_common.c |  389 +++++++++++++++++++++
>>  drivers/thermal/samsung/exynos_thermal_common.h |   83 +++++
>>  5 files changed, 498 insertions(+), 419 deletions(-)
>>  create mode 100644 drivers/thermal/samsung/exynos_thermal_common.c
>>  create mode 100644 drivers/thermal/samsung/exynos_thermal_common.h
>>
>> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
>> index 2d3d9dc..7857e20 100644
>> --- a/drivers/thermal/samsung/Kconfig
>> +++ b/drivers/thermal/samsung/Kconfig
>> @@ -1,9 +1,17 @@
>>  config EXYNOS_THERMAL
>> -     tristate "Temperature sensor on Samsung EXYNOS"
>> +     tristate "Exynos thermal management unit driver"
>>       depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
>> -     depends on CPU_THERMAL
>>       help
>> -       If you say yes here you get support for TMU (Thermal Management
>> -       Unit) on SAMSUNG EXYNOS series of SoC. This helps in registering
>> -       the exynos thermal driver with the core thermal layer and cpu
>> -       cooling API's.
>> +       If you say yes here you get support for the exynos thermal driver
>> +       for exynos4 and exynos5 soc. This driver initialises the TMU, reports
>> +       temperature and handles cooling action if defined. This driver uses
>> +       core thermal API's.
>> +
>> +config EXYNOS_THERMAL_CORE
>> +     bool "Core thermal framework support for EXYNOS SOC's"
>> +     depends on EXYNOS_THERMAL
>> +     help
>> +       If you say yes here you get support for EXYNOS TMU
>> +       (Thermal Management Unit) common registration/unregistration
>> +       functions to the core thermal layer and also to use the generic
>> +       cpu cooling API's.
>
> I'm still not quite clear what you want to get there.
> If EXYNOS_THERMAL=y and EXYNOS_THERMAL_CORE=n, you'll get an Exynos tmu
> driver which is not shown in /sys/class/thermal/ and can not be used for
> thermal management?
Yes I understood your point.
I have kept separate config entry EXYNOS_THERMAL_CORE to make it
scalable. Say a totally different TMU controller comes which is not
possible to fit in the current exynos_tmu.c file and new file might be
needed but still this new thermal controller can use the thermal core
file. Even for 5440 I had hard time integrating the thermal driver as
it is quite different from the existing driver.
In the current scenario even though EXYNOS_THERMAL_CORE=n, TMU h/w is
initialised and there are other mechanisms to read the temperature
like I2C based but yes as you said full thermal management is not
possible.

Regards,
Amit Daniel
>
> thanks,
> rui
>> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
>> index 1fe6d93..6227d4f 100644
>> --- a/drivers/thermal/samsung/Makefile
>> +++ b/drivers/thermal/samsung/Makefile
>> @@ -1,4 +1,6 @@
>>  #
>>  # Samsung thermal specific Makefile
>>  #
>> -obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o
>> +obj-$(CONFIG_EXYNOS_THERMAL)                 += exynos_soc_thermal.o
>> +exynos_soc_thermal-y                         := exynos_thermal.o
>> +exynos_soc_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
>> diff --git a/drivers/thermal/samsung/exynos_thermal.c b/drivers/thermal/samsung/exynos_thermal.c
>> index d20ce9e..4c85945 100644
>> --- a/drivers/thermal/samsung/exynos_thermal.c
>> +++ b/drivers/thermal/samsung/exynos_thermal.c
>> @@ -21,23 +21,19 @@
>>   *
>>   */
>>
>> -#include <linux/module.h>
>> -#include <linux/err.h>
>> -#include <linux/kernel.h>
>> -#include <linux/slab.h>
>> -#include <linux/platform_device.h>
>> -#include <linux/interrupt.h>
>>  #include <linux/clk.h>
>> -#include <linux/workqueue.h>
>> -#include <linux/sysfs.h>
>> -#include <linux/kobject.h>
>>  #include <linux/io.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/kernel.h>
>> +#include <linux/kobject.h>
>> +#include <linux/module.h>
>>  #include <linux/mutex.h>
>> -#include <linux/platform_data/exynos_thermal.h>
>> -#include <linux/thermal.h>
>> -#include <linux/cpufreq.h>
>> -#include <linux/cpu_cooling.h>
>>  #include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/platform_data/exynos_thermal.h>
>> +#include <linux/slab.h>
>> +#include <linux/workqueue.h>
>> +#include "exynos_thermal_common.h"
>>
>>  /* Exynos generic registers */
>>  #define EXYNOS_TMU_REG_TRIMINFO              0x0
>> @@ -88,16 +84,6 @@
>>  #define EFUSE_MIN_VALUE 40
>>  #define EFUSE_MAX_VALUE 100
>>
>> -/* In-kernel thermal framework related macros & definations */
>> -#define SENSOR_NAME_LEN      16
>> -#define MAX_TRIP_COUNT       8
>> -#define MAX_COOLING_DEVICE 4
>> -#define MAX_THRESHOLD_LEVS 4
>> -
>> -#define ACTIVE_INTERVAL 500
>> -#define IDLE_INTERVAL 10000
>> -#define MCELSIUS     1000
>> -
>>  #ifdef CONFIG_THERMAL_EMULATION
>>  #define EXYNOS_EMUL_TIME     0x57F0
>>  #define EXYNOS_EMUL_TIME_SHIFT       16
>> @@ -106,17 +92,6 @@
>>  #define EXYNOS_EMUL_ENABLE   0x1
>>  #endif /* CONFIG_THERMAL_EMULATION */
>>
>> -/* CPU Zone information */
>> -#define PANIC_ZONE      4
>> -#define WARN_ZONE       3
>> -#define MONITOR_ZONE    2
>> -#define SAFE_ZONE       1
>> -
>> -#define GET_ZONE(trip) (trip + 2)
>> -#define GET_TRIP(zone) (zone - 2)
>> -
>> -#define EXYNOS_ZONE_COUNT    3
>> -
>>  struct exynos_tmu_data {
>>       struct exynos_tmu_platform_data *pdata;
>>       struct resource *mem;
>> @@ -129,384 +104,6 @@ struct exynos_tmu_data {
>>       u8 temp_error1, temp_error2;
>>  };
>>
>> -struct       thermal_trip_point_conf {
>> -     int trip_val[MAX_TRIP_COUNT];
>> -     int trip_count;
>> -     u8 trigger_falling;
>> -};
>> -
>> -struct       thermal_cooling_conf {
>> -     struct freq_clip_table freq_data[MAX_TRIP_COUNT];
>> -     int freq_clip_count;
>> -};
>> -
>> -struct thermal_sensor_conf {
>> -     char name[SENSOR_NAME_LEN];
>> -     int (*read_temperature)(void *data);
>> -     int (*write_emul_temp)(void *drv_data, unsigned long temp);
>> -     struct thermal_trip_point_conf trip_data;
>> -     struct thermal_cooling_conf cooling_data;
>> -     void *private_data;
>> -};
>> -
>> -struct exynos_thermal_zone {
>> -     enum thermal_device_mode mode;
>> -     struct thermal_zone_device *therm_dev;
>> -     struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
>> -     unsigned int cool_dev_size;
>> -     struct platform_device *exynos4_dev;
>> -     struct thermal_sensor_conf *sensor_conf;
>> -     bool bind;
>> -};
>> -
>> -static struct exynos_thermal_zone *th_zone;
>> -static void exynos_unregister_thermal(void);
>> -static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
>> -
>> -/* Get mode callback functions for thermal zone */
>> -static int exynos_get_mode(struct thermal_zone_device *thermal,
>> -                     enum thermal_device_mode *mode)
>> -{
>> -     if (th_zone)
>> -             *mode = th_zone->mode;
>> -     return 0;
>> -}
>> -
>> -/* Set mode callback functions for thermal zone */
>> -static int exynos_set_mode(struct thermal_zone_device *thermal,
>> -                     enum thermal_device_mode mode)
>> -{
>> -     if (!th_zone->therm_dev) {
>> -             pr_notice("thermal zone not registered\n");
>> -             return 0;
>> -     }
>> -
>> -     mutex_lock(&th_zone->therm_dev->lock);
>> -
>> -     if (mode == THERMAL_DEVICE_ENABLED &&
>> -             !th_zone->sensor_conf->trip_data.trigger_falling)
>> -             th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
>> -     else
>> -             th_zone->therm_dev->polling_delay = 0;
>> -
>> -     mutex_unlock(&th_zone->therm_dev->lock);
>> -
>> -     th_zone->mode = mode;
>> -     thermal_zone_device_update(th_zone->therm_dev);
>> -     pr_info("thermal polling set for duration=%d msec\n",
>> -                             th_zone->therm_dev->polling_delay);
>> -     return 0;
>> -}
>> -
>> -
>> -/* Get trip type callback functions for thermal zone */
>> -static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
>> -                              enum thermal_trip_type *type)
>> -{
>> -     switch (GET_ZONE(trip)) {
>> -     case MONITOR_ZONE:
>> -     case WARN_ZONE:
>> -             *type = THERMAL_TRIP_ACTIVE;
>> -             break;
>> -     case PANIC_ZONE:
>> -             *type = THERMAL_TRIP_CRITICAL;
>> -             break;
>> -     default:
>> -             return -EINVAL;
>> -     }
>> -     return 0;
>> -}
>> -
>> -/* Get trip temperature callback functions for thermal zone */
>> -static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
>> -                             unsigned long *temp)
>> -{
>> -     if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
>> -             return -EINVAL;
>> -
>> -     *temp = th_zone->sensor_conf->trip_data.trip_val[trip];
>> -     /* convert the temperature into millicelsius */
>> -     *temp = *temp * MCELSIUS;
>> -
>> -     return 0;
>> -}
>> -
>> -/* Get critical temperature callback functions for thermal zone */
>> -static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
>> -                             unsigned long *temp)
>> -{
>> -     int ret;
>> -     /* Panic zone */
>> -     ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
>> -     return ret;
>> -}
>> -
>> -/* Bind callback functions for thermal zone */
>> -static int exynos_bind(struct thermal_zone_device *thermal,
>> -                     struct thermal_cooling_device *cdev)
>> -{
>> -     int ret = 0, i, tab_size, level;
>> -     struct freq_clip_table *tab_ptr, *clip_data;
>> -     struct thermal_sensor_conf *data = th_zone->sensor_conf;
>> -
>> -     tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
>> -     tab_size = data->cooling_data.freq_clip_count;
>> -
>> -     if (tab_ptr == NULL || tab_size == 0)
>> -             return -EINVAL;
>> -
>> -     /* find the cooling device registered*/
>> -     for (i = 0; i < th_zone->cool_dev_size; i++)
>> -             if (cdev == th_zone->cool_dev[i])
>> -                     break;
>> -
>> -     /* No matching cooling device */
>> -     if (i == th_zone->cool_dev_size)
>> -             return 0;
>> -
>> -     /* Bind the thermal zone to the cpufreq cooling device */
>> -     for (i = 0; i < tab_size; i++) {
>> -             clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
>> -             level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
>> -             if (level == THERMAL_CSTATE_INVALID)
>> -                     return 0;
>> -             switch (GET_ZONE(i)) {
>> -             case MONITOR_ZONE:
>> -             case WARN_ZONE:
>> -                     if (thermal_zone_bind_cooling_device(thermal, i, cdev,
>> -                                                             level, 0)) {
>> -                             pr_err("error binding cdev inst %d\n", i);
>> -                             ret = -EINVAL;
>> -                     }
>> -                     th_zone->bind = true;
>> -                     break;
>> -             default:
>> -                     ret = -EINVAL;
>> -             }
>> -     }
>> -
>> -     return ret;
>> -}
>> -
>> -/* Unbind callback functions for thermal zone */
>> -static int exynos_unbind(struct thermal_zone_device *thermal,
>> -                     struct thermal_cooling_device *cdev)
>> -{
>> -     int ret = 0, i, tab_size;
>> -     struct thermal_sensor_conf *data = th_zone->sensor_conf;
>> -
>> -     if (th_zone->bind == false)
>> -             return 0;
>> -
>> -     tab_size = data->cooling_data.freq_clip_count;
>> -
>> -     if (tab_size == 0)
>> -             return -EINVAL;
>> -
>> -     /* find the cooling device registered*/
>> -     for (i = 0; i < th_zone->cool_dev_size; i++)
>> -             if (cdev == th_zone->cool_dev[i])
>> -                     break;
>> -
>> -     /* No matching cooling device */
>> -     if (i == th_zone->cool_dev_size)
>> -             return 0;
>> -
>> -     /* Bind the thermal zone to the cpufreq cooling device */
>> -     for (i = 0; i < tab_size; i++) {
>> -             switch (GET_ZONE(i)) {
>> -             case MONITOR_ZONE:
>> -             case WARN_ZONE:
>> -                     if (thermal_zone_unbind_cooling_device(thermal, i,
>> -                                                             cdev)) {
>> -                             pr_err("error unbinding cdev inst=%d\n", i);
>> -                             ret = -EINVAL;
>> -                     }
>> -                     th_zone->bind = false;
>> -                     break;
>> -             default:
>> -                     ret = -EINVAL;
>> -             }
>> -     }
>> -     return ret;
>> -}
>> -
>> -/* Get temperature callback functions for thermal zone */
>> -static int exynos_get_temp(struct thermal_zone_device *thermal,
>> -                     unsigned long *temp)
>> -{
>> -     void *data;
>> -
>> -     if (!th_zone->sensor_conf) {
>> -             pr_info("Temperature sensor not initialised\n");
>> -             return -EINVAL;
>> -     }
>> -     data = th_zone->sensor_conf->private_data;
>> -     *temp = th_zone->sensor_conf->read_temperature(data);
>> -     /* convert the temperature into millicelsius */
>> -     *temp = *temp * MCELSIUS;
>> -     return 0;
>> -}
>> -
>> -/* Get temperature callback functions for thermal zone */
>> -static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
>> -                                             unsigned long temp)
>> -{
>> -     void *data;
>> -     int ret = -EINVAL;
>> -
>> -     if (!th_zone->sensor_conf) {
>> -             pr_info("Temperature sensor not initialised\n");
>> -             return -EINVAL;
>> -     }
>> -     data = th_zone->sensor_conf->private_data;
>> -     if (th_zone->sensor_conf->write_emul_temp)
>> -             ret = th_zone->sensor_conf->write_emul_temp(data, temp);
>> -     return ret;
>> -}
>> -
>> -/* Get the temperature trend */
>> -static int exynos_get_trend(struct thermal_zone_device *thermal,
>> -                     int trip, enum thermal_trend *trend)
>> -{
>> -     int ret;
>> -     unsigned long trip_temp;
>> -
>> -     ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
>> -     if (ret < 0)
>> -             return ret;
>> -
>> -     if (thermal->temperature >= trip_temp)
>> -             *trend = THERMAL_TREND_RAISE_FULL;
>> -     else
>> -             *trend = THERMAL_TREND_DROP_FULL;
>> -
>> -     return 0;
>> -}
>> -/* Operation callback functions for thermal zone */
>> -static struct thermal_zone_device_ops const exynos_dev_ops = {
>> -     .bind = exynos_bind,
>> -     .unbind = exynos_unbind,
>> -     .get_temp = exynos_get_temp,
>> -     .set_emul_temp = exynos_set_emul_temp,
>> -     .get_trend = exynos_get_trend,
>> -     .get_mode = exynos_get_mode,
>> -     .set_mode = exynos_set_mode,
>> -     .get_trip_type = exynos_get_trip_type,
>> -     .get_trip_temp = exynos_get_trip_temp,
>> -     .get_crit_temp = exynos_get_crit_temp,
>> -};
>> -
>> -/*
>> - * This function may be called from interrupt based temperature sensor
>> - * when threshold is changed.
>> - */
>> -static void exynos_report_trigger(void)
>> -{
>> -     unsigned int i;
>> -     char data[10];
>> -     char *envp[] = { data, NULL };
>> -
>> -     if (!th_zone || !th_zone->therm_dev)
>> -             return;
>> -     if (th_zone->bind == false) {
>> -             for (i = 0; i < th_zone->cool_dev_size; i++) {
>> -                     if (!th_zone->cool_dev[i])
>> -                             continue;
>> -                     exynos_bind(th_zone->therm_dev,
>> -                                     th_zone->cool_dev[i]);
>> -             }
>> -     }
>> -
>> -     thermal_zone_device_update(th_zone->therm_dev);
>> -
>> -     mutex_lock(&th_zone->therm_dev->lock);
>> -     /* Find the level for which trip happened */
>> -     for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
>> -             if (th_zone->therm_dev->last_temperature <
>> -                     th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
>> -                     break;
>> -     }
>> -
>> -     if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
>> -             !th_zone->sensor_conf->trip_data.trigger_falling) {
>> -             if (i > 0)
>> -                     th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
>> -             else
>> -                     th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
>> -     }
>> -
>> -     snprintf(data, sizeof(data), "%u", i);
>> -     kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
>> -     mutex_unlock(&th_zone->therm_dev->lock);
>> -}
>> -
>> -/* Register with the in-kernel thermal management */
>> -static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
>> -{
>> -     int ret;
>> -     struct cpumask mask_val;
>> -
>> -     if (!sensor_conf || !sensor_conf->read_temperature) {
>> -             pr_err("Temperature sensor not initialised\n");
>> -             return -EINVAL;
>> -     }
>> -
>> -     th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
>> -     if (!th_zone)
>> -             return -ENOMEM;
>> -
>> -     th_zone->sensor_conf = sensor_conf;
>> -     cpumask_set_cpu(0, &mask_val);
>> -     th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
>> -     if (IS_ERR(th_zone->cool_dev[0])) {
>> -             pr_err("Failed to register cpufreq cooling device\n");
>> -             ret = -EINVAL;
>> -             goto err_unregister;
>> -     }
>> -     th_zone->cool_dev_size++;
>> -
>> -     th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
>> -                     EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
>> -                     sensor_conf->trip_data.trigger_falling ?
>> -                     0 : IDLE_INTERVAL);
>> -
>> -     if (IS_ERR(th_zone->therm_dev)) {
>> -             pr_err("Failed to register thermal zone device\n");
>> -             ret = PTR_ERR(th_zone->therm_dev);
>> -             goto err_unregister;
>> -     }
>> -     th_zone->mode = THERMAL_DEVICE_ENABLED;
>> -
>> -     pr_info("Exynos: Kernel Thermal management registered\n");
>> -
>> -     return 0;
>> -
>> -err_unregister:
>> -     exynos_unregister_thermal();
>> -     return ret;
>> -}
>> -
>> -/* Un-Register with the in-kernel thermal management */
>> -static void exynos_unregister_thermal(void)
>> -{
>> -     int i;
>> -
>> -     if (!th_zone)
>> -             return;
>> -
>> -     if (th_zone->therm_dev)
>> -             thermal_zone_device_unregister(th_zone->therm_dev);
>> -
>> -     for (i = 0; i < th_zone->cool_dev_size; i++) {
>> -             if (th_zone->cool_dev[i])
>> -                     cpufreq_cooling_unregister(th_zone->cool_dev[i]);
>> -     }
>> -
>> -     kfree(th_zone);
>> -     pr_info("Exynos: Kernel Thermal management unregistered\n");
>> -}
>> -
>>  /*
>>   * TMU treats temperature as a mapped temperature code.
>>   * The temperature is converted differently depending on the calibration type.
>> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
>> new file mode 100644
>> index 0000000..9a57606
>> --- /dev/null
>> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
>> @@ -0,0 +1,389 @@
>> +/*
>> + * exynos_thermal_common.c - Samsung EXYNOS common thermal file
>> + *
>> + *  Copyright (C) 2013 Samsung Electronics
>> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
>> + *
>> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
>> + *
>> + */
>> +
>> +#include <linux/cpufreq.h>
>> +#include <linux/cpu_cooling.h>
>> +#include <linux/err.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/kobject.h>
>> +#include <linux/mutex.h>
>> +#include <linux/platform_data/exynos_thermal.h>
>> +#include <linux/slab.h>
>> +#include <linux/thermal.h>
>> +#include "exynos_thermal_common.h"
>> +
>> +struct exynos_thermal_zone {
>> +     enum thermal_device_mode mode;
>> +     struct thermal_zone_device *therm_dev;
>> +     struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
>> +     unsigned int cool_dev_size;
>> +     struct platform_device *exynos4_dev;
>> +     struct thermal_sensor_conf *sensor_conf;
>> +     bool bind;
>> +};
>> +
>> +static struct exynos_thermal_zone *th_zone;
>> +
>> +/* Get mode callback functions for thermal zone */
>> +static int exynos_get_mode(struct thermal_zone_device *thermal,
>> +                     enum thermal_device_mode *mode)
>> +{
>> +     if (th_zone)
>> +             *mode = th_zone->mode;
>> +     return 0;
>> +}
>> +
>> +/* Set mode callback functions for thermal zone */
>> +static int exynos_set_mode(struct thermal_zone_device *thermal,
>> +                     enum thermal_device_mode mode)
>> +{
>> +     if (!th_zone->therm_dev) {
>> +             pr_notice("thermal zone not registered\n");
>> +             return 0;
>> +     }
>> +
>> +     mutex_lock(&th_zone->therm_dev->lock);
>> +
>> +     if (mode == THERMAL_DEVICE_ENABLED &&
>> +             !th_zone->sensor_conf->trip_data.trigger_falling)
>> +             th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
>> +     else
>> +             th_zone->therm_dev->polling_delay = 0;
>> +
>> +     mutex_unlock(&th_zone->therm_dev->lock);
>> +
>> +     th_zone->mode = mode;
>> +     thermal_zone_device_update(th_zone->therm_dev);
>> +     pr_info("thermal polling set for duration=%d msec\n",
>> +                             th_zone->therm_dev->polling_delay);
>> +     return 0;
>> +}
>> +
>> +
>> +/* Get trip type callback functions for thermal zone */
>> +static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
>> +                              enum thermal_trip_type *type)
>> +{
>> +     switch (GET_ZONE(trip)) {
>> +     case MONITOR_ZONE:
>> +     case WARN_ZONE:
>> +             *type = THERMAL_TRIP_ACTIVE;
>> +             break;
>> +     case PANIC_ZONE:
>> +             *type = THERMAL_TRIP_CRITICAL;
>> +             break;
>> +     default:
>> +             return -EINVAL;
>> +     }
>> +     return 0;
>> +}
>> +
>> +/* Get trip temperature callback functions for thermal zone */
>> +static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
>> +                             unsigned long *temp)
>> +{
>> +     if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
>> +             return -EINVAL;
>> +
>> +     *temp = th_zone->sensor_conf->trip_data.trip_val[trip];
>> +     /* convert the temperature into millicelsius */
>> +     *temp = *temp * MCELSIUS;
>> +
>> +     return 0;
>> +}
>> +
>> +/* Get critical temperature callback functions for thermal zone */
>> +static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
>> +                             unsigned long *temp)
>> +{
>> +     int ret;
>> +     /* Panic zone */
>> +     ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
>> +     return ret;
>> +}
>> +
>> +/* Bind callback functions for thermal zone */
>> +static int exynos_bind(struct thermal_zone_device *thermal,
>> +                     struct thermal_cooling_device *cdev)
>> +{
>> +     int ret = 0, i, tab_size, level;
>> +     struct freq_clip_table *tab_ptr, *clip_data;
>> +     struct thermal_sensor_conf *data = th_zone->sensor_conf;
>> +
>> +     tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
>> +     tab_size = data->cooling_data.freq_clip_count;
>> +
>> +     if (tab_ptr == NULL || tab_size == 0)
>> +             return -EINVAL;
>> +
>> +     /* find the cooling device registered*/
>> +     for (i = 0; i < th_zone->cool_dev_size; i++)
>> +             if (cdev == th_zone->cool_dev[i])
>> +                     break;
>> +
>> +     /* No matching cooling device */
>> +     if (i == th_zone->cool_dev_size)
>> +             return 0;
>> +
>> +     /* Bind the thermal zone to the cpufreq cooling device */
>> +     for (i = 0; i < tab_size; i++) {
>> +             clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
>> +             level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
>> +             if (level == THERMAL_CSTATE_INVALID)
>> +                     return 0;
>> +             switch (GET_ZONE(i)) {
>> +             case MONITOR_ZONE:
>> +             case WARN_ZONE:
>> +                     if (thermal_zone_bind_cooling_device(thermal, i, cdev,
>> +                                                             level, 0)) {
>> +                             pr_err("error binding cdev inst %d\n", i);
>> +                             ret = -EINVAL;
>> +                     }
>> +                     th_zone->bind = true;
>> +                     break;
>> +             default:
>> +                     ret = -EINVAL;
>> +             }
>> +     }
>> +
>> +     return ret;
>> +}
>> +
>> +/* Unbind callback functions for thermal zone */
>> +static int exynos_unbind(struct thermal_zone_device *thermal,
>> +                     struct thermal_cooling_device *cdev)
>> +{
>> +     int ret = 0, i, tab_size;
>> +     struct thermal_sensor_conf *data = th_zone->sensor_conf;
>> +
>> +     if (th_zone->bind == false)
>> +             return 0;
>> +
>> +     tab_size = data->cooling_data.freq_clip_count;
>> +
>> +     if (tab_size == 0)
>> +             return -EINVAL;
>> +
>> +     /* find the cooling device registered*/
>> +     for (i = 0; i < th_zone->cool_dev_size; i++)
>> +             if (cdev == th_zone->cool_dev[i])
>> +                     break;
>> +
>> +     /* No matching cooling device */
>> +     if (i == th_zone->cool_dev_size)
>> +             return 0;
>> +
>> +     /* Bind the thermal zone to the cpufreq cooling device */
>> +     for (i = 0; i < tab_size; i++) {
>> +             switch (GET_ZONE(i)) {
>> +             case MONITOR_ZONE:
>> +             case WARN_ZONE:
>> +                     if (thermal_zone_unbind_cooling_device(thermal, i,
>> +                                                             cdev)) {
>> +                             pr_err("error unbinding cdev inst=%d\n", i);
>> +                             ret = -EINVAL;
>> +                     }
>> +                     th_zone->bind = false;
>> +                     break;
>> +             default:
>> +                     ret = -EINVAL;
>> +             }
>> +     }
>> +     return ret;
>> +}
>> +
>> +/* Get temperature callback functions for thermal zone */
>> +static int exynos_get_temp(struct thermal_zone_device *thermal,
>> +                     unsigned long *temp)
>> +{
>> +     void *data;
>> +
>> +     if (!th_zone->sensor_conf) {
>> +             pr_info("Temperature sensor not initialised\n");
>> +             return -EINVAL;
>> +     }
>> +     data = th_zone->sensor_conf->private_data;
>> +     *temp = th_zone->sensor_conf->read_temperature(data);
>> +     /* convert the temperature into millicelsius */
>> +     *temp = *temp * MCELSIUS;
>> +     return 0;
>> +}
>> +
>> +/* Get temperature callback functions for thermal zone */
>> +static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
>> +                                             unsigned long temp)
>> +{
>> +     void *data;
>> +     int ret = -EINVAL;
>> +
>> +     if (!th_zone->sensor_conf) {
>> +             pr_info("Temperature sensor not initialised\n");
>> +             return -EINVAL;
>> +     }
>> +     data = th_zone->sensor_conf->private_data;
>> +     if (th_zone->sensor_conf->write_emul_temp)
>> +             ret = th_zone->sensor_conf->write_emul_temp(data, temp);
>> +     return ret;
>> +}
>> +
>> +/* Get the temperature trend */
>> +static int exynos_get_trend(struct thermal_zone_device *thermal,
>> +                     int trip, enum thermal_trend *trend)
>> +{
>> +     int ret;
>> +     unsigned long trip_temp;
>> +
>> +     ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
>> +     if (ret < 0)
>> +             return ret;
>> +
>> +     if (thermal->temperature >= trip_temp)
>> +             *trend = THERMAL_TREND_RAISE_FULL;
>> +     else
>> +             *trend = THERMAL_TREND_DROP_FULL;
>> +
>> +     return 0;
>> +}
>> +/* Operation callback functions for thermal zone */
>> +static struct thermal_zone_device_ops const exynos_dev_ops = {
>> +     .bind = exynos_bind,
>> +     .unbind = exynos_unbind,
>> +     .get_temp = exynos_get_temp,
>> +     .set_emul_temp = exynos_set_emul_temp,
>> +     .get_trend = exynos_get_trend,
>> +     .get_mode = exynos_get_mode,
>> +     .set_mode = exynos_set_mode,
>> +     .get_trip_type = exynos_get_trip_type,
>> +     .get_trip_temp = exynos_get_trip_temp,
>> +     .get_crit_temp = exynos_get_crit_temp,
>> +};
>> +
>> +/*
>> + * This function may be called from interrupt based temperature sensor
>> + * when threshold is changed.
>> + */
>> +void exynos_report_trigger(void)
>> +{
>> +     unsigned int i;
>> +     char data[10];
>> +     char *envp[] = { data, NULL };
>> +
>> +     if (!th_zone || !th_zone->therm_dev)
>> +             return;
>> +     if (th_zone->bind == false) {
>> +             for (i = 0; i < th_zone->cool_dev_size; i++) {
>> +                     if (!th_zone->cool_dev[i])
>> +                             continue;
>> +                     exynos_bind(th_zone->therm_dev,
>> +                                     th_zone->cool_dev[i]);
>> +             }
>> +     }
>> +
>> +     thermal_zone_device_update(th_zone->therm_dev);
>> +
>> +     mutex_lock(&th_zone->therm_dev->lock);
>> +     /* Find the level for which trip happened */
>> +     for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
>> +             if (th_zone->therm_dev->last_temperature <
>> +                     th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
>> +                     break;
>> +     }
>> +
>> +     if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
>> +             !th_zone->sensor_conf->trip_data.trigger_falling) {
>> +             if (i > 0)
>> +                     th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
>> +             else
>> +                     th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
>> +     }
>> +
>> +     snprintf(data, sizeof(data), "%u", i);
>> +     kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
>> +     mutex_unlock(&th_zone->therm_dev->lock);
>> +}
>> +
>> +/* Register with the in-kernel thermal management */
>> +int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
>> +{
>> +     int ret;
>> +     struct cpumask mask_val;
>> +
>> +     if (!sensor_conf || !sensor_conf->read_temperature) {
>> +             pr_err("Temperature sensor not initialised\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
>> +     if (!th_zone)
>> +             return -ENOMEM;
>> +
>> +     th_zone->sensor_conf = sensor_conf;
>> +     cpumask_set_cpu(0, &mask_val);
>> +     th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
>> +     if (IS_ERR(th_zone->cool_dev[0])) {
>> +             pr_err("Failed to register cpufreq cooling device\n");
>> +             ret = -EINVAL;
>> +             goto err_unregister;
>> +     }
>> +     th_zone->cool_dev_size++;
>> +
>> +     th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
>> +                     EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
>> +                     sensor_conf->trip_data.trigger_falling ?
>> +                     0 : IDLE_INTERVAL);
>> +
>> +     if (IS_ERR(th_zone->therm_dev)) {
>> +             pr_err("Failed to register thermal zone device\n");
>> +             ret = PTR_ERR(th_zone->therm_dev);
>> +             goto err_unregister;
>> +     }
>> +     th_zone->mode = THERMAL_DEVICE_ENABLED;
>> +
>> +     pr_info("Exynos: Kernel Thermal management registered\n");
>> +
>> +     return 0;
>> +
>> +err_unregister:
>> +     exynos_unregister_thermal();
>> +     return ret;
>> +}
>> +
>> +/* Un-Register with the in-kernel thermal management */
>> +void exynos_unregister_thermal(void)
>> +{
>> +     int i;
>> +
>> +     if (!th_zone)
>> +             return;
>> +
>> +     if (th_zone->therm_dev)
>> +             thermal_zone_device_unregister(th_zone->therm_dev);
>> +
>> +     for (i = 0; i < th_zone->cool_dev_size; i++) {
>> +             if (th_zone->cool_dev[i])
>> +                     cpufreq_cooling_unregister(th_zone->cool_dev[i]);
>> +     }
>> +
>> +     kfree(th_zone);
>> +     pr_info("Exynos: Kernel Thermal management unregistered\n");
>> +}
>> diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
>> new file mode 100644
>> index 0000000..da2add0
>> --- /dev/null
>> +++ b/drivers/thermal/samsung/exynos_thermal_common.h
>> @@ -0,0 +1,83 @@
>> +/*
>> + * exynos_thermal_common.h - Samsung EXYNOS common header file
>> + *
>> + *  Copyright (C) 2013 Samsung Electronics
>> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
>> + *
>> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
>> + *
>> + */
>> +
>> +#ifndef _LINUX_EXYNOS_THERMAL_COMMON_H
>> +#define _LINUX_EXYNOS_THERMAL_COMMON_H
>> +
>> +/* In-kernel thermal framework related macros & definations */
>> +#define SENSOR_NAME_LEN      16
>> +#define MAX_TRIP_COUNT       8
>> +#define MAX_COOLING_DEVICE 4
>> +#define MAX_THRESHOLD_LEVS 4
>> +
>> +#define ACTIVE_INTERVAL 500
>> +#define IDLE_INTERVAL 10000
>> +#define MCELSIUS     1000
>> +
>> +/* CPU Zone information */
>> +#define PANIC_ZONE      4
>> +#define WARN_ZONE       3
>> +#define MONITOR_ZONE    2
>> +#define SAFE_ZONE       1
>> +
>> +#define GET_ZONE(trip) (trip + 2)
>> +#define GET_TRIP(zone) (zone - 2)
>> +
>> +#define EXYNOS_ZONE_COUNT    3
>> +
>> +struct       thermal_trip_point_conf {
>> +     int trip_val[MAX_TRIP_COUNT];
>> +     int trip_count;
>> +     u8 trigger_falling;
>> +};
>> +
>> +struct       thermal_cooling_conf {
>> +     struct freq_clip_table freq_data[MAX_TRIP_COUNT];
>> +     int freq_clip_count;
>> +};
>> +
>> +struct thermal_sensor_conf {
>> +     char name[SENSOR_NAME_LEN];
>> +     int (*read_temperature)(void *data);
>> +     int (*write_emul_temp)(void *drv_data, unsigned long temp);
>> +     struct thermal_trip_point_conf trip_data;
>> +     struct thermal_cooling_conf cooling_data;
>> +     void *private_data;
>> +};
>> +
>> +/*Functions used exynos based thermal sensor driver*/
>> +#ifdef CONFIG_EXYNOS_THERMAL_CORE
>> +void exynos_unregister_thermal(void);
>> +int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
>> +void exynos_report_trigger(void);
>> +#else
>> +static inline void
>> +exynos_unregister_thermal(void) { return; }
>> +
>> +static inline int
>> +exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
>> +
>> +static inline void
>> +exynos_report_trigger(void) { return; }
>> +
>> +#endif /* CONFIG_EXYNOS_COMMON */
>> +#endif /* _LINUX_EXYNOS_THERMAL_COMMON_H */
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RESEND PATCH V3 01/21] thermal: exynos: Moving exynos thermal files into samsung directory
  2013-05-07 13:07   ` [RESEND PATCH " Amit Daniel Kachhap
@ 2013-05-08 15:49       ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-08 15:49 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 4097 bytes --]

On 07-05-2013 09:07, Amit Daniel Kachhap wrote:
> This movement of files is done for easy maintenance and adding more
> new sensor's support for exynos platform easily . This will also help in
> bifurcating exynos common, sensor driver and sensor data related parts.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/Kconfig                        |   13 +++++--------
>  drivers/thermal/Makefile                       |    2 +-
>  drivers/thermal/samsung/Kconfig                |    9 +++++++++
>  drivers/thermal/samsung/Makefile               |    4 ++++
>  drivers/thermal/{ => samsung}/exynos_thermal.c |    0
>  5 files changed, 19 insertions(+), 9 deletions(-)
>  create mode 100644 drivers/thermal/samsung/Kconfig
>  create mode 100644 drivers/thermal/samsung/Makefile
>  rename drivers/thermal/{ => samsung}/exynos_thermal.c (100%)
> 
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 5e3c025..081ddc5 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -114,14 +114,6 @@ config KIRKWOOD_THERMAL
>  	  Support for the Kirkwood thermal sensor driver into the Linux thermal
>  	  framework. Only kirkwood 88F6282 and 88F6283 have this sensor.
>  
> -config EXYNOS_THERMAL
> -	tristate "Temperature sensor on Samsung EXYNOS"
> -	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
> -	depends on CPU_THERMAL
> -	help
> -	  If you say yes here you get support for TMU (Thermal Management
> -	  Unit) on SAMSUNG EXYNOS series of SoC.
> -
>  config DOVE_THERMAL
>  	tristate "Temperature sensor on Marvell Dove SoCs"
>  	depends on ARCH_DOVE
> @@ -169,4 +161,9 @@ config INTEL_POWERCLAMP
>  	  enforce idle time which results in more package C-state residency. The
>  	  user interface is exposed via generic thermal framework.
>  
> +menu "Samsung thermal drivers"
> +depends on PLAT_SAMSUNG
> +source "drivers/thermal/samsung/Kconfig"
> +endmenu
> +
>  endif
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index c054d41..b3063a9 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -17,7 +17,7 @@ thermal_sys-$(CONFIG_CPU_THERMAL)	+= cpu_cooling.o
>  obj-$(CONFIG_SPEAR_THERMAL)	+= spear_thermal.o
>  obj-$(CONFIG_RCAR_THERMAL)	+= rcar_thermal.o
>  obj-$(CONFIG_KIRKWOOD_THERMAL)  += kirkwood_thermal.o
> -obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
> +obj-y				+= samsung/
>  obj-$(CONFIG_DOVE_THERMAL)  	+= dove_thermal.o
>  obj-$(CONFIG_DB8500_THERMAL)	+= db8500_thermal.o
>  obj-$(CONFIG_ARMADA_THERMAL)	+= armada_thermal.o
> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
> new file mode 100644
> index 0000000..2d3d9dc
> --- /dev/null
> +++ b/drivers/thermal/samsung/Kconfig
> @@ -0,0 +1,9 @@
> +config EXYNOS_THERMAL
> +	tristate "Temperature sensor on Samsung EXYNOS"
> +	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)

Do you really want to keep a list of Kconfig dependency here?

I was suggested to have a config entry (like ARCH_HAS_BANDBAP) and then
in the driver use:
	depends on ARCH_HAS_BANDGAP

And the arch/ code would just selects ARCH_HAS_BANDGAP (like
ARCH_HAS_CPUFREQ).

> +	depends on CPU_THERMAL
> +	help
> +	  If you say yes here you get support for TMU (Thermal Management
> +	  Unit) on SAMSUNG EXYNOS series of SoC. This helps in registering
> +	  the exynos thermal driver with the core thermal layer and cpu
> +	  cooling API's.
> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
> new file mode 100644
> index 0000000..1fe6d93
> --- /dev/null
> +++ b/drivers/thermal/samsung/Makefile
> @@ -0,0 +1,4 @@
> +#
> +# Samsung thermal specific Makefile
> +#
> +obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
> diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/samsung/exynos_thermal.c
> similarity index 100%
> rename from drivers/thermal/exynos_thermal.c
> rename to drivers/thermal/samsung/exynos_thermal.c
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RESEND PATCH V3 01/21] thermal: exynos: Moving exynos thermal files into samsung directory
@ 2013-05-08 15:49       ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-08 15:49 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 4097 bytes --]

On 07-05-2013 09:07, Amit Daniel Kachhap wrote:
> This movement of files is done for easy maintenance and adding more
> new sensor's support for exynos platform easily . This will also help in
> bifurcating exynos common, sensor driver and sensor data related parts.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/Kconfig                        |   13 +++++--------
>  drivers/thermal/Makefile                       |    2 +-
>  drivers/thermal/samsung/Kconfig                |    9 +++++++++
>  drivers/thermal/samsung/Makefile               |    4 ++++
>  drivers/thermal/{ => samsung}/exynos_thermal.c |    0
>  5 files changed, 19 insertions(+), 9 deletions(-)
>  create mode 100644 drivers/thermal/samsung/Kconfig
>  create mode 100644 drivers/thermal/samsung/Makefile
>  rename drivers/thermal/{ => samsung}/exynos_thermal.c (100%)
> 
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 5e3c025..081ddc5 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -114,14 +114,6 @@ config KIRKWOOD_THERMAL
>  	  Support for the Kirkwood thermal sensor driver into the Linux thermal
>  	  framework. Only kirkwood 88F6282 and 88F6283 have this sensor.
>  
> -config EXYNOS_THERMAL
> -	tristate "Temperature sensor on Samsung EXYNOS"
> -	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
> -	depends on CPU_THERMAL
> -	help
> -	  If you say yes here you get support for TMU (Thermal Management
> -	  Unit) on SAMSUNG EXYNOS series of SoC.
> -
>  config DOVE_THERMAL
>  	tristate "Temperature sensor on Marvell Dove SoCs"
>  	depends on ARCH_DOVE
> @@ -169,4 +161,9 @@ config INTEL_POWERCLAMP
>  	  enforce idle time which results in more package C-state residency. The
>  	  user interface is exposed via generic thermal framework.
>  
> +menu "Samsung thermal drivers"
> +depends on PLAT_SAMSUNG
> +source "drivers/thermal/samsung/Kconfig"
> +endmenu
> +
>  endif
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index c054d41..b3063a9 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -17,7 +17,7 @@ thermal_sys-$(CONFIG_CPU_THERMAL)	+= cpu_cooling.o
>  obj-$(CONFIG_SPEAR_THERMAL)	+= spear_thermal.o
>  obj-$(CONFIG_RCAR_THERMAL)	+= rcar_thermal.o
>  obj-$(CONFIG_KIRKWOOD_THERMAL)  += kirkwood_thermal.o
> -obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
> +obj-y				+= samsung/
>  obj-$(CONFIG_DOVE_THERMAL)  	+= dove_thermal.o
>  obj-$(CONFIG_DB8500_THERMAL)	+= db8500_thermal.o
>  obj-$(CONFIG_ARMADA_THERMAL)	+= armada_thermal.o
> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
> new file mode 100644
> index 0000000..2d3d9dc
> --- /dev/null
> +++ b/drivers/thermal/samsung/Kconfig
> @@ -0,0 +1,9 @@
> +config EXYNOS_THERMAL
> +	tristate "Temperature sensor on Samsung EXYNOS"
> +	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)

Do you really want to keep a list of Kconfig dependency here?

I was suggested to have a config entry (like ARCH_HAS_BANDBAP) and then
in the driver use:
	depends on ARCH_HAS_BANDGAP

And the arch/ code would just selects ARCH_HAS_BANDGAP (like
ARCH_HAS_CPUFREQ).

> +	depends on CPU_THERMAL
> +	help
> +	  If you say yes here you get support for TMU (Thermal Management
> +	  Unit) on SAMSUNG EXYNOS series of SoC. This helps in registering
> +	  the exynos thermal driver with the core thermal layer and cpu
> +	  cooling API's.
> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
> new file mode 100644
> index 0000000..1fe6d93
> --- /dev/null
> +++ b/drivers/thermal/samsung/Makefile
> @@ -0,0 +1,4 @@
> +#
> +# Samsung thermal specific Makefile
> +#
> +obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
> diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/samsung/exynos_thermal.c
> similarity index 100%
> rename from drivers/thermal/exynos_thermal.c
> rename to drivers/thermal/samsung/exynos_thermal.c
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 02/21] thermal: exynos: Bifurcate exynos thermal common and tmu controller code
  2013-05-07 13:00 ` [PATCH V3 02/21] thermal: exynos: Bifurcate exynos thermal common and tmu controller code Amit Daniel Kachhap
@ 2013-05-08 16:01     ` Eduardo Valentin
  2013-05-08 16:01     ` Eduardo Valentin
  1 sibling, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-08 16:01 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 32113 bytes --]

On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
> This code bifurcates exynos thermal implementation into common and sensor
> specific parts. The common thermal code interacts with core thermal layer and
> core cpufreq cooling parts and is independent of SOC specific driver. This
> change is needed to cleanly add support for new TMU sensors.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/Kconfig                 |   20 +-
>  drivers/thermal/samsung/Makefile                |    4 +-
>  drivers/thermal/samsung/exynos_thermal.c        |  421 +----------------------
>  drivers/thermal/samsung/exynos_thermal_common.c |  389 +++++++++++++++++++++
>  drivers/thermal/samsung/exynos_thermal_common.h |   83 +++++
>  5 files changed, 498 insertions(+), 419 deletions(-)
>  create mode 100644 drivers/thermal/samsung/exynos_thermal_common.c
>  create mode 100644 drivers/thermal/samsung/exynos_thermal_common.h
> 
> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
> index 2d3d9dc..7857e20 100644
> --- a/drivers/thermal/samsung/Kconfig
> +++ b/drivers/thermal/samsung/Kconfig
> @@ -1,9 +1,17 @@
>  config EXYNOS_THERMAL
> -	tristate "Temperature sensor on Samsung EXYNOS"
> +	tristate "Exynos thermal management unit driver"
>  	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
> -	depends on CPU_THERMAL
>  	help
> -	  If you say yes here you get support for TMU (Thermal Management
> -	  Unit) on SAMSUNG EXYNOS series of SoC. This helps in registering
> -	  the exynos thermal driver with the core thermal layer and cpu
> -	  cooling API's.
> +	  If you say yes here you get support for the exynos thermal driver
> +	  for exynos4 and exynos5 soc. This driver initialises the TMU, reports
> +	  temperature and handles cooling action if defined. This driver uses
> +	  core thermal API's.
> +
> +config EXYNOS_THERMAL_CORE
> +	bool "Core thermal framework support for EXYNOS SOC's"
> +	depends on EXYNOS_THERMAL
> +	help
> +	  If you say yes here you get support for EXYNOS TMU
> +	  (Thermal Management Unit) common registration/unregistration
> +	  functions to the core thermal layer and also to use the generic
> +	  cpu cooling API's.
> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
> index 1fe6d93..6227d4f 100644
> --- a/drivers/thermal/samsung/Makefile
> +++ b/drivers/thermal/samsung/Makefile
> @@ -1,4 +1,6 @@
>  #
>  # Samsung thermal specific Makefile
>  #
> -obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
> +obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_soc_thermal.o
> +exynos_soc_thermal-y				:= exynos_thermal.o
> +exynos_soc_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
> diff --git a/drivers/thermal/samsung/exynos_thermal.c b/drivers/thermal/samsung/exynos_thermal.c
> index d20ce9e..4c85945 100644
> --- a/drivers/thermal/samsung/exynos_thermal.c
> +++ b/drivers/thermal/samsung/exynos_thermal.c
> @@ -21,23 +21,19 @@
>   *
>   */
>  
> -#include <linux/module.h>
> -#include <linux/err.h>
> -#include <linux/kernel.h>
> -#include <linux/slab.h>
> -#include <linux/platform_device.h>
> -#include <linux/interrupt.h>
>  #include <linux/clk.h>
> -#include <linux/workqueue.h>
> -#include <linux/sysfs.h>
> -#include <linux/kobject.h>
>  #include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/kobject.h>
> +#include <linux/module.h>
>  #include <linux/mutex.h>
> -#include <linux/platform_data/exynos_thermal.h>
> -#include <linux/thermal.h>
> -#include <linux/cpufreq.h>
> -#include <linux/cpu_cooling.h>
>  #include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/platform_data/exynos_thermal.h>
> +#include <linux/slab.h>
> +#include <linux/workqueue.h>

nip: I would recommend a blank line here to separate includes from
include/linux to your locals.

> +#include "exynos_thermal_common.h"

While here, a question on the above is if you really need all the above
includes.

>  
>  /* Exynos generic registers */
>  #define EXYNOS_TMU_REG_TRIMINFO		0x0
> @@ -88,16 +84,6 @@
>  #define EFUSE_MIN_VALUE 40
>  #define EFUSE_MAX_VALUE 100
>  
> -/* In-kernel thermal framework related macros & definations */
> -#define SENSOR_NAME_LEN	16
> -#define MAX_TRIP_COUNT	8
> -#define MAX_COOLING_DEVICE 4
> -#define MAX_THRESHOLD_LEVS 4
> -
> -#define ACTIVE_INTERVAL 500
> -#define IDLE_INTERVAL 10000
> -#define MCELSIUS	1000
> -
>  #ifdef CONFIG_THERMAL_EMULATION
>  #define EXYNOS_EMUL_TIME	0x57F0
>  #define EXYNOS_EMUL_TIME_SHIFT	16
> @@ -106,17 +92,6 @@
>  #define EXYNOS_EMUL_ENABLE	0x1
>  #endif /* CONFIG_THERMAL_EMULATION */
>  
> -/* CPU Zone information */
> -#define PANIC_ZONE      4
> -#define WARN_ZONE       3
> -#define MONITOR_ZONE    2
> -#define SAFE_ZONE       1
> -
> -#define GET_ZONE(trip) (trip + 2)
> -#define GET_TRIP(zone) (zone - 2)
> -
> -#define EXYNOS_ZONE_COUNT	3
> -
>  struct exynos_tmu_data {
>  	struct exynos_tmu_platform_data *pdata;
>  	struct resource *mem;
> @@ -129,384 +104,6 @@ struct exynos_tmu_data {
>  	u8 temp_error1, temp_error2;
>  };
>  
> -struct	thermal_trip_point_conf {
> -	int trip_val[MAX_TRIP_COUNT];
> -	int trip_count;
> -	u8 trigger_falling;
> -};
> -
> -struct	thermal_cooling_conf {
> -	struct freq_clip_table freq_data[MAX_TRIP_COUNT];
> -	int freq_clip_count;
> -};
> -
> -struct thermal_sensor_conf {
> -	char name[SENSOR_NAME_LEN];
> -	int (*read_temperature)(void *data);
> -	int (*write_emul_temp)(void *drv_data, unsigned long temp);
> -	struct thermal_trip_point_conf trip_data;
> -	struct thermal_cooling_conf cooling_data;
> -	void *private_data;
> -};
> -
> -struct exynos_thermal_zone {
> -	enum thermal_device_mode mode;
> -	struct thermal_zone_device *therm_dev;
> -	struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
> -	unsigned int cool_dev_size;
> -	struct platform_device *exynos4_dev;
> -	struct thermal_sensor_conf *sensor_conf;
> -	bool bind;
> -};
> -
> -static struct exynos_thermal_zone *th_zone;
> -static void exynos_unregister_thermal(void);
> -static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
> -
> -/* Get mode callback functions for thermal zone */
> -static int exynos_get_mode(struct thermal_zone_device *thermal,
> -			enum thermal_device_mode *mode)
> -{
> -	if (th_zone)
> -		*mode = th_zone->mode;
> -	return 0;
> -}
> -
> -/* Set mode callback functions for thermal zone */
> -static int exynos_set_mode(struct thermal_zone_device *thermal,
> -			enum thermal_device_mode mode)
> -{
> -	if (!th_zone->therm_dev) {
> -		pr_notice("thermal zone not registered\n");
> -		return 0;
> -	}
> -
> -	mutex_lock(&th_zone->therm_dev->lock);
> -
> -	if (mode == THERMAL_DEVICE_ENABLED &&
> -		!th_zone->sensor_conf->trip_data.trigger_falling)
> -		th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
> -	else
> -		th_zone->therm_dev->polling_delay = 0;
> -
> -	mutex_unlock(&th_zone->therm_dev->lock);
> -
> -	th_zone->mode = mode;
> -	thermal_zone_device_update(th_zone->therm_dev);
> -	pr_info("thermal polling set for duration=%d msec\n",
> -				th_zone->therm_dev->polling_delay);
> -	return 0;
> -}
> -
> -
> -/* Get trip type callback functions for thermal zone */
> -static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
> -				 enum thermal_trip_type *type)
> -{
> -	switch (GET_ZONE(trip)) {
> -	case MONITOR_ZONE:
> -	case WARN_ZONE:
> -		*type = THERMAL_TRIP_ACTIVE;
> -		break;
> -	case PANIC_ZONE:
> -		*type = THERMAL_TRIP_CRITICAL;
> -		break;
> -	default:
> -		return -EINVAL;
> -	}
> -	return 0;
> -}
> -
> -/* Get trip temperature callback functions for thermal zone */
> -static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
> -				unsigned long *temp)
> -{
> -	if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
> -		return -EINVAL;
> -
> -	*temp = th_zone->sensor_conf->trip_data.trip_val[trip];
> -	/* convert the temperature into millicelsius */
> -	*temp = *temp * MCELSIUS;
> -
> -	return 0;
> -}
> -
> -/* Get critical temperature callback functions for thermal zone */
> -static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
> -				unsigned long *temp)
> -{
> -	int ret;
> -	/* Panic zone */
> -	ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
> -	return ret;
> -}
> -
> -/* Bind callback functions for thermal zone */
> -static int exynos_bind(struct thermal_zone_device *thermal,
> -			struct thermal_cooling_device *cdev)
> -{
> -	int ret = 0, i, tab_size, level;
> -	struct freq_clip_table *tab_ptr, *clip_data;
> -	struct thermal_sensor_conf *data = th_zone->sensor_conf;
> -
> -	tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
> -	tab_size = data->cooling_data.freq_clip_count;
> -
> -	if (tab_ptr == NULL || tab_size == 0)
> -		return -EINVAL;
> -
> -	/* find the cooling device registered*/
> -	for (i = 0; i < th_zone->cool_dev_size; i++)
> -		if (cdev == th_zone->cool_dev[i])
> -			break;
> -
> -	/* No matching cooling device */
> -	if (i == th_zone->cool_dev_size)
> -		return 0;
> -
> -	/* Bind the thermal zone to the cpufreq cooling device */
> -	for (i = 0; i < tab_size; i++) {
> -		clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
> -		level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
> -		if (level == THERMAL_CSTATE_INVALID)
> -			return 0;
> -		switch (GET_ZONE(i)) {
> -		case MONITOR_ZONE:
> -		case WARN_ZONE:
> -			if (thermal_zone_bind_cooling_device(thermal, i, cdev,
> -								level, 0)) {
> -				pr_err("error binding cdev inst %d\n", i);
> -				ret = -EINVAL;
> -			}
> -			th_zone->bind = true;
> -			break;
> -		default:
> -			ret = -EINVAL;
> -		}
> -	}
> -
> -	return ret;
> -}
> -
> -/* Unbind callback functions for thermal zone */
> -static int exynos_unbind(struct thermal_zone_device *thermal,
> -			struct thermal_cooling_device *cdev)
> -{
> -	int ret = 0, i, tab_size;
> -	struct thermal_sensor_conf *data = th_zone->sensor_conf;
> -
> -	if (th_zone->bind == false)
> -		return 0;
> -
> -	tab_size = data->cooling_data.freq_clip_count;
> -
> -	if (tab_size == 0)
> -		return -EINVAL;
> -
> -	/* find the cooling device registered*/
> -	for (i = 0; i < th_zone->cool_dev_size; i++)
> -		if (cdev == th_zone->cool_dev[i])
> -			break;
> -
> -	/* No matching cooling device */
> -	if (i == th_zone->cool_dev_size)
> -		return 0;
> -
> -	/* Bind the thermal zone to the cpufreq cooling device */
> -	for (i = 0; i < tab_size; i++) {
> -		switch (GET_ZONE(i)) {
> -		case MONITOR_ZONE:
> -		case WARN_ZONE:
> -			if (thermal_zone_unbind_cooling_device(thermal, i,
> -								cdev)) {
> -				pr_err("error unbinding cdev inst=%d\n", i);
> -				ret = -EINVAL;
> -			}
> -			th_zone->bind = false;
> -			break;
> -		default:
> -			ret = -EINVAL;
> -		}
> -	}
> -	return ret;
> -}
> -
> -/* Get temperature callback functions for thermal zone */
> -static int exynos_get_temp(struct thermal_zone_device *thermal,
> -			unsigned long *temp)
> -{
> -	void *data;
> -
> -	if (!th_zone->sensor_conf) {
> -		pr_info("Temperature sensor not initialised\n");
> -		return -EINVAL;
> -	}
> -	data = th_zone->sensor_conf->private_data;
> -	*temp = th_zone->sensor_conf->read_temperature(data);
> -	/* convert the temperature into millicelsius */
> -	*temp = *temp * MCELSIUS;
> -	return 0;
> -}
> -
> -/* Get temperature callback functions for thermal zone */
> -static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
> -						unsigned long temp)
> -{
> -	void *data;
> -	int ret = -EINVAL;
> -
> -	if (!th_zone->sensor_conf) {
> -		pr_info("Temperature sensor not initialised\n");
> -		return -EINVAL;
> -	}
> -	data = th_zone->sensor_conf->private_data;
> -	if (th_zone->sensor_conf->write_emul_temp)
> -		ret = th_zone->sensor_conf->write_emul_temp(data, temp);
> -	return ret;
> -}
> -
> -/* Get the temperature trend */
> -static int exynos_get_trend(struct thermal_zone_device *thermal,
> -			int trip, enum thermal_trend *trend)
> -{
> -	int ret;
> -	unsigned long trip_temp;
> -
> -	ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
> -	if (ret < 0)
> -		return ret;
> -
> -	if (thermal->temperature >= trip_temp)
> -		*trend = THERMAL_TREND_RAISE_FULL;
> -	else
> -		*trend = THERMAL_TREND_DROP_FULL;
> -
> -	return 0;
> -}
> -/* Operation callback functions for thermal zone */
> -static struct thermal_zone_device_ops const exynos_dev_ops = {
> -	.bind = exynos_bind,
> -	.unbind = exynos_unbind,
> -	.get_temp = exynos_get_temp,
> -	.set_emul_temp = exynos_set_emul_temp,
> -	.get_trend = exynos_get_trend,
> -	.get_mode = exynos_get_mode,
> -	.set_mode = exynos_set_mode,
> -	.get_trip_type = exynos_get_trip_type,
> -	.get_trip_temp = exynos_get_trip_temp,
> -	.get_crit_temp = exynos_get_crit_temp,
> -};
> -
> -/*
> - * This function may be called from interrupt based temperature sensor
> - * when threshold is changed.
> - */
> -static void exynos_report_trigger(void)
> -{
> -	unsigned int i;
> -	char data[10];
> -	char *envp[] = { data, NULL };
> -
> -	if (!th_zone || !th_zone->therm_dev)
> -		return;
> -	if (th_zone->bind == false) {
> -		for (i = 0; i < th_zone->cool_dev_size; i++) {
> -			if (!th_zone->cool_dev[i])
> -				continue;
> -			exynos_bind(th_zone->therm_dev,
> -					th_zone->cool_dev[i]);
> -		}
> -	}
> -
> -	thermal_zone_device_update(th_zone->therm_dev);
> -
> -	mutex_lock(&th_zone->therm_dev->lock);
> -	/* Find the level for which trip happened */
> -	for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
> -		if (th_zone->therm_dev->last_temperature <
> -			th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
> -			break;
> -	}
> -
> -	if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
> -		!th_zone->sensor_conf->trip_data.trigger_falling) {
> -		if (i > 0)
> -			th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
> -		else
> -			th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
> -	}
> -
> -	snprintf(data, sizeof(data), "%u", i);
> -	kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
> -	mutex_unlock(&th_zone->therm_dev->lock);
> -}
> -
> -/* Register with the in-kernel thermal management */
> -static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
> -{
> -	int ret;
> -	struct cpumask mask_val;
> -
> -	if (!sensor_conf || !sensor_conf->read_temperature) {
> -		pr_err("Temperature sensor not initialised\n");
> -		return -EINVAL;
> -	}
> -
> -	th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
> -	if (!th_zone)
> -		return -ENOMEM;
> -
> -	th_zone->sensor_conf = sensor_conf;
> -	cpumask_set_cpu(0, &mask_val);
> -	th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
> -	if (IS_ERR(th_zone->cool_dev[0])) {
> -		pr_err("Failed to register cpufreq cooling device\n");
> -		ret = -EINVAL;
> -		goto err_unregister;
> -	}
> -	th_zone->cool_dev_size++;
> -
> -	th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
> -			EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
> -			sensor_conf->trip_data.trigger_falling ?
> -			0 : IDLE_INTERVAL);
> -
> -	if (IS_ERR(th_zone->therm_dev)) {
> -		pr_err("Failed to register thermal zone device\n");
> -		ret = PTR_ERR(th_zone->therm_dev);
> -		goto err_unregister;
> -	}
> -	th_zone->mode = THERMAL_DEVICE_ENABLED;
> -
> -	pr_info("Exynos: Kernel Thermal management registered\n");
> -
> -	return 0;
> -
> -err_unregister:
> -	exynos_unregister_thermal();
> -	return ret;
> -}
> -
> -/* Un-Register with the in-kernel thermal management */
> -static void exynos_unregister_thermal(void)
> -{
> -	int i;
> -
> -	if (!th_zone)
> -		return;
> -
> -	if (th_zone->therm_dev)
> -		thermal_zone_device_unregister(th_zone->therm_dev);
> -
> -	for (i = 0; i < th_zone->cool_dev_size; i++) {
> -		if (th_zone->cool_dev[i])
> -			cpufreq_cooling_unregister(th_zone->cool_dev[i]);
> -	}
> -
> -	kfree(th_zone);
> -	pr_info("Exynos: Kernel Thermal management unregistered\n");
> -}
> -
>  /*
>   * TMU treats temperature as a mapped temperature code.
>   * The temperature is converted differently depending on the calibration type.
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
> new file mode 100644
> index 0000000..9a57606
> --- /dev/null
> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
> @@ -0,0 +1,389 @@
> +/*
> + * exynos_thermal_common.c - Samsung EXYNOS common thermal file
> + *
> + *  Copyright (C) 2013 Samsung Electronics
> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
> + *
> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#include <linux/cpufreq.h>
> +#include <linux/cpu_cooling.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/kobject.h>
> +#include <linux/mutex.h>
> +#include <linux/platform_data/exynos_thermal.h>
> +#include <linux/slab.h>
> +#include <linux/thermal.h>
> +#include "exynos_thermal_common.h"
> +


same comments applies to the above includes.

> +struct exynos_thermal_zone {
> +	enum thermal_device_mode mode;
> +	struct thermal_zone_device *therm_dev;
> +	struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
> +	unsigned int cool_dev_size;
> +	struct platform_device *exynos4_dev;
> +	struct thermal_sensor_conf *sensor_conf;
> +	bool bind;
> +};
> +
> +static struct exynos_thermal_zone *th_zone;
> +
> +/* Get mode callback functions for thermal zone */
> +static int exynos_get_mode(struct thermal_zone_device *thermal,
> +			enum thermal_device_mode *mode)
> +{
> +	if (th_zone)
> +		*mode = th_zone->mode;
> +	return 0;
> +}
> +
> +/* Set mode callback functions for thermal zone */
> +static int exynos_set_mode(struct thermal_zone_device *thermal,
> +			enum thermal_device_mode mode)
> +{
> +	if (!th_zone->therm_dev) {
> +		pr_notice("thermal zone not registered\n");
> +		return 0;
> +	}
> +
> +	mutex_lock(&th_zone->therm_dev->lock);
> +
> +	if (mode == THERMAL_DEVICE_ENABLED &&
> +		!th_zone->sensor_conf->trip_data.trigger_falling)
> +		th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
> +	else
> +		th_zone->therm_dev->polling_delay = 0;
> +
> +	mutex_unlock(&th_zone->therm_dev->lock);
> +
> +	th_zone->mode = mode;
> +	thermal_zone_device_update(th_zone->therm_dev);
> +	pr_info("thermal polling set for duration=%d msec\n",
> +				th_zone->therm_dev->polling_delay);

Do you really want to flood your serial line with the above message? I d
say it is at most a pr_debug.

> +	return 0;
> +}
> +
> +
> +/* Get trip type callback functions for thermal zone */
> +static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
> +				 enum thermal_trip_type *type)
> +{
> +	switch (GET_ZONE(trip)) {
> +	case MONITOR_ZONE:
> +	case WARN_ZONE:
> +		*type = THERMAL_TRIP_ACTIVE;
> +		break;
> +	case PANIC_ZONE:
> +		*type = THERMAL_TRIP_CRITICAL;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	return 0;
> +}
> +
> +/* Get trip temperature callback functions for thermal zone */
> +static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
> +				unsigned long *temp)
> +{
> +	if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
> +		return -EINVAL;
> +
> +	*temp = th_zone->sensor_conf->trip_data.trip_val[trip];
> +	/* convert the temperature into millicelsius */
> +	*temp = *temp * MCELSIUS;
> +
> +	return 0;
> +}
> +
> +/* Get critical temperature callback functions for thermal zone */
> +static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
> +				unsigned long *temp)
> +{
> +	int ret;
> +	/* Panic zone */
> +	ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
> +	return ret;
> +}
> +
> +/* Bind callback functions for thermal zone */
> +static int exynos_bind(struct thermal_zone_device *thermal,
> +			struct thermal_cooling_device *cdev)
> +{
> +	int ret = 0, i, tab_size, level;
> +	struct freq_clip_table *tab_ptr, *clip_data;
> +	struct thermal_sensor_conf *data = th_zone->sensor_conf;
> +
> +	tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
> +	tab_size = data->cooling_data.freq_clip_count;
> +
> +	if (tab_ptr == NULL || tab_size == 0)
> +		return -EINVAL;
> +
> +	/* find the cooling device registered*/
> +	for (i = 0; i < th_zone->cool_dev_size; i++)
> +		if (cdev == th_zone->cool_dev[i])
> +			break;
> +
> +	/* No matching cooling device */
> +	if (i == th_zone->cool_dev_size)
> +		return 0;
> +
> +	/* Bind the thermal zone to the cpufreq cooling device */
> +	for (i = 0; i < tab_size; i++) {
> +		clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
> +		level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
> +		if (level == THERMAL_CSTATE_INVALID)
> +			return 0;
> +		switch (GET_ZONE(i)) {
> +		case MONITOR_ZONE:
> +		case WARN_ZONE:
> +			if (thermal_zone_bind_cooling_device(thermal, i, cdev,
> +								level, 0)) {
> +				pr_err("error binding cdev inst %d\n", i);
> +				ret = -EINVAL;
> +			}
> +			th_zone->bind = true;
> +			break;
> +		default:
> +			ret = -EINVAL;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +/* Unbind callback functions for thermal zone */
> +static int exynos_unbind(struct thermal_zone_device *thermal,
> +			struct thermal_cooling_device *cdev)
> +{
> +	int ret = 0, i, tab_size;
> +	struct thermal_sensor_conf *data = th_zone->sensor_conf;
> +
> +	if (th_zone->bind == false)
> +		return 0;
> +
> +	tab_size = data->cooling_data.freq_clip_count;
> +
> +	if (tab_size == 0)
> +		return -EINVAL;
> +
> +	/* find the cooling device registered*/
> +	for (i = 0; i < th_zone->cool_dev_size; i++)
> +		if (cdev == th_zone->cool_dev[i])
> +			break;
> +
> +	/* No matching cooling device */
> +	if (i == th_zone->cool_dev_size)
> +		return 0;
> +
> +	/* Bind the thermal zone to the cpufreq cooling device */
> +	for (i = 0; i < tab_size; i++) {
> +		switch (GET_ZONE(i)) {
> +		case MONITOR_ZONE:
> +		case WARN_ZONE:
> +			if (thermal_zone_unbind_cooling_device(thermal, i,
> +								cdev)) {
> +				pr_err("error unbinding cdev inst=%d\n", i);
> +				ret = -EINVAL;
> +			}
> +			th_zone->bind = false;
> +			break;
> +		default:
> +			ret = -EINVAL;
> +		}
> +	}
> +	return ret;
> +}
> +
> +/* Get temperature callback functions for thermal zone */
> +static int exynos_get_temp(struct thermal_zone_device *thermal,
> +			unsigned long *temp)
> +{
> +	void *data;
> +
> +	if (!th_zone->sensor_conf) {
> +		pr_info("Temperature sensor not initialised\n");
> +		return -EINVAL;
> +	}
> +	data = th_zone->sensor_conf->private_data;
> +	*temp = th_zone->sensor_conf->read_temperature(data);
> +	/* convert the temperature into millicelsius */
> +	*temp = *temp * MCELSIUS;
> +	return 0;
> +}
> +
> +/* Get temperature callback functions for thermal zone */
> +static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
> +						unsigned long temp)
> +{
> +	void *data;
> +	int ret = -EINVAL;
> +
> +	if (!th_zone->sensor_conf) {
> +		pr_info("Temperature sensor not initialised\n");
> +		return -EINVAL;
> +	}
> +	data = th_zone->sensor_conf->private_data;
> +	if (th_zone->sensor_conf->write_emul_temp)
> +		ret = th_zone->sensor_conf->write_emul_temp(data, temp);
> +	return ret;
> +}
> +
> +/* Get the temperature trend */
> +static int exynos_get_trend(struct thermal_zone_device *thermal,
> +			int trip, enum thermal_trend *trend)
> +{
> +	int ret;
> +	unsigned long trip_temp;
> +
> +	ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (thermal->temperature >= trip_temp)
> +		*trend = THERMAL_TREND_RAISE_FULL;
> +	else
> +		*trend = THERMAL_TREND_DROP_FULL;
> +
> +	return 0;
> +}
> +/* Operation callback functions for thermal zone */
> +static struct thermal_zone_device_ops const exynos_dev_ops = {
> +	.bind = exynos_bind,
> +	.unbind = exynos_unbind,
> +	.get_temp = exynos_get_temp,
> +	.set_emul_temp = exynos_set_emul_temp,
> +	.get_trend = exynos_get_trend,
> +	.get_mode = exynos_get_mode,
> +	.set_mode = exynos_set_mode,
> +	.get_trip_type = exynos_get_trip_type,
> +	.get_trip_temp = exynos_get_trip_temp,
> +	.get_crit_temp = exynos_get_crit_temp,
> +};
> +
> +/*
> + * This function may be called from interrupt based temperature sensor
> + * when threshold is changed.
> + */
> +void exynos_report_trigger(void)
> +{
> +	unsigned int i;
> +	char data[10];
> +	char *envp[] = { data, NULL };
> +
> +	if (!th_zone || !th_zone->therm_dev)
> +		return;
> +	if (th_zone->bind == false) {
> +		for (i = 0; i < th_zone->cool_dev_size; i++) {
> +			if (!th_zone->cool_dev[i])
> +				continue;
> +			exynos_bind(th_zone->therm_dev,
> +					th_zone->cool_dev[i]);
> +		}
> +	}
> +
> +	thermal_zone_device_update(th_zone->therm_dev);
> +
> +	mutex_lock(&th_zone->therm_dev->lock);
> +	/* Find the level for which trip happened */
> +	for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
> +		if (th_zone->therm_dev->last_temperature <
> +			th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
> +			break;
> +	}
> +
> +	if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
> +		!th_zone->sensor_conf->trip_data.trigger_falling) {
> +		if (i > 0)
> +			th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
> +		else
> +			th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
> +	}
> +
> +	snprintf(data, sizeof(data), "%u", i);
> +	kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
> +	mutex_unlock(&th_zone->therm_dev->lock);
> +}
> +
> +/* Register with the in-kernel thermal management */
> +int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
> +{
> +	int ret;
> +	struct cpumask mask_val;
> +
> +	if (!sensor_conf || !sensor_conf->read_temperature) {
> +		pr_err("Temperature sensor not initialised\n");
> +		return -EINVAL;
> +	}
> +
> +	th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
> +	if (!th_zone)
> +		return -ENOMEM;
> +

I d suggest switching to device resource managed allocation.

> +	th_zone->sensor_conf = sensor_conf;
> +	cpumask_set_cpu(0, &mask_val);
> +	th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
> +	if (IS_ERR(th_zone->cool_dev[0])) {
> +		pr_err("Failed to register cpufreq cooling device\n");
> +		ret = -EINVAL;
> +		goto err_unregister;
> +	}
> +	th_zone->cool_dev_size++;
> +
> +	th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
> +			EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
> +			sensor_conf->trip_data.trigger_falling ?
> +			0 : IDLE_INTERVAL);
> +
> +	if (IS_ERR(th_zone->therm_dev)) {
> +		pr_err("Failed to register thermal zone device\n");
> +		ret = PTR_ERR(th_zone->therm_dev);
> +		goto err_unregister;
> +	}
> +	th_zone->mode = THERMAL_DEVICE_ENABLED;
> +
> +	pr_info("Exynos: Kernel Thermal management registered\n");
> +
> +	return 0;
> +
> +err_unregister:
> +	exynos_unregister_thermal();
> +	return ret;
> +}
> +
> +/* Un-Register with the in-kernel thermal management */
> +void exynos_unregister_thermal(void)
> +{
> +	int i;
> +
> +	if (!th_zone)
> +		return;
> +
> +	if (th_zone->therm_dev)
> +		thermal_zone_device_unregister(th_zone->therm_dev);
> +
> +	for (i = 0; i < th_zone->cool_dev_size; i++) {
> +		if (th_zone->cool_dev[i])
> +			cpufreq_cooling_unregister(th_zone->cool_dev[i]);
> +	}
> +
> +	kfree(th_zone);
> +	pr_info("Exynos: Kernel Thermal management unregistered\n");
> +}
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
> new file mode 100644
> index 0000000..da2add0
> --- /dev/null
> +++ b/drivers/thermal/samsung/exynos_thermal_common.h
> @@ -0,0 +1,83 @@
> +/*
> + * exynos_thermal_common.h - Samsung EXYNOS common header file
> + *
> + *  Copyright (C) 2013 Samsung Electronics
> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
> + *
> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#ifndef _LINUX_EXYNOS_THERMAL_COMMON_H
> +#define _LINUX_EXYNOS_THERMAL_COMMON_H
> +

How about simply _EXYNOS_THERMAL_COMMON_H?

> +/* In-kernel thermal framework related macros & definations */
> +#define SENSOR_NAME_LEN	16
> +#define MAX_TRIP_COUNT	8
> +#define MAX_COOLING_DEVICE 4
> +#define MAX_THRESHOLD_LEVS 4
> +
> +#define ACTIVE_INTERVAL 500
> +#define IDLE_INTERVAL 10000
> +#define MCELSIUS	1000
> +
> +/* CPU Zone information */
> +#define PANIC_ZONE      4
> +#define WARN_ZONE       3
> +#define MONITOR_ZONE    2
> +#define SAFE_ZONE       1
> +
> +#define GET_ZONE(trip) (trip + 2)
> +#define GET_TRIP(zone) (zone - 2)
> +
> +#define EXYNOS_ZONE_COUNT	3
> +
> +struct	thermal_trip_point_conf {
> +	int trip_val[MAX_TRIP_COUNT];
> +	int trip_count;
> +	u8 trigger_falling;
> +};
> +
> +struct	thermal_cooling_conf {
> +	struct freq_clip_table freq_data[MAX_TRIP_COUNT];

You need to have the include for the above type

> +	int freq_clip_count;
> +};
> +
> +struct thermal_sensor_conf {
> +	char name[SENSOR_NAME_LEN];
> +	int (*read_temperature)(void *data);
> +	int (*write_emul_temp)(void *drv_data, unsigned long temp);
> +	struct thermal_trip_point_conf trip_data;
> +	struct thermal_cooling_conf cooling_daa;
> +	void *private_data;
> +};
> +
> +/*Functions used exynos based thermal sensor driver*/
> +#ifdef CONFIG_EXYNOS_THERMAL_CORE
> +void exynos_unregister_thermal(void);
> +int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
> +void exynos_report_trigger(void);
> +#else
> +static inline void
> +exynos_unregister_thermal(void) { return; }
> +
> +static inline int
> +exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
> +
> +static inline void
> +exynos_report_trigger(void) { return; }
> +
> +#endif /* CONFIG_EXYNOS_COMMON */
> +#endif /* _LINUX_EXYNOS_THERMAL_COMMON_H */
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 02/21] thermal: exynos: Bifurcate exynos thermal common and tmu controller code
@ 2013-05-08 16:01     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-08 16:01 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 32113 bytes --]

On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
> This code bifurcates exynos thermal implementation into common and sensor
> specific parts. The common thermal code interacts with core thermal layer and
> core cpufreq cooling parts and is independent of SOC specific driver. This
> change is needed to cleanly add support for new TMU sensors.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/Kconfig                 |   20 +-
>  drivers/thermal/samsung/Makefile                |    4 +-
>  drivers/thermal/samsung/exynos_thermal.c        |  421 +----------------------
>  drivers/thermal/samsung/exynos_thermal_common.c |  389 +++++++++++++++++++++
>  drivers/thermal/samsung/exynos_thermal_common.h |   83 +++++
>  5 files changed, 498 insertions(+), 419 deletions(-)
>  create mode 100644 drivers/thermal/samsung/exynos_thermal_common.c
>  create mode 100644 drivers/thermal/samsung/exynos_thermal_common.h
> 
> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
> index 2d3d9dc..7857e20 100644
> --- a/drivers/thermal/samsung/Kconfig
> +++ b/drivers/thermal/samsung/Kconfig
> @@ -1,9 +1,17 @@
>  config EXYNOS_THERMAL
> -	tristate "Temperature sensor on Samsung EXYNOS"
> +	tristate "Exynos thermal management unit driver"
>  	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
> -	depends on CPU_THERMAL
>  	help
> -	  If you say yes here you get support for TMU (Thermal Management
> -	  Unit) on SAMSUNG EXYNOS series of SoC. This helps in registering
> -	  the exynos thermal driver with the core thermal layer and cpu
> -	  cooling API's.
> +	  If you say yes here you get support for the exynos thermal driver
> +	  for exynos4 and exynos5 soc. This driver initialises the TMU, reports
> +	  temperature and handles cooling action if defined. This driver uses
> +	  core thermal API's.
> +
> +config EXYNOS_THERMAL_CORE
> +	bool "Core thermal framework support for EXYNOS SOC's"
> +	depends on EXYNOS_THERMAL
> +	help
> +	  If you say yes here you get support for EXYNOS TMU
> +	  (Thermal Management Unit) common registration/unregistration
> +	  functions to the core thermal layer and also to use the generic
> +	  cpu cooling API's.
> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
> index 1fe6d93..6227d4f 100644
> --- a/drivers/thermal/samsung/Makefile
> +++ b/drivers/thermal/samsung/Makefile
> @@ -1,4 +1,6 @@
>  #
>  # Samsung thermal specific Makefile
>  #
> -obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
> +obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_soc_thermal.o
> +exynos_soc_thermal-y				:= exynos_thermal.o
> +exynos_soc_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
> diff --git a/drivers/thermal/samsung/exynos_thermal.c b/drivers/thermal/samsung/exynos_thermal.c
> index d20ce9e..4c85945 100644
> --- a/drivers/thermal/samsung/exynos_thermal.c
> +++ b/drivers/thermal/samsung/exynos_thermal.c
> @@ -21,23 +21,19 @@
>   *
>   */
>  
> -#include <linux/module.h>
> -#include <linux/err.h>
> -#include <linux/kernel.h>
> -#include <linux/slab.h>
> -#include <linux/platform_device.h>
> -#include <linux/interrupt.h>
>  #include <linux/clk.h>
> -#include <linux/workqueue.h>
> -#include <linux/sysfs.h>
> -#include <linux/kobject.h>
>  #include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/kobject.h>
> +#include <linux/module.h>
>  #include <linux/mutex.h>
> -#include <linux/platform_data/exynos_thermal.h>
> -#include <linux/thermal.h>
> -#include <linux/cpufreq.h>
> -#include <linux/cpu_cooling.h>
>  #include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/platform_data/exynos_thermal.h>
> +#include <linux/slab.h>
> +#include <linux/workqueue.h>

nip: I would recommend a blank line here to separate includes from
include/linux to your locals.

> +#include "exynos_thermal_common.h"

While here, a question on the above is if you really need all the above
includes.

>  
>  /* Exynos generic registers */
>  #define EXYNOS_TMU_REG_TRIMINFO		0x0
> @@ -88,16 +84,6 @@
>  #define EFUSE_MIN_VALUE 40
>  #define EFUSE_MAX_VALUE 100
>  
> -/* In-kernel thermal framework related macros & definations */
> -#define SENSOR_NAME_LEN	16
> -#define MAX_TRIP_COUNT	8
> -#define MAX_COOLING_DEVICE 4
> -#define MAX_THRESHOLD_LEVS 4
> -
> -#define ACTIVE_INTERVAL 500
> -#define IDLE_INTERVAL 10000
> -#define MCELSIUS	1000
> -
>  #ifdef CONFIG_THERMAL_EMULATION
>  #define EXYNOS_EMUL_TIME	0x57F0
>  #define EXYNOS_EMUL_TIME_SHIFT	16
> @@ -106,17 +92,6 @@
>  #define EXYNOS_EMUL_ENABLE	0x1
>  #endif /* CONFIG_THERMAL_EMULATION */
>  
> -/* CPU Zone information */
> -#define PANIC_ZONE      4
> -#define WARN_ZONE       3
> -#define MONITOR_ZONE    2
> -#define SAFE_ZONE       1
> -
> -#define GET_ZONE(trip) (trip + 2)
> -#define GET_TRIP(zone) (zone - 2)
> -
> -#define EXYNOS_ZONE_COUNT	3
> -
>  struct exynos_tmu_data {
>  	struct exynos_tmu_platform_data *pdata;
>  	struct resource *mem;
> @@ -129,384 +104,6 @@ struct exynos_tmu_data {
>  	u8 temp_error1, temp_error2;
>  };
>  
> -struct	thermal_trip_point_conf {
> -	int trip_val[MAX_TRIP_COUNT];
> -	int trip_count;
> -	u8 trigger_falling;
> -};
> -
> -struct	thermal_cooling_conf {
> -	struct freq_clip_table freq_data[MAX_TRIP_COUNT];
> -	int freq_clip_count;
> -};
> -
> -struct thermal_sensor_conf {
> -	char name[SENSOR_NAME_LEN];
> -	int (*read_temperature)(void *data);
> -	int (*write_emul_temp)(void *drv_data, unsigned long temp);
> -	struct thermal_trip_point_conf trip_data;
> -	struct thermal_cooling_conf cooling_data;
> -	void *private_data;
> -};
> -
> -struct exynos_thermal_zone {
> -	enum thermal_device_mode mode;
> -	struct thermal_zone_device *therm_dev;
> -	struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
> -	unsigned int cool_dev_size;
> -	struct platform_device *exynos4_dev;
> -	struct thermal_sensor_conf *sensor_conf;
> -	bool bind;
> -};
> -
> -static struct exynos_thermal_zone *th_zone;
> -static void exynos_unregister_thermal(void);
> -static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
> -
> -/* Get mode callback functions for thermal zone */
> -static int exynos_get_mode(struct thermal_zone_device *thermal,
> -			enum thermal_device_mode *mode)
> -{
> -	if (th_zone)
> -		*mode = th_zone->mode;
> -	return 0;
> -}
> -
> -/* Set mode callback functions for thermal zone */
> -static int exynos_set_mode(struct thermal_zone_device *thermal,
> -			enum thermal_device_mode mode)
> -{
> -	if (!th_zone->therm_dev) {
> -		pr_notice("thermal zone not registered\n");
> -		return 0;
> -	}
> -
> -	mutex_lock(&th_zone->therm_dev->lock);
> -
> -	if (mode == THERMAL_DEVICE_ENABLED &&
> -		!th_zone->sensor_conf->trip_data.trigger_falling)
> -		th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
> -	else
> -		th_zone->therm_dev->polling_delay = 0;
> -
> -	mutex_unlock(&th_zone->therm_dev->lock);
> -
> -	th_zone->mode = mode;
> -	thermal_zone_device_update(th_zone->therm_dev);
> -	pr_info("thermal polling set for duration=%d msec\n",
> -				th_zone->therm_dev->polling_delay);
> -	return 0;
> -}
> -
> -
> -/* Get trip type callback functions for thermal zone */
> -static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
> -				 enum thermal_trip_type *type)
> -{
> -	switch (GET_ZONE(trip)) {
> -	case MONITOR_ZONE:
> -	case WARN_ZONE:
> -		*type = THERMAL_TRIP_ACTIVE;
> -		break;
> -	case PANIC_ZONE:
> -		*type = THERMAL_TRIP_CRITICAL;
> -		break;
> -	default:
> -		return -EINVAL;
> -	}
> -	return 0;
> -}
> -
> -/* Get trip temperature callback functions for thermal zone */
> -static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
> -				unsigned long *temp)
> -{
> -	if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
> -		return -EINVAL;
> -
> -	*temp = th_zone->sensor_conf->trip_data.trip_val[trip];
> -	/* convert the temperature into millicelsius */
> -	*temp = *temp * MCELSIUS;
> -
> -	return 0;
> -}
> -
> -/* Get critical temperature callback functions for thermal zone */
> -static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
> -				unsigned long *temp)
> -{
> -	int ret;
> -	/* Panic zone */
> -	ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
> -	return ret;
> -}
> -
> -/* Bind callback functions for thermal zone */
> -static int exynos_bind(struct thermal_zone_device *thermal,
> -			struct thermal_cooling_device *cdev)
> -{
> -	int ret = 0, i, tab_size, level;
> -	struct freq_clip_table *tab_ptr, *clip_data;
> -	struct thermal_sensor_conf *data = th_zone->sensor_conf;
> -
> -	tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
> -	tab_size = data->cooling_data.freq_clip_count;
> -
> -	if (tab_ptr == NULL || tab_size == 0)
> -		return -EINVAL;
> -
> -	/* find the cooling device registered*/
> -	for (i = 0; i < th_zone->cool_dev_size; i++)
> -		if (cdev == th_zone->cool_dev[i])
> -			break;
> -
> -	/* No matching cooling device */
> -	if (i == th_zone->cool_dev_size)
> -		return 0;
> -
> -	/* Bind the thermal zone to the cpufreq cooling device */
> -	for (i = 0; i < tab_size; i++) {
> -		clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
> -		level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
> -		if (level == THERMAL_CSTATE_INVALID)
> -			return 0;
> -		switch (GET_ZONE(i)) {
> -		case MONITOR_ZONE:
> -		case WARN_ZONE:
> -			if (thermal_zone_bind_cooling_device(thermal, i, cdev,
> -								level, 0)) {
> -				pr_err("error binding cdev inst %d\n", i);
> -				ret = -EINVAL;
> -			}
> -			th_zone->bind = true;
> -			break;
> -		default:
> -			ret = -EINVAL;
> -		}
> -	}
> -
> -	return ret;
> -}
> -
> -/* Unbind callback functions for thermal zone */
> -static int exynos_unbind(struct thermal_zone_device *thermal,
> -			struct thermal_cooling_device *cdev)
> -{
> -	int ret = 0, i, tab_size;
> -	struct thermal_sensor_conf *data = th_zone->sensor_conf;
> -
> -	if (th_zone->bind == false)
> -		return 0;
> -
> -	tab_size = data->cooling_data.freq_clip_count;
> -
> -	if (tab_size == 0)
> -		return -EINVAL;
> -
> -	/* find the cooling device registered*/
> -	for (i = 0; i < th_zone->cool_dev_size; i++)
> -		if (cdev == th_zone->cool_dev[i])
> -			break;
> -
> -	/* No matching cooling device */
> -	if (i == th_zone->cool_dev_size)
> -		return 0;
> -
> -	/* Bind the thermal zone to the cpufreq cooling device */
> -	for (i = 0; i < tab_size; i++) {
> -		switch (GET_ZONE(i)) {
> -		case MONITOR_ZONE:
> -		case WARN_ZONE:
> -			if (thermal_zone_unbind_cooling_device(thermal, i,
> -								cdev)) {
> -				pr_err("error unbinding cdev inst=%d\n", i);
> -				ret = -EINVAL;
> -			}
> -			th_zone->bind = false;
> -			break;
> -		default:
> -			ret = -EINVAL;
> -		}
> -	}
> -	return ret;
> -}
> -
> -/* Get temperature callback functions for thermal zone */
> -static int exynos_get_temp(struct thermal_zone_device *thermal,
> -			unsigned long *temp)
> -{
> -	void *data;
> -
> -	if (!th_zone->sensor_conf) {
> -		pr_info("Temperature sensor not initialised\n");
> -		return -EINVAL;
> -	}
> -	data = th_zone->sensor_conf->private_data;
> -	*temp = th_zone->sensor_conf->read_temperature(data);
> -	/* convert the temperature into millicelsius */
> -	*temp = *temp * MCELSIUS;
> -	return 0;
> -}
> -
> -/* Get temperature callback functions for thermal zone */
> -static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
> -						unsigned long temp)
> -{
> -	void *data;
> -	int ret = -EINVAL;
> -
> -	if (!th_zone->sensor_conf) {
> -		pr_info("Temperature sensor not initialised\n");
> -		return -EINVAL;
> -	}
> -	data = th_zone->sensor_conf->private_data;
> -	if (th_zone->sensor_conf->write_emul_temp)
> -		ret = th_zone->sensor_conf->write_emul_temp(data, temp);
> -	return ret;
> -}
> -
> -/* Get the temperature trend */
> -static int exynos_get_trend(struct thermal_zone_device *thermal,
> -			int trip, enum thermal_trend *trend)
> -{
> -	int ret;
> -	unsigned long trip_temp;
> -
> -	ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
> -	if (ret < 0)
> -		return ret;
> -
> -	if (thermal->temperature >= trip_temp)
> -		*trend = THERMAL_TREND_RAISE_FULL;
> -	else
> -		*trend = THERMAL_TREND_DROP_FULL;
> -
> -	return 0;
> -}
> -/* Operation callback functions for thermal zone */
> -static struct thermal_zone_device_ops const exynos_dev_ops = {
> -	.bind = exynos_bind,
> -	.unbind = exynos_unbind,
> -	.get_temp = exynos_get_temp,
> -	.set_emul_temp = exynos_set_emul_temp,
> -	.get_trend = exynos_get_trend,
> -	.get_mode = exynos_get_mode,
> -	.set_mode = exynos_set_mode,
> -	.get_trip_type = exynos_get_trip_type,
> -	.get_trip_temp = exynos_get_trip_temp,
> -	.get_crit_temp = exynos_get_crit_temp,
> -};
> -
> -/*
> - * This function may be called from interrupt based temperature sensor
> - * when threshold is changed.
> - */
> -static void exynos_report_trigger(void)
> -{
> -	unsigned int i;
> -	char data[10];
> -	char *envp[] = { data, NULL };
> -
> -	if (!th_zone || !th_zone->therm_dev)
> -		return;
> -	if (th_zone->bind == false) {
> -		for (i = 0; i < th_zone->cool_dev_size; i++) {
> -			if (!th_zone->cool_dev[i])
> -				continue;
> -			exynos_bind(th_zone->therm_dev,
> -					th_zone->cool_dev[i]);
> -		}
> -	}
> -
> -	thermal_zone_device_update(th_zone->therm_dev);
> -
> -	mutex_lock(&th_zone->therm_dev->lock);
> -	/* Find the level for which trip happened */
> -	for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
> -		if (th_zone->therm_dev->last_temperature <
> -			th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
> -			break;
> -	}
> -
> -	if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
> -		!th_zone->sensor_conf->trip_data.trigger_falling) {
> -		if (i > 0)
> -			th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
> -		else
> -			th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
> -	}
> -
> -	snprintf(data, sizeof(data), "%u", i);
> -	kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
> -	mutex_unlock(&th_zone->therm_dev->lock);
> -}
> -
> -/* Register with the in-kernel thermal management */
> -static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
> -{
> -	int ret;
> -	struct cpumask mask_val;
> -
> -	if (!sensor_conf || !sensor_conf->read_temperature) {
> -		pr_err("Temperature sensor not initialised\n");
> -		return -EINVAL;
> -	}
> -
> -	th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
> -	if (!th_zone)
> -		return -ENOMEM;
> -
> -	th_zone->sensor_conf = sensor_conf;
> -	cpumask_set_cpu(0, &mask_val);
> -	th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
> -	if (IS_ERR(th_zone->cool_dev[0])) {
> -		pr_err("Failed to register cpufreq cooling device\n");
> -		ret = -EINVAL;
> -		goto err_unregister;
> -	}
> -	th_zone->cool_dev_size++;
> -
> -	th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
> -			EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
> -			sensor_conf->trip_data.trigger_falling ?
> -			0 : IDLE_INTERVAL);
> -
> -	if (IS_ERR(th_zone->therm_dev)) {
> -		pr_err("Failed to register thermal zone device\n");
> -		ret = PTR_ERR(th_zone->therm_dev);
> -		goto err_unregister;
> -	}
> -	th_zone->mode = THERMAL_DEVICE_ENABLED;
> -
> -	pr_info("Exynos: Kernel Thermal management registered\n");
> -
> -	return 0;
> -
> -err_unregister:
> -	exynos_unregister_thermal();
> -	return ret;
> -}
> -
> -/* Un-Register with the in-kernel thermal management */
> -static void exynos_unregister_thermal(void)
> -{
> -	int i;
> -
> -	if (!th_zone)
> -		return;
> -
> -	if (th_zone->therm_dev)
> -		thermal_zone_device_unregister(th_zone->therm_dev);
> -
> -	for (i = 0; i < th_zone->cool_dev_size; i++) {
> -		if (th_zone->cool_dev[i])
> -			cpufreq_cooling_unregister(th_zone->cool_dev[i]);
> -	}
> -
> -	kfree(th_zone);
> -	pr_info("Exynos: Kernel Thermal management unregistered\n");
> -}
> -
>  /*
>   * TMU treats temperature as a mapped temperature code.
>   * The temperature is converted differently depending on the calibration type.
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
> new file mode 100644
> index 0000000..9a57606
> --- /dev/null
> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
> @@ -0,0 +1,389 @@
> +/*
> + * exynos_thermal_common.c - Samsung EXYNOS common thermal file
> + *
> + *  Copyright (C) 2013 Samsung Electronics
> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
> + *
> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#include <linux/cpufreq.h>
> +#include <linux/cpu_cooling.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/kobject.h>
> +#include <linux/mutex.h>
> +#include <linux/platform_data/exynos_thermal.h>
> +#include <linux/slab.h>
> +#include <linux/thermal.h>
> +#include "exynos_thermal_common.h"
> +


same comments applies to the above includes.

> +struct exynos_thermal_zone {
> +	enum thermal_device_mode mode;
> +	struct thermal_zone_device *therm_dev;
> +	struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
> +	unsigned int cool_dev_size;
> +	struct platform_device *exynos4_dev;
> +	struct thermal_sensor_conf *sensor_conf;
> +	bool bind;
> +};
> +
> +static struct exynos_thermal_zone *th_zone;
> +
> +/* Get mode callback functions for thermal zone */
> +static int exynos_get_mode(struct thermal_zone_device *thermal,
> +			enum thermal_device_mode *mode)
> +{
> +	if (th_zone)
> +		*mode = th_zone->mode;
> +	return 0;
> +}
> +
> +/* Set mode callback functions for thermal zone */
> +static int exynos_set_mode(struct thermal_zone_device *thermal,
> +			enum thermal_device_mode mode)
> +{
> +	if (!th_zone->therm_dev) {
> +		pr_notice("thermal zone not registered\n");
> +		return 0;
> +	}
> +
> +	mutex_lock(&th_zone->therm_dev->lock);
> +
> +	if (mode == THERMAL_DEVICE_ENABLED &&
> +		!th_zone->sensor_conf->trip_data.trigger_falling)
> +		th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
> +	else
> +		th_zone->therm_dev->polling_delay = 0;
> +
> +	mutex_unlock(&th_zone->therm_dev->lock);
> +
> +	th_zone->mode = mode;
> +	thermal_zone_device_update(th_zone->therm_dev);
> +	pr_info("thermal polling set for duration=%d msec\n",
> +				th_zone->therm_dev->polling_delay);

Do you really want to flood your serial line with the above message? I d
say it is at most a pr_debug.

> +	return 0;
> +}
> +
> +
> +/* Get trip type callback functions for thermal zone */
> +static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
> +				 enum thermal_trip_type *type)
> +{
> +	switch (GET_ZONE(trip)) {
> +	case MONITOR_ZONE:
> +	case WARN_ZONE:
> +		*type = THERMAL_TRIP_ACTIVE;
> +		break;
> +	case PANIC_ZONE:
> +		*type = THERMAL_TRIP_CRITICAL;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	return 0;
> +}
> +
> +/* Get trip temperature callback functions for thermal zone */
> +static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
> +				unsigned long *temp)
> +{
> +	if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
> +		return -EINVAL;
> +
> +	*temp = th_zone->sensor_conf->trip_data.trip_val[trip];
> +	/* convert the temperature into millicelsius */
> +	*temp = *temp * MCELSIUS;
> +
> +	return 0;
> +}
> +
> +/* Get critical temperature callback functions for thermal zone */
> +static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
> +				unsigned long *temp)
> +{
> +	int ret;
> +	/* Panic zone */
> +	ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
> +	return ret;
> +}
> +
> +/* Bind callback functions for thermal zone */
> +static int exynos_bind(struct thermal_zone_device *thermal,
> +			struct thermal_cooling_device *cdev)
> +{
> +	int ret = 0, i, tab_size, level;
> +	struct freq_clip_table *tab_ptr, *clip_data;
> +	struct thermal_sensor_conf *data = th_zone->sensor_conf;
> +
> +	tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
> +	tab_size = data->cooling_data.freq_clip_count;
> +
> +	if (tab_ptr == NULL || tab_size == 0)
> +		return -EINVAL;
> +
> +	/* find the cooling device registered*/
> +	for (i = 0; i < th_zone->cool_dev_size; i++)
> +		if (cdev == th_zone->cool_dev[i])
> +			break;
> +
> +	/* No matching cooling device */
> +	if (i == th_zone->cool_dev_size)
> +		return 0;
> +
> +	/* Bind the thermal zone to the cpufreq cooling device */
> +	for (i = 0; i < tab_size; i++) {
> +		clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
> +		level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
> +		if (level == THERMAL_CSTATE_INVALID)
> +			return 0;
> +		switch (GET_ZONE(i)) {
> +		case MONITOR_ZONE:
> +		case WARN_ZONE:
> +			if (thermal_zone_bind_cooling_device(thermal, i, cdev,
> +								level, 0)) {
> +				pr_err("error binding cdev inst %d\n", i);
> +				ret = -EINVAL;
> +			}
> +			th_zone->bind = true;
> +			break;
> +		default:
> +			ret = -EINVAL;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +/* Unbind callback functions for thermal zone */
> +static int exynos_unbind(struct thermal_zone_device *thermal,
> +			struct thermal_cooling_device *cdev)
> +{
> +	int ret = 0, i, tab_size;
> +	struct thermal_sensor_conf *data = th_zone->sensor_conf;
> +
> +	if (th_zone->bind == false)
> +		return 0;
> +
> +	tab_size = data->cooling_data.freq_clip_count;
> +
> +	if (tab_size == 0)
> +		return -EINVAL;
> +
> +	/* find the cooling device registered*/
> +	for (i = 0; i < th_zone->cool_dev_size; i++)
> +		if (cdev == th_zone->cool_dev[i])
> +			break;
> +
> +	/* No matching cooling device */
> +	if (i == th_zone->cool_dev_size)
> +		return 0;
> +
> +	/* Bind the thermal zone to the cpufreq cooling device */
> +	for (i = 0; i < tab_size; i++) {
> +		switch (GET_ZONE(i)) {
> +		case MONITOR_ZONE:
> +		case WARN_ZONE:
> +			if (thermal_zone_unbind_cooling_device(thermal, i,
> +								cdev)) {
> +				pr_err("error unbinding cdev inst=%d\n", i);
> +				ret = -EINVAL;
> +			}
> +			th_zone->bind = false;
> +			break;
> +		default:
> +			ret = -EINVAL;
> +		}
> +	}
> +	return ret;
> +}
> +
> +/* Get temperature callback functions for thermal zone */
> +static int exynos_get_temp(struct thermal_zone_device *thermal,
> +			unsigned long *temp)
> +{
> +	void *data;
> +
> +	if (!th_zone->sensor_conf) {
> +		pr_info("Temperature sensor not initialised\n");
> +		return -EINVAL;
> +	}
> +	data = th_zone->sensor_conf->private_data;
> +	*temp = th_zone->sensor_conf->read_temperature(data);
> +	/* convert the temperature into millicelsius */
> +	*temp = *temp * MCELSIUS;
> +	return 0;
> +}
> +
> +/* Get temperature callback functions for thermal zone */
> +static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
> +						unsigned long temp)
> +{
> +	void *data;
> +	int ret = -EINVAL;
> +
> +	if (!th_zone->sensor_conf) {
> +		pr_info("Temperature sensor not initialised\n");
> +		return -EINVAL;
> +	}
> +	data = th_zone->sensor_conf->private_data;
> +	if (th_zone->sensor_conf->write_emul_temp)
> +		ret = th_zone->sensor_conf->write_emul_temp(data, temp);
> +	return ret;
> +}
> +
> +/* Get the temperature trend */
> +static int exynos_get_trend(struct thermal_zone_device *thermal,
> +			int trip, enum thermal_trend *trend)
> +{
> +	int ret;
> +	unsigned long trip_temp;
> +
> +	ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (thermal->temperature >= trip_temp)
> +		*trend = THERMAL_TREND_RAISE_FULL;
> +	else
> +		*trend = THERMAL_TREND_DROP_FULL;
> +
> +	return 0;
> +}
> +/* Operation callback functions for thermal zone */
> +static struct thermal_zone_device_ops const exynos_dev_ops = {
> +	.bind = exynos_bind,
> +	.unbind = exynos_unbind,
> +	.get_temp = exynos_get_temp,
> +	.set_emul_temp = exynos_set_emul_temp,
> +	.get_trend = exynos_get_trend,
> +	.get_mode = exynos_get_mode,
> +	.set_mode = exynos_set_mode,
> +	.get_trip_type = exynos_get_trip_type,
> +	.get_trip_temp = exynos_get_trip_temp,
> +	.get_crit_temp = exynos_get_crit_temp,
> +};
> +
> +/*
> + * This function may be called from interrupt based temperature sensor
> + * when threshold is changed.
> + */
> +void exynos_report_trigger(void)
> +{
> +	unsigned int i;
> +	char data[10];
> +	char *envp[] = { data, NULL };
> +
> +	if (!th_zone || !th_zone->therm_dev)
> +		return;
> +	if (th_zone->bind == false) {
> +		for (i = 0; i < th_zone->cool_dev_size; i++) {
> +			if (!th_zone->cool_dev[i])
> +				continue;
> +			exynos_bind(th_zone->therm_dev,
> +					th_zone->cool_dev[i]);
> +		}
> +	}
> +
> +	thermal_zone_device_update(th_zone->therm_dev);
> +
> +	mutex_lock(&th_zone->therm_dev->lock);
> +	/* Find the level for which trip happened */
> +	for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
> +		if (th_zone->therm_dev->last_temperature <
> +			th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
> +			break;
> +	}
> +
> +	if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
> +		!th_zone->sensor_conf->trip_data.trigger_falling) {
> +		if (i > 0)
> +			th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
> +		else
> +			th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
> +	}
> +
> +	snprintf(data, sizeof(data), "%u", i);
> +	kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
> +	mutex_unlock(&th_zone->therm_dev->lock);
> +}
> +
> +/* Register with the in-kernel thermal management */
> +int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
> +{
> +	int ret;
> +	struct cpumask mask_val;
> +
> +	if (!sensor_conf || !sensor_conf->read_temperature) {
> +		pr_err("Temperature sensor not initialised\n");
> +		return -EINVAL;
> +	}
> +
> +	th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
> +	if (!th_zone)
> +		return -ENOMEM;
> +

I d suggest switching to device resource managed allocation.

> +	th_zone->sensor_conf = sensor_conf;
> +	cpumask_set_cpu(0, &mask_val);
> +	th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
> +	if (IS_ERR(th_zone->cool_dev[0])) {
> +		pr_err("Failed to register cpufreq cooling device\n");
> +		ret = -EINVAL;
> +		goto err_unregister;
> +	}
> +	th_zone->cool_dev_size++;
> +
> +	th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
> +			EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
> +			sensor_conf->trip_data.trigger_falling ?
> +			0 : IDLE_INTERVAL);
> +
> +	if (IS_ERR(th_zone->therm_dev)) {
> +		pr_err("Failed to register thermal zone device\n");
> +		ret = PTR_ERR(th_zone->therm_dev);
> +		goto err_unregister;
> +	}
> +	th_zone->mode = THERMAL_DEVICE_ENABLED;
> +
> +	pr_info("Exynos: Kernel Thermal management registered\n");
> +
> +	return 0;
> +
> +err_unregister:
> +	exynos_unregister_thermal();
> +	return ret;
> +}
> +
> +/* Un-Register with the in-kernel thermal management */
> +void exynos_unregister_thermal(void)
> +{
> +	int i;
> +
> +	if (!th_zone)
> +		return;
> +
> +	if (th_zone->therm_dev)
> +		thermal_zone_device_unregister(th_zone->therm_dev);
> +
> +	for (i = 0; i < th_zone->cool_dev_size; i++) {
> +		if (th_zone->cool_dev[i])
> +			cpufreq_cooling_unregister(th_zone->cool_dev[i]);
> +	}
> +
> +	kfree(th_zone);
> +	pr_info("Exynos: Kernel Thermal management unregistered\n");
> +}
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
> new file mode 100644
> index 0000000..da2add0
> --- /dev/null
> +++ b/drivers/thermal/samsung/exynos_thermal_common.h
> @@ -0,0 +1,83 @@
> +/*
> + * exynos_thermal_common.h - Samsung EXYNOS common header file
> + *
> + *  Copyright (C) 2013 Samsung Electronics
> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
> + *
> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#ifndef _LINUX_EXYNOS_THERMAL_COMMON_H
> +#define _LINUX_EXYNOS_THERMAL_COMMON_H
> +

How about simply _EXYNOS_THERMAL_COMMON_H?

> +/* In-kernel thermal framework related macros & definations */
> +#define SENSOR_NAME_LEN	16
> +#define MAX_TRIP_COUNT	8
> +#define MAX_COOLING_DEVICE 4
> +#define MAX_THRESHOLD_LEVS 4
> +
> +#define ACTIVE_INTERVAL 500
> +#define IDLE_INTERVAL 10000
> +#define MCELSIUS	1000
> +
> +/* CPU Zone information */
> +#define PANIC_ZONE      4
> +#define WARN_ZONE       3
> +#define MONITOR_ZONE    2
> +#define SAFE_ZONE       1
> +
> +#define GET_ZONE(trip) (trip + 2)
> +#define GET_TRIP(zone) (zone - 2)
> +
> +#define EXYNOS_ZONE_COUNT	3
> +
> +struct	thermal_trip_point_conf {
> +	int trip_val[MAX_TRIP_COUNT];
> +	int trip_count;
> +	u8 trigger_falling;
> +};
> +
> +struct	thermal_cooling_conf {
> +	struct freq_clip_table freq_data[MAX_TRIP_COUNT];

You need to have the include for the above type

> +	int freq_clip_count;
> +};
> +
> +struct thermal_sensor_conf {
> +	char name[SENSOR_NAME_LEN];
> +	int (*read_temperature)(void *data);
> +	int (*write_emul_temp)(void *drv_data, unsigned long temp);
> +	struct thermal_trip_point_conf trip_data;
> +	struct thermal_cooling_conf cooling_daa;
> +	void *private_data;
> +};
> +
> +/*Functions used exynos based thermal sensor driver*/
> +#ifdef CONFIG_EXYNOS_THERMAL_CORE
> +void exynos_unregister_thermal(void);
> +int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
> +void exynos_report_trigger(void);
> +#else
> +static inline void
> +exynos_unregister_thermal(void) { return; }
> +
> +static inline int
> +exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
> +
> +static inline void
> +exynos_report_trigger(void) { return; }
> +
> +#endif /* CONFIG_EXYNOS_COMMON */
> +#endif /* _LINUX_EXYNOS_THERMAL_COMMON_H */
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RESEND PATCH V3 01/21] thermal: exynos: Moving exynos thermal files into samsung directory
  2013-05-08 15:49       ` Eduardo Valentin
  (?)
@ 2013-05-09  2:15       ` amit daniel kachhap
  -1 siblings, 0 replies; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-09  2:15 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel, Kukjin Kim

Hi Eduardo,

On Wed, May 8, 2013 at 9:19 PM, Eduardo Valentin
<eduardo.valentin@ti.com> wrote:
> On 07-05-2013 09:07, Amit Daniel Kachhap wrote:
>> This movement of files is done for easy maintenance and adding more
>> new sensor's support for exynos platform easily . This will also help in
>> bifurcating exynos common, sensor driver and sensor data related parts.
>>
>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>> ---
>>  drivers/thermal/Kconfig                        |   13 +++++--------
>>  drivers/thermal/Makefile                       |    2 +-
>>  drivers/thermal/samsung/Kconfig                |    9 +++++++++
>>  drivers/thermal/samsung/Makefile               |    4 ++++
>>  drivers/thermal/{ => samsung}/exynos_thermal.c |    0
>>  5 files changed, 19 insertions(+), 9 deletions(-)
>>  create mode 100644 drivers/thermal/samsung/Kconfig
>>  create mode 100644 drivers/thermal/samsung/Makefile
>>  rename drivers/thermal/{ => samsung}/exynos_thermal.c (100%)
>>
>> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
>> index 5e3c025..081ddc5 100644
>> --- a/drivers/thermal/Kconfig
>> +++ b/drivers/thermal/Kconfig
>> @@ -114,14 +114,6 @@ config KIRKWOOD_THERMAL
>>         Support for the Kirkwood thermal sensor driver into the Linux thermal
>>         framework. Only kirkwood 88F6282 and 88F6283 have this sensor.
>>
>> -config EXYNOS_THERMAL
>> -     tristate "Temperature sensor on Samsung EXYNOS"
>> -     depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
>> -     depends on CPU_THERMAL
>> -     help
>> -       If you say yes here you get support for TMU (Thermal Management
>> -       Unit) on SAMSUNG EXYNOS series of SoC.
>> -
>>  config DOVE_THERMAL
>>       tristate "Temperature sensor on Marvell Dove SoCs"
>>       depends on ARCH_DOVE
>> @@ -169,4 +161,9 @@ config INTEL_POWERCLAMP
>>         enforce idle time which results in more package C-state residency. The
>>         user interface is exposed via generic thermal framework.
>>
>> +menu "Samsung thermal drivers"
>> +depends on PLAT_SAMSUNG
>> +source "drivers/thermal/samsung/Kconfig"
>> +endmenu
>> +
>>  endif
>> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
>> index c054d41..b3063a9 100644
>> --- a/drivers/thermal/Makefile
>> +++ b/drivers/thermal/Makefile
>> @@ -17,7 +17,7 @@ thermal_sys-$(CONFIG_CPU_THERMAL)   += cpu_cooling.o
>>  obj-$(CONFIG_SPEAR_THERMAL)  += spear_thermal.o
>>  obj-$(CONFIG_RCAR_THERMAL)   += rcar_thermal.o
>>  obj-$(CONFIG_KIRKWOOD_THERMAL)  += kirkwood_thermal.o
>> -obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o
>> +obj-y                                += samsung/
>>  obj-$(CONFIG_DOVE_THERMAL)   += dove_thermal.o
>>  obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o
>>  obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
>> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
>> new file mode 100644
>> index 0000000..2d3d9dc
>> --- /dev/null
>> +++ b/drivers/thermal/samsung/Kconfig
>> @@ -0,0 +1,9 @@
>> +config EXYNOS_THERMAL
>> +     tristate "Temperature sensor on Samsung EXYNOS"
>> +     depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
>
> Do you really want to keep a list of Kconfig dependency here?
>
> I was suggested to have a config entry (like ARCH_HAS_BANDBAP) and then
> in the driver use:
>         depends on ARCH_HAS_BANDGAP
>
> And the arch/ code would just selects ARCH_HAS_BANDGAP (like
> ARCH_HAS_CPUFREQ).

yes your suggestion looks good and then no need to change this Kconfig
for new SOC. Will incorporate this in new version.

Regards,
Amit Daniel
>
>> +     depends on CPU_THERMAL
>> +     help
>> +       If you say yes here you get support for TMU (Thermal Management
>> +       Unit) on SAMSUNG EXYNOS series of SoC. This helps in registering
>> +       the exynos thermal driver with the core thermal layer and cpu
>> +       cooling API's.
>> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
>> new file mode 100644
>> index 0000000..1fe6d93
>> --- /dev/null
>> +++ b/drivers/thermal/samsung/Makefile
>> @@ -0,0 +1,4 @@
>> +#
>> +# Samsung thermal specific Makefile
>> +#
>> +obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o
>> diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/samsung/exynos_thermal.c
>> similarity index 100%
>> rename from drivers/thermal/exynos_thermal.c
>> rename to drivers/thermal/samsung/exynos_thermal.c
>>
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 02/21] thermal: exynos: Bifurcate exynos thermal common and tmu controller code
  2013-05-08 16:01     ` Eduardo Valentin
  (?)
@ 2013-05-09  5:15     ` amit daniel kachhap
  -1 siblings, 0 replies; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-09  5:15 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel, Kukjin Kim

Hi Eduardo,

Thanks for the review.

On Wed, May 8, 2013 at 9:31 PM, Eduardo Valentin
<eduardo.valentin@ti.com> wrote:
> On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
>> This code bifurcates exynos thermal implementation into common and sensor
>> specific parts. The common thermal code interacts with core thermal layer and
>> core cpufreq cooling parts and is independent of SOC specific driver. This
>> change is needed to cleanly add support for new TMU sensors.
>>
>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>> ---
>>  drivers/thermal/samsung/Kconfig                 |   20 +-
>>  drivers/thermal/samsung/Makefile                |    4 +-
>>  drivers/thermal/samsung/exynos_thermal.c        |  421 +----------------------
>>  drivers/thermal/samsung/exynos_thermal_common.c |  389 +++++++++++++++++++++
>>  drivers/thermal/samsung/exynos_thermal_common.h |   83 +++++
>>  5 files changed, 498 insertions(+), 419 deletions(-)
>>  create mode 100644 drivers/thermal/samsung/exynos_thermal_common.c
>>  create mode 100644 drivers/thermal/samsung/exynos_thermal_common.h
>>
>> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
>> index 2d3d9dc..7857e20 100644
>> --- a/drivers/thermal/samsung/Kconfig
>> +++ b/drivers/thermal/samsung/Kconfig
>> @@ -1,9 +1,17 @@
>>  config EXYNOS_THERMAL
>> -     tristate "Temperature sensor on Samsung EXYNOS"
>> +     tristate "Exynos thermal management unit driver"
>>       depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
>> -     depends on CPU_THERMAL
>>       help
>> -       If you say yes here you get support for TMU (Thermal Management
>> -       Unit) on SAMSUNG EXYNOS series of SoC. This helps in registering
>> -       the exynos thermal driver with the core thermal layer and cpu
>> -       cooling API's.
>> +       If you say yes here you get support for the exynos thermal driver
>> +       for exynos4 and exynos5 soc. This driver initialises the TMU, reports
>> +       temperature and handles cooling action if defined. This driver uses
>> +       core thermal API's.
>> +
>> +config EXYNOS_THERMAL_CORE
>> +     bool "Core thermal framework support for EXYNOS SOC's"
>> +     depends on EXYNOS_THERMAL
>> +     help
>> +       If you say yes here you get support for EXYNOS TMU
>> +       (Thermal Management Unit) common registration/unregistration
>> +       functions to the core thermal layer and also to use the generic
>> +       cpu cooling API's.
>> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
>> index 1fe6d93..6227d4f 100644
>> --- a/drivers/thermal/samsung/Makefile
>> +++ b/drivers/thermal/samsung/Makefile
>> @@ -1,4 +1,6 @@
>>  #
>>  # Samsung thermal specific Makefile
>>  #
>> -obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o
>> +obj-$(CONFIG_EXYNOS_THERMAL)                 += exynos_soc_thermal.o
>> +exynos_soc_thermal-y                         := exynos_thermal.o
>> +exynos_soc_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
>> diff --git a/drivers/thermal/samsung/exynos_thermal.c b/drivers/thermal/samsung/exynos_thermal.c
>> index d20ce9e..4c85945 100644
>> --- a/drivers/thermal/samsung/exynos_thermal.c
>> +++ b/drivers/thermal/samsung/exynos_thermal.c
>> @@ -21,23 +21,19 @@
>>   *
>>   */
>>
>> -#include <linux/module.h>
>> -#include <linux/err.h>
>> -#include <linux/kernel.h>
>> -#include <linux/slab.h>
>> -#include <linux/platform_device.h>
>> -#include <linux/interrupt.h>
>>  #include <linux/clk.h>
>> -#include <linux/workqueue.h>
>> -#include <linux/sysfs.h>
>> -#include <linux/kobject.h>
>>  #include <linux/io.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/kernel.h>
>> +#include <linux/kobject.h>
>> +#include <linux/module.h>
>>  #include <linux/mutex.h>
>> -#include <linux/platform_data/exynos_thermal.h>
>> -#include <linux/thermal.h>
>> -#include <linux/cpufreq.h>
>> -#include <linux/cpu_cooling.h>
>>  #include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/platform_data/exynos_thermal.h>
>> +#include <linux/slab.h>
>> +#include <linux/workqueue.h>
>
> nip: I would recommend a blank line here to separate includes from
> include/linux to your locals.
Ok.
>
>> +#include "exynos_thermal_common.h"
>
> While here, a question on the above is if you really need all the above
> includes.
Yes some includes are redundant. Will remove them.
>
>>
>>  /* Exynos generic registers */
>>  #define EXYNOS_TMU_REG_TRIMINFO              0x0
>> @@ -88,16 +84,6 @@
>>  #define EFUSE_MIN_VALUE 40
>>  #define EFUSE_MAX_VALUE 100
>>
>> -/* In-kernel thermal framework related macros & definations */
>> -#define SENSOR_NAME_LEN      16
>> -#define MAX_TRIP_COUNT       8
>> -#define MAX_COOLING_DEVICE 4
>> -#define MAX_THRESHOLD_LEVS 4
>> -
>> -#define ACTIVE_INTERVAL 500
>> -#define IDLE_INTERVAL 10000
>> -#define MCELSIUS     1000
>> -
>>  #ifdef CONFIG_THERMAL_EMULATION
>>  #define EXYNOS_EMUL_TIME     0x57F0
>>  #define EXYNOS_EMUL_TIME_SHIFT       16
>> @@ -106,17 +92,6 @@
>>  #define EXYNOS_EMUL_ENABLE   0x1
>>  #endif /* CONFIG_THERMAL_EMULATION */
>>
>> -/* CPU Zone information */
>> -#define PANIC_ZONE      4
>> -#define WARN_ZONE       3
>> -#define MONITOR_ZONE    2
>> -#define SAFE_ZONE       1
>> -
>> -#define GET_ZONE(trip) (trip + 2)
>> -#define GET_TRIP(zone) (zone - 2)
>> -
>> -#define EXYNOS_ZONE_COUNT    3
>> -
>>  struct exynos_tmu_data {
>>       struct exynos_tmu_platform_data *pdata;
>>       struct resource *mem;
>> @@ -129,384 +104,6 @@ struct exynos_tmu_data {
>>       u8 temp_error1, temp_error2;
>>  };
>>
>> -struct       thermal_trip_point_conf {
>> -     int trip_val[MAX_TRIP_COUNT];
>> -     int trip_count;
>> -     u8 trigger_falling;
>> -};
>> -
>> -struct       thermal_cooling_conf {
>> -     struct freq_clip_table freq_data[MAX_TRIP_COUNT];
>> -     int freq_clip_count;
>> -};
>> -
>> -struct thermal_sensor_conf {
>> -     char name[SENSOR_NAME_LEN];
>> -     int (*read_temperature)(void *data);
>> -     int (*write_emul_temp)(void *drv_data, unsigned long temp);
>> -     struct thermal_trip_point_conf trip_data;
>> -     struct thermal_cooling_conf cooling_data;
>> -     void *private_data;
>> -};
>> -
>> -struct exynos_thermal_zone {
>> -     enum thermal_device_mode mode;
>> -     struct thermal_zone_device *therm_dev;
>> -     struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
>> -     unsigned int cool_dev_size;
>> -     struct platform_device *exynos4_dev;
>> -     struct thermal_sensor_conf *sensor_conf;
>> -     bool bind;
>> -};
>> -
>> -static struct exynos_thermal_zone *th_zone;
>> -static void exynos_unregister_thermal(void);
>> -static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
>> -
>> -/* Get mode callback functions for thermal zone */
>> -static int exynos_get_mode(struct thermal_zone_device *thermal,
>> -                     enum thermal_device_mode *mode)
>> -{
>> -     if (th_zone)
>> -             *mode = th_zone->mode;
>> -     return 0;
>> -}
>> -
>> -/* Set mode callback functions for thermal zone */
>> -static int exynos_set_mode(struct thermal_zone_device *thermal,
>> -                     enum thermal_device_mode mode)
>> -{
>> -     if (!th_zone->therm_dev) {
>> -             pr_notice("thermal zone not registered\n");
>> -             return 0;
>> -     }
>> -
>> -     mutex_lock(&th_zone->therm_dev->lock);
>> -
>> -     if (mode == THERMAL_DEVICE_ENABLED &&
>> -             !th_zone->sensor_conf->trip_data.trigger_falling)
>> -             th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
>> -     else
>> -             th_zone->therm_dev->polling_delay = 0;
>> -
>> -     mutex_unlock(&th_zone->therm_dev->lock);
>> -
>> -     th_zone->mode = mode;
>> -     thermal_zone_device_update(th_zone->therm_dev);
>> -     pr_info("thermal polling set for duration=%d msec\n",
>> -                             th_zone->therm_dev->polling_delay);
>> -     return 0;
>> -}
>> -
>> -
>> -/* Get trip type callback functions for thermal zone */
>> -static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
>> -                              enum thermal_trip_type *type)
>> -{
>> -     switch (GET_ZONE(trip)) {
>> -     case MONITOR_ZONE:
>> -     case WARN_ZONE:
>> -             *type = THERMAL_TRIP_ACTIVE;
>> -             break;
>> -     case PANIC_ZONE:
>> -             *type = THERMAL_TRIP_CRITICAL;
>> -             break;
>> -     default:
>> -             return -EINVAL;
>> -     }
>> -     return 0;
>> -}
>> -
>> -/* Get trip temperature callback functions for thermal zone */
>> -static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
>> -                             unsigned long *temp)
>> -{
>> -     if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
>> -             return -EINVAL;
>> -
>> -     *temp = th_zone->sensor_conf->trip_data.trip_val[trip];
>> -     /* convert the temperature into millicelsius */
>> -     *temp = *temp * MCELSIUS;
>> -
>> -     return 0;
>> -}
>> -
>> -/* Get critical temperature callback functions for thermal zone */
>> -static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
>> -                             unsigned long *temp)
>> -{
>> -     int ret;
>> -     /* Panic zone */
>> -     ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
>> -     return ret;
>> -}
>> -
>> -/* Bind callback functions for thermal zone */
>> -static int exynos_bind(struct thermal_zone_device *thermal,
>> -                     struct thermal_cooling_device *cdev)
>> -{
>> -     int ret = 0, i, tab_size, level;
>> -     struct freq_clip_table *tab_ptr, *clip_data;
>> -     struct thermal_sensor_conf *data = th_zone->sensor_conf;
>> -
>> -     tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
>> -     tab_size = data->cooling_data.freq_clip_count;
>> -
>> -     if (tab_ptr == NULL || tab_size == 0)
>> -             return -EINVAL;
>> -
>> -     /* find the cooling device registered*/
>> -     for (i = 0; i < th_zone->cool_dev_size; i++)
>> -             if (cdev == th_zone->cool_dev[i])
>> -                     break;
>> -
>> -     /* No matching cooling device */
>> -     if (i == th_zone->cool_dev_size)
>> -             return 0;
>> -
>> -     /* Bind the thermal zone to the cpufreq cooling device */
>> -     for (i = 0; i < tab_size; i++) {
>> -             clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
>> -             level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
>> -             if (level == THERMAL_CSTATE_INVALID)
>> -                     return 0;
>> -             switch (GET_ZONE(i)) {
>> -             case MONITOR_ZONE:
>> -             case WARN_ZONE:
>> -                     if (thermal_zone_bind_cooling_device(thermal, i, cdev,
>> -                                                             level, 0)) {
>> -                             pr_err("error binding cdev inst %d\n", i);
>> -                             ret = -EINVAL;
>> -                     }
>> -                     th_zone->bind = true;
>> -                     break;
>> -             default:
>> -                     ret = -EINVAL;
>> -             }
>> -     }
>> -
>> -     return ret;
>> -}
>> -
>> -/* Unbind callback functions for thermal zone */
>> -static int exynos_unbind(struct thermal_zone_device *thermal,
>> -                     struct thermal_cooling_device *cdev)
>> -{
>> -     int ret = 0, i, tab_size;
>> -     struct thermal_sensor_conf *data = th_zone->sensor_conf;
>> -
>> -     if (th_zone->bind == false)
>> -             return 0;
>> -
>> -     tab_size = data->cooling_data.freq_clip_count;
>> -
>> -     if (tab_size == 0)
>> -             return -EINVAL;
>> -
>> -     /* find the cooling device registered*/
>> -     for (i = 0; i < th_zone->cool_dev_size; i++)
>> -             if (cdev == th_zone->cool_dev[i])
>> -                     break;
>> -
>> -     /* No matching cooling device */
>> -     if (i == th_zone->cool_dev_size)
>> -             return 0;
>> -
>> -     /* Bind the thermal zone to the cpufreq cooling device */
>> -     for (i = 0; i < tab_size; i++) {
>> -             switch (GET_ZONE(i)) {
>> -             case MONITOR_ZONE:
>> -             case WARN_ZONE:
>> -                     if (thermal_zone_unbind_cooling_device(thermal, i,
>> -                                                             cdev)) {
>> -                             pr_err("error unbinding cdev inst=%d\n", i);
>> -                             ret = -EINVAL;
>> -                     }
>> -                     th_zone->bind = false;
>> -                     break;
>> -             default:
>> -                     ret = -EINVAL;
>> -             }
>> -     }
>> -     return ret;
>> -}
>> -
>> -/* Get temperature callback functions for thermal zone */
>> -static int exynos_get_temp(struct thermal_zone_device *thermal,
>> -                     unsigned long *temp)
>> -{
>> -     void *data;
>> -
>> -     if (!th_zone->sensor_conf) {
>> -             pr_info("Temperature sensor not initialised\n");
>> -             return -EINVAL;
>> -     }
>> -     data = th_zone->sensor_conf->private_data;
>> -     *temp = th_zone->sensor_conf->read_temperature(data);
>> -     /* convert the temperature into millicelsius */
>> -     *temp = *temp * MCELSIUS;
>> -     return 0;
>> -}
>> -
>> -/* Get temperature callback functions for thermal zone */
>> -static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
>> -                                             unsigned long temp)
>> -{
>> -     void *data;
>> -     int ret = -EINVAL;
>> -
>> -     if (!th_zone->sensor_conf) {
>> -             pr_info("Temperature sensor not initialised\n");
>> -             return -EINVAL;
>> -     }
>> -     data = th_zone->sensor_conf->private_data;
>> -     if (th_zone->sensor_conf->write_emul_temp)
>> -             ret = th_zone->sensor_conf->write_emul_temp(data, temp);
>> -     return ret;
>> -}
>> -
>> -/* Get the temperature trend */
>> -static int exynos_get_trend(struct thermal_zone_device *thermal,
>> -                     int trip, enum thermal_trend *trend)
>> -{
>> -     int ret;
>> -     unsigned long trip_temp;
>> -
>> -     ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
>> -     if (ret < 0)
>> -             return ret;
>> -
>> -     if (thermal->temperature >= trip_temp)
>> -             *trend = THERMAL_TREND_RAISE_FULL;
>> -     else
>> -             *trend = THERMAL_TREND_DROP_FULL;
>> -
>> -     return 0;
>> -}
>> -/* Operation callback functions for thermal zone */
>> -static struct thermal_zone_device_ops const exynos_dev_ops = {
>> -     .bind = exynos_bind,
>> -     .unbind = exynos_unbind,
>> -     .get_temp = exynos_get_temp,
>> -     .set_emul_temp = exynos_set_emul_temp,
>> -     .get_trend = exynos_get_trend,
>> -     .get_mode = exynos_get_mode,
>> -     .set_mode = exynos_set_mode,
>> -     .get_trip_type = exynos_get_trip_type,
>> -     .get_trip_temp = exynos_get_trip_temp,
>> -     .get_crit_temp = exynos_get_crit_temp,
>> -};
>> -
>> -/*
>> - * This function may be called from interrupt based temperature sensor
>> - * when threshold is changed.
>> - */
>> -static void exynos_report_trigger(void)
>> -{
>> -     unsigned int i;
>> -     char data[10];
>> -     char *envp[] = { data, NULL };
>> -
>> -     if (!th_zone || !th_zone->therm_dev)
>> -             return;
>> -     if (th_zone->bind == false) {
>> -             for (i = 0; i < th_zone->cool_dev_size; i++) {
>> -                     if (!th_zone->cool_dev[i])
>> -                             continue;
>> -                     exynos_bind(th_zone->therm_dev,
>> -                                     th_zone->cool_dev[i]);
>> -             }
>> -     }
>> -
>> -     thermal_zone_device_update(th_zone->therm_dev);
>> -
>> -     mutex_lock(&th_zone->therm_dev->lock);
>> -     /* Find the level for which trip happened */
>> -     for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
>> -             if (th_zone->therm_dev->last_temperature <
>> -                     th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
>> -                     break;
>> -     }
>> -
>> -     if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
>> -             !th_zone->sensor_conf->trip_data.trigger_falling) {
>> -             if (i > 0)
>> -                     th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
>> -             else
>> -                     th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
>> -     }
>> -
>> -     snprintf(data, sizeof(data), "%u", i);
>> -     kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
>> -     mutex_unlock(&th_zone->therm_dev->lock);
>> -}
>> -
>> -/* Register with the in-kernel thermal management */
>> -static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
>> -{
>> -     int ret;
>> -     struct cpumask mask_val;
>> -
>> -     if (!sensor_conf || !sensor_conf->read_temperature) {
>> -             pr_err("Temperature sensor not initialised\n");
>> -             return -EINVAL;
>> -     }
>> -
>> -     th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
>> -     if (!th_zone)
>> -             return -ENOMEM;
>> -
>> -     th_zone->sensor_conf = sensor_conf;
>> -     cpumask_set_cpu(0, &mask_val);
>> -     th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
>> -     if (IS_ERR(th_zone->cool_dev[0])) {
>> -             pr_err("Failed to register cpufreq cooling device\n");
>> -             ret = -EINVAL;
>> -             goto err_unregister;
>> -     }
>> -     th_zone->cool_dev_size++;
>> -
>> -     th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
>> -                     EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
>> -                     sensor_conf->trip_data.trigger_falling ?
>> -                     0 : IDLE_INTERVAL);
>> -
>> -     if (IS_ERR(th_zone->therm_dev)) {
>> -             pr_err("Failed to register thermal zone device\n");
>> -             ret = PTR_ERR(th_zone->therm_dev);
>> -             goto err_unregister;
>> -     }
>> -     th_zone->mode = THERMAL_DEVICE_ENABLED;
>> -
>> -     pr_info("Exynos: Kernel Thermal management registered\n");
>> -
>> -     return 0;
>> -
>> -err_unregister:
>> -     exynos_unregister_thermal();
>> -     return ret;
>> -}
>> -
>> -/* Un-Register with the in-kernel thermal management */
>> -static void exynos_unregister_thermal(void)
>> -{
>> -     int i;
>> -
>> -     if (!th_zone)
>> -             return;
>> -
>> -     if (th_zone->therm_dev)
>> -             thermal_zone_device_unregister(th_zone->therm_dev);
>> -
>> -     for (i = 0; i < th_zone->cool_dev_size; i++) {
>> -             if (th_zone->cool_dev[i])
>> -                     cpufreq_cooling_unregister(th_zone->cool_dev[i]);
>> -     }
>> -
>> -     kfree(th_zone);
>> -     pr_info("Exynos: Kernel Thermal management unregistered\n");
>> -}
>> -
>>  /*
>>   * TMU treats temperature as a mapped temperature code.
>>   * The temperature is converted differently depending on the calibration type.
>> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
>> new file mode 100644
>> index 0000000..9a57606
>> --- /dev/null
>> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
>> @@ -0,0 +1,389 @@
>> +/*
>> + * exynos_thermal_common.c - Samsung EXYNOS common thermal file
>> + *
>> + *  Copyright (C) 2013 Samsung Electronics
>> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
>> + *
>> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
>> + *
>> + */
>> +
>> +#include <linux/cpufreq.h>
>> +#include <linux/cpu_cooling.h>
>> +#include <linux/err.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/kobject.h>
>> +#include <linux/mutex.h>
>> +#include <linux/platform_data/exynos_thermal.h>
>> +#include <linux/slab.h>
>> +#include <linux/thermal.h>
>> +#include "exynos_thermal_common.h"
>> +
>
>
> same comments applies to the above includes.
Ok
>
>> +struct exynos_thermal_zone {
>> +     enum thermal_device_mode mode;
>> +     struct thermal_zone_device *therm_dev;
>> +     struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
>> +     unsigned int cool_dev_size;
>> +     struct platform_device *exynos4_dev;
>> +     struct thermal_sensor_conf *sensor_conf;
>> +     bool bind;
>> +};
>> +
>> +static struct exynos_thermal_zone *th_zone;
>> +
>> +/* Get mode callback functions for thermal zone */
>> +static int exynos_get_mode(struct thermal_zone_device *thermal,
>> +                     enum thermal_device_mode *mode)
>> +{
>> +     if (th_zone)
>> +             *mode = th_zone->mode;
>> +     return 0;
>> +}
>> +
>> +/* Set mode callback functions for thermal zone */
>> +static int exynos_set_mode(struct thermal_zone_device *thermal,
>> +                     enum thermal_device_mode mode)
>> +{
>> +     if (!th_zone->therm_dev) {
>> +             pr_notice("thermal zone not registered\n");
>> +             return 0;
>> +     }
>> +
>> +     mutex_lock(&th_zone->therm_dev->lock);
>> +
>> +     if (mode == THERMAL_DEVICE_ENABLED &&
>> +             !th_zone->sensor_conf->trip_data.trigger_falling)
>> +             th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
>> +     else
>> +             th_zone->therm_dev->polling_delay = 0;
>> +
>> +     mutex_unlock(&th_zone->therm_dev->lock);
>> +
>> +     th_zone->mode = mode;
>> +     thermal_zone_device_update(th_zone->therm_dev);
>> +     pr_info("thermal polling set for duration=%d msec\n",
>> +                             th_zone->therm_dev->polling_delay);
>
> Do you really want to flood your serial line with the above message? I d
> say it is at most a pr_debug.
ok pr_debug is fine.
>
>> +     return 0;
>> +}
>> +
>> +
>> +/* Get trip type callback functions for thermal zone */
>> +static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
>> +                              enum thermal_trip_type *type)
>> +{
>> +     switch (GET_ZONE(trip)) {
>> +     case MONITOR_ZONE:
>> +     case WARN_ZONE:
>> +             *type = THERMAL_TRIP_ACTIVE;
>> +             break;
>> +     case PANIC_ZONE:
>> +             *type = THERMAL_TRIP_CRITICAL;
>> +             break;
>> +     default:
>> +             return -EINVAL;
>> +     }
>> +     return 0;
>> +}
>> +
>> +/* Get trip temperature callback functions for thermal zone */
>> +static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
>> +                             unsigned long *temp)
>> +{
>> +     if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
>> +             return -EINVAL;
>> +
>> +     *temp = th_zone->sensor_conf->trip_data.trip_val[trip];
>> +     /* convert the temperature into millicelsius */
>> +     *temp = *temp * MCELSIUS;
>> +
>> +     return 0;
>> +}
>> +
>> +/* Get critical temperature callback functions for thermal zone */
>> +static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
>> +                             unsigned long *temp)
>> +{
>> +     int ret;
>> +     /* Panic zone */
>> +     ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
>> +     return ret;
>> +}
>> +
>> +/* Bind callback functions for thermal zone */
>> +static int exynos_bind(struct thermal_zone_device *thermal,
>> +                     struct thermal_cooling_device *cdev)
>> +{
>> +     int ret = 0, i, tab_size, level;
>> +     struct freq_clip_table *tab_ptr, *clip_data;
>> +     struct thermal_sensor_conf *data = th_zone->sensor_conf;
>> +
>> +     tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
>> +     tab_size = data->cooling_data.freq_clip_count;
>> +
>> +     if (tab_ptr == NULL || tab_size == 0)
>> +             return -EINVAL;
>> +
>> +     /* find the cooling device registered*/
>> +     for (i = 0; i < th_zone->cool_dev_size; i++)
>> +             if (cdev == th_zone->cool_dev[i])
>> +                     break;
>> +
>> +     /* No matching cooling device */
>> +     if (i == th_zone->cool_dev_size)
>> +             return 0;
>> +
>> +     /* Bind the thermal zone to the cpufreq cooling device */
>> +     for (i = 0; i < tab_size; i++) {
>> +             clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
>> +             level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
>> +             if (level == THERMAL_CSTATE_INVALID)
>> +                     return 0;
>> +             switch (GET_ZONE(i)) {
>> +             case MONITOR_ZONE:
>> +             case WARN_ZONE:
>> +                     if (thermal_zone_bind_cooling_device(thermal, i, cdev,
>> +                                                             level, 0)) {
>> +                             pr_err("error binding cdev inst %d\n", i);
>> +                             ret = -EINVAL;
>> +                     }
>> +                     th_zone->bind = true;
>> +                     break;
>> +             default:
>> +                     ret = -EINVAL;
>> +             }
>> +     }
>> +
>> +     return ret;
>> +}
>> +
>> +/* Unbind callback functions for thermal zone */
>> +static int exynos_unbind(struct thermal_zone_device *thermal,
>> +                     struct thermal_cooling_device *cdev)
>> +{
>> +     int ret = 0, i, tab_size;
>> +     struct thermal_sensor_conf *data = th_zone->sensor_conf;
>> +
>> +     if (th_zone->bind == false)
>> +             return 0;
>> +
>> +     tab_size = data->cooling_data.freq_clip_count;
>> +
>> +     if (tab_size == 0)
>> +             return -EINVAL;
>> +
>> +     /* find the cooling device registered*/
>> +     for (i = 0; i < th_zone->cool_dev_size; i++)
>> +             if (cdev == th_zone->cool_dev[i])
>> +                     break;
>> +
>> +     /* No matching cooling device */
>> +     if (i == th_zone->cool_dev_size)
>> +             return 0;
>> +
>> +     /* Bind the thermal zone to the cpufreq cooling device */
>> +     for (i = 0; i < tab_size; i++) {
>> +             switch (GET_ZONE(i)) {
>> +             case MONITOR_ZONE:
>> +             case WARN_ZONE:
>> +                     if (thermal_zone_unbind_cooling_device(thermal, i,
>> +                                                             cdev)) {
>> +                             pr_err("error unbinding cdev inst=%d\n", i);
>> +                             ret = -EINVAL;
>> +                     }
>> +                     th_zone->bind = false;
>> +                     break;
>> +             default:
>> +                     ret = -EINVAL;
>> +             }
>> +     }
>> +     return ret;
>> +}
>> +
>> +/* Get temperature callback functions for thermal zone */
>> +static int exynos_get_temp(struct thermal_zone_device *thermal,
>> +                     unsigned long *temp)
>> +{
>> +     void *data;
>> +
>> +     if (!th_zone->sensor_conf) {
>> +             pr_info("Temperature sensor not initialised\n");
>> +             return -EINVAL;
>> +     }
>> +     data = th_zone->sensor_conf->private_data;
>> +     *temp = th_zone->sensor_conf->read_temperature(data);
>> +     /* convert the temperature into millicelsius */
>> +     *temp = *temp * MCELSIUS;
>> +     return 0;
>> +}
>> +
>> +/* Get temperature callback functions for thermal zone */
>> +static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
>> +                                             unsigned long temp)
>> +{
>> +     void *data;
>> +     int ret = -EINVAL;
>> +
>> +     if (!th_zone->sensor_conf) {
>> +             pr_info("Temperature sensor not initialised\n");
>> +             return -EINVAL;
>> +     }
>> +     data = th_zone->sensor_conf->private_data;
>> +     if (th_zone->sensor_conf->write_emul_temp)
>> +             ret = th_zone->sensor_conf->write_emul_temp(data, temp);
>> +     return ret;
>> +}
>> +
>> +/* Get the temperature trend */
>> +static int exynos_get_trend(struct thermal_zone_device *thermal,
>> +                     int trip, enum thermal_trend *trend)
>> +{
>> +     int ret;
>> +     unsigned long trip_temp;
>> +
>> +     ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
>> +     if (ret < 0)
>> +             return ret;
>> +
>> +     if (thermal->temperature >= trip_temp)
>> +             *trend = THERMAL_TREND_RAISE_FULL;
>> +     else
>> +             *trend = THERMAL_TREND_DROP_FULL;
>> +
>> +     return 0;
>> +}
>> +/* Operation callback functions for thermal zone */
>> +static struct thermal_zone_device_ops const exynos_dev_ops = {
>> +     .bind = exynos_bind,
>> +     .unbind = exynos_unbind,
>> +     .get_temp = exynos_get_temp,
>> +     .set_emul_temp = exynos_set_emul_temp,
>> +     .get_trend = exynos_get_trend,
>> +     .get_mode = exynos_get_mode,
>> +     .set_mode = exynos_set_mode,
>> +     .get_trip_type = exynos_get_trip_type,
>> +     .get_trip_temp = exynos_get_trip_temp,
>> +     .get_crit_temp = exynos_get_crit_temp,
>> +};
>> +
>> +/*
>> + * This function may be called from interrupt based temperature sensor
>> + * when threshold is changed.
>> + */
>> +void exynos_report_trigger(void)
>> +{
>> +     unsigned int i;
>> +     char data[10];
>> +     char *envp[] = { data, NULL };
>> +
>> +     if (!th_zone || !th_zone->therm_dev)
>> +             return;
>> +     if (th_zone->bind == false) {
>> +             for (i = 0; i < th_zone->cool_dev_size; i++) {
>> +                     if (!th_zone->cool_dev[i])
>> +                             continue;
>> +                     exynos_bind(th_zone->therm_dev,
>> +                                     th_zone->cool_dev[i]);
>> +             }
>> +     }
>> +
>> +     thermal_zone_device_update(th_zone->therm_dev);
>> +
>> +     mutex_lock(&th_zone->therm_dev->lock);
>> +     /* Find the level for which trip happened */
>> +     for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
>> +             if (th_zone->therm_dev->last_temperature <
>> +                     th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
>> +                     break;
>> +     }
>> +
>> +     if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
>> +             !th_zone->sensor_conf->trip_data.trigger_falling) {
>> +             if (i > 0)
>> +                     th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
>> +             else
>> +                     th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
>> +     }
>> +
>> +     snprintf(data, sizeof(data), "%u", i);
>> +     kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
>> +     mutex_unlock(&th_zone->therm_dev->lock);
>> +}
>> +
>> +/* Register with the in-kernel thermal management */
>> +int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
>> +{
>> +     int ret;
>> +     struct cpumask mask_val;
>> +
>> +     if (!sensor_conf || !sensor_conf->read_temperature) {
>> +             pr_err("Temperature sensor not initialised\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
>> +     if (!th_zone)
>> +             return -ENOMEM;
>> +
>
> I d suggest switching to device resource managed allocation.
Ok.
>
>> +     th_zone->sensor_conf = sensor_conf;
>> +     cpumask_set_cpu(0, &mask_val);
>> +     th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
>> +     if (IS_ERR(th_zone->cool_dev[0])) {
>> +             pr_err("Failed to register cpufreq cooling device\n");
>> +             ret = -EINVAL;
>> +             goto err_unregister;
>> +     }
>> +     th_zone->cool_dev_size++;
>> +
>> +     th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
>> +                     EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
>> +                     sensor_conf->trip_data.trigger_falling ?
>> +                     0 : IDLE_INTERVAL);
>> +
>> +     if (IS_ERR(th_zone->therm_dev)) {
>> +             pr_err("Failed to register thermal zone device\n");
>> +             ret = PTR_ERR(th_zone->therm_dev);
>> +             goto err_unregister;
>> +     }
>> +     th_zone->mode = THERMAL_DEVICE_ENABLED;
>> +
>> +     pr_info("Exynos: Kernel Thermal management registered\n");
>> +
>> +     return 0;
>> +
>> +err_unregister:
>> +     exynos_unregister_thermal();
>> +     return ret;
>> +}
>> +
>> +/* Un-Register with the in-kernel thermal management */
>> +void exynos_unregister_thermal(void)
>> +{
>> +     int i;
>> +
>> +     if (!th_zone)
>> +             return;
>> +
>> +     if (th_zone->therm_dev)
>> +             thermal_zone_device_unregister(th_zone->therm_dev);
>> +
>> +     for (i = 0; i < th_zone->cool_dev_size; i++) {
>> +             if (th_zone->cool_dev[i])
>> +                     cpufreq_cooling_unregister(th_zone->cool_dev[i]);
>> +     }
>> +
>> +     kfree(th_zone);
>> +     pr_info("Exynos: Kernel Thermal management unregistered\n");
>> +}
>> diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
>> new file mode 100644
>> index 0000000..da2add0
>> --- /dev/null
>> +++ b/drivers/thermal/samsung/exynos_thermal_common.h
>> @@ -0,0 +1,83 @@
>> +/*
>> + * exynos_thermal_common.h - Samsung EXYNOS common header file
>> + *
>> + *  Copyright (C) 2013 Samsung Electronics
>> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
>> + *
>> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
>> + *
>> + */
>> +
>> +#ifndef _LINUX_EXYNOS_THERMAL_COMMON_H
>> +#define _LINUX_EXYNOS_THERMAL_COMMON_H
>> +
>
> How about simply _EXYNOS_THERMAL_COMMON_H?
Ok
>
>> +/* In-kernel thermal framework related macros & definations */
>> +#define SENSOR_NAME_LEN      16
>> +#define MAX_TRIP_COUNT       8
>> +#define MAX_COOLING_DEVICE 4
>> +#define MAX_THRESHOLD_LEVS 4
>> +
>> +#define ACTIVE_INTERVAL 500
>> +#define IDLE_INTERVAL 10000
>> +#define MCELSIUS     1000
>> +
>> +/* CPU Zone information */
>> +#define PANIC_ZONE      4
>> +#define WARN_ZONE       3
>> +#define MONITOR_ZONE    2
>> +#define SAFE_ZONE       1
>> +
>> +#define GET_ZONE(trip) (trip + 2)
>> +#define GET_TRIP(zone) (zone - 2)
>> +
>> +#define EXYNOS_ZONE_COUNT    3
>> +
>> +struct       thermal_trip_point_conf {
>> +     int trip_val[MAX_TRIP_COUNT];
>> +     int trip_count;
>> +     u8 trigger_falling;
>> +};
>> +
>> +struct       thermal_cooling_conf {
>> +     struct freq_clip_table freq_data[MAX_TRIP_COUNT];
>
> You need to have the include for the above type
Above structure defination is added in the same file in the later
patches. Since this patch is intermediate and compiled so didn't do.

Regards,
Amit Daniel
>
>> +     int freq_clip_count;
>> +};
>> +
>> +struct thermal_sensor_conf {
>> +     char name[SENSOR_NAME_LEN];
>> +     int (*read_temperature)(void *data);
>> +     int (*write_emul_temp)(void *drv_data, unsigned long temp);
>> +     struct thermal_trip_point_conf trip_data;
>> +     struct thermal_cooling_conf cooling_daa;
>> +     void *private_data;
>> +};
>> +
>> +/*Functions used exynos based thermal sensor driver*/
>> +#ifdef CONFIG_EXYNOS_THERMAL_CORE
>> +void exynos_unregister_thermal(void);
>> +int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
>> +void exynos_report_trigger(void);
>> +#else
>> +static inline void
>> +exynos_unregister_thermal(void) { return; }
>> +
>> +static inline int
>> +exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
>> +
>> +static inline void
>> +exynos_report_trigger(void) { return; }
>> +
>> +#endif /* CONFIG_EXYNOS_COMMON */
>> +#endif /* _LINUX_EXYNOS_THERMAL_COMMON_H */
>>
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 04/21] thermal: exynos: Move exynos_thermal.h from include/* to driver/* folder
  2013-05-07 13:00 ` [PATCH V3 04/21] thermal: exynos: Move exynos_thermal.h from include/* to driver/* folder Amit Daniel Kachhap
@ 2013-05-09 13:28     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 13:28 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 4502 bytes --]

Hello Amit,

On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
> This patch renames and moves  include/linux/platform_data/exynos_thermal.h to
> drivers/thermal/samsung/exynos_tmu.h. This file movement is needed as exynos
> SOC's are not supporting non-DT based platforms. Also the rename is needed as this
> file now just contains exynos tmu driver related definations.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/exynos_thermal_common.c    |    1 -
>  drivers/thermal/samsung/exynos_thermal_common.h    |   15 +++++++++++++++
>  drivers/thermal/samsung/exynos_tmu.c               |    2 +-
>  .../thermal/samsung/exynos_tmu.h                   |   15 ---------------
>  4 files changed, 16 insertions(+), 17 deletions(-)
>  rename include/linux/platform_data/exynos_thermal.h => drivers/thermal/samsung/exynos_tmu.h (88%)
> 
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
> index 9a57606..dae5476 100644
> --- a/drivers/thermal/samsung/exynos_thermal_common.c
> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
> @@ -27,7 +27,6 @@
>  #include <linux/kernel.h>
>  #include <linux/kobject.h>
>  #include <linux/mutex.h>
> -#include <linux/platform_data/exynos_thermal.h>
>  #include <linux/slab.h>
>  #include <linux/thermal.h>
>  #include "exynos_thermal_common.h"
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
> index da2add0..1c3f8b7 100644
> --- a/drivers/thermal/samsung/exynos_thermal_common.h
> +++ b/drivers/thermal/samsung/exynos_thermal_common.h
> @@ -44,6 +44,21 @@
>  
>  #define EXYNOS_ZONE_COUNT	3
>  
> +/**
> + * struct freq_clip_table
> + * @freq_clip_max: maximum frequency allowed for this cooling state.
> + * @temp_level: Temperature level at which the temperature clipping will
> + *	happen.
> + * @mask_val: cpumask of the allowed cpu's where the clipping will take place.
> + *
> + * This structure is required to be filled and passed to the
> + * cpufreq_cooling_unregister function.
> + */
> +struct freq_clip_table {
> +	unsigned int freq_clip_max;
> +	unsigned int temp_level;
> +	const struct cpumask *mask_val;
> +};
>  struct	thermal_trip_point_conf {
>  	int trip_val[MAX_TRIP_COUNT];
>  	int trip_count;
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index 3de3e61..a02f2c9 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -30,10 +30,10 @@
>  #include <linux/mutex.h>
>  #include <linux/of.h>
>  #include <linux/platform_device.h>
> -#include <linux/platform_data/exynos_thermal.h>
>  #include <linux/slab.h>
>  #include <linux/workqueue.h>
>  #include "exynos_thermal_common.h"
> +#include "exynos_tmu.h"
>  
>  /* Exynos generic registers */
>  #define EXYNOS_TMU_REG_TRIMINFO		0x0
> diff --git a/include/linux/platform_data/exynos_thermal.h b/drivers/thermal/samsung/exynos_tmu.h
> similarity index 88%
> rename from include/linux/platform_data/exynos_thermal.h
> rename to drivers/thermal/samsung/exynos_tmu.h
> index da7e627..342fb1f 100644
> --- a/include/linux/platform_data/exynos_thermal.h
> +++ b/drivers/thermal/samsung/exynos_tmu.h
> @@ -33,21 +33,6 @@ enum soc_type {
>  	SOC_ARCH_EXYNOS4210 = 1,
>  	SOC_ARCH_EXYNOS,
>  };
> -/**
> - * struct freq_clip_table
> - * @freq_clip_max: maximum frequency allowed for this cooling state.
> - * @temp_level: Temperature level at which the temperature clipping will
> - *	happen.
> - * @mask_val: cpumask of the allowed cpu's where the clipping will take place.
> - *
> - * This structure is required to be filled and passed to the
> - * cpufreq_cooling_unregister function.
> - */
> -struct freq_clip_table {
> -	unsigned int freq_clip_max;
> -	unsigned int temp_level;
> -	const struct cpumask *mask_val;
> -};
>

You explain why you need to rename the header, and thats what you do in
this patch. On the other hand, you also move the freq_clip_table
structure definition. This change is present in this patch, I dont see
the connection with the file rename, and you also do not explain why it
is needed. Can you please consider, either split this change to other
(new) patch or explain it also in this patch?


>  /**
>   * struct exynos_tmu_platform_data
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 04/21] thermal: exynos: Move exynos_thermal.h from include/* to driver/* folder
@ 2013-05-09 13:28     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 13:28 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 4502 bytes --]

Hello Amit,

On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
> This patch renames and moves  include/linux/platform_data/exynos_thermal.h to
> drivers/thermal/samsung/exynos_tmu.h. This file movement is needed as exynos
> SOC's are not supporting non-DT based platforms. Also the rename is needed as this
> file now just contains exynos tmu driver related definations.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/exynos_thermal_common.c    |    1 -
>  drivers/thermal/samsung/exynos_thermal_common.h    |   15 +++++++++++++++
>  drivers/thermal/samsung/exynos_tmu.c               |    2 +-
>  .../thermal/samsung/exynos_tmu.h                   |   15 ---------------
>  4 files changed, 16 insertions(+), 17 deletions(-)
>  rename include/linux/platform_data/exynos_thermal.h => drivers/thermal/samsung/exynos_tmu.h (88%)
> 
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
> index 9a57606..dae5476 100644
> --- a/drivers/thermal/samsung/exynos_thermal_common.c
> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
> @@ -27,7 +27,6 @@
>  #include <linux/kernel.h>
>  #include <linux/kobject.h>
>  #include <linux/mutex.h>
> -#include <linux/platform_data/exynos_thermal.h>
>  #include <linux/slab.h>
>  #include <linux/thermal.h>
>  #include "exynos_thermal_common.h"
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
> index da2add0..1c3f8b7 100644
> --- a/drivers/thermal/samsung/exynos_thermal_common.h
> +++ b/drivers/thermal/samsung/exynos_thermal_common.h
> @@ -44,6 +44,21 @@
>  
>  #define EXYNOS_ZONE_COUNT	3
>  
> +/**
> + * struct freq_clip_table
> + * @freq_clip_max: maximum frequency allowed for this cooling state.
> + * @temp_level: Temperature level at which the temperature clipping will
> + *	happen.
> + * @mask_val: cpumask of the allowed cpu's where the clipping will take place.
> + *
> + * This structure is required to be filled and passed to the
> + * cpufreq_cooling_unregister function.
> + */
> +struct freq_clip_table {
> +	unsigned int freq_clip_max;
> +	unsigned int temp_level;
> +	const struct cpumask *mask_val;
> +};
>  struct	thermal_trip_point_conf {
>  	int trip_val[MAX_TRIP_COUNT];
>  	int trip_count;
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index 3de3e61..a02f2c9 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -30,10 +30,10 @@
>  #include <linux/mutex.h>
>  #include <linux/of.h>
>  #include <linux/platform_device.h>
> -#include <linux/platform_data/exynos_thermal.h>
>  #include <linux/slab.h>
>  #include <linux/workqueue.h>
>  #include "exynos_thermal_common.h"
> +#include "exynos_tmu.h"
>  
>  /* Exynos generic registers */
>  #define EXYNOS_TMU_REG_TRIMINFO		0x0
> diff --git a/include/linux/platform_data/exynos_thermal.h b/drivers/thermal/samsung/exynos_tmu.h
> similarity index 88%
> rename from include/linux/platform_data/exynos_thermal.h
> rename to drivers/thermal/samsung/exynos_tmu.h
> index da7e627..342fb1f 100644
> --- a/include/linux/platform_data/exynos_thermal.h
> +++ b/drivers/thermal/samsung/exynos_tmu.h
> @@ -33,21 +33,6 @@ enum soc_type {
>  	SOC_ARCH_EXYNOS4210 = 1,
>  	SOC_ARCH_EXYNOS,
>  };
> -/**
> - * struct freq_clip_table
> - * @freq_clip_max: maximum frequency allowed for this cooling state.
> - * @temp_level: Temperature level at which the temperature clipping will
> - *	happen.
> - * @mask_val: cpumask of the allowed cpu's where the clipping will take place.
> - *
> - * This structure is required to be filled and passed to the
> - * cpufreq_cooling_unregister function.
> - */
> -struct freq_clip_table {
> -	unsigned int freq_clip_max;
> -	unsigned int temp_level;
> -	const struct cpumask *mask_val;
> -};
>

You explain why you need to rename the header, and thats what you do in
this patch. On the other hand, you also move the freq_clip_table
structure definition. This change is present in this patch, I dont see
the connection with the file rename, and you also do not explain why it
is needed. Can you please consider, either split this change to other
(new) patch or explain it also in this patch?


>  /**
>   * struct exynos_tmu_platform_data
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 05/21] thermal: exynos: Bifurcate exynos tmu driver and configuration data
  2013-05-07 13:00 ` [PATCH V3 05/21] thermal: exynos: Bifurcate exynos tmu driver and configuration data Amit Daniel Kachhap
@ 2013-05-09 13:39     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 13:39 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 12126 bytes --]

Hey Amit,

On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
> This code splits the exynos tmu driver code into SOC specific data parts.
> This will simplify adding new SOC specific data to the same TMU controller.

I like the idea of spliting the code from data. The driver goes into a
self contained direction. Thanks for doing this.Couple of minor comments
follows.

> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/Kconfig                 |   13 ++++-
>  drivers/thermal/samsung/Makefile                |    1 +
>  drivers/thermal/samsung/exynos_thermal_common.h |    3 +-
>  drivers/thermal/samsung/exynos_tmu.c            |   67 +------------------
>  drivers/thermal/samsung/exynos_tmu_data.c       |   78 +++++++++++++++++++++++
>  drivers/thermal/samsung/exynos_tmu_data.h       |   41 ++++++++++++
>  6 files changed, 137 insertions(+), 66 deletions(-)
>  create mode 100644 drivers/thermal/samsung/exynos_tmu_data.c
>  create mode 100644 drivers/thermal/samsung/exynos_tmu_data.h
> 
> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
> index 7857e20..f23f533 100644
> --- a/drivers/thermal/samsung/Kconfig
> +++ b/drivers/thermal/samsung/Kconfig
> @@ -5,7 +5,8 @@ config EXYNOS_THERMAL
>  	  If you say yes here you get support for the exynos thermal driver
>  	  for exynos4 and exynos5 soc. This driver initialises the TMU, reports
>  	  temperature and handles cooling action if defined. This driver uses
> -	  core thermal API's.
> +	  core thermal API's and TMU configuration data from the supported
> +	  soc's.
>  
>  config EXYNOS_THERMAL_CORE
>  	bool "Core thermal framework support for EXYNOS SOC's"
> @@ -15,3 +16,13 @@ config EXYNOS_THERMAL_CORE
>  	  (Thermal Management Unit) common registration/unregistration
>  	  functions to the core thermal layer and also to use the generic
>  	  cpu cooling API's.
> +
> +config EXYNOS_THERMAL_DATA
> +	bool "Temperature sensor congiguration data for EXYNOS series SOC"
> +	depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250)
> +	depends on EXYNOS_THERMAL
> +	help
> +	  If you say yes here you can enable TMU (Thermal Management Unit) on
> +	  SAMSUNG EXYNOS 4210, 4412, 4414 and 5250 series of SoC. This option
> +	  enables/prepares the configuration, trip and cooling data for the TMU
> +	  driver.

What is your strategy here? Looks like you want to provide all required
data (for all supported SoCs) based on 1 config entry
(EXYNOS_THERMAL_DATA). What do you think of having one per SoC supported?

> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
> index 22528d6..c0446e8 100644
> --- a/drivers/thermal/samsung/Makefile
> +++ b/drivers/thermal/samsung/Makefile
> @@ -4,3 +4,4 @@
>  obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_thermal.o
>  exynos_thermal-y				:= exynos_tmu.o
>  exynos_thermal-$(CONFIG_EXYNOS_THERMAL_CORE)	+= exynos_thermal_common.o
> +exynos_thermal-$(CONFIG_EXYNOS_THERMAL_DATA)	+= exynos_tmu_data.o
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
> index 1c3f8b7..3b85858 100644
> --- a/drivers/thermal/samsung/exynos_thermal_common.h
> +++ b/drivers/thermal/samsung/exynos_thermal_common.h
> @@ -62,7 +62,7 @@ struct freq_clip_table {
>  struct	thermal_trip_point_conf {
>  	int trip_val[MAX_TRIP_COUNT];
>  	int trip_count;
> -	u8 trigger_falling;
> +	unsigned char trigger_falling;
>  };

Why do you need this change to bifurcate data / code? (Sounds like you
probably want to send this in a separate patch, as it seams to be a
separated issue).

>  
>  struct	thermal_cooling_conf {
> @@ -93,6 +93,5 @@ exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
>  
>  static inline void
>  exynos_report_trigger(void) { return; }
> -

I dont think this is realted to this patch.

>  #endif /* CONFIG_EXYNOS_COMMON */
>  #endif /* _LINUX_EXYNOS_THERMAL_COMMON_H */
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index a02f2c9..05b5068 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -34,6 +34,7 @@
>  #include <linux/workqueue.h>
>  #include "exynos_thermal_common.h"
>  #include "exynos_tmu.h"
> +#include "exynos_tmu_data.h"
>  
>  /* Exynos generic registers */
>  #define EXYNOS_TMU_REG_TRIMINFO		0x0
> @@ -385,66 +386,6 @@ static struct thermal_sensor_conf exynos_sensor_conf = {
>  	.write_emul_temp	= exynos_tmu_set_emulation,
>  };
>  
> -#if defined(CONFIG_CPU_EXYNOS4210)
> -static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
> -	.threshold = 80,
> -	.trigger_levels[0] = 5,
> -	.trigger_levels[1] = 20,
> -	.trigger_levels[2] = 30,
> -	.trigger_level0_en = 1,
> -	.trigger_level1_en = 1,
> -	.trigger_level2_en = 1,
> -	.trigger_level3_en = 0,
> -	.gain = 15,
> -	.reference_voltage = 7,
> -	.cal_type = TYPE_ONE_POINT_TRIMMING,
> -	.freq_tab[0] = {
> -		.freq_clip_max = 800 * 1000,
> -		.temp_level = 85,
> -	},
> -	.freq_tab[1] = {
> -		.freq_clip_max = 200 * 1000,
> -		.temp_level = 100,
> -	},
> -	.freq_tab_count = 2,
> -	.type = SOC_ARCH_EXYNOS4210,
> -};
> -#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
> -#else
> -#define EXYNOS4210_TMU_DRV_DATA (NULL)
> -#endif
> -
> -#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
> -static struct exynos_tmu_platform_data const exynos_default_tmu_data = {
> -	.threshold_falling = 10,
> -	.trigger_levels[0] = 85,
> -	.trigger_levels[1] = 103,
> -	.trigger_levels[2] = 110,
> -	.trigger_level0_en = 1,
> -	.trigger_level1_en = 1,
> -	.trigger_level2_en = 1,
> -	.trigger_level3_en = 0,
> -	.gain = 8,
> -	.reference_voltage = 16,
> -	.noise_cancel_mode = 4,
> -	.cal_type = TYPE_ONE_POINT_TRIMMING,
> -	.efuse_value = 55,
> -	.freq_tab[0] = {
> -		.freq_clip_max = 800 * 1000,
> -		.temp_level = 85,
> -	},
> -	.freq_tab[1] = {
> -		.freq_clip_max = 200 * 1000,
> -		.temp_level = 103,
> -	},
> -	.freq_tab_count = 2,
> -	.type = SOC_ARCH_EXYNOS,
> -};
> -#define EXYNOS_TMU_DRV_DATA (&exynos_default_tmu_data)
> -#else
> -#define EXYNOS_TMU_DRV_DATA (NULL)
> -#endif
> -
>  #ifdef CONFIG_OF
>  static const struct of_device_id exynos_tmu_match[] = {
>  	{
> @@ -453,11 +394,11 @@ static const struct of_device_id exynos_tmu_match[] = {
>  	},
>  	{
>  		.compatible = "samsung,exynos4412-tmu",
> -		.data = (void *)EXYNOS_TMU_DRV_DATA,
> +		.data = (void *)EXYNOS5250_TMU_DRV_DATA,
>  	},
>  	{
>  		.compatible = "samsung,exynos5250-tmu",
> -		.data = (void *)EXYNOS_TMU_DRV_DATA,
> +		.data = (void *)EXYNOS5250_TMU_DRV_DATA,
>  	},
>  	{},
>  };
> @@ -471,7 +412,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = {
>  	},
>  	{
>  		.name		= "exynos5250-tmu",
> -		.driver_data    = (kernel_ulong_t)EXYNOS_TMU_DRV_DATA,
> +		.driver_data    = (kernel_ulong_t)EXYNOS5250_TMU_DRV_DATA,
>  	},
>  	{ },
>  };
> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
> new file mode 100644
> index 0000000..13a60ca
> --- /dev/null
> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
> @@ -0,0 +1,78 @@
> +/*
> + * exynos_tmu_data.c - Samsung EXYNOS tmu data file
> + *
> + *  Copyright (C) 2013 Samsung Electronics
> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
> + *
> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#include "exynos_thermal_common.h"
> +#include "exynos_tmu.h"
> +
> +#if defined(CONFIG_CPU_EXYNOS4210)
> +struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
> +	.threshold = 80,
> +	.trigger_levels[0] = 5,
> +	.trigger_levels[1] = 20,
> +	.trigger_levels[2] = 30,
> +	.trigger_level0_en = 1,
> +	.trigger_level1_en = 1,
> +	.trigger_level2_en = 1,
> +	.trigger_level3_en = 0,
> +	.gain = 15,
> +	.reference_voltage = 7,
> +	.cal_type = TYPE_ONE_POINT_TRIMMING,
> +	.freq_tab[0] = {
> +		.freq_clip_max = 800 * 1000,
> +		.temp_level = 85,
> +	},
> +	.freq_tab[1] = {
> +		.freq_clip_max = 200 * 1000,
> +		.temp_level = 100,
> +	},
> +	.freq_tab_count = 2,
> +	.type = SOC_ARCH_EXYNOS4210,
> +};
> +#endif
> +
> +#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
> +struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
> +	.threshold_falling = 10,
> +	.trigger_levels[0] = 85,
> +	.trigger_levels[1] = 103,
> +	.trigger_levels[2] = 110,
> +	.trigger_level0_en = 1,
> +	.trigger_level1_en = 1,
> +	.trigger_level2_en = 1,
> +	.trigger_level3_en = 0,
> +	.gain = 8,
> +	.reference_voltage = 16,
> +	.noise_cancel_mode = 4,
> +	.cal_type = TYPE_ONE_POINT_TRIMMING,
> +	.efuse_value = 55,
> +	.freq_tab[0] = {
> +		.freq_clip_max = 800 * 1000,
> +		.temp_level = 85,
> +	},
> +	.freq_tab[1] = {
> +		.freq_clip_max = 200 * 1000,
> +		.temp_level = 103,
> +	},
> +	.freq_tab_count = 2,
> +	.type = SOC_ARCH_EXYNOS,
> +};
> +#endif

If you define config entries per SoC data, you could have a file per SoC
data and remove the #ifdefery by solving the config in the Makefile.
What do you think?

> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
> new file mode 100644
> index 0000000..5b69711
> --- /dev/null
> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
> @@ -0,0 +1,41 @@
> +/*
> + * exynos_tmu_data.h - Samsung EXYNOS tmu data header file
> + *
> + *  Copyright (C) 2013 Samsung Electronics
> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
> + *
> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#ifndef _LINUX_EXYNOS_TMU_DATA_H
> +#define _LINUX_EXYNOS_TMU_DATA_H
> +
how about _EXYNOS_TMU_DATA_H ?



> +#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
> +extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
> +#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
> +#else
> +#define EXYNOS4210_TMU_DRV_DATA (NULL)
> +#endif
> +
> +#if (defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)) && \
> +defined(CONFIG_EXYNOS_THERMAL_DATA)
> +extern struct exynos_tmu_platform_data const exynos5250_default_tmu_data;
> +#define EXYNOS5250_TMU_DRV_DATA (&exynos5250_default_tmu_data)
> +#else
> +#define EXYNOS5250_TMU_DRV_DATA (NULL)
> +#endif
> +
> +#endif /*_LINUX_EXYNOS_TMU_DATA_H*/
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 05/21] thermal: exynos: Bifurcate exynos tmu driver and configuration data
@ 2013-05-09 13:39     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 13:39 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 12126 bytes --]

Hey Amit,

On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
> This code splits the exynos tmu driver code into SOC specific data parts.
> This will simplify adding new SOC specific data to the same TMU controller.

I like the idea of spliting the code from data. The driver goes into a
self contained direction. Thanks for doing this.Couple of minor comments
follows.

> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/Kconfig                 |   13 ++++-
>  drivers/thermal/samsung/Makefile                |    1 +
>  drivers/thermal/samsung/exynos_thermal_common.h |    3 +-
>  drivers/thermal/samsung/exynos_tmu.c            |   67 +------------------
>  drivers/thermal/samsung/exynos_tmu_data.c       |   78 +++++++++++++++++++++++
>  drivers/thermal/samsung/exynos_tmu_data.h       |   41 ++++++++++++
>  6 files changed, 137 insertions(+), 66 deletions(-)
>  create mode 100644 drivers/thermal/samsung/exynos_tmu_data.c
>  create mode 100644 drivers/thermal/samsung/exynos_tmu_data.h
> 
> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
> index 7857e20..f23f533 100644
> --- a/drivers/thermal/samsung/Kconfig
> +++ b/drivers/thermal/samsung/Kconfig
> @@ -5,7 +5,8 @@ config EXYNOS_THERMAL
>  	  If you say yes here you get support for the exynos thermal driver
>  	  for exynos4 and exynos5 soc. This driver initialises the TMU, reports
>  	  temperature and handles cooling action if defined. This driver uses
> -	  core thermal API's.
> +	  core thermal API's and TMU configuration data from the supported
> +	  soc's.
>  
>  config EXYNOS_THERMAL_CORE
>  	bool "Core thermal framework support for EXYNOS SOC's"
> @@ -15,3 +16,13 @@ config EXYNOS_THERMAL_CORE
>  	  (Thermal Management Unit) common registration/unregistration
>  	  functions to the core thermal layer and also to use the generic
>  	  cpu cooling API's.
> +
> +config EXYNOS_THERMAL_DATA
> +	bool "Temperature sensor congiguration data for EXYNOS series SOC"
> +	depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250)
> +	depends on EXYNOS_THERMAL
> +	help
> +	  If you say yes here you can enable TMU (Thermal Management Unit) on
> +	  SAMSUNG EXYNOS 4210, 4412, 4414 and 5250 series of SoC. This option
> +	  enables/prepares the configuration, trip and cooling data for the TMU
> +	  driver.

What is your strategy here? Looks like you want to provide all required
data (for all supported SoCs) based on 1 config entry
(EXYNOS_THERMAL_DATA). What do you think of having one per SoC supported?

> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
> index 22528d6..c0446e8 100644
> --- a/drivers/thermal/samsung/Makefile
> +++ b/drivers/thermal/samsung/Makefile
> @@ -4,3 +4,4 @@
>  obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_thermal.o
>  exynos_thermal-y				:= exynos_tmu.o
>  exynos_thermal-$(CONFIG_EXYNOS_THERMAL_CORE)	+= exynos_thermal_common.o
> +exynos_thermal-$(CONFIG_EXYNOS_THERMAL_DATA)	+= exynos_tmu_data.o
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
> index 1c3f8b7..3b85858 100644
> --- a/drivers/thermal/samsung/exynos_thermal_common.h
> +++ b/drivers/thermal/samsung/exynos_thermal_common.h
> @@ -62,7 +62,7 @@ struct freq_clip_table {
>  struct	thermal_trip_point_conf {
>  	int trip_val[MAX_TRIP_COUNT];
>  	int trip_count;
> -	u8 trigger_falling;
> +	unsigned char trigger_falling;
>  };

Why do you need this change to bifurcate data / code? (Sounds like you
probably want to send this in a separate patch, as it seams to be a
separated issue).

>  
>  struct	thermal_cooling_conf {
> @@ -93,6 +93,5 @@ exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
>  
>  static inline void
>  exynos_report_trigger(void) { return; }
> -

I dont think this is realted to this patch.

>  #endif /* CONFIG_EXYNOS_COMMON */
>  #endif /* _LINUX_EXYNOS_THERMAL_COMMON_H */
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index a02f2c9..05b5068 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -34,6 +34,7 @@
>  #include <linux/workqueue.h>
>  #include "exynos_thermal_common.h"
>  #include "exynos_tmu.h"
> +#include "exynos_tmu_data.h"
>  
>  /* Exynos generic registers */
>  #define EXYNOS_TMU_REG_TRIMINFO		0x0
> @@ -385,66 +386,6 @@ static struct thermal_sensor_conf exynos_sensor_conf = {
>  	.write_emul_temp	= exynos_tmu_set_emulation,
>  };
>  
> -#if defined(CONFIG_CPU_EXYNOS4210)
> -static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
> -	.threshold = 80,
> -	.trigger_levels[0] = 5,
> -	.trigger_levels[1] = 20,
> -	.trigger_levels[2] = 30,
> -	.trigger_level0_en = 1,
> -	.trigger_level1_en = 1,
> -	.trigger_level2_en = 1,
> -	.trigger_level3_en = 0,
> -	.gain = 15,
> -	.reference_voltage = 7,
> -	.cal_type = TYPE_ONE_POINT_TRIMMING,
> -	.freq_tab[0] = {
> -		.freq_clip_max = 800 * 1000,
> -		.temp_level = 85,
> -	},
> -	.freq_tab[1] = {
> -		.freq_clip_max = 200 * 1000,
> -		.temp_level = 100,
> -	},
> -	.freq_tab_count = 2,
> -	.type = SOC_ARCH_EXYNOS4210,
> -};
> -#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
> -#else
> -#define EXYNOS4210_TMU_DRV_DATA (NULL)
> -#endif
> -
> -#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
> -static struct exynos_tmu_platform_data const exynos_default_tmu_data = {
> -	.threshold_falling = 10,
> -	.trigger_levels[0] = 85,
> -	.trigger_levels[1] = 103,
> -	.trigger_levels[2] = 110,
> -	.trigger_level0_en = 1,
> -	.trigger_level1_en = 1,
> -	.trigger_level2_en = 1,
> -	.trigger_level3_en = 0,
> -	.gain = 8,
> -	.reference_voltage = 16,
> -	.noise_cancel_mode = 4,
> -	.cal_type = TYPE_ONE_POINT_TRIMMING,
> -	.efuse_value = 55,
> -	.freq_tab[0] = {
> -		.freq_clip_max = 800 * 1000,
> -		.temp_level = 85,
> -	},
> -	.freq_tab[1] = {
> -		.freq_clip_max = 200 * 1000,
> -		.temp_level = 103,
> -	},
> -	.freq_tab_count = 2,
> -	.type = SOC_ARCH_EXYNOS,
> -};
> -#define EXYNOS_TMU_DRV_DATA (&exynos_default_tmu_data)
> -#else
> -#define EXYNOS_TMU_DRV_DATA (NULL)
> -#endif
> -
>  #ifdef CONFIG_OF
>  static const struct of_device_id exynos_tmu_match[] = {
>  	{
> @@ -453,11 +394,11 @@ static const struct of_device_id exynos_tmu_match[] = {
>  	},
>  	{
>  		.compatible = "samsung,exynos4412-tmu",
> -		.data = (void *)EXYNOS_TMU_DRV_DATA,
> +		.data = (void *)EXYNOS5250_TMU_DRV_DATA,
>  	},
>  	{
>  		.compatible = "samsung,exynos5250-tmu",
> -		.data = (void *)EXYNOS_TMU_DRV_DATA,
> +		.data = (void *)EXYNOS5250_TMU_DRV_DATA,
>  	},
>  	{},
>  };
> @@ -471,7 +412,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = {
>  	},
>  	{
>  		.name		= "exynos5250-tmu",
> -		.driver_data    = (kernel_ulong_t)EXYNOS_TMU_DRV_DATA,
> +		.driver_data    = (kernel_ulong_t)EXYNOS5250_TMU_DRV_DATA,
>  	},
>  	{ },
>  };
> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
> new file mode 100644
> index 0000000..13a60ca
> --- /dev/null
> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
> @@ -0,0 +1,78 @@
> +/*
> + * exynos_tmu_data.c - Samsung EXYNOS tmu data file
> + *
> + *  Copyright (C) 2013 Samsung Electronics
> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
> + *
> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#include "exynos_thermal_common.h"
> +#include "exynos_tmu.h"
> +
> +#if defined(CONFIG_CPU_EXYNOS4210)
> +struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
> +	.threshold = 80,
> +	.trigger_levels[0] = 5,
> +	.trigger_levels[1] = 20,
> +	.trigger_levels[2] = 30,
> +	.trigger_level0_en = 1,
> +	.trigger_level1_en = 1,
> +	.trigger_level2_en = 1,
> +	.trigger_level3_en = 0,
> +	.gain = 15,
> +	.reference_voltage = 7,
> +	.cal_type = TYPE_ONE_POINT_TRIMMING,
> +	.freq_tab[0] = {
> +		.freq_clip_max = 800 * 1000,
> +		.temp_level = 85,
> +	},
> +	.freq_tab[1] = {
> +		.freq_clip_max = 200 * 1000,
> +		.temp_level = 100,
> +	},
> +	.freq_tab_count = 2,
> +	.type = SOC_ARCH_EXYNOS4210,
> +};
> +#endif
> +
> +#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
> +struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
> +	.threshold_falling = 10,
> +	.trigger_levels[0] = 85,
> +	.trigger_levels[1] = 103,
> +	.trigger_levels[2] = 110,
> +	.trigger_level0_en = 1,
> +	.trigger_level1_en = 1,
> +	.trigger_level2_en = 1,
> +	.trigger_level3_en = 0,
> +	.gain = 8,
> +	.reference_voltage = 16,
> +	.noise_cancel_mode = 4,
> +	.cal_type = TYPE_ONE_POINT_TRIMMING,
> +	.efuse_value = 55,
> +	.freq_tab[0] = {
> +		.freq_clip_max = 800 * 1000,
> +		.temp_level = 85,
> +	},
> +	.freq_tab[1] = {
> +		.freq_clip_max = 200 * 1000,
> +		.temp_level = 103,
> +	},
> +	.freq_tab_count = 2,
> +	.type = SOC_ARCH_EXYNOS,
> +};
> +#endif

If you define config entries per SoC data, you could have a file per SoC
data and remove the #ifdefery by solving the config in the Makefile.
What do you think?

> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
> new file mode 100644
> index 0000000..5b69711
> --- /dev/null
> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
> @@ -0,0 +1,41 @@
> +/*
> + * exynos_tmu_data.h - Samsung EXYNOS tmu data header file
> + *
> + *  Copyright (C) 2013 Samsung Electronics
> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
> + *
> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#ifndef _LINUX_EXYNOS_TMU_DATA_H
> +#define _LINUX_EXYNOS_TMU_DATA_H
> +
how about _EXYNOS_TMU_DATA_H ?



> +#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
> +extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
> +#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
> +#else
> +#define EXYNOS4210_TMU_DRV_DATA (NULL)
> +#endif
> +
> +#if (defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)) && \
> +defined(CONFIG_EXYNOS_THERMAL_DATA)
> +extern struct exynos_tmu_platform_data const exynos5250_default_tmu_data;
> +#define EXYNOS5250_TMU_DRV_DATA (&exynos5250_default_tmu_data)
> +#else
> +#define EXYNOS5250_TMU_DRV_DATA (NULL)
> +#endif
> +
> +#endif /*_LINUX_EXYNOS_TMU_DATA_H*/
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 06/21] thermal: exynos: Add missing definations and code cleanup
  2013-05-07 13:00 ` [PATCH V3 06/21] thermal: exynos: Add missing definations and code cleanup Amit Daniel Kachhap
@ 2013-05-09 13:52     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 13:52 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 5353 bytes --]

Amit,

On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
> This patch adds some extra register bitfield definations and cleans
> up the code to prepare for moving register macros and definations inside
> the TMU data section.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/exynos_tmu.c |   62 +++++++++++++++++++++++++---------
>  1 files changed, 46 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index 05b5068..a43afc4 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -47,9 +47,12 @@
>  
>  #define EXYNOS_TMU_TRIM_TEMP_MASK	0xff
>  #define EXYNOS_TMU_GAIN_SHIFT		8
> +#define EXYNOS_TMU_GAIN_MASK		0xf
>  #define EXYNOS_TMU_REF_VOLTAGE_SHIFT	24
> -#define EXYNOS_TMU_CORE_ON		3
> -#define EXYNOS_TMU_CORE_OFF		2
> +#define EXYNOS_TMU_REF_VOLTAGE_MASK	0x1f
> +#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK	0xf
> +#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT	8
> +#define EXYNOS_TMU_CORE_EN_SHIFT	0
>  #define EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET	50
>  
>  /* Exynos4210 specific registers */
> @@ -67,6 +70,7 @@
>  #define EXYNOS4210_TMU_TRIG_LEVEL1_MASK	0x10
>  #define EXYNOS4210_TMU_TRIG_LEVEL2_MASK	0x100
>  #define EXYNOS4210_TMU_TRIG_LEVEL3_MASK	0x1000
> +#define EXYNOS4210_TMU_TRIG_LEVEL_MASK	0x1111
>  #define EXYNOS4210_TMU_INTCLEAR_VAL	0x1111
>  
>  /* Exynos5250 and Exynos4412 specific registers */
> @@ -76,17 +80,30 @@
>  #define EXYNOS_EMUL_CON		0x80
>  
>  #define EXYNOS_TRIMINFO_RELOAD		0x1
> +#define EXYNOS_TRIMINFO_SHIFT		0x0
> +#define EXYNOS_TMU_RISE_INT_MASK	0x111
> +#define EXYNOS_TMU_RISE_INT_SHIFT	0
> +#define EXYNOS_TMU_FALL_INT_MASK	0x111
> +#define EXYNOS_TMU_FALL_INT_SHIFT	12
>  #define EXYNOS_TMU_CLEAR_RISE_INT	0x111
>  #define EXYNOS_TMU_CLEAR_FALL_INT	(0x111 << 12)
> -#define EXYNOS_MUX_ADDR_VALUE		6
> -#define EXYNOS_MUX_ADDR_SHIFT		20
>  #define EXYNOS_TMU_TRIP_MODE_SHIFT	13
> +#define EXYNOS_TMU_TRIP_MODE_MASK	0x7
> +
> +#define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
> +#define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
> +#define EXYNOS_TMU_INTEN_RISE2_SHIFT	8
> +#define EXYNOS_TMU_INTEN_RISE3_SHIFT	12
> +#define EXYNOS_TMU_INTEN_FALL0_SHIFT	16
> +#define EXYNOS_TMU_INTEN_FALL1_SHIFT	20
> +#define EXYNOS_TMU_INTEN_FALL2_SHIFT	24
>  
>  #define EFUSE_MIN_VALUE 40
>  #define EFUSE_MAX_VALUE 100
>  
>  #ifdef CONFIG_THERMAL_EMULATION
>  #define EXYNOS_EMUL_TIME	0x57F0
> +#define EXYNOS_EMUL_TIME_MASK	0xffff
>  #define EXYNOS_EMUL_TIME_SHIFT	16
>  #define EXYNOS_EMUL_DATA_SHIFT	8
>  #define EXYNOS_EMUL_DATA_MASK	0xFF


What is the pattern above? Sometimes you use decimal notation sometimes
you use hex notation. On a quick look I could not see a pattern..

> @@ -265,24 +282,37 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	con = pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT |
> -		pdata->gain << EXYNOS_TMU_GAIN_SHIFT;
> +	con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
>  

You have a important change here. Before you would just apply a value
based on your local configuration. Now you are considering what is
present in your ctrl register. Is this really a code cleanup required
for moving the register definitions?

> -	if (data->soc == SOC_ARCH_EXYNOS) {
> -		con |= pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT;
> -		con |= (EXYNOS_MUX_ADDR_VALUE << EXYNOS_MUX_ADDR_SHIFT);
> +	if (pdata->reference_voltage) {
> +		con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK <<
> +				EXYNOS_TMU_REF_VOLTAGE_SHIFT);
> +		con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
> +	}
> +
> +	if (pdata->gain) {
> +		con &= ~(EXYNOS_TMU_GAIN_MASK << EXYNOS_TMU_GAIN_SHIFT);
> +		con |= (pdata->gain << EXYNOS_TMU_GAIN_SHIFT);
> +	}
> +
> +	if (pdata->noise_cancel_mode) {
> +		con &= ~(EXYNOS_TMU_TRIP_MODE_MASK <<
> +					EXYNOS_TMU_TRIP_MODE_SHIFT);
> +		con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);

For all the above ifs: Dont you want to clear those bits in case the
pdata config says those flags are not set? For instance, if pdata->gain
== 0, do you need to con &= ~(EXYNOS_TMU_GAIN_MASK <<
EXYNOS_TMU_GAIN_SHIFT); ??

>  	}
>  
>  	if (on) {
> -		con |= EXYNOS_TMU_CORE_ON;
> -		interrupt_en = pdata->trigger_level3_en << 12 |
> -			pdata->trigger_level2_en << 8 |
> -			pdata->trigger_level1_en << 4 |
> -			pdata->trigger_level0_en;
> +		con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
> +		interrupt_en =
> +		pdata->trigger_level3_en << EXYNOS_TMU_INTEN_RISE3_SHIFT |
> +		pdata->trigger_level2_en << EXYNOS_TMU_INTEN_RISE2_SHIFT |
> +		pdata->trigger_level1_en << EXYNOS_TMU_INTEN_RISE1_SHIFT |
> +		pdata->trigger_level0_en << EXYNOS_TMU_INTEN_RISE0_SHIFT;
>  		if (pdata->threshold_falling)
> -			interrupt_en |= interrupt_en << 16;
> +			interrupt_en |=
> +				interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
>  	} else {
> -		con |= EXYNOS_TMU_CORE_OFF;
> +		con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
>  		interrupt_en = 0; /* Disable all interrupts */
>  	}
>  	writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 06/21] thermal: exynos: Add missing definations and code cleanup
@ 2013-05-09 13:52     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 13:52 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 5353 bytes --]

Amit,

On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
> This patch adds some extra register bitfield definations and cleans
> up the code to prepare for moving register macros and definations inside
> the TMU data section.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/exynos_tmu.c |   62 +++++++++++++++++++++++++---------
>  1 files changed, 46 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index 05b5068..a43afc4 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -47,9 +47,12 @@
>  
>  #define EXYNOS_TMU_TRIM_TEMP_MASK	0xff
>  #define EXYNOS_TMU_GAIN_SHIFT		8
> +#define EXYNOS_TMU_GAIN_MASK		0xf
>  #define EXYNOS_TMU_REF_VOLTAGE_SHIFT	24
> -#define EXYNOS_TMU_CORE_ON		3
> -#define EXYNOS_TMU_CORE_OFF		2
> +#define EXYNOS_TMU_REF_VOLTAGE_MASK	0x1f
> +#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK	0xf
> +#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT	8
> +#define EXYNOS_TMU_CORE_EN_SHIFT	0
>  #define EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET	50
>  
>  /* Exynos4210 specific registers */
> @@ -67,6 +70,7 @@
>  #define EXYNOS4210_TMU_TRIG_LEVEL1_MASK	0x10
>  #define EXYNOS4210_TMU_TRIG_LEVEL2_MASK	0x100
>  #define EXYNOS4210_TMU_TRIG_LEVEL3_MASK	0x1000
> +#define EXYNOS4210_TMU_TRIG_LEVEL_MASK	0x1111
>  #define EXYNOS4210_TMU_INTCLEAR_VAL	0x1111
>  
>  /* Exynos5250 and Exynos4412 specific registers */
> @@ -76,17 +80,30 @@
>  #define EXYNOS_EMUL_CON		0x80
>  
>  #define EXYNOS_TRIMINFO_RELOAD		0x1
> +#define EXYNOS_TRIMINFO_SHIFT		0x0
> +#define EXYNOS_TMU_RISE_INT_MASK	0x111
> +#define EXYNOS_TMU_RISE_INT_SHIFT	0
> +#define EXYNOS_TMU_FALL_INT_MASK	0x111
> +#define EXYNOS_TMU_FALL_INT_SHIFT	12
>  #define EXYNOS_TMU_CLEAR_RISE_INT	0x111
>  #define EXYNOS_TMU_CLEAR_FALL_INT	(0x111 << 12)
> -#define EXYNOS_MUX_ADDR_VALUE		6
> -#define EXYNOS_MUX_ADDR_SHIFT		20
>  #define EXYNOS_TMU_TRIP_MODE_SHIFT	13
> +#define EXYNOS_TMU_TRIP_MODE_MASK	0x7
> +
> +#define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
> +#define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
> +#define EXYNOS_TMU_INTEN_RISE2_SHIFT	8
> +#define EXYNOS_TMU_INTEN_RISE3_SHIFT	12
> +#define EXYNOS_TMU_INTEN_FALL0_SHIFT	16
> +#define EXYNOS_TMU_INTEN_FALL1_SHIFT	20
> +#define EXYNOS_TMU_INTEN_FALL2_SHIFT	24
>  
>  #define EFUSE_MIN_VALUE 40
>  #define EFUSE_MAX_VALUE 100
>  
>  #ifdef CONFIG_THERMAL_EMULATION
>  #define EXYNOS_EMUL_TIME	0x57F0
> +#define EXYNOS_EMUL_TIME_MASK	0xffff
>  #define EXYNOS_EMUL_TIME_SHIFT	16
>  #define EXYNOS_EMUL_DATA_SHIFT	8
>  #define EXYNOS_EMUL_DATA_MASK	0xFF


What is the pattern above? Sometimes you use decimal notation sometimes
you use hex notation. On a quick look I could not see a pattern..

> @@ -265,24 +282,37 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	con = pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT |
> -		pdata->gain << EXYNOS_TMU_GAIN_SHIFT;
> +	con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
>  

You have a important change here. Before you would just apply a value
based on your local configuration. Now you are considering what is
present in your ctrl register. Is this really a code cleanup required
for moving the register definitions?

> -	if (data->soc == SOC_ARCH_EXYNOS) {
> -		con |= pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT;
> -		con |= (EXYNOS_MUX_ADDR_VALUE << EXYNOS_MUX_ADDR_SHIFT);
> +	if (pdata->reference_voltage) {
> +		con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK <<
> +				EXYNOS_TMU_REF_VOLTAGE_SHIFT);
> +		con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
> +	}
> +
> +	if (pdata->gain) {
> +		con &= ~(EXYNOS_TMU_GAIN_MASK << EXYNOS_TMU_GAIN_SHIFT);
> +		con |= (pdata->gain << EXYNOS_TMU_GAIN_SHIFT);
> +	}
> +
> +	if (pdata->noise_cancel_mode) {
> +		con &= ~(EXYNOS_TMU_TRIP_MODE_MASK <<
> +					EXYNOS_TMU_TRIP_MODE_SHIFT);
> +		con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);

For all the above ifs: Dont you want to clear those bits in case the
pdata config says those flags are not set? For instance, if pdata->gain
== 0, do you need to con &= ~(EXYNOS_TMU_GAIN_MASK <<
EXYNOS_TMU_GAIN_SHIFT); ??

>  	}
>  
>  	if (on) {
> -		con |= EXYNOS_TMU_CORE_ON;
> -		interrupt_en = pdata->trigger_level3_en << 12 |
> -			pdata->trigger_level2_en << 8 |
> -			pdata->trigger_level1_en << 4 |
> -			pdata->trigger_level0_en;
> +		con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
> +		interrupt_en =
> +		pdata->trigger_level3_en << EXYNOS_TMU_INTEN_RISE3_SHIFT |
> +		pdata->trigger_level2_en << EXYNOS_TMU_INTEN_RISE2_SHIFT |
> +		pdata->trigger_level1_en << EXYNOS_TMU_INTEN_RISE1_SHIFT |
> +		pdata->trigger_level0_en << EXYNOS_TMU_INTEN_RISE0_SHIFT;
>  		if (pdata->threshold_falling)
> -			interrupt_en |= interrupt_en << 16;
> +			interrupt_en |=
> +				interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
>  	} else {
> -		con |= EXYNOS_TMU_CORE_OFF;
> +		con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
>  		interrupt_en = 0; /* Disable all interrupts */
>  	}
>  	writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 09/21] thermal: exynos: Move register definitions from driver file to data file
  2013-05-07 13:00 ` [PATCH V3 09/21] thermal: exynos: Move register definitions from driver file to data file Amit Daniel Kachhap
@ 2013-05-09 14:32     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 14:32 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 22793 bytes --]

Hey Amit,

On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
> This patch migrates the TMU register definition/bitfields to data file. This
> is needed to support SoC's which use the same TMU controller but register
> validity, offsets or bitfield may slightly vary across SOC's.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/exynos_tmu.c      |  177 +++++++++-------------------
>  drivers/thermal/samsung/exynos_tmu.h      |   76 ++++++++++++
>  drivers/thermal/samsung/exynos_tmu_data.c |   59 ++++++++++
>  drivers/thermal/samsung/exynos_tmu_data.h |   68 +++++++++++
>  4 files changed, 260 insertions(+), 120 deletions(-)
> 
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index 23baeeb..97b87aa 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -36,77 +36,6 @@
>  #include "exynos_tmu.h"
>  #include "exynos_tmu_data.h"
>  
> -/* Exynos generic registers */
> -#define EXYNOS_TMU_REG_TRIMINFO		0x0
> -#define EXYNOS_TMU_REG_CONTROL		0x20
> -#define EXYNOS_TMU_REG_STATUS		0x28
> -#define EXYNOS_TMU_REG_CURRENT_TEMP	0x40
> -#define EXYNOS_TMU_REG_INTEN		0x70
> -#define EXYNOS_TMU_REG_INTSTAT		0x74
> -#define EXYNOS_TMU_REG_INTCLEAR		0x78
> -
> -#define EXYNOS_TMU_TRIM_TEMP_MASK	0xff
> -#define EXYNOS_TMU_GAIN_SHIFT		8
> -#define EXYNOS_TMU_GAIN_MASK		0xf
> -#define EXYNOS_TMU_REF_VOLTAGE_SHIFT	24
> -#define EXYNOS_TMU_REF_VOLTAGE_MASK	0x1f
> -#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK	0xf
> -#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT	8
> -#define EXYNOS_TMU_CORE_EN_SHIFT	0
> -
> -/* Exynos4210 specific registers */
> -#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP	0x44
> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL0	0x50
> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL1	0x54
> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL2	0x58
> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL3	0x5C
> -#define EXYNOS4210_TMU_REG_PAST_TEMP0	0x60
> -#define EXYNOS4210_TMU_REG_PAST_TEMP1	0x64
> -#define EXYNOS4210_TMU_REG_PAST_TEMP2	0x68
> -#define EXYNOS4210_TMU_REG_PAST_TEMP3	0x6C
> -
> -#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK	0x1
> -#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK	0x10
> -#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK	0x100
> -#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK	0x1000
> -#define EXYNOS4210_TMU_TRIG_LEVEL_MASK	0x1111
> -#define EXYNOS4210_TMU_INTCLEAR_VAL	0x1111
> -
> -/* Exynos5250 and Exynos4412 specific registers */
> -#define EXYNOS_TMU_TRIMINFO_CON	0x14
> -#define EXYNOS_THD_TEMP_RISE		0x50
> -#define EXYNOS_THD_TEMP_FALL		0x54
> -#define EXYNOS_EMUL_CON		0x80
> -
> -#define EXYNOS_TRIMINFO_RELOAD		0x1
> -#define EXYNOS_TRIMINFO_SHIFT		0x0
> -#define EXYNOS_TMU_RISE_INT_MASK	0x111
> -#define EXYNOS_TMU_RISE_INT_SHIFT	0
> -#define EXYNOS_TMU_FALL_INT_MASK	0x111
> -#define EXYNOS_TMU_FALL_INT_SHIFT	12
> -#define EXYNOS_TMU_CLEAR_RISE_INT	0x111
> -#define EXYNOS_TMU_CLEAR_FALL_INT	(0x111 << 12)
> -#define EXYNOS_TMU_TRIP_MODE_SHIFT	13
> -#define EXYNOS_TMU_TRIP_MODE_MASK	0x7
> -#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT	12
> -
> -#define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
> -#define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
> -#define EXYNOS_TMU_INTEN_RISE2_SHIFT	8
> -#define EXYNOS_TMU_INTEN_RISE3_SHIFT	12
> -#define EXYNOS_TMU_INTEN_FALL0_SHIFT	16
> -#define EXYNOS_TMU_INTEN_FALL1_SHIFT	20
> -#define EXYNOS_TMU_INTEN_FALL2_SHIFT	24
> -
> -#ifdef CONFIG_THERMAL_EMULATION
> -#define EXYNOS_EMUL_TIME	0x57F0
> -#define EXYNOS_EMUL_TIME_MASK	0xffff
> -#define EXYNOS_EMUL_TIME_SHIFT	16
> -#define EXYNOS_EMUL_DATA_SHIFT	8
> -#define EXYNOS_EMUL_DATA_MASK	0xFF
> -#define EXYNOS_EMUL_ENABLE	0x1
> -#endif /* CONFIG_THERMAL_EMULATION */
> -
>  struct exynos_tmu_data {
>  	struct exynos_tmu_platform_data *pdata;
>  	struct resource *mem;
> @@ -191,6 +120,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  {
>  	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
> +	struct exynos_tmu_registers *reg = pdata->registers;
>  	unsigned int status, trim_info, con;
>  	unsigned int rising_threshold = 0, falling_threshold = 0;
>  	int ret = 0, threshold_code, i, trigger_levs = 0;
> @@ -198,20 +128,20 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	status = readb(data->base + EXYNOS_TMU_REG_STATUS);
> +	status = readb(data->base + reg->tmu_status);
>  	if (!status) {
>  		ret = -EBUSY;
>  		goto out;
>  	}
>  
> -	if (data->soc == SOC_ARCH_EXYNOS) {
> -		__raw_writel(EXYNOS_TRIMINFO_RELOAD,
> -				data->base + EXYNOS_TMU_TRIMINFO_CON);
> -	}
> +	if (data->soc == SOC_ARCH_EXYNOS)
> +		__raw_writel(1, data->base + reg->triminfo_ctrl);
> +
>  	/* Save trimming info in order to perform calibration */
> -	trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
> -	data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
> -	data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
> +	trim_info = readl(data->base + reg->triminfo_data);
> +	data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
> +	data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
> +				EXYNOS_TMU_TEMP_MASK);

You changed from EXYNOS_TMU_TRIM_TEMP_MASK to EXYNOS_TMU_TEMP_MASK. Was
it this really what you wanted?

>  
>  	if ((pdata->min_efuse_value > data->temp_error1) ||
>  			(data->temp_error1 > pdata->max_efuse_value) ||
> @@ -231,13 +161,12 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  			goto out;
>  		}
>  		writeb(threshold_code,
> -			data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
> +			data->base + reg->threshold_temp);
>  		for (i = 0; i < trigger_levs; i++)
>  			writeb(pdata->trigger_levels[i],
> -			data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
> +			data->base + reg->threshold_th0 + i * 4);
>  

Is 4 your addressing unit? I believe there is a macro definition for this.

> -		writel(EXYNOS4210_TMU_INTCLEAR_VAL,
> -			data->base + EXYNOS_TMU_REG_INTCLEAR);
> +		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>  	} else if (data->soc == SOC_ARCH_EXYNOS) {
>  		/* Write temperature code for rising and falling threshold */
>  		for (i = 0; i < trigger_levs; i++) {
> @@ -258,18 +187,19 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  			}
>  			if (pdata->trigger_type[i] != HW_TRIP)
>  				continue;
> -			con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
> -			con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
> -			writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
> +			con = readl(data->base + reg->tmu_ctrl);
> +			con |= (1 << reg->therm_trip_en_shift);
> +			writel(con, data->base + reg->tmu_ctrl);
>  		}
>  
>  		writel(rising_threshold,
> -				data->base + EXYNOS_THD_TEMP_RISE);
> +				data->base + reg->threshold_th0);
>  		writel(falling_threshold,
> -				data->base + EXYNOS_THD_TEMP_FALL);
> +				data->base + reg->threshold_th1);
>  
> -		writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
> -				data->base + EXYNOS_TMU_REG_INTCLEAR);
> +		writel((reg->inten_rise_mask << reg->inten_rise_shift) |
> +			(reg->inten_fall_mask << reg->inten_fall_shift),
> +				data->base + reg->tmu_intclear);
>  	}
>  out:
>  	clk_disable(data->clk);
> @@ -282,46 +212,46 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>  {
>  	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
> +	struct exynos_tmu_registers *reg = pdata->registers;
>  	unsigned int con, interrupt_en;
>  
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
> +	con = readl(data->base + reg->tmu_ctrl);
>  
>  	if (pdata->reference_voltage) {
> -		con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK <<
> -				EXYNOS_TMU_REF_VOLTAGE_SHIFT);
> -		con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
> +		con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
> +		con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
>  	}
>  
>  	if (pdata->gain) {
> -		con &= ~(EXYNOS_TMU_GAIN_MASK << EXYNOS_TMU_GAIN_SHIFT);
> -		con |= (pdata->gain << EXYNOS_TMU_GAIN_SHIFT);
> +		con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
> +		con |= (pdata->gain << reg->buf_slope_sel_shift);
>  	}
>  
>  	if (pdata->noise_cancel_mode) {
> -		con &= ~(EXYNOS_TMU_TRIP_MODE_MASK <<
> -					EXYNOS_TMU_TRIP_MODE_SHIFT);
> -		con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
> +		con &= ~(reg->therm_trip_mode_mask <<
> +					reg->therm_trip_mode_shift);
> +		con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
>  	}
>  
>  	if (on) {
> -		con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
> +		con |= (1 << reg->core_en_shift);
>  		interrupt_en =
> -		pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT |
> -		pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT |
> -		pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT |
> -		pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT;
> +			pdata->trigger_enable[3] << reg->inten_rise3_shift |
> +			pdata->trigger_enable[2] << reg->inten_rise2_shift |
> +			pdata->trigger_enable[1] << reg->inten_rise1_shift |
> +			pdata->trigger_enable[0] << reg->inten_rise0_shift;
>  		if (pdata->threshold_falling)
>  			interrupt_en |=
> -				interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
> +				interrupt_en << reg->inten_fall0_shift;
>  	} else {
> -		con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
> +		con &= ~(1 << reg->core_en_shift);
>  		interrupt_en = 0; /* Disable all interrupts */
>  	}
> -	writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
> -	writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
> +	writel(interrupt_en, data->base + reg->tmu_inten);
> +	writel(con, data->base + reg->tmu_ctrl);
>  
>  	clk_disable(data->clk);
>  	mutex_unlock(&data->lock);
> @@ -329,13 +259,15 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>  
>  static int exynos_tmu_read(struct exynos_tmu_data *data)
>  {
> +	struct exynos_tmu_platform_data *pdata = data->pdata;
> +	struct exynos_tmu_registers *reg = pdata->registers;
>  	u8 temp_code;
>  	int temp;
>  
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
> +	temp_code = readb(data->base + reg->tmu_cur_temp);
>  	temp = code_to_temp(data, temp_code);
>  
>  	clk_disable(data->clk);
> @@ -348,7 +280,9 @@ static int exynos_tmu_read(struct exynos_tmu_data *data)
>  static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>  {
>  	struct exynos_tmu_data *data = drv_data;
> -	unsigned int reg;
> +	struct exynos_tmu_platform_data *pdata = data->pdata;
> +	struct exynos_tmu_registers *reg = pdata->registers;
> +	unsigned int val;
>  	int ret = -EINVAL;
>  
>  	if (data->soc == SOC_ARCH_EXYNOS4210)
> @@ -360,19 +294,19 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	reg = readl(data->base + EXYNOS_EMUL_CON);
> +	val = readl(data->base + reg->emul_con);
>  
>  	if (temp) {
>  		temp /= MCELSIUS;
>  
> -		reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
> +		val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
>  			(temp_to_code(data, temp)
> -			 << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
> +			 << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
>  	} else {
> -		reg &= ~EXYNOS_EMUL_ENABLE;
> +		val &= ~EXYNOS_EMUL_ENABLE;
>  	}
>  
> -	writel(reg, data->base + EXYNOS_EMUL_CON);
> +	writel(val, data->base + reg->emul_con);
>  
>  	clk_disable(data->clk);
>  	mutex_unlock(&data->lock);
> @@ -389,17 +323,20 @@ static void exynos_tmu_work(struct work_struct *work)
>  {
>  	struct exynos_tmu_data *data = container_of(work,
>  			struct exynos_tmu_data, irq_work);
> +	struct exynos_tmu_platform_data *pdata = data->pdata;
> +	struct exynos_tmu_registers *reg = pdata->registers;
>  
>  	exynos_report_trigger();
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
> +
>  	if (data->soc == SOC_ARCH_EXYNOS)
> -		writel(EXYNOS_TMU_CLEAR_RISE_INT |
> -				EXYNOS_TMU_CLEAR_FALL_INT,
> -				data->base + EXYNOS_TMU_REG_INTCLEAR);
> +		writel((reg->inten_rise_mask << reg->inten_rise_shift) |
> +			(reg->inten_fall_mask << reg->inten_fall_shift),
> +				data->base + reg->tmu_intclear);
>  	else
> -		writel(EXYNOS4210_TMU_INTCLEAR_VAL,
> -				data->base + EXYNOS_TMU_REG_INTCLEAR);
> +		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
> +
>  	clk_disable(data->clk);
>  	mutex_unlock(&data->lock);
>  
> diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
> index 70cc518..1e5e492 100644
> --- a/drivers/thermal/samsung/exynos_tmu.h
> +++ b/drivers/thermal/samsung/exynos_tmu.h
> @@ -46,6 +46,81 @@ enum soc_type {
>  };
>  
>  /**
> + * struct exynos_tmu_register - register descriptors to access registers and
> + * bitfields. The register validity, offsets and bitfield values may vary
> + * slightly across different exynos SOC's.

No documentation for your registers? Or at least where to find explanation?

> + */
> +struct exynos_tmu_registers {
> +	u32	triminfo_data;
> +	u32	triminfo_25_shift;
> +	u32	triminfo_85_shift;
> +
> +	u32	triminfo_ctrl;
> +	u32	triminfo_reload_shift;
> +
> +	u32	tmu_ctrl;
> +	u32	buf_vref_sel_shift;
> +	u32	buf_vref_sel_mask;
> +	u32	therm_trip_mode_shift;
> +	u32	therm_trip_mode_mask;
> +	u32	therm_trip_en_shift;
> +	u32	buf_slope_sel_shift;
> +	u32	buf_slope_sel_mask;
> +	u32	therm_trip_tq_en_shift;
> +	u32	core_en_shift;
> +
> +	u32	tmu_status;
> +
> +	u32	tmu_cur_temp;
> +	u32	tmu_cur_temp_shift;
> +
> +	u32	threshold_temp;
> +
> +	u32	threshold_th0;
> +	u32	threshold_th0_l0_shift;
> +	u32	threshold_th0_l1_shift;
> +	u32	threshold_th0_l2_shift;
> +	u32	threshold_th0_l3_shift;
> +
> +	u32	threshold_th1;
> +	u32	threshold_th1_l0_shift;
> +	u32	threshold_th1_l1_shift;
> +	u32	threshold_th1_l2_shift;
> +	u32	threshold_th1_l3_shift;
> +
> +	u32	threshold_th2;
> +	u32	threshold_th2_l0_shift;
> +
> +	u32	threshold_th3;
> +	u32	threshold_th3_l0_shift;
> +
> +	u32	tmu_inten;
> +	u32	inten_rise_shift;
> +	u32	inten_rise_mask;
> +	u32	inten_fall_shift;
> +	u32	inten_fall_mask;
> +	u32	inten_rise0_shift;
> +	u32	inten_rise1_shift;
> +	u32	inten_rise2_shift;
> +	u32	inten_rise3_shift;
> +	u32	inten_fall0_shift;
> +	u32	inten_fall1_shift;
> +	u32	inten_fall2_shift;
> +	u32	inten_fall3_shift;
> +
> +	u32	tmu_intstat;
> +
> +	u32	tmu_intclear;
> +
> +	u32	tmu_evten;
> +
> +	u32	emul_con;
> +	u32	emul_temp_shift;
> +	u32	emul_time_shift;
> +	u32	emul_time_mask;
> +};
> +
> +/**
>   * struct exynos_tmu_platform_data
>   * @threshold: basic temperature for generating interrupt
>   *	       25 <= threshold <= 125 [unit: degree Celsius]
> @@ -116,5 +191,6 @@ struct exynos_tmu_platform_data {
>  	enum soc_type type;
>  	struct freq_clip_table freq_tab[4];
>  	unsigned int freq_tab_count;
> +	struct exynos_tmu_registers *registers;
>  };
>  #endif /* _LINUX_EXYNOS_THERMAL_H */
> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
> index 6b937f5..3a1ded1 100644
> --- a/drivers/thermal/samsung/exynos_tmu_data.c
> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
> @@ -25,6 +25,28 @@
>  #include "exynos_tmu_data.h"
>  
>  #if defined(CONFIG_CPU_EXYNOS4210)
> +static struct exynos_tmu_registers exynos4210_tmu_registers = {
> +	.triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
> +	.triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
> +	.triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
> +	.tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
> +	.buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
> +	.buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
> +	.buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
> +	.buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
> +	.core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
> +	.tmu_status = EXYNOS_TMU_REG_STATUS,
> +	.tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
> +	.threshold_temp = EXYNOS4210_TMU_REG_THRESHOLD_TEMP,
> +	.threshold_th0 = EXYNOS4210_TMU_REG_TRIG_LEVEL0,
> +	.tmu_inten = EXYNOS_TMU_REG_INTEN,
> +	.inten_rise_mask = EXYNOS4210_TMU_TRIG_LEVEL_MASK,
> +	.inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
> +	.inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
> +	.inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
> +	.inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
> +	.tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
> +};
>  struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>  	.threshold = 80,
>  	.trigger_levels[0] = 5,
> @@ -55,10 +77,46 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>  	},
>  	.freq_tab_count = 2,
>  	.type = SOC_ARCH_EXYNOS4210,
> +	.registers = &exynos4210_tmu_registers,
>  };
>  #endif
>  
>  #if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
> +static struct exynos_tmu_registers exynos5250_tmu_registers = {
> +	.triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
> +	.triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
> +	.triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
> +	.triminfo_ctrl = EXYNOS_TMU_TRIMINFO_CON,
> +	.triminfo_reload_shift = EXYNOS_TRIMINFO_RELOAD_SHIFT,
> +	.tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
> +	.buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
> +	.buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
> +	.therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
> +	.therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
> +	.therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
> +	.buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
> +	.buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
> +	.core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
> +	.tmu_status = EXYNOS_TMU_REG_STATUS,
> +	.tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
> +	.threshold_th0 = EXYNOS_THD_TEMP_RISE,
> +	.threshold_th1 = EXYNOS_THD_TEMP_FALL,
> +	.tmu_inten = EXYNOS_TMU_REG_INTEN,
> +	.inten_rise_mask = EXYNOS_TMU_RISE_INT_MASK,
> +	.inten_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
> +	.inten_fall_mask = EXYNOS_TMU_FALL_INT_MASK,
> +	.inten_fall_shift = EXYNOS_TMU_FALL_INT_SHIFT,
> +	.inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
> +	.inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
> +	.inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
> +	.inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
> +	.inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
> +	.tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
> +	.emul_con = EXYNOS_EMUL_CON,
> +	.emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
> +	.emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
> +	.emul_time_mask = EXYNOS_EMUL_TIME_MASK,
> +};
>  struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>  	.threshold_falling = 10,
>  	.trigger_levels[0] = 85,
> @@ -93,5 +151,6 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>  	},
>  	.freq_tab_count = 2,
>  	.type = SOC_ARCH_EXYNOS,
> +	.registers = &exynos5250_tmu_registers,
>  };
>  #endif

One thing, I believe your data can be declared as const.

> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
> index 5b69711..0560413 100644
> --- a/drivers/thermal/samsung/exynos_tmu_data.h
> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
> @@ -23,6 +23,74 @@
>  #ifndef _LINUX_EXYNOS_TMU_DATA_H
>  #define _LINUX_EXYNOS_TMU_DATA_H
>  
> +/* Exynos generic registers */
> +#define EXYNOS_TMU_REG_TRIMINFO		0x0
> +#define EXYNOS_TMU_REG_CONTROL		0x20
> +#define EXYNOS_TMU_REG_STATUS		0x28
> +#define EXYNOS_TMU_REG_CURRENT_TEMP	0x40
> +#define EXYNOS_TMU_REG_INTEN		0x70
> +#define EXYNOS_TMU_REG_INTSTAT		0x74
> +#define EXYNOS_TMU_REG_INTCLEAR		0x78
> +
> +#define EXYNOS_TMU_TEMP_MASK		0xff
> +#define EXYNOS_TMU_REF_VOLTAGE_SHIFT	24
> +#define EXYNOS_TMU_REF_VOLTAGE_MASK	0x1f
> +#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK	0xf
> +#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT	8
> +#define EXYNOS_TMU_CORE_EN_SHIFT	0
> +
> +/* Exynos4210 specific registers */
> +#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP	0x44
> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL0	0x50
> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL1	0x54
> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL2	0x58
> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL3	0x5C
> +#define EXYNOS4210_TMU_REG_PAST_TEMP0	0x60
> +#define EXYNOS4210_TMU_REG_PAST_TEMP1	0x64
> +#define EXYNOS4210_TMU_REG_PAST_TEMP2	0x68
> +#define EXYNOS4210_TMU_REG_PAST_TEMP3	0x6C
> +
> +#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK	0x1
> +#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK	0x10
> +#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK	0x100
> +#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK	0x1000
> +#define EXYNOS4210_TMU_TRIG_LEVEL_MASK	0x1111
> +#define EXYNOS4210_TMU_INTCLEAR_VAL	0x1111
> +
> +/* Exynos5250 and Exynos4412 specific registers */
> +#define EXYNOS_TMU_TRIMINFO_CON	0x14
> +#define EXYNOS_THD_TEMP_RISE		0x50
> +#define EXYNOS_THD_TEMP_FALL		0x54
> +#define EXYNOS_EMUL_CON		0x80
> +
> +#define EXYNOS_TRIMINFO_RELOAD_SHIFT	1
> +#define EXYNOS_TRIMINFO_25_SHIFT	0
> +#define EXYNOS_TRIMINFO_85_SHIFT	8
> +#define EXYNOS_TMU_RISE_INT_MASK	0x111
> +#define EXYNOS_TMU_RISE_INT_SHIFT	0
> +#define EXYNOS_TMU_FALL_INT_MASK	0x111
> +#define EXYNOS_TMU_FALL_INT_SHIFT	12
> +#define EXYNOS_TMU_CLEAR_RISE_INT	0x111
> +#define EXYNOS_TMU_CLEAR_FALL_INT	(0x111 << 12)
> +#define EXYNOS_TMU_TRIP_MODE_SHIFT	13
> +#define EXYNOS_TMU_TRIP_MODE_MASK	0x7
> +#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT	12
> +
> +#define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
> +#define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
> +#define EXYNOS_TMU_INTEN_RISE2_SHIFT	8
> +#define EXYNOS_TMU_INTEN_RISE3_SHIFT	12
> +#define EXYNOS_TMU_INTEN_FALL0_SHIFT	16
> +#define EXYNOS_TMU_INTEN_FALL1_SHIFT	20
> +#define EXYNOS_TMU_INTEN_FALL2_SHIFT	24
> +
> +#define EXYNOS_EMUL_TIME	0x57F0
> +#define EXYNOS_EMUL_TIME_MASK	0xffff
> +#define EXYNOS_EMUL_TIME_SHIFT	16
> +#define EXYNOS_EMUL_DATA_SHIFT	8
> +#define EXYNOS_EMUL_DATA_MASK	0xFF
> +#define EXYNOS_EMUL_ENABLE	0x1
> +
>  #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>  extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
>  #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 09/21] thermal: exynos: Move register definitions from driver file to data file
@ 2013-05-09 14:32     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 14:32 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 22793 bytes --]

Hey Amit,

On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
> This patch migrates the TMU register definition/bitfields to data file. This
> is needed to support SoC's which use the same TMU controller but register
> validity, offsets or bitfield may slightly vary across SOC's.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/exynos_tmu.c      |  177 +++++++++-------------------
>  drivers/thermal/samsung/exynos_tmu.h      |   76 ++++++++++++
>  drivers/thermal/samsung/exynos_tmu_data.c |   59 ++++++++++
>  drivers/thermal/samsung/exynos_tmu_data.h |   68 +++++++++++
>  4 files changed, 260 insertions(+), 120 deletions(-)
> 
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index 23baeeb..97b87aa 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -36,77 +36,6 @@
>  #include "exynos_tmu.h"
>  #include "exynos_tmu_data.h"
>  
> -/* Exynos generic registers */
> -#define EXYNOS_TMU_REG_TRIMINFO		0x0
> -#define EXYNOS_TMU_REG_CONTROL		0x20
> -#define EXYNOS_TMU_REG_STATUS		0x28
> -#define EXYNOS_TMU_REG_CURRENT_TEMP	0x40
> -#define EXYNOS_TMU_REG_INTEN		0x70
> -#define EXYNOS_TMU_REG_INTSTAT		0x74
> -#define EXYNOS_TMU_REG_INTCLEAR		0x78
> -
> -#define EXYNOS_TMU_TRIM_TEMP_MASK	0xff
> -#define EXYNOS_TMU_GAIN_SHIFT		8
> -#define EXYNOS_TMU_GAIN_MASK		0xf
> -#define EXYNOS_TMU_REF_VOLTAGE_SHIFT	24
> -#define EXYNOS_TMU_REF_VOLTAGE_MASK	0x1f
> -#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK	0xf
> -#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT	8
> -#define EXYNOS_TMU_CORE_EN_SHIFT	0
> -
> -/* Exynos4210 specific registers */
> -#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP	0x44
> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL0	0x50
> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL1	0x54
> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL2	0x58
> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL3	0x5C
> -#define EXYNOS4210_TMU_REG_PAST_TEMP0	0x60
> -#define EXYNOS4210_TMU_REG_PAST_TEMP1	0x64
> -#define EXYNOS4210_TMU_REG_PAST_TEMP2	0x68
> -#define EXYNOS4210_TMU_REG_PAST_TEMP3	0x6C
> -
> -#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK	0x1
> -#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK	0x10
> -#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK	0x100
> -#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK	0x1000
> -#define EXYNOS4210_TMU_TRIG_LEVEL_MASK	0x1111
> -#define EXYNOS4210_TMU_INTCLEAR_VAL	0x1111
> -
> -/* Exynos5250 and Exynos4412 specific registers */
> -#define EXYNOS_TMU_TRIMINFO_CON	0x14
> -#define EXYNOS_THD_TEMP_RISE		0x50
> -#define EXYNOS_THD_TEMP_FALL		0x54
> -#define EXYNOS_EMUL_CON		0x80
> -
> -#define EXYNOS_TRIMINFO_RELOAD		0x1
> -#define EXYNOS_TRIMINFO_SHIFT		0x0
> -#define EXYNOS_TMU_RISE_INT_MASK	0x111
> -#define EXYNOS_TMU_RISE_INT_SHIFT	0
> -#define EXYNOS_TMU_FALL_INT_MASK	0x111
> -#define EXYNOS_TMU_FALL_INT_SHIFT	12
> -#define EXYNOS_TMU_CLEAR_RISE_INT	0x111
> -#define EXYNOS_TMU_CLEAR_FALL_INT	(0x111 << 12)
> -#define EXYNOS_TMU_TRIP_MODE_SHIFT	13
> -#define EXYNOS_TMU_TRIP_MODE_MASK	0x7
> -#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT	12
> -
> -#define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
> -#define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
> -#define EXYNOS_TMU_INTEN_RISE2_SHIFT	8
> -#define EXYNOS_TMU_INTEN_RISE3_SHIFT	12
> -#define EXYNOS_TMU_INTEN_FALL0_SHIFT	16
> -#define EXYNOS_TMU_INTEN_FALL1_SHIFT	20
> -#define EXYNOS_TMU_INTEN_FALL2_SHIFT	24
> -
> -#ifdef CONFIG_THERMAL_EMULATION
> -#define EXYNOS_EMUL_TIME	0x57F0
> -#define EXYNOS_EMUL_TIME_MASK	0xffff
> -#define EXYNOS_EMUL_TIME_SHIFT	16
> -#define EXYNOS_EMUL_DATA_SHIFT	8
> -#define EXYNOS_EMUL_DATA_MASK	0xFF
> -#define EXYNOS_EMUL_ENABLE	0x1
> -#endif /* CONFIG_THERMAL_EMULATION */
> -
>  struct exynos_tmu_data {
>  	struct exynos_tmu_platform_data *pdata;
>  	struct resource *mem;
> @@ -191,6 +120,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  {
>  	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
> +	struct exynos_tmu_registers *reg = pdata->registers;
>  	unsigned int status, trim_info, con;
>  	unsigned int rising_threshold = 0, falling_threshold = 0;
>  	int ret = 0, threshold_code, i, trigger_levs = 0;
> @@ -198,20 +128,20 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	status = readb(data->base + EXYNOS_TMU_REG_STATUS);
> +	status = readb(data->base + reg->tmu_status);
>  	if (!status) {
>  		ret = -EBUSY;
>  		goto out;
>  	}
>  
> -	if (data->soc == SOC_ARCH_EXYNOS) {
> -		__raw_writel(EXYNOS_TRIMINFO_RELOAD,
> -				data->base + EXYNOS_TMU_TRIMINFO_CON);
> -	}
> +	if (data->soc == SOC_ARCH_EXYNOS)
> +		__raw_writel(1, data->base + reg->triminfo_ctrl);
> +
>  	/* Save trimming info in order to perform calibration */
> -	trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
> -	data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
> -	data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
> +	trim_info = readl(data->base + reg->triminfo_data);
> +	data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
> +	data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
> +				EXYNOS_TMU_TEMP_MASK);

You changed from EXYNOS_TMU_TRIM_TEMP_MASK to EXYNOS_TMU_TEMP_MASK. Was
it this really what you wanted?

>  
>  	if ((pdata->min_efuse_value > data->temp_error1) ||
>  			(data->temp_error1 > pdata->max_efuse_value) ||
> @@ -231,13 +161,12 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  			goto out;
>  		}
>  		writeb(threshold_code,
> -			data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
> +			data->base + reg->threshold_temp);
>  		for (i = 0; i < trigger_levs; i++)
>  			writeb(pdata->trigger_levels[i],
> -			data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
> +			data->base + reg->threshold_th0 + i * 4);
>  

Is 4 your addressing unit? I believe there is a macro definition for this.

> -		writel(EXYNOS4210_TMU_INTCLEAR_VAL,
> -			data->base + EXYNOS_TMU_REG_INTCLEAR);
> +		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>  	} else if (data->soc == SOC_ARCH_EXYNOS) {
>  		/* Write temperature code for rising and falling threshold */
>  		for (i = 0; i < trigger_levs; i++) {
> @@ -258,18 +187,19 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  			}
>  			if (pdata->trigger_type[i] != HW_TRIP)
>  				continue;
> -			con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
> -			con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
> -			writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
> +			con = readl(data->base + reg->tmu_ctrl);
> +			con |= (1 << reg->therm_trip_en_shift);
> +			writel(con, data->base + reg->tmu_ctrl);
>  		}
>  
>  		writel(rising_threshold,
> -				data->base + EXYNOS_THD_TEMP_RISE);
> +				data->base + reg->threshold_th0);
>  		writel(falling_threshold,
> -				data->base + EXYNOS_THD_TEMP_FALL);
> +				data->base + reg->threshold_th1);
>  
> -		writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
> -				data->base + EXYNOS_TMU_REG_INTCLEAR);
> +		writel((reg->inten_rise_mask << reg->inten_rise_shift) |
> +			(reg->inten_fall_mask << reg->inten_fall_shift),
> +				data->base + reg->tmu_intclear);
>  	}
>  out:
>  	clk_disable(data->clk);
> @@ -282,46 +212,46 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>  {
>  	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
> +	struct exynos_tmu_registers *reg = pdata->registers;
>  	unsigned int con, interrupt_en;
>  
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
> +	con = readl(data->base + reg->tmu_ctrl);
>  
>  	if (pdata->reference_voltage) {
> -		con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK <<
> -				EXYNOS_TMU_REF_VOLTAGE_SHIFT);
> -		con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
> +		con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
> +		con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
>  	}
>  
>  	if (pdata->gain) {
> -		con &= ~(EXYNOS_TMU_GAIN_MASK << EXYNOS_TMU_GAIN_SHIFT);
> -		con |= (pdata->gain << EXYNOS_TMU_GAIN_SHIFT);
> +		con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
> +		con |= (pdata->gain << reg->buf_slope_sel_shift);
>  	}
>  
>  	if (pdata->noise_cancel_mode) {
> -		con &= ~(EXYNOS_TMU_TRIP_MODE_MASK <<
> -					EXYNOS_TMU_TRIP_MODE_SHIFT);
> -		con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
> +		con &= ~(reg->therm_trip_mode_mask <<
> +					reg->therm_trip_mode_shift);
> +		con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
>  	}
>  
>  	if (on) {
> -		con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
> +		con |= (1 << reg->core_en_shift);
>  		interrupt_en =
> -		pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT |
> -		pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT |
> -		pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT |
> -		pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT;
> +			pdata->trigger_enable[3] << reg->inten_rise3_shift |
> +			pdata->trigger_enable[2] << reg->inten_rise2_shift |
> +			pdata->trigger_enable[1] << reg->inten_rise1_shift |
> +			pdata->trigger_enable[0] << reg->inten_rise0_shift;
>  		if (pdata->threshold_falling)
>  			interrupt_en |=
> -				interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
> +				interrupt_en << reg->inten_fall0_shift;
>  	} else {
> -		con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
> +		con &= ~(1 << reg->core_en_shift);
>  		interrupt_en = 0; /* Disable all interrupts */
>  	}
> -	writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
> -	writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
> +	writel(interrupt_en, data->base + reg->tmu_inten);
> +	writel(con, data->base + reg->tmu_ctrl);
>  
>  	clk_disable(data->clk);
>  	mutex_unlock(&data->lock);
> @@ -329,13 +259,15 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>  
>  static int exynos_tmu_read(struct exynos_tmu_data *data)
>  {
> +	struct exynos_tmu_platform_data *pdata = data->pdata;
> +	struct exynos_tmu_registers *reg = pdata->registers;
>  	u8 temp_code;
>  	int temp;
>  
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
> +	temp_code = readb(data->base + reg->tmu_cur_temp);
>  	temp = code_to_temp(data, temp_code);
>  
>  	clk_disable(data->clk);
> @@ -348,7 +280,9 @@ static int exynos_tmu_read(struct exynos_tmu_data *data)
>  static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>  {
>  	struct exynos_tmu_data *data = drv_data;
> -	unsigned int reg;
> +	struct exynos_tmu_platform_data *pdata = data->pdata;
> +	struct exynos_tmu_registers *reg = pdata->registers;
> +	unsigned int val;
>  	int ret = -EINVAL;
>  
>  	if (data->soc == SOC_ARCH_EXYNOS4210)
> @@ -360,19 +294,19 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	reg = readl(data->base + EXYNOS_EMUL_CON);
> +	val = readl(data->base + reg->emul_con);
>  
>  	if (temp) {
>  		temp /= MCELSIUS;
>  
> -		reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
> +		val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
>  			(temp_to_code(data, temp)
> -			 << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
> +			 << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
>  	} else {
> -		reg &= ~EXYNOS_EMUL_ENABLE;
> +		val &= ~EXYNOS_EMUL_ENABLE;
>  	}
>  
> -	writel(reg, data->base + EXYNOS_EMUL_CON);
> +	writel(val, data->base + reg->emul_con);
>  
>  	clk_disable(data->clk);
>  	mutex_unlock(&data->lock);
> @@ -389,17 +323,20 @@ static void exynos_tmu_work(struct work_struct *work)
>  {
>  	struct exynos_tmu_data *data = container_of(work,
>  			struct exynos_tmu_data, irq_work);
> +	struct exynos_tmu_platform_data *pdata = data->pdata;
> +	struct exynos_tmu_registers *reg = pdata->registers;
>  
>  	exynos_report_trigger();
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
> +
>  	if (data->soc == SOC_ARCH_EXYNOS)
> -		writel(EXYNOS_TMU_CLEAR_RISE_INT |
> -				EXYNOS_TMU_CLEAR_FALL_INT,
> -				data->base + EXYNOS_TMU_REG_INTCLEAR);
> +		writel((reg->inten_rise_mask << reg->inten_rise_shift) |
> +			(reg->inten_fall_mask << reg->inten_fall_shift),
> +				data->base + reg->tmu_intclear);
>  	else
> -		writel(EXYNOS4210_TMU_INTCLEAR_VAL,
> -				data->base + EXYNOS_TMU_REG_INTCLEAR);
> +		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
> +
>  	clk_disable(data->clk);
>  	mutex_unlock(&data->lock);
>  
> diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
> index 70cc518..1e5e492 100644
> --- a/drivers/thermal/samsung/exynos_tmu.h
> +++ b/drivers/thermal/samsung/exynos_tmu.h
> @@ -46,6 +46,81 @@ enum soc_type {
>  };
>  
>  /**
> + * struct exynos_tmu_register - register descriptors to access registers and
> + * bitfields. The register validity, offsets and bitfield values may vary
> + * slightly across different exynos SOC's.

No documentation for your registers? Or at least where to find explanation?

> + */
> +struct exynos_tmu_registers {
> +	u32	triminfo_data;
> +	u32	triminfo_25_shift;
> +	u32	triminfo_85_shift;
> +
> +	u32	triminfo_ctrl;
> +	u32	triminfo_reload_shift;
> +
> +	u32	tmu_ctrl;
> +	u32	buf_vref_sel_shift;
> +	u32	buf_vref_sel_mask;
> +	u32	therm_trip_mode_shift;
> +	u32	therm_trip_mode_mask;
> +	u32	therm_trip_en_shift;
> +	u32	buf_slope_sel_shift;
> +	u32	buf_slope_sel_mask;
> +	u32	therm_trip_tq_en_shift;
> +	u32	core_en_shift;
> +
> +	u32	tmu_status;
> +
> +	u32	tmu_cur_temp;
> +	u32	tmu_cur_temp_shift;
> +
> +	u32	threshold_temp;
> +
> +	u32	threshold_th0;
> +	u32	threshold_th0_l0_shift;
> +	u32	threshold_th0_l1_shift;
> +	u32	threshold_th0_l2_shift;
> +	u32	threshold_th0_l3_shift;
> +
> +	u32	threshold_th1;
> +	u32	threshold_th1_l0_shift;
> +	u32	threshold_th1_l1_shift;
> +	u32	threshold_th1_l2_shift;
> +	u32	threshold_th1_l3_shift;
> +
> +	u32	threshold_th2;
> +	u32	threshold_th2_l0_shift;
> +
> +	u32	threshold_th3;
> +	u32	threshold_th3_l0_shift;
> +
> +	u32	tmu_inten;
> +	u32	inten_rise_shift;
> +	u32	inten_rise_mask;
> +	u32	inten_fall_shift;
> +	u32	inten_fall_mask;
> +	u32	inten_rise0_shift;
> +	u32	inten_rise1_shift;
> +	u32	inten_rise2_shift;
> +	u32	inten_rise3_shift;
> +	u32	inten_fall0_shift;
> +	u32	inten_fall1_shift;
> +	u32	inten_fall2_shift;
> +	u32	inten_fall3_shift;
> +
> +	u32	tmu_intstat;
> +
> +	u32	tmu_intclear;
> +
> +	u32	tmu_evten;
> +
> +	u32	emul_con;
> +	u32	emul_temp_shift;
> +	u32	emul_time_shift;
> +	u32	emul_time_mask;
> +};
> +
> +/**
>   * struct exynos_tmu_platform_data
>   * @threshold: basic temperature for generating interrupt
>   *	       25 <= threshold <= 125 [unit: degree Celsius]
> @@ -116,5 +191,6 @@ struct exynos_tmu_platform_data {
>  	enum soc_type type;
>  	struct freq_clip_table freq_tab[4];
>  	unsigned int freq_tab_count;
> +	struct exynos_tmu_registers *registers;
>  };
>  #endif /* _LINUX_EXYNOS_THERMAL_H */
> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
> index 6b937f5..3a1ded1 100644
> --- a/drivers/thermal/samsung/exynos_tmu_data.c
> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
> @@ -25,6 +25,28 @@
>  #include "exynos_tmu_data.h"
>  
>  #if defined(CONFIG_CPU_EXYNOS4210)
> +static struct exynos_tmu_registers exynos4210_tmu_registers = {
> +	.triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
> +	.triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
> +	.triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
> +	.tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
> +	.buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
> +	.buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
> +	.buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
> +	.buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
> +	.core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
> +	.tmu_status = EXYNOS_TMU_REG_STATUS,
> +	.tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
> +	.threshold_temp = EXYNOS4210_TMU_REG_THRESHOLD_TEMP,
> +	.threshold_th0 = EXYNOS4210_TMU_REG_TRIG_LEVEL0,
> +	.tmu_inten = EXYNOS_TMU_REG_INTEN,
> +	.inten_rise_mask = EXYNOS4210_TMU_TRIG_LEVEL_MASK,
> +	.inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
> +	.inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
> +	.inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
> +	.inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
> +	.tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
> +};
>  struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>  	.threshold = 80,
>  	.trigger_levels[0] = 5,
> @@ -55,10 +77,46 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>  	},
>  	.freq_tab_count = 2,
>  	.type = SOC_ARCH_EXYNOS4210,
> +	.registers = &exynos4210_tmu_registers,
>  };
>  #endif
>  
>  #if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
> +static struct exynos_tmu_registers exynos5250_tmu_registers = {
> +	.triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
> +	.triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
> +	.triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
> +	.triminfo_ctrl = EXYNOS_TMU_TRIMINFO_CON,
> +	.triminfo_reload_shift = EXYNOS_TRIMINFO_RELOAD_SHIFT,
> +	.tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
> +	.buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
> +	.buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
> +	.therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
> +	.therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
> +	.therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
> +	.buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
> +	.buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
> +	.core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
> +	.tmu_status = EXYNOS_TMU_REG_STATUS,
> +	.tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
> +	.threshold_th0 = EXYNOS_THD_TEMP_RISE,
> +	.threshold_th1 = EXYNOS_THD_TEMP_FALL,
> +	.tmu_inten = EXYNOS_TMU_REG_INTEN,
> +	.inten_rise_mask = EXYNOS_TMU_RISE_INT_MASK,
> +	.inten_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
> +	.inten_fall_mask = EXYNOS_TMU_FALL_INT_MASK,
> +	.inten_fall_shift = EXYNOS_TMU_FALL_INT_SHIFT,
> +	.inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
> +	.inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
> +	.inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
> +	.inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
> +	.inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
> +	.tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
> +	.emul_con = EXYNOS_EMUL_CON,
> +	.emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
> +	.emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
> +	.emul_time_mask = EXYNOS_EMUL_TIME_MASK,
> +};
>  struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>  	.threshold_falling = 10,
>  	.trigger_levels[0] = 85,
> @@ -93,5 +151,6 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>  	},
>  	.freq_tab_count = 2,
>  	.type = SOC_ARCH_EXYNOS,
> +	.registers = &exynos5250_tmu_registers,
>  };
>  #endif

One thing, I believe your data can be declared as const.

> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
> index 5b69711..0560413 100644
> --- a/drivers/thermal/samsung/exynos_tmu_data.h
> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
> @@ -23,6 +23,74 @@
>  #ifndef _LINUX_EXYNOS_TMU_DATA_H
>  #define _LINUX_EXYNOS_TMU_DATA_H
>  
> +/* Exynos generic registers */
> +#define EXYNOS_TMU_REG_TRIMINFO		0x0
> +#define EXYNOS_TMU_REG_CONTROL		0x20
> +#define EXYNOS_TMU_REG_STATUS		0x28
> +#define EXYNOS_TMU_REG_CURRENT_TEMP	0x40
> +#define EXYNOS_TMU_REG_INTEN		0x70
> +#define EXYNOS_TMU_REG_INTSTAT		0x74
> +#define EXYNOS_TMU_REG_INTCLEAR		0x78
> +
> +#define EXYNOS_TMU_TEMP_MASK		0xff
> +#define EXYNOS_TMU_REF_VOLTAGE_SHIFT	24
> +#define EXYNOS_TMU_REF_VOLTAGE_MASK	0x1f
> +#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK	0xf
> +#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT	8
> +#define EXYNOS_TMU_CORE_EN_SHIFT	0
> +
> +/* Exynos4210 specific registers */
> +#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP	0x44
> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL0	0x50
> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL1	0x54
> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL2	0x58
> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL3	0x5C
> +#define EXYNOS4210_TMU_REG_PAST_TEMP0	0x60
> +#define EXYNOS4210_TMU_REG_PAST_TEMP1	0x64
> +#define EXYNOS4210_TMU_REG_PAST_TEMP2	0x68
> +#define EXYNOS4210_TMU_REG_PAST_TEMP3	0x6C
> +
> +#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK	0x1
> +#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK	0x10
> +#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK	0x100
> +#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK	0x1000
> +#define EXYNOS4210_TMU_TRIG_LEVEL_MASK	0x1111
> +#define EXYNOS4210_TMU_INTCLEAR_VAL	0x1111
> +
> +/* Exynos5250 and Exynos4412 specific registers */
> +#define EXYNOS_TMU_TRIMINFO_CON	0x14
> +#define EXYNOS_THD_TEMP_RISE		0x50
> +#define EXYNOS_THD_TEMP_FALL		0x54
> +#define EXYNOS_EMUL_CON		0x80
> +
> +#define EXYNOS_TRIMINFO_RELOAD_SHIFT	1
> +#define EXYNOS_TRIMINFO_25_SHIFT	0
> +#define EXYNOS_TRIMINFO_85_SHIFT	8
> +#define EXYNOS_TMU_RISE_INT_MASK	0x111
> +#define EXYNOS_TMU_RISE_INT_SHIFT	0
> +#define EXYNOS_TMU_FALL_INT_MASK	0x111
> +#define EXYNOS_TMU_FALL_INT_SHIFT	12
> +#define EXYNOS_TMU_CLEAR_RISE_INT	0x111
> +#define EXYNOS_TMU_CLEAR_FALL_INT	(0x111 << 12)
> +#define EXYNOS_TMU_TRIP_MODE_SHIFT	13
> +#define EXYNOS_TMU_TRIP_MODE_MASK	0x7
> +#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT	12
> +
> +#define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
> +#define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
> +#define EXYNOS_TMU_INTEN_RISE2_SHIFT	8
> +#define EXYNOS_TMU_INTEN_RISE3_SHIFT	12
> +#define EXYNOS_TMU_INTEN_FALL0_SHIFT	16
> +#define EXYNOS_TMU_INTEN_FALL1_SHIFT	20
> +#define EXYNOS_TMU_INTEN_FALL2_SHIFT	24
> +
> +#define EXYNOS_EMUL_TIME	0x57F0
> +#define EXYNOS_EMUL_TIME_MASK	0xffff
> +#define EXYNOS_EMUL_TIME_SHIFT	16
> +#define EXYNOS_EMUL_DATA_SHIFT	8
> +#define EXYNOS_EMUL_DATA_MASK	0xFF
> +#define EXYNOS_EMUL_ENABLE	0x1
> +
>  #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>  extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
>  #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 10/21] thermal: exynos: Fix to clear only the generated interrupts
  2013-05-07 13:01 ` [PATCH V3 10/21] thermal: exynos: Fix to clear only the generated interrupts Amit Daniel Kachhap
@ 2013-05-09 14:33     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 14:33 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 2720 bytes --]

On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
> This patch uses the TMU status register to know the generated interrupts
> and only clear them in the interrupt handler.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/exynos_tmu.c      |   10 ++++------
>  drivers/thermal/samsung/exynos_tmu_data.c |    2 ++
>  2 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index 97b87aa..082d5a2 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -325,17 +325,15 @@ static void exynos_tmu_work(struct work_struct *work)
>  			struct exynos_tmu_data, irq_work);
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	struct exynos_tmu_registers *reg = pdata->registers;
> +	unsigned int val_irq;
>  
>  	exynos_report_trigger();
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	if (data->soc == SOC_ARCH_EXYNOS)
> -		writel((reg->inten_rise_mask << reg->inten_rise_shift) |
> -			(reg->inten_fall_mask << reg->inten_fall_shift),
> -				data->base + reg->tmu_intclear);
> -	else
> -		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
> +	val_irq = readl(data->base + reg->tmu_intstat);
> +	/* clear the interrupts */
> +	writel(val_irq, data->base + reg->tmu_intclear);
>  

hmmm.. Don t you need to act accordingly depending on what is in your
int status?

>  	clk_disable(data->clk);
>  	mutex_unlock(&data->lock);
> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
> index 3a1ded1..7322597 100644
> --- a/drivers/thermal/samsung/exynos_tmu_data.c
> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
> @@ -45,6 +45,7 @@ static struct exynos_tmu_registers exynos4210_tmu_registers = {
>  	.inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>  	.inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>  	.inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
> +	.tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
>  	.tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>  };
>  struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
> @@ -111,6 +112,7 @@ static struct exynos_tmu_registers exynos5250_tmu_registers = {
>  	.inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>  	.inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>  	.inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
> +	.tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
>  	.tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>  	.emul_con = EXYNOS_EMUL_CON,
>  	.emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 10/21] thermal: exynos: Fix to clear only the generated interrupts
@ 2013-05-09 14:33     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 14:33 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 2720 bytes --]

On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
> This patch uses the TMU status register to know the generated interrupts
> and only clear them in the interrupt handler.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/exynos_tmu.c      |   10 ++++------
>  drivers/thermal/samsung/exynos_tmu_data.c |    2 ++
>  2 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index 97b87aa..082d5a2 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -325,17 +325,15 @@ static void exynos_tmu_work(struct work_struct *work)
>  			struct exynos_tmu_data, irq_work);
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	struct exynos_tmu_registers *reg = pdata->registers;
> +	unsigned int val_irq;
>  
>  	exynos_report_trigger();
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	if (data->soc == SOC_ARCH_EXYNOS)
> -		writel((reg->inten_rise_mask << reg->inten_rise_shift) |
> -			(reg->inten_fall_mask << reg->inten_fall_shift),
> -				data->base + reg->tmu_intclear);
> -	else
> -		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
> +	val_irq = readl(data->base + reg->tmu_intstat);
> +	/* clear the interrupts */
> +	writel(val_irq, data->base + reg->tmu_intclear);
>  

hmmm.. Don t you need to act accordingly depending on what is in your
int status?

>  	clk_disable(data->clk);
>  	mutex_unlock(&data->lock);
> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
> index 3a1ded1..7322597 100644
> --- a/drivers/thermal/samsung/exynos_tmu_data.c
> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
> @@ -45,6 +45,7 @@ static struct exynos_tmu_registers exynos4210_tmu_registers = {
>  	.inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>  	.inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>  	.inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
> +	.tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
>  	.tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>  };
>  struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
> @@ -111,6 +112,7 @@ static struct exynos_tmu_registers exynos5250_tmu_registers = {
>  	.inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>  	.inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>  	.inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
> +	.tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
>  	.tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>  	.emul_con = EXYNOS_EMUL_CON,
>  	.emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 20/21] thermal: exynos: Support for TMU regulator defined at device tree
  2013-05-07 13:01 ` [PATCH V3 20/21] thermal: exynos: Support for TMU regulator defined at device tree Amit Daniel Kachhap
@ 2013-05-09 14:44     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 14:44 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 3944 bytes --]

On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
> TMU probe function now checks for a device tree defined regulator.
> For compatibility reasons it is allowed to probe driver even without
> this regulator defined.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  .../devicetree/bindings/thermal/exynos-thermal.txt |    4 ++++
>  drivers/thermal/samsung/exynos_tmu.c               |   19 +++++++++++++++++++
>  2 files changed, 23 insertions(+), 0 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
> index 970eeba..ff62f7a 100644
> --- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
> +++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
> @@ -14,6 +14,9 @@
>  - interrupts : Should contain interrupt for thermal system
>  - clocks : The main clock for TMU device
>  - clock-names : Thermal system clock name
> +- vtmu-supply: This entry is optional and provides the regulator node supplying
> +		voltage to TMU. If needed this entry can be placed inside
> +		board/platform specific dts file.
>  
>  Example 1):
>  
> @@ -25,6 +28,7 @@ Example 1):
>  		clocks = <&clock 383>;
>  		clock-names = "tmu_apbif";
>  		status = "disabled";
> +		vtmu-supply = <&tmu_regulator_node>;
>  	};
>  
>  Example 2):
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index 72446c9..b7c609a 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -32,6 +32,7 @@
>  #include <linux/of_address.h>
>  #include <linux/of_irq.h>
>  #include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
>  #include <linux/slab.h>
>  #include <linux/workqueue.h>
>  #include "exynos_thermal_common.h"
> @@ -52,6 +53,7 @@
>   * @clk: pointer to the clock structure.
>   * @temp_error1: fused value of the first point trim.
>   * @temp_error2: fused value of the second point trim.
> + * @regulator: pointer to the TMU regulator structure.
>   * @reg_conf: pointer to structure to register with core thermal.
>   */
>  struct exynos_tmu_data {
> @@ -65,6 +67,7 @@ struct exynos_tmu_data {
>  	struct mutex lock;
>  	struct clk *clk;
>  	u8 temp_error1, temp_error2;
> +	struct regulator *regulator;
>  	struct thermal_sensor_conf *reg_conf;
>  };
>  
> @@ -501,10 +504,23 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>  	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	struct resource res;
> +	int ret;
>  
>  	if (!data)
>  		return -ENODEV;
>  
> +	/* Try enabling the regulator if found */
> +	data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
> +	if (!IS_ERR(data->regulator)) {
> +		ret = regulator_enable(data->regulator);
> +		if (ret) {
> +			dev_err(&pdev->dev, "failed to enable vtmu\n");
> +			return ret;
> +		}
> +	} else {
> +		dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");

Now that you have a bitfield for your features, shouldnt this become a
check? If the SoC requires the regulator, then it has to return a valid
regulator (regulator_get). Meaning, if your SoC version requires this
feature and the regulator_get returns an error, you must treat as an
error an not continue gracefuly.

> +	}
> +
>  	data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
>  	if (data->id < 0)
>  		data->id = 0;
> @@ -669,6 +685,9 @@ static int exynos_tmu_remove(struct platform_device *pdev)
>  
>  	clk_unprepare(data->clk);
>  
> +	if (!IS_ERR(data->regulator))
> +		regulator_disable(data->regulator);
> +
>  	platform_set_drvdata(pdev, NULL);
>  
>  	return 0;
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 20/21] thermal: exynos: Support for TMU regulator defined at device tree
@ 2013-05-09 14:44     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 14:44 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 3944 bytes --]

On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
> TMU probe function now checks for a device tree defined regulator.
> For compatibility reasons it is allowed to probe driver even without
> this regulator defined.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  .../devicetree/bindings/thermal/exynos-thermal.txt |    4 ++++
>  drivers/thermal/samsung/exynos_tmu.c               |   19 +++++++++++++++++++
>  2 files changed, 23 insertions(+), 0 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
> index 970eeba..ff62f7a 100644
> --- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
> +++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
> @@ -14,6 +14,9 @@
>  - interrupts : Should contain interrupt for thermal system
>  - clocks : The main clock for TMU device
>  - clock-names : Thermal system clock name
> +- vtmu-supply: This entry is optional and provides the regulator node supplying
> +		voltage to TMU. If needed this entry can be placed inside
> +		board/platform specific dts file.
>  
>  Example 1):
>  
> @@ -25,6 +28,7 @@ Example 1):
>  		clocks = <&clock 383>;
>  		clock-names = "tmu_apbif";
>  		status = "disabled";
> +		vtmu-supply = <&tmu_regulator_node>;
>  	};
>  
>  Example 2):
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index 72446c9..b7c609a 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -32,6 +32,7 @@
>  #include <linux/of_address.h>
>  #include <linux/of_irq.h>
>  #include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
>  #include <linux/slab.h>
>  #include <linux/workqueue.h>
>  #include "exynos_thermal_common.h"
> @@ -52,6 +53,7 @@
>   * @clk: pointer to the clock structure.
>   * @temp_error1: fused value of the first point trim.
>   * @temp_error2: fused value of the second point trim.
> + * @regulator: pointer to the TMU regulator structure.
>   * @reg_conf: pointer to structure to register with core thermal.
>   */
>  struct exynos_tmu_data {
> @@ -65,6 +67,7 @@ struct exynos_tmu_data {
>  	struct mutex lock;
>  	struct clk *clk;
>  	u8 temp_error1, temp_error2;
> +	struct regulator *regulator;
>  	struct thermal_sensor_conf *reg_conf;
>  };
>  
> @@ -501,10 +504,23 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>  	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	struct resource res;
> +	int ret;
>  
>  	if (!data)
>  		return -ENODEV;
>  
> +	/* Try enabling the regulator if found */
> +	data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
> +	if (!IS_ERR(data->regulator)) {
> +		ret = regulator_enable(data->regulator);
> +		if (ret) {
> +			dev_err(&pdev->dev, "failed to enable vtmu\n");
> +			return ret;
> +		}
> +	} else {
> +		dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");

Now that you have a bitfield for your features, shouldnt this become a
check? If the SoC requires the regulator, then it has to return a valid
regulator (regulator_get). Meaning, if your SoC version requires this
feature and the regulator_get returns an error, you must treat as an
error an not continue gracefuly.

> +	}
> +
>  	data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
>  	if (data->id < 0)
>  		data->id = 0;
> @@ -669,6 +685,9 @@ static int exynos_tmu_remove(struct platform_device *pdev)
>  
>  	clk_unprepare(data->clk);
>  
> +	if (!IS_ERR(data->regulator))
> +		regulator_disable(data->regulator);
> +
>  	platform_set_drvdata(pdev, NULL);
>  
>  	return 0;
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 18/21] thermal: exynos: Add support for exynos5440 TMU sensor.
  2013-05-07 13:01 ` [PATCH V3 18/21] thermal: exynos: Add support for exynos5440 TMU sensor Amit Daniel Kachhap
@ 2013-05-09 14:47     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 14:47 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 21820 bytes --]

Hey Amit,

On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
> This patch modifies TMU controller to add changes needed to work with
> exynos5440 platform. Also register definitions and required configuration data
> are added. This sensor registers 3 instance of the tmu controller with the
> thermal zone and hence reports 3 temperature output. This controller supports
> upto five trip points. For critical threshold the driver uses the core driver
> thermal framework for shutdown.
> 

I would kindly request you to split this patch. Looks like you add
altogether in one patch both data, driver adaptation (for your new soc)
and on top, new features. I would suggest splitting this things in
smaller steps. Easier to review, track, bitsec and find bugs (if any).

> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  .../devicetree/bindings/thermal/exynos-thermal.txt |   28 ++++-
>  drivers/thermal/samsung/Kconfig                    |    4 +-
>  drivers/thermal/samsung/exynos_thermal_common.c    |    2 +-
>  drivers/thermal/samsung/exynos_tmu.c               |  139 +++++++++++++++++---
>  drivers/thermal/samsung/exynos_tmu.h               |    7 +
>  drivers/thermal/samsung/exynos_tmu_data.c          |   66 +++++++++-
>  drivers/thermal/samsung/exynos_tmu_data.h          |   40 ++++++
>  7 files changed, 261 insertions(+), 25 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
> index 535fd0e..970eeba 100644
> --- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
> +++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
> @@ -6,13 +6,16 @@
>  	       "samsung,exynos4412-tmu"
>  	       "samsung,exynos4210-tmu"
>  	       "samsung,exynos5250-tmu"
> +	       "samsung,exynos5440-tmu"
>  - interrupt-parent : The phandle for the interrupt controller
> -- reg : Address range of the thermal registers
> +- reg : Address range of the thermal registers. For exynos5440-tmu which has 3
> +	instances of TMU, 2 set of register has to supplied. First set belongs
> +	to each instance of TMU and second set belongs to common TMU registers.
>  - interrupts : Should contain interrupt for thermal system
>  - clocks : The main clock for TMU device
>  - clock-names : Thermal system clock name
>  
> -Example:
> +Example 1):
>  
>  	tmu@100C0000 {
>  		compatible = "samsung,exynos4412-tmu";
> @@ -23,3 +26,24 @@ Example:
>  		clock-names = "tmu_apbif";
>  		status = "disabled";
>  	};
> +
> +Example 2):
> +
> +	tmuctrl_0: tmuctrl@160118 {
> +		compatible = "samsung,exynos5440-tmu";
> +		reg = <0x160118 0x230>, <0x160368 0x10>;
> +		interrupts = <0 58 0>;
> +		clocks = <&clock 21>;
> +		clock-names = "tmu_apbif";
> +	};
> +
> +Note: For multi-instance tmu each instance should have an alias correctly
> +numbered in "aliases" node.
> +
> +Example:
> +
> +aliases {
> +	tmuctrl0 = &tmuctrl_0;
> +	tmuctrl1 = &tmuctrl_1;
> +	tmuctrl2 = &tmuctrl_2;
> +};
> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
> index f23f533..fce04f3 100644
> --- a/drivers/thermal/samsung/Kconfig
> +++ b/drivers/thermal/samsung/Kconfig
> @@ -19,10 +19,10 @@ config EXYNOS_THERMAL_CORE
>  
>  config EXYNOS_THERMAL_DATA
>  	bool "Temperature sensor congiguration data for EXYNOS series SOC"
> -	depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250)
> +	depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250 || SOC_EXYNOS5440)
>  	depends on EXYNOS_THERMAL
>  	help
>  	  If you say yes here you can enable TMU (Thermal Management Unit) on
> -	  SAMSUNG EXYNOS 4210, 4412, 4414 and 5250 series of SoC. This option
> +	  SAMSUNG EXYNOS 4210, 4412, 4414, 5250 and 5440 series of SoC. This option
>  	  enables/prepares the configuration, trip and cooling data for the TMU
>  	  driver.
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
> index b0dc63e..de43e18 100644
> --- a/drivers/thermal/samsung/exynos_thermal_common.c
> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
> @@ -370,7 +370,7 @@ int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
>  	th_zone->mode = THERMAL_DEVICE_ENABLED;
>  	sensor_conf->pzone_data = th_zone;
>  
> -	pr_info("Exynos: Kernel Thermal management registered\n");
> +	pr_info("Exynos: Thermal zone(%s) registered\n", sensor_conf->name);
>  
>  	return 0;
>  
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index c1a8c5f..72446c9 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -44,6 +44,7 @@
>   * @id: identifier of the one instance of the TMU controller.
>   * @pdata: pointer to the tmu platform/configuration data
>   * @base: base address of the single instance of the TMU controller.
> + * @base_common: base address of the common registers of the TMU controller.
>   * @irq: irq number of the TMU controller.
>   * @soc: id of the SOC type.
>   * @irq_work: pointer to the irq work structure.
> @@ -57,6 +58,7 @@ struct exynos_tmu_data {
>  	int id;
>  	struct exynos_tmu_platform_data *pdata;
>  	void __iomem *base;
> +	void __iomem *base_common;
>  	int irq;
>  	enum soc_type soc;
>  	struct work_struct irq_work;
> @@ -75,6 +77,9 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	int temp_code;
>  
> +	if (pdata->cal_mode == HW_MODE)
> +		return temp;
> +
>  	if (data->soc == SOC_ARCH_EXYNOS4210)
>  		/* temp should range between 25 and 125 */
>  		if (temp < 25 || temp > 125) {
> @@ -109,6 +114,9 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	int temp;
>  
> +	if (pdata->cal_mode == HW_MODE)
> +		return temp_code;
> +
>  	if (data->soc == SOC_ARCH_EXYNOS4210)
>  		/* temp_code should range between 75 and 175 */
>  		if (temp_code < 75 || temp_code > 175) {
> @@ -139,33 +147,63 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	struct exynos_tmu_registers *reg = pdata->registers;
> -	unsigned int status, trim_info, con;
> +	unsigned int status, trim_info = 0, con;
>  	unsigned int rising_threshold = 0, falling_threshold = 0;
>  	int ret = 0, threshold_code, i, trigger_levs = 0;
>  
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	status = readb(data->base + reg->tmu_status);
> -	if (!status) {
> -		ret = -EBUSY;
> -		goto out;
> +	if (TMU_SUPPORTS(pdata, READY_STATUS)) {
> +		status = readb(data->base + reg->tmu_status);
> +		if (!status) {
> +			ret = -EBUSY;
> +			goto out;
> +		}
>  	}
>  
>  	if (TMU_SUPPORTS(pdata, TRIM_RELOAD))
>  		__raw_writel(1, data->base + reg->triminfo_ctrl);
>  
> +	if (pdata->cal_mode == HW_MODE)
> +		goto skip_calib_data;
> +
>  	/* Save trimming info in order to perform calibration */
> -	trim_info = readl(data->base + reg->triminfo_data);
> +	if (data->soc == SOC_ARCH_EXYNOS5440) {
> +		/*
> +		 * For exynos5440 soc triminfo value is swapped between TMU0 and
> +		 * TMU2, so the below logic is needed.
> +		 */
> +		switch (data->id) {
> +		case 0:
> +			trim_info = readl(data->base +
> +			EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
> +			break;
> +		case 1:
> +			trim_info = readl(data->base + reg->triminfo_data);
> +			break;
> +		case 2:
> +			trim_info = readl(data->base -
> +			EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
> +		}
> +	} else {
> +		trim_info = readl(data->base + reg->triminfo_data);
> +	}
>  	data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
>  	data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
>  				EXYNOS_TMU_TEMP_MASK);
>  
> -	if ((pdata->min_efuse_value > data->temp_error1) ||
> -			(data->temp_error1 > pdata->max_efuse_value) ||
> -			(data->temp_error2 != 0))
> -		data->temp_error1 = pdata->efuse_value;
> +	if (!data->temp_error1 ||
> +		(pdata->min_efuse_value > data->temp_error1) ||
> +		(data->temp_error1 > pdata->max_efuse_value))
> +		data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
> +
> +	if (!data->temp_error2)
> +		data->temp_error2 =
> +			(pdata->efuse_value >> reg->triminfo_85_shift) &
> +			EXYNOS_TMU_TEMP_MASK;
>  
> +skip_calib_data:
>  	/* Count trigger levels to be enabled */
>  	for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
>  		if (pdata->trigger_levels[i])
> @@ -185,9 +223,10 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  			data->base + reg->threshold_th0 + i * 4);
>  
>  		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
> -	} else if (data->soc == SOC_ARCH_EXYNOS) {
> +	} else if (data->soc == SOC_ARCH_EXYNOS ||
> +			data->soc == SOC_ARCH_EXYNOS5440) {
>  		/* Write temperature code for rising and falling threshold */
> -		for (i = 0; i < trigger_levs; i++) {
> +		for (i = 0; i < trigger_levs && i < 4 ; i++) {
>  			threshold_code = temp_to_code(data,
>  						pdata->trigger_levels[i]);
>  			if (threshold_code < 0) {
> @@ -218,7 +257,29 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  		writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>  			(reg->inten_fall_mask << reg->inten_fall_shift),
>  				data->base + reg->tmu_intclear);
> +
> +		/* if 5th threshold limit is also present, use TH2 register */
> +		i = 4;
> +		if (pdata->trigger_levels[i]) {
> +			threshold_code = temp_to_code(data,
> +						pdata->trigger_levels[i]);
> +			if (threshold_code < 0) {
> +				ret = threshold_code;
> +				goto out;
> +			}
> +			rising_threshold = threshold_code << 24;
> +			writel(rising_threshold,
> +				data->base + reg->threshold_th2);
> +			if (pdata->trigger_type[i] == HW_TRIP) {
> +				con = readl(data->base + reg->tmu_ctrl);
> +				con |= (1 << reg->therm_trip_en_shift);
> +				writel(con, data->base + reg->tmu_ctrl);
> +			}
> +		}
>  	}
> +	/*Clear the PMIN in the common TMU register*/
> +	if (reg->tmu_pmin && !data->id)
> +		writel(0, data->base_common + reg->tmu_pmin);
>  out:
>  	clk_disable(data->clk);
>  	mutex_unlock(&data->lock);
> @@ -254,6 +315,11 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>  		con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
>  	}
>  
> +	if (pdata->cal_mode == HW_MODE) {
> +		con &= ~(reg->calib_mode_mask << reg->calib_mode_shift);
> +		con |= pdata->cal_type << reg->calib_mode_shift;
> +	}
> +
>  	if (on) {
>  		con |= (1 << reg->core_en_shift);
>  		interrupt_en =
> @@ -317,9 +383,11 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>  	if (temp) {
>  		temp /= MCELSIUS;
>  
> -		val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
> -			(temp_to_code(data, temp)
> -			 << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
> +		if (data->soc == SOC_ARCH_EXYNOS && reg->emul_time_shift)
> +			val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift);
> +
> +		val |= (temp_to_code(data, temp) << reg->emul_temp_shift) |
> +			EXYNOS_EMUL_ENABLE;
>  	} else {
>  		val &= ~EXYNOS_EMUL_ENABLE;
>  	}
> @@ -343,7 +411,14 @@ static void exynos_tmu_work(struct work_struct *work)
>  			struct exynos_tmu_data, irq_work);
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	struct exynos_tmu_registers *reg = pdata->registers;
> -	unsigned int val_irq;
> +	unsigned int val_irq, val_type;
> +
> +	/* Find which sensor generated this interrupt */
> +	if (reg->tmu_irqstatus) {
> +		val_type = readl(data->base_common + reg->tmu_irqstatus);
> +		if (!((val_type >> data->id) & 0x1))
> +			goto out;
> +	}
>  
>  	exynos_report_trigger(data->reg_conf);
>  	mutex_lock(&data->lock);
> @@ -355,7 +430,7 @@ static void exynos_tmu_work(struct work_struct *work)
>  
>  	clk_disable(data->clk);
>  	mutex_unlock(&data->lock);
> -
> +out:
>  	enable_irq(data->irq);
>  }
>  
> @@ -383,6 +458,10 @@ static const struct of_device_id exynos_tmu_match[] = {
>  		.compatible = "samsung,exynos5250-tmu",
>  		.data = (void *)EXYNOS5250_TMU_DRV_DATA,
>  	},
> +	{
> +		.compatible = "samsung,exynos5440-tmu",
> +		.data = (void *)EXYNOS5440_TMU_DRV_DATA,
> +	},
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, exynos_tmu_match);
> @@ -420,6 +499,7 @@ static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
>  static int exynos_map_dt_data(struct platform_device *pdev)
>  {
>  	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
> +	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	struct resource res;
>  
>  	if (!data)
> @@ -436,7 +516,7 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>  	}
>  
>  	if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
> -		dev_err(&pdev->dev, "failed to get Resource\n");
> +		dev_err(&pdev->dev, "failed to get Resource 0\n");
>  		return -ENODEV;
>  	}
>  
> @@ -445,6 +525,26 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>  		dev_err(&pdev->dev, "Failed to ioremap memory\n");
>  		return -ENOMEM;
>  	}
> +
> +	/*
> +	 * Check if the TMU is multi instance type and then try to map the
> +	 * memory of common registers.
> +	 */
> +	if (!TMU_SUPPORTS(pdata, MULTI_INST))
> +		return 0;
> +
> +	if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
> +		dev_err(&pdev->dev, "failed to get Resource 1\n");
> +		return -ENODEV;
> +	}
> +
> +	data->base_common = devm_ioremap(&pdev->dev, res.start,
> +					resource_size(&res));
> +	if (!data->base) {
> +		dev_err(&pdev->dev, "Failed to ioremap memory\n");
> +		return -ENOMEM;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -496,7 +596,8 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>  		return ret;
>  
>  	if (pdata->type == SOC_ARCH_EXYNOS ||
> -				pdata->type == SOC_ARCH_EXYNOS4210)
> +		pdata->type == SOC_ARCH_EXYNOS4210 ||
> +		pdata->type == SOC_ARCH_EXYNOS5440)
>  		data->soc = pdata->type;
>  	else {
>  		ret = -EINVAL;
> diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
> index de1c342..cc6b10e 100644
> --- a/drivers/thermal/samsung/exynos_tmu.h
> +++ b/drivers/thermal/samsung/exynos_tmu.h
> @@ -43,6 +43,7 @@ enum trigger_type {
>  enum soc_type {
>  	SOC_ARCH_EXYNOS4210 = 1,
>  	SOC_ARCH_EXYNOS,
> +	SOC_ARCH_EXYNOS5440,
>  };
>  
>  /**
> @@ -61,6 +62,7 @@ enum soc_type {
>  #define TMU_SUPPORT_MULTI_INST			BIT(1)
>  #define TMU_SUPPORT_TRIM_RELOAD			BIT(2)
>  #define TMU_SUPPORT_FALLING_TRIP		BIT(3)
> +#define TMU_SUPPORT_READY_STATUS		BIT(4)
>  
>  #define TMU_SUPPORTS(a, b)	(a->features & TMU_SUPPORT_ ## b)
>  
> @@ -85,6 +87,8 @@ struct exynos_tmu_registers {
>  	u32	therm_trip_en_shift;
>  	u32	buf_slope_sel_shift;
>  	u32	buf_slope_sel_mask;
> +	u32	calib_mode_shift;
> +	u32	calib_mode_mask;
>  	u32	therm_trip_tq_en_shift;
>  	u32	core_en_shift;
>  
> @@ -137,6 +141,9 @@ struct exynos_tmu_registers {
>  	u32	emul_temp_shift;
>  	u32	emul_time_shift;
>  	u32	emul_time_mask;
> +
> +	u32	tmu_irqstatus;
> +	u32	tmu_pmin;
>  };
>  
>  /**
> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
> index 8a587d4..25629e6 100644
> --- a/drivers/thermal/samsung/exynos_tmu_data.c
> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
> @@ -79,6 +79,7 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>  	.freq_tab_count = 2,
>  	.type = SOC_ARCH_EXYNOS4210,
>  	.registers = &exynos4210_tmu_registers,
> +	.features = (TMU_SUPPORT_READY_STATUS),
>  };
>  #endif
>  
> @@ -155,6 +156,69 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>  	.type = SOC_ARCH_EXYNOS,
>  	.registers = &exynos5250_tmu_registers,
>  	.features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD |
> -			TMU_SUPPORT_FALLING_TRIP),
> +			TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS),
> +};
> +#endif
> +
> +#if defined(CONFIG_SOC_EXYNOS5440)
> +static struct exynos_tmu_registers exynos5440_tmu_registers = {
> +	.triminfo_data = EXYNOS5440_TMU_S0_7_TRIM,
> +	.triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
> +	.triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
> +	.tmu_ctrl = EXYNOS5440_TMU_S0_7_CTRL,
> +	.buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
> +	.buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
> +	.therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
> +	.therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
> +	.therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
> +	.buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
> +	.buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
> +	.calib_mode_shift = EXYNOS_TMU_CALIB_MODE_SHIFT,
> +	.calib_mode_mask = EXYNOS_TMU_CALIB_MODE_MASK,
> +	.core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
> +	.tmu_status = EXYNOS5440_TMU_S0_7_STATUS,
> +	.tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP,
> +	.threshold_th0 = EXYNOS5440_TMU_S0_7_TH0,
> +	.threshold_th1 = EXYNOS5440_TMU_S0_7_TH1,
> +	.threshold_th2 = EXYNOS5440_TMU_S0_7_TH2,
> +	.tmu_inten = EXYNOS5440_TMU_S0_7_IRQEN,
> +	.inten_rise_mask = EXYNOS5440_TMU_RISE_INT_MASK,
> +	.inten_rise_shift = EXYNOS5440_TMU_RISE_INT_SHIFT,
> +	.inten_fall_mask = EXYNOS5440_TMU_FALL_INT_MASK,
> +	.inten_fall_shift = EXYNOS5440_TMU_FALL_INT_SHIFT,
> +	.inten_rise0_shift = EXYNOS5440_TMU_INTEN_RISE0_SHIFT,
> +	.inten_rise1_shift = EXYNOS5440_TMU_INTEN_RISE1_SHIFT,
> +	.inten_rise2_shift = EXYNOS5440_TMU_INTEN_RISE2_SHIFT,
> +	.inten_rise3_shift = EXYNOS5440_TMU_INTEN_RISE3_SHIFT,
> +	.inten_fall0_shift = EXYNOS5440_TMU_INTEN_FALL0_SHIFT,
> +	.tmu_evten = EXYNOS5440_TMU_S0_7_EVTEN,
> +	.tmu_intstat = EXYNOS5440_TMU_S0_7_IRQ,
> +	.tmu_intclear = EXYNOS5440_TMU_S0_7_IRQ,
> +	.tmu_irqstatus = EXYNOS5440_TMU_IRQ_STATUS,
> +	.emul_con = EXYNOS5440_TMU_S0_7_DEBUG,
> +	.emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
> +	.tmu_pmin = EXYNOS5440_TMU_PMIN,
> +};
> +struct exynos_tmu_platform_data const exynos5440_default_tmu_data = {
> +	.trigger_levels[0] = 100,
> +	.trigger_levels[4] = 105,
> +	.trigger_enable[0] = 1,
> +	.trigger_type[0] = 1,
> +	.trigger_type[4] = 2,
> +	.gain = 5,
> +	.reference_voltage = 16,
> +	.noise_cancel_mode = 4,
> +	.cal_type = TYPE_TWO_POINT_TRIMMING,
> +	.cal_mode = 0,
> +	.efuse_value = 0x5b2d,
> +	.min_efuse_value = 16,
> +	.max_efuse_value = 76,
> +	.first_point_trim = 25,
> +	.second_point_trim = 70,
> +	.default_temp_offset = 25,
> +	.type = SOC_ARCH_EXYNOS5440,
> +	.registers = &exynos5440_tmu_registers,
> +	.features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP |
> +			TMU_SUPPORT_MULTI_INST),
>  };
>  #endif
> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
> index 0560413..c409f3a 100644
> --- a/drivers/thermal/samsung/exynos_tmu_data.h
> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
> @@ -75,6 +75,8 @@
>  #define EXYNOS_TMU_TRIP_MODE_SHIFT	13
>  #define EXYNOS_TMU_TRIP_MODE_MASK	0x7
>  #define EXYNOS_TMU_THERM_TRIP_EN_SHIFT	12
> +#define EXYNOS_TMU_CALIB_MODE_SHIFT	4
> +#define EXYNOS_TMU_CALIB_MODE_MASK	0x3
>  
>  #define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
>  #define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
> @@ -91,6 +93,37 @@
>  #define EXYNOS_EMUL_DATA_MASK	0xFF
>  #define EXYNOS_EMUL_ENABLE	0x1
>  
> +/*exynos5440 specific registers*/
> +#define EXYNOS5440_TMU_S0_7_TRIM		0x000
> +#define EXYNOS5440_TMU_S0_7_CTRL		0x020
> +#define EXYNOS5440_TMU_S0_7_DEBUG		0x040
> +#define EXYNOS5440_TMU_S0_7_STATUS		0x060
> +#define EXYNOS5440_TMU_S0_7_TEMP		0x0f0
> +#define EXYNOS5440_TMU_S0_7_TH0			0x110
> +#define EXYNOS5440_TMU_S0_7_TH1			0x130
> +#define EXYNOS5440_TMU_S0_7_TH2			0x150
> +#define EXYNOS5440_TMU_S0_7_EVTEN		0x1F0
> +#define EXYNOS5440_TMU_S0_7_IRQEN		0x210
> +#define EXYNOS5440_TMU_S0_7_IRQ			0x230
> +/* exynos5440 common registers */
> +#define EXYNOS5440_TMU_IRQ_STATUS		0x000
> +#define EXYNOS5440_TMU_PMIN			0x004
> +#define EXYNOS5440_TMU_TEMP			0x008
> +
> +#define EXYNOS5440_EFUSE_SWAP_OFFSET		8
> +#define EXYNOS5440_TMU_RISE_INT_MASK		0xf
> +#define EXYNOS5440_TMU_RISE_INT_SHIFT		0
> +#define EXYNOS5440_TMU_FALL_INT_MASK		0xf
> +#define EXYNOS5440_TMU_FALL_INT_SHIFT		4
> +#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT	0
> +#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT	1
> +#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT	2
> +#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT	3
> +#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT	4
> +#define EXYNOS5440_TMU_INTEN_FALL1_SHIFT	5
> +#define EXYNOS5440_TMU_INTEN_FALL2_SHIFT	6
> +#define EXYNOS5440_TMU_INTEN_FALL3_SHIFT	7
> +
>  #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>  extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
>  #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
> @@ -106,4 +139,11 @@ extern struct exynos_tmu_platform_data const exynos5250_default_tmu_data;
>  #define EXYNOS5250_TMU_DRV_DATA (NULL)
>  #endif
>  
> +#if defined(CONFIG_SOC_EXYNOS5440) && defined(CONFIG_EXYNOS_THERMAL_DATA)
> +extern struct exynos_tmu_platform_data const exynos5440_default_tmu_data;
> +#define EXYNOS5440_TMU_DRV_DATA (&exynos5440_default_tmu_data)
> +#else
> +#define EXYNOS5440_TMU_DRV_DATA (NULL)
> +#endif
> +
>  #endif /*_LINUX_EXYNOS_TMU_DATA_H*/
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 18/21] thermal: exynos: Add support for exynos5440 TMU sensor.
@ 2013-05-09 14:47     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 14:47 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 21820 bytes --]

Hey Amit,

On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
> This patch modifies TMU controller to add changes needed to work with
> exynos5440 platform. Also register definitions and required configuration data
> are added. This sensor registers 3 instance of the tmu controller with the
> thermal zone and hence reports 3 temperature output. This controller supports
> upto five trip points. For critical threshold the driver uses the core driver
> thermal framework for shutdown.
> 

I would kindly request you to split this patch. Looks like you add
altogether in one patch both data, driver adaptation (for your new soc)
and on top, new features. I would suggest splitting this things in
smaller steps. Easier to review, track, bitsec and find bugs (if any).

> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  .../devicetree/bindings/thermal/exynos-thermal.txt |   28 ++++-
>  drivers/thermal/samsung/Kconfig                    |    4 +-
>  drivers/thermal/samsung/exynos_thermal_common.c    |    2 +-
>  drivers/thermal/samsung/exynos_tmu.c               |  139 +++++++++++++++++---
>  drivers/thermal/samsung/exynos_tmu.h               |    7 +
>  drivers/thermal/samsung/exynos_tmu_data.c          |   66 +++++++++-
>  drivers/thermal/samsung/exynos_tmu_data.h          |   40 ++++++
>  7 files changed, 261 insertions(+), 25 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
> index 535fd0e..970eeba 100644
> --- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
> +++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
> @@ -6,13 +6,16 @@
>  	       "samsung,exynos4412-tmu"
>  	       "samsung,exynos4210-tmu"
>  	       "samsung,exynos5250-tmu"
> +	       "samsung,exynos5440-tmu"
>  - interrupt-parent : The phandle for the interrupt controller
> -- reg : Address range of the thermal registers
> +- reg : Address range of the thermal registers. For exynos5440-tmu which has 3
> +	instances of TMU, 2 set of register has to supplied. First set belongs
> +	to each instance of TMU and second set belongs to common TMU registers.
>  - interrupts : Should contain interrupt for thermal system
>  - clocks : The main clock for TMU device
>  - clock-names : Thermal system clock name
>  
> -Example:
> +Example 1):
>  
>  	tmu@100C0000 {
>  		compatible = "samsung,exynos4412-tmu";
> @@ -23,3 +26,24 @@ Example:
>  		clock-names = "tmu_apbif";
>  		status = "disabled";
>  	};
> +
> +Example 2):
> +
> +	tmuctrl_0: tmuctrl@160118 {
> +		compatible = "samsung,exynos5440-tmu";
> +		reg = <0x160118 0x230>, <0x160368 0x10>;
> +		interrupts = <0 58 0>;
> +		clocks = <&clock 21>;
> +		clock-names = "tmu_apbif";
> +	};
> +
> +Note: For multi-instance tmu each instance should have an alias correctly
> +numbered in "aliases" node.
> +
> +Example:
> +
> +aliases {
> +	tmuctrl0 = &tmuctrl_0;
> +	tmuctrl1 = &tmuctrl_1;
> +	tmuctrl2 = &tmuctrl_2;
> +};
> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
> index f23f533..fce04f3 100644
> --- a/drivers/thermal/samsung/Kconfig
> +++ b/drivers/thermal/samsung/Kconfig
> @@ -19,10 +19,10 @@ config EXYNOS_THERMAL_CORE
>  
>  config EXYNOS_THERMAL_DATA
>  	bool "Temperature sensor congiguration data for EXYNOS series SOC"
> -	depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250)
> +	depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250 || SOC_EXYNOS5440)
>  	depends on EXYNOS_THERMAL
>  	help
>  	  If you say yes here you can enable TMU (Thermal Management Unit) on
> -	  SAMSUNG EXYNOS 4210, 4412, 4414 and 5250 series of SoC. This option
> +	  SAMSUNG EXYNOS 4210, 4412, 4414, 5250 and 5440 series of SoC. This option
>  	  enables/prepares the configuration, trip and cooling data for the TMU
>  	  driver.
> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
> index b0dc63e..de43e18 100644
> --- a/drivers/thermal/samsung/exynos_thermal_common.c
> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
> @@ -370,7 +370,7 @@ int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
>  	th_zone->mode = THERMAL_DEVICE_ENABLED;
>  	sensor_conf->pzone_data = th_zone;
>  
> -	pr_info("Exynos: Kernel Thermal management registered\n");
> +	pr_info("Exynos: Thermal zone(%s) registered\n", sensor_conf->name);
>  
>  	return 0;
>  
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index c1a8c5f..72446c9 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -44,6 +44,7 @@
>   * @id: identifier of the one instance of the TMU controller.
>   * @pdata: pointer to the tmu platform/configuration data
>   * @base: base address of the single instance of the TMU controller.
> + * @base_common: base address of the common registers of the TMU controller.
>   * @irq: irq number of the TMU controller.
>   * @soc: id of the SOC type.
>   * @irq_work: pointer to the irq work structure.
> @@ -57,6 +58,7 @@ struct exynos_tmu_data {
>  	int id;
>  	struct exynos_tmu_platform_data *pdata;
>  	void __iomem *base;
> +	void __iomem *base_common;
>  	int irq;
>  	enum soc_type soc;
>  	struct work_struct irq_work;
> @@ -75,6 +77,9 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	int temp_code;
>  
> +	if (pdata->cal_mode == HW_MODE)
> +		return temp;
> +
>  	if (data->soc == SOC_ARCH_EXYNOS4210)
>  		/* temp should range between 25 and 125 */
>  		if (temp < 25 || temp > 125) {
> @@ -109,6 +114,9 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	int temp;
>  
> +	if (pdata->cal_mode == HW_MODE)
> +		return temp_code;
> +
>  	if (data->soc == SOC_ARCH_EXYNOS4210)
>  		/* temp_code should range between 75 and 175 */
>  		if (temp_code < 75 || temp_code > 175) {
> @@ -139,33 +147,63 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	struct exynos_tmu_registers *reg = pdata->registers;
> -	unsigned int status, trim_info, con;
> +	unsigned int status, trim_info = 0, con;
>  	unsigned int rising_threshold = 0, falling_threshold = 0;
>  	int ret = 0, threshold_code, i, trigger_levs = 0;
>  
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> -	status = readb(data->base + reg->tmu_status);
> -	if (!status) {
> -		ret = -EBUSY;
> -		goto out;
> +	if (TMU_SUPPORTS(pdata, READY_STATUS)) {
> +		status = readb(data->base + reg->tmu_status);
> +		if (!status) {
> +			ret = -EBUSY;
> +			goto out;
> +		}
>  	}
>  
>  	if (TMU_SUPPORTS(pdata, TRIM_RELOAD))
>  		__raw_writel(1, data->base + reg->triminfo_ctrl);
>  
> +	if (pdata->cal_mode == HW_MODE)
> +		goto skip_calib_data;
> +
>  	/* Save trimming info in order to perform calibration */
> -	trim_info = readl(data->base + reg->triminfo_data);
> +	if (data->soc == SOC_ARCH_EXYNOS5440) {
> +		/*
> +		 * For exynos5440 soc triminfo value is swapped between TMU0 and
> +		 * TMU2, so the below logic is needed.
> +		 */
> +		switch (data->id) {
> +		case 0:
> +			trim_info = readl(data->base +
> +			EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
> +			break;
> +		case 1:
> +			trim_info = readl(data->base + reg->triminfo_data);
> +			break;
> +		case 2:
> +			trim_info = readl(data->base -
> +			EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
> +		}
> +	} else {
> +		trim_info = readl(data->base + reg->triminfo_data);
> +	}
>  	data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
>  	data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
>  				EXYNOS_TMU_TEMP_MASK);
>  
> -	if ((pdata->min_efuse_value > data->temp_error1) ||
> -			(data->temp_error1 > pdata->max_efuse_value) ||
> -			(data->temp_error2 != 0))
> -		data->temp_error1 = pdata->efuse_value;
> +	if (!data->temp_error1 ||
> +		(pdata->min_efuse_value > data->temp_error1) ||
> +		(data->temp_error1 > pdata->max_efuse_value))
> +		data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
> +
> +	if (!data->temp_error2)
> +		data->temp_error2 =
> +			(pdata->efuse_value >> reg->triminfo_85_shift) &
> +			EXYNOS_TMU_TEMP_MASK;
>  
> +skip_calib_data:
>  	/* Count trigger levels to be enabled */
>  	for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
>  		if (pdata->trigger_levels[i])
> @@ -185,9 +223,10 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  			data->base + reg->threshold_th0 + i * 4);
>  
>  		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
> -	} else if (data->soc == SOC_ARCH_EXYNOS) {
> +	} else if (data->soc == SOC_ARCH_EXYNOS ||
> +			data->soc == SOC_ARCH_EXYNOS5440) {
>  		/* Write temperature code for rising and falling threshold */
> -		for (i = 0; i < trigger_levs; i++) {
> +		for (i = 0; i < trigger_levs && i < 4 ; i++) {
>  			threshold_code = temp_to_code(data,
>  						pdata->trigger_levels[i]);
>  			if (threshold_code < 0) {
> @@ -218,7 +257,29 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  		writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>  			(reg->inten_fall_mask << reg->inten_fall_shift),
>  				data->base + reg->tmu_intclear);
> +
> +		/* if 5th threshold limit is also present, use TH2 register */
> +		i = 4;
> +		if (pdata->trigger_levels[i]) {
> +			threshold_code = temp_to_code(data,
> +						pdata->trigger_levels[i]);
> +			if (threshold_code < 0) {
> +				ret = threshold_code;
> +				goto out;
> +			}
> +			rising_threshold = threshold_code << 24;
> +			writel(rising_threshold,
> +				data->base + reg->threshold_th2);
> +			if (pdata->trigger_type[i] == HW_TRIP) {
> +				con = readl(data->base + reg->tmu_ctrl);
> +				con |= (1 << reg->therm_trip_en_shift);
> +				writel(con, data->base + reg->tmu_ctrl);
> +			}
> +		}
>  	}
> +	/*Clear the PMIN in the common TMU register*/
> +	if (reg->tmu_pmin && !data->id)
> +		writel(0, data->base_common + reg->tmu_pmin);
>  out:
>  	clk_disable(data->clk);
>  	mutex_unlock(&data->lock);
> @@ -254,6 +315,11 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>  		con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
>  	}
>  
> +	if (pdata->cal_mode == HW_MODE) {
> +		con &= ~(reg->calib_mode_mask << reg->calib_mode_shift);
> +		con |= pdata->cal_type << reg->calib_mode_shift;
> +	}
> +
>  	if (on) {
>  		con |= (1 << reg->core_en_shift);
>  		interrupt_en =
> @@ -317,9 +383,11 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>  	if (temp) {
>  		temp /= MCELSIUS;
>  
> -		val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
> -			(temp_to_code(data, temp)
> -			 << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
> +		if (data->soc == SOC_ARCH_EXYNOS && reg->emul_time_shift)
> +			val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift);
> +
> +		val |= (temp_to_code(data, temp) << reg->emul_temp_shift) |
> +			EXYNOS_EMUL_ENABLE;
>  	} else {
>  		val &= ~EXYNOS_EMUL_ENABLE;
>  	}
> @@ -343,7 +411,14 @@ static void exynos_tmu_work(struct work_struct *work)
>  			struct exynos_tmu_data, irq_work);
>  	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	struct exynos_tmu_registers *reg = pdata->registers;
> -	unsigned int val_irq;
> +	unsigned int val_irq, val_type;
> +
> +	/* Find which sensor generated this interrupt */
> +	if (reg->tmu_irqstatus) {
> +		val_type = readl(data->base_common + reg->tmu_irqstatus);
> +		if (!((val_type >> data->id) & 0x1))
> +			goto out;
> +	}
>  
>  	exynos_report_trigger(data->reg_conf);
>  	mutex_lock(&data->lock);
> @@ -355,7 +430,7 @@ static void exynos_tmu_work(struct work_struct *work)
>  
>  	clk_disable(data->clk);
>  	mutex_unlock(&data->lock);
> -
> +out:
>  	enable_irq(data->irq);
>  }
>  
> @@ -383,6 +458,10 @@ static const struct of_device_id exynos_tmu_match[] = {
>  		.compatible = "samsung,exynos5250-tmu",
>  		.data = (void *)EXYNOS5250_TMU_DRV_DATA,
>  	},
> +	{
> +		.compatible = "samsung,exynos5440-tmu",
> +		.data = (void *)EXYNOS5440_TMU_DRV_DATA,
> +	},
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, exynos_tmu_match);
> @@ -420,6 +499,7 @@ static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
>  static int exynos_map_dt_data(struct platform_device *pdev)
>  {
>  	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
> +	struct exynos_tmu_platform_data *pdata = data->pdata;
>  	struct resource res;
>  
>  	if (!data)
> @@ -436,7 +516,7 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>  	}
>  
>  	if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
> -		dev_err(&pdev->dev, "failed to get Resource\n");
> +		dev_err(&pdev->dev, "failed to get Resource 0\n");
>  		return -ENODEV;
>  	}
>  
> @@ -445,6 +525,26 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>  		dev_err(&pdev->dev, "Failed to ioremap memory\n");
>  		return -ENOMEM;
>  	}
> +
> +	/*
> +	 * Check if the TMU is multi instance type and then try to map the
> +	 * memory of common registers.
> +	 */
> +	if (!TMU_SUPPORTS(pdata, MULTI_INST))
> +		return 0;
> +
> +	if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
> +		dev_err(&pdev->dev, "failed to get Resource 1\n");
> +		return -ENODEV;
> +	}
> +
> +	data->base_common = devm_ioremap(&pdev->dev, res.start,
> +					resource_size(&res));
> +	if (!data->base) {
> +		dev_err(&pdev->dev, "Failed to ioremap memory\n");
> +		return -ENOMEM;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -496,7 +596,8 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>  		return ret;
>  
>  	if (pdata->type == SOC_ARCH_EXYNOS ||
> -				pdata->type == SOC_ARCH_EXYNOS4210)
> +		pdata->type == SOC_ARCH_EXYNOS4210 ||
> +		pdata->type == SOC_ARCH_EXYNOS5440)
>  		data->soc = pdata->type;
>  	else {
>  		ret = -EINVAL;
> diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
> index de1c342..cc6b10e 100644
> --- a/drivers/thermal/samsung/exynos_tmu.h
> +++ b/drivers/thermal/samsung/exynos_tmu.h
> @@ -43,6 +43,7 @@ enum trigger_type {
>  enum soc_type {
>  	SOC_ARCH_EXYNOS4210 = 1,
>  	SOC_ARCH_EXYNOS,
> +	SOC_ARCH_EXYNOS5440,
>  };
>  
>  /**
> @@ -61,6 +62,7 @@ enum soc_type {
>  #define TMU_SUPPORT_MULTI_INST			BIT(1)
>  #define TMU_SUPPORT_TRIM_RELOAD			BIT(2)
>  #define TMU_SUPPORT_FALLING_TRIP		BIT(3)
> +#define TMU_SUPPORT_READY_STATUS		BIT(4)
>  
>  #define TMU_SUPPORTS(a, b)	(a->features & TMU_SUPPORT_ ## b)
>  
> @@ -85,6 +87,8 @@ struct exynos_tmu_registers {
>  	u32	therm_trip_en_shift;
>  	u32	buf_slope_sel_shift;
>  	u32	buf_slope_sel_mask;
> +	u32	calib_mode_shift;
> +	u32	calib_mode_mask;
>  	u32	therm_trip_tq_en_shift;
>  	u32	core_en_shift;
>  
> @@ -137,6 +141,9 @@ struct exynos_tmu_registers {
>  	u32	emul_temp_shift;
>  	u32	emul_time_shift;
>  	u32	emul_time_mask;
> +
> +	u32	tmu_irqstatus;
> +	u32	tmu_pmin;
>  };
>  
>  /**
> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
> index 8a587d4..25629e6 100644
> --- a/drivers/thermal/samsung/exynos_tmu_data.c
> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
> @@ -79,6 +79,7 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>  	.freq_tab_count = 2,
>  	.type = SOC_ARCH_EXYNOS4210,
>  	.registers = &exynos4210_tmu_registers,
> +	.features = (TMU_SUPPORT_READY_STATUS),
>  };
>  #endif
>  
> @@ -155,6 +156,69 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>  	.type = SOC_ARCH_EXYNOS,
>  	.registers = &exynos5250_tmu_registers,
>  	.features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD |
> -			TMU_SUPPORT_FALLING_TRIP),
> +			TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS),
> +};
> +#endif
> +
> +#if defined(CONFIG_SOC_EXYNOS5440)
> +static struct exynos_tmu_registers exynos5440_tmu_registers = {
> +	.triminfo_data = EXYNOS5440_TMU_S0_7_TRIM,
> +	.triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
> +	.triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
> +	.tmu_ctrl = EXYNOS5440_TMU_S0_7_CTRL,
> +	.buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
> +	.buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
> +	.therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
> +	.therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
> +	.therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
> +	.buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
> +	.buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
> +	.calib_mode_shift = EXYNOS_TMU_CALIB_MODE_SHIFT,
> +	.calib_mode_mask = EXYNOS_TMU_CALIB_MODE_MASK,
> +	.core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
> +	.tmu_status = EXYNOS5440_TMU_S0_7_STATUS,
> +	.tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP,
> +	.threshold_th0 = EXYNOS5440_TMU_S0_7_TH0,
> +	.threshold_th1 = EXYNOS5440_TMU_S0_7_TH1,
> +	.threshold_th2 = EXYNOS5440_TMU_S0_7_TH2,
> +	.tmu_inten = EXYNOS5440_TMU_S0_7_IRQEN,
> +	.inten_rise_mask = EXYNOS5440_TMU_RISE_INT_MASK,
> +	.inten_rise_shift = EXYNOS5440_TMU_RISE_INT_SHIFT,
> +	.inten_fall_mask = EXYNOS5440_TMU_FALL_INT_MASK,
> +	.inten_fall_shift = EXYNOS5440_TMU_FALL_INT_SHIFT,
> +	.inten_rise0_shift = EXYNOS5440_TMU_INTEN_RISE0_SHIFT,
> +	.inten_rise1_shift = EXYNOS5440_TMU_INTEN_RISE1_SHIFT,
> +	.inten_rise2_shift = EXYNOS5440_TMU_INTEN_RISE2_SHIFT,
> +	.inten_rise3_shift = EXYNOS5440_TMU_INTEN_RISE3_SHIFT,
> +	.inten_fall0_shift = EXYNOS5440_TMU_INTEN_FALL0_SHIFT,
> +	.tmu_evten = EXYNOS5440_TMU_S0_7_EVTEN,
> +	.tmu_intstat = EXYNOS5440_TMU_S0_7_IRQ,
> +	.tmu_intclear = EXYNOS5440_TMU_S0_7_IRQ,
> +	.tmu_irqstatus = EXYNOS5440_TMU_IRQ_STATUS,
> +	.emul_con = EXYNOS5440_TMU_S0_7_DEBUG,
> +	.emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
> +	.tmu_pmin = EXYNOS5440_TMU_PMIN,
> +};
> +struct exynos_tmu_platform_data const exynos5440_default_tmu_data = {
> +	.trigger_levels[0] = 100,
> +	.trigger_levels[4] = 105,
> +	.trigger_enable[0] = 1,
> +	.trigger_type[0] = 1,
> +	.trigger_type[4] = 2,
> +	.gain = 5,
> +	.reference_voltage = 16,
> +	.noise_cancel_mode = 4,
> +	.cal_type = TYPE_TWO_POINT_TRIMMING,
> +	.cal_mode = 0,
> +	.efuse_value = 0x5b2d,
> +	.min_efuse_value = 16,
> +	.max_efuse_value = 76,
> +	.first_point_trim = 25,
> +	.second_point_trim = 70,
> +	.default_temp_offset = 25,
> +	.type = SOC_ARCH_EXYNOS5440,
> +	.registers = &exynos5440_tmu_registers,
> +	.features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP |
> +			TMU_SUPPORT_MULTI_INST),
>  };
>  #endif
> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
> index 0560413..c409f3a 100644
> --- a/drivers/thermal/samsung/exynos_tmu_data.h
> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
> @@ -75,6 +75,8 @@
>  #define EXYNOS_TMU_TRIP_MODE_SHIFT	13
>  #define EXYNOS_TMU_TRIP_MODE_MASK	0x7
>  #define EXYNOS_TMU_THERM_TRIP_EN_SHIFT	12
> +#define EXYNOS_TMU_CALIB_MODE_SHIFT	4
> +#define EXYNOS_TMU_CALIB_MODE_MASK	0x3
>  
>  #define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
>  #define EXYNOS_TMU_INTEN_RISE1_SHIFT	4
> @@ -91,6 +93,37 @@
>  #define EXYNOS_EMUL_DATA_MASK	0xFF
>  #define EXYNOS_EMUL_ENABLE	0x1
>  
> +/*exynos5440 specific registers*/
> +#define EXYNOS5440_TMU_S0_7_TRIM		0x000
> +#define EXYNOS5440_TMU_S0_7_CTRL		0x020
> +#define EXYNOS5440_TMU_S0_7_DEBUG		0x040
> +#define EXYNOS5440_TMU_S0_7_STATUS		0x060
> +#define EXYNOS5440_TMU_S0_7_TEMP		0x0f0
> +#define EXYNOS5440_TMU_S0_7_TH0			0x110
> +#define EXYNOS5440_TMU_S0_7_TH1			0x130
> +#define EXYNOS5440_TMU_S0_7_TH2			0x150
> +#define EXYNOS5440_TMU_S0_7_EVTEN		0x1F0
> +#define EXYNOS5440_TMU_S0_7_IRQEN		0x210
> +#define EXYNOS5440_TMU_S0_7_IRQ			0x230
> +/* exynos5440 common registers */
> +#define EXYNOS5440_TMU_IRQ_STATUS		0x000
> +#define EXYNOS5440_TMU_PMIN			0x004
> +#define EXYNOS5440_TMU_TEMP			0x008
> +
> +#define EXYNOS5440_EFUSE_SWAP_OFFSET		8
> +#define EXYNOS5440_TMU_RISE_INT_MASK		0xf
> +#define EXYNOS5440_TMU_RISE_INT_SHIFT		0
> +#define EXYNOS5440_TMU_FALL_INT_MASK		0xf
> +#define EXYNOS5440_TMU_FALL_INT_SHIFT		4
> +#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT	0
> +#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT	1
> +#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT	2
> +#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT	3
> +#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT	4
> +#define EXYNOS5440_TMU_INTEN_FALL1_SHIFT	5
> +#define EXYNOS5440_TMU_INTEN_FALL2_SHIFT	6
> +#define EXYNOS5440_TMU_INTEN_FALL3_SHIFT	7
> +
>  #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>  extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
>  #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
> @@ -106,4 +139,11 @@ extern struct exynos_tmu_platform_data const exynos5250_default_tmu_data;
>  #define EXYNOS5250_TMU_DRV_DATA (NULL)
>  #endif
>  
> +#if defined(CONFIG_SOC_EXYNOS5440) && defined(CONFIG_EXYNOS_THERMAL_DATA)
> +extern struct exynos_tmu_platform_data const exynos5440_default_tmu_data;
> +#define EXYNOS5440_TMU_DRV_DATA (&exynos5440_default_tmu_data)
> +#else
> +#define EXYNOS5440_TMU_DRV_DATA (NULL)
> +#endif
> +
>  #endif /*_LINUX_EXYNOS_TMU_DATA_H*/
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 15/21] thermal: exynos: Add support to handle many instances of TMU
  2013-05-07 13:01 ` [PATCH V3 15/21] thermal: exynos: Add support to handle many instances of TMU Amit Daniel Kachhap
@ 2013-05-09 14:53     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 14:53 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 8699 bytes --]

On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
> This patch adds support to handle multiple instances of the TMU controllers.
> This is done by removing the static structure to register with the core thermal
> and creating it dynamically for each instance of the TMU controller. The
> interrupt is made shared type to handle interrupts for all the TMU. Also
> the identifier of the TMU controller is extracted from device tree alias.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/exynos_tmu.c |  125 +++++++++++++++++++++++-----------
>  1 files changed, 84 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index bdf40ef..94d6e8e 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -29,6 +29,8 @@
>  #include <linux/module.h>
>  #include <linux/mutex.h>
>  #include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
>  #include <linux/platform_device.h>
>  #include <linux/slab.h>
>  #include <linux/workqueue.h>
> @@ -36,9 +38,24 @@
>  #include "exynos_tmu.h"
>  #include "exynos_tmu_data.h"
>  
> +/**
> + * struct exynos_tmu_data : A structure to hold the private data of the TMU
> +	driver
> + * @id: identifier of the one instance of the TMU controller.
> + * @pdata: pointer to the tmu platform/configuration data
> + * @base: base address of the single instance of the TMU controller.
> + * @irq: irq number of the TMU controller.
> + * @soc: id of the SOC type.
> + * @irq_work: pointer to the irq work structure.
> + * @lock: lock to implement synchronization.
> + * @clk: pointer to the clock structure.
> + * @temp_error1: fused value of the first point trim.
> + * @temp_error2: fused value of the second point trim.
> + * @reg_conf: pointer to structure to register with core thermal.
> + */
>  struct exynos_tmu_data {
> +	int id;
>  	struct exynos_tmu_platform_data *pdata;
> -	struct resource *mem;
>  	void __iomem *base;
>  	int irq;
>  	enum soc_type soc;
> @@ -46,6 +63,7 @@ struct exynos_tmu_data {
>  	struct mutex lock;
>  	struct clk *clk;
>  	u8 temp_error1, temp_error2;
> +	struct thermal_sensor_conf *reg_conf;
>  };
>  
>  /*
> @@ -319,12 +337,6 @@ static int exynos_tmu_set_emulation(void *drv_data,	unsigned long temp)
>  	{ return -EINVAL; }
>  #endif/*CONFIG_THERMAL_EMULATION*/
>  
> -static struct thermal_sensor_conf exynos_sensor_conf = {
> -	.name			= "exynos-therm",
> -	.read_temperature	= (int (*)(void *))exynos_tmu_read,
> -	.write_emul_temp	= exynos_tmu_set_emulation,
> -};
> -
>  static void exynos_tmu_work(struct work_struct *work)
>  {
>  	struct exynos_tmu_data *data = container_of(work,
> @@ -333,7 +345,7 @@ static void exynos_tmu_work(struct work_struct *work)
>  	struct exynos_tmu_registers *reg = pdata->registers;
>  	unsigned int val_irq;
>  
> -	exynos_report_trigger(&exynos_sensor_conf);
> +	exynos_report_trigger(data->reg_conf);
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> @@ -405,10 +417,42 @@ static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
>  			platform_get_device_id(pdev)->driver_data;
>  }
>  
> +static int exynos_map_dt_data(struct platform_device *pdev)
> +{
> +	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
> +	struct resource res;
> +
> +	if (!data)
> +		return -ENODEV;
> +
> +	data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
> +	if (data->id < 0)
> +		data->id = 0;
> +
> +	data->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
> +	if (data->irq <= 0) {
> +		dev_err(&pdev->dev, "failed to get IRQ\n");
> +		return -ENODEV;
> +	}
> +
> +	if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
> +		dev_err(&pdev->dev, "failed to get Resource\n");
> +		return -ENODEV;
> +	}
> +
> +	data->base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
> +	if (!data->base) {
> +		dev_err(&pdev->dev, "Failed to ioremap memory\n");
> +		return -ENOMEM;

looks like the statement below fits better here:
		return ERR_PTR(-EADDRNOTAVAIL);

> +	}

blank line?

> +	return 0;
> +}
> +
>  static int exynos_tmu_probe(struct platform_device *pdev)
>  {
>  	struct exynos_tmu_data *data;
>  	struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
> +	struct thermal_sensor_conf *sensor_conf;
>  	int ret, i;
>  
>  	if (!pdata)
> @@ -425,26 +469,17 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>  		return -ENOMEM;
>  	}
>  
> -	data->irq = platform_get_irq(pdev, 0);
> -	if (data->irq < 0) {
> -		dev_err(&pdev->dev, "Failed to get platform irq\n");
> -		return data->irq;
> -	}
> -
> -	INIT_WORK(&data->irq_work, exynos_tmu_work);
> -
> -	data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	if (!data->mem) {
> -		dev_err(&pdev->dev, "Failed to get platform resource\n");
> -		return -ENOENT;
> -	}
> +	data->pdata = pdata;
> +	platform_set_drvdata(pdev, data);
> +	mutex_init(&data->lock);
>  
> -	data->base = devm_ioremap_resource(&pdev->dev, data->mem);
> -	if (IS_ERR(data->base))
> -		return PTR_ERR(data->base);
> +	ret = exynos_map_dt_data(pdev);
> +	if (ret)
> +		return ret;
>  
> +	INIT_WORK(&data->irq_work, exynos_tmu_work);
>  	ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
> -		IRQF_TRIGGER_RISING, "exynos-tmu", data);
> +		IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
>  		return ret;
> @@ -469,10 +504,6 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>  		goto err_clk;
>  	}
>  
> -	data->pdata = pdata;
> -	platform_set_drvdata(pdev, data);
> -	mutex_init(&data->lock);
> -
>  	ret = exynos_tmu_initialize(pdev);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Failed to initialize TMU\n");
> @@ -481,28 +512,40 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>  
>  	exynos_tmu_control(pdev, true);
>  
> -	/* Register the sensor with thermal management interface */
> -	(&exynos_sensor_conf)->driver_data = data;
> -	exynos_sensor_conf.trip_data.trip_count = pdata->trigger_enable[0] +
> +	/* Allocate a structure to register with the exynos core thermal */
> +	sensor_conf = devm_kzalloc(&pdev->dev,
> +				sizeof(struct thermal_sensor_conf), GFP_KERNEL);
> +	if (!sensor_conf) {
> +		dev_err(&pdev->dev, "Failed to allocate registration struct\n");
> +		ret = -ENOMEM;
> +		goto err_clk;
> +	}
> +	data->reg_conf = sensor_conf;
> +	sprintf(sensor_conf->name, "therm_zone%d", data->id);
> +	sensor_conf->read_temperature = (int (*)(void *))exynos_tmu_read;
> +	sensor_conf->write_emul_temp =
> +		(int (*)(void *, unsigned long))exynos_tmu_set_emulation;
> +	sensor_conf->driver_data = data;
> +	sensor_conf->trip_data.trip_count = pdata->trigger_enable[0] +
>  			pdata->trigger_enable[1] + pdata->trigger_enable[2]+
>  			pdata->trigger_enable[3];
>  
> -	for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
> -		exynos_sensor_conf.trip_data.trip_val[i] =
> +	for (i = 0; i < sensor_conf->trip_data.trip_count; i++)
> +		sensor_conf->trip_data.trip_val[i] =
>  			pdata->threshold + pdata->trigger_levels[i];
>  
> -	exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
> +	sensor_conf->trip_data.trigger_falling = pdata->threshold_falling;
>  
> -	exynos_sensor_conf.cooling_data.freq_clip_count =
> -						pdata->freq_tab_count;
> +	sensor_conf->cooling_data.freq_clip_count = pdata->freq_tab_count;
>  	for (i = 0; i < pdata->freq_tab_count; i++) {
> -		exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
> +		sensor_conf->cooling_data.freq_data[i].freq_clip_max =
>  					pdata->freq_tab[i].freq_clip_max;
> -		exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
> +		sensor_conf->cooling_data.freq_data[i].temp_level =
>  					pdata->freq_tab[i].temp_level;
>  	}
>  
> -	ret = exynos_register_thermal(&exynos_sensor_conf);
> +	/* Register the sensor with thermal management interface */
> +	ret = exynos_register_thermal(sensor_conf);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Failed to register thermal interface\n");
>  		goto err_clk;
> @@ -521,7 +564,7 @@ static int exynos_tmu_remove(struct platform_device *pdev)
>  
>  	exynos_tmu_control(pdev, false);
>  
> -	exynos_unregister_thermal(&exynos_sensor_conf);
> +	exynos_unregister_thermal(data->reg_conf);
>  
>  	clk_unprepare(data->clk);
>  
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 15/21] thermal: exynos: Add support to handle many instances of TMU
@ 2013-05-09 14:53     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-09 14:53 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 8699 bytes --]

On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
> This patch adds support to handle multiple instances of the TMU controllers.
> This is done by removing the static structure to register with the core thermal
> and creating it dynamically for each instance of the TMU controller. The
> interrupt is made shared type to handle interrupts for all the TMU. Also
> the identifier of the TMU controller is extracted from device tree alias.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
> ---
>  drivers/thermal/samsung/exynos_tmu.c |  125 +++++++++++++++++++++++-----------
>  1 files changed, 84 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index bdf40ef..94d6e8e 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -29,6 +29,8 @@
>  #include <linux/module.h>
>  #include <linux/mutex.h>
>  #include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
>  #include <linux/platform_device.h>
>  #include <linux/slab.h>
>  #include <linux/workqueue.h>
> @@ -36,9 +38,24 @@
>  #include "exynos_tmu.h"
>  #include "exynos_tmu_data.h"
>  
> +/**
> + * struct exynos_tmu_data : A structure to hold the private data of the TMU
> +	driver
> + * @id: identifier of the one instance of the TMU controller.
> + * @pdata: pointer to the tmu platform/configuration data
> + * @base: base address of the single instance of the TMU controller.
> + * @irq: irq number of the TMU controller.
> + * @soc: id of the SOC type.
> + * @irq_work: pointer to the irq work structure.
> + * @lock: lock to implement synchronization.
> + * @clk: pointer to the clock structure.
> + * @temp_error1: fused value of the first point trim.
> + * @temp_error2: fused value of the second point trim.
> + * @reg_conf: pointer to structure to register with core thermal.
> + */
>  struct exynos_tmu_data {
> +	int id;
>  	struct exynos_tmu_platform_data *pdata;
> -	struct resource *mem;
>  	void __iomem *base;
>  	int irq;
>  	enum soc_type soc;
> @@ -46,6 +63,7 @@ struct exynos_tmu_data {
>  	struct mutex lock;
>  	struct clk *clk;
>  	u8 temp_error1, temp_error2;
> +	struct thermal_sensor_conf *reg_conf;
>  };
>  
>  /*
> @@ -319,12 +337,6 @@ static int exynos_tmu_set_emulation(void *drv_data,	unsigned long temp)
>  	{ return -EINVAL; }
>  #endif/*CONFIG_THERMAL_EMULATION*/
>  
> -static struct thermal_sensor_conf exynos_sensor_conf = {
> -	.name			= "exynos-therm",
> -	.read_temperature	= (int (*)(void *))exynos_tmu_read,
> -	.write_emul_temp	= exynos_tmu_set_emulation,
> -};
> -
>  static void exynos_tmu_work(struct work_struct *work)
>  {
>  	struct exynos_tmu_data *data = container_of(work,
> @@ -333,7 +345,7 @@ static void exynos_tmu_work(struct work_struct *work)
>  	struct exynos_tmu_registers *reg = pdata->registers;
>  	unsigned int val_irq;
>  
> -	exynos_report_trigger(&exynos_sensor_conf);
> +	exynos_report_trigger(data->reg_conf);
>  	mutex_lock(&data->lock);
>  	clk_enable(data->clk);
>  
> @@ -405,10 +417,42 @@ static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
>  			platform_get_device_id(pdev)->driver_data;
>  }
>  
> +static int exynos_map_dt_data(struct platform_device *pdev)
> +{
> +	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
> +	struct resource res;
> +
> +	if (!data)
> +		return -ENODEV;
> +
> +	data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
> +	if (data->id < 0)
> +		data->id = 0;
> +
> +	data->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
> +	if (data->irq <= 0) {
> +		dev_err(&pdev->dev, "failed to get IRQ\n");
> +		return -ENODEV;
> +	}
> +
> +	if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
> +		dev_err(&pdev->dev, "failed to get Resource\n");
> +		return -ENODEV;
> +	}
> +
> +	data->base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
> +	if (!data->base) {
> +		dev_err(&pdev->dev, "Failed to ioremap memory\n");
> +		return -ENOMEM;

looks like the statement below fits better here:
		return ERR_PTR(-EADDRNOTAVAIL);

> +	}

blank line?

> +	return 0;
> +}
> +
>  static int exynos_tmu_probe(struct platform_device *pdev)
>  {
>  	struct exynos_tmu_data *data;
>  	struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
> +	struct thermal_sensor_conf *sensor_conf;
>  	int ret, i;
>  
>  	if (!pdata)
> @@ -425,26 +469,17 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>  		return -ENOMEM;
>  	}
>  
> -	data->irq = platform_get_irq(pdev, 0);
> -	if (data->irq < 0) {
> -		dev_err(&pdev->dev, "Failed to get platform irq\n");
> -		return data->irq;
> -	}
> -
> -	INIT_WORK(&data->irq_work, exynos_tmu_work);
> -
> -	data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	if (!data->mem) {
> -		dev_err(&pdev->dev, "Failed to get platform resource\n");
> -		return -ENOENT;
> -	}
> +	data->pdata = pdata;
> +	platform_set_drvdata(pdev, data);
> +	mutex_init(&data->lock);
>  
> -	data->base = devm_ioremap_resource(&pdev->dev, data->mem);
> -	if (IS_ERR(data->base))
> -		return PTR_ERR(data->base);
> +	ret = exynos_map_dt_data(pdev);
> +	if (ret)
> +		return ret;
>  
> +	INIT_WORK(&data->irq_work, exynos_tmu_work);
>  	ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
> -		IRQF_TRIGGER_RISING, "exynos-tmu", data);
> +		IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
>  		return ret;
> @@ -469,10 +504,6 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>  		goto err_clk;
>  	}
>  
> -	data->pdata = pdata;
> -	platform_set_drvdata(pdev, data);
> -	mutex_init(&data->lock);
> -
>  	ret = exynos_tmu_initialize(pdev);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Failed to initialize TMU\n");
> @@ -481,28 +512,40 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>  
>  	exynos_tmu_control(pdev, true);
>  
> -	/* Register the sensor with thermal management interface */
> -	(&exynos_sensor_conf)->driver_data = data;
> -	exynos_sensor_conf.trip_data.trip_count = pdata->trigger_enable[0] +
> +	/* Allocate a structure to register with the exynos core thermal */
> +	sensor_conf = devm_kzalloc(&pdev->dev,
> +				sizeof(struct thermal_sensor_conf), GFP_KERNEL);
> +	if (!sensor_conf) {
> +		dev_err(&pdev->dev, "Failed to allocate registration struct\n");
> +		ret = -ENOMEM;
> +		goto err_clk;
> +	}
> +	data->reg_conf = sensor_conf;
> +	sprintf(sensor_conf->name, "therm_zone%d", data->id);
> +	sensor_conf->read_temperature = (int (*)(void *))exynos_tmu_read;
> +	sensor_conf->write_emul_temp =
> +		(int (*)(void *, unsigned long))exynos_tmu_set_emulation;
> +	sensor_conf->driver_data = data;
> +	sensor_conf->trip_data.trip_count = pdata->trigger_enable[0] +
>  			pdata->trigger_enable[1] + pdata->trigger_enable[2]+
>  			pdata->trigger_enable[3];
>  
> -	for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
> -		exynos_sensor_conf.trip_data.trip_val[i] =
> +	for (i = 0; i < sensor_conf->trip_data.trip_count; i++)
> +		sensor_conf->trip_data.trip_val[i] =
>  			pdata->threshold + pdata->trigger_levels[i];
>  
> -	exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
> +	sensor_conf->trip_data.trigger_falling = pdata->threshold_falling;
>  
> -	exynos_sensor_conf.cooling_data.freq_clip_count =
> -						pdata->freq_tab_count;
> +	sensor_conf->cooling_data.freq_clip_count = pdata->freq_tab_count;
>  	for (i = 0; i < pdata->freq_tab_count; i++) {
> -		exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
> +		sensor_conf->cooling_data.freq_data[i].freq_clip_max =
>  					pdata->freq_tab[i].freq_clip_max;
> -		exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
> +		sensor_conf->cooling_data.freq_data[i].temp_level =
>  					pdata->freq_tab[i].temp_level;
>  	}
>  
> -	ret = exynos_register_thermal(&exynos_sensor_conf);
> +	/* Register the sensor with thermal management interface */
> +	ret = exynos_register_thermal(sensor_conf);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Failed to register thermal interface\n");
>  		goto err_clk;
> @@ -521,7 +564,7 @@ static int exynos_tmu_remove(struct platform_device *pdev)
>  
>  	exynos_tmu_control(pdev, false);
>  
> -	exynos_unregister_thermal(&exynos_sensor_conf);
> +	exynos_unregister_thermal(data->reg_conf);
>  
>  	clk_unprepare(data->clk);
>  
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 04/21] thermal: exynos: Move exynos_thermal.h from include/* to driver/* folder
  2013-05-09 13:28     ` Eduardo Valentin
  (?)
@ 2013-05-10  1:53     ` amit daniel kachhap
  -1 siblings, 0 replies; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-10  1:53 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel, Kukjin Kim

Hi,

On Thu, May 9, 2013 at 6:58 PM, Eduardo Valentin
<eduardo.valentin@ti.com> wrote:
> Hello Amit,
>
> On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
>> This patch renames and moves  include/linux/platform_data/exynos_thermal.h to
>> drivers/thermal/samsung/exynos_tmu.h. This file movement is needed as exynos
>> SOC's are not supporting non-DT based platforms. Also the rename is needed as this
>> file now just contains exynos tmu driver related definations.
>>
>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>> ---
>>  drivers/thermal/samsung/exynos_thermal_common.c    |    1 -
>>  drivers/thermal/samsung/exynos_thermal_common.h    |   15 +++++++++++++++
>>  drivers/thermal/samsung/exynos_tmu.c               |    2 +-
>>  .../thermal/samsung/exynos_tmu.h                   |   15 ---------------
>>  4 files changed, 16 insertions(+), 17 deletions(-)
>>  rename include/linux/platform_data/exynos_thermal.h => drivers/thermal/samsung/exynos_tmu.h (88%)
>>
>> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
>> index 9a57606..dae5476 100644
>> --- a/drivers/thermal/samsung/exynos_thermal_common.c
>> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
>> @@ -27,7 +27,6 @@
>>  #include <linux/kernel.h>
>>  #include <linux/kobject.h>
>>  #include <linux/mutex.h>
>> -#include <linux/platform_data/exynos_thermal.h>
>>  #include <linux/slab.h>
>>  #include <linux/thermal.h>
>>  #include "exynos_thermal_common.h"
>> diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
>> index da2add0..1c3f8b7 100644
>> --- a/drivers/thermal/samsung/exynos_thermal_common.h
>> +++ b/drivers/thermal/samsung/exynos_thermal_common.h
>> @@ -44,6 +44,21 @@
>>
>>  #define EXYNOS_ZONE_COUNT    3
>>
>> +/**
>> + * struct freq_clip_table
>> + * @freq_clip_max: maximum frequency allowed for this cooling state.
>> + * @temp_level: Temperature level at which the temperature clipping will
>> + *   happen.
>> + * @mask_val: cpumask of the allowed cpu's where the clipping will take place.
>> + *
>> + * This structure is required to be filled and passed to the
>> + * cpufreq_cooling_unregister function.
>> + */
>> +struct freq_clip_table {
>> +     unsigned int freq_clip_max;
>> +     unsigned int temp_level;
>> +     const struct cpumask *mask_val;
>> +};
>>  struct       thermal_trip_point_conf {
>>       int trip_val[MAX_TRIP_COUNT];
>>       int trip_count;
>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>> index 3de3e61..a02f2c9 100644
>> --- a/drivers/thermal/samsung/exynos_tmu.c
>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>> @@ -30,10 +30,10 @@
>>  #include <linux/mutex.h>
>>  #include <linux/of.h>
>>  #include <linux/platform_device.h>
>> -#include <linux/platform_data/exynos_thermal.h>
>>  #include <linux/slab.h>
>>  #include <linux/workqueue.h>
>>  #include "exynos_thermal_common.h"
>> +#include "exynos_tmu.h"
>>
>>  /* Exynos generic registers */
>>  #define EXYNOS_TMU_REG_TRIMINFO              0x0
>> diff --git a/include/linux/platform_data/exynos_thermal.h b/drivers/thermal/samsung/exynos_tmu.h
>> similarity index 88%
>> rename from include/linux/platform_data/exynos_thermal.h
>> rename to drivers/thermal/samsung/exynos_tmu.h
>> index da7e627..342fb1f 100644
>> --- a/include/linux/platform_data/exynos_thermal.h
>> +++ b/drivers/thermal/samsung/exynos_tmu.h
>> @@ -33,21 +33,6 @@ enum soc_type {
>>       SOC_ARCH_EXYNOS4210 = 1,
>>       SOC_ARCH_EXYNOS,
>>  };
>> -/**
>> - * struct freq_clip_table
>> - * @freq_clip_max: maximum frequency allowed for this cooling state.
>> - * @temp_level: Temperature level at which the temperature clipping will
>> - *   happen.
>> - * @mask_val: cpumask of the allowed cpu's where the clipping will take place.
>> - *
>> - * This structure is required to be filled and passed to the
>> - * cpufreq_cooling_unregister function.
>> - */
>> -struct freq_clip_table {
>> -     unsigned int freq_clip_max;
>> -     unsigned int temp_level;
>> -     const struct cpumask *mask_val;
>> -};
>>
>
> You explain why you need to rename the header, and thats what you do in
> this patch. On the other hand, you also move the freq_clip_table
> structure definition. This change is present in this patch, I dont see
> the connection with the file rename, and you also do not explain why it
> is needed. Can you please consider, either split this change to other
> (new) patch or explain it also in this patch?
Yes I forgot to add explanation here. This is done to fix compilation
issue when this header is moved. Basically struct freq_clip_table is a
candidate of common header and I have not included exynos_tmu.h into
exynos_thermal_common.h. Will provide a detailed explanation.

Thanks,
Amit
>
>
>>  /**
>>   * struct exynos_tmu_platform_data
>>
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 05/21] thermal: exynos: Bifurcate exynos tmu driver and configuration data
  2013-05-09 13:39     ` Eduardo Valentin
  (?)
@ 2013-05-10  2:05     ` amit daniel kachhap
  -1 siblings, 0 replies; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-10  2:05 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel, Kukjin Kim

Hi Eduardo,

On Thu, May 9, 2013 at 7:09 PM, Eduardo Valentin
<eduardo.valentin@ti.com> wrote:
> Hey Amit,
>
> On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
>> This code splits the exynos tmu driver code into SOC specific data parts.
>> This will simplify adding new SOC specific data to the same TMU controller.
>
> I like the idea of spliting the code from data. The driver goes into a
> self contained direction. Thanks for doing this.Couple of minor comments
> follows.
>
>>
>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>> ---
>>  drivers/thermal/samsung/Kconfig                 |   13 ++++-
>>  drivers/thermal/samsung/Makefile                |    1 +
>>  drivers/thermal/samsung/exynos_thermal_common.h |    3 +-
>>  drivers/thermal/samsung/exynos_tmu.c            |   67 +------------------
>>  drivers/thermal/samsung/exynos_tmu_data.c       |   78 +++++++++++++++++++++++
>>  drivers/thermal/samsung/exynos_tmu_data.h       |   41 ++++++++++++
>>  6 files changed, 137 insertions(+), 66 deletions(-)
>>  create mode 100644 drivers/thermal/samsung/exynos_tmu_data.c
>>  create mode 100644 drivers/thermal/samsung/exynos_tmu_data.h
>>
>> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
>> index 7857e20..f23f533 100644
>> --- a/drivers/thermal/samsung/Kconfig
>> +++ b/drivers/thermal/samsung/Kconfig
>> @@ -5,7 +5,8 @@ config EXYNOS_THERMAL
>>         If you say yes here you get support for the exynos thermal driver
>>         for exynos4 and exynos5 soc. This driver initialises the TMU, reports
>>         temperature and handles cooling action if defined. This driver uses
>> -       core thermal API's.
>> +       core thermal API's and TMU configuration data from the supported
>> +       soc's.
>>
>>  config EXYNOS_THERMAL_CORE
>>       bool "Core thermal framework support for EXYNOS SOC's"
>> @@ -15,3 +16,13 @@ config EXYNOS_THERMAL_CORE
>>         (Thermal Management Unit) common registration/unregistration
>>         functions to the core thermal layer and also to use the generic
>>         cpu cooling API's.
>> +
>> +config EXYNOS_THERMAL_DATA
>> +     bool "Temperature sensor congiguration data for EXYNOS series SOC"
>> +     depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250)
>> +     depends on EXYNOS_THERMAL
>> +     help
>> +       If you say yes here you can enable TMU (Thermal Management Unit) on
>> +       SAMSUNG EXYNOS 4210, 4412, 4414 and 5250 series of SoC. This option
>> +       enables/prepares the configuration, trip and cooling data for the TMU
>> +       driver.
>
> What is your strategy here? Looks like you want to provide all required
> data (for all supported SoCs) based on 1 config entry
> (EXYNOS_THERMAL_DATA). What do you think of having one per SoC supported?

Yesterday you gave a comment that introduce something like
ARCH_HAS_TMU so now each SOC if needed will enable this from the
platform Kconfig. In this scenario I will remove EXYNOS_THERMAL_DATA
as it is not required. Also having new Kconfig or each data file for
each SOC seems too much to me :) although they are logically correct.
In many cases different soc's share the same data(here 5250, 4412,
4212). For this re-structuring I feel a single file for data looks
fine.

Thanks,
Amit Daniel
>
>> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
>> index 22528d6..c0446e8 100644
>> --- a/drivers/thermal/samsung/Makefile
>> +++ b/drivers/thermal/samsung/Makefile
>> @@ -4,3 +4,4 @@
>>  obj-$(CONFIG_EXYNOS_THERMAL)                 += exynos_thermal.o
>>  exynos_thermal-y                             := exynos_tmu.o
>>  exynos_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
>> +exynos_thermal-$(CONFIG_EXYNOS_THERMAL_DATA) += exynos_tmu_data.o
>> diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
>> index 1c3f8b7..3b85858 100644
>> --- a/drivers/thermal/samsung/exynos_thermal_common.h
>> +++ b/drivers/thermal/samsung/exynos_thermal_common.h
>> @@ -62,7 +62,7 @@ struct freq_clip_table {
>>  struct       thermal_trip_point_conf {
>>       int trip_val[MAX_TRIP_COUNT];
>>       int trip_count;
>> -     u8 trigger_falling;
>> +     unsigned char trigger_falling;
>>  };
>
> Why do you need this change to bifurcate data / code? (Sounds like you
> probably want to send this in a separate patch, as it seams to be a
> separated issue).
>
>>
>>  struct       thermal_cooling_conf {
>> @@ -93,6 +93,5 @@ exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
>>
>>  static inline void
>>  exynos_report_trigger(void) { return; }
>> -
>
> I dont think this is realted to this patch.
>
>>  #endif /* CONFIG_EXYNOS_COMMON */
>>  #endif /* _LINUX_EXYNOS_THERMAL_COMMON_H */
>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>> index a02f2c9..05b5068 100644
>> --- a/drivers/thermal/samsung/exynos_tmu.c
>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>> @@ -34,6 +34,7 @@
>>  #include <linux/workqueue.h>
>>  #include "exynos_thermal_common.h"
>>  #include "exynos_tmu.h"
>> +#include "exynos_tmu_data.h"
>>
>>  /* Exynos generic registers */
>>  #define EXYNOS_TMU_REG_TRIMINFO              0x0
>> @@ -385,66 +386,6 @@ static struct thermal_sensor_conf exynos_sensor_conf = {
>>       .write_emul_temp        = exynos_tmu_set_emulation,
>>  };
>>
>> -#if defined(CONFIG_CPU_EXYNOS4210)
>> -static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>> -     .threshold = 80,
>> -     .trigger_levels[0] = 5,
>> -     .trigger_levels[1] = 20,
>> -     .trigger_levels[2] = 30,
>> -     .trigger_level0_en = 1,
>> -     .trigger_level1_en = 1,
>> -     .trigger_level2_en = 1,
>> -     .trigger_level3_en = 0,
>> -     .gain = 15,
>> -     .reference_voltage = 7,
>> -     .cal_type = TYPE_ONE_POINT_TRIMMING,
>> -     .freq_tab[0] = {
>> -             .freq_clip_max = 800 * 1000,
>> -             .temp_level = 85,
>> -     },
>> -     .freq_tab[1] = {
>> -             .freq_clip_max = 200 * 1000,
>> -             .temp_level = 100,
>> -     },
>> -     .freq_tab_count = 2,
>> -     .type = SOC_ARCH_EXYNOS4210,
>> -};
>> -#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
>> -#else
>> -#define EXYNOS4210_TMU_DRV_DATA (NULL)
>> -#endif
>> -
>> -#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
>> -static struct exynos_tmu_platform_data const exynos_default_tmu_data = {
>> -     .threshold_falling = 10,
>> -     .trigger_levels[0] = 85,
>> -     .trigger_levels[1] = 103,
>> -     .trigger_levels[2] = 110,
>> -     .trigger_level0_en = 1,
>> -     .trigger_level1_en = 1,
>> -     .trigger_level2_en = 1,
>> -     .trigger_level3_en = 0,
>> -     .gain = 8,
>> -     .reference_voltage = 16,
>> -     .noise_cancel_mode = 4,
>> -     .cal_type = TYPE_ONE_POINT_TRIMMING,
>> -     .efuse_value = 55,
>> -     .freq_tab[0] = {
>> -             .freq_clip_max = 800 * 1000,
>> -             .temp_level = 85,
>> -     },
>> -     .freq_tab[1] = {
>> -             .freq_clip_max = 200 * 1000,
>> -             .temp_level = 103,
>> -     },
>> -     .freq_tab_count = 2,
>> -     .type = SOC_ARCH_EXYNOS,
>> -};
>> -#define EXYNOS_TMU_DRV_DATA (&exynos_default_tmu_data)
>> -#else
>> -#define EXYNOS_TMU_DRV_DATA (NULL)
>> -#endif
>> -
>>  #ifdef CONFIG_OF
>>  static const struct of_device_id exynos_tmu_match[] = {
>>       {
>> @@ -453,11 +394,11 @@ static const struct of_device_id exynos_tmu_match[] = {
>>       },
>>       {
>>               .compatible = "samsung,exynos4412-tmu",
>> -             .data = (void *)EXYNOS_TMU_DRV_DATA,
>> +             .data = (void *)EXYNOS5250_TMU_DRV_DATA,
>>       },
>>       {
>>               .compatible = "samsung,exynos5250-tmu",
>> -             .data = (void *)EXYNOS_TMU_DRV_DATA,
>> +             .data = (void *)EXYNOS5250_TMU_DRV_DATA,
>>       },
>>       {},
>>  };
>> @@ -471,7 +412,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = {
>>       },
>>       {
>>               .name           = "exynos5250-tmu",
>> -             .driver_data    = (kernel_ulong_t)EXYNOS_TMU_DRV_DATA,
>> +             .driver_data    = (kernel_ulong_t)EXYNOS5250_TMU_DRV_DATA,
>>       },
>>       { },
>>  };
>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
>> new file mode 100644
>> index 0000000..13a60ca
>> --- /dev/null
>> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
>> @@ -0,0 +1,78 @@
>> +/*
>> + * exynos_tmu_data.c - Samsung EXYNOS tmu data file
>> + *
>> + *  Copyright (C) 2013 Samsung Electronics
>> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
>> + *
>> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
>> + *
>> + */
>> +
>> +#include "exynos_thermal_common.h"
>> +#include "exynos_tmu.h"
>> +
>> +#if defined(CONFIG_CPU_EXYNOS4210)
>> +struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>> +     .threshold = 80,
>> +     .trigger_levels[0] = 5,
>> +     .trigger_levels[1] = 20,
>> +     .trigger_levels[2] = 30,
>> +     .trigger_level0_en = 1,
>> +     .trigger_level1_en = 1,
>> +     .trigger_level2_en = 1,
>> +     .trigger_level3_en = 0,
>> +     .gain = 15,
>> +     .reference_voltage = 7,
>> +     .cal_type = TYPE_ONE_POINT_TRIMMING,
>> +     .freq_tab[0] = {
>> +             .freq_clip_max = 800 * 1000,
>> +             .temp_level = 85,
>> +     },
>> +     .freq_tab[1] = {
>> +             .freq_clip_max = 200 * 1000,
>> +             .temp_level = 100,
>> +     },
>> +     .freq_tab_count = 2,
>> +     .type = SOC_ARCH_EXYNOS4210,
>> +};
>> +#endif
>> +
>> +#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
>> +struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>> +     .threshold_falling = 10,
>> +     .trigger_levels[0] = 85,
>> +     .trigger_levels[1] = 103,
>> +     .trigger_levels[2] = 110,
>> +     .trigger_level0_en = 1,
>> +     .trigger_level1_en = 1,
>> +     .trigger_level2_en = 1,
>> +     .trigger_level3_en = 0,
>> +     .gain = 8,
>> +     .reference_voltage = 16,
>> +     .noise_cancel_mode = 4,
>> +     .cal_type = TYPE_ONE_POINT_TRIMMING,
>> +     .efuse_value = 55,
>> +     .freq_tab[0] = {
>> +             .freq_clip_max = 800 * 1000,
>> +             .temp_level = 85,
>> +     },
>> +     .freq_tab[1] = {
>> +             .freq_clip_max = 200 * 1000,
>> +             .temp_level = 103,
>> +     },
>> +     .freq_tab_count = 2,
>> +     .type = SOC_ARCH_EXYNOS,
>> +};
>> +#endif
>
> If you define config entries per SoC data, you could have a file per SoC
> data and remove the #ifdefery by solving the config in the Makefile.
> What do you think?
>
>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
>> new file mode 100644
>> index 0000000..5b69711
>> --- /dev/null
>> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
>> @@ -0,0 +1,41 @@
>> +/*
>> + * exynos_tmu_data.h - Samsung EXYNOS tmu data header file
>> + *
>> + *  Copyright (C) 2013 Samsung Electronics
>> + *  Amit Daniel Kachhap <amit.daniel@samsung.com>
>> + *
>> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
>> + *
>> + */
>> +
>> +#ifndef _LINUX_EXYNOS_TMU_DATA_H
>> +#define _LINUX_EXYNOS_TMU_DATA_H
>> +
> how about _EXYNOS_TMU_DATA_H ?
>
>
>
>> +#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>> +extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
>> +#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
>> +#else
>> +#define EXYNOS4210_TMU_DRV_DATA (NULL)
>> +#endif
>> +
>> +#if (defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)) && \
>> +defined(CONFIG_EXYNOS_THERMAL_DATA)
>> +extern struct exynos_tmu_platform_data const exynos5250_default_tmu_data;
>> +#define EXYNOS5250_TMU_DRV_DATA (&exynos5250_default_tmu_data)
>> +#else
>> +#define EXYNOS5250_TMU_DRV_DATA (NULL)
>> +#endif
>> +
>> +#endif /*_LINUX_EXYNOS_TMU_DATA_H*/
>>
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 06/21] thermal: exynos: Add missing definations and code cleanup
  2013-05-09 13:52     ` Eduardo Valentin
  (?)
@ 2013-05-10  2:12     ` amit daniel kachhap
  -1 siblings, 0 replies; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-10  2:12 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel, Kukjin Kim

Hi,

On Thu, May 9, 2013 at 7:22 PM, Eduardo Valentin
<eduardo.valentin@ti.com> wrote:
> Amit,
>
> On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
>> This patch adds some extra register bitfield definations and cleans
>> up the code to prepare for moving register macros and definations inside
>> the TMU data section.
>>
>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>> ---
>>  drivers/thermal/samsung/exynos_tmu.c |   62 +++++++++++++++++++++++++---------
>>  1 files changed, 46 insertions(+), 16 deletions(-)
>>
>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>> index 05b5068..a43afc4 100644
>> --- a/drivers/thermal/samsung/exynos_tmu.c
>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>> @@ -47,9 +47,12 @@
>>
>>  #define EXYNOS_TMU_TRIM_TEMP_MASK    0xff
>>  #define EXYNOS_TMU_GAIN_SHIFT                8
>> +#define EXYNOS_TMU_GAIN_MASK         0xf
>>  #define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
>> -#define EXYNOS_TMU_CORE_ON           3
>> -#define EXYNOS_TMU_CORE_OFF          2
>> +#define EXYNOS_TMU_REF_VOLTAGE_MASK  0x1f
>> +#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK        0xf
>> +#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT       8
>> +#define EXYNOS_TMU_CORE_EN_SHIFT     0
>>  #define EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET   50
>>
>>  /* Exynos4210 specific registers */
>> @@ -67,6 +70,7 @@
>>  #define EXYNOS4210_TMU_TRIG_LEVEL1_MASK      0x10
>>  #define EXYNOS4210_TMU_TRIG_LEVEL2_MASK      0x100
>>  #define EXYNOS4210_TMU_TRIG_LEVEL3_MASK      0x1000
>> +#define EXYNOS4210_TMU_TRIG_LEVEL_MASK       0x1111
>>  #define EXYNOS4210_TMU_INTCLEAR_VAL  0x1111
>>
>>  /* Exynos5250 and Exynos4412 specific registers */
>> @@ -76,17 +80,30 @@
>>  #define EXYNOS_EMUL_CON              0x80
>>
>>  #define EXYNOS_TRIMINFO_RELOAD               0x1
>> +#define EXYNOS_TRIMINFO_SHIFT                0x0
>> +#define EXYNOS_TMU_RISE_INT_MASK     0x111
>> +#define EXYNOS_TMU_RISE_INT_SHIFT    0
>> +#define EXYNOS_TMU_FALL_INT_MASK     0x111
>> +#define EXYNOS_TMU_FALL_INT_SHIFT    12
>>  #define EXYNOS_TMU_CLEAR_RISE_INT    0x111
>>  #define EXYNOS_TMU_CLEAR_FALL_INT    (0x111 << 12)
>> -#define EXYNOS_MUX_ADDR_VALUE                6
>> -#define EXYNOS_MUX_ADDR_SHIFT                20
>>  #define EXYNOS_TMU_TRIP_MODE_SHIFT   13
>> +#define EXYNOS_TMU_TRIP_MODE_MASK    0x7
>> +
>> +#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
>> +#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
>> +#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
>> +#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
>> +#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
>> +#define EXYNOS_TMU_INTEN_FALL1_SHIFT 20
>> +#define EXYNOS_TMU_INTEN_FALL2_SHIFT 24
>>
>>  #define EFUSE_MIN_VALUE 40
>>  #define EFUSE_MAX_VALUE 100
>>
>>  #ifdef CONFIG_THERMAL_EMULATION
>>  #define EXYNOS_EMUL_TIME     0x57F0
>> +#define EXYNOS_EMUL_TIME_MASK        0xffff
>>  #define EXYNOS_EMUL_TIME_SHIFT       16
>>  #define EXYNOS_EMUL_DATA_SHIFT       8
>>  #define EXYNOS_EMUL_DATA_MASK        0xFF
>
>
> What is the pattern above? Sometimes you use decimal notation sometimes
> you use hex notation. On a quick look I could not see a pattern..
For mask I have used hex and for shift I have used decimal as they
help looking at data sheet easily but I am not sure if there is any
coding guidelines for this.
>
>> @@ -265,24 +282,37 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>       mutex_lock(&data->lock);
>>       clk_enable(data->clk);
>>
>> -     con = pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT |
>> -             pdata->gain << EXYNOS_TMU_GAIN_SHIFT;
>> +     con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
>>
>
> You have a important change here. Before you would just apply a value
> based on your local configuration. Now you are considering what is
> present in your ctrl register. Is this really a code cleanup required
> for moving the register definitions?
My intention of doing it like this way is to use the default value
from the controller if no data value is passed. In case any data value
just use it.
>
>> -     if (data->soc == SOC_ARCH_EXYNOS) {
>> -             con |= pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT;
>> -             con |= (EXYNOS_MUX_ADDR_VALUE << EXYNOS_MUX_ADDR_SHIFT);
>> +     if (pdata->reference_voltage) {
>> +             con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK <<
>> +                             EXYNOS_TMU_REF_VOLTAGE_SHIFT);
>> +             con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
>> +     }
>> +
>> +     if (pdata->gain) {
>> +             con &= ~(EXYNOS_TMU_GAIN_MASK << EXYNOS_TMU_GAIN_SHIFT);
>> +             con |= (pdata->gain << EXYNOS_TMU_GAIN_SHIFT);
>> +     }
>> +
>> +     if (pdata->noise_cancel_mode) {
>> +             con &= ~(EXYNOS_TMU_TRIP_MODE_MASK <<
>> +                                     EXYNOS_TMU_TRIP_MODE_SHIFT);
>> +             con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
>
> For all the above ifs: Dont you want to clear those bits in case the
> pdata config says those flags are not set? For instance, if pdata->gain
> == 0, do you need to con &= ~(EXYNOS_TMU_GAIN_MASK <<
> EXYNOS_TMU_GAIN_SHIFT); ??
if data value is not passed I want to retain the default value and not clear it.

Thanks,
Amit Daniel
>
>>       }
>>
>>       if (on) {
>> -             con |= EXYNOS_TMU_CORE_ON;
>> -             interrupt_en = pdata->trigger_level3_en << 12 |
>> -                     pdata->trigger_level2_en << 8 |
>> -                     pdata->trigger_level1_en << 4 |
>> -                     pdata->trigger_level0_en;
>> +             con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
>> +             interrupt_en =
>> +             pdata->trigger_level3_en << EXYNOS_TMU_INTEN_RISE3_SHIFT |
>> +             pdata->trigger_level2_en << EXYNOS_TMU_INTEN_RISE2_SHIFT |
>> +             pdata->trigger_level1_en << EXYNOS_TMU_INTEN_RISE1_SHIFT |
>> +             pdata->trigger_level0_en << EXYNOS_TMU_INTEN_RISE0_SHIFT;
>>               if (pdata->threshold_falling)
>> -                     interrupt_en |= interrupt_en << 16;
>> +                     interrupt_en |=
>> +                             interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
>>       } else {
>> -             con |= EXYNOS_TMU_CORE_OFF;
>> +             con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
>>               interrupt_en = 0; /* Disable all interrupts */
>>       }
>>       writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
>>
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 09/21] thermal: exynos: Move register definitions from driver file to data file
  2013-05-09 14:32     ` Eduardo Valentin
  (?)
@ 2013-05-10  2:17     ` amit daniel kachhap
  2013-05-10 14:14         ` Eduardo Valentin
  -1 siblings, 1 reply; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-10  2:17 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel, Kukjin Kim

Hi Eduardo,

On Thu, May 9, 2013 at 8:02 PM, Eduardo Valentin
<eduardo.valentin@ti.com> wrote:
> Hey Amit,
>
> On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
>> This patch migrates the TMU register definition/bitfields to data file. This
>> is needed to support SoC's which use the same TMU controller but register
>> validity, offsets or bitfield may slightly vary across SOC's.
>>
>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>> ---
>>  drivers/thermal/samsung/exynos_tmu.c      |  177 +++++++++-------------------
>>  drivers/thermal/samsung/exynos_tmu.h      |   76 ++++++++++++
>>  drivers/thermal/samsung/exynos_tmu_data.c |   59 ++++++++++
>>  drivers/thermal/samsung/exynos_tmu_data.h |   68 +++++++++++
>>  4 files changed, 260 insertions(+), 120 deletions(-)
>>
>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>> index 23baeeb..97b87aa 100644
>> --- a/drivers/thermal/samsung/exynos_tmu.c
>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>> @@ -36,77 +36,6 @@
>>  #include "exynos_tmu.h"
>>  #include "exynos_tmu_data.h"
>>
>> -/* Exynos generic registers */
>> -#define EXYNOS_TMU_REG_TRIMINFO              0x0
>> -#define EXYNOS_TMU_REG_CONTROL               0x20
>> -#define EXYNOS_TMU_REG_STATUS                0x28
>> -#define EXYNOS_TMU_REG_CURRENT_TEMP  0x40
>> -#define EXYNOS_TMU_REG_INTEN         0x70
>> -#define EXYNOS_TMU_REG_INTSTAT               0x74
>> -#define EXYNOS_TMU_REG_INTCLEAR              0x78
>> -
>> -#define EXYNOS_TMU_TRIM_TEMP_MASK    0xff
>> -#define EXYNOS_TMU_GAIN_SHIFT                8
>> -#define EXYNOS_TMU_GAIN_MASK         0xf
>> -#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
>> -#define EXYNOS_TMU_REF_VOLTAGE_MASK  0x1f
>> -#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK        0xf
>> -#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT       8
>> -#define EXYNOS_TMU_CORE_EN_SHIFT     0
>> -
>> -/* Exynos4210 specific registers */
>> -#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP    0x44
>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL0       0x50
>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL1       0x54
>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL2       0x58
>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL3       0x5C
>> -#define EXYNOS4210_TMU_REG_PAST_TEMP0        0x60
>> -#define EXYNOS4210_TMU_REG_PAST_TEMP1        0x64
>> -#define EXYNOS4210_TMU_REG_PAST_TEMP2        0x68
>> -#define EXYNOS4210_TMU_REG_PAST_TEMP3        0x6C
>> -
>> -#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK      0x1
>> -#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK      0x10
>> -#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK      0x100
>> -#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK      0x1000
>> -#define EXYNOS4210_TMU_TRIG_LEVEL_MASK       0x1111
>> -#define EXYNOS4210_TMU_INTCLEAR_VAL  0x1111
>> -
>> -/* Exynos5250 and Exynos4412 specific registers */
>> -#define EXYNOS_TMU_TRIMINFO_CON      0x14
>> -#define EXYNOS_THD_TEMP_RISE         0x50
>> -#define EXYNOS_THD_TEMP_FALL         0x54
>> -#define EXYNOS_EMUL_CON              0x80
>> -
>> -#define EXYNOS_TRIMINFO_RELOAD               0x1
>> -#define EXYNOS_TRIMINFO_SHIFT                0x0
>> -#define EXYNOS_TMU_RISE_INT_MASK     0x111
>> -#define EXYNOS_TMU_RISE_INT_SHIFT    0
>> -#define EXYNOS_TMU_FALL_INT_MASK     0x111
>> -#define EXYNOS_TMU_FALL_INT_SHIFT    12
>> -#define EXYNOS_TMU_CLEAR_RISE_INT    0x111
>> -#define EXYNOS_TMU_CLEAR_FALL_INT    (0x111 << 12)
>> -#define EXYNOS_TMU_TRIP_MODE_SHIFT   13
>> -#define EXYNOS_TMU_TRIP_MODE_MASK    0x7
>> -#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT       12
>> -
>> -#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
>> -#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
>> -#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
>> -#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
>> -#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
>> -#define EXYNOS_TMU_INTEN_FALL1_SHIFT 20
>> -#define EXYNOS_TMU_INTEN_FALL2_SHIFT 24
>> -
>> -#ifdef CONFIG_THERMAL_EMULATION
>> -#define EXYNOS_EMUL_TIME     0x57F0
>> -#define EXYNOS_EMUL_TIME_MASK        0xffff
>> -#define EXYNOS_EMUL_TIME_SHIFT       16
>> -#define EXYNOS_EMUL_DATA_SHIFT       8
>> -#define EXYNOS_EMUL_DATA_MASK        0xFF
>> -#define EXYNOS_EMUL_ENABLE   0x1
>> -#endif /* CONFIG_THERMAL_EMULATION */
>> -
>>  struct exynos_tmu_data {
>>       struct exynos_tmu_platform_data *pdata;
>>       struct resource *mem;
>> @@ -191,6 +120,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>  {
>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>       unsigned int status, trim_info, con;
>>       unsigned int rising_threshold = 0, falling_threshold = 0;
>>       int ret = 0, threshold_code, i, trigger_levs = 0;
>> @@ -198,20 +128,20 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>       mutex_lock(&data->lock);
>>       clk_enable(data->clk);
>>
>> -     status = readb(data->base + EXYNOS_TMU_REG_STATUS);
>> +     status = readb(data->base + reg->tmu_status);
>>       if (!status) {
>>               ret = -EBUSY;
>>               goto out;
>>       }
>>
>> -     if (data->soc == SOC_ARCH_EXYNOS) {
>> -             __raw_writel(EXYNOS_TRIMINFO_RELOAD,
>> -                             data->base + EXYNOS_TMU_TRIMINFO_CON);
>> -     }
>> +     if (data->soc == SOC_ARCH_EXYNOS)
>> +             __raw_writel(1, data->base + reg->triminfo_ctrl);
>> +
>>       /* Save trimming info in order to perform calibration */
>> -     trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
>> -     data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
>> -     data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
>> +     trim_info = readl(data->base + reg->triminfo_data);
>> +     data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
>> +     data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
>> +                             EXYNOS_TMU_TEMP_MASK);
>
> You changed from EXYNOS_TMU_TRIM_TEMP_MASK to EXYNOS_TMU_TEMP_MASK. Was
> it this really what you wanted?
Actually temp masks are same so removed  EXYNOS_TMU_TRIM_TEMP_MASK.
>
>>
>>       if ((pdata->min_efuse_value > data->temp_error1) ||
>>                       (data->temp_error1 > pdata->max_efuse_value) ||
>> @@ -231,13 +161,12 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>                       goto out;
>>               }
>>               writeb(threshold_code,
>> -                     data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
>> +                     data->base + reg->threshold_temp);
>>               for (i = 0; i < trigger_levs; i++)
>>                       writeb(pdata->trigger_levels[i],
>> -                     data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
>> +                     data->base + reg->threshold_th0 + i * 4);
>>
>
> Is 4 your addressing unit? I believe there is a macro definition for this.
yes 4 is a addressing unit. This is only used for 1 SOC so didn't define macro.
>
>> -             writel(EXYNOS4210_TMU_INTCLEAR_VAL,
>> -                     data->base + EXYNOS_TMU_REG_INTCLEAR);
>> +             writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>>       } else if (data->soc == SOC_ARCH_EXYNOS) {
>>               /* Write temperature code for rising and falling threshold */
>>               for (i = 0; i < trigger_levs; i++) {
>> @@ -258,18 +187,19 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>                       }
>>                       if (pdata->trigger_type[i] != HW_TRIP)
>>                               continue;
>> -                     con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
>> -                     con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
>> -                     writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
>> +                     con = readl(data->base + reg->tmu_ctrl);
>> +                     con |= (1 << reg->therm_trip_en_shift);
>> +                     writel(con, data->base + reg->tmu_ctrl);
>>               }
>>
>>               writel(rising_threshold,
>> -                             data->base + EXYNOS_THD_TEMP_RISE);
>> +                             data->base + reg->threshold_th0);
>>               writel(falling_threshold,
>> -                             data->base + EXYNOS_THD_TEMP_FALL);
>> +                             data->base + reg->threshold_th1);
>>
>> -             writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
>> -                             data->base + EXYNOS_TMU_REG_INTCLEAR);
>> +             writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>> +                     (reg->inten_fall_mask << reg->inten_fall_shift),
>> +                             data->base + reg->tmu_intclear);
>>       }
>>  out:
>>       clk_disable(data->clk);
>> @@ -282,46 +212,46 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>  {
>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>       unsigned int con, interrupt_en;
>>
>>       mutex_lock(&data->lock);
>>       clk_enable(data->clk);
>>
>> -     con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
>> +     con = readl(data->base + reg->tmu_ctrl);
>>
>>       if (pdata->reference_voltage) {
>> -             con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK <<
>> -                             EXYNOS_TMU_REF_VOLTAGE_SHIFT);
>> -             con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
>> +             con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
>> +             con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
>>       }
>>
>>       if (pdata->gain) {
>> -             con &= ~(EXYNOS_TMU_GAIN_MASK << EXYNOS_TMU_GAIN_SHIFT);
>> -             con |= (pdata->gain << EXYNOS_TMU_GAIN_SHIFT);
>> +             con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
>> +             con |= (pdata->gain << reg->buf_slope_sel_shift);
>>       }
>>
>>       if (pdata->noise_cancel_mode) {
>> -             con &= ~(EXYNOS_TMU_TRIP_MODE_MASK <<
>> -                                     EXYNOS_TMU_TRIP_MODE_SHIFT);
>> -             con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
>> +             con &= ~(reg->therm_trip_mode_mask <<
>> +                                     reg->therm_trip_mode_shift);
>> +             con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
>>       }
>>
>>       if (on) {
>> -             con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
>> +             con |= (1 << reg->core_en_shift);
>>               interrupt_en =
>> -             pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT |
>> -             pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT |
>> -             pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT |
>> -             pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT;
>> +                     pdata->trigger_enable[3] << reg->inten_rise3_shift |
>> +                     pdata->trigger_enable[2] << reg->inten_rise2_shift |
>> +                     pdata->trigger_enable[1] << reg->inten_rise1_shift |
>> +                     pdata->trigger_enable[0] << reg->inten_rise0_shift;
>>               if (pdata->threshold_falling)
>>                       interrupt_en |=
>> -                             interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
>> +                             interrupt_en << reg->inten_fall0_shift;
>>       } else {
>> -             con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
>> +             con &= ~(1 << reg->core_en_shift);
>>               interrupt_en = 0; /* Disable all interrupts */
>>       }
>> -     writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
>> -     writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
>> +     writel(interrupt_en, data->base + reg->tmu_inten);
>> +     writel(con, data->base + reg->tmu_ctrl);
>>
>>       clk_disable(data->clk);
>>       mutex_unlock(&data->lock);
>> @@ -329,13 +259,15 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>
>>  static int exynos_tmu_read(struct exynos_tmu_data *data)
>>  {
>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>       u8 temp_code;
>>       int temp;
>>
>>       mutex_lock(&data->lock);
>>       clk_enable(data->clk);
>>
>> -     temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
>> +     temp_code = readb(data->base + reg->tmu_cur_temp);
>>       temp = code_to_temp(data, temp_code);
>>
>>       clk_disable(data->clk);
>> @@ -348,7 +280,9 @@ static int exynos_tmu_read(struct exynos_tmu_data *data)
>>  static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>>  {
>>       struct exynos_tmu_data *data = drv_data;
>> -     unsigned int reg;
>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>> +     struct exynos_tmu_registers *reg = pdata->registers;
>> +     unsigned int val;
>>       int ret = -EINVAL;
>>
>>       if (data->soc == SOC_ARCH_EXYNOS4210)
>> @@ -360,19 +294,19 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>>       mutex_lock(&data->lock);
>>       clk_enable(data->clk);
>>
>> -     reg = readl(data->base + EXYNOS_EMUL_CON);
>> +     val = readl(data->base + reg->emul_con);
>>
>>       if (temp) {
>>               temp /= MCELSIUS;
>>
>> -             reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
>> +             val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
>>                       (temp_to_code(data, temp)
>> -                      << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
>> +                      << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
>>       } else {
>> -             reg &= ~EXYNOS_EMUL_ENABLE;
>> +             val &= ~EXYNOS_EMUL_ENABLE;
>>       }
>>
>> -     writel(reg, data->base + EXYNOS_EMUL_CON);
>> +     writel(val, data->base + reg->emul_con);
>>
>>       clk_disable(data->clk);
>>       mutex_unlock(&data->lock);
>> @@ -389,17 +323,20 @@ static void exynos_tmu_work(struct work_struct *work)
>>  {
>>       struct exynos_tmu_data *data = container_of(work,
>>                       struct exynos_tmu_data, irq_work);
>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>
>>       exynos_report_trigger();
>>       mutex_lock(&data->lock);
>>       clk_enable(data->clk);
>> +
>>       if (data->soc == SOC_ARCH_EXYNOS)
>> -             writel(EXYNOS_TMU_CLEAR_RISE_INT |
>> -                             EXYNOS_TMU_CLEAR_FALL_INT,
>> -                             data->base + EXYNOS_TMU_REG_INTCLEAR);
>> +             writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>> +                     (reg->inten_fall_mask << reg->inten_fall_shift),
>> +                             data->base + reg->tmu_intclear);
>>       else
>> -             writel(EXYNOS4210_TMU_INTCLEAR_VAL,
>> -                             data->base + EXYNOS_TMU_REG_INTCLEAR);
>> +             writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>> +
>>       clk_disable(data->clk);
>>       mutex_unlock(&data->lock);
>>
>> diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
>> index 70cc518..1e5e492 100644
>> --- a/drivers/thermal/samsung/exynos_tmu.h
>> +++ b/drivers/thermal/samsung/exynos_tmu.h
>> @@ -46,6 +46,81 @@ enum soc_type {
>>  };
>>
>>  /**
>> + * struct exynos_tmu_register - register descriptors to access registers and
>> + * bitfields. The register validity, offsets and bitfield values may vary
>> + * slightly across different exynos SOC's.
>
> No documentation for your registers? Or at least where to find explanation?
yes didn't write documentation. Will do it.
>
>> + */
>> +struct exynos_tmu_registers {
>> +     u32     triminfo_data;
>> +     u32     triminfo_25_shift;
>> +     u32     triminfo_85_shift;
>> +
>> +     u32     triminfo_ctrl;
>> +     u32     triminfo_reload_shift;
>> +
>> +     u32     tmu_ctrl;
>> +     u32     buf_vref_sel_shift;
>> +     u32     buf_vref_sel_mask;
>> +     u32     therm_trip_mode_shift;
>> +     u32     therm_trip_mode_mask;
>> +     u32     therm_trip_en_shift;
>> +     u32     buf_slope_sel_shift;
>> +     u32     buf_slope_sel_mask;
>> +     u32     therm_trip_tq_en_shift;
>> +     u32     core_en_shift;
>> +
>> +     u32     tmu_status;
>> +
>> +     u32     tmu_cur_temp;
>> +     u32     tmu_cur_temp_shift;
>> +
>> +     u32     threshold_temp;
>> +
>> +     u32     threshold_th0;
>> +     u32     threshold_th0_l0_shift;
>> +     u32     threshold_th0_l1_shift;
>> +     u32     threshold_th0_l2_shift;
>> +     u32     threshold_th0_l3_shift;
>> +
>> +     u32     threshold_th1;
>> +     u32     threshold_th1_l0_shift;
>> +     u32     threshold_th1_l1_shift;
>> +     u32     threshold_th1_l2_shift;
>> +     u32     threshold_th1_l3_shift;
>> +
>> +     u32     threshold_th2;
>> +     u32     threshold_th2_l0_shift;
>> +
>> +     u32     threshold_th3;
>> +     u32     threshold_th3_l0_shift;
>> +
>> +     u32     tmu_inten;
>> +     u32     inten_rise_shift;
>> +     u32     inten_rise_mask;
>> +     u32     inten_fall_shift;
>> +     u32     inten_fall_mask;
>> +     u32     inten_rise0_shift;
>> +     u32     inten_rise1_shift;
>> +     u32     inten_rise2_shift;
>> +     u32     inten_rise3_shift;
>> +     u32     inten_fall0_shift;
>> +     u32     inten_fall1_shift;
>> +     u32     inten_fall2_shift;
>> +     u32     inten_fall3_shift;
>> +
>> +     u32     tmu_intstat;
>> +
>> +     u32     tmu_intclear;
>> +
>> +     u32     tmu_evten;
>> +
>> +     u32     emul_con;
>> +     u32     emul_temp_shift;
>> +     u32     emul_time_shift;
>> +     u32     emul_time_mask;
>> +};
>> +
>> +/**
>>   * struct exynos_tmu_platform_data
>>   * @threshold: basic temperature for generating interrupt
>>   *          25 <= threshold <= 125 [unit: degree Celsius]
>> @@ -116,5 +191,6 @@ struct exynos_tmu_platform_data {
>>       enum soc_type type;
>>       struct freq_clip_table freq_tab[4];
>>       unsigned int freq_tab_count;
>> +     struct exynos_tmu_registers *registers;
>>  };
>>  #endif /* _LINUX_EXYNOS_THERMAL_H */
>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
>> index 6b937f5..3a1ded1 100644
>> --- a/drivers/thermal/samsung/exynos_tmu_data.c
>> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
>> @@ -25,6 +25,28 @@
>>  #include "exynos_tmu_data.h"
>>
>>  #if defined(CONFIG_CPU_EXYNOS4210)
>> +static struct exynos_tmu_registers exynos4210_tmu_registers = {
>> +     .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
>> +     .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
>> +     .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
>> +     .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
>> +     .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
>> +     .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
>> +     .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
>> +     .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
>> +     .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
>> +     .tmu_status = EXYNOS_TMU_REG_STATUS,
>> +     .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
>> +     .threshold_temp = EXYNOS4210_TMU_REG_THRESHOLD_TEMP,
>> +     .threshold_th0 = EXYNOS4210_TMU_REG_TRIG_LEVEL0,
>> +     .tmu_inten = EXYNOS_TMU_REG_INTEN,
>> +     .inten_rise_mask = EXYNOS4210_TMU_TRIG_LEVEL_MASK,
>> +     .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
>> +     .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>> +     .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>> +     .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>> +     .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>> +};
>>  struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>       .threshold = 80,
>>       .trigger_levels[0] = 5,
>> @@ -55,10 +77,46 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>       },
>>       .freq_tab_count = 2,
>>       .type = SOC_ARCH_EXYNOS4210,
>> +     .registers = &exynos4210_tmu_registers,
>>  };
>>  #endif
>>
>>  #if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
>> +static struct exynos_tmu_registers exynos5250_tmu_registers = {
>> +     .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
>> +     .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
>> +     .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
>> +     .triminfo_ctrl = EXYNOS_TMU_TRIMINFO_CON,
>> +     .triminfo_reload_shift = EXYNOS_TRIMINFO_RELOAD_SHIFT,
>> +     .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
>> +     .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
>> +     .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
>> +     .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
>> +     .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
>> +     .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
>> +     .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
>> +     .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
>> +     .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
>> +     .tmu_status = EXYNOS_TMU_REG_STATUS,
>> +     .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
>> +     .threshold_th0 = EXYNOS_THD_TEMP_RISE,
>> +     .threshold_th1 = EXYNOS_THD_TEMP_FALL,
>> +     .tmu_inten = EXYNOS_TMU_REG_INTEN,
>> +     .inten_rise_mask = EXYNOS_TMU_RISE_INT_MASK,
>> +     .inten_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
>> +     .inten_fall_mask = EXYNOS_TMU_FALL_INT_MASK,
>> +     .inten_fall_shift = EXYNOS_TMU_FALL_INT_SHIFT,
>> +     .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
>> +     .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>> +     .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>> +     .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>> +     .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
>> +     .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>> +     .emul_con = EXYNOS_EMUL_CON,
>> +     .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
>> +     .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
>> +     .emul_time_mask = EXYNOS_EMUL_TIME_MASK,
>> +};
>>  struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>>       .threshold_falling = 10,
>>       .trigger_levels[0] = 85,
>> @@ -93,5 +151,6 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>>       },
>>       .freq_tab_count = 2,
>>       .type = SOC_ARCH_EXYNOS,
>> +     .registers = &exynos5250_tmu_registers,
>>  };
>>  #endif
>
> One thing, I believe your data can be declared as const.
yes they are already const.

Thanks,
Amit Daniel
>
>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
>> index 5b69711..0560413 100644
>> --- a/drivers/thermal/samsung/exynos_tmu_data.h
>> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
>> @@ -23,6 +23,74 @@
>>  #ifndef _LINUX_EXYNOS_TMU_DATA_H
>>  #define _LINUX_EXYNOS_TMU_DATA_H
>>
>> +/* Exynos generic registers */
>> +#define EXYNOS_TMU_REG_TRIMINFO              0x0
>> +#define EXYNOS_TMU_REG_CONTROL               0x20
>> +#define EXYNOS_TMU_REG_STATUS                0x28
>> +#define EXYNOS_TMU_REG_CURRENT_TEMP  0x40
>> +#define EXYNOS_TMU_REG_INTEN         0x70
>> +#define EXYNOS_TMU_REG_INTSTAT               0x74
>> +#define EXYNOS_TMU_REG_INTCLEAR              0x78
>> +
>> +#define EXYNOS_TMU_TEMP_MASK         0xff
>> +#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
>> +#define EXYNOS_TMU_REF_VOLTAGE_MASK  0x1f
>> +#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK        0xf
>> +#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT       8
>> +#define EXYNOS_TMU_CORE_EN_SHIFT     0
>> +
>> +/* Exynos4210 specific registers */
>> +#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP    0x44
>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL0       0x50
>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL1       0x54
>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL2       0x58
>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL3       0x5C
>> +#define EXYNOS4210_TMU_REG_PAST_TEMP0        0x60
>> +#define EXYNOS4210_TMU_REG_PAST_TEMP1        0x64
>> +#define EXYNOS4210_TMU_REG_PAST_TEMP2        0x68
>> +#define EXYNOS4210_TMU_REG_PAST_TEMP3        0x6C
>> +
>> +#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK      0x1
>> +#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK      0x10
>> +#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK      0x100
>> +#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK      0x1000
>> +#define EXYNOS4210_TMU_TRIG_LEVEL_MASK       0x1111
>> +#define EXYNOS4210_TMU_INTCLEAR_VAL  0x1111
>> +
>> +/* Exynos5250 and Exynos4412 specific registers */
>> +#define EXYNOS_TMU_TRIMINFO_CON      0x14
>> +#define EXYNOS_THD_TEMP_RISE         0x50
>> +#define EXYNOS_THD_TEMP_FALL         0x54
>> +#define EXYNOS_EMUL_CON              0x80
>> +
>> +#define EXYNOS_TRIMINFO_RELOAD_SHIFT 1
>> +#define EXYNOS_TRIMINFO_25_SHIFT     0
>> +#define EXYNOS_TRIMINFO_85_SHIFT     8
>> +#define EXYNOS_TMU_RISE_INT_MASK     0x111
>> +#define EXYNOS_TMU_RISE_INT_SHIFT    0
>> +#define EXYNOS_TMU_FALL_INT_MASK     0x111
>> +#define EXYNOS_TMU_FALL_INT_SHIFT    12
>> +#define EXYNOS_TMU_CLEAR_RISE_INT    0x111
>> +#define EXYNOS_TMU_CLEAR_FALL_INT    (0x111 << 12)
>> +#define EXYNOS_TMU_TRIP_MODE_SHIFT   13
>> +#define EXYNOS_TMU_TRIP_MODE_MASK    0x7
>> +#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT       12
>> +
>> +#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
>> +#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
>> +#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
>> +#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
>> +#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
>> +#define EXYNOS_TMU_INTEN_FALL1_SHIFT 20
>> +#define EXYNOS_TMU_INTEN_FALL2_SHIFT 24
>> +
>> +#define EXYNOS_EMUL_TIME     0x57F0
>> +#define EXYNOS_EMUL_TIME_MASK        0xffff
>> +#define EXYNOS_EMUL_TIME_SHIFT       16
>> +#define EXYNOS_EMUL_DATA_SHIFT       8
>> +#define EXYNOS_EMUL_DATA_MASK        0xFF
>> +#define EXYNOS_EMUL_ENABLE   0x1
>> +
>>  #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>>  extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
>>  #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
>>
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 10/21] thermal: exynos: Fix to clear only the generated interrupts
  2013-05-09 14:33     ` Eduardo Valentin
  (?)
@ 2013-05-10  2:22     ` amit daniel kachhap
  2013-05-10 15:40         ` Eduardo Valentin
  -1 siblings, 1 reply; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-10  2:22 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel, Kukjin Kim

Hi,

On Thu, May 9, 2013 at 8:03 PM, Eduardo Valentin
<eduardo.valentin@ti.com> wrote:
> On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
>> This patch uses the TMU status register to know the generated interrupts
>> and only clear them in the interrupt handler.
>>
>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>> ---
>>  drivers/thermal/samsung/exynos_tmu.c      |   10 ++++------
>>  drivers/thermal/samsung/exynos_tmu_data.c |    2 ++
>>  2 files changed, 6 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>> index 97b87aa..082d5a2 100644
>> --- a/drivers/thermal/samsung/exynos_tmu.c
>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>> @@ -325,17 +325,15 @@ static void exynos_tmu_work(struct work_struct *work)
>>                       struct exynos_tmu_data, irq_work);
>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>       struct exynos_tmu_registers *reg = pdata->registers;
>> +     unsigned int val_irq;
>>
>>       exynos_report_trigger();
>>       mutex_lock(&data->lock);
>>       clk_enable(data->clk);
>>
>> -     if (data->soc == SOC_ARCH_EXYNOS)
>> -             writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>> -                     (reg->inten_fall_mask << reg->inten_fall_shift),
>> -                             data->base + reg->tmu_intclear);
>> -     else
>> -             writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>> +     val_irq = readl(data->base + reg->tmu_intstat);
>> +     /* clear the interrupts */
>> +     writel(val_irq, data->base + reg->tmu_intclear);
>>
>
> hmmm.. Don t you need to act accordingly depending on what is in your
> int status?

Earlier also it is done like this way. Basically core thermal layer
checks temp for each trip so even if I check for which threshold
interrupt is raised it is of no use. Anyway this is a TODO for me.

Thanks,
Amit Daniel
>
>>       clk_disable(data->clk);
>>       mutex_unlock(&data->lock);
>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
>> index 3a1ded1..7322597 100644
>> --- a/drivers/thermal/samsung/exynos_tmu_data.c
>> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
>> @@ -45,6 +45,7 @@ static struct exynos_tmu_registers exynos4210_tmu_registers = {
>>       .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>>       .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>       .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>> +     .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
>>       .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>  };
>>  struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>> @@ -111,6 +112,7 @@ static struct exynos_tmu_registers exynos5250_tmu_registers = {
>>       .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>       .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>       .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
>> +     .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
>>       .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>       .emul_con = EXYNOS_EMUL_CON,
>>       .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
>>
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 20/21] thermal: exynos: Support for TMU regulator defined at device tree
  2013-05-09 14:44     ` Eduardo Valentin
  (?)
@ 2013-05-10  2:28     ` amit daniel kachhap
  2013-05-10 16:05         ` Eduardo Valentin
  -1 siblings, 1 reply; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-10  2:28 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel, Kukjin Kim

Hi Eduardo,

On Thu, May 9, 2013 at 8:14 PM, Eduardo Valentin
<eduardo.valentin@ti.com> wrote:
> On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
>> TMU probe function now checks for a device tree defined regulator.
>> For compatibility reasons it is allowed to probe driver even without
>> this regulator defined.
>>
>> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>> ---
>>  .../devicetree/bindings/thermal/exynos-thermal.txt |    4 ++++
>>  drivers/thermal/samsung/exynos_tmu.c               |   19 +++++++++++++++++++
>>  2 files changed, 23 insertions(+), 0 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>> index 970eeba..ff62f7a 100644
>> --- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>> +++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>> @@ -14,6 +14,9 @@
>>  - interrupts : Should contain interrupt for thermal system
>>  - clocks : The main clock for TMU device
>>  - clock-names : Thermal system clock name
>> +- vtmu-supply: This entry is optional and provides the regulator node supplying
>> +             voltage to TMU. If needed this entry can be placed inside
>> +             board/platform specific dts file.
>>
>>  Example 1):
>>
>> @@ -25,6 +28,7 @@ Example 1):
>>               clocks = <&clock 383>;
>>               clock-names = "tmu_apbif";
>>               status = "disabled";
>> +             vtmu-supply = <&tmu_regulator_node>;
>>       };
>>
>>  Example 2):
>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>> index 72446c9..b7c609a 100644
>> --- a/drivers/thermal/samsung/exynos_tmu.c
>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>> @@ -32,6 +32,7 @@
>>  #include <linux/of_address.h>
>>  #include <linux/of_irq.h>
>>  #include <linux/platform_device.h>
>> +#include <linux/regulator/consumer.h>
>>  #include <linux/slab.h>
>>  #include <linux/workqueue.h>
>>  #include "exynos_thermal_common.h"
>> @@ -52,6 +53,7 @@
>>   * @clk: pointer to the clock structure.
>>   * @temp_error1: fused value of the first point trim.
>>   * @temp_error2: fused value of the second point trim.
>> + * @regulator: pointer to the TMU regulator structure.
>>   * @reg_conf: pointer to structure to register with core thermal.
>>   */
>>  struct exynos_tmu_data {
>> @@ -65,6 +67,7 @@ struct exynos_tmu_data {
>>       struct mutex lock;
>>       struct clk *clk;
>>       u8 temp_error1, temp_error2;
>> +     struct regulator *regulator;
>>       struct thermal_sensor_conf *reg_conf;
>>  };
>>
>> @@ -501,10 +504,23 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>       struct resource res;
>> +     int ret;
>>
>>       if (!data)
>>               return -ENODEV;
>>
>> +     /* Try enabling the regulator if found */
>> +     data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
>> +     if (!IS_ERR(data->regulator)) {
>> +             ret = regulator_enable(data->regulator);
>> +             if (ret) {
>> +                     dev_err(&pdev->dev, "failed to enable vtmu\n");
>> +                     return ret;
>> +             }
>> +     } else {
>> +             dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
>
> Now that you have a bitfield for your features, shouldnt this become a
> check? If the SoC requires the regulator, then it has to return a valid
> regulator (regulator_get). Meaning, if your SoC version requires this
> feature and the regulator_get returns an error, you must treat as an
> error an not continue gracefuly.

Earlier I also thought of using bit feature for this but then the
regulator source usually depends upon the board design so each soc may
have several boards. So regulator information is not part of SOC data.
Since this information is there is in DT only so I left this part for
the DT to handle.

Thanks,
Amit Daniel
>
>> +     }
>> +
>>       data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
>>       if (data->id < 0)
>>               data->id = 0;
>> @@ -669,6 +685,9 @@ static int exynos_tmu_remove(struct platform_device *pdev)
>>
>>       clk_unprepare(data->clk);
>>
>> +     if (!IS_ERR(data->regulator))
>> +             regulator_disable(data->regulator);
>> +
>>       platform_set_drvdata(pdev, NULL);
>>
>>       return 0;
>>
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 18/21] thermal: exynos: Add support for exynos5440 TMU sensor.
  2013-05-09 14:47     ` Eduardo Valentin
  (?)
@ 2013-05-10  2:31     ` amit daniel kachhap
  2013-05-10 14:14         ` Eduardo Valentin
  -1 siblings, 1 reply; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-10  2:31 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel, Kukjin Kim

Hi Eduardo,

On Thu, May 9, 2013 at 8:17 PM, Eduardo Valentin
<eduardo.valentin@ti.com> wrote:
> Hey Amit,
>
> On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
>> This patch modifies TMU controller to add changes needed to work with
>> exynos5440 platform. Also register definitions and required configuration data
>> are added. This sensor registers 3 instance of the tmu controller with the
>> thermal zone and hence reports 3 temperature output. This controller supports
>> upto five trip points. For critical threshold the driver uses the core driver
>> thermal framework for shutdown.
>>
>
> I would kindly request you to split this patch. Looks like you add
> altogether in one patch both data, driver adaptation (for your new soc)
> and on top, new features. I would suggest splitting this things in
> smaller steps. Easier to review, track, bitsec and find bugs (if any).

Yes your suggestion sounds reasonable. Will split into at least 3 patches.

Thanks,
Amit
>
>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>> ---
>>  .../devicetree/bindings/thermal/exynos-thermal.txt |   28 ++++-
>>  drivers/thermal/samsung/Kconfig                    |    4 +-
>>  drivers/thermal/samsung/exynos_thermal_common.c    |    2 +-
>>  drivers/thermal/samsung/exynos_tmu.c               |  139 +++++++++++++++++---
>>  drivers/thermal/samsung/exynos_tmu.h               |    7 +
>>  drivers/thermal/samsung/exynos_tmu_data.c          |   66 +++++++++-
>>  drivers/thermal/samsung/exynos_tmu_data.h          |   40 ++++++
>>  7 files changed, 261 insertions(+), 25 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>> index 535fd0e..970eeba 100644
>> --- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>> +++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>> @@ -6,13 +6,16 @@
>>              "samsung,exynos4412-tmu"
>>              "samsung,exynos4210-tmu"
>>              "samsung,exynos5250-tmu"
>> +            "samsung,exynos5440-tmu"
>>  - interrupt-parent : The phandle for the interrupt controller
>> -- reg : Address range of the thermal registers
>> +- reg : Address range of the thermal registers. For exynos5440-tmu which has 3
>> +     instances of TMU, 2 set of register has to supplied. First set belongs
>> +     to each instance of TMU and second set belongs to common TMU registers.
>>  - interrupts : Should contain interrupt for thermal system
>>  - clocks : The main clock for TMU device
>>  - clock-names : Thermal system clock name
>>
>> -Example:
>> +Example 1):
>>
>>       tmu@100C0000 {
>>               compatible = "samsung,exynos4412-tmu";
>> @@ -23,3 +26,24 @@ Example:
>>               clock-names = "tmu_apbif";
>>               status = "disabled";
>>       };
>> +
>> +Example 2):
>> +
>> +     tmuctrl_0: tmuctrl@160118 {
>> +             compatible = "samsung,exynos5440-tmu";
>> +             reg = <0x160118 0x230>, <0x160368 0x10>;
>> +             interrupts = <0 58 0>;
>> +             clocks = <&clock 21>;
>> +             clock-names = "tmu_apbif";
>> +     };
>> +
>> +Note: For multi-instance tmu each instance should have an alias correctly
>> +numbered in "aliases" node.
>> +
>> +Example:
>> +
>> +aliases {
>> +     tmuctrl0 = &tmuctrl_0;
>> +     tmuctrl1 = &tmuctrl_1;
>> +     tmuctrl2 = &tmuctrl_2;
>> +};
>> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
>> index f23f533..fce04f3 100644
>> --- a/drivers/thermal/samsung/Kconfig
>> +++ b/drivers/thermal/samsung/Kconfig
>> @@ -19,10 +19,10 @@ config EXYNOS_THERMAL_CORE
>>
>>  config EXYNOS_THERMAL_DATA
>>       bool "Temperature sensor congiguration data for EXYNOS series SOC"
>> -     depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250)
>> +     depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250 || SOC_EXYNOS5440)
>>       depends on EXYNOS_THERMAL
>>       help
>>         If you say yes here you can enable TMU (Thermal Management Unit) on
>> -       SAMSUNG EXYNOS 4210, 4412, 4414 and 5250 series of SoC. This option
>> +       SAMSUNG EXYNOS 4210, 4412, 4414, 5250 and 5440 series of SoC. This option
>>         enables/prepares the configuration, trip and cooling data for the TMU
>>         driver.
>> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
>> index b0dc63e..de43e18 100644
>> --- a/drivers/thermal/samsung/exynos_thermal_common.c
>> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
>> @@ -370,7 +370,7 @@ int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
>>       th_zone->mode = THERMAL_DEVICE_ENABLED;
>>       sensor_conf->pzone_data = th_zone;
>>
>> -     pr_info("Exynos: Kernel Thermal management registered\n");
>> +     pr_info("Exynos: Thermal zone(%s) registered\n", sensor_conf->name);
>>
>>       return 0;
>>
>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>> index c1a8c5f..72446c9 100644
>> --- a/drivers/thermal/samsung/exynos_tmu.c
>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>> @@ -44,6 +44,7 @@
>>   * @id: identifier of the one instance of the TMU controller.
>>   * @pdata: pointer to the tmu platform/configuration data
>>   * @base: base address of the single instance of the TMU controller.
>> + * @base_common: base address of the common registers of the TMU controller.
>>   * @irq: irq number of the TMU controller.
>>   * @soc: id of the SOC type.
>>   * @irq_work: pointer to the irq work structure.
>> @@ -57,6 +58,7 @@ struct exynos_tmu_data {
>>       int id;
>>       struct exynos_tmu_platform_data *pdata;
>>       void __iomem *base;
>> +     void __iomem *base_common;
>>       int irq;
>>       enum soc_type soc;
>>       struct work_struct irq_work;
>> @@ -75,6 +77,9 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>       int temp_code;
>>
>> +     if (pdata->cal_mode == HW_MODE)
>> +             return temp;
>> +
>>       if (data->soc == SOC_ARCH_EXYNOS4210)
>>               /* temp should range between 25 and 125 */
>>               if (temp < 25 || temp > 125) {
>> @@ -109,6 +114,9 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>       int temp;
>>
>> +     if (pdata->cal_mode == HW_MODE)
>> +             return temp_code;
>> +
>>       if (data->soc == SOC_ARCH_EXYNOS4210)
>>               /* temp_code should range between 75 and 175 */
>>               if (temp_code < 75 || temp_code > 175) {
>> @@ -139,33 +147,63 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>       struct exynos_tmu_registers *reg = pdata->registers;
>> -     unsigned int status, trim_info, con;
>> +     unsigned int status, trim_info = 0, con;
>>       unsigned int rising_threshold = 0, falling_threshold = 0;
>>       int ret = 0, threshold_code, i, trigger_levs = 0;
>>
>>       mutex_lock(&data->lock);
>>       clk_enable(data->clk);
>>
>> -     status = readb(data->base + reg->tmu_status);
>> -     if (!status) {
>> -             ret = -EBUSY;
>> -             goto out;
>> +     if (TMU_SUPPORTS(pdata, READY_STATUS)) {
>> +             status = readb(data->base + reg->tmu_status);
>> +             if (!status) {
>> +                     ret = -EBUSY;
>> +                     goto out;
>> +             }
>>       }
>>
>>       if (TMU_SUPPORTS(pdata, TRIM_RELOAD))
>>               __raw_writel(1, data->base + reg->triminfo_ctrl);
>>
>> +     if (pdata->cal_mode == HW_MODE)
>> +             goto skip_calib_data;
>> +
>>       /* Save trimming info in order to perform calibration */
>> -     trim_info = readl(data->base + reg->triminfo_data);
>> +     if (data->soc == SOC_ARCH_EXYNOS5440) {
>> +             /*
>> +              * For exynos5440 soc triminfo value is swapped between TMU0 and
>> +              * TMU2, so the below logic is needed.
>> +              */
>> +             switch (data->id) {
>> +             case 0:
>> +                     trim_info = readl(data->base +
>> +                     EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
>> +                     break;
>> +             case 1:
>> +                     trim_info = readl(data->base + reg->triminfo_data);
>> +                     break;
>> +             case 2:
>> +                     trim_info = readl(data->base -
>> +                     EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
>> +             }
>> +     } else {
>> +             trim_info = readl(data->base + reg->triminfo_data);
>> +     }
>>       data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
>>       data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
>>                               EXYNOS_TMU_TEMP_MASK);
>>
>> -     if ((pdata->min_efuse_value > data->temp_error1) ||
>> -                     (data->temp_error1 > pdata->max_efuse_value) ||
>> -                     (data->temp_error2 != 0))
>> -             data->temp_error1 = pdata->efuse_value;
>> +     if (!data->temp_error1 ||
>> +             (pdata->min_efuse_value > data->temp_error1) ||
>> +             (data->temp_error1 > pdata->max_efuse_value))
>> +             data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
>> +
>> +     if (!data->temp_error2)
>> +             data->temp_error2 =
>> +                     (pdata->efuse_value >> reg->triminfo_85_shift) &
>> +                     EXYNOS_TMU_TEMP_MASK;
>>
>> +skip_calib_data:
>>       /* Count trigger levels to be enabled */
>>       for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
>>               if (pdata->trigger_levels[i])
>> @@ -185,9 +223,10 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>                       data->base + reg->threshold_th0 + i * 4);
>>
>>               writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>> -     } else if (data->soc == SOC_ARCH_EXYNOS) {
>> +     } else if (data->soc == SOC_ARCH_EXYNOS ||
>> +                     data->soc == SOC_ARCH_EXYNOS5440) {
>>               /* Write temperature code for rising and falling threshold */
>> -             for (i = 0; i < trigger_levs; i++) {
>> +             for (i = 0; i < trigger_levs && i < 4 ; i++) {
>>                       threshold_code = temp_to_code(data,
>>                                               pdata->trigger_levels[i]);
>>                       if (threshold_code < 0) {
>> @@ -218,7 +257,29 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>               writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>>                       (reg->inten_fall_mask << reg->inten_fall_shift),
>>                               data->base + reg->tmu_intclear);
>> +
>> +             /* if 5th threshold limit is also present, use TH2 register */
>> +             i = 4;
>> +             if (pdata->trigger_levels[i]) {
>> +                     threshold_code = temp_to_code(data,
>> +                                             pdata->trigger_levels[i]);
>> +                     if (threshold_code < 0) {
>> +                             ret = threshold_code;
>> +                             goto out;
>> +                     }
>> +                     rising_threshold = threshold_code << 24;
>> +                     writel(rising_threshold,
>> +                             data->base + reg->threshold_th2);
>> +                     if (pdata->trigger_type[i] == HW_TRIP) {
>> +                             con = readl(data->base + reg->tmu_ctrl);
>> +                             con |= (1 << reg->therm_trip_en_shift);
>> +                             writel(con, data->base + reg->tmu_ctrl);
>> +                     }
>> +             }
>>       }
>> +     /*Clear the PMIN in the common TMU register*/
>> +     if (reg->tmu_pmin && !data->id)
>> +             writel(0, data->base_common + reg->tmu_pmin);
>>  out:
>>       clk_disable(data->clk);
>>       mutex_unlock(&data->lock);
>> @@ -254,6 +315,11 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>               con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
>>       }
>>
>> +     if (pdata->cal_mode == HW_MODE) {
>> +             con &= ~(reg->calib_mode_mask << reg->calib_mode_shift);
>> +             con |= pdata->cal_type << reg->calib_mode_shift;
>> +     }
>> +
>>       if (on) {
>>               con |= (1 << reg->core_en_shift);
>>               interrupt_en =
>> @@ -317,9 +383,11 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>>       if (temp) {
>>               temp /= MCELSIUS;
>>
>> -             val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
>> -                     (temp_to_code(data, temp)
>> -                      << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
>> +             if (data->soc == SOC_ARCH_EXYNOS && reg->emul_time_shift)
>> +                     val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift);
>> +
>> +             val |= (temp_to_code(data, temp) << reg->emul_temp_shift) |
>> +                     EXYNOS_EMUL_ENABLE;
>>       } else {
>>               val &= ~EXYNOS_EMUL_ENABLE;
>>       }
>> @@ -343,7 +411,14 @@ static void exynos_tmu_work(struct work_struct *work)
>>                       struct exynos_tmu_data, irq_work);
>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>       struct exynos_tmu_registers *reg = pdata->registers;
>> -     unsigned int val_irq;
>> +     unsigned int val_irq, val_type;
>> +
>> +     /* Find which sensor generated this interrupt */
>> +     if (reg->tmu_irqstatus) {
>> +             val_type = readl(data->base_common + reg->tmu_irqstatus);
>> +             if (!((val_type >> data->id) & 0x1))
>> +                     goto out;
>> +     }
>>
>>       exynos_report_trigger(data->reg_conf);
>>       mutex_lock(&data->lock);
>> @@ -355,7 +430,7 @@ static void exynos_tmu_work(struct work_struct *work)
>>
>>       clk_disable(data->clk);
>>       mutex_unlock(&data->lock);
>> -
>> +out:
>>       enable_irq(data->irq);
>>  }
>>
>> @@ -383,6 +458,10 @@ static const struct of_device_id exynos_tmu_match[] = {
>>               .compatible = "samsung,exynos5250-tmu",
>>               .data = (void *)EXYNOS5250_TMU_DRV_DATA,
>>       },
>> +     {
>> +             .compatible = "samsung,exynos5440-tmu",
>> +             .data = (void *)EXYNOS5440_TMU_DRV_DATA,
>> +     },
>>       {},
>>  };
>>  MODULE_DEVICE_TABLE(of, exynos_tmu_match);
>> @@ -420,6 +499,7 @@ static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
>>  static int exynos_map_dt_data(struct platform_device *pdev)
>>  {
>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>>       struct resource res;
>>
>>       if (!data)
>> @@ -436,7 +516,7 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>>       }
>>
>>       if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
>> -             dev_err(&pdev->dev, "failed to get Resource\n");
>> +             dev_err(&pdev->dev, "failed to get Resource 0\n");
>>               return -ENODEV;
>>       }
>>
>> @@ -445,6 +525,26 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>>               dev_err(&pdev->dev, "Failed to ioremap memory\n");
>>               return -ENOMEM;
>>       }
>> +
>> +     /*
>> +      * Check if the TMU is multi instance type and then try to map the
>> +      * memory of common registers.
>> +      */
>> +     if (!TMU_SUPPORTS(pdata, MULTI_INST))
>> +             return 0;
>> +
>> +     if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
>> +             dev_err(&pdev->dev, "failed to get Resource 1\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     data->base_common = devm_ioremap(&pdev->dev, res.start,
>> +                                     resource_size(&res));
>> +     if (!data->base) {
>> +             dev_err(&pdev->dev, "Failed to ioremap memory\n");
>> +             return -ENOMEM;
>> +     }
>> +
>>       return 0;
>>  }
>>
>> @@ -496,7 +596,8 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>>               return ret;
>>
>>       if (pdata->type == SOC_ARCH_EXYNOS ||
>> -                             pdata->type == SOC_ARCH_EXYNOS4210)
>> +             pdata->type == SOC_ARCH_EXYNOS4210 ||
>> +             pdata->type == SOC_ARCH_EXYNOS5440)
>>               data->soc = pdata->type;
>>       else {
>>               ret = -EINVAL;
>> diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
>> index de1c342..cc6b10e 100644
>> --- a/drivers/thermal/samsung/exynos_tmu.h
>> +++ b/drivers/thermal/samsung/exynos_tmu.h
>> @@ -43,6 +43,7 @@ enum trigger_type {
>>  enum soc_type {
>>       SOC_ARCH_EXYNOS4210 = 1,
>>       SOC_ARCH_EXYNOS,
>> +     SOC_ARCH_EXYNOS5440,
>>  };
>>
>>  /**
>> @@ -61,6 +62,7 @@ enum soc_type {
>>  #define TMU_SUPPORT_MULTI_INST                       BIT(1)
>>  #define TMU_SUPPORT_TRIM_RELOAD                      BIT(2)
>>  #define TMU_SUPPORT_FALLING_TRIP             BIT(3)
>> +#define TMU_SUPPORT_READY_STATUS             BIT(4)
>>
>>  #define TMU_SUPPORTS(a, b)   (a->features & TMU_SUPPORT_ ## b)
>>
>> @@ -85,6 +87,8 @@ struct exynos_tmu_registers {
>>       u32     therm_trip_en_shift;
>>       u32     buf_slope_sel_shift;
>>       u32     buf_slope_sel_mask;
>> +     u32     calib_mode_shift;
>> +     u32     calib_mode_mask;
>>       u32     therm_trip_tq_en_shift;
>>       u32     core_en_shift;
>>
>> @@ -137,6 +141,9 @@ struct exynos_tmu_registers {
>>       u32     emul_temp_shift;
>>       u32     emul_time_shift;
>>       u32     emul_time_mask;
>> +
>> +     u32     tmu_irqstatus;
>> +     u32     tmu_pmin;
>>  };
>>
>>  /**
>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
>> index 8a587d4..25629e6 100644
>> --- a/drivers/thermal/samsung/exynos_tmu_data.c
>> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
>> @@ -79,6 +79,7 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>       .freq_tab_count = 2,
>>       .type = SOC_ARCH_EXYNOS4210,
>>       .registers = &exynos4210_tmu_registers,
>> +     .features = (TMU_SUPPORT_READY_STATUS),
>>  };
>>  #endif
>>
>> @@ -155,6 +156,69 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>>       .type = SOC_ARCH_EXYNOS,
>>       .registers = &exynos5250_tmu_registers,
>>       .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD |
>> -                     TMU_SUPPORT_FALLING_TRIP),
>> +                     TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS),
>> +};
>> +#endif
>> +
>> +#if defined(CONFIG_SOC_EXYNOS5440)
>> +static struct exynos_tmu_registers exynos5440_tmu_registers = {
>> +     .triminfo_data = EXYNOS5440_TMU_S0_7_TRIM,
>> +     .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
>> +     .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
>> +     .tmu_ctrl = EXYNOS5440_TMU_S0_7_CTRL,
>> +     .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
>> +     .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
>> +     .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
>> +     .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
>> +     .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
>> +     .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
>> +     .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
>> +     .calib_mode_shift = EXYNOS_TMU_CALIB_MODE_SHIFT,
>> +     .calib_mode_mask = EXYNOS_TMU_CALIB_MODE_MASK,
>> +     .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
>> +     .tmu_status = EXYNOS5440_TMU_S0_7_STATUS,
>> +     .tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP,
>> +     .threshold_th0 = EXYNOS5440_TMU_S0_7_TH0,
>> +     .threshold_th1 = EXYNOS5440_TMU_S0_7_TH1,
>> +     .threshold_th2 = EXYNOS5440_TMU_S0_7_TH2,
>> +     .tmu_inten = EXYNOS5440_TMU_S0_7_IRQEN,
>> +     .inten_rise_mask = EXYNOS5440_TMU_RISE_INT_MASK,
>> +     .inten_rise_shift = EXYNOS5440_TMU_RISE_INT_SHIFT,
>> +     .inten_fall_mask = EXYNOS5440_TMU_FALL_INT_MASK,
>> +     .inten_fall_shift = EXYNOS5440_TMU_FALL_INT_SHIFT,
>> +     .inten_rise0_shift = EXYNOS5440_TMU_INTEN_RISE0_SHIFT,
>> +     .inten_rise1_shift = EXYNOS5440_TMU_INTEN_RISE1_SHIFT,
>> +     .inten_rise2_shift = EXYNOS5440_TMU_INTEN_RISE2_SHIFT,
>> +     .inten_rise3_shift = EXYNOS5440_TMU_INTEN_RISE3_SHIFT,
>> +     .inten_fall0_shift = EXYNOS5440_TMU_INTEN_FALL0_SHIFT,
>> +     .tmu_evten = EXYNOS5440_TMU_S0_7_EVTEN,
>> +     .tmu_intstat = EXYNOS5440_TMU_S0_7_IRQ,
>> +     .tmu_intclear = EXYNOS5440_TMU_S0_7_IRQ,
>> +     .tmu_irqstatus = EXYNOS5440_TMU_IRQ_STATUS,
>> +     .emul_con = EXYNOS5440_TMU_S0_7_DEBUG,
>> +     .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
>> +     .tmu_pmin = EXYNOS5440_TMU_PMIN,
>> +};
>> +struct exynos_tmu_platform_data const exynos5440_default_tmu_data = {
>> +     .trigger_levels[0] = 100,
>> +     .trigger_levels[4] = 105,
>> +     .trigger_enable[0] = 1,
>> +     .trigger_type[0] = 1,
>> +     .trigger_type[4] = 2,
>> +     .gain = 5,
>> +     .reference_voltage = 16,
>> +     .noise_cancel_mode = 4,
>> +     .cal_type = TYPE_TWO_POINT_TRIMMING,
>> +     .cal_mode = 0,
>> +     .efuse_value = 0x5b2d,
>> +     .min_efuse_value = 16,
>> +     .max_efuse_value = 76,
>> +     .first_point_trim = 25,
>> +     .second_point_trim = 70,
>> +     .default_temp_offset = 25,
>> +     .type = SOC_ARCH_EXYNOS5440,
>> +     .registers = &exynos5440_tmu_registers,
>> +     .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP |
>> +                     TMU_SUPPORT_MULTI_INST),
>>  };
>>  #endif
>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
>> index 0560413..c409f3a 100644
>> --- a/drivers/thermal/samsung/exynos_tmu_data.h
>> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
>> @@ -75,6 +75,8 @@
>>  #define EXYNOS_TMU_TRIP_MODE_SHIFT   13
>>  #define EXYNOS_TMU_TRIP_MODE_MASK    0x7
>>  #define EXYNOS_TMU_THERM_TRIP_EN_SHIFT       12
>> +#define EXYNOS_TMU_CALIB_MODE_SHIFT  4
>> +#define EXYNOS_TMU_CALIB_MODE_MASK   0x3
>>
>>  #define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
>>  #define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
>> @@ -91,6 +93,37 @@
>>  #define EXYNOS_EMUL_DATA_MASK        0xFF
>>  #define EXYNOS_EMUL_ENABLE   0x1
>>
>> +/*exynos5440 specific registers*/
>> +#define EXYNOS5440_TMU_S0_7_TRIM             0x000
>> +#define EXYNOS5440_TMU_S0_7_CTRL             0x020
>> +#define EXYNOS5440_TMU_S0_7_DEBUG            0x040
>> +#define EXYNOS5440_TMU_S0_7_STATUS           0x060
>> +#define EXYNOS5440_TMU_S0_7_TEMP             0x0f0
>> +#define EXYNOS5440_TMU_S0_7_TH0                      0x110
>> +#define EXYNOS5440_TMU_S0_7_TH1                      0x130
>> +#define EXYNOS5440_TMU_S0_7_TH2                      0x150
>> +#define EXYNOS5440_TMU_S0_7_EVTEN            0x1F0
>> +#define EXYNOS5440_TMU_S0_7_IRQEN            0x210
>> +#define EXYNOS5440_TMU_S0_7_IRQ                      0x230
>> +/* exynos5440 common registers */
>> +#define EXYNOS5440_TMU_IRQ_STATUS            0x000
>> +#define EXYNOS5440_TMU_PMIN                  0x004
>> +#define EXYNOS5440_TMU_TEMP                  0x008
>> +
>> +#define EXYNOS5440_EFUSE_SWAP_OFFSET         8
>> +#define EXYNOS5440_TMU_RISE_INT_MASK         0xf
>> +#define EXYNOS5440_TMU_RISE_INT_SHIFT                0
>> +#define EXYNOS5440_TMU_FALL_INT_MASK         0xf
>> +#define EXYNOS5440_TMU_FALL_INT_SHIFT                4
>> +#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT     0
>> +#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT     1
>> +#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT     2
>> +#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT     3
>> +#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT     4
>> +#define EXYNOS5440_TMU_INTEN_FALL1_SHIFT     5
>> +#define EXYNOS5440_TMU_INTEN_FALL2_SHIFT     6
>> +#define EXYNOS5440_TMU_INTEN_FALL3_SHIFT     7
>> +
>>  #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>>  extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
>>  #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
>> @@ -106,4 +139,11 @@ extern struct exynos_tmu_platform_data const exynos5250_default_tmu_data;
>>  #define EXYNOS5250_TMU_DRV_DATA (NULL)
>>  #endif
>>
>> +#if defined(CONFIG_SOC_EXYNOS5440) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>> +extern struct exynos_tmu_platform_data const exynos5440_default_tmu_data;
>> +#define EXYNOS5440_TMU_DRV_DATA (&exynos5440_default_tmu_data)
>> +#else
>> +#define EXYNOS5440_TMU_DRV_DATA (NULL)
>> +#endif
>> +
>>  #endif /*_LINUX_EXYNOS_TMU_DATA_H*/
>>
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 15/21] thermal: exynos: Add support to handle many instances of TMU
  2013-05-09 14:53     ` Eduardo Valentin
  (?)
@ 2013-05-10  2:32     ` amit daniel kachhap
  -1 siblings, 0 replies; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-10  2:32 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel, Kukjin Kim

On Thu, May 9, 2013 at 8:23 PM, Eduardo Valentin
<eduardo.valentin@ti.com> wrote:
> On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
>> This patch adds support to handle multiple instances of the TMU controllers.
>> This is done by removing the static structure to register with the core thermal
>> and creating it dynamically for each instance of the TMU controller. The
>> interrupt is made shared type to handle interrupts for all the TMU. Also
>> the identifier of the TMU controller is extracted from device tree alias.
>>
>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>> ---
>>  drivers/thermal/samsung/exynos_tmu.c |  125 +++++++++++++++++++++++-----------
>>  1 files changed, 84 insertions(+), 41 deletions(-)
>>
>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>> index bdf40ef..94d6e8e 100644
>> --- a/drivers/thermal/samsung/exynos_tmu.c
>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>> @@ -29,6 +29,8 @@
>>  #include <linux/module.h>
>>  #include <linux/mutex.h>
>>  #include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_irq.h>
>>  #include <linux/platform_device.h>
>>  #include <linux/slab.h>
>>  #include <linux/workqueue.h>
>> @@ -36,9 +38,24 @@
>>  #include "exynos_tmu.h"
>>  #include "exynos_tmu_data.h"
>>
>> +/**
>> + * struct exynos_tmu_data : A structure to hold the private data of the TMU
>> +     driver
>> + * @id: identifier of the one instance of the TMU controller.
>> + * @pdata: pointer to the tmu platform/configuration data
>> + * @base: base address of the single instance of the TMU controller.
>> + * @irq: irq number of the TMU controller.
>> + * @soc: id of the SOC type.
>> + * @irq_work: pointer to the irq work structure.
>> + * @lock: lock to implement synchronization.
>> + * @clk: pointer to the clock structure.
>> + * @temp_error1: fused value of the first point trim.
>> + * @temp_error2: fused value of the second point trim.
>> + * @reg_conf: pointer to structure to register with core thermal.
>> + */
>>  struct exynos_tmu_data {
>> +     int id;
>>       struct exynos_tmu_platform_data *pdata;
>> -     struct resource *mem;
>>       void __iomem *base;
>>       int irq;
>>       enum soc_type soc;
>> @@ -46,6 +63,7 @@ struct exynos_tmu_data {
>>       struct mutex lock;
>>       struct clk *clk;
>>       u8 temp_error1, temp_error2;
>> +     struct thermal_sensor_conf *reg_conf;
>>  };
>>
>>  /*
>> @@ -319,12 +337,6 @@ static int exynos_tmu_set_emulation(void *drv_data,      unsigned long temp)
>>       { return -EINVAL; }
>>  #endif/*CONFIG_THERMAL_EMULATION*/
>>
>> -static struct thermal_sensor_conf exynos_sensor_conf = {
>> -     .name                   = "exynos-therm",
>> -     .read_temperature       = (int (*)(void *))exynos_tmu_read,
>> -     .write_emul_temp        = exynos_tmu_set_emulation,
>> -};
>> -
>>  static void exynos_tmu_work(struct work_struct *work)
>>  {
>>       struct exynos_tmu_data *data = container_of(work,
>> @@ -333,7 +345,7 @@ static void exynos_tmu_work(struct work_struct *work)
>>       struct exynos_tmu_registers *reg = pdata->registers;
>>       unsigned int val_irq;
>>
>> -     exynos_report_trigger(&exynos_sensor_conf);
>> +     exynos_report_trigger(data->reg_conf);
>>       mutex_lock(&data->lock);
>>       clk_enable(data->clk);
>>
>> @@ -405,10 +417,42 @@ static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
>>                       platform_get_device_id(pdev)->driver_data;
>>  }
>>
>> +static int exynos_map_dt_data(struct platform_device *pdev)
>> +{
>> +     struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>> +     struct resource res;
>> +
>> +     if (!data)
>> +             return -ENODEV;
>> +
>> +     data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
>> +     if (data->id < 0)
>> +             data->id = 0;
>> +
>> +     data->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
>> +     if (data->irq <= 0) {
>> +             dev_err(&pdev->dev, "failed to get IRQ\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
>> +             dev_err(&pdev->dev, "failed to get Resource\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     data->base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
>> +     if (!data->base) {
>> +             dev_err(&pdev->dev, "Failed to ioremap memory\n");
>> +             return -ENOMEM;
>
> looks like the statement below fits better here:
>                 return ERR_PTR(-EADDRNOTAVAIL);

Ok.
>
>> +     }
>
> blank line?
Ok.
>
>> +     return 0;
>> +}
>> +
>>  static int exynos_tmu_probe(struct platform_device *pdev)
>>  {
>>       struct exynos_tmu_data *data;
>>       struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
>> +     struct thermal_sensor_conf *sensor_conf;
>>       int ret, i;
>>
>>       if (!pdata)
>> @@ -425,26 +469,17 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>>               return -ENOMEM;
>>       }
>>
>> -     data->irq = platform_get_irq(pdev, 0);
>> -     if (data->irq < 0) {
>> -             dev_err(&pdev->dev, "Failed to get platform irq\n");
>> -             return data->irq;
>> -     }
>> -
>> -     INIT_WORK(&data->irq_work, exynos_tmu_work);
>> -
>> -     data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> -     if (!data->mem) {
>> -             dev_err(&pdev->dev, "Failed to get platform resource\n");
>> -             return -ENOENT;
>> -     }
>> +     data->pdata = pdata;
>> +     platform_set_drvdata(pdev, data);
>> +     mutex_init(&data->lock);
>>
>> -     data->base = devm_ioremap_resource(&pdev->dev, data->mem);
>> -     if (IS_ERR(data->base))
>> -             return PTR_ERR(data->base);
>> +     ret = exynos_map_dt_data(pdev);
>> +     if (ret)
>> +             return ret;
>>
>> +     INIT_WORK(&data->irq_work, exynos_tmu_work);
>>       ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
>> -             IRQF_TRIGGER_RISING, "exynos-tmu", data);
>> +             IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
>>       if (ret) {
>>               dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
>>               return ret;
>> @@ -469,10 +504,6 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>>               goto err_clk;
>>       }
>>
>> -     data->pdata = pdata;
>> -     platform_set_drvdata(pdev, data);
>> -     mutex_init(&data->lock);
>> -
>>       ret = exynos_tmu_initialize(pdev);
>>       if (ret) {
>>               dev_err(&pdev->dev, "Failed to initialize TMU\n");
>> @@ -481,28 +512,40 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>>
>>       exynos_tmu_control(pdev, true);
>>
>> -     /* Register the sensor with thermal management interface */
>> -     (&exynos_sensor_conf)->driver_data = data;
>> -     exynos_sensor_conf.trip_data.trip_count = pdata->trigger_enable[0] +
>> +     /* Allocate a structure to register with the exynos core thermal */
>> +     sensor_conf = devm_kzalloc(&pdev->dev,
>> +                             sizeof(struct thermal_sensor_conf), GFP_KERNEL);
>> +     if (!sensor_conf) {
>> +             dev_err(&pdev->dev, "Failed to allocate registration struct\n");
>> +             ret = -ENOMEM;
>> +             goto err_clk;
>> +     }
>> +     data->reg_conf = sensor_conf;
>> +     sprintf(sensor_conf->name, "therm_zone%d", data->id);
>> +     sensor_conf->read_temperature = (int (*)(void *))exynos_tmu_read;
>> +     sensor_conf->write_emul_temp =
>> +             (int (*)(void *, unsigned long))exynos_tmu_set_emulation;
>> +     sensor_conf->driver_data = data;
>> +     sensor_conf->trip_data.trip_count = pdata->trigger_enable[0] +
>>                       pdata->trigger_enable[1] + pdata->trigger_enable[2]+
>>                       pdata->trigger_enable[3];
>>
>> -     for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
>> -             exynos_sensor_conf.trip_data.trip_val[i] =
>> +     for (i = 0; i < sensor_conf->trip_data.trip_count; i++)
>> +             sensor_conf->trip_data.trip_val[i] =
>>                       pdata->threshold + pdata->trigger_levels[i];
>>
>> -     exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
>> +     sensor_conf->trip_data.trigger_falling = pdata->threshold_falling;
>>
>> -     exynos_sensor_conf.cooling_data.freq_clip_count =
>> -                                             pdata->freq_tab_count;
>> +     sensor_conf->cooling_data.freq_clip_count = pdata->freq_tab_count;
>>       for (i = 0; i < pdata->freq_tab_count; i++) {
>> -             exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
>> +             sensor_conf->cooling_data.freq_data[i].freq_clip_max =
>>                                       pdata->freq_tab[i].freq_clip_max;
>> -             exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
>> +             sensor_conf->cooling_data.freq_data[i].temp_level =
>>                                       pdata->freq_tab[i].temp_level;
>>       }
>>
>> -     ret = exynos_register_thermal(&exynos_sensor_conf);
>> +     /* Register the sensor with thermal management interface */
>> +     ret = exynos_register_thermal(sensor_conf);
>>       if (ret) {
>>               dev_err(&pdev->dev, "Failed to register thermal interface\n");
>>               goto err_clk;
>> @@ -521,7 +564,7 @@ static int exynos_tmu_remove(struct platform_device *pdev)
>>
>>       exynos_tmu_control(pdev, false);
>>
>> -     exynos_unregister_thermal(&exynos_sensor_conf);
>> +     exynos_unregister_thermal(data->reg_conf);
>>
>>       clk_unprepare(data->clk);
>>
>>
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 09/21] thermal: exynos: Move register definitions from driver file to data file
  2013-05-10  2:17     ` amit daniel kachhap
@ 2013-05-10 14:14         ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-10 14:14 UTC (permalink / raw)
  To: amit daniel kachhap
  Cc: Eduardo Valentin, linux-pm, Zhang Rui, linux-samsung-soc,
	linux-kernel, Kukjin Kim

[-- Attachment #1: Type: text/plain, Size: 27700 bytes --]

On 09-05-2013 22:17, amit daniel kachhap wrote:
> Hi Eduardo,
> 
> On Thu, May 9, 2013 at 8:02 PM, Eduardo Valentin
> <eduardo.valentin@ti.com> wrote:
>> Hey Amit,
>>
>> On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
>>> This patch migrates the TMU register definition/bitfields to data file. This
>>> is needed to support SoC's which use the same TMU controller but register
>>> validity, offsets or bitfield may slightly vary across SOC's.
>>>
>>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>>> ---
>>>  drivers/thermal/samsung/exynos_tmu.c      |  177 +++++++++-------------------
>>>  drivers/thermal/samsung/exynos_tmu.h      |   76 ++++++++++++
>>>  drivers/thermal/samsung/exynos_tmu_data.c |   59 ++++++++++
>>>  drivers/thermal/samsung/exynos_tmu_data.h |   68 +++++++++++
>>>  4 files changed, 260 insertions(+), 120 deletions(-)
>>>
>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>>> index 23baeeb..97b87aa 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>>> @@ -36,77 +36,6 @@
>>>  #include "exynos_tmu.h"
>>>  #include "exynos_tmu_data.h"
>>>
>>> -/* Exynos generic registers */
>>> -#define EXYNOS_TMU_REG_TRIMINFO              0x0
>>> -#define EXYNOS_TMU_REG_CONTROL               0x20
>>> -#define EXYNOS_TMU_REG_STATUS                0x28
>>> -#define EXYNOS_TMU_REG_CURRENT_TEMP  0x40
>>> -#define EXYNOS_TMU_REG_INTEN         0x70
>>> -#define EXYNOS_TMU_REG_INTSTAT               0x74
>>> -#define EXYNOS_TMU_REG_INTCLEAR              0x78
>>> -
>>> -#define EXYNOS_TMU_TRIM_TEMP_MASK    0xff
>>> -#define EXYNOS_TMU_GAIN_SHIFT                8
>>> -#define EXYNOS_TMU_GAIN_MASK         0xf
>>> -#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
>>> -#define EXYNOS_TMU_REF_VOLTAGE_MASK  0x1f
>>> -#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK        0xf
>>> -#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT       8
>>> -#define EXYNOS_TMU_CORE_EN_SHIFT     0
>>> -
>>> -/* Exynos4210 specific registers */
>>> -#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP    0x44
>>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL0       0x50
>>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL1       0x54
>>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL2       0x58
>>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL3       0x5C
>>> -#define EXYNOS4210_TMU_REG_PAST_TEMP0        0x60
>>> -#define EXYNOS4210_TMU_REG_PAST_TEMP1        0x64
>>> -#define EXYNOS4210_TMU_REG_PAST_TEMP2        0x68
>>> -#define EXYNOS4210_TMU_REG_PAST_TEMP3        0x6C
>>> -
>>> -#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK      0x1
>>> -#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK      0x10
>>> -#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK      0x100
>>> -#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK      0x1000
>>> -#define EXYNOS4210_TMU_TRIG_LEVEL_MASK       0x1111
>>> -#define EXYNOS4210_TMU_INTCLEAR_VAL  0x1111
>>> -
>>> -/* Exynos5250 and Exynos4412 specific registers */
>>> -#define EXYNOS_TMU_TRIMINFO_CON      0x14
>>> -#define EXYNOS_THD_TEMP_RISE         0x50
>>> -#define EXYNOS_THD_TEMP_FALL         0x54
>>> -#define EXYNOS_EMUL_CON              0x80
>>> -
>>> -#define EXYNOS_TRIMINFO_RELOAD               0x1
>>> -#define EXYNOS_TRIMINFO_SHIFT                0x0
>>> -#define EXYNOS_TMU_RISE_INT_MASK     0x111
>>> -#define EXYNOS_TMU_RISE_INT_SHIFT    0
>>> -#define EXYNOS_TMU_FALL_INT_MASK     0x111
>>> -#define EXYNOS_TMU_FALL_INT_SHIFT    12
>>> -#define EXYNOS_TMU_CLEAR_RISE_INT    0x111
>>> -#define EXYNOS_TMU_CLEAR_FALL_INT    (0x111 << 12)
>>> -#define EXYNOS_TMU_TRIP_MODE_SHIFT   13
>>> -#define EXYNOS_TMU_TRIP_MODE_MASK    0x7
>>> -#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT       12
>>> -
>>> -#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
>>> -#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
>>> -#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
>>> -#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
>>> -#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
>>> -#define EXYNOS_TMU_INTEN_FALL1_SHIFT 20
>>> -#define EXYNOS_TMU_INTEN_FALL2_SHIFT 24
>>> -
>>> -#ifdef CONFIG_THERMAL_EMULATION
>>> -#define EXYNOS_EMUL_TIME     0x57F0
>>> -#define EXYNOS_EMUL_TIME_MASK        0xffff
>>> -#define EXYNOS_EMUL_TIME_SHIFT       16
>>> -#define EXYNOS_EMUL_DATA_SHIFT       8
>>> -#define EXYNOS_EMUL_DATA_MASK        0xFF
>>> -#define EXYNOS_EMUL_ENABLE   0x1
>>> -#endif /* CONFIG_THERMAL_EMULATION */
>>> -
>>>  struct exynos_tmu_data {
>>>       struct exynos_tmu_platform_data *pdata;
>>>       struct resource *mem;
>>> @@ -191,6 +120,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>  {
>>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>       unsigned int status, trim_info, con;
>>>       unsigned int rising_threshold = 0, falling_threshold = 0;
>>>       int ret = 0, threshold_code, i, trigger_levs = 0;
>>> @@ -198,20 +128,20 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>>
>>> -     status = readb(data->base + EXYNOS_TMU_REG_STATUS);
>>> +     status = readb(data->base + reg->tmu_status);
>>>       if (!status) {
>>>               ret = -EBUSY;
>>>               goto out;
>>>       }
>>>
>>> -     if (data->soc == SOC_ARCH_EXYNOS) {
>>> -             __raw_writel(EXYNOS_TRIMINFO_RELOAD,
>>> -                             data->base + EXYNOS_TMU_TRIMINFO_CON);
>>> -     }
>>> +     if (data->soc == SOC_ARCH_EXYNOS)
>>> +             __raw_writel(1, data->base + reg->triminfo_ctrl);
>>> +
>>>       /* Save trimming info in order to perform calibration */
>>> -     trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
>>> -     data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
>>> -     data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
>>> +     trim_info = readl(data->base + reg->triminfo_data);
>>> +     data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
>>> +     data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
>>> +                             EXYNOS_TMU_TEMP_MASK);
>>
>> You changed from EXYNOS_TMU_TRIM_TEMP_MASK to EXYNOS_TMU_TEMP_MASK. Was
>> it this really what you wanted?
> Actually temp masks are same so removed  EXYNOS_TMU_TRIM_TEMP_MASK.

ok

>>
>>>
>>>       if ((pdata->min_efuse_value > data->temp_error1) ||
>>>                       (data->temp_error1 > pdata->max_efuse_value) ||
>>> @@ -231,13 +161,12 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>                       goto out;
>>>               }
>>>               writeb(threshold_code,
>>> -                     data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
>>> +                     data->base + reg->threshold_temp);
>>>               for (i = 0; i < trigger_levs; i++)
>>>                       writeb(pdata->trigger_levels[i],
>>> -                     data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
>>> +                     data->base + reg->threshold_th0 + i * 4);
>>>
>>
>> Is 4 your addressing unit? I believe there is a macro definition for this.
> yes 4 is a addressing unit. This is only used for 1 SOC so didn't define macro.

Yeah, I though we would have one already. Quick git grep and could not
find. How about using sizeof(void *) ?

>>
>>> -             writel(EXYNOS4210_TMU_INTCLEAR_VAL,
>>> -                     data->base + EXYNOS_TMU_REG_INTCLEAR);
>>> +             writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>>>       } else if (data->soc == SOC_ARCH_EXYNOS) {
>>>               /* Write temperature code for rising and falling threshold */
>>>               for (i = 0; i < trigger_levs; i++) {
>>> @@ -258,18 +187,19 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>                       }
>>>                       if (pdata->trigger_type[i] != HW_TRIP)
>>>                               continue;
>>> -                     con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
>>> -                     con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
>>> -                     writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
>>> +                     con = readl(data->base + reg->tmu_ctrl);
>>> +                     con |= (1 << reg->therm_trip_en_shift);
>>> +                     writel(con, data->base + reg->tmu_ctrl);
>>>               }
>>>
>>>               writel(rising_threshold,
>>> -                             data->base + EXYNOS_THD_TEMP_RISE);
>>> +                             data->base + reg->threshold_th0);
>>>               writel(falling_threshold,
>>> -                             data->base + EXYNOS_THD_TEMP_FALL);
>>> +                             data->base + reg->threshold_th1);
>>>
>>> -             writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
>>> -                             data->base + EXYNOS_TMU_REG_INTCLEAR);
>>> +             writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>>> +                     (reg->inten_fall_mask << reg->inten_fall_shift),
>>> +                             data->base + reg->tmu_intclear);
>>>       }
>>>  out:
>>>       clk_disable(data->clk);
>>> @@ -282,46 +212,46 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>>  {
>>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>       unsigned int con, interrupt_en;
>>>
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>>
>>> -     con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
>>> +     con = readl(data->base + reg->tmu_ctrl);
>>>
>>>       if (pdata->reference_voltage) {
>>> -             con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK <<
>>> -                             EXYNOS_TMU_REF_VOLTAGE_SHIFT);
>>> -             con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
>>> +             con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
>>> +             con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
>>>       }
>>>
>>>       if (pdata->gain) {
>>> -             con &= ~(EXYNOS_TMU_GAIN_MASK << EXYNOS_TMU_GAIN_SHIFT);
>>> -             con |= (pdata->gain << EXYNOS_TMU_GAIN_SHIFT);
>>> +             con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
>>> +             con |= (pdata->gain << reg->buf_slope_sel_shift);
>>>       }
>>>
>>>       if (pdata->noise_cancel_mode) {
>>> -             con &= ~(EXYNOS_TMU_TRIP_MODE_MASK <<
>>> -                                     EXYNOS_TMU_TRIP_MODE_SHIFT);
>>> -             con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
>>> +             con &= ~(reg->therm_trip_mode_mask <<
>>> +                                     reg->therm_trip_mode_shift);
>>> +             con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
>>>       }
>>>
>>>       if (on) {
>>> -             con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
>>> +             con |= (1 << reg->core_en_shift);
>>>               interrupt_en =
>>> -             pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT |
>>> -             pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT |
>>> -             pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT |
>>> -             pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT;
>>> +                     pdata->trigger_enable[3] << reg->inten_rise3_shift |
>>> +                     pdata->trigger_enable[2] << reg->inten_rise2_shift |
>>> +                     pdata->trigger_enable[1] << reg->inten_rise1_shift |
>>> +                     pdata->trigger_enable[0] << reg->inten_rise0_shift;
>>>               if (pdata->threshold_falling)
>>>                       interrupt_en |=
>>> -                             interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
>>> +                             interrupt_en << reg->inten_fall0_shift;
>>>       } else {
>>> -             con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
>>> +             con &= ~(1 << reg->core_en_shift);
>>>               interrupt_en = 0; /* Disable all interrupts */
>>>       }
>>> -     writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
>>> -     writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
>>> +     writel(interrupt_en, data->base + reg->tmu_inten);
>>> +     writel(con, data->base + reg->tmu_ctrl);
>>>
>>>       clk_disable(data->clk);
>>>       mutex_unlock(&data->lock);
>>> @@ -329,13 +259,15 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>>
>>>  static int exynos_tmu_read(struct exynos_tmu_data *data)
>>>  {
>>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>       u8 temp_code;
>>>       int temp;
>>>
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>>
>>> -     temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
>>> +     temp_code = readb(data->base + reg->tmu_cur_temp);
>>>       temp = code_to_temp(data, temp_code);
>>>
>>>       clk_disable(data->clk);
>>> @@ -348,7 +280,9 @@ static int exynos_tmu_read(struct exynos_tmu_data *data)
>>>  static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>>>  {
>>>       struct exynos_tmu_data *data = drv_data;
>>> -     unsigned int reg;
>>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>> +     unsigned int val;
>>>       int ret = -EINVAL;
>>>
>>>       if (data->soc == SOC_ARCH_EXYNOS4210)
>>> @@ -360,19 +294,19 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>>
>>> -     reg = readl(data->base + EXYNOS_EMUL_CON);
>>> +     val = readl(data->base + reg->emul_con);
>>>
>>>       if (temp) {
>>>               temp /= MCELSIUS;
>>>
>>> -             reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
>>> +             val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
>>>                       (temp_to_code(data, temp)
>>> -                      << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
>>> +                      << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
>>>       } else {
>>> -             reg &= ~EXYNOS_EMUL_ENABLE;
>>> +             val &= ~EXYNOS_EMUL_ENABLE;
>>>       }
>>>
>>> -     writel(reg, data->base + EXYNOS_EMUL_CON);
>>> +     writel(val, data->base + reg->emul_con);
>>>
>>>       clk_disable(data->clk);
>>>       mutex_unlock(&data->lock);
>>> @@ -389,17 +323,20 @@ static void exynos_tmu_work(struct work_struct *work)
>>>  {
>>>       struct exynos_tmu_data *data = container_of(work,
>>>                       struct exynos_tmu_data, irq_work);
>>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>
>>>       exynos_report_trigger();
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>> +
>>>       if (data->soc == SOC_ARCH_EXYNOS)
>>> -             writel(EXYNOS_TMU_CLEAR_RISE_INT |
>>> -                             EXYNOS_TMU_CLEAR_FALL_INT,
>>> -                             data->base + EXYNOS_TMU_REG_INTCLEAR);
>>> +             writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>>> +                     (reg->inten_fall_mask << reg->inten_fall_shift),
>>> +                             data->base + reg->tmu_intclear);
>>>       else
>>> -             writel(EXYNOS4210_TMU_INTCLEAR_VAL,
>>> -                             data->base + EXYNOS_TMU_REG_INTCLEAR);
>>> +             writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>>> +
>>>       clk_disable(data->clk);
>>>       mutex_unlock(&data->lock);
>>>
>>> diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
>>> index 70cc518..1e5e492 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu.h
>>> +++ b/drivers/thermal/samsung/exynos_tmu.h
>>> @@ -46,6 +46,81 @@ enum soc_type {
>>>  };
>>>
>>>  /**
>>> + * struct exynos_tmu_register - register descriptors to access registers and
>>> + * bitfields. The register validity, offsets and bitfield values may vary
>>> + * slightly across different exynos SOC's.
>>
>> No documentation for your registers? Or at least where to find explanation?
> yes didn't write documentation. Will do it.
>>
>>> + */
>>> +struct exynos_tmu_registers {
>>> +     u32     triminfo_data;
>>> +     u32     triminfo_25_shift;
>>> +     u32     triminfo_85_shift;
>>> +
>>> +     u32     triminfo_ctrl;
>>> +     u32     triminfo_reload_shift;
>>> +
>>> +     u32     tmu_ctrl;
>>> +     u32     buf_vref_sel_shift;
>>> +     u32     buf_vref_sel_mask;
>>> +     u32     therm_trip_mode_shift;
>>> +     u32     therm_trip_mode_mask;
>>> +     u32     therm_trip_en_shift;
>>> +     u32     buf_slope_sel_shift;
>>> +     u32     buf_slope_sel_mask;
>>> +     u32     therm_trip_tq_en_shift;
>>> +     u32     core_en_shift;
>>> +
>>> +     u32     tmu_status;
>>> +
>>> +     u32     tmu_cur_temp;
>>> +     u32     tmu_cur_temp_shift;
>>> +
>>> +     u32     threshold_temp;
>>> +
>>> +     u32     threshold_th0;
>>> +     u32     threshold_th0_l0_shift;
>>> +     u32     threshold_th0_l1_shift;
>>> +     u32     threshold_th0_l2_shift;
>>> +     u32     threshold_th0_l3_shift;
>>> +
>>> +     u32     threshold_th1;
>>> +     u32     threshold_th1_l0_shift;
>>> +     u32     threshold_th1_l1_shift;
>>> +     u32     threshold_th1_l2_shift;
>>> +     u32     threshold_th1_l3_shift;
>>> +
>>> +     u32     threshold_th2;
>>> +     u32     threshold_th2_l0_shift;
>>> +
>>> +     u32     threshold_th3;
>>> +     u32     threshold_th3_l0_shift;
>>> +
>>> +     u32     tmu_inten;
>>> +     u32     inten_rise_shift;
>>> +     u32     inten_rise_mask;
>>> +     u32     inten_fall_shift;
>>> +     u32     inten_fall_mask;
>>> +     u32     inten_rise0_shift;
>>> +     u32     inten_rise1_shift;
>>> +     u32     inten_rise2_shift;
>>> +     u32     inten_rise3_shift;
>>> +     u32     inten_fall0_shift;
>>> +     u32     inten_fall1_shift;
>>> +     u32     inten_fall2_shift;
>>> +     u32     inten_fall3_shift;
>>> +
>>> +     u32     tmu_intstat;
>>> +
>>> +     u32     tmu_intclear;
>>> +
>>> +     u32     tmu_evten;
>>> +
>>> +     u32     emul_con;
>>> +     u32     emul_temp_shift;
>>> +     u32     emul_time_shift;
>>> +     u32     emul_time_mask;
>>> +};
>>> +
>>> +/**
>>>   * struct exynos_tmu_platform_data
>>>   * @threshold: basic temperature for generating interrupt
>>>   *          25 <= threshold <= 125 [unit: degree Celsius]
>>> @@ -116,5 +191,6 @@ struct exynos_tmu_platform_data {
>>>       enum soc_type type;
>>>       struct freq_clip_table freq_tab[4];
>>>       unsigned int freq_tab_count;
>>> +     struct exynos_tmu_registers *registers;
>>>  };
>>>  #endif /* _LINUX_EXYNOS_THERMAL_H */
>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
>>> index 6b937f5..3a1ded1 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu_data.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
>>> @@ -25,6 +25,28 @@
>>>  #include "exynos_tmu_data.h"
>>>
>>>  #if defined(CONFIG_CPU_EXYNOS4210)
>>> +static struct exynos_tmu_registers exynos4210_tmu_registers = {
>>> +     .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
>>> +     .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
>>> +     .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
>>> +     .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
>>> +     .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
>>> +     .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
>>> +     .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
>>> +     .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
>>> +     .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
>>> +     .tmu_status = EXYNOS_TMU_REG_STATUS,
>>> +     .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
>>> +     .threshold_temp = EXYNOS4210_TMU_REG_THRESHOLD_TEMP,
>>> +     .threshold_th0 = EXYNOS4210_TMU_REG_TRIG_LEVEL0,
>>> +     .tmu_inten = EXYNOS_TMU_REG_INTEN,
>>> +     .inten_rise_mask = EXYNOS4210_TMU_TRIG_LEVEL_MASK,
>>> +     .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
>>> +     .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>>> +     .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>> +     .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>> +     .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>> +};
>>>  struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>>       .threshold = 80,
>>>       .trigger_levels[0] = 5,
>>> @@ -55,10 +77,46 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>>       },
>>>       .freq_tab_count = 2,
>>>       .type = SOC_ARCH_EXYNOS4210,
>>> +     .registers = &exynos4210_tmu_registers,
>>>  };
>>>  #endif
>>>
>>>  #if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
>>> +static struct exynos_tmu_registers exynos5250_tmu_registers = {
>>> +     .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
>>> +     .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
>>> +     .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
>>> +     .triminfo_ctrl = EXYNOS_TMU_TRIMINFO_CON,
>>> +     .triminfo_reload_shift = EXYNOS_TRIMINFO_RELOAD_SHIFT,
>>> +     .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
>>> +     .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
>>> +     .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
>>> +     .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
>>> +     .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
>>> +     .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
>>> +     .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
>>> +     .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
>>> +     .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
>>> +     .tmu_status = EXYNOS_TMU_REG_STATUS,
>>> +     .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
>>> +     .threshold_th0 = EXYNOS_THD_TEMP_RISE,
>>> +     .threshold_th1 = EXYNOS_THD_TEMP_FALL,
>>> +     .tmu_inten = EXYNOS_TMU_REG_INTEN,
>>> +     .inten_rise_mask = EXYNOS_TMU_RISE_INT_MASK,
>>> +     .inten_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
>>> +     .inten_fall_mask = EXYNOS_TMU_FALL_INT_MASK,
>>> +     .inten_fall_shift = EXYNOS_TMU_FALL_INT_SHIFT,
>>> +     .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
>>> +     .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>>> +     .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>> +     .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>> +     .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
>>> +     .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>> +     .emul_con = EXYNOS_EMUL_CON,
>>> +     .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
>>> +     .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
>>> +     .emul_time_mask = EXYNOS_EMUL_TIME_MASK,
>>> +};
>>>  struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>>>       .threshold_falling = 10,
>>>       .trigger_levels[0] = 85,
>>> @@ -93,5 +151,6 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>>>       },
>>>       .freq_tab_count = 2,
>>>       .type = SOC_ARCH_EXYNOS,
>>> +     .registers = &exynos5250_tmu_registers,
>>>  };
>>>  #endif
>>
>> One thing, I believe your data can be declared as const.
> yes they are already const.
> 

Not all. The register structs you are adding are not const, for instance.

> Thanks,
> Amit Daniel
>>
>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
>>> index 5b69711..0560413 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu_data.h
>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
>>> @@ -23,6 +23,74 @@
>>>  #ifndef _LINUX_EXYNOS_TMU_DATA_H
>>>  #define _LINUX_EXYNOS_TMU_DATA_H
>>>
>>> +/* Exynos generic registers */
>>> +#define EXYNOS_TMU_REG_TRIMINFO              0x0
>>> +#define EXYNOS_TMU_REG_CONTROL               0x20
>>> +#define EXYNOS_TMU_REG_STATUS                0x28
>>> +#define EXYNOS_TMU_REG_CURRENT_TEMP  0x40
>>> +#define EXYNOS_TMU_REG_INTEN         0x70
>>> +#define EXYNOS_TMU_REG_INTSTAT               0x74
>>> +#define EXYNOS_TMU_REG_INTCLEAR              0x78
>>> +
>>> +#define EXYNOS_TMU_TEMP_MASK         0xff
>>> +#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
>>> +#define EXYNOS_TMU_REF_VOLTAGE_MASK  0x1f
>>> +#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK        0xf
>>> +#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT       8
>>> +#define EXYNOS_TMU_CORE_EN_SHIFT     0
>>> +
>>> +/* Exynos4210 specific registers */
>>> +#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP    0x44
>>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL0       0x50
>>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL1       0x54
>>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL2       0x58
>>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL3       0x5C
>>> +#define EXYNOS4210_TMU_REG_PAST_TEMP0        0x60
>>> +#define EXYNOS4210_TMU_REG_PAST_TEMP1        0x64
>>> +#define EXYNOS4210_TMU_REG_PAST_TEMP2        0x68
>>> +#define EXYNOS4210_TMU_REG_PAST_TEMP3        0x6C
>>> +
>>> +#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK      0x1
>>> +#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK      0x10
>>> +#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK      0x100
>>> +#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK      0x1000
>>> +#define EXYNOS4210_TMU_TRIG_LEVEL_MASK       0x1111
>>> +#define EXYNOS4210_TMU_INTCLEAR_VAL  0x1111
>>> +
>>> +/* Exynos5250 and Exynos4412 specific registers */
>>> +#define EXYNOS_TMU_TRIMINFO_CON      0x14
>>> +#define EXYNOS_THD_TEMP_RISE         0x50
>>> +#define EXYNOS_THD_TEMP_FALL         0x54
>>> +#define EXYNOS_EMUL_CON              0x80
>>> +
>>> +#define EXYNOS_TRIMINFO_RELOAD_SHIFT 1
>>> +#define EXYNOS_TRIMINFO_25_SHIFT     0
>>> +#define EXYNOS_TRIMINFO_85_SHIFT     8
>>> +#define EXYNOS_TMU_RISE_INT_MASK     0x111
>>> +#define EXYNOS_TMU_RISE_INT_SHIFT    0
>>> +#define EXYNOS_TMU_FALL_INT_MASK     0x111
>>> +#define EXYNOS_TMU_FALL_INT_SHIFT    12
>>> +#define EXYNOS_TMU_CLEAR_RISE_INT    0x111
>>> +#define EXYNOS_TMU_CLEAR_FALL_INT    (0x111 << 12)
>>> +#define EXYNOS_TMU_TRIP_MODE_SHIFT   13
>>> +#define EXYNOS_TMU_TRIP_MODE_MASK    0x7
>>> +#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT       12
>>> +
>>> +#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
>>> +#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
>>> +#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
>>> +#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
>>> +#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
>>> +#define EXYNOS_TMU_INTEN_FALL1_SHIFT 20
>>> +#define EXYNOS_TMU_INTEN_FALL2_SHIFT 24
>>> +
>>> +#define EXYNOS_EMUL_TIME     0x57F0
>>> +#define EXYNOS_EMUL_TIME_MASK        0xffff
>>> +#define EXYNOS_EMUL_TIME_SHIFT       16
>>> +#define EXYNOS_EMUL_DATA_SHIFT       8
>>> +#define EXYNOS_EMUL_DATA_MASK        0xFF
>>> +#define EXYNOS_EMUL_ENABLE   0x1
>>> +
>>>  #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>>>  extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
>>>  #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
>>>
>>
>>
> 
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 09/21] thermal: exynos: Move register definitions from driver file to data file
@ 2013-05-10 14:14         ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-10 14:14 UTC (permalink / raw)
  To: amit daniel kachhap
  Cc: Eduardo Valentin, linux-pm, Zhang Rui, linux-samsung-soc,
	linux-kernel, Kukjin Kim

[-- Attachment #1: Type: text/plain, Size: 27700 bytes --]

On 09-05-2013 22:17, amit daniel kachhap wrote:
> Hi Eduardo,
> 
> On Thu, May 9, 2013 at 8:02 PM, Eduardo Valentin
> <eduardo.valentin@ti.com> wrote:
>> Hey Amit,
>>
>> On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
>>> This patch migrates the TMU register definition/bitfields to data file. This
>>> is needed to support SoC's which use the same TMU controller but register
>>> validity, offsets or bitfield may slightly vary across SOC's.
>>>
>>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>>> ---
>>>  drivers/thermal/samsung/exynos_tmu.c      |  177 +++++++++-------------------
>>>  drivers/thermal/samsung/exynos_tmu.h      |   76 ++++++++++++
>>>  drivers/thermal/samsung/exynos_tmu_data.c |   59 ++++++++++
>>>  drivers/thermal/samsung/exynos_tmu_data.h |   68 +++++++++++
>>>  4 files changed, 260 insertions(+), 120 deletions(-)
>>>
>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>>> index 23baeeb..97b87aa 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>>> @@ -36,77 +36,6 @@
>>>  #include "exynos_tmu.h"
>>>  #include "exynos_tmu_data.h"
>>>
>>> -/* Exynos generic registers */
>>> -#define EXYNOS_TMU_REG_TRIMINFO              0x0
>>> -#define EXYNOS_TMU_REG_CONTROL               0x20
>>> -#define EXYNOS_TMU_REG_STATUS                0x28
>>> -#define EXYNOS_TMU_REG_CURRENT_TEMP  0x40
>>> -#define EXYNOS_TMU_REG_INTEN         0x70
>>> -#define EXYNOS_TMU_REG_INTSTAT               0x74
>>> -#define EXYNOS_TMU_REG_INTCLEAR              0x78
>>> -
>>> -#define EXYNOS_TMU_TRIM_TEMP_MASK    0xff
>>> -#define EXYNOS_TMU_GAIN_SHIFT                8
>>> -#define EXYNOS_TMU_GAIN_MASK         0xf
>>> -#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
>>> -#define EXYNOS_TMU_REF_VOLTAGE_MASK  0x1f
>>> -#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK        0xf
>>> -#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT       8
>>> -#define EXYNOS_TMU_CORE_EN_SHIFT     0
>>> -
>>> -/* Exynos4210 specific registers */
>>> -#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP    0x44
>>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL0       0x50
>>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL1       0x54
>>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL2       0x58
>>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL3       0x5C
>>> -#define EXYNOS4210_TMU_REG_PAST_TEMP0        0x60
>>> -#define EXYNOS4210_TMU_REG_PAST_TEMP1        0x64
>>> -#define EXYNOS4210_TMU_REG_PAST_TEMP2        0x68
>>> -#define EXYNOS4210_TMU_REG_PAST_TEMP3        0x6C
>>> -
>>> -#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK      0x1
>>> -#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK      0x10
>>> -#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK      0x100
>>> -#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK      0x1000
>>> -#define EXYNOS4210_TMU_TRIG_LEVEL_MASK       0x1111
>>> -#define EXYNOS4210_TMU_INTCLEAR_VAL  0x1111
>>> -
>>> -/* Exynos5250 and Exynos4412 specific registers */
>>> -#define EXYNOS_TMU_TRIMINFO_CON      0x14
>>> -#define EXYNOS_THD_TEMP_RISE         0x50
>>> -#define EXYNOS_THD_TEMP_FALL         0x54
>>> -#define EXYNOS_EMUL_CON              0x80
>>> -
>>> -#define EXYNOS_TRIMINFO_RELOAD               0x1
>>> -#define EXYNOS_TRIMINFO_SHIFT                0x0
>>> -#define EXYNOS_TMU_RISE_INT_MASK     0x111
>>> -#define EXYNOS_TMU_RISE_INT_SHIFT    0
>>> -#define EXYNOS_TMU_FALL_INT_MASK     0x111
>>> -#define EXYNOS_TMU_FALL_INT_SHIFT    12
>>> -#define EXYNOS_TMU_CLEAR_RISE_INT    0x111
>>> -#define EXYNOS_TMU_CLEAR_FALL_INT    (0x111 << 12)
>>> -#define EXYNOS_TMU_TRIP_MODE_SHIFT   13
>>> -#define EXYNOS_TMU_TRIP_MODE_MASK    0x7
>>> -#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT       12
>>> -
>>> -#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
>>> -#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
>>> -#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
>>> -#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
>>> -#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
>>> -#define EXYNOS_TMU_INTEN_FALL1_SHIFT 20
>>> -#define EXYNOS_TMU_INTEN_FALL2_SHIFT 24
>>> -
>>> -#ifdef CONFIG_THERMAL_EMULATION
>>> -#define EXYNOS_EMUL_TIME     0x57F0
>>> -#define EXYNOS_EMUL_TIME_MASK        0xffff
>>> -#define EXYNOS_EMUL_TIME_SHIFT       16
>>> -#define EXYNOS_EMUL_DATA_SHIFT       8
>>> -#define EXYNOS_EMUL_DATA_MASK        0xFF
>>> -#define EXYNOS_EMUL_ENABLE   0x1
>>> -#endif /* CONFIG_THERMAL_EMULATION */
>>> -
>>>  struct exynos_tmu_data {
>>>       struct exynos_tmu_platform_data *pdata;
>>>       struct resource *mem;
>>> @@ -191,6 +120,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>  {
>>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>       unsigned int status, trim_info, con;
>>>       unsigned int rising_threshold = 0, falling_threshold = 0;
>>>       int ret = 0, threshold_code, i, trigger_levs = 0;
>>> @@ -198,20 +128,20 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>>
>>> -     status = readb(data->base + EXYNOS_TMU_REG_STATUS);
>>> +     status = readb(data->base + reg->tmu_status);
>>>       if (!status) {
>>>               ret = -EBUSY;
>>>               goto out;
>>>       }
>>>
>>> -     if (data->soc == SOC_ARCH_EXYNOS) {
>>> -             __raw_writel(EXYNOS_TRIMINFO_RELOAD,
>>> -                             data->base + EXYNOS_TMU_TRIMINFO_CON);
>>> -     }
>>> +     if (data->soc == SOC_ARCH_EXYNOS)
>>> +             __raw_writel(1, data->base + reg->triminfo_ctrl);
>>> +
>>>       /* Save trimming info in order to perform calibration */
>>> -     trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
>>> -     data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
>>> -     data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
>>> +     trim_info = readl(data->base + reg->triminfo_data);
>>> +     data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
>>> +     data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
>>> +                             EXYNOS_TMU_TEMP_MASK);
>>
>> You changed from EXYNOS_TMU_TRIM_TEMP_MASK to EXYNOS_TMU_TEMP_MASK. Was
>> it this really what you wanted?
> Actually temp masks are same so removed  EXYNOS_TMU_TRIM_TEMP_MASK.

ok

>>
>>>
>>>       if ((pdata->min_efuse_value > data->temp_error1) ||
>>>                       (data->temp_error1 > pdata->max_efuse_value) ||
>>> @@ -231,13 +161,12 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>                       goto out;
>>>               }
>>>               writeb(threshold_code,
>>> -                     data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
>>> +                     data->base + reg->threshold_temp);
>>>               for (i = 0; i < trigger_levs; i++)
>>>                       writeb(pdata->trigger_levels[i],
>>> -                     data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
>>> +                     data->base + reg->threshold_th0 + i * 4);
>>>
>>
>> Is 4 your addressing unit? I believe there is a macro definition for this.
> yes 4 is a addressing unit. This is only used for 1 SOC so didn't define macro.

Yeah, I though we would have one already. Quick git grep and could not
find. How about using sizeof(void *) ?

>>
>>> -             writel(EXYNOS4210_TMU_INTCLEAR_VAL,
>>> -                     data->base + EXYNOS_TMU_REG_INTCLEAR);
>>> +             writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>>>       } else if (data->soc == SOC_ARCH_EXYNOS) {
>>>               /* Write temperature code for rising and falling threshold */
>>>               for (i = 0; i < trigger_levs; i++) {
>>> @@ -258,18 +187,19 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>                       }
>>>                       if (pdata->trigger_type[i] != HW_TRIP)
>>>                               continue;
>>> -                     con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
>>> -                     con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
>>> -                     writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
>>> +                     con = readl(data->base + reg->tmu_ctrl);
>>> +                     con |= (1 << reg->therm_trip_en_shift);
>>> +                     writel(con, data->base + reg->tmu_ctrl);
>>>               }
>>>
>>>               writel(rising_threshold,
>>> -                             data->base + EXYNOS_THD_TEMP_RISE);
>>> +                             data->base + reg->threshold_th0);
>>>               writel(falling_threshold,
>>> -                             data->base + EXYNOS_THD_TEMP_FALL);
>>> +                             data->base + reg->threshold_th1);
>>>
>>> -             writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
>>> -                             data->base + EXYNOS_TMU_REG_INTCLEAR);
>>> +             writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>>> +                     (reg->inten_fall_mask << reg->inten_fall_shift),
>>> +                             data->base + reg->tmu_intclear);
>>>       }
>>>  out:
>>>       clk_disable(data->clk);
>>> @@ -282,46 +212,46 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>>  {
>>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>       unsigned int con, interrupt_en;
>>>
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>>
>>> -     con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
>>> +     con = readl(data->base + reg->tmu_ctrl);
>>>
>>>       if (pdata->reference_voltage) {
>>> -             con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK <<
>>> -                             EXYNOS_TMU_REF_VOLTAGE_SHIFT);
>>> -             con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
>>> +             con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
>>> +             con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
>>>       }
>>>
>>>       if (pdata->gain) {
>>> -             con &= ~(EXYNOS_TMU_GAIN_MASK << EXYNOS_TMU_GAIN_SHIFT);
>>> -             con |= (pdata->gain << EXYNOS_TMU_GAIN_SHIFT);
>>> +             con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
>>> +             con |= (pdata->gain << reg->buf_slope_sel_shift);
>>>       }
>>>
>>>       if (pdata->noise_cancel_mode) {
>>> -             con &= ~(EXYNOS_TMU_TRIP_MODE_MASK <<
>>> -                                     EXYNOS_TMU_TRIP_MODE_SHIFT);
>>> -             con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
>>> +             con &= ~(reg->therm_trip_mode_mask <<
>>> +                                     reg->therm_trip_mode_shift);
>>> +             con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
>>>       }
>>>
>>>       if (on) {
>>> -             con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
>>> +             con |= (1 << reg->core_en_shift);
>>>               interrupt_en =
>>> -             pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT |
>>> -             pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT |
>>> -             pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT |
>>> -             pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT;
>>> +                     pdata->trigger_enable[3] << reg->inten_rise3_shift |
>>> +                     pdata->trigger_enable[2] << reg->inten_rise2_shift |
>>> +                     pdata->trigger_enable[1] << reg->inten_rise1_shift |
>>> +                     pdata->trigger_enable[0] << reg->inten_rise0_shift;
>>>               if (pdata->threshold_falling)
>>>                       interrupt_en |=
>>> -                             interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
>>> +                             interrupt_en << reg->inten_fall0_shift;
>>>       } else {
>>> -             con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
>>> +             con &= ~(1 << reg->core_en_shift);
>>>               interrupt_en = 0; /* Disable all interrupts */
>>>       }
>>> -     writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
>>> -     writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
>>> +     writel(interrupt_en, data->base + reg->tmu_inten);
>>> +     writel(con, data->base + reg->tmu_ctrl);
>>>
>>>       clk_disable(data->clk);
>>>       mutex_unlock(&data->lock);
>>> @@ -329,13 +259,15 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>>
>>>  static int exynos_tmu_read(struct exynos_tmu_data *data)
>>>  {
>>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>       u8 temp_code;
>>>       int temp;
>>>
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>>
>>> -     temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
>>> +     temp_code = readb(data->base + reg->tmu_cur_temp);
>>>       temp = code_to_temp(data, temp_code);
>>>
>>>       clk_disable(data->clk);
>>> @@ -348,7 +280,9 @@ static int exynos_tmu_read(struct exynos_tmu_data *data)
>>>  static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>>>  {
>>>       struct exynos_tmu_data *data = drv_data;
>>> -     unsigned int reg;
>>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>> +     unsigned int val;
>>>       int ret = -EINVAL;
>>>
>>>       if (data->soc == SOC_ARCH_EXYNOS4210)
>>> @@ -360,19 +294,19 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>>
>>> -     reg = readl(data->base + EXYNOS_EMUL_CON);
>>> +     val = readl(data->base + reg->emul_con);
>>>
>>>       if (temp) {
>>>               temp /= MCELSIUS;
>>>
>>> -             reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
>>> +             val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
>>>                       (temp_to_code(data, temp)
>>> -                      << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
>>> +                      << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
>>>       } else {
>>> -             reg &= ~EXYNOS_EMUL_ENABLE;
>>> +             val &= ~EXYNOS_EMUL_ENABLE;
>>>       }
>>>
>>> -     writel(reg, data->base + EXYNOS_EMUL_CON);
>>> +     writel(val, data->base + reg->emul_con);
>>>
>>>       clk_disable(data->clk);
>>>       mutex_unlock(&data->lock);
>>> @@ -389,17 +323,20 @@ static void exynos_tmu_work(struct work_struct *work)
>>>  {
>>>       struct exynos_tmu_data *data = container_of(work,
>>>                       struct exynos_tmu_data, irq_work);
>>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>
>>>       exynos_report_trigger();
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>> +
>>>       if (data->soc == SOC_ARCH_EXYNOS)
>>> -             writel(EXYNOS_TMU_CLEAR_RISE_INT |
>>> -                             EXYNOS_TMU_CLEAR_FALL_INT,
>>> -                             data->base + EXYNOS_TMU_REG_INTCLEAR);
>>> +             writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>>> +                     (reg->inten_fall_mask << reg->inten_fall_shift),
>>> +                             data->base + reg->tmu_intclear);
>>>       else
>>> -             writel(EXYNOS4210_TMU_INTCLEAR_VAL,
>>> -                             data->base + EXYNOS_TMU_REG_INTCLEAR);
>>> +             writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>>> +
>>>       clk_disable(data->clk);
>>>       mutex_unlock(&data->lock);
>>>
>>> diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
>>> index 70cc518..1e5e492 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu.h
>>> +++ b/drivers/thermal/samsung/exynos_tmu.h
>>> @@ -46,6 +46,81 @@ enum soc_type {
>>>  };
>>>
>>>  /**
>>> + * struct exynos_tmu_register - register descriptors to access registers and
>>> + * bitfields. The register validity, offsets and bitfield values may vary
>>> + * slightly across different exynos SOC's.
>>
>> No documentation for your registers? Or at least where to find explanation?
> yes didn't write documentation. Will do it.
>>
>>> + */
>>> +struct exynos_tmu_registers {
>>> +     u32     triminfo_data;
>>> +     u32     triminfo_25_shift;
>>> +     u32     triminfo_85_shift;
>>> +
>>> +     u32     triminfo_ctrl;
>>> +     u32     triminfo_reload_shift;
>>> +
>>> +     u32     tmu_ctrl;
>>> +     u32     buf_vref_sel_shift;
>>> +     u32     buf_vref_sel_mask;
>>> +     u32     therm_trip_mode_shift;
>>> +     u32     therm_trip_mode_mask;
>>> +     u32     therm_trip_en_shift;
>>> +     u32     buf_slope_sel_shift;
>>> +     u32     buf_slope_sel_mask;
>>> +     u32     therm_trip_tq_en_shift;
>>> +     u32     core_en_shift;
>>> +
>>> +     u32     tmu_status;
>>> +
>>> +     u32     tmu_cur_temp;
>>> +     u32     tmu_cur_temp_shift;
>>> +
>>> +     u32     threshold_temp;
>>> +
>>> +     u32     threshold_th0;
>>> +     u32     threshold_th0_l0_shift;
>>> +     u32     threshold_th0_l1_shift;
>>> +     u32     threshold_th0_l2_shift;
>>> +     u32     threshold_th0_l3_shift;
>>> +
>>> +     u32     threshold_th1;
>>> +     u32     threshold_th1_l0_shift;
>>> +     u32     threshold_th1_l1_shift;
>>> +     u32     threshold_th1_l2_shift;
>>> +     u32     threshold_th1_l3_shift;
>>> +
>>> +     u32     threshold_th2;
>>> +     u32     threshold_th2_l0_shift;
>>> +
>>> +     u32     threshold_th3;
>>> +     u32     threshold_th3_l0_shift;
>>> +
>>> +     u32     tmu_inten;
>>> +     u32     inten_rise_shift;
>>> +     u32     inten_rise_mask;
>>> +     u32     inten_fall_shift;
>>> +     u32     inten_fall_mask;
>>> +     u32     inten_rise0_shift;
>>> +     u32     inten_rise1_shift;
>>> +     u32     inten_rise2_shift;
>>> +     u32     inten_rise3_shift;
>>> +     u32     inten_fall0_shift;
>>> +     u32     inten_fall1_shift;
>>> +     u32     inten_fall2_shift;
>>> +     u32     inten_fall3_shift;
>>> +
>>> +     u32     tmu_intstat;
>>> +
>>> +     u32     tmu_intclear;
>>> +
>>> +     u32     tmu_evten;
>>> +
>>> +     u32     emul_con;
>>> +     u32     emul_temp_shift;
>>> +     u32     emul_time_shift;
>>> +     u32     emul_time_mask;
>>> +};
>>> +
>>> +/**
>>>   * struct exynos_tmu_platform_data
>>>   * @threshold: basic temperature for generating interrupt
>>>   *          25 <= threshold <= 125 [unit: degree Celsius]
>>> @@ -116,5 +191,6 @@ struct exynos_tmu_platform_data {
>>>       enum soc_type type;
>>>       struct freq_clip_table freq_tab[4];
>>>       unsigned int freq_tab_count;
>>> +     struct exynos_tmu_registers *registers;
>>>  };
>>>  #endif /* _LINUX_EXYNOS_THERMAL_H */
>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
>>> index 6b937f5..3a1ded1 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu_data.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
>>> @@ -25,6 +25,28 @@
>>>  #include "exynos_tmu_data.h"
>>>
>>>  #if defined(CONFIG_CPU_EXYNOS4210)
>>> +static struct exynos_tmu_registers exynos4210_tmu_registers = {
>>> +     .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
>>> +     .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
>>> +     .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
>>> +     .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
>>> +     .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
>>> +     .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
>>> +     .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
>>> +     .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
>>> +     .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
>>> +     .tmu_status = EXYNOS_TMU_REG_STATUS,
>>> +     .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
>>> +     .threshold_temp = EXYNOS4210_TMU_REG_THRESHOLD_TEMP,
>>> +     .threshold_th0 = EXYNOS4210_TMU_REG_TRIG_LEVEL0,
>>> +     .tmu_inten = EXYNOS_TMU_REG_INTEN,
>>> +     .inten_rise_mask = EXYNOS4210_TMU_TRIG_LEVEL_MASK,
>>> +     .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
>>> +     .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>>> +     .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>> +     .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>> +     .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>> +};
>>>  struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>>       .threshold = 80,
>>>       .trigger_levels[0] = 5,
>>> @@ -55,10 +77,46 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>>       },
>>>       .freq_tab_count = 2,
>>>       .type = SOC_ARCH_EXYNOS4210,
>>> +     .registers = &exynos4210_tmu_registers,
>>>  };
>>>  #endif
>>>
>>>  #if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
>>> +static struct exynos_tmu_registers exynos5250_tmu_registers = {
>>> +     .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
>>> +     .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
>>> +     .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
>>> +     .triminfo_ctrl = EXYNOS_TMU_TRIMINFO_CON,
>>> +     .triminfo_reload_shift = EXYNOS_TRIMINFO_RELOAD_SHIFT,
>>> +     .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
>>> +     .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
>>> +     .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
>>> +     .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
>>> +     .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
>>> +     .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
>>> +     .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
>>> +     .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
>>> +     .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
>>> +     .tmu_status = EXYNOS_TMU_REG_STATUS,
>>> +     .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
>>> +     .threshold_th0 = EXYNOS_THD_TEMP_RISE,
>>> +     .threshold_th1 = EXYNOS_THD_TEMP_FALL,
>>> +     .tmu_inten = EXYNOS_TMU_REG_INTEN,
>>> +     .inten_rise_mask = EXYNOS_TMU_RISE_INT_MASK,
>>> +     .inten_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
>>> +     .inten_fall_mask = EXYNOS_TMU_FALL_INT_MASK,
>>> +     .inten_fall_shift = EXYNOS_TMU_FALL_INT_SHIFT,
>>> +     .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
>>> +     .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>>> +     .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>> +     .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>> +     .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
>>> +     .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>> +     .emul_con = EXYNOS_EMUL_CON,
>>> +     .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
>>> +     .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
>>> +     .emul_time_mask = EXYNOS_EMUL_TIME_MASK,
>>> +};
>>>  struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>>>       .threshold_falling = 10,
>>>       .trigger_levels[0] = 85,
>>> @@ -93,5 +151,6 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>>>       },
>>>       .freq_tab_count = 2,
>>>       .type = SOC_ARCH_EXYNOS,
>>> +     .registers = &exynos5250_tmu_registers,
>>>  };
>>>  #endif
>>
>> One thing, I believe your data can be declared as const.
> yes they are already const.
> 

Not all. The register structs you are adding are not const, for instance.

> Thanks,
> Amit Daniel
>>
>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
>>> index 5b69711..0560413 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu_data.h
>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
>>> @@ -23,6 +23,74 @@
>>>  #ifndef _LINUX_EXYNOS_TMU_DATA_H
>>>  #define _LINUX_EXYNOS_TMU_DATA_H
>>>
>>> +/* Exynos generic registers */
>>> +#define EXYNOS_TMU_REG_TRIMINFO              0x0
>>> +#define EXYNOS_TMU_REG_CONTROL               0x20
>>> +#define EXYNOS_TMU_REG_STATUS                0x28
>>> +#define EXYNOS_TMU_REG_CURRENT_TEMP  0x40
>>> +#define EXYNOS_TMU_REG_INTEN         0x70
>>> +#define EXYNOS_TMU_REG_INTSTAT               0x74
>>> +#define EXYNOS_TMU_REG_INTCLEAR              0x78
>>> +
>>> +#define EXYNOS_TMU_TEMP_MASK         0xff
>>> +#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
>>> +#define EXYNOS_TMU_REF_VOLTAGE_MASK  0x1f
>>> +#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK        0xf
>>> +#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT       8
>>> +#define EXYNOS_TMU_CORE_EN_SHIFT     0
>>> +
>>> +/* Exynos4210 specific registers */
>>> +#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP    0x44
>>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL0       0x50
>>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL1       0x54
>>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL2       0x58
>>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL3       0x5C
>>> +#define EXYNOS4210_TMU_REG_PAST_TEMP0        0x60
>>> +#define EXYNOS4210_TMU_REG_PAST_TEMP1        0x64
>>> +#define EXYNOS4210_TMU_REG_PAST_TEMP2        0x68
>>> +#define EXYNOS4210_TMU_REG_PAST_TEMP3        0x6C
>>> +
>>> +#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK      0x1
>>> +#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK      0x10
>>> +#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK      0x100
>>> +#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK      0x1000
>>> +#define EXYNOS4210_TMU_TRIG_LEVEL_MASK       0x1111
>>> +#define EXYNOS4210_TMU_INTCLEAR_VAL  0x1111
>>> +
>>> +/* Exynos5250 and Exynos4412 specific registers */
>>> +#define EXYNOS_TMU_TRIMINFO_CON      0x14
>>> +#define EXYNOS_THD_TEMP_RISE         0x50
>>> +#define EXYNOS_THD_TEMP_FALL         0x54
>>> +#define EXYNOS_EMUL_CON              0x80
>>> +
>>> +#define EXYNOS_TRIMINFO_RELOAD_SHIFT 1
>>> +#define EXYNOS_TRIMINFO_25_SHIFT     0
>>> +#define EXYNOS_TRIMINFO_85_SHIFT     8
>>> +#define EXYNOS_TMU_RISE_INT_MASK     0x111
>>> +#define EXYNOS_TMU_RISE_INT_SHIFT    0
>>> +#define EXYNOS_TMU_FALL_INT_MASK     0x111
>>> +#define EXYNOS_TMU_FALL_INT_SHIFT    12
>>> +#define EXYNOS_TMU_CLEAR_RISE_INT    0x111
>>> +#define EXYNOS_TMU_CLEAR_FALL_INT    (0x111 << 12)
>>> +#define EXYNOS_TMU_TRIP_MODE_SHIFT   13
>>> +#define EXYNOS_TMU_TRIP_MODE_MASK    0x7
>>> +#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT       12
>>> +
>>> +#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
>>> +#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
>>> +#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
>>> +#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
>>> +#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
>>> +#define EXYNOS_TMU_INTEN_FALL1_SHIFT 20
>>> +#define EXYNOS_TMU_INTEN_FALL2_SHIFT 24
>>> +
>>> +#define EXYNOS_EMUL_TIME     0x57F0
>>> +#define EXYNOS_EMUL_TIME_MASK        0xffff
>>> +#define EXYNOS_EMUL_TIME_SHIFT       16
>>> +#define EXYNOS_EMUL_DATA_SHIFT       8
>>> +#define EXYNOS_EMUL_DATA_MASK        0xFF
>>> +#define EXYNOS_EMUL_ENABLE   0x1
>>> +
>>>  #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>>>  extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
>>>  #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
>>>
>>
>>
> 
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 18/21] thermal: exynos: Add support for exynos5440 TMU sensor.
  2013-05-10  2:31     ` amit daniel kachhap
@ 2013-05-10 14:14         ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-10 14:14 UTC (permalink / raw)
  To: amit daniel kachhap
  Cc: Eduardo Valentin, linux-pm, Zhang Rui, linux-samsung-soc,
	linux-kernel, Kukjin Kim

[-- Attachment #1: Type: text/plain, Size: 26177 bytes --]

On 09-05-2013 22:31, amit daniel kachhap wrote:
> Hi Eduardo,
> 
> On Thu, May 9, 2013 at 8:17 PM, Eduardo Valentin
> <eduardo.valentin@ti.com> wrote:
>> Hey Amit,
>>
>> On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
>>> This patch modifies TMU controller to add changes needed to work with
>>> exynos5440 platform. Also register definitions and required configuration data
>>> are added. This sensor registers 3 instance of the tmu controller with the
>>> thermal zone and hence reports 3 temperature output. This controller supports
>>> upto five trip points. For critical threshold the driver uses the core driver
>>> thermal framework for shutdown.
>>>
>>
>> I would kindly request you to split this patch. Looks like you add
>> altogether in one patch both data, driver adaptation (for your new soc)
>> and on top, new features. I would suggest splitting this things in
>> smaller steps. Easier to review, track, bitsec and find bugs (if any).
> 
> Yes your suggestion sounds reasonable. Will split into at least 3 patches.

Thanks.

> 
> Thanks,
> Amit
>>
>>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>>> ---
>>>  .../devicetree/bindings/thermal/exynos-thermal.txt |   28 ++++-
>>>  drivers/thermal/samsung/Kconfig                    |    4 +-
>>>  drivers/thermal/samsung/exynos_thermal_common.c    |    2 +-
>>>  drivers/thermal/samsung/exynos_tmu.c               |  139 +++++++++++++++++---
>>>  drivers/thermal/samsung/exynos_tmu.h               |    7 +
>>>  drivers/thermal/samsung/exynos_tmu_data.c          |   66 +++++++++-
>>>  drivers/thermal/samsung/exynos_tmu_data.h          |   40 ++++++
>>>  7 files changed, 261 insertions(+), 25 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>>> index 535fd0e..970eeba 100644
>>> --- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>>> +++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>>> @@ -6,13 +6,16 @@
>>>              "samsung,exynos4412-tmu"
>>>              "samsung,exynos4210-tmu"
>>>              "samsung,exynos5250-tmu"
>>> +            "samsung,exynos5440-tmu"
>>>  - interrupt-parent : The phandle for the interrupt controller
>>> -- reg : Address range of the thermal registers
>>> +- reg : Address range of the thermal registers. For exynos5440-tmu which has 3
>>> +     instances of TMU, 2 set of register has to supplied. First set belongs
>>> +     to each instance of TMU and second set belongs to common TMU registers.
>>>  - interrupts : Should contain interrupt for thermal system
>>>  - clocks : The main clock for TMU device
>>>  - clock-names : Thermal system clock name
>>>
>>> -Example:
>>> +Example 1):
>>>
>>>       tmu@100C0000 {
>>>               compatible = "samsung,exynos4412-tmu";
>>> @@ -23,3 +26,24 @@ Example:
>>>               clock-names = "tmu_apbif";
>>>               status = "disabled";
>>>       };
>>> +
>>> +Example 2):
>>> +
>>> +     tmuctrl_0: tmuctrl@160118 {
>>> +             compatible = "samsung,exynos5440-tmu";
>>> +             reg = <0x160118 0x230>, <0x160368 0x10>;
>>> +             interrupts = <0 58 0>;
>>> +             clocks = <&clock 21>;
>>> +             clock-names = "tmu_apbif";
>>> +     };
>>> +
>>> +Note: For multi-instance tmu each instance should have an alias correctly
>>> +numbered in "aliases" node.
>>> +
>>> +Example:
>>> +
>>> +aliases {
>>> +     tmuctrl0 = &tmuctrl_0;
>>> +     tmuctrl1 = &tmuctrl_1;
>>> +     tmuctrl2 = &tmuctrl_2;
>>> +};
>>> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
>>> index f23f533..fce04f3 100644
>>> --- a/drivers/thermal/samsung/Kconfig
>>> +++ b/drivers/thermal/samsung/Kconfig
>>> @@ -19,10 +19,10 @@ config EXYNOS_THERMAL_CORE
>>>
>>>  config EXYNOS_THERMAL_DATA
>>>       bool "Temperature sensor congiguration data for EXYNOS series SOC"
>>> -     depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250)
>>> +     depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250 || SOC_EXYNOS5440)
>>>       depends on EXYNOS_THERMAL
>>>       help
>>>         If you say yes here you can enable TMU (Thermal Management Unit) on
>>> -       SAMSUNG EXYNOS 4210, 4412, 4414 and 5250 series of SoC. This option
>>> +       SAMSUNG EXYNOS 4210, 4412, 4414, 5250 and 5440 series of SoC. This option
>>>         enables/prepares the configuration, trip and cooling data for the TMU
>>>         driver.
>>> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
>>> index b0dc63e..de43e18 100644
>>> --- a/drivers/thermal/samsung/exynos_thermal_common.c
>>> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
>>> @@ -370,7 +370,7 @@ int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
>>>       th_zone->mode = THERMAL_DEVICE_ENABLED;
>>>       sensor_conf->pzone_data = th_zone;
>>>
>>> -     pr_info("Exynos: Kernel Thermal management registered\n");
>>> +     pr_info("Exynos: Thermal zone(%s) registered\n", sensor_conf->name);
>>>
>>>       return 0;
>>>
>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>>> index c1a8c5f..72446c9 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>>> @@ -44,6 +44,7 @@
>>>   * @id: identifier of the one instance of the TMU controller.
>>>   * @pdata: pointer to the tmu platform/configuration data
>>>   * @base: base address of the single instance of the TMU controller.
>>> + * @base_common: base address of the common registers of the TMU controller.
>>>   * @irq: irq number of the TMU controller.
>>>   * @soc: id of the SOC type.
>>>   * @irq_work: pointer to the irq work structure.
>>> @@ -57,6 +58,7 @@ struct exynos_tmu_data {
>>>       int id;
>>>       struct exynos_tmu_platform_data *pdata;
>>>       void __iomem *base;
>>> +     void __iomem *base_common;
>>>       int irq;
>>>       enum soc_type soc;
>>>       struct work_struct irq_work;
>>> @@ -75,6 +77,9 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       int temp_code;
>>>
>>> +     if (pdata->cal_mode == HW_MODE)
>>> +             return temp;
>>> +
>>>       if (data->soc == SOC_ARCH_EXYNOS4210)
>>>               /* temp should range between 25 and 125 */
>>>               if (temp < 25 || temp > 125) {
>>> @@ -109,6 +114,9 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       int temp;
>>>
>>> +     if (pdata->cal_mode == HW_MODE)
>>> +             return temp_code;
>>> +
>>>       if (data->soc == SOC_ARCH_EXYNOS4210)
>>>               /* temp_code should range between 75 and 175 */
>>>               if (temp_code < 75 || temp_code > 175) {
>>> @@ -139,33 +147,63 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       struct exynos_tmu_registers *reg = pdata->registers;
>>> -     unsigned int status, trim_info, con;
>>> +     unsigned int status, trim_info = 0, con;
>>>       unsigned int rising_threshold = 0, falling_threshold = 0;
>>>       int ret = 0, threshold_code, i, trigger_levs = 0;
>>>
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>>
>>> -     status = readb(data->base + reg->tmu_status);
>>> -     if (!status) {
>>> -             ret = -EBUSY;
>>> -             goto out;
>>> +     if (TMU_SUPPORTS(pdata, READY_STATUS)) {
>>> +             status = readb(data->base + reg->tmu_status);
>>> +             if (!status) {
>>> +                     ret = -EBUSY;
>>> +                     goto out;
>>> +             }
>>>       }
>>>
>>>       if (TMU_SUPPORTS(pdata, TRIM_RELOAD))
>>>               __raw_writel(1, data->base + reg->triminfo_ctrl);
>>>
>>> +     if (pdata->cal_mode == HW_MODE)
>>> +             goto skip_calib_data;
>>> +
>>>       /* Save trimming info in order to perform calibration */
>>> -     trim_info = readl(data->base + reg->triminfo_data);
>>> +     if (data->soc == SOC_ARCH_EXYNOS5440) {
>>> +             /*
>>> +              * For exynos5440 soc triminfo value is swapped between TMU0 and
>>> +              * TMU2, so the below logic is needed.
>>> +              */
>>> +             switch (data->id) {
>>> +             case 0:
>>> +                     trim_info = readl(data->base +
>>> +                     EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
>>> +                     break;
>>> +             case 1:
>>> +                     trim_info = readl(data->base + reg->triminfo_data);
>>> +                     break;
>>> +             case 2:
>>> +                     trim_info = readl(data->base -
>>> +                     EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
>>> +             }
>>> +     } else {
>>> +             trim_info = readl(data->base + reg->triminfo_data);
>>> +     }
>>>       data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
>>>       data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
>>>                               EXYNOS_TMU_TEMP_MASK);
>>>
>>> -     if ((pdata->min_efuse_value > data->temp_error1) ||
>>> -                     (data->temp_error1 > pdata->max_efuse_value) ||
>>> -                     (data->temp_error2 != 0))
>>> -             data->temp_error1 = pdata->efuse_value;
>>> +     if (!data->temp_error1 ||
>>> +             (pdata->min_efuse_value > data->temp_error1) ||
>>> +             (data->temp_error1 > pdata->max_efuse_value))
>>> +             data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
>>> +
>>> +     if (!data->temp_error2)
>>> +             data->temp_error2 =
>>> +                     (pdata->efuse_value >> reg->triminfo_85_shift) &
>>> +                     EXYNOS_TMU_TEMP_MASK;
>>>
>>> +skip_calib_data:
>>>       /* Count trigger levels to be enabled */
>>>       for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
>>>               if (pdata->trigger_levels[i])
>>> @@ -185,9 +223,10 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>                       data->base + reg->threshold_th0 + i * 4);
>>>
>>>               writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>>> -     } else if (data->soc == SOC_ARCH_EXYNOS) {
>>> +     } else if (data->soc == SOC_ARCH_EXYNOS ||
>>> +                     data->soc == SOC_ARCH_EXYNOS5440) {
>>>               /* Write temperature code for rising and falling threshold */
>>> -             for (i = 0; i < trigger_levs; i++) {
>>> +             for (i = 0; i < trigger_levs && i < 4 ; i++) {
>>>                       threshold_code = temp_to_code(data,
>>>                                               pdata->trigger_levels[i]);
>>>                       if (threshold_code < 0) {
>>> @@ -218,7 +257,29 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>               writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>>>                       (reg->inten_fall_mask << reg->inten_fall_shift),
>>>                               data->base + reg->tmu_intclear);
>>> +
>>> +             /* if 5th threshold limit is also present, use TH2 register */
>>> +             i = 4;
>>> +             if (pdata->trigger_levels[i]) {
>>> +                     threshold_code = temp_to_code(data,
>>> +                                             pdata->trigger_levels[i]);
>>> +                     if (threshold_code < 0) {
>>> +                             ret = threshold_code;
>>> +                             goto out;
>>> +                     }
>>> +                     rising_threshold = threshold_code << 24;
>>> +                     writel(rising_threshold,
>>> +                             data->base + reg->threshold_th2);
>>> +                     if (pdata->trigger_type[i] == HW_TRIP) {
>>> +                             con = readl(data->base + reg->tmu_ctrl);
>>> +                             con |= (1 << reg->therm_trip_en_shift);
>>> +                             writel(con, data->base + reg->tmu_ctrl);
>>> +                     }
>>> +             }
>>>       }
>>> +     /*Clear the PMIN in the common TMU register*/
>>> +     if (reg->tmu_pmin && !data->id)
>>> +             writel(0, data->base_common + reg->tmu_pmin);
>>>  out:
>>>       clk_disable(data->clk);
>>>       mutex_unlock(&data->lock);
>>> @@ -254,6 +315,11 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>>               con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
>>>       }
>>>
>>> +     if (pdata->cal_mode == HW_MODE) {
>>> +             con &= ~(reg->calib_mode_mask << reg->calib_mode_shift);
>>> +             con |= pdata->cal_type << reg->calib_mode_shift;
>>> +     }
>>> +
>>>       if (on) {
>>>               con |= (1 << reg->core_en_shift);
>>>               interrupt_en =
>>> @@ -317,9 +383,11 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>>>       if (temp) {
>>>               temp /= MCELSIUS;
>>>
>>> -             val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
>>> -                     (temp_to_code(data, temp)
>>> -                      << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
>>> +             if (data->soc == SOC_ARCH_EXYNOS && reg->emul_time_shift)
>>> +                     val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift);
>>> +
>>> +             val |= (temp_to_code(data, temp) << reg->emul_temp_shift) |
>>> +                     EXYNOS_EMUL_ENABLE;
>>>       } else {
>>>               val &= ~EXYNOS_EMUL_ENABLE;
>>>       }
>>> @@ -343,7 +411,14 @@ static void exynos_tmu_work(struct work_struct *work)
>>>                       struct exynos_tmu_data, irq_work);
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       struct exynos_tmu_registers *reg = pdata->registers;
>>> -     unsigned int val_irq;
>>> +     unsigned int val_irq, val_type;
>>> +
>>> +     /* Find which sensor generated this interrupt */
>>> +     if (reg->tmu_irqstatus) {
>>> +             val_type = readl(data->base_common + reg->tmu_irqstatus);
>>> +             if (!((val_type >> data->id) & 0x1))
>>> +                     goto out;
>>> +     }
>>>
>>>       exynos_report_trigger(data->reg_conf);
>>>       mutex_lock(&data->lock);
>>> @@ -355,7 +430,7 @@ static void exynos_tmu_work(struct work_struct *work)
>>>
>>>       clk_disable(data->clk);
>>>       mutex_unlock(&data->lock);
>>> -
>>> +out:
>>>       enable_irq(data->irq);
>>>  }
>>>
>>> @@ -383,6 +458,10 @@ static const struct of_device_id exynos_tmu_match[] = {
>>>               .compatible = "samsung,exynos5250-tmu",
>>>               .data = (void *)EXYNOS5250_TMU_DRV_DATA,
>>>       },
>>> +     {
>>> +             .compatible = "samsung,exynos5440-tmu",
>>> +             .data = (void *)EXYNOS5440_TMU_DRV_DATA,
>>> +     },
>>>       {},
>>>  };
>>>  MODULE_DEVICE_TABLE(of, exynos_tmu_match);
>>> @@ -420,6 +499,7 @@ static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
>>>  static int exynos_map_dt_data(struct platform_device *pdev)
>>>  {
>>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       struct resource res;
>>>
>>>       if (!data)
>>> @@ -436,7 +516,7 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>>>       }
>>>
>>>       if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
>>> -             dev_err(&pdev->dev, "failed to get Resource\n");
>>> +             dev_err(&pdev->dev, "failed to get Resource 0\n");
>>>               return -ENODEV;
>>>       }
>>>
>>> @@ -445,6 +525,26 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>>>               dev_err(&pdev->dev, "Failed to ioremap memory\n");
>>>               return -ENOMEM;
>>>       }
>>> +
>>> +     /*
>>> +      * Check if the TMU is multi instance type and then try to map the
>>> +      * memory of common registers.
>>> +      */
>>> +     if (!TMU_SUPPORTS(pdata, MULTI_INST))
>>> +             return 0;
>>> +
>>> +     if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
>>> +             dev_err(&pdev->dev, "failed to get Resource 1\n");
>>> +             return -ENODEV;
>>> +     }
>>> +
>>> +     data->base_common = devm_ioremap(&pdev->dev, res.start,
>>> +                                     resource_size(&res));
>>> +     if (!data->base) {
>>> +             dev_err(&pdev->dev, "Failed to ioremap memory\n");
>>> +             return -ENOMEM;
>>> +     }
>>> +
>>>       return 0;
>>>  }
>>>
>>> @@ -496,7 +596,8 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>>>               return ret;
>>>
>>>       if (pdata->type == SOC_ARCH_EXYNOS ||
>>> -                             pdata->type == SOC_ARCH_EXYNOS4210)
>>> +             pdata->type == SOC_ARCH_EXYNOS4210 ||
>>> +             pdata->type == SOC_ARCH_EXYNOS5440)
>>>               data->soc = pdata->type;
>>>       else {
>>>               ret = -EINVAL;
>>> diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
>>> index de1c342..cc6b10e 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu.h
>>> +++ b/drivers/thermal/samsung/exynos_tmu.h
>>> @@ -43,6 +43,7 @@ enum trigger_type {
>>>  enum soc_type {
>>>       SOC_ARCH_EXYNOS4210 = 1,
>>>       SOC_ARCH_EXYNOS,
>>> +     SOC_ARCH_EXYNOS5440,
>>>  };
>>>
>>>  /**
>>> @@ -61,6 +62,7 @@ enum soc_type {
>>>  #define TMU_SUPPORT_MULTI_INST                       BIT(1)
>>>  #define TMU_SUPPORT_TRIM_RELOAD                      BIT(2)
>>>  #define TMU_SUPPORT_FALLING_TRIP             BIT(3)
>>> +#define TMU_SUPPORT_READY_STATUS             BIT(4)
>>>
>>>  #define TMU_SUPPORTS(a, b)   (a->features & TMU_SUPPORT_ ## b)
>>>
>>> @@ -85,6 +87,8 @@ struct exynos_tmu_registers {
>>>       u32     therm_trip_en_shift;
>>>       u32     buf_slope_sel_shift;
>>>       u32     buf_slope_sel_mask;
>>> +     u32     calib_mode_shift;
>>> +     u32     calib_mode_mask;
>>>       u32     therm_trip_tq_en_shift;
>>>       u32     core_en_shift;
>>>
>>> @@ -137,6 +141,9 @@ struct exynos_tmu_registers {
>>>       u32     emul_temp_shift;
>>>       u32     emul_time_shift;
>>>       u32     emul_time_mask;
>>> +
>>> +     u32     tmu_irqstatus;
>>> +     u32     tmu_pmin;
>>>  };
>>>
>>>  /**
>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
>>> index 8a587d4..25629e6 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu_data.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
>>> @@ -79,6 +79,7 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>>       .freq_tab_count = 2,
>>>       .type = SOC_ARCH_EXYNOS4210,
>>>       .registers = &exynos4210_tmu_registers,
>>> +     .features = (TMU_SUPPORT_READY_STATUS),
>>>  };
>>>  #endif
>>>
>>> @@ -155,6 +156,69 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>>>       .type = SOC_ARCH_EXYNOS,
>>>       .registers = &exynos5250_tmu_registers,
>>>       .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD |
>>> -                     TMU_SUPPORT_FALLING_TRIP),
>>> +                     TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS),
>>> +};
>>> +#endif
>>> +
>>> +#if defined(CONFIG_SOC_EXYNOS5440)
>>> +static struct exynos_tmu_registers exynos5440_tmu_registers = {
>>> +     .triminfo_data = EXYNOS5440_TMU_S0_7_TRIM,
>>> +     .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
>>> +     .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
>>> +     .tmu_ctrl = EXYNOS5440_TMU_S0_7_CTRL,
>>> +     .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
>>> +     .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
>>> +     .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
>>> +     .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
>>> +     .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
>>> +     .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
>>> +     .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
>>> +     .calib_mode_shift = EXYNOS_TMU_CALIB_MODE_SHIFT,
>>> +     .calib_mode_mask = EXYNOS_TMU_CALIB_MODE_MASK,
>>> +     .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
>>> +     .tmu_status = EXYNOS5440_TMU_S0_7_STATUS,
>>> +     .tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP,
>>> +     .threshold_th0 = EXYNOS5440_TMU_S0_7_TH0,
>>> +     .threshold_th1 = EXYNOS5440_TMU_S0_7_TH1,
>>> +     .threshold_th2 = EXYNOS5440_TMU_S0_7_TH2,
>>> +     .tmu_inten = EXYNOS5440_TMU_S0_7_IRQEN,
>>> +     .inten_rise_mask = EXYNOS5440_TMU_RISE_INT_MASK,
>>> +     .inten_rise_shift = EXYNOS5440_TMU_RISE_INT_SHIFT,
>>> +     .inten_fall_mask = EXYNOS5440_TMU_FALL_INT_MASK,
>>> +     .inten_fall_shift = EXYNOS5440_TMU_FALL_INT_SHIFT,
>>> +     .inten_rise0_shift = EXYNOS5440_TMU_INTEN_RISE0_SHIFT,
>>> +     .inten_rise1_shift = EXYNOS5440_TMU_INTEN_RISE1_SHIFT,
>>> +     .inten_rise2_shift = EXYNOS5440_TMU_INTEN_RISE2_SHIFT,
>>> +     .inten_rise3_shift = EXYNOS5440_TMU_INTEN_RISE3_SHIFT,
>>> +     .inten_fall0_shift = EXYNOS5440_TMU_INTEN_FALL0_SHIFT,
>>> +     .tmu_evten = EXYNOS5440_TMU_S0_7_EVTEN,
>>> +     .tmu_intstat = EXYNOS5440_TMU_S0_7_IRQ,
>>> +     .tmu_intclear = EXYNOS5440_TMU_S0_7_IRQ,
>>> +     .tmu_irqstatus = EXYNOS5440_TMU_IRQ_STATUS,
>>> +     .emul_con = EXYNOS5440_TMU_S0_7_DEBUG,
>>> +     .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
>>> +     .tmu_pmin = EXYNOS5440_TMU_PMIN,
>>> +};
>>> +struct exynos_tmu_platform_data const exynos5440_default_tmu_data = {
>>> +     .trigger_levels[0] = 100,
>>> +     .trigger_levels[4] = 105,
>>> +     .trigger_enable[0] = 1,
>>> +     .trigger_type[0] = 1,
>>> +     .trigger_type[4] = 2,
>>> +     .gain = 5,
>>> +     .reference_voltage = 16,
>>> +     .noise_cancel_mode = 4,
>>> +     .cal_type = TYPE_TWO_POINT_TRIMMING,
>>> +     .cal_mode = 0,
>>> +     .efuse_value = 0x5b2d,
>>> +     .min_efuse_value = 16,
>>> +     .max_efuse_value = 76,
>>> +     .first_point_trim = 25,
>>> +     .second_point_trim = 70,
>>> +     .default_temp_offset = 25,
>>> +     .type = SOC_ARCH_EXYNOS5440,
>>> +     .registers = &exynos5440_tmu_registers,
>>> +     .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP |
>>> +                     TMU_SUPPORT_MULTI_INST),
>>>  };
>>>  #endif
>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
>>> index 0560413..c409f3a 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu_data.h
>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
>>> @@ -75,6 +75,8 @@
>>>  #define EXYNOS_TMU_TRIP_MODE_SHIFT   13
>>>  #define EXYNOS_TMU_TRIP_MODE_MASK    0x7
>>>  #define EXYNOS_TMU_THERM_TRIP_EN_SHIFT       12
>>> +#define EXYNOS_TMU_CALIB_MODE_SHIFT  4
>>> +#define EXYNOS_TMU_CALIB_MODE_MASK   0x3
>>>
>>>  #define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
>>>  #define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
>>> @@ -91,6 +93,37 @@
>>>  #define EXYNOS_EMUL_DATA_MASK        0xFF
>>>  #define EXYNOS_EMUL_ENABLE   0x1
>>>
>>> +/*exynos5440 specific registers*/
>>> +#define EXYNOS5440_TMU_S0_7_TRIM             0x000
>>> +#define EXYNOS5440_TMU_S0_7_CTRL             0x020
>>> +#define EXYNOS5440_TMU_S0_7_DEBUG            0x040
>>> +#define EXYNOS5440_TMU_S0_7_STATUS           0x060
>>> +#define EXYNOS5440_TMU_S0_7_TEMP             0x0f0
>>> +#define EXYNOS5440_TMU_S0_7_TH0                      0x110
>>> +#define EXYNOS5440_TMU_S0_7_TH1                      0x130
>>> +#define EXYNOS5440_TMU_S0_7_TH2                      0x150
>>> +#define EXYNOS5440_TMU_S0_7_EVTEN            0x1F0
>>> +#define EXYNOS5440_TMU_S0_7_IRQEN            0x210
>>> +#define EXYNOS5440_TMU_S0_7_IRQ                      0x230
>>> +/* exynos5440 common registers */
>>> +#define EXYNOS5440_TMU_IRQ_STATUS            0x000
>>> +#define EXYNOS5440_TMU_PMIN                  0x004
>>> +#define EXYNOS5440_TMU_TEMP                  0x008
>>> +
>>> +#define EXYNOS5440_EFUSE_SWAP_OFFSET         8
>>> +#define EXYNOS5440_TMU_RISE_INT_MASK         0xf
>>> +#define EXYNOS5440_TMU_RISE_INT_SHIFT                0
>>> +#define EXYNOS5440_TMU_FALL_INT_MASK         0xf
>>> +#define EXYNOS5440_TMU_FALL_INT_SHIFT                4
>>> +#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT     0
>>> +#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT     1
>>> +#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT     2
>>> +#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT     3
>>> +#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT     4
>>> +#define EXYNOS5440_TMU_INTEN_FALL1_SHIFT     5
>>> +#define EXYNOS5440_TMU_INTEN_FALL2_SHIFT     6
>>> +#define EXYNOS5440_TMU_INTEN_FALL3_SHIFT     7
>>> +
>>>  #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>>>  extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
>>>  #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
>>> @@ -106,4 +139,11 @@ extern struct exynos_tmu_platform_data const exynos5250_default_tmu_data;
>>>  #define EXYNOS5250_TMU_DRV_DATA (NULL)
>>>  #endif
>>>
>>> +#if defined(CONFIG_SOC_EXYNOS5440) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>>> +extern struct exynos_tmu_platform_data const exynos5440_default_tmu_data;
>>> +#define EXYNOS5440_TMU_DRV_DATA (&exynos5440_default_tmu_data)
>>> +#else
>>> +#define EXYNOS5440_TMU_DRV_DATA (NULL)
>>> +#endif
>>> +
>>>  #endif /*_LINUX_EXYNOS_TMU_DATA_H*/
>>>
>>
>>
> 
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 18/21] thermal: exynos: Add support for exynos5440 TMU sensor.
@ 2013-05-10 14:14         ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-10 14:14 UTC (permalink / raw)
  To: amit daniel kachhap
  Cc: Eduardo Valentin, linux-pm, Zhang Rui, linux-samsung-soc,
	linux-kernel, Kukjin Kim

[-- Attachment #1: Type: text/plain, Size: 26177 bytes --]

On 09-05-2013 22:31, amit daniel kachhap wrote:
> Hi Eduardo,
> 
> On Thu, May 9, 2013 at 8:17 PM, Eduardo Valentin
> <eduardo.valentin@ti.com> wrote:
>> Hey Amit,
>>
>> On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
>>> This patch modifies TMU controller to add changes needed to work with
>>> exynos5440 platform. Also register definitions and required configuration data
>>> are added. This sensor registers 3 instance of the tmu controller with the
>>> thermal zone and hence reports 3 temperature output. This controller supports
>>> upto five trip points. For critical threshold the driver uses the core driver
>>> thermal framework for shutdown.
>>>
>>
>> I would kindly request you to split this patch. Looks like you add
>> altogether in one patch both data, driver adaptation (for your new soc)
>> and on top, new features. I would suggest splitting this things in
>> smaller steps. Easier to review, track, bitsec and find bugs (if any).
> 
> Yes your suggestion sounds reasonable. Will split into at least 3 patches.

Thanks.

> 
> Thanks,
> Amit
>>
>>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>>> ---
>>>  .../devicetree/bindings/thermal/exynos-thermal.txt |   28 ++++-
>>>  drivers/thermal/samsung/Kconfig                    |    4 +-
>>>  drivers/thermal/samsung/exynos_thermal_common.c    |    2 +-
>>>  drivers/thermal/samsung/exynos_tmu.c               |  139 +++++++++++++++++---
>>>  drivers/thermal/samsung/exynos_tmu.h               |    7 +
>>>  drivers/thermal/samsung/exynos_tmu_data.c          |   66 +++++++++-
>>>  drivers/thermal/samsung/exynos_tmu_data.h          |   40 ++++++
>>>  7 files changed, 261 insertions(+), 25 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>>> index 535fd0e..970eeba 100644
>>> --- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>>> +++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>>> @@ -6,13 +6,16 @@
>>>              "samsung,exynos4412-tmu"
>>>              "samsung,exynos4210-tmu"
>>>              "samsung,exynos5250-tmu"
>>> +            "samsung,exynos5440-tmu"
>>>  - interrupt-parent : The phandle for the interrupt controller
>>> -- reg : Address range of the thermal registers
>>> +- reg : Address range of the thermal registers. For exynos5440-tmu which has 3
>>> +     instances of TMU, 2 set of register has to supplied. First set belongs
>>> +     to each instance of TMU and second set belongs to common TMU registers.
>>>  - interrupts : Should contain interrupt for thermal system
>>>  - clocks : The main clock for TMU device
>>>  - clock-names : Thermal system clock name
>>>
>>> -Example:
>>> +Example 1):
>>>
>>>       tmu@100C0000 {
>>>               compatible = "samsung,exynos4412-tmu";
>>> @@ -23,3 +26,24 @@ Example:
>>>               clock-names = "tmu_apbif";
>>>               status = "disabled";
>>>       };
>>> +
>>> +Example 2):
>>> +
>>> +     tmuctrl_0: tmuctrl@160118 {
>>> +             compatible = "samsung,exynos5440-tmu";
>>> +             reg = <0x160118 0x230>, <0x160368 0x10>;
>>> +             interrupts = <0 58 0>;
>>> +             clocks = <&clock 21>;
>>> +             clock-names = "tmu_apbif";
>>> +     };
>>> +
>>> +Note: For multi-instance tmu each instance should have an alias correctly
>>> +numbered in "aliases" node.
>>> +
>>> +Example:
>>> +
>>> +aliases {
>>> +     tmuctrl0 = &tmuctrl_0;
>>> +     tmuctrl1 = &tmuctrl_1;
>>> +     tmuctrl2 = &tmuctrl_2;
>>> +};
>>> diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
>>> index f23f533..fce04f3 100644
>>> --- a/drivers/thermal/samsung/Kconfig
>>> +++ b/drivers/thermal/samsung/Kconfig
>>> @@ -19,10 +19,10 @@ config EXYNOS_THERMAL_CORE
>>>
>>>  config EXYNOS_THERMAL_DATA
>>>       bool "Temperature sensor congiguration data for EXYNOS series SOC"
>>> -     depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250)
>>> +     depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250 || SOC_EXYNOS5440)
>>>       depends on EXYNOS_THERMAL
>>>       help
>>>         If you say yes here you can enable TMU (Thermal Management Unit) on
>>> -       SAMSUNG EXYNOS 4210, 4412, 4414 and 5250 series of SoC. This option
>>> +       SAMSUNG EXYNOS 4210, 4412, 4414, 5250 and 5440 series of SoC. This option
>>>         enables/prepares the configuration, trip and cooling data for the TMU
>>>         driver.
>>> diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
>>> index b0dc63e..de43e18 100644
>>> --- a/drivers/thermal/samsung/exynos_thermal_common.c
>>> +++ b/drivers/thermal/samsung/exynos_thermal_common.c
>>> @@ -370,7 +370,7 @@ int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
>>>       th_zone->mode = THERMAL_DEVICE_ENABLED;
>>>       sensor_conf->pzone_data = th_zone;
>>>
>>> -     pr_info("Exynos: Kernel Thermal management registered\n");
>>> +     pr_info("Exynos: Thermal zone(%s) registered\n", sensor_conf->name);
>>>
>>>       return 0;
>>>
>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>>> index c1a8c5f..72446c9 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>>> @@ -44,6 +44,7 @@
>>>   * @id: identifier of the one instance of the TMU controller.
>>>   * @pdata: pointer to the tmu platform/configuration data
>>>   * @base: base address of the single instance of the TMU controller.
>>> + * @base_common: base address of the common registers of the TMU controller.
>>>   * @irq: irq number of the TMU controller.
>>>   * @soc: id of the SOC type.
>>>   * @irq_work: pointer to the irq work structure.
>>> @@ -57,6 +58,7 @@ struct exynos_tmu_data {
>>>       int id;
>>>       struct exynos_tmu_platform_data *pdata;
>>>       void __iomem *base;
>>> +     void __iomem *base_common;
>>>       int irq;
>>>       enum soc_type soc;
>>>       struct work_struct irq_work;
>>> @@ -75,6 +77,9 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       int temp_code;
>>>
>>> +     if (pdata->cal_mode == HW_MODE)
>>> +             return temp;
>>> +
>>>       if (data->soc == SOC_ARCH_EXYNOS4210)
>>>               /* temp should range between 25 and 125 */
>>>               if (temp < 25 || temp > 125) {
>>> @@ -109,6 +114,9 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       int temp;
>>>
>>> +     if (pdata->cal_mode == HW_MODE)
>>> +             return temp_code;
>>> +
>>>       if (data->soc == SOC_ARCH_EXYNOS4210)
>>>               /* temp_code should range between 75 and 175 */
>>>               if (temp_code < 75 || temp_code > 175) {
>>> @@ -139,33 +147,63 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       struct exynos_tmu_registers *reg = pdata->registers;
>>> -     unsigned int status, trim_info, con;
>>> +     unsigned int status, trim_info = 0, con;
>>>       unsigned int rising_threshold = 0, falling_threshold = 0;
>>>       int ret = 0, threshold_code, i, trigger_levs = 0;
>>>
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>>
>>> -     status = readb(data->base + reg->tmu_status);
>>> -     if (!status) {
>>> -             ret = -EBUSY;
>>> -             goto out;
>>> +     if (TMU_SUPPORTS(pdata, READY_STATUS)) {
>>> +             status = readb(data->base + reg->tmu_status);
>>> +             if (!status) {
>>> +                     ret = -EBUSY;
>>> +                     goto out;
>>> +             }
>>>       }
>>>
>>>       if (TMU_SUPPORTS(pdata, TRIM_RELOAD))
>>>               __raw_writel(1, data->base + reg->triminfo_ctrl);
>>>
>>> +     if (pdata->cal_mode == HW_MODE)
>>> +             goto skip_calib_data;
>>> +
>>>       /* Save trimming info in order to perform calibration */
>>> -     trim_info = readl(data->base + reg->triminfo_data);
>>> +     if (data->soc == SOC_ARCH_EXYNOS5440) {
>>> +             /*
>>> +              * For exynos5440 soc triminfo value is swapped between TMU0 and
>>> +              * TMU2, so the below logic is needed.
>>> +              */
>>> +             switch (data->id) {
>>> +             case 0:
>>> +                     trim_info = readl(data->base +
>>> +                     EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
>>> +                     break;
>>> +             case 1:
>>> +                     trim_info = readl(data->base + reg->triminfo_data);
>>> +                     break;
>>> +             case 2:
>>> +                     trim_info = readl(data->base -
>>> +                     EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
>>> +             }
>>> +     } else {
>>> +             trim_info = readl(data->base + reg->triminfo_data);
>>> +     }
>>>       data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
>>>       data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
>>>                               EXYNOS_TMU_TEMP_MASK);
>>>
>>> -     if ((pdata->min_efuse_value > data->temp_error1) ||
>>> -                     (data->temp_error1 > pdata->max_efuse_value) ||
>>> -                     (data->temp_error2 != 0))
>>> -             data->temp_error1 = pdata->efuse_value;
>>> +     if (!data->temp_error1 ||
>>> +             (pdata->min_efuse_value > data->temp_error1) ||
>>> +             (data->temp_error1 > pdata->max_efuse_value))
>>> +             data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
>>> +
>>> +     if (!data->temp_error2)
>>> +             data->temp_error2 =
>>> +                     (pdata->efuse_value >> reg->triminfo_85_shift) &
>>> +                     EXYNOS_TMU_TEMP_MASK;
>>>
>>> +skip_calib_data:
>>>       /* Count trigger levels to be enabled */
>>>       for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
>>>               if (pdata->trigger_levels[i])
>>> @@ -185,9 +223,10 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>                       data->base + reg->threshold_th0 + i * 4);
>>>
>>>               writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>>> -     } else if (data->soc == SOC_ARCH_EXYNOS) {
>>> +     } else if (data->soc == SOC_ARCH_EXYNOS ||
>>> +                     data->soc == SOC_ARCH_EXYNOS5440) {
>>>               /* Write temperature code for rising and falling threshold */
>>> -             for (i = 0; i < trigger_levs; i++) {
>>> +             for (i = 0; i < trigger_levs && i < 4 ; i++) {
>>>                       threshold_code = temp_to_code(data,
>>>                                               pdata->trigger_levels[i]);
>>>                       if (threshold_code < 0) {
>>> @@ -218,7 +257,29 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>               writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>>>                       (reg->inten_fall_mask << reg->inten_fall_shift),
>>>                               data->base + reg->tmu_intclear);
>>> +
>>> +             /* if 5th threshold limit is also present, use TH2 register */
>>> +             i = 4;
>>> +             if (pdata->trigger_levels[i]) {
>>> +                     threshold_code = temp_to_code(data,
>>> +                                             pdata->trigger_levels[i]);
>>> +                     if (threshold_code < 0) {
>>> +                             ret = threshold_code;
>>> +                             goto out;
>>> +                     }
>>> +                     rising_threshold = threshold_code << 24;
>>> +                     writel(rising_threshold,
>>> +                             data->base + reg->threshold_th2);
>>> +                     if (pdata->trigger_type[i] == HW_TRIP) {
>>> +                             con = readl(data->base + reg->tmu_ctrl);
>>> +                             con |= (1 << reg->therm_trip_en_shift);
>>> +                             writel(con, data->base + reg->tmu_ctrl);
>>> +                     }
>>> +             }
>>>       }
>>> +     /*Clear the PMIN in the common TMU register*/
>>> +     if (reg->tmu_pmin && !data->id)
>>> +             writel(0, data->base_common + reg->tmu_pmin);
>>>  out:
>>>       clk_disable(data->clk);
>>>       mutex_unlock(&data->lock);
>>> @@ -254,6 +315,11 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>>               con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
>>>       }
>>>
>>> +     if (pdata->cal_mode == HW_MODE) {
>>> +             con &= ~(reg->calib_mode_mask << reg->calib_mode_shift);
>>> +             con |= pdata->cal_type << reg->calib_mode_shift;
>>> +     }
>>> +
>>>       if (on) {
>>>               con |= (1 << reg->core_en_shift);
>>>               interrupt_en =
>>> @@ -317,9 +383,11 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>>>       if (temp) {
>>>               temp /= MCELSIUS;
>>>
>>> -             val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
>>> -                     (temp_to_code(data, temp)
>>> -                      << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
>>> +             if (data->soc == SOC_ARCH_EXYNOS && reg->emul_time_shift)
>>> +                     val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift);
>>> +
>>> +             val |= (temp_to_code(data, temp) << reg->emul_temp_shift) |
>>> +                     EXYNOS_EMUL_ENABLE;
>>>       } else {
>>>               val &= ~EXYNOS_EMUL_ENABLE;
>>>       }
>>> @@ -343,7 +411,14 @@ static void exynos_tmu_work(struct work_struct *work)
>>>                       struct exynos_tmu_data, irq_work);
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       struct exynos_tmu_registers *reg = pdata->registers;
>>> -     unsigned int val_irq;
>>> +     unsigned int val_irq, val_type;
>>> +
>>> +     /* Find which sensor generated this interrupt */
>>> +     if (reg->tmu_irqstatus) {
>>> +             val_type = readl(data->base_common + reg->tmu_irqstatus);
>>> +             if (!((val_type >> data->id) & 0x1))
>>> +                     goto out;
>>> +     }
>>>
>>>       exynos_report_trigger(data->reg_conf);
>>>       mutex_lock(&data->lock);
>>> @@ -355,7 +430,7 @@ static void exynos_tmu_work(struct work_struct *work)
>>>
>>>       clk_disable(data->clk);
>>>       mutex_unlock(&data->lock);
>>> -
>>> +out:
>>>       enable_irq(data->irq);
>>>  }
>>>
>>> @@ -383,6 +458,10 @@ static const struct of_device_id exynos_tmu_match[] = {
>>>               .compatible = "samsung,exynos5250-tmu",
>>>               .data = (void *)EXYNOS5250_TMU_DRV_DATA,
>>>       },
>>> +     {
>>> +             .compatible = "samsung,exynos5440-tmu",
>>> +             .data = (void *)EXYNOS5440_TMU_DRV_DATA,
>>> +     },
>>>       {},
>>>  };
>>>  MODULE_DEVICE_TABLE(of, exynos_tmu_match);
>>> @@ -420,6 +499,7 @@ static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
>>>  static int exynos_map_dt_data(struct platform_device *pdev)
>>>  {
>>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       struct resource res;
>>>
>>>       if (!data)
>>> @@ -436,7 +516,7 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>>>       }
>>>
>>>       if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
>>> -             dev_err(&pdev->dev, "failed to get Resource\n");
>>> +             dev_err(&pdev->dev, "failed to get Resource 0\n");
>>>               return -ENODEV;
>>>       }
>>>
>>> @@ -445,6 +525,26 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>>>               dev_err(&pdev->dev, "Failed to ioremap memory\n");
>>>               return -ENOMEM;
>>>       }
>>> +
>>> +     /*
>>> +      * Check if the TMU is multi instance type and then try to map the
>>> +      * memory of common registers.
>>> +      */
>>> +     if (!TMU_SUPPORTS(pdata, MULTI_INST))
>>> +             return 0;
>>> +
>>> +     if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
>>> +             dev_err(&pdev->dev, "failed to get Resource 1\n");
>>> +             return -ENODEV;
>>> +     }
>>> +
>>> +     data->base_common = devm_ioremap(&pdev->dev, res.start,
>>> +                                     resource_size(&res));
>>> +     if (!data->base) {
>>> +             dev_err(&pdev->dev, "Failed to ioremap memory\n");
>>> +             return -ENOMEM;
>>> +     }
>>> +
>>>       return 0;
>>>  }
>>>
>>> @@ -496,7 +596,8 @@ static int exynos_tmu_probe(struct platform_device *pdev)
>>>               return ret;
>>>
>>>       if (pdata->type == SOC_ARCH_EXYNOS ||
>>> -                             pdata->type == SOC_ARCH_EXYNOS4210)
>>> +             pdata->type == SOC_ARCH_EXYNOS4210 ||
>>> +             pdata->type == SOC_ARCH_EXYNOS5440)
>>>               data->soc = pdata->type;
>>>       else {
>>>               ret = -EINVAL;
>>> diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
>>> index de1c342..cc6b10e 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu.h
>>> +++ b/drivers/thermal/samsung/exynos_tmu.h
>>> @@ -43,6 +43,7 @@ enum trigger_type {
>>>  enum soc_type {
>>>       SOC_ARCH_EXYNOS4210 = 1,
>>>       SOC_ARCH_EXYNOS,
>>> +     SOC_ARCH_EXYNOS5440,
>>>  };
>>>
>>>  /**
>>> @@ -61,6 +62,7 @@ enum soc_type {
>>>  #define TMU_SUPPORT_MULTI_INST                       BIT(1)
>>>  #define TMU_SUPPORT_TRIM_RELOAD                      BIT(2)
>>>  #define TMU_SUPPORT_FALLING_TRIP             BIT(3)
>>> +#define TMU_SUPPORT_READY_STATUS             BIT(4)
>>>
>>>  #define TMU_SUPPORTS(a, b)   (a->features & TMU_SUPPORT_ ## b)
>>>
>>> @@ -85,6 +87,8 @@ struct exynos_tmu_registers {
>>>       u32     therm_trip_en_shift;
>>>       u32     buf_slope_sel_shift;
>>>       u32     buf_slope_sel_mask;
>>> +     u32     calib_mode_shift;
>>> +     u32     calib_mode_mask;
>>>       u32     therm_trip_tq_en_shift;
>>>       u32     core_en_shift;
>>>
>>> @@ -137,6 +141,9 @@ struct exynos_tmu_registers {
>>>       u32     emul_temp_shift;
>>>       u32     emul_time_shift;
>>>       u32     emul_time_mask;
>>> +
>>> +     u32     tmu_irqstatus;
>>> +     u32     tmu_pmin;
>>>  };
>>>
>>>  /**
>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
>>> index 8a587d4..25629e6 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu_data.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
>>> @@ -79,6 +79,7 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>>       .freq_tab_count = 2,
>>>       .type = SOC_ARCH_EXYNOS4210,
>>>       .registers = &exynos4210_tmu_registers,
>>> +     .features = (TMU_SUPPORT_READY_STATUS),
>>>  };
>>>  #endif
>>>
>>> @@ -155,6 +156,69 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>>>       .type = SOC_ARCH_EXYNOS,
>>>       .registers = &exynos5250_tmu_registers,
>>>       .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD |
>>> -                     TMU_SUPPORT_FALLING_TRIP),
>>> +                     TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS),
>>> +};
>>> +#endif
>>> +
>>> +#if defined(CONFIG_SOC_EXYNOS5440)
>>> +static struct exynos_tmu_registers exynos5440_tmu_registers = {
>>> +     .triminfo_data = EXYNOS5440_TMU_S0_7_TRIM,
>>> +     .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
>>> +     .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
>>> +     .tmu_ctrl = EXYNOS5440_TMU_S0_7_CTRL,
>>> +     .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
>>> +     .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
>>> +     .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
>>> +     .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
>>> +     .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
>>> +     .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
>>> +     .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
>>> +     .calib_mode_shift = EXYNOS_TMU_CALIB_MODE_SHIFT,
>>> +     .calib_mode_mask = EXYNOS_TMU_CALIB_MODE_MASK,
>>> +     .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
>>> +     .tmu_status = EXYNOS5440_TMU_S0_7_STATUS,
>>> +     .tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP,
>>> +     .threshold_th0 = EXYNOS5440_TMU_S0_7_TH0,
>>> +     .threshold_th1 = EXYNOS5440_TMU_S0_7_TH1,
>>> +     .threshold_th2 = EXYNOS5440_TMU_S0_7_TH2,
>>> +     .tmu_inten = EXYNOS5440_TMU_S0_7_IRQEN,
>>> +     .inten_rise_mask = EXYNOS5440_TMU_RISE_INT_MASK,
>>> +     .inten_rise_shift = EXYNOS5440_TMU_RISE_INT_SHIFT,
>>> +     .inten_fall_mask = EXYNOS5440_TMU_FALL_INT_MASK,
>>> +     .inten_fall_shift = EXYNOS5440_TMU_FALL_INT_SHIFT,
>>> +     .inten_rise0_shift = EXYNOS5440_TMU_INTEN_RISE0_SHIFT,
>>> +     .inten_rise1_shift = EXYNOS5440_TMU_INTEN_RISE1_SHIFT,
>>> +     .inten_rise2_shift = EXYNOS5440_TMU_INTEN_RISE2_SHIFT,
>>> +     .inten_rise3_shift = EXYNOS5440_TMU_INTEN_RISE3_SHIFT,
>>> +     .inten_fall0_shift = EXYNOS5440_TMU_INTEN_FALL0_SHIFT,
>>> +     .tmu_evten = EXYNOS5440_TMU_S0_7_EVTEN,
>>> +     .tmu_intstat = EXYNOS5440_TMU_S0_7_IRQ,
>>> +     .tmu_intclear = EXYNOS5440_TMU_S0_7_IRQ,
>>> +     .tmu_irqstatus = EXYNOS5440_TMU_IRQ_STATUS,
>>> +     .emul_con = EXYNOS5440_TMU_S0_7_DEBUG,
>>> +     .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
>>> +     .tmu_pmin = EXYNOS5440_TMU_PMIN,
>>> +};
>>> +struct exynos_tmu_platform_data const exynos5440_default_tmu_data = {
>>> +     .trigger_levels[0] = 100,
>>> +     .trigger_levels[4] = 105,
>>> +     .trigger_enable[0] = 1,
>>> +     .trigger_type[0] = 1,
>>> +     .trigger_type[4] = 2,
>>> +     .gain = 5,
>>> +     .reference_voltage = 16,
>>> +     .noise_cancel_mode = 4,
>>> +     .cal_type = TYPE_TWO_POINT_TRIMMING,
>>> +     .cal_mode = 0,
>>> +     .efuse_value = 0x5b2d,
>>> +     .min_efuse_value = 16,
>>> +     .max_efuse_value = 76,
>>> +     .first_point_trim = 25,
>>> +     .second_point_trim = 70,
>>> +     .default_temp_offset = 25,
>>> +     .type = SOC_ARCH_EXYNOS5440,
>>> +     .registers = &exynos5440_tmu_registers,
>>> +     .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP |
>>> +                     TMU_SUPPORT_MULTI_INST),
>>>  };
>>>  #endif
>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
>>> index 0560413..c409f3a 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu_data.h
>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
>>> @@ -75,6 +75,8 @@
>>>  #define EXYNOS_TMU_TRIP_MODE_SHIFT   13
>>>  #define EXYNOS_TMU_TRIP_MODE_MASK    0x7
>>>  #define EXYNOS_TMU_THERM_TRIP_EN_SHIFT       12
>>> +#define EXYNOS_TMU_CALIB_MODE_SHIFT  4
>>> +#define EXYNOS_TMU_CALIB_MODE_MASK   0x3
>>>
>>>  #define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
>>>  #define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
>>> @@ -91,6 +93,37 @@
>>>  #define EXYNOS_EMUL_DATA_MASK        0xFF
>>>  #define EXYNOS_EMUL_ENABLE   0x1
>>>
>>> +/*exynos5440 specific registers*/
>>> +#define EXYNOS5440_TMU_S0_7_TRIM             0x000
>>> +#define EXYNOS5440_TMU_S0_7_CTRL             0x020
>>> +#define EXYNOS5440_TMU_S0_7_DEBUG            0x040
>>> +#define EXYNOS5440_TMU_S0_7_STATUS           0x060
>>> +#define EXYNOS5440_TMU_S0_7_TEMP             0x0f0
>>> +#define EXYNOS5440_TMU_S0_7_TH0                      0x110
>>> +#define EXYNOS5440_TMU_S0_7_TH1                      0x130
>>> +#define EXYNOS5440_TMU_S0_7_TH2                      0x150
>>> +#define EXYNOS5440_TMU_S0_7_EVTEN            0x1F0
>>> +#define EXYNOS5440_TMU_S0_7_IRQEN            0x210
>>> +#define EXYNOS5440_TMU_S0_7_IRQ                      0x230
>>> +/* exynos5440 common registers */
>>> +#define EXYNOS5440_TMU_IRQ_STATUS            0x000
>>> +#define EXYNOS5440_TMU_PMIN                  0x004
>>> +#define EXYNOS5440_TMU_TEMP                  0x008
>>> +
>>> +#define EXYNOS5440_EFUSE_SWAP_OFFSET         8
>>> +#define EXYNOS5440_TMU_RISE_INT_MASK         0xf
>>> +#define EXYNOS5440_TMU_RISE_INT_SHIFT                0
>>> +#define EXYNOS5440_TMU_FALL_INT_MASK         0xf
>>> +#define EXYNOS5440_TMU_FALL_INT_SHIFT                4
>>> +#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT     0
>>> +#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT     1
>>> +#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT     2
>>> +#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT     3
>>> +#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT     4
>>> +#define EXYNOS5440_TMU_INTEN_FALL1_SHIFT     5
>>> +#define EXYNOS5440_TMU_INTEN_FALL2_SHIFT     6
>>> +#define EXYNOS5440_TMU_INTEN_FALL3_SHIFT     7
>>> +
>>>  #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>>>  extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
>>>  #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
>>> @@ -106,4 +139,11 @@ extern struct exynos_tmu_platform_data const exynos5250_default_tmu_data;
>>>  #define EXYNOS5250_TMU_DRV_DATA (NULL)
>>>  #endif
>>>
>>> +#if defined(CONFIG_SOC_EXYNOS5440) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>>> +extern struct exynos_tmu_platform_data const exynos5440_default_tmu_data;
>>> +#define EXYNOS5440_TMU_DRV_DATA (&exynos5440_default_tmu_data)
>>> +#else
>>> +#define EXYNOS5440_TMU_DRV_DATA (NULL)
>>> +#endif
>>> +
>>>  #endif /*_LINUX_EXYNOS_TMU_DATA_H*/
>>>
>>
>>
> 
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 03/21] thermal: exynos: Rename exynos_thermal.c to exynos_tmu.c
  2013-05-07 13:00 ` [PATCH V3 03/21] thermal: exynos: Rename exynos_thermal.c to exynos_tmu.c Amit Daniel Kachhap
@ 2013-05-10 15:12     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-10 15:12 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 2017 bytes --]

On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
> This patch renames exynos_thermal.c to exynos_tmu.c. This change is needed as
> this file now just contains exynos tmu driver related codes and thermal zone
> or cpufreq cooling registration related changes are not there anymore.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>

This one looks fine to me.

Acked-by: Eduardo Valentin <eduardo.valentin@ti.com>

> ---
>  drivers/thermal/samsung/Makefile                   |    6 +++---
>  .../samsung/{exynos_thermal.c => exynos_tmu.c}     |    2 +-
>  2 files changed, 4 insertions(+), 4 deletions(-)
>  rename drivers/thermal/samsung/{exynos_thermal.c => exynos_tmu.c} (99%)
> 
> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
> index 6227d4f..22528d6 100644
> --- a/drivers/thermal/samsung/Makefile
> +++ b/drivers/thermal/samsung/Makefile
> @@ -1,6 +1,6 @@
>  #
>  # Samsung thermal specific Makefile
>  #
> -obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_soc_thermal.o
> -exynos_soc_thermal-y				:= exynos_thermal.o
> -exynos_soc_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
> +obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_thermal.o
> +exynos_thermal-y				:= exynos_tmu.o
> +exynos_thermal-$(CONFIG_EXYNOS_THERMAL_CORE)	+= exynos_thermal_common.o
> diff --git a/drivers/thermal/samsung/exynos_thermal.c b/drivers/thermal/samsung/exynos_tmu.c
> similarity index 99%
> rename from drivers/thermal/samsung/exynos_thermal.c
> rename to drivers/thermal/samsung/exynos_tmu.c
> index 4c85945..3de3e61 100644
> --- a/drivers/thermal/samsung/exynos_thermal.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -1,5 +1,5 @@
>  /*
> - * exynos_thermal.c - Samsung EXYNOS TMU (Thermal Management Unit)
> + * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
>   *
>   *  Copyright (C) 2011 Samsung Electronics
>   *  Donggeun Kim <dg77.kim@samsung.com>
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 03/21] thermal: exynos: Rename exynos_thermal.c to exynos_tmu.c
@ 2013-05-10 15:12     ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-10 15:12 UTC (permalink / raw)
  To: Amit Daniel Kachhap
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel,
	amit.kachhap, Kukjin Kim, Eduardo Valentin

[-- Attachment #1: Type: text/plain, Size: 2017 bytes --]

On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
> This patch renames exynos_thermal.c to exynos_tmu.c. This change is needed as
> this file now just contains exynos tmu driver related codes and thermal zone
> or cpufreq cooling registration related changes are not there anymore.
> 
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>

This one looks fine to me.

Acked-by: Eduardo Valentin <eduardo.valentin@ti.com>

> ---
>  drivers/thermal/samsung/Makefile                   |    6 +++---
>  .../samsung/{exynos_thermal.c => exynos_tmu.c}     |    2 +-
>  2 files changed, 4 insertions(+), 4 deletions(-)
>  rename drivers/thermal/samsung/{exynos_thermal.c => exynos_tmu.c} (99%)
> 
> diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
> index 6227d4f..22528d6 100644
> --- a/drivers/thermal/samsung/Makefile
> +++ b/drivers/thermal/samsung/Makefile
> @@ -1,6 +1,6 @@
>  #
>  # Samsung thermal specific Makefile
>  #
> -obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_soc_thermal.o
> -exynos_soc_thermal-y				:= exynos_thermal.o
> -exynos_soc_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
> +obj-$(CONFIG_EXYNOS_THERMAL)			+= exynos_thermal.o
> +exynos_thermal-y				:= exynos_tmu.o
> +exynos_thermal-$(CONFIG_EXYNOS_THERMAL_CORE)	+= exynos_thermal_common.o
> diff --git a/drivers/thermal/samsung/exynos_thermal.c b/drivers/thermal/samsung/exynos_tmu.c
> similarity index 99%
> rename from drivers/thermal/samsung/exynos_thermal.c
> rename to drivers/thermal/samsung/exynos_tmu.c
> index 4c85945..3de3e61 100644
> --- a/drivers/thermal/samsung/exynos_thermal.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -1,5 +1,5 @@
>  /*
> - * exynos_thermal.c - Samsung EXYNOS TMU (Thermal Management Unit)
> + * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
>   *
>   *  Copyright (C) 2011 Samsung Electronics
>   *  Donggeun Kim <dg77.kim@samsung.com>
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 10/21] thermal: exynos: Fix to clear only the generated interrupts
  2013-05-10  2:22     ` amit daniel kachhap
@ 2013-05-10 15:40         ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-10 15:40 UTC (permalink / raw)
  To: amit daniel kachhap
  Cc: Eduardo Valentin, linux-pm, Zhang Rui, linux-samsung-soc,
	linux-kernel, Kukjin Kim

[-- Attachment #1: Type: text/plain, Size: 3471 bytes --]

On 09-05-2013 22:22, amit daniel kachhap wrote:
> Hi,
> 
> On Thu, May 9, 2013 at 8:03 PM, Eduardo Valentin
> <eduardo.valentin@ti.com> wrote:
>> On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
>>> This patch uses the TMU status register to know the generated interrupts
>>> and only clear them in the interrupt handler.
>>>
>>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>>> ---
>>>  drivers/thermal/samsung/exynos_tmu.c      |   10 ++++------
>>>  drivers/thermal/samsung/exynos_tmu_data.c |    2 ++
>>>  2 files changed, 6 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>>> index 97b87aa..082d5a2 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>>> @@ -325,17 +325,15 @@ static void exynos_tmu_work(struct work_struct *work)
>>>                       struct exynos_tmu_data, irq_work);
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       struct exynos_tmu_registers *reg = pdata->registers;
>>> +     unsigned int val_irq;
>>>
>>>       exynos_report_trigger();
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>>
>>> -     if (data->soc == SOC_ARCH_EXYNOS)
>>> -             writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>>> -                     (reg->inten_fall_mask << reg->inten_fall_shift),
>>> -                             data->base + reg->tmu_intclear);
>>> -     else
>>> -             writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>>> +     val_irq = readl(data->base + reg->tmu_intstat);
>>> +     /* clear the interrupts */
>>> +     writel(val_irq, data->base + reg->tmu_intclear);
>>>
>>
>> hmmm.. Don t you need to act accordingly depending on what is in your
>> int status?
> 
> Earlier also it is done like this way. Basically core thermal layer
> checks temp for each trip so even if I check for which threshold
> interrupt is raised it is of no use. Anyway this is a TODO for me.
> 

Please add  a /* TODO: */ entry then.

> Thanks,
> Amit Daniel
>>
>>>       clk_disable(data->clk);
>>>       mutex_unlock(&data->lock);
>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
>>> index 3a1ded1..7322597 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu_data.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
>>> @@ -45,6 +45,7 @@ static struct exynos_tmu_registers exynos4210_tmu_registers = {
>>>       .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>>>       .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>>       .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>> +     .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
>>>       .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>>  };
>>>  struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>> @@ -111,6 +112,7 @@ static struct exynos_tmu_registers exynos5250_tmu_registers = {
>>>       .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>>       .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>>       .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
>>> +     .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
>>>       .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>>       .emul_con = EXYNOS_EMUL_CON,
>>>       .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
>>>
>>
>>
> 
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 10/21] thermal: exynos: Fix to clear only the generated interrupts
@ 2013-05-10 15:40         ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-10 15:40 UTC (permalink / raw)
  To: amit daniel kachhap
  Cc: Eduardo Valentin, linux-pm, Zhang Rui, linux-samsung-soc,
	linux-kernel, Kukjin Kim

[-- Attachment #1: Type: text/plain, Size: 3471 bytes --]

On 09-05-2013 22:22, amit daniel kachhap wrote:
> Hi,
> 
> On Thu, May 9, 2013 at 8:03 PM, Eduardo Valentin
> <eduardo.valentin@ti.com> wrote:
>> On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
>>> This patch uses the TMU status register to know the generated interrupts
>>> and only clear them in the interrupt handler.
>>>
>>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>>> ---
>>>  drivers/thermal/samsung/exynos_tmu.c      |   10 ++++------
>>>  drivers/thermal/samsung/exynos_tmu_data.c |    2 ++
>>>  2 files changed, 6 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>>> index 97b87aa..082d5a2 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>>> @@ -325,17 +325,15 @@ static void exynos_tmu_work(struct work_struct *work)
>>>                       struct exynos_tmu_data, irq_work);
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       struct exynos_tmu_registers *reg = pdata->registers;
>>> +     unsigned int val_irq;
>>>
>>>       exynos_report_trigger();
>>>       mutex_lock(&data->lock);
>>>       clk_enable(data->clk);
>>>
>>> -     if (data->soc == SOC_ARCH_EXYNOS)
>>> -             writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>>> -                     (reg->inten_fall_mask << reg->inten_fall_shift),
>>> -                             data->base + reg->tmu_intclear);
>>> -     else
>>> -             writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>>> +     val_irq = readl(data->base + reg->tmu_intstat);
>>> +     /* clear the interrupts */
>>> +     writel(val_irq, data->base + reg->tmu_intclear);
>>>
>>
>> hmmm.. Don t you need to act accordingly depending on what is in your
>> int status?
> 
> Earlier also it is done like this way. Basically core thermal layer
> checks temp for each trip so even if I check for which threshold
> interrupt is raised it is of no use. Anyway this is a TODO for me.
> 

Please add  a /* TODO: */ entry then.

> Thanks,
> Amit Daniel
>>
>>>       clk_disable(data->clk);
>>>       mutex_unlock(&data->lock);
>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
>>> index 3a1ded1..7322597 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu_data.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
>>> @@ -45,6 +45,7 @@ static struct exynos_tmu_registers exynos4210_tmu_registers = {
>>>       .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>>>       .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>>       .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>> +     .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
>>>       .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>>  };
>>>  struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>> @@ -111,6 +112,7 @@ static struct exynos_tmu_registers exynos5250_tmu_registers = {
>>>       .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>>       .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>>       .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
>>> +     .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
>>>       .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>>       .emul_con = EXYNOS_EMUL_CON,
>>>       .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
>>>
>>
>>
> 
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 20/21] thermal: exynos: Support for TMU regulator defined at device tree
  2013-05-10  2:28     ` amit daniel kachhap
@ 2013-05-10 16:05         ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-10 16:05 UTC (permalink / raw)
  To: amit daniel kachhap
  Cc: Eduardo Valentin, linux-pm, Zhang Rui, linux-samsung-soc,
	linux-kernel, Kukjin Kim

[-- Attachment #1: Type: text/plain, Size: 5330 bytes --]

On 09-05-2013 22:28, amit daniel kachhap wrote:
> Hi Eduardo,
> 
> On Thu, May 9, 2013 at 8:14 PM, Eduardo Valentin
> <eduardo.valentin@ti.com> wrote:
>> On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
>>> TMU probe function now checks for a device tree defined regulator.
>>> For compatibility reasons it is allowed to probe driver even without
>>> this regulator defined.
>>>
>>> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
>>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>>> ---
>>>  .../devicetree/bindings/thermal/exynos-thermal.txt |    4 ++++
>>>  drivers/thermal/samsung/exynos_tmu.c               |   19 +++++++++++++++++++
>>>  2 files changed, 23 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>>> index 970eeba..ff62f7a 100644
>>> --- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>>> +++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>>> @@ -14,6 +14,9 @@
>>>  - interrupts : Should contain interrupt for thermal system
>>>  - clocks : The main clock for TMU device
>>>  - clock-names : Thermal system clock name
>>> +- vtmu-supply: This entry is optional and provides the regulator node supplying
>>> +             voltage to TMU. If needed this entry can be placed inside
>>> +             board/platform specific dts file.
>>>
>>>  Example 1):
>>>
>>> @@ -25,6 +28,7 @@ Example 1):
>>>               clocks = <&clock 383>;
>>>               clock-names = "tmu_apbif";
>>>               status = "disabled";
>>> +             vtmu-supply = <&tmu_regulator_node>;
>>>       };
>>>
>>>  Example 2):
>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>>> index 72446c9..b7c609a 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>>> @@ -32,6 +32,7 @@
>>>  #include <linux/of_address.h>
>>>  #include <linux/of_irq.h>
>>>  #include <linux/platform_device.h>
>>> +#include <linux/regulator/consumer.h>
>>>  #include <linux/slab.h>
>>>  #include <linux/workqueue.h>
>>>  #include "exynos_thermal_common.h"
>>> @@ -52,6 +53,7 @@
>>>   * @clk: pointer to the clock structure.
>>>   * @temp_error1: fused value of the first point trim.
>>>   * @temp_error2: fused value of the second point trim.
>>> + * @regulator: pointer to the TMU regulator structure.
>>>   * @reg_conf: pointer to structure to register with core thermal.
>>>   */
>>>  struct exynos_tmu_data {
>>> @@ -65,6 +67,7 @@ struct exynos_tmu_data {
>>>       struct mutex lock;
>>>       struct clk *clk;
>>>       u8 temp_error1, temp_error2;
>>> +     struct regulator *regulator;
>>>       struct thermal_sensor_conf *reg_conf;
>>>  };
>>>
>>> @@ -501,10 +504,23 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       struct resource res;
>>> +     int ret;
>>>
>>>       if (!data)
>>>               return -ENODEV;
>>>
>>> +     /* Try enabling the regulator if found */
>>> +     data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
>>> +     if (!IS_ERR(data->regulator)) {
>>> +             ret = regulator_enable(data->regulator);
>>> +             if (ret) {
>>> +                     dev_err(&pdev->dev, "failed to enable vtmu\n");
>>> +                     return ret;
>>> +             }
>>> +     } else {
>>> +             dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
>>
>> Now that you have a bitfield for your features, shouldnt this become a
>> check? If the SoC requires the regulator, then it has to return a valid
>> regulator (regulator_get). Meaning, if your SoC version requires this
>> feature and the regulator_get returns an error, you must treat as an
>> error an not continue gracefuly.
> 
> Earlier I also thought of using bit feature for this but then the
> regulator source usually depends upon the board design so each soc may
> have several boards. So regulator information is not part of SOC data.
> Since this information is there is in DT only so I left this part for
> the DT to handle.
> 


Hmmm.. well, that is actually arguable. Take from driver perspective. If
a regulator is required for a device to work you have to make it a
requirement and not rely on whatever state the system has booted.

From previous discussions, I understood on of your chip versions
actually require a regulator to be activated in order to get the sensors
properly working. Is this understanding correct?

> Thanks,
> Amit Daniel
>>
>>> +     }
>>> +
>>>       data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
>>>       if (data->id < 0)
>>>               data->id = 0;
>>> @@ -669,6 +685,9 @@ static int exynos_tmu_remove(struct platform_device *pdev)
>>>
>>>       clk_unprepare(data->clk);
>>>
>>> +     if (!IS_ERR(data->regulator))
>>> +             regulator_disable(data->regulator);
>>> +
>>>       platform_set_drvdata(pdev, NULL);
>>>
>>>       return 0;
>>>
>>
>>
> 
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 20/21] thermal: exynos: Support for TMU regulator defined at device tree
@ 2013-05-10 16:05         ` Eduardo Valentin
  0 siblings, 0 replies; 67+ messages in thread
From: Eduardo Valentin @ 2013-05-10 16:05 UTC (permalink / raw)
  To: amit daniel kachhap
  Cc: Eduardo Valentin, linux-pm, Zhang Rui, linux-samsung-soc,
	linux-kernel, Kukjin Kim

[-- Attachment #1: Type: text/plain, Size: 5330 bytes --]

On 09-05-2013 22:28, amit daniel kachhap wrote:
> Hi Eduardo,
> 
> On Thu, May 9, 2013 at 8:14 PM, Eduardo Valentin
> <eduardo.valentin@ti.com> wrote:
>> On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
>>> TMU probe function now checks for a device tree defined regulator.
>>> For compatibility reasons it is allowed to probe driver even without
>>> this regulator defined.
>>>
>>> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
>>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>>> ---
>>>  .../devicetree/bindings/thermal/exynos-thermal.txt |    4 ++++
>>>  drivers/thermal/samsung/exynos_tmu.c               |   19 +++++++++++++++++++
>>>  2 files changed, 23 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>>> index 970eeba..ff62f7a 100644
>>> --- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>>> +++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
>>> @@ -14,6 +14,9 @@
>>>  - interrupts : Should contain interrupt for thermal system
>>>  - clocks : The main clock for TMU device
>>>  - clock-names : Thermal system clock name
>>> +- vtmu-supply: This entry is optional and provides the regulator node supplying
>>> +             voltage to TMU. If needed this entry can be placed inside
>>> +             board/platform specific dts file.
>>>
>>>  Example 1):
>>>
>>> @@ -25,6 +28,7 @@ Example 1):
>>>               clocks = <&clock 383>;
>>>               clock-names = "tmu_apbif";
>>>               status = "disabled";
>>> +             vtmu-supply = <&tmu_regulator_node>;
>>>       };
>>>
>>>  Example 2):
>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>>> index 72446c9..b7c609a 100644
>>> --- a/drivers/thermal/samsung/exynos_tmu.c
>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>>> @@ -32,6 +32,7 @@
>>>  #include <linux/of_address.h>
>>>  #include <linux/of_irq.h>
>>>  #include <linux/platform_device.h>
>>> +#include <linux/regulator/consumer.h>
>>>  #include <linux/slab.h>
>>>  #include <linux/workqueue.h>
>>>  #include "exynos_thermal_common.h"
>>> @@ -52,6 +53,7 @@
>>>   * @clk: pointer to the clock structure.
>>>   * @temp_error1: fused value of the first point trim.
>>>   * @temp_error2: fused value of the second point trim.
>>> + * @regulator: pointer to the TMU regulator structure.
>>>   * @reg_conf: pointer to structure to register with core thermal.
>>>   */
>>>  struct exynos_tmu_data {
>>> @@ -65,6 +67,7 @@ struct exynos_tmu_data {
>>>       struct mutex lock;
>>>       struct clk *clk;
>>>       u8 temp_error1, temp_error2;
>>> +     struct regulator *regulator;
>>>       struct thermal_sensor_conf *reg_conf;
>>>  };
>>>
>>> @@ -501,10 +504,23 @@ static int exynos_map_dt_data(struct platform_device *pdev)
>>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>       struct resource res;
>>> +     int ret;
>>>
>>>       if (!data)
>>>               return -ENODEV;
>>>
>>> +     /* Try enabling the regulator if found */
>>> +     data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
>>> +     if (!IS_ERR(data->regulator)) {
>>> +             ret = regulator_enable(data->regulator);
>>> +             if (ret) {
>>> +                     dev_err(&pdev->dev, "failed to enable vtmu\n");
>>> +                     return ret;
>>> +             }
>>> +     } else {
>>> +             dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
>>
>> Now that you have a bitfield for your features, shouldnt this become a
>> check? If the SoC requires the regulator, then it has to return a valid
>> regulator (regulator_get). Meaning, if your SoC version requires this
>> feature and the regulator_get returns an error, you must treat as an
>> error an not continue gracefuly.
> 
> Earlier I also thought of using bit feature for this but then the
> regulator source usually depends upon the board design so each soc may
> have several boards. So regulator information is not part of SOC data.
> Since this information is there is in DT only so I left this part for
> the DT to handle.
> 


Hmmm.. well, that is actually arguable. Take from driver perspective. If
a regulator is required for a device to work you have to make it a
requirement and not rely on whatever state the system has booted.

From previous discussions, I understood on of your chip versions
actually require a regulator to be activated in order to get the sensors
properly working. Is this understanding correct?

> Thanks,
> Amit Daniel
>>
>>> +     }
>>> +
>>>       data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
>>>       if (data->id < 0)
>>>               data->id = 0;
>>> @@ -669,6 +685,9 @@ static int exynos_tmu_remove(struct platform_device *pdev)
>>>
>>>       clk_unprepare(data->clk);
>>>
>>> +     if (!IS_ERR(data->regulator))
>>> +             regulator_disable(data->regulator);
>>> +
>>>       platform_set_drvdata(pdev, NULL);
>>>
>>>       return 0;
>>>
>>
>>
> 
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 09/21] thermal: exynos: Move register definitions from driver file to data file
  2013-05-10 14:14         ` Eduardo Valentin
  (?)
@ 2013-05-13  1:35         ` amit daniel kachhap
  -1 siblings, 0 replies; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-13  1:35 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel, Kukjin Kim

On Fri, May 10, 2013 at 7:44 PM, Eduardo Valentin
<eduardo.valentin@ti.com> wrote:
> On 09-05-2013 22:17, amit daniel kachhap wrote:
>> Hi Eduardo,
>>
>> On Thu, May 9, 2013 at 8:02 PM, Eduardo Valentin
>> <eduardo.valentin@ti.com> wrote:
>>> Hey Amit,
>>>
>>> On 07-05-2013 09:00, Amit Daniel Kachhap wrote:
>>>> This patch migrates the TMU register definition/bitfields to data file. This
>>>> is needed to support SoC's which use the same TMU controller but register
>>>> validity, offsets or bitfield may slightly vary across SOC's.
>>>>
>>>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>>>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>>>> ---
>>>>  drivers/thermal/samsung/exynos_tmu.c      |  177 +++++++++-------------------
>>>>  drivers/thermal/samsung/exynos_tmu.h      |   76 ++++++++++++
>>>>  drivers/thermal/samsung/exynos_tmu_data.c |   59 ++++++++++
>>>>  drivers/thermal/samsung/exynos_tmu_data.h |   68 +++++++++++
>>>>  4 files changed, 260 insertions(+), 120 deletions(-)
>>>>
>>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>>>> index 23baeeb..97b87aa 100644
>>>> --- a/drivers/thermal/samsung/exynos_tmu.c
>>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>>>> @@ -36,77 +36,6 @@
>>>>  #include "exynos_tmu.h"
>>>>  #include "exynos_tmu_data.h"
>>>>
>>>> -/* Exynos generic registers */
>>>> -#define EXYNOS_TMU_REG_TRIMINFO              0x0
>>>> -#define EXYNOS_TMU_REG_CONTROL               0x20
>>>> -#define EXYNOS_TMU_REG_STATUS                0x28
>>>> -#define EXYNOS_TMU_REG_CURRENT_TEMP  0x40
>>>> -#define EXYNOS_TMU_REG_INTEN         0x70
>>>> -#define EXYNOS_TMU_REG_INTSTAT               0x74
>>>> -#define EXYNOS_TMU_REG_INTCLEAR              0x78
>>>> -
>>>> -#define EXYNOS_TMU_TRIM_TEMP_MASK    0xff
>>>> -#define EXYNOS_TMU_GAIN_SHIFT                8
>>>> -#define EXYNOS_TMU_GAIN_MASK         0xf
>>>> -#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
>>>> -#define EXYNOS_TMU_REF_VOLTAGE_MASK  0x1f
>>>> -#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK        0xf
>>>> -#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT       8
>>>> -#define EXYNOS_TMU_CORE_EN_SHIFT     0
>>>> -
>>>> -/* Exynos4210 specific registers */
>>>> -#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP    0x44
>>>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL0       0x50
>>>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL1       0x54
>>>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL2       0x58
>>>> -#define EXYNOS4210_TMU_REG_TRIG_LEVEL3       0x5C
>>>> -#define EXYNOS4210_TMU_REG_PAST_TEMP0        0x60
>>>> -#define EXYNOS4210_TMU_REG_PAST_TEMP1        0x64
>>>> -#define EXYNOS4210_TMU_REG_PAST_TEMP2        0x68
>>>> -#define EXYNOS4210_TMU_REG_PAST_TEMP3        0x6C
>>>> -
>>>> -#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK      0x1
>>>> -#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK      0x10
>>>> -#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK      0x100
>>>> -#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK      0x1000
>>>> -#define EXYNOS4210_TMU_TRIG_LEVEL_MASK       0x1111
>>>> -#define EXYNOS4210_TMU_INTCLEAR_VAL  0x1111
>>>> -
>>>> -/* Exynos5250 and Exynos4412 specific registers */
>>>> -#define EXYNOS_TMU_TRIMINFO_CON      0x14
>>>> -#define EXYNOS_THD_TEMP_RISE         0x50
>>>> -#define EXYNOS_THD_TEMP_FALL         0x54
>>>> -#define EXYNOS_EMUL_CON              0x80
>>>> -
>>>> -#define EXYNOS_TRIMINFO_RELOAD               0x1
>>>> -#define EXYNOS_TRIMINFO_SHIFT                0x0
>>>> -#define EXYNOS_TMU_RISE_INT_MASK     0x111
>>>> -#define EXYNOS_TMU_RISE_INT_SHIFT    0
>>>> -#define EXYNOS_TMU_FALL_INT_MASK     0x111
>>>> -#define EXYNOS_TMU_FALL_INT_SHIFT    12
>>>> -#define EXYNOS_TMU_CLEAR_RISE_INT    0x111
>>>> -#define EXYNOS_TMU_CLEAR_FALL_INT    (0x111 << 12)
>>>> -#define EXYNOS_TMU_TRIP_MODE_SHIFT   13
>>>> -#define EXYNOS_TMU_TRIP_MODE_MASK    0x7
>>>> -#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT       12
>>>> -
>>>> -#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
>>>> -#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
>>>> -#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
>>>> -#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
>>>> -#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
>>>> -#define EXYNOS_TMU_INTEN_FALL1_SHIFT 20
>>>> -#define EXYNOS_TMU_INTEN_FALL2_SHIFT 24
>>>> -
>>>> -#ifdef CONFIG_THERMAL_EMULATION
>>>> -#define EXYNOS_EMUL_TIME     0x57F0
>>>> -#define EXYNOS_EMUL_TIME_MASK        0xffff
>>>> -#define EXYNOS_EMUL_TIME_SHIFT       16
>>>> -#define EXYNOS_EMUL_DATA_SHIFT       8
>>>> -#define EXYNOS_EMUL_DATA_MASK        0xFF
>>>> -#define EXYNOS_EMUL_ENABLE   0x1
>>>> -#endif /* CONFIG_THERMAL_EMULATION */
>>>> -
>>>>  struct exynos_tmu_data {
>>>>       struct exynos_tmu_platform_data *pdata;
>>>>       struct resource *mem;
>>>> @@ -191,6 +120,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>>  {
>>>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>>       unsigned int status, trim_info, con;
>>>>       unsigned int rising_threshold = 0, falling_threshold = 0;
>>>>       int ret = 0, threshold_code, i, trigger_levs = 0;
>>>> @@ -198,20 +128,20 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>>       mutex_lock(&data->lock);
>>>>       clk_enable(data->clk);
>>>>
>>>> -     status = readb(data->base + EXYNOS_TMU_REG_STATUS);
>>>> +     status = readb(data->base + reg->tmu_status);
>>>>       if (!status) {
>>>>               ret = -EBUSY;
>>>>               goto out;
>>>>       }
>>>>
>>>> -     if (data->soc == SOC_ARCH_EXYNOS) {
>>>> -             __raw_writel(EXYNOS_TRIMINFO_RELOAD,
>>>> -                             data->base + EXYNOS_TMU_TRIMINFO_CON);
>>>> -     }
>>>> +     if (data->soc == SOC_ARCH_EXYNOS)
>>>> +             __raw_writel(1, data->base + reg->triminfo_ctrl);
>>>> +
>>>>       /* Save trimming info in order to perform calibration */
>>>> -     trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
>>>> -     data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
>>>> -     data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
>>>> +     trim_info = readl(data->base + reg->triminfo_data);
>>>> +     data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
>>>> +     data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
>>>> +                             EXYNOS_TMU_TEMP_MASK);
>>>
>>> You changed from EXYNOS_TMU_TRIM_TEMP_MASK to EXYNOS_TMU_TEMP_MASK. Was
>>> it this really what you wanted?
>> Actually temp masks are same so removed  EXYNOS_TMU_TRIM_TEMP_MASK.
>
> ok
>
>>>
>>>>
>>>>       if ((pdata->min_efuse_value > data->temp_error1) ||
>>>>                       (data->temp_error1 > pdata->max_efuse_value) ||
>>>> @@ -231,13 +161,12 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>>                       goto out;
>>>>               }
>>>>               writeb(threshold_code,
>>>> -                     data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
>>>> +                     data->base + reg->threshold_temp);
>>>>               for (i = 0; i < trigger_levs; i++)
>>>>                       writeb(pdata->trigger_levels[i],
>>>> -                     data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
>>>> +                     data->base + reg->threshold_th0 + i * 4);
>>>>
>>>
>>> Is 4 your addressing unit? I believe there is a macro definition for this.
>> yes 4 is a addressing unit. This is only used for 1 SOC so didn't define macro.
>
> Yeah, I though we would have one already. Quick git grep and could not
> find. How about using sizeof(void *) ?
Yes it is should be fine.
>
>>>
>>>> -             writel(EXYNOS4210_TMU_INTCLEAR_VAL,
>>>> -                     data->base + EXYNOS_TMU_REG_INTCLEAR);
>>>> +             writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>>>>       } else if (data->soc == SOC_ARCH_EXYNOS) {
>>>>               /* Write temperature code for rising and falling threshold */
>>>>               for (i = 0; i < trigger_levs; i++) {
>>>> @@ -258,18 +187,19 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>>                       }
>>>>                       if (pdata->trigger_type[i] != HW_TRIP)
>>>>                               continue;
>>>> -                     con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
>>>> -                     con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
>>>> -                     writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
>>>> +                     con = readl(data->base + reg->tmu_ctrl);
>>>> +                     con |= (1 << reg->therm_trip_en_shift);
>>>> +                     writel(con, data->base + reg->tmu_ctrl);
>>>>               }
>>>>
>>>>               writel(rising_threshold,
>>>> -                             data->base + EXYNOS_THD_TEMP_RISE);
>>>> +                             data->base + reg->threshold_th0);
>>>>               writel(falling_threshold,
>>>> -                             data->base + EXYNOS_THD_TEMP_FALL);
>>>> +                             data->base + reg->threshold_th1);
>>>>
>>>> -             writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
>>>> -                             data->base + EXYNOS_TMU_REG_INTCLEAR);
>>>> +             writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>>>> +                     (reg->inten_fall_mask << reg->inten_fall_shift),
>>>> +                             data->base + reg->tmu_intclear);
>>>>       }
>>>>  out:
>>>>       clk_disable(data->clk);
>>>> @@ -282,46 +212,46 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>>>  {
>>>>       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>>       unsigned int con, interrupt_en;
>>>>
>>>>       mutex_lock(&data->lock);
>>>>       clk_enable(data->clk);
>>>>
>>>> -     con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
>>>> +     con = readl(data->base + reg->tmu_ctrl);
>>>>
>>>>       if (pdata->reference_voltage) {
>>>> -             con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK <<
>>>> -                             EXYNOS_TMU_REF_VOLTAGE_SHIFT);
>>>> -             con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
>>>> +             con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
>>>> +             con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
>>>>       }
>>>>
>>>>       if (pdata->gain) {
>>>> -             con &= ~(EXYNOS_TMU_GAIN_MASK << EXYNOS_TMU_GAIN_SHIFT);
>>>> -             con |= (pdata->gain << EXYNOS_TMU_GAIN_SHIFT);
>>>> +             con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
>>>> +             con |= (pdata->gain << reg->buf_slope_sel_shift);
>>>>       }
>>>>
>>>>       if (pdata->noise_cancel_mode) {
>>>> -             con &= ~(EXYNOS_TMU_TRIP_MODE_MASK <<
>>>> -                                     EXYNOS_TMU_TRIP_MODE_SHIFT);
>>>> -             con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
>>>> +             con &= ~(reg->therm_trip_mode_mask <<
>>>> +                                     reg->therm_trip_mode_shift);
>>>> +             con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
>>>>       }
>>>>
>>>>       if (on) {
>>>> -             con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
>>>> +             con |= (1 << reg->core_en_shift);
>>>>               interrupt_en =
>>>> -             pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT |
>>>> -             pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT |
>>>> -             pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT |
>>>> -             pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT;
>>>> +                     pdata->trigger_enable[3] << reg->inten_rise3_shift |
>>>> +                     pdata->trigger_enable[2] << reg->inten_rise2_shift |
>>>> +                     pdata->trigger_enable[1] << reg->inten_rise1_shift |
>>>> +                     pdata->trigger_enable[0] << reg->inten_rise0_shift;
>>>>               if (pdata->threshold_falling)
>>>>                       interrupt_en |=
>>>> -                             interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
>>>> +                             interrupt_en << reg->inten_fall0_shift;
>>>>       } else {
>>>> -             con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
>>>> +             con &= ~(1 << reg->core_en_shift);
>>>>               interrupt_en = 0; /* Disable all interrupts */
>>>>       }
>>>> -     writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
>>>> -     writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
>>>> +     writel(interrupt_en, data->base + reg->tmu_inten);
>>>> +     writel(con, data->base + reg->tmu_ctrl);
>>>>
>>>>       clk_disable(data->clk);
>>>>       mutex_unlock(&data->lock);
>>>> @@ -329,13 +259,15 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>>>
>>>>  static int exynos_tmu_read(struct exynos_tmu_data *data)
>>>>  {
>>>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>>       u8 temp_code;
>>>>       int temp;
>>>>
>>>>       mutex_lock(&data->lock);
>>>>       clk_enable(data->clk);
>>>>
>>>> -     temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
>>>> +     temp_code = readb(data->base + reg->tmu_cur_temp);
>>>>       temp = code_to_temp(data, temp_code);
>>>>
>>>>       clk_disable(data->clk);
>>>> @@ -348,7 +280,9 @@ static int exynos_tmu_read(struct exynos_tmu_data *data)
>>>>  static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>>>>  {
>>>>       struct exynos_tmu_data *data = drv_data;
>>>> -     unsigned int reg;
>>>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>> +     unsigned int val;
>>>>       int ret = -EINVAL;
>>>>
>>>>       if (data->soc == SOC_ARCH_EXYNOS4210)
>>>> @@ -360,19 +294,19 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
>>>>       mutex_lock(&data->lock);
>>>>       clk_enable(data->clk);
>>>>
>>>> -     reg = readl(data->base + EXYNOS_EMUL_CON);
>>>> +     val = readl(data->base + reg->emul_con);
>>>>
>>>>       if (temp) {
>>>>               temp /= MCELSIUS;
>>>>
>>>> -             reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
>>>> +             val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
>>>>                       (temp_to_code(data, temp)
>>>> -                      << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
>>>> +                      << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
>>>>       } else {
>>>> -             reg &= ~EXYNOS_EMUL_ENABLE;
>>>> +             val &= ~EXYNOS_EMUL_ENABLE;
>>>>       }
>>>>
>>>> -     writel(reg, data->base + EXYNOS_EMUL_CON);
>>>> +     writel(val, data->base + reg->emul_con);
>>>>
>>>>       clk_disable(data->clk);
>>>>       mutex_unlock(&data->lock);
>>>> @@ -389,17 +323,20 @@ static void exynos_tmu_work(struct work_struct *work)
>>>>  {
>>>>       struct exynos_tmu_data *data = container_of(work,
>>>>                       struct exynos_tmu_data, irq_work);
>>>> +     struct exynos_tmu_platform_data *pdata = data->pdata;
>>>> +     struct exynos_tmu_registers *reg = pdata->registers;
>>>>
>>>>       exynos_report_trigger();
>>>>       mutex_lock(&data->lock);
>>>>       clk_enable(data->clk);
>>>> +
>>>>       if (data->soc == SOC_ARCH_EXYNOS)
>>>> -             writel(EXYNOS_TMU_CLEAR_RISE_INT |
>>>> -                             EXYNOS_TMU_CLEAR_FALL_INT,
>>>> -                             data->base + EXYNOS_TMU_REG_INTCLEAR);
>>>> +             writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>>>> +                     (reg->inten_fall_mask << reg->inten_fall_shift),
>>>> +                             data->base + reg->tmu_intclear);
>>>>       else
>>>> -             writel(EXYNOS4210_TMU_INTCLEAR_VAL,
>>>> -                             data->base + EXYNOS_TMU_REG_INTCLEAR);
>>>> +             writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>>>> +
>>>>       clk_disable(data->clk);
>>>>       mutex_unlock(&data->lock);
>>>>
>>>> diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
>>>> index 70cc518..1e5e492 100644
>>>> --- a/drivers/thermal/samsung/exynos_tmu.h
>>>> +++ b/drivers/thermal/samsung/exynos_tmu.h
>>>> @@ -46,6 +46,81 @@ enum soc_type {
>>>>  };
>>>>
>>>>  /**
>>>> + * struct exynos_tmu_register - register descriptors to access registers and
>>>> + * bitfields. The register validity, offsets and bitfield values may vary
>>>> + * slightly across different exynos SOC's.
>>>
>>> No documentation for your registers? Or at least where to find explanation?
>> yes didn't write documentation. Will do it.
>>>
>>>> + */
>>>> +struct exynos_tmu_registers {
>>>> +     u32     triminfo_data;
>>>> +     u32     triminfo_25_shift;
>>>> +     u32     triminfo_85_shift;
>>>> +
>>>> +     u32     triminfo_ctrl;
>>>> +     u32     triminfo_reload_shift;
>>>> +
>>>> +     u32     tmu_ctrl;
>>>> +     u32     buf_vref_sel_shift;
>>>> +     u32     buf_vref_sel_mask;
>>>> +     u32     therm_trip_mode_shift;
>>>> +     u32     therm_trip_mode_mask;
>>>> +     u32     therm_trip_en_shift;
>>>> +     u32     buf_slope_sel_shift;
>>>> +     u32     buf_slope_sel_mask;
>>>> +     u32     therm_trip_tq_en_shift;
>>>> +     u32     core_en_shift;
>>>> +
>>>> +     u32     tmu_status;
>>>> +
>>>> +     u32     tmu_cur_temp;
>>>> +     u32     tmu_cur_temp_shift;
>>>> +
>>>> +     u32     threshold_temp;
>>>> +
>>>> +     u32     threshold_th0;
>>>> +     u32     threshold_th0_l0_shift;
>>>> +     u32     threshold_th0_l1_shift;
>>>> +     u32     threshold_th0_l2_shift;
>>>> +     u32     threshold_th0_l3_shift;
>>>> +
>>>> +     u32     threshold_th1;
>>>> +     u32     threshold_th1_l0_shift;
>>>> +     u32     threshold_th1_l1_shift;
>>>> +     u32     threshold_th1_l2_shift;
>>>> +     u32     threshold_th1_l3_shift;
>>>> +
>>>> +     u32     threshold_th2;
>>>> +     u32     threshold_th2_l0_shift;
>>>> +
>>>> +     u32     threshold_th3;
>>>> +     u32     threshold_th3_l0_shift;
>>>> +
>>>> +     u32     tmu_inten;
>>>> +     u32     inten_rise_shift;
>>>> +     u32     inten_rise_mask;
>>>> +     u32     inten_fall_shift;
>>>> +     u32     inten_fall_mask;
>>>> +     u32     inten_rise0_shift;
>>>> +     u32     inten_rise1_shift;
>>>> +     u32     inten_rise2_shift;
>>>> +     u32     inten_rise3_shift;
>>>> +     u32     inten_fall0_shift;
>>>> +     u32     inten_fall1_shift;
>>>> +     u32     inten_fall2_shift;
>>>> +     u32     inten_fall3_shift;
>>>> +
>>>> +     u32     tmu_intstat;
>>>> +
>>>> +     u32     tmu_intclear;
>>>> +
>>>> +     u32     tmu_evten;
>>>> +
>>>> +     u32     emul_con;
>>>> +     u32     emul_temp_shift;
>>>> +     u32     emul_time_shift;
>>>> +     u32     emul_time_mask;
>>>> +};
>>>> +
>>>> +/**
>>>>   * struct exynos_tmu_platform_data
>>>>   * @threshold: basic temperature for generating interrupt
>>>>   *          25 <= threshold <= 125 [unit: degree Celsius]
>>>> @@ -116,5 +191,6 @@ struct exynos_tmu_platform_data {
>>>>       enum soc_type type;
>>>>       struct freq_clip_table freq_tab[4];
>>>>       unsigned int freq_tab_count;
>>>> +     struct exynos_tmu_registers *registers;
>>>>  };
>>>>  #endif /* _LINUX_EXYNOS_THERMAL_H */
>>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
>>>> index 6b937f5..3a1ded1 100644
>>>> --- a/drivers/thermal/samsung/exynos_tmu_data.c
>>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
>>>> @@ -25,6 +25,28 @@
>>>>  #include "exynos_tmu_data.h"
>>>>
>>>>  #if defined(CONFIG_CPU_EXYNOS4210)
>>>> +static struct exynos_tmu_registers exynos4210_tmu_registers = {
>>>> +     .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
>>>> +     .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
>>>> +     .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
>>>> +     .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
>>>> +     .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
>>>> +     .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
>>>> +     .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
>>>> +     .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
>>>> +     .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
>>>> +     .tmu_status = EXYNOS_TMU_REG_STATUS,
>>>> +     .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
>>>> +     .threshold_temp = EXYNOS4210_TMU_REG_THRESHOLD_TEMP,
>>>> +     .threshold_th0 = EXYNOS4210_TMU_REG_TRIG_LEVEL0,
>>>> +     .tmu_inten = EXYNOS_TMU_REG_INTEN,
>>>> +     .inten_rise_mask = EXYNOS4210_TMU_TRIG_LEVEL_MASK,
>>>> +     .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
>>>> +     .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>>>> +     .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>>> +     .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>>> +     .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>>> +};
>>>>  struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>>>       .threshold = 80,
>>>>       .trigger_levels[0] = 5,
>>>> @@ -55,10 +77,46 @@ struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>>>       },
>>>>       .freq_tab_count = 2,
>>>>       .type = SOC_ARCH_EXYNOS4210,
>>>> +     .registers = &exynos4210_tmu_registers,
>>>>  };
>>>>  #endif
>>>>
>>>>  #if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
>>>> +static struct exynos_tmu_registers exynos5250_tmu_registers = {
>>>> +     .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
>>>> +     .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
>>>> +     .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
>>>> +     .triminfo_ctrl = EXYNOS_TMU_TRIMINFO_CON,
>>>> +     .triminfo_reload_shift = EXYNOS_TRIMINFO_RELOAD_SHIFT,
>>>> +     .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
>>>> +     .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
>>>> +     .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
>>>> +     .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
>>>> +     .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
>>>> +     .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
>>>> +     .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
>>>> +     .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
>>>> +     .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
>>>> +     .tmu_status = EXYNOS_TMU_REG_STATUS,
>>>> +     .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
>>>> +     .threshold_th0 = EXYNOS_THD_TEMP_RISE,
>>>> +     .threshold_th1 = EXYNOS_THD_TEMP_FALL,
>>>> +     .tmu_inten = EXYNOS_TMU_REG_INTEN,
>>>> +     .inten_rise_mask = EXYNOS_TMU_RISE_INT_MASK,
>>>> +     .inten_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
>>>> +     .inten_fall_mask = EXYNOS_TMU_FALL_INT_MASK,
>>>> +     .inten_fall_shift = EXYNOS_TMU_FALL_INT_SHIFT,
>>>> +     .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
>>>> +     .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>>>> +     .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>>> +     .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>>> +     .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
>>>> +     .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>>> +     .emul_con = EXYNOS_EMUL_CON,
>>>> +     .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
>>>> +     .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
>>>> +     .emul_time_mask = EXYNOS_EMUL_TIME_MASK,
>>>> +};
>>>>  struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>>>>       .threshold_falling = 10,
>>>>       .trigger_levels[0] = 85,
>>>> @@ -93,5 +151,6 @@ struct exynos_tmu_platform_data const exynos5250_default_tmu_data = {
>>>>       },
>>>>       .freq_tab_count = 2,
>>>>       .type = SOC_ARCH_EXYNOS,
>>>> +     .registers = &exynos5250_tmu_registers,
>>>>  };
>>>>  #endif
>>>
>>> One thing, I believe your data can be declared as const.
>> yes they are already const.
>>
>
> Not all. The register structs you are adding are not const, for instance.
ok right.
>
>> Thanks,
>> Amit Daniel
>>>
>>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
>>>> index 5b69711..0560413 100644
>>>> --- a/drivers/thermal/samsung/exynos_tmu_data.h
>>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.h
>>>> @@ -23,6 +23,74 @@
>>>>  #ifndef _LINUX_EXYNOS_TMU_DATA_H
>>>>  #define _LINUX_EXYNOS_TMU_DATA_H
>>>>
>>>> +/* Exynos generic registers */
>>>> +#define EXYNOS_TMU_REG_TRIMINFO              0x0
>>>> +#define EXYNOS_TMU_REG_CONTROL               0x20
>>>> +#define EXYNOS_TMU_REG_STATUS                0x28
>>>> +#define EXYNOS_TMU_REG_CURRENT_TEMP  0x40
>>>> +#define EXYNOS_TMU_REG_INTEN         0x70
>>>> +#define EXYNOS_TMU_REG_INTSTAT               0x74
>>>> +#define EXYNOS_TMU_REG_INTCLEAR              0x78
>>>> +
>>>> +#define EXYNOS_TMU_TEMP_MASK         0xff
>>>> +#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
>>>> +#define EXYNOS_TMU_REF_VOLTAGE_MASK  0x1f
>>>> +#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK        0xf
>>>> +#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT       8
>>>> +#define EXYNOS_TMU_CORE_EN_SHIFT     0
>>>> +
>>>> +/* Exynos4210 specific registers */
>>>> +#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP    0x44
>>>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL0       0x50
>>>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL1       0x54
>>>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL2       0x58
>>>> +#define EXYNOS4210_TMU_REG_TRIG_LEVEL3       0x5C
>>>> +#define EXYNOS4210_TMU_REG_PAST_TEMP0        0x60
>>>> +#define EXYNOS4210_TMU_REG_PAST_TEMP1        0x64
>>>> +#define EXYNOS4210_TMU_REG_PAST_TEMP2        0x68
>>>> +#define EXYNOS4210_TMU_REG_PAST_TEMP3        0x6C
>>>> +
>>>> +#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK      0x1
>>>> +#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK      0x10
>>>> +#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK      0x100
>>>> +#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK      0x1000
>>>> +#define EXYNOS4210_TMU_TRIG_LEVEL_MASK       0x1111
>>>> +#define EXYNOS4210_TMU_INTCLEAR_VAL  0x1111
>>>> +
>>>> +/* Exynos5250 and Exynos4412 specific registers */
>>>> +#define EXYNOS_TMU_TRIMINFO_CON      0x14
>>>> +#define EXYNOS_THD_TEMP_RISE         0x50
>>>> +#define EXYNOS_THD_TEMP_FALL         0x54
>>>> +#define EXYNOS_EMUL_CON              0x80
>>>> +
>>>> +#define EXYNOS_TRIMINFO_RELOAD_SHIFT 1
>>>> +#define EXYNOS_TRIMINFO_25_SHIFT     0
>>>> +#define EXYNOS_TRIMINFO_85_SHIFT     8
>>>> +#define EXYNOS_TMU_RISE_INT_MASK     0x111
>>>> +#define EXYNOS_TMU_RISE_INT_SHIFT    0
>>>> +#define EXYNOS_TMU_FALL_INT_MASK     0x111
>>>> +#define EXYNOS_TMU_FALL_INT_SHIFT    12
>>>> +#define EXYNOS_TMU_CLEAR_RISE_INT    0x111
>>>> +#define EXYNOS_TMU_CLEAR_FALL_INT    (0x111 << 12)
>>>> +#define EXYNOS_TMU_TRIP_MODE_SHIFT   13
>>>> +#define EXYNOS_TMU_TRIP_MODE_MASK    0x7
>>>> +#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT       12
>>>> +
>>>> +#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
>>>> +#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
>>>> +#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
>>>> +#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
>>>> +#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
>>>> +#define EXYNOS_TMU_INTEN_FALL1_SHIFT 20
>>>> +#define EXYNOS_TMU_INTEN_FALL2_SHIFT 24
>>>> +
>>>> +#define EXYNOS_EMUL_TIME     0x57F0
>>>> +#define EXYNOS_EMUL_TIME_MASK        0xffff
>>>> +#define EXYNOS_EMUL_TIME_SHIFT       16
>>>> +#define EXYNOS_EMUL_DATA_SHIFT       8
>>>> +#define EXYNOS_EMUL_DATA_MASK        0xFF
>>>> +#define EXYNOS_EMUL_ENABLE   0x1
>>>> +
>>>>  #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS_THERMAL_DATA)
>>>>  extern struct exynos_tmu_platform_data const exynos4210_default_tmu_data;
>>>>  #define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
>>>>
>>>
>>>
>>
>>
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH V3 10/21] thermal: exynos: Fix to clear only the generated interrupts
  2013-05-10 15:40         ` Eduardo Valentin
  (?)
@ 2013-05-13  1:36         ` amit daniel kachhap
  -1 siblings, 0 replies; 67+ messages in thread
From: amit daniel kachhap @ 2013-05-13  1:36 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: linux-pm, Zhang Rui, linux-samsung-soc, linux-kernel, Kukjin Kim

On Fri, May 10, 2013 at 9:10 PM, Eduardo Valentin
<eduardo.valentin@ti.com> wrote:
> On 09-05-2013 22:22, amit daniel kachhap wrote:
>> Hi,
>>
>> On Thu, May 9, 2013 at 8:03 PM, Eduardo Valentin
>> <eduardo.valentin@ti.com> wrote:
>>> On 07-05-2013 09:01, Amit Daniel Kachhap wrote:
>>>> This patch uses the TMU status register to know the generated interrupts
>>>> and only clear them in the interrupt handler.
>>>>
>>>> Acked-by: Kukjin Kim <kgene.kim@samsung.com>
>>>> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
>>>> ---
>>>>  drivers/thermal/samsung/exynos_tmu.c      |   10 ++++------
>>>>  drivers/thermal/samsung/exynos_tmu_data.c |    2 ++
>>>>  2 files changed, 6 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>>>> index 97b87aa..082d5a2 100644
>>>> --- a/drivers/thermal/samsung/exynos_tmu.c
>>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>>>> @@ -325,17 +325,15 @@ static void exynos_tmu_work(struct work_struct *work)
>>>>                       struct exynos_tmu_data, irq_work);
>>>>       struct exynos_tmu_platform_data *pdata = data->pdata;
>>>>       struct exynos_tmu_registers *reg = pdata->registers;
>>>> +     unsigned int val_irq;
>>>>
>>>>       exynos_report_trigger();
>>>>       mutex_lock(&data->lock);
>>>>       clk_enable(data->clk);
>>>>
>>>> -     if (data->soc == SOC_ARCH_EXYNOS)
>>>> -             writel((reg->inten_rise_mask << reg->inten_rise_shift) |
>>>> -                     (reg->inten_fall_mask << reg->inten_fall_shift),
>>>> -                             data->base + reg->tmu_intclear);
>>>> -     else
>>>> -             writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
>>>> +     val_irq = readl(data->base + reg->tmu_intstat);
>>>> +     /* clear the interrupts */
>>>> +     writel(val_irq, data->base + reg->tmu_intclear);
>>>>
>>>
>>> hmmm.. Don t you need to act accordingly depending on what is in your
>>> int status?
>>
>> Earlier also it is done like this way. Basically core thermal layer
>> checks temp for each trip so even if I check for which threshold
>> interrupt is raised it is of no use. Anyway this is a TODO for me.
>>
>
> Please add  a /* TODO: */ entry then.
ok,

Thanks,
Amit Daniel
>
>> Thanks,
>> Amit Daniel
>>>
>>>>       clk_disable(data->clk);
>>>>       mutex_unlock(&data->lock);
>>>> diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
>>>> index 3a1ded1..7322597 100644
>>>> --- a/drivers/thermal/samsung/exynos_tmu_data.c
>>>> +++ b/drivers/thermal/samsung/exynos_tmu_data.c
>>>> @@ -45,6 +45,7 @@ static struct exynos_tmu_registers exynos4210_tmu_registers = {
>>>>       .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
>>>>       .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>>>       .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>>> +     .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
>>>>       .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>>>  };
>>>>  struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
>>>> @@ -111,6 +112,7 @@ static struct exynos_tmu_registers exynos5250_tmu_registers = {
>>>>       .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
>>>>       .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
>>>>       .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
>>>> +     .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
>>>>       .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
>>>>       .emul_con = EXYNOS_EMUL_CON,
>>>>       .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
>>>>
>>>
>>>
>>
>>
>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

end of thread, other threads:[~2013-05-13  1:36 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-07 13:00 [PATCH V3 0/20] thermal: exynos: Add thermal driver for exynos5440 Amit Daniel Kachhap
2013-05-07 13:00 ` [PATCH V3 01/21] thermal: exynos: Moving exynos thermal files into samsung directory Amit Daniel Kachhap
2013-05-07 13:07   ` [RESEND PATCH " Amit Daniel Kachhap
2013-05-08 15:49     ` Eduardo Valentin
2013-05-08 15:49       ` Eduardo Valentin
2013-05-09  2:15       ` amit daniel kachhap
2013-05-07 13:00 ` [PATCH V3 02/21] thermal: exynos: Bifurcate exynos thermal common and tmu controller code Amit Daniel Kachhap
2013-05-07 13:41   ` Zhang Rui
2013-05-08  3:49     ` amit daniel kachhap
2013-05-08 16:01   ` Eduardo Valentin
2013-05-08 16:01     ` Eduardo Valentin
2013-05-09  5:15     ` amit daniel kachhap
2013-05-07 13:00 ` [PATCH V3 03/21] thermal: exynos: Rename exynos_thermal.c to exynos_tmu.c Amit Daniel Kachhap
2013-05-10 15:12   ` Eduardo Valentin
2013-05-10 15:12     ` Eduardo Valentin
2013-05-07 13:00 ` [PATCH V3 04/21] thermal: exynos: Move exynos_thermal.h from include/* to driver/* folder Amit Daniel Kachhap
2013-05-09 13:28   ` Eduardo Valentin
2013-05-09 13:28     ` Eduardo Valentin
2013-05-10  1:53     ` amit daniel kachhap
2013-05-07 13:00 ` [PATCH V3 05/21] thermal: exynos: Bifurcate exynos tmu driver and configuration data Amit Daniel Kachhap
2013-05-09 13:39   ` Eduardo Valentin
2013-05-09 13:39     ` Eduardo Valentin
2013-05-10  2:05     ` amit daniel kachhap
2013-05-07 13:00 ` [PATCH V3 06/21] thermal: exynos: Add missing definations and code cleanup Amit Daniel Kachhap
2013-05-09 13:52   ` Eduardo Valentin
2013-05-09 13:52     ` Eduardo Valentin
2013-05-10  2:12     ` amit daniel kachhap
2013-05-07 13:00 ` [PATCH V3 07/21] thermal: exynos: Add extra entries in the tmu platform data Amit Daniel Kachhap
2013-05-07 13:00 ` [PATCH V3 08/21] thermal: exynos: Support thermal tripping Amit Daniel Kachhap
2013-05-07 13:00 ` [PATCH V3 09/21] thermal: exynos: Move register definitions from driver file to data file Amit Daniel Kachhap
2013-05-09 14:32   ` Eduardo Valentin
2013-05-09 14:32     ` Eduardo Valentin
2013-05-10  2:17     ` amit daniel kachhap
2013-05-10 14:14       ` Eduardo Valentin
2013-05-10 14:14         ` Eduardo Valentin
2013-05-13  1:35         ` amit daniel kachhap
2013-05-07 13:01 ` [PATCH V3 10/21] thermal: exynos: Fix to clear only the generated interrupts Amit Daniel Kachhap
2013-05-09 14:33   ` Eduardo Valentin
2013-05-09 14:33     ` Eduardo Valentin
2013-05-10  2:22     ` amit daniel kachhap
2013-05-10 15:40       ` Eduardo Valentin
2013-05-10 15:40         ` Eduardo Valentin
2013-05-13  1:36         ` amit daniel kachhap
2013-05-07 13:01 ` [PATCH V3 11/21] thermal: exynos: Add support for instance based register/unregister Amit Daniel Kachhap
2013-05-07 13:01 ` [PATCH V3 12/21] thermal: exynos: Modify private_data to appropriate name driver_data Amit Daniel Kachhap
2013-05-07 13:01 ` [PATCH V3 13/21] thermal: exynos: Return success even if no cooling data supplied Amit Daniel Kachhap
2013-05-07 13:01 ` [PATCH V3 14/21] thermal: exynos: Make the zone handling dependent on trip count Amit Daniel Kachhap
2013-05-07 13:01 ` [PATCH V3 15/21] thermal: exynos: Add support to handle many instances of TMU Amit Daniel Kachhap
2013-05-09 14:53   ` Eduardo Valentin
2013-05-09 14:53     ` Eduardo Valentin
2013-05-10  2:32     ` amit daniel kachhap
2013-05-07 13:01 ` [PATCH V3 16/21] thermal: exynos: Add features to check instead of using SOC type Amit Daniel Kachhap
2013-05-07 13:01 ` [PATCH V3 17/21] ARM: dts: thermal: exynos4: Add documentation for Exynos SoC thermal bindings Amit Daniel Kachhap
2013-05-07 13:01 ` [PATCH V3 18/21] thermal: exynos: Add support for exynos5440 TMU sensor Amit Daniel Kachhap
2013-05-09 14:47   ` Eduardo Valentin
2013-05-09 14:47     ` Eduardo Valentin
2013-05-10  2:31     ` amit daniel kachhap
2013-05-10 14:14       ` Eduardo Valentin
2013-05-10 14:14         ` Eduardo Valentin
2013-05-07 13:01 ` [PATCH V3 19/21] Documentation: thermal: Explain the exynos thermal driver model Amit Daniel Kachhap
2013-05-07 13:01 ` [PATCH V3 20/21] thermal: exynos: Support for TMU regulator defined at device tree Amit Daniel Kachhap
2013-05-09 14:44   ` Eduardo Valentin
2013-05-09 14:44     ` Eduardo Valentin
2013-05-10  2:28     ` amit daniel kachhap
2013-05-10 16:05       ` Eduardo Valentin
2013-05-10 16:05         ` Eduardo Valentin
2013-05-07 13:01 ` [PATCH V3 21/21] ARM: dts: Add device tree node for exynos5440 TMU controller Amit Daniel Kachhap

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.