History

Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal

Pull thermal soc updates from Eduardo Valentin: - thermal core has a new devm_* API for registering cooling devices. I took the entire series, that is why you see changes on drivers/hwmon in this pull (Guenter Roeck) - rockchip thermal driver gains support to PX30 SoC (Elaine Zhang) - the generic-adc thermal driver now considers the lookup table DT property as optional (Jean-Francois Dagenais) - Refactoring of tsens thermal driver (Amit Kucheria) - Cleanups on cpu cooling driver (Daniel Lezcano) - broadcom thermal driver dropped support to ACPI (Srinath Mannam) - tegra thermal driver gains support to OC hw throttle and GPU throtle (Wei Ni) - Fixes in several thermal drivers. * 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal: (59 commits) hwmon: (pwm-fan) Use devm_thermal_of_cooling_device_register hwmon: (npcm750-pwm-fan) Use devm_thermal_of_cooling_device_register hwmon: (mlxreg-fan) Use devm_thermal_of_cooling_device_register hwmon: (gpio-fan) Use devm_thermal_of_cooling_device_register hwmon: (aspeed-pwm-tacho) Use devm_thermal_of_cooling_device_register thermal: rcar_gen3_thermal: Fix to show correct trip points number thermal: rcar_thermal: update calculation formula for R-Car Gen3 SoCs thermal: cpu_cooling: Actually trace CPU load in thermal_power_cpu_get_power thermal: rockchip: Support the PX30 SoC in thermal driver dt-bindings: rockchip-thermal: Support the PX30 SoC compatible thermal: rockchip: fix up the tsadc pinctrl setting error thermal: broadcom: Remove ACPI support thermal: Fix build error of missing devm_ioremap_resource on UM thermal/drivers/cpu_cooling: Remove pointless field thermal/drivers/cpu_cooling: Add Software Package Data Exchange (SPDX) thermal/drivers/cpu_cooling: Fixup the header and copyright thermal/drivers/cpu_cooling: Remove pointless test in power2state() thermal: rcar_gen3_thermal: disable interrupt in .remove thermal: rcar_gen3_thermal: fix interrupt type thermal: Introduce devm_thermal_of_cooling_device_register ...

Linus Torvalds committed 7 years ago

Commit a455eda2 parents cc7ce90 37bcec542 files · +2339 −605Browse files

Unified · Split

42 files
  1. Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt +33 −0
  2. Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt +57 −5
  3. Documentation/devicetree/bindings/thermal/qcom-tsens.txt +14 −0
  4. Documentation/devicetree/bindings/thermal/rockchip-thermal.txt +1 −0
  5. Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt +8 −2
  6. MAINTAINERS +6 −0
  7. drivers/hwmon/aspeed-pwm-tacho.c +2 −4
  8. drivers/hwmon/gpio-fan.c +9 −16
  9. drivers/hwmon/mlxreg-fan.c +10 −21
  10. drivers/hwmon/npcm750-pwm-fan.c +2 −4
  11. drivers/hwmon/pwm-fan.c +38 −59
  12. drivers/thermal/Kconfig +11 −0
  13. drivers/thermal/Makefile +1 −0
  14. drivers/thermal/broadcom/sr-thermal.c +0 −8
  15. drivers/thermal/cpu_cooling.c +7 −23
  16. drivers/thermal/of-thermal.c +3 −0
  17. drivers/thermal/qcom/Makefile +3 −1
  18. drivers/thermal/qcom/tsens-8916.c +0 −105
  19. drivers/thermal/qcom/tsens-8960.c +42 −42
  20. drivers/thermal/qcom/tsens-common.c +112 −47
  21. drivers/thermal/qcom/tsens-v0_1.c +156 −10
  22. drivers/thermal/qcom/tsens-v1.c +193 −0
  23. drivers/thermal/qcom/tsens-v2.c +58 −53
  24. drivers/thermal/qcom/tsens.c +54 −46
  25. drivers/thermal/qcom/tsens.h +262 −29
  26. drivers/thermal/qoriq_thermal.c +0 −5
  27. drivers/thermal/rcar_gen3_thermal.c +14 −37
  28. drivers/thermal/rcar_thermal.c +10 −1
  29. drivers/thermal/rockchip_thermal.c +71 −3
  30. drivers/thermal/st/Kconfig +11 −11
  31. drivers/thermal/st/stm_thermal.c +2 −4
  32. drivers/thermal/tegra/Kconfig +2 −2
  33. drivers/thermal/tegra/soctherm.c +904 −57
  34. drivers/thermal/tegra/soctherm.h +16 −0
  35. drivers/thermal/tegra/tegra124-soctherm.c +6 −1
  36. drivers/thermal/tegra/tegra132-soctherm.c +6 −1
  37. drivers/thermal/tegra/tegra210-soctherm.c +14 −1
  38. drivers/thermal/thermal-generic-adc.c +6 −3
  39. drivers/thermal/thermal_core.c +49 −0
  40. drivers/thermal/thermal_mmio.c +129 −0
  41. include/dt-bindings/thermal/tegra124-soctherm.h +4 −4
  42. include/linux/thermal.h +13 −0
Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt+33−0
@@ -0,0 +1,33 @@
1+Amazon's Annapurna Labs Thermal Sensor
2+
3+Simple thermal device that allows temperature reading by a single MMIO
4+transaction.
5+
6+Required properties:
7+- compatible: "amazon,al-thermal".
8+- reg: The physical base address and length of the sensor's registers.
9+- #thermal-sensor-cells: Must be 1. See ./thermal.txt for a description.
10+
11+Example:
12+ thermal: thermal {
13+ compatible = "amazon,al-thermal";
14+ reg = <0x0 0x05002860 0x0 0x1>;
15+ #thermal-sensor-cells = <0x1>;
16+ };
17+
18+ thermal-zones {
19+ thermal-z0 {
20+ polling-delay-passive = <250>;
21+ polling-delay = <1000>;
22+ thermal-sensors = <&thermal 0>;
23+ trips {
24+ critical {
25+ temperature = <105000>;
26+ hysteresis = <2000>;
27+ type = "critical";
28+ };
29+ };
30+
31+ };
32+ };
33+
Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt+57−5
@@ -52,13 +52,47 @@ Required properties : · 51 unmodified lines
5252 Must set as following values:
5353 TEGRA_SOCTHERM_THROT_LEVEL_LOW, TEGRA_SOCTHERM_THROT_LEVEL_MED
5454 TEGRA_SOCTHERM_THROT_LEVEL_HIGH, TEGRA_SOCTHERM_THROT_LEVEL_NONE
55+ - nvidia,gpu-throt-level: This property is for Tegra124 and Tegra210.
56+ It is the level of pulse skippers, which used to throttle clock
57+ frequencies. It indicates gpu clock throttling depth and can be
58+ programmed to any of the following values which represent a throttling
59+ percentage:
60+ TEGRA_SOCTHERM_THROT_LEVEL_NONE (0%)
61+ TEGRA_SOCTHERM_THROT_LEVEL_LOW (50%),
62+ TEGRA_SOCTHERM_THROT_LEVEL_MED (75%),
63+ TEGRA_SOCTHERM_THROT_LEVEL_HIGH (85%).
5564 - #cooling-cells: Should be 1. This cooling device only support on/off state.
5665 See ./thermal.txt for a description of this property.
5766
67+ Optional properties: The following properties are T210 specific and
68+ valid only for OCx throttle events.
69+ - nvidia,count-threshold: Specifies the number of OC events that are
70+ required for triggering an interrupt. Interrupts are not triggered if
71+ the property is missing. A value of 0 will interrupt on every OC alarm.
72+ - nvidia,polarity-active-low: Configures the polarity of the OC alaram
73+ signal. If present, this means assert low, otherwise assert high.
74+ - nvidia,alarm-filter: Number of clocks to filter event. When the filter
75+ expires (which means the OC event has not occurred for a long time),
76+ the counter is cleared and filter is rearmed. Default value is 0.
77+ - nvidia,throttle-period-us: Specifies the number of uSec for which
78+ throttling is engaged after the OC event is deasserted. Default value
79+ is 0.
80+
81+Optional properties:
82+- nvidia,thermtrips : When present, this property specifies the temperature at
83+ which the soctherm hardware will assert the thermal trigger signal to the
84+ Power Management IC, which can be configured to reset or shutdown the device.
85+ It is an array of pairs where each pair represents a tsensor id followed by a
86+ temperature in milli Celcius. In the absence of this property the critical
87+ trip point will be used for thermtrip temperature.
88+
5889 Note:
59−- the "critical" type trip points will be set to SOC_THERM hardware as the
60−shut down temperature. Once the temperature of this thermal zone is higher
61−than it, the system will be shutdown or reset by hardware.
90+- the "critical" type trip points will be used to set the temperature at which
91+the SOC_THERM hardware will assert a thermal trigger if the "nvidia,thermtrips"
92+property is missing. When the thermtrips property is present, the breach of a
93+critical trip point is reported back to the thermal framework to implement
94+software shutdown.
95+
6296 - the "hot" type trip points will be set to SOC_THERM hardware as the throttle
6397 temperature. Once the the temperature of this thermal zone is higher
6498 than it, it will trigger the HW throttle event.
@@ -79,25 +113,32 @@ Example : · 14 unmodified lines
79113
80114 #thermal-sensor-cells = <1>;
81115
116+ nvidia,thermtrips = <TEGRA124_SOCTHERM_SENSOR_CPU 102500
117+ TEGRA124_SOCTHERM_SENSOR_GPU 103000>;
118+
82119 throttle-cfgs {
83120 /*
84121 * When the "heavy" cooling device triggered,
85− * the HW will skip cpu clock's pulse in 85% depth
122+ * the HW will skip cpu clock's pulse in 85% depth,
123+ * skip gpu clock's pulse in 85% level
86124 */
87125 throttle_heavy: heavy {
88126 nvidia,priority = <100>;
89127 nvidia,cpu-throt-percent = <85>;
128+ nvidia,gpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_HIGH>;
90129
91130 #cooling-cells = <1>;
92131 };
93132
94133 /*
95134 * When the "light" cooling device triggered,
96− * the HW will skip cpu clock's pulse in 50% depth
135+ * the HW will skip cpu clock's pulse in 50% depth,
136+ * skip gpu clock's pulse in 50% level
97137 */
98138 throttle_light: light {
99139 nvidia,priority = <80>;
100140 nvidia,cpu-throt-percent = <50>;
141+ nvidia,gpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_LOW>;
101142
102143 #cooling-cells = <1>;
103144 };
@@ -107,6 +148,17 @@ Example : · 3 unmodified lines
107148 * arbiter will select the highest priority as the final throttle
108149 * settings to skip cpu pulse.
109150 */
151+
152+ throttle_oc1: oc1 {
153+ nvidia,priority = <50>;
154+ nvidia,polarity-active-low;
155+ nvidia,count-threshold = <100>;
156+ nvidia,alarm-filter = <5100000>;
157+ nvidia,throttle-period-us = <0>;
158+ nvidia,cpu-throt-percent = <75>;
159+ nvidia,gpu-throt-level =
160+ <TEGRA_SOCTHERM_THROT_LEVEL_MED>;
161+ };
110162 };
111163 };
112164
Documentation/devicetree/bindings/thermal/qcom-tsens.txt+14−0
@@ -6,11 +6,14 @@ Required properties: · 5 unmodified lines
66 - "qcom,msm8916-tsens" (MSM8916)
77 - "qcom,msm8974-tsens" (MSM8974)
88 - "qcom,msm8996-tsens" (MSM8996)
9+ - "qcom,qcs404-tsens", "qcom,tsens-v1" (QCS404)
910 - "qcom,msm8998-tsens", "qcom,tsens-v2" (MSM8998)
1011 - "qcom,sdm845-tsens", "qcom,tsens-v2" (SDM845)
1112 The generic "qcom,tsens-v2" property must be used as a fallback for any SoC
1213 with version 2 of the TSENS IP. MSM8996 is the only exception because the
1314 generic property did not exist when support was added.
15+ Similarly, the generic "qcom,tsens-v1" property must be used as a fallback for
16+ any SoC with version 1 of the TSENS IP.
1417
1518 - reg: Address range of the thermal registers.
1619 New platforms containing v2.x.y of the TSENS IP must specify the SROT and TM
@@ -39,3 +42,14 @@ tsens0: thermal-sensor@c263000 { · 22 unmodified lines
3942 #qcom,sensors = <13>;
4043 #thermal-sensor-cells = <1>;
4144 };
45+
46+Example 3 (for any platform containing v1 of the TSENS IP):
47+tsens: thermal-sensor@4a9000 {
48+ compatible = "qcom,qcs404-tsens", "qcom,tsens-v1";
49+ reg = <0x004a9000 0x1000>, /* TM */
50+ <0x004a8000 0x1000>; /* SROT */
51+ nvmem-cells = <&tsens_caldata>;
52+ nvmem-cell-names = "calib";
53+ #qcom,sensors = <10>;
54+ #thermal-sensor-cells = <1>;
55+ };
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt+1−0
@@ -2,6 +2,7 @@ · 1 unmodified line
22
33 Required properties:
44 - compatible : should be "rockchip,<name>-tsadc"
5+ "rockchip,px30-tsadc": found on PX30 SoCs
56 "rockchip,rv1108-tsadc": found on RV1108 SoCs
67 "rockchip,rk3228-tsadc": found on RK3228 SoCs
78 "rockchip,rk3288-tsadc": found on RK3288 SoCs
Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt+8−2
@@ -8,16 +8,22 @@ temperature using voltage-temperature lookup table. · 7 unmodified lines
88 Required properties:
99 ===================
1010 - compatible: Must be "generic-adc-thermal".
11+- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description
12+ of this property.
13+Optional properties:
14+===================
1115 - temperature-lookup-table: Two dimensional array of Integer; lookup table
1216 to map the relation between ADC value and
1317 temperature. When ADC is read, the value is
1418 looked up on the table to get the equivalent
1519 temperature.
20+
1621 The first value of the each row of array is the
1722 temperature in milliCelsius and second value of
1823 the each row of array is the ADC read value.
19−- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description
20− of this property.
24+
25+ If not specified, driver assumes the ADC channel
26+ gives milliCelsius directly.
2127
2228 Example :
2329 #include <dt-bindings/thermal/thermal.h>
MAINTAINERS+6−0
@@ -742,6 +742,12 @@ F: drivers/tty/serial/altera_jtaguart.c · 741 unmodified lines
742742 F: include/linux/altera_uart.h
743743 F: include/linux/altera_jtaguart.h
744744
745+AMAZON ANNAPURNA LABS THERMAL MMIO DRIVER
746+M: Talel Shenhar <talel@amazon.com>
747+S: Maintained
748+F: Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt
749+F: drivers/thermal/thermal_mmio.c
750+
745751 AMAZON ETHERNET DRIVERS
746752 M: Netanel Belgazal <netanel@amazon.com>
747753 R: Saeed Bishara <saeedb@amazon.com>
drivers/hwmon/aspeed-pwm-tacho.c+2−4
@@ -830,10 +830,8 @@ static int aspeed_create_pwm_cooling(struct device *dev, · 829 unmodified lines
830830 }
831831 snprintf(cdev->name, MAX_CDEV_NAME_LEN, "%pOFn%d", child, pwm_port);
832832
833− cdev->tcdev = thermal_of_cooling_device_register(child,
834− cdev->name,
835− cdev,
836− &aspeed_pwm_cool_ops);
833+ cdev->tcdev = devm_thermal_of_cooling_device_register(dev, child,
834+ cdev->name, cdev, &aspeed_pwm_cool_ops);
837835 if (IS_ERR(cdev->tcdev))
838836 return PTR_ERR(cdev->tcdev);
839837
drivers/hwmon/gpio-fan.c+9−16
@@ -498,6 +498,11 @@ static const struct of_device_id of_gpio_fan_match[] = { · 497 unmodified lines
498498 };
499499 MODULE_DEVICE_TABLE(of, of_gpio_fan_match);
500500
501+static void gpio_fan_stop(void *data)
502+{
503+ set_fan_speed(data, 0);
504+}
505+
501506 static int gpio_fan_probe(struct platform_device *pdev)
502507 {
503508 int err;
@@ -532,6 +537,7 @@ static int gpio_fan_probe(struct platform_device *pdev) · 28 unmodified lines
532537 err = fan_ctrl_init(fan_data);
533538 if (err)
534539 return err;
540+ devm_add_action_or_reset(dev, gpio_fan_stop, fan_data);
535541 }
536542
537543 /* Make this driver part of hwmon class. */
@@ -543,32 +549,20 @@ static int gpio_fan_probe(struct platform_device *pdev) · 5 unmodified lines
543549 return PTR_ERR(fan_data->hwmon_dev);
544550
545551 /* Optional cooling device register for Device tree platforms */
546− fan_data->cdev = thermal_of_cooling_device_register(np,
547− "gpio-fan",
548− fan_data,
549− &gpio_fan_cool_ops);
552+ fan_data->cdev = devm_thermal_of_cooling_device_register(dev, np,
553+ "gpio-fan", fan_data, &gpio_fan_cool_ops);
550554
551555 dev_info(dev, "GPIO fan initialized\n");
552556
553557 return 0;
554558 }
555559
556−static int gpio_fan_remove(struct platform_device *pdev)
560+static void gpio_fan_shutdown(struct platform_device *pdev)
557561 {
558562 struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
559563
560− if (!IS_ERR(fan_data->cdev))
561− thermal_cooling_device_unregister(fan_data->cdev);
562−
563564 if (fan_data->gpios)
564565 set_fan_speed(fan_data, 0);
565−
566− return 0;
567−}
568−
569−static void gpio_fan_shutdown(struct platform_device *pdev)
570−{
571− gpio_fan_remove(pdev);
572566 }
573567
574568 #ifdef CONFIG_PM_SLEEP
@@ -602,7 +596,6 @@ static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume); · 27 unmodified lines
602596
603597 static struct platform_driver gpio_fan_driver = {
604598 .probe = gpio_fan_probe,
605− .remove = gpio_fan_remove,
606599 .shutdown = gpio_fan_shutdown,
607600 .driver = {
608601 .name = "gpio-fan",
drivers/hwmon/mlxreg-fan.c+10−21
@@ -465,42 +465,42 @@ static int mlxreg_fan_config(struct mlxreg_fan *fan, · 464 unmodified lines
465465 static int mlxreg_fan_probe(struct platform_device *pdev)
466466 {
467467 struct mlxreg_core_platform_data *pdata;
468+ struct device *dev = &pdev->dev;
468469 struct mlxreg_fan *fan;
469470 struct device *hwm;
470471 int err;
471472
472− pdata = dev_get_platdata(&pdev->dev);
473+ pdata = dev_get_platdata(dev);
473474 if (!pdata) {
474− dev_err(&pdev->dev, "Failed to get platform data.\n");
475+ dev_err(dev, "Failed to get platform data.\n");
475476 return -EINVAL;
476477 }
477478
478− fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL);
479+ fan = devm_kzalloc(dev, sizeof(*fan), GFP_KERNEL);
479480 if (!fan)
480481 return -ENOMEM;
481482
482− fan->dev = &pdev->dev;
483+ fan->dev = dev;
483484 fan->regmap = pdata->regmap;
484− platform_set_drvdata(pdev, fan);
485485
486486 err = mlxreg_fan_config(fan, pdata);
487487 if (err)
488488 return err;
489489
490− hwm = devm_hwmon_device_register_with_info(&pdev->dev, "mlxreg_fan",
490+ hwm = devm_hwmon_device_register_with_info(dev, "mlxreg_fan",
491491 fan,
492492 &mlxreg_fan_hwmon_chip_info,
493493 NULL);
494494 if (IS_ERR(hwm)) {
495− dev_err(&pdev->dev, "Failed to register hwmon device\n");
495+ dev_err(dev, "Failed to register hwmon device\n");
496496 return PTR_ERR(hwm);
497497 }
498498
499499 if (IS_REACHABLE(CONFIG_THERMAL)) {
500− fan->cdev = thermal_cooling_device_register("mlxreg_fan", fan,
501− &mlxreg_fan_cooling_ops);
500+ fan->cdev = devm_thermal_of_cooling_device_register(dev,
501+ NULL, "mlxreg_fan", fan, &mlxreg_fan_cooling_ops);
502502 if (IS_ERR(fan->cdev)) {
503− dev_err(&pdev->dev, "Failed to register cooling device\n");
503+ dev_err(dev, "Failed to register cooling device\n");
504504 return PTR_ERR(fan->cdev);
505505 }
506506 }
@@ -508,22 +508,11 @@ static int mlxreg_fan_probe(struct platform_device *pdev) · 1 unmodified line
508508 return 0;
509509 }
510510
511−static int mlxreg_fan_remove(struct platform_device *pdev)
512−{
513− struct mlxreg_fan *fan = platform_get_drvdata(pdev);
514−
515− if (IS_REACHABLE(CONFIG_THERMAL))
516− thermal_cooling_device_unregister(fan->cdev);
517−
518− return 0;
519−}
520−
521511 static struct platform_driver mlxreg_fan_driver = {
522512 .driver = {
523513 .name = "mlxreg-fan",
524514 },
525515 .probe = mlxreg_fan_probe,
526− .remove = mlxreg_fan_remove,
527516 };
528517
529518 module_platform_driver(mlxreg_fan_driver);
drivers/hwmon/npcm750-pwm-fan.c+2−4
@@ -846,10 +846,8 @@ static int npcm7xx_create_pwm_cooling(struct device *dev, · 845 unmodified lines
846846 snprintf(cdev->name, THERMAL_NAME_LENGTH, "%pOFn%d", child,
847847 pwm_port);
848848
849− cdev->tcdev = thermal_of_cooling_device_register(child,
850− cdev->name,
851− cdev,
852− &npcm7xx_pwm_cool_ops);
849+ cdev->tcdev = devm_thermal_of_cooling_device_register(dev, child,
850+ cdev->name, cdev, &npcm7xx_pwm_cool_ops);
853851 if (IS_ERR(cdev->tcdev))
854852 return PTR_ERR(cdev->tcdev);
855853
drivers/hwmon/pwm-fan.c+38−59
@@ -273,27 +273,40 @@ static int pwm_fan_of_get_cooling_data(struct device *dev, · 272 unmodified lines
273273 return 0;
274274 }
275275
276+static void pwm_fan_regulator_disable(void *data)
277+{
278+ regulator_disable(data);
279+}
280+
281+static void pwm_fan_pwm_disable(void *__ctx)
282+{
283+ struct pwm_fan_ctx *ctx = __ctx;
284+ pwm_disable(ctx->pwm);
285+ del_timer_sync(&ctx->rpm_timer);
286+}
287+
276288 static int pwm_fan_probe(struct platform_device *pdev)
277289 {
278290 struct thermal_cooling_device *cdev;
291+ struct device *dev = &pdev->dev;
279292 struct pwm_fan_ctx *ctx;
280293 struct device *hwmon;
281294 int ret;
282295 struct pwm_state state = { };
283296 u32 ppr = 2;
284297
285− ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
298+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
286299 if (!ctx)
287300 return -ENOMEM;
288301
289302 mutex_init(&ctx->lock);
290303
291− ctx->pwm = devm_of_pwm_get(&pdev->dev, pdev->dev.of_node, NULL);
304+ ctx->pwm = devm_of_pwm_get(dev, dev->of_node, NULL);
292305 if (IS_ERR(ctx->pwm)) {
293306 ret = PTR_ERR(ctx->pwm);
294307
295308 if (ret != -EPROBE_DEFER)
296− dev_err(&pdev->dev, "Could not get PWM: %d\n", ret);
309+ dev_err(dev, "Could not get PWM: %d\n", ret);
297310
298311 return ret;
299312 }
@@ -304,7 +317,7 @@ static int pwm_fan_probe(struct platform_device *pdev) · 4 unmodified lines
304317 if (ctx->irq == -EPROBE_DEFER)
305318 return ctx->irq;
306319
307− ctx->reg_en = devm_regulator_get_optional(&pdev->dev, "fan");
320+ ctx->reg_en = devm_regulator_get_optional(dev, "fan");
308321 if (IS_ERR(ctx->reg_en)) {
309322 if (PTR_ERR(ctx->reg_en) != -ENODEV)
310323 return PTR_ERR(ctx->reg_en);
@@ -313,10 +326,11 @@ static int pwm_fan_probe(struct platform_device *pdev) · 2 unmodified lines
313326 } else {
314327 ret = regulator_enable(ctx->reg_en);
315328 if (ret) {
316− dev_err(&pdev->dev,
317− "Failed to enable fan supply: %d\n", ret);
329+ dev_err(dev, "Failed to enable fan supply: %d\n", ret);
318330 return ret;
319331 }
332+ devm_add_action_or_reset(dev, pwm_fan_regulator_disable,
333+ ctx->reg_en);
320334 }
321335
322336 ctx->pwm_value = MAX_PWM;
@@ -328,91 +342,57 @@ static int pwm_fan_probe(struct platform_device *pdev) · 5 unmodified lines
328342
329343 ret = pwm_apply_state(ctx->pwm, &state);
330344 if (ret) {
331− dev_err(&pdev->dev, "Failed to configure PWM: %d\n", ret);
332− goto err_reg_disable;
345+ dev_err(dev, "Failed to configure PWM: %d\n", ret);
346+ return ret;
333347 }
334−
335348 timer_setup(&ctx->rpm_timer, sample_timer, 0);
349+ devm_add_action_or_reset(dev, pwm_fan_pwm_disable, ctx);
336350
337− of_property_read_u32(pdev->dev.of_node, "pulses-per-revolution", &ppr);
351+ of_property_read_u32(dev->of_node, "pulses-per-revolution", &ppr);
338352 ctx->pulses_per_revolution = ppr;
339353 if (!ctx->pulses_per_revolution) {
340− dev_err(&pdev->dev, "pulses-per-revolution can't be zero.\n");
341− ret = -EINVAL;
342− goto err_pwm_disable;
354+ dev_err(dev, "pulses-per-revolution can't be zero.\n");
355+ return -EINVAL;
343356 }
344357
345358 if (ctx->irq > 0) {
346− ret = devm_request_irq(&pdev->dev, ctx->irq, pulse_handler, 0,
359+ ret = devm_request_irq(dev, ctx->irq, pulse_handler, 0,
347360 pdev->name, ctx);
348361 if (ret) {
349− dev_err(&pdev->dev,
350− "Failed to request interrupt: %d\n", ret);
351− goto err_pwm_disable;
362+ dev_err(dev, "Failed to request interrupt: %d\n", ret);
363+ return ret;
352364 }
353365 ctx->sample_start = ktime_get();
354366 mod_timer(&ctx->rpm_timer, jiffies + HZ);
355367 }
356368
357− hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, "pwmfan",
369+ hwmon = devm_hwmon_device_register_with_groups(dev, "pwmfan",
358370 ctx, pwm_fan_groups);
359371 if (IS_ERR(hwmon)) {
360− ret = PTR_ERR(hwmon);
361− dev_err(&pdev->dev,
362− "Failed to register hwmon device: %d\n", ret);
363− goto err_del_timer;
372+ dev_err(dev, "Failed to register hwmon device\n");
373+ return PTR_ERR(hwmon);
364374 }
365375
366− ret = pwm_fan_of_get_cooling_data(&pdev->dev, ctx);
376+ ret = pwm_fan_of_get_cooling_data(dev, ctx);
367377 if (ret)
368− goto err_del_timer;
378+ return ret;
369379
370380 ctx->pwm_fan_state = ctx->pwm_fan_max_state;
371381 if (IS_ENABLED(CONFIG_THERMAL)) {
372− cdev = thermal_of_cooling_device_register(pdev->dev.of_node,
373− "pwm-fan", ctx,
374− &pwm_fan_cooling_ops);
382+ cdev = devm_thermal_of_cooling_device_register(dev,
383+ dev->of_node, "pwm-fan", ctx, &pwm_fan_cooling_ops);
375384 if (IS_ERR(cdev)) {
376385 ret = PTR_ERR(cdev);
377− dev_err(&pdev->dev,
386+ dev_err(dev,
378387 "Failed to register pwm-fan as cooling device: %d\n",
379388 ret);
380− goto err_del_timer;
389+ return ret;
381390 }
382391 ctx->cdev = cdev;
383392 thermal_cdev_update(cdev);
384393 }
385394
386395 return 0;
387−
388−err_del_timer:
389− del_timer_sync(&ctx->rpm_timer);
390−
391−err_pwm_disable:
392− state.enabled = false;
393− pwm_apply_state(ctx->pwm, &state);
394−
395−err_reg_disable:
396− if (ctx->reg_en)
397− regulator_disable(ctx->reg_en);
398−
399− return ret;
400−}
401−
402−static int pwm_fan_remove(struct platform_device *pdev)
403−{
404− struct pwm_fan_ctx *ctx = platform_get_drvdata(pdev);
405−
406− thermal_cooling_device_unregister(ctx->cdev);
407− del_timer_sync(&ctx->rpm_timer);
408−
409− if (ctx->pwm_value)
410− pwm_disable(ctx->pwm);
411−
412− if (ctx->reg_en)
413− regulator_disable(ctx->reg_en);
414−
415− return 0;
416396 }
417397
418398 #ifdef CONFIG_PM_SLEEP
@@ -480,7 +460,6 @@ MODULE_DEVICE_TABLE(of, of_pwm_fan_match); · 61 unmodified lines
480460
481461 static struct platform_driver pwm_fan_driver = {
482462 .probe = pwm_fan_probe,
483− .remove = pwm_fan_remove,
484463 .driver = {
485464 .name = "pwm-fan",
486465 .pm = &pwm_fan_pm,
drivers/thermal/Kconfig+11−0
@@ -200,6 +200,17 @@ config THERMAL_EMULATION · 199 unmodified lines
200200 because userland can easily disable the thermal policy by simply
201201 flooding this sysfs node with low temperature values.
202202
203+config THERMAL_MMIO
204+ tristate "Generic Thermal MMIO driver"
205+ depends on OF || COMPILE_TEST
206+ depends on HAS_IOMEM
207+ help
208+ This option enables the generic thermal MMIO driver that will use
209+ memory-mapped reads to get the temperature. Any HW/System that
210+ allows temperature reading by a single memory-mapped reading, be it
211+ register or shared memory, is a potential candidate to work with this
212+ driver.
213+
203214 config HISI_THERMAL
204215 tristate "Hisilicon thermal driver"
205216 depends on ARCH_HISI || COMPILE_TEST
drivers/thermal/Makefile+1−0
@@ -29,6 +29,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o · 28 unmodified lines
2929
3030 # platform thermal drivers
3131 obj-y += broadcom/
32+obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
3233 obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
3334 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
3435 obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
drivers/thermal/broadcom/sr-thermal.c+0−8
@@ -3,7 +3,6 @@ · 2 unmodified lines
33 * Copyright (C) 2018 Broadcom
44 */
55
6−#include <linux/acpi.h>
76 #include <linux/module.h>
87 #include <linux/of_address.h>
98 #include <linux/platform_device.h>
@@ -100,18 +99,11 @@ static const struct of_device_id sr_thermal_of_match[] = { · 90 unmodified lines
10099 };
101100 MODULE_DEVICE_TABLE(of, sr_thermal_of_match);
102101
103−static const struct acpi_device_id sr_thermal_acpi_ids[] = {
104− { .id = "BRCM0500" },
105− { /* sentinel */ }
106−};
107−MODULE_DEVICE_TABLE(acpi, sr_thermal_acpi_ids);
108−
109102 static struct platform_driver sr_thermal_driver = {
110103 .probe = sr_thermal_probe,
111104 .driver = {
112105 .name = "sr-thermal",
113106 .of_match_table = sr_thermal_of_match,
114− .acpi_match_table = ACPI_PTR(sr_thermal_acpi_ids),
115107 },
116108 };
117109 module_platform_driver(sr_thermal_driver);
drivers/thermal/cpu_cooling.c+7−23
@@ -1,26 +1,14 @@
1+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * linux/drivers/thermal/cpu_cooling.c
34 *
45 * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com)
5− * Copyright (C) 2012 Amit Daniel <amit.kachhap@linaro.org>
66 *
7− * Copyright (C) 2014 Viresh Kumar <viresh.kumar@linaro.org>
7+ * Copyright (C) 2012-2018 Linaro Limited.
88 *
9− * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10− * This program is free software; you can redistribute it and/or modify
11− * it under the terms of the GNU General Public License as published by
12− * the Free Software Foundation; version 2 of the License.
9+ * Authors: Amit Daniel <amit.kachhap@linaro.org>
10+ * Viresh Kumar <viresh.kumar@linaro.org>
1311 *
14− * This program is distributed in the hope that it will be useful, but
15− * WITHOUT ANY WARRANTY; without even the implied warranty of
16− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17− * General Public License for more details.
18− *
19− * You should have received a copy of the GNU General Public License along
20− * with this program; if not, write to the Free Software Foundation, Inc.,
21− * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22− *
23− * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2412 */
2513 #include <linux/module.h>
2614 #include <linux/thermal.h>
@@ -99,7 +87,6 @@ struct cpufreq_cooling_device { · 72 unmodified lines
9987 unsigned int clipped_freq;
10088 unsigned int max_level;
10189 struct freq_table *freq_table; /* In descending order */
102− struct thermal_cooling_device *cdev;
10390 struct cpufreq_policy *policy;
10491 struct list_head node;
10592 struct time_in_idle *idle_time;
@@ -207,8 +194,7 @@ static int update_freq_table(struct cpufreq_cooling_device *cpufreq_cdev, · 101 unmodified lines
207194
208195 dev = get_cpu_device(cpu);
209196 if (unlikely(!dev)) {
210− dev_warn(&cpufreq_cdev->cdev->device,
211− "No cpu device for cpu %d\n", cpu);
197+ pr_warn("No cpu device for cpu %d\n", cpu);
212198 return -ENODEV;
213199 }
214200
@@ -458,7 +444,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, · 243 unmodified lines
458444 load = 0;
459445
460446 total_load += load;
461− if (trace_thermal_power_cpu_limit_enabled() && load_cpu)
447+ if (load_cpu)
462448 load_cpu[i] = load;
463449
464450 i++;
@@ -541,7 +527,6 @@ static int cpufreq_power2state(struct thermal_cooling_device *cdev, · 76 unmodified lines
541527 struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
542528 struct cpufreq_policy *policy = cpufreq_cdev->policy;
543529
544− power = power > 0 ? power : 0;
545530 last_load = cpufreq_cdev->last_load ?: 1;
546531 normalised_power = (power * 100) / last_load;
547532 target_freq = cpu_power_to_freq(cpufreq_cdev, normalised_power);
@@ -692,7 +677,6 @@ __cpufreq_cooling_register(struct device_node *np, · 144 unmodified lines
692677 goto remove_ida;
693678
694679 cpufreq_cdev->clipped_freq = cpufreq_cdev->freq_table[0].frequency;
695− cpufreq_cdev->cdev = cdev;
696680
697681 mutex_lock(&cooling_list_lock);
698682 /* Register the notifier for first cpufreq cooling device */
@@ -810,7 +794,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) · 111 unmodified lines
810794 cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
811795 CPUFREQ_POLICY_NOTIFIER);
812796
813− thermal_cooling_device_unregister(cpufreq_cdev->cdev);
797+ thermal_cooling_device_unregister(cdev);
814798 ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id);
815799 kfree(cpufreq_cdev->idle_time);
816800 kfree(cpufreq_cdev->freq_table);
drivers/thermal/of-thermal.c+3−0
@@ -5,6 +5,9 @@ · 4 unmodified lines
55 * Copyright (C) 2013 Texas Instruments
66 * Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
77 */
8+
9+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10+
811 #include <linux/thermal.h>
912 #include <linux/slab.h>
1013 #include <linux/types.h>
drivers/thermal/qcom/Makefile+3−1
@@ -1,3 +1,5 @@
11 obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o
2−qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-v2.o
2+
3+qcom_tsens-y += tsens.o tsens-common.o tsens-v0_1.o \
4+ tsens-8960.o tsens-v2.o tsens-v1.o
35 obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
drivers/thermal/qcom/tsens-8916.c+0−105
@@ -1,105 +0,0 @@
1−// SPDX-License-Identifier: GPL-2.0
2−/*
3− * Copyright (c) 2015, The Linux Foundation. All rights reserved.
4− */
5−
6−#include <linux/platform_device.h>
7−#include "tsens.h"
8−
9−/* eeprom layout data for 8916 */
10−#define BASE0_MASK 0x0000007f
11−#define BASE1_MASK 0xfe000000
12−#define BASE0_SHIFT 0
13−#define BASE1_SHIFT 25
14−
15−#define S0_P1_MASK 0x00000f80
16−#define S1_P1_MASK 0x003e0000
17−#define S2_P1_MASK 0xf8000000
18−#define S3_P1_MASK 0x000003e0
19−#define S4_P1_MASK 0x000f8000
20−
21−#define S0_P2_MASK 0x0001f000
22−#define S1_P2_MASK 0x07c00000
23−#define S2_P2_MASK 0x0000001f
24−#define S3_P2_MASK 0x00007c00
25−#define S4_P2_MASK 0x01f00000
26−
27−#define S0_P1_SHIFT 7
28−#define S1_P1_SHIFT 17
29−#define S2_P1_SHIFT 27
30−#define S3_P1_SHIFT 5
31−#define S4_P1_SHIFT 15
32−
33−#define S0_P2_SHIFT 12
34−#define S1_P2_SHIFT 22
35−#define S2_P2_SHIFT 0
36−#define S3_P2_SHIFT 10
37−#define S4_P2_SHIFT 20
38−
39−#define CAL_SEL_MASK 0xe0000000
40−#define CAL_SEL_SHIFT 29
41−
42−static int calibrate_8916(struct tsens_device *tmdev)
43−{
44− int base0 = 0, base1 = 0, i;
45− u32 p1[5], p2[5];
46− int mode = 0;
47− u32 *qfprom_cdata, *qfprom_csel;
48−
49− qfprom_cdata = (u32 *)qfprom_read(tmdev->dev, "calib");
50− if (IS_ERR(qfprom_cdata))
51− return PTR_ERR(qfprom_cdata);
52−
53− qfprom_csel = (u32 *)qfprom_read(tmdev->dev, "calib_sel");
54− if (IS_ERR(qfprom_csel))
55− return PTR_ERR(qfprom_csel);
56−
57− mode = (qfprom_csel[0] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
58− dev_dbg(tmdev->dev, "calibration mode is %d\n", mode);
59−
60− switch (mode) {
61− case TWO_PT_CALIB:
62− base1 = (qfprom_cdata[1] & BASE1_MASK) >> BASE1_SHIFT;
63− p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
64− p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
65− p2[2] = (qfprom_cdata[1] & S2_P2_MASK) >> S2_P2_SHIFT;
66− p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
67− p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
68− for (i = 0; i < tmdev->num_sensors; i++)
69− p2[i] = ((base1 + p2[i]) << 3);
70− /* Fall through */
71− case ONE_PT_CALIB2:
72− base0 = (qfprom_cdata[0] & BASE0_MASK);
73− p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
74− p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
75− p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
76− p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
77− p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
78− for (i = 0; i < tmdev->num_sensors; i++)
79− p1[i] = (((base0) + p1[i]) << 3);
80− break;
81− default:
82− for (i = 0; i < tmdev->num_sensors; i++) {
83− p1[i] = 500;
84− p2[i] = 780;
85− }
86− break;
87− }
88−
89− compute_intercept_slope(tmdev, p1, p2, mode);
90−
91− return 0;
92−}
93−
94−static const struct tsens_ops ops_8916 = {
95− .init = init_common,
96− .calibrate = calibrate_8916,
97− .get_temp = get_temp_common,
98−};
99−
100−const struct tsens_data data_8916 = {
101− .num_sensors = 5,
102− .ops = &ops_8916,
103− .reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 },
104− .hw_ids = (unsigned int []){0, 1, 2, 4, 5 },
105−};
drivers/thermal/qcom/tsens-8960.c+42−42
@@ -56,21 +56,21 @@ · 55 unmodified lines
5656 #define TRDY_MASK BIT(7)
5757 #define TIMEOUT_US 100
5858
59−static int suspend_8960(struct tsens_device *tmdev)
59+static int suspend_8960(struct tsens_priv *priv)
6060 {
6161 int ret;
6262 unsigned int mask;
63− struct regmap *map = tmdev->tm_map;
63+ struct regmap *map = priv->tm_map;
6464
65− ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold);
65+ ret = regmap_read(map, THRESHOLD_ADDR, &priv->ctx.threshold);
6666 if (ret)
6767 return ret;
6868
69− ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control);
69+ ret = regmap_read(map, CNTL_ADDR, &priv->ctx.control);
7070 if (ret)
7171 return ret;
7272
73− if (tmdev->num_sensors > 1)
73+ if (priv->num_sensors > 1)
7474 mask = SLP_CLK_ENA | EN;
7575 else
7676 mask = SLP_CLK_ENA_8660 | EN;
@@ -82,10 +82,10 @@ static int suspend_8960(struct tsens_device *tmdev) · 5 unmodified lines
8282 return 0;
8383 }
8484
85−static int resume_8960(struct tsens_device *tmdev)
85+static int resume_8960(struct tsens_priv *priv)
8686 {
8787 int ret;
88− struct regmap *map = tmdev->tm_map;
88+ struct regmap *map = priv->tm_map;
8989
9090 ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
9191 if (ret)
@@ -95,80 +95,80 @@ static int resume_8960(struct tsens_device *tmdev) · 3 unmodified lines
9595 * Separate CONFIG restore is not needed only for 8660 as
9696 * config is part of CTRL Addr and its restored as such
9797 */
98− if (tmdev->num_sensors > 1) {
98+ if (priv->num_sensors > 1) {
9999 ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
100100 if (ret)
101101 return ret;
102102 }
103103
104− ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold);
104+ ret = regmap_write(map, THRESHOLD_ADDR, priv->ctx.threshold);
105105 if (ret)
106106 return ret;
107107
108− ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control);
108+ ret = regmap_write(map, CNTL_ADDR, priv->ctx.control);
109109 if (ret)
110110 return ret;
111111
112112 return 0;
113113 }
114114
115−static int enable_8960(struct tsens_device *tmdev, int id)
115+static int enable_8960(struct tsens_priv *priv, int id)
116116 {
117117 int ret;
118118 u32 reg, mask;
119119
120− ret = regmap_read(tmdev->tm_map, CNTL_ADDR, &reg);
120+ ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg);
121121 if (ret)
122122 return ret;
123123
124124 mask = BIT(id + SENSOR0_SHIFT);
125− ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg | SW_RST);
125+ ret = regmap_write(priv->tm_map, CNTL_ADDR, reg | SW_RST);
126126 if (ret)
127127 return ret;
128128
129− if (tmdev->num_sensors > 1)
129+ if (priv->num_sensors > 1)
130130 reg |= mask | SLP_CLK_ENA | EN;
131131 else
132132 reg |= mask | SLP_CLK_ENA_8660 | EN;
133133
134− ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg);
134+ ret = regmap_write(priv->tm_map, CNTL_ADDR, reg);
135135 if (ret)
136136 return ret;
137137
138138 return 0;
139139 }
140140
141−static void disable_8960(struct tsens_device *tmdev)
141+static void disable_8960(struct tsens_priv *priv)
142142 {
143143 int ret;
144144 u32 reg_cntl;
145145 u32 mask;
146146
147− mask = GENMASK(tmdev->num_sensors - 1, 0);
147+ mask = GENMASK(priv->num_sensors - 1, 0);
148148 mask <<= SENSOR0_SHIFT;
149149 mask |= EN;
150150
151− ret = regmap_read(tmdev->tm_map, CNTL_ADDR, &reg_cntl);
151+ ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg_cntl);
152152 if (ret)
153153 return;
154154
155155 reg_cntl &= ~mask;
156156
157− if (tmdev->num_sensors > 1)
157+ if (priv->num_sensors > 1)
158158 reg_cntl &= ~SLP_CLK_ENA;
159159 else
160160 reg_cntl &= ~SLP_CLK_ENA_8660;
161161
162− regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
162+ regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
163163 }
164164
165−static int init_8960(struct tsens_device *tmdev)
165+static int init_8960(struct tsens_priv *priv)
166166 {
167167 int ret, i;
168168 u32 reg_cntl;
169169
170− tmdev->tm_map = dev_get_regmap(tmdev->dev, NULL);
171− if (!tmdev->tm_map)
170+ priv->tm_map = dev_get_regmap(priv->dev, NULL);
171+ if (!priv->tm_map)
172172 return -ENODEV;
173173
174174 /*
@@ -177,21 +177,21 @@ static int init_8960(struct tsens_device *tmdev) · 2 unmodified lines
177177 * but the control registers stay in the same place, i.e
178178 * directly after the first 5 status registers.
179179 */
180− for (i = 0; i < tmdev->num_sensors; i++) {
180+ for (i = 0; i < priv->num_sensors; i++) {
181181 if (i >= 5)
182− tmdev->sensor[i].status = S0_STATUS_ADDR + 40;
183− tmdev->sensor[i].status += i * 4;
182+ priv->sensor[i].status = S0_STATUS_ADDR + 40;
183+ priv->sensor[i].status += i * 4;
184184 }
185185
186186 reg_cntl = SW_RST;
187− ret = regmap_update_bits(tmdev->tm_map, CNTL_ADDR, SW_RST, reg_cntl);
187+ ret = regmap_update_bits(priv->tm_map, CNTL_ADDR, SW_RST, reg_cntl);
188188 if (ret)
189189 return ret;
190190
191− if (tmdev->num_sensors > 1) {
191+ if (priv->num_sensors > 1) {
192192 reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18);
193193 reg_cntl &= ~SW_RST;
194− ret = regmap_update_bits(tmdev->tm_map, CONFIG_ADDR,
194+ ret = regmap_update_bits(priv->tm_map, CONFIG_ADDR,
195195 CONFIG_MASK, CONFIG);
196196 } else {
197197 reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16);
@@ -199,30 +199,30 @@ static int init_8960(struct tsens_device *tmdev) · 1 unmodified line
199199 reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660;
200200 }
201201
202− reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT;
203− ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
202+ reg_cntl |= GENMASK(priv->num_sensors - 1, 0) << SENSOR0_SHIFT;
203+ ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
204204 if (ret)
205205 return ret;
206206
207207 reg_cntl |= EN;
208− ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
208+ ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
209209 if (ret)
210210 return ret;
211211
212212 return 0;
213213 }
214214
215−static int calibrate_8960(struct tsens_device *tmdev)
215+static int calibrate_8960(struct tsens_priv *priv)
216216 {
217217 int i;
218218 char *data;
219219
220− ssize_t num_read = tmdev->num_sensors;
221− struct tsens_sensor *s = tmdev->sensor;
220+ ssize_t num_read = priv->num_sensors;
221+ struct tsens_sensor *s = priv->sensor;
222222
223− data = qfprom_read(tmdev->dev, "calib");
223+ data = qfprom_read(priv->dev, "calib");
224224 if (IS_ERR(data))
225− data = qfprom_read(tmdev->dev, "calib_backup");
225+ data = qfprom_read(priv->dev, "calib_backup");
226226 if (IS_ERR(data))
227227 return PTR_ERR(data);
228228
@@ -243,21 +243,21 @@ static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s) · 14 unmodified lines
243243 return adc_code * slope + offset;
244244 }
245245
246−static int get_temp_8960(struct tsens_device *tmdev, int id, int *temp)
246+static int get_temp_8960(struct tsens_priv *priv, int id, int *temp)
247247 {
248248 int ret;
249249 u32 code, trdy;
250− const struct tsens_sensor *s = &tmdev->sensor[id];
250+ const struct tsens_sensor *s = &priv->sensor[id];
251251 unsigned long timeout;
252252
253253 timeout = jiffies + usecs_to_jiffies(TIMEOUT_US);
254254 do {
255− ret = regmap_read(tmdev->tm_map, INT_STATUS_ADDR, &trdy);
255+ ret = regmap_read(priv->tm_map, INT_STATUS_ADDR, &trdy);
256256 if (ret)
257257 return ret;
258258 if (!(trdy & TRDY_MASK))
259259 continue;
260− ret = regmap_read(tmdev->tm_map, s->status, &code);
260+ ret = regmap_read(priv->tm_map, s->status, &code);
261261 if (ret)
262262 return ret;
263263 *temp = code_to_mdegC(code, s);
@@ -277,7 +277,7 @@ static const struct tsens_ops ops_8960 = { · 13 unmodified lines
277277 .resume = resume_8960,
278278 };
279279
280−const struct tsens_data data_8960 = {
280+const struct tsens_plat_data data_8960 = {
281281 .num_sensors = 11,
282282 .ops = &ops_8960,
283283 };
drivers/thermal/qcom/tsens-common.c+112−47
@@ -12,18 +12,6 @@ · 11 unmodified lines
1212 #include <linux/regmap.h>
1313 #include "tsens.h"
1414
15−/* SROT */
16−#define TSENS_EN BIT(0)
17−
18−/* TM */
19−#define STATUS_OFFSET 0x30
20−#define SN_ADDR_OFFSET 0x4
21−#define SN_ST_TEMP_MASK 0x3ff
22−#define CAL_DEGC_PT1 30
23−#define CAL_DEGC_PT2 120
24−#define SLOPE_FACTOR 1000
25−#define SLOPE_DEFAULT 3200
26−
2715 char *qfprom_read(struct device *dev, const char *cname)
2816 {
2917 struct nvmem_cell *cell;
@@ -46,18 +34,18 @@ char *qfprom_read(struct device *dev, const char *cname) · 16 unmodified lines
4634 * and offset values are derived from tz->tzp->slope and tz->tzp->offset
4735 * resp.
4836 */
49−void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
37+void compute_intercept_slope(struct tsens_priv *priv, u32 *p1,
5038 u32 *p2, u32 mode)
5139 {
5240 int i;
5341 int num, den;
5442
55− for (i = 0; i < tmdev->num_sensors; i++) {
56− dev_dbg(tmdev->dev,
43+ for (i = 0; i < priv->num_sensors; i++) {
44+ dev_dbg(priv->dev,
5745 "sensor%d - data_point1:%#x data_point2:%#x\n",
5846 i, p1[i], p2[i]);
5947
60− tmdev->sensor[i].slope = SLOPE_DEFAULT;
48+ priv->sensor[i].slope = SLOPE_DEFAULT;
6149 if (mode == TWO_PT_CALIB) {
6250 /*
6351 * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
@@ -66,16 +54,30 @@ void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1, · 2 unmodified lines
6654 num = p2[i] - p1[i];
6755 num *= SLOPE_FACTOR;
6856 den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
69− tmdev->sensor[i].slope = num / den;
57+ priv->sensor[i].slope = num / den;
7058 }
7159
72− tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
60+ priv->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
7361 (CAL_DEGC_PT1 *
74− tmdev->sensor[i].slope);
75− dev_dbg(tmdev->dev, "offset:%d\n", tmdev->sensor[i].offset);
62+ priv->sensor[i].slope);
63+ dev_dbg(priv->dev, "offset:%d\n", priv->sensor[i].offset);
7664 }
7765 }
7866
67+bool is_sensor_enabled(struct tsens_priv *priv, u32 hw_id)
68+{
69+ u32 val;
70+ int ret;
71+
72+ if ((hw_id > (priv->num_sensors - 1)) || (hw_id < 0))
73+ return -EINVAL;
74+ ret = regmap_field_read(priv->rf[SENSOR_EN], &val);
75+ if (ret)
76+ return ret;
77+
78+ return val & (1 << hw_id);
79+}
80+
7981 static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
8082 {
8183 int degc, num, den;
@@ -95,18 +97,54 @@ static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s) · 13 unmodified lines
9597 return degc;
9698 }
9799
98−int get_temp_common(struct tsens_device *tmdev, int id, int *temp)
100+int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp)
99101 {
100− struct tsens_sensor *s = &tmdev->sensor[id];
101− u32 code;
102− unsigned int status_reg;
102+ struct tsens_sensor *s = &priv->sensor[i];
103+ u32 temp_idx = LAST_TEMP_0 + s->hw_id;
104+ u32 valid_idx = VALID_0 + s->hw_id;
105+ u32 last_temp = 0, valid, mask;
106+ int ret;
107+
108+ ret = regmap_field_read(priv->rf[valid_idx], &valid);
109+ if (ret)
110+ return ret;
111+ while (!valid) {
112+ /* Valid bit is 0 for 6 AHB clock cycles.
113+ * At 19.2MHz, 1 AHB clock is ~60ns.
114+ * We should enter this loop very, very rarely.
115+ */
116+ ndelay(400);
117+ ret = regmap_field_read(priv->rf[valid_idx], &valid);
118+ if (ret)
119+ return ret;
120+ }
121+
122+ /* Valid bit is set, OK to read the temperature */
123+ ret = regmap_field_read(priv->rf[temp_idx], &last_temp);
124+ if (ret)
125+ return ret;
126+
127+ if (priv->feat->adc) {
128+ /* Convert temperature from ADC code to milliCelsius */
129+ *temp = code_to_degc(last_temp, s) * 1000;
130+ } else {
131+ mask = GENMASK(priv->fields[LAST_TEMP_0].msb,
132+ priv->fields[LAST_TEMP_0].lsb);
133+ /* Convert temperature from deciCelsius to milliCelsius */
134+ *temp = sign_extend32(last_temp, fls(mask) - 1) * 100;
135+ }
136+
137+ return 0;
138+}
139+
140+int get_temp_common(struct tsens_priv *priv, int i, int *temp)
141+{
142+ struct tsens_sensor *s = &priv->sensor[i];
103143 int last_temp = 0, ret;
104144
105− status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * SN_ADDR_OFFSET;
106− ret = regmap_read(tmdev->tm_map, status_reg, &code);
145+ ret = regmap_field_read(priv->rf[LAST_TEMP_0 + s->hw_id], &last_temp);
107146 if (ret)
108147 return ret;
109− last_temp = code & SN_ST_TEMP_MASK;
110148
111149 *temp = code_to_degc(last_temp, s) * 1000;
112150
@@ -127,21 +165,21 @@ static const struct regmap_config tsens_srot_config = { · 14 unmodified lines
127165 .reg_stride = 4,
128166 };
129167
130−int __init init_common(struct tsens_device *tmdev)
168+int __init init_common(struct tsens_priv *priv)
131169 {
132170 void __iomem *tm_base, *srot_base;
171+ struct device *dev = priv->dev;
133172 struct resource *res;
134− u32 code;
135− int ret;
136− struct platform_device *op = of_find_device_by_node(tmdev->dev->of_node);
137− u16 ctrl_offset = tmdev->reg_offsets[SROT_CTRL_OFFSET];
173+ u32 enabled;
174+ int ret, i, j;
175+ struct platform_device *op = of_find_device_by_node(priv->dev->of_node);
138176
139177 if (!op)
140178 return -EINVAL;
141179
142180 if (op->num_resources > 1) {
143181 /* DT with separate SROT and TM address space */
144− tmdev->tm_offset = 0;
182+ priv->tm_offset = 0;
145183 res = platform_get_resource(op, IORESOURCE_MEM, 1);
146184 srot_base = devm_ioremap_resource(&op->dev, res);
147185 if (IS_ERR(srot_base)) {
@@ -149,16 +187,15 @@ int __init init_common(struct tsens_device *tmdev) · 1 unmodified line
149187 goto err_put_device;
150188 }
151189
152− tmdev->srot_map = devm_regmap_init_mmio(tmdev->dev, srot_base,
190+ priv->srot_map = devm_regmap_init_mmio(dev, srot_base,
153191 &tsens_srot_config);
154− if (IS_ERR(tmdev->srot_map)) {
155− ret = PTR_ERR(tmdev->srot_map);
192+ if (IS_ERR(priv->srot_map)) {
193+ ret = PTR_ERR(priv->srot_map);
156194 goto err_put_device;
157195 }
158−
159196 } else {
160197 /* old DTs where SROT and TM were in a contiguous 2K block */
161− tmdev->tm_offset = 0x1000;
198+ priv->tm_offset = 0x1000;
162199 }
163200
164201 res = platform_get_resource(op, IORESOURCE_MEM, 0);
@@ -168,19 +205,47 @@ int __init init_common(struct tsens_device *tmdev) · 3 unmodified lines
168205 goto err_put_device;
169206 }
170207
171− tmdev->tm_map = devm_regmap_init_mmio(tmdev->dev, tm_base, &tsens_config);
172− if (IS_ERR(tmdev->tm_map)) {
173− ret = PTR_ERR(tmdev->tm_map);
208+ priv->tm_map = devm_regmap_init_mmio(dev, tm_base, &tsens_config);
209+ if (IS_ERR(priv->tm_map)) {
210+ ret = PTR_ERR(priv->tm_map);
174211 goto err_put_device;
175212 }
176213
177− if (tmdev->srot_map) {
178− ret = regmap_read(tmdev->srot_map, ctrl_offset, &code);
179− if (ret)
214+ priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
215+ priv->fields[TSENS_EN]);
216+ if (IS_ERR(priv->rf[TSENS_EN])) {
217+ ret = PTR_ERR(priv->rf[TSENS_EN]);
218+ goto err_put_device;
219+ }
220+ ret = regmap_field_read(priv->rf[TSENS_EN], &enabled);
221+ if (ret)
222+ goto err_put_device;
223+ if (!enabled) {
224+ dev_err(dev, "tsens device is not enabled\n");
225+ ret = -ENODEV;
226+ goto err_put_device;
227+ }
228+
229+ priv->rf[SENSOR_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
230+ priv->fields[SENSOR_EN]);
231+ if (IS_ERR(priv->rf[SENSOR_EN])) {
232+ ret = PTR_ERR(priv->rf[SENSOR_EN]);
233+ goto err_put_device;
234+ }
235+ /* now alloc regmap_fields in tm_map */
236+ for (i = 0, j = LAST_TEMP_0; i < priv->feat->max_sensors; i++, j++) {
237+ priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map,
238+ priv->fields[j]);
239+ if (IS_ERR(priv->rf[j])) {
240+ ret = PTR_ERR(priv->rf[j]);
180241 goto err_put_device;
181− if (!(code & TSENS_EN)) {
182− dev_err(tmdev->dev, "tsens device is not enabled\n");
183− ret = -ENODEV;
242+ }
243+ }
244+ for (i = 0, j = VALID_0; i < priv->feat->max_sensors; i++, j++) {
245+ priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map,
246+ priv->fields[j]);
247+ if (IS_ERR(priv->rf[j])) {
248+ ret = PTR_ERR(priv->rf[j]);
184249 goto err_put_device;
185250 }
186251 }
drivers/thermal/qcom/tsens-v0_1.crenamed from drivers/thermal/qcom/tsens-8974.c+156−10
@@ -6,6 +6,48 @@ · 5 unmodified lines
66 #include <linux/platform_device.h>
77 #include "tsens.h"
88
9+/* ----- SROT ------ */
10+#define SROT_CTRL_OFF 0x0000
11+
12+/* ----- TM ------ */
13+#define TM_INT_EN_OFF 0x0000
14+#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004
15+#define TM_Sn_STATUS_OFF 0x0030
16+#define TM_TRDY_OFF 0x005c
17+
18+/* eeprom layout data for 8916 */
19+#define MSM8916_BASE0_MASK 0x0000007f
20+#define MSM8916_BASE1_MASK 0xfe000000
21+#define MSM8916_BASE0_SHIFT 0
22+#define MSM8916_BASE1_SHIFT 25
23+
24+#define MSM8916_S0_P1_MASK 0x00000f80
25+#define MSM8916_S1_P1_MASK 0x003e0000
26+#define MSM8916_S2_P1_MASK 0xf8000000
27+#define MSM8916_S3_P1_MASK 0x000003e0
28+#define MSM8916_S4_P1_MASK 0x000f8000
29+
30+#define MSM8916_S0_P2_MASK 0x0001f000
31+#define MSM8916_S1_P2_MASK 0x07c00000
32+#define MSM8916_S2_P2_MASK 0x0000001f
33+#define MSM8916_S3_P2_MASK 0x00007c00
34+#define MSM8916_S4_P2_MASK 0x01f00000
35+
36+#define MSM8916_S0_P1_SHIFT 7
37+#define MSM8916_S1_P1_SHIFT 17
38+#define MSM8916_S2_P1_SHIFT 27
39+#define MSM8916_S3_P1_SHIFT 5
40+#define MSM8916_S4_P1_SHIFT 15
41+
42+#define MSM8916_S0_P2_SHIFT 12
43+#define MSM8916_S1_P2_SHIFT 22
44+#define MSM8916_S2_P2_SHIFT 0
45+#define MSM8916_S3_P2_SHIFT 10
46+#define MSM8916_S4_P2_SHIFT 20
47+
48+#define MSM8916_CAL_SEL_MASK 0xe0000000
49+#define MSM8916_CAL_SEL_SHIFT 29
50+
951 /* eeprom layout data for 8974 */
1052 #define BASE1_MASK 0xff
1153 #define S0_P1_MASK 0x3f00
@@ -91,7 +133,59 @@ · 79 unmodified lines
91133
92134 #define BIT_APPEND 0x3
93135
94−static int calibrate_8974(struct tsens_device *tmdev)
136+static int calibrate_8916(struct tsens_priv *priv)
137+{
138+ int base0 = 0, base1 = 0, i;
139+ u32 p1[5], p2[5];
140+ int mode = 0;
141+ u32 *qfprom_cdata, *qfprom_csel;
142+
143+ qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
144+ if (IS_ERR(qfprom_cdata))
145+ return PTR_ERR(qfprom_cdata);
146+
147+ qfprom_csel = (u32 *)qfprom_read(priv->dev, "calib_sel");
148+ if (IS_ERR(qfprom_csel))
149+ return PTR_ERR(qfprom_csel);
150+
151+ mode = (qfprom_csel[0] & MSM8916_CAL_SEL_MASK) >> MSM8916_CAL_SEL_SHIFT;
152+ dev_dbg(priv->dev, "calibration mode is %d\n", mode);
153+
154+ switch (mode) {
155+ case TWO_PT_CALIB:
156+ base1 = (qfprom_cdata[1] & MSM8916_BASE1_MASK) >> MSM8916_BASE1_SHIFT;
157+ p2[0] = (qfprom_cdata[0] & MSM8916_S0_P2_MASK) >> MSM8916_S0_P2_SHIFT;
158+ p2[1] = (qfprom_cdata[0] & MSM8916_S1_P2_MASK) >> MSM8916_S1_P2_SHIFT;
159+ p2[2] = (qfprom_cdata[1] & MSM8916_S2_P2_MASK) >> MSM8916_S2_P2_SHIFT;
160+ p2[3] = (qfprom_cdata[1] & MSM8916_S3_P2_MASK) >> MSM8916_S3_P2_SHIFT;
161+ p2[4] = (qfprom_cdata[1] & MSM8916_S4_P2_MASK) >> MSM8916_S4_P2_SHIFT;
162+ for (i = 0; i < priv->num_sensors; i++)
163+ p2[i] = ((base1 + p2[i]) << 3);
164+ /* Fall through */
165+ case ONE_PT_CALIB2:
166+ base0 = (qfprom_cdata[0] & MSM8916_BASE0_MASK);
167+ p1[0] = (qfprom_cdata[0] & MSM8916_S0_P1_MASK) >> MSM8916_S0_P1_SHIFT;
168+ p1[1] = (qfprom_cdata[0] & MSM8916_S1_P1_MASK) >> MSM8916_S1_P1_SHIFT;
169+ p1[2] = (qfprom_cdata[0] & MSM8916_S2_P1_MASK) >> MSM8916_S2_P1_SHIFT;
170+ p1[3] = (qfprom_cdata[1] & MSM8916_S3_P1_MASK) >> MSM8916_S3_P1_SHIFT;
171+ p1[4] = (qfprom_cdata[1] & MSM8916_S4_P1_MASK) >> MSM8916_S4_P1_SHIFT;
172+ for (i = 0; i < priv->num_sensors; i++)
173+ p1[i] = (((base0) + p1[i]) << 3);
174+ break;
175+ default:
176+ for (i = 0; i < priv->num_sensors; i++) {
177+ p1[i] = 500;
178+ p2[i] = 780;
179+ }
180+ break;
181+ }
182+
183+ compute_intercept_slope(priv, p1, p2, mode);
184+
185+ return 0;
186+}
187+
188+static int calibrate_8974(struct tsens_priv *priv)
95189 {
96190 int base1 = 0, base2 = 0, i;
97191 u32 p1[11], p2[11];
@@ -99,11 +193,11 @@ static int calibrate_8974(struct tsens_device *tmdev) · 1 unmodified line
99193 u32 *calib, *bkp;
100194 u32 calib_redun_sel;
101195
102− calib = (u32 *)qfprom_read(tmdev->dev, "calib");
196+ calib = (u32 *)qfprom_read(priv->dev, "calib");
103197 if (IS_ERR(calib))
104198 return PTR_ERR(calib);
105199
106− bkp = (u32 *)qfprom_read(tmdev->dev, "calib_backup");
200+ bkp = (u32 *)qfprom_read(priv->dev, "calib_backup");
107201 if (IS_ERR(bkp))
108202 return PTR_ERR(bkp);
109203
@@ -184,25 +278,25 @@ static int calibrate_8974(struct tsens_device *tmdev) · 74 unmodified lines
184278
185279 switch (mode) {
186280 case ONE_PT_CALIB:
187− for (i = 0; i < tmdev->num_sensors; i++)
281+ for (i = 0; i < priv->num_sensors; i++)
188282 p1[i] += (base1 << 2) | BIT_APPEND;
189283 break;
190284 case TWO_PT_CALIB:
191− for (i = 0; i < tmdev->num_sensors; i++) {
285+ for (i = 0; i < priv->num_sensors; i++) {
192286 p2[i] += base2;
193287 p2[i] <<= 2;
194288 p2[i] |= BIT_APPEND;
195289 }
196290 /* Fall through */
197291 case ONE_PT_CALIB2:
198− for (i = 0; i < tmdev->num_sensors; i++) {
292+ for (i = 0; i < priv->num_sensors; i++) {
199293 p1[i] += base1;
200294 p1[i] <<= 2;
201295 p1[i] |= BIT_APPEND;
202296 }
203297 break;
204298 default:
205− for (i = 0; i < tmdev->num_sensors; i++)
299+ for (i = 0; i < priv->num_sensors; i++)
206300 p2[i] = 780;
207301 p1[0] = 502;
208302 p1[1] = 509;
@@ -218,19 +312,71 @@ static int calibrate_8974(struct tsens_device *tmdev) · 9 unmodified lines
218312 break;
219313 }
220314
221− compute_intercept_slope(tmdev, p1, p2, mode);
315+ compute_intercept_slope(priv, p1, p2, mode);
222316
223317 return 0;
224318 }
225319
320+/* v0.1: 8916, 8974 */
321+
322+static const struct tsens_features tsens_v0_1_feat = {
323+ .ver_major = VER_0_1,
324+ .crit_int = 0,
325+ .adc = 1,
326+ .srot_split = 1,
327+ .max_sensors = 11,
328+};
329+
330+static const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = {
331+ /* ----- SROT ------ */
332+ /* No VERSION information */
333+
334+ /* CTRL_OFFSET */
335+ [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
336+ [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
337+ [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13),
338+
339+ /* ----- TM ------ */
340+ /* INTERRUPT ENABLE */
341+ [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0),
342+
343+ /* Sn_STATUS */
344+ REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9),
345+ /* No VALID field on v0.1 */
346+ REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10),
347+ REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11),
348+ REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12),
349+ /* No CRITICAL field on v0.1 */
350+ REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS, TM_Sn_STATUS_OFF, 13, 13),
351+
352+ /* TRDY: 1=ready, 0=in progress */
353+ [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
354+};
355+
356+static const struct tsens_ops ops_8916 = {
357+ .init = init_common,
358+ .calibrate = calibrate_8916,
359+ .get_temp = get_temp_common,
360+};
361+
362+const struct tsens_plat_data data_8916 = {
363+ .num_sensors = 5,
364+ .ops = &ops_8916,
365+ .hw_ids = (unsigned int []){0, 1, 2, 4, 5 },
366+
367+ .feat = &tsens_v0_1_feat,
368+ .fields = tsens_v0_1_regfields,
369+};
370+
226371 static const struct tsens_ops ops_8974 = {
227372 .init = init_common,
228373 .calibrate = calibrate_8974,
229374 .get_temp = get_temp_common,
230375 };
231376
232−const struct tsens_data data_8974 = {
377+const struct tsens_plat_data data_8974 = {
233378 .num_sensors = 11,
234379 .ops = &ops_8974,
235− .reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 },
380+ .feat = &tsens_v0_1_feat,
381+ .fields = tsens_v0_1_regfields,
236382 };
drivers/thermal/qcom/tsens-v1.c+193−0
@@ -0,0 +1,193 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Copyright (c) 2019, Linaro Limited
4+ */
5+
6+#include <linux/bitops.h>
7+#include <linux/regmap.h>
8+#include <linux/delay.h>
9+#include "tsens.h"
10+
11+/* ----- SROT ------ */
12+#define SROT_HW_VER_OFF 0x0000
13+#define SROT_CTRL_OFF 0x0004
14+
15+/* ----- TM ------ */
16+#define TM_INT_EN_OFF 0x0000
17+#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004
18+#define TM_Sn_STATUS_OFF 0x0044
19+#define TM_TRDY_OFF 0x0084
20+
21+/* eeprom layout data for qcs404/405 (v1) */
22+#define BASE0_MASK 0x000007f8
23+#define BASE1_MASK 0x0007f800
24+#define BASE0_SHIFT 3
25+#define BASE1_SHIFT 11
26+
27+#define S0_P1_MASK 0x0000003f
28+#define S1_P1_MASK 0x0003f000
29+#define S2_P1_MASK 0x3f000000
30+#define S3_P1_MASK 0x000003f0
31+#define S4_P1_MASK 0x003f0000
32+#define S5_P1_MASK 0x0000003f
33+#define S6_P1_MASK 0x0003f000
34+#define S7_P1_MASK 0x3f000000
35+#define S8_P1_MASK 0x000003f0
36+#define S9_P1_MASK 0x003f0000
37+
38+#define S0_P2_MASK 0x00000fc0
39+#define S1_P2_MASK 0x00fc0000
40+#define S2_P2_MASK_1_0 0xc0000000
41+#define S2_P2_MASK_5_2 0x0000000f
42+#define S3_P2_MASK 0x0000fc00
43+#define S4_P2_MASK 0x0fc00000
44+#define S5_P2_MASK 0x00000fc0
45+#define S6_P2_MASK 0x00fc0000
46+#define S7_P2_MASK_1_0 0xc0000000
47+#define S7_P2_MASK_5_2 0x0000000f
48+#define S8_P2_MASK 0x0000fc00
49+#define S9_P2_MASK 0x0fc00000
50+
51+#define S0_P1_SHIFT 0
52+#define S0_P2_SHIFT 6
53+#define S1_P1_SHIFT 12
54+#define S1_P2_SHIFT 18
55+#define S2_P1_SHIFT 24
56+#define S2_P2_SHIFT_1_0 30
57+
58+#define S2_P2_SHIFT_5_2 0
59+#define S3_P1_SHIFT 4
60+#define S3_P2_SHIFT 10
61+#define S4_P1_SHIFT 16
62+#define S4_P2_SHIFT 22
63+
64+#define S5_P1_SHIFT 0
65+#define S5_P2_SHIFT 6
66+#define S6_P1_SHIFT 12
67+#define S6_P2_SHIFT 18
68+#define S7_P1_SHIFT 24
69+#define S7_P2_SHIFT_1_0 30
70+
71+#define S7_P2_SHIFT_5_2 0
72+#define S8_P1_SHIFT 4
73+#define S8_P2_SHIFT 10
74+#define S9_P1_SHIFT 16
75+#define S9_P2_SHIFT 22
76+
77+#define CAL_SEL_MASK 7
78+#define CAL_SEL_SHIFT 0
79+
80+static int calibrate_v1(struct tsens_priv *priv)
81+{
82+ u32 base0 = 0, base1 = 0;
83+ u32 p1[10], p2[10];
84+ u32 mode = 0, lsb = 0, msb = 0;
85+ u32 *qfprom_cdata;
86+ int i;
87+
88+ qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
89+ if (IS_ERR(qfprom_cdata))
90+ return PTR_ERR(qfprom_cdata);
91+
92+ mode = (qfprom_cdata[4] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
93+ dev_dbg(priv->dev, "calibration mode is %d\n", mode);
94+
95+ switch (mode) {
96+ case TWO_PT_CALIB:
97+ base1 = (qfprom_cdata[4] & BASE1_MASK) >> BASE1_SHIFT;
98+ p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
99+ p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
100+ /* This value is split over two registers, 2 bits and 4 bits */
101+ lsb = (qfprom_cdata[0] & S2_P2_MASK_1_0) >> S2_P2_SHIFT_1_0;
102+ msb = (qfprom_cdata[1] & S2_P2_MASK_5_2) >> S2_P2_SHIFT_5_2;
103+ p2[2] = msb << 2 | lsb;
104+ p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
105+ p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
106+ p2[5] = (qfprom_cdata[2] & S5_P2_MASK) >> S5_P2_SHIFT;
107+ p2[6] = (qfprom_cdata[2] & S6_P2_MASK) >> S6_P2_SHIFT;
108+ /* This value is split over two registers, 2 bits and 4 bits */
109+ lsb = (qfprom_cdata[2] & S7_P2_MASK_1_0) >> S7_P2_SHIFT_1_0;
110+ msb = (qfprom_cdata[3] & S7_P2_MASK_5_2) >> S7_P2_SHIFT_5_2;
111+ p2[7] = msb << 2 | lsb;
112+ p2[8] = (qfprom_cdata[3] & S8_P2_MASK) >> S8_P2_SHIFT;
113+ p2[9] = (qfprom_cdata[3] & S9_P2_MASK) >> S9_P2_SHIFT;
114+ for (i = 0; i < priv->num_sensors; i++)
115+ p2[i] = ((base1 + p2[i]) << 2);
116+ /* Fall through */
117+ case ONE_PT_CALIB2:
118+ base0 = (qfprom_cdata[4] & BASE0_MASK) >> BASE0_SHIFT;
119+ p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
120+ p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
121+ p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
122+ p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
123+ p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
124+ p1[5] = (qfprom_cdata[2] & S5_P1_MASK) >> S5_P1_SHIFT;
125+ p1[6] = (qfprom_cdata[2] & S6_P1_MASK) >> S6_P1_SHIFT;
126+ p1[7] = (qfprom_cdata[2] & S7_P1_MASK) >> S7_P1_SHIFT;
127+ p1[8] = (qfprom_cdata[3] & S8_P1_MASK) >> S8_P1_SHIFT;
128+ p1[9] = (qfprom_cdata[3] & S9_P1_MASK) >> S9_P1_SHIFT;
129+ for (i = 0; i < priv->num_sensors; i++)
130+ p1[i] = (((base0) + p1[i]) << 2);
131+ break;
132+ default:
133+ for (i = 0; i < priv->num_sensors; i++) {
134+ p1[i] = 500;
135+ p2[i] = 780;
136+ }
137+ break;
138+ }
139+
140+ compute_intercept_slope(priv, p1, p2, mode);
141+
142+ return 0;
143+}
144+
145+/* v1.x: qcs404,405 */
146+
147+static const struct tsens_features tsens_v1_feat = {
148+ .ver_major = VER_1_X,
149+ .crit_int = 0,
150+ .adc = 1,
151+ .srot_split = 1,
152+ .max_sensors = 11,
153+};
154+
155+static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = {
156+ /* ----- SROT ------ */
157+ /* VERSION */
158+ [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),
159+ [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),
160+ [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15),
161+ /* CTRL_OFFSET */
162+ [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
163+ [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
164+ [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13),
165+
166+ /* ----- TM ------ */
167+ /* INTERRUPT ENABLE */
168+ [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0),
169+
170+ /* Sn_STATUS */
171+ REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9),
172+ REG_FIELD_FOR_EACH_SENSOR11(VALID, TM_Sn_STATUS_OFF, 14, 14),
173+ REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10),
174+ REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11),
175+ REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12),
176+ /* No CRITICAL field on v1.x */
177+ REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS, TM_Sn_STATUS_OFF, 13, 13),
178+
179+ /* TRDY: 1=ready, 0=in progress */
180+ [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
181+};
182+
183+static const struct tsens_ops ops_generic_v1 = {
184+ .init = init_common,
185+ .calibrate = calibrate_v1,
186+ .get_temp = get_temp_tsens_valid,
187+};
188+
189+const struct tsens_plat_data data_tsens_v1 = {
190+ .ops = &ops_generic_v1,
191+ .feat = &tsens_v1_feat,
192+ .fields = tsens_v1_regfields,
193+};
drivers/thermal/qcom/tsens-v2.c+58−53
@@ -4,76 +4,81 @@ · 3 unmodified lines
44 * Copyright (c) 2018, Linaro Limited
55 */
66
7−#include <linux/regmap.h>
87 #include <linux/bitops.h>
8+#include <linux/regmap.h>
99 #include "tsens.h"
1010
11−#define STATUS_OFFSET 0xa0
12−#define LAST_TEMP_MASK 0xfff
13−#define STATUS_VALID_BIT BIT(21)
11+/* ----- SROT ------ */
12+#define SROT_HW_VER_OFF 0x0000
13+#define SROT_CTRL_OFF 0x0004
14+
15+/* ----- TM ------ */
16+#define TM_INT_EN_OFF 0x0004
17+#define TM_UPPER_LOWER_INT_STATUS_OFF 0x0008
18+#define TM_UPPER_LOWER_INT_CLEAR_OFF 0x000c
19+#define TM_UPPER_LOWER_INT_MASK_OFF 0x0010
20+#define TM_CRITICAL_INT_STATUS_OFF 0x0014
21+#define TM_CRITICAL_INT_CLEAR_OFF 0x0018
22+#define TM_CRITICAL_INT_MASK_OFF 0x001c
23+#define TM_Sn_UPPER_LOWER_THRESHOLD_OFF 0x0020
24+#define TM_Sn_CRITICAL_THRESHOLD_OFF 0x0060
25+#define TM_Sn_STATUS_OFF 0x00a0
26+#define TM_TRDY_OFF 0x00e4
1427
15−static int get_temp_tsens_v2(struct tsens_device *tmdev, int id, int *temp)
16−{
17− struct tsens_sensor *s = &tmdev->sensor[id];
18− u32 code;
19− unsigned int status_reg;
20− u32 last_temp = 0, last_temp2 = 0, last_temp3 = 0;
21− int ret;
28+/* v2.x: 8996, 8998, sdm845 */
2229
23− status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * 4;
24− ret = regmap_read(tmdev->tm_map, status_reg, &code);
25− if (ret)
26− return ret;
27− last_temp = code & LAST_TEMP_MASK;
28− if (code & STATUS_VALID_BIT)
29− goto done;
30+static const struct tsens_features tsens_v2_feat = {
31+ .ver_major = VER_2_X,
32+ .crit_int = 1,
33+ .adc = 0,
34+ .srot_split = 1,
35+ .max_sensors = 16,
36+};
3037
31− /* Try a second time */
32− ret = regmap_read(tmdev->tm_map, status_reg, &code);
33− if (ret)
34− return ret;
35− if (code & STATUS_VALID_BIT) {
36− last_temp = code & LAST_TEMP_MASK;
37− goto done;
38− } else {
39− last_temp2 = code & LAST_TEMP_MASK;
40− }
38+static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
39+ /* ----- SROT ------ */
40+ /* VERSION */
41+ [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),
42+ [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),
43+ [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15),
44+ /* CTRL_OFF */
45+ [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
46+ [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
47+ [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 18),
4148
42− /* Try a third/last time */
43− ret = regmap_read(tmdev->tm_map, status_reg, &code);
44− if (ret)
45− return ret;
46− if (code & STATUS_VALID_BIT) {
47− last_temp = code & LAST_TEMP_MASK;
48− goto done;
49− } else {
50− last_temp3 = code & LAST_TEMP_MASK;
51− }
49+ /* ----- TM ------ */
50+ /* INTERRUPT ENABLE */
51+ /* v2 has separate enables for UPPER/LOWER/CRITICAL interrupts */
52+ [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 2),
5253
53− if (last_temp == last_temp2)
54− last_temp = last_temp2;
55− else if (last_temp2 == last_temp3)
56− last_temp = last_temp3;
57−done:
58− /* Convert temperature from deciCelsius to milliCelsius */
59− *temp = sign_extend32(last_temp, fls(LAST_TEMP_MASK) - 1) * 100;
54+ /* Sn_STATUS */
55+ REG_FIELD_FOR_EACH_SENSOR16(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 11),
56+ REG_FIELD_FOR_EACH_SENSOR16(VALID, TM_Sn_STATUS_OFF, 21, 21),
57+ REG_FIELD_FOR_EACH_SENSOR16(MIN_STATUS, TM_Sn_STATUS_OFF, 16, 16),
58+ REG_FIELD_FOR_EACH_SENSOR16(LOWER_STATUS, TM_Sn_STATUS_OFF, 17, 17),
59+ REG_FIELD_FOR_EACH_SENSOR16(UPPER_STATUS, TM_Sn_STATUS_OFF, 18, 18),
60+ REG_FIELD_FOR_EACH_SENSOR16(CRITICAL_STATUS, TM_Sn_STATUS_OFF, 19, 19),
61+ REG_FIELD_FOR_EACH_SENSOR16(MAX_STATUS, TM_Sn_STATUS_OFF, 20, 20),
6062
61− return 0;
62−}
63+ /* TRDY: 1=ready, 0=in progress */
64+ [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
65+};
6366
6467 static const struct tsens_ops ops_generic_v2 = {
6568 .init = init_common,
66− .get_temp = get_temp_tsens_v2,
69+ .get_temp = get_temp_tsens_valid,
6770 };
6871
69−const struct tsens_data data_tsens_v2 = {
70− .ops = &ops_generic_v2,
71− .reg_offsets = { [SROT_CTRL_OFFSET] = 0x4 },
72+const struct tsens_plat_data data_tsens_v2 = {
73+ .ops = &ops_generic_v2,
74+ .feat = &tsens_v2_feat,
75+ .fields = tsens_v2_regfields,
7276 };
7377
7478 /* Kept around for backward compatibility with old msm8996.dtsi */
75−const struct tsens_data data_8996 = {
79+const struct tsens_plat_data data_8996 = {
7680 .num_sensors = 13,
7781 .ops = &ops_generic_v2,
78− .reg_offsets = { [SROT_CTRL_OFFSET] = 0x4 },
82+ .feat = &tsens_v2_feat,
83+ .fields = tsens_v2_regfields,
7984 };
drivers/thermal/qcom/tsens.c+54−46
@@ -15,38 +15,38 @@ · 14 unmodified lines
1515 static int tsens_get_temp(void *data, int *temp)
1616 {
1717 const struct tsens_sensor *s = data;
18− struct tsens_device *tmdev = s->tmdev;
18+ struct tsens_priv *priv = s->priv;
1919
20− return tmdev->ops->get_temp(tmdev, s->id, temp);
20+ return priv->ops->get_temp(priv, s->id, temp);
2121 }
2222
23−static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend)
23+static int tsens_get_trend(void *data, int trip, enum thermal_trend *trend)
2424 {
25− const struct tsens_sensor *s = p;
26− struct tsens_device *tmdev = s->tmdev;
25+ const struct tsens_sensor *s = data;
26+ struct tsens_priv *priv = s->priv;
2727
28− if (tmdev->ops->get_trend)
29− return tmdev->ops->get_trend(tmdev, s->id, trend);
28+ if (priv->ops->get_trend)
29+ return priv->ops->get_trend(priv, s->id, trend);
3030
3131 return -ENOTSUPP;
3232 }
3333
3434 static int __maybe_unused tsens_suspend(struct device *dev)
3535 {
36− struct tsens_device *tmdev = dev_get_drvdata(dev);
36+ struct tsens_priv *priv = dev_get_drvdata(dev);
3737
38− if (tmdev->ops && tmdev->ops->suspend)
39− return tmdev->ops->suspend(tmdev);
38+ if (priv->ops && priv->ops->suspend)
39+ return priv->ops->suspend(priv);
4040
4141 return 0;
4242 }
4343
4444 static int __maybe_unused tsens_resume(struct device *dev)
4545 {
46− struct tsens_device *tmdev = dev_get_drvdata(dev);
46+ struct tsens_priv *priv = dev_get_drvdata(dev);
4747
48− if (tmdev->ops && tmdev->ops->resume)
49− return tmdev->ops->resume(tmdev);
48+ if (priv->ops && priv->ops->resume)
49+ return priv->ops->resume(priv);
5050
5151 return 0;
5252 }
@@ -63,6 +63,9 @@ static const struct of_device_id tsens_table[] = { · 10 unmodified lines
6363 }, {
6464 .compatible = "qcom,msm8996-tsens",
6565 .data = &data_8996,
66+ }, {
67+ .compatible = "qcom,tsens-v1",
68+ .data = &data_tsens_v1,
6669 }, {
6770 .compatible = "qcom,tsens-v2",
6871 .data = &data_tsens_v2,
@@ -76,22 +79,27 @@ static const struct thermal_zone_of_device_ops tsens_of_ops = { · 7 unmodified lines
7679 .get_trend = tsens_get_trend,
7780 };
7881
79−static int tsens_register(struct tsens_device *tmdev)
82+static int tsens_register(struct tsens_priv *priv)
8083 {
8184 int i;
8285 struct thermal_zone_device *tzd;
8386
84− for (i = 0; i < tmdev->num_sensors; i++) {
85− tmdev->sensor[i].tmdev = tmdev;
86− tmdev->sensor[i].id = i;
87− tzd = devm_thermal_zone_of_sensor_register(tmdev->dev, i,
88− &tmdev->sensor[i],
87+ for (i = 0; i < priv->num_sensors; i++) {
88+ if (!is_sensor_enabled(priv, priv->sensor[i].hw_id)) {
89+ dev_err(priv->dev, "sensor %d: disabled\n",
90+ priv->sensor[i].hw_id);
91+ continue;
92+ }
93+ priv->sensor[i].priv = priv;
94+ priv->sensor[i].id = i;
95+ tzd = devm_thermal_zone_of_sensor_register(priv->dev, i,
96+ &priv->sensor[i],
8997 &tsens_of_ops);
9098 if (IS_ERR(tzd))
9199 continue;
92− tmdev->sensor[i].tzd = tzd;
93− if (tmdev->ops->enable)
94− tmdev->ops->enable(tmdev, i);
100+ priv->sensor[i].tzd = tzd;
101+ if (priv->ops->enable)
102+ priv->ops->enable(priv, i);
95103 }
96104 return 0;
97105 }
@@ -101,8 +109,8 @@ static int tsens_probe(struct platform_device *pdev) · 3 unmodified lines
101109 int ret, i;
102110 struct device *dev;
103111 struct device_node *np;
104− struct tsens_device *tmdev;
105− const struct tsens_data *data;
112+ struct tsens_priv *priv;
113+ const struct tsens_plat_data *data;
106114 const struct of_device_id *id;
107115 u32 num_sensors;
108116
@@ -129,55 +137,55 @@ static int tsens_probe(struct platform_device *pdev) · 20 unmodified lines
129137 return -EINVAL;
130138 }
131139
132− tmdev = devm_kzalloc(dev,
133− struct_size(tmdev, sensor, num_sensors),
140+ priv = devm_kzalloc(dev,
141+ struct_size(priv, sensor, num_sensors),
134142 GFP_KERNEL);
135− if (!tmdev)
143+ if (!priv)
136144 return -ENOMEM;
137145
138− tmdev->dev = dev;
139− tmdev->num_sensors = num_sensors;
140− tmdev->ops = data->ops;
141− for (i = 0; i < tmdev->num_sensors; i++) {
146+ priv->dev = dev;
147+ priv->num_sensors = num_sensors;
148+ priv->ops = data->ops;
149+ for (i = 0; i < priv->num_sensors; i++) {
142150 if (data->hw_ids)
143− tmdev->sensor[i].hw_id = data->hw_ids[i];
151+ priv->sensor[i].hw_id = data->hw_ids[i];
144152 else
145− tmdev->sensor[i].hw_id = i;
146− }
147− for (i = 0; i < REG_ARRAY_SIZE; i++) {
148− tmdev->reg_offsets[i] = data->reg_offsets[i];
153+ priv->sensor[i].hw_id = i;
149154 }
155+ priv->feat = data->feat;
156+ priv->fields = data->fields;
150157
151− if (!tmdev->ops || !tmdev->ops->init || !tmdev->ops->get_temp)
158+ if (!priv->ops || !priv->ops->init || !priv->ops->get_temp)
152159 return -EINVAL;
153160
154− ret = tmdev->ops->init(tmdev);
161+ ret = priv->ops->init(priv);
155162 if (ret < 0) {
156163 dev_err(dev, "tsens init failed\n");
157164 return ret;
158165 }
159166
160− if (tmdev->ops->calibrate) {
161− ret = tmdev->ops->calibrate(tmdev);
167+ if (priv->ops->calibrate) {
168+ ret = priv->ops->calibrate(priv);
162169 if (ret < 0) {
163− dev_err(dev, "tsens calibration failed\n");
170+ if (ret != -EPROBE_DEFER)
171+ dev_err(dev, "tsens calibration failed\n");
164172 return ret;
165173 }
166174 }
167175
168− ret = tsens_register(tmdev);
176+ ret = tsens_register(priv);
169177
170− platform_set_drvdata(pdev, tmdev);
178+ platform_set_drvdata(pdev, priv);
171179
172180 return ret;
173181 }
174182
175183 static int tsens_remove(struct platform_device *pdev)
176184 {
177− struct tsens_device *tmdev = platform_get_drvdata(pdev);
185+ struct tsens_priv *priv = platform_get_drvdata(pdev);
178186
179− if (tmdev->ops->disable)
180− tmdev->ops->disable(tmdev);
187+ if (priv->ops->disable)
188+ priv->ops->disable(priv);
181189
182190 return 0;
183191 }
drivers/thermal/qcom/tsens.h+262−29
@@ -9,17 +9,39 @@ · 8 unmodified lines
99 #define ONE_PT_CALIB 0x1
1010 #define ONE_PT_CALIB2 0x2
1111 #define TWO_PT_CALIB 0x3
12+#define CAL_DEGC_PT1 30
13+#define CAL_DEGC_PT2 120
14+#define SLOPE_FACTOR 1000
15+#define SLOPE_DEFAULT 3200
16+
1217
1318 #include <linux/thermal.h>
19+#include <linux/regmap.h>
20+
21+struct tsens_priv;
1422
15−struct tsens_device;
23+enum tsens_ver {
24+ VER_0_1 = 0,
25+ VER_1_X,
26+ VER_2_X,
27+};
1628
29+/**
30+ * struct tsens_sensor - data for each sensor connected to the tsens device
31+ * @priv: tsens device instance that this sensor is connected to
32+ * @tzd: pointer to the thermal zone that this sensor is in
33+ * @offset: offset of temperature adjustment curve
34+ * @id: Sensor ID
35+ * @hw_id: HW ID can be used in case of platform-specific IDs
36+ * @slope: slope of temperature adjustment curve
37+ * @status: 8960-specific variable to track 8960 and 8660 status register offset
38+ */
1739 struct tsens_sensor {
18− struct tsens_device *tmdev;
40+ struct tsens_priv *priv;
1941 struct thermal_zone_device *tzd;
2042 int offset;
21− int id;
22− int hw_id;
43+ unsigned int id;
44+ unsigned int hw_id;
2345 int slope;
2446 u32 status;
2547 };
@@ -37,63 +59,274 @@ struct tsens_sensor { · 11 unmodified lines
3759 */
3860 struct tsens_ops {
3961 /* mandatory callbacks */
40− int (*init)(struct tsens_device *);
41− int (*calibrate)(struct tsens_device *);
42− int (*get_temp)(struct tsens_device *, int, int *);
62+ int (*init)(struct tsens_priv *priv);
63+ int (*calibrate)(struct tsens_priv *priv);
64+ int (*get_temp)(struct tsens_priv *priv, int i, int *temp);
4365 /* optional callbacks */
44− int (*enable)(struct tsens_device *, int);
45− void (*disable)(struct tsens_device *);
46− int (*suspend)(struct tsens_device *);
47− int (*resume)(struct tsens_device *);
48− int (*get_trend)(struct tsens_device *, int, enum thermal_trend *);
66+ int (*enable)(struct tsens_priv *priv, int i);
67+ void (*disable)(struct tsens_priv *priv);
68+ int (*suspend)(struct tsens_priv *priv);
69+ int (*resume)(struct tsens_priv *priv);
70+ int (*get_trend)(struct tsens_priv *priv, int i, enum thermal_trend *trend);
4971 };
5072
51−enum reg_list {
52− SROT_CTRL_OFFSET,
73+#define REG_FIELD_FOR_EACH_SENSOR11(_name, _offset, _startbit, _stopbit) \
74+ [_name##_##0] = REG_FIELD(_offset, _startbit, _stopbit), \
75+ [_name##_##1] = REG_FIELD(_offset + 4, _startbit, _stopbit), \
76+ [_name##_##2] = REG_FIELD(_offset + 8, _startbit, _stopbit), \
77+ [_name##_##3] = REG_FIELD(_offset + 12, _startbit, _stopbit), \
78+ [_name##_##4] = REG_FIELD(_offset + 16, _startbit, _stopbit), \
79+ [_name##_##5] = REG_FIELD(_offset + 20, _startbit, _stopbit), \
80+ [_name##_##6] = REG_FIELD(_offset + 24, _startbit, _stopbit), \
81+ [_name##_##7] = REG_FIELD(_offset + 28, _startbit, _stopbit), \
82+ [_name##_##8] = REG_FIELD(_offset + 32, _startbit, _stopbit), \
83+ [_name##_##9] = REG_FIELD(_offset + 36, _startbit, _stopbit), \
84+ [_name##_##10] = REG_FIELD(_offset + 40, _startbit, _stopbit)
5385
54− REG_ARRAY_SIZE,
86+#define REG_FIELD_FOR_EACH_SENSOR16(_name, _offset, _startbit, _stopbit) \
87+ [_name##_##0] = REG_FIELD(_offset, _startbit, _stopbit), \
88+ [_name##_##1] = REG_FIELD(_offset + 4, _startbit, _stopbit), \
89+ [_name##_##2] = REG_FIELD(_offset + 8, _startbit, _stopbit), \
90+ [_name##_##3] = REG_FIELD(_offset + 12, _startbit, _stopbit), \
91+ [_name##_##4] = REG_FIELD(_offset + 16, _startbit, _stopbit), \
92+ [_name##_##5] = REG_FIELD(_offset + 20, _startbit, _stopbit), \
93+ [_name##_##6] = REG_FIELD(_offset + 24, _startbit, _stopbit), \
94+ [_name##_##7] = REG_FIELD(_offset + 28, _startbit, _stopbit), \
95+ [_name##_##8] = REG_FIELD(_offset + 32, _startbit, _stopbit), \
96+ [_name##_##9] = REG_FIELD(_offset + 36, _startbit, _stopbit), \
97+ [_name##_##10] = REG_FIELD(_offset + 40, _startbit, _stopbit), \
98+ [_name##_##11] = REG_FIELD(_offset + 44, _startbit, _stopbit), \
99+ [_name##_##12] = REG_FIELD(_offset + 48, _startbit, _stopbit), \
100+ [_name##_##13] = REG_FIELD(_offset + 52, _startbit, _stopbit), \
101+ [_name##_##14] = REG_FIELD(_offset + 56, _startbit, _stopbit), \
102+ [_name##_##15] = REG_FIELD(_offset + 60, _startbit, _stopbit)
103+
104+/* reg_field IDs to use as an index into an array */
105+enum regfield_ids {
106+ /* ----- SROT ------ */
107+ /* HW_VER */
108+ VER_MAJOR = 0,
109+ VER_MINOR,
110+ VER_STEP,
111+ /* CTRL_OFFSET */
112+ TSENS_EN = 3,
113+ TSENS_SW_RST,
114+ SENSOR_EN,
115+ CODE_OR_TEMP,
116+
117+ /* ----- TM ------ */
118+ /* STATUS */
119+ LAST_TEMP_0 = 7, /* Last temperature reading */
120+ LAST_TEMP_1,
121+ LAST_TEMP_2,
122+ LAST_TEMP_3,
123+ LAST_TEMP_4,
124+ LAST_TEMP_5,
125+ LAST_TEMP_6,
126+ LAST_TEMP_7,
127+ LAST_TEMP_8,
128+ LAST_TEMP_9,
129+ LAST_TEMP_10,
130+ LAST_TEMP_11,
131+ LAST_TEMP_12,
132+ LAST_TEMP_13,
133+ LAST_TEMP_14,
134+ LAST_TEMP_15,
135+ VALID_0 = 23, /* VALID reading or not */
136+ VALID_1,
137+ VALID_2,
138+ VALID_3,
139+ VALID_4,
140+ VALID_5,
141+ VALID_6,
142+ VALID_7,
143+ VALID_8,
144+ VALID_9,
145+ VALID_10,
146+ VALID_11,
147+ VALID_12,
148+ VALID_13,
149+ VALID_14,
150+ VALID_15,
151+ MIN_STATUS_0, /* MIN threshold violated */
152+ MIN_STATUS_1,
153+ MIN_STATUS_2,
154+ MIN_STATUS_3,
155+ MIN_STATUS_4,
156+ MIN_STATUS_5,
157+ MIN_STATUS_6,
158+ MIN_STATUS_7,
159+ MIN_STATUS_8,
160+ MIN_STATUS_9,
161+ MIN_STATUS_10,
162+ MIN_STATUS_11,
163+ MIN_STATUS_12,
164+ MIN_STATUS_13,
165+ MIN_STATUS_14,
166+ MIN_STATUS_15,
167+ MAX_STATUS_0, /* MAX threshold violated */
168+ MAX_STATUS_1,
169+ MAX_STATUS_2,
170+ MAX_STATUS_3,
171+ MAX_STATUS_4,
172+ MAX_STATUS_5,
173+ MAX_STATUS_6,
174+ MAX_STATUS_7,
175+ MAX_STATUS_8,
176+ MAX_STATUS_9,
177+ MAX_STATUS_10,
178+ MAX_STATUS_11,
179+ MAX_STATUS_12,
180+ MAX_STATUS_13,
181+ MAX_STATUS_14,
182+ MAX_STATUS_15,
183+ LOWER_STATUS_0, /* LOWER threshold violated */
184+ LOWER_STATUS_1,
185+ LOWER_STATUS_2,
186+ LOWER_STATUS_3,
187+ LOWER_STATUS_4,
188+ LOWER_STATUS_5,
189+ LOWER_STATUS_6,
190+ LOWER_STATUS_7,
191+ LOWER_STATUS_8,
192+ LOWER_STATUS_9,
193+ LOWER_STATUS_10,
194+ LOWER_STATUS_11,
195+ LOWER_STATUS_12,
196+ LOWER_STATUS_13,
197+ LOWER_STATUS_14,
198+ LOWER_STATUS_15,
199+ UPPER_STATUS_0, /* UPPER threshold violated */
200+ UPPER_STATUS_1,
201+ UPPER_STATUS_2,
202+ UPPER_STATUS_3,
203+ UPPER_STATUS_4,
204+ UPPER_STATUS_5,
205+ UPPER_STATUS_6,
206+ UPPER_STATUS_7,
207+ UPPER_STATUS_8,
208+ UPPER_STATUS_9,
209+ UPPER_STATUS_10,
210+ UPPER_STATUS_11,
211+ UPPER_STATUS_12,
212+ UPPER_STATUS_13,
213+ UPPER_STATUS_14,
214+ UPPER_STATUS_15,
215+ CRITICAL_STATUS_0, /* CRITICAL threshold violated */
216+ CRITICAL_STATUS_1,
217+ CRITICAL_STATUS_2,
218+ CRITICAL_STATUS_3,
219+ CRITICAL_STATUS_4,
220+ CRITICAL_STATUS_5,
221+ CRITICAL_STATUS_6,
222+ CRITICAL_STATUS_7,
223+ CRITICAL_STATUS_8,
224+ CRITICAL_STATUS_9,
225+ CRITICAL_STATUS_10,
226+ CRITICAL_STATUS_11,
227+ CRITICAL_STATUS_12,
228+ CRITICAL_STATUS_13,
229+ CRITICAL_STATUS_14,
230+ CRITICAL_STATUS_15,
231+ /* TRDY */
232+ TRDY,
233+ /* INTERRUPT ENABLE */
234+ INT_EN, /* Pre-V1, V1.x */
235+ LOW_INT_EN, /* V2.x */
236+ UP_INT_EN, /* V2.x */
237+ CRIT_INT_EN, /* V2.x */
238+
239+ /* Keep last */
240+ MAX_REGFIELDS
55241 };
56242
57243 /**
58− * struct tsens_data - tsens instance specific data
59− * @num_sensors: Max number of sensors supported by platform
244+ * struct tsens_features - Features supported by the IP
245+ * @ver_major: Major number of IP version
246+ * @crit_int: does the IP support critical interrupts?
247+ * @adc: do the sensors only output adc code (instead of temperature)?
248+ * @srot_split: does the IP neatly splits the register space into SROT and TM,
249+ * with SROT only being available to secure boot firmware?
250+ * @max_sensors: maximum sensors supported by this version of the IP
251+ */
252+struct tsens_features {
253+ unsigned int ver_major;
254+ unsigned int crit_int:1;
255+ unsigned int adc:1;
256+ unsigned int srot_split:1;
257+ unsigned int max_sensors;
258+};
259+
260+/**
261+ * struct tsens_plat_data - tsens compile-time platform data
262+ * @num_sensors: Number of sensors supported by platform
60263 * @ops: operations the tsens instance supports
61264 * @hw_ids: Subset of sensors ids supported by platform, if not the first n
62− * @reg_offsets: Register offsets for commonly used registers
265+ * @feat: features of the IP
266+ * @fields: bitfield locations
63267 */
64−struct tsens_data {
268+struct tsens_plat_data {
65269 const u32 num_sensors;
66270 const struct tsens_ops *ops;
67− const u16 reg_offsets[REG_ARRAY_SIZE];
68271 unsigned int *hw_ids;
272+ const struct tsens_features *feat;
273+ const struct reg_field *fields;
69274 };
70275
71−/* Registers to be saved/restored across a context loss */
276+/**
277+ * struct tsens_context - Registers to be saved/restored across a context loss
278+ */
72279 struct tsens_context {
73280 int threshold;
74281 int control;
75282 };
76283
77−struct tsens_device {
284+/**
285+ * struct tsens_priv - private data for each instance of the tsens IP
286+ * @dev: pointer to struct device
287+ * @num_sensors: number of sensors enabled on this device
288+ * @tm_map: pointer to TM register address space
289+ * @srot_map: pointer to SROT register address space
290+ * @tm_offset: deal with old device trees that don't address TM and SROT
291+ * address space separately
292+ * @rf: array of regmap_fields used to store value of the field
293+ * @ctx: registers to be saved and restored during suspend/resume
294+ * @feat: features of the IP
295+ * @fields: bitfield locations
296+ * @ops: pointer to list of callbacks supported by this device
297+ * @sensor: list of sensors attached to this device
298+ */
299+struct tsens_priv {
78300 struct device *dev;
79301 u32 num_sensors;
80302 struct regmap *tm_map;
81303 struct regmap *srot_map;
82304 u32 tm_offset;
83− u16 reg_offsets[REG_ARRAY_SIZE];
305+ struct regmap_field *rf[MAX_REGFIELDS];
84306 struct tsens_context ctx;
307+ const struct tsens_features *feat;
308+ const struct reg_field *fields;
85309 const struct tsens_ops *ops;
86310 struct tsens_sensor sensor[0];
87311 };
88312
89−char *qfprom_read(struct device *, const char *);
90−void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
91−int init_common(struct tsens_device *);
92−int get_temp_common(struct tsens_device *, int, int *);
313+char *qfprom_read(struct device *dev, const char *cname);
314+void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mode);
315+int init_common(struct tsens_priv *priv);
316+int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp);
317+int get_temp_common(struct tsens_priv *priv, int i, int *temp);
318+bool is_sensor_enabled(struct tsens_priv *priv, u32 hw_id);
319+
320+/* TSENS target */
321+extern const struct tsens_plat_data data_8960;
322+
323+/* TSENS v0.1 targets */
324+extern const struct tsens_plat_data data_8916, data_8974;
93325
94326 /* TSENS v1 targets */
95−extern const struct tsens_data data_8916, data_8974, data_8960;
327+extern const struct tsens_plat_data data_tsens_v1;
328+
96329 /* TSENS v2 targets */
97−extern const struct tsens_data data_8996, data_tsens_v2;
330+extern const struct tsens_plat_data data_8996, data_tsens_v2;
98331
99332 #endif /* __QCOM_TSENS_H__ */
drivers/thermal/qoriq_thermal.c+0−5
@@ -193,11 +193,6 @@ static int qoriq_tmu_probe(struct platform_device *pdev) · 192 unmodified lines
193193 struct qoriq_tmu_data *data;
194194 struct device_node *np = pdev->dev.of_node;
195195
196− if (!np) {
197− dev_err(&pdev->dev, "Device OF-Node is NULL");
198− return -ENODEV;
199− }
200−
201196 data = devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data),
202197 GFP_KERNEL);
203198 if (!data)
drivers/thermal/rcar_gen3_thermal.c+14−37
@@ -14,7 +14,6 @@ · 13 unmodified lines
1414 #include <linux/of_device.h>
1515 #include <linux/platform_device.h>
1616 #include <linux/pm_runtime.h>
17−#include <linux/spinlock.h>
1817 #include <linux/sys_soc.h>
1918 #include <linux/thermal.h>
2019
@@ -82,7 +81,6 @@ struct rcar_gen3_thermal_tsc { · 61 unmodified lines
8281 struct rcar_gen3_thermal_priv {
8382 struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM];
8483 unsigned int num_tscs;
85− spinlock_t lock; /* Protect interrupts on and off */
8684 void (*thermal_init)(struct rcar_gen3_thermal_tsc *tsc);
8785 };
8886
@@ -232,38 +230,16 @@ static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data) · 143 unmodified lines
232230 {
233231 struct rcar_gen3_thermal_priv *priv = data;
234232 u32 status;
235− int i, ret = IRQ_HANDLED;
233+ int i;
236234
237− spin_lock(&priv->lock);
238235 for (i = 0; i < priv->num_tscs; i++) {
239236 status = rcar_gen3_thermal_read(priv->tscs[i], REG_GEN3_IRQSTR);
240237 rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQSTR, 0);
241238 if (status)
242− ret = IRQ_WAKE_THREAD;
239+ thermal_zone_device_update(priv->tscs[i]->zone,
240+ THERMAL_EVENT_UNSPECIFIED);
243241 }
244242
245− if (ret == IRQ_WAKE_THREAD)
246− rcar_thermal_irq_set(priv, false);
247−
248− spin_unlock(&priv->lock);
249−
250− return ret;
251−}
252−
253−static irqreturn_t rcar_gen3_thermal_irq_thread(int irq, void *data)
254−{
255− struct rcar_gen3_thermal_priv *priv = data;
256− unsigned long flags;
257− int i;
258−
259− for (i = 0; i < priv->num_tscs; i++)
260− thermal_zone_device_update(priv->tscs[i]->zone,
261− THERMAL_EVENT_UNSPECIFIED);
262−
263− spin_lock_irqsave(&priv->lock, flags);
264− rcar_thermal_irq_set(priv, true);
265− spin_unlock_irqrestore(&priv->lock, flags);
266−
267243 return IRQ_HANDLED;
268244 }
269245
@@ -307,7 +283,7 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_tsc *tsc) · 37 unmodified lines
307283
308284 usleep_range(1000, 2000);
309285
310− rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F);
286+ rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0);
311287 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0);
312288 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2);
313289
@@ -331,6 +307,9 @@ MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids); · 17 unmodified lines
331307 static int rcar_gen3_thermal_remove(struct platform_device *pdev)
332308 {
333309 struct device *dev = &pdev->dev;
310+ struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev);
311+
312+ rcar_thermal_irq_set(priv, false);
334313
335314 pm_runtime_put(dev);
336315 pm_runtime_disable(dev);
@@ -371,8 +350,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) · 34 unmodified lines
371350 if (soc_device_match(r8a7795es1))
372351 priv->thermal_init = rcar_gen3_thermal_init_r8a7795es1;
373352
374− spin_lock_init(&priv->lock);
375−
376353 platform_set_drvdata(pdev, priv);
377354
378355 /*
@@ -390,9 +367,9 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) · 11 unmodified lines
390367 if (!irqname)
391368 return -ENOMEM;
392369
393− ret = devm_request_threaded_irq(dev, irq, rcar_gen3_thermal_irq,
394− rcar_gen3_thermal_irq_thread,
395− IRQF_SHARED, irqname, priv);
370+ ret = devm_request_threaded_irq(dev, irq, NULL,
371+ rcar_gen3_thermal_irq,
372+ IRQF_ONESHOT, irqname, priv);
396373 if (ret)
397374 return ret;
398375 }
@@ -433,10 +410,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) · 34 unmodified lines
433410 }
434411 tsc->zone = zone;
435412
436− ret = of_thermal_get_ntrips(tsc->zone);
437− if (ret < 0)
438− goto error_unregister;
439−
440413 tsc->zone->tzp->no_hwmon = false;
441414 ret = thermal_add_hwmon_sysfs(tsc->zone);
442415 if (ret)
@@ -448,6 +421,10 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) · 5 unmodified lines
448421 goto error_unregister;
449422 }
450423
424+ ret = of_thermal_get_ntrips(tsc->zone);
425+ if (ret < 0)
426+ goto error_unregister;
427+
451428 dev_info(dev, "TSC%d: Loaded %d trip points\n", i, ret);
452429 }
453430
drivers/thermal/rcar_thermal.c+10−1
@@ -52,6 +52,7 @@ struct rcar_thermal_chip { · 51 unmodified lines
5252 unsigned int irq_per_ch : 1;
5353 unsigned int needs_suspend_resume : 1;
5454 unsigned int nirqs;
55+ unsigned int ctemp_bands;
5556 };
5657
5758 static const struct rcar_thermal_chip rcar_thermal = {
@@ -60,6 +61,7 @@ static const struct rcar_thermal_chip rcar_thermal = { · 2 unmodified lines
6061 .irq_per_ch = 0,
6162 .needs_suspend_resume = 0,
6263 .nirqs = 1,
64+ .ctemp_bands = 1,
6365 };
6466
6567 static const struct rcar_thermal_chip rcar_gen2_thermal = {
@@ -68,6 +70,7 @@ static const struct rcar_thermal_chip rcar_gen2_thermal = { · 2 unmodified lines
6870 .irq_per_ch = 0,
6971 .needs_suspend_resume = 0,
7072 .nirqs = 1,
73+ .ctemp_bands = 1,
7174 };
7275
7376 static const struct rcar_thermal_chip rcar_gen3_thermal = {
@@ -80,6 +83,7 @@ static const struct rcar_thermal_chip rcar_gen3_thermal = { · 6 unmodified lines
8083 * interrupts to detect a temperature change, rise or fall.
8184 */
8285 .nirqs = 2,
86+ .ctemp_bands = 2,
8387 };
8488
8589 struct rcar_thermal_priv {
@@ -263,7 +267,12 @@ static int rcar_thermal_get_current_temp(struct rcar_thermal_priv *priv, · 177 unmodified lines
263267 return ret;
264268
265269 mutex_lock(&priv->lock);
266− tmp = MCELSIUS((priv->ctemp * 5) - 65);
270+ if (priv->chip->ctemp_bands == 1)
271+ tmp = MCELSIUS((priv->ctemp * 5) - 65);
272+ else if (priv->ctemp < 24)
273+ tmp = MCELSIUS(((priv->ctemp * 55) - 720) / 10);
274+ else
275+ tmp = MCELSIUS((priv->ctemp * 5) - 60);
267276 mutex_unlock(&priv->lock);
268277
269278 if ((tmp < MCELSIUS(-45)) || (tmp > MCELSIUS(125))) {
drivers/thermal/rockchip_thermal.c+71−3
@@ -172,6 +172,9 @@ struct rockchip_thermal_data { · 171 unmodified lines
172172 int tshut_temp;
173173 enum tshut_mode tshut_mode;
174174 enum tshut_polarity tshut_polarity;
175+ struct pinctrl *pinctrl;
176+ struct pinctrl_state *gpio_state;
177+ struct pinctrl_state *otp_state;
175178 };
176179
177180 /**
@@ -222,11 +225,15 @@ struct rockchip_thermal_data { · 44 unmodified lines
222225 #define GRF_TSADC_TESTBIT_L 0x0e648
223226 #define GRF_TSADC_TESTBIT_H 0x0e64c
224227
228+#define PX30_GRF_SOC_CON2 0x0408
229+
225230 #define GRF_SARADC_TESTBIT_ON (0x10001 << 2)
226231 #define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2)
227232 #define GRF_TSADC_VCM_EN_L (0x10001 << 7)
228233 #define GRF_TSADC_VCM_EN_H (0x10001 << 7)
229234
235+#define GRF_CON_TSADC_CH_INV (0x10001 << 1)
236+
230237 /**
231238 * struct tsadc_table - code to temperature conversion table
232239 * @code: the value of adc channel
@@ -689,6 +696,13 @@ static void rk_tsadcv3_initialize(struct regmap *grf, void __iomem *regs, · 456 unmodified lines
689696 regs + TSADCV2_AUTO_CON);
690697 }
691698
699+static void rk_tsadcv4_initialize(struct regmap *grf, void __iomem *regs,
700+ enum tshut_polarity tshut_polarity)
701+{
702+ rk_tsadcv2_initialize(grf, regs, tshut_polarity);
703+ regmap_write(grf, PX30_GRF_SOC_CON2, GRF_CON_TSADC_CH_INV);
704+}
705+
692706 static void rk_tsadcv2_irq_ack(void __iomem *regs)
693707 {
694708 u32 val;
@@ -818,6 +832,30 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs, · 123 unmodified lines
818832 writel_relaxed(val, regs + TSADCV2_INT_EN);
819833 }
820834
835+static const struct rockchip_tsadc_chip px30_tsadc_data = {
836+ .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
837+ .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */
838+ .chn_num = 2, /* 2 channels for tsadc */
839+
840+ .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */
841+ .tshut_temp = 95000,
842+
843+ .initialize = rk_tsadcv4_initialize,
844+ .irq_ack = rk_tsadcv3_irq_ack,
845+ .control = rk_tsadcv3_control,
846+ .get_temp = rk_tsadcv2_get_temp,
847+ .set_alarm_temp = rk_tsadcv2_alarm_temp,
848+ .set_tshut_temp = rk_tsadcv2_tshut_temp,
849+ .set_tshut_mode = rk_tsadcv2_tshut_mode,
850+
851+ .table = {
852+ .id = rk3328_code_table,
853+ .length = ARRAY_SIZE(rk3328_code_table),
854+ .data_mask = TSADCV2_DATA_MASK,
855+ .mode = ADC_INCREMENT,
856+ },
857+};
858+
821859 static const struct rockchip_tsadc_chip rv1108_tsadc_data = {
822860 .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
823861 .chn_num = 1, /* one channel for tsadc */
@@ -990,6 +1028,9 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = { · 166 unmodified lines
9901028 };
9911029
9921030 static const struct of_device_id of_rockchip_thermal_match[] = {
1031+ { .compatible = "rockchip,px30-tsadc",
1032+ .data = (void *)&px30_tsadc_data,
1033+ },
9931034 {
9941035 .compatible = "rockchip,rv1108-tsadc",
9951036 .data = (void *)&rv1108_tsadc_data,
@@ -1242,6 +1283,8 @@ static int rockchip_thermal_probe(struct platform_device *pdev) · 246 unmodified lines
12421283 return error;
12431284 }
12441285
1286+ thermal->chip->control(thermal->regs, false);
1287+
12451288 error = clk_prepare_enable(thermal->clk);
12461289 if (error) {
12471290 dev_err(&pdev->dev, "failed to enable converter clock: %d\n",
@@ -1267,6 +1310,30 @@ static int rockchip_thermal_probe(struct platform_device *pdev) · 19 unmodified lines
12671310 thermal->chip->initialize(thermal->grf, thermal->regs,
12681311 thermal->tshut_polarity);
12691312
1313+ if (thermal->tshut_mode == TSHUT_MODE_GPIO) {
1314+ thermal->pinctrl = devm_pinctrl_get(&pdev->dev);
1315+ if (IS_ERR(thermal->pinctrl)) {
1316+ dev_err(&pdev->dev, "failed to find thermal pinctrl\n");
1317+ return PTR_ERR(thermal->pinctrl);
1318+ }
1319+
1320+ thermal->gpio_state = pinctrl_lookup_state(thermal->pinctrl,
1321+ "gpio");
1322+ if (IS_ERR_OR_NULL(thermal->gpio_state)) {
1323+ dev_err(&pdev->dev, "failed to find thermal gpio state\n");
1324+ return -EINVAL;
1325+ }
1326+
1327+ thermal->otp_state = pinctrl_lookup_state(thermal->pinctrl,
1328+ "otpout");
1329+ if (IS_ERR_OR_NULL(thermal->otp_state)) {
1330+ dev_err(&pdev->dev, "failed to find thermal otpout state\n");
1331+ return -EINVAL;
1332+ }
1333+
1334+ pinctrl_select_state(thermal->pinctrl, thermal->otp_state);
1335+ }
1336+
12701337 for (i = 0; i < thermal->chip->chn_num; i++) {
12711338 error = rockchip_thermal_register_sensor(pdev, thermal,
12721339 &thermal->sensors[i],
@@ -1337,8 +1404,8 @@ static int __maybe_unused rockchip_thermal_suspend(struct device *dev) · 64 unmodified lines
13371404
13381405 clk_disable(thermal->pclk);
13391406 clk_disable(thermal->clk);
1340−
1341− pinctrl_pm_select_sleep_state(dev);
1407+ if (thermal->tshut_mode == TSHUT_MODE_GPIO)
1408+ pinctrl_select_state(thermal->pinctrl, thermal->gpio_state);
13421409
13431410 return 0;
13441411 }
@@ -1383,7 +1450,8 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev) · 38 unmodified lines
13831450 for (i = 0; i < thermal->chip->chn_num; i++)
13841451 rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
13851452
1386− pinctrl_pm_select_default_state(dev);
1453+ if (thermal->tshut_mode == TSHUT_MODE_GPIO)
1454+ pinctrl_select_state(thermal->pinctrl, thermal->otp_state);
13871455
13881456 return 0;
13891457 }
drivers/thermal/st/Kconfig+11−11
@@ -3,9 +3,9 @@ · 2 unmodified lines
33 #
44
55 config ST_THERMAL
6− tristate "Thermal sensors on STMicroelectronics STi series of SoCs"
7− help
8− Support for thermal sensors on STMicroelectronics STi series of SoCs.
6+ tristate "Thermal sensors on STMicroelectronics STi series of SoCs"
7+ help
8+ Support for thermal sensors on STMicroelectronics STi series of SoCs.
99
1010 config ST_THERMAL_SYSCFG
1111 select ST_THERMAL
@@ -16,11 +16,11 @@ config ST_THERMAL_MEMMAP · 4 unmodified lines
1616 tristate "STi series memory mapped access based thermal sensors"
1717
1818 config STM32_THERMAL
19− tristate "Thermal framework support on STMicroelectronics STM32 series of SoCs"
20− depends on MACH_STM32MP157
21− default y
22− help
23− Support for thermal framework on STMicroelectronics STM32 series of
24− SoCs. This thermal driver allows to access to general thermal framework
25− functionalities and to acces to SoC sensor functionalities. This
26− configuration is fully dependent of MACH_STM32MP157.
19+ tristate "Thermal framework support on STMicroelectronics STM32 series of SoCs"
20+ depends on MACH_STM32MP157
21+ default y
22+ help
23+ Support for thermal framework on STMicroelectronics STM32 series of
24+ SoCs. This thermal driver allows to access to general thermal framework
25+ functionalities and to acces to SoC sensor functionalities. This
26+ configuration is fully dependent of MACH_STM32MP157.
drivers/thermal/st/stm_thermal.c+2−4
@@ -570,8 +570,7 @@ thermal_unprepare: · 569 unmodified lines
570570 static int stm_thermal_suspend(struct device *dev)
571571 {
572572 int ret;
573− struct platform_device *pdev = to_platform_device(dev);
574− struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev);
573+ struct stm_thermal_sensor *sensor = dev_get_drvdata(dev);
575574
576575 ret = stm_thermal_sensor_off(sensor);
577576 if (ret)
@@ -585,8 +584,7 @@ static int stm_thermal_suspend(struct device *dev) · 7 unmodified lines
585584 static int stm_thermal_resume(struct device *dev)
586585 {
587586 int ret;
588− struct platform_device *pdev = to_platform_device(dev);
589− struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev);
587+ struct stm_thermal_sensor *sensor = dev_get_drvdata(dev);
590588
591589 ret = stm_thermal_prepare(sensor);
592590 if (ret)
drivers/thermal/tegra/Kconfig+2−2
@@ -14,7 +14,7 @@ config TEGRA_BPMP_THERMAL · 13 unmodified lines
1414 tristate "Tegra BPMP thermal sensing"
1515 depends on TEGRA_BPMP || COMPILE_TEST
1616 help
17− Enable this option for support for sensing system temperature of NVIDIA
18− Tegra systems-on-chip with the BPMP coprocessor (Tegra186).
17+ Enable this option for support for sensing system temperature of NVIDIA
18+ Tegra systems-on-chip with the BPMP coprocessor (Tegra186).
1919
2020 endmenu
drivers/thermal/tegra/soctherm.c+904−57
@@ -1,5 +1,6 @@
1+// SPDX-License-Identifier: GPL-2.0
12 /*
2− * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
3+ * Copyright (c) 2014 - 2018, NVIDIA CORPORATION. All rights reserved.
34 *
45 * Author:
56 * Mikko Perttunen <mperttunen@nvidia.com>
@@ -22,6 +23,8 @@ · 16 unmodified lines
2223 #include <linux/err.h>
2324 #include <linux/interrupt.h>
2425 #include <linux/io.h>
26+#include <linux/irq.h>
27+#include <linux/irqdomain.h>
2528 #include <linux/module.h>
2629 #include <linux/of.h>
2730 #include <linux/platform_device.h>
@@ -85,12 +88,51 @@ · 57 unmodified lines
8588 #define THERMCTL_LVL0_UP_STATS 0x10
8689 #define THERMCTL_LVL0_DN_STATS 0x14
8790
91+#define THERMCTL_INTR_STATUS 0x84
92+
93+#define TH_INTR_MD0_MASK BIT(25)
94+#define TH_INTR_MU0_MASK BIT(24)
95+#define TH_INTR_GD0_MASK BIT(17)
96+#define TH_INTR_GU0_MASK BIT(16)
97+#define TH_INTR_CD0_MASK BIT(9)
98+#define TH_INTR_CU0_MASK BIT(8)
99+#define TH_INTR_PD0_MASK BIT(1)
100+#define TH_INTR_PU0_MASK BIT(0)
101+#define TH_INTR_IGNORE_MASK 0xFCFCFCFC
102+
88103 #define THERMCTL_STATS_CTL 0x94
89104 #define STATS_CTL_CLR_DN 0x8
90105 #define STATS_CTL_EN_DN 0x4
91106 #define STATS_CTL_CLR_UP 0x2
92107 #define STATS_CTL_EN_UP 0x1
93108
109+#define OC1_CFG 0x310
110+#define OC1_CFG_LONG_LATENCY_MASK BIT(6)
111+#define OC1_CFG_HW_RESTORE_MASK BIT(5)
112+#define OC1_CFG_PWR_GOOD_MASK_MASK BIT(4)
113+#define OC1_CFG_THROTTLE_MODE_MASK (0x3 << 2)
114+#define OC1_CFG_ALARM_POLARITY_MASK BIT(1)
115+#define OC1_CFG_EN_THROTTLE_MASK BIT(0)
116+
117+#define OC1_CNT_THRESHOLD 0x314
118+#define OC1_THROTTLE_PERIOD 0x318
119+#define OC1_ALARM_COUNT 0x31c
120+#define OC1_FILTER 0x320
121+#define OC1_STATS 0x3a8
122+
123+#define OC_INTR_STATUS 0x39c
124+#define OC_INTR_ENABLE 0x3a0
125+#define OC_INTR_DISABLE 0x3a4
126+#define OC_STATS_CTL 0x3c4
127+#define OC_STATS_CTL_CLR_ALL 0x2
128+#define OC_STATS_CTL_EN_ALL 0x1
129+
130+#define OC_INTR_OC1_MASK BIT(0)
131+#define OC_INTR_OC2_MASK BIT(1)
132+#define OC_INTR_OC3_MASK BIT(2)
133+#define OC_INTR_OC4_MASK BIT(3)
134+#define OC_INTR_OC5_MASK BIT(4)
135+
94136 #define THROT_GLOBAL_CFG 0x400
95137 #define THROT_GLOBAL_ENB_MASK BIT(0)
96138
@@ -160,6 +202,15 @@ · 63 unmodified lines
160202 /* get dividend from the depth */
161203 #define THROT_DEPTH_DIVIDEND(depth) ((256 * (100 - (depth)) / 100) - 1)
162204
205+/* gk20a nv_therm interface N:3 Mapping. Levels defined in tegra124-sochterm.h
206+ * level vector
207+ * NONE 3'b000
208+ * LOW 3'b001
209+ * MED 3'b011
210+ * HIGH 3'b111
211+ */
212+#define THROT_LEVEL_TO_DEPTH(level) ((0x1 << (level)) - 1)
213+
163214 /* get THROT_PSKIP_xxx offset per LIGHT/HEAVY throt and CPU/GPU dev */
164215 #define THROT_OFFSET 0x30
165216 #define THROT_PSKIP_CTRL(throt, dev) (THROT_PSKIP_CTRL_LITE_CPU + \
@@ -173,6 +224,25 @@ · 7 unmodified lines
173224 #define THROT_DELAY_CTRL(throt) (THROT_DELAY_LITE + \
174225 (THROT_OFFSET * throt))
175226
227+#define ALARM_OFFSET 0x14
228+#define ALARM_CFG(throt) (OC1_CFG + \
229+ (ALARM_OFFSET * (throt - THROTTLE_OC1)))
230+
231+#define ALARM_CNT_THRESHOLD(throt) (OC1_CNT_THRESHOLD + \
232+ (ALARM_OFFSET * (throt - THROTTLE_OC1)))
233+
234+#define ALARM_THROTTLE_PERIOD(throt) (OC1_THROTTLE_PERIOD + \
235+ (ALARM_OFFSET * (throt - THROTTLE_OC1)))
236+
237+#define ALARM_ALARM_COUNT(throt) (OC1_ALARM_COUNT + \
238+ (ALARM_OFFSET * (throt - THROTTLE_OC1)))
239+
240+#define ALARM_FILTER(throt) (OC1_FILTER + \
241+ (ALARM_OFFSET * (throt - THROTTLE_OC1)))
242+
243+#define ALARM_STATS(throt) (OC1_STATS + \
244+ (4 * (throt - THROTTLE_OC1)))
245+
176246 /* get CCROC_THROT_PSKIP_xxx offset per HIGH/MED/LOW vect*/
177247 #define CCROC_THROT_OFFSET 0x0c
178248 #define CCROC_THROT_PSKIP_CTRL_CPU_REG(vect) (CCROC_THROT_PSKIP_CTRL_CPU + \
@@ -184,15 +254,32 @@ · 5 unmodified lines
184254 #define THERMCTL_LVL_REGS_SIZE 0x20
185255 #define THERMCTL_LVL_REG(rg, lv) ((rg) + ((lv) * THERMCTL_LVL_REGS_SIZE))
186256
257+#define OC_THROTTLE_MODE_DISABLED 0
258+#define OC_THROTTLE_MODE_BRIEF 2
259+
187260 static const int min_low_temp = -127000;
188261 static const int max_high_temp = 127000;
189262
190263 enum soctherm_throttle_id {
191264 THROTTLE_LIGHT = 0,
192265 THROTTLE_HEAVY,
266+ THROTTLE_OC1,
267+ THROTTLE_OC2,
268+ THROTTLE_OC3,
269+ THROTTLE_OC4,
270+ THROTTLE_OC5, /* OC5 is reserved */
193271 THROTTLE_SIZE,
194272 };
195273
274+enum soctherm_oc_irq_id {
275+ TEGRA_SOC_OC_IRQ_1,
276+ TEGRA_SOC_OC_IRQ_2,
277+ TEGRA_SOC_OC_IRQ_3,
278+ TEGRA_SOC_OC_IRQ_4,
279+ TEGRA_SOC_OC_IRQ_5,
280+ TEGRA_SOC_OC_IRQ_MAX,
281+};
282+
196283 enum soctherm_throttle_dev_id {
197284 THROTTLE_DEV_CPU = 0,
198285 THROTTLE_DEV_GPU,
@@ -202,6 +289,11 @@ enum soctherm_throttle_dev_id { · 3 unmodified lines
202289 static const char *const throt_names[] = {
203290 [THROTTLE_LIGHT] = "light",
204291 [THROTTLE_HEAVY] = "heavy",
292+ [THROTTLE_OC1] = "oc1",
293+ [THROTTLE_OC2] = "oc2",
294+ [THROTTLE_OC3] = "oc3",
295+ [THROTTLE_OC4] = "oc4",
296+ [THROTTLE_OC5] = "oc5",
205297 };
206298
207299 struct tegra_soctherm;
@@ -213,12 +305,23 @@ struct tegra_thermctl_zone { · 5 unmodified lines
213305 const struct tegra_tsensor_group *sg;
214306 };
215307
308+struct soctherm_oc_cfg {
309+ u32 active_low;
310+ u32 throt_period;
311+ u32 alarm_cnt_thresh;
312+ u32 alarm_filter;
313+ u32 mode;
314+ bool intr_en;
315+};
316+
216317 struct soctherm_throt_cfg {
217318 const char *name;
218319 unsigned int id;
219320 u8 priority;
220321 u8 cpu_throt_level;
221322 u32 cpu_throt_depth;
323+ u32 gpu_throt_level;
324+ struct soctherm_oc_cfg oc_cfg;
222325 struct thermal_cooling_device *cdev;
223326 bool init;
224327 };
@@ -231,6 +334,9 @@ struct tegra_soctherm { · 6 unmodified lines
231334 void __iomem *clk_regs;
232335 void __iomem *ccroc_regs;
233336
337+ int thermal_irq;
338+ int edp_irq;
339+
234340 u32 *calib;
235341 struct thermal_zone_device **thermctl_tzs;
236342 struct tegra_soctherm_soc *soc;
@@ -238,8 +344,19 @@ struct tegra_soctherm { · 1 unmodified line
238344 struct soctherm_throt_cfg throt_cfgs[THROTTLE_SIZE];
239345
240346 struct dentry *debugfs_dir;
347+
348+ struct mutex thermctl_lock;
241349 };
242350
351+struct soctherm_oc_irq_chip_data {
352+ struct mutex irq_lock; /* serialize OC IRQs */
353+ struct irq_chip irq_chip;
354+ struct irq_domain *domain;
355+ int irq_enable;
356+};
357+
358+static struct soctherm_oc_irq_chip_data soc_irq_cdata;
359+
243360 /**
244361 * ccroc_writel() - writes a value to a CCROC register
245362 * @ts: pointer to a struct tegra_soctherm
@@ -446,6 +563,24 @@ find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name) · 200 unmodified lines
446563 return NULL;
447564 }
448565
566+static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id)
567+{
568+ int i, temp = min_low_temp;
569+ struct tsensor_group_thermtrips *tt = ts->soc->thermtrips;
570+
571+ if (id >= TEGRA124_SOCTHERM_SENSOR_NUM)
572+ return temp;
573+
574+ if (tt) {
575+ for (i = 0; i < ts->soc->num_ttgs; i++) {
576+ if (tt[i].id == id)
577+ return tt[i].temp;
578+ }
579+ }
580+
581+ return temp;
582+}
583+
449584 static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
450585 {
451586 struct tegra_thermctl_zone *zone = data;
@@ -464,7 +599,16 @@ static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp) · 12 unmodified lines
464599 return ret;
465600
466601 if (type == THERMAL_TRIP_CRITICAL) {
467− return thermtrip_program(dev, sg, temp);
602+ /*
603+ * If thermtrips property is set in DT,
604+ * doesn't need to program critical type trip to HW,
605+ * if not, program critical trip to HW.
606+ */
607+ if (min_low_temp == tsensor_group_thermtrip_get(ts, sg->id))
608+ return thermtrip_program(dev, sg, temp);
609+ else
610+ return 0;
611+
468612 } else if (type == THERMAL_TRIP_HOT) {
469613 int i;
470614
@@ -519,10 +663,60 @@ static int tegra_thermctl_get_trend(void *data, int trip, · 48 unmodified lines
519663 return 0;
520664 }
521665
666+static void thermal_irq_enable(struct tegra_thermctl_zone *zn)
667+{
668+ u32 r;
669+
670+ /* multiple zones could be handling and setting trips at once */
671+ mutex_lock(&zn->ts->thermctl_lock);
672+ r = readl(zn->ts->regs + THERMCTL_INTR_ENABLE);
673+ r = REG_SET_MASK(r, zn->sg->thermctl_isr_mask, TH_INTR_UP_DN_EN);
674+ writel(r, zn->ts->regs + THERMCTL_INTR_ENABLE);
675+ mutex_unlock(&zn->ts->thermctl_lock);
676+}
677+
678+static void thermal_irq_disable(struct tegra_thermctl_zone *zn)
679+{
680+ u32 r;
681+
682+ /* multiple zones could be handling and setting trips at once */
683+ mutex_lock(&zn->ts->thermctl_lock);
684+ r = readl(zn->ts->regs + THERMCTL_INTR_DISABLE);
685+ r = REG_SET_MASK(r, zn->sg->thermctl_isr_mask, 0);
686+ writel(r, zn->ts->regs + THERMCTL_INTR_DISABLE);
687+ mutex_unlock(&zn->ts->thermctl_lock);
688+}
689+
690+static int tegra_thermctl_set_trips(void *data, int lo, int hi)
691+{
692+ struct tegra_thermctl_zone *zone = data;
693+ u32 r;
694+
695+ thermal_irq_disable(zone);
696+
697+ r = readl(zone->ts->regs + zone->sg->thermctl_lvl0_offset);
698+ r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 0);
699+ writel(r, zone->ts->regs + zone->sg->thermctl_lvl0_offset);
700+
701+ lo = enforce_temp_range(zone->dev, lo) / zone->ts->soc->thresh_grain;
702+ hi = enforce_temp_range(zone->dev, hi) / zone->ts->soc->thresh_grain;
703+ dev_dbg(zone->dev, "%s hi:%d, lo:%d\n", __func__, hi, lo);
704+
705+ r = REG_SET_MASK(r, zone->sg->thermctl_lvl0_up_thresh_mask, hi);
706+ r = REG_SET_MASK(r, zone->sg->thermctl_lvl0_dn_thresh_mask, lo);
707+ r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 1);
708+ writel(r, zone->ts->regs + zone->sg->thermctl_lvl0_offset);
709+
710+ thermal_irq_enable(zone);
711+
712+ return 0;
713+}
714+
522715 static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = {
523716 .get_temp = tegra_thermctl_get_temp,
524717 .set_trip_temp = tegra_thermctl_set_trip_temp,
525718 .get_trend = tegra_thermctl_get_trend,
719+ .set_trips = tegra_thermctl_set_trips,
526720 };
527721
528722 static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp)
@@ -555,7 +749,8 @@ static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp) · 26 unmodified lines
555749 * @dev: struct device * of the SOC_THERM instance
556750 *
557751 * Configure the SOC_THERM HW trip points, setting "THERMTRIP"
558− * "THROTTLE" trip points , using "critical" or "hot" type trip_temp
752+ * "THROTTLE" trip points , using "thermtrips", "critical" or "hot"
753+ * type trip_temp
559754 * from thermal zone.
560755 * After they have been configured, THERMTRIP or THROTTLE will take
561756 * action when the configured SoC thermal sensor group reaches a
@@ -577,28 +772,23 @@ static int tegra_soctherm_set_hwtrips(struct device *dev, · 15 unmodified lines
577772 {
578773 struct tegra_soctherm *ts = dev_get_drvdata(dev);
579774 struct soctherm_throt_cfg *stc;
580− int i, trip, temperature;
581− int ret;
775+ int i, trip, temperature, ret;
582776
583− ret = tz->ops->get_crit_temp(tz, &temperature);
584− if (ret) {
585− dev_warn(dev, "thermtrip: %s: missing critical temperature\n",
586− sg->name);
587− goto set_throttle;
588− }
777+ /* Get thermtrips. If missing, try to get critical trips. */
778+ temperature = tsensor_group_thermtrip_get(ts, sg->id);
779+ if (min_low_temp == temperature)
780+ if (tz->ops->get_crit_temp(tz, &temperature))
781+ temperature = max_high_temp;
589782
590783 ret = thermtrip_program(dev, sg, temperature);
591784 if (ret) {
592− dev_err(dev, "thermtrip: %s: error during enable\n",
593− sg->name);
785+ dev_err(dev, "thermtrip: %s: error during enable\n", sg->name);
594786 return ret;
595787 }
596788
597− dev_info(dev,
598− "thermtrip: will shut down when %s reaches %d mC\n",
789+ dev_info(dev, "thermtrip: will shut down when %s reaches %d mC\n",
599790 sg->name, temperature);
600791
601−set_throttle:
602792 ret = get_hot_temp(tz, &trip, &temperature);
603793 if (ret) {
604794 dev_info(dev, "throttrip: %s: missing hot temperature\n",
@@ -606,7 +796,7 @@ set_throttle: · 1 unmodified line
606796 return 0;
607797 }
608798
609− for (i = 0; i < THROTTLE_SIZE; i++) {
799+ for (i = 0; i < THROTTLE_OC1; i++) {
610800 struct thermal_cooling_device *cdev;
611801
612802 if (!ts->throt_cfgs[i].init)
@@ -638,6 +828,461 @@ set_throttle: · 25 unmodified lines
638828 return 0;
639829 }
640830
831+static irqreturn_t soctherm_thermal_isr(int irq, void *dev_id)
832+{
833+ struct tegra_soctherm *ts = dev_id;
834+ u32 r;
835+
836+ /* Case for no lock:
837+ * Although interrupts are enabled in set_trips, there is still no need
838+ * to lock here because the interrupts are disabled before programming
839+ * new trip points. Hence there cant be a interrupt on the same sensor.
840+ * An interrupt can however occur on a sensor while trips are being
841+ * programmed on a different one. This beign a LEVEL interrupt won't
842+ * cause a new interrupt but this is taken care of by the re-reading of
843+ * the STATUS register in the thread function.
844+ */
845+ r = readl(ts->regs + THERMCTL_INTR_STATUS);
846+ writel(r, ts->regs + THERMCTL_INTR_DISABLE);
847+
848+ return IRQ_WAKE_THREAD;
849+}
850+
851+/**
852+ * soctherm_thermal_isr_thread() - Handles a thermal interrupt request
853+ * @irq: The interrupt number being requested; not used
854+ * @dev_id: Opaque pointer to tegra_soctherm;
855+ *
856+ * Clears the interrupt status register if there are expected
857+ * interrupt bits set.
858+ * The interrupt(s) are then handled by updating the corresponding
859+ * thermal zones.
860+ *
861+ * An error is logged if any unexpected interrupt bits are set.
862+ *
863+ * Disabled interrupts are re-enabled.
864+ *
865+ * Return: %IRQ_HANDLED. Interrupt was handled and no further processing
866+ * is needed.
867+ */
868+static irqreturn_t soctherm_thermal_isr_thread(int irq, void *dev_id)
869+{
870+ struct tegra_soctherm *ts = dev_id;
871+ struct thermal_zone_device *tz;
872+ u32 st, ex = 0, cp = 0, gp = 0, pl = 0, me = 0;
873+
874+ st = readl(ts->regs + THERMCTL_INTR_STATUS);
875+
876+ /* deliberately clear expected interrupts handled in SW */
877+ cp |= st & TH_INTR_CD0_MASK;
878+ cp |= st & TH_INTR_CU0_MASK;
879+
880+ gp |= st & TH_INTR_GD0_MASK;
881+ gp |= st & TH_INTR_GU0_MASK;
882+
883+ pl |= st & TH_INTR_PD0_MASK;
884+ pl |= st & TH_INTR_PU0_MASK;
885+
886+ me |= st & TH_INTR_MD0_MASK;
887+ me |= st & TH_INTR_MU0_MASK;
888+
889+ ex |= cp | gp | pl | me;
890+ if (ex) {
891+ writel(ex, ts->regs + THERMCTL_INTR_STATUS);
892+ st &= ~ex;
893+
894+ if (cp) {
895+ tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_CPU];
896+ thermal_zone_device_update(tz,
897+ THERMAL_EVENT_UNSPECIFIED);
898+ }
899+
900+ if (gp) {
901+ tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_GPU];
902+ thermal_zone_device_update(tz,
903+ THERMAL_EVENT_UNSPECIFIED);
904+ }
905+
906+ if (pl) {
907+ tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_PLLX];
908+ thermal_zone_device_update(tz,
909+ THERMAL_EVENT_UNSPECIFIED);
910+ }
911+
912+ if (me) {
913+ tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_MEM];
914+ thermal_zone_device_update(tz,
915+ THERMAL_EVENT_UNSPECIFIED);
916+ }
917+ }
918+
919+ /* deliberately ignore expected interrupts NOT handled in SW */
920+ ex |= TH_INTR_IGNORE_MASK;
921+ st &= ~ex;
922+
923+ if (st) {
924+ /* Whine about any other unexpected INTR bits still set */
925+ pr_err("soctherm: Ignored unexpected INTRs 0x%08x\n", st);
926+ writel(st, ts->regs + THERMCTL_INTR_STATUS);
927+ }
928+
929+ return IRQ_HANDLED;
930+}
931+
932+/**
933+ * soctherm_oc_intr_enable() - Enables the soctherm over-current interrupt
934+ * @alarm: The soctherm throttle id
935+ * @enable: Flag indicating enable the soctherm over-current
936+ * interrupt or disable it
937+ *
938+ * Enables a specific over-current pins @alarm to raise an interrupt if the flag
939+ * is set and the alarm corresponds to OC1, OC2, OC3, or OC4.
940+ */
941+static void soctherm_oc_intr_enable(struct tegra_soctherm *ts,
942+ enum soctherm_throttle_id alarm,
943+ bool enable)
944+{
945+ u32 r;
946+
947+ if (!enable)
948+ return;
949+
950+ r = readl(ts->regs + OC_INTR_ENABLE);
951+ switch (alarm) {
952+ case THROTTLE_OC1:
953+ r = REG_SET_MASK(r, OC_INTR_OC1_MASK, 1);
954+ break;
955+ case THROTTLE_OC2:
956+ r = REG_SET_MASK(r, OC_INTR_OC2_MASK, 1);
957+ break;
958+ case THROTTLE_OC3:
959+ r = REG_SET_MASK(r, OC_INTR_OC3_MASK, 1);
960+ break;
961+ case THROTTLE_OC4:
962+ r = REG_SET_MASK(r, OC_INTR_OC4_MASK, 1);
963+ break;
964+ default:
965+ r = 0;
966+ break;
967+ }
968+ writel(r, ts->regs + OC_INTR_ENABLE);
969+}
970+
971+/**
972+ * soctherm_handle_alarm() - Handles soctherm alarms
973+ * @alarm: The soctherm throttle id
974+ *
975+ * "Handles" over-current alarms (OC1, OC2, OC3, and OC4) by printing
976+ * a warning or informative message.
977+ *
978+ * Return: -EINVAL for @alarm = THROTTLE_OC3, otherwise 0 (success).
979+ */
980+static int soctherm_handle_alarm(enum soctherm_throttle_id alarm)
981+{
982+ int rv = -EINVAL;
983+
984+ switch (alarm) {
985+ case THROTTLE_OC1:
986+ pr_debug("soctherm: Successfully handled OC1 alarm\n");
987+ rv = 0;
988+ break;
989+
990+ case THROTTLE_OC2:
991+ pr_debug("soctherm: Successfully handled OC2 alarm\n");
992+ rv = 0;
993+ break;
994+
995+ case THROTTLE_OC3:
996+ pr_debug("soctherm: Successfully handled OC3 alarm\n");
997+ rv = 0;
998+ break;
999+
1000+ case THROTTLE_OC4:
1001+ pr_debug("soctherm: Successfully handled OC4 alarm\n");
1002+ rv = 0;
1003+ break;
1004+
1005+ default:
1006+ break;
1007+ }
1008+
1009+ if (rv)
1010+ pr_err("soctherm: ERROR in handling %s alarm\n",
1011+ throt_names[alarm]);
1012+
1013+ return rv;
1014+}
1015+
1016+/**
1017+ * soctherm_edp_isr_thread() - log an over-current interrupt request
1018+ * @irq: OC irq number. Currently not being used. See description
1019+ * @arg: a void pointer for callback, currently not being used
1020+ *
1021+ * Over-current events are handled in hardware. This function is called to log
1022+ * and handle any OC events that happened. Additionally, it checks every
1023+ * over-current interrupt registers for registers are set but
1024+ * was not expected (i.e. any discrepancy in interrupt status) by the function,
1025+ * the discrepancy will logged.
1026+ *
1027+ * Return: %IRQ_HANDLED
1028+ */
1029+static irqreturn_t soctherm_edp_isr_thread(int irq, void *arg)
1030+{
1031+ struct tegra_soctherm *ts = arg;
1032+ u32 st, ex, oc1, oc2, oc3, oc4;
1033+
1034+ st = readl(ts->regs + OC_INTR_STATUS);
1035+
1036+ /* deliberately clear expected interrupts handled in SW */
1037+ oc1 = st & OC_INTR_OC1_MASK;
1038+ oc2 = st & OC_INTR_OC2_MASK;
1039+ oc3 = st & OC_INTR_OC3_MASK;
1040+ oc4 = st & OC_INTR_OC4_MASK;
1041+ ex = oc1 | oc2 | oc3 | oc4;
1042+
1043+ pr_err("soctherm: OC ALARM 0x%08x\n", ex);
1044+ if (ex) {
1045+ writel(st, ts->regs + OC_INTR_STATUS);
1046+ st &= ~ex;
1047+
1048+ if (oc1 && !soctherm_handle_alarm(THROTTLE_OC1))
1049+ soctherm_oc_intr_enable(ts, THROTTLE_OC1, true);
1050+
1051+ if (oc2 && !soctherm_handle_alarm(THROTTLE_OC2))
1052+ soctherm_oc_intr_enable(ts, THROTTLE_OC2, true);
1053+
1054+ if (oc3 && !soctherm_handle_alarm(THROTTLE_OC3))
1055+ soctherm_oc_intr_enable(ts, THROTTLE_OC3, true);
1056+
1057+ if (oc4 && !soctherm_handle_alarm(THROTTLE_OC4))
1058+ soctherm_oc_intr_enable(ts, THROTTLE_OC4, true);
1059+
1060+ if (oc1 && soc_irq_cdata.irq_enable & BIT(0))
1061+ handle_nested_irq(
1062+ irq_find_mapping(soc_irq_cdata.domain, 0));
1063+
1064+ if (oc2 && soc_irq_cdata.irq_enable & BIT(1))
1065+ handle_nested_irq(
1066+ irq_find_mapping(soc_irq_cdata.domain, 1));
1067+
1068+ if (oc3 && soc_irq_cdata.irq_enable & BIT(2))
1069+ handle_nested_irq(
1070+ irq_find_mapping(soc_irq_cdata.domain, 2));
1071+
1072+ if (oc4 && soc_irq_cdata.irq_enable & BIT(3))
1073+ handle_nested_irq(
1074+ irq_find_mapping(soc_irq_cdata.domain, 3));
1075+ }
1076+
1077+ if (st) {
1078+ pr_err("soctherm: Ignored unexpected OC ALARM 0x%08x\n", st);
1079+ writel(st, ts->regs + OC_INTR_STATUS);
1080+ }
1081+
1082+ return IRQ_HANDLED;
1083+}
1084+
1085+/**
1086+ * soctherm_edp_isr() - Disables any active interrupts
1087+ * @irq: The interrupt request number
1088+ * @arg: Opaque pointer to an argument
1089+ *
1090+ * Writes to the OC_INTR_DISABLE register the over current interrupt status,
1091+ * masking any asserted interrupts. Doing this prevents the same interrupts
1092+ * from triggering this isr repeatedly. The thread woken by this isr will
1093+ * handle asserted interrupts and subsequently unmask/re-enable them.
1094+ *
1095+ * The OC_INTR_DISABLE register indicates which OC interrupts
1096+ * have been disabled.
1097+ *
1098+ * Return: %IRQ_WAKE_THREAD, handler requests to wake the handler thread
1099+ */
1100+static irqreturn_t soctherm_edp_isr(int irq, void *arg)
1101+{
1102+ struct tegra_soctherm *ts = arg;
1103+ u32 r;
1104+
1105+ if (!ts)
1106+ return IRQ_NONE;
1107+
1108+ r = readl(ts->regs + OC_INTR_STATUS);
1109+ writel(r, ts->regs + OC_INTR_DISABLE);
1110+
1111+ return IRQ_WAKE_THREAD;
1112+}
1113+
1114+/**
1115+ * soctherm_oc_irq_lock() - locks the over-current interrupt request
1116+ * @data: Interrupt request data
1117+ *
1118+ * Looks up the chip data from @data and locks the mutex associated with
1119+ * a particular over-current interrupt request.
1120+ */
1121+static void soctherm_oc_irq_lock(struct irq_data *data)
1122+{
1123+ struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);
1124+
1125+ mutex_lock(&d->irq_lock);
1126+}
1127+
1128+/**
1129+ * soctherm_oc_irq_sync_unlock() - Unlocks the OC interrupt request
1130+ * @data: Interrupt request data
1131+ *
1132+ * Looks up the interrupt request data @data and unlocks the mutex associated
1133+ * with a particular over-current interrupt request.
1134+ */
1135+static void soctherm_oc_irq_sync_unlock(struct irq_data *data)
1136+{
1137+ struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);
1138+
1139+ mutex_unlock(&d->irq_lock);
1140+}
1141+
1142+/**
1143+ * soctherm_oc_irq_enable() - Enables the SOC_THERM over-current interrupt queue
1144+ * @data: irq_data structure of the chip
1145+ *
1146+ * Sets the irq_enable bit of SOC_THERM allowing SOC_THERM
1147+ * to respond to over-current interrupts.
1148+ *
1149+ */
1150+static void soctherm_oc_irq_enable(struct irq_data *data)
1151+{
1152+ struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);
1153+
1154+ d->irq_enable |= BIT(data->hwirq);
1155+}
1156+
1157+/**
1158+ * soctherm_oc_irq_disable() - Disables overcurrent interrupt requests
1159+ * @irq_data: The interrupt request information
1160+ *
1161+ * Clears the interrupt request enable bit of the overcurrent
1162+ * interrupt request chip data.
1163+ *
1164+ * Return: Nothing is returned (void)
1165+ */
1166+static void soctherm_oc_irq_disable(struct irq_data *data)
1167+{
1168+ struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);
1169+
1170+ d->irq_enable &= ~BIT(data->hwirq);
1171+}
1172+
1173+static int soctherm_oc_irq_set_type(struct irq_data *data, unsigned int type)
1174+{
1175+ return 0;
1176+}
1177+
1178+/**
1179+ * soctherm_oc_irq_map() - SOC_THERM interrupt request domain mapper
1180+ * @h: Interrupt request domain
1181+ * @virq: Virtual interrupt request number
1182+ * @hw: Hardware interrupt request number
1183+ *
1184+ * Mapping callback function for SOC_THERM's irq_domain. When a SOC_THERM
1185+ * interrupt request is called, the irq_domain takes the request's virtual
1186+ * request number (much like a virtual memory address) and maps it to a
1187+ * physical hardware request number.
1188+ *
1189+ * When a mapping doesn't already exist for a virtual request number, the
1190+ * irq_domain calls this function to associate the virtual request number with
1191+ * a hardware request number.
1192+ *
1193+ * Return: 0
1194+ */
1195+static int soctherm_oc_irq_map(struct irq_domain *h, unsigned int virq,
1196+ irq_hw_number_t hw)
1197+{
1198+ struct soctherm_oc_irq_chip_data *data = h->host_data;
1199+
1200+ irq_set_chip_data(virq, data);
1201+ irq_set_chip(virq, &data->irq_chip);
1202+ irq_set_nested_thread(virq, 1);
1203+ return 0;
1204+}
1205+
1206+/**
1207+ * soctherm_irq_domain_xlate_twocell() - xlate for soctherm interrupts
1208+ * @d: Interrupt request domain
1209+ * @intspec: Array of u32s from DTs "interrupt" property
1210+ * @intsize: Number of values inside the intspec array
1211+ * @out_hwirq: HW IRQ value associated with this interrupt
1212+ * @out_type: The IRQ SENSE type for this interrupt.
1213+ *
1214+ * This Device Tree IRQ specifier translation function will translate a
1215+ * specific "interrupt" as defined by 2 DT values where the cell values map
1216+ * the hwirq number + 1 and linux irq flags. Since the output is the hwirq
1217+ * number, this function will subtract 1 from the value listed in DT.
1218+ *
1219+ * Return: 0
1220+ */
1221+static int soctherm_irq_domain_xlate_twocell(struct irq_domain *d,
1222+ struct device_node *ctrlr, const u32 *intspec, unsigned int intsize,
1223+ irq_hw_number_t *out_hwirq, unsigned int *out_type)
1224+{
1225+ if (WARN_ON(intsize < 2))
1226+ return -EINVAL;
1227+
1228+ /*
1229+ * The HW value is 1 index less than the DT IRQ values.
1230+ * i.e. OC4 goes to HW index 3.
1231+ */
1232+ *out_hwirq = intspec[0] - 1;
1233+ *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
1234+ return 0;
1235+}
1236+
1237+static const struct irq_domain_ops soctherm_oc_domain_ops = {
1238+ .map = soctherm_oc_irq_map,
1239+ .xlate = soctherm_irq_domain_xlate_twocell,
1240+};
1241+
1242+/**
1243+ * soctherm_oc_int_init() - Initial enabling of the over
1244+ * current interrupts
1245+ * @np: The devicetree node for soctherm
1246+ * @num_irqs: The number of new interrupt requests
1247+ *
1248+ * Sets the over current interrupt request chip data
1249+ *
1250+ * Return: 0 on success or if overcurrent interrupts are not enabled,
1251+ * -ENOMEM (out of memory), or irq_base if the function failed to
1252+ * allocate the irqs
1253+ */
1254+static int soctherm_oc_int_init(struct device_node *np, int num_irqs)
1255+{
1256+ if (!num_irqs) {
1257+ pr_info("%s(): OC interrupts are not enabled\n", __func__);
1258+ return 0;
1259+ }
1260+
1261+ mutex_init(&soc_irq_cdata.irq_lock);
1262+ soc_irq_cdata.irq_enable = 0;
1263+
1264+ soc_irq_cdata.irq_chip.name = "soc_therm_oc";
1265+ soc_irq_cdata.irq_chip.irq_bus_lock = soctherm_oc_irq_lock;
1266+ soc_irq_cdata.irq_chip.irq_bus_sync_unlock =
1267+ soctherm_oc_irq_sync_unlock;
1268+ soc_irq_cdata.irq_chip.irq_disable = soctherm_oc_irq_disable;
1269+ soc_irq_cdata.irq_chip.irq_enable = soctherm_oc_irq_enable;
1270+ soc_irq_cdata.irq_chip.irq_set_type = soctherm_oc_irq_set_type;
1271+ soc_irq_cdata.irq_chip.irq_set_wake = NULL;
1272+
1273+ soc_irq_cdata.domain = irq_domain_add_linear(np, num_irqs,
1274+ &soctherm_oc_domain_ops,
1275+ &soc_irq_cdata);
1276+
1277+ if (!soc_irq_cdata.domain) {
1278+ pr_err("%s: Failed to create IRQ domain\n", __func__);
1279+ return -ENOMEM;
1280+ }
1281+
1282+ pr_debug("%s(): OC interrupts enabled successful\n", __func__);
1283+ return 0;
1284+}
1285+
6411286 #ifdef CONFIG_DEBUG_FS
6421287 static int regs_show(struct seq_file *s, void *data)
6431288 {
@@ -929,6 +1574,120 @@ static const struct thermal_cooling_device_ops throt_cooling_ops = { · 285 unmodified lines
9291574 .set_cur_state = throt_set_cdev_state,
9301575 };
9311576
1577+static int soctherm_thermtrips_parse(struct platform_device *pdev)
1578+{
1579+ struct device *dev = &pdev->dev;
1580+ struct tegra_soctherm *ts = dev_get_drvdata(dev);
1581+ struct tsensor_group_thermtrips *tt = ts->soc->thermtrips;
1582+ const int max_num_prop = ts->soc->num_ttgs * 2;
1583+ u32 *tlb;
1584+ int i, j, n, ret;
1585+
1586+ if (!tt)
1587+ return -ENOMEM;
1588+
1589+ n = of_property_count_u32_elems(dev->of_node, "nvidia,thermtrips");
1590+ if (n <= 0) {
1591+ dev_info(dev,
1592+ "missing thermtrips, will use critical trips as shut down temp\n");
1593+ return n;
1594+ }
1595+
1596+ n = min(max_num_prop, n);
1597+
1598+ tlb = devm_kcalloc(&pdev->dev, max_num_prop, sizeof(u32), GFP_KERNEL);
1599+ if (!tlb)
1600+ return -ENOMEM;
1601+ ret = of_property_read_u32_array(dev->of_node, "nvidia,thermtrips",
1602+ tlb, n);
1603+ if (ret) {
1604+ dev_err(dev, "invalid num ele: thermtrips:%d\n", ret);
1605+ return ret;
1606+ }
1607+
1608+ i = 0;
1609+ for (j = 0; j < n; j = j + 2) {
1610+ if (tlb[j] >= TEGRA124_SOCTHERM_SENSOR_NUM)
1611+ continue;
1612+
1613+ tt[i].id = tlb[j];
1614+ tt[i].temp = tlb[j + 1];
1615+ i++;
1616+ }
1617+
1618+ return 0;
1619+}
1620+
1621+static void soctherm_oc_cfg_parse(struct device *dev,
1622+ struct device_node *np_oc,
1623+ struct soctherm_throt_cfg *stc)
1624+{
1625+ u32 val;
1626+
1627+ if (of_property_read_bool(np_oc, "nvidia,polarity-active-low"))
1628+ stc->oc_cfg.active_low = 1;
1629+ else
1630+ stc->oc_cfg.active_low = 0;
1631+
1632+ if (!of_property_read_u32(np_oc, "nvidia,count-threshold", &val)) {
1633+ stc->oc_cfg.intr_en = 1;
1634+ stc->oc_cfg.alarm_cnt_thresh = val;
1635+ }
1636+
1637+ if (!of_property_read_u32(np_oc, "nvidia,throttle-period-us", &val))
1638+ stc->oc_cfg.throt_period = val;
1639+
1640+ if (!of_property_read_u32(np_oc, "nvidia,alarm-filter", &val))
1641+ stc->oc_cfg.alarm_filter = val;
1642+
1643+ /* BRIEF throttling by default, do not support STICKY */
1644+ stc->oc_cfg.mode = OC_THROTTLE_MODE_BRIEF;
1645+}
1646+
1647+static int soctherm_throt_cfg_parse(struct device *dev,
1648+ struct device_node *np,
1649+ struct soctherm_throt_cfg *stc)
1650+{
1651+ struct tegra_soctherm *ts = dev_get_drvdata(dev);
1652+ int ret;
1653+ u32 val;
1654+
1655+ ret = of_property_read_u32(np, "nvidia,priority", &val);
1656+ if (ret) {
1657+ dev_err(dev, "throttle-cfg: %s: invalid priority\n", stc->name);
1658+ return -EINVAL;
1659+ }
1660+ stc->priority = val;
1661+
1662+ ret = of_property_read_u32(np, ts->soc->use_ccroc ?
1663+ "nvidia,cpu-throt-level" :
1664+ "nvidia,cpu-throt-percent", &val);
1665+ if (!ret) {
1666+ if (ts->soc->use_ccroc &&
1667+ val <= TEGRA_SOCTHERM_THROT_LEVEL_HIGH)
1668+ stc->cpu_throt_level = val;
1669+ else if (!ts->soc->use_ccroc && val <= 100)
1670+ stc->cpu_throt_depth = val;
1671+ else
1672+ goto err;
1673+ } else {
1674+ goto err;
1675+ }
1676+
1677+ ret = of_property_read_u32(np, "nvidia,gpu-throt-level", &val);
1678+ if (!ret && val <= TEGRA_SOCTHERM_THROT_LEVEL_HIGH)
1679+ stc->gpu_throt_level = val;
1680+ else
1681+ goto err;
1682+
1683+ return 0;
1684+
1685+err:
1686+ dev_err(dev, "throttle-cfg: %s: no throt prop or invalid prop\n",
1687+ stc->name);
1688+ return -EINVAL;
1689+}
1690+
9321691 /**
9331692 * soctherm_init_hw_throt_cdev() - Parse the HW throttle configurations
9341693 * and register them as cooling devices.
@@ -939,8 +1698,7 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev) · 4 unmodified lines
9391698 struct tegra_soctherm *ts = dev_get_drvdata(dev);
9401699 struct device_node *np_stc, *np_stcc;
9411700 const char *name;
942− u32 val;
943− int i, r;
1701+ int i;
9441702
9451703 for (i = 0; i < THROTTLE_SIZE; i++) {
9461704 ts->throt_cfgs[i].name = throt_names[i];
@@ -958,6 +1716,7 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev) · 11 unmodified lines
9581716 for_each_child_of_node(np_stc, np_stcc) {
9591717 struct soctherm_throt_cfg *stc;
9601718 struct thermal_cooling_device *tcd;
1719+ int err;
9611720
9621721 name = np_stcc->name;
9631722 stc = find_throttle_cfg_by_name(ts, name);
@@ -967,51 +1726,34 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev) · 3 unmodified lines
9671726 continue;
9681727 }
9691728
970− r = of_property_read_u32(np_stcc, "nvidia,priority", &val);
971− if (r) {
972− dev_info(dev,
973− "throttle-cfg: %s: missing priority\n", name);
974− continue;
1729+ if (stc->init) {
1730+ dev_err(dev, "throttle-cfg: %s: redefined!\n", name);
1731+ of_node_put(np_stcc);
1732+ break;
9751733 }
976− stc->priority = val;
977−
978− if (ts->soc->use_ccroc) {
979− r = of_property_read_u32(np_stcc,
980− "nvidia,cpu-throt-level",
981− &val);
982− if (r) {
983− dev_info(dev,
984− "throttle-cfg: %s: missing cpu-throt-level\n",
985− name);
986− continue;
987− }
988− stc->cpu_throt_level = val;
1734+
1735+ err = soctherm_throt_cfg_parse(dev, np_stcc, stc);
1736+ if (err)
1737+ continue;
1738+
1739+ if (stc->id >= THROTTLE_OC1) {
1740+ soctherm_oc_cfg_parse(dev, np_stcc, stc);
1741+ stc->init = true;
9891742 } else {
990− r = of_property_read_u32(np_stcc,
991− "nvidia,cpu-throt-percent",
992− &val);
993− if (r) {
994− dev_info(dev,
995− "throttle-cfg: %s: missing cpu-throt-percent\n",
996− name);
997− continue;
998− }
999− stc->cpu_throt_depth = val;
1000− }
10011743
1002− tcd = thermal_of_cooling_device_register(np_stcc,
1744+ tcd = thermal_of_cooling_device_register(np_stcc,
10031745 (char *)name, ts,
10041746 &throt_cooling_ops);
1005− of_node_put(np_stcc);
1006− if (IS_ERR_OR_NULL(tcd)) {
1007− dev_err(dev,
1008− "throttle-cfg: %s: failed to register cooling device\n",
1009− name);
1010− continue;
1747+ if (IS_ERR_OR_NULL(tcd)) {
1748+ dev_err(dev,
1749+ "throttle-cfg: %s: failed to register cooling device\n",
1750+ name);
1751+ continue;
1752+ }
1753+ stc->cdev = tcd;
1754+ stc->init = true;
10111755 }
10121756
1013− stc->cdev = tcd;
1014− stc->init = true;
10151757 }
10161758
10171759 of_node_put(np_stc);
@@ -1140,6 +1882,50 @@ static void throttlectl_cpu_mn(struct tegra_soctherm *ts, · 122 unmodified lines
11401882 writel(r, ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));
11411883 }
11421884
1885+/**
1886+ * throttlectl_gpu_level_select() - selects throttling level for GPU
1887+ * @throt: the LIGHT/HEAVY of throttle event id
1888+ *
1889+ * This function programs soctherm's interface to GK20a NV_THERM to select
1890+ * pre-configured "Low", "Medium" or "Heavy" throttle levels.
1891+ *
1892+ * Return: boolean true if HW was programmed
1893+ */
1894+static void throttlectl_gpu_level_select(struct tegra_soctherm *ts,
1895+ enum soctherm_throttle_id throt)
1896+{
1897+ u32 r, level, throt_vect;
1898+
1899+ level = ts->throt_cfgs[throt].gpu_throt_level;
1900+ throt_vect = THROT_LEVEL_TO_DEPTH(level);
1901+ r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_GPU));
1902+ r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1);
1903+ r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT_GPU_MASK, throt_vect);
1904+ writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_GPU));
1905+}
1906+
1907+static int soctherm_oc_cfg_program(struct tegra_soctherm *ts,
1908+ enum soctherm_throttle_id throt)
1909+{
1910+ u32 r;
1911+ struct soctherm_oc_cfg *oc = &ts->throt_cfgs[throt].oc_cfg;
1912+
1913+ if (oc->mode == OC_THROTTLE_MODE_DISABLED)
1914+ return -EINVAL;
1915+
1916+ r = REG_SET_MASK(0, OC1_CFG_HW_RESTORE_MASK, 1);
1917+ r = REG_SET_MASK(r, OC1_CFG_THROTTLE_MODE_MASK, oc->mode);
1918+ r = REG_SET_MASK(r, OC1_CFG_ALARM_POLARITY_MASK, oc->active_low);
1919+ r = REG_SET_MASK(r, OC1_CFG_EN_THROTTLE_MASK, 1);
1920+ writel(r, ts->regs + ALARM_CFG(throt));
1921+ writel(oc->throt_period, ts->regs + ALARM_THROTTLE_PERIOD(throt));
1922+ writel(oc->alarm_cnt_thresh, ts->regs + ALARM_CNT_THRESHOLD(throt));
1923+ writel(oc->alarm_filter, ts->regs + ALARM_FILTER(throt));
1924+ soctherm_oc_intr_enable(ts, throt, oc->intr_en);
1925+
1926+ return 0;
1927+}
1928+
11431929 /**
11441930 * soctherm_throttle_program() - programs pulse skippers' configuration
11451931 * @throt: the LIGHT/HEAVY of the throttle event id.
@@ -1156,12 +1942,17 @@ static void soctherm_throttle_program(struct tegra_soctherm *ts, · 10 unmodified lines
11561942 if (!stc.init)
11571943 return;
11581944
1945+ if ((throt >= THROTTLE_OC1) && (soctherm_oc_cfg_program(ts, throt)))
1946+ return;
1947+
11591948 /* Setup PSKIP parameters */
11601949 if (ts->soc->use_ccroc)
11611950 throttlectl_cpu_level_select(ts, throt);
11621951 else
11631952 throttlectl_cpu_mn(ts, throt);
11641953
1954+ throttlectl_gpu_level_select(ts, throt);
1955+
11651956 r = REG_SET_MASK(0, THROT_PRIORITY_LITE_PRIO_MASK, stc.priority);
11661957 writel(r, ts->regs + THROT_PRIORITY_CTRL(throt));
11671958
@@ -1215,6 +2006,57 @@ static void tegra_soctherm_throttle(struct device *dev) · 47 unmodified lines
12152006 writel(v, ts->regs + THERMCTL_STATS_CTL);
12162007 }
12172008
2009+static int soctherm_interrupts_init(struct platform_device *pdev,
2010+ struct tegra_soctherm *tegra)
2011+{
2012+ struct device_node *np = pdev->dev.of_node;
2013+ int ret;
2014+
2015+ ret = soctherm_oc_int_init(np, TEGRA_SOC_OC_IRQ_MAX);
2016+ if (ret < 0) {
2017+ dev_err(&pdev->dev, "soctherm_oc_int_init failed\n");
2018+ return ret;
2019+ }
2020+
2021+ tegra->thermal_irq = platform_get_irq(pdev, 0);
2022+ if (tegra->thermal_irq < 0) {
2023+ dev_dbg(&pdev->dev, "get 'thermal_irq' failed.\n");
2024+ return 0;
2025+ }
2026+
2027+ tegra->edp_irq = platform_get_irq(pdev, 1);
2028+ if (tegra->edp_irq < 0) {
2029+ dev_dbg(&pdev->dev, "get 'edp_irq' failed.\n");
2030+ return 0;
2031+ }
2032+
2033+ ret = devm_request_threaded_irq(&pdev->dev,
2034+ tegra->thermal_irq,
2035+ soctherm_thermal_isr,
2036+ soctherm_thermal_isr_thread,
2037+ IRQF_ONESHOT,
2038+ dev_name(&pdev->dev),
2039+ tegra);
2040+ if (ret < 0) {
2041+ dev_err(&pdev->dev, "request_irq 'thermal_irq' failed.\n");
2042+ return ret;
2043+ }
2044+
2045+ ret = devm_request_threaded_irq(&pdev->dev,
2046+ tegra->edp_irq,
2047+ soctherm_edp_isr,
2048+ soctherm_edp_isr_thread,
2049+ IRQF_ONESHOT,
2050+ "soctherm_edp",
2051+ tegra);
2052+ if (ret < 0) {
2053+ dev_err(&pdev->dev, "request_irq 'edp_irq' failed.\n");
2054+ return ret;
2055+ }
2056+
2057+ return 0;
2058+}
2059+
12182060 static void soctherm_init(struct platform_device *pdev)
12192061 {
12202062 struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
@@ -1292,6 +2134,7 @@ static int tegra_soctherm_probe(struct platform_device *pdev) · 71 unmodified lines
12922134 if (!tegra)
12932135 return -ENOMEM;
12942136
2137+ mutex_init(&tegra->thermctl_lock);
12952138 dev_set_drvdata(&pdev->dev, tegra);
12962139
12972140 tegra->soc = soc;
@@ -1370,6 +2213,8 @@ static int tegra_soctherm_probe(struct platform_device *pdev) · 72 unmodified lines
13702213 if (err)
13712214 return err;
13722215
2216+ soctherm_thermtrips_parse(pdev);
2217+
13732218 soctherm_init_hw_throt_cdev(pdev);
13742219
13752220 soctherm_init(pdev);
@@ -1406,6 +2251,8 @@ static int tegra_soctherm_probe(struct platform_device *pdev) · 30 unmodified lines
14062251 goto disable_clocks;
14072252 }
14082253
2254+ err = soctherm_interrupts_init(pdev, tegra);
2255+
14092256 soctherm_debug_init(pdev);
14102257
14112258 return 0;
drivers/thermal/tegra/soctherm.h+16−0
@@ -1,3 +1,4 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
12 /*
23 * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
34 *
@@ -29,6 +30,14 @@ · 25 unmodified lines
2930 #define THERMCTL_THERMTRIP_CTL 0x80
3031 /* BITs are defined in device file */
3132
33+#define THERMCTL_INTR_ENABLE 0x88
34+#define THERMCTL_INTR_DISABLE 0x8c
35+#define TH_INTR_UP_DN_EN 0x3
36+#define THERM_IRQ_MEM_MASK (TH_INTR_UP_DN_EN << 24)
37+#define THERM_IRQ_GPU_MASK (TH_INTR_UP_DN_EN << 16)
38+#define THERM_IRQ_CPU_MASK (TH_INTR_UP_DN_EN << 8)
39+#define THERM_IRQ_TSENSE_MASK (TH_INTR_UP_DN_EN << 0)
40+
3241 #define SENSOR_PDIV 0x1c0
3342 #define SENSOR_PDIV_CPU_MASK (0xf << 12)
3443 #define SENSOR_PDIV_GPU_MASK (0xf << 8)
@@ -70,6 +79,7 @@ struct tegra_tsensor_group { · 35 unmodified lines
7079 u32 thermtrip_enable_mask;
7180 u32 thermtrip_any_en_mask;
7281 u32 thermtrip_threshold_mask;
82+ u32 thermctl_isr_mask;
7383 u16 thermctl_lvl0_offset;
7484 u32 thermctl_lvl0_up_thresh_mask;
7585 u32 thermctl_lvl0_dn_thresh_mask;
@@ -92,6 +102,11 @@ struct tegra_tsensor { · 16 unmodified lines
92102 const struct tegra_tsensor_group *group;
93103 };
94104
105+struct tsensor_group_thermtrips {
106+ u8 id;
107+ u32 temp;
108+};
109+
95110 struct tegra_soctherm_fuse {
96111 u32 fuse_base_cp_mask, fuse_base_cp_shift;
97112 u32 fuse_base_ft_mask, fuse_base_ft_shift;
@@ -113,6 +128,7 @@ struct tegra_soctherm_soc { · 15 unmodified lines
113128 const int thresh_grain;
114129 const unsigned int bptt;
115130 const bool use_ccroc;
131+ struct tsensor_group_thermtrips *thermtrips;
116132 };
117133
118134 int tegra_calc_shared_calib(const struct tegra_soctherm_fuse *tfuse,
drivers/thermal/tegra/tegra124-soctherm.c+6−1
@@ -1,5 +1,6 @@
1+// SPDX-License-Identifier: GPL-2.0
12 /*
2− * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
3+ * Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved.
34 *
45 * This software is licensed under the terms of the GNU General Public
56 * License version 2, as published by the Free Software Foundation, and
@@ -55,6 +56,7 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_cpu = { · 49 unmodified lines
5556 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
5657 .thermtrip_enable_mask = TEGRA124_THERMTRIP_CPU_EN_MASK,
5758 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_CPU_THRESH_MASK,
59+ .thermctl_isr_mask = THERM_IRQ_CPU_MASK,
5860 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
5961 .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
6062 .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -73,6 +75,7 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_gpu = { · 12 unmodified lines
7375 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
7476 .thermtrip_enable_mask = TEGRA124_THERMTRIP_GPU_EN_MASK,
7577 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
78+ .thermctl_isr_mask = THERM_IRQ_GPU_MASK,
7679 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
7780 .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
7881 .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -89,6 +92,7 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_pll = { · 10 unmodified lines
8992 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
9093 .thermtrip_enable_mask = TEGRA124_THERMTRIP_TSENSE_EN_MASK,
9194 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_TSENSE_THRESH_MASK,
95+ .thermctl_isr_mask = THERM_IRQ_TSENSE_MASK,
9296 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
9397 .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
9498 .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -107,6 +111,7 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_mem = { · 12 unmodified lines
107111 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
108112 .thermtrip_enable_mask = TEGRA124_THERMTRIP_MEM_EN_MASK,
109113 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
114+ .thermctl_isr_mask = THERM_IRQ_MEM_MASK,
110115 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
111116 .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
112117 .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
drivers/thermal/tegra/tegra132-soctherm.c+6−1
@@ -1,5 +1,6 @@
1+// SPDX-License-Identifier: GPL-2.0
12 /*
2− * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
3+ * Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved.
34 *
45 * This software is licensed under the terms of the GNU General Public
56 * License version 2, as published by the Free Software Foundation, and
@@ -55,6 +56,7 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_cpu = { · 49 unmodified lines
5556 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
5657 .thermtrip_enable_mask = TEGRA132_THERMTRIP_CPU_EN_MASK,
5758 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_CPU_THRESH_MASK,
59+ .thermctl_isr_mask = THERM_IRQ_CPU_MASK,
5860 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
5961 .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
6062 .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -73,6 +75,7 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_gpu = { · 12 unmodified lines
7375 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
7476 .thermtrip_enable_mask = TEGRA132_THERMTRIP_GPU_EN_MASK,
7577 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
78+ .thermctl_isr_mask = THERM_IRQ_GPU_MASK,
7679 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
7780 .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
7881 .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -89,6 +92,7 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_pll = { · 10 unmodified lines
8992 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
9093 .thermtrip_enable_mask = TEGRA132_THERMTRIP_TSENSE_EN_MASK,
9194 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_TSENSE_THRESH_MASK,
95+ .thermctl_isr_mask = THERM_IRQ_TSENSE_MASK,
9296 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
9397 .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
9498 .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -107,6 +111,7 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_mem = { · 12 unmodified lines
107111 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
108112 .thermtrip_enable_mask = TEGRA132_THERMTRIP_MEM_EN_MASK,
109113 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
114+ .thermctl_isr_mask = THERM_IRQ_MEM_MASK,
110115 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
111116 .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
112117 .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
drivers/thermal/tegra/tegra210-soctherm.c+14−1
@@ -1,5 +1,6 @@
1+// SPDX-License-Identifier: GPL-2.0
12 /*
2− * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
3+ * Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved.
34 *
45 * This software is licensed under the terms of the GNU General Public
56 * License version 2, as published by the Free Software Foundation, and
@@ -56,6 +57,7 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_cpu = { · 50 unmodified lines
5657 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
5758 .thermtrip_enable_mask = TEGRA210_THERMTRIP_CPU_EN_MASK,
5859 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_CPU_THRESH_MASK,
60+ .thermctl_isr_mask = THERM_IRQ_CPU_MASK,
5961 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
6062 .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
6163 .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -74,6 +76,7 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_gpu = { · 12 unmodified lines
7476 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
7577 .thermtrip_enable_mask = TEGRA210_THERMTRIP_GPU_EN_MASK,
7678 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
79+ .thermctl_isr_mask = THERM_IRQ_GPU_MASK,
7780 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
7881 .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
7982 .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -90,6 +93,7 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_pll = { · 10 unmodified lines
9093 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
9194 .thermtrip_enable_mask = TEGRA210_THERMTRIP_TSENSE_EN_MASK,
9295 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_TSENSE_THRESH_MASK,
96+ .thermctl_isr_mask = THERM_IRQ_TSENSE_MASK,
9397 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
9498 .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
9599 .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -108,6 +112,7 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_mem = { · 12 unmodified lines
108112 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
109113 .thermtrip_enable_mask = TEGRA210_THERMTRIP_MEM_EN_MASK,
110114 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
115+ .thermctl_isr_mask = THERM_IRQ_MEM_MASK,
111116 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
112117 .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
113118 .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -203,6 +208,13 @@ static const struct tegra_soctherm_fuse tegra210_soctherm_fuse = { · 89 unmodified lines
203208 .fuse_spare_realignment = 0,
204209 };
205210
211+struct tsensor_group_thermtrips tegra210_tsensor_thermtrips[] = {
212+ {.id = TEGRA124_SOCTHERM_SENSOR_NUM},
213+ {.id = TEGRA124_SOCTHERM_SENSOR_NUM},
214+ {.id = TEGRA124_SOCTHERM_SENSOR_NUM},
215+ {.id = TEGRA124_SOCTHERM_SENSOR_NUM},
216+};
217+
206218 const struct tegra_soctherm_soc tegra210_soctherm = {
207219 .tsensors = tegra210_tsensors,
208220 .num_tsensors = ARRAY_SIZE(tegra210_tsensors),
@@ -212,4 +224,5 @@ const struct tegra_soctherm_soc tegra210_soctherm = { · 3 unmodified lines
212224 .thresh_grain = TEGRA210_THRESH_GRAIN,
213225 .bptt = TEGRA210_BPTT,
214226 .use_ccroc = false,
227+ .thermtrips = tegra210_tsensor_thermtrips,
215228 };
drivers/thermal/thermal-generic-adc.c+6−3
@@ -29,6 +29,9 @@ static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val) · 28 unmodified lines
2929 int temp, temp_hi, temp_lo, adc_hi, adc_lo;
3030 int i;
3131
32+ if (!gti->lookup_table)
33+ return val;
34+
3235 for (i = 0; i < gti->nlookup_table; i++) {
3336 if (val >= gti->lookup_table[2 * i + 1])
3437 break;
@@ -81,9 +84,9 @@ static int gadc_thermal_read_linear_lookup_table(struct device *dev, · 46 unmodified lines
8184
8285 ntable = of_property_count_elems_of_size(np, "temperature-lookup-table",
8386 sizeof(u32));
84− if (ntable < 0) {
85− dev_err(dev, "Lookup table is not provided\n");
86− return ntable;
87+ if (ntable <= 0) {
88+ dev_notice(dev, "no lookup table, assuming DAC channel returns milliCelcius\n");
89+ return 0;
8790 }
8891
8992 if (ntable % 2) {
drivers/thermal/thermal_core.c+49−0
@@ -1046,6 +1046,55 @@ thermal_of_cooling_device_register(struct device_node *np, · 1045 unmodified lines
10461046 }
10471047 EXPORT_SYMBOL_GPL(thermal_of_cooling_device_register);
10481048
1049+static void thermal_cooling_device_release(struct device *dev, void *res)
1050+{
1051+ thermal_cooling_device_unregister(
1052+ *(struct thermal_cooling_device **)res);
1053+}
1054+
1055+/**
1056+ * devm_thermal_of_cooling_device_register() - register an OF thermal cooling
1057+ * device
1058+ * @dev: a valid struct device pointer of a sensor device.
1059+ * @np: a pointer to a device tree node.
1060+ * @type: the thermal cooling device type.
1061+ * @devdata: device private data.
1062+ * @ops: standard thermal cooling devices callbacks.
1063+ *
1064+ * This function will register a cooling device with device tree node reference.
1065+ * This interface function adds a new thermal cooling device (fan/processor/...)
1066+ * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself
1067+ * to all the thermal zone devices registered at the same time.
1068+ *
1069+ * Return: a pointer to the created struct thermal_cooling_device or an
1070+ * ERR_PTR. Caller must check return value with IS_ERR*() helpers.
1071+ */
1072+struct thermal_cooling_device *
1073+devm_thermal_of_cooling_device_register(struct device *dev,
1074+ struct device_node *np,
1075+ char *type, void *devdata,
1076+ const struct thermal_cooling_device_ops *ops)
1077+{
1078+ struct thermal_cooling_device **ptr, *tcd;
1079+
1080+ ptr = devres_alloc(thermal_cooling_device_release, sizeof(*ptr),
1081+ GFP_KERNEL);
1082+ if (!ptr)
1083+ return ERR_PTR(-ENOMEM);
1084+
1085+ tcd = __thermal_cooling_device_register(np, type, devdata, ops);
1086+ if (IS_ERR(tcd)) {
1087+ devres_free(ptr);
1088+ return tcd;
1089+ }
1090+
1091+ *ptr = tcd;
1092+ devres_add(dev, ptr);
1093+
1094+ return tcd;
1095+}
1096+EXPORT_SYMBOL_GPL(devm_thermal_of_cooling_device_register);
1097+
10491098 static void __unbind(struct thermal_zone_device *tz, int mask,
10501099 struct thermal_cooling_device *cdev)
10511100 {
drivers/thermal/thermal_mmio.c+129−0
@@ -0,0 +1,129 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+ */
5+
6+#include <linux/module.h>
7+#include <linux/of_address.h>
8+#include <linux/platform_device.h>
9+#include <linux/thermal.h>
10+
11+struct thermal_mmio {
12+ void __iomem *mmio_base;
13+ u32 (*read_mmio)(void __iomem *mmio_base);
14+ u32 mask;
15+ int factor;
16+};
17+
18+static u32 thermal_mmio_readb(void __iomem *mmio_base)
19+{
20+ return readb(mmio_base);
21+}
22+
23+static int thermal_mmio_get_temperature(void *private, int *temp)
24+{
25+ int t;
26+ struct thermal_mmio *sensor =
27+ (struct thermal_mmio *)private;
28+
29+ t = sensor->read_mmio(sensor->mmio_base) & sensor->mask;
30+ t *= sensor->factor;
31+
32+ *temp = t;
33+
34+ return 0;
35+}
36+
37+static struct thermal_zone_of_device_ops thermal_mmio_ops = {
38+ .get_temp = thermal_mmio_get_temperature,
39+};
40+
41+static int thermal_mmio_probe(struct platform_device *pdev)
42+{
43+ struct resource *resource;
44+ struct thermal_mmio *sensor;
45+ int (*sensor_init_func)(struct platform_device *pdev,
46+ struct thermal_mmio *sensor);
47+ struct thermal_zone_device *thermal_zone;
48+ int ret;
49+ int temperature;
50+
51+ sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL);
52+ if (!sensor)
53+ return -ENOMEM;
54+
55+ resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
56+ if (IS_ERR(resource)) {
57+ dev_err(&pdev->dev,
58+ "fail to get platform memory resource (%ld)\n",
59+ PTR_ERR(resource));
60+ return PTR_ERR(resource);
61+ }
62+
63+ sensor->mmio_base = devm_ioremap_resource(&pdev->dev, resource);
64+ if (IS_ERR(sensor->mmio_base)) {
65+ dev_err(&pdev->dev, "failed to ioremap memory (%ld)\n",
66+ PTR_ERR(sensor->mmio_base));
67+ return PTR_ERR(sensor->mmio_base);
68+ }
69+
70+ sensor_init_func = device_get_match_data(&pdev->dev);
71+ if (sensor_init_func) {
72+ ret = sensor_init_func(pdev, sensor);
73+ if (ret) {
74+ dev_err(&pdev->dev,
75+ "failed to initialize sensor (%d)\n",
76+ ret);
77+ return ret;
78+ }
79+ }
80+
81+ thermal_zone = devm_thermal_zone_of_sensor_register(&pdev->dev,
82+ 0,
83+ sensor,
84+ &thermal_mmio_ops);
85+ if (IS_ERR(thermal_zone)) {
86+ dev_err(&pdev->dev,
87+ "failed to register sensor (%ld)\n",
88+ PTR_ERR(thermal_zone));
89+ return PTR_ERR(thermal_zone);
90+ }
91+
92+ thermal_mmio_get_temperature(sensor, &temperature);
93+ dev_info(&pdev->dev,
94+ "thermal mmio sensor %s registered, current temperature: %d\n",
95+ pdev->name, temperature);
96+
97+ return 0;
98+}
99+
100+static int al_thermal_init(struct platform_device *pdev,
101+ struct thermal_mmio *sensor)
102+{
103+ sensor->read_mmio = thermal_mmio_readb;
104+ sensor->mask = 0xff;
105+ sensor->factor = 1000;
106+
107+ return 0;
108+}
109+
110+static const struct of_device_id thermal_mmio_id_table[] = {
111+ { .compatible = "amazon,al-thermal", .data = al_thermal_init},
112+ {}
113+};
114+MODULE_DEVICE_TABLE(of, thermal_mmio_id_table);
115+
116+static struct platform_driver thermal_mmio_driver = {
117+ .probe = thermal_mmio_probe,
118+ .driver = {
119+ .name = "thermal-mmio",
120+ .owner = THIS_MODULE,
121+ .of_match_table = of_match_ptr(thermal_mmio_id_table),
122+ },
123+};
124+
125+module_platform_driver(thermal_mmio_driver);
126+
127+MODULE_AUTHOR("Talel Shenhar <talel@amazon.com>");
128+MODULE_DESCRIPTION("Thermal MMIO Driver");
129+MODULE_LICENSE("GPL v2");
include/dt-bindings/thermal/tegra124-soctherm.h+4−4
@@ -12,9 +12,9 @@ · 11 unmodified lines
1212 #define TEGRA124_SOCTHERM_SENSOR_PLLX 3
1313 #define TEGRA124_SOCTHERM_SENSOR_NUM 4
1414
15−#define TEGRA_SOCTHERM_THROT_LEVEL_LOW 0
16−#define TEGRA_SOCTHERM_THROT_LEVEL_MED 1
17−#define TEGRA_SOCTHERM_THROT_LEVEL_HIGH 2
18−#define TEGRA_SOCTHERM_THROT_LEVEL_NONE -1
15+#define TEGRA_SOCTHERM_THROT_LEVEL_NONE 0
16+#define TEGRA_SOCTHERM_THROT_LEVEL_LOW 1
17+#define TEGRA_SOCTHERM_THROT_LEVEL_MED 2
18+#define TEGRA_SOCTHERM_THROT_LEVEL_HIGH 3
1919
2020 #endif
include/linux/thermal.h+13−0
@@ -447,6 +447,11 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *, void *, · 446 unmodified lines
447447 struct thermal_cooling_device *
448448 thermal_of_cooling_device_register(struct device_node *np, char *, void *,
449449 const struct thermal_cooling_device_ops *);
450+struct thermal_cooling_device *
451+devm_thermal_of_cooling_device_register(struct device *dev,
452+ struct device_node *np,
453+ char *type, void *devdata,
454+ const struct thermal_cooling_device_ops *ops);
450455 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
451456 struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
452457 int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
@@ -503,6 +508,14 @@ static inline struct thermal_cooling_device * · 50 unmodified lines
503508 thermal_of_cooling_device_register(struct device_node *np,
504509 char *type, void *devdata, const struct thermal_cooling_device_ops *ops)
505510 { return ERR_PTR(-ENODEV); }
511+static inline struct thermal_cooling_device *
512+devm_thermal_of_cooling_device_register(struct device *dev,
513+ struct device_node *np,
514+ char *type, void *devdata,
515+ const struct thermal_cooling_device_ops *ops)
516+{
517+ return ERR_PTR(-ENODEV);
518+}
506519 static inline void thermal_cooling_device_unregister(
507520 struct thermal_cooling_device *cdev)
508521 { }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t