diff options
-rw-r--r-- | drivers/power/power_supply_core.c | 96 | ||||
-rw-r--r-- | include/linux/power_supply.h | 1 |
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 */ | ||
221 | static 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 | |||
237 | static 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 | |||
253 | static 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 | |||
268 | static 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 | |||
274 | static 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 | |||
293 | static 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 |
220 | static int psy_register_thermal(struct power_supply *psy) | 300 | static int psy_register_thermal(struct power_supply *psy) |
221 | { | 301 | { |
@@ -225,6 +305,15 @@ static int psy_register_thermal(struct power_supply *psy) | |||
225 | static void psy_unregister_thermal(struct power_supply *psy) | 305 | static void psy_unregister_thermal(struct power_supply *psy) |
226 | { | 306 | { |
227 | } | 307 | } |
308 | |||
309 | static int psy_register_cooler(struct power_supply *psy) | ||
310 | { | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static void psy_unregister_cooler(struct power_supply *psy) | ||
315 | { | ||
316 | } | ||
228 | #endif | 317 | #endif |
229 | 318 | ||
230 | int power_supply_register(struct device *parent, struct power_supply *psy) | 319 | int 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 | ||
270 | create_triggers_failed: | 363 | create_triggers_failed: |
364 | psy_unregister_cooler(psy); | ||
365 | register_cooler_failed: | ||
271 | psy_unregister_thermal(psy); | 366 | psy_unregister_thermal(psy); |
272 | register_thermal_failed: | 367 | register_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 |