diff options
22 files changed, 890 insertions, 267 deletions
diff --git a/Documentation/devicetree/bindings/thermal/qoriq-thermal.txt b/Documentation/devicetree/bindings/thermal/qoriq-thermal.txt index 66223d561972..20ca4ef9d776 100644 --- a/Documentation/devicetree/bindings/thermal/qoriq-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/qoriq-thermal.txt | |||
| @@ -17,6 +17,12 @@ Required properties: | |||
| 17 | calibration data, as specified by the SoC reference manual. | 17 | calibration data, as specified by the SoC reference manual. |
| 18 | The first cell of each pair is the value to be written to TTCFGR, | 18 | The first cell of each pair is the value to be written to TTCFGR, |
| 19 | and the second is the value to be written to TSCFGR. | 19 | and the second is the value to be written to TSCFGR. |
| 20 | - #thermal-sensor-cells : Must be 1. The sensor specifier is the monitoring | ||
| 21 | site ID, and represents the "n" in TRITSRn and TRATSRn. | ||
| 22 | |||
| 23 | Optional property: | ||
| 24 | - little-endian : If present, the TMU registers are little endian. If absent, | ||
| 25 | the default is big endian. | ||
| 20 | 26 | ||
| 21 | Example: | 27 | Example: |
| 22 | 28 | ||
| @@ -60,4 +66,5 @@ tmu@f0000 { | |||
| 60 | 66 | ||
| 61 | 0x00030000 0x00000012 | 67 | 0x00030000 0x00000012 |
| 62 | 0x00030001 0x0000001d>; | 68 | 0x00030001 0x0000001d>; |
| 69 | #thermal-sensor-cells = <1>; | ||
| 63 | }; | 70 | }; |
diff --git a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt new file mode 100644 index 000000000000..07a9713ae6a7 --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | * DT bindings for Renesas R-Car Gen3 Thermal Sensor driver | ||
| 2 | |||
| 3 | On R-Car Gen3 SoCs, the thermal sensor controllers (TSC) control the thermal | ||
| 4 | sensors (THS) which are the analog circuits for measuring temperature (Tj) | ||
| 5 | inside the LSI. | ||
| 6 | |||
| 7 | Required properties: | ||
| 8 | - compatible : "renesas,<soctype>-thermal", | ||
| 9 | Examples with soctypes are: | ||
| 10 | - "renesas,r8a7795-thermal" (R-Car H3) | ||
| 11 | - "renesas,r8a7796-thermal" (R-Car M3-W) | ||
| 12 | - reg : Address ranges of the thermal registers. Each sensor | ||
| 13 | needs one address range. Sorting must be done in | ||
| 14 | increasing order according to datasheet, i.e. | ||
| 15 | TSC1, TSC2, ... | ||
| 16 | - clocks : Must contain a reference to the functional clock. | ||
| 17 | - #thermal-sensor-cells : must be <1>. | ||
| 18 | |||
| 19 | Optional properties: | ||
| 20 | |||
| 21 | - interrupts : interrupts routed to the TSC (3 for H3 and M3-W) | ||
| 22 | - power-domain : Must contain a reference to the power domain. This | ||
| 23 | property is mandatory if the thermal sensor instance | ||
| 24 | is part of a controllable power domain. | ||
| 25 | |||
| 26 | Example: | ||
| 27 | |||
| 28 | tsc: thermal@e6198000 { | ||
| 29 | compatible = "renesas,r8a7795-thermal"; | ||
| 30 | reg = <0 0xe6198000 0 0x68>, | ||
| 31 | <0 0xe61a0000 0 0x5c>, | ||
| 32 | <0 0xe61a8000 0 0x5c>; | ||
| 33 | interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, | ||
| 34 | <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>, | ||
| 35 | <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; | ||
| 36 | clocks = <&cpg CPG_MOD 522>; | ||
| 37 | power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; | ||
| 38 | #thermal-sensor-cells = <1>; | ||
| 39 | status = "okay"; | ||
| 40 | }; | ||
| 41 | |||
| 42 | thermal-zones { | ||
| 43 | sensor_thermal1: sensor-thermal1 { | ||
| 44 | polling-delay-passive = <250>; | ||
| 45 | polling-delay = <1000>; | ||
| 46 | thermal-sensors = <&tsc 0>; | ||
| 47 | |||
| 48 | trips { | ||
| 49 | sensor1_crit: sensor1-crit { | ||
| 50 | temperature = <90000>; | ||
| 51 | hysteresis = <2000>; | ||
| 52 | type = "critical"; | ||
| 53 | }; | ||
| 54 | }; | ||
| 55 | }; | ||
| 56 | }; | ||
diff --git a/Documentation/devicetree/bindings/thermal/zx2967-thermal.txt b/Documentation/devicetree/bindings/thermal/zx2967-thermal.txt new file mode 100644 index 000000000000..3dc1c6bf0478 --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/zx2967-thermal.txt | |||
| @@ -0,0 +1,116 @@ | |||
| 1 | * ZTE zx2967 family Thermal | ||
| 2 | |||
| 3 | Required Properties: | ||
| 4 | - compatible: should be one of the following. | ||
| 5 | * zte,zx296718-thermal | ||
| 6 | - reg: physical base address of the controller and length of memory mapped | ||
| 7 | region. | ||
| 8 | - clocks : Pairs of phandle and specifier referencing the controller's clocks. | ||
| 9 | - clock-names: "topcrm" for the topcrm clock. | ||
| 10 | "apb" for the apb clock. | ||
| 11 | - #thermal-sensor-cells: must be 0. | ||
| 12 | |||
| 13 | Please note: slope coefficient defined in thermal-zones section need to be | ||
| 14 | multiplied by 1000. | ||
| 15 | |||
| 16 | Example for tempsensor: | ||
| 17 | |||
| 18 | tempsensor: tempsensor@148a000 { | ||
| 19 | compatible = "zte,zx296718-thermal"; | ||
| 20 | reg = <0x0148a000 0x20>; | ||
| 21 | clocks = <&topcrm TEMPSENSOR_GATE>, <&audiocrm AUDIO_TS_PCLK>; | ||
| 22 | clock-names = "topcrm", "apb"; | ||
| 23 | #thermal-sensor-cells = <0>; | ||
| 24 | }; | ||
| 25 | |||
| 26 | Example for cooling device: | ||
| 27 | |||
| 28 | cooling_dev: cooling_dev { | ||
| 29 | cluster0_cooling_dev: cluster0-cooling-dev { | ||
| 30 | #cooling-cells = <2>; | ||
| 31 | cpumask = <0xf>; | ||
| 32 | capacitance = <1500>; | ||
| 33 | }; | ||
| 34 | |||
| 35 | cluster1_cooling_dev: cluster1-cooling-dev { | ||
| 36 | #cooling-cells = <2>; | ||
| 37 | cpumask = <0x30>; | ||
| 38 | capacitance = <2000>; | ||
| 39 | }; | ||
| 40 | }; | ||
| 41 | |||
| 42 | Example for thermal zones: | ||
| 43 | |||
| 44 | thermal-zones { | ||
| 45 | zx296718_thermal: zx296718_thermal { | ||
| 46 | polling-delay-passive = <500>; | ||
| 47 | polling-delay = <1000>; | ||
| 48 | sustainable-power = <6500>; | ||
| 49 | |||
| 50 | thermal-sensors = <&tempsensor 0>; | ||
| 51 | /* | ||
| 52 | * slope need to be multiplied by 1000. | ||
| 53 | */ | ||
| 54 | coefficients = <1951 (-922)>; | ||
| 55 | |||
| 56 | trips { | ||
| 57 | trip0: switch_on_temperature { | ||
| 58 | temperature = <90000>; | ||
| 59 | hysteresis = <2000>; | ||
| 60 | type = "passive"; | ||
| 61 | }; | ||
| 62 | |||
| 63 | trip1: desired_temperature { | ||
| 64 | temperature = <100000>; | ||
| 65 | hysteresis = <2000>; | ||
| 66 | type = "passive"; | ||
| 67 | }; | ||
| 68 | |||
| 69 | crit: critical_temperature { | ||
| 70 | temperature = <110000>; | ||
| 71 | hysteresis = <2000>; | ||
| 72 | type = "critical"; | ||
| 73 | }; | ||
| 74 | }; | ||
| 75 | |||
| 76 | cooling-maps { | ||
| 77 | map0 { | ||
| 78 | trip = <&trip0>; | ||
| 79 | cooling-device = <&gpu 2 5>; | ||
| 80 | }; | ||
| 81 | |||
| 82 | map1 { | ||
| 83 | trip = <&trip0>; | ||
| 84 | cooling-device = <&cluster0_cooling_dev 1 2>; | ||
| 85 | }; | ||
| 86 | |||
| 87 | map2 { | ||
| 88 | trip = <&trip1>; | ||
| 89 | cooling-device = <&cluster0_cooling_dev 1 2>; | ||
| 90 | }; | ||
| 91 | |||
| 92 | map3 { | ||
| 93 | trip = <&crit>; | ||
| 94 | cooling-device = <&cluster0_cooling_dev 1 2>; | ||
| 95 | }; | ||
| 96 | |||
| 97 | map4 { | ||
| 98 | trip = <&trip0>; | ||
| 99 | cooling-device = <&cluster1_cooling_dev 1 2>; | ||
| 100 | contribution = <9000>; | ||
| 101 | }; | ||
| 102 | |||
| 103 | map5 { | ||
| 104 | trip = <&trip1>; | ||
| 105 | cooling-device = <&cluster1_cooling_dev 1 2>; | ||
| 106 | contribution = <4096>; | ||
| 107 | }; | ||
| 108 | |||
| 109 | map6 { | ||
| 110 | trip = <&crit>; | ||
| 111 | cooling-device = <&cluster1_cooling_dev 1 2>; | ||
| 112 | contribution = <4096>; | ||
| 113 | }; | ||
| 114 | }; | ||
| 115 | }; | ||
| 116 | }; | ||
diff --git a/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi b/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi index da2894c59479..4908af501098 100644 --- a/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi | |||
| @@ -422,7 +422,7 @@ | |||
| 422 | 0x00030001 0x0000000d | 422 | 0x00030001 0x0000000d |
| 423 | 0x00030002 0x00000019 | 423 | 0x00030002 0x00000019 |
| 424 | 0x00030003 0x00000024>; | 424 | 0x00030003 0x00000024>; |
| 425 | #thermal-sensor-cells = <0>; | 425 | #thermal-sensor-cells = <1>; |
| 426 | }; | 426 | }; |
| 427 | 427 | ||
| 428 | thermal-zones { | 428 | thermal-zones { |
| @@ -430,7 +430,7 @@ | |||
| 430 | polling-delay-passive = <1000>; | 430 | polling-delay-passive = <1000>; |
| 431 | polling-delay = <5000>; | 431 | polling-delay = <5000>; |
| 432 | 432 | ||
| 433 | thermal-sensors = <&tmu>; | 433 | thermal-sensors = <&tmu 0>; |
| 434 | 434 | ||
| 435 | trips { | 435 | trips { |
| 436 | cpu_alert: cpu-alert { | 436 | cpu_alert: cpu-alert { |
diff --git a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi index 44e399b17f6f..145c7f43b5b6 100644 --- a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi | |||
| @@ -526,7 +526,7 @@ | |||
| 526 | 526 | ||
| 527 | 0x00030000 0x00000012 | 527 | 0x00030000 0x00000012 |
| 528 | 0x00030001 0x0000001d>; | 528 | 0x00030001 0x0000001d>; |
| 529 | #thermal-sensor-cells = <0>; | 529 | #thermal-sensor-cells = <1>; |
| 530 | }; | 530 | }; |
| 531 | 531 | ||
| 532 | thermal-zones { | 532 | thermal-zones { |
| @@ -534,7 +534,7 @@ | |||
| 534 | polling-delay-passive = <1000>; | 534 | polling-delay-passive = <1000>; |
| 535 | polling-delay = <5000>; | 535 | polling-delay = <5000>; |
| 536 | 536 | ||
| 537 | thermal-sensors = <&tmu>; | 537 | thermal-sensors = <&tmu 2>; |
| 538 | 538 | ||
| 539 | trips { | 539 | trips { |
| 540 | cpu_alert: cpu-alert { | 540 | cpu_alert: cpu-alert { |
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index c2c056cc7ea5..776b34396144 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig | |||
| @@ -245,6 +245,15 @@ config RCAR_THERMAL | |||
| 245 | Enable this to plug the R-Car thermal sensor driver into the Linux | 245 | Enable this to plug the R-Car thermal sensor driver into the Linux |
| 246 | thermal framework. | 246 | thermal framework. |
| 247 | 247 | ||
| 248 | config RCAR_GEN3_THERMAL | ||
| 249 | tristate "Renesas R-Car Gen3 thermal driver" | ||
| 250 | depends on ARCH_RENESAS || COMPILE_TEST | ||
| 251 | depends on HAS_IOMEM | ||
| 252 | depends on OF | ||
| 253 | help | ||
| 254 | Enable this to plug the R-Car Gen3 thermal sensor driver into the Linux | ||
| 255 | thermal framework. | ||
| 256 | |||
| 248 | config KIRKWOOD_THERMAL | 257 | config KIRKWOOD_THERMAL |
| 249 | tristate "Temperature sensor on Marvell Kirkwood SoCs" | 258 | tristate "Temperature sensor on Marvell Kirkwood SoCs" |
| 250 | depends on MACH_KIRKWOOD || COMPILE_TEST | 259 | depends on MACH_KIRKWOOD || COMPILE_TEST |
| @@ -436,4 +445,12 @@ depends on (ARCH_QCOM && OF) || COMPILE_TEST | |||
| 436 | source "drivers/thermal/qcom/Kconfig" | 445 | source "drivers/thermal/qcom/Kconfig" |
| 437 | endmenu | 446 | endmenu |
| 438 | 447 | ||
| 448 | config ZX2967_THERMAL | ||
| 449 | tristate "Thermal sensors on zx2967 SoC" | ||
| 450 | depends on ARCH_ZX || COMPILE_TEST | ||
| 451 | help | ||
| 452 | Enable the zx2967 thermal sensors driver, which supports | ||
| 453 | the primitive temperature sensor embedded in zx2967 SoCs. | ||
| 454 | This sensor generates the real time die temperature. | ||
| 455 | |||
| 439 | endif | 456 | endif |
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 6a3d7b573036..7adae2029355 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile | |||
| @@ -31,6 +31,7 @@ obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o | |||
| 31 | obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o | 31 | obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o |
| 32 | obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o | 32 | obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o |
| 33 | obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o | 33 | obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o |
| 34 | obj-$(CONFIG_RCAR_GEN3_THERMAL) += rcar_gen3_thermal.o | ||
| 34 | obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o | 35 | obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o |
| 35 | obj-y += samsung/ | 36 | obj-y += samsung/ |
| 36 | obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o | 37 | obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o |
| @@ -56,3 +57,4 @@ obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/ | |||
| 56 | obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o | 57 | obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o |
| 57 | obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o | 58 | obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o |
| 58 | obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o | 59 | obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o |
| 60 | obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o | ||
diff --git a/drivers/thermal/clock_cooling.c b/drivers/thermal/clock_cooling.c index ed5dd0e88657..56711c25584d 100644 --- a/drivers/thermal/clock_cooling.c +++ b/drivers/thermal/clock_cooling.c | |||
| @@ -65,42 +65,7 @@ struct clock_cooling_device { | |||
| 65 | }; | 65 | }; |
| 66 | #define to_clock_cooling_device(x) \ | 66 | #define to_clock_cooling_device(x) \ |
| 67 | container_of(x, struct clock_cooling_device, clk_rate_change_nb) | 67 | container_of(x, struct clock_cooling_device, clk_rate_change_nb) |
| 68 | static DEFINE_IDR(clock_idr); | 68 | static DEFINE_IDA(clock_ida); |
| 69 | static DEFINE_MUTEX(cooling_clock_lock); | ||
| 70 | |||
| 71 | /** | ||
| 72 | * clock_cooling_get_idr - function to get an unique id. | ||
| 73 | * @id: int * value generated by this function. | ||
| 74 | * | ||
| 75 | * This function will populate @id with an unique | ||
| 76 | * id, using the idr API. | ||
| 77 | * | ||
| 78 | * Return: 0 on success, an error code on failure. | ||
| 79 | */ | ||
| 80 | static int clock_cooling_get_idr(int *id) | ||
| 81 | { | ||
| 82 | int ret; | ||
| 83 | |||
| 84 | mutex_lock(&cooling_clock_lock); | ||
| 85 | ret = idr_alloc(&clock_idr, NULL, 0, 0, GFP_KERNEL); | ||
| 86 | mutex_unlock(&cooling_clock_lock); | ||
| 87 | if (unlikely(ret < 0)) | ||
| 88 | return ret; | ||
| 89 | *id = ret; | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | /** | ||
| 95 | * release_idr - function to free the unique id. | ||
| 96 | * @id: int value representing the unique id. | ||
| 97 | */ | ||
| 98 | static void release_idr(int id) | ||
| 99 | { | ||
| 100 | mutex_lock(&cooling_clock_lock); | ||
| 101 | idr_remove(&clock_idr, id); | ||
| 102 | mutex_unlock(&cooling_clock_lock); | ||
| 103 | } | ||
| 104 | 69 | ||
| 105 | /* Below code defines functions to be used for clock as cooling device */ | 70 | /* Below code defines functions to be used for clock as cooling device */ |
| 106 | 71 | ||
| @@ -432,16 +397,17 @@ clock_cooling_register(struct device *dev, const char *clock_name) | |||
| 432 | if (IS_ERR(ccdev->clk)) | 397 | if (IS_ERR(ccdev->clk)) |
| 433 | return ERR_CAST(ccdev->clk); | 398 | return ERR_CAST(ccdev->clk); |
| 434 | 399 | ||
| 435 | ret = clock_cooling_get_idr(&ccdev->id); | 400 | ret = ida_simple_get(&clock_ida, 0, 0, GFP_KERNEL); |
| 436 | if (ret) | 401 | if (ret < 0) |
| 437 | return ERR_PTR(-EINVAL); | 402 | return ERR_PTR(ret); |
| 403 | ccdev->id = ret; | ||
| 438 | 404 | ||
| 439 | snprintf(dev_name, sizeof(dev_name), "thermal-clock-%d", ccdev->id); | 405 | snprintf(dev_name, sizeof(dev_name), "thermal-clock-%d", ccdev->id); |
| 440 | 406 | ||
| 441 | cdev = thermal_cooling_device_register(dev_name, ccdev, | 407 | cdev = thermal_cooling_device_register(dev_name, ccdev, |
| 442 | &clock_cooling_ops); | 408 | &clock_cooling_ops); |
| 443 | if (IS_ERR(cdev)) { | 409 | if (IS_ERR(cdev)) { |
| 444 | release_idr(ccdev->id); | 410 | ida_simple_remove(&clock_ida, ccdev->id); |
| 445 | return ERR_PTR(-EINVAL); | 411 | return ERR_PTR(-EINVAL); |
| 446 | } | 412 | } |
| 447 | ccdev->cdev = cdev; | 413 | ccdev->cdev = cdev; |
| @@ -450,7 +416,7 @@ clock_cooling_register(struct device *dev, const char *clock_name) | |||
| 450 | /* Assuming someone has already filled the opp table for this device */ | 416 | /* Assuming someone has already filled the opp table for this device */ |
| 451 | ret = dev_pm_opp_init_cpufreq_table(dev, &ccdev->freq_table); | 417 | ret = dev_pm_opp_init_cpufreq_table(dev, &ccdev->freq_table); |
| 452 | if (ret) { | 418 | if (ret) { |
| 453 | release_idr(ccdev->id); | 419 | ida_simple_remove(&clock_ida, ccdev->id); |
| 454 | return ERR_PTR(ret); | 420 | return ERR_PTR(ret); |
| 455 | } | 421 | } |
| 456 | ccdev->clock_state = 0; | 422 | ccdev->clock_state = 0; |
| @@ -481,6 +447,6 @@ void clock_cooling_unregister(struct thermal_cooling_device *cdev) | |||
| 481 | dev_pm_opp_free_cpufreq_table(ccdev->dev, &ccdev->freq_table); | 447 | dev_pm_opp_free_cpufreq_table(ccdev->dev, &ccdev->freq_table); |
| 482 | 448 | ||
| 483 | thermal_cooling_device_unregister(ccdev->cdev); | 449 | thermal_cooling_device_unregister(ccdev->cdev); |
| 484 | release_idr(ccdev->id); | 450 | ida_simple_remove(&clock_ida, ccdev->id); |
| 485 | } | 451 | } |
| 486 | EXPORT_SYMBOL_GPL(clock_cooling_unregister); | 452 | EXPORT_SYMBOL_GPL(clock_cooling_unregister); |
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 85fdbf762fa0..91048eeca28b 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/thermal.h> | 26 | #include <linux/thermal.h> |
| 27 | #include <linux/cpufreq.h> | 27 | #include <linux/cpufreq.h> |
| 28 | #include <linux/err.h> | 28 | #include <linux/err.h> |
| 29 | #include <linux/idr.h> | ||
| 29 | #include <linux/pm_opp.h> | 30 | #include <linux/pm_opp.h> |
| 30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
| 31 | #include <linux/cpu.h> | 32 | #include <linux/cpu.h> |
| @@ -104,50 +105,13 @@ struct cpufreq_cooling_device { | |||
| 104 | struct device *cpu_dev; | 105 | struct device *cpu_dev; |
| 105 | get_static_t plat_get_static_power; | 106 | get_static_t plat_get_static_power; |
| 106 | }; | 107 | }; |
| 107 | static DEFINE_IDR(cpufreq_idr); | 108 | static DEFINE_IDA(cpufreq_ida); |
| 108 | static DEFINE_MUTEX(cooling_cpufreq_lock); | ||
| 109 | 109 | ||
| 110 | static unsigned int cpufreq_dev_count; | 110 | static unsigned int cpufreq_dev_count; |
| 111 | 111 | ||
| 112 | static DEFINE_MUTEX(cooling_list_lock); | 112 | static DEFINE_MUTEX(cooling_list_lock); |
| 113 | static LIST_HEAD(cpufreq_dev_list); | 113 | static LIST_HEAD(cpufreq_dev_list); |
| 114 | 114 | ||
| 115 | /** | ||
| 116 | * get_idr - function to get a unique id. | ||
| 117 | * @idr: struct idr * handle used to create a id. | ||
| 118 | * @id: int * value generated by this function. | ||
| 119 | * | ||
| 120 | * This function will populate @id with an unique | ||
| 121 | * id, using the idr API. | ||
| 122 | * | ||
| 123 | * Return: 0 on success, an error code on failure. | ||
| 124 | */ | ||
| 125 | static int get_idr(struct idr *idr, int *id) | ||
| 126 | { | ||
| 127 | int ret; | ||
| 128 | |||
| 129 | mutex_lock(&cooling_cpufreq_lock); | ||
| 130 | ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL); | ||
| 131 | mutex_unlock(&cooling_cpufreq_lock); | ||
| 132 | if (unlikely(ret < 0)) | ||
| 133 | return ret; | ||
| 134 | *id = ret; | ||
| 135 | |||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | /** | ||
| 140 | * release_idr - function to free the unique id. | ||
| 141 | * @idr: struct idr * handle used for creating the id. | ||
| 142 | * @id: int value representing the unique id. | ||
| 143 | */ | ||
| 144 | static void release_idr(struct idr *idr, int id) | ||
| 145 | { | ||
| 146 | mutex_lock(&cooling_cpufreq_lock); | ||
| 147 | idr_remove(idr, id); | ||
| 148 | mutex_unlock(&cooling_cpufreq_lock); | ||
| 149 | } | ||
| 150 | |||
| 151 | /* Below code defines functions to be used for cpufreq as cooling device */ | 115 | /* Below code defines functions to be used for cpufreq as cooling device */ |
| 152 | 116 | ||
| 153 | /** | 117 | /** |
| @@ -645,31 +609,39 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev, | |||
| 645 | unsigned long state, u32 *power) | 609 | unsigned long state, u32 *power) |
| 646 | { | 610 | { |
| 647 | unsigned int freq, num_cpus; | 611 | unsigned int freq, num_cpus; |
| 648 | cpumask_t cpumask; | 612 | cpumask_var_t cpumask; |
| 649 | u32 static_power, dynamic_power; | 613 | u32 static_power, dynamic_power; |
| 650 | int ret; | 614 | int ret; |
| 651 | struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; | 615 | struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; |
| 652 | 616 | ||
| 653 | cpumask_and(&cpumask, &cpufreq_device->allowed_cpus, cpu_online_mask); | 617 | if (!alloc_cpumask_var(&cpumask, GFP_KERNEL)) |
| 654 | num_cpus = cpumask_weight(&cpumask); | 618 | return -ENOMEM; |
| 619 | |||
| 620 | cpumask_and(cpumask, &cpufreq_device->allowed_cpus, cpu_online_mask); | ||
| 621 | num_cpus = cpumask_weight(cpumask); | ||
| 655 | 622 | ||
| 656 | /* None of our cpus are online, so no power */ | 623 | /* None of our cpus are online, so no power */ |
| 657 | if (num_cpus == 0) { | 624 | if (num_cpus == 0) { |
| 658 | *power = 0; | 625 | *power = 0; |
| 659 | return 0; | 626 | ret = 0; |
| 627 | goto out; | ||
| 660 | } | 628 | } |
| 661 | 629 | ||
| 662 | freq = cpufreq_device->freq_table[state]; | 630 | freq = cpufreq_device->freq_table[state]; |
| 663 | if (!freq) | 631 | if (!freq) { |
| 664 | return -EINVAL; | 632 | ret = -EINVAL; |
| 633 | goto out; | ||
| 634 | } | ||
| 665 | 635 | ||
| 666 | dynamic_power = cpu_freq_to_power(cpufreq_device, freq) * num_cpus; | 636 | dynamic_power = cpu_freq_to_power(cpufreq_device, freq) * num_cpus; |
| 667 | ret = get_static_power(cpufreq_device, tz, freq, &static_power); | 637 | ret = get_static_power(cpufreq_device, tz, freq, &static_power); |
| 668 | if (ret) | 638 | if (ret) |
| 669 | return ret; | 639 | goto out; |
| 670 | 640 | ||
| 671 | *power = static_power + dynamic_power; | 641 | *power = static_power + dynamic_power; |
| 672 | return 0; | 642 | out: |
| 643 | free_cpumask_var(cpumask); | ||
| 644 | return ret; | ||
| 673 | } | 645 | } |
| 674 | 646 | ||
| 675 | /** | 647 | /** |
| @@ -795,16 +767,20 @@ __cpufreq_cooling_register(struct device_node *np, | |||
| 795 | struct cpufreq_cooling_device *cpufreq_dev; | 767 | struct cpufreq_cooling_device *cpufreq_dev; |
| 796 | char dev_name[THERMAL_NAME_LENGTH]; | 768 | char dev_name[THERMAL_NAME_LENGTH]; |
| 797 | struct cpufreq_frequency_table *pos, *table; | 769 | struct cpufreq_frequency_table *pos, *table; |
| 798 | struct cpumask temp_mask; | 770 | cpumask_var_t temp_mask; |
| 799 | unsigned int freq, i, num_cpus; | 771 | unsigned int freq, i, num_cpus; |
| 800 | int ret; | 772 | int ret; |
| 801 | struct thermal_cooling_device_ops *cooling_ops; | 773 | struct thermal_cooling_device_ops *cooling_ops; |
| 802 | 774 | ||
| 803 | cpumask_and(&temp_mask, clip_cpus, cpu_online_mask); | 775 | if (!alloc_cpumask_var(&temp_mask, GFP_KERNEL)) |
| 804 | policy = cpufreq_cpu_get(cpumask_first(&temp_mask)); | 776 | return ERR_PTR(-ENOMEM); |
| 777 | |||
| 778 | cpumask_and(temp_mask, clip_cpus, cpu_online_mask); | ||
| 779 | policy = cpufreq_cpu_get(cpumask_first(temp_mask)); | ||
| 805 | if (!policy) { | 780 | if (!policy) { |
| 806 | pr_debug("%s: CPUFreq policy not found\n", __func__); | 781 | pr_debug("%s: CPUFreq policy not found\n", __func__); |
| 807 | return ERR_PTR(-EPROBE_DEFER); | 782 | cool_dev = ERR_PTR(-EPROBE_DEFER); |
| 783 | goto free_cpumask; | ||
| 808 | } | 784 | } |
| 809 | 785 | ||
| 810 | table = policy->freq_table; | 786 | table = policy->freq_table; |
| @@ -867,11 +843,12 @@ __cpufreq_cooling_register(struct device_node *np, | |||
| 867 | cooling_ops = &cpufreq_cooling_ops; | 843 | cooling_ops = &cpufreq_cooling_ops; |
| 868 | } | 844 | } |
| 869 | 845 | ||
| 870 | ret = get_idr(&cpufreq_idr, &cpufreq_dev->id); | 846 | ret = ida_simple_get(&cpufreq_ida, 0, 0, GFP_KERNEL); |
| 871 | if (ret) { | 847 | if (ret < 0) { |
| 872 | cool_dev = ERR_PTR(ret); | 848 | cool_dev = ERR_PTR(ret); |
| 873 | goto free_power_table; | 849 | goto free_power_table; |
| 874 | } | 850 | } |
| 851 | cpufreq_dev->id = ret; | ||
| 875 | 852 | ||
| 876 | /* Fill freq-table in descending order of frequencies */ | 853 | /* Fill freq-table in descending order of frequencies */ |
| 877 | for (i = 0, freq = -1; i <= cpufreq_dev->max_level; i++) { | 854 | for (i = 0, freq = -1; i <= cpufreq_dev->max_level; i++) { |
| @@ -891,27 +868,24 @@ __cpufreq_cooling_register(struct device_node *np, | |||
| 891 | cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev, | 868 | cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev, |
| 892 | cooling_ops); | 869 | cooling_ops); |
| 893 | if (IS_ERR(cool_dev)) | 870 | if (IS_ERR(cool_dev)) |
| 894 | goto remove_idr; | 871 | goto remove_ida; |
| 895 | 872 | ||
| 896 | cpufreq_dev->clipped_freq = cpufreq_dev->freq_table[0]; | 873 | cpufreq_dev->clipped_freq = cpufreq_dev->freq_table[0]; |
| 897 | cpufreq_dev->cool_dev = cool_dev; | 874 | cpufreq_dev->cool_dev = cool_dev; |
| 898 | 875 | ||
| 899 | mutex_lock(&cooling_cpufreq_lock); | ||
| 900 | |||
| 901 | mutex_lock(&cooling_list_lock); | 876 | mutex_lock(&cooling_list_lock); |
| 902 | list_add(&cpufreq_dev->node, &cpufreq_dev_list); | 877 | list_add(&cpufreq_dev->node, &cpufreq_dev_list); |
| 903 | mutex_unlock(&cooling_list_lock); | ||
| 904 | 878 | ||
| 905 | /* Register the notifier for first cpufreq cooling device */ | 879 | /* Register the notifier for first cpufreq cooling device */ |
| 906 | if (!cpufreq_dev_count++) | 880 | if (!cpufreq_dev_count++) |
| 907 | cpufreq_register_notifier(&thermal_cpufreq_notifier_block, | 881 | cpufreq_register_notifier(&thermal_cpufreq_notifier_block, |
| 908 | CPUFREQ_POLICY_NOTIFIER); | 882 | CPUFREQ_POLICY_NOTIFIER); |
| 909 | mutex_unlock(&cooling_cpufreq_lock); | 883 | mutex_unlock(&cooling_list_lock); |
| 910 | 884 | ||
| 911 | goto put_policy; | 885 | goto put_policy; |
| 912 | 886 | ||
| 913 | remove_idr: | 887 | remove_ida: |
| 914 | release_idr(&cpufreq_idr, cpufreq_dev->id); | 888 | ida_simple_remove(&cpufreq_ida, cpufreq_dev->id); |
| 915 | free_power_table: | 889 | free_power_table: |
| 916 | kfree(cpufreq_dev->dyn_power_table); | 890 | kfree(cpufreq_dev->dyn_power_table); |
| 917 | free_table: | 891 | free_table: |
| @@ -924,7 +898,8 @@ free_cdev: | |||
| 924 | kfree(cpufreq_dev); | 898 | kfree(cpufreq_dev); |
| 925 | put_policy: | 899 | put_policy: |
| 926 | cpufreq_cpu_put(policy); | 900 | cpufreq_cpu_put(policy); |
| 927 | 901 | free_cpumask: | |
| 902 | free_cpumask_var(temp_mask); | ||
| 928 | return cool_dev; | 903 | return cool_dev; |
| 929 | } | 904 | } |
| 930 | 905 | ||
| @@ -1052,20 +1027,17 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) | |||
| 1052 | 1027 | ||
| 1053 | cpufreq_dev = cdev->devdata; | 1028 | cpufreq_dev = cdev->devdata; |
| 1054 | 1029 | ||
| 1030 | mutex_lock(&cooling_list_lock); | ||
| 1055 | /* Unregister the notifier for the last cpufreq cooling device */ | 1031 | /* Unregister the notifier for the last cpufreq cooling device */ |
| 1056 | mutex_lock(&cooling_cpufreq_lock); | ||
| 1057 | if (!--cpufreq_dev_count) | 1032 | if (!--cpufreq_dev_count) |
| 1058 | cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block, | 1033 | cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block, |
| 1059 | CPUFREQ_POLICY_NOTIFIER); | 1034 | CPUFREQ_POLICY_NOTIFIER); |
| 1060 | 1035 | ||
| 1061 | mutex_lock(&cooling_list_lock); | ||
| 1062 | list_del(&cpufreq_dev->node); | 1036 | list_del(&cpufreq_dev->node); |
| 1063 | mutex_unlock(&cooling_list_lock); | 1037 | mutex_unlock(&cooling_list_lock); |
| 1064 | 1038 | ||
| 1065 | mutex_unlock(&cooling_cpufreq_lock); | ||
| 1066 | |||
| 1067 | thermal_cooling_device_unregister(cpufreq_dev->cool_dev); | 1039 | thermal_cooling_device_unregister(cpufreq_dev->cool_dev); |
| 1068 | release_idr(&cpufreq_idr, cpufreq_dev->id); | 1040 | ida_simple_remove(&cpufreq_ida, cpufreq_dev->id); |
| 1069 | kfree(cpufreq_dev->dyn_power_table); | 1041 | kfree(cpufreq_dev->dyn_power_table); |
| 1070 | kfree(cpufreq_dev->time_in_idle_timestamp); | 1042 | kfree(cpufreq_dev->time_in_idle_timestamp); |
| 1071 | kfree(cpufreq_dev->time_in_idle); | 1043 | kfree(cpufreq_dev->time_in_idle); |
diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c index ba7a5cd994dc..7743a78d4723 100644 --- a/drivers/thermal/devfreq_cooling.c +++ b/drivers/thermal/devfreq_cooling.c | |||
| @@ -21,14 +21,14 @@ | |||
| 21 | #include <linux/devfreq.h> | 21 | #include <linux/devfreq.h> |
| 22 | #include <linux/devfreq_cooling.h> | 22 | #include <linux/devfreq_cooling.h> |
| 23 | #include <linux/export.h> | 23 | #include <linux/export.h> |
| 24 | #include <linux/idr.h> | ||
| 24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 25 | #include <linux/pm_opp.h> | 26 | #include <linux/pm_opp.h> |
| 26 | #include <linux/thermal.h> | 27 | #include <linux/thermal.h> |
| 27 | 28 | ||
| 28 | #include <trace/events/thermal.h> | 29 | #include <trace/events/thermal.h> |
| 29 | 30 | ||
| 30 | static DEFINE_MUTEX(devfreq_lock); | 31 | static DEFINE_IDA(devfreq_ida); |
| 31 | static DEFINE_IDR(devfreq_idr); | ||
| 32 | 32 | ||
| 33 | /** | 33 | /** |
| 34 | * struct devfreq_cooling_device - Devfreq cooling device | 34 | * struct devfreq_cooling_device - Devfreq cooling device |
| @@ -58,42 +58,6 @@ struct devfreq_cooling_device { | |||
| 58 | }; | 58 | }; |
| 59 | 59 | ||
| 60 | /** | 60 | /** |
| 61 | * get_idr - function to get a unique id. | ||
| 62 | * @idr: struct idr * handle used to create a id. | ||
| 63 | * @id: int * value generated by this function. | ||
| 64 | * | ||
| 65 | * This function will populate @id with an unique | ||
| 66 | * id, using the idr API. | ||
| 67 | * | ||
| 68 | * Return: 0 on success, an error code on failure. | ||
| 69 | */ | ||
| 70 | static int get_idr(struct idr *idr, int *id) | ||
| 71 | { | ||
| 72 | int ret; | ||
| 73 | |||
| 74 | mutex_lock(&devfreq_lock); | ||
| 75 | ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL); | ||
| 76 | mutex_unlock(&devfreq_lock); | ||
| 77 | if (unlikely(ret < 0)) | ||
| 78 | return ret; | ||
| 79 | *id = ret; | ||
| 80 | |||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | |||
| 84 | /** | ||
| 85 | * release_idr - function to free the unique id. | ||
| 86 | * @idr: struct idr * handle used for creating the id. | ||
| 87 | * @id: int value representing the unique id. | ||
| 88 | */ | ||
| 89 | static void release_idr(struct idr *idr, int id) | ||
| 90 | { | ||
| 91 | mutex_lock(&devfreq_lock); | ||
| 92 | idr_remove(idr, id); | ||
| 93 | mutex_unlock(&devfreq_lock); | ||
| 94 | } | ||
| 95 | |||
| 96 | /** | ||
| 97 | * partition_enable_opps() - disable all opps above a given state | 61 | * partition_enable_opps() - disable all opps above a given state |
| 98 | * @dfc: Pointer to devfreq we are operating on | 62 | * @dfc: Pointer to devfreq we are operating on |
| 99 | * @cdev_state: cooling device state we're setting | 63 | * @cdev_state: cooling device state we're setting |
| @@ -489,9 +453,10 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, | |||
| 489 | if (err) | 453 | if (err) |
| 490 | goto free_dfc; | 454 | goto free_dfc; |
| 491 | 455 | ||
| 492 | err = get_idr(&devfreq_idr, &dfc->id); | 456 | err = ida_simple_get(&devfreq_ida, 0, 0, GFP_KERNEL); |
| 493 | if (err) | 457 | if (err < 0) |
| 494 | goto free_tables; | 458 | goto free_tables; |
| 459 | dfc->id = err; | ||
| 495 | 460 | ||
| 496 | snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id); | 461 | snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id); |
| 497 | 462 | ||
| @@ -502,15 +467,15 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, | |||
| 502 | dev_err(df->dev.parent, | 467 | dev_err(df->dev.parent, |
| 503 | "Failed to register devfreq cooling device (%d)\n", | 468 | "Failed to register devfreq cooling device (%d)\n", |
| 504 | err); | 469 | err); |
| 505 | goto release_idr; | 470 | goto release_ida; |
| 506 | } | 471 | } |
| 507 | 472 | ||
| 508 | dfc->cdev = cdev; | 473 | dfc->cdev = cdev; |
| 509 | 474 | ||
| 510 | return cdev; | 475 | return cdev; |
| 511 | 476 | ||
| 512 | release_idr: | 477 | release_ida: |
| 513 | release_idr(&devfreq_idr, dfc->id); | 478 | ida_simple_remove(&devfreq_ida, dfc->id); |
| 514 | free_tables: | 479 | free_tables: |
| 515 | kfree(dfc->power_table); | 480 | kfree(dfc->power_table); |
| 516 | kfree(dfc->freq_table); | 481 | kfree(dfc->freq_table); |
| @@ -558,7 +523,7 @@ void devfreq_cooling_unregister(struct thermal_cooling_device *cdev) | |||
| 558 | dfc = cdev->devdata; | 523 | dfc = cdev->devdata; |
| 559 | 524 | ||
| 560 | thermal_cooling_device_unregister(dfc->cdev); | 525 | thermal_cooling_device_unregister(dfc->cdev); |
| 561 | release_idr(&devfreq_idr, dfc->id); | 526 | ida_simple_remove(&devfreq_ida, dfc->id); |
| 562 | kfree(dfc->power_table); | 527 | kfree(dfc->power_table); |
| 563 | kfree(dfc->freq_table); | 528 | kfree(dfc->freq_table); |
| 564 | 529 | ||
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 06912f0602b7..fb648a45754e 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c | |||
| @@ -489,6 +489,10 @@ static int imx_thermal_probe(struct platform_device *pdev) | |||
| 489 | data->tempmon = map; | 489 | data->tempmon = map; |
| 490 | 490 | ||
| 491 | data->socdata = of_device_get_match_data(&pdev->dev); | 491 | data->socdata = of_device_get_match_data(&pdev->dev); |
| 492 | if (!data->socdata) { | ||
| 493 | dev_err(&pdev->dev, "no device match found\n"); | ||
| 494 | return -ENODEV; | ||
| 495 | } | ||
| 492 | 496 | ||
| 493 | /* make sure the IRQ flag is clear before enabling irq on i.MX6SX */ | 497 | /* make sure the IRQ flag is clear before enabling irq on i.MX6SX */ |
| 494 | if (data->socdata->version == TEMPMON_IMX6SX) { | 498 | if (data->socdata->version == TEMPMON_IMX6SX) { |
diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c index df64692e9e64..a47103a659fa 100644 --- a/drivers/thermal/intel_powerclamp.c +++ b/drivers/thermal/intel_powerclamp.c | |||
| @@ -461,16 +461,13 @@ static void poll_pkg_cstate(struct work_struct *dummy) | |||
| 461 | { | 461 | { |
| 462 | static u64 msr_last; | 462 | static u64 msr_last; |
| 463 | static u64 tsc_last; | 463 | static u64 tsc_last; |
| 464 | static unsigned long jiffies_last; | ||
| 465 | 464 | ||
| 466 | u64 msr_now; | 465 | u64 msr_now; |
| 467 | unsigned long jiffies_now; | ||
| 468 | u64 tsc_now; | 466 | u64 tsc_now; |
| 469 | u64 val64; | 467 | u64 val64; |
| 470 | 468 | ||
| 471 | msr_now = pkg_state_counter(); | 469 | msr_now = pkg_state_counter(); |
| 472 | tsc_now = rdtsc(); | 470 | tsc_now = rdtsc(); |
| 473 | jiffies_now = jiffies; | ||
| 474 | 471 | ||
| 475 | /* calculate pkg cstate vs tsc ratio */ | 472 | /* calculate pkg cstate vs tsc ratio */ |
| 476 | if (!msr_last || !tsc_last) | 473 | if (!msr_last || !tsc_last) |
| @@ -485,7 +482,6 @@ static void poll_pkg_cstate(struct work_struct *dummy) | |||
| 485 | 482 | ||
| 486 | /* update record */ | 483 | /* update record */ |
| 487 | msr_last = msr_now; | 484 | msr_last = msr_now; |
| 488 | jiffies_last = jiffies_now; | ||
| 489 | tsc_last = tsc_now; | 485 | tsc_last = tsc_now; |
| 490 | 486 | ||
| 491 | if (true == clamping) | 487 | if (true == clamping) |
diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index 34169c32d495..1aff7fde54b1 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c | |||
| @@ -183,37 +183,37 @@ struct mtk_thermal { | |||
| 183 | }; | 183 | }; |
| 184 | 184 | ||
| 185 | /* MT8173 thermal sensor data */ | 185 | /* MT8173 thermal sensor data */ |
| 186 | const int mt8173_bank_data[MT8173_NUM_ZONES][3] = { | 186 | static const int mt8173_bank_data[MT8173_NUM_ZONES][3] = { |
| 187 | { MT8173_TS2, MT8173_TS3 }, | 187 | { MT8173_TS2, MT8173_TS3 }, |
| 188 | { MT8173_TS2, MT8173_TS4 }, | 188 | { MT8173_TS2, MT8173_TS4 }, |
| 189 | { MT8173_TS1, MT8173_TS2, MT8173_TSABB }, | 189 | { MT8173_TS1, MT8173_TS2, MT8173_TSABB }, |
| 190 | { MT8173_TS2 }, | 190 | { MT8173_TS2 }, |
| 191 | }; | 191 | }; |
| 192 | 192 | ||
| 193 | const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = { | 193 | static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = { |
| 194 | TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR2 | 194 | TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR2 |
| 195 | }; | 195 | }; |
| 196 | 196 | ||
| 197 | const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = { | 197 | static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = { |
| 198 | TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3 | 198 | TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3 |
| 199 | }; | 199 | }; |
| 200 | 200 | ||
| 201 | const int mt8173_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 }; | 201 | static const int mt8173_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 }; |
| 202 | 202 | ||
| 203 | /* MT2701 thermal sensor data */ | 203 | /* MT2701 thermal sensor data */ |
| 204 | const int mt2701_bank_data[MT2701_NUM_SENSORS] = { | 204 | static const int mt2701_bank_data[MT2701_NUM_SENSORS] = { |
| 205 | MT2701_TS1, MT2701_TS2, MT2701_TSABB | 205 | MT2701_TS1, MT2701_TS2, MT2701_TSABB |
| 206 | }; | 206 | }; |
| 207 | 207 | ||
| 208 | const int mt2701_msr[MT2701_NUM_SENSORS_PER_ZONE] = { | 208 | static const int mt2701_msr[MT2701_NUM_SENSORS_PER_ZONE] = { |
| 209 | TEMP_MSR0, TEMP_MSR1, TEMP_MSR2 | 209 | TEMP_MSR0, TEMP_MSR1, TEMP_MSR2 |
| 210 | }; | 210 | }; |
| 211 | 211 | ||
| 212 | const int mt2701_adcpnp[MT2701_NUM_SENSORS_PER_ZONE] = { | 212 | static const int mt2701_adcpnp[MT2701_NUM_SENSORS_PER_ZONE] = { |
| 213 | TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2 | 213 | TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2 |
| 214 | }; | 214 | }; |
| 215 | 215 | ||
| 216 | const int mt2701_mux_values[MT2701_NUM_SENSORS] = { 0, 1, 16 }; | 216 | static const int mt2701_mux_values[MT2701_NUM_SENSORS] = { 0, 1, 16 }; |
| 217 | 217 | ||
| 218 | /** | 218 | /** |
| 219 | * The MT8173 thermal controller has four banks. Each bank can read up to | 219 | * The MT8173 thermal controller has four banks. Each bank can read up to |
diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c new file mode 100644 index 000000000000..d33c845244b1 --- /dev/null +++ b/drivers/thermal/rcar_gen3_thermal.c | |||
| @@ -0,0 +1,335 @@ | |||
| 1 | /* | ||
| 2 | * R-Car Gen3 THS thermal sensor driver | ||
| 3 | * Based on rcar_thermal.c and work from Hien Dang and Khiem Nguyen. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2016 Renesas Electronics Corporation. | ||
| 6 | * Copyright (C) 2016 Sang Engineering | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; version 2 of the License. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, but | ||
| 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * General Public License for more details. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | #include <linux/delay.h> | ||
| 19 | #include <linux/err.h> | ||
| 20 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/io.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/mutex.h> | ||
| 24 | #include <linux/of_device.h> | ||
| 25 | #include <linux/platform_device.h> | ||
| 26 | #include <linux/pm_runtime.h> | ||
| 27 | #include <linux/thermal.h> | ||
| 28 | |||
| 29 | /* Register offsets */ | ||
| 30 | #define REG_GEN3_IRQSTR 0x04 | ||
| 31 | #define REG_GEN3_IRQMSK 0x08 | ||
| 32 | #define REG_GEN3_IRQCTL 0x0C | ||
| 33 | #define REG_GEN3_IRQEN 0x10 | ||
| 34 | #define REG_GEN3_IRQTEMP1 0x14 | ||
| 35 | #define REG_GEN3_IRQTEMP2 0x18 | ||
| 36 | #define REG_GEN3_IRQTEMP3 0x1C | ||
| 37 | #define REG_GEN3_CTSR 0x20 | ||
| 38 | #define REG_GEN3_THCTR 0x20 | ||
| 39 | #define REG_GEN3_TEMP 0x28 | ||
| 40 | #define REG_GEN3_THCODE1 0x50 | ||
| 41 | #define REG_GEN3_THCODE2 0x54 | ||
| 42 | #define REG_GEN3_THCODE3 0x58 | ||
| 43 | |||
| 44 | /* CTSR bits */ | ||
| 45 | #define CTSR_PONM BIT(8) | ||
| 46 | #define CTSR_AOUT BIT(7) | ||
| 47 | #define CTSR_THBGR BIT(5) | ||
| 48 | #define CTSR_VMEN BIT(4) | ||
| 49 | #define CTSR_VMST BIT(1) | ||
| 50 | #define CTSR_THSST BIT(0) | ||
| 51 | |||
| 52 | /* THCTR bits */ | ||
| 53 | #define THCTR_PONM BIT(6) | ||
| 54 | #define THCTR_THSST BIT(0) | ||
| 55 | |||
| 56 | #define CTEMP_MASK 0xFFF | ||
| 57 | |||
| 58 | #define MCELSIUS(temp) ((temp) * 1000) | ||
| 59 | #define GEN3_FUSE_MASK 0xFFF | ||
| 60 | |||
| 61 | #define TSC_MAX_NUM 3 | ||
| 62 | |||
| 63 | /* Structure for thermal temperature calculation */ | ||
| 64 | struct equation_coefs { | ||
| 65 | int a1; | ||
| 66 | int b1; | ||
| 67 | int a2; | ||
| 68 | int b2; | ||
| 69 | }; | ||
| 70 | |||
| 71 | struct rcar_gen3_thermal_tsc { | ||
| 72 | void __iomem *base; | ||
| 73 | struct thermal_zone_device *zone; | ||
| 74 | struct equation_coefs coef; | ||
| 75 | struct mutex lock; | ||
| 76 | }; | ||
| 77 | |||
| 78 | struct rcar_gen3_thermal_priv { | ||
| 79 | struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM]; | ||
| 80 | }; | ||
| 81 | |||
| 82 | struct rcar_gen3_thermal_data { | ||
| 83 | void (*thermal_init)(struct rcar_gen3_thermal_tsc *tsc); | ||
| 84 | }; | ||
| 85 | |||
| 86 | static inline u32 rcar_gen3_thermal_read(struct rcar_gen3_thermal_tsc *tsc, | ||
| 87 | u32 reg) | ||
| 88 | { | ||
| 89 | return ioread32(tsc->base + reg); | ||
| 90 | } | ||
| 91 | |||
| 92 | static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc, | ||
| 93 | u32 reg, u32 data) | ||
| 94 | { | ||
| 95 | iowrite32(data, tsc->base + reg); | ||
| 96 | } | ||
| 97 | |||
| 98 | /* | ||
| 99 | * Linear approximation for temperature | ||
| 100 | * | ||
| 101 | * [reg] = [temp] * a + b => [temp] = ([reg] - b) / a | ||
| 102 | * | ||
| 103 | * The constants a and b are calculated using two triplets of int values PTAT | ||
| 104 | * and THCODE. PTAT and THCODE can either be read from hardware or use hard | ||
| 105 | * coded values from driver. The formula to calculate a and b are taken from | ||
| 106 | * BSP and sparsely documented and understood. | ||
| 107 | * | ||
| 108 | * Examining the linear formula and the formula used to calculate constants a | ||
| 109 | * and b while knowing that the span for PTAT and THCODE values are between | ||
| 110 | * 0x000 and 0xfff the largest integer possible is 0xfff * 0xfff == 0xffe001. | ||
| 111 | * Integer also needs to be signed so that leaves 7 bits for binary | ||
| 112 | * fixed point scaling. | ||
| 113 | */ | ||
| 114 | |||
| 115 | #define FIXPT_SHIFT 7 | ||
| 116 | #define FIXPT_INT(_x) ((_x) << FIXPT_SHIFT) | ||
| 117 | #define FIXPT_DIV(_a, _b) DIV_ROUND_CLOSEST(((_a) << FIXPT_SHIFT), (_b)) | ||
| 118 | #define FIXPT_TO_MCELSIUS(_x) ((_x) * 1000 >> FIXPT_SHIFT) | ||
| 119 | |||
| 120 | #define RCAR3_THERMAL_GRAN 500 /* mili Celsius */ | ||
| 121 | |||
| 122 | /* no idea where these constants come from */ | ||
| 123 | #define TJ_1 96 | ||
| 124 | #define TJ_3 -41 | ||
| 125 | |||
| 126 | static void rcar_gen3_thermal_calc_coefs(struct equation_coefs *coef, | ||
| 127 | int *ptat, int *thcode) | ||
| 128 | { | ||
| 129 | int tj_2; | ||
| 130 | |||
| 131 | /* TODO: Find documentation and document constant calculation formula */ | ||
| 132 | |||
| 133 | /* | ||
| 134 | * Division is not scaled in BSP and if scaled it might overflow | ||
| 135 | * the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled | ||
| 136 | */ | ||
| 137 | tj_2 = (FIXPT_INT((ptat[1] - ptat[2]) * 137) | ||
| 138 | / (ptat[0] - ptat[2])) - FIXPT_INT(41); | ||
| 139 | |||
| 140 | coef->a1 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[2]), | ||
| 141 | tj_2 - FIXPT_INT(TJ_3)); | ||
| 142 | coef->b1 = FIXPT_INT(thcode[2]) - coef->a1 * TJ_3; | ||
| 143 | |||
| 144 | coef->a2 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[0]), | ||
| 145 | tj_2 - FIXPT_INT(TJ_1)); | ||
| 146 | coef->b2 = FIXPT_INT(thcode[0]) - coef->a2 * TJ_1; | ||
| 147 | } | ||
| 148 | |||
| 149 | static int rcar_gen3_thermal_round(int temp) | ||
| 150 | { | ||
| 151 | int result, round_offs; | ||
| 152 | |||
| 153 | round_offs = temp >= 0 ? RCAR3_THERMAL_GRAN / 2 : | ||
| 154 | -RCAR3_THERMAL_GRAN / 2; | ||
| 155 | result = (temp + round_offs) / RCAR3_THERMAL_GRAN; | ||
| 156 | return result * RCAR3_THERMAL_GRAN; | ||
| 157 | } | ||
| 158 | |||
| 159 | static int rcar_gen3_thermal_get_temp(void *devdata, int *temp) | ||
| 160 | { | ||
| 161 | struct rcar_gen3_thermal_tsc *tsc = devdata; | ||
| 162 | int mcelsius, val1, val2; | ||
| 163 | u32 reg; | ||
| 164 | |||
| 165 | /* Read register and convert to mili Celsius */ | ||
| 166 | mutex_lock(&tsc->lock); | ||
| 167 | |||
| 168 | reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK; | ||
| 169 | |||
| 170 | val1 = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1, tsc->coef.a1); | ||
| 171 | val2 = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b2, tsc->coef.a2); | ||
| 172 | mcelsius = FIXPT_TO_MCELSIUS((val1 + val2) / 2); | ||
| 173 | |||
| 174 | mutex_unlock(&tsc->lock); | ||
| 175 | |||
| 176 | /* Make sure we are inside specifications */ | ||
| 177 | if ((mcelsius < MCELSIUS(-40)) || (mcelsius > MCELSIUS(125))) | ||
| 178 | return -EIO; | ||
| 179 | |||
| 180 | /* Round value to device granularity setting */ | ||
| 181 | *temp = rcar_gen3_thermal_round(mcelsius); | ||
| 182 | |||
| 183 | return 0; | ||
| 184 | } | ||
| 185 | |||
| 186 | static struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = { | ||
| 187 | .get_temp = rcar_gen3_thermal_get_temp, | ||
| 188 | }; | ||
| 189 | |||
| 190 | static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc) | ||
| 191 | { | ||
| 192 | rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR); | ||
| 193 | rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, 0x0); | ||
| 194 | |||
| 195 | usleep_range(1000, 2000); | ||
| 196 | |||
| 197 | rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_PONM); | ||
| 198 | rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F); | ||
| 199 | rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, | ||
| 200 | CTSR_PONM | CTSR_AOUT | CTSR_THBGR | CTSR_VMEN); | ||
| 201 | |||
| 202 | usleep_range(100, 200); | ||
| 203 | |||
| 204 | rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, | ||
| 205 | CTSR_PONM | CTSR_AOUT | CTSR_THBGR | CTSR_VMEN | | ||
| 206 | CTSR_VMST | CTSR_THSST); | ||
| 207 | |||
| 208 | usleep_range(1000, 2000); | ||
| 209 | } | ||
| 210 | |||
| 211 | static void r8a7796_thermal_init(struct rcar_gen3_thermal_tsc *tsc) | ||
| 212 | { | ||
| 213 | u32 reg_val; | ||
| 214 | |||
| 215 | reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR); | ||
| 216 | reg_val &= ~THCTR_PONM; | ||
| 217 | rcar_gen3_thermal_write(tsc, REG_GEN3_THCTR, reg_val); | ||
| 218 | |||
| 219 | usleep_range(1000, 2000); | ||
| 220 | |||
| 221 | rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F); | ||
| 222 | reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR); | ||
| 223 | reg_val |= THCTR_THSST; | ||
| 224 | rcar_gen3_thermal_write(tsc, REG_GEN3_THCTR, reg_val); | ||
| 225 | } | ||
| 226 | |||
| 227 | static const struct rcar_gen3_thermal_data r8a7795_data = { | ||
| 228 | .thermal_init = r8a7795_thermal_init, | ||
| 229 | }; | ||
| 230 | |||
| 231 | static const struct rcar_gen3_thermal_data r8a7796_data = { | ||
| 232 | .thermal_init = r8a7796_thermal_init, | ||
| 233 | }; | ||
| 234 | |||
| 235 | static const struct of_device_id rcar_gen3_thermal_dt_ids[] = { | ||
| 236 | { .compatible = "renesas,r8a7795-thermal", .data = &r8a7795_data}, | ||
| 237 | { .compatible = "renesas,r8a7796-thermal", .data = &r8a7796_data}, | ||
| 238 | {}, | ||
| 239 | }; | ||
| 240 | MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids); | ||
| 241 | |||
| 242 | static int rcar_gen3_thermal_remove(struct platform_device *pdev) | ||
| 243 | { | ||
| 244 | struct device *dev = &pdev->dev; | ||
| 245 | |||
| 246 | pm_runtime_put(dev); | ||
| 247 | pm_runtime_disable(dev); | ||
| 248 | |||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 252 | static int rcar_gen3_thermal_probe(struct platform_device *pdev) | ||
| 253 | { | ||
| 254 | struct rcar_gen3_thermal_priv *priv; | ||
| 255 | struct device *dev = &pdev->dev; | ||
| 256 | struct resource *res; | ||
| 257 | struct thermal_zone_device *zone; | ||
| 258 | int ret, i; | ||
| 259 | const struct rcar_gen3_thermal_data *match_data = | ||
| 260 | of_device_get_match_data(dev); | ||
| 261 | |||
| 262 | /* default values if FUSEs are missing */ | ||
| 263 | /* TODO: Read values from hardware on supported platforms */ | ||
| 264 | int ptat[3] = { 2351, 1509, 435 }; | ||
| 265 | int thcode[TSC_MAX_NUM][3] = { | ||
| 266 | { 3248, 2800, 2221 }, | ||
| 267 | { 3245, 2795, 2216 }, | ||
| 268 | { 3250, 2805, 2237 }, | ||
| 269 | }; | ||
| 270 | |||
| 271 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
| 272 | if (!priv) | ||
| 273 | return -ENOMEM; | ||
| 274 | |||
| 275 | platform_set_drvdata(pdev, priv); | ||
| 276 | |||
| 277 | pm_runtime_enable(dev); | ||
| 278 | pm_runtime_get_sync(dev); | ||
| 279 | |||
| 280 | for (i = 0; i < TSC_MAX_NUM; i++) { | ||
| 281 | struct rcar_gen3_thermal_tsc *tsc; | ||
| 282 | |||
| 283 | tsc = devm_kzalloc(dev, sizeof(*tsc), GFP_KERNEL); | ||
| 284 | if (!tsc) { | ||
| 285 | ret = -ENOMEM; | ||
| 286 | goto error_unregister; | ||
| 287 | } | ||
| 288 | |||
| 289 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
| 290 | if (!res) | ||
| 291 | break; | ||
| 292 | |||
| 293 | tsc->base = devm_ioremap_resource(dev, res); | ||
| 294 | if (IS_ERR(tsc->base)) { | ||
| 295 | ret = PTR_ERR(tsc->base); | ||
| 296 | goto error_unregister; | ||
| 297 | } | ||
| 298 | |||
| 299 | priv->tscs[i] = tsc; | ||
| 300 | mutex_init(&tsc->lock); | ||
| 301 | |||
| 302 | match_data->thermal_init(tsc); | ||
| 303 | rcar_gen3_thermal_calc_coefs(&tsc->coef, ptat, thcode[i]); | ||
| 304 | |||
| 305 | zone = devm_thermal_zone_of_sensor_register(dev, i, tsc, | ||
| 306 | &rcar_gen3_tz_of_ops); | ||
| 307 | if (IS_ERR(zone)) { | ||
| 308 | dev_err(dev, "Can't register thermal zone\n"); | ||
| 309 | ret = PTR_ERR(zone); | ||
| 310 | goto error_unregister; | ||
| 311 | } | ||
| 312 | tsc->zone = zone; | ||
| 313 | } | ||
| 314 | |||
| 315 | return 0; | ||
| 316 | |||
| 317 | error_unregister: | ||
| 318 | rcar_gen3_thermal_remove(pdev); | ||
| 319 | |||
| 320 | return ret; | ||
| 321 | } | ||
| 322 | |||
| 323 | static struct platform_driver rcar_gen3_thermal_driver = { | ||
| 324 | .driver = { | ||
| 325 | .name = "rcar_gen3_thermal", | ||
| 326 | .of_match_table = rcar_gen3_thermal_dt_ids, | ||
| 327 | }, | ||
| 328 | .probe = rcar_gen3_thermal_probe, | ||
| 329 | .remove = rcar_gen3_thermal_remove, | ||
| 330 | }; | ||
| 331 | module_platform_driver(rcar_gen3_thermal_driver); | ||
| 332 | |||
| 333 | MODULE_LICENSE("GPL v2"); | ||
| 334 | MODULE_DESCRIPTION("R-Car Gen3 THS thermal sensor driver"); | ||
| 335 | MODULE_AUTHOR("Wolfram Sang <wsa+renesas@sang-engineering.com>"); | ||
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index ad1186dd6132..7b8ef09d2b3c 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c | |||
| @@ -1168,7 +1168,6 @@ static int exynos_of_sensor_conf(struct device_node *np, | |||
| 1168 | pdata->default_temp_offset = (u8)value; | 1168 | pdata->default_temp_offset = (u8)value; |
| 1169 | 1169 | ||
| 1170 | of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type); | 1170 | of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type); |
| 1171 | of_property_read_u32(np, "samsung,tmu_cal_mode", &pdata->cal_mode); | ||
| 1172 | 1171 | ||
| 1173 | of_node_put(np); | 1172 | of_node_put(np); |
| 1174 | return 0; | 1173 | return 0; |
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index 440c7140b660..5149c2a3030c 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h | |||
| @@ -70,7 +70,6 @@ struct exynos_tmu_platform_data { | |||
| 70 | 70 | ||
| 71 | enum soc_type type; | 71 | enum soc_type type; |
| 72 | u32 cal_type; | 72 | u32 cal_type; |
| 73 | u32 cal_mode; | ||
| 74 | }; | 73 | }; |
| 75 | 74 | ||
| 76 | #endif /* _EXYNOS_TMU_H */ | 75 | #endif /* _EXYNOS_TMU_H */ |
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 655591316a88..11f0675cb7e5 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c | |||
| @@ -36,9 +36,8 @@ MODULE_AUTHOR("Zhang Rui"); | |||
| 36 | MODULE_DESCRIPTION("Generic thermal management sysfs support"); | 36 | MODULE_DESCRIPTION("Generic thermal management sysfs support"); |
| 37 | MODULE_LICENSE("GPL v2"); | 37 | MODULE_LICENSE("GPL v2"); |
| 38 | 38 | ||
| 39 | static DEFINE_IDR(thermal_tz_idr); | 39 | static DEFINE_IDA(thermal_tz_ida); |
| 40 | static DEFINE_IDR(thermal_cdev_idr); | 40 | static DEFINE_IDA(thermal_cdev_ida); |
| 41 | static DEFINE_MUTEX(thermal_idr_lock); | ||
| 42 | 41 | ||
| 43 | static LIST_HEAD(thermal_tz_list); | 42 | static LIST_HEAD(thermal_tz_list); |
| 44 | static LIST_HEAD(thermal_cdev_list); | 43 | static LIST_HEAD(thermal_cdev_list); |
| @@ -589,29 +588,6 @@ void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz, | |||
| 589 | * - thermal zone devices lifecycle: registration, unregistration, | 588 | * - thermal zone devices lifecycle: registration, unregistration, |
| 590 | * binding, and unbinding. | 589 | * binding, and unbinding. |
| 591 | */ | 590 | */ |
| 592 | static int get_idr(struct idr *idr, struct mutex *lock, int *id) | ||
| 593 | { | ||
| 594 | int ret; | ||
| 595 | |||
| 596 | if (lock) | ||
| 597 | mutex_lock(lock); | ||
| 598 | ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL); | ||
| 599 | if (lock) | ||
| 600 | mutex_unlock(lock); | ||
| 601 | if (unlikely(ret < 0)) | ||
| 602 | return ret; | ||
| 603 | *id = ret; | ||
| 604 | return 0; | ||
| 605 | } | ||
| 606 | |||
| 607 | static void release_idr(struct idr *idr, struct mutex *lock, int id) | ||
| 608 | { | ||
| 609 | if (lock) | ||
| 610 | mutex_lock(lock); | ||
| 611 | idr_remove(idr, id); | ||
| 612 | if (lock) | ||
| 613 | mutex_unlock(lock); | ||
| 614 | } | ||
| 615 | 591 | ||
| 616 | /** | 592 | /** |
| 617 | * thermal_zone_bind_cooling_device() - bind a cooling device to a thermal zone | 593 | * thermal_zone_bind_cooling_device() - bind a cooling device to a thermal zone |
| @@ -685,15 +661,16 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | |||
| 685 | dev->target = THERMAL_NO_TARGET; | 661 | dev->target = THERMAL_NO_TARGET; |
| 686 | dev->weight = weight; | 662 | dev->weight = weight; |
| 687 | 663 | ||
| 688 | result = get_idr(&tz->idr, &tz->lock, &dev->id); | 664 | result = ida_simple_get(&tz->ida, 0, 0, GFP_KERNEL); |
| 689 | if (result) | 665 | if (result < 0) |
| 690 | goto free_mem; | 666 | goto free_mem; |
| 691 | 667 | ||
| 668 | dev->id = result; | ||
| 692 | sprintf(dev->name, "cdev%d", dev->id); | 669 | sprintf(dev->name, "cdev%d", dev->id); |
| 693 | result = | 670 | result = |
| 694 | sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name); | 671 | sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name); |
| 695 | if (result) | 672 | if (result) |
| 696 | goto release_idr; | 673 | goto release_ida; |
| 697 | 674 | ||
| 698 | sprintf(dev->attr_name, "cdev%d_trip_point", dev->id); | 675 | sprintf(dev->attr_name, "cdev%d_trip_point", dev->id); |
| 699 | sysfs_attr_init(&dev->attr.attr); | 676 | sysfs_attr_init(&dev->attr.attr); |
| @@ -737,8 +714,8 @@ remove_trip_file: | |||
| 737 | device_remove_file(&tz->device, &dev->attr); | 714 | device_remove_file(&tz->device, &dev->attr); |
| 738 | remove_symbol_link: | 715 | remove_symbol_link: |
| 739 | sysfs_remove_link(&tz->device.kobj, dev->name); | 716 | sysfs_remove_link(&tz->device.kobj, dev->name); |
| 740 | release_idr: | 717 | release_ida: |
| 741 | release_idr(&tz->idr, &tz->lock, dev->id); | 718 | ida_simple_remove(&tz->ida, dev->id); |
| 742 | free_mem: | 719 | free_mem: |
| 743 | kfree(dev); | 720 | kfree(dev); |
| 744 | return result; | 721 | return result; |
| @@ -785,7 +762,7 @@ unbind: | |||
| 785 | device_remove_file(&tz->device, &pos->weight_attr); | 762 | device_remove_file(&tz->device, &pos->weight_attr); |
| 786 | device_remove_file(&tz->device, &pos->attr); | 763 | device_remove_file(&tz->device, &pos->attr); |
| 787 | sysfs_remove_link(&tz->device.kobj, pos->name); | 764 | sysfs_remove_link(&tz->device.kobj, pos->name); |
| 788 | release_idr(&tz->idr, &tz->lock, pos->id); | 765 | ida_simple_remove(&tz->ida, pos->id); |
| 789 | kfree(pos); | 766 | kfree(pos); |
| 790 | return 0; | 767 | return 0; |
| 791 | } | 768 | } |
| @@ -925,12 +902,13 @@ __thermal_cooling_device_register(struct device_node *np, | |||
| 925 | if (!cdev) | 902 | if (!cdev) |
| 926 | return ERR_PTR(-ENOMEM); | 903 | return ERR_PTR(-ENOMEM); |
| 927 | 904 | ||
| 928 | result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id); | 905 | result = ida_simple_get(&thermal_cdev_ida, 0, 0, GFP_KERNEL); |
| 929 | if (result) { | 906 | if (result < 0) { |
| 930 | kfree(cdev); | 907 | kfree(cdev); |
| 931 | return ERR_PTR(result); | 908 | return ERR_PTR(result); |
| 932 | } | 909 | } |
| 933 | 910 | ||
| 911 | cdev->id = result; | ||
| 934 | strlcpy(cdev->type, type ? : "", sizeof(cdev->type)); | 912 | strlcpy(cdev->type, type ? : "", sizeof(cdev->type)); |
| 935 | mutex_init(&cdev->lock); | 913 | mutex_init(&cdev->lock); |
| 936 | INIT_LIST_HEAD(&cdev->thermal_instances); | 914 | INIT_LIST_HEAD(&cdev->thermal_instances); |
| @@ -943,7 +921,7 @@ __thermal_cooling_device_register(struct device_node *np, | |||
| 943 | dev_set_name(&cdev->device, "cooling_device%d", cdev->id); | 921 | dev_set_name(&cdev->device, "cooling_device%d", cdev->id); |
| 944 | result = device_register(&cdev->device); | 922 | result = device_register(&cdev->device); |
| 945 | if (result) { | 923 | if (result) { |
| 946 | release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); | 924 | ida_simple_remove(&thermal_cdev_ida, cdev->id); |
| 947 | kfree(cdev); | 925 | kfree(cdev); |
| 948 | return ERR_PTR(result); | 926 | return ERR_PTR(result); |
| 949 | } | 927 | } |
| @@ -1070,7 +1048,7 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev) | |||
| 1070 | 1048 | ||
| 1071 | mutex_unlock(&thermal_list_lock); | 1049 | mutex_unlock(&thermal_list_lock); |
| 1072 | 1050 | ||
| 1073 | release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); | 1051 | ida_simple_remove(&thermal_cdev_ida, cdev->id); |
| 1074 | device_unregister(&cdev->device); | 1052 | device_unregister(&cdev->device); |
| 1075 | } | 1053 | } |
| 1076 | EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister); | 1054 | EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister); |
| @@ -1172,14 +1150,15 @@ thermal_zone_device_register(const char *type, int trips, int mask, | |||
| 1172 | return ERR_PTR(-ENOMEM); | 1150 | return ERR_PTR(-ENOMEM); |
| 1173 | 1151 | ||
| 1174 | INIT_LIST_HEAD(&tz->thermal_instances); | 1152 | INIT_LIST_HEAD(&tz->thermal_instances); |
| 1175 | idr_init(&tz->idr); | 1153 | ida_init(&tz->ida); |
| 1176 | mutex_init(&tz->lock); | 1154 | mutex_init(&tz->lock); |
| 1177 | result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id); | 1155 | result = ida_simple_get(&thermal_tz_ida, 0, 0, GFP_KERNEL); |
| 1178 | if (result) { | 1156 | if (result < 0) { |
| 1179 | kfree(tz); | 1157 | kfree(tz); |
| 1180 | return ERR_PTR(result); | 1158 | return ERR_PTR(result); |
| 1181 | } | 1159 | } |
| 1182 | 1160 | ||
| 1161 | tz->id = result; | ||
| 1183 | strlcpy(tz->type, type, sizeof(tz->type)); | 1162 | strlcpy(tz->type, type, sizeof(tz->type)); |
| 1184 | tz->ops = ops; | 1163 | tz->ops = ops; |
| 1185 | tz->tzp = tzp; | 1164 | tz->tzp = tzp; |
| @@ -1201,7 +1180,7 @@ thermal_zone_device_register(const char *type, int trips, int mask, | |||
| 1201 | dev_set_name(&tz->device, "thermal_zone%d", tz->id); | 1180 | dev_set_name(&tz->device, "thermal_zone%d", tz->id); |
| 1202 | result = device_register(&tz->device); | 1181 | result = device_register(&tz->device); |
| 1203 | if (result) { | 1182 | if (result) { |
| 1204 | release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); | 1183 | ida_simple_remove(&thermal_tz_ida, tz->id); |
| 1205 | kfree(tz); | 1184 | kfree(tz); |
| 1206 | return ERR_PTR(result); | 1185 | return ERR_PTR(result); |
| 1207 | } | 1186 | } |
| @@ -1255,7 +1234,7 @@ thermal_zone_device_register(const char *type, int trips, int mask, | |||
| 1255 | return tz; | 1234 | return tz; |
| 1256 | 1235 | ||
| 1257 | unregister: | 1236 | unregister: |
| 1258 | release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); | 1237 | ida_simple_remove(&thermal_tz_ida, tz->id); |
| 1259 | device_unregister(&tz->device); | 1238 | device_unregister(&tz->device); |
| 1260 | return ERR_PTR(result); | 1239 | return ERR_PTR(result); |
| 1261 | } | 1240 | } |
| @@ -1313,8 +1292,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) | |||
| 1313 | thermal_set_governor(tz, NULL); | 1292 | thermal_set_governor(tz, NULL); |
| 1314 | 1293 | ||
| 1315 | thermal_remove_hwmon_sysfs(tz); | 1294 | thermal_remove_hwmon_sysfs(tz); |
| 1316 | release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); | 1295 | ida_simple_remove(&thermal_tz_ida, tz->id); |
| 1317 | idr_destroy(&tz->idr); | 1296 | ida_destroy(&tz->ida); |
| 1318 | mutex_destroy(&tz->lock); | 1297 | mutex_destroy(&tz->lock); |
| 1319 | device_unregister(&tz->device); | 1298 | device_unregister(&tz->device); |
| 1320 | } | 1299 | } |
| @@ -1514,9 +1493,8 @@ unregister_class: | |||
| 1514 | unregister_governors: | 1493 | unregister_governors: |
| 1515 | thermal_unregister_governors(); | 1494 | thermal_unregister_governors(); |
| 1516 | error: | 1495 | error: |
| 1517 | idr_destroy(&thermal_tz_idr); | 1496 | ida_destroy(&thermal_tz_ida); |
| 1518 | idr_destroy(&thermal_cdev_idr); | 1497 | ida_destroy(&thermal_cdev_ida); |
| 1519 | mutex_destroy(&thermal_idr_lock); | ||
| 1520 | mutex_destroy(&thermal_list_lock); | 1498 | mutex_destroy(&thermal_list_lock); |
| 1521 | mutex_destroy(&thermal_governor_lock); | 1499 | mutex_destroy(&thermal_governor_lock); |
| 1522 | return result; | 1500 | return result; |
| @@ -1529,9 +1507,8 @@ static void __exit thermal_exit(void) | |||
| 1529 | genetlink_exit(); | 1507 | genetlink_exit(); |
| 1530 | class_unregister(&thermal_class); | 1508 | class_unregister(&thermal_class); |
| 1531 | thermal_unregister_governors(); | 1509 | thermal_unregister_governors(); |
| 1532 | idr_destroy(&thermal_tz_idr); | 1510 | ida_destroy(&thermal_tz_ida); |
| 1533 | idr_destroy(&thermal_cdev_idr); | 1511 | ida_destroy(&thermal_cdev_ida); |
| 1534 | mutex_destroy(&thermal_idr_lock); | ||
| 1535 | mutex_destroy(&thermal_list_lock); | 1512 | mutex_destroy(&thermal_list_lock); |
| 1536 | mutex_destroy(&thermal_governor_lock); | 1513 | mutex_destroy(&thermal_governor_lock); |
| 1537 | } | 1514 | } |
diff --git a/drivers/thermal/ti-soc-thermal/Kconfig b/drivers/thermal/ti-soc-thermal/Kconfig index ea8283f08aa6..fe0e877f84d0 100644 --- a/drivers/thermal/ti-soc-thermal/Kconfig +++ b/drivers/thermal/ti-soc-thermal/Kconfig | |||
| @@ -11,7 +11,6 @@ config TI_SOC_THERMAL | |||
| 11 | config TI_THERMAL | 11 | config TI_THERMAL |
| 12 | bool "Texas Instruments SoCs thermal framework support" | 12 | bool "Texas Instruments SoCs thermal framework support" |
| 13 | depends on TI_SOC_THERMAL | 13 | depends on TI_SOC_THERMAL |
| 14 | depends on CPU_THERMAL | ||
| 15 | help | 14 | help |
| 16 | If you say yes here you want to get support for generic thermal | 15 | If you say yes here you want to get support for generic thermal |
| 17 | framework for the Texas Instruments on die bandgap temperature sensor. | 16 | framework for the Texas Instruments on die bandgap temperature sensor. |
diff --git a/drivers/thermal/ti-soc-thermal/dra752-bandgap.h b/drivers/thermal/ti-soc-thermal/dra752-bandgap.h index 6b0f2b1160f7..a31e4b5e82cd 100644 --- a/drivers/thermal/ti-soc-thermal/dra752-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/dra752-bandgap.h | |||
| @@ -54,7 +54,6 @@ | |||
| 54 | #define DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET 0x8 | 54 | #define DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET 0x8 |
| 55 | #define DRA752_TEMP_SENSOR_CORE_OFFSET 0x154 | 55 | #define DRA752_TEMP_SENSOR_CORE_OFFSET 0x154 |
| 56 | #define DRA752_BANDGAP_THRESHOLD_CORE_OFFSET 0x1ac | 56 | #define DRA752_BANDGAP_THRESHOLD_CORE_OFFSET 0x1ac |
| 57 | #define DRA752_BANDGAP_TSHUT_CORE_OFFSET 0x1b8 | ||
| 58 | #define DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET 0x1c4 | 57 | #define DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET 0x1c4 |
| 59 | #define DRA752_DTEMP_CORE_0_OFFSET 0x208 | 58 | #define DRA752_DTEMP_CORE_0_OFFSET 0x208 |
| 60 | #define DRA752_DTEMP_CORE_1_OFFSET 0x20c | 59 | #define DRA752_DTEMP_CORE_1_OFFSET 0x20c |
| @@ -66,7 +65,6 @@ | |||
| 66 | #define DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET 0x388 | 65 | #define DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET 0x388 |
| 67 | #define DRA752_TEMP_SENSOR_IVA_OFFSET 0x398 | 66 | #define DRA752_TEMP_SENSOR_IVA_OFFSET 0x398 |
| 68 | #define DRA752_BANDGAP_THRESHOLD_IVA_OFFSET 0x3a4 | 67 | #define DRA752_BANDGAP_THRESHOLD_IVA_OFFSET 0x3a4 |
| 69 | #define DRA752_BANDGAP_TSHUT_IVA_OFFSET 0x3ac | ||
| 70 | #define DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET 0x3b4 | 68 | #define DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET 0x3b4 |
| 71 | #define DRA752_DTEMP_IVA_0_OFFSET 0x3d0 | 69 | #define DRA752_DTEMP_IVA_0_OFFSET 0x3d0 |
| 72 | #define DRA752_DTEMP_IVA_1_OFFSET 0x3d4 | 70 | #define DRA752_DTEMP_IVA_1_OFFSET 0x3d4 |
| @@ -78,7 +76,6 @@ | |||
| 78 | #define DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET 0x4 | 76 | #define DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET 0x4 |
| 79 | #define DRA752_TEMP_SENSOR_MPU_OFFSET 0x14c | 77 | #define DRA752_TEMP_SENSOR_MPU_OFFSET 0x14c |
| 80 | #define DRA752_BANDGAP_THRESHOLD_MPU_OFFSET 0x1a4 | 78 | #define DRA752_BANDGAP_THRESHOLD_MPU_OFFSET 0x1a4 |
| 81 | #define DRA752_BANDGAP_TSHUT_MPU_OFFSET 0x1b0 | ||
| 82 | #define DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET 0x1bc | 79 | #define DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET 0x1bc |
| 83 | #define DRA752_DTEMP_MPU_0_OFFSET 0x1e0 | 80 | #define DRA752_DTEMP_MPU_0_OFFSET 0x1e0 |
| 84 | #define DRA752_DTEMP_MPU_1_OFFSET 0x1e4 | 81 | #define DRA752_DTEMP_MPU_1_OFFSET 0x1e4 |
| @@ -90,7 +87,6 @@ | |||
| 90 | #define DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET 0x384 | 87 | #define DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET 0x384 |
| 91 | #define DRA752_TEMP_SENSOR_DSPEVE_OFFSET 0x394 | 88 | #define DRA752_TEMP_SENSOR_DSPEVE_OFFSET 0x394 |
| 92 | #define DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET 0x3a0 | 89 | #define DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET 0x3a0 |
| 93 | #define DRA752_BANDGAP_TSHUT_DSPEVE_OFFSET 0x3a8 | ||
| 94 | #define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET 0x3b0 | 90 | #define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET 0x3b0 |
| 95 | #define DRA752_DTEMP_DSPEVE_0_OFFSET 0x3bc | 91 | #define DRA752_DTEMP_DSPEVE_0_OFFSET 0x3bc |
| 96 | #define DRA752_DTEMP_DSPEVE_1_OFFSET 0x3c0 | 92 | #define DRA752_DTEMP_DSPEVE_1_OFFSET 0x3c0 |
| @@ -102,7 +98,6 @@ | |||
| 102 | #define DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET 0x0 | 98 | #define DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET 0x0 |
| 103 | #define DRA752_TEMP_SENSOR_GPU_OFFSET 0x150 | 99 | #define DRA752_TEMP_SENSOR_GPU_OFFSET 0x150 |
| 104 | #define DRA752_BANDGAP_THRESHOLD_GPU_OFFSET 0x1a8 | 100 | #define DRA752_BANDGAP_THRESHOLD_GPU_OFFSET 0x1a8 |
| 105 | #define DRA752_BANDGAP_TSHUT_GPU_OFFSET 0x1b4 | ||
| 106 | #define DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET 0x1c0 | 101 | #define DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET 0x1c0 |
| 107 | #define DRA752_DTEMP_GPU_0_OFFSET 0x1f4 | 102 | #define DRA752_DTEMP_GPU_0_OFFSET 0x1f4 |
| 108 | #define DRA752_DTEMP_GPU_1_OFFSET 0x1f8 | 103 | #define DRA752_DTEMP_GPU_1_OFFSET 0x1f8 |
| @@ -173,10 +168,6 @@ | |||
| 173 | #define DRA752_BANDGAP_THRESHOLD_HOT_MASK (0x3ff << 16) | 168 | #define DRA752_BANDGAP_THRESHOLD_HOT_MASK (0x3ff << 16) |
| 174 | #define DRA752_BANDGAP_THRESHOLD_COLD_MASK (0x3ff << 0) | 169 | #define DRA752_BANDGAP_THRESHOLD_COLD_MASK (0x3ff << 0) |
| 175 | 170 | ||
| 176 | /* DRA752.TSHUT_THRESHOLD */ | ||
| 177 | #define DRA752_TSHUT_THRESHOLD_MUXCTRL_MASK BIT(31) | ||
| 178 | #define DRA752_TSHUT_THRESHOLD_HOT_MASK (0x3ff << 16) | ||
| 179 | #define DRA752_TSHUT_THRESHOLD_COLD_MASK (0x3ff << 0) | ||
| 180 | 171 | ||
| 181 | /* DRA752.BANDGAP_CUMUL_DTEMP_CORE */ | 172 | /* DRA752.BANDGAP_CUMUL_DTEMP_CORE */ |
| 182 | #define DRA752_BANDGAP_CUMUL_DTEMP_CORE_MASK (0xffffffff << 0) | 173 | #define DRA752_BANDGAP_CUMUL_DTEMP_CORE_MASK (0xffffffff << 0) |
| @@ -216,8 +207,6 @@ | |||
| 216 | #define DRA752_GPU_MAX_TEMP 125000 | 207 | #define DRA752_GPU_MAX_TEMP 125000 |
| 217 | #define DRA752_GPU_HYST_VAL 5000 | 208 | #define DRA752_GPU_HYST_VAL 5000 |
| 218 | /* interrupts thresholds */ | 209 | /* interrupts thresholds */ |
| 219 | #define DRA752_GPU_TSHUT_HOT 915 | ||
| 220 | #define DRA752_GPU_TSHUT_COLD 900 | ||
| 221 | #define DRA752_GPU_T_HOT 800 | 210 | #define DRA752_GPU_T_HOT 800 |
| 222 | #define DRA752_GPU_T_COLD 795 | 211 | #define DRA752_GPU_T_COLD 795 |
| 223 | 212 | ||
| @@ -230,8 +219,6 @@ | |||
| 230 | #define DRA752_MPU_MAX_TEMP 125000 | 219 | #define DRA752_MPU_MAX_TEMP 125000 |
| 231 | #define DRA752_MPU_HYST_VAL 5000 | 220 | #define DRA752_MPU_HYST_VAL 5000 |
| 232 | /* interrupts thresholds */ | 221 | /* interrupts thresholds */ |
| 233 | #define DRA752_MPU_TSHUT_HOT 915 | ||
| 234 | #define DRA752_MPU_TSHUT_COLD 900 | ||
| 235 | #define DRA752_MPU_T_HOT 800 | 222 | #define DRA752_MPU_T_HOT 800 |
| 236 | #define DRA752_MPU_T_COLD 795 | 223 | #define DRA752_MPU_T_COLD 795 |
| 237 | 224 | ||
| @@ -244,8 +231,6 @@ | |||
| 244 | #define DRA752_CORE_MAX_TEMP 125000 | 231 | #define DRA752_CORE_MAX_TEMP 125000 |
| 245 | #define DRA752_CORE_HYST_VAL 5000 | 232 | #define DRA752_CORE_HYST_VAL 5000 |
| 246 | /* interrupts thresholds */ | 233 | /* interrupts thresholds */ |
| 247 | #define DRA752_CORE_TSHUT_HOT 915 | ||
| 248 | #define DRA752_CORE_TSHUT_COLD 900 | ||
| 249 | #define DRA752_CORE_T_HOT 800 | 234 | #define DRA752_CORE_T_HOT 800 |
| 250 | #define DRA752_CORE_T_COLD 795 | 235 | #define DRA752_CORE_T_COLD 795 |
| 251 | 236 | ||
| @@ -258,8 +243,6 @@ | |||
| 258 | #define DRA752_DSPEVE_MAX_TEMP 125000 | 243 | #define DRA752_DSPEVE_MAX_TEMP 125000 |
| 259 | #define DRA752_DSPEVE_HYST_VAL 5000 | 244 | #define DRA752_DSPEVE_HYST_VAL 5000 |
| 260 | /* interrupts thresholds */ | 245 | /* interrupts thresholds */ |
| 261 | #define DRA752_DSPEVE_TSHUT_HOT 915 | ||
| 262 | #define DRA752_DSPEVE_TSHUT_COLD 900 | ||
| 263 | #define DRA752_DSPEVE_T_HOT 800 | 246 | #define DRA752_DSPEVE_T_HOT 800 |
| 264 | #define DRA752_DSPEVE_T_COLD 795 | 247 | #define DRA752_DSPEVE_T_COLD 795 |
| 265 | 248 | ||
| @@ -272,8 +255,6 @@ | |||
| 272 | #define DRA752_IVA_MAX_TEMP 125000 | 255 | #define DRA752_IVA_MAX_TEMP 125000 |
| 273 | #define DRA752_IVA_HYST_VAL 5000 | 256 | #define DRA752_IVA_HYST_VAL 5000 |
| 274 | /* interrupts thresholds */ | 257 | /* interrupts thresholds */ |
| 275 | #define DRA752_IVA_TSHUT_HOT 915 | ||
| 276 | #define DRA752_IVA_TSHUT_COLD 900 | ||
| 277 | #define DRA752_IVA_T_HOT 800 | 258 | #define DRA752_IVA_T_HOT 800 |
| 278 | #define DRA752_IVA_T_COLD 795 | 259 | #define DRA752_IVA_T_COLD 795 |
| 279 | 260 | ||
diff --git a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c index 58b5c6694cd4..118d7d847715 100644 --- a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c +++ b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c | |||
| @@ -49,9 +49,6 @@ dra752_core_temp_sensor_registers = { | |||
| 49 | .bgap_threshold = DRA752_BANDGAP_THRESHOLD_CORE_OFFSET, | 49 | .bgap_threshold = DRA752_BANDGAP_THRESHOLD_CORE_OFFSET, |
| 50 | .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, | 50 | .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, |
| 51 | .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, | 51 | .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, |
| 52 | .tshut_threshold = DRA752_BANDGAP_TSHUT_CORE_OFFSET, | ||
| 53 | .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, | ||
| 54 | .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, | ||
| 55 | .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, | 52 | .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, |
| 56 | .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, | 53 | .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, |
| 57 | .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK, | 54 | .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK, |
| @@ -85,9 +82,6 @@ dra752_iva_temp_sensor_registers = { | |||
| 85 | .bgap_threshold = DRA752_BANDGAP_THRESHOLD_IVA_OFFSET, | 82 | .bgap_threshold = DRA752_BANDGAP_THRESHOLD_IVA_OFFSET, |
| 86 | .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, | 83 | .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, |
| 87 | .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, | 84 | .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, |
| 88 | .tshut_threshold = DRA752_BANDGAP_TSHUT_IVA_OFFSET, | ||
| 89 | .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, | ||
| 90 | .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, | ||
| 91 | .bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET, | 85 | .bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET, |
| 92 | .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, | 86 | .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, |
| 93 | .status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK, | 87 | .status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK, |
| @@ -121,9 +115,6 @@ dra752_mpu_temp_sensor_registers = { | |||
| 121 | .bgap_threshold = DRA752_BANDGAP_THRESHOLD_MPU_OFFSET, | 115 | .bgap_threshold = DRA752_BANDGAP_THRESHOLD_MPU_OFFSET, |
| 122 | .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, | 116 | .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, |
| 123 | .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, | 117 | .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, |
| 124 | .tshut_threshold = DRA752_BANDGAP_TSHUT_MPU_OFFSET, | ||
| 125 | .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, | ||
| 126 | .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, | ||
| 127 | .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, | 118 | .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, |
| 128 | .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, | 119 | .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, |
| 129 | .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK, | 120 | .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK, |
| @@ -157,9 +148,6 @@ dra752_dspeve_temp_sensor_registers = { | |||
| 157 | .bgap_threshold = DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET, | 148 | .bgap_threshold = DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET, |
| 158 | .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, | 149 | .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, |
| 159 | .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, | 150 | .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, |
| 160 | .tshut_threshold = DRA752_BANDGAP_TSHUT_DSPEVE_OFFSET, | ||
| 161 | .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, | ||
| 162 | .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, | ||
| 163 | .bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET, | 151 | .bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET, |
| 164 | .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, | 152 | .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, |
| 165 | .status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK, | 153 | .status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK, |
| @@ -193,9 +181,6 @@ dra752_gpu_temp_sensor_registers = { | |||
| 193 | .bgap_threshold = DRA752_BANDGAP_THRESHOLD_GPU_OFFSET, | 181 | .bgap_threshold = DRA752_BANDGAP_THRESHOLD_GPU_OFFSET, |
| 194 | .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, | 182 | .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, |
| 195 | .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, | 183 | .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, |
| 196 | .tshut_threshold = DRA752_BANDGAP_TSHUT_GPU_OFFSET, | ||
| 197 | .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, | ||
| 198 | .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, | ||
| 199 | .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, | 184 | .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, |
| 200 | .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, | 185 | .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, |
| 201 | .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK, | 186 | .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK, |
| @@ -211,8 +196,6 @@ dra752_gpu_temp_sensor_registers = { | |||
| 211 | 196 | ||
| 212 | /* Thresholds and limits for DRA752 MPU temperature sensor */ | 197 | /* Thresholds and limits for DRA752 MPU temperature sensor */ |
| 213 | static struct temp_sensor_data dra752_mpu_temp_sensor_data = { | 198 | static struct temp_sensor_data dra752_mpu_temp_sensor_data = { |
| 214 | .tshut_hot = DRA752_MPU_TSHUT_HOT, | ||
| 215 | .tshut_cold = DRA752_MPU_TSHUT_COLD, | ||
| 216 | .t_hot = DRA752_MPU_T_HOT, | 199 | .t_hot = DRA752_MPU_T_HOT, |
| 217 | .t_cold = DRA752_MPU_T_COLD, | 200 | .t_cold = DRA752_MPU_T_COLD, |
| 218 | .min_freq = DRA752_MPU_MIN_FREQ, | 201 | .min_freq = DRA752_MPU_MIN_FREQ, |
| @@ -226,8 +209,6 @@ static struct temp_sensor_data dra752_mpu_temp_sensor_data = { | |||
| 226 | 209 | ||
| 227 | /* Thresholds and limits for DRA752 GPU temperature sensor */ | 210 | /* Thresholds and limits for DRA752 GPU temperature sensor */ |
| 228 | static struct temp_sensor_data dra752_gpu_temp_sensor_data = { | 211 | static struct temp_sensor_data dra752_gpu_temp_sensor_data = { |
| 229 | .tshut_hot = DRA752_GPU_TSHUT_HOT, | ||
| 230 | .tshut_cold = DRA752_GPU_TSHUT_COLD, | ||
| 231 | .t_hot = DRA752_GPU_T_HOT, | 212 | .t_hot = DRA752_GPU_T_HOT, |
| 232 | .t_cold = DRA752_GPU_T_COLD, | 213 | .t_cold = DRA752_GPU_T_COLD, |
| 233 | .min_freq = DRA752_GPU_MIN_FREQ, | 214 | .min_freq = DRA752_GPU_MIN_FREQ, |
| @@ -241,8 +222,6 @@ static struct temp_sensor_data dra752_gpu_temp_sensor_data = { | |||
| 241 | 222 | ||
| 242 | /* Thresholds and limits for DRA752 CORE temperature sensor */ | 223 | /* Thresholds and limits for DRA752 CORE temperature sensor */ |
| 243 | static struct temp_sensor_data dra752_core_temp_sensor_data = { | 224 | static struct temp_sensor_data dra752_core_temp_sensor_data = { |
| 244 | .tshut_hot = DRA752_CORE_TSHUT_HOT, | ||
| 245 | .tshut_cold = DRA752_CORE_TSHUT_COLD, | ||
| 246 | .t_hot = DRA752_CORE_T_HOT, | 225 | .t_hot = DRA752_CORE_T_HOT, |
| 247 | .t_cold = DRA752_CORE_T_COLD, | 226 | .t_cold = DRA752_CORE_T_COLD, |
| 248 | .min_freq = DRA752_CORE_MIN_FREQ, | 227 | .min_freq = DRA752_CORE_MIN_FREQ, |
| @@ -256,8 +235,6 @@ static struct temp_sensor_data dra752_core_temp_sensor_data = { | |||
| 256 | 235 | ||
| 257 | /* Thresholds and limits for DRA752 DSPEVE temperature sensor */ | 236 | /* Thresholds and limits for DRA752 DSPEVE temperature sensor */ |
| 258 | static struct temp_sensor_data dra752_dspeve_temp_sensor_data = { | 237 | static struct temp_sensor_data dra752_dspeve_temp_sensor_data = { |
| 259 | .tshut_hot = DRA752_DSPEVE_TSHUT_HOT, | ||
| 260 | .tshut_cold = DRA752_DSPEVE_TSHUT_COLD, | ||
| 261 | .t_hot = DRA752_DSPEVE_T_HOT, | 238 | .t_hot = DRA752_DSPEVE_T_HOT, |
| 262 | .t_cold = DRA752_DSPEVE_T_COLD, | 239 | .t_cold = DRA752_DSPEVE_T_COLD, |
| 263 | .min_freq = DRA752_DSPEVE_MIN_FREQ, | 240 | .min_freq = DRA752_DSPEVE_MIN_FREQ, |
| @@ -271,8 +248,6 @@ static struct temp_sensor_data dra752_dspeve_temp_sensor_data = { | |||
| 271 | 248 | ||
| 272 | /* Thresholds and limits for DRA752 IVA temperature sensor */ | 249 | /* Thresholds and limits for DRA752 IVA temperature sensor */ |
| 273 | static struct temp_sensor_data dra752_iva_temp_sensor_data = { | 250 | static struct temp_sensor_data dra752_iva_temp_sensor_data = { |
| 274 | .tshut_hot = DRA752_IVA_TSHUT_HOT, | ||
| 275 | .tshut_cold = DRA752_IVA_TSHUT_COLD, | ||
| 276 | .t_hot = DRA752_IVA_T_HOT, | 251 | .t_hot = DRA752_IVA_T_HOT, |
| 277 | .t_cold = DRA752_IVA_T_COLD, | 252 | .t_cold = DRA752_IVA_T_COLD, |
| 278 | .min_freq = DRA752_IVA_MIN_FREQ, | 253 | .min_freq = DRA752_IVA_MIN_FREQ, |
| @@ -416,8 +391,7 @@ int dra752_adc_to_temp[DRA752_ADC_END_VALUE - DRA752_ADC_START_VALUE + 1] = { | |||
| 416 | 391 | ||
| 417 | /* DRA752 data */ | 392 | /* DRA752 data */ |
| 418 | const struct ti_bandgap_data dra752_data = { | 393 | const struct ti_bandgap_data dra752_data = { |
| 419 | .features = TI_BANDGAP_FEATURE_TSHUT_CONFIG | | 394 | .features = TI_BANDGAP_FEATURE_FREEZE_BIT | |
| 420 | TI_BANDGAP_FEATURE_FREEZE_BIT | | ||
| 421 | TI_BANDGAP_FEATURE_TALERT | | 395 | TI_BANDGAP_FEATURE_TALERT | |
| 422 | TI_BANDGAP_FEATURE_COUNTER_DELAY | | 396 | TI_BANDGAP_FEATURE_COUNTER_DELAY | |
| 423 | TI_BANDGAP_FEATURE_HISTORY_BUFFER | | 397 | TI_BANDGAP_FEATURE_HISTORY_BUFFER | |
diff --git a/drivers/thermal/zx2967_thermal.c b/drivers/thermal/zx2967_thermal.c new file mode 100644 index 000000000000..a5670ad2cfc8 --- /dev/null +++ b/drivers/thermal/zx2967_thermal.c | |||
| @@ -0,0 +1,258 @@ | |||
| 1 | /* | ||
| 2 | * ZTE's zx2967 family thermal sensor driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2017 ZTE Ltd. | ||
| 5 | * | ||
| 6 | * Author: Baoyou Xie <baoyou.xie@linaro.org> | ||
| 7 | * | ||
| 8 | * License terms: GNU General Public License (GPL) version 2 | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/clk.h> | ||
| 12 | #include <linux/device.h> | ||
| 13 | #include <linux/err.h> | ||
| 14 | #include <linux/iopoll.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/thermal.h> | ||
| 18 | |||
| 19 | /* Power Mode: 0->low 1->high */ | ||
| 20 | #define ZX2967_THERMAL_POWER_MODE 0 | ||
| 21 | #define ZX2967_POWER_MODE_LOW 0 | ||
| 22 | #define ZX2967_POWER_MODE_HIGH 1 | ||
| 23 | |||
| 24 | /* DCF Control Register */ | ||
| 25 | #define ZX2967_THERMAL_DCF 0x4 | ||
| 26 | #define ZX2967_DCF_EN BIT(1) | ||
| 27 | #define ZX2967_DCF_FREEZE BIT(0) | ||
| 28 | |||
| 29 | /* Selection Register */ | ||
| 30 | #define ZX2967_THERMAL_SEL 0x8 | ||
| 31 | |||
| 32 | /* Control Register */ | ||
| 33 | #define ZX2967_THERMAL_CTRL 0x10 | ||
| 34 | |||
| 35 | #define ZX2967_THERMAL_READY BIT(12) | ||
| 36 | #define ZX2967_THERMAL_TEMP_MASK GENMASK(11, 0) | ||
| 37 | #define ZX2967_THERMAL_ID_MASK 0x18 | ||
| 38 | #define ZX2967_THERMAL_ID 0x10 | ||
| 39 | |||
| 40 | #define ZX2967_GET_TEMP_TIMEOUT_US (100 * 1024) | ||
| 41 | |||
| 42 | /** | ||
| 43 | * struct zx2967_thermal_priv - zx2967 thermal sensor private structure | ||
| 44 | * @tzd: struct thermal_zone_device where the sensor is registered | ||
| 45 | * @lock: prevents read sensor in parallel | ||
| 46 | * @clk_topcrm: topcrm clk structure | ||
| 47 | * @clk_apb: apb clk structure | ||
| 48 | * @regs: pointer to base address of the thermal sensor | ||
| 49 | */ | ||
| 50 | |||
| 51 | struct zx2967_thermal_priv { | ||
| 52 | struct thermal_zone_device *tzd; | ||
| 53 | struct mutex lock; | ||
| 54 | struct clk *clk_topcrm; | ||
| 55 | struct clk *clk_apb; | ||
| 56 | void __iomem *regs; | ||
| 57 | struct device *dev; | ||
| 58 | }; | ||
| 59 | |||
| 60 | static int zx2967_thermal_get_temp(void *data, int *temp) | ||
| 61 | { | ||
| 62 | void __iomem *regs; | ||
| 63 | struct zx2967_thermal_priv *priv = data; | ||
| 64 | u32 val; | ||
| 65 | int ret; | ||
| 66 | |||
| 67 | if (!priv->tzd) | ||
| 68 | return -EAGAIN; | ||
| 69 | |||
| 70 | regs = priv->regs; | ||
| 71 | mutex_lock(&priv->lock); | ||
| 72 | writel_relaxed(ZX2967_POWER_MODE_LOW, | ||
| 73 | regs + ZX2967_THERMAL_POWER_MODE); | ||
| 74 | writel_relaxed(ZX2967_DCF_EN, regs + ZX2967_THERMAL_DCF); | ||
| 75 | |||
| 76 | val = readl_relaxed(regs + ZX2967_THERMAL_SEL); | ||
| 77 | val &= ~ZX2967_THERMAL_ID_MASK; | ||
| 78 | val |= ZX2967_THERMAL_ID; | ||
| 79 | writel_relaxed(val, regs + ZX2967_THERMAL_SEL); | ||
| 80 | |||
| 81 | /* | ||
| 82 | * Must wait for a while, surely it's a bit odd. | ||
| 83 | * otherwise temperature value we got has a few deviation, even if | ||
| 84 | * the THERMAL_READY bit is set. | ||
| 85 | */ | ||
| 86 | usleep_range(100, 300); | ||
| 87 | ret = readx_poll_timeout(readl, regs + ZX2967_THERMAL_CTRL, | ||
| 88 | val, val & ZX2967_THERMAL_READY, 300, | ||
| 89 | ZX2967_GET_TEMP_TIMEOUT_US); | ||
| 90 | if (ret) { | ||
| 91 | dev_err(priv->dev, "Thermal sensor data timeout\n"); | ||
| 92 | goto unlock; | ||
| 93 | } | ||
| 94 | |||
| 95 | writel_relaxed(ZX2967_DCF_FREEZE | ZX2967_DCF_EN, | ||
| 96 | regs + ZX2967_THERMAL_DCF); | ||
| 97 | val = readl_relaxed(regs + ZX2967_THERMAL_CTRL) | ||
| 98 | & ZX2967_THERMAL_TEMP_MASK; | ||
| 99 | writel_relaxed(ZX2967_POWER_MODE_HIGH, | ||
| 100 | regs + ZX2967_THERMAL_POWER_MODE); | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Calculate temperature | ||
| 104 | * In dts, slope is multiplied by 1000. | ||
| 105 | */ | ||
| 106 | *temp = DIV_ROUND_CLOSEST(((s32)val + priv->tzd->tzp->offset) * 1000, | ||
| 107 | priv->tzd->tzp->slope); | ||
| 108 | |||
| 109 | unlock: | ||
| 110 | mutex_unlock(&priv->lock); | ||
| 111 | return ret; | ||
| 112 | } | ||
| 113 | |||
| 114 | static struct thermal_zone_of_device_ops zx2967_of_thermal_ops = { | ||
| 115 | .get_temp = zx2967_thermal_get_temp, | ||
| 116 | }; | ||
| 117 | |||
| 118 | static int zx2967_thermal_probe(struct platform_device *pdev) | ||
| 119 | { | ||
| 120 | struct zx2967_thermal_priv *priv; | ||
| 121 | struct resource *res; | ||
| 122 | int ret; | ||
| 123 | |||
| 124 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
| 125 | if (!priv) | ||
| 126 | return -ENOMEM; | ||
| 127 | |||
| 128 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 129 | priv->regs = devm_ioremap_resource(&pdev->dev, res); | ||
| 130 | if (IS_ERR(priv->regs)) | ||
| 131 | return PTR_ERR(priv->regs); | ||
| 132 | |||
| 133 | priv->clk_topcrm = devm_clk_get(&pdev->dev, "topcrm"); | ||
| 134 | if (IS_ERR(priv->clk_topcrm)) { | ||
| 135 | ret = PTR_ERR(priv->clk_topcrm); | ||
| 136 | dev_err(&pdev->dev, "failed to get topcrm clock: %d\n", ret); | ||
| 137 | return ret; | ||
| 138 | } | ||
| 139 | |||
| 140 | ret = clk_prepare_enable(priv->clk_topcrm); | ||
| 141 | if (ret) { | ||
| 142 | dev_err(&pdev->dev, "failed to enable topcrm clock: %d\n", | ||
| 143 | ret); | ||
| 144 | return ret; | ||
| 145 | } | ||
| 146 | |||
| 147 | priv->clk_apb = devm_clk_get(&pdev->dev, "apb"); | ||
| 148 | if (IS_ERR(priv->clk_apb)) { | ||
| 149 | ret = PTR_ERR(priv->clk_apb); | ||
| 150 | dev_err(&pdev->dev, "failed to get apb clock: %d\n", ret); | ||
| 151 | goto disable_clk_topcrm; | ||
| 152 | } | ||
| 153 | |||
| 154 | ret = clk_prepare_enable(priv->clk_apb); | ||
| 155 | if (ret) { | ||
| 156 | dev_err(&pdev->dev, "failed to enable apb clock: %d\n", | ||
| 157 | ret); | ||
| 158 | goto disable_clk_topcrm; | ||
| 159 | } | ||
| 160 | |||
| 161 | mutex_init(&priv->lock); | ||
| 162 | priv->tzd = thermal_zone_of_sensor_register(&pdev->dev, | ||
| 163 | 0, priv, &zx2967_of_thermal_ops); | ||
| 164 | |||
| 165 | if (IS_ERR(priv->tzd)) { | ||
| 166 | ret = PTR_ERR(priv->tzd); | ||
| 167 | dev_err(&pdev->dev, "failed to register sensor: %d\n", ret); | ||
| 168 | goto disable_clk_all; | ||
| 169 | } | ||
| 170 | |||
| 171 | if (priv->tzd->tzp->slope == 0) { | ||
| 172 | thermal_zone_of_sensor_unregister(&pdev->dev, priv->tzd); | ||
| 173 | dev_err(&pdev->dev, "coefficients of sensor is invalid\n"); | ||
| 174 | ret = -EINVAL; | ||
| 175 | goto disable_clk_all; | ||
| 176 | } | ||
| 177 | |||
| 178 | priv->dev = &pdev->dev; | ||
| 179 | platform_set_drvdata(pdev, priv); | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | |||
| 183 | disable_clk_all: | ||
| 184 | clk_disable_unprepare(priv->clk_apb); | ||
| 185 | disable_clk_topcrm: | ||
| 186 | clk_disable_unprepare(priv->clk_topcrm); | ||
| 187 | return ret; | ||
| 188 | } | ||
| 189 | |||
| 190 | static int zx2967_thermal_exit(struct platform_device *pdev) | ||
| 191 | { | ||
| 192 | struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev); | ||
| 193 | |||
| 194 | thermal_zone_of_sensor_unregister(&pdev->dev, priv->tzd); | ||
| 195 | clk_disable_unprepare(priv->clk_topcrm); | ||
| 196 | clk_disable_unprepare(priv->clk_apb); | ||
| 197 | |||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | static const struct of_device_id zx2967_thermal_id_table[] = { | ||
| 202 | { .compatible = "zte,zx296718-thermal" }, | ||
| 203 | {} | ||
| 204 | }; | ||
| 205 | MODULE_DEVICE_TABLE(of, zx2967_thermal_id_table); | ||
| 206 | |||
| 207 | #ifdef CONFIG_PM_SLEEP | ||
| 208 | static int zx2967_thermal_suspend(struct device *dev) | ||
| 209 | { | ||
| 210 | struct platform_device *pdev = to_platform_device(dev); | ||
| 211 | struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev); | ||
| 212 | |||
| 213 | if (priv && priv->clk_topcrm) | ||
| 214 | clk_disable_unprepare(priv->clk_topcrm); | ||
| 215 | |||
| 216 | if (priv && priv->clk_apb) | ||
| 217 | clk_disable_unprepare(priv->clk_apb); | ||
| 218 | |||
| 219 | return 0; | ||
| 220 | } | ||
| 221 | |||
| 222 | static int zx2967_thermal_resume(struct device *dev) | ||
| 223 | { | ||
| 224 | struct platform_device *pdev = to_platform_device(dev); | ||
| 225 | struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev); | ||
| 226 | int error; | ||
| 227 | |||
| 228 | error = clk_prepare_enable(priv->clk_topcrm); | ||
| 229 | if (error) | ||
| 230 | return error; | ||
| 231 | |||
| 232 | error = clk_prepare_enable(priv->clk_apb); | ||
| 233 | if (error) { | ||
| 234 | clk_disable_unprepare(priv->clk_topcrm); | ||
| 235 | return error; | ||
| 236 | } | ||
| 237 | |||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | #endif | ||
| 241 | |||
| 242 | static SIMPLE_DEV_PM_OPS(zx2967_thermal_pm_ops, | ||
| 243 | zx2967_thermal_suspend, zx2967_thermal_resume); | ||
| 244 | |||
| 245 | static struct platform_driver zx2967_thermal_driver = { | ||
| 246 | .probe = zx2967_thermal_probe, | ||
| 247 | .remove = zx2967_thermal_exit, | ||
| 248 | .driver = { | ||
| 249 | .name = "zx2967_thermal", | ||
| 250 | .of_match_table = zx2967_thermal_id_table, | ||
| 251 | .pm = &zx2967_thermal_pm_ops, | ||
| 252 | }, | ||
| 253 | }; | ||
| 254 | module_platform_driver(zx2967_thermal_driver); | ||
| 255 | |||
| 256 | MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>"); | ||
| 257 | MODULE_DESCRIPTION("ZTE zx2967 thermal driver"); | ||
| 258 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/include/linux/thermal.h b/include/linux/thermal.h index e275e98bdceb..dab11f97e1c6 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h | |||
| @@ -194,7 +194,7 @@ struct thermal_attr { | |||
| 194 | * @governor: pointer to the governor for this thermal zone | 194 | * @governor: pointer to the governor for this thermal zone |
| 195 | * @governor_data: private pointer for governor data | 195 | * @governor_data: private pointer for governor data |
| 196 | * @thermal_instances: list of &struct thermal_instance of this thermal zone | 196 | * @thermal_instances: list of &struct thermal_instance of this thermal zone |
| 197 | * @idr: &struct idr to generate unique id for this zone's cooling | 197 | * @ida: &struct ida to generate unique id for this zone's cooling |
| 198 | * devices | 198 | * devices |
| 199 | * @lock: lock to protect thermal_instances list | 199 | * @lock: lock to protect thermal_instances list |
| 200 | * @node: node in thermal_tz_list (in thermal_core.c) | 200 | * @node: node in thermal_tz_list (in thermal_core.c) |
| @@ -227,7 +227,7 @@ struct thermal_zone_device { | |||
| 227 | struct thermal_governor *governor; | 227 | struct thermal_governor *governor; |
| 228 | void *governor_data; | 228 | void *governor_data; |
| 229 | struct list_head thermal_instances; | 229 | struct list_head thermal_instances; |
| 230 | struct idr idr; | 230 | struct ida ida; |
| 231 | struct mutex lock; | 231 | struct mutex lock; |
| 232 | struct list_head node; | 232 | struct list_head node; |
| 233 | struct delayed_work poll_queue; | 233 | struct delayed_work poll_queue; |
