in supply/pda_power.c [261:428]
static int pda_power_probe(struct platform_device *pdev)
{
struct power_supply_config psy_cfg = {};
int ret = 0;
dev = &pdev->dev;
if (pdev->id != -1) {
dev_err(dev, "it's meaningless to register several "
"pda_powers; use id = -1\n");
ret = -EINVAL;
goto wrongid;
}
pdata = pdev->dev.platform_data;
if (pdata->init) {
ret = pdata->init(dev);
if (ret < 0)
goto init_failed;
}
ac_draw = regulator_get(dev, "ac_draw");
if (IS_ERR(ac_draw)) {
dev_dbg(dev, "couldn't get ac_draw regulator\n");
ac_draw = NULL;
}
update_status();
update_charger();
if (!pdata->wait_for_status)
pdata->wait_for_status = 500;
if (!pdata->wait_for_charger)
pdata->wait_for_charger = 500;
if (!pdata->polling_interval)
pdata->polling_interval = 2000;
if (!pdata->ac_max_uA)
pdata->ac_max_uA = 500000;
INIT_DELAYED_WORK(&charger_work, charger_work_func);
INIT_DELAYED_WORK(&supply_work, supply_work_func);
ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
if (pdata->supplied_to) {
psy_cfg.supplied_to = pdata->supplied_to;
psy_cfg.num_supplicants = pdata->num_supplicants;
} else {
psy_cfg.supplied_to = pda_power_supplied_to;
psy_cfg.num_supplicants = ARRAY_SIZE(pda_power_supplied_to);
}
#if IS_ENABLED(CONFIG_USB_PHY)
transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (!IS_ERR_OR_NULL(transceiver)) {
if (!pdata->is_usb_online)
pdata->is_usb_online = otg_is_usb_online;
if (!pdata->is_ac_online)
pdata->is_ac_online = otg_is_ac_online;
}
#endif
if (pdata->is_ac_online) {
pda_psy_ac = power_supply_register(&pdev->dev,
&pda_psy_ac_desc, &psy_cfg);
if (IS_ERR(pda_psy_ac)) {
dev_err(dev, "failed to register %s power supply\n",
pda_psy_ac_desc.name);
ret = PTR_ERR(pda_psy_ac);
goto ac_supply_failed;
}
if (ac_irq) {
ret = request_irq(ac_irq->start, power_changed_isr,
get_irq_flags(ac_irq), ac_irq->name,
pda_psy_ac);
if (ret) {
dev_err(dev, "request ac irq failed\n");
goto ac_irq_failed;
}
} else {
polling = 1;
}
}
if (pdata->is_usb_online) {
pda_psy_usb = power_supply_register(&pdev->dev,
&pda_psy_usb_desc,
&psy_cfg);
if (IS_ERR(pda_psy_usb)) {
dev_err(dev, "failed to register %s power supply\n",
pda_psy_usb_desc.name);
ret = PTR_ERR(pda_psy_usb);
goto usb_supply_failed;
}
if (usb_irq) {
ret = request_irq(usb_irq->start, power_changed_isr,
get_irq_flags(usb_irq),
usb_irq->name, pda_psy_usb);
if (ret) {
dev_err(dev, "request usb irq failed\n");
goto usb_irq_failed;
}
} else {
polling = 1;
}
}
#if IS_ENABLED(CONFIG_USB_PHY)
if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
otg_nb.notifier_call = otg_handle_notification;
ret = usb_register_notifier(transceiver, &otg_nb);
if (ret) {
dev_err(dev, "failure to register otg notifier\n");
goto otg_reg_notifier_failed;
}
polling = 0;
}
#endif
if (polling) {
dev_dbg(dev, "will poll for status\n");
INIT_DELAYED_WORK(&polling_work, polling_work_func);
cancel_delayed_work(&polling_work);
schedule_delayed_work(&polling_work,
msecs_to_jiffies(pdata->polling_interval));
}
if (ac_irq || usb_irq)
device_init_wakeup(&pdev->dev, 1);
return 0;
#if IS_ENABLED(CONFIG_USB_PHY)
otg_reg_notifier_failed:
if (pdata->is_usb_online && usb_irq)
free_irq(usb_irq->start, pda_psy_usb);
#endif
usb_irq_failed:
if (pdata->is_usb_online)
power_supply_unregister(pda_psy_usb);
usb_supply_failed:
if (pdata->is_ac_online && ac_irq)
free_irq(ac_irq->start, pda_psy_ac);
#if IS_ENABLED(CONFIG_USB_PHY)
if (!IS_ERR_OR_NULL(transceiver))
usb_put_phy(transceiver);
#endif
ac_irq_failed:
if (pdata->is_ac_online)
power_supply_unregister(pda_psy_ac);
ac_supply_failed:
if (ac_draw) {
regulator_put(ac_draw);
ac_draw = NULL;
}
if (pdata->exit)
pdata->exit(dev);
init_failed:
wrongid:
return ret;
}