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 f1d511a9475b..338a88bf6662 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/thermal.h> | 34 | #include <linux/thermal.h> |
35 | #include <linux/reboot.h> | 35 | #include <linux/reboot.h> |
36 | #include <linux/string.h> | 36 | #include <linux/string.h> |
37 | #include <linux/of.h> | ||
37 | #include <net/netlink.h> | 38 | #include <net/netlink.h> |
38 | #include <net/genetlink.h> | 39 | #include <net/genetlink.h> |
39 | 40 | ||
@@ -403,7 +404,7 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp) | |||
403 | enum thermal_trip_type type; | 404 | enum thermal_trip_type type; |
404 | #endif | 405 | #endif |
405 | 406 | ||
406 | if (!tz || IS_ERR(tz)) | 407 | if (!tz || IS_ERR(tz) || !tz->ops->get_temp) |
407 | goto exit; | 408 | goto exit; |
408 | 409 | ||
409 | mutex_lock(&tz->lock); | 410 | mutex_lock(&tz->lock); |
@@ -450,12 +451,18 @@ static void update_temperature(struct thermal_zone_device *tz) | |||
450 | tz->last_temperature = tz->temperature; | 451 | tz->last_temperature = tz->temperature; |
451 | tz->temperature = temp; | 452 | tz->temperature = temp; |
452 | mutex_unlock(&tz->lock); | 453 | mutex_unlock(&tz->lock); |
454 | |||
455 | dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", | ||
456 | tz->last_temperature, tz->temperature); | ||
453 | } | 457 | } |
454 | 458 | ||
455 | void thermal_zone_device_update(struct thermal_zone_device *tz) | 459 | void thermal_zone_device_update(struct thermal_zone_device *tz) |
456 | { | 460 | { |
457 | int count; | 461 | int count; |
458 | 462 | ||
463 | if (!tz->ops->get_temp) | ||
464 | return; | ||
465 | |||
459 | update_temperature(tz); | 466 | update_temperature(tz); |
460 | 467 | ||
461 | for (count = 0; count < tz->trips; count++) | 468 | for (count = 0; count < tz->trips; count++) |
@@ -774,6 +781,9 @@ emul_temp_store(struct device *dev, struct device_attribute *attr, | |||
774 | ret = tz->ops->set_emul_temp(tz, temperature); | 781 | ret = tz->ops->set_emul_temp(tz, temperature); |
775 | } | 782 | } |
776 | 783 | ||
784 | if (!ret) | ||
785 | thermal_zone_device_update(tz); | ||
786 | |||
777 | return ret ? ret : count; | 787 | return ret ? ret : count; |
778 | } | 788 | } |
779 | static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); | 789 | static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); |
@@ -1052,7 +1062,8 @@ static struct class thermal_class = { | |||
1052 | }; | 1062 | }; |
1053 | 1063 | ||
1054 | /** | 1064 | /** |
1055 | * thermal_cooling_device_register() - register a new thermal cooling device | 1065 | * __thermal_cooling_device_register() - register a new thermal cooling device |
1066 | * @np: a pointer to a device tree node. | ||
1056 | * @type: the thermal cooling device type. | 1067 | * @type: the thermal cooling device type. |
1057 | * @devdata: device private data. | 1068 | * @devdata: device private data. |
1058 | * @ops: standard thermal cooling devices callbacks. | 1069 | * @ops: standard thermal cooling devices callbacks. |
@@ -1060,13 +1071,16 @@ static struct class thermal_class = { | |||
1060 | * This interface function adds a new thermal cooling device (fan/processor/...) | 1071 | * This interface function adds a new thermal cooling device (fan/processor/...) |
1061 | * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself | 1072 | * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself |
1062 | * to all the thermal zone devices registered at the same time. | 1073 | * to all the thermal zone devices registered at the same time. |
1074 | * It also gives the opportunity to link the cooling device to a device tree | ||
1075 | * node, so that it can be bound to a thermal zone created out of device tree. | ||
1063 | * | 1076 | * |
1064 | * Return: a pointer to the created struct thermal_cooling_device or an | 1077 | * Return: a pointer to the created struct thermal_cooling_device or an |
1065 | * ERR_PTR. Caller must check return value with IS_ERR*() helpers. | 1078 | * ERR_PTR. Caller must check return value with IS_ERR*() helpers. |
1066 | */ | 1079 | */ |
1067 | struct thermal_cooling_device * | 1080 | static struct thermal_cooling_device * |
1068 | thermal_cooling_device_register(char *type, void *devdata, | 1081 | __thermal_cooling_device_register(struct device_node *np, |
1069 | const struct thermal_cooling_device_ops *ops) | 1082 | char *type, void *devdata, |
1083 | const struct thermal_cooling_device_ops *ops) | ||
1070 | { | 1084 | { |
1071 | struct thermal_cooling_device *cdev; | 1085 | struct thermal_cooling_device *cdev; |
1072 | int result; | 1086 | int result; |
@@ -1091,6 +1105,7 @@ thermal_cooling_device_register(char *type, void *devdata, | |||
1091 | strlcpy(cdev->type, type ? : "", sizeof(cdev->type)); | 1105 | strlcpy(cdev->type, type ? : "", sizeof(cdev->type)); |
1092 | mutex_init(&cdev->lock); | 1106 | mutex_init(&cdev->lock); |
1093 | INIT_LIST_HEAD(&cdev->thermal_instances); | 1107 | INIT_LIST_HEAD(&cdev->thermal_instances); |
1108 | cdev->np = np; | ||
1094 | cdev->ops = ops; | 1109 | cdev->ops = ops; |
1095 | cdev->updated = true; | 1110 | cdev->updated = true; |
1096 | cdev->device.class = &thermal_class; | 1111 | cdev->device.class = &thermal_class; |
@@ -1133,9 +1148,53 @@ unregister: | |||
1133 | device_unregister(&cdev->device); | 1148 | device_unregister(&cdev->device); |
1134 | return ERR_PTR(result); | 1149 | return ERR_PTR(result); |
1135 | } | 1150 | } |
1151 | |||
1152 | /** | ||
1153 | * thermal_cooling_device_register() - register a new thermal cooling device | ||
1154 | * @type: the thermal cooling device type. | ||
1155 | * @devdata: device private data. | ||
1156 | * @ops: standard thermal cooling devices callbacks. | ||
1157 | * | ||
1158 | * This interface function adds a new thermal cooling device (fan/processor/...) | ||
1159 | * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself | ||
1160 | * to all the thermal zone devices registered at the same time. | ||
1161 | * | ||
1162 | * Return: a pointer to the created struct thermal_cooling_device or an | ||
1163 | * ERR_PTR. Caller must check return value with IS_ERR*() helpers. | ||
1164 | */ | ||
1165 | struct thermal_cooling_device * | ||
1166 | thermal_cooling_device_register(char *type, void *devdata, | ||
1167 | const struct thermal_cooling_device_ops *ops) | ||
1168 | { | ||
1169 | return __thermal_cooling_device_register(NULL, type, devdata, ops); | ||
1170 | } | ||
1136 | EXPORT_SYMBOL_GPL(thermal_cooling_device_register); | 1171 | EXPORT_SYMBOL_GPL(thermal_cooling_device_register); |
1137 | 1172 | ||
1138 | /** | 1173 | /** |
1174 | * thermal_of_cooling_device_register() - register an OF thermal cooling device | ||
1175 | * @np: a pointer to a device tree node. | ||
1176 | * @type: the thermal cooling device type. | ||
1177 | * @devdata: device private data. | ||
1178 | * @ops: standard thermal cooling devices callbacks. | ||
1179 | * | ||
1180 | * This function will register a cooling device with device tree node reference. | ||
1181 | * This interface function adds a new thermal cooling device (fan/processor/...) | ||
1182 | * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself | ||
1183 | * to all the thermal zone devices registered at the same time. | ||
1184 | * | ||
1185 | * Return: a pointer to the created struct thermal_cooling_device or an | ||
1186 | * ERR_PTR. Caller must check return value with IS_ERR*() helpers. | ||
1187 | */ | ||
1188 | struct thermal_cooling_device * | ||
1189 | thermal_of_cooling_device_register(struct device_node *np, | ||
1190 | char *type, void *devdata, | ||
1191 | const struct thermal_cooling_device_ops *ops) | ||
1192 | { | ||
1193 | return __thermal_cooling_device_register(np, type, devdata, ops); | ||
1194 | } | ||
1195 | EXPORT_SYMBOL_GPL(thermal_of_cooling_device_register); | ||
1196 | |||
1197 | /** | ||
1139 | * thermal_cooling_device_unregister - removes the registered thermal cooling device | 1198 | * thermal_cooling_device_unregister - removes the registered thermal cooling device |
1140 | * @cdev: the thermal cooling device to remove. | 1199 | * @cdev: the thermal cooling device to remove. |
1141 | * | 1200 | * |
@@ -1207,6 +1266,8 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) | |||
1207 | mutex_lock(&cdev->lock); | 1266 | mutex_lock(&cdev->lock); |
1208 | /* Make sure cdev enters the deepest cooling state */ | 1267 | /* Make sure cdev enters the deepest cooling state */ |
1209 | list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) { | 1268 | list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) { |
1269 | dev_dbg(&cdev->device, "zone%d->target=%lu\n", | ||
1270 | instance->tz->id, instance->target); | ||
1210 | if (instance->target == THERMAL_NO_TARGET) | 1271 | if (instance->target == THERMAL_NO_TARGET) |
1211 | continue; | 1272 | continue; |
1212 | if (instance->target > target) | 1273 | if (instance->target > target) |
@@ -1215,6 +1276,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) | |||
1215 | mutex_unlock(&cdev->lock); | 1276 | mutex_unlock(&cdev->lock); |
1216 | cdev->ops->set_cur_state(cdev, target); | 1277 | cdev->ops->set_cur_state(cdev, target); |
1217 | cdev->updated = true; | 1278 | cdev->updated = true; |
1279 | dev_dbg(&cdev->device, "set to state %lu\n", target); | ||
1218 | } | 1280 | } |
1219 | EXPORT_SYMBOL(thermal_cdev_update); | 1281 | EXPORT_SYMBOL(thermal_cdev_update); |
1220 | 1282 | ||
@@ -1370,7 +1432,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz) | |||
1370 | */ | 1432 | */ |
1371 | struct thermal_zone_device *thermal_zone_device_register(const char *type, | 1433 | struct thermal_zone_device *thermal_zone_device_register(const char *type, |
1372 | int trips, int mask, void *devdata, | 1434 | int trips, int mask, void *devdata, |
1373 | const struct thermal_zone_device_ops *ops, | 1435 | struct thermal_zone_device_ops *ops, |
1374 | const struct thermal_zone_params *tzp, | 1436 | const struct thermal_zone_params *tzp, |
1375 | int passive_delay, int polling_delay) | 1437 | int passive_delay, int polling_delay) |
1376 | { | 1438 | { |
@@ -1386,7 +1448,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, | |||
1386 | if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips) | 1448 | if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips) |
1387 | return ERR_PTR(-EINVAL); | 1449 | return ERR_PTR(-EINVAL); |
1388 | 1450 | ||
1389 | if (!ops || !ops->get_temp) | 1451 | if (!ops) |
1390 | return ERR_PTR(-EINVAL); | 1452 | return ERR_PTR(-EINVAL); |
1391 | 1453 | ||
1392 | if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp)) | 1454 | 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, | |||
1490 | 1552 | ||
1491 | INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); | 1553 | INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); |
1492 | 1554 | ||
1555 | if (!tz->ops->get_temp) | ||
1556 | thermal_zone_device_set_polling(tz, 0); | ||
1557 | |||
1493 | thermal_zone_device_update(tz); | 1558 | thermal_zone_device_update(tz); |
1494 | 1559 | ||
1495 | if (!result) | 1560 | if (!result) |
@@ -1740,8 +1805,14 @@ static int __init thermal_init(void) | |||
1740 | if (result) | 1805 | if (result) |
1741 | goto unregister_class; | 1806 | goto unregister_class; |
1742 | 1807 | ||
1808 | result = of_parse_thermal_zones(); | ||
1809 | if (result) | ||
1810 | goto exit_netlink; | ||
1811 | |||
1743 | return 0; | 1812 | return 0; |
1744 | 1813 | ||
1814 | exit_netlink: | ||
1815 | genetlink_exit(); | ||
1745 | unregister_governors: | 1816 | unregister_governors: |
1746 | thermal_unregister_governors(); | 1817 | thermal_unregister_governors(); |
1747 | unregister_class: | 1818 | unregister_class: |
@@ -1757,6 +1828,7 @@ error: | |||
1757 | 1828 | ||
1758 | static void __exit thermal_exit(void) | 1829 | static void __exit thermal_exit(void) |
1759 | { | 1830 | { |
1831 | of_thermal_destroy_zones(); | ||
1760 | genetlink_exit(); | 1832 | genetlink_exit(); |
1761 | class_unregister(&thermal_class); | 1833 | class_unregister(&thermal_class); |
1762 | thermal_unregister_governors(); | 1834 | thermal_unregister_governors(); |