aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-02-19 20:51:22 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-19 20:51:22 -0500
commit3d883483dc0a7261d73d8b1857a7387a1dd99eee (patch)
tree738306f233967a93a9725c697fce6d3b36e6d78a
parente3a1f6cac1fe20e7ac01d96c914c25726723a64e (diff)
parent6c247393cfdd6695717f80ff31f9fd9af8c2c525 (diff)
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal
Pull more thermal managament updates from Zhang Rui: "Specifics: - Exynos thermal driver refactoring. Several cleanups, code optimization, unused symbols removal, and unused feature removal in Exynos thermal driver. Thanks Lukasz for this effort. - Exynos thermal driver support to OF thermal. After the code refactoring, the driver earned the support to OF thermal. Chip thermal data were moved from driver code to DTS, reducing the code footprint. Thanks Lukasz for this. - After receiving the OF thermal support, the exynos thermal driver now must allow modular build. Thanks Arnd for detecting, reporting and fixing this. - Exynos thermal driver support to Exynos 7 SoC. Thanks Abhilash for this. - Accurate temperature reporting on Rockchip thermal driver, thanks to Caesar. - Fix on how OF thermal enables its zones, thanks Lukasz for fixing. - Fixes in OF thermal examples under Documentation/. Thanks Srinivas for fixing" * 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal: thermal: exynos: Add TMU support for Exynos7 SoC dts: Documentation: Add documentation for Exynos7 SoC thermal bindings cpufreq: exynos: allow modular build thermal: Fix examples in DT documentation thermal: exynos: Correct sanity check at exynos_report_trigger() function thermal: Kconfig: Remove config for not used EXYNOS_THERMAL_CORE thermal: exynos: Remove exynos_tmu_data.c file thermal: rockchip: make temperature reporting much more accurate thermal: exynos: Remove exynos_thermal_common.[c|h] files thermal: samsung: core: Exynos TMU rework to use device tree for configuration dts: Documentation: Update exynos-thermal.txt example for Exynos5440 dts: Documentation: Extending documentation entry for exynos-thermal cpufreq: exynos: Use device tree to determine if cpufreq cooling should be registered thermal: exynos: Modify exynos thermal code to use device tree for cpu cooling configuration thermal: exynos: Provide thermal_exynos.h file to be included in device tree files thermal: exynos: cosmetic: Correct comment format thermal: of: Enable thermal_zoneX when sensor is correctly added
-rw-r--r--Documentation/devicetree/bindings/thermal/exynos-thermal.txt21
-rw-r--r--Documentation/devicetree/bindings/thermal/thermal.txt74
-rw-r--r--drivers/cpufreq/Kconfig.arm44
-rw-r--r--drivers/cpufreq/Makefile9
-rw-r--r--drivers/cpufreq/exynos-cpufreq.c33
-rw-r--r--drivers/thermal/of-thermal.c3
-rw-r--r--drivers/thermal/rockchip_thermal.c36
-rw-r--r--drivers/thermal/samsung/Kconfig9
-rw-r--r--drivers/thermal/samsung/Makefile2
-rw-r--r--drivers/thermal/samsung/exynos_thermal_common.c427
-rw-r--r--drivers/thermal/samsung/exynos_thermal_common.h106
-rw-r--r--drivers/thermal/samsung/exynos_tmu.c553
-rw-r--r--drivers/thermal/samsung/exynos_tmu.h77
-rw-r--r--drivers/thermal/samsung/exynos_tmu_data.c264
-rw-r--r--include/dt-bindings/thermal/thermal_exynos.h28
15 files changed, 596 insertions, 1090 deletions
diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
index ae738f562acc..695150a4136b 100644
--- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
@@ -12,6 +12,7 @@
12 "samsung,exynos5420-tmu-ext-triminfo" for TMU channels 2, 3 and 4 12 "samsung,exynos5420-tmu-ext-triminfo" for TMU channels 2, 3 and 4
13 Exynos5420 (Must pass triminfo base and triminfo clock) 13 Exynos5420 (Must pass triminfo base and triminfo clock)
14 "samsung,exynos5440-tmu" 14 "samsung,exynos5440-tmu"
15 "samsung,exynos7-tmu"
15- interrupt-parent : The phandle for the interrupt controller 16- interrupt-parent : The phandle for the interrupt controller
16- reg : Address range of the thermal registers. For soc's which has multiple 17- reg : Address range of the thermal registers. For soc's which has multiple
17 instances of TMU and some registers are shared across all TMU's like 18 instances of TMU and some registers are shared across all TMU's like
@@ -32,13 +33,28 @@
32- clocks : The main clocks for TMU device 33- clocks : The main clocks for TMU device
33 -- 1. operational clock for TMU channel 34 -- 1. operational clock for TMU channel
34 -- 2. optional clock to access the shared registers of TMU channel 35 -- 2. optional clock to access the shared registers of TMU channel
36 -- 3. optional special clock for functional operation
35- clock-names : Thermal system clock name 37- clock-names : Thermal system clock name
36 -- "tmu_apbif" operational clock for current TMU channel 38 -- "tmu_apbif" operational clock for current TMU channel
37 -- "tmu_triminfo_apbif" clock to access the shared triminfo register 39 -- "tmu_triminfo_apbif" clock to access the shared triminfo register
38 for current TMU channel 40 for current TMU channel
41 -- "tmu_sclk" clock for functional operation of the current TMU
42 channel
39- vtmu-supply: This entry is optional and provides the regulator node supplying 43- vtmu-supply: This entry is optional and provides the regulator node supplying
40 voltage to TMU. If needed this entry can be placed inside 44 voltage to TMU. If needed this entry can be placed inside
41 board/platform specific dts file. 45 board/platform specific dts file.
46Following properties are mandatory (depending on SoC):
47- samsung,tmu_gain: Gain value for internal TMU operation.
48- samsung,tmu_reference_voltage: Value of TMU IP block's reference voltage
49- samsung,tmu_noise_cancel_mode: Mode for noise cancellation
50- samsung,tmu_efuse_value: Default level of temperature - it is needed when
51 in factory fusing produced wrong value
52- samsung,tmu_min_efuse_value: Minimum temperature fused value
53- samsung,tmu_max_efuse_value: Maximum temperature fused value
54- samsung,tmu_first_point_trim: First point trimming value
55- samsung,tmu_second_point_trim: Second point trimming value
56- samsung,tmu_default_temp_offset: Default temperature offset
57- samsung,tmu_cal_type: Callibration type
42 58
43Example 1): 59Example 1):
44 60
@@ -51,6 +67,7 @@ Example 1):
51 clock-names = "tmu_apbif"; 67 clock-names = "tmu_apbif";
52 status = "disabled"; 68 status = "disabled";
53 vtmu-supply = <&tmu_regulator_node>; 69 vtmu-supply = <&tmu_regulator_node>;
70 #include "exynos4412-tmu-sensor-conf.dtsi"
54 }; 71 };
55 72
56Example 2): 73Example 2):
@@ -61,6 +78,7 @@ Example 2):
61 interrupts = <0 58 0>; 78 interrupts = <0 58 0>;
62 clocks = <&clock 21>; 79 clocks = <&clock 21>;
63 clock-names = "tmu_apbif"; 80 clock-names = "tmu_apbif";
81 #include "exynos5440-tmu-sensor-conf.dtsi"
64 }; 82 };
65 83
66Example 3): (In case of Exynos5420 "with misplaced TRIMINFO register") 84Example 3): (In case of Exynos5420 "with misplaced TRIMINFO register")
@@ -70,6 +88,7 @@ Example 3): (In case of Exynos5420 "with misplaced TRIMINFO register")
70 interrupts = <0 184 0>; 88 interrupts = <0 184 0>;
71 clocks = <&clock 318>, <&clock 318>; 89 clocks = <&clock 318>, <&clock 318>;
72 clock-names = "tmu_apbif", "tmu_triminfo_apbif"; 90 clock-names = "tmu_apbif", "tmu_triminfo_apbif";
91 #include "exynos4412-tmu-sensor-conf.dtsi"
73 }; 92 };
74 93
75 tmu_cpu3: tmu@1006c000 { 94 tmu_cpu3: tmu@1006c000 {
@@ -78,6 +97,7 @@ Example 3): (In case of Exynos5420 "with misplaced TRIMINFO register")
78 interrupts = <0 185 0>; 97 interrupts = <0 185 0>;
79 clocks = <&clock 318>, <&clock 319>; 98 clocks = <&clock 318>, <&clock 319>;
80 clock-names = "tmu_apbif", "tmu_triminfo_apbif"; 99 clock-names = "tmu_apbif", "tmu_triminfo_apbif";
100 #include "exynos4412-tmu-sensor-conf.dtsi"
81 }; 101 };
82 102
83 tmu_gpu: tmu@100a0000 { 103 tmu_gpu: tmu@100a0000 {
@@ -86,6 +106,7 @@ Example 3): (In case of Exynos5420 "with misplaced TRIMINFO register")
86 interrupts = <0 215 0>; 106 interrupts = <0 215 0>;
87 clocks = <&clock 319>, <&clock 318>; 107 clocks = <&clock 319>, <&clock 318>;
88 clock-names = "tmu_apbif", "tmu_triminfo_apbif"; 108 clock-names = "tmu_apbif", "tmu_triminfo_apbif";
109 #include "exynos4412-tmu-sensor-conf.dtsi"
89 }; 110 };
90 111
91Note: For multi-instance tmu each instance should have an alias correctly 112Note: For multi-instance tmu each instance should have an alias correctly
diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
index f5db6b72a36f..29fe0bfae38e 100644
--- a/Documentation/devicetree/bindings/thermal/thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/thermal.txt
@@ -251,24 +251,24 @@ ocp {
251}; 251};
252 252
253thermal-zones { 253thermal-zones {
254 cpu-thermal: cpu-thermal { 254 cpu_thermal: cpu-thermal {
255 polling-delay-passive = <250>; /* milliseconds */ 255 polling-delay-passive = <250>; /* milliseconds */
256 polling-delay = <1000>; /* milliseconds */ 256 polling-delay = <1000>; /* milliseconds */
257 257
258 thermal-sensors = <&bandgap0>; 258 thermal-sensors = <&bandgap0>;
259 259
260 trips { 260 trips {
261 cpu-alert0: cpu-alert { 261 cpu_alert0: cpu-alert0 {
262 temperature = <90000>; /* millicelsius */ 262 temperature = <90000>; /* millicelsius */
263 hysteresis = <2000>; /* millicelsius */ 263 hysteresis = <2000>; /* millicelsius */
264 type = "active"; 264 type = "active";
265 }; 265 };
266 cpu-alert1: cpu-alert { 266 cpu_alert1: cpu-alert1 {
267 temperature = <100000>; /* millicelsius */ 267 temperature = <100000>; /* millicelsius */
268 hysteresis = <2000>; /* millicelsius */ 268 hysteresis = <2000>; /* millicelsius */
269 type = "passive"; 269 type = "passive";
270 }; 270 };
271 cpu-crit: cpu-crit { 271 cpu_crit: cpu-crit {
272 temperature = <125000>; /* millicelsius */ 272 temperature = <125000>; /* millicelsius */
273 hysteresis = <2000>; /* millicelsius */ 273 hysteresis = <2000>; /* millicelsius */
274 type = "critical"; 274 type = "critical";
@@ -277,17 +277,17 @@ thermal-zones {
277 277
278 cooling-maps { 278 cooling-maps {
279 map0 { 279 map0 {
280 trip = <&cpu-alert0>; 280 trip = <&cpu_alert0>;
281 cooling-device = <&fan0 THERMAL_NO_LIMITS 4>; 281 cooling-device = <&fan0 THERMAL_NO_LIMIT 4>;
282 }; 282 };
283 map1 { 283 map1 {
284 trip = <&cpu-alert1>; 284 trip = <&cpu_alert1>;
285 cooling-device = <&fan0 5 THERMAL_NO_LIMITS>; 285 cooling-device = <&fan0 5 THERMAL_NO_LIMIT>;
286 }; 286 };
287 map2 { 287 map2 {
288 trip = <&cpu-alert1>; 288 trip = <&cpu_alert1>;
289 cooling-device = 289 cooling-device =
290 <&cpu0 THERMAL_NO_LIMITS THERMAL_NO_LIMITS>; 290 <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
291 }; 291 };
292 }; 292 };
293 }; 293 };
@@ -298,13 +298,13 @@ used to monitor the zone 'cpu-thermal' using its sole sensor. A fan
298device (fan0) is controlled via I2C bus 1, at address 0x48, and has ten 298device (fan0) is controlled via I2C bus 1, at address 0x48, and has ten
299different cooling states 0-9. It is used to remove the heat out of 299different cooling states 0-9. It is used to remove the heat out of
300the thermal zone 'cpu-thermal' using its cooling states 300the thermal zone 'cpu-thermal' using its cooling states
301from its minimum to 4, when it reaches trip point 'cpu-alert0' 301from its minimum to 4, when it reaches trip point 'cpu_alert0'
302at 90C, as an example of active cooling. The same cooling device is used at 302at 90C, as an example of active cooling. The same cooling device is used at
303'cpu-alert1', but from 5 to its maximum state. The cpu@0 device is also 303'cpu_alert1', but from 5 to its maximum state. The cpu@0 device is also
304linked to the same thermal zone, 'cpu-thermal', as a passive cooling device, 304linked to the same thermal zone, 'cpu-thermal', as a passive cooling device,
305using all its cooling states at trip point 'cpu-alert1', 305using all its cooling states at trip point 'cpu_alert1',
306which is a trip point at 100C. On the thermal zone 'cpu-thermal', at the 306which is a trip point at 100C. On the thermal zone 'cpu-thermal', at the
307temperature of 125C, represented by the trip point 'cpu-crit', the silicon 307temperature of 125C, represented by the trip point 'cpu_crit', the silicon
308is not reliable anymore. 308is not reliable anymore.
309 309
310(b) - IC with several internal sensors 310(b) - IC with several internal sensors
@@ -329,7 +329,7 @@ ocp {
329}; 329};
330 330
331thermal-zones { 331thermal-zones {
332 cpu-thermal: cpu-thermal { 332 cpu_thermal: cpu-thermal {
333 polling-delay-passive = <250>; /* milliseconds */ 333 polling-delay-passive = <250>; /* milliseconds */
334 polling-delay = <1000>; /* milliseconds */ 334 polling-delay = <1000>; /* milliseconds */
335 335
@@ -338,12 +338,12 @@ thermal-zones {
338 338
339 trips { 339 trips {
340 /* each zone within the SoC may have its own trips */ 340 /* each zone within the SoC may have its own trips */
341 cpu-alert: cpu-alert { 341 cpu_alert: cpu-alert {
342 temperature = <100000>; /* millicelsius */ 342 temperature = <100000>; /* millicelsius */
343 hysteresis = <2000>; /* millicelsius */ 343 hysteresis = <2000>; /* millicelsius */
344 type = "passive"; 344 type = "passive";
345 }; 345 };
346 cpu-crit: cpu-crit { 346 cpu_crit: cpu-crit {
347 temperature = <125000>; /* millicelsius */ 347 temperature = <125000>; /* millicelsius */
348 hysteresis = <2000>; /* millicelsius */ 348 hysteresis = <2000>; /* millicelsius */
349 type = "critical"; 349 type = "critical";
@@ -356,7 +356,7 @@ thermal-zones {
356 }; 356 };
357 }; 357 };
358 358
359 gpu-thermal: gpu-thermal { 359 gpu_thermal: gpu-thermal {
360 polling-delay-passive = <120>; /* milliseconds */ 360 polling-delay-passive = <120>; /* milliseconds */
361 polling-delay = <1000>; /* milliseconds */ 361 polling-delay = <1000>; /* milliseconds */
362 362
@@ -365,12 +365,12 @@ thermal-zones {
365 365
366 trips { 366 trips {
367 /* each zone within the SoC may have its own trips */ 367 /* each zone within the SoC may have its own trips */
368 gpu-alert: gpu-alert { 368 gpu_alert: gpu-alert {
369 temperature = <90000>; /* millicelsius */ 369 temperature = <90000>; /* millicelsius */
370 hysteresis = <2000>; /* millicelsius */ 370 hysteresis = <2000>; /* millicelsius */
371 type = "passive"; 371 type = "passive";
372 }; 372 };
373 gpu-crit: gpu-crit { 373 gpu_crit: gpu-crit {
374 temperature = <105000>; /* millicelsius */ 374 temperature = <105000>; /* millicelsius */
375 hysteresis = <2000>; /* millicelsius */ 375 hysteresis = <2000>; /* millicelsius */
376 type = "critical"; 376 type = "critical";
@@ -383,7 +383,7 @@ thermal-zones {
383 }; 383 };
384 }; 384 };
385 385
386 dsp-thermal: dsp-thermal { 386 dsp_thermal: dsp-thermal {
387 polling-delay-passive = <50>; /* milliseconds */ 387 polling-delay-passive = <50>; /* milliseconds */
388 polling-delay = <1000>; /* milliseconds */ 388 polling-delay = <1000>; /* milliseconds */
389 389
@@ -392,12 +392,12 @@ thermal-zones {
392 392
393 trips { 393 trips {
394 /* each zone within the SoC may have its own trips */ 394 /* each zone within the SoC may have its own trips */
395 dsp-alert: gpu-alert { 395 dsp_alert: dsp-alert {
396 temperature = <90000>; /* millicelsius */ 396 temperature = <90000>; /* millicelsius */
397 hysteresis = <2000>; /* millicelsius */ 397 hysteresis = <2000>; /* millicelsius */
398 type = "passive"; 398 type = "passive";
399 }; 399 };
400 dsp-crit: gpu-crit { 400 dsp_crit: gpu-crit {
401 temperature = <135000>; /* millicelsius */ 401 temperature = <135000>; /* millicelsius */
402 hysteresis = <2000>; /* millicelsius */ 402 hysteresis = <2000>; /* millicelsius */
403 type = "critical"; 403 type = "critical";
@@ -457,7 +457,7 @@ ocp {
457}; 457};
458 458
459thermal-zones { 459thermal-zones {
460 cpu-thermal: cpu-thermal { 460 cpu_thermal: cpu-thermal {
461 polling-delay-passive = <250>; /* milliseconds */ 461 polling-delay-passive = <250>; /* milliseconds */
462 polling-delay = <1000>; /* milliseconds */ 462 polling-delay = <1000>; /* milliseconds */
463 463
@@ -508,7 +508,7 @@ with many sensors and many cooling devices.
508 /* 508 /*
509 * An IC with several temperature sensor. 509 * An IC with several temperature sensor.
510 */ 510 */
511 adc-dummy: sensor@0x50 { 511 adc_dummy: sensor@0x50 {
512 ... 512 ...
513 #thermal-sensor-cells = <1>; /* sensor internal ID */ 513 #thermal-sensor-cells = <1>; /* sensor internal ID */
514 }; 514 };
@@ -520,7 +520,7 @@ thermal-zones {
520 polling-delay = <2500>; /* milliseconds */ 520 polling-delay = <2500>; /* milliseconds */
521 521
522 /* sensor ID */ 522 /* sensor ID */
523 thermal-sensors = <&adc-dummy 4>; 523 thermal-sensors = <&adc_dummy 4>;
524 524
525 trips { 525 trips {
526 ... 526 ...
@@ -531,14 +531,14 @@ thermal-zones {
531 }; 531 };
532 }; 532 };
533 533
534 board-thermal: board-thermal { 534 board_thermal: board-thermal {
535 polling-delay-passive = <1000>; /* milliseconds */ 535 polling-delay-passive = <1000>; /* milliseconds */
536 polling-delay = <2500>; /* milliseconds */ 536 polling-delay = <2500>; /* milliseconds */
537 537
538 /* sensor ID */ 538 /* sensor ID */
539 thermal-sensors = <&adc-dummy 0>, /* pcb top edge */ 539 thermal-sensors = <&adc_dummy 0>, /* pcb top edge */
540 <&adc-dummy 1>, /* lcd */ 540 <&adc_dummy 1>, /* lcd */
541 <&adc-dymmy 2>; /* back cover */ 541 <&adc_dummy 2>; /* back cover */
542 /* 542 /*
543 * An array of coefficients describing the sensor 543 * An array of coefficients describing the sensor
544 * linear relation. E.g.: 544 * linear relation. E.g.:
@@ -548,22 +548,22 @@ thermal-zones {
548 548
549 trips { 549 trips {
550 /* Trips are based on resulting linear equation */ 550 /* Trips are based on resulting linear equation */
551 cpu-trip: cpu-trip { 551 cpu_trip: cpu-trip {
552 temperature = <60000>; /* millicelsius */ 552 temperature = <60000>; /* millicelsius */
553 hysteresis = <2000>; /* millicelsius */ 553 hysteresis = <2000>; /* millicelsius */
554 type = "passive"; 554 type = "passive";
555 }; 555 };
556 gpu-trip: gpu-trip { 556 gpu_trip: gpu-trip {
557 temperature = <55000>; /* millicelsius */ 557 temperature = <55000>; /* millicelsius */
558 hysteresis = <2000>; /* millicelsius */ 558 hysteresis = <2000>; /* millicelsius */
559 type = "passive"; 559 type = "passive";
560 } 560 }
561 lcd-trip: lcp-trip { 561 lcd_trip: lcp-trip {
562 temperature = <53000>; /* millicelsius */ 562 temperature = <53000>; /* millicelsius */
563 hysteresis = <2000>; /* millicelsius */ 563 hysteresis = <2000>; /* millicelsius */
564 type = "passive"; 564 type = "passive";
565 }; 565 };
566 crit-trip: crit-trip { 566 crit_trip: crit-trip {
567 temperature = <68000>; /* millicelsius */ 567 temperature = <68000>; /* millicelsius */
568 hysteresis = <2000>; /* millicelsius */ 568 hysteresis = <2000>; /* millicelsius */
569 type = "critical"; 569 type = "critical";
@@ -572,17 +572,17 @@ thermal-zones {
572 572
573 cooling-maps { 573 cooling-maps {
574 map0 { 574 map0 {
575 trip = <&cpu-trip>; 575 trip = <&cpu_trip>;
576 cooling-device = <&cpu0 0 2>; 576 cooling-device = <&cpu0 0 2>;
577 contribution = <55>; 577 contribution = <55>;
578 }; 578 };
579 map1 { 579 map1 {
580 trip = <&gpu-trip>; 580 trip = <&gpu_trip>;
581 cooling-device = <&gpu0 0 2>; 581 cooling-device = <&gpu0 0 2>;
582 contribution = <20>; 582 contribution = <20>;
583 }; 583 };
584 map2 { 584 map2 {
585 trip = <&lcd-trip>; 585 trip = <&lcd_trip>;
586 cooling-device = <&lcd0 5 10>; 586 cooling-device = <&lcd0 5 10>;
587 contribution = <15>; 587 contribution = <15>;
588 }; 588 };
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 0f9a2c3c0e0d..1b06fc4640e2 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -26,13 +26,21 @@ config ARM_VEXPRESS_SPC_CPUFREQ
26 26
27 27
28config ARM_EXYNOS_CPUFREQ 28config ARM_EXYNOS_CPUFREQ
29 bool 29 tristate "SAMSUNG EXYNOS CPUfreq Driver"
30 depends on CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250
31 depends on THERMAL
32 help
33 This adds the CPUFreq driver for Samsung EXYNOS platforms.
34 Supported SoC versions are:
35 Exynos4210, Exynos4212, Exynos4412, and Exynos5250.
36
37 If in doubt, say N.
30 38
31config ARM_EXYNOS4210_CPUFREQ 39config ARM_EXYNOS4210_CPUFREQ
32 bool "SAMSUNG EXYNOS4210" 40 bool "SAMSUNG EXYNOS4210"
33 depends on CPU_EXYNOS4210 41 depends on CPU_EXYNOS4210
42 depends on ARM_EXYNOS_CPUFREQ
34 default y 43 default y
35 select ARM_EXYNOS_CPUFREQ
36 help 44 help
37 This adds the CPUFreq driver for Samsung EXYNOS4210 45 This adds the CPUFreq driver for Samsung EXYNOS4210
38 SoC (S5PV310 or S5PC210). 46 SoC (S5PV310 or S5PC210).
@@ -42,8 +50,8 @@ config ARM_EXYNOS4210_CPUFREQ
42config ARM_EXYNOS4X12_CPUFREQ 50config ARM_EXYNOS4X12_CPUFREQ
43 bool "SAMSUNG EXYNOS4x12" 51 bool "SAMSUNG EXYNOS4x12"
44 depends on SOC_EXYNOS4212 || SOC_EXYNOS4412 52 depends on SOC_EXYNOS4212 || SOC_EXYNOS4412
53 depends on ARM_EXYNOS_CPUFREQ
45 default y 54 default y
46 select ARM_EXYNOS_CPUFREQ
47 help 55 help
48 This adds the CPUFreq driver for Samsung EXYNOS4X12 56 This adds the CPUFreq driver for Samsung EXYNOS4X12
49 SoC (EXYNOS4212 or EXYNOS4412). 57 SoC (EXYNOS4212 or EXYNOS4412).
@@ -53,28 +61,14 @@ config ARM_EXYNOS4X12_CPUFREQ
53config ARM_EXYNOS5250_CPUFREQ 61config ARM_EXYNOS5250_CPUFREQ
54 bool "SAMSUNG EXYNOS5250" 62 bool "SAMSUNG EXYNOS5250"
55 depends on SOC_EXYNOS5250 63 depends on SOC_EXYNOS5250
64 depends on ARM_EXYNOS_CPUFREQ
56 default y 65 default y
57 select ARM_EXYNOS_CPUFREQ
58 help 66 help
59 This adds the CPUFreq driver for Samsung EXYNOS5250 67 This adds the CPUFreq driver for Samsung EXYNOS5250
60 SoC. 68 SoC.
61 69
62 If in doubt, say N. 70 If in doubt, say N.
63 71
64config ARM_EXYNOS5440_CPUFREQ
65 bool "SAMSUNG EXYNOS5440"
66 depends on SOC_EXYNOS5440
67 depends on HAVE_CLK && OF
68 select PM_OPP
69 default y
70 help
71 This adds the CPUFreq driver for Samsung EXYNOS5440
72 SoC. The nature of exynos5440 clock controller is
73 different than previous exynos controllers so not using
74 the common exynos framework.
75
76 If in doubt, say N.
77
78config ARM_EXYNOS_CPU_FREQ_BOOST_SW 72config ARM_EXYNOS_CPU_FREQ_BOOST_SW
79 bool "EXYNOS Frequency Overclocking - Software" 73 bool "EXYNOS Frequency Overclocking - Software"
80 depends on ARM_EXYNOS_CPUFREQ && THERMAL 74 depends on ARM_EXYNOS_CPUFREQ && THERMAL
@@ -90,6 +84,20 @@ config ARM_EXYNOS_CPU_FREQ_BOOST_SW
90 84
91 If in doubt, say N. 85 If in doubt, say N.
92 86
87config ARM_EXYNOS5440_CPUFREQ
88 tristate "SAMSUNG EXYNOS5440"
89 depends on SOC_EXYNOS5440
90 depends on HAVE_CLK && OF
91 select PM_OPP
92 default y
93 help
94 This adds the CPUFreq driver for Samsung EXYNOS5440
95 SoC. The nature of exynos5440 clock controller is
96 different than previous exynos controllers so not using
97 the common exynos framework.
98
99 If in doubt, say N.
100
93config ARM_HIGHBANK_CPUFREQ 101config ARM_HIGHBANK_CPUFREQ
94 tristate "Calxeda Highbank-based" 102 tristate "Calxeda Highbank-based"
95 depends on ARCH_HIGHBANK && CPUFREQ_DT && REGULATOR 103 depends on ARCH_HIGHBANK && CPUFREQ_DT && REGULATOR
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8b4220ac888b..82a1821471fd 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -52,10 +52,11 @@ obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
52 52
53obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o 53obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
54obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o 54obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o
55obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o 55obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += arm-exynos-cpufreq.o
56obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o 56arm-exynos-cpufreq-y := exynos-cpufreq.o
57obj-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o 57arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
58obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o 58arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o
59arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o
59obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o 60obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
60obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o 61obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
61obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o 62obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index f99a0b0b7c06..5e98c6b1f284 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -18,10 +18,13 @@
18#include <linux/cpufreq.h> 18#include <linux/cpufreq.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/of.h> 20#include <linux/of.h>
21#include <linux/cpu_cooling.h>
22#include <linux/cpu.h>
21 23
22#include "exynos-cpufreq.h" 24#include "exynos-cpufreq.h"
23 25
24static struct exynos_dvfs_info *exynos_info; 26static struct exynos_dvfs_info *exynos_info;
27static struct thermal_cooling_device *cdev;
25static struct regulator *arm_regulator; 28static struct regulator *arm_regulator;
26static unsigned int locking_frequency; 29static unsigned int locking_frequency;
27 30
@@ -156,6 +159,7 @@ static struct cpufreq_driver exynos_driver = {
156 159
157static int exynos_cpufreq_probe(struct platform_device *pdev) 160static int exynos_cpufreq_probe(struct platform_device *pdev)
158{ 161{
162 struct device_node *cpus, *np;
159 int ret = -EINVAL; 163 int ret = -EINVAL;
160 164
161 exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL); 165 exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL);
@@ -198,9 +202,36 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
198 /* Done here as we want to capture boot frequency */ 202 /* Done here as we want to capture boot frequency */
199 locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000; 203 locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000;
200 204
201 if (!cpufreq_register_driver(&exynos_driver)) 205 ret = cpufreq_register_driver(&exynos_driver);
206 if (ret)
207 goto err_cpufreq_reg;
208
209 cpus = of_find_node_by_path("/cpus");
210 if (!cpus) {
211 pr_err("failed to find cpus node\n");
212 return 0;
213 }
214
215 np = of_get_next_child(cpus, NULL);
216 if (!np) {
217 pr_err("failed to find cpus child node\n");
218 of_node_put(cpus);
202 return 0; 219 return 0;
220 }
221
222 if (of_find_property(np, "#cooling-cells", NULL)) {
223 cdev = of_cpufreq_cooling_register(np,
224 cpu_present_mask);
225 if (IS_ERR(cdev))
226 pr_err("running cpufreq without cooling device: %ld\n",
227 PTR_ERR(cdev));
228 }
229 of_node_put(np);
230 of_node_put(cpus);
231
232 return 0;
203 233
234err_cpufreq_reg:
204 dev_err(&pdev->dev, "failed to register cpufreq driver\n"); 235 dev_err(&pdev->dev, "failed to register cpufreq driver\n");
205 regulator_put(arm_regulator); 236 regulator_put(arm_regulator);
206err_vdd_arm: 237err_vdd_arm:
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index d717f3dab6f1..668fb1bdea9e 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -497,6 +497,9 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,
497 if (sensor_specs.np == sensor_np && id == sensor_id) { 497 if (sensor_specs.np == sensor_np && id == sensor_id) {
498 tzd = thermal_zone_of_add_sensor(child, sensor_np, 498 tzd = thermal_zone_of_add_sensor(child, sensor_np,
499 data, ops); 499 data, ops);
500 if (!IS_ERR(tzd))
501 tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED);
502
500 of_node_put(sensor_specs.np); 503 of_node_put(sensor_specs.np);
501 of_node_put(child); 504 of_node_put(child);
502 goto exit; 505 goto exit;
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index 9c6ce548e363..3aa46ac7cdbc 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -193,19 +193,20 @@ static u32 rk_tsadcv2_temp_to_code(long temp)
193 193
194static long rk_tsadcv2_code_to_temp(u32 code) 194static long rk_tsadcv2_code_to_temp(u32 code)
195{ 195{
196 int high, low, mid; 196 unsigned int low = 0;
197 197 unsigned int high = ARRAY_SIZE(v2_code_table) - 1;
198 low = 0; 198 unsigned int mid = (low + high) / 2;
199 high = ARRAY_SIZE(v2_code_table) - 1; 199 unsigned int num;
200 mid = (high + low) / 2; 200 unsigned long denom;
201 201
202 if (code > v2_code_table[low].code || code < v2_code_table[high].code) 202 /* Invalid code, return -EAGAIN */
203 return 125000; /* No code available, return max temperature */ 203 if (code > TSADCV2_DATA_MASK)
204 return -EAGAIN;
204 205
205 while (low <= high) { 206 while (low <= high && mid) {
206 if (code >= v2_code_table[mid].code && code < 207 if (code >= v2_code_table[mid].code &&
207 v2_code_table[mid - 1].code) 208 code < v2_code_table[mid - 1].code)
208 return v2_code_table[mid].temp; 209 break;
209 else if (code < v2_code_table[mid].code) 210 else if (code < v2_code_table[mid].code)
210 low = mid + 1; 211 low = mid + 1;
211 else 212 else
@@ -213,7 +214,16 @@ static long rk_tsadcv2_code_to_temp(u32 code)
213 mid = (low + high) / 2; 214 mid = (low + high) / 2;
214 } 215 }
215 216
216 return 125000; 217 /*
218 * The 5C granularity provided by the table is too much. Let's
219 * assume that the relationship between sensor readings and
220 * temperature between 2 table entries is linear and interpolate
221 * to produce less granular result.
222 */
223 num = v2_code_table[mid].temp - v2_code_table[mid - 1].temp;
224 num *= v2_code_table[mid - 1].code - code;
225 denom = v2_code_table[mid - 1].code - v2_code_table[mid].code;
226 return v2_code_table[mid - 1].temp + (num / denom);
217} 227}
218 228
219/** 229/**
diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
index c43306ecc0ab..c8e35c1a43dc 100644
--- a/drivers/thermal/samsung/Kconfig
+++ b/drivers/thermal/samsung/Kconfig
@@ -7,12 +7,3 @@ config EXYNOS_THERMAL
7 the TMU, reports temperature and handles cooling action if defined. 7 the TMU, reports temperature and handles cooling action if defined.
8 This driver uses the Exynos core thermal APIs and TMU configuration 8 This driver uses the Exynos core thermal APIs and TMU configuration
9 data from the supported SoCs. 9 data from the supported SoCs.
10
11config EXYNOS_THERMAL_CORE
12 bool "Core thermal framework support for EXYNOS SOCs"
13 depends on EXYNOS_THERMAL
14 help
15 If you say yes here you get support for EXYNOS TMU
16 (Thermal Management Unit) common registration/unregistration
17 functions to the core thermal layer and also to use the generic
18 CPU cooling APIs.
diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
index c09d83095dc2..1e47d0d89ce0 100644
--- a/drivers/thermal/samsung/Makefile
+++ b/drivers/thermal/samsung/Makefile
@@ -3,5 +3,3 @@
3# 3#
4obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o 4obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o
5exynos_thermal-y := exynos_tmu.o 5exynos_thermal-y := exynos_tmu.o
6exynos_thermal-y += exynos_tmu_data.o
7exynos_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
deleted file mode 100644
index 6dc3815cc73f..000000000000
--- a/drivers/thermal/samsung/exynos_thermal_common.c
+++ /dev/null
@@ -1,427 +0,0 @@
1/*
2 * exynos_thermal_common.c - Samsung EXYNOS common thermal file
3 *
4 * Copyright (C) 2013 Samsung Electronics
5 * Amit Daniel Kachhap <amit.daniel@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/cpu_cooling.h>
24#include <linux/err.h>
25#include <linux/slab.h>
26#include <linux/thermal.h>
27
28#include "exynos_thermal_common.h"
29
30struct exynos_thermal_zone {
31 enum thermal_device_mode mode;
32 struct thermal_zone_device *therm_dev;
33 struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
34 unsigned int cool_dev_size;
35 struct platform_device *exynos4_dev;
36 struct thermal_sensor_conf *sensor_conf;
37 bool bind;
38};
39
40/* Get mode callback functions for thermal zone */
41static int exynos_get_mode(struct thermal_zone_device *thermal,
42 enum thermal_device_mode *mode)
43{
44 struct exynos_thermal_zone *th_zone = thermal->devdata;
45 if (th_zone)
46 *mode = th_zone->mode;
47 return 0;
48}
49
50/* Set mode callback functions for thermal zone */
51static int exynos_set_mode(struct thermal_zone_device *thermal,
52 enum thermal_device_mode mode)
53{
54 struct exynos_thermal_zone *th_zone = thermal->devdata;
55 if (!th_zone) {
56 dev_err(&thermal->device,
57 "thermal zone not registered\n");
58 return 0;
59 }
60
61 mutex_lock(&thermal->lock);
62
63 if (mode == THERMAL_DEVICE_ENABLED &&
64 !th_zone->sensor_conf->trip_data.trigger_falling)
65 thermal->polling_delay = IDLE_INTERVAL;
66 else
67 thermal->polling_delay = 0;
68
69 mutex_unlock(&thermal->lock);
70
71 th_zone->mode = mode;
72 thermal_zone_device_update(thermal);
73 dev_dbg(th_zone->sensor_conf->dev,
74 "thermal polling set for duration=%d msec\n",
75 thermal->polling_delay);
76 return 0;
77}
78
79
80/* Get trip type callback functions for thermal zone */
81static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
82 enum thermal_trip_type *type)
83{
84 struct exynos_thermal_zone *th_zone = thermal->devdata;
85 int max_trip = th_zone->sensor_conf->trip_data.trip_count;
86 int trip_type;
87
88 if (trip < 0 || trip >= max_trip)
89 return -EINVAL;
90
91 trip_type = th_zone->sensor_conf->trip_data.trip_type[trip];
92
93 if (trip_type == SW_TRIP)
94 *type = THERMAL_TRIP_CRITICAL;
95 else if (trip_type == THROTTLE_ACTIVE)
96 *type = THERMAL_TRIP_ACTIVE;
97 else if (trip_type == THROTTLE_PASSIVE)
98 *type = THERMAL_TRIP_PASSIVE;
99 else
100 return -EINVAL;
101
102 return 0;
103}
104
105/* Get trip temperature callback functions for thermal zone */
106static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
107 unsigned long *temp)
108{
109 struct exynos_thermal_zone *th_zone = thermal->devdata;
110 int max_trip = th_zone->sensor_conf->trip_data.trip_count;
111
112 if (trip < 0 || trip >= max_trip)
113 return -EINVAL;
114
115 *temp = th_zone->sensor_conf->trip_data.trip_val[trip];
116 /* convert the temperature into millicelsius */
117 *temp = *temp * MCELSIUS;
118
119 return 0;
120}
121
122/* Get critical temperature callback functions for thermal zone */
123static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
124 unsigned long *temp)
125{
126 struct exynos_thermal_zone *th_zone = thermal->devdata;
127 int max_trip = th_zone->sensor_conf->trip_data.trip_count;
128 /* Get the temp of highest trip*/
129 return exynos_get_trip_temp(thermal, max_trip - 1, temp);
130}
131
132/* Bind callback functions for thermal zone */
133static int exynos_bind(struct thermal_zone_device *thermal,
134 struct thermal_cooling_device *cdev)
135{
136 int ret = 0, i, tab_size, level;
137 struct freq_clip_table *tab_ptr, *clip_data;
138 struct exynos_thermal_zone *th_zone = thermal->devdata;
139 struct thermal_sensor_conf *data = th_zone->sensor_conf;
140
141 tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
142 tab_size = data->cooling_data.freq_clip_count;
143
144 if (tab_ptr == NULL || tab_size == 0)
145 return 0;
146
147 /* find the cooling device registered*/
148 for (i = 0; i < th_zone->cool_dev_size; i++)
149 if (cdev == th_zone->cool_dev[i])
150 break;
151
152 /* No matching cooling device */
153 if (i == th_zone->cool_dev_size)
154 return 0;
155
156 /* Bind the thermal zone to the cpufreq cooling device */
157 for (i = 0; i < tab_size; i++) {
158 clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
159 level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
160 if (level == THERMAL_CSTATE_INVALID)
161 return 0;
162 switch (GET_ZONE(i)) {
163 case MONITOR_ZONE:
164 case WARN_ZONE:
165 if (thermal_zone_bind_cooling_device(thermal, i, cdev,
166 level, 0)) {
167 dev_err(data->dev,
168 "error unbinding cdev inst=%d\n", i);
169 ret = -EINVAL;
170 }
171 th_zone->bind = true;
172 break;
173 default:
174 ret = -EINVAL;
175 }
176 }
177
178 return ret;
179}
180
181/* Unbind callback functions for thermal zone */
182static int exynos_unbind(struct thermal_zone_device *thermal,
183 struct thermal_cooling_device *cdev)
184{
185 int ret = 0, i, tab_size;
186 struct exynos_thermal_zone *th_zone = thermal->devdata;
187 struct thermal_sensor_conf *data = th_zone->sensor_conf;
188
189 if (th_zone->bind == false)
190 return 0;
191
192 tab_size = data->cooling_data.freq_clip_count;
193
194 if (tab_size == 0)
195 return 0;
196
197 /* find the cooling device registered*/
198 for (i = 0; i < th_zone->cool_dev_size; i++)
199 if (cdev == th_zone->cool_dev[i])
200 break;
201
202 /* No matching cooling device */
203 if (i == th_zone->cool_dev_size)
204 return 0;
205
206 /* Bind the thermal zone to the cpufreq cooling device */
207 for (i = 0; i < tab_size; i++) {
208 switch (GET_ZONE(i)) {
209 case MONITOR_ZONE:
210 case WARN_ZONE:
211 if (thermal_zone_unbind_cooling_device(thermal, i,
212 cdev)) {
213 dev_err(data->dev,
214 "error unbinding cdev inst=%d\n", i);
215 ret = -EINVAL;
216 }
217 th_zone->bind = false;
218 break;
219 default:
220 ret = -EINVAL;
221 }
222 }
223 return ret;
224}
225
226/* Get temperature callback functions for thermal zone */
227static int exynos_get_temp(struct thermal_zone_device *thermal,
228 unsigned long *temp)
229{
230 struct exynos_thermal_zone *th_zone = thermal->devdata;
231 void *data;
232
233 if (!th_zone->sensor_conf) {
234 dev_err(&thermal->device,
235 "Temperature sensor not initialised\n");
236 return -EINVAL;
237 }
238 data = th_zone->sensor_conf->driver_data;
239 *temp = th_zone->sensor_conf->read_temperature(data);
240 /* convert the temperature into millicelsius */
241 *temp = *temp * MCELSIUS;
242 return 0;
243}
244
245/* Get temperature callback functions for thermal zone */
246static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
247 unsigned long temp)
248{
249 void *data;
250 int ret = -EINVAL;
251 struct exynos_thermal_zone *th_zone = thermal->devdata;
252
253 if (!th_zone->sensor_conf) {
254 dev_err(&thermal->device,
255 "Temperature sensor not initialised\n");
256 return -EINVAL;
257 }
258 data = th_zone->sensor_conf->driver_data;
259 if (th_zone->sensor_conf->write_emul_temp)
260 ret = th_zone->sensor_conf->write_emul_temp(data, temp);
261 return ret;
262}
263
264/* Get the temperature trend */
265static int exynos_get_trend(struct thermal_zone_device *thermal,
266 int trip, enum thermal_trend *trend)
267{
268 int ret;
269 unsigned long trip_temp;
270
271 ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
272 if (ret < 0)
273 return ret;
274
275 if (thermal->temperature >= trip_temp)
276 *trend = THERMAL_TREND_RAISE_FULL;
277 else
278 *trend = THERMAL_TREND_DROP_FULL;
279
280 return 0;
281}
282/* Operation callback functions for thermal zone */
283static struct thermal_zone_device_ops exynos_dev_ops = {
284 .bind = exynos_bind,
285 .unbind = exynos_unbind,
286 .get_temp = exynos_get_temp,
287 .set_emul_temp = exynos_set_emul_temp,
288 .get_trend = exynos_get_trend,
289 .get_mode = exynos_get_mode,
290 .set_mode = exynos_set_mode,
291 .get_trip_type = exynos_get_trip_type,
292 .get_trip_temp = exynos_get_trip_temp,
293 .get_crit_temp = exynos_get_crit_temp,
294};
295
296/*
297 * This function may be called from interrupt based temperature sensor
298 * when threshold is changed.
299 */
300void exynos_report_trigger(struct thermal_sensor_conf *conf)
301{
302 unsigned int i;
303 char data[10];
304 char *envp[] = { data, NULL };
305 struct exynos_thermal_zone *th_zone;
306
307 if (!conf || !conf->pzone_data) {
308 pr_err("Invalid temperature sensor configuration data\n");
309 return;
310 }
311
312 th_zone = conf->pzone_data;
313
314 if (th_zone->bind == false) {
315 for (i = 0; i < th_zone->cool_dev_size; i++) {
316 if (!th_zone->cool_dev[i])
317 continue;
318 exynos_bind(th_zone->therm_dev,
319 th_zone->cool_dev[i]);
320 }
321 }
322
323 thermal_zone_device_update(th_zone->therm_dev);
324
325 mutex_lock(&th_zone->therm_dev->lock);
326 /* Find the level for which trip happened */
327 for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
328 if (th_zone->therm_dev->last_temperature <
329 th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
330 break;
331 }
332
333 if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
334 !th_zone->sensor_conf->trip_data.trigger_falling) {
335 if (i > 0)
336 th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
337 else
338 th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
339 }
340
341 snprintf(data, sizeof(data), "%u", i);
342 kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
343 mutex_unlock(&th_zone->therm_dev->lock);
344}
345
346/* Register with the in-kernel thermal management */
347int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
348{
349 int ret;
350 struct exynos_thermal_zone *th_zone;
351
352 if (!sensor_conf || !sensor_conf->read_temperature) {
353 pr_err("Temperature sensor not initialised\n");
354 return -EINVAL;
355 }
356
357 th_zone = devm_kzalloc(sensor_conf->dev,
358 sizeof(struct exynos_thermal_zone), GFP_KERNEL);
359 if (!th_zone)
360 return -ENOMEM;
361
362 th_zone->sensor_conf = sensor_conf;
363 /*
364 * TODO: 1) Handle multiple cooling devices in a thermal zone
365 * 2) Add a flag/name in cooling info to map to specific
366 * sensor
367 */
368 if (sensor_conf->cooling_data.freq_clip_count > 0) {
369 th_zone->cool_dev[th_zone->cool_dev_size] =
370 cpufreq_cooling_register(cpu_present_mask);
371 if (IS_ERR(th_zone->cool_dev[th_zone->cool_dev_size])) {
372 ret = PTR_ERR(th_zone->cool_dev[th_zone->cool_dev_size]);
373 if (ret != -EPROBE_DEFER)
374 dev_err(sensor_conf->dev,
375 "Failed to register cpufreq cooling device: %d\n",
376 ret);
377 goto err_unregister;
378 }
379 th_zone->cool_dev_size++;
380 }
381
382 th_zone->therm_dev = thermal_zone_device_register(
383 sensor_conf->name, sensor_conf->trip_data.trip_count,
384 0, th_zone, &exynos_dev_ops, NULL, 0,
385 sensor_conf->trip_data.trigger_falling ? 0 :
386 IDLE_INTERVAL);
387
388 if (IS_ERR(th_zone->therm_dev)) {
389 dev_err(sensor_conf->dev,
390 "Failed to register thermal zone device\n");
391 ret = PTR_ERR(th_zone->therm_dev);
392 goto err_unregister;
393 }
394 th_zone->mode = THERMAL_DEVICE_ENABLED;
395 sensor_conf->pzone_data = th_zone;
396
397 dev_info(sensor_conf->dev,
398 "Exynos: Thermal zone(%s) registered\n", sensor_conf->name);
399
400 return 0;
401
402err_unregister:
403 exynos_unregister_thermal(sensor_conf);
404 return ret;
405}
406
407/* Un-Register with the in-kernel thermal management */
408void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf)
409{
410 int i;
411 struct exynos_thermal_zone *th_zone;
412
413 if (!sensor_conf || !sensor_conf->pzone_data) {
414 pr_err("Invalid temperature sensor configuration data\n");
415 return;
416 }
417
418 th_zone = sensor_conf->pzone_data;
419
420 thermal_zone_device_unregister(th_zone->therm_dev);
421
422 for (i = 0; i < th_zone->cool_dev_size; ++i)
423 cpufreq_cooling_unregister(th_zone->cool_dev[i]);
424
425 dev_info(sensor_conf->dev,
426 "Exynos: Kernel Thermal management unregistered\n");
427}
diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
deleted file mode 100644
index cd4471925cdd..000000000000
--- a/drivers/thermal/samsung/exynos_thermal_common.h
+++ /dev/null
@@ -1,106 +0,0 @@
1/*
2 * exynos_thermal_common.h - Samsung EXYNOS common header file
3 *
4 * Copyright (C) 2013 Samsung Electronics
5 * Amit Daniel Kachhap <amit.daniel@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#ifndef _EXYNOS_THERMAL_COMMON_H
24#define _EXYNOS_THERMAL_COMMON_H
25
26/* In-kernel thermal framework related macros & definations */
27#define SENSOR_NAME_LEN 16
28#define MAX_TRIP_COUNT 8
29#define MAX_COOLING_DEVICE 4
30
31#define ACTIVE_INTERVAL 500
32#define IDLE_INTERVAL 10000
33#define MCELSIUS 1000
34
35/* CPU Zone information */
36#define PANIC_ZONE 4
37#define WARN_ZONE 3
38#define MONITOR_ZONE 2
39#define SAFE_ZONE 1
40
41#define GET_ZONE(trip) (trip + 2)
42#define GET_TRIP(zone) (zone - 2)
43
44enum trigger_type {
45 THROTTLE_ACTIVE = 1,
46 THROTTLE_PASSIVE,
47 SW_TRIP,
48 HW_TRIP,
49};
50
51/**
52 * struct freq_clip_table
53 * @freq_clip_max: maximum frequency allowed for this cooling state.
54 * @temp_level: Temperature level at which the temperature clipping will
55 * happen.
56 * @mask_val: cpumask of the allowed cpu's where the clipping will take place.
57 *
58 * This structure is required to be filled and passed to the
59 * cpufreq_cooling_unregister function.
60 */
61struct freq_clip_table {
62 unsigned int freq_clip_max;
63 unsigned int temp_level;
64 const struct cpumask *mask_val;
65};
66
67struct thermal_trip_point_conf {
68 int trip_val[MAX_TRIP_COUNT];
69 int trip_type[MAX_TRIP_COUNT];
70 int trip_count;
71 unsigned char trigger_falling;
72};
73
74struct thermal_cooling_conf {
75 struct freq_clip_table freq_data[MAX_TRIP_COUNT];
76 int freq_clip_count;
77};
78
79struct thermal_sensor_conf {
80 char name[SENSOR_NAME_LEN];
81 int (*read_temperature)(void *data);
82 int (*write_emul_temp)(void *drv_data, unsigned long temp);
83 struct thermal_trip_point_conf trip_data;
84 struct thermal_cooling_conf cooling_data;
85 void *driver_data;
86 void *pzone_data;
87 struct device *dev;
88};
89
90/*Functions used exynos based thermal sensor driver*/
91#ifdef CONFIG_EXYNOS_THERMAL_CORE
92void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf);
93int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
94void exynos_report_trigger(struct thermal_sensor_conf *sensor_conf);
95#else
96static inline void
97exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf) { return; }
98
99static inline int
100exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
101
102static inline void
103exynos_report_trigger(struct thermal_sensor_conf *sensor_conf) { return; }
104
105#endif /* CONFIG_EXYNOS_THERMAL_CORE */
106#endif /* _EXYNOS_THERMAL_COMMON_H */
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index d2f1e62a4232..fbeedc072cc2 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -1,6 +1,10 @@
1/* 1/*
2 * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit) 2 * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
3 * 3 *
4 * Copyright (C) 2014 Samsung Electronics
5 * Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
6 * Lukasz Majewski <l.majewski@samsung.com>
7 *
4 * Copyright (C) 2011 Samsung Electronics 8 * Copyright (C) 2011 Samsung Electronics
5 * Donggeun Kim <dg77.kim@samsung.com> 9 * Donggeun Kim <dg77.kim@samsung.com>
6 * Amit Daniel Kachhap <amit.kachhap@linaro.org> 10 * Amit Daniel Kachhap <amit.kachhap@linaro.org>
@@ -31,8 +35,8 @@
31#include <linux/platform_device.h> 35#include <linux/platform_device.h>
32#include <linux/regulator/consumer.h> 36#include <linux/regulator/consumer.h>
33 37
34#include "exynos_thermal_common.h"
35#include "exynos_tmu.h" 38#include "exynos_tmu.h"
39#include "../thermal_core.h"
36 40
37/* Exynos generic registers */ 41/* Exynos generic registers */
38#define EXYNOS_TMU_REG_TRIMINFO 0x0 42#define EXYNOS_TMU_REG_TRIMINFO 0x0
@@ -115,6 +119,27 @@
115#define EXYNOS5440_TMU_TH_RISE4_SHIFT 24 119#define EXYNOS5440_TMU_TH_RISE4_SHIFT 24
116#define EXYNOS5440_EFUSE_SWAP_OFFSET 8 120#define EXYNOS5440_EFUSE_SWAP_OFFSET 8
117 121
122/* Exynos7 specific registers */
123#define EXYNOS7_THD_TEMP_RISE7_6 0x50
124#define EXYNOS7_THD_TEMP_FALL7_6 0x60
125#define EXYNOS7_TMU_REG_INTEN 0x110
126#define EXYNOS7_TMU_REG_INTPEND 0x118
127#define EXYNOS7_TMU_REG_EMUL_CON 0x160
128
129#define EXYNOS7_TMU_TEMP_MASK 0x1ff
130#define EXYNOS7_PD_DET_EN_SHIFT 23
131#define EXYNOS7_TMU_INTEN_RISE0_SHIFT 0
132#define EXYNOS7_TMU_INTEN_RISE1_SHIFT 1
133#define EXYNOS7_TMU_INTEN_RISE2_SHIFT 2
134#define EXYNOS7_TMU_INTEN_RISE3_SHIFT 3
135#define EXYNOS7_TMU_INTEN_RISE4_SHIFT 4
136#define EXYNOS7_TMU_INTEN_RISE5_SHIFT 5
137#define EXYNOS7_TMU_INTEN_RISE6_SHIFT 6
138#define EXYNOS7_TMU_INTEN_RISE7_SHIFT 7
139#define EXYNOS7_EMUL_DATA_SHIFT 7
140#define EXYNOS7_EMUL_DATA_MASK 0x1ff
141
142#define MCELSIUS 1000
118/** 143/**
119 * struct exynos_tmu_data : A structure to hold the private data of the TMU 144 * struct exynos_tmu_data : A structure to hold the private data of the TMU
120 driver 145 driver
@@ -128,6 +153,7 @@
128 * @lock: lock to implement synchronization. 153 * @lock: lock to implement synchronization.
129 * @clk: pointer to the clock structure. 154 * @clk: pointer to the clock structure.
130 * @clk_sec: pointer to the clock structure for accessing the base_second. 155 * @clk_sec: pointer to the clock structure for accessing the base_second.
156 * @sclk: pointer to the clock structure for accessing the tmu special clk.
131 * @temp_error1: fused value of the first point trim. 157 * @temp_error1: fused value of the first point trim.
132 * @temp_error2: fused value of the second point trim. 158 * @temp_error2: fused value of the second point trim.
133 * @regulator: pointer to the TMU regulator structure. 159 * @regulator: pointer to the TMU regulator structure.
@@ -147,10 +173,11 @@ struct exynos_tmu_data {
147 enum soc_type soc; 173 enum soc_type soc;
148 struct work_struct irq_work; 174 struct work_struct irq_work;
149 struct mutex lock; 175 struct mutex lock;
150 struct clk *clk, *clk_sec; 176 struct clk *clk, *clk_sec, *sclk;
151 u8 temp_error1, temp_error2; 177 u16 temp_error1, temp_error2;
152 struct regulator *regulator; 178 struct regulator *regulator;
153 struct thermal_sensor_conf *reg_conf; 179 struct thermal_zone_device *tzd;
180
154 int (*tmu_initialize)(struct platform_device *pdev); 181 int (*tmu_initialize)(struct platform_device *pdev);
155 void (*tmu_control)(struct platform_device *pdev, bool on); 182 void (*tmu_control)(struct platform_device *pdev, bool on);
156 int (*tmu_read)(struct exynos_tmu_data *data); 183 int (*tmu_read)(struct exynos_tmu_data *data);
@@ -159,6 +186,33 @@ struct exynos_tmu_data {
159 void (*tmu_clear_irqs)(struct exynos_tmu_data *data); 186 void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
160}; 187};
161 188
189static void exynos_report_trigger(struct exynos_tmu_data *p)
190{
191 char data[10], *envp[] = { data, NULL };
192 struct thermal_zone_device *tz = p->tzd;
193 unsigned long temp;
194 unsigned int i;
195
196 if (!tz) {
197 pr_err("No thermal zone device defined\n");
198 return;
199 }
200
201 thermal_zone_device_update(tz);
202
203 mutex_lock(&tz->lock);
204 /* Find the level for which trip happened */
205 for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
206 tz->ops->get_trip_temp(tz, i, &temp);
207 if (tz->last_temperature < temp)
208 break;
209 }
210
211 snprintf(data, sizeof(data), "%u", i);
212 kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, envp);
213 mutex_unlock(&tz->lock);
214}
215
162/* 216/*
163 * TMU treats temperature as a mapped temperature code. 217 * TMU treats temperature as a mapped temperature code.
164 * The temperature is converted differently depending on the calibration type. 218 * The temperature is converted differently depending on the calibration type.
@@ -190,7 +244,7 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
190 * Calculate a temperature value from a temperature code. 244 * Calculate a temperature value from a temperature code.
191 * The unit of the temperature is degree Celsius. 245 * The unit of the temperature is degree Celsius.
192 */ 246 */
193static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code) 247static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code)
194{ 248{
195 struct exynos_tmu_platform_data *pdata = data->pdata; 249 struct exynos_tmu_platform_data *pdata = data->pdata;
196 int temp; 250 int temp;
@@ -234,14 +288,25 @@ static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info)
234 288
235static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling) 289static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling)
236{ 290{
237 struct exynos_tmu_platform_data *pdata = data->pdata; 291 struct thermal_zone_device *tz = data->tzd;
292 const struct thermal_trip * const trips =
293 of_thermal_get_trip_points(tz);
294 unsigned long temp;
238 int i; 295 int i;
239 296
240 for (i = 0; i < pdata->non_hw_trigger_levels; i++) { 297 if (!trips) {
241 u8 temp = pdata->trigger_levels[i]; 298 pr_err("%s: Cannot get trip points from of-thermal.c!\n",
299 __func__);
300 return 0;
301 }
302
303 for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
304 if (trips[i].type == THERMAL_TRIP_CRITICAL)
305 continue;
242 306
307 temp = trips[i].temperature / MCELSIUS;
243 if (falling) 308 if (falling)
244 temp -= pdata->threshold_falling; 309 temp -= (trips[i].hysteresis / MCELSIUS);
245 else 310 else
246 threshold &= ~(0xff << 8 * i); 311 threshold &= ~(0xff << 8 * i);
247 312
@@ -305,9 +370,19 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
305static int exynos4210_tmu_initialize(struct platform_device *pdev) 370static int exynos4210_tmu_initialize(struct platform_device *pdev)
306{ 371{
307 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 372 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
308 struct exynos_tmu_platform_data *pdata = data->pdata; 373 struct thermal_zone_device *tz = data->tzd;
309 unsigned int status; 374 const struct thermal_trip * const trips =
375 of_thermal_get_trip_points(tz);
310 int ret = 0, threshold_code, i; 376 int ret = 0, threshold_code, i;
377 unsigned long reference, temp;
378 unsigned int status;
379
380 if (!trips) {
381 pr_err("%s: Cannot get trip points from of-thermal.c!\n",
382 __func__);
383 ret = -ENODEV;
384 goto out;
385 }
311 386
312 status = readb(data->base + EXYNOS_TMU_REG_STATUS); 387 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
313 if (!status) { 388 if (!status) {
@@ -318,12 +393,19 @@ static int exynos4210_tmu_initialize(struct platform_device *pdev)
318 sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO)); 393 sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO));
319 394
320 /* Write temperature code for threshold */ 395 /* Write temperature code for threshold */
321 threshold_code = temp_to_code(data, pdata->threshold); 396 reference = trips[0].temperature / MCELSIUS;
397 threshold_code = temp_to_code(data, reference);
398 if (threshold_code < 0) {
399 ret = threshold_code;
400 goto out;
401 }
322 writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP); 402 writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
323 403
324 for (i = 0; i < pdata->non_hw_trigger_levels; i++) 404 for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
325 writeb(pdata->trigger_levels[i], data->base + 405 temp = trips[i].temperature / MCELSIUS;
406 writeb(temp - reference, data->base +
326 EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4); 407 EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
408 }
327 409
328 data->tmu_clear_irqs(data); 410 data->tmu_clear_irqs(data);
329out: 411out:
@@ -333,9 +415,11 @@ out:
333static int exynos4412_tmu_initialize(struct platform_device *pdev) 415static int exynos4412_tmu_initialize(struct platform_device *pdev)
334{ 416{
335 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 417 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
336 struct exynos_tmu_platform_data *pdata = data->pdata; 418 const struct thermal_trip * const trips =
419 of_thermal_get_trip_points(data->tzd);
337 unsigned int status, trim_info, con, ctrl, rising_threshold; 420 unsigned int status, trim_info, con, ctrl, rising_threshold;
338 int ret = 0, threshold_code, i; 421 int ret = 0, threshold_code, i;
422 unsigned long crit_temp = 0;
339 423
340 status = readb(data->base + EXYNOS_TMU_REG_STATUS); 424 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
341 if (!status) { 425 if (!status) {
@@ -373,17 +457,29 @@ static int exynos4412_tmu_initialize(struct platform_device *pdev)
373 data->tmu_clear_irqs(data); 457 data->tmu_clear_irqs(data);
374 458
375 /* if last threshold limit is also present */ 459 /* if last threshold limit is also present */
376 i = pdata->max_trigger_level - 1; 460 for (i = 0; i < of_thermal_get_ntrips(data->tzd); i++) {
377 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) { 461 if (trips[i].type == THERMAL_TRIP_CRITICAL) {
378 threshold_code = temp_to_code(data, pdata->trigger_levels[i]); 462 crit_temp = trips[i].temperature;
379 /* 1-4 level to be assigned in th0 reg */ 463 break;
380 rising_threshold &= ~(0xff << 8 * i); 464 }
381 rising_threshold |= threshold_code << 8 * i;
382 writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
383 con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
384 con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
385 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
386 } 465 }
466
467 if (i == of_thermal_get_ntrips(data->tzd)) {
468 pr_err("%s: No CRITICAL trip point defined at of-thermal.c!\n",
469 __func__);
470 ret = -EINVAL;
471 goto out;
472 }
473
474 threshold_code = temp_to_code(data, crit_temp / MCELSIUS);
475 /* 1-4 level to be assigned in th0 reg */
476 rising_threshold &= ~(0xff << 8 * i);
477 rising_threshold |= threshold_code << 8 * i;
478 writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
479 con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
480 con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
481 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
482
387out: 483out:
388 return ret; 484 return ret;
389} 485}
@@ -391,9 +487,9 @@ out:
391static int exynos5440_tmu_initialize(struct platform_device *pdev) 487static int exynos5440_tmu_initialize(struct platform_device *pdev)
392{ 488{
393 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 489 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
394 struct exynos_tmu_platform_data *pdata = data->pdata;
395 unsigned int trim_info = 0, con, rising_threshold; 490 unsigned int trim_info = 0, con, rising_threshold;
396 int ret = 0, threshold_code, i; 491 int ret = 0, threshold_code;
492 unsigned long crit_temp = 0;
397 493
398 /* 494 /*
399 * For exynos5440 soc triminfo value is swapped between TMU0 and 495 * For exynos5440 soc triminfo value is swapped between TMU0 and
@@ -422,9 +518,8 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev)
422 data->tmu_clear_irqs(data); 518 data->tmu_clear_irqs(data);
423 519
424 /* if last threshold limit is also present */ 520 /* if last threshold limit is also present */
425 i = pdata->max_trigger_level - 1; 521 if (!data->tzd->ops->get_crit_temp(data->tzd, &crit_temp)) {
426 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) { 522 threshold_code = temp_to_code(data, crit_temp / MCELSIUS);
427 threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
428 /* 5th level to be assigned in th2 reg */ 523 /* 5th level to be assigned in th2 reg */
429 rising_threshold = 524 rising_threshold =
430 threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT; 525 threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT;
@@ -439,10 +534,88 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev)
439 return ret; 534 return ret;
440} 535}
441 536
442static void exynos4210_tmu_control(struct platform_device *pdev, bool on) 537static int exynos7_tmu_initialize(struct platform_device *pdev)
443{ 538{
444 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 539 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
540 struct thermal_zone_device *tz = data->tzd;
445 struct exynos_tmu_platform_data *pdata = data->pdata; 541 struct exynos_tmu_platform_data *pdata = data->pdata;
542 unsigned int status, trim_info;
543 unsigned int rising_threshold = 0, falling_threshold = 0;
544 int ret = 0, threshold_code, i;
545 unsigned long temp, temp_hist;
546 unsigned int reg_off, bit_off;
547
548 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
549 if (!status) {
550 ret = -EBUSY;
551 goto out;
552 }
553
554 trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
555
556 data->temp_error1 = trim_info & EXYNOS7_TMU_TEMP_MASK;
557 if (!data->temp_error1 ||
558 (pdata->min_efuse_value > data->temp_error1) ||
559 (data->temp_error1 > pdata->max_efuse_value))
560 data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
561
562 /* Write temperature code for rising and falling threshold */
563 for (i = (of_thermal_get_ntrips(tz) - 1); i >= 0; i--) {
564 /*
565 * On exynos7 there are 4 rising and 4 falling threshold
566 * registers (0x50-0x5c and 0x60-0x6c respectively). Each
567 * register holds the value of two threshold levels (at bit
568 * offsets 0 and 16). Based on the fact that there are atmost
569 * eight possible trigger levels, calculate the register and
570 * bit offsets where the threshold levels are to be written.
571 *
572 * e.g. EXYNOS7_THD_TEMP_RISE7_6 (0x50)
573 * [24:16] - Threshold level 7
574 * [8:0] - Threshold level 6
575 * e.g. EXYNOS7_THD_TEMP_RISE5_4 (0x54)
576 * [24:16] - Threshold level 5
577 * [8:0] - Threshold level 4
578 *
579 * and similarly for falling thresholds.
580 *
581 * Based on the above, calculate the register and bit offsets
582 * for rising/falling threshold levels and populate them.
583 */
584 reg_off = ((7 - i) / 2) * 4;
585 bit_off = ((8 - i) % 2);
586
587 tz->ops->get_trip_temp(tz, i, &temp);
588 temp /= MCELSIUS;
589
590 tz->ops->get_trip_hyst(tz, i, &temp_hist);
591 temp_hist = temp - (temp_hist / MCELSIUS);
592
593 /* Set 9-bit temperature code for rising threshold levels */
594 threshold_code = temp_to_code(data, temp);
595 rising_threshold = readl(data->base +
596 EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
597 rising_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
598 rising_threshold |= threshold_code << (16 * bit_off);
599 writel(rising_threshold,
600 data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
601
602 /* Set 9-bit temperature code for falling threshold levels */
603 threshold_code = temp_to_code(data, temp_hist);
604 falling_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
605 falling_threshold |= threshold_code << (16 * bit_off);
606 writel(falling_threshold,
607 data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off);
608 }
609
610 data->tmu_clear_irqs(data);
611out:
612 return ret;
613}
614
615static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
616{
617 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
618 struct thermal_zone_device *tz = data->tzd;
446 unsigned int con, interrupt_en; 619 unsigned int con, interrupt_en;
447 620
448 con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); 621 con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
@@ -450,10 +623,15 @@ static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
450 if (on) { 623 if (on) {
451 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); 624 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
452 interrupt_en = 625 interrupt_en =
453 pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT | 626 (of_thermal_is_trip_valid(tz, 3)
454 pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT | 627 << EXYNOS_TMU_INTEN_RISE3_SHIFT) |
455 pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT | 628 (of_thermal_is_trip_valid(tz, 2)
456 pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT; 629 << EXYNOS_TMU_INTEN_RISE2_SHIFT) |
630 (of_thermal_is_trip_valid(tz, 1)
631 << EXYNOS_TMU_INTEN_RISE1_SHIFT) |
632 (of_thermal_is_trip_valid(tz, 0)
633 << EXYNOS_TMU_INTEN_RISE0_SHIFT);
634
457 if (data->soc != SOC_ARCH_EXYNOS4210) 635 if (data->soc != SOC_ARCH_EXYNOS4210)
458 interrupt_en |= 636 interrupt_en |=
459 interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT; 637 interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
@@ -468,7 +646,7 @@ static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
468static void exynos5440_tmu_control(struct platform_device *pdev, bool on) 646static void exynos5440_tmu_control(struct platform_device *pdev, bool on)
469{ 647{
470 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 648 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
471 struct exynos_tmu_platform_data *pdata = data->pdata; 649 struct thermal_zone_device *tz = data->tzd;
472 unsigned int con, interrupt_en; 650 unsigned int con, interrupt_en;
473 651
474 con = get_con_reg(data, readl(data->base + EXYNOS5440_TMU_S0_7_CTRL)); 652 con = get_con_reg(data, readl(data->base + EXYNOS5440_TMU_S0_7_CTRL));
@@ -476,11 +654,16 @@ static void exynos5440_tmu_control(struct platform_device *pdev, bool on)
476 if (on) { 654 if (on) {
477 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); 655 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
478 interrupt_en = 656 interrupt_en =
479 pdata->trigger_enable[3] << EXYNOS5440_TMU_INTEN_RISE3_SHIFT | 657 (of_thermal_is_trip_valid(tz, 3)
480 pdata->trigger_enable[2] << EXYNOS5440_TMU_INTEN_RISE2_SHIFT | 658 << EXYNOS5440_TMU_INTEN_RISE3_SHIFT) |
481 pdata->trigger_enable[1] << EXYNOS5440_TMU_INTEN_RISE1_SHIFT | 659 (of_thermal_is_trip_valid(tz, 2)
482 pdata->trigger_enable[0] << EXYNOS5440_TMU_INTEN_RISE0_SHIFT; 660 << EXYNOS5440_TMU_INTEN_RISE2_SHIFT) |
483 interrupt_en |= interrupt_en << EXYNOS5440_TMU_INTEN_FALL0_SHIFT; 661 (of_thermal_is_trip_valid(tz, 1)
662 << EXYNOS5440_TMU_INTEN_RISE1_SHIFT) |
663 (of_thermal_is_trip_valid(tz, 0)
664 << EXYNOS5440_TMU_INTEN_RISE0_SHIFT);
665 interrupt_en |=
666 interrupt_en << EXYNOS5440_TMU_INTEN_FALL0_SHIFT;
484 } else { 667 } else {
485 con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); 668 con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
486 interrupt_en = 0; /* Disable all interrupts */ 669 interrupt_en = 0; /* Disable all interrupts */
@@ -489,19 +672,62 @@ static void exynos5440_tmu_control(struct platform_device *pdev, bool on)
489 writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL); 672 writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
490} 673}
491 674
492static int exynos_tmu_read(struct exynos_tmu_data *data) 675static void exynos7_tmu_control(struct platform_device *pdev, bool on)
493{ 676{
494 int ret; 677 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
678 struct thermal_zone_device *tz = data->tzd;
679 unsigned int con, interrupt_en;
680
681 con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
682
683 if (on) {
684 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
685 interrupt_en =
686 (of_thermal_is_trip_valid(tz, 7)
687 << EXYNOS7_TMU_INTEN_RISE7_SHIFT) |
688 (of_thermal_is_trip_valid(tz, 6)
689 << EXYNOS7_TMU_INTEN_RISE6_SHIFT) |
690 (of_thermal_is_trip_valid(tz, 5)
691 << EXYNOS7_TMU_INTEN_RISE5_SHIFT) |
692 (of_thermal_is_trip_valid(tz, 4)
693 << EXYNOS7_TMU_INTEN_RISE4_SHIFT) |
694 (of_thermal_is_trip_valid(tz, 3)
695 << EXYNOS7_TMU_INTEN_RISE3_SHIFT) |
696 (of_thermal_is_trip_valid(tz, 2)
697 << EXYNOS7_TMU_INTEN_RISE2_SHIFT) |
698 (of_thermal_is_trip_valid(tz, 1)
699 << EXYNOS7_TMU_INTEN_RISE1_SHIFT) |
700 (of_thermal_is_trip_valid(tz, 0)
701 << EXYNOS7_TMU_INTEN_RISE0_SHIFT);
702
703 interrupt_en |=
704 interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
705 } else {
706 con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
707 interrupt_en = 0; /* Disable all interrupts */
708 }
709 con |= 1 << EXYNOS7_PD_DET_EN_SHIFT;
710
711 writel(interrupt_en, data->base + EXYNOS7_TMU_REG_INTEN);
712 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
713}
714
715static int exynos_get_temp(void *p, long *temp)
716{
717 struct exynos_tmu_data *data = p;
718
719 if (!data)
720 return -EINVAL;
495 721
496 mutex_lock(&data->lock); 722 mutex_lock(&data->lock);
497 clk_enable(data->clk); 723 clk_enable(data->clk);
498 ret = data->tmu_read(data); 724
499 if (ret >= 0) 725 *temp = code_to_temp(data, data->tmu_read(data)) * MCELSIUS;
500 ret = code_to_temp(data, ret); 726
501 clk_disable(data->clk); 727 clk_disable(data->clk);
502 mutex_unlock(&data->lock); 728 mutex_unlock(&data->lock);
503 729
504 return ret; 730 return 0;
505} 731}
506 732
507#ifdef CONFIG_THERMAL_EMULATION 733#ifdef CONFIG_THERMAL_EMULATION
@@ -515,9 +741,19 @@ static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
515 val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT); 741 val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT);
516 val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT); 742 val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT);
517 } 743 }
518 val &= ~(EXYNOS_EMUL_DATA_MASK << EXYNOS_EMUL_DATA_SHIFT); 744 if (data->soc == SOC_ARCH_EXYNOS7) {
519 val |= (temp_to_code(data, temp) << EXYNOS_EMUL_DATA_SHIFT) | 745 val &= ~(EXYNOS7_EMUL_DATA_MASK <<
520 EXYNOS_EMUL_ENABLE; 746 EXYNOS7_EMUL_DATA_SHIFT);
747 val |= (temp_to_code(data, temp) <<
748 EXYNOS7_EMUL_DATA_SHIFT) |
749 EXYNOS_EMUL_ENABLE;
750 } else {
751 val &= ~(EXYNOS_EMUL_DATA_MASK <<
752 EXYNOS_EMUL_DATA_SHIFT);
753 val |= (temp_to_code(data, temp) <<
754 EXYNOS_EMUL_DATA_SHIFT) |
755 EXYNOS_EMUL_ENABLE;
756 }
521 } else { 757 } else {
522 val &= ~EXYNOS_EMUL_ENABLE; 758 val &= ~EXYNOS_EMUL_ENABLE;
523 } 759 }
@@ -533,6 +769,8 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
533 769
534 if (data->soc == SOC_ARCH_EXYNOS5260) 770 if (data->soc == SOC_ARCH_EXYNOS5260)
535 emul_con = EXYNOS5260_EMUL_CON; 771 emul_con = EXYNOS5260_EMUL_CON;
772 else if (data->soc == SOC_ARCH_EXYNOS7)
773 emul_con = EXYNOS7_TMU_REG_EMUL_CON;
536 else 774 else
537 emul_con = EXYNOS_EMUL_CON; 775 emul_con = EXYNOS_EMUL_CON;
538 776
@@ -576,7 +814,7 @@ out:
576#define exynos5440_tmu_set_emulation NULL 814#define exynos5440_tmu_set_emulation NULL
577static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp) 815static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
578 { return -EINVAL; } 816 { return -EINVAL; }
579#endif/*CONFIG_THERMAL_EMULATION*/ 817#endif /* CONFIG_THERMAL_EMULATION */
580 818
581static int exynos4210_tmu_read(struct exynos_tmu_data *data) 819static int exynos4210_tmu_read(struct exynos_tmu_data *data)
582{ 820{
@@ -596,6 +834,12 @@ static int exynos5440_tmu_read(struct exynos_tmu_data *data)
596 return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP); 834 return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP);
597} 835}
598 836
837static int exynos7_tmu_read(struct exynos_tmu_data *data)
838{
839 return readw(data->base + EXYNOS_TMU_REG_CURRENT_TEMP) &
840 EXYNOS7_TMU_TEMP_MASK;
841}
842
599static void exynos_tmu_work(struct work_struct *work) 843static void exynos_tmu_work(struct work_struct *work)
600{ 844{
601 struct exynos_tmu_data *data = container_of(work, 845 struct exynos_tmu_data *data = container_of(work,
@@ -613,7 +857,7 @@ static void exynos_tmu_work(struct work_struct *work)
613 if (!IS_ERR(data->clk_sec)) 857 if (!IS_ERR(data->clk_sec))
614 clk_disable(data->clk_sec); 858 clk_disable(data->clk_sec);
615 859
616 exynos_report_trigger(data->reg_conf); 860 exynos_report_trigger(data);
617 mutex_lock(&data->lock); 861 mutex_lock(&data->lock);
618 clk_enable(data->clk); 862 clk_enable(data->clk);
619 863
@@ -634,6 +878,9 @@ static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data)
634 if (data->soc == SOC_ARCH_EXYNOS5260) { 878 if (data->soc == SOC_ARCH_EXYNOS5260) {
635 tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT; 879 tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT;
636 tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR; 880 tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR;
881 } else if (data->soc == SOC_ARCH_EXYNOS7) {
882 tmu_intstat = EXYNOS7_TMU_REG_INTPEND;
883 tmu_intclear = EXYNOS7_TMU_REG_INTPEND;
637 } else { 884 } else {
638 tmu_intstat = EXYNOS_TMU_REG_INTSTAT; 885 tmu_intstat = EXYNOS_TMU_REG_INTSTAT;
639 tmu_intclear = EXYNOS_TMU_REG_INTCLEAR; 886 tmu_intclear = EXYNOS_TMU_REG_INTCLEAR;
@@ -673,55 +920,94 @@ static irqreturn_t exynos_tmu_irq(int irq, void *id)
673static const struct of_device_id exynos_tmu_match[] = { 920static const struct of_device_id exynos_tmu_match[] = {
674 { 921 {
675 .compatible = "samsung,exynos3250-tmu", 922 .compatible = "samsung,exynos3250-tmu",
676 .data = &exynos3250_default_tmu_data,
677 }, 923 },
678 { 924 {
679 .compatible = "samsung,exynos4210-tmu", 925 .compatible = "samsung,exynos4210-tmu",
680 .data = &exynos4210_default_tmu_data,
681 }, 926 },
682 { 927 {
683 .compatible = "samsung,exynos4412-tmu", 928 .compatible = "samsung,exynos4412-tmu",
684 .data = &exynos4412_default_tmu_data,
685 }, 929 },
686 { 930 {
687 .compatible = "samsung,exynos5250-tmu", 931 .compatible = "samsung,exynos5250-tmu",
688 .data = &exynos5250_default_tmu_data,
689 }, 932 },
690 { 933 {
691 .compatible = "samsung,exynos5260-tmu", 934 .compatible = "samsung,exynos5260-tmu",
692 .data = &exynos5260_default_tmu_data,
693 }, 935 },
694 { 936 {
695 .compatible = "samsung,exynos5420-tmu", 937 .compatible = "samsung,exynos5420-tmu",
696 .data = &exynos5420_default_tmu_data,
697 }, 938 },
698 { 939 {
699 .compatible = "samsung,exynos5420-tmu-ext-triminfo", 940 .compatible = "samsung,exynos5420-tmu-ext-triminfo",
700 .data = &exynos5420_default_tmu_data,
701 }, 941 },
702 { 942 {
703 .compatible = "samsung,exynos5440-tmu", 943 .compatible = "samsung,exynos5440-tmu",
704 .data = &exynos5440_default_tmu_data, 944 },
945 {
946 .compatible = "samsung,exynos7-tmu",
705 }, 947 },
706 {}, 948 {},
707}; 949};
708MODULE_DEVICE_TABLE(of, exynos_tmu_match); 950MODULE_DEVICE_TABLE(of, exynos_tmu_match);
709 951
710static inline struct exynos_tmu_platform_data *exynos_get_driver_data( 952static int exynos_of_get_soc_type(struct device_node *np)
711 struct platform_device *pdev, int id) 953{
954 if (of_device_is_compatible(np, "samsung,exynos3250-tmu"))
955 return SOC_ARCH_EXYNOS3250;
956 else if (of_device_is_compatible(np, "samsung,exynos4210-tmu"))
957 return SOC_ARCH_EXYNOS4210;
958 else if (of_device_is_compatible(np, "samsung,exynos4412-tmu"))
959 return SOC_ARCH_EXYNOS4412;
960 else if (of_device_is_compatible(np, "samsung,exynos5250-tmu"))
961 return SOC_ARCH_EXYNOS5250;
962 else if (of_device_is_compatible(np, "samsung,exynos5260-tmu"))
963 return SOC_ARCH_EXYNOS5260;
964 else if (of_device_is_compatible(np, "samsung,exynos5420-tmu"))
965 return SOC_ARCH_EXYNOS5420;
966 else if (of_device_is_compatible(np,
967 "samsung,exynos5420-tmu-ext-triminfo"))
968 return SOC_ARCH_EXYNOS5420_TRIMINFO;
969 else if (of_device_is_compatible(np, "samsung,exynos5440-tmu"))
970 return SOC_ARCH_EXYNOS5440;
971 else if (of_device_is_compatible(np, "samsung,exynos7-tmu"))
972 return SOC_ARCH_EXYNOS7;
973
974 return -EINVAL;
975}
976
977static int exynos_of_sensor_conf(struct device_node *np,
978 struct exynos_tmu_platform_data *pdata)
712{ 979{
713 struct exynos_tmu_init_data *data_table; 980 u32 value;
714 struct exynos_tmu_platform_data *tmu_data; 981 int ret;
715 const struct of_device_id *match;
716 982
717 match = of_match_node(exynos_tmu_match, pdev->dev.of_node); 983 of_node_get(np);
718 if (!match) 984
719 return NULL; 985 ret = of_property_read_u32(np, "samsung,tmu_gain", &value);
720 data_table = (struct exynos_tmu_init_data *) match->data; 986 pdata->gain = (u8)value;
721 if (!data_table || id >= data_table->tmu_count) 987 of_property_read_u32(np, "samsung,tmu_reference_voltage", &value);
722 return NULL; 988 pdata->reference_voltage = (u8)value;
723 tmu_data = data_table->tmu_data; 989 of_property_read_u32(np, "samsung,tmu_noise_cancel_mode", &value);
724 return (struct exynos_tmu_platform_data *) (tmu_data + id); 990 pdata->noise_cancel_mode = (u8)value;
991
992 of_property_read_u32(np, "samsung,tmu_efuse_value",
993 &pdata->efuse_value);
994 of_property_read_u32(np, "samsung,tmu_min_efuse_value",
995 &pdata->min_efuse_value);
996 of_property_read_u32(np, "samsung,tmu_max_efuse_value",
997 &pdata->max_efuse_value);
998
999 of_property_read_u32(np, "samsung,tmu_first_point_trim", &value);
1000 pdata->first_point_trim = (u8)value;
1001 of_property_read_u32(np, "samsung,tmu_second_point_trim", &value);
1002 pdata->second_point_trim = (u8)value;
1003 of_property_read_u32(np, "samsung,tmu_default_temp_offset", &value);
1004 pdata->default_temp_offset = (u8)value;
1005
1006 of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type);
1007 of_property_read_u32(np, "samsung,tmu_cal_mode", &pdata->cal_mode);
1008
1009 of_node_put(np);
1010 return 0;
725} 1011}
726 1012
727static int exynos_map_dt_data(struct platform_device *pdev) 1013static int exynos_map_dt_data(struct platform_device *pdev)
@@ -771,14 +1057,15 @@ static int exynos_map_dt_data(struct platform_device *pdev)
771 return -EADDRNOTAVAIL; 1057 return -EADDRNOTAVAIL;
772 } 1058 }
773 1059
774 pdata = exynos_get_driver_data(pdev, data->id); 1060 pdata = devm_kzalloc(&pdev->dev,
775 if (!pdata) { 1061 sizeof(struct exynos_tmu_platform_data),
776 dev_err(&pdev->dev, "No platform init data supplied.\n"); 1062 GFP_KERNEL);
777 return -ENODEV; 1063 if (!pdata)
778 } 1064 return -ENOMEM;
779 1065
1066 exynos_of_sensor_conf(pdev->dev.of_node, pdata);
780 data->pdata = pdata; 1067 data->pdata = pdata;
781 data->soc = pdata->type; 1068 data->soc = exynos_of_get_soc_type(pdev->dev.of_node);
782 1069
783 switch (data->soc) { 1070 switch (data->soc) {
784 case SOC_ARCH_EXYNOS4210: 1071 case SOC_ARCH_EXYNOS4210:
@@ -806,6 +1093,13 @@ static int exynos_map_dt_data(struct platform_device *pdev)
806 data->tmu_set_emulation = exynos5440_tmu_set_emulation; 1093 data->tmu_set_emulation = exynos5440_tmu_set_emulation;
807 data->tmu_clear_irqs = exynos5440_tmu_clear_irqs; 1094 data->tmu_clear_irqs = exynos5440_tmu_clear_irqs;
808 break; 1095 break;
1096 case SOC_ARCH_EXYNOS7:
1097 data->tmu_initialize = exynos7_tmu_initialize;
1098 data->tmu_control = exynos7_tmu_control;
1099 data->tmu_read = exynos7_tmu_read;
1100 data->tmu_set_emulation = exynos4412_tmu_set_emulation;
1101 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
1102 break;
809 default: 1103 default:
810 dev_err(&pdev->dev, "Platform not supported\n"); 1104 dev_err(&pdev->dev, "Platform not supported\n");
811 return -EINVAL; 1105 return -EINVAL;
@@ -834,12 +1128,16 @@ static int exynos_map_dt_data(struct platform_device *pdev)
834 return 0; 1128 return 0;
835} 1129}
836 1130
1131static struct thermal_zone_of_device_ops exynos_sensor_ops = {
1132 .get_temp = exynos_get_temp,
1133 .set_emul_temp = exynos_tmu_set_emulation,
1134};
1135
837static int exynos_tmu_probe(struct platform_device *pdev) 1136static int exynos_tmu_probe(struct platform_device *pdev)
838{ 1137{
839 struct exynos_tmu_data *data;
840 struct exynos_tmu_platform_data *pdata; 1138 struct exynos_tmu_platform_data *pdata;
841 struct thermal_sensor_conf *sensor_conf; 1139 struct exynos_tmu_data *data;
842 int ret, i; 1140 int ret;
843 1141
844 data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data), 1142 data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
845 GFP_KERNEL); 1143 GFP_KERNEL);
@@ -849,9 +1147,15 @@ static int exynos_tmu_probe(struct platform_device *pdev)
849 platform_set_drvdata(pdev, data); 1147 platform_set_drvdata(pdev, data);
850 mutex_init(&data->lock); 1148 mutex_init(&data->lock);
851 1149
1150 data->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
1151 &exynos_sensor_ops);
1152 if (IS_ERR(data->tzd)) {
1153 pr_err("thermal: tz: %p ERROR\n", data->tzd);
1154 return PTR_ERR(data->tzd);
1155 }
852 ret = exynos_map_dt_data(pdev); 1156 ret = exynos_map_dt_data(pdev);
853 if (ret) 1157 if (ret)
854 return ret; 1158 goto err_sensor;
855 1159
856 pdata = data->pdata; 1160 pdata = data->pdata;
857 1161
@@ -860,20 +1164,22 @@ static int exynos_tmu_probe(struct platform_device *pdev)
860 data->clk = devm_clk_get(&pdev->dev, "tmu_apbif"); 1164 data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
861 if (IS_ERR(data->clk)) { 1165 if (IS_ERR(data->clk)) {
862 dev_err(&pdev->dev, "Failed to get clock\n"); 1166 dev_err(&pdev->dev, "Failed to get clock\n");
863 return PTR_ERR(data->clk); 1167 ret = PTR_ERR(data->clk);
1168 goto err_sensor;
864 } 1169 }
865 1170
866 data->clk_sec = devm_clk_get(&pdev->dev, "tmu_triminfo_apbif"); 1171 data->clk_sec = devm_clk_get(&pdev->dev, "tmu_triminfo_apbif");
867 if (IS_ERR(data->clk_sec)) { 1172 if (IS_ERR(data->clk_sec)) {
868 if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO) { 1173 if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO) {
869 dev_err(&pdev->dev, "Failed to get triminfo clock\n"); 1174 dev_err(&pdev->dev, "Failed to get triminfo clock\n");
870 return PTR_ERR(data->clk_sec); 1175 ret = PTR_ERR(data->clk_sec);
1176 goto err_sensor;
871 } 1177 }
872 } else { 1178 } else {
873 ret = clk_prepare(data->clk_sec); 1179 ret = clk_prepare(data->clk_sec);
874 if (ret) { 1180 if (ret) {
875 dev_err(&pdev->dev, "Failed to get clock\n"); 1181 dev_err(&pdev->dev, "Failed to get clock\n");
876 return ret; 1182 goto err_sensor;
877 } 1183 }
878 } 1184 }
879 1185
@@ -883,82 +1189,57 @@ static int exynos_tmu_probe(struct platform_device *pdev)
883 goto err_clk_sec; 1189 goto err_clk_sec;
884 } 1190 }
885 1191
886 ret = exynos_tmu_initialize(pdev); 1192 if (data->soc == SOC_ARCH_EXYNOS7) {
887 if (ret) { 1193 data->sclk = devm_clk_get(&pdev->dev, "tmu_sclk");
888 dev_err(&pdev->dev, "Failed to initialize TMU\n"); 1194 if (IS_ERR(data->sclk)) {
889 goto err_clk; 1195 dev_err(&pdev->dev, "Failed to get sclk\n");
1196 goto err_clk;
1197 } else {
1198 ret = clk_prepare_enable(data->sclk);
1199 if (ret) {
1200 dev_err(&pdev->dev, "Failed to enable sclk\n");
1201 goto err_clk;
1202 }
1203 }
890 } 1204 }
891 1205
892 exynos_tmu_control(pdev, true); 1206 ret = exynos_tmu_initialize(pdev);
893
894 /* Allocate a structure to register with the exynos core thermal */
895 sensor_conf = devm_kzalloc(&pdev->dev,
896 sizeof(struct thermal_sensor_conf), GFP_KERNEL);
897 if (!sensor_conf) {
898 ret = -ENOMEM;
899 goto err_clk;
900 }
901 sprintf(sensor_conf->name, "therm_zone%d", data->id);
902 sensor_conf->read_temperature = (int (*)(void *))exynos_tmu_read;
903 sensor_conf->write_emul_temp =
904 (int (*)(void *, unsigned long))exynos_tmu_set_emulation;
905 sensor_conf->driver_data = data;
906 sensor_conf->trip_data.trip_count = pdata->trigger_enable[0] +
907 pdata->trigger_enable[1] + pdata->trigger_enable[2]+
908 pdata->trigger_enable[3];
909
910 for (i = 0; i < sensor_conf->trip_data.trip_count; i++) {
911 sensor_conf->trip_data.trip_val[i] =
912 pdata->threshold + pdata->trigger_levels[i];
913 sensor_conf->trip_data.trip_type[i] =
914 pdata->trigger_type[i];
915 }
916
917 sensor_conf->trip_data.trigger_falling = pdata->threshold_falling;
918
919 sensor_conf->cooling_data.freq_clip_count = pdata->freq_tab_count;
920 for (i = 0; i < pdata->freq_tab_count; i++) {
921 sensor_conf->cooling_data.freq_data[i].freq_clip_max =
922 pdata->freq_tab[i].freq_clip_max;
923 sensor_conf->cooling_data.freq_data[i].temp_level =
924 pdata->freq_tab[i].temp_level;
925 }
926 sensor_conf->dev = &pdev->dev;
927 /* Register the sensor with thermal management interface */
928 ret = exynos_register_thermal(sensor_conf);
929 if (ret) { 1207 if (ret) {
930 if (ret != -EPROBE_DEFER) 1208 dev_err(&pdev->dev, "Failed to initialize TMU\n");
931 dev_err(&pdev->dev, 1209 goto err_sclk;
932 "Failed to register thermal interface: %d\n",
933 ret);
934 goto err_clk;
935 } 1210 }
936 data->reg_conf = sensor_conf;
937 1211
938 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq, 1212 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
939 IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data); 1213 IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
940 if (ret) { 1214 if (ret) {
941 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq); 1215 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
942 goto err_clk; 1216 goto err_sclk;
943 } 1217 }
944 1218
1219 exynos_tmu_control(pdev, true);
945 return 0; 1220 return 0;
1221err_sclk:
1222 clk_disable_unprepare(data->sclk);
946err_clk: 1223err_clk:
947 clk_unprepare(data->clk); 1224 clk_unprepare(data->clk);
948err_clk_sec: 1225err_clk_sec:
949 if (!IS_ERR(data->clk_sec)) 1226 if (!IS_ERR(data->clk_sec))
950 clk_unprepare(data->clk_sec); 1227 clk_unprepare(data->clk_sec);
1228err_sensor:
1229 thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd);
1230
951 return ret; 1231 return ret;
952} 1232}
953 1233
954static int exynos_tmu_remove(struct platform_device *pdev) 1234static int exynos_tmu_remove(struct platform_device *pdev)
955{ 1235{
956 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 1236 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
1237 struct thermal_zone_device *tzd = data->tzd;
957 1238
958 exynos_unregister_thermal(data->reg_conf); 1239 thermal_zone_of_sensor_unregister(&pdev->dev, tzd);
959
960 exynos_tmu_control(pdev, false); 1240 exynos_tmu_control(pdev, false);
961 1241
1242 clk_disable_unprepare(data->sclk);
962 clk_unprepare(data->clk); 1243 clk_unprepare(data->clk);
963 if (!IS_ERR(data->clk_sec)) 1244 if (!IS_ERR(data->clk_sec))
964 clk_unprepare(data->clk_sec); 1245 clk_unprepare(data->clk_sec);
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
index da3009bff6c4..4d71ec6c9aa0 100644
--- a/drivers/thermal/samsung/exynos_tmu.h
+++ b/drivers/thermal/samsung/exynos_tmu.h
@@ -23,16 +23,7 @@
23#ifndef _EXYNOS_TMU_H 23#ifndef _EXYNOS_TMU_H
24#define _EXYNOS_TMU_H 24#define _EXYNOS_TMU_H
25#include <linux/cpu_cooling.h> 25#include <linux/cpu_cooling.h>
26 26#include <dt-bindings/thermal/thermal_exynos.h>
27#include "exynos_thermal_common.h"
28
29enum calibration_type {
30 TYPE_ONE_POINT_TRIMMING,
31 TYPE_ONE_POINT_TRIMMING_25,
32 TYPE_ONE_POINT_TRIMMING_85,
33 TYPE_TWO_POINT_TRIMMING,
34 TYPE_NONE,
35};
36 27
37enum soc_type { 28enum soc_type {
38 SOC_ARCH_EXYNOS3250 = 1, 29 SOC_ARCH_EXYNOS3250 = 1,
@@ -43,38 +34,11 @@ enum soc_type {
43 SOC_ARCH_EXYNOS5420, 34 SOC_ARCH_EXYNOS5420,
44 SOC_ARCH_EXYNOS5420_TRIMINFO, 35 SOC_ARCH_EXYNOS5420_TRIMINFO,
45 SOC_ARCH_EXYNOS5440, 36 SOC_ARCH_EXYNOS5440,
37 SOC_ARCH_EXYNOS7,
46}; 38};
47 39
48/** 40/**
49 * struct exynos_tmu_platform_data 41 * struct exynos_tmu_platform_data
50 * @threshold: basic temperature for generating interrupt
51 * 25 <= threshold <= 125 [unit: degree Celsius]
52 * @threshold_falling: differntial value for setting threshold
53 * of temperature falling interrupt.
54 * @trigger_levels: array for each interrupt levels
55 * [unit: degree Celsius]
56 * 0: temperature for trigger_level0 interrupt
57 * condition for trigger_level0 interrupt:
58 * current temperature > threshold + trigger_levels[0]
59 * 1: temperature for trigger_level1 interrupt
60 * condition for trigger_level1 interrupt:
61 * current temperature > threshold + trigger_levels[1]
62 * 2: temperature for trigger_level2 interrupt
63 * condition for trigger_level2 interrupt:
64 * current temperature > threshold + trigger_levels[2]
65 * 3: temperature for trigger_level3 interrupt
66 * condition for trigger_level3 interrupt:
67 * current temperature > threshold + trigger_levels[3]
68 * @trigger_type: defines the type of trigger. Possible values are,
69 * THROTTLE_ACTIVE trigger type
70 * THROTTLE_PASSIVE trigger type
71 * SW_TRIP trigger type
72 * HW_TRIP
73 * @trigger_enable[]: array to denote which trigger levels are enabled.
74 * 1 = enable trigger_level[] interrupt,
75 * 0 = disable trigger_level[] interrupt
76 * @max_trigger_level: max trigger level supported by the TMU
77 * @non_hw_trigger_levels: number of defined non-hardware trigger levels
78 * @gain: gain of amplifier in the positive-TC generator block 42 * @gain: gain of amplifier in the positive-TC generator block
79 * 0 < gain <= 15 43 * 0 < gain <= 15
80 * @reference_voltage: reference voltage of amplifier 44 * @reference_voltage: reference voltage of amplifier
@@ -86,24 +50,12 @@ enum soc_type {
86 * @efuse_value: platform defined fuse value 50 * @efuse_value: platform defined fuse value
87 * @min_efuse_value: minimum valid trimming data 51 * @min_efuse_value: minimum valid trimming data
88 * @max_efuse_value: maximum valid trimming data 52 * @max_efuse_value: maximum valid trimming data
89 * @first_point_trim: temp value of the first point trimming
90 * @second_point_trim: temp value of the second point trimming
91 * @default_temp_offset: default temperature offset in case of no trimming 53 * @default_temp_offset: default temperature offset in case of no trimming
92 * @cal_type: calibration type for temperature 54 * @cal_type: calibration type for temperature
93 * @freq_clip_table: Table representing frequency reduction percentage.
94 * @freq_tab_count: Count of the above table as frequency reduction may
95 * applicable to only some of the trigger levels.
96 * 55 *
97 * This structure is required for configuration of exynos_tmu driver. 56 * This structure is required for configuration of exynos_tmu driver.
98 */ 57 */
99struct exynos_tmu_platform_data { 58struct exynos_tmu_platform_data {
100 u8 threshold;
101 u8 threshold_falling;
102 u8 trigger_levels[MAX_TRIP_COUNT];
103 enum trigger_type trigger_type[MAX_TRIP_COUNT];
104 bool trigger_enable[MAX_TRIP_COUNT];
105 u8 max_trigger_level;
106 u8 non_hw_trigger_levels;
107 u8 gain; 59 u8 gain;
108 u8 reference_voltage; 60 u8 reference_voltage;
109 u8 noise_cancel_mode; 61 u8 noise_cancel_mode;
@@ -115,30 +67,9 @@ struct exynos_tmu_platform_data {
115 u8 second_point_trim; 67 u8 second_point_trim;
116 u8 default_temp_offset; 68 u8 default_temp_offset;
117 69
118 enum calibration_type cal_type;
119 enum soc_type type; 70 enum soc_type type;
120 struct freq_clip_table freq_tab[4]; 71 u32 cal_type;
121 unsigned int freq_tab_count; 72 u32 cal_mode;
122};
123
124/**
125 * struct exynos_tmu_init_data
126 * @tmu_count: number of TMU instances.
127 * @tmu_data: platform data of all TMU instances.
128 * This structure is required to store data for multi-instance exynos tmu
129 * driver.
130 */
131struct exynos_tmu_init_data {
132 int tmu_count;
133 struct exynos_tmu_platform_data tmu_data[];
134}; 73};
135 74
136extern struct exynos_tmu_init_data const exynos3250_default_tmu_data;
137extern struct exynos_tmu_init_data const exynos4210_default_tmu_data;
138extern struct exynos_tmu_init_data const exynos4412_default_tmu_data;
139extern struct exynos_tmu_init_data const exynos5250_default_tmu_data;
140extern struct exynos_tmu_init_data const exynos5260_default_tmu_data;
141extern struct exynos_tmu_init_data const exynos5420_default_tmu_data;
142extern struct exynos_tmu_init_data const exynos5440_default_tmu_data;
143
144#endif /* _EXYNOS_TMU_H */ 75#endif /* _EXYNOS_TMU_H */
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
deleted file mode 100644
index b23910069f68..000000000000
--- a/drivers/thermal/samsung/exynos_tmu_data.c
+++ /dev/null
@@ -1,264 +0,0 @@
1/*
2 * exynos_tmu_data.c - Samsung EXYNOS tmu data file
3 *
4 * Copyright (C) 2013 Samsung Electronics
5 * Amit Daniel Kachhap <amit.daniel@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 "exynos_thermal_common.h"
24#include "exynos_tmu.h"
25
26struct exynos_tmu_init_data const exynos4210_default_tmu_data = {
27 .tmu_data = {
28 {
29 .threshold = 80,
30 .trigger_levels[0] = 5,
31 .trigger_levels[1] = 20,
32 .trigger_levels[2] = 30,
33 .trigger_enable[0] = true,
34 .trigger_enable[1] = true,
35 .trigger_enable[2] = true,
36 .trigger_enable[3] = false,
37 .trigger_type[0] = THROTTLE_ACTIVE,
38 .trigger_type[1] = THROTTLE_ACTIVE,
39 .trigger_type[2] = SW_TRIP,
40 .max_trigger_level = 4,
41 .non_hw_trigger_levels = 3,
42 .gain = 15,
43 .reference_voltage = 7,
44 .cal_type = TYPE_ONE_POINT_TRIMMING,
45 .min_efuse_value = 40,
46 .max_efuse_value = 100,
47 .first_point_trim = 25,
48 .second_point_trim = 85,
49 .default_temp_offset = 50,
50 .freq_tab[0] = {
51 .freq_clip_max = 800 * 1000,
52 .temp_level = 85,
53 },
54 .freq_tab[1] = {
55 .freq_clip_max = 200 * 1000,
56 .temp_level = 100,
57 },
58 .freq_tab_count = 2,
59 .type = SOC_ARCH_EXYNOS4210,
60 },
61 },
62 .tmu_count = 1,
63};
64
65#define EXYNOS3250_TMU_DATA \
66 .threshold_falling = 10, \
67 .trigger_levels[0] = 70, \
68 .trigger_levels[1] = 95, \
69 .trigger_levels[2] = 110, \
70 .trigger_levels[3] = 120, \
71 .trigger_enable[0] = true, \
72 .trigger_enable[1] = true, \
73 .trigger_enable[2] = true, \
74 .trigger_enable[3] = false, \
75 .trigger_type[0] = THROTTLE_ACTIVE, \
76 .trigger_type[1] = THROTTLE_ACTIVE, \
77 .trigger_type[2] = SW_TRIP, \
78 .trigger_type[3] = HW_TRIP, \
79 .max_trigger_level = 4, \
80 .non_hw_trigger_levels = 3, \
81 .gain = 8, \
82 .reference_voltage = 16, \
83 .noise_cancel_mode = 4, \
84 .cal_type = TYPE_TWO_POINT_TRIMMING, \
85 .efuse_value = 55, \
86 .min_efuse_value = 40, \
87 .max_efuse_value = 100, \
88 .first_point_trim = 25, \
89 .second_point_trim = 85, \
90 .default_temp_offset = 50, \
91 .freq_tab[0] = { \
92 .freq_clip_max = 800 * 1000, \
93 .temp_level = 70, \
94 }, \
95 .freq_tab[1] = { \
96 .freq_clip_max = 400 * 1000, \
97 .temp_level = 95, \
98 }, \
99 .freq_tab_count = 2
100
101struct exynos_tmu_init_data const exynos3250_default_tmu_data = {
102 .tmu_data = {
103 {
104 EXYNOS3250_TMU_DATA,
105 .type = SOC_ARCH_EXYNOS3250,
106 },
107 },
108 .tmu_count = 1,
109};
110
111#define EXYNOS4412_TMU_DATA \
112 .threshold_falling = 10, \
113 .trigger_levels[0] = 70, \
114 .trigger_levels[1] = 95, \
115 .trigger_levels[2] = 110, \
116 .trigger_levels[3] = 120, \
117 .trigger_enable[0] = true, \
118 .trigger_enable[1] = true, \
119 .trigger_enable[2] = true, \
120 .trigger_enable[3] = false, \
121 .trigger_type[0] = THROTTLE_ACTIVE, \
122 .trigger_type[1] = THROTTLE_ACTIVE, \
123 .trigger_type[2] = SW_TRIP, \
124 .trigger_type[3] = HW_TRIP, \
125 .max_trigger_level = 4, \
126 .non_hw_trigger_levels = 3, \
127 .gain = 8, \
128 .reference_voltage = 16, \
129 .noise_cancel_mode = 4, \
130 .cal_type = TYPE_ONE_POINT_TRIMMING, \
131 .efuse_value = 55, \
132 .min_efuse_value = 40, \
133 .max_efuse_value = 100, \
134 .first_point_trim = 25, \
135 .second_point_trim = 85, \
136 .default_temp_offset = 50, \
137 .freq_tab[0] = { \
138 .freq_clip_max = 1400 * 1000, \
139 .temp_level = 70, \
140 }, \
141 .freq_tab[1] = { \
142 .freq_clip_max = 400 * 1000, \
143 .temp_level = 95, \
144 }, \
145 .freq_tab_count = 2
146
147struct exynos_tmu_init_data const exynos4412_default_tmu_data = {
148 .tmu_data = {
149 {
150 EXYNOS4412_TMU_DATA,
151 .type = SOC_ARCH_EXYNOS4412,
152 },
153 },
154 .tmu_count = 1,
155};
156
157struct exynos_tmu_init_data const exynos5250_default_tmu_data = {
158 .tmu_data = {
159 {
160 EXYNOS4412_TMU_DATA,
161 .type = SOC_ARCH_EXYNOS5250,
162 },
163 },
164 .tmu_count = 1,
165};
166
167#define __EXYNOS5260_TMU_DATA \
168 .threshold_falling = 10, \
169 .trigger_levels[0] = 85, \
170 .trigger_levels[1] = 103, \
171 .trigger_levels[2] = 110, \
172 .trigger_levels[3] = 120, \
173 .trigger_enable[0] = true, \
174 .trigger_enable[1] = true, \
175 .trigger_enable[2] = true, \
176 .trigger_enable[3] = false, \
177 .trigger_type[0] = THROTTLE_ACTIVE, \
178 .trigger_type[1] = THROTTLE_ACTIVE, \
179 .trigger_type[2] = SW_TRIP, \
180 .trigger_type[3] = HW_TRIP, \
181 .max_trigger_level = 4, \
182 .non_hw_trigger_levels = 3, \
183 .gain = 8, \
184 .reference_voltage = 16, \
185 .noise_cancel_mode = 4, \
186 .cal_type = TYPE_ONE_POINT_TRIMMING, \
187 .efuse_value = 55, \
188 .min_efuse_value = 40, \
189 .max_efuse_value = 100, \
190 .first_point_trim = 25, \
191 .second_point_trim = 85, \
192 .default_temp_offset = 50, \
193 .freq_tab[0] = { \
194 .freq_clip_max = 800 * 1000, \
195 .temp_level = 85, \
196 }, \
197 .freq_tab[1] = { \
198 .freq_clip_max = 200 * 1000, \
199 .temp_level = 103, \
200 }, \
201 .freq_tab_count = 2, \
202
203#define EXYNOS5260_TMU_DATA \
204 __EXYNOS5260_TMU_DATA \
205 .type = SOC_ARCH_EXYNOS5260
206
207struct exynos_tmu_init_data const exynos5260_default_tmu_data = {
208 .tmu_data = {
209 { EXYNOS5260_TMU_DATA },
210 { EXYNOS5260_TMU_DATA },
211 { EXYNOS5260_TMU_DATA },
212 { EXYNOS5260_TMU_DATA },
213 { EXYNOS5260_TMU_DATA },
214 },
215 .tmu_count = 5,
216};
217
218#define EXYNOS5420_TMU_DATA \
219 __EXYNOS5260_TMU_DATA \
220 .type = SOC_ARCH_EXYNOS5420
221
222#define EXYNOS5420_TMU_DATA_SHARED \
223 __EXYNOS5260_TMU_DATA \
224 .type = SOC_ARCH_EXYNOS5420_TRIMINFO
225
226struct exynos_tmu_init_data const exynos5420_default_tmu_data = {
227 .tmu_data = {
228 { EXYNOS5420_TMU_DATA },
229 { EXYNOS5420_TMU_DATA },
230 { EXYNOS5420_TMU_DATA_SHARED },
231 { EXYNOS5420_TMU_DATA_SHARED },
232 { EXYNOS5420_TMU_DATA_SHARED },
233 },
234 .tmu_count = 5,
235};
236
237#define EXYNOS5440_TMU_DATA \
238 .trigger_levels[0] = 100, \
239 .trigger_levels[4] = 105, \
240 .trigger_enable[0] = 1, \
241 .trigger_type[0] = SW_TRIP, \
242 .trigger_type[4] = HW_TRIP, \
243 .max_trigger_level = 5, \
244 .non_hw_trigger_levels = 1, \
245 .gain = 5, \
246 .reference_voltage = 16, \
247 .noise_cancel_mode = 4, \
248 .cal_type = TYPE_ONE_POINT_TRIMMING, \
249 .efuse_value = 0x5b2d, \
250 .min_efuse_value = 16, \
251 .max_efuse_value = 76, \
252 .first_point_trim = 25, \
253 .second_point_trim = 70, \
254 .default_temp_offset = 25, \
255 .type = SOC_ARCH_EXYNOS5440
256
257struct exynos_tmu_init_data const exynos5440_default_tmu_data = {
258 .tmu_data = {
259 { EXYNOS5440_TMU_DATA } ,
260 { EXYNOS5440_TMU_DATA } ,
261 { EXYNOS5440_TMU_DATA } ,
262 },
263 .tmu_count = 3,
264};
diff --git a/include/dt-bindings/thermal/thermal_exynos.h b/include/dt-bindings/thermal/thermal_exynos.h
new file mode 100644
index 000000000000..0646500bca69
--- /dev/null
+++ b/include/dt-bindings/thermal/thermal_exynos.h
@@ -0,0 +1,28 @@
1/*
2 * thermal_exynos.h - Samsung EXYNOS TMU device tree definitions
3 *
4 * Copyright (C) 2014 Samsung Electronics
5 * Lukasz Majewski <l.majewski@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 */
18
19#ifndef _EXYNOS_THERMAL_TMU_DT_H
20#define _EXYNOS_THERMAL_TMU_DT_H
21
22#define TYPE_ONE_POINT_TRIMMING 0
23#define TYPE_ONE_POINT_TRIMMING_25 1
24#define TYPE_ONE_POINT_TRIMMING_85 2
25#define TYPE_TWO_POINT_TRIMMING 3
26#define TYPE_NONE 4
27
28#endif /* _EXYNOS_THERMAL_TMU_DT_H */