diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-17 19:40:22 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-17 19:40:22 +0200 |
commit | 5a77b6a0131f7197e1a037f65fc7cbabcb4fe680 (patch) | |
tree | 78259db0fae2871b2ad6a6ec8dffe2e652a7418b | |
parent | Merge tag 'ovl-update-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff) | |
parent | thermal: core: Adding missing nlmsg_free() in thermal_genl_sampling_temp() (diff) | |
download | linux-5a77b6a0131f7197e1a037f65fc7cbabcb4fe680.tar.xz linux-5a77b6a0131f7197e1a037f65fc7cbabcb4fe680.zip |
Merge tag 'thermal-v5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux
Pull thermal updates from Daniel Lezcano:
- Fix Kconfig typo "acces" -> "access" (Colin Ian King)
- Use dev_error_probe() to simplify the error handling on imx and imx8
platforms (Anson Huang)
- Use dedicated kobj_to_dev() instead of container_of() in the sysfs
core code (Tian Tao)
- Fix coding style by adding braces to a one line conditional statement
on rcar (Geert Uytterhoeven)
- Add DT binding documentation for the r8a774e1 platform and update the
Kconfig description supporting RZ/G2 SoCs (Lad Prabhakar)
- Simplify the return expression of stm_thermal_prepare on the stm32
platform (Qinglang Miao)
- Fix the unit in the function documentation for the idle injection
cooling device (Zhuguang Qing)
- Remove an unecessary mutex_init() in the core code (Qinglang Miao)
- Add support for keep alive events in the core code and the specific
int340x (Srinivas Pandruvada)
- Remove unused thermal zone variable in devfreq and cpufreq cooling
devices (Zhuguang Qing)
- Add the A100's THS controller support (Yangtao Li)
- Add power management on the omap3's bandgap sensor (Adam Ford)
- Fix a missing nlmsg_free in the netlink core error path (Jing
Xiangfeng)
* tag 'thermal-v5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux:
thermal: core: Adding missing nlmsg_free() in thermal_genl_sampling_temp()
thermal: ti-soc-thermal: Enable addition power management
thermal: sun8i: Add A100's THS controller support
thermal: sun8i: add TEMP_CALIB_MASK for calibration data in sun50i_h6_ths_calibrate
dt-bindings: thermal: sun8i: Add binding for A100's THS controller
thermal: cooling: Remove unused variable *tz
thermal: int340x: Add keep alive response method
thermal: core: Add new event for sending keep alive notifications
thermal: int340x: Provide notification for OEM variable change
thermal: core: remove unnecessary mutex_init()
thermal/idle_inject: Fix comment of idle_duration_us and name of latency_ns
thermal: Kconfig: Update description for RCAR_GEN3_THERMAL config
thermal: stm32: simplify the return expression of stm_thermal_prepare()
dt-bindings: thermal: rcar-gen3-thermal: Add r8a774e1 support
thermal: rcar_thermal: Add missing braces to conditional statement
thermal: Use kobj_to_dev() instead of container_of()
thermal: imx8mm: Use dev_err_probe() to simplify error handling
thermal: imx: Use dev_err_probe() to simplify error handling
drivers: thermal: Kconfig: fix spelling mistake "acces" -> "access"
22 files changed, 156 insertions, 82 deletions
diff --git a/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml b/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml index 44ba6765697d..31edd051295a 100644 --- a/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml +++ b/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml @@ -17,6 +17,7 @@ properties: - allwinner,sun8i-h3-ths - allwinner,sun8i-r40-ths - allwinner,sun50i-a64-ths + - allwinner,sun50i-a100-ths - allwinner,sun50i-h5-ths - allwinner,sun50i-h6-ths @@ -61,7 +62,9 @@ allOf: properties: compatible: contains: - const: allwinner,sun50i-h6-ths + enum: + - allwinner,sun50i-a100-ths + - allwinner,sun50i-h6-ths then: properties: @@ -103,6 +106,7 @@ allOf: - const: allwinner,sun8i-h3-ths - const: allwinner,sun8i-r40-ths - const: allwinner,sun50i-a64-ths + - const: allwinner,sun50i-a100-ths - const: allwinner,sun50i-h5-ths - const: allwinner,sun50i-h6-ths diff --git a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml index b1a55ae497de..f386f2a7c06c 100644 --- a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml @@ -20,6 +20,7 @@ properties: enum: - renesas,r8a774a1-thermal # RZ/G2M - renesas,r8a774b1-thermal # RZ/G2N + - renesas,r8a774e1-thermal # RZ/G2H - renesas,r8a7795-thermal # R-Car H3 - renesas,r8a7796-thermal # R-Car M3-W - renesas,r8a77961-thermal # R-Car M3-W+ diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index b668224f906d..7edc8dc6bbab 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -346,13 +346,13 @@ config RCAR_THERMAL thermal framework. config RCAR_GEN3_THERMAL - tristate "Renesas R-Car Gen3 thermal driver" + tristate "Renesas R-Car Gen3 and RZ/G2 thermal driver" depends on ARCH_RENESAS || COMPILE_TEST depends on HAS_IOMEM depends on OF help - Enable this to plug the R-Car Gen3 thermal sensor driver into the Linux - thermal framework. + Enable this to plug the R-Car Gen3 or RZ/G2 thermal sensor driver into + the Linux thermal framework. config KIRKWOOD_THERMAL tristate "Temperature sensor on Marvell Kirkwood SoCs" diff --git a/drivers/thermal/cpufreq_cooling.c b/drivers/thermal/cpufreq_cooling.c index 6cf23a54e853..cc2959f22f01 100644 --- a/drivers/thermal/cpufreq_cooling.c +++ b/drivers/thermal/cpufreq_cooling.c @@ -182,7 +182,6 @@ static u32 get_dynamic_power(struct cpufreq_cooling_device *cpufreq_cdev, /** * cpufreq_get_requested_power() - get the current power * @cdev: &thermal_cooling_device pointer - * @tz: a valid thermal zone device pointer * @power: pointer in which to store the resulting power * * Calculate the current power consumption of the cpus in milliwatts @@ -203,7 +202,6 @@ static u32 get_dynamic_power(struct cpufreq_cooling_device *cpufreq_cdev, * Return: 0 on success, -E* if getting the static power failed. */ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, - struct thermal_zone_device *tz, u32 *power) { unsigned long freq; @@ -253,7 +251,6 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, /** * cpufreq_state2power() - convert a cpu cdev state to power consumed * @cdev: &thermal_cooling_device pointer - * @tz: a valid thermal zone device pointer * @state: cooling device state to be converted * @power: pointer in which to store the resulting power * @@ -266,7 +263,6 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, * when calculating the static power. */ static int cpufreq_state2power(struct thermal_cooling_device *cdev, - struct thermal_zone_device *tz, unsigned long state, u32 *power) { unsigned int freq, num_cpus, idx; @@ -288,7 +284,6 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev, /** * cpufreq_power2state() - convert power to a cooling device state * @cdev: &thermal_cooling_device pointer - * @tz: a valid thermal zone device pointer * @power: power in milliwatts to be converted * @state: pointer in which to store the resulting state * @@ -306,8 +301,7 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev, * device. */ static int cpufreq_power2state(struct thermal_cooling_device *cdev, - struct thermal_zone_device *tz, u32 power, - unsigned long *state) + u32 power, unsigned long *state) { unsigned int target_freq; u32 last_load, normalised_power; diff --git a/drivers/thermal/cpuidle_cooling.c b/drivers/thermal/cpuidle_cooling.c index 78e3e8238116..7ecab4b16b29 100644 --- a/drivers/thermal/cpuidle_cooling.c +++ b/drivers/thermal/cpuidle_cooling.c @@ -30,7 +30,7 @@ static DEFINE_IDA(cpuidle_ida); /** * cpuidle_cooling_runtime - Running time computation - * @idle_duration_us: the idle cooling device + * @idle_duration_us: CPU idle time to inject in microseconds * @state: a percentile based number * * The running duration is computed from the idle injection duration diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c index a12d29096229..dfab49a67252 100644 --- a/drivers/thermal/devfreq_cooling.c +++ b/drivers/thermal/devfreq_cooling.c @@ -229,7 +229,6 @@ static inline unsigned long get_total_power(struct devfreq_cooling_device *dfc, static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev, - struct thermal_zone_device *tz, u32 *power) { struct devfreq_cooling_device *dfc = cdev->devdata; @@ -289,7 +288,6 @@ fail: } static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev, - struct thermal_zone_device *tz, unsigned long state, u32 *power) { @@ -308,7 +306,6 @@ static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev, } static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev, - struct thermal_zone_device *tz, u32 power, unsigned long *state) { struct devfreq_cooling_device *dfc = cdev->devdata; diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c index 5cb518d8f156..ab0be26f0816 100644 --- a/drivers/thermal/gov_power_allocator.c +++ b/drivers/thermal/gov_power_allocator.c @@ -96,7 +96,7 @@ static u32 estimate_sustainable_power(struct thermal_zone_device *tz) if (instance->trip != params->trip_max_desired_temperature) continue; - if (power_actor_get_min_power(cdev, tz, &min_power)) + if (power_actor_get_min_power(cdev, &min_power)) continue; sustainable_power += min_power; @@ -388,7 +388,7 @@ static int allocate_power(struct thermal_zone_device *tz, if (!cdev_is_power_actor(cdev)) continue; - if (cdev->ops->get_requested_power(cdev, tz, &req_power[i])) + if (cdev->ops->get_requested_power(cdev, &req_power[i])) continue; if (!total_weight) @@ -398,7 +398,7 @@ static int allocate_power(struct thermal_zone_device *tz, weighted_req_power[i] = frac_to_int(weight * req_power[i]); - if (power_actor_get_max_power(cdev, tz, &max_power[i])) + if (power_actor_get_max_power(cdev, &max_power[i])) continue; total_req_power += req_power[i]; diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c index f5124f14cf81..a1e4f9bb4cb0 100644 --- a/drivers/thermal/imx8mm_thermal.c +++ b/drivers/thermal/imx8mm_thermal.c @@ -146,13 +146,9 @@ static int imx8mm_tmu_probe(struct platform_device *pdev) return PTR_ERR(tmu->base); tmu->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(tmu->clk)) { - ret = PTR_ERR(tmu->clk); - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "failed to get tmu clock: %d\n", ret); - return ret; - } + if (IS_ERR(tmu->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(tmu->clk), + "failed to get tmu clock\n"); ret = clk_prepare_enable(tmu->clk); if (ret) { diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 3f74ab4c1ab9..2c7473d86a59 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -716,14 +716,9 @@ static int imx_thermal_probe(struct platform_device *pdev) if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) { ret = imx_init_from_nvmem_cells(pdev); - if (ret) { - if (ret == -EPROBE_DEFER) - return ret; - - dev_err(&pdev->dev, "failed to init from nvmem: %d\n", - ret); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to init from nvmem\n"); } else { ret = imx_init_from_tempmon_data(pdev); if (ret) { @@ -746,14 +741,9 @@ static int imx_thermal_probe(struct platform_device *pdev) data->socdata->power_down_mask); ret = imx_thermal_register_legacy_cooling(data); - if (ret) { - if (ret == -EPROBE_DEFER) - return ret; - - dev_err(&pdev->dev, - "failed to register cpufreq cooling device: %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to register cpufreq cooling device\n"); data->thermal_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(data->thermal_clk)) { diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index 4f5859d4c780..0966551cbaaa 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -14,6 +14,7 @@ #define INT3400_THERMAL_TABLE_CHANGED 0x83 #define INT3400_ODVP_CHANGED 0x88 +#define INT3400_KEEP_ALIVE 0xA0 enum int3400_thermal_uuid { INT3400_THERMAL_PASSIVE_1, @@ -83,8 +84,33 @@ static struct bin_attribute *data_attributes[] = { NULL, }; +static ssize_t imok_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct int3400_thermal_priv *priv = dev_get_drvdata(dev); + acpi_status status; + int input, ret; + + ret = kstrtouint(buf, 10, &input); + if (ret) + return ret; + status = acpi_execute_simple_method(priv->adev->handle, "IMOK", input); + if (ACPI_FAILURE(status)) + return -EIO; + + return count; +} + +static DEVICE_ATTR_WO(imok); + +static struct attribute *imok_attr[] = { + &dev_attr_imok.attr, + NULL +}; + static const struct attribute_group data_attribute_group = { .bin_attrs = data_attributes, + .attrs = imok_attr, }; static ssize_t available_uuids_show(struct device *dev, @@ -349,30 +375,33 @@ static void int3400_notify(acpi_handle handle, { struct int3400_thermal_priv *priv = data; char *thermal_prop[5]; + int therm_event; if (!priv) return; switch (event) { case INT3400_THERMAL_TABLE_CHANGED: - thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s", - priv->thermal->type); - thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d", - priv->thermal->temperature); - thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP="); - thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d", - THERMAL_TABLE_CHANGED); - thermal_prop[4] = NULL; - kobject_uevent_env(&priv->thermal->device.kobj, KOBJ_CHANGE, - thermal_prop); + therm_event = THERMAL_TABLE_CHANGED; + break; + case INT3400_KEEP_ALIVE: + therm_event = THERMAL_EVENT_KEEP_ALIVE; break; case INT3400_ODVP_CHANGED: evaluate_odvp(priv); + therm_event = THERMAL_DEVICE_POWER_CAPABILITY_CHANGED; break; default: /* Ignore unknown notification codes sent to INT3400 device */ - break; + return; } + + thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s", priv->thermal->type); + thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d", priv->thermal->temperature); + thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP="); + thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d", therm_event); + thermal_prop[4] = NULL; + kobject_uevent_env(&priv->thermal->device.kobj, KOBJ_CHANGE, thermal_prop); } static int int3400_thermal_get_temp(struct thermal_zone_device *thermal, diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 787710bb88fe..5c2a13bf249c 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -546,11 +546,11 @@ static int rcar_thermal_probe(struct platform_device *pdev) if (ret < 0) goto error_unregister; - if (chip->use_of_thermal) + if (chip->use_of_thermal) { priv->zone = devm_thermal_zone_of_sensor_register( dev, i, priv, &rcar_thermal_zone_of_ops); - else { + } else { priv->zone = thermal_zone_device_register( "rcar_thermal", 1, 0, priv, diff --git a/drivers/thermal/st/Kconfig b/drivers/thermal/st/Kconfig index 3c3b695cc3e9..58ece381956b 100644 --- a/drivers/thermal/st/Kconfig +++ b/drivers/thermal/st/Kconfig @@ -23,5 +23,5 @@ config STM32_THERMAL help Support for thermal framework on STMicroelectronics STM32 series of SoCs. This thermal driver allows to access to general thermal framework - functionalities and to acces to SoC sensor functionalities. This + functionalities and to access to SoC sensor functionalities. This configuration is fully dependent of MACH_STM32MP157. diff --git a/drivers/thermal/st/stm_thermal.c b/drivers/thermal/st/stm_thermal.c index 331e2b768df5..5fd3fb8912a6 100644 --- a/drivers/thermal/st/stm_thermal.c +++ b/drivers/thermal/st/stm_thermal.c @@ -446,14 +446,9 @@ thermal_unprepare: #ifdef CONFIG_PM_SLEEP static int stm_thermal_suspend(struct device *dev) { - int ret; struct stm_thermal_sensor *sensor = dev_get_drvdata(dev); - ret = stm_thermal_sensor_off(sensor); - if (ret) - return ret; - - return 0; + return stm_thermal_sensor_off(sensor); } static int stm_thermal_resume(struct device *dev) diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index 74d73be16496..f8b13071a6f4 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -244,7 +244,7 @@ static int sun50i_h6_ths_calibrate(struct ths_device *tmdev, ft_temp = (caldata[0] & FT_TEMP_MASK) * 100; for (i = 0; i < tmdev->chip->sensor_num; i++) { - int sensor_reg = caldata[i + 1]; + int sensor_reg = caldata[i + 1] & TEMP_CALIB_MASK; int cdata, offset; int sensor_temp = tmdev->chip->calc_temp(tmdev, i, sensor_reg); @@ -590,6 +590,19 @@ static const struct ths_thermal_chip sun50i_a64_ths = { .calc_temp = sun8i_ths_calc_temp, }; +static const struct ths_thermal_chip sun50i_a100_ths = { + .sensor_num = 3, + .has_bus_clk_reset = true, + .ft_deviation = 8000, + .offset = 187744, + .scale = 672, + .temp_data_base = SUN50I_H6_THS_TEMP_DATA, + .calibrate = sun50i_h6_ths_calibrate, + .init = sun50i_h6_thermal_init, + .irq_ack = sun50i_h6_irq_ack, + .calc_temp = sun8i_ths_calc_temp, +}; + static const struct ths_thermal_chip sun50i_h5_ths = { .sensor_num = 2, .has_mod_clk = true, @@ -619,6 +632,7 @@ static const struct of_device_id of_ths_match[] = { { .compatible = "allwinner,sun8i-h3-ths", .data = &sun8i_h3_ths }, { .compatible = "allwinner,sun8i-r40-ths", .data = &sun8i_r40_ths }, { .compatible = "allwinner,sun50i-a64-ths", .data = &sun50i_a64_ths }, + { .compatible = "allwinner,sun50i-a100-ths", .data = &sun50i_a100_ths }, { .compatible = "allwinner,sun50i-h5-ths", .data = &sun50i_h5_ths }, { .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths }, { /* sentinel */ }, diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index a6616e530a84..c6d74bc1c90b 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -603,7 +603,6 @@ static void thermal_zone_device_check(struct work_struct *work) /** * power_actor_get_max_power() - get the maximum power that a cdev can consume * @cdev: pointer to &thermal_cooling_device - * @tz: a valid thermal zone device pointer * @max_power: pointer in which to store the maximum power * * Calculate the maximum power consumption in milliwats that the @@ -613,18 +612,17 @@ static void thermal_zone_device_check(struct work_struct *work) * power_actor API or -E* on other error. */ int power_actor_get_max_power(struct thermal_cooling_device *cdev, - struct thermal_zone_device *tz, u32 *max_power) + u32 *max_power) { if (!cdev_is_power_actor(cdev)) return -EINVAL; - return cdev->ops->state2power(cdev, tz, 0, max_power); + return cdev->ops->state2power(cdev, 0, max_power); } /** * power_actor_get_min_power() - get the mainimum power that a cdev can consume * @cdev: pointer to &thermal_cooling_device - * @tz: a valid thermal zone device pointer * @min_power: pointer in which to store the minimum power * * Calculate the minimum power consumption in milliwatts that the @@ -634,7 +632,7 @@ int power_actor_get_max_power(struct thermal_cooling_device *cdev, * power_actor API or -E* on other error. */ int power_actor_get_min_power(struct thermal_cooling_device *cdev, - struct thermal_zone_device *tz, u32 *min_power) + u32 *min_power) { unsigned long max_state; int ret; @@ -646,7 +644,7 @@ int power_actor_get_min_power(struct thermal_cooling_device *cdev, if (ret) return ret; - return cdev->ops->state2power(cdev, tz, max_state, min_power); + return cdev->ops->state2power(cdev, max_state, min_power); } /** @@ -670,7 +668,7 @@ int power_actor_set_power(struct thermal_cooling_device *cdev, if (!cdev_is_power_actor(cdev)) return -EINVAL; - ret = cdev->ops->power2state(cdev, instance->tz, power, &state); + ret = cdev->ops->power2state(cdev, power, &state); if (ret) return ret; @@ -1652,7 +1650,6 @@ static int __init thermal_init(void) if (result) goto error; - mutex_init(&poweroff_lock); result = thermal_register_governors(); if (result) goto error; diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index e00fc5585ea8..764c2de31771 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -66,9 +66,9 @@ static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev) } int power_actor_get_max_power(struct thermal_cooling_device *cdev, - struct thermal_zone_device *tz, u32 *max_power); + u32 *max_power); int power_actor_get_min_power(struct thermal_cooling_device *cdev, - struct thermal_zone_device *tz, u32 *min_power); + u32 *min_power); int power_actor_set_power(struct thermal_cooling_device *cdev, struct thermal_instance *ti, u32 power); /** diff --git a/drivers/thermal/thermal_netlink.c b/drivers/thermal/thermal_netlink.c index da2891fcac89..1234dbe95895 100644 --- a/drivers/thermal/thermal_netlink.c +++ b/drivers/thermal/thermal_netlink.c @@ -78,7 +78,7 @@ int thermal_genl_sampling_temp(int id, int temp) hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0, THERMAL_GENL_SAMPLING_TEMP); if (!hdr) - return -EMSGSIZE; + goto out_free; if (nla_put_u32(skb, THERMAL_GENL_ATTR_TZ_ID, id)) goto out_cancel; @@ -93,6 +93,7 @@ int thermal_genl_sampling_temp(int id, int temp) return 0; out_cancel: genlmsg_cancel(skb, hdr); +out_free: nlmsg_free(skb); return -EMSGSIZE; diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index 8c231219e15d..a6f371fc9af2 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -448,7 +448,7 @@ static umode_t thermal_zone_passive_is_visible(struct kobject *kobj, struct attribute *attr, int attrno) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct thermal_zone_device *tz; enum thermal_trip_type trip_type; int count, passive = 0; diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index ab19ceff6e2a..5e596168ba73 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -25,10 +25,20 @@ #include <linux/of_platform.h> #include <linux/of_irq.h> #include <linux/io.h> +#include <linux/cpu_pm.h> +#include <linux/device.h> +#include <linux/pm_runtime.h> +#include <linux/pm.h> +#include <linux/of.h> +#include <linux/of_device.h> #include "ti-bandgap.h" static int ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id); +#ifdef CONFIG_PM_SLEEP +static int bandgap_omap_cpu_notifier(struct notifier_block *nb, + unsigned long cmd, void *v); +#endif /*** Helper functions to access registers and their bitfields ***/ @@ -1008,6 +1018,11 @@ int ti_bandgap_probe(struct platform_device *pdev) } } +#ifdef CONFIG_PM_SLEEP + bgp->nb.notifier_call = bandgap_omap_cpu_notifier; + cpu_pm_register_notifier(&bgp->nb); +#endif + return 0; remove_last_cooling: @@ -1041,7 +1056,9 @@ int ti_bandgap_remove(struct platform_device *pdev) struct ti_bandgap *bgp = platform_get_drvdata(pdev); int i; - /* First thing is to remove sensor interfaces */ + cpu_pm_unregister_notifier(&bgp->nb); + + /* Remove sensor interfaces */ for (i = 0; i < bgp->conf->sensor_count; i++) { if (bgp->conf->sensors[i].unregister_cooling) bgp->conf->sensors[i].unregister_cooling(bgp, i); @@ -1150,9 +1167,43 @@ static int ti_bandgap_suspend(struct device *dev) if (TI_BANDGAP_HAS(bgp, CLK_CTRL)) clk_disable_unprepare(bgp->fclock); + bgp->is_suspended = true; + return err; } +static int bandgap_omap_cpu_notifier(struct notifier_block *nb, + unsigned long cmd, void *v) +{ + struct ti_bandgap *bgp; + + bgp = container_of(nb, struct ti_bandgap, nb); + + spin_lock(&bgp->lock); + switch (cmd) { + case CPU_CLUSTER_PM_ENTER: + if (bgp->is_suspended) + break; + ti_bandgap_save_ctxt(bgp); + ti_bandgap_power(bgp, false); + if (TI_BANDGAP_HAS(bgp, CLK_CTRL)) + clk_disable(bgp->fclock); + break; + case CPU_CLUSTER_PM_ENTER_FAILED: + case CPU_CLUSTER_PM_EXIT: + if (bgp->is_suspended) + break; + if (TI_BANDGAP_HAS(bgp, CLK_CTRL)) + clk_enable(bgp->fclock); + ti_bandgap_power(bgp, true); + ti_bandgap_restore_ctxt(bgp); + break; + } + spin_unlock(&bgp->lock); + + return NOTIFY_OK; +} + static int ti_bandgap_resume(struct device *dev) { struct ti_bandgap *bgp = dev_get_drvdata(dev); @@ -1161,6 +1212,7 @@ static int ti_bandgap_resume(struct device *dev) clk_prepare_enable(bgp->fclock); ti_bandgap_power(bgp, true); + bgp->is_suspended = false; return ti_bandgap_restore_ctxt(bgp); } diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h index fce4657e9486..ed0ea4b17b25 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h @@ -12,6 +12,10 @@ #include <linux/spinlock.h> #include <linux/types.h> #include <linux/err.h> +#include <linux/cpu_pm.h> +#include <linux/device.h> +#include <linux/pm_runtime.h> +#include <linux/pm.h> struct gpio_desc; @@ -203,6 +207,8 @@ struct ti_bandgap { int irq; struct gpio_desc *tshut_gpiod; u32 clk_rate; + struct notifier_block nb; + unsigned int is_suspended:1; }; /** diff --git a/include/linux/idle_inject.h b/include/linux/idle_inject.h index 91a8612b8bf9..fb88e23a99d3 100644 --- a/include/linux/idle_inject.h +++ b/include/linux/idle_inject.h @@ -28,6 +28,6 @@ void idle_inject_get_duration(struct idle_inject_device *ii_dev, unsigned int *idle_duration_us); void idle_inject_set_latency(struct idle_inject_device *ii_dev, - unsigned int latency_ns); + unsigned int latency_us); #endif /* __IDLE_INJECT_H__ */ diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 42ef807e5d84..d07ea27e72a9 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -55,6 +55,7 @@ enum thermal_notify_event { THERMAL_DEVICE_UP, /* Thermal device is up after a down event */ THERMAL_DEVICE_POWER_CAPABILITY_CHANGED, /* power capability changed */ THERMAL_TABLE_CHANGED, /* Thermal table(s) changed */ + THERMAL_EVENT_KEEP_ALIVE, /* Request for user space handler to respond */ }; struct thermal_zone_device_ops { @@ -84,12 +85,9 @@ struct thermal_cooling_device_ops { int (*get_max_state) (struct thermal_cooling_device *, unsigned long *); int (*get_cur_state) (struct thermal_cooling_device *, unsigned long *); int (*set_cur_state) (struct thermal_cooling_device *, unsigned long); - int (*get_requested_power)(struct thermal_cooling_device *, - struct thermal_zone_device *, u32 *); - int (*state2power)(struct thermal_cooling_device *, - struct thermal_zone_device *, unsigned long, u32 *); - int (*power2state)(struct thermal_cooling_device *, - struct thermal_zone_device *, u32, unsigned long *); + int (*get_requested_power)(struct thermal_cooling_device *, u32 *); + int (*state2power)(struct thermal_cooling_device *, unsigned long, u32 *); + int (*power2state)(struct thermal_cooling_device *, u32, unsigned long *); }; struct thermal_cooling_device { |