aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/ec.c30
-rw-r--r--drivers/acpi/processor_idle.c3
-rw-r--r--drivers/acpi/thermal.c93
-rw-r--r--drivers/cpuidle/cpuidle.c2
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/exynos4_tmu.c518
-rw-r--r--drivers/platform/x86/acerhdf.c5
-rw-r--r--drivers/platform/x86/intel_mid_thermal.c2
-rw-r--r--drivers/power/power_supply_core.c2
-rw-r--r--drivers/staging/omap-thermal/omap-thermal-common.c5
-rw-r--r--drivers/thermal/Kconfig26
-rw-r--r--drivers/thermal/Makefile5
-rw-r--r--drivers/thermal/cpu_cooling.c449
-rw-r--r--drivers/thermal/exynos_thermal.c997
-rw-r--r--drivers/thermal/rcar_thermal.c260
-rw-r--r--drivers/thermal/spear_thermal.c2
-rw-r--r--drivers/thermal/thermal_sys.c321
18 files changed, 2044 insertions, 687 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 7edaccce6640..a51df9681319 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -71,9 +71,6 @@ enum ec_command {
71#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ 71#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
72#define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */ 72#define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */
73 73
74#define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts
75 per one transaction */
76
77enum { 74enum {
78 EC_FLAGS_QUERY_PENDING, /* Query is pending */ 75 EC_FLAGS_QUERY_PENDING, /* Query is pending */
79 EC_FLAGS_GPE_STORM, /* GPE storm detected */ 76 EC_FLAGS_GPE_STORM, /* GPE storm detected */
@@ -87,6 +84,15 @@ static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
87module_param(ec_delay, uint, 0644); 84module_param(ec_delay, uint, 0644);
88MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes"); 85MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
89 86
87/*
88 * If the number of false interrupts per one transaction exceeds
89 * this threshold, will think there is a GPE storm happened and
90 * will disable the GPE for normal transaction.
91 */
92static unsigned int ec_storm_threshold __read_mostly = 8;
93module_param(ec_storm_threshold, uint, 0644);
94MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm");
95
90/* If we find an EC via the ECDT, we need to keep a ptr to its context */ 96/* If we find an EC via the ECDT, we need to keep a ptr to its context */
91/* External interfaces use first EC only, so remember */ 97/* External interfaces use first EC only, so remember */
92typedef int (*acpi_ec_query_func) (void *data); 98typedef int (*acpi_ec_query_func) (void *data);
@@ -319,7 +325,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
319 msleep(1); 325 msleep(1);
320 /* It is safe to enable the GPE outside of the transaction. */ 326 /* It is safe to enable the GPE outside of the transaction. */
321 acpi_enable_gpe(NULL, ec->gpe); 327 acpi_enable_gpe(NULL, ec->gpe);
322 } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { 328 } else if (t->irq_count > ec_storm_threshold) {
323 pr_info(PREFIX "GPE storm detected, " 329 pr_info(PREFIX "GPE storm detected, "
324 "transactions will use polling mode\n"); 330 "transactions will use polling mode\n");
325 set_bit(EC_FLAGS_GPE_STORM, &ec->flags); 331 set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
@@ -924,6 +930,17 @@ static int ec_flag_msi(const struct dmi_system_id *id)
924 return 0; 930 return 0;
925} 931}
926 932
933/*
934 * Clevo M720 notebook actually works ok with IRQ mode, if we lifted
935 * the GPE storm threshold back to 20
936 */
937static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
938{
939 pr_debug("Setting the EC GPE storm threshold to 20\n");
940 ec_storm_threshold = 20;
941 return 0;
942}
943
927static struct dmi_system_id __initdata ec_dmi_table[] = { 944static struct dmi_system_id __initdata ec_dmi_table[] = {
928 { 945 {
929 ec_skip_dsdt_scan, "Compal JFL92", { 946 ec_skip_dsdt_scan, "Compal JFL92", {
@@ -955,10 +972,13 @@ static struct dmi_system_id __initdata ec_dmi_table[] = {
955 { 972 {
956 ec_validate_ecdt, "ASUS hardware", { 973 ec_validate_ecdt, "ASUS hardware", {
957 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL}, 974 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL},
975 {
976 ec_enlarge_storm_threshold, "CLEVO hardware", {
977 DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
978 DMI_MATCH(DMI_PRODUCT_NAME, "M720T/M730T"),}, NULL},
958 {}, 979 {},
959}; 980};
960 981
961
962int __init acpi_ec_ecdt_probe(void) 982int __init acpi_ec_ecdt_probe(void)
963{ 983{
964 acpi_status status; 984 acpi_status status;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 3655ab923812..e8086c725305 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -1132,7 +1132,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
1132int acpi_processor_hotplug(struct acpi_processor *pr) 1132int acpi_processor_hotplug(struct acpi_processor *pr)
1133{ 1133{
1134 int ret = 0; 1134 int ret = 0;
1135 struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id); 1135 struct cpuidle_device *dev;
1136 1136
1137 if (disabled_by_idle_boot_param()) 1137 if (disabled_by_idle_boot_param())
1138 return 0; 1138 return 0;
@@ -1147,6 +1147,7 @@ int acpi_processor_hotplug(struct acpi_processor *pr)
1147 if (!pr->flags.power_setup_done) 1147 if (!pr->flags.power_setup_done)
1148 return -ENODEV; 1148 return -ENODEV;
1149 1149
1150 dev = per_cpu(acpi_cpuidle_device, pr->id);
1150 cpuidle_pause_and_lock(); 1151 cpuidle_pause_and_lock();
1151 cpuidle_disable_device(dev); 1152 cpuidle_disable_device(dev);
1152 acpi_processor_get_power_info(pr); 1153 acpi_processor_get_power_info(pr);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index edda74a43406..804204d41999 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -708,6 +708,40 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
708 return -EINVAL; 708 return -EINVAL;
709} 709}
710 710
711static int thermal_get_trend(struct thermal_zone_device *thermal,
712 int trip, enum thermal_trend *trend)
713{
714 struct acpi_thermal *tz = thermal->devdata;
715 enum thermal_trip_type type;
716 int i;
717
718 if (thermal_get_trip_type(thermal, trip, &type))
719 return -EINVAL;
720
721 if (type == THERMAL_TRIP_ACTIVE) {
722 /* aggressive active cooling */
723 *trend = THERMAL_TREND_RAISING;
724 return 0;
725 }
726
727 /*
728 * tz->temperature has already been updated by generic thermal layer,
729 * before this callback being invoked
730 */
731 i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
732 + (tz->trips.passive.tc2
733 * (tz->temperature - tz->trips.passive.temperature));
734
735 if (i > 0)
736 *trend = THERMAL_TREND_RAISING;
737 else if (i < 0)
738 *trend = THERMAL_TREND_DROPPING;
739 else
740 *trend = THERMAL_TREND_STABLE;
741 return 0;
742}
743
744
711static int thermal_notify(struct thermal_zone_device *thermal, int trip, 745static int thermal_notify(struct thermal_zone_device *thermal, int trip,
712 enum thermal_trip_type trip_type) 746 enum thermal_trip_type trip_type)
713{ 747{
@@ -731,11 +765,9 @@ static int thermal_notify(struct thermal_zone_device *thermal, int trip,
731 return 0; 765 return 0;
732} 766}
733 767
734typedef int (*cb)(struct thermal_zone_device *, int,
735 struct thermal_cooling_device *);
736static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, 768static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
737 struct thermal_cooling_device *cdev, 769 struct thermal_cooling_device *cdev,
738 cb action) 770 bool bind)
739{ 771{
740 struct acpi_device *device = cdev->devdata; 772 struct acpi_device *device = cdev->devdata;
741 struct acpi_thermal *tz = thermal->devdata; 773 struct acpi_thermal *tz = thermal->devdata;
@@ -759,11 +791,19 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
759 i++) { 791 i++) {
760 handle = tz->trips.passive.devices.handles[i]; 792 handle = tz->trips.passive.devices.handles[i];
761 status = acpi_bus_get_device(handle, &dev); 793 status = acpi_bus_get_device(handle, &dev);
762 if (ACPI_SUCCESS(status) && (dev == device)) { 794 if (ACPI_FAILURE(status) || dev != device)
763 result = action(thermal, trip, cdev); 795 continue;
764 if (result) 796 if (bind)
765 goto failed; 797 result =
766 } 798 thermal_zone_bind_cooling_device
799 (thermal, trip, cdev,
800 THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
801 else
802 result =
803 thermal_zone_unbind_cooling_device
804 (thermal, trip, cdev);
805 if (result)
806 goto failed;
767 } 807 }
768 } 808 }
769 809
@@ -776,11 +816,17 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
776 j++) { 816 j++) {
777 handle = tz->trips.active[i].devices.handles[j]; 817 handle = tz->trips.active[i].devices.handles[j];
778 status = acpi_bus_get_device(handle, &dev); 818 status = acpi_bus_get_device(handle, &dev);
779 if (ACPI_SUCCESS(status) && (dev == device)) { 819 if (ACPI_FAILURE(status) || dev != device)
780 result = action(thermal, trip, cdev); 820 continue;
781 if (result) 821 if (bind)
782 goto failed; 822 result = thermal_zone_bind_cooling_device
783 } 823 (thermal, trip, cdev,
824 THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
825 else
826 result = thermal_zone_unbind_cooling_device
827 (thermal, trip, cdev);
828 if (result)
829 goto failed;
784 } 830 }
785 } 831 }
786 832
@@ -788,7 +834,14 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
788 handle = tz->devices.handles[i]; 834 handle = tz->devices.handles[i];
789 status = acpi_bus_get_device(handle, &dev); 835 status = acpi_bus_get_device(handle, &dev);
790 if (ACPI_SUCCESS(status) && (dev == device)) { 836 if (ACPI_SUCCESS(status) && (dev == device)) {
791 result = action(thermal, -1, cdev); 837 if (bind)
838 result = thermal_zone_bind_cooling_device
839 (thermal, -1, cdev,
840 THERMAL_NO_LIMIT,
841 THERMAL_NO_LIMIT);
842 else
843 result = thermal_zone_unbind_cooling_device
844 (thermal, -1, cdev);
792 if (result) 845 if (result)
793 goto failed; 846 goto failed;
794 } 847 }
@@ -802,16 +855,14 @@ static int
802acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal, 855acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
803 struct thermal_cooling_device *cdev) 856 struct thermal_cooling_device *cdev)
804{ 857{
805 return acpi_thermal_cooling_device_cb(thermal, cdev, 858 return acpi_thermal_cooling_device_cb(thermal, cdev, true);
806 thermal_zone_bind_cooling_device);
807} 859}
808 860
809static int 861static int
810acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal, 862acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
811 struct thermal_cooling_device *cdev) 863 struct thermal_cooling_device *cdev)
812{ 864{
813 return acpi_thermal_cooling_device_cb(thermal, cdev, 865 return acpi_thermal_cooling_device_cb(thermal, cdev, false);
814 thermal_zone_unbind_cooling_device);
815} 866}
816 867
817static const struct thermal_zone_device_ops acpi_thermal_zone_ops = { 868static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
@@ -823,6 +874,7 @@ static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
823 .get_trip_type = thermal_get_trip_type, 874 .get_trip_type = thermal_get_trip_type,
824 .get_trip_temp = thermal_get_trip_temp, 875 .get_trip_temp = thermal_get_trip_temp,
825 .get_crit_temp = thermal_get_crit_temp, 876 .get_crit_temp = thermal_get_crit_temp,
877 .get_trend = thermal_get_trend,
826 .notify = thermal_notify, 878 .notify = thermal_notify,
827}; 879};
828 880
@@ -849,15 +901,12 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
849 tz->thermal_zone = 901 tz->thermal_zone =
850 thermal_zone_device_register("acpitz", trips, 0, tz, 902 thermal_zone_device_register("acpitz", trips, 0, tz,
851 &acpi_thermal_zone_ops, 903 &acpi_thermal_zone_ops,
852 tz->trips.passive.tc1,
853 tz->trips.passive.tc2,
854 tz->trips.passive.tsp*100, 904 tz->trips.passive.tsp*100,
855 tz->polling_frequency*100); 905 tz->polling_frequency*100);
856 else 906 else
857 tz->thermal_zone = 907 tz->thermal_zone =
858 thermal_zone_device_register("acpitz", trips, 0, tz, 908 thermal_zone_device_register("acpitz", trips, 0, tz,
859 &acpi_thermal_zone_ops, 909 &acpi_thermal_zone_ops, 0,
860 0, 0, 0,
861 tz->polling_frequency*100); 910 tz->polling_frequency*100);
862 if (IS_ERR(tz->thermal_zone)) 911 if (IS_ERR(tz->thermal_zone))
863 return -ENODEV; 912 return -ENODEV;
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index e28f6ea46f1a..7f15b8514a18 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -368,7 +368,7 @@ EXPORT_SYMBOL_GPL(cpuidle_enable_device);
368 */ 368 */
369void cpuidle_disable_device(struct cpuidle_device *dev) 369void cpuidle_disable_device(struct cpuidle_device *dev)
370{ 370{
371 if (!dev->enabled) 371 if (!dev || !dev->enabled)
372 return; 372 return;
373 if (!cpuidle_get_driver() || !cpuidle_curr_governor) 373 if (!cpuidle_get_driver() || !cpuidle_curr_governor)
374 return; 374 return;
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c74e73b2069a..c4633de64465 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -334,16 +334,6 @@ config SENSORS_DA9052_ADC
334 This driver can also be built as module. If so, the module 334 This driver can also be built as module. If so, the module
335 will be called da9052-hwmon. 335 will be called da9052-hwmon.
336 336
337config SENSORS_EXYNOS4_TMU
338 tristate "Temperature sensor on Samsung EXYNOS4"
339 depends on ARCH_EXYNOS4
340 help
341 If you say yes here you get support for TMU (Thermal Management
342 Unit) on SAMSUNG EXYNOS4 series of SoC.
343
344 This driver can also be built as a module. If so, the module
345 will be called exynos4-tmu.
346
347config SENSORS_I5K_AMB 337config SENSORS_I5K_AMB
348 tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets" 338 tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
349 depends on PCI 339 depends on PCI
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index a62ce17ddbfc..8d5fcb5e8e9f 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -50,7 +50,6 @@ obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
50obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o 50obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o
51obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o 51obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o
52obj-$(CONFIG_SENSORS_EMC6W201) += emc6w201.o 52obj-$(CONFIG_SENSORS_EMC6W201) += emc6w201.o
53obj-$(CONFIG_SENSORS_EXYNOS4_TMU) += exynos4_tmu.o
54obj-$(CONFIG_SENSORS_F71805F) += f71805f.o 53obj-$(CONFIG_SENSORS_F71805F) += f71805f.o
55obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o 54obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o
56obj-$(CONFIG_SENSORS_F75375S) += f75375s.o 55obj-$(CONFIG_SENSORS_F75375S) += f75375s.o
diff --git a/drivers/hwmon/exynos4_tmu.c b/drivers/hwmon/exynos4_tmu.c
deleted file mode 100644
index e912059140cd..000000000000
--- a/drivers/hwmon/exynos4_tmu.c
+++ /dev/null
@@ -1,518 +0,0 @@
1/*
2 * exynos4_tmu.c - Samsung EXYNOS4 TMU (Thermal Management Unit)
3 *
4 * Copyright (C) 2011 Samsung Electronics
5 * Donggeun Kim <dg77.kim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <linux/module.h>
24#include <linux/err.h>
25#include <linux/kernel.h>
26#include <linux/slab.h>
27#include <linux/platform_device.h>
28#include <linux/interrupt.h>
29#include <linux/clk.h>
30#include <linux/workqueue.h>
31#include <linux/sysfs.h>
32#include <linux/kobject.h>
33#include <linux/io.h>
34#include <linux/mutex.h>
35
36#include <linux/hwmon.h>
37#include <linux/hwmon-sysfs.h>
38
39#include <linux/platform_data/exynos4_tmu.h>
40
41#define EXYNOS4_TMU_REG_TRIMINFO 0x0
42#define EXYNOS4_TMU_REG_CONTROL 0x20
43#define EXYNOS4_TMU_REG_STATUS 0x28
44#define EXYNOS4_TMU_REG_CURRENT_TEMP 0x40
45#define EXYNOS4_TMU_REG_THRESHOLD_TEMP 0x44
46#define EXYNOS4_TMU_REG_TRIG_LEVEL0 0x50
47#define EXYNOS4_TMU_REG_TRIG_LEVEL1 0x54
48#define EXYNOS4_TMU_REG_TRIG_LEVEL2 0x58
49#define EXYNOS4_TMU_REG_TRIG_LEVEL3 0x5C
50#define EXYNOS4_TMU_REG_PAST_TEMP0 0x60
51#define EXYNOS4_TMU_REG_PAST_TEMP1 0x64
52#define EXYNOS4_TMU_REG_PAST_TEMP2 0x68
53#define EXYNOS4_TMU_REG_PAST_TEMP3 0x6C
54#define EXYNOS4_TMU_REG_INTEN 0x70
55#define EXYNOS4_TMU_REG_INTSTAT 0x74
56#define EXYNOS4_TMU_REG_INTCLEAR 0x78
57
58#define EXYNOS4_TMU_GAIN_SHIFT 8
59#define EXYNOS4_TMU_REF_VOLTAGE_SHIFT 24
60
61#define EXYNOS4_TMU_TRIM_TEMP_MASK 0xff
62#define EXYNOS4_TMU_CORE_ON 3
63#define EXYNOS4_TMU_CORE_OFF 2
64#define EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET 50
65#define EXYNOS4_TMU_TRIG_LEVEL0_MASK 0x1
66#define EXYNOS4_TMU_TRIG_LEVEL1_MASK 0x10
67#define EXYNOS4_TMU_TRIG_LEVEL2_MASK 0x100
68#define EXYNOS4_TMU_TRIG_LEVEL3_MASK 0x1000
69#define EXYNOS4_TMU_INTCLEAR_VAL 0x1111
70
71struct exynos4_tmu_data {
72 struct exynos4_tmu_platform_data *pdata;
73 struct device *hwmon_dev;
74 struct resource *mem;
75 void __iomem *base;
76 int irq;
77 struct work_struct irq_work;
78 struct mutex lock;
79 struct clk *clk;
80 u8 temp_error1, temp_error2;
81};
82
83/*
84 * TMU treats temperature as a mapped temperature code.
85 * The temperature is converted differently depending on the calibration type.
86 */
87static int temp_to_code(struct exynos4_tmu_data *data, u8 temp)
88{
89 struct exynos4_tmu_platform_data *pdata = data->pdata;
90 int temp_code;
91
92 /* temp should range between 25 and 125 */
93 if (temp < 25 || temp > 125) {
94 temp_code = -EINVAL;
95 goto out;
96 }
97
98 switch (pdata->cal_type) {
99 case TYPE_TWO_POINT_TRIMMING:
100 temp_code = (temp - 25) *
101 (data->temp_error2 - data->temp_error1) /
102 (85 - 25) + data->temp_error1;
103 break;
104 case TYPE_ONE_POINT_TRIMMING:
105 temp_code = temp + data->temp_error1 - 25;
106 break;
107 default:
108 temp_code = temp + EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET;
109 break;
110 }
111out:
112 return temp_code;
113}
114
115/*
116 * Calculate a temperature value from a temperature code.
117 * The unit of the temperature is degree Celsius.
118 */
119static int code_to_temp(struct exynos4_tmu_data *data, u8 temp_code)
120{
121 struct exynos4_tmu_platform_data *pdata = data->pdata;
122 int temp;
123
124 /* temp_code should range between 75 and 175 */
125 if (temp_code < 75 || temp_code > 175) {
126 temp = -ENODATA;
127 goto out;
128 }
129
130 switch (pdata->cal_type) {
131 case TYPE_TWO_POINT_TRIMMING:
132 temp = (temp_code - data->temp_error1) * (85 - 25) /
133 (data->temp_error2 - data->temp_error1) + 25;
134 break;
135 case TYPE_ONE_POINT_TRIMMING:
136 temp = temp_code - data->temp_error1 + 25;
137 break;
138 default:
139 temp = temp_code - EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET;
140 break;
141 }
142out:
143 return temp;
144}
145
146static int exynos4_tmu_initialize(struct platform_device *pdev)
147{
148 struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
149 struct exynos4_tmu_platform_data *pdata = data->pdata;
150 unsigned int status, trim_info;
151 int ret = 0, threshold_code;
152
153 mutex_lock(&data->lock);
154 clk_enable(data->clk);
155
156 status = readb(data->base + EXYNOS4_TMU_REG_STATUS);
157 if (!status) {
158 ret = -EBUSY;
159 goto out;
160 }
161
162 /* Save trimming info in order to perform calibration */
163 trim_info = readl(data->base + EXYNOS4_TMU_REG_TRIMINFO);
164 data->temp_error1 = trim_info & EXYNOS4_TMU_TRIM_TEMP_MASK;
165 data->temp_error2 = ((trim_info >> 8) & EXYNOS4_TMU_TRIM_TEMP_MASK);
166
167 /* Write temperature code for threshold */
168 threshold_code = temp_to_code(data, pdata->threshold);
169 if (threshold_code < 0) {
170 ret = threshold_code;
171 goto out;
172 }
173 writeb(threshold_code,
174 data->base + EXYNOS4_TMU_REG_THRESHOLD_TEMP);
175
176 writeb(pdata->trigger_levels[0],
177 data->base + EXYNOS4_TMU_REG_TRIG_LEVEL0);
178 writeb(pdata->trigger_levels[1],
179 data->base + EXYNOS4_TMU_REG_TRIG_LEVEL1);
180 writeb(pdata->trigger_levels[2],
181 data->base + EXYNOS4_TMU_REG_TRIG_LEVEL2);
182 writeb(pdata->trigger_levels[3],
183 data->base + EXYNOS4_TMU_REG_TRIG_LEVEL3);
184
185 writel(EXYNOS4_TMU_INTCLEAR_VAL,
186 data->base + EXYNOS4_TMU_REG_INTCLEAR);
187out:
188 clk_disable(data->clk);
189 mutex_unlock(&data->lock);
190
191 return ret;
192}
193
194static void exynos4_tmu_control(struct platform_device *pdev, bool on)
195{
196 struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
197 struct exynos4_tmu_platform_data *pdata = data->pdata;
198 unsigned int con, interrupt_en;
199
200 mutex_lock(&data->lock);
201 clk_enable(data->clk);
202
203 con = pdata->reference_voltage << EXYNOS4_TMU_REF_VOLTAGE_SHIFT |
204 pdata->gain << EXYNOS4_TMU_GAIN_SHIFT;
205 if (on) {
206 con |= EXYNOS4_TMU_CORE_ON;
207 interrupt_en = pdata->trigger_level3_en << 12 |
208 pdata->trigger_level2_en << 8 |
209 pdata->trigger_level1_en << 4 |
210 pdata->trigger_level0_en;
211 } else {
212 con |= EXYNOS4_TMU_CORE_OFF;
213 interrupt_en = 0; /* Disable all interrupts */
214 }
215 writel(interrupt_en, data->base + EXYNOS4_TMU_REG_INTEN);
216 writel(con, data->base + EXYNOS4_TMU_REG_CONTROL);
217
218 clk_disable(data->clk);
219 mutex_unlock(&data->lock);
220}
221
222static int exynos4_tmu_read(struct exynos4_tmu_data *data)
223{
224 u8 temp_code;
225 int temp;
226
227 mutex_lock(&data->lock);
228 clk_enable(data->clk);
229
230 temp_code = readb(data->base + EXYNOS4_TMU_REG_CURRENT_TEMP);
231 temp = code_to_temp(data, temp_code);
232
233 clk_disable(data->clk);
234 mutex_unlock(&data->lock);
235
236 return temp;
237}
238
239static void exynos4_tmu_work(struct work_struct *work)
240{
241 struct exynos4_tmu_data *data = container_of(work,
242 struct exynos4_tmu_data, irq_work);
243
244 mutex_lock(&data->lock);
245 clk_enable(data->clk);
246
247 writel(EXYNOS4_TMU_INTCLEAR_VAL, data->base + EXYNOS4_TMU_REG_INTCLEAR);
248
249 kobject_uevent(&data->hwmon_dev->kobj, KOBJ_CHANGE);
250
251 enable_irq(data->irq);
252
253 clk_disable(data->clk);
254 mutex_unlock(&data->lock);
255}
256
257static irqreturn_t exynos4_tmu_irq(int irq, void *id)
258{
259 struct exynos4_tmu_data *data = id;
260
261 disable_irq_nosync(irq);
262 schedule_work(&data->irq_work);
263
264 return IRQ_HANDLED;
265}
266
267static ssize_t exynos4_tmu_show_name(struct device *dev,
268 struct device_attribute *attr, char *buf)
269{
270 return sprintf(buf, "exynos4-tmu\n");
271}
272
273static ssize_t exynos4_tmu_show_temp(struct device *dev,
274 struct device_attribute *attr, char *buf)
275{
276 struct exynos4_tmu_data *data = dev_get_drvdata(dev);
277 int ret;
278
279 ret = exynos4_tmu_read(data);
280 if (ret < 0)
281 return ret;
282
283 /* convert from degree Celsius to millidegree Celsius */
284 return sprintf(buf, "%d\n", ret * 1000);
285}
286
287static ssize_t exynos4_tmu_show_alarm(struct device *dev,
288 struct device_attribute *devattr, char *buf)
289{
290 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
291 struct exynos4_tmu_data *data = dev_get_drvdata(dev);
292 struct exynos4_tmu_platform_data *pdata = data->pdata;
293 int temp;
294 unsigned int trigger_level;
295
296 temp = exynos4_tmu_read(data);
297 if (temp < 0)
298 return temp;
299
300 trigger_level = pdata->threshold + pdata->trigger_levels[attr->index];
301
302 return sprintf(buf, "%d\n", !!(temp > trigger_level));
303}
304
305static ssize_t exynos4_tmu_show_level(struct device *dev,
306 struct device_attribute *devattr, char *buf)
307{
308 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
309 struct exynos4_tmu_data *data = dev_get_drvdata(dev);
310 struct exynos4_tmu_platform_data *pdata = data->pdata;
311 unsigned int temp = pdata->threshold +
312 pdata->trigger_levels[attr->index];
313
314 return sprintf(buf, "%u\n", temp * 1000);
315}
316
317static DEVICE_ATTR(name, S_IRUGO, exynos4_tmu_show_name, NULL);
318static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, exynos4_tmu_show_temp, NULL, 0);
319
320static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
321 exynos4_tmu_show_alarm, NULL, 1);
322static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO,
323 exynos4_tmu_show_alarm, NULL, 2);
324static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO,
325 exynos4_tmu_show_alarm, NULL, 3);
326
327static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, exynos4_tmu_show_level, NULL, 1);
328static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, exynos4_tmu_show_level, NULL, 2);
329static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO,
330 exynos4_tmu_show_level, NULL, 3);
331
332static struct attribute *exynos4_tmu_attributes[] = {
333 &dev_attr_name.attr,
334 &sensor_dev_attr_temp1_input.dev_attr.attr,
335 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
336 &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
337 &sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr,
338 &sensor_dev_attr_temp1_max.dev_attr.attr,
339 &sensor_dev_attr_temp1_crit.dev_attr.attr,
340 &sensor_dev_attr_temp1_emergency.dev_attr.attr,
341 NULL,
342};
343
344static const struct attribute_group exynos4_tmu_attr_group = {
345 .attrs = exynos4_tmu_attributes,
346};
347
348static int __devinit exynos4_tmu_probe(struct platform_device *pdev)
349{
350 struct exynos4_tmu_data *data;
351 struct exynos4_tmu_platform_data *pdata = pdev->dev.platform_data;
352 int ret;
353
354 if (!pdata) {
355 dev_err(&pdev->dev, "No platform init data supplied.\n");
356 return -ENODEV;
357 }
358
359 data = kzalloc(sizeof(struct exynos4_tmu_data), GFP_KERNEL);
360 if (!data) {
361 dev_err(&pdev->dev, "Failed to allocate driver structure\n");
362 return -ENOMEM;
363 }
364
365 data->irq = platform_get_irq(pdev, 0);
366 if (data->irq < 0) {
367 ret = data->irq;
368 dev_err(&pdev->dev, "Failed to get platform irq\n");
369 goto err_free;
370 }
371
372 INIT_WORK(&data->irq_work, exynos4_tmu_work);
373
374 data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
375 if (!data->mem) {
376 ret = -ENOENT;
377 dev_err(&pdev->dev, "Failed to get platform resource\n");
378 goto err_free;
379 }
380
381 data->mem = request_mem_region(data->mem->start,
382 resource_size(data->mem), pdev->name);
383 if (!data->mem) {
384 ret = -ENODEV;
385 dev_err(&pdev->dev, "Failed to request memory region\n");
386 goto err_free;
387 }
388
389 data->base = ioremap(data->mem->start, resource_size(data->mem));
390 if (!data->base) {
391 ret = -ENODEV;
392 dev_err(&pdev->dev, "Failed to ioremap memory\n");
393 goto err_mem_region;
394 }
395
396 ret = request_irq(data->irq, exynos4_tmu_irq,
397 IRQF_TRIGGER_RISING,
398 "exynos4-tmu", data);
399 if (ret) {
400 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
401 goto err_io_remap;
402 }
403
404 data->clk = clk_get(NULL, "tmu_apbif");
405 if (IS_ERR(data->clk)) {
406 ret = PTR_ERR(data->clk);
407 dev_err(&pdev->dev, "Failed to get clock\n");
408 goto err_irq;
409 }
410
411 data->pdata = pdata;
412 platform_set_drvdata(pdev, data);
413 mutex_init(&data->lock);
414
415 ret = exynos4_tmu_initialize(pdev);
416 if (ret) {
417 dev_err(&pdev->dev, "Failed to initialize TMU\n");
418 goto err_clk;
419 }
420
421 ret = sysfs_create_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
422 if (ret) {
423 dev_err(&pdev->dev, "Failed to create sysfs group\n");
424 goto err_clk;
425 }
426
427 data->hwmon_dev = hwmon_device_register(&pdev->dev);
428 if (IS_ERR(data->hwmon_dev)) {
429 ret = PTR_ERR(data->hwmon_dev);
430 dev_err(&pdev->dev, "Failed to register hwmon device\n");
431 goto err_create_group;
432 }
433
434 exynos4_tmu_control(pdev, true);
435
436 return 0;
437
438err_create_group:
439 sysfs_remove_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
440err_clk:
441 platform_set_drvdata(pdev, NULL);
442 clk_put(data->clk);
443err_irq:
444 free_irq(data->irq, data);
445err_io_remap:
446 iounmap(data->base);
447err_mem_region:
448 release_mem_region(data->mem->start, resource_size(data->mem));
449err_free:
450 kfree(data);
451
452 return ret;
453}
454
455static int __devexit exynos4_tmu_remove(struct platform_device *pdev)
456{
457 struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
458
459 exynos4_tmu_control(pdev, false);
460
461 hwmon_device_unregister(data->hwmon_dev);
462 sysfs_remove_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
463
464 clk_put(data->clk);
465
466 free_irq(data->irq, data);
467
468 iounmap(data->base);
469 release_mem_region(data->mem->start, resource_size(data->mem));
470
471 platform_set_drvdata(pdev, NULL);
472
473 kfree(data);
474
475 return 0;
476}
477
478#ifdef CONFIG_PM_SLEEP
479static int exynos4_tmu_suspend(struct device *dev)
480{
481 exynos4_tmu_control(to_platform_device(dev), false);
482
483 return 0;
484}
485
486static int exynos4_tmu_resume(struct device *dev)
487{
488 struct platform_device *pdev = to_platform_device(dev);
489
490 exynos4_tmu_initialize(pdev);
491 exynos4_tmu_control(pdev, true);
492
493 return 0;
494}
495
496static SIMPLE_DEV_PM_OPS(exynos4_tmu_pm,
497 exynos4_tmu_suspend, exynos4_tmu_resume);
498#define EXYNOS4_TMU_PM &exynos4_tmu_pm
499#else
500#define EXYNOS4_TMU_PM NULL
501#endif
502
503static struct platform_driver exynos4_tmu_driver = {
504 .driver = {
505 .name = "exynos4-tmu",
506 .owner = THIS_MODULE,
507 .pm = EXYNOS4_TMU_PM,
508 },
509 .probe = exynos4_tmu_probe,
510 .remove = __devexit_p(exynos4_tmu_remove),
511};
512
513module_platform_driver(exynos4_tmu_driver);
514
515MODULE_DESCRIPTION("EXYNOS4 TMU Driver");
516MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
517MODULE_LICENSE("GPL");
518MODULE_ALIAS("platform:exynos4-tmu");
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index 39abb150bdd4..84c56881ba80 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -329,7 +329,8 @@ static int acerhdf_bind(struct thermal_zone_device *thermal,
329 if (cdev != cl_dev) 329 if (cdev != cl_dev)
330 return 0; 330 return 0;
331 331
332 if (thermal_zone_bind_cooling_device(thermal, 0, cdev)) { 332 if (thermal_zone_bind_cooling_device(thermal, 0, cdev,
333 THERMAL_NO_LIMIT, THERMAL_NO_LIMIT)) {
333 pr_err("error binding cooling dev\n"); 334 pr_err("error binding cooling dev\n");
334 return -EINVAL; 335 return -EINVAL;
335 } 336 }
@@ -661,7 +662,7 @@ static int acerhdf_register_thermal(void)
661 return -EINVAL; 662 return -EINVAL;
662 663
663 thz_dev = thermal_zone_device_register("acerhdf", 1, 0, NULL, 664 thz_dev = thermal_zone_device_register("acerhdf", 1, 0, NULL,
664 &acerhdf_dev_ops, 0, 0, 0, 665 &acerhdf_dev_ops, 0,
665 (kernelmode) ? interval*1000 : 0); 666 (kernelmode) ? interval*1000 : 0);
666 if (IS_ERR(thz_dev)) 667 if (IS_ERR(thz_dev))
667 return -EINVAL; 668 return -EINVAL;
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
index 3a27113deda9..c8097616dd62 100644
--- a/drivers/platform/x86/intel_mid_thermal.c
+++ b/drivers/platform/x86/intel_mid_thermal.c
@@ -502,7 +502,7 @@ static int mid_thermal_probe(struct platform_device *pdev)
502 goto err; 502 goto err;
503 } 503 }
504 pinfo->tzd[i] = thermal_zone_device_register(name[i], 504 pinfo->tzd[i] = thermal_zone_device_register(name[i],
505 0, 0, td_info, &tzd_ops, 0, 0, 0, 0); 505 0, 0, td_info, &tzd_ops, 0, 0);
506 if (IS_ERR(pinfo->tzd[i])) { 506 if (IS_ERR(pinfo->tzd[i])) {
507 kfree(td_info); 507 kfree(td_info);
508 ret = PTR_ERR(pinfo->tzd[i]); 508 ret = PTR_ERR(pinfo->tzd[i]);
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 08cc8a3c15af..2436f1350013 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -201,7 +201,7 @@ static int psy_register_thermal(struct power_supply *psy)
201 for (i = 0; i < psy->num_properties; i++) { 201 for (i = 0; i < psy->num_properties; i++) {
202 if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) { 202 if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) {
203 psy->tzd = thermal_zone_device_register(psy->name, 0, 0, 203 psy->tzd = thermal_zone_device_register(psy->name, 0, 0,
204 psy, &psy_tzd_ops, 0, 0, 0, 0); 204 psy, &psy_tzd_ops, 0, 0);
205 if (IS_ERR(psy->tzd)) 205 if (IS_ERR(psy->tzd))
206 return PTR_ERR(psy->tzd); 206 return PTR_ERR(psy->tzd);
207 break; 207 break;
diff --git a/drivers/staging/omap-thermal/omap-thermal-common.c b/drivers/staging/omap-thermal/omap-thermal-common.c
index 46ee0a9f49d9..5c0c203b887f 100644
--- a/drivers/staging/omap-thermal/omap-thermal-common.c
+++ b/drivers/staging/omap-thermal/omap-thermal-common.c
@@ -126,7 +126,9 @@ static int omap_thermal_bind(struct thermal_zone_device *thermal,
126 126
127 /* TODO: bind with min and max states */ 127 /* TODO: bind with min and max states */
128 /* Simple thing, two trips, one passive another critical */ 128 /* Simple thing, two trips, one passive another critical */
129 return thermal_zone_bind_cooling_device(thermal, 0, cdev); 129 return thermal_zone_bind_cooling_device(thermal, 0, cdev,
130 THERMAL_NO_LIMIT,
131 THERMAL_NO_LIMIT);
130} 132}
131 133
132/* Unbind callback functions for thermal zone */ 134/* Unbind callback functions for thermal zone */
@@ -268,7 +270,6 @@ int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id,
268 /* Create thermal zone */ 270 /* Create thermal zone */
269 data->omap_thermal = thermal_zone_device_register(domain, 271 data->omap_thermal = thermal_zone_device_register(domain,
270 OMAP_TRIP_NUMBER, 0, data, &omap_thermal_ops, 272 OMAP_TRIP_NUMBER, 0, data, &omap_thermal_ops,
271 1, 2, /*TODO: remove this when FW allows */
272 FAST_TEMP_MONITORING_RATE, 273 FAST_TEMP_MONITORING_RATE,
273 FAST_TEMP_MONITORING_RATE); 274 FAST_TEMP_MONITORING_RATE);
274 if (IS_ERR_OR_NULL(data->omap_thermal)) { 275 if (IS_ERR_OR_NULL(data->omap_thermal)) {
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 3ab2bd540b54..edfd67d25013 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -19,6 +19,17 @@ config THERMAL_HWMON
19 depends on HWMON=y || HWMON=THERMAL 19 depends on HWMON=y || HWMON=THERMAL
20 default y 20 default y
21 21
22config CPU_THERMAL
23 bool "generic cpu cooling support"
24 depends on THERMAL && CPU_FREQ
25 help
26 This implements the generic cpu cooling mechanism through frequency
27 reduction, cpu hotplug and any other ways of reducing temperature. An
28 ACPI version of this already exists(drivers/acpi/processor_thermal.c).
29 This will be useful for platforms using the generic thermal interface
30 and not the ACPI interface.
31 If you want this support, you should say Y here.
32
22config SPEAR_THERMAL 33config SPEAR_THERMAL
23 bool "SPEAr thermal sensor driver" 34 bool "SPEAr thermal sensor driver"
24 depends on THERMAL 35 depends on THERMAL
@@ -27,3 +38,18 @@ config SPEAR_THERMAL
27 help 38 help
28 Enable this to plug the SPEAr thermal sensor driver into the Linux 39 Enable this to plug the SPEAr thermal sensor driver into the Linux
29 thermal framework 40 thermal framework
41
42config RCAR_THERMAL
43 tristate "Renesas R-Car thermal driver"
44 depends on THERMAL
45 depends on ARCH_SHMOBILE
46 help
47 Enable this to plug the R-Car thermal sensor driver into the Linux
48 thermal framework
49
50config EXYNOS_THERMAL
51 tristate "Temperature sensor on Samsung EXYNOS"
52 depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5) && THERMAL
53 help
54 If you say yes here you get support for TMU (Thermal Managment
55 Unit) on SAMSUNG EXYNOS series of SoC.
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index a9fff0bf4b14..885550dc64b7 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -3,4 +3,7 @@
3# 3#
4 4
5obj-$(CONFIG_THERMAL) += thermal_sys.o 5obj-$(CONFIG_THERMAL) += thermal_sys.o
6obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o \ No newline at end of file 6obj-$(CONFIG_CPU_THERMAL) += cpu_cooling.o
7obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
8obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
9obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
new file mode 100644
index 000000000000..cc1c930a90e4
--- /dev/null
+++ b/drivers/thermal/cpu_cooling.c
@@ -0,0 +1,449 @@
1/*
2 * linux/drivers/thermal/cpu_cooling.c
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com)
5 * Copyright (C) 2012 Amit Daniel <amit.kachhap@linaro.org>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 *
21 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 */
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/thermal.h>
26#include <linux/platform_device.h>
27#include <linux/cpufreq.h>
28#include <linux/err.h>
29#include <linux/slab.h>
30#include <linux/cpu.h>
31#include <linux/cpu_cooling.h>
32
33/**
34 * struct cpufreq_cooling_device
35 * @id: unique integer value corresponding to each cpufreq_cooling_device
36 * registered.
37 * @cool_dev: thermal_cooling_device pointer to keep track of the the
38 * egistered cooling device.
39 * @cpufreq_state: integer value representing the current state of cpufreq
40 * cooling devices.
41 * @cpufreq_val: integer value representing the absolute value of the clipped
42 * frequency.
43 * @allowed_cpus: all the cpus involved for this cpufreq_cooling_device.
44 * @node: list_head to link all cpufreq_cooling_device together.
45 *
46 * This structure is required for keeping information of each
47 * cpufreq_cooling_device registered as a list whose head is represented by
48 * cooling_cpufreq_list. In order to prevent corruption of this list a
49 * mutex lock cooling_cpufreq_lock is used.
50 */
51struct cpufreq_cooling_device {
52 int id;
53 struct thermal_cooling_device *cool_dev;
54 unsigned int cpufreq_state;
55 unsigned int cpufreq_val;
56 struct cpumask allowed_cpus;
57 struct list_head node;
58};
59static LIST_HEAD(cooling_cpufreq_list);
60static DEFINE_IDR(cpufreq_idr);
61
62static struct mutex cooling_cpufreq_lock;
63
64/* notify_table passes value to the CPUFREQ_ADJUST callback function. */
65#define NOTIFY_INVALID NULL
66struct cpufreq_cooling_device *notify_device;
67
68/**
69 * get_idr - function to get a unique id.
70 * @idr: struct idr * handle used to create a id.
71 * @id: int * value generated by this function.
72 */
73static int get_idr(struct idr *idr, int *id)
74{
75 int err;
76again:
77 if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
78 return -ENOMEM;
79
80 mutex_lock(&cooling_cpufreq_lock);
81 err = idr_get_new(idr, NULL, id);
82 mutex_unlock(&cooling_cpufreq_lock);
83
84 if (unlikely(err == -EAGAIN))
85 goto again;
86 else if (unlikely(err))
87 return err;
88
89 *id = *id & MAX_IDR_MASK;
90 return 0;
91}
92
93/**
94 * release_idr - function to free the unique id.
95 * @idr: struct idr * handle used for creating the id.
96 * @id: int value representing the unique id.
97 */
98static void release_idr(struct idr *idr, int id)
99{
100 mutex_lock(&cooling_cpufreq_lock);
101 idr_remove(idr, id);
102 mutex_unlock(&cooling_cpufreq_lock);
103}
104
105/* Below code defines functions to be used for cpufreq as cooling device */
106
107/**
108 * is_cpufreq_valid - function to check if a cpu has frequency transition policy.
109 * @cpu: cpu for which check is needed.
110 */
111static int is_cpufreq_valid(int cpu)
112{
113 struct cpufreq_policy policy;
114 return !cpufreq_get_policy(&policy, cpu);
115}
116
117/**
118 * get_cpu_frequency - get the absolute value of frequency from level.
119 * @cpu: cpu for which frequency is fetched.
120 * @level: level of frequency of the CPU
121 * e.g level=1 --> 1st MAX FREQ, LEVEL=2 ---> 2nd MAX FREQ, .... etc
122 */
123static unsigned int get_cpu_frequency(unsigned int cpu, unsigned long level)
124{
125 int ret = 0, i = 0;
126 unsigned long level_index;
127 bool descend = false;
128 struct cpufreq_frequency_table *table =
129 cpufreq_frequency_get_table(cpu);
130 if (!table)
131 return ret;
132
133 while (table[i].frequency != CPUFREQ_TABLE_END) {
134 if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
135 continue;
136
137 /*check if table in ascending or descending order*/
138 if ((table[i + 1].frequency != CPUFREQ_TABLE_END) &&
139 (table[i + 1].frequency < table[i].frequency)
140 && !descend) {
141 descend = true;
142 }
143
144 /*return if level matched and table in descending order*/
145 if (descend && i == level)
146 return table[i].frequency;
147 i++;
148 }
149 i--;
150
151 if (level > i || descend)
152 return ret;
153 level_index = i - level;
154
155 /*Scan the table in reverse order and match the level*/
156 while (i >= 0) {
157 if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
158 continue;
159 /*return if level matched*/
160 if (i == level_index)
161 return table[i].frequency;
162 i--;
163 }
164 return ret;
165}
166
167/**
168 * cpufreq_apply_cooling - function to apply frequency clipping.
169 * @cpufreq_device: cpufreq_cooling_device pointer containing frequency
170 * clipping data.
171 * @cooling_state: value of the cooling state.
172 */
173static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device,
174 unsigned long cooling_state)
175{
176 unsigned int cpuid, clip_freq;
177 struct cpumask *maskPtr = &cpufreq_device->allowed_cpus;
178 unsigned int cpu = cpumask_any(maskPtr);
179
180
181 /* Check if the old cooling action is same as new cooling action */
182 if (cpufreq_device->cpufreq_state == cooling_state)
183 return 0;
184
185 clip_freq = get_cpu_frequency(cpu, cooling_state);
186 if (!clip_freq)
187 return -EINVAL;
188
189 cpufreq_device->cpufreq_state = cooling_state;
190 cpufreq_device->cpufreq_val = clip_freq;
191 notify_device = cpufreq_device;
192
193 for_each_cpu(cpuid, maskPtr) {
194 if (is_cpufreq_valid(cpuid))
195 cpufreq_update_policy(cpuid);
196 }
197
198 notify_device = NOTIFY_INVALID;
199
200 return 0;
201}
202
203/**
204 * cpufreq_thermal_notifier - notifier callback for cpufreq policy change.
205 * @nb: struct notifier_block * with callback info.
206 * @event: value showing cpufreq event for which this function invoked.
207 * @data: callback-specific data
208 */
209static int cpufreq_thermal_notifier(struct notifier_block *nb,
210 unsigned long event, void *data)
211{
212 struct cpufreq_policy *policy = data;
213 unsigned long max_freq = 0;
214
215 if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID)
216 return 0;
217
218 if (cpumask_test_cpu(policy->cpu, &notify_device->allowed_cpus))
219 max_freq = notify_device->cpufreq_val;
220
221 /* Never exceed user_policy.max*/
222 if (max_freq > policy->user_policy.max)
223 max_freq = policy->user_policy.max;
224
225 if (policy->max != max_freq)
226 cpufreq_verify_within_limits(policy, 0, max_freq);
227
228 return 0;
229}
230
231/*
232 * cpufreq cooling device callback functions are defined below
233 */
234
235/**
236 * cpufreq_get_max_state - callback function to get the max cooling state.
237 * @cdev: thermal cooling device pointer.
238 * @state: fill this variable with the max cooling state.
239 */
240static int cpufreq_get_max_state(struct thermal_cooling_device *cdev,
241 unsigned long *state)
242{
243 int ret = -EINVAL, i = 0;
244 struct cpufreq_cooling_device *cpufreq_device;
245 struct cpumask *maskPtr;
246 unsigned int cpu;
247 struct cpufreq_frequency_table *table;
248
249 mutex_lock(&cooling_cpufreq_lock);
250 list_for_each_entry(cpufreq_device, &cooling_cpufreq_list, node) {
251 if (cpufreq_device && cpufreq_device->cool_dev == cdev)
252 break;
253 }
254 if (cpufreq_device == NULL)
255 goto return_get_max_state;
256
257 maskPtr = &cpufreq_device->allowed_cpus;
258 cpu = cpumask_any(maskPtr);
259 table = cpufreq_frequency_get_table(cpu);
260 if (!table) {
261 *state = 0;
262 ret = 0;
263 goto return_get_max_state;
264 }
265
266 while (table[i].frequency != CPUFREQ_TABLE_END) {
267 if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
268 continue;
269 i++;
270 }
271 if (i > 0) {
272 *state = --i;
273 ret = 0;
274 }
275
276return_get_max_state:
277 mutex_unlock(&cooling_cpufreq_lock);
278 return ret;
279}
280
281/**
282 * cpufreq_get_cur_state - callback function to get the current cooling state.
283 * @cdev: thermal cooling device pointer.
284 * @state: fill this variable with the current cooling state.
285 */
286static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
287 unsigned long *state)
288{
289 int ret = -EINVAL;
290 struct cpufreq_cooling_device *cpufreq_device;
291
292 mutex_lock(&cooling_cpufreq_lock);
293 list_for_each_entry(cpufreq_device, &cooling_cpufreq_list, node) {
294 if (cpufreq_device && cpufreq_device->cool_dev == cdev) {
295 *state = cpufreq_device->cpufreq_state;
296 ret = 0;
297 break;
298 }
299 }
300 mutex_unlock(&cooling_cpufreq_lock);
301
302 return ret;
303}
304
305/**
306 * cpufreq_set_cur_state - callback function to set the current cooling state.
307 * @cdev: thermal cooling device pointer.
308 * @state: set this variable to the current cooling state.
309 */
310static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
311 unsigned long state)
312{
313 int ret = -EINVAL;
314 struct cpufreq_cooling_device *cpufreq_device;
315
316 mutex_lock(&cooling_cpufreq_lock);
317 list_for_each_entry(cpufreq_device, &cooling_cpufreq_list, node) {
318 if (cpufreq_device && cpufreq_device->cool_dev == cdev) {
319 ret = 0;
320 break;
321 }
322 }
323 if (!ret)
324 ret = cpufreq_apply_cooling(cpufreq_device, state);
325
326 mutex_unlock(&cooling_cpufreq_lock);
327
328 return ret;
329}
330
331/* Bind cpufreq callbacks to thermal cooling device ops */
332static struct thermal_cooling_device_ops const cpufreq_cooling_ops = {
333 .get_max_state = cpufreq_get_max_state,
334 .get_cur_state = cpufreq_get_cur_state,
335 .set_cur_state = cpufreq_set_cur_state,
336};
337
338/* Notifier for cpufreq policy change */
339static struct notifier_block thermal_cpufreq_notifier_block = {
340 .notifier_call = cpufreq_thermal_notifier,
341};
342
343/**
344 * cpufreq_cooling_register - function to create cpufreq cooling device.
345 * @clip_cpus: cpumask of cpus where the frequency constraints will happen.
346 */
347struct thermal_cooling_device *cpufreq_cooling_register(
348 struct cpumask *clip_cpus)
349{
350 struct thermal_cooling_device *cool_dev;
351 struct cpufreq_cooling_device *cpufreq_dev = NULL;
352 unsigned int cpufreq_dev_count = 0, min = 0, max = 0;
353 char dev_name[THERMAL_NAME_LENGTH];
354 int ret = 0, i;
355 struct cpufreq_policy policy;
356
357 list_for_each_entry(cpufreq_dev, &cooling_cpufreq_list, node)
358 cpufreq_dev_count++;
359
360 /*Verify that all the clip cpus have same freq_min, freq_max limit*/
361 for_each_cpu(i, clip_cpus) {
362 /*continue if cpufreq policy not found and not return error*/
363 if (!cpufreq_get_policy(&policy, i))
364 continue;
365 if (min == 0 && max == 0) {
366 min = policy.cpuinfo.min_freq;
367 max = policy.cpuinfo.max_freq;
368 } else {
369 if (min != policy.cpuinfo.min_freq ||
370 max != policy.cpuinfo.max_freq)
371 return ERR_PTR(-EINVAL);
372}
373 }
374 cpufreq_dev = kzalloc(sizeof(struct cpufreq_cooling_device),
375 GFP_KERNEL);
376 if (!cpufreq_dev)
377 return ERR_PTR(-ENOMEM);
378
379 cpumask_copy(&cpufreq_dev->allowed_cpus, clip_cpus);
380
381 if (cpufreq_dev_count == 0)
382 mutex_init(&cooling_cpufreq_lock);
383
384 ret = get_idr(&cpufreq_idr, &cpufreq_dev->id);
385 if (ret) {
386 kfree(cpufreq_dev);
387 return ERR_PTR(-EINVAL);
388 }
389
390 sprintf(dev_name, "thermal-cpufreq-%d", cpufreq_dev->id);
391
392 cool_dev = thermal_cooling_device_register(dev_name, cpufreq_dev,
393 &cpufreq_cooling_ops);
394 if (!cool_dev) {
395 release_idr(&cpufreq_idr, cpufreq_dev->id);
396 kfree(cpufreq_dev);
397 return ERR_PTR(-EINVAL);
398 }
399 cpufreq_dev->cool_dev = cool_dev;
400 cpufreq_dev->cpufreq_state = 0;
401 mutex_lock(&cooling_cpufreq_lock);
402 list_add_tail(&cpufreq_dev->node, &cooling_cpufreq_list);
403
404 /* Register the notifier for first cpufreq cooling device */
405 if (cpufreq_dev_count == 0)
406 cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
407 CPUFREQ_POLICY_NOTIFIER);
408
409 mutex_unlock(&cooling_cpufreq_lock);
410 return cool_dev;
411}
412EXPORT_SYMBOL(cpufreq_cooling_register);
413
414/**
415 * cpufreq_cooling_unregister - function to remove cpufreq cooling device.
416 * @cdev: thermal cooling device pointer.
417 */
418void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
419{
420 struct cpufreq_cooling_device *cpufreq_dev = NULL;
421 unsigned int cpufreq_dev_count = 0;
422
423 mutex_lock(&cooling_cpufreq_lock);
424 list_for_each_entry(cpufreq_dev, &cooling_cpufreq_list, node) {
425 if (cpufreq_dev && cpufreq_dev->cool_dev == cdev)
426 break;
427 cpufreq_dev_count++;
428 }
429
430 if (!cpufreq_dev || cpufreq_dev->cool_dev != cdev) {
431 mutex_unlock(&cooling_cpufreq_lock);
432 return;
433 }
434
435 list_del(&cpufreq_dev->node);
436
437 /* Unregister the notifier for the last cpufreq cooling device */
438 if (cpufreq_dev_count == 1) {
439 cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
440 CPUFREQ_POLICY_NOTIFIER);
441 }
442 mutex_unlock(&cooling_cpufreq_lock);
443 thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
444 release_idr(&cpufreq_idr, cpufreq_dev->id);
445 if (cpufreq_dev_count == 1)
446 mutex_destroy(&cooling_cpufreq_lock);
447 kfree(cpufreq_dev);
448}
449EXPORT_SYMBOL(cpufreq_cooling_unregister);
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c
new file mode 100644
index 000000000000..fd03e8581afc
--- /dev/null
+++ b/drivers/thermal/exynos_thermal.c
@@ -0,0 +1,997 @@
1/*
2 * exynos_thermal.c - Samsung EXYNOS TMU (Thermal Management Unit)
3 *
4 * Copyright (C) 2011 Samsung Electronics
5 * Donggeun Kim <dg77.kim@samsung.com>
6 * Amit Daniel Kachhap <amit.kachhap@linaro.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/err.h>
26#include <linux/kernel.h>
27#include <linux/slab.h>
28#include <linux/platform_device.h>
29#include <linux/interrupt.h>
30#include <linux/clk.h>
31#include <linux/workqueue.h>
32#include <linux/sysfs.h>
33#include <linux/kobject.h>
34#include <linux/io.h>
35#include <linux/mutex.h>
36#include <linux/platform_data/exynos_thermal.h>
37#include <linux/thermal.h>
38#include <linux/cpufreq.h>
39#include <linux/cpu_cooling.h>
40#include <linux/of.h>
41
42#include <plat/cpu.h>
43
44/* Exynos generic registers */
45#define EXYNOS_TMU_REG_TRIMINFO 0x0
46#define EXYNOS_TMU_REG_CONTROL 0x20
47#define EXYNOS_TMU_REG_STATUS 0x28
48#define EXYNOS_TMU_REG_CURRENT_TEMP 0x40
49#define EXYNOS_TMU_REG_INTEN 0x70
50#define EXYNOS_TMU_REG_INTSTAT 0x74
51#define EXYNOS_TMU_REG_INTCLEAR 0x78
52
53#define EXYNOS_TMU_TRIM_TEMP_MASK 0xff
54#define EXYNOS_TMU_GAIN_SHIFT 8
55#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
56#define EXYNOS_TMU_CORE_ON 3
57#define EXYNOS_TMU_CORE_OFF 2
58#define EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET 50
59
60/* Exynos4210 specific registers */
61#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP 0x44
62#define EXYNOS4210_TMU_REG_TRIG_LEVEL0 0x50
63#define EXYNOS4210_TMU_REG_TRIG_LEVEL1 0x54
64#define EXYNOS4210_TMU_REG_TRIG_LEVEL2 0x58
65#define EXYNOS4210_TMU_REG_TRIG_LEVEL3 0x5C
66#define EXYNOS4210_TMU_REG_PAST_TEMP0 0x60
67#define EXYNOS4210_TMU_REG_PAST_TEMP1 0x64
68#define EXYNOS4210_TMU_REG_PAST_TEMP2 0x68
69#define EXYNOS4210_TMU_REG_PAST_TEMP3 0x6C
70
71#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK 0x1
72#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK 0x10
73#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK 0x100
74#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK 0x1000
75#define EXYNOS4210_TMU_INTCLEAR_VAL 0x1111
76
77/* Exynos5250 and Exynos4412 specific registers */
78#define EXYNOS_TMU_TRIMINFO_CON 0x14
79#define EXYNOS_THD_TEMP_RISE 0x50
80#define EXYNOS_THD_TEMP_FALL 0x54
81#define EXYNOS_EMUL_CON 0x80
82
83#define EXYNOS_TRIMINFO_RELOAD 0x1
84#define EXYNOS_TMU_CLEAR_RISE_INT 0x111
85#define EXYNOS_TMU_CLEAR_FALL_INT (0x111 << 16)
86#define EXYNOS_MUX_ADDR_VALUE 6
87#define EXYNOS_MUX_ADDR_SHIFT 20
88#define EXYNOS_TMU_TRIP_MODE_SHIFT 13
89
90#define EFUSE_MIN_VALUE 40
91#define EFUSE_MAX_VALUE 100
92
93/* In-kernel thermal framework related macros & definations */
94#define SENSOR_NAME_LEN 16
95#define MAX_TRIP_COUNT 8
96#define MAX_COOLING_DEVICE 4
97
98#define ACTIVE_INTERVAL 500
99#define IDLE_INTERVAL 10000
100#define MCELSIUS 1000
101
102/* CPU Zone information */
103#define PANIC_ZONE 4
104#define WARN_ZONE 3
105#define MONITOR_ZONE 2
106#define SAFE_ZONE 1
107
108#define GET_ZONE(trip) (trip + 2)
109#define GET_TRIP(zone) (zone - 2)
110
111#define EXYNOS_ZONE_COUNT 3
112
113struct exynos_tmu_data {
114 struct exynos_tmu_platform_data *pdata;
115 struct resource *mem;
116 void __iomem *base;
117 int irq;
118 enum soc_type soc;
119 struct work_struct irq_work;
120 struct mutex lock;
121 struct clk *clk;
122 u8 temp_error1, temp_error2;
123};
124
125struct thermal_trip_point_conf {
126 int trip_val[MAX_TRIP_COUNT];
127 int trip_count;
128};
129
130struct thermal_cooling_conf {
131 struct freq_clip_table freq_data[MAX_TRIP_COUNT];
132 int freq_clip_count;
133};
134
135struct thermal_sensor_conf {
136 char name[SENSOR_NAME_LEN];
137 int (*read_temperature)(void *data);
138 struct thermal_trip_point_conf trip_data;
139 struct thermal_cooling_conf cooling_data;
140 void *private_data;
141};
142
143struct exynos_thermal_zone {
144 enum thermal_device_mode mode;
145 struct thermal_zone_device *therm_dev;
146 struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
147 unsigned int cool_dev_size;
148 struct platform_device *exynos4_dev;
149 struct thermal_sensor_conf *sensor_conf;
150 bool bind;
151};
152
153static struct exynos_thermal_zone *th_zone;
154static void exynos_unregister_thermal(void);
155static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
156
157/* Get mode callback functions for thermal zone */
158static int exynos_get_mode(struct thermal_zone_device *thermal,
159 enum thermal_device_mode *mode)
160{
161 if (th_zone)
162 *mode = th_zone->mode;
163 return 0;
164}
165
166/* Set mode callback functions for thermal zone */
167static int exynos_set_mode(struct thermal_zone_device *thermal,
168 enum thermal_device_mode mode)
169{
170 if (!th_zone->therm_dev) {
171 pr_notice("thermal zone not registered\n");
172 return 0;
173 }
174
175 mutex_lock(&th_zone->therm_dev->lock);
176
177 if (mode == THERMAL_DEVICE_ENABLED)
178 th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
179 else
180 th_zone->therm_dev->polling_delay = 0;
181
182 mutex_unlock(&th_zone->therm_dev->lock);
183
184 th_zone->mode = mode;
185 thermal_zone_device_update(th_zone->therm_dev);
186 pr_info("thermal polling set for duration=%d msec\n",
187 th_zone->therm_dev->polling_delay);
188 return 0;
189}
190
191
192/* Get trip type callback functions for thermal zone */
193static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
194 enum thermal_trip_type *type)
195{
196 switch (GET_ZONE(trip)) {
197 case MONITOR_ZONE:
198 case WARN_ZONE:
199 *type = THERMAL_TRIP_ACTIVE;
200 break;
201 case PANIC_ZONE:
202 *type = THERMAL_TRIP_CRITICAL;
203 break;
204 default:
205 return -EINVAL;
206 }
207 return 0;
208}
209
210/* Get trip temperature callback functions for thermal zone */
211static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
212 unsigned long *temp)
213{
214 if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
215 return -EINVAL;
216
217 *temp = th_zone->sensor_conf->trip_data.trip_val[trip];
218 /* convert the temperature into millicelsius */
219 *temp = *temp * MCELSIUS;
220
221 return 0;
222}
223
224/* Get critical temperature callback functions for thermal zone */
225static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
226 unsigned long *temp)
227{
228 int ret;
229 /* Panic zone */
230 ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
231 return ret;
232}
233
234static int exynos_get_frequency_level(unsigned int cpu, unsigned int freq)
235{
236 int i = 0, ret = -EINVAL;
237 struct cpufreq_frequency_table *table = NULL;
238#ifdef CONFIG_CPU_FREQ
239 table = cpufreq_frequency_get_table(cpu);
240#endif
241 if (!table)
242 return ret;
243
244 while (table[i].frequency != CPUFREQ_TABLE_END) {
245 if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
246 continue;
247 if (table[i].frequency == freq)
248 return i;
249 i++;
250 }
251 return ret;
252}
253
254/* Bind callback functions for thermal zone */
255static int exynos_bind(struct thermal_zone_device *thermal,
256 struct thermal_cooling_device *cdev)
257{
258 int ret = 0, i, tab_size, level;
259 struct freq_clip_table *tab_ptr, *clip_data;
260 struct thermal_sensor_conf *data = th_zone->sensor_conf;
261
262 tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
263 tab_size = data->cooling_data.freq_clip_count;
264
265 if (tab_ptr == NULL || tab_size == 0)
266 return -EINVAL;
267
268 /* find the cooling device registered*/
269 for (i = 0; i < th_zone->cool_dev_size; i++)
270 if (cdev == th_zone->cool_dev[i])
271 break;
272
273 /* No matching cooling device */
274 if (i == th_zone->cool_dev_size)
275 return 0;
276
277 /* Bind the thermal zone to the cpufreq cooling device */
278 for (i = 0; i < tab_size; i++) {
279 clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
280 level = exynos_get_frequency_level(0, clip_data->freq_clip_max);
281 if (level < 0)
282 return 0;
283 switch (GET_ZONE(i)) {
284 case MONITOR_ZONE:
285 case WARN_ZONE:
286 if (thermal_zone_bind_cooling_device(thermal, i, cdev,
287 level, level)) {
288 pr_err("error binding cdev inst %d\n", i);
289 ret = -EINVAL;
290 }
291 th_zone->bind = true;
292 break;
293 default:
294 ret = -EINVAL;
295 }
296 }
297
298 return ret;
299}
300
301/* Unbind callback functions for thermal zone */
302static int exynos_unbind(struct thermal_zone_device *thermal,
303 struct thermal_cooling_device *cdev)
304{
305 int ret = 0, i, tab_size;
306 struct thermal_sensor_conf *data = th_zone->sensor_conf;
307
308 if (th_zone->bind == false)
309 return 0;
310
311 tab_size = data->cooling_data.freq_clip_count;
312
313 if (tab_size == 0)
314 return -EINVAL;
315
316 /* find the cooling device registered*/
317 for (i = 0; i < th_zone->cool_dev_size; i++)
318 if (cdev == th_zone->cool_dev[i])
319 break;
320
321 /* No matching cooling device */
322 if (i == th_zone->cool_dev_size)
323 return 0;
324
325 /* Bind the thermal zone to the cpufreq cooling device */
326 for (i = 0; i < tab_size; i++) {
327 switch (GET_ZONE(i)) {
328 case MONITOR_ZONE:
329 case WARN_ZONE:
330 if (thermal_zone_unbind_cooling_device(thermal, i,
331 cdev)) {
332 pr_err("error unbinding cdev inst=%d\n", i);
333 ret = -EINVAL;
334 }
335 th_zone->bind = false;
336 break;
337 default:
338 ret = -EINVAL;
339 }
340 }
341 return ret;
342}
343
344/* Get temperature callback functions for thermal zone */
345static int exynos_get_temp(struct thermal_zone_device *thermal,
346 unsigned long *temp)
347{
348 void *data;
349
350 if (!th_zone->sensor_conf) {
351 pr_info("Temperature sensor not initialised\n");
352 return -EINVAL;
353 }
354 data = th_zone->sensor_conf->private_data;
355 *temp = th_zone->sensor_conf->read_temperature(data);
356 /* convert the temperature into millicelsius */
357 *temp = *temp * MCELSIUS;
358 return 0;
359}
360
361/* Get the temperature trend */
362static int exynos_get_trend(struct thermal_zone_device *thermal,
363 int trip, enum thermal_trend *trend)
364{
365 if (thermal->temperature >= trip)
366 *trend = THERMAL_TREND_RAISING;
367 else
368 *trend = THERMAL_TREND_DROPPING;
369
370 return 0;
371}
372/* Operation callback functions for thermal zone */
373static struct thermal_zone_device_ops const exynos_dev_ops = {
374 .bind = exynos_bind,
375 .unbind = exynos_unbind,
376 .get_temp = exynos_get_temp,
377 .get_trend = exynos_get_trend,
378 .get_mode = exynos_get_mode,
379 .set_mode = exynos_set_mode,
380 .get_trip_type = exynos_get_trip_type,
381 .get_trip_temp = exynos_get_trip_temp,
382 .get_crit_temp = exynos_get_crit_temp,
383};
384
385/*
386 * This function may be called from interrupt based temperature sensor
387 * when threshold is changed.
388 */
389static void exynos_report_trigger(void)
390{
391 unsigned int i;
392 char data[10];
393 char *envp[] = { data, NULL };
394
395 if (!th_zone || !th_zone->therm_dev)
396 return;
397 if (th_zone->bind == false) {
398 for (i = 0; i < th_zone->cool_dev_size; i++) {
399 if (!th_zone->cool_dev[i])
400 continue;
401 exynos_bind(th_zone->therm_dev,
402 th_zone->cool_dev[i]);
403 }
404 }
405
406 thermal_zone_device_update(th_zone->therm_dev);
407
408 mutex_lock(&th_zone->therm_dev->lock);
409 /* Find the level for which trip happened */
410 for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
411 if (th_zone->therm_dev->last_temperature <
412 th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
413 break;
414 }
415
416 if (th_zone->mode == THERMAL_DEVICE_ENABLED) {
417 if (i > 0)
418 th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
419 else
420 th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
421 }
422
423 snprintf(data, sizeof(data), "%u", i);
424 kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
425 mutex_unlock(&th_zone->therm_dev->lock);
426}
427
428/* Register with the in-kernel thermal management */
429static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
430{
431 int ret;
432 struct cpumask mask_val;
433
434 if (!sensor_conf || !sensor_conf->read_temperature) {
435 pr_err("Temperature sensor not initialised\n");
436 return -EINVAL;
437 }
438
439 th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
440 if (!th_zone)
441 return -ENOMEM;
442
443 th_zone->sensor_conf = sensor_conf;
444 cpumask_set_cpu(0, &mask_val);
445 th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
446 if (IS_ERR(th_zone->cool_dev[0])) {
447 pr_err("Failed to register cpufreq cooling device\n");
448 ret = -EINVAL;
449 goto err_unregister;
450 }
451 th_zone->cool_dev_size++;
452
453 th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
454 EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, 0,
455 IDLE_INTERVAL);
456
457 if (IS_ERR(th_zone->therm_dev)) {
458 pr_err("Failed to register thermal zone device\n");
459 ret = -EINVAL;
460 goto err_unregister;
461 }
462 th_zone->mode = THERMAL_DEVICE_ENABLED;
463
464 pr_info("Exynos: Kernel Thermal management registered\n");
465
466 return 0;
467
468err_unregister:
469 exynos_unregister_thermal();
470 return ret;
471}
472
473/* Un-Register with the in-kernel thermal management */
474static void exynos_unregister_thermal(void)
475{
476 int i;
477
478 if (!th_zone)
479 return;
480
481 if (th_zone->therm_dev)
482 thermal_zone_device_unregister(th_zone->therm_dev);
483
484 for (i = 0; i < th_zone->cool_dev_size; i++) {
485 if (th_zone->cool_dev[i])
486 cpufreq_cooling_unregister(th_zone->cool_dev[i]);
487 }
488
489 kfree(th_zone);
490 pr_info("Exynos: Kernel Thermal management unregistered\n");
491}
492
493/*
494 * TMU treats temperature as a mapped temperature code.
495 * The temperature is converted differently depending on the calibration type.
496 */
497static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
498{
499 struct exynos_tmu_platform_data *pdata = data->pdata;
500 int temp_code;
501
502 if (data->soc == SOC_ARCH_EXYNOS4210)
503 /* temp should range between 25 and 125 */
504 if (temp < 25 || temp > 125) {
505 temp_code = -EINVAL;
506 goto out;
507 }
508
509 switch (pdata->cal_type) {
510 case TYPE_TWO_POINT_TRIMMING:
511 temp_code = (temp - 25) *
512 (data->temp_error2 - data->temp_error1) /
513 (85 - 25) + data->temp_error1;
514 break;
515 case TYPE_ONE_POINT_TRIMMING:
516 temp_code = temp + data->temp_error1 - 25;
517 break;
518 default:
519 temp_code = temp + EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
520 break;
521 }
522out:
523 return temp_code;
524}
525
526/*
527 * Calculate a temperature value from a temperature code.
528 * The unit of the temperature is degree Celsius.
529 */
530static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
531{
532 struct exynos_tmu_platform_data *pdata = data->pdata;
533 int temp;
534
535 if (data->soc == SOC_ARCH_EXYNOS4210)
536 /* temp_code should range between 75 and 175 */
537 if (temp_code < 75 || temp_code > 175) {
538 temp = -ENODATA;
539 goto out;
540 }
541
542 switch (pdata->cal_type) {
543 case TYPE_TWO_POINT_TRIMMING:
544 temp = (temp_code - data->temp_error1) * (85 - 25) /
545 (data->temp_error2 - data->temp_error1) + 25;
546 break;
547 case TYPE_ONE_POINT_TRIMMING:
548 temp = temp_code - data->temp_error1 + 25;
549 break;
550 default:
551 temp = temp_code - EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
552 break;
553 }
554out:
555 return temp;
556}
557
558static int exynos_tmu_initialize(struct platform_device *pdev)
559{
560 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
561 struct exynos_tmu_platform_data *pdata = data->pdata;
562 unsigned int status, trim_info, rising_threshold;
563 int ret = 0, threshold_code;
564
565 mutex_lock(&data->lock);
566 clk_enable(data->clk);
567
568 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
569 if (!status) {
570 ret = -EBUSY;
571 goto out;
572 }
573
574 if (data->soc == SOC_ARCH_EXYNOS) {
575 __raw_writel(EXYNOS_TRIMINFO_RELOAD,
576 data->base + EXYNOS_TMU_TRIMINFO_CON);
577 }
578 /* Save trimming info in order to perform calibration */
579 trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
580 data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
581 data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
582
583 if ((EFUSE_MIN_VALUE > data->temp_error1) ||
584 (data->temp_error1 > EFUSE_MAX_VALUE) ||
585 (data->temp_error2 != 0))
586 data->temp_error1 = pdata->efuse_value;
587
588 if (data->soc == SOC_ARCH_EXYNOS4210) {
589 /* Write temperature code for threshold */
590 threshold_code = temp_to_code(data, pdata->threshold);
591 if (threshold_code < 0) {
592 ret = threshold_code;
593 goto out;
594 }
595 writeb(threshold_code,
596 data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
597
598 writeb(pdata->trigger_levels[0],
599 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0);
600 writeb(pdata->trigger_levels[1],
601 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL1);
602 writeb(pdata->trigger_levels[2],
603 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL2);
604 writeb(pdata->trigger_levels[3],
605 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL3);
606
607 writel(EXYNOS4210_TMU_INTCLEAR_VAL,
608 data->base + EXYNOS_TMU_REG_INTCLEAR);
609 } else if (data->soc == SOC_ARCH_EXYNOS) {
610 /* Write temperature code for threshold */
611 threshold_code = temp_to_code(data, pdata->trigger_levels[0]);
612 if (threshold_code < 0) {
613 ret = threshold_code;
614 goto out;
615 }
616 rising_threshold = threshold_code;
617 threshold_code = temp_to_code(data, pdata->trigger_levels[1]);
618 if (threshold_code < 0) {
619 ret = threshold_code;
620 goto out;
621 }
622 rising_threshold |= (threshold_code << 8);
623 threshold_code = temp_to_code(data, pdata->trigger_levels[2]);
624 if (threshold_code < 0) {
625 ret = threshold_code;
626 goto out;
627 }
628 rising_threshold |= (threshold_code << 16);
629
630 writel(rising_threshold,
631 data->base + EXYNOS_THD_TEMP_RISE);
632 writel(0, data->base + EXYNOS_THD_TEMP_FALL);
633
634 writel(EXYNOS_TMU_CLEAR_RISE_INT|EXYNOS_TMU_CLEAR_FALL_INT,
635 data->base + EXYNOS_TMU_REG_INTCLEAR);
636 }
637out:
638 clk_disable(data->clk);
639 mutex_unlock(&data->lock);
640
641 return ret;
642}
643
644static void exynos_tmu_control(struct platform_device *pdev, bool on)
645{
646 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
647 struct exynos_tmu_platform_data *pdata = data->pdata;
648 unsigned int con, interrupt_en;
649
650 mutex_lock(&data->lock);
651 clk_enable(data->clk);
652
653 con = pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT |
654 pdata->gain << EXYNOS_TMU_GAIN_SHIFT;
655
656 if (data->soc == SOC_ARCH_EXYNOS) {
657 con |= pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT;
658 con |= (EXYNOS_MUX_ADDR_VALUE << EXYNOS_MUX_ADDR_SHIFT);
659 }
660
661 if (on) {
662 con |= EXYNOS_TMU_CORE_ON;
663 interrupt_en = pdata->trigger_level3_en << 12 |
664 pdata->trigger_level2_en << 8 |
665 pdata->trigger_level1_en << 4 |
666 pdata->trigger_level0_en;
667 } else {
668 con |= EXYNOS_TMU_CORE_OFF;
669 interrupt_en = 0; /* Disable all interrupts */
670 }
671 writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
672 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
673
674 clk_disable(data->clk);
675 mutex_unlock(&data->lock);
676}
677
678static int exynos_tmu_read(struct exynos_tmu_data *data)
679{
680 u8 temp_code;
681 int temp;
682
683 mutex_lock(&data->lock);
684 clk_enable(data->clk);
685
686 temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
687 temp = code_to_temp(data, temp_code);
688
689 clk_disable(data->clk);
690 mutex_unlock(&data->lock);
691
692 return temp;
693}
694
695static void exynos_tmu_work(struct work_struct *work)
696{
697 struct exynos_tmu_data *data = container_of(work,
698 struct exynos_tmu_data, irq_work);
699
700 mutex_lock(&data->lock);
701 clk_enable(data->clk);
702
703
704 if (data->soc == SOC_ARCH_EXYNOS)
705 writel(EXYNOS_TMU_CLEAR_RISE_INT,
706 data->base + EXYNOS_TMU_REG_INTCLEAR);
707 else
708 writel(EXYNOS4210_TMU_INTCLEAR_VAL,
709 data->base + EXYNOS_TMU_REG_INTCLEAR);
710
711 clk_disable(data->clk);
712 mutex_unlock(&data->lock);
713 exynos_report_trigger();
714 enable_irq(data->irq);
715}
716
717static irqreturn_t exynos_tmu_irq(int irq, void *id)
718{
719 struct exynos_tmu_data *data = id;
720
721 disable_irq_nosync(irq);
722 schedule_work(&data->irq_work);
723
724 return IRQ_HANDLED;
725}
726static struct thermal_sensor_conf exynos_sensor_conf = {
727 .name = "exynos-therm",
728 .read_temperature = (int (*)(void *))exynos_tmu_read,
729};
730
731#if defined(CONFIG_CPU_EXYNOS4210)
732static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
733 .threshold = 80,
734 .trigger_levels[0] = 5,
735 .trigger_levels[1] = 20,
736 .trigger_levels[2] = 30,
737 .trigger_level0_en = 1,
738 .trigger_level1_en = 1,
739 .trigger_level2_en = 1,
740 .trigger_level3_en = 0,
741 .gain = 15,
742 .reference_voltage = 7,
743 .cal_type = TYPE_ONE_POINT_TRIMMING,
744 .freq_tab[0] = {
745 .freq_clip_max = 800 * 1000,
746 .temp_level = 85,
747 },
748 .freq_tab[1] = {
749 .freq_clip_max = 200 * 1000,
750 .temp_level = 100,
751 },
752 .freq_tab_count = 2,
753 .type = SOC_ARCH_EXYNOS4210,
754};
755#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
756#else
757#define EXYNOS4210_TMU_DRV_DATA (NULL)
758#endif
759
760#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
761static struct exynos_tmu_platform_data const exynos_default_tmu_data = {
762 .trigger_levels[0] = 85,
763 .trigger_levels[1] = 103,
764 .trigger_levels[2] = 110,
765 .trigger_level0_en = 1,
766 .trigger_level1_en = 1,
767 .trigger_level2_en = 1,
768 .trigger_level3_en = 0,
769 .gain = 8,
770 .reference_voltage = 16,
771 .noise_cancel_mode = 4,
772 .cal_type = TYPE_ONE_POINT_TRIMMING,
773 .efuse_value = 55,
774 .freq_tab[0] = {
775 .freq_clip_max = 800 * 1000,
776 .temp_level = 85,
777 },
778 .freq_tab[1] = {
779 .freq_clip_max = 200 * 1000,
780 .temp_level = 103,
781 },
782 .freq_tab_count = 2,
783 .type = SOC_ARCH_EXYNOS,
784};
785#define EXYNOS_TMU_DRV_DATA (&exynos_default_tmu_data)
786#else
787#define EXYNOS_TMU_DRV_DATA (NULL)
788#endif
789
790#ifdef CONFIG_OF
791static const struct of_device_id exynos_tmu_match[] = {
792 {
793 .compatible = "samsung,exynos4210-tmu",
794 .data = (void *)EXYNOS4210_TMU_DRV_DATA,
795 },
796 {
797 .compatible = "samsung,exynos5250-tmu",
798 .data = (void *)EXYNOS_TMU_DRV_DATA,
799 },
800 {},
801};
802MODULE_DEVICE_TABLE(of, exynos_tmu_match);
803#else
804#define exynos_tmu_match NULL
805#endif
806
807static struct platform_device_id exynos_tmu_driver_ids[] = {
808 {
809 .name = "exynos4210-tmu",
810 .driver_data = (kernel_ulong_t)EXYNOS4210_TMU_DRV_DATA,
811 },
812 {
813 .name = "exynos5250-tmu",
814 .driver_data = (kernel_ulong_t)EXYNOS_TMU_DRV_DATA,
815 },
816 { },
817};
818MODULE_DEVICE_TABLE(platform, exynos4_tmu_driver_ids);
819
820static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
821 struct platform_device *pdev)
822{
823#ifdef CONFIG_OF
824 if (pdev->dev.of_node) {
825 const struct of_device_id *match;
826 match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
827 if (!match)
828 return NULL;
829 return (struct exynos_tmu_platform_data *) match->data;
830 }
831#endif
832 return (struct exynos_tmu_platform_data *)
833 platform_get_device_id(pdev)->driver_data;
834}
835static int __devinit exynos_tmu_probe(struct platform_device *pdev)
836{
837 struct exynos_tmu_data *data;
838 struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
839 int ret, i;
840
841 if (!pdata)
842 pdata = exynos_get_driver_data(pdev);
843
844 if (!pdata) {
845 dev_err(&pdev->dev, "No platform init data supplied.\n");
846 return -ENODEV;
847 }
848 data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
849 GFP_KERNEL);
850 if (!data) {
851 dev_err(&pdev->dev, "Failed to allocate driver structure\n");
852 return -ENOMEM;
853 }
854
855 data->irq = platform_get_irq(pdev, 0);
856 if (data->irq < 0) {
857 dev_err(&pdev->dev, "Failed to get platform irq\n");
858 return data->irq;
859 }
860
861 INIT_WORK(&data->irq_work, exynos_tmu_work);
862
863 data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
864 if (!data->mem) {
865 dev_err(&pdev->dev, "Failed to get platform resource\n");
866 return -ENOENT;
867 }
868
869 data->base = devm_request_and_ioremap(&pdev->dev, data->mem);
870 if (!data->base) {
871 dev_err(&pdev->dev, "Failed to ioremap memory\n");
872 return -ENODEV;
873 }
874
875 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
876 IRQF_TRIGGER_RISING, "exynos-tmu", data);
877 if (ret) {
878 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
879 return ret;
880 }
881
882 data->clk = clk_get(NULL, "tmu_apbif");
883 if (IS_ERR(data->clk)) {
884 dev_err(&pdev->dev, "Failed to get clock\n");
885 return PTR_ERR(data->clk);
886 }
887
888 if (pdata->type == SOC_ARCH_EXYNOS ||
889 pdata->type == SOC_ARCH_EXYNOS4210)
890 data->soc = pdata->type;
891 else {
892 ret = -EINVAL;
893 dev_err(&pdev->dev, "Platform not supported\n");
894 goto err_clk;
895 }
896
897 data->pdata = pdata;
898 platform_set_drvdata(pdev, data);
899 mutex_init(&data->lock);
900
901 ret = exynos_tmu_initialize(pdev);
902 if (ret) {
903 dev_err(&pdev->dev, "Failed to initialize TMU\n");
904 goto err_clk;
905 }
906
907 exynos_tmu_control(pdev, true);
908
909 /* Register the sensor with thermal management interface */
910 (&exynos_sensor_conf)->private_data = data;
911 exynos_sensor_conf.trip_data.trip_count = pdata->trigger_level0_en +
912 pdata->trigger_level1_en + pdata->trigger_level2_en +
913 pdata->trigger_level3_en;
914
915 for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
916 exynos_sensor_conf.trip_data.trip_val[i] =
917 pdata->threshold + pdata->trigger_levels[i];
918
919 exynos_sensor_conf.cooling_data.freq_clip_count =
920 pdata->freq_tab_count;
921 for (i = 0; i < pdata->freq_tab_count; i++) {
922 exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
923 pdata->freq_tab[i].freq_clip_max;
924 exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
925 pdata->freq_tab[i].temp_level;
926 }
927
928 ret = exynos_register_thermal(&exynos_sensor_conf);
929 if (ret) {
930 dev_err(&pdev->dev, "Failed to register thermal interface\n");
931 goto err_clk;
932 }
933 return 0;
934err_clk:
935 platform_set_drvdata(pdev, NULL);
936 clk_put(data->clk);
937 return ret;
938}
939
940static int __devexit exynos_tmu_remove(struct platform_device *pdev)
941{
942 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
943
944 exynos_tmu_control(pdev, false);
945
946 exynos_unregister_thermal();
947
948 clk_put(data->clk);
949
950 platform_set_drvdata(pdev, NULL);
951
952 return 0;
953}
954
955#ifdef CONFIG_PM_SLEEP
956static int exynos_tmu_suspend(struct device *dev)
957{
958 exynos_tmu_control(to_platform_device(dev), false);
959
960 return 0;
961}
962
963static int exynos_tmu_resume(struct device *dev)
964{
965 struct platform_device *pdev = to_platform_device(dev);
966
967 exynos_tmu_initialize(pdev);
968 exynos_tmu_control(pdev, true);
969
970 return 0;
971}
972
973static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
974 exynos_tmu_suspend, exynos_tmu_resume);
975#define EXYNOS_TMU_PM (&exynos_tmu_pm)
976#else
977#define EXYNOS_TMU_PM NULL
978#endif
979
980static struct platform_driver exynos_tmu_driver = {
981 .driver = {
982 .name = "exynos-tmu",
983 .owner = THIS_MODULE,
984 .pm = EXYNOS_TMU_PM,
985 .of_match_table = exynos_tmu_match,
986 },
987 .probe = exynos_tmu_probe,
988 .remove = __devexit_p(exynos_tmu_remove),
989 .id_table = exynos_tmu_driver_ids,
990};
991
992module_platform_driver(exynos_tmu_driver);
993
994MODULE_DESCRIPTION("EXYNOS TMU Driver");
995MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
996MODULE_LICENSE("GPL");
997MODULE_ALIAS("platform:exynos-tmu");
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
new file mode 100644
index 000000000000..d4452716aaab
--- /dev/null
+++ b/drivers/thermal/rcar_thermal.c
@@ -0,0 +1,260 @@
1/*
2 * R-Car THS/TSC thermal sensor driver
3 *
4 * Copyright (C) 2012 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 */
20#include <linux/delay.h>
21#include <linux/err.h>
22#include <linux/io.h>
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/slab.h>
26#include <linux/spinlock.h>
27#include <linux/thermal.h>
28
29#define THSCR 0x2c
30#define THSSR 0x30
31
32/* THSCR */
33#define CPTAP 0xf
34
35/* THSSR */
36#define CTEMP 0x3f
37
38
39struct rcar_thermal_priv {
40 void __iomem *base;
41 struct device *dev;
42 spinlock_t lock;
43 u32 comp;
44};
45
46/*
47 * basic functions
48 */
49static u32 rcar_thermal_read(struct rcar_thermal_priv *priv, u32 reg)
50{
51 unsigned long flags;
52 u32 ret;
53
54 spin_lock_irqsave(&priv->lock, flags);
55
56 ret = ioread32(priv->base + reg);
57
58 spin_unlock_irqrestore(&priv->lock, flags);
59
60 return ret;
61}
62
63#if 0 /* no user at this point */
64static void rcar_thermal_write(struct rcar_thermal_priv *priv,
65 u32 reg, u32 data)
66{
67 unsigned long flags;
68
69 spin_lock_irqsave(&priv->lock, flags);
70
71 iowrite32(data, priv->base + reg);
72
73 spin_unlock_irqrestore(&priv->lock, flags);
74}
75#endif
76
77static void rcar_thermal_bset(struct rcar_thermal_priv *priv, u32 reg,
78 u32 mask, u32 data)
79{
80 unsigned long flags;
81 u32 val;
82
83 spin_lock_irqsave(&priv->lock, flags);
84
85 val = ioread32(priv->base + reg);
86 val &= ~mask;
87 val |= (data & mask);
88 iowrite32(val, priv->base + reg);
89
90 spin_unlock_irqrestore(&priv->lock, flags);
91}
92
93/*
94 * zone device functions
95 */
96static int rcar_thermal_get_temp(struct thermal_zone_device *zone,
97 unsigned long *temp)
98{
99 struct rcar_thermal_priv *priv = zone->devdata;
100 int val, min, max, tmp;
101
102 tmp = -200; /* default */
103 while (1) {
104 if (priv->comp < 1 || priv->comp > 12) {
105 dev_err(priv->dev,
106 "THSSR invalid data (%d)\n", priv->comp);
107 priv->comp = 4; /* for next thermal */
108 return -EINVAL;
109 }
110
111 /*
112 * THS comparator offset and the reference temperature
113 *
114 * Comparator | reference | Temperature field
115 * offset | temperature | measurement
116 * | (degrees C) | (degrees C)
117 * -------------+---------------+-------------------
118 * 1 | -45 | -45 to -30
119 * 2 | -30 | -30 to -15
120 * 3 | -15 | -15 to 0
121 * 4 | 0 | 0 to +15
122 * 5 | +15 | +15 to +30
123 * 6 | +30 | +30 to +45
124 * 7 | +45 | +45 to +60
125 * 8 | +60 | +60 to +75
126 * 9 | +75 | +75 to +90
127 * 10 | +90 | +90 to +105
128 * 11 | +105 | +105 to +120
129 * 12 | +120 | +120 to +135
130 */
131
132 /* calculate thermal limitation */
133 min = (priv->comp * 15) - 60;
134 max = min + 15;
135
136 /*
137 * we need to wait 300us after changing comparator offset
138 * to get stable temperature.
139 * see "Usage Notes" on datasheet
140 */
141 rcar_thermal_bset(priv, THSCR, CPTAP, priv->comp);
142 udelay(300);
143
144 /* calculate current temperature */
145 val = rcar_thermal_read(priv, THSSR) & CTEMP;
146 val = (val * 5) - 65;
147
148 dev_dbg(priv->dev, "comp/min/max/val = %d/%d/%d/%d\n",
149 priv->comp, min, max, val);
150
151 /*
152 * If val is same as min/max, then,
153 * it should try again on next comparator.
154 * But the val might be correct temperature.
155 * Keep it on "tmp" and compare with next val.
156 */
157 if (tmp == val)
158 break;
159
160 if (val <= min) {
161 tmp = min;
162 priv->comp--; /* try again */
163 } else if (val >= max) {
164 tmp = max;
165 priv->comp++; /* try again */
166 } else {
167 tmp = val;
168 break;
169 }
170 }
171
172 *temp = tmp;
173 return 0;
174}
175
176static struct thermal_zone_device_ops rcar_thermal_zone_ops = {
177 .get_temp = rcar_thermal_get_temp,
178};
179
180/*
181 * platform functions
182 */
183static int rcar_thermal_probe(struct platform_device *pdev)
184{
185 struct thermal_zone_device *zone;
186 struct rcar_thermal_priv *priv;
187 struct resource *res;
188 int ret;
189
190 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
191 if (!res) {
192 dev_err(&pdev->dev, "Could not get platform resource\n");
193 return -ENODEV;
194 }
195
196 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
197 if (!priv) {
198 dev_err(&pdev->dev, "Could not allocate priv\n");
199 return -ENOMEM;
200 }
201
202 priv->comp = 4; /* basic setup */
203 priv->dev = &pdev->dev;
204 spin_lock_init(&priv->lock);
205 priv->base = devm_ioremap_nocache(&pdev->dev,
206 res->start, resource_size(res));
207 if (!priv->base) {
208 dev_err(&pdev->dev, "Unable to ioremap thermal register\n");
209 ret = -ENOMEM;
210 goto error_free_priv;
211 }
212
213 zone = thermal_zone_device_register("rcar_thermal", 0, priv,
214 &rcar_thermal_zone_ops, 0, 0);
215 if (IS_ERR(zone)) {
216 dev_err(&pdev->dev, "thermal zone device is NULL\n");
217 ret = PTR_ERR(zone);
218 goto error_iounmap;
219 }
220
221 platform_set_drvdata(pdev, zone);
222
223 dev_info(&pdev->dev, "proved\n");
224
225 return 0;
226
227error_iounmap:
228 devm_iounmap(&pdev->dev, priv->base);
229error_free_priv:
230 devm_kfree(&pdev->dev, priv);
231
232 return ret;
233}
234
235static int rcar_thermal_remove(struct platform_device *pdev)
236{
237 struct thermal_zone_device *zone = platform_get_drvdata(pdev);
238 struct rcar_thermal_priv *priv = zone->devdata;
239
240 thermal_zone_device_unregister(zone);
241 platform_set_drvdata(pdev, NULL);
242
243 devm_iounmap(&pdev->dev, priv->base);
244 devm_kfree(&pdev->dev, priv);
245
246 return 0;
247}
248
249static struct platform_driver rcar_thermal_driver = {
250 .driver = {
251 .name = "rcar_thermal",
252 },
253 .probe = rcar_thermal_probe,
254 .remove = rcar_thermal_remove,
255};
256module_platform_driver(rcar_thermal_driver);
257
258MODULE_LICENSE("GPL");
259MODULE_DESCRIPTION("R-Car THS/TSC thermal sensor driver");
260MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
index 5f8ee39f2000..9bc969261d01 100644
--- a/drivers/thermal/spear_thermal.c
+++ b/drivers/thermal/spear_thermal.c
@@ -147,7 +147,7 @@ static int spear_thermal_probe(struct platform_device *pdev)
147 writel_relaxed(stdev->flags, stdev->thermal_base); 147 writel_relaxed(stdev->flags, stdev->thermal_base);
148 148
149 spear_thermal = thermal_zone_device_register("spear_thermal", 0, 0, 149 spear_thermal = thermal_zone_device_register("spear_thermal", 0, 0,
150 stdev, &ops, 0, 0, 0, 0); 150 stdev, &ops, 0, 0);
151 if (IS_ERR(spear_thermal)) { 151 if (IS_ERR(spear_thermal)) {
152 dev_err(&pdev->dev, "thermal zone device is NULL\n"); 152 dev_err(&pdev->dev, "thermal zone device is NULL\n");
153 ret = PTR_ERR(spear_thermal); 153 ret = PTR_ERR(spear_thermal);
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index efd81bb25e01..9ee42ca4d289 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -41,15 +41,25 @@ MODULE_AUTHOR("Zhang Rui");
41MODULE_DESCRIPTION("Generic thermal management sysfs support"); 41MODULE_DESCRIPTION("Generic thermal management sysfs support");
42MODULE_LICENSE("GPL"); 42MODULE_LICENSE("GPL");
43 43
44struct thermal_cooling_device_instance { 44#define THERMAL_NO_TARGET -1UL
45/*
46 * This structure is used to describe the behavior of
47 * a certain cooling device on a certain trip point
48 * in a certain thermal zone
49 */
50struct thermal_instance {
45 int id; 51 int id;
46 char name[THERMAL_NAME_LENGTH]; 52 char name[THERMAL_NAME_LENGTH];
47 struct thermal_zone_device *tz; 53 struct thermal_zone_device *tz;
48 struct thermal_cooling_device *cdev; 54 struct thermal_cooling_device *cdev;
49 int trip; 55 int trip;
56 unsigned long upper; /* Highest cooling state for this trip point */
57 unsigned long lower; /* Lowest cooling state for this trip point */
58 unsigned long target; /* expected cooling state */
50 char attr_name[THERMAL_NAME_LENGTH]; 59 char attr_name[THERMAL_NAME_LENGTH];
51 struct device_attribute attr; 60 struct device_attribute attr;
52 struct list_head node; 61 struct list_head tz_node; /* node in tz->thermal_instances */
62 struct list_head cdev_node; /* node in cdev->thermal_instances */
53}; 63};
54 64
55static DEFINE_IDR(thermal_tz_idr); 65static DEFINE_IDR(thermal_tz_idr);
@@ -308,8 +318,9 @@ passive_store(struct device *dev, struct device_attribute *attr,
308 if (!strncmp("Processor", cdev->type, 318 if (!strncmp("Processor", cdev->type,
309 sizeof("Processor"))) 319 sizeof("Processor")))
310 thermal_zone_bind_cooling_device(tz, 320 thermal_zone_bind_cooling_device(tz,
311 THERMAL_TRIPS_NONE, 321 THERMAL_TRIPS_NONE, cdev,
312 cdev); 322 THERMAL_NO_LIMIT,
323 THERMAL_NO_LIMIT);
313 } 324 }
314 mutex_unlock(&thermal_list_lock); 325 mutex_unlock(&thermal_list_lock);
315 if (!tz->passive_delay) 326 if (!tz->passive_delay)
@@ -327,9 +338,6 @@ passive_store(struct device *dev, struct device_attribute *attr,
327 tz->passive_delay = 0; 338 tz->passive_delay = 0;
328 } 339 }
329 340
330 tz->tc1 = 1;
331 tz->tc2 = 1;
332
333 tz->forced_passive = state; 341 tz->forced_passive = state;
334 342
335 thermal_zone_device_update(tz); 343 thermal_zone_device_update(tz);
@@ -425,10 +433,10 @@ static ssize_t
425thermal_cooling_device_trip_point_show(struct device *dev, 433thermal_cooling_device_trip_point_show(struct device *dev,
426 struct device_attribute *attr, char *buf) 434 struct device_attribute *attr, char *buf)
427{ 435{
428 struct thermal_cooling_device_instance *instance; 436 struct thermal_instance *instance;
429 437
430 instance = 438 instance =
431 container_of(attr, struct thermal_cooling_device_instance, attr); 439 container_of(attr, struct thermal_instance, attr);
432 440
433 if (instance->trip == THERMAL_TRIPS_NONE) 441 if (instance->trip == THERMAL_TRIPS_NONE)
434 return sprintf(buf, "-1\n"); 442 return sprintf(buf, "-1\n");
@@ -590,7 +598,7 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
590 temp->tz = tz; 598 temp->tz = tz;
591 hwmon->count++; 599 hwmon->count++;
592 600
593 snprintf(temp->temp_input.name, THERMAL_NAME_LENGTH, 601 snprintf(temp->temp_input.name, sizeof(temp->temp_input.name),
594 "temp%d_input", hwmon->count); 602 "temp%d_input", hwmon->count);
595 temp->temp_input.attr.attr.name = temp->temp_input.name; 603 temp->temp_input.attr.attr.name = temp->temp_input.name;
596 temp->temp_input.attr.attr.mode = 0444; 604 temp->temp_input.attr.attr.mode = 0444;
@@ -603,7 +611,8 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
603 if (tz->ops->get_crit_temp) { 611 if (tz->ops->get_crit_temp) {
604 unsigned long temperature; 612 unsigned long temperature;
605 if (!tz->ops->get_crit_temp(tz, &temperature)) { 613 if (!tz->ops->get_crit_temp(tz, &temperature)) {
606 snprintf(temp->temp_crit.name, THERMAL_NAME_LENGTH, 614 snprintf(temp->temp_crit.name,
615 sizeof(temp->temp_crit.name),
607 "temp%d_crit", hwmon->count); 616 "temp%d_crit", hwmon->count);
608 temp->temp_crit.attr.attr.name = temp->temp_crit.name; 617 temp->temp_crit.attr.attr.name = temp->temp_crit.name;
609 temp->temp_crit.attr.attr.mode = 0444; 618 temp->temp_crit.attr.attr.mode = 0444;
@@ -704,74 +713,6 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
704 cancel_delayed_work(&tz->poll_queue); 713 cancel_delayed_work(&tz->poll_queue);
705} 714}
706 715
707static void thermal_zone_device_passive(struct thermal_zone_device *tz,
708 int temp, int trip_temp, int trip)
709{
710 int trend = 0;
711 struct thermal_cooling_device_instance *instance;
712 struct thermal_cooling_device *cdev;
713 long state, max_state;
714
715 /*
716 * Above Trip?
717 * -----------
718 * Calculate the thermal trend (using the passive cooling equation)
719 * and modify the performance limit for all passive cooling devices
720 * accordingly. Note that we assume symmetry.
721 */
722 if (temp >= trip_temp) {
723 tz->passive = true;
724
725 trend = (tz->tc1 * (temp - tz->last_temperature)) +
726 (tz->tc2 * (temp - trip_temp));
727
728 /* Heating up? */
729 if (trend > 0) {
730 list_for_each_entry(instance, &tz->cooling_devices,
731 node) {
732 if (instance->trip != trip)
733 continue;
734 cdev = instance->cdev;
735 cdev->ops->get_cur_state(cdev, &state);
736 cdev->ops->get_max_state(cdev, &max_state);
737 if (state++ < max_state)
738 cdev->ops->set_cur_state(cdev, state);
739 }
740 } else if (trend < 0) { /* Cooling off? */
741 list_for_each_entry(instance, &tz->cooling_devices,
742 node) {
743 if (instance->trip != trip)
744 continue;
745 cdev = instance->cdev;
746 cdev->ops->get_cur_state(cdev, &state);
747 cdev->ops->get_max_state(cdev, &max_state);
748 if (state > 0)
749 cdev->ops->set_cur_state(cdev, --state);
750 }
751 }
752 return;
753 }
754
755 /*
756 * Below Trip?
757 * -----------
758 * Implement passive cooling hysteresis to slowly increase performance
759 * and avoid thrashing around the passive trip point. Note that we
760 * assume symmetry.
761 */
762 list_for_each_entry(instance, &tz->cooling_devices, node) {
763 if (instance->trip != trip)
764 continue;
765 cdev = instance->cdev;
766 cdev->ops->get_cur_state(cdev, &state);
767 cdev->ops->get_max_state(cdev, &max_state);
768 if (state > 0)
769 cdev->ops->set_cur_state(cdev, --state);
770 if (state == 0)
771 tz->passive = false;
772 }
773}
774
775static void thermal_zone_device_check(struct work_struct *work) 716static void thermal_zone_device_check(struct work_struct *work)
776{ 717{
777 struct thermal_zone_device *tz = container_of(work, struct 718 struct thermal_zone_device *tz = container_of(work, struct
@@ -791,12 +732,14 @@ static void thermal_zone_device_check(struct work_struct *work)
791 */ 732 */
792int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, 733int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
793 int trip, 734 int trip,
794 struct thermal_cooling_device *cdev) 735 struct thermal_cooling_device *cdev,
736 unsigned long upper, unsigned long lower)
795{ 737{
796 struct thermal_cooling_device_instance *dev; 738 struct thermal_instance *dev;
797 struct thermal_cooling_device_instance *pos; 739 struct thermal_instance *pos;
798 struct thermal_zone_device *pos1; 740 struct thermal_zone_device *pos1;
799 struct thermal_cooling_device *pos2; 741 struct thermal_cooling_device *pos2;
742 unsigned long max_state;
800 int result; 743 int result;
801 744
802 if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE)) 745 if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE))
@@ -814,13 +757,26 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
814 if (tz != pos1 || cdev != pos2) 757 if (tz != pos1 || cdev != pos2)
815 return -EINVAL; 758 return -EINVAL;
816 759
760 cdev->ops->get_max_state(cdev, &max_state);
761
762 /* lower default 0, upper default max_state */
763 lower = lower == THERMAL_NO_LIMIT ? 0 : lower;
764 upper = upper == THERMAL_NO_LIMIT ? max_state : upper;
765
766 if (lower > upper || upper > max_state)
767 return -EINVAL;
768
817 dev = 769 dev =
818 kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL); 770 kzalloc(sizeof(struct thermal_instance), GFP_KERNEL);
819 if (!dev) 771 if (!dev)
820 return -ENOMEM; 772 return -ENOMEM;
821 dev->tz = tz; 773 dev->tz = tz;
822 dev->cdev = cdev; 774 dev->cdev = cdev;
823 dev->trip = trip; 775 dev->trip = trip;
776 dev->upper = upper;
777 dev->lower = lower;
778 dev->target = THERMAL_NO_TARGET;
779
824 result = get_idr(&tz->idr, &tz->lock, &dev->id); 780 result = get_idr(&tz->idr, &tz->lock, &dev->id);
825 if (result) 781 if (result)
826 goto free_mem; 782 goto free_mem;
@@ -841,13 +797,17 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
841 goto remove_symbol_link; 797 goto remove_symbol_link;
842 798
843 mutex_lock(&tz->lock); 799 mutex_lock(&tz->lock);
844 list_for_each_entry(pos, &tz->cooling_devices, node) 800 mutex_lock(&cdev->lock);
801 list_for_each_entry(pos, &tz->thermal_instances, tz_node)
845 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { 802 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
846 result = -EEXIST; 803 result = -EEXIST;
847 break; 804 break;
848 } 805 }
849 if (!result) 806 if (!result) {
850 list_add_tail(&dev->node, &tz->cooling_devices); 807 list_add_tail(&dev->tz_node, &tz->thermal_instances);
808 list_add_tail(&dev->cdev_node, &cdev->thermal_instances);
809 }
810 mutex_unlock(&cdev->lock);
851 mutex_unlock(&tz->lock); 811 mutex_unlock(&tz->lock);
852 812
853 if (!result) 813 if (!result)
@@ -877,16 +837,20 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
877 int trip, 837 int trip,
878 struct thermal_cooling_device *cdev) 838 struct thermal_cooling_device *cdev)
879{ 839{
880 struct thermal_cooling_device_instance *pos, *next; 840 struct thermal_instance *pos, *next;
881 841
882 mutex_lock(&tz->lock); 842 mutex_lock(&tz->lock);
883 list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) { 843 mutex_lock(&cdev->lock);
844 list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) {
884 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { 845 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
885 list_del(&pos->node); 846 list_del(&pos->tz_node);
847 list_del(&pos->cdev_node);
848 mutex_unlock(&cdev->lock);
886 mutex_unlock(&tz->lock); 849 mutex_unlock(&tz->lock);
887 goto unbind; 850 goto unbind;
888 } 851 }
889 } 852 }
853 mutex_unlock(&cdev->lock);
890 mutex_unlock(&tz->lock); 854 mutex_unlock(&tz->lock);
891 855
892 return -ENODEV; 856 return -ENODEV;
@@ -934,7 +898,7 @@ thermal_cooling_device_register(char *type, void *devdata,
934 struct thermal_zone_device *pos; 898 struct thermal_zone_device *pos;
935 int result; 899 int result;
936 900
937 if (strlen(type) >= THERMAL_NAME_LENGTH) 901 if (type && strlen(type) >= THERMAL_NAME_LENGTH)
938 return ERR_PTR(-EINVAL); 902 return ERR_PTR(-EINVAL);
939 903
940 if (!ops || !ops->get_max_state || !ops->get_cur_state || 904 if (!ops || !ops->get_max_state || !ops->get_cur_state ||
@@ -951,8 +915,11 @@ thermal_cooling_device_register(char *type, void *devdata,
951 return ERR_PTR(result); 915 return ERR_PTR(result);
952 } 916 }
953 917
954 strcpy(cdev->type, type); 918 strcpy(cdev->type, type ? : "");
919 mutex_init(&cdev->lock);
920 INIT_LIST_HEAD(&cdev->thermal_instances);
955 cdev->ops = ops; 921 cdev->ops = ops;
922 cdev->updated = true;
956 cdev->device.class = &thermal_class; 923 cdev->device.class = &thermal_class;
957 cdev->devdata = devdata; 924 cdev->devdata = devdata;
958 dev_set_name(&cdev->device, "cooling_device%d", cdev->id); 925 dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
@@ -1044,6 +1011,136 @@ void thermal_cooling_device_unregister(struct
1044} 1011}
1045EXPORT_SYMBOL(thermal_cooling_device_unregister); 1012EXPORT_SYMBOL(thermal_cooling_device_unregister);
1046 1013
1014static void thermal_cdev_do_update(struct thermal_cooling_device *cdev)
1015{
1016 struct thermal_instance *instance;
1017 unsigned long target = 0;
1018
1019 /* cooling device is updated*/
1020 if (cdev->updated)
1021 return;
1022
1023 mutex_lock(&cdev->lock);
1024 /* Make sure cdev enters the deepest cooling state */
1025 list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
1026 if (instance->target == THERMAL_NO_TARGET)
1027 continue;
1028 if (instance->target > target)
1029 target = instance->target;
1030 }
1031 mutex_unlock(&cdev->lock);
1032 cdev->ops->set_cur_state(cdev, target);
1033 cdev->updated = true;
1034}
1035
1036static void thermal_zone_do_update(struct thermal_zone_device *tz)
1037{
1038 struct thermal_instance *instance;
1039
1040 list_for_each_entry(instance, &tz->thermal_instances, tz_node)
1041 thermal_cdev_do_update(instance->cdev);
1042}
1043
1044/*
1045 * Cooling algorithm for both active and passive cooling
1046 *
1047 * 1. if the temperature is higher than a trip point,
1048 * a. if the trend is THERMAL_TREND_RAISING, use higher cooling
1049 * state for this trip point
1050 * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
1051 * state for this trip point
1052 *
1053 * 2. if the temperature is lower than a trip point, use lower
1054 * cooling state for this trip point
1055 *
1056 * Note that this behaves the same as the previous passive cooling
1057 * algorithm.
1058 */
1059
1060static void thermal_zone_trip_update(struct thermal_zone_device *tz,
1061 int trip, long temp)
1062{
1063 struct thermal_instance *instance;
1064 struct thermal_cooling_device *cdev = NULL;
1065 unsigned long cur_state, max_state;
1066 long trip_temp;
1067 enum thermal_trip_type trip_type;
1068 enum thermal_trend trend;
1069
1070 if (trip == THERMAL_TRIPS_NONE) {
1071 trip_temp = tz->forced_passive;
1072 trip_type = THERMAL_TRIPS_NONE;
1073 } else {
1074 tz->ops->get_trip_temp(tz, trip, &trip_temp);
1075 tz->ops->get_trip_type(tz, trip, &trip_type);
1076 }
1077
1078 if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
1079 /*
1080 * compare the current temperature and previous temperature
1081 * to get the thermal trend, if no special requirement
1082 */
1083 if (tz->temperature > tz->last_temperature)
1084 trend = THERMAL_TREND_RAISING;
1085 else if (tz->temperature < tz->last_temperature)
1086 trend = THERMAL_TREND_DROPPING;
1087 else
1088 trend = THERMAL_TREND_STABLE;
1089 }
1090
1091 if (temp >= trip_temp) {
1092 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
1093 if (instance->trip != trip)
1094 continue;
1095
1096 cdev = instance->cdev;
1097
1098 cdev->ops->get_cur_state(cdev, &cur_state);
1099 cdev->ops->get_max_state(cdev, &max_state);
1100
1101 if (trend == THERMAL_TREND_RAISING) {
1102 cur_state = cur_state < instance->upper ?
1103 (cur_state + 1) : instance->upper;
1104 } else if (trend == THERMAL_TREND_DROPPING) {
1105 cur_state = cur_state > instance->lower ?
1106 (cur_state - 1) : instance->lower;
1107 }
1108
1109 /* activate a passive thermal instance */
1110 if ((trip_type == THERMAL_TRIP_PASSIVE ||
1111 trip_type == THERMAL_TRIPS_NONE) &&
1112 instance->target == THERMAL_NO_TARGET)
1113 tz->passive++;
1114
1115 instance->target = cur_state;
1116 cdev->updated = false; /* cooling device needs update */
1117 }
1118 } else { /* below trip */
1119 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
1120 if (instance->trip != trip)
1121 continue;
1122
1123 /* Do not use the inactive thermal instance */
1124 if (instance->target == THERMAL_NO_TARGET)
1125 continue;
1126 cdev = instance->cdev;
1127 cdev->ops->get_cur_state(cdev, &cur_state);
1128
1129 cur_state = cur_state > instance->lower ?
1130 (cur_state - 1) : THERMAL_NO_TARGET;
1131
1132 /* deactivate a passive thermal instance */
1133 if ((trip_type == THERMAL_TRIP_PASSIVE ||
1134 trip_type == THERMAL_TRIPS_NONE) &&
1135 cur_state == THERMAL_NO_TARGET)
1136 tz->passive--;
1137 instance->target = cur_state;
1138 cdev->updated = false; /* cooling device needs update */
1139 }
1140 }
1141
1142 return;
1143}
1047/** 1144/**
1048 * thermal_zone_device_update - force an update of a thermal zone's state 1145 * thermal_zone_device_update - force an update of a thermal zone's state
1049 * @ttz: the thermal zone to update 1146 * @ttz: the thermal zone to update
@@ -1054,8 +1151,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
1054 int count, ret = 0; 1151 int count, ret = 0;
1055 long temp, trip_temp; 1152 long temp, trip_temp;
1056 enum thermal_trip_type trip_type; 1153 enum thermal_trip_type trip_type;
1057 struct thermal_cooling_device_instance *instance;
1058 struct thermal_cooling_device *cdev;
1059 1154
1060 mutex_lock(&tz->lock); 1155 mutex_lock(&tz->lock);
1061 1156
@@ -1065,6 +1160,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
1065 goto leave; 1160 goto leave;
1066 } 1161 }
1067 1162
1163 tz->last_temperature = tz->temperature;
1164 tz->temperature = temp;
1165
1068 for (count = 0; count < tz->trips; count++) { 1166 for (count = 0; count < tz->trips; count++) {
1069 tz->ops->get_trip_type(tz, count, &trip_type); 1167 tz->ops->get_trip_type(tz, count, &trip_type);
1070 tz->ops->get_trip_temp(tz, count, &trip_temp); 1168 tz->ops->get_trip_temp(tz, count, &trip_temp);
@@ -1088,32 +1186,18 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
1088 tz->ops->notify(tz, count, trip_type); 1186 tz->ops->notify(tz, count, trip_type);
1089 break; 1187 break;
1090 case THERMAL_TRIP_ACTIVE: 1188 case THERMAL_TRIP_ACTIVE:
1091 list_for_each_entry(instance, &tz->cooling_devices, 1189 thermal_zone_trip_update(tz, count, temp);
1092 node) {
1093 if (instance->trip != count)
1094 continue;
1095
1096 cdev = instance->cdev;
1097
1098 if (temp >= trip_temp)
1099 cdev->ops->set_cur_state(cdev, 1);
1100 else
1101 cdev->ops->set_cur_state(cdev, 0);
1102 }
1103 break; 1190 break;
1104 case THERMAL_TRIP_PASSIVE: 1191 case THERMAL_TRIP_PASSIVE:
1105 if (temp >= trip_temp || tz->passive) 1192 if (temp >= trip_temp || tz->passive)
1106 thermal_zone_device_passive(tz, temp, 1193 thermal_zone_trip_update(tz, count, temp);
1107 trip_temp, count);
1108 break; 1194 break;
1109 } 1195 }
1110 } 1196 }
1111 1197
1112 if (tz->forced_passive) 1198 if (tz->forced_passive)
1113 thermal_zone_device_passive(tz, temp, tz->forced_passive, 1199 thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, temp);
1114 THERMAL_TRIPS_NONE); 1200 thermal_zone_do_update(tz);
1115
1116 tz->last_temperature = temp;
1117 1201
1118leave: 1202leave:
1119 if (tz->passive) 1203 if (tz->passive)
@@ -1236,8 +1320,6 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
1236 * @mask: a bit string indicating the writeablility of trip points 1320 * @mask: a bit string indicating the writeablility of trip points
1237 * @devdata: private device data 1321 * @devdata: private device data
1238 * @ops: standard thermal zone device callbacks 1322 * @ops: standard thermal zone device callbacks
1239 * @tc1: thermal coefficient 1 for passive calculations
1240 * @tc2: thermal coefficient 2 for passive calculations
1241 * @passive_delay: number of milliseconds to wait between polls when 1323 * @passive_delay: number of milliseconds to wait between polls when
1242 * performing passive cooling 1324 * performing passive cooling
1243 * @polling_delay: number of milliseconds to wait between polls when checking 1325 * @polling_delay: number of milliseconds to wait between polls when checking
@@ -1245,13 +1327,12 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
1245 * driven systems) 1327 * driven systems)
1246 * 1328 *
1247 * thermal_zone_device_unregister() must be called when the device is no 1329 * thermal_zone_device_unregister() must be called when the device is no
1248 * longer needed. The passive cooling formula uses tc1 and tc2 as described in 1330 * longer needed. The passive cooling depends on the .get_trend() return value.
1249 * section 11.1.5.1 of the ACPI specification 3.0.
1250 */ 1331 */
1251struct thermal_zone_device *thermal_zone_device_register(const char *type, 1332struct thermal_zone_device *thermal_zone_device_register(const char *type,
1252 int trips, int mask, void *devdata, 1333 int trips, int mask, void *devdata,
1253 const struct thermal_zone_device_ops *ops, 1334 const struct thermal_zone_device_ops *ops,
1254 int tc1, int tc2, int passive_delay, int polling_delay) 1335 int passive_delay, int polling_delay)
1255{ 1336{
1256 struct thermal_zone_device *tz; 1337 struct thermal_zone_device *tz;
1257 struct thermal_cooling_device *pos; 1338 struct thermal_cooling_device *pos;
@@ -1260,7 +1341,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1260 int count; 1341 int count;
1261 int passive = 0; 1342 int passive = 0;
1262 1343
1263 if (strlen(type) >= THERMAL_NAME_LENGTH) 1344 if (type && strlen(type) >= THERMAL_NAME_LENGTH)
1264 return ERR_PTR(-EINVAL); 1345 return ERR_PTR(-EINVAL);
1265 1346
1266 if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips) 1347 if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips)
@@ -1273,7 +1354,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1273 if (!tz) 1354 if (!tz)
1274 return ERR_PTR(-ENOMEM); 1355 return ERR_PTR(-ENOMEM);
1275 1356
1276 INIT_LIST_HEAD(&tz->cooling_devices); 1357 INIT_LIST_HEAD(&tz->thermal_instances);
1277 idr_init(&tz->idr); 1358 idr_init(&tz->idr);
1278 mutex_init(&tz->lock); 1359 mutex_init(&tz->lock);
1279 result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id); 1360 result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id);
@@ -1282,13 +1363,11 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1282 return ERR_PTR(result); 1363 return ERR_PTR(result);
1283 } 1364 }
1284 1365
1285 strcpy(tz->type, type); 1366 strcpy(tz->type, type ? : "");
1286 tz->ops = ops; 1367 tz->ops = ops;
1287 tz->device.class = &thermal_class; 1368 tz->device.class = &thermal_class;
1288 tz->devdata = devdata; 1369 tz->devdata = devdata;
1289 tz->trips = trips; 1370 tz->trips = trips;
1290 tz->tc1 = tc1;
1291 tz->tc2 = tc2;
1292 tz->passive_delay = passive_delay; 1371 tz->passive_delay = passive_delay;
1293 tz->polling_delay = polling_delay; 1372 tz->polling_delay = polling_delay;
1294 1373