- 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)
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEEGn3N4YVz0WNVyHskqDIjiipP6E8FAl+GwbYACgkQqDIjiipP
 6E8IFAf/UnO1HqfK96FnVJXx5ClXFE8PQhdVejxBEsNCJqUOwlqfpyONy7mgwABb
 EuOvp5ZLX6ly9xG6J4NJhE4gN4DxqRKe0S3bQMU+DX8TQHc3otDKHILJbHrJdOY+
 BYZpGxuCjU9yZrsJopztZIcpG7cF78d39XCJVSrBhoOBqPLXNGZkUUzOv9+QQti3
 ipdhqB3kUzkgDFgIrDxX8t0vybQZSbiRWNUGrw/WQjMsG0NGIarCUHW4wiaea6gU
 L2x1QDR5h9hxEAJiTBarOtF7ZlE15fpria0mWfTgmNMArMEtRBL60kBnmYa4o3EG
 CseR7x1MdTCSqLCzKGfQyKv5SFgnVg==
 =P6zv
 -----END PGP SIGNATURE-----

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"
This commit is contained in:
Linus Torvalds 2020-10-17 10:40:22 -07:00
commit 5a77b6a013
22 changed files with 156 additions and 82 deletions

View File

@ -17,6 +17,7 @@ properties:
- allwinner,sun8i-h3-ths - allwinner,sun8i-h3-ths
- allwinner,sun8i-r40-ths - allwinner,sun8i-r40-ths
- allwinner,sun50i-a64-ths - allwinner,sun50i-a64-ths
- allwinner,sun50i-a100-ths
- allwinner,sun50i-h5-ths - allwinner,sun50i-h5-ths
- allwinner,sun50i-h6-ths - allwinner,sun50i-h6-ths
@ -61,7 +62,9 @@ allOf:
properties: properties:
compatible: compatible:
contains: contains:
const: allwinner,sun50i-h6-ths enum:
- allwinner,sun50i-a100-ths
- allwinner,sun50i-h6-ths
then: then:
properties: properties:
@ -103,6 +106,7 @@ allOf:
- const: allwinner,sun8i-h3-ths - const: allwinner,sun8i-h3-ths
- const: allwinner,sun8i-r40-ths - const: allwinner,sun8i-r40-ths
- const: allwinner,sun50i-a64-ths - const: allwinner,sun50i-a64-ths
- const: allwinner,sun50i-a100-ths
- const: allwinner,sun50i-h5-ths - const: allwinner,sun50i-h5-ths
- const: allwinner,sun50i-h6-ths - const: allwinner,sun50i-h6-ths

View File

@ -20,6 +20,7 @@ properties:
enum: enum:
- renesas,r8a774a1-thermal # RZ/G2M - renesas,r8a774a1-thermal # RZ/G2M
- renesas,r8a774b1-thermal # RZ/G2N - renesas,r8a774b1-thermal # RZ/G2N
- renesas,r8a774e1-thermal # RZ/G2H
- renesas,r8a7795-thermal # R-Car H3 - renesas,r8a7795-thermal # R-Car H3
- renesas,r8a7796-thermal # R-Car M3-W - renesas,r8a7796-thermal # R-Car M3-W
- renesas,r8a77961-thermal # R-Car M3-W+ - renesas,r8a77961-thermal # R-Car M3-W+

View File

@ -346,13 +346,13 @@ config RCAR_THERMAL
thermal framework. thermal framework.
config RCAR_GEN3_THERMAL 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 ARCH_RENESAS || COMPILE_TEST
depends on HAS_IOMEM depends on HAS_IOMEM
depends on OF depends on OF
help help
Enable this to plug the R-Car Gen3 thermal sensor driver into the Linux Enable this to plug the R-Car Gen3 or RZ/G2 thermal sensor driver into
thermal framework. the Linux thermal framework.
config KIRKWOOD_THERMAL config KIRKWOOD_THERMAL
tristate "Temperature sensor on Marvell Kirkwood SoCs" tristate "Temperature sensor on Marvell Kirkwood SoCs"

View File

@ -182,7 +182,6 @@ static u32 get_dynamic_power(struct cpufreq_cooling_device *cpufreq_cdev,
/** /**
* cpufreq_get_requested_power() - get the current power * cpufreq_get_requested_power() - get the current power
* @cdev: &thermal_cooling_device pointer * @cdev: &thermal_cooling_device pointer
* @tz: a valid thermal zone device pointer
* @power: pointer in which to store the resulting power * @power: pointer in which to store the resulting power
* *
* Calculate the current power consumption of the cpus in milliwatts * 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. * Return: 0 on success, -E* if getting the static power failed.
*/ */
static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
struct thermal_zone_device *tz,
u32 *power) u32 *power)
{ {
unsigned long freq; 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 * cpufreq_state2power() - convert a cpu cdev state to power consumed
* @cdev: &thermal_cooling_device pointer * @cdev: &thermal_cooling_device pointer
* @tz: a valid thermal zone device pointer
* @state: cooling device state to be converted * @state: cooling device state to be converted
* @power: pointer in which to store the resulting power * @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. * when calculating the static power.
*/ */
static int cpufreq_state2power(struct thermal_cooling_device *cdev, static int cpufreq_state2power(struct thermal_cooling_device *cdev,
struct thermal_zone_device *tz,
unsigned long state, u32 *power) unsigned long state, u32 *power)
{ {
unsigned int freq, num_cpus, idx; 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 * cpufreq_power2state() - convert power to a cooling device state
* @cdev: &thermal_cooling_device pointer * @cdev: &thermal_cooling_device pointer
* @tz: a valid thermal zone device pointer
* @power: power in milliwatts to be converted * @power: power in milliwatts to be converted
* @state: pointer in which to store the resulting state * @state: pointer in which to store the resulting state
* *
@ -306,8 +301,7 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev,
* device. * device.
*/ */
static int cpufreq_power2state(struct thermal_cooling_device *cdev, static int cpufreq_power2state(struct thermal_cooling_device *cdev,
struct thermal_zone_device *tz, u32 power, u32 power, unsigned long *state)
unsigned long *state)
{ {
unsigned int target_freq; unsigned int target_freq;
u32 last_load, normalised_power; u32 last_load, normalised_power;

View File

@ -30,7 +30,7 @@ static DEFINE_IDA(cpuidle_ida);
/** /**
* cpuidle_cooling_runtime - Running time computation * 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 * @state: a percentile based number
* *
* The running duration is computed from the idle injection duration * The running duration is computed from the idle injection duration

View File

@ -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, static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev,
struct thermal_zone_device *tz,
u32 *power) u32 *power)
{ {
struct devfreq_cooling_device *dfc = cdev->devdata; struct devfreq_cooling_device *dfc = cdev->devdata;
@ -289,7 +288,6 @@ fail:
} }
static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev, static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev,
struct thermal_zone_device *tz,
unsigned long state, unsigned long state,
u32 *power) 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, static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev,
struct thermal_zone_device *tz,
u32 power, unsigned long *state) u32 power, unsigned long *state)
{ {
struct devfreq_cooling_device *dfc = cdev->devdata; struct devfreq_cooling_device *dfc = cdev->devdata;

View File

@ -96,7 +96,7 @@ static u32 estimate_sustainable_power(struct thermal_zone_device *tz)
if (instance->trip != params->trip_max_desired_temperature) if (instance->trip != params->trip_max_desired_temperature)
continue; continue;
if (power_actor_get_min_power(cdev, tz, &min_power)) if (power_actor_get_min_power(cdev, &min_power))
continue; continue;
sustainable_power += min_power; sustainable_power += min_power;
@ -388,7 +388,7 @@ static int allocate_power(struct thermal_zone_device *tz,
if (!cdev_is_power_actor(cdev)) if (!cdev_is_power_actor(cdev))
continue; continue;
if (cdev->ops->get_requested_power(cdev, tz, &req_power[i])) if (cdev->ops->get_requested_power(cdev, &req_power[i]))
continue; continue;
if (!total_weight) 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]); 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; continue;
total_req_power += req_power[i]; total_req_power += req_power[i];

View File

@ -146,13 +146,9 @@ static int imx8mm_tmu_probe(struct platform_device *pdev)
return PTR_ERR(tmu->base); return PTR_ERR(tmu->base);
tmu->clk = devm_clk_get(&pdev->dev, NULL); tmu->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(tmu->clk)) { if (IS_ERR(tmu->clk))
ret = PTR_ERR(tmu->clk); return dev_err_probe(&pdev->dev, PTR_ERR(tmu->clk),
if (ret != -EPROBE_DEFER) "failed to get tmu clock\n");
dev_err(&pdev->dev,
"failed to get tmu clock: %d\n", ret);
return ret;
}
ret = clk_prepare_enable(tmu->clk); ret = clk_prepare_enable(tmu->clk);
if (ret) { if (ret) {

View File

@ -716,14 +716,9 @@ static int imx_thermal_probe(struct platform_device *pdev)
if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) { if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) {
ret = imx_init_from_nvmem_cells(pdev); ret = imx_init_from_nvmem_cells(pdev);
if (ret) { if (ret)
if (ret == -EPROBE_DEFER) return dev_err_probe(&pdev->dev, ret,
return ret; "failed to init from nvmem\n");
dev_err(&pdev->dev, "failed to init from nvmem: %d\n",
ret);
return ret;
}
} else { } else {
ret = imx_init_from_tempmon_data(pdev); ret = imx_init_from_tempmon_data(pdev);
if (ret) { if (ret) {
@ -746,14 +741,9 @@ static int imx_thermal_probe(struct platform_device *pdev)
data->socdata->power_down_mask); data->socdata->power_down_mask);
ret = imx_thermal_register_legacy_cooling(data); ret = imx_thermal_register_legacy_cooling(data);
if (ret) { if (ret)
if (ret == -EPROBE_DEFER) return dev_err_probe(&pdev->dev, ret,
return ret; "failed to register cpufreq cooling device\n");
dev_err(&pdev->dev,
"failed to register cpufreq cooling device: %d\n", ret);
return ret;
}
data->thermal_clk = devm_clk_get(&pdev->dev, NULL); data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(data->thermal_clk)) { if (IS_ERR(data->thermal_clk)) {

View File

@ -14,6 +14,7 @@
#define INT3400_THERMAL_TABLE_CHANGED 0x83 #define INT3400_THERMAL_TABLE_CHANGED 0x83
#define INT3400_ODVP_CHANGED 0x88 #define INT3400_ODVP_CHANGED 0x88
#define INT3400_KEEP_ALIVE 0xA0
enum int3400_thermal_uuid { enum int3400_thermal_uuid {
INT3400_THERMAL_PASSIVE_1, INT3400_THERMAL_PASSIVE_1,
@ -83,8 +84,33 @@ static struct bin_attribute *data_attributes[] = {
NULL, 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 = { static const struct attribute_group data_attribute_group = {
.bin_attrs = data_attributes, .bin_attrs = data_attributes,
.attrs = imok_attr,
}; };
static ssize_t available_uuids_show(struct device *dev, 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; struct int3400_thermal_priv *priv = data;
char *thermal_prop[5]; char *thermal_prop[5];
int therm_event;
if (!priv) if (!priv)
return; return;
switch (event) { switch (event) {
case INT3400_THERMAL_TABLE_CHANGED: case INT3400_THERMAL_TABLE_CHANGED:
thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s", therm_event = THERMAL_TABLE_CHANGED;
priv->thermal->type); break;
thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d", case INT3400_KEEP_ALIVE:
priv->thermal->temperature); therm_event = THERMAL_EVENT_KEEP_ALIVE;
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);
break; break;
case INT3400_ODVP_CHANGED: case INT3400_ODVP_CHANGED:
evaluate_odvp(priv); evaluate_odvp(priv);
therm_event = THERMAL_DEVICE_POWER_CAPABILITY_CHANGED;
break; break;
default: default:
/* Ignore unknown notification codes sent to INT3400 device */ /* 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, static int int3400_thermal_get_temp(struct thermal_zone_device *thermal,

View File

@ -546,11 +546,11 @@ static int rcar_thermal_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto error_unregister; goto error_unregister;
if (chip->use_of_thermal) if (chip->use_of_thermal) {
priv->zone = devm_thermal_zone_of_sensor_register( priv->zone = devm_thermal_zone_of_sensor_register(
dev, i, priv, dev, i, priv,
&rcar_thermal_zone_of_ops); &rcar_thermal_zone_of_ops);
else { } else {
priv->zone = thermal_zone_device_register( priv->zone = thermal_zone_device_register(
"rcar_thermal", "rcar_thermal",
1, 0, priv, 1, 0, priv,

View File

@ -23,5 +23,5 @@ config STM32_THERMAL
help help
Support for thermal framework on STMicroelectronics STM32 series of Support for thermal framework on STMicroelectronics STM32 series of
SoCs. This thermal driver allows to access to general thermal framework 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. configuration is fully dependent of MACH_STM32MP157.

View File

@ -446,14 +446,9 @@ thermal_unprepare:
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int stm_thermal_suspend(struct device *dev) static int stm_thermal_suspend(struct device *dev)
{ {
int ret;
struct stm_thermal_sensor *sensor = dev_get_drvdata(dev); struct stm_thermal_sensor *sensor = dev_get_drvdata(dev);
ret = stm_thermal_sensor_off(sensor); return stm_thermal_sensor_off(sensor);
if (ret)
return ret;
return 0;
} }
static int stm_thermal_resume(struct device *dev) static int stm_thermal_resume(struct device *dev)

View File

@ -244,7 +244,7 @@ static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
ft_temp = (caldata[0] & FT_TEMP_MASK) * 100; ft_temp = (caldata[0] & FT_TEMP_MASK) * 100;
for (i = 0; i < tmdev->chip->sensor_num; i++) { 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 cdata, offset;
int sensor_temp = tmdev->chip->calc_temp(tmdev, i, sensor_reg); 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, .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 = { static const struct ths_thermal_chip sun50i_h5_ths = {
.sensor_num = 2, .sensor_num = 2,
.has_mod_clk = true, .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-h3-ths", .data = &sun8i_h3_ths },
{ .compatible = "allwinner,sun8i-r40-ths", .data = &sun8i_r40_ths }, { .compatible = "allwinner,sun8i-r40-ths", .data = &sun8i_r40_ths },
{ .compatible = "allwinner,sun50i-a64-ths", .data = &sun50i_a64_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-h5-ths", .data = &sun50i_h5_ths },
{ .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths }, { .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths },
{ /* sentinel */ }, { /* sentinel */ },

View File

@ -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 * power_actor_get_max_power() - get the maximum power that a cdev can consume
* @cdev: pointer to &thermal_cooling_device * @cdev: pointer to &thermal_cooling_device
* @tz: a valid thermal zone device pointer
* @max_power: pointer in which to store the maximum power * @max_power: pointer in which to store the maximum power
* *
* Calculate the maximum power consumption in milliwats that the * 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. * power_actor API or -E* on other error.
*/ */
int power_actor_get_max_power(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)
{ {
if (!cdev_is_power_actor(cdev)) if (!cdev_is_power_actor(cdev))
return -EINVAL; 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 * power_actor_get_min_power() - get the mainimum power that a cdev can consume
* @cdev: pointer to &thermal_cooling_device * @cdev: pointer to &thermal_cooling_device
* @tz: a valid thermal zone device pointer
* @min_power: pointer in which to store the minimum power * @min_power: pointer in which to store the minimum power
* *
* Calculate the minimum power consumption in milliwatts that the * 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. * power_actor API or -E* on other error.
*/ */
int power_actor_get_min_power(struct thermal_cooling_device *cdev, 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; unsigned long max_state;
int ret; int ret;
@ -646,7 +644,7 @@ int power_actor_get_min_power(struct thermal_cooling_device *cdev,
if (ret) if (ret)
return 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)) if (!cdev_is_power_actor(cdev))
return -EINVAL; return -EINVAL;
ret = cdev->ops->power2state(cdev, instance->tz, power, &state); ret = cdev->ops->power2state(cdev, power, &state);
if (ret) if (ret)
return ret; return ret;
@ -1652,7 +1650,6 @@ static int __init thermal_init(void)
if (result) if (result)
goto error; goto error;
mutex_init(&poweroff_lock);
result = thermal_register_governors(); result = thermal_register_governors();
if (result) if (result)
goto error; goto error;

View File

@ -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, 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, 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, int power_actor_set_power(struct thermal_cooling_device *cdev,
struct thermal_instance *ti, u32 power); struct thermal_instance *ti, u32 power);
/** /**

View File

@ -78,7 +78,7 @@ int thermal_genl_sampling_temp(int id, int temp)
hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0, hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0,
THERMAL_GENL_SAMPLING_TEMP); THERMAL_GENL_SAMPLING_TEMP);
if (!hdr) if (!hdr)
return -EMSGSIZE; goto out_free;
if (nla_put_u32(skb, THERMAL_GENL_ATTR_TZ_ID, id)) if (nla_put_u32(skb, THERMAL_GENL_ATTR_TZ_ID, id))
goto out_cancel; goto out_cancel;
@ -93,6 +93,7 @@ int thermal_genl_sampling_temp(int id, int temp)
return 0; return 0;
out_cancel: out_cancel:
genlmsg_cancel(skb, hdr); genlmsg_cancel(skb, hdr);
out_free:
nlmsg_free(skb); nlmsg_free(skb);
return -EMSGSIZE; return -EMSGSIZE;

View File

@ -448,7 +448,7 @@ static umode_t thermal_zone_passive_is_visible(struct kobject *kobj,
struct attribute *attr, struct attribute *attr,
int attrno) int attrno)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = kobj_to_dev(kobj);
struct thermal_zone_device *tz; struct thermal_zone_device *tz;
enum thermal_trip_type trip_type; enum thermal_trip_type trip_type;
int count, passive = 0; int count, passive = 0;

View File

@ -25,10 +25,20 @@
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/io.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" #include "ti-bandgap.h"
static int ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id); 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 ***/ /*** 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; return 0;
remove_last_cooling: remove_last_cooling:
@ -1041,7 +1056,9 @@ int ti_bandgap_remove(struct platform_device *pdev)
struct ti_bandgap *bgp = platform_get_drvdata(pdev); struct ti_bandgap *bgp = platform_get_drvdata(pdev);
int i; 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++) { for (i = 0; i < bgp->conf->sensor_count; i++) {
if (bgp->conf->sensors[i].unregister_cooling) if (bgp->conf->sensors[i].unregister_cooling)
bgp->conf->sensors[i].unregister_cooling(bgp, i); 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)) if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
clk_disable_unprepare(bgp->fclock); clk_disable_unprepare(bgp->fclock);
bgp->is_suspended = true;
return err; 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) static int ti_bandgap_resume(struct device *dev)
{ {
struct ti_bandgap *bgp = dev_get_drvdata(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); clk_prepare_enable(bgp->fclock);
ti_bandgap_power(bgp, true); ti_bandgap_power(bgp, true);
bgp->is_suspended = false;
return ti_bandgap_restore_ctxt(bgp); return ti_bandgap_restore_ctxt(bgp);
} }

View File

@ -12,6 +12,10 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/err.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; struct gpio_desc;
@ -203,6 +207,8 @@ struct ti_bandgap {
int irq; int irq;
struct gpio_desc *tshut_gpiod; struct gpio_desc *tshut_gpiod;
u32 clk_rate; u32 clk_rate;
struct notifier_block nb;
unsigned int is_suspended:1;
}; };
/** /**

View File

@ -28,6 +28,6 @@ void idle_inject_get_duration(struct idle_inject_device *ii_dev,
unsigned int *idle_duration_us); unsigned int *idle_duration_us);
void idle_inject_set_latency(struct idle_inject_device *ii_dev, void idle_inject_set_latency(struct idle_inject_device *ii_dev,
unsigned int latency_ns); unsigned int latency_us);
#endif /* __IDLE_INJECT_H__ */ #endif /* __IDLE_INJECT_H__ */

View File

@ -55,6 +55,7 @@ enum thermal_notify_event {
THERMAL_DEVICE_UP, /* Thermal device is up after a down event */ THERMAL_DEVICE_UP, /* Thermal device is up after a down event */
THERMAL_DEVICE_POWER_CAPABILITY_CHANGED, /* power capability changed */ THERMAL_DEVICE_POWER_CAPABILITY_CHANGED, /* power capability changed */
THERMAL_TABLE_CHANGED, /* Thermal table(s) changed */ THERMAL_TABLE_CHANGED, /* Thermal table(s) changed */
THERMAL_EVENT_KEEP_ALIVE, /* Request for user space handler to respond */
}; };
struct thermal_zone_device_ops { 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_max_state) (struct thermal_cooling_device *, unsigned long *);
int (*get_cur_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 (*set_cur_state) (struct thermal_cooling_device *, unsigned long);
int (*get_requested_power)(struct thermal_cooling_device *, int (*get_requested_power)(struct thermal_cooling_device *, u32 *);
struct thermal_zone_device *, u32 *); int (*state2power)(struct thermal_cooling_device *, unsigned long, u32 *);
int (*state2power)(struct thermal_cooling_device *, int (*power2state)(struct thermal_cooling_device *, u32, unsigned long *);
struct thermal_zone_device *, unsigned long, u32 *);
int (*power2state)(struct thermal_cooling_device *,
struct thermal_zone_device *, u32, unsigned long *);
}; };
struct thermal_cooling_device { struct thermal_cooling_device {