Commit 35b11d2e authored by Javi Merino's avatar Javi Merino Committed by Eduardo Valentin

thermal: extend the cooling device API to include power information

Add three optional callbacks to the cooling device interface to allow
them to express power.  In addition to the callbacks, add helpers to
identify cooling devices that implement the power cooling device API.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: Eduardo Valentin <edubezval@gmail.com>
Signed-off-by: default avatarJavi Merino <javi.merino@arm.com>
Signed-off-by: default avatarEduardo Valentin <edubezval@gmail.com>
parent e33df1d2
...@@ -875,6 +875,58 @@ emul_temp_store(struct device *dev, struct device_attribute *attr, ...@@ -875,6 +875,58 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
#endif/*CONFIG_THERMAL_EMULATION*/ #endif/*CONFIG_THERMAL_EMULATION*/
/**
* 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
* cooling device can currently consume and store it in @max_power.
*
* Return: 0 on success, -EINVAL if @cdev doesn't support the
* 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)
{
if (!cdev_is_power_actor(cdev))
return -EINVAL;
return cdev->ops->state2power(cdev, tz, 0, max_power);
}
/**
* power_actor_set_power() - limit the maximum power that a cooling device can consume
* @cdev: pointer to &thermal_cooling_device
* @instance: thermal instance to update
* @power: the power in milliwatts
*
* Set the cooling device to consume at most @power milliwatts.
*
* Return: 0 on success, -EINVAL if the cooling device does not
* implement the power actor API or -E* for other failures.
*/
int power_actor_set_power(struct thermal_cooling_device *cdev,
struct thermal_instance *instance, u32 power)
{
unsigned long state;
int ret;
if (!cdev_is_power_actor(cdev))
return -EINVAL;
ret = cdev->ops->power2state(cdev, instance->tz, power, &state);
if (ret)
return ret;
instance->target = state;
cdev->updated = false;
thermal_cdev_update(cdev);
return 0;
}
static DEVICE_ATTR(type, 0444, type_show, NULL); static DEVICE_ATTR(type, 0444, type_show, NULL);
static DEVICE_ATTR(temp, 0444, temp_show, NULL); static DEVICE_ATTR(temp, 0444, temp_show, NULL);
static DEVICE_ATTR(mode, 0644, mode_show, mode_store); static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
......
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
struct thermal_zone_device; struct thermal_zone_device;
struct thermal_cooling_device; struct thermal_cooling_device;
struct thermal_instance;
enum thermal_device_mode { enum thermal_device_mode {
THERMAL_DEVICE_DISABLED = 0, THERMAL_DEVICE_DISABLED = 0,
...@@ -116,6 +117,12 @@ struct thermal_cooling_device_ops { ...@@ -116,6 +117,12 @@ 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 *,
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 *);
}; };
struct thermal_cooling_device { struct thermal_cooling_device {
...@@ -331,6 +338,16 @@ void thermal_zone_of_sensor_unregister(struct device *dev, ...@@ -331,6 +338,16 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
#endif #endif
#if IS_ENABLED(CONFIG_THERMAL) #if IS_ENABLED(CONFIG_THERMAL)
static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev)
{
return cdev->ops->get_requested_power && cdev->ops->state2power &&
cdev->ops->power2state;
}
int power_actor_get_max_power(struct thermal_cooling_device *,
struct thermal_zone_device *tz, u32 *max_power);
int power_actor_set_power(struct thermal_cooling_device *,
struct thermal_instance *, u32);
struct thermal_zone_device *thermal_zone_device_register(const char *, int, int, struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
void *, struct thermal_zone_device_ops *, void *, struct thermal_zone_device_ops *,
const struct thermal_zone_params *, int, int); const struct thermal_zone_params *, int, int);
...@@ -359,6 +376,14 @@ struct thermal_instance *get_thermal_instance(struct thermal_zone_device *, ...@@ -359,6 +376,14 @@ struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
void thermal_cdev_update(struct thermal_cooling_device *); void thermal_cdev_update(struct thermal_cooling_device *);
void thermal_notify_framework(struct thermal_zone_device *, int); void thermal_notify_framework(struct thermal_zone_device *, int);
#else #else
static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev)
{ return false; }
static inline int power_actor_get_max_power(struct thermal_cooling_device *cdev,
struct thermal_zone_device *tz, u32 *max_power)
{ return 0; }
static inline int power_actor_set_power(struct thermal_cooling_device *cdev,
struct thermal_instance *tz, u32 power)
{ return 0; }
static inline struct thermal_zone_device *thermal_zone_device_register( static inline struct thermal_zone_device *thermal_zone_device_register(
const char *type, int trips, int mask, void *devdata, const char *type, int trips, int mask, void *devdata,
struct thermal_zone_device_ops *ops, struct thermal_zone_device_ops *ops,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment