diff options
Diffstat (limited to 'drivers/thermal/thermal_core.c')
-rw-r--r-- | drivers/thermal/thermal_core.c | 86 |
1 files changed, 79 insertions, 7 deletions
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index f1d511a9475..338a88bf666 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -34,6 +34,7 @@ #include <linux/thermal.h> #include <linux/reboot.h> #include <linux/string.h> +#include <linux/of.h> #include <net/netlink.h> #include <net/genetlink.h> @@ -403,7 +404,7 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp) enum thermal_trip_type type; #endif - if (!tz || IS_ERR(tz)) + if (!tz || IS_ERR(tz) || !tz->ops->get_temp) goto exit; mutex_lock(&tz->lock); @@ -450,12 +451,18 @@ static void update_temperature(struct thermal_zone_device *tz) tz->last_temperature = tz->temperature; tz->temperature = temp; mutex_unlock(&tz->lock); + + dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", + tz->last_temperature, tz->temperature); } void thermal_zone_device_update(struct thermal_zone_device *tz) { int count; + if (!tz->ops->get_temp) + return; + update_temperature(tz); for (count = 0; count < tz->trips; count++) @@ -774,6 +781,9 @@ emul_temp_store(struct device *dev, struct device_attribute *attr, ret = tz->ops->set_emul_temp(tz, temperature); } + if (!ret) + thermal_zone_device_update(tz); + return ret ? ret : count; } static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); @@ -1052,7 +1062,8 @@ static struct class thermal_class = { }; /** - * thermal_cooling_device_register() - register a new thermal cooling device + * __thermal_cooling_device_register() - register a new thermal cooling device + * @np: a pointer to a device tree node. * @type: the thermal cooling device type. * @devdata: device private data. * @ops: standard thermal cooling devices callbacks. @@ -1060,13 +1071,16 @@ static struct class thermal_class = { * This interface function adds a new thermal cooling device (fan/processor/...) * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself * to all the thermal zone devices registered at the same time. + * It also gives the opportunity to link the cooling device to a device tree + * node, so that it can be bound to a thermal zone created out of device tree. * * Return: a pointer to the created struct thermal_cooling_device or an * ERR_PTR. Caller must check return value with IS_ERR*() helpers. */ -struct thermal_cooling_device * -thermal_cooling_device_register(char *type, void *devdata, - const struct thermal_cooling_device_ops *ops) +static struct thermal_cooling_device * +__thermal_cooling_device_register(struct device_node *np, + char *type, void *devdata, + const struct thermal_cooling_device_ops *ops) { struct thermal_cooling_device *cdev; int result; @@ -1091,6 +1105,7 @@ thermal_cooling_device_register(char *type, void *devdata, strlcpy(cdev->type, type ? : "", sizeof(cdev->type)); mutex_init(&cdev->lock); INIT_LIST_HEAD(&cdev->thermal_instances); + cdev->np = np; cdev->ops = ops; cdev->updated = true; cdev->device.class = &thermal_class; @@ -1133,9 +1148,53 @@ unregister: device_unregister(&cdev->device); return ERR_PTR(result); } + +/** + * thermal_cooling_device_register() - register a new thermal cooling device + * @type: the thermal cooling device type. + * @devdata: device private data. + * @ops: standard thermal cooling devices callbacks. + * + * This interface function adds a new thermal cooling device (fan/processor/...) + * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself + * to all the thermal zone devices registered at the same time. + * + * Return: a pointer to the created struct thermal_cooling_device or an + * ERR_PTR. Caller must check return value with IS_ERR*() helpers. + */ +struct thermal_cooling_device * +thermal_cooling_device_register(char *type, void *devdata, + const struct thermal_cooling_device_ops *ops) +{ + return __thermal_cooling_device_register(NULL, type, devdata, ops); +} EXPORT_SYMBOL_GPL(thermal_cooling_device_register); /** + * thermal_of_cooling_device_register() - register an OF thermal cooling device + * @np: a pointer to a device tree node. + * @type: the thermal cooling device type. + * @devdata: device private data. + * @ops: standard thermal cooling devices callbacks. + * + * This function will register a cooling device with device tree node reference. + * This interface function adds a new thermal cooling device (fan/processor/...) + * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself + * to all the thermal zone devices registered at the same time. + * + * Return: a pointer to the created struct thermal_cooling_device or an + * ERR_PTR. Caller must check return value with IS_ERR*() helpers. + */ +struct thermal_cooling_device * +thermal_of_cooling_device_register(struct device_node *np, + char *type, void *devdata, + const struct thermal_cooling_device_ops *ops) +{ + return __thermal_cooling_device_register(np, type, devdata, ops); +} +EXPORT_SYMBOL_GPL(thermal_of_cooling_device_register); + +/** * thermal_cooling_device_unregister - removes the registered thermal cooling device * @cdev: the thermal cooling device to remove. * @@ -1207,6 +1266,8 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) mutex_lock(&cdev->lock); /* Make sure cdev enters the deepest cooling state */ list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) { + dev_dbg(&cdev->device, "zone%d->target=%lu\n", + instance->tz->id, instance->target); if (instance->target == THERMAL_NO_TARGET) continue; if (instance->target > target) @@ -1215,6 +1276,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) mutex_unlock(&cdev->lock); cdev->ops->set_cur_state(cdev, target); cdev->updated = true; + dev_dbg(&cdev->device, "set to state %lu\n", target); } EXPORT_SYMBOL(thermal_cdev_update); @@ -1370,7 +1432,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz) */ struct thermal_zone_device *thermal_zone_device_register(const char *type, int trips, int mask, void *devdata, - const struct thermal_zone_device_ops *ops, + struct thermal_zone_device_ops *ops, const struct thermal_zone_params *tzp, int passive_delay, int polling_delay) { @@ -1386,7 +1448,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips) return ERR_PTR(-EINVAL); - if (!ops || !ops->get_temp) + if (!ops) return ERR_PTR(-EINVAL); if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp)) @@ -1490,6 +1552,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); + if (!tz->ops->get_temp) + thermal_zone_device_set_polling(tz, 0); + thermal_zone_device_update(tz); if (!result) @@ -1740,8 +1805,14 @@ static int __init thermal_init(void) if (result) goto unregister_class; + result = of_parse_thermal_zones(); + if (result) + goto exit_netlink; + return 0; +exit_netlink: + genetlink_exit(); unregister_governors: thermal_unregister_governors(); unregister_class: @@ -1757,6 +1828,7 @@ error: static void __exit thermal_exit(void) { + of_thermal_destroy_zones(); genetlink_exit(); class_unregister(&thermal_class); thermal_unregister_governors(); |