aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
authorRamakrishna Pallala <ramakrishna.pallala@intel.com>2012-10-09 12:55:59 -0400
committerAnton Vorontsov <anton.vorontsov@linaro.org>2012-11-17 23:32:33 -0500
commit952aeeb3ee28bc12a70744e40636de40688eb60d (patch)
tree4690ab3549e59edee53e24df60f33295f96c0359 /drivers/power
parentea2ce92e44dc83b7a69c2aedd9c52bfe7fee1a62 (diff)
power_supply: Register power supply for thermal cooling device
This patch registers the power supply as a cooling device if the power supply has support for charge throttling. Now with this change low level drivers need not register with thermal framework as it is automatically done by power supply framework. Signed-off-by: Ramakrishna Pallala <ramakrishna.pallala@intel.com> Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/power_supply_core.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 2436f1350013..f984da1066ec 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -216,6 +216,86 @@ static void psy_unregister_thermal(struct power_supply *psy)
216 return; 216 return;
217 thermal_zone_device_unregister(psy->tzd); 217 thermal_zone_device_unregister(psy->tzd);
218} 218}
219
220/* thermal cooling device callbacks */
221static int ps_get_max_charge_cntl_limit(struct thermal_cooling_device *tcd,
222 unsigned long *state)
223{
224 struct power_supply *psy;
225 union power_supply_propval val;
226 int ret;
227
228 psy = tcd->devdata;
229 ret = psy->get_property(psy,
230 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, &val);
231 if (!ret)
232 *state = val.intval;
233
234 return ret;
235}
236
237static int ps_get_cur_chrage_cntl_limit(struct thermal_cooling_device *tcd,
238 unsigned long *state)
239{
240 struct power_supply *psy;
241 union power_supply_propval val;
242 int ret;
243
244 psy = tcd->devdata;
245 ret = psy->get_property(psy,
246 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val);
247 if (!ret)
248 *state = val.intval;
249
250 return ret;
251}
252
253static int ps_set_cur_charge_cntl_limit(struct thermal_cooling_device *tcd,
254 unsigned long state)
255{
256 struct power_supply *psy;
257 union power_supply_propval val;
258 int ret;
259
260 psy = tcd->devdata;
261 val.intval = state;
262 ret = psy->set_property(psy,
263 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val);
264
265 return ret;
266}
267
268static struct thermal_cooling_device_ops psy_tcd_ops = {
269 .get_max_state = ps_get_max_charge_cntl_limit,
270 .get_cur_state = ps_get_cur_chrage_cntl_limit,
271 .set_cur_state = ps_set_cur_charge_cntl_limit,
272};
273
274static int psy_register_cooler(struct power_supply *psy)
275{
276 int i;
277
278 /* Register for cooling device if psy can control charging */
279 for (i = 0; i < psy->num_properties; i++) {
280 if (psy->properties[i] ==
281 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT) {
282 psy->tcd = thermal_cooling_device_register(
283 (char *)psy->name,
284 psy, &psy_tcd_ops);
285 if (IS_ERR(psy->tcd))
286 return PTR_ERR(psy->tcd);
287 break;
288 }
289 }
290 return 0;
291}
292
293static void psy_unregister_cooler(struct power_supply *psy)
294{
295 if (IS_ERR_OR_NULL(psy->tcd))
296 return;
297 thermal_cooling_device_unregister(psy->tcd);
298}
219#else 299#else
220static int psy_register_thermal(struct power_supply *psy) 300static int psy_register_thermal(struct power_supply *psy)
221{ 301{
@@ -225,6 +305,15 @@ static int psy_register_thermal(struct power_supply *psy)
225static void psy_unregister_thermal(struct power_supply *psy) 305static void psy_unregister_thermal(struct power_supply *psy)
226{ 306{
227} 307}
308
309static int psy_register_cooler(struct power_supply *psy)
310{
311 return 0;
312}
313
314static void psy_unregister_cooler(struct power_supply *psy)
315{
316}
228#endif 317#endif
229 318
230int power_supply_register(struct device *parent, struct power_supply *psy) 319int power_supply_register(struct device *parent, struct power_supply *psy)
@@ -259,6 +348,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
259 if (rc) 348 if (rc)
260 goto register_thermal_failed; 349 goto register_thermal_failed;
261 350
351 rc = psy_register_cooler(psy);
352 if (rc)
353 goto register_cooler_failed;
354
262 rc = power_supply_create_triggers(psy); 355 rc = power_supply_create_triggers(psy);
263 if (rc) 356 if (rc)
264 goto create_triggers_failed; 357 goto create_triggers_failed;
@@ -268,6 +361,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
268 goto success; 361 goto success;
269 362
270create_triggers_failed: 363create_triggers_failed:
364 psy_unregister_cooler(psy);
365register_cooler_failed:
271 psy_unregister_thermal(psy); 366 psy_unregister_thermal(psy);
272register_thermal_failed: 367register_thermal_failed:
273 device_del(dev); 368 device_del(dev);
@@ -284,6 +379,7 @@ void power_supply_unregister(struct power_supply *psy)
284 cancel_work_sync(&psy->changed_work); 379 cancel_work_sync(&psy->changed_work);
285 sysfs_remove_link(&psy->dev->kobj, "powers"); 380 sysfs_remove_link(&psy->dev->kobj, "powers");
286 power_supply_remove_triggers(psy); 381 power_supply_remove_triggers(psy);
382 psy_unregister_cooler(psy);
287 psy_unregister_thermal(psy); 383 psy_unregister_thermal(psy);
288 device_unregister(psy->dev); 384 device_unregister(psy->dev);
289} 385}