aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
authorJenny TC <jenny.tc@intel.com>2012-05-09 11:06:47 -0400
committerAnton Vorontsov <cbouatmailru@gmail.com>2012-06-18 00:25:39 -0400
commit3be330bf8860dc6079da5acc81295787a04cf4c9 (patch)
tree3d62ec1d5bcbfcee0d52f56a2193171785d3a569 /drivers/power
parent7dbae5562e86f2731d13bd2b8b3ea3f974f4b87d (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.c65
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
174static 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
192static struct thermal_zone_device_ops psy_tzd_ops = {
193 .get_temp = power_supply_read_temp,
194};
195
196static 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
213static 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
220static int psy_register_thermal(struct power_supply *psy)
221{
222 return 0;
223}
224
225static void psy_unregister_thermal(struct power_supply *psy)
226{
227}
228#endif
229
172int power_supply_register(struct device *parent, struct power_supply *psy) 230int 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
208create_triggers_failed: 270create_triggers_failed:
271 psy_unregister_thermal(psy);
272register_thermal_failed:
209 device_del(dev); 273 device_del(dev);
210kobject_set_name_failed: 274kobject_set_name_failed:
211device_add_failed: 275device_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}
225EXPORT_SYMBOL_GPL(power_supply_unregister); 290EXPORT_SYMBOL_GPL(power_supply_unregister);