diff options
author | Jenny TC <jenny.tc@intel.com> | 2012-05-09 11:06:47 -0400 |
---|---|---|
committer | Anton Vorontsov <cbouatmailru@gmail.com> | 2012-06-18 00:25:39 -0400 |
commit | 3be330bf8860dc6079da5acc81295787a04cf4c9 (patch) | |
tree | 3d62ec1d5bcbfcee0d52f56a2193171785d3a569 /drivers/power | |
parent | 7dbae5562e86f2731d13bd2b8b3ea3f974f4b87d (diff) |
power_supply: Register battery as a thermal zone
Battery and charger contribute to Thermals in most of the embedded
devices. So, it makes sense to identify them as Thermal zones in a
particular platform.
This patch registers a thermal zone if the power supply is reporting
a temperature property. The thermal zone will be used by platform's
thermal management solution.
Signed-off-by: Jenny TC <jenny.tc@intel.com>
Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/power_supply_core.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 6ad61272678..ff990d26a0c 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/power_supply.h> | 19 | #include <linux/power_supply.h> |
20 | #include <linux/thermal.h> | ||
20 | #include "power_supply.h" | 21 | #include "power_supply.h" |
21 | 22 | ||
22 | /* exported for the APM Power driver, APM emulation */ | 23 | /* exported for the APM Power driver, APM emulation */ |
@@ -169,6 +170,63 @@ static void power_supply_dev_release(struct device *dev) | |||
169 | kfree(dev); | 170 | kfree(dev); |
170 | } | 171 | } |
171 | 172 | ||
173 | #ifdef CONFIG_THERMAL | ||
174 | static int power_supply_read_temp(struct thermal_zone_device *tzd, | ||
175 | unsigned long *temp) | ||
176 | { | ||
177 | struct power_supply *psy; | ||
178 | union power_supply_propval val; | ||
179 | int ret; | ||
180 | |||
181 | WARN_ON(tzd == NULL); | ||
182 | psy = tzd->devdata; | ||
183 | ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val); | ||
184 | |||
185 | /* Convert tenths of degree Celsius to milli degree Celsius. */ | ||
186 | if (!ret) | ||
187 | *temp = val.intval * 100; | ||
188 | |||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static struct thermal_zone_device_ops psy_tzd_ops = { | ||
193 | .get_temp = power_supply_read_temp, | ||
194 | }; | ||
195 | |||
196 | static int psy_register_thermal(struct power_supply *psy) | ||
197 | { | ||
198 | int i; | ||
199 | |||
200 | /* Register battery zone device psy reports temperature */ | ||
201 | for (i = 0; i < psy->num_properties; i++) { | ||
202 | if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) { | ||
203 | psy->tzd = thermal_zone_device_register(psy->name, 0, | ||
204 | psy, &psy_tzd_ops, 0, 0, 0, 0); | ||
205 | if (IS_ERR(psy->tzd)) | ||
206 | return PTR_ERR(psy->tzd); | ||
207 | break; | ||
208 | } | ||
209 | } | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static void psy_unregister_thermal(struct power_supply *psy) | ||
214 | { | ||
215 | if (IS_ERR_OR_NULL(psy->tzd)) | ||
216 | return; | ||
217 | thermal_zone_device_unregister(psy->tzd); | ||
218 | } | ||
219 | #else | ||
220 | static int psy_register_thermal(struct power_supply *psy) | ||
221 | { | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static void psy_unregister_thermal(struct power_supply *psy) | ||
226 | { | ||
227 | } | ||
228 | #endif | ||
229 | |||
172 | int power_supply_register(struct device *parent, struct power_supply *psy) | 230 | int power_supply_register(struct device *parent, struct power_supply *psy) |
173 | { | 231 | { |
174 | struct device *dev; | 232 | struct device *dev; |
@@ -197,6 +255,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy) | |||
197 | if (rc) | 255 | if (rc) |
198 | goto device_add_failed; | 256 | goto device_add_failed; |
199 | 257 | ||
258 | rc = psy_register_thermal(psy); | ||
259 | if (rc) | ||
260 | goto register_thermal_failed; | ||
261 | |||
200 | rc = power_supply_create_triggers(psy); | 262 | rc = power_supply_create_triggers(psy); |
201 | if (rc) | 263 | if (rc) |
202 | goto create_triggers_failed; | 264 | goto create_triggers_failed; |
@@ -206,6 +268,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy) | |||
206 | goto success; | 268 | goto success; |
207 | 269 | ||
208 | create_triggers_failed: | 270 | create_triggers_failed: |
271 | psy_unregister_thermal(psy); | ||
272 | register_thermal_failed: | ||
209 | device_del(dev); | 273 | device_del(dev); |
210 | kobject_set_name_failed: | 274 | kobject_set_name_failed: |
211 | device_add_failed: | 275 | device_add_failed: |
@@ -220,6 +284,7 @@ void power_supply_unregister(struct power_supply *psy) | |||
220 | cancel_work_sync(&psy->changed_work); | 284 | cancel_work_sync(&psy->changed_work); |
221 | sysfs_remove_link(&psy->dev->kobj, "powers"); | 285 | sysfs_remove_link(&psy->dev->kobj, "powers"); |
222 | power_supply_remove_triggers(psy); | 286 | power_supply_remove_triggers(psy); |
287 | psy_unregister_thermal(psy); | ||
223 | device_unregister(psy->dev); | 288 | device_unregister(psy->dev); |
224 | } | 289 | } |
225 | EXPORT_SYMBOL_GPL(power_supply_unregister); | 290 | EXPORT_SYMBOL_GPL(power_supply_unregister); |