Commit 3d883483dc0a7261d73d8b1857a7387a1dd99eee

Authored by Linus Torvalds

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

Showing 15 changed files Side-by-side Diff

Documentation/devicetree/bindings/thermal/exynos-thermal.txt
... ... @@ -12,6 +12,7 @@
12 12 "samsung,exynos5420-tmu-ext-triminfo" for TMU channels 2, 3 and 4
13 13 Exynos5420 (Must pass triminfo base and triminfo clock)
14 14 "samsung,exynos5440-tmu"
  15 + "samsung,exynos7-tmu"
15 16 - interrupt-parent : The phandle for the interrupt controller
16 17 - reg : Address range of the thermal registers. For soc's which has multiple
17 18 instances of TMU and some registers are shared across all TMU's like
18 19  
19 20  
... ... @@ -32,13 +33,28 @@
32 33 - clocks : The main clocks for TMU device
33 34 -- 1. operational clock for TMU channel
34 35 -- 2. optional clock to access the shared registers of TMU channel
  36 + -- 3. optional special clock for functional operation
35 37 - clock-names : Thermal system clock name
36 38 -- "tmu_apbif" operational clock for current TMU channel
37 39 -- "tmu_triminfo_apbif" clock to access the shared triminfo register
38 40 for current TMU channel
  41 + -- "tmu_sclk" clock for functional operation of the current TMU
  42 + channel
39 43 - vtmu-supply: This entry is optional and provides the regulator node supplying
40 44 voltage to TMU. If needed this entry can be placed inside
41 45 board/platform specific dts file.
  46 +Following 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  
43 59 Example 1):
44 60  
... ... @@ -51,6 +67,7 @@
51 67 clock-names = "tmu_apbif";
52 68 status = "disabled";
53 69 vtmu-supply = <&tmu_regulator_node>;
  70 + #include "exynos4412-tmu-sensor-conf.dtsi"
54 71 };
55 72  
56 73 Example 2):
... ... @@ -61,6 +78,7 @@
61 78 interrupts = <0 58 0>;
62 79 clocks = <&clock 21>;
63 80 clock-names = "tmu_apbif";
  81 + #include "exynos5440-tmu-sensor-conf.dtsi"
64 82 };
65 83  
66 84 Example 3): (In case of Exynos5420 "with misplaced TRIMINFO register")
... ... @@ -70,6 +88,7 @@
70 88 interrupts = <0 184 0>;
71 89 clocks = <&clock 318>, <&clock 318>;
72 90 clock-names = "tmu_apbif", "tmu_triminfo_apbif";
  91 + #include "exynos4412-tmu-sensor-conf.dtsi"
73 92 };
74 93  
75 94 tmu_cpu3: tmu@1006c000 {
... ... @@ -78,6 +97,7 @@
78 97 interrupts = <0 185 0>;
79 98 clocks = <&clock 318>, <&clock 319>;
80 99 clock-names = "tmu_apbif", "tmu_triminfo_apbif";
  100 + #include "exynos4412-tmu-sensor-conf.dtsi"
81 101 };
82 102  
83 103 tmu_gpu: tmu@100a0000 {
... ... @@ -86,6 +106,7 @@
86 106 interrupts = <0 215 0>;
87 107 clocks = <&clock 319>, <&clock 318>;
88 108 clock-names = "tmu_apbif", "tmu_triminfo_apbif";
  109 + #include "exynos4412-tmu-sensor-conf.dtsi"
89 110 };
90 111  
91 112 Note: For multi-instance tmu each instance should have an alias correctly
Documentation/devicetree/bindings/thermal/thermal.txt
... ... @@ -251,24 +251,24 @@
251 251 };
252 252  
253 253 thermal-zones {
254   - cpu-thermal: cpu-thermal {
  254 + cpu_thermal: cpu-thermal {
255 255 polling-delay-passive = <250>; /* milliseconds */
256 256 polling-delay = <1000>; /* milliseconds */
257 257  
258 258 thermal-sensors = <&bandgap0>;
259 259  
260 260 trips {
261   - cpu-alert0: cpu-alert {
  261 + cpu_alert0: cpu-alert0 {
262 262 temperature = <90000>; /* millicelsius */
263 263 hysteresis = <2000>; /* millicelsius */
264 264 type = "active";
265 265 };
266   - cpu-alert1: cpu-alert {
  266 + cpu_alert1: cpu-alert1 {
267 267 temperature = <100000>; /* millicelsius */
268 268 hysteresis = <2000>; /* millicelsius */
269 269 type = "passive";
270 270 };
271   - cpu-crit: cpu-crit {
  271 + cpu_crit: cpu-crit {
272 272 temperature = <125000>; /* millicelsius */
273 273 hysteresis = <2000>; /* millicelsius */
274 274 type = "critical";
275 275  
276 276  
277 277  
... ... @@ -277,17 +277,17 @@
277 277  
278 278 cooling-maps {
279 279 map0 {
280   - trip = <&cpu-alert0>;
281   - cooling-device = <&fan0 THERMAL_NO_LIMITS 4>;
  280 + trip = <&cpu_alert0>;
  281 + cooling-device = <&fan0 THERMAL_NO_LIMIT 4>;
282 282 };
283 283 map1 {
284   - trip = <&cpu-alert1>;
285   - cooling-device = <&fan0 5 THERMAL_NO_LIMITS>;
  284 + trip = <&cpu_alert1>;
  285 + cooling-device = <&fan0 5 THERMAL_NO_LIMIT>;
286 286 };
287 287 map2 {
288   - trip = <&cpu-alert1>;
  288 + trip = <&cpu_alert1>;
289 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 };
294 294  
295 295  
296 296  
... ... @@ -298,13 +298,13 @@
298 298 device (fan0) is controlled via I2C bus 1, at address 0x48, and has ten
299 299 different cooling states 0-9. It is used to remove the heat out of
300 300 the thermal zone 'cpu-thermal' using its cooling states
301   -from its minimum to 4, when it reaches trip point 'cpu-alert0'
  301 +from its minimum to 4, when it reaches trip point 'cpu_alert0'
302 302 at 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
304 304 linked to the same thermal zone, 'cpu-thermal', as a passive cooling device,
305   -using all its cooling states at trip point 'cpu-alert1',
  305 +using all its cooling states at trip point 'cpu_alert1',
306 306 which is a trip point at 100C. On the thermal zone 'cpu-thermal', at the
307   -temperature of 125C, represented by the trip point 'cpu-crit', the silicon
  307 +temperature of 125C, represented by the trip point 'cpu_crit', the silicon
308 308 is not reliable anymore.
309 309  
310 310 (b) - IC with several internal sensors
... ... @@ -329,7 +329,7 @@
329 329 };
330 330  
331 331 thermal-zones {
332   - cpu-thermal: cpu-thermal {
  332 + cpu_thermal: cpu-thermal {
333 333 polling-delay-passive = <250>; /* milliseconds */
334 334 polling-delay = <1000>; /* milliseconds */
335 335  
336 336  
... ... @@ -338,12 +338,12 @@
338 338  
339 339 trips {
340 340 /* each zone within the SoC may have its own trips */
341   - cpu-alert: cpu-alert {
  341 + cpu_alert: cpu-alert {
342 342 temperature = <100000>; /* millicelsius */
343 343 hysteresis = <2000>; /* millicelsius */
344 344 type = "passive";
345 345 };
346   - cpu-crit: cpu-crit {
  346 + cpu_crit: cpu-crit {
347 347 temperature = <125000>; /* millicelsius */
348 348 hysteresis = <2000>; /* millicelsius */
349 349 type = "critical";
... ... @@ -356,7 +356,7 @@
356 356 };
357 357 };
358 358  
359   - gpu-thermal: gpu-thermal {
  359 + gpu_thermal: gpu-thermal {
360 360 polling-delay-passive = <120>; /* milliseconds */
361 361 polling-delay = <1000>; /* milliseconds */
362 362  
363 363  
... ... @@ -365,12 +365,12 @@
365 365  
366 366 trips {
367 367 /* each zone within the SoC may have its own trips */
368   - gpu-alert: gpu-alert {
  368 + gpu_alert: gpu-alert {
369 369 temperature = <90000>; /* millicelsius */
370 370 hysteresis = <2000>; /* millicelsius */
371 371 type = "passive";
372 372 };
373   - gpu-crit: gpu-crit {
  373 + gpu_crit: gpu-crit {
374 374 temperature = <105000>; /* millicelsius */
375 375 hysteresis = <2000>; /* millicelsius */
376 376 type = "critical";
... ... @@ -383,7 +383,7 @@
383 383 };
384 384 };
385 385  
386   - dsp-thermal: dsp-thermal {
  386 + dsp_thermal: dsp-thermal {
387 387 polling-delay-passive = <50>; /* milliseconds */
388 388 polling-delay = <1000>; /* milliseconds */
389 389  
390 390  
... ... @@ -392,12 +392,12 @@
392 392  
393 393 trips {
394 394 /* each zone within the SoC may have its own trips */
395   - dsp-alert: gpu-alert {
  395 + dsp_alert: dsp-alert {
396 396 temperature = <90000>; /* millicelsius */
397 397 hysteresis = <2000>; /* millicelsius */
398 398 type = "passive";
399 399 };
400   - dsp-crit: gpu-crit {
  400 + dsp_crit: gpu-crit {
401 401 temperature = <135000>; /* millicelsius */
402 402 hysteresis = <2000>; /* millicelsius */
403 403 type = "critical";
... ... @@ -457,7 +457,7 @@
457 457 };
458 458  
459 459 thermal-zones {
460   - cpu-thermal: cpu-thermal {
  460 + cpu_thermal: cpu-thermal {
461 461 polling-delay-passive = <250>; /* milliseconds */
462 462 polling-delay = <1000>; /* milliseconds */
463 463  
... ... @@ -508,7 +508,7 @@
508 508 /*
509 509 * An IC with several temperature sensor.
510 510 */
511   - adc-dummy: sensor@0x50 {
  511 + adc_dummy: sensor@0x50 {
512 512 ...
513 513 #thermal-sensor-cells = <1>; /* sensor internal ID */
514 514 };
... ... @@ -520,7 +520,7 @@
520 520 polling-delay = <2500>; /* milliseconds */
521 521  
522 522 /* sensor ID */
523   - thermal-sensors = <&adc-dummy 4>;
  523 + thermal-sensors = <&adc_dummy 4>;
524 524  
525 525 trips {
526 526 ...
527 527  
... ... @@ -531,14 +531,14 @@
531 531 };
532 532 };
533 533  
534   - board-thermal: board-thermal {
  534 + board_thermal: board-thermal {
535 535 polling-delay-passive = <1000>; /* milliseconds */
536 536 polling-delay = <2500>; /* milliseconds */
537 537  
538 538 /* sensor ID */
539   - thermal-sensors = <&adc-dummy 0>, /* pcb top edge */
540   - <&adc-dummy 1>, /* lcd */
541   - <&adc-dymmy 2>; /* back cover */
  539 + thermal-sensors = <&adc_dummy 0>, /* pcb top edge */
  540 + <&adc_dummy 1>, /* lcd */
  541 + <&adc_dummy 2>; /* back cover */
542 542 /*
543 543 * An array of coefficients describing the sensor
544 544 * linear relation. E.g.:
545 545  
546 546  
547 547  
... ... @@ -548,22 +548,22 @@
548 548  
549 549 trips {
550 550 /* Trips are based on resulting linear equation */
551   - cpu-trip: cpu-trip {
  551 + cpu_trip: cpu-trip {
552 552 temperature = <60000>; /* millicelsius */
553 553 hysteresis = <2000>; /* millicelsius */
554 554 type = "passive";
555 555 };
556   - gpu-trip: gpu-trip {
  556 + gpu_trip: gpu-trip {
557 557 temperature = <55000>; /* millicelsius */
558 558 hysteresis = <2000>; /* millicelsius */
559 559 type = "passive";
560 560 }
561   - lcd-trip: lcp-trip {
  561 + lcd_trip: lcp-trip {
562 562 temperature = <53000>; /* millicelsius */
563 563 hysteresis = <2000>; /* millicelsius */
564 564 type = "passive";
565 565 };
566   - crit-trip: crit-trip {
  566 + crit_trip: crit-trip {
567 567 temperature = <68000>; /* millicelsius */
568 568 hysteresis = <2000>; /* millicelsius */
569 569 type = "critical";
570 570  
571 571  
... ... @@ -572,17 +572,17 @@
572 572  
573 573 cooling-maps {
574 574 map0 {
575   - trip = <&cpu-trip>;
  575 + trip = <&cpu_trip>;
576 576 cooling-device = <&cpu0 0 2>;
577 577 contribution = <55>;
578 578 };
579 579 map1 {
580   - trip = <&gpu-trip>;
  580 + trip = <&gpu_trip>;
581 581 cooling-device = <&gpu0 0 2>;
582 582 contribution = <20>;
583 583 };
584 584 map2 {
585   - trip = <&lcd-trip>;
  585 + trip = <&lcd_trip>;
586 586 cooling-device = <&lcd0 5 10>;
587 587 contribution = <15>;
588 588 };
drivers/cpufreq/Kconfig.arm
... ... @@ -26,13 +26,21 @@
26 26  
27 27  
28 28 config 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.
30 36  
  37 + If in doubt, say N.
  38 +
31 39 config ARM_EXYNOS4210_CPUFREQ
32 40 bool "SAMSUNG EXYNOS4210"
33 41 depends on CPU_EXYNOS4210
  42 + depends on ARM_EXYNOS_CPUFREQ
34 43 default y
35   - select ARM_EXYNOS_CPUFREQ
36 44 help
37 45 This adds the CPUFreq driver for Samsung EXYNOS4210
38 46 SoC (S5PV310 or S5PC210).
39 47  
... ... @@ -42,8 +50,8 @@
42 50 config ARM_EXYNOS4X12_CPUFREQ
43 51 bool "SAMSUNG EXYNOS4x12"
44 52 depends on SOC_EXYNOS4212 || SOC_EXYNOS4412
  53 + depends on ARM_EXYNOS_CPUFREQ
45 54 default y
46   - select ARM_EXYNOS_CPUFREQ
47 55 help
48 56 This adds the CPUFreq driver for Samsung EXYNOS4X12
49 57 SoC (EXYNOS4212 or EXYNOS4412).
50 58  
51 59  
... ... @@ -53,28 +61,14 @@
53 61 config ARM_EXYNOS5250_CPUFREQ
54 62 bool "SAMSUNG EXYNOS5250"
55 63 depends on SOC_EXYNOS5250
  64 + depends on ARM_EXYNOS_CPUFREQ
56 65 default y
57   - select ARM_EXYNOS_CPUFREQ
58 66 help
59 67 This adds the CPUFreq driver for Samsung EXYNOS5250
60 68 SoC.
61 69  
62 70 If in doubt, say N.
63 71  
64   -config 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   -
78 72 config ARM_EXYNOS_CPU_FREQ_BOOST_SW
79 73 bool "EXYNOS Frequency Overclocking - Software"
80 74 depends on ARM_EXYNOS_CPUFREQ && THERMAL
... ... @@ -87,6 +81,20 @@
87 81  
88 82 It requires, for safe operation, thermal framework with properly
89 83 defined trip points.
  84 +
  85 + If in doubt, say N.
  86 +
  87 +config 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.
90 98  
91 99 If in doubt, say N.
92 100  
drivers/cpufreq/Makefile
... ... @@ -52,10 +52,11 @@
52 52  
53 53 obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
54 54 obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o
55   -obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o
56   -obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
57   -obj-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o
58   -obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o
  55 +obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += arm-exynos-cpufreq.o
  56 +arm-exynos-cpufreq-y := exynos-cpufreq.o
  57 +arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
  58 +arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o
  59 +arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o
59 60 obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
60 61 obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
61 62 obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
drivers/cpufreq/exynos-cpufreq.c
... ... @@ -18,10 +18,13 @@
18 18 #include <linux/cpufreq.h>
19 19 #include <linux/platform_device.h>
20 20 #include <linux/of.h>
  21 +#include <linux/cpu_cooling.h>
  22 +#include <linux/cpu.h>
21 23  
22 24 #include "exynos-cpufreq.h"
23 25  
24 26 static struct exynos_dvfs_info *exynos_info;
  27 +static struct thermal_cooling_device *cdev;
25 28 static struct regulator *arm_regulator;
26 29 static unsigned int locking_frequency;
27 30  
... ... @@ -156,6 +159,7 @@
156 159  
157 160 static int exynos_cpufreq_probe(struct platform_device *pdev)
158 161 {
  162 + struct device_node *cpus, *np;
159 163 int ret = -EINVAL;
160 164  
161 165 exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL);
162 166  
163 167  
... ... @@ -198,9 +202,36 @@
198 202 /* Done here as we want to capture boot frequency */
199 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");
202 212 return 0;
  213 + }
203 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);
  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;
  233 +
  234 +err_cpufreq_reg:
204 235 dev_err(&pdev->dev, "failed to register cpufreq driver\n");
205 236 regulator_put(arm_regulator);
206 237 err_vdd_arm:
drivers/thermal/of-thermal.c
... ... @@ -497,6 +497,9 @@
497 497 if (sensor_specs.np == sensor_np && id == sensor_id) {
498 498 tzd = thermal_zone_of_add_sensor(child, sensor_np,
499 499 data, ops);
  500 + if (!IS_ERR(tzd))
  501 + tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED);
  502 +
500 503 of_node_put(sensor_specs.np);
501 504 of_node_put(child);
502 505 goto exit;
drivers/thermal/rockchip_thermal.c
... ... @@ -193,19 +193,20 @@
193 193  
194 194 static long rk_tsadcv2_code_to_temp(u32 code)
195 195 {
196   - int high, low, mid;
  196 + unsigned int low = 0;
  197 + unsigned int high = ARRAY_SIZE(v2_code_table) - 1;
  198 + unsigned int mid = (low + high) / 2;
  199 + unsigned int num;
  200 + unsigned long denom;
197 201  
198   - low = 0;
199   - high = ARRAY_SIZE(v2_code_table) - 1;
200   - mid = (high + low) / 2;
  202 + /* Invalid code, return -EAGAIN */
  203 + if (code > TSADCV2_DATA_MASK)
  204 + return -EAGAIN;
201 205  
202   - if (code > v2_code_table[low].code || code < v2_code_table[high].code)
203   - return 125000; /* No code available, return max temperature */
204   -
205   - while (low <= high) {
206   - if (code >= v2_code_table[mid].code && code <
207   - v2_code_table[mid - 1].code)
208   - return v2_code_table[mid].temp;
  206 + while (low <= high && mid) {
  207 + if (code >= v2_code_table[mid].code &&
  208 + code < v2_code_table[mid - 1].code)
  209 + break;
209 210 else if (code < v2_code_table[mid].code)
210 211 low = mid + 1;
211 212 else
... ... @@ -213,7 +214,16 @@
213 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 /**
drivers/thermal/samsung/Kconfig
... ... @@ -7,13 +7,4 @@
7 7 the TMU, reports temperature and handles cooling action if defined.
8 8 This driver uses the Exynos core thermal APIs and TMU configuration
9 9 data from the supported SoCs.
10   -
11   -config 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.
drivers/thermal/samsung/Makefile
... ... @@ -3,6 +3,4 @@
3 3 #
4 4 obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o
5 5 exynos_thermal-y := exynos_tmu.o
6   -exynos_thermal-y += exynos_tmu_data.o
7   -exynos_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
drivers/thermal/samsung/exynos_thermal_common.c
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   -
30   -struct 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 */
41   -static 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 */
51   -static 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 */
81   -static 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 */
106   -static 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 */
123   -static 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 */
133   -static 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 */
182   -static 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 */
227   -static 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 */
246   -static 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 */
265   -static 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 */
283   -static 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   - */
300   -void 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 */
347   -int 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   -
402   -err_unregister:
403   - exynos_unregister_thermal(sensor_conf);
404   - return ret;
405   -}
406   -
407   -/* Un-Register with the in-kernel thermal management */
408   -void 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   -}
drivers/thermal/samsung/exynos_thermal_common.h
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   -
44   -enum 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   - */
61   -struct freq_clip_table {
62   - unsigned int freq_clip_max;
63   - unsigned int temp_level;
64   - const struct cpumask *mask_val;
65   -};
66   -
67   -struct 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   -
74   -struct thermal_cooling_conf {
75   - struct freq_clip_table freq_data[MAX_TRIP_COUNT];
76   - int freq_clip_count;
77   -};
78   -
79   -struct 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
92   -void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf);
93   -int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
94   -void exynos_report_trigger(struct thermal_sensor_conf *sensor_conf);
95   -#else
96   -static inline void
97   -exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf) { return; }
98   -
99   -static inline int
100   -exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
101   -
102   -static inline void
103   -exynos_report_trigger(struct thermal_sensor_conf *sensor_conf) { return; }
104   -
105   -#endif /* CONFIG_EXYNOS_THERMAL_CORE */
106   -#endif /* _EXYNOS_THERMAL_COMMON_H */
drivers/thermal/samsung/exynos_tmu.c
1 1 /*
2 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 8 * Copyright (C) 2011 Samsung Electronics
5 9 * Donggeun Kim <dg77.kim@samsung.com>
6 10 * Amit Daniel Kachhap <amit.kachhap@linaro.org>
7 11  
... ... @@ -31,8 +35,8 @@
31 35 #include <linux/platform_device.h>
32 36 #include <linux/regulator/consumer.h>
33 37  
34   -#include "exynos_thermal_common.h"
35 38 #include "exynos_tmu.h"
  39 +#include "../thermal_core.h"
36 40  
37 41 /* Exynos generic registers */
38 42 #define EXYNOS_TMU_REG_TRIMINFO 0x0
... ... @@ -115,6 +119,27 @@
115 119 #define EXYNOS5440_TMU_TH_RISE4_SHIFT 24
116 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 144 * struct exynos_tmu_data : A structure to hold the private data of the TMU
120 145 driver
... ... @@ -128,6 +153,7 @@
128 153 * @lock: lock to implement synchronization.
129 154 * @clk: pointer to the clock structure.
130 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 157 * @temp_error1: fused value of the first point trim.
132 158 * @temp_error2: fused value of the second point trim.
133 159 * @regulator: pointer to the TMU regulator structure.
134 160  
... ... @@ -147,10 +173,11 @@
147 173 enum soc_type soc;
148 174 struct work_struct irq_work;
149 175 struct mutex lock;
150   - struct clk *clk, *clk_sec;
151   - u8 temp_error1, temp_error2;
  176 + struct clk *clk, *clk_sec, *sclk;
  177 + u16 temp_error1, temp_error2;
152 178 struct regulator *regulator;
153   - struct thermal_sensor_conf *reg_conf;
  179 + struct thermal_zone_device *tzd;
  180 +
154 181 int (*tmu_initialize)(struct platform_device *pdev);
155 182 void (*tmu_control)(struct platform_device *pdev, bool on);
156 183 int (*tmu_read)(struct exynos_tmu_data *data);
... ... @@ -159,6 +186,33 @@
159 186 void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
160 187 };
161 188  
  189 +static 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 217 * TMU treats temperature as a mapped temperature code.
164 218 * The temperature is converted differently depending on the calibration type.
... ... @@ -190,7 +244,7 @@
190 244 * Calculate a temperature value from a temperature code.
191 245 * The unit of the temperature is degree Celsius.
192 246 */
193   -static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
  247 +static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code)
194 248 {
195 249 struct exynos_tmu_platform_data *pdata = data->pdata;
196 250 int temp;
197 251  
198 252  
199 253  
... ... @@ -234,14 +288,25 @@
234 288  
235 289 static 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 295 int i;
239 296  
240   - for (i = 0; i < pdata->non_hw_trigger_levels; i++) {
241   - u8 temp = pdata->trigger_levels[i];
  297 + if (!trips) {
  298 + pr_err("%s: Cannot get trip points from of-thermal.c!\n",
  299 + __func__);
  300 + return 0;
  301 + }
242 302  
  303 + for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
  304 + if (trips[i].type == THERMAL_TRIP_CRITICAL)
  305 + continue;
  306 +
  307 + temp = trips[i].temperature / MCELSIUS;
243 308 if (falling)
244   - temp -= pdata->threshold_falling;
  309 + temp -= (trips[i].hysteresis / MCELSIUS);
245 310 else
246 311 threshold &= ~(0xff << 8 * i);
247 312  
248 313  
249 314  
... ... @@ -305,10 +370,20 @@
305 370 static int exynos4210_tmu_initialize(struct platform_device *pdev)
306 371 {
307 372 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
308   - struct exynos_tmu_platform_data *pdata = data->pdata;
309   - unsigned int status;
  373 + struct thermal_zone_device *tz = data->tzd;
  374 + const struct thermal_trip * const trips =
  375 + of_thermal_get_trip_points(tz);
310 376 int ret = 0, threshold_code, i;
  377 + unsigned long reference, temp;
  378 + unsigned int status;
311 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 + }
  386 +
312 387 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
313 388 if (!status) {
314 389 ret = -EBUSY;
315 390  
316 391  
... ... @@ -318,12 +393,19 @@
318 393 sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO));
319 394  
320 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 402 writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
323 403  
324   - for (i = 0; i < pdata->non_hw_trigger_levels; i++)
325   - writeb(pdata->trigger_levels[i], data->base +
  404 + for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
  405 + temp = trips[i].temperature / MCELSIUS;
  406 + writeb(temp - reference, data->base +
326 407 EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
  408 + }
327 409  
328 410 data->tmu_clear_irqs(data);
329 411 out:
330 412  
... ... @@ -333,9 +415,11 @@
333 415 static int exynos4412_tmu_initialize(struct platform_device *pdev)
334 416 {
335 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 420 unsigned int status, trim_info, con, ctrl, rising_threshold;
338 421 int ret = 0, threshold_code, i;
  422 + unsigned long crit_temp = 0;
339 423  
340 424 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
341 425 if (!status) {
342 426  
... ... @@ -373,17 +457,29 @@
373 457 data->tmu_clear_irqs(data);
374 458  
375 459 /* if last threshold limit is also present */
376   - i = pdata->max_trigger_level - 1;
377   - if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) {
378   - threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
379   - /* 1-4 level to be assigned in th0 reg */
380   - rising_threshold &= ~(0xff << 8 * i);
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);
  460 + for (i = 0; i < of_thermal_get_ntrips(data->tzd); i++) {
  461 + if (trips[i].type == THERMAL_TRIP_CRITICAL) {
  462 + crit_temp = trips[i].temperature;
  463 + break;
  464 + }
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 +
387 483 out:
388 484 return ret;
389 485 }
390 486  
... ... @@ -391,9 +487,9 @@
391 487 static int exynos5440_tmu_initialize(struct platform_device *pdev)
392 488 {
393 489 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
394   - struct exynos_tmu_platform_data *pdata = data->pdata;
395 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 495 * For exynos5440 soc triminfo value is swapped between TMU0 and
... ... @@ -422,9 +518,8 @@
422 518 data->tmu_clear_irqs(data);
423 519  
424 520 /* if last threshold limit is also present */
425   - i = pdata->max_trigger_level - 1;
426   - if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) {
427   - threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
  521 + if (!data->tzd->ops->get_crit_temp(data->tzd, &crit_temp)) {
  522 + threshold_code = temp_to_code(data, crit_temp / MCELSIUS);
428 523 /* 5th level to be assigned in th2 reg */
429 524 rising_threshold =
430 525 threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT;
431 526  
432 527  
... ... @@ -439,10 +534,88 @@
439 534 return ret;
440 535 }
441 536  
442   -static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
  537 +static int exynos7_tmu_initialize(struct platform_device *pdev)
443 538 {
444 539 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
  540 + struct thermal_zone_device *tz = data->tzd;
445 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);
  611 +out:
  612 + return ret;
  613 +}
  614 +
  615 +static 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 619 unsigned int con, interrupt_en;
447 620  
448 621 con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
... ... @@ -450,10 +623,15 @@
450 623 if (on) {
451 624 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
452 625 interrupt_en =
453   - pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT |
454   - pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT |
455   - pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT |
456   - pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT;
  626 + (of_thermal_is_trip_valid(tz, 3)
  627 + << EXYNOS_TMU_INTEN_RISE3_SHIFT) |
  628 + (of_thermal_is_trip_valid(tz, 2)
  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 635 if (data->soc != SOC_ARCH_EXYNOS4210)
458 636 interrupt_en |=
459 637 interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
... ... @@ -468,7 +646,7 @@
468 646 static void exynos5440_tmu_control(struct platform_device *pdev, bool on)
469 647 {
470 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 650 unsigned int con, interrupt_en;
473 651  
474 652 con = get_con_reg(data, readl(data->base + EXYNOS5440_TMU_S0_7_CTRL));
... ... @@ -476,11 +654,16 @@
476 654 if (on) {
477 655 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
478 656 interrupt_en =
479   - pdata->trigger_enable[3] << EXYNOS5440_TMU_INTEN_RISE3_SHIFT |
480   - pdata->trigger_enable[2] << EXYNOS5440_TMU_INTEN_RISE2_SHIFT |
481   - pdata->trigger_enable[1] << EXYNOS5440_TMU_INTEN_RISE1_SHIFT |
482   - pdata->trigger_enable[0] << EXYNOS5440_TMU_INTEN_RISE0_SHIFT;
483   - interrupt_en |= interrupt_en << EXYNOS5440_TMU_INTEN_FALL0_SHIFT;
  657 + (of_thermal_is_trip_valid(tz, 3)
  658 + << EXYNOS5440_TMU_INTEN_RISE3_SHIFT) |
  659 + (of_thermal_is_trip_valid(tz, 2)
  660 + << EXYNOS5440_TMU_INTEN_RISE2_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 667 } else {
485 668 con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
486 669 interrupt_en = 0; /* Disable all interrupts */
487 670  
488 671  
489 672  
490 673  
... ... @@ -489,19 +672,62 @@
489 672 writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
490 673 }
491 674  
492   -static int exynos_tmu_read(struct exynos_tmu_data *data)
  675 +static 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;
495 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 +
  715 +static int exynos_get_temp(void *p, long *temp)
  716 +{
  717 + struct exynos_tmu_data *data = p;
  718 +
  719 + if (!data)
  720 + return -EINVAL;
  721 +
496 722 mutex_lock(&data->lock);
497 723 clk_enable(data->clk);
498   - ret = data->tmu_read(data);
499   - if (ret >= 0)
500   - ret = code_to_temp(data, ret);
  724 +
  725 + *temp = code_to_temp(data, data->tmu_read(data)) * MCELSIUS;
  726 +
501 727 clk_disable(data->clk);
502 728 mutex_unlock(&data->lock);
503 729  
504   - return ret;
  730 + return 0;
505 731 }
506 732  
507 733 #ifdef CONFIG_THERMAL_EMULATION
... ... @@ -515,9 +741,19 @@
515 741 val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT);
516 742 val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT);
517 743 }
518   - val &= ~(EXYNOS_EMUL_DATA_MASK << EXYNOS_EMUL_DATA_SHIFT);
519   - val |= (temp_to_code(data, temp) << EXYNOS_EMUL_DATA_SHIFT) |
520   - EXYNOS_EMUL_ENABLE;
  744 + if (data->soc == SOC_ARCH_EXYNOS7) {
  745 + val &= ~(EXYNOS7_EMUL_DATA_MASK <<
  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 757 } else {
522 758 val &= ~EXYNOS_EMUL_ENABLE;
523 759 }
... ... @@ -533,6 +769,8 @@
533 769  
534 770 if (data->soc == SOC_ARCH_EXYNOS5260)
535 771 emul_con = EXYNOS5260_EMUL_CON;
  772 + else if (data->soc == SOC_ARCH_EXYNOS7)
  773 + emul_con = EXYNOS7_TMU_REG_EMUL_CON;
536 774 else
537 775 emul_con = EXYNOS_EMUL_CON;
538 776  
... ... @@ -576,7 +814,7 @@
576 814 #define exynos5440_tmu_set_emulation NULL
577 815 static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
578 816 { return -EINVAL; }
579   -#endif/*CONFIG_THERMAL_EMULATION*/
  817 +#endif /* CONFIG_THERMAL_EMULATION */
580 818  
581 819 static int exynos4210_tmu_read(struct exynos_tmu_data *data)
582 820 {
... ... @@ -596,6 +834,12 @@
596 834 return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP);
597 835 }
598 836  
  837 +static 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 +
599 843 static void exynos_tmu_work(struct work_struct *work)
600 844 {
601 845 struct exynos_tmu_data *data = container_of(work,
... ... @@ -613,7 +857,7 @@
613 857 if (!IS_ERR(data->clk_sec))
614 858 clk_disable(data->clk_sec);
615 859  
616   - exynos_report_trigger(data->reg_conf);
  860 + exynos_report_trigger(data);
617 861 mutex_lock(&data->lock);
618 862 clk_enable(data->clk);
619 863  
... ... @@ -634,6 +878,9 @@
634 878 if (data->soc == SOC_ARCH_EXYNOS5260) {
635 879 tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT;
636 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 884 } else {
638 885 tmu_intstat = EXYNOS_TMU_REG_INTSTAT;
639 886 tmu_intclear = EXYNOS_TMU_REG_INTCLEAR;
640 887  
641 888  
642 889  
643 890  
644 891  
645 892  
646 893  
647 894  
648 895  
649 896  
650 897  
651 898  
... ... @@ -673,57 +920,96 @@
673 920 static const struct of_device_id exynos_tmu_match[] = {
674 921 {
675 922 .compatible = "samsung,exynos3250-tmu",
676   - .data = &exynos3250_default_tmu_data,
677 923 },
678 924 {
679 925 .compatible = "samsung,exynos4210-tmu",
680   - .data = &exynos4210_default_tmu_data,
681 926 },
682 927 {
683 928 .compatible = "samsung,exynos4412-tmu",
684   - .data = &exynos4412_default_tmu_data,
685 929 },
686 930 {
687 931 .compatible = "samsung,exynos5250-tmu",
688   - .data = &exynos5250_default_tmu_data,
689 932 },
690 933 {
691 934 .compatible = "samsung,exynos5260-tmu",
692   - .data = &exynos5260_default_tmu_data,
693 935 },
694 936 {
695 937 .compatible = "samsung,exynos5420-tmu",
696   - .data = &exynos5420_default_tmu_data,
697 938 },
698 939 {
699 940 .compatible = "samsung,exynos5420-tmu-ext-triminfo",
700   - .data = &exynos5420_default_tmu_data,
701 941 },
702 942 {
703 943 .compatible = "samsung,exynos5440-tmu",
704   - .data = &exynos5440_default_tmu_data,
705 944 },
  945 + {
  946 + .compatible = "samsung,exynos7-tmu",
  947 + },
706 948 {},
707 949 };
708 950 MODULE_DEVICE_TABLE(of, exynos_tmu_match);
709 951  
710   -static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
711   - struct platform_device *pdev, int id)
  952 +static int exynos_of_get_soc_type(struct device_node *np)
712 953 {
713   - struct exynos_tmu_init_data *data_table;
714   - struct exynos_tmu_platform_data *tmu_data;
715   - const struct of_device_id *match;
  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;
716 973  
717   - match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
718   - if (!match)
719   - return NULL;
720   - data_table = (struct exynos_tmu_init_data *) match->data;
721   - if (!data_table || id >= data_table->tmu_count)
722   - return NULL;
723   - tmu_data = data_table->tmu_data;
724   - return (struct exynos_tmu_platform_data *) (tmu_data + id);
  974 + return -EINVAL;
725 975 }
726 976  
  977 +static int exynos_of_sensor_conf(struct device_node *np,
  978 + struct exynos_tmu_platform_data *pdata)
  979 +{
  980 + u32 value;
  981 + int ret;
  982 +
  983 + of_node_get(np);
  984 +
  985 + ret = of_property_read_u32(np, "samsung,tmu_gain", &value);
  986 + pdata->gain = (u8)value;
  987 + of_property_read_u32(np, "samsung,tmu_reference_voltage", &value);
  988 + pdata->reference_voltage = (u8)value;
  989 + of_property_read_u32(np, "samsung,tmu_noise_cancel_mode", &value);
  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;
  1011 +}
  1012 +
727 1013 static int exynos_map_dt_data(struct platform_device *pdev)
728 1014 {
729 1015 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
730 1016  
731 1017  
... ... @@ -771,14 +1057,15 @@
771 1057 return -EADDRNOTAVAIL;
772 1058 }
773 1059  
774   - pdata = exynos_get_driver_data(pdev, data->id);
775   - if (!pdata) {
776   - dev_err(&pdev->dev, "No platform init data supplied.\n");
777   - return -ENODEV;
778   - }
  1060 + pdata = devm_kzalloc(&pdev->dev,
  1061 + sizeof(struct exynos_tmu_platform_data),
  1062 + GFP_KERNEL);
  1063 + if (!pdata)
  1064 + return -ENOMEM;
779 1065  
  1066 + exynos_of_sensor_conf(pdev->dev.of_node, pdata);
780 1067 data->pdata = pdata;
781   - data->soc = pdata->type;
  1068 + data->soc = exynos_of_get_soc_type(pdev->dev.of_node);
782 1069  
783 1070 switch (data->soc) {
784 1071 case SOC_ARCH_EXYNOS4210:
... ... @@ -806,6 +1093,13 @@
806 1093 data->tmu_set_emulation = exynos5440_tmu_set_emulation;
807 1094 data->tmu_clear_irqs = exynos5440_tmu_clear_irqs;
808 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 1103 default:
810 1104 dev_err(&pdev->dev, "Platform not supported\n");
811 1105 return -EINVAL;
812 1106  
813 1107  
... ... @@ -834,12 +1128,16 @@
834 1128 return 0;
835 1129 }
836 1130  
  1131 +static 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 +
837 1136 static int exynos_tmu_probe(struct platform_device *pdev)
838 1137 {
839   - struct exynos_tmu_data *data;
840 1138 struct exynos_tmu_platform_data *pdata;
841   - struct thermal_sensor_conf *sensor_conf;
842   - int ret, i;
  1139 + struct exynos_tmu_data *data;
  1140 + int ret;
843 1141  
844 1142 data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
845 1143 GFP_KERNEL);
846 1144  
... ... @@ -849,9 +1147,15 @@
849 1147 platform_set_drvdata(pdev, data);
850 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 1156 ret = exynos_map_dt_data(pdev);
853 1157 if (ret)
854   - return ret;
  1158 + goto err_sensor;
855 1159  
856 1160 pdata = data->pdata;
857 1161  
858 1162  
859 1163  
... ... @@ -860,20 +1164,22 @@
860 1164 data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
861 1165 if (IS_ERR(data->clk)) {
862 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 1171 data->clk_sec = devm_clk_get(&pdev->dev, "tmu_triminfo_apbif");
867 1172 if (IS_ERR(data->clk_sec)) {
868 1173 if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO) {
869 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 1178 } else {
873 1179 ret = clk_prepare(data->clk_sec);
874 1180 if (ret) {
875 1181 dev_err(&pdev->dev, "Failed to get clock\n");
876   - return ret;
  1182 + goto err_sensor;
877 1183 }
878 1184 }
879 1185  
880 1186  
881 1187  
882 1188  
883 1189  
884 1190  
885 1191  
886 1192  
887 1193  
888 1194  
... ... @@ -883,82 +1189,57 @@
883 1189 goto err_clk_sec;
884 1190 }
885 1191  
  1192 + if (data->soc == SOC_ARCH_EXYNOS7) {
  1193 + data->sclk = devm_clk_get(&pdev->dev, "tmu_sclk");
  1194 + if (IS_ERR(data->sclk)) {
  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 + }
  1204 + }
  1205 +
886 1206 ret = exynos_tmu_initialize(pdev);
887 1207 if (ret) {
888 1208 dev_err(&pdev->dev, "Failed to initialize TMU\n");
889   - goto err_clk;
  1209 + goto err_sclk;
890 1210 }
891 1211  
892   - exynos_tmu_control(pdev, true);
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) {
930   - if (ret != -EPROBE_DEFER)
931   - dev_err(&pdev->dev,
932   - "Failed to register thermal interface: %d\n",
933   - ret);
934   - goto err_clk;
935   - }
936   - data->reg_conf = sensor_conf;
937   -
938 1212 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
939 1213 IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
940 1214 if (ret) {
941 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 1220 return 0;
  1221 +err_sclk:
  1222 + clk_disable_unprepare(data->sclk);
946 1223 err_clk:
947 1224 clk_unprepare(data->clk);
948 1225 err_clk_sec:
949 1226 if (!IS_ERR(data->clk_sec))
950 1227 clk_unprepare(data->clk_sec);
  1228 +err_sensor:
  1229 + thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd);
  1230 +
951 1231 return ret;
952 1232 }
953 1233  
954 1234 static int exynos_tmu_remove(struct platform_device *pdev)
955 1235 {
956 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);
959   -
  1239 + thermal_zone_of_sensor_unregister(&pdev->dev, tzd);
960 1240 exynos_tmu_control(pdev, false);
961 1241  
  1242 + clk_disable_unprepare(data->sclk);
962 1243 clk_unprepare(data->clk);
963 1244 if (!IS_ERR(data->clk_sec))
964 1245 clk_unprepare(data->clk_sec);
drivers/thermal/samsung/exynos_tmu.h
... ... @@ -23,17 +23,8 @@
23 23 #ifndef _EXYNOS_TMU_H
24 24 #define _EXYNOS_TMU_H
25 25 #include <linux/cpu_cooling.h>
  26 +#include <dt-bindings/thermal/thermal_exynos.h>
26 27  
27   -#include "exynos_thermal_common.h"
28   -
29   -enum 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   -
37 28 enum soc_type {
38 29 SOC_ARCH_EXYNOS3250 = 1,
39 30 SOC_ARCH_EXYNOS4210,
40 31  
... ... @@ -43,38 +34,11 @@
43 34 SOC_ARCH_EXYNOS5420,
44 35 SOC_ARCH_EXYNOS5420_TRIMINFO,
45 36 SOC_ARCH_EXYNOS5440,
  37 + SOC_ARCH_EXYNOS7,
46 38 };
47 39  
48 40 /**
49 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 42 * @gain: gain of amplifier in the positive-TC generator block
79 43 * 0 < gain <= 15
80 44 * @reference_voltage: reference voltage of amplifier
81 45  
82 46  
... ... @@ -86,24 +50,12 @@
86 50 * @efuse_value: platform defined fuse value
87 51 * @min_efuse_value: minimum valid trimming data
88 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 53 * @default_temp_offset: default temperature offset in case of no trimming
92 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 56 * This structure is required for configuration of exynos_tmu driver.
98 57 */
99 58 struct 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 59 u8 gain;
108 60 u8 reference_voltage;
109 61 u8 noise_cancel_mode;
110 62  
111 63  
... ... @@ -115,31 +67,10 @@
115 67 u8 second_point_trim;
116 68 u8 default_temp_offset;
117 69  
118   - enum calibration_type cal_type;
119 70 enum soc_type type;
120   - struct freq_clip_table freq_tab[4];
121   - unsigned int freq_tab_count;
  71 + u32 cal_type;
  72 + u32 cal_mode;
122 73 };
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   - */
131   -struct exynos_tmu_init_data {
132   - int tmu_count;
133   - struct exynos_tmu_platform_data tmu_data[];
134   -};
135   -
136   -extern struct exynos_tmu_init_data const exynos3250_default_tmu_data;
137   -extern struct exynos_tmu_init_data const exynos4210_default_tmu_data;
138   -extern struct exynos_tmu_init_data const exynos4412_default_tmu_data;
139   -extern struct exynos_tmu_init_data const exynos5250_default_tmu_data;
140   -extern struct exynos_tmu_init_data const exynos5260_default_tmu_data;
141   -extern struct exynos_tmu_init_data const exynos5420_default_tmu_data;
142   -extern struct exynos_tmu_init_data const exynos5440_default_tmu_data;
143 74  
144 75 #endif /* _EXYNOS_TMU_H */
drivers/thermal/samsung/exynos_tmu_data.c
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   -
26   -struct 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   -
101   -struct 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   -
147   -struct 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   -
157   -struct 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   -
207   -struct 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   -
226   -struct 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   -
257   -struct 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   -};
include/dt-bindings/thermal/thermal_exynos.h
  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 */