aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/power/power_supply_core.c96
-rw-r--r--include/linux/power_supply.h1
2 files changed, 97 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}
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 445b4b249af5..1f0ab90aff00 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -188,6 +188,7 @@ struct power_supply {
188 struct work_struct changed_work; 188 struct work_struct changed_work;
189#ifdef CONFIG_THERMAL 189#ifdef CONFIG_THERMAL
190 struct thermal_zone_device *tzd; 190 struct thermal_zone_device *tzd;
191 struct thermal_cooling_device *tcd;
191#endif 192#endif
192 193
193#ifdef CONFIG_LEDS_TRIGGERS 194#ifdef CONFIG_LEDS_TRIGGERS