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
25static inline unsigned int get_irq_flags(struct resource *res)
26{
27	return IRQF_SHARED | (res->flags & IRQF_TRIGGER_MASK);
28}
29
30static struct device *dev;
31static struct pda_power_pdata *pdata;
32static struct resource *ac_irq, *usb_irq;
33static struct timer_list charger_timer;
34static struct timer_list supply_timer;
35static struct timer_list polling_timer;
36static int polling;
37static struct power_supply *pda_psy_ac, *pda_psy_usb;
38
39#if IS_ENABLED(CONFIG_USB_PHY)
40static struct usb_phy *transceiver;
41static struct notifier_block otg_nb;
42#endif
43
44static struct regulator *ac_draw;
45
46enum {
47	PDA_PSY_OFFLINE = 0,
48	PDA_PSY_ONLINE = 1,
49	PDA_PSY_TO_CHANGE,
50};
51static int new_ac_status = -1;
52static int new_usb_status = -1;
53static int ac_status = -1;
54static int usb_status = -1;
55
56static 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
75static enum power_supply_property pda_power_props[] = {
76	POWER_SUPPLY_PROP_ONLINE,
77};
78
79static char *pda_power_supplied_to[] = {
80	"main-battery",
81	"backup-battery",
82};
83
84static 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
92static 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
100static 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
109static 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
143static 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
156static 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
168static void charger_timer_func(unsigned long unused)
169{
170	update_status();
171	psy_changed();
172}
173
174static 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
193static 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)
219static int otg_is_usb_online(void)
220{
221	return (transceiver->last_event == USB_EVENT_VBUS ||
222		transceiver->last_event == USB_EVENT_ENUMERATED);
223}
224
225static int otg_is_ac_online(void)
226{
227	return (transceiver->last_event == USB_EVENT_CHARGER);
228}
229
230static 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
260static 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)
399otg_reg_notifier_failed:
400	if (pdata->is_usb_online && usb_irq)
401		free_irq(usb_irq->start, pda_psy_usb);
402#endif
403usb_irq_failed:
404	if (pdata->is_usb_online)
405		power_supply_unregister(pda_psy_usb);
406usb_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
413ac_irq_failed:
414	if (pdata->is_ac_online)
415		power_supply_unregister(pda_psy_ac);
416ac_supply_failed:
417	if (ac_draw) {
418		regulator_put(ac_draw);
419		ac_draw = NULL;
420	}
421	if (pdata->exit)
422		pdata->exit(dev);
423init_failed:
424wrongid:
425	return ret;
426}
427
428static 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
459static int ac_wakeup_enabled;
460static int usb_wakeup_enabled;
461
462static 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
481static 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
500static 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
510module_platform_driver(pda_power_pdrv);
511
512MODULE_LICENSE("GPL");
513MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
514MODULE_ALIAS("platform:pda-power");
515