1 /*
2  * Common power driver for PDAs and phones with one or two external
3  * power supplies (AC/USB) connected to main and backup batteries,
4  * and optional builtin charger.
5  *
6  * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12 
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/err.h>
16 #include <linux/interrupt.h>
17 #include <linux/notifier.h>
18 #include <linux/power_supply.h>
19 #include <linux/pda_power.h>
20 #include <linux/regulator/consumer.h>
21 #include <linux/timer.h>
22 #include <linux/jiffies.h>
23 #include <linux/usb/otg.h>
24 
get_irq_flags(struct resource * res)25 static inline unsigned int get_irq_flags(struct resource *res)
26 {
27 	return IRQF_SHARED | (res->flags & IRQF_TRIGGER_MASK);
28 }
29 
30 static struct device *dev;
31 static struct pda_power_pdata *pdata;
32 static struct resource *ac_irq, *usb_irq;
33 static struct timer_list charger_timer;
34 static struct timer_list supply_timer;
35 static struct timer_list polling_timer;
36 static int polling;
37 static struct power_supply *pda_psy_ac, *pda_psy_usb;
38 
39 #if IS_ENABLED(CONFIG_USB_PHY)
40 static struct usb_phy *transceiver;
41 static struct notifier_block otg_nb;
42 #endif
43 
44 static struct regulator *ac_draw;
45 
46 enum {
47 	PDA_PSY_OFFLINE = 0,
48 	PDA_PSY_ONLINE = 1,
49 	PDA_PSY_TO_CHANGE,
50 };
51 static int new_ac_status = -1;
52 static int new_usb_status = -1;
53 static int ac_status = -1;
54 static int usb_status = -1;
55 
pda_power_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)56 static int pda_power_get_property(struct power_supply *psy,
57 				  enum power_supply_property psp,
58 				  union power_supply_propval *val)
59 {
60 	switch (psp) {
61 	case POWER_SUPPLY_PROP_ONLINE:
62 		if (psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
63 			val->intval = pdata->is_ac_online ?
64 				      pdata->is_ac_online() : 0;
65 		else
66 			val->intval = pdata->is_usb_online ?
67 				      pdata->is_usb_online() : 0;
68 		break;
69 	default:
70 		return -EINVAL;
71 	}
72 	return 0;
73 }
74 
75 static enum power_supply_property pda_power_props[] = {
76 	POWER_SUPPLY_PROP_ONLINE,
77 };
78 
79 static char *pda_power_supplied_to[] = {
80 	"main-battery",
81 	"backup-battery",
82 };
83 
84 static const struct power_supply_desc pda_psy_ac_desc = {
85 	.name = "ac",
86 	.type = POWER_SUPPLY_TYPE_MAINS,
87 	.properties = pda_power_props,
88 	.num_properties = ARRAY_SIZE(pda_power_props),
89 	.get_property = pda_power_get_property,
90 };
91 
92 static const struct power_supply_desc pda_psy_usb_desc = {
93 	.name = "usb",
94 	.type = POWER_SUPPLY_TYPE_USB,
95 	.properties = pda_power_props,
96 	.num_properties = ARRAY_SIZE(pda_power_props),
97 	.get_property = pda_power_get_property,
98 };
99 
update_status(void)100 static void update_status(void)
101 {
102 	if (pdata->is_ac_online)
103 		new_ac_status = !!pdata->is_ac_online();
104 
105 	if (pdata->is_usb_online)
106 		new_usb_status = !!pdata->is_usb_online();
107 }
108 
update_charger(void)109 static void update_charger(void)
110 {
111 	static int regulator_enabled;
112 	int max_uA = pdata->ac_max_uA;
113 
114 	if (pdata->set_charge) {
115 		if (new_ac_status > 0) {
116 			dev_dbg(dev, "charger on (AC)\n");
117 			pdata->set_charge(PDA_POWER_CHARGE_AC);
118 		} else if (new_usb_status > 0) {
119 			dev_dbg(dev, "charger on (USB)\n");
120 			pdata->set_charge(PDA_POWER_CHARGE_USB);
121 		} else {
122 			dev_dbg(dev, "charger off\n");
123 			pdata->set_charge(0);
124 		}
125 	} else if (ac_draw) {
126 		if (new_ac_status > 0) {
127 			regulator_set_current_limit(ac_draw, max_uA, max_uA);
128 			if (!regulator_enabled) {
129 				dev_dbg(dev, "charger on (AC)\n");
130 				WARN_ON(regulator_enable(ac_draw));
131 				regulator_enabled = 1;
132 			}
133 		} else {
134 			if (regulator_enabled) {
135 				dev_dbg(dev, "charger off\n");
136 				WARN_ON(regulator_disable(ac_draw));
137 				regulator_enabled = 0;
138 			}
139 		}
140 	}
141 }
142 
supply_timer_func(unsigned long unused)143 static void supply_timer_func(unsigned long unused)
144 {
145 	if (ac_status == PDA_PSY_TO_CHANGE) {
146 		ac_status = new_ac_status;
147 		power_supply_changed(pda_psy_ac);
148 	}
149 
150 	if (usb_status == PDA_PSY_TO_CHANGE) {
151 		usb_status = new_usb_status;
152 		power_supply_changed(pda_psy_usb);
153 	}
154 }
155 
psy_changed(void)156 static void psy_changed(void)
157 {
158 	update_charger();
159 
160 	/*
161 	 * Okay, charger set. Now wait a bit before notifying supplicants,
162 	 * charge power should stabilize.
163 	 */
164 	mod_timer(&supply_timer,
165 		  jiffies + msecs_to_jiffies(pdata->wait_for_charger));
166 }
167 
charger_timer_func(unsigned long unused)168 static void charger_timer_func(unsigned long unused)
169 {
170 	update_status();
171 	psy_changed();
172 }
173 
power_changed_isr(int irq,void * power_supply)174 static irqreturn_t power_changed_isr(int irq, void *power_supply)
175 {
176 	if (power_supply == pda_psy_ac)
177 		ac_status = PDA_PSY_TO_CHANGE;
178 	else if (power_supply == pda_psy_usb)
179 		usb_status = PDA_PSY_TO_CHANGE;
180 	else
181 		return IRQ_NONE;
182 
183 	/*
184 	 * Wait a bit before reading ac/usb line status and setting charger,
185 	 * because ac/usb status readings may lag from irq.
186 	 */
187 	mod_timer(&charger_timer,
188 		  jiffies + msecs_to_jiffies(pdata->wait_for_status));
189 
190 	return IRQ_HANDLED;
191 }
192 
polling_timer_func(unsigned long unused)193 static void polling_timer_func(unsigned long unused)
194 {
195 	int changed = 0;
196 
197 	dev_dbg(dev, "polling...\n");
198 
199 	update_status();
200 
201 	if (!ac_irq && new_ac_status != ac_status) {
202 		ac_status = PDA_PSY_TO_CHANGE;
203 		changed = 1;
204 	}
205 
206 	if (!usb_irq && new_usb_status != usb_status) {
207 		usb_status = PDA_PSY_TO_CHANGE;
208 		changed = 1;
209 	}
210 
211 	if (changed)
212 		psy_changed();
213 
214 	mod_timer(&polling_timer,
215 		  jiffies + msecs_to_jiffies(pdata->polling_interval));
216 }
217 
218 #if IS_ENABLED(CONFIG_USB_PHY)
otg_is_usb_online(void)219 static int otg_is_usb_online(void)
220 {
221 	return (transceiver->last_event == USB_EVENT_VBUS ||
222 		transceiver->last_event == USB_EVENT_ENUMERATED);
223 }
224 
otg_is_ac_online(void)225 static int otg_is_ac_online(void)
226 {
227 	return (transceiver->last_event == USB_EVENT_CHARGER);
228 }
229 
otg_handle_notification(struct notifier_block * nb,unsigned long event,void * unused)230 static int otg_handle_notification(struct notifier_block *nb,
231 		unsigned long event, void *unused)
232 {
233 	switch (event) {
234 	case USB_EVENT_CHARGER:
235 		ac_status = PDA_PSY_TO_CHANGE;
236 		break;
237 	case USB_EVENT_VBUS:
238 	case USB_EVENT_ENUMERATED:
239 		usb_status = PDA_PSY_TO_CHANGE;
240 		break;
241 	case USB_EVENT_NONE:
242 		ac_status = PDA_PSY_TO_CHANGE;
243 		usb_status = PDA_PSY_TO_CHANGE;
244 		break;
245 	default:
246 		return NOTIFY_OK;
247 	}
248 
249 	/*
250 	 * Wait a bit before reading ac/usb line status and setting charger,
251 	 * because ac/usb status readings may lag from irq.
252 	 */
253 	mod_timer(&charger_timer,
254 		  jiffies + msecs_to_jiffies(pdata->wait_for_status));
255 
256 	return NOTIFY_OK;
257 }
258 #endif
259 
pda_power_probe(struct platform_device * pdev)260 static int pda_power_probe(struct platform_device *pdev)
261 {
262 	struct power_supply_config psy_cfg = {};
263 	int ret = 0;
264 
265 	dev = &pdev->dev;
266 
267 	if (pdev->id != -1) {
268 		dev_err(dev, "it's meaningless to register several "
269 			"pda_powers; use id = -1\n");
270 		ret = -EINVAL;
271 		goto wrongid;
272 	}
273 
274 	pdata = pdev->dev.platform_data;
275 
276 	if (pdata->init) {
277 		ret = pdata->init(dev);
278 		if (ret < 0)
279 			goto init_failed;
280 	}
281 
282 	ac_draw = regulator_get(dev, "ac_draw");
283 	if (IS_ERR(ac_draw)) {
284 		dev_dbg(dev, "couldn't get ac_draw regulator\n");
285 		ac_draw = NULL;
286 	}
287 
288 	update_status();
289 	update_charger();
290 
291 	if (!pdata->wait_for_status)
292 		pdata->wait_for_status = 500;
293 
294 	if (!pdata->wait_for_charger)
295 		pdata->wait_for_charger = 500;
296 
297 	if (!pdata->polling_interval)
298 		pdata->polling_interval = 2000;
299 
300 	if (!pdata->ac_max_uA)
301 		pdata->ac_max_uA = 500000;
302 
303 	setup_timer(&charger_timer, charger_timer_func, 0);
304 	setup_timer(&supply_timer, supply_timer_func, 0);
305 
306 	ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
307 	usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
308 
309 	if (pdata->supplied_to) {
310 		psy_cfg.supplied_to = pdata->supplied_to;
311 		psy_cfg.num_supplicants = pdata->num_supplicants;
312 	} else {
313 		psy_cfg.supplied_to = pda_power_supplied_to;
314 		psy_cfg.num_supplicants = ARRAY_SIZE(pda_power_supplied_to);
315 	}
316 
317 #if IS_ENABLED(CONFIG_USB_PHY)
318 	transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
319 	if (!IS_ERR_OR_NULL(transceiver)) {
320 		if (!pdata->is_usb_online)
321 			pdata->is_usb_online = otg_is_usb_online;
322 		if (!pdata->is_ac_online)
323 			pdata->is_ac_online = otg_is_ac_online;
324 	}
325 #endif
326 
327 	if (pdata->is_ac_online) {
328 		pda_psy_ac = power_supply_register(&pdev->dev,
329 						   &pda_psy_ac_desc, &psy_cfg);
330 		if (IS_ERR(pda_psy_ac)) {
331 			dev_err(dev, "failed to register %s power supply\n",
332 				pda_psy_ac_desc.name);
333 			ret = PTR_ERR(pda_psy_ac);
334 			goto ac_supply_failed;
335 		}
336 
337 		if (ac_irq) {
338 			ret = request_irq(ac_irq->start, power_changed_isr,
339 					  get_irq_flags(ac_irq), ac_irq->name,
340 					  pda_psy_ac);
341 			if (ret) {
342 				dev_err(dev, "request ac irq failed\n");
343 				goto ac_irq_failed;
344 			}
345 		} else {
346 			polling = 1;
347 		}
348 	}
349 
350 	if (pdata->is_usb_online) {
351 		pda_psy_usb = power_supply_register(&pdev->dev,
352 						    &pda_psy_usb_desc,
353 						    &psy_cfg);
354 		if (IS_ERR(pda_psy_usb)) {
355 			dev_err(dev, "failed to register %s power supply\n",
356 				pda_psy_usb_desc.name);
357 			ret = PTR_ERR(pda_psy_usb);
358 			goto usb_supply_failed;
359 		}
360 
361 		if (usb_irq) {
362 			ret = request_irq(usb_irq->start, power_changed_isr,
363 					  get_irq_flags(usb_irq),
364 					  usb_irq->name, pda_psy_usb);
365 			if (ret) {
366 				dev_err(dev, "request usb irq failed\n");
367 				goto usb_irq_failed;
368 			}
369 		} else {
370 			polling = 1;
371 		}
372 	}
373 
374 #if IS_ENABLED(CONFIG_USB_PHY)
375 	if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
376 		otg_nb.notifier_call = otg_handle_notification;
377 		ret = usb_register_notifier(transceiver, &otg_nb);
378 		if (ret) {
379 			dev_err(dev, "failure to register otg notifier\n");
380 			goto otg_reg_notifier_failed;
381 		}
382 		polling = 0;
383 	}
384 #endif
385 
386 	if (polling) {
387 		dev_dbg(dev, "will poll for status\n");
388 		setup_timer(&polling_timer, polling_timer_func, 0);
389 		mod_timer(&polling_timer,
390 			  jiffies + msecs_to_jiffies(pdata->polling_interval));
391 	}
392 
393 	if (ac_irq || usb_irq)
394 		device_init_wakeup(&pdev->dev, 1);
395 
396 	return 0;
397 
398 #if IS_ENABLED(CONFIG_USB_PHY)
399 otg_reg_notifier_failed:
400 	if (pdata->is_usb_online && usb_irq)
401 		free_irq(usb_irq->start, pda_psy_usb);
402 #endif
403 usb_irq_failed:
404 	if (pdata->is_usb_online)
405 		power_supply_unregister(pda_psy_usb);
406 usb_supply_failed:
407 	if (pdata->is_ac_online && ac_irq)
408 		free_irq(ac_irq->start, pda_psy_ac);
409 #if IS_ENABLED(CONFIG_USB_PHY)
410 	if (!IS_ERR_OR_NULL(transceiver))
411 		usb_put_phy(transceiver);
412 #endif
413 ac_irq_failed:
414 	if (pdata->is_ac_online)
415 		power_supply_unregister(pda_psy_ac);
416 ac_supply_failed:
417 	if (ac_draw) {
418 		regulator_put(ac_draw);
419 		ac_draw = NULL;
420 	}
421 	if (pdata->exit)
422 		pdata->exit(dev);
423 init_failed:
424 wrongid:
425 	return ret;
426 }
427 
pda_power_remove(struct platform_device * pdev)428 static int pda_power_remove(struct platform_device *pdev)
429 {
430 	if (pdata->is_usb_online && usb_irq)
431 		free_irq(usb_irq->start, pda_psy_usb);
432 	if (pdata->is_ac_online && ac_irq)
433 		free_irq(ac_irq->start, pda_psy_ac);
434 
435 	if (polling)
436 		del_timer_sync(&polling_timer);
437 	del_timer_sync(&charger_timer);
438 	del_timer_sync(&supply_timer);
439 
440 	if (pdata->is_usb_online)
441 		power_supply_unregister(pda_psy_usb);
442 	if (pdata->is_ac_online)
443 		power_supply_unregister(pda_psy_ac);
444 #if IS_ENABLED(CONFIG_USB_PHY)
445 	if (!IS_ERR_OR_NULL(transceiver))
446 		usb_put_phy(transceiver);
447 #endif
448 	if (ac_draw) {
449 		regulator_put(ac_draw);
450 		ac_draw = NULL;
451 	}
452 	if (pdata->exit)
453 		pdata->exit(dev);
454 
455 	return 0;
456 }
457 
458 #ifdef CONFIG_PM
459 static int ac_wakeup_enabled;
460 static int usb_wakeup_enabled;
461 
pda_power_suspend(struct platform_device * pdev,pm_message_t state)462 static int pda_power_suspend(struct platform_device *pdev, pm_message_t state)
463 {
464 	if (pdata->suspend) {
465 		int ret = pdata->suspend(state);
466 
467 		if (ret)
468 			return ret;
469 	}
470 
471 	if (device_may_wakeup(&pdev->dev)) {
472 		if (ac_irq)
473 			ac_wakeup_enabled = !enable_irq_wake(ac_irq->start);
474 		if (usb_irq)
475 			usb_wakeup_enabled = !enable_irq_wake(usb_irq->start);
476 	}
477 
478 	return 0;
479 }
480 
pda_power_resume(struct platform_device * pdev)481 static int pda_power_resume(struct platform_device *pdev)
482 {
483 	if (device_may_wakeup(&pdev->dev)) {
484 		if (usb_irq && usb_wakeup_enabled)
485 			disable_irq_wake(usb_irq->start);
486 		if (ac_irq && ac_wakeup_enabled)
487 			disable_irq_wake(ac_irq->start);
488 	}
489 
490 	if (pdata->resume)
491 		return pdata->resume();
492 
493 	return 0;
494 }
495 #else
496 #define pda_power_suspend NULL
497 #define pda_power_resume NULL
498 #endif /* CONFIG_PM */
499 
500 static struct platform_driver pda_power_pdrv = {
501 	.driver = {
502 		.name = "pda-power",
503 	},
504 	.probe = pda_power_probe,
505 	.remove = pda_power_remove,
506 	.suspend = pda_power_suspend,
507 	.resume = pda_power_resume,
508 };
509 
510 module_platform_driver(pda_power_pdrv);
511 
512 MODULE_LICENSE("GPL");
513 MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
514 MODULE_ALIAS("platform:pda-power");
515