diff options
Diffstat (limited to 'drivers/power/wm831x_power.c')
| -rw-r--r-- | drivers/power/wm831x_power.c | 107 |
1 files changed, 67 insertions, 40 deletions
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c index ddf8cf5f320..3bed2f55cf7 100644 --- a/drivers/power/wm831x_power.c +++ b/drivers/power/wm831x_power.c @@ -24,6 +24,10 @@ struct wm831x_power { struct power_supply wall; struct power_supply usb; struct power_supply battery; + char wall_name[20]; + char usb_name[20]; + char battery_name[20]; + bool have_battery; }; static int wm831x_power_check_online(struct wm831x *wm831x, int supply, @@ -446,7 +450,8 @@ static irqreturn_t wm831x_bat_irq(int irq, void *data) /* The battery charger is autonomous so we don't need to do * anything except kick user space */ - power_supply_changed(&wm831x_power->battery); + if (wm831x_power->have_battery) + power_supply_changed(&wm831x_power->battery); return IRQ_HANDLED; } @@ -476,16 +481,18 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data) dev_dbg(wm831x->dev, "Power source changed\n"); /* Just notify for everything - little harm in overnotifying. */ - power_supply_changed(&wm831x_power->battery); + if (wm831x_power->have_battery) + power_supply_changed(&wm831x_power->battery); power_supply_changed(&wm831x_power->usb); power_supply_changed(&wm831x_power->wall); return IRQ_HANDLED; } -static __devinit int wm831x_power_probe(struct platform_device *pdev) +static int wm831x_power_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); + struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data; struct wm831x_power *power; struct power_supply *usb; struct power_supply *battery; @@ -503,12 +510,28 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) battery = &power->battery; wall = &power->wall; + if (wm831x_pdata && wm831x_pdata->wm831x_num) { + snprintf(power->wall_name, sizeof(power->wall_name), + "wm831x-wall.%d", wm831x_pdata->wm831x_num); + snprintf(power->battery_name, sizeof(power->wall_name), + "wm831x-battery.%d", wm831x_pdata->wm831x_num); + snprintf(power->usb_name, sizeof(power->wall_name), + "wm831x-usb.%d", wm831x_pdata->wm831x_num); + } else { + snprintf(power->wall_name, sizeof(power->wall_name), + "wm831x-wall"); + snprintf(power->battery_name, sizeof(power->wall_name), + "wm831x-battery"); + snprintf(power->usb_name, sizeof(power->wall_name), + "wm831x-usb"); + } + /* We ignore configuration failures since we can still read back * the status without enabling the charger. */ wm831x_config_battery(wm831x); - wall->name = "wm831x-wall"; + wall->name = power->wall_name; wall->type = POWER_SUPPLY_TYPE_MAINS; wall->properties = wm831x_wall_props; wall->num_properties = ARRAY_SIZE(wm831x_wall_props); @@ -517,35 +540,42 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) if (ret) goto err_kmalloc; - battery->name = "wm831x-battery"; - battery->properties = wm831x_bat_props; - battery->num_properties = ARRAY_SIZE(wm831x_bat_props); - battery->get_property = wm831x_bat_get_prop; - battery->use_for_apm = 1; - ret = power_supply_register(&pdev->dev, battery); - if (ret) - goto err_wall; - - usb->name = "wm831x-usb", + usb->name = power->usb_name, usb->type = POWER_SUPPLY_TYPE_USB; usb->properties = wm831x_usb_props; usb->num_properties = ARRAY_SIZE(wm831x_usb_props); usb->get_property = wm831x_usb_get_prop; ret = power_supply_register(&pdev->dev, usb); if (ret) - goto err_battery; + goto err_wall; + + ret = wm831x_reg_read(wm831x, WM831X_CHARGER_CONTROL_1); + if (ret < 0) + goto err_wall; + power->have_battery = ret & WM831X_CHG_ENA; + + if (power->have_battery) { + battery->name = power->battery_name; + battery->properties = wm831x_bat_props; + battery->num_properties = ARRAY_SIZE(wm831x_bat_props); + battery->get_property = wm831x_bat_get_prop; + battery->use_for_apm = 1; + ret = power_supply_register(&pdev->dev, battery); + if (ret) + goto err_usb; + } - irq = platform_get_irq_byname(pdev, "SYSLO"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq, IRQF_TRIGGER_RISING, "System power low", power); if (ret != 0) { dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", irq, ret); - goto err_usb; + goto err_battery; } - irq = platform_get_irq_byname(pdev, "PWR SRC"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq, IRQF_TRIGGER_RISING, "Power source", power); @@ -556,7 +586,9 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) } for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { - irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); + irq = wm831x_irq(wm831x, + platform_get_irq_byname(pdev, + wm831x_bat_irqs[i])); ret = request_threaded_irq(irq, NULL, wm831x_bat_irq, IRQF_TRIGGER_RISING, wm831x_bat_irqs[i], @@ -576,15 +608,16 @@ err_bat_irq: irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); free_irq(irq, power); } - irq = platform_get_irq_byname(pdev, "PWR SRC"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); free_irq(irq, power); err_syslo: - irq = platform_get_irq_byname(pdev, "SYSLO"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); free_irq(irq, power); +err_battery: + if (power->have_battery) + power_supply_unregister(battery); err_usb: power_supply_unregister(usb); -err_battery: - power_supply_unregister(battery); err_wall: power_supply_unregister(wall); err_kmalloc: @@ -592,23 +625,27 @@ err_kmalloc: return ret; } -static __devexit int wm831x_power_remove(struct platform_device *pdev) +static int wm831x_power_remove(struct platform_device *pdev) { struct wm831x_power *wm831x_power = platform_get_drvdata(pdev); + struct wm831x *wm831x = wm831x_power->wm831x; int irq, i; for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { - irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); + irq = wm831x_irq(wm831x, + platform_get_irq_byname(pdev, + wm831x_bat_irqs[i])); free_irq(irq, wm831x_power); } - irq = platform_get_irq_byname(pdev, "PWR SRC"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); free_irq(irq, wm831x_power); - irq = platform_get_irq_byname(pdev, "SYSLO"); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); free_irq(irq, wm831x_power); - power_supply_unregister(&wm831x_power->battery); + if (wm831x_power->have_battery) + power_supply_unregister(&wm831x_power->battery); power_supply_unregister(&wm831x_power->wall); power_supply_unregister(&wm831x_power->usb); kfree(wm831x_power); @@ -617,23 +654,13 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev) static struct platform_driver wm831x_power_driver = { .probe = wm831x_power_probe, - .remove = __devexit_p(wm831x_power_remove), + .remove = wm831x_power_remove, .driver = { .name = "wm831x-power", }, }; -static int __init wm831x_power_init(void) -{ - return platform_driver_register(&wm831x_power_driver); -} -module_init(wm831x_power_init); - -static void __exit wm831x_power_exit(void) -{ - platform_driver_unregister(&wm831x_power_driver); -} -module_exit(wm831x_power_exit); +module_platform_driver(wm831x_power_driver); MODULE_DESCRIPTION("Power supply driver for WM831x PMICs"); MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
