diff --git a/Documentation/devicetree/bindings/power_supply/gpio-charger.txt b/Documentation/devicetree/bindings/power_supply/gpio-charger.txt new file mode 100644 index 0000000000000000000000000000000000000000..adbb5dc5b6e9ec05f54986a0bd40fccc36372a7c --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/gpio-charger.txt @@ -0,0 +1,27 @@ +gpio-charger + +Required properties : + - compatible : "gpio-charger" + - gpios : GPIO indicating the charger presence. + See GPIO binding in bindings/gpio/gpio.txt . + - charger-type : power supply type, one of + unknown + battery + ups + mains + usb-sdp (USB standard downstream port) + usb-dcp (USB dedicated charging port) + usb-cdp (USB charging downstream port) + usb-aca (USB accessory charger adapter) + +Example: + + usb_charger: charger { + compatible = "gpio-charger"; + charger-type = "usb-sdp"; + gpios = <&gpf0 2 0 0 0>; + } + + battery { + power-supplies = <&usb_charger>; + }; diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index 041f9b638d28c5f788ee2c828d29b853728f67b4..39694883d3bf6c7ea108018c409a232d7495acef 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c @@ -351,13 +351,9 @@ static int ds278x_resume(struct device *dev) schedule_delayed_work(&info->bat_work, DS278x_DELAY); return 0; } +#endif /* CONFIG_PM_SLEEP */ static SIMPLE_DEV_PM_OPS(ds278x_battery_pm_ops, ds278x_suspend, ds278x_resume); -#define DS278X_BATTERY_PM_OPS (&ds278x_battery_pm_ops) - -#else -#define DS278X_BATTERY_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ enum ds278x_num_id { DS2782 = 0, @@ -460,7 +456,7 @@ MODULE_DEVICE_TABLE(i2c, ds278x_id); static struct i2c_driver ds278x_battery_driver = { .driver = { .name = "ds2782-battery", - .pm = DS278X_BATTERY_PM_OPS, + .pm = &ds278x_battery_pm_ops, }, .probe = ds278x_battery_probe, .remove = ds278x_battery_remove, diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c index 3ee889fe00219e1d2e4a7fa1b9f16f987b9444d7..aef74bdf7ab31690ebb1d286df3a593e24d18788 100644 --- a/drivers/power/gpio-charger.c +++ b/drivers/power/gpio-charger.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include @@ -69,6 +71,59 @@ static enum power_supply_property gpio_charger_properties[] = { POWER_SUPPLY_PROP_ONLINE, }; +static +struct gpio_charger_platform_data *gpio_charger_parse_dt(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct gpio_charger_platform_data *pdata; + const char *chargetype; + enum of_gpio_flags flags; + int ret; + + if (!np) + return ERR_PTR(-ENOENT); + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + pdata->name = np->name; + + pdata->gpio = of_get_gpio_flags(np, 0, &flags); + if (pdata->gpio < 0) { + if (pdata->gpio != -EPROBE_DEFER) + dev_err(dev, "could not get charger gpio\n"); + return ERR_PTR(pdata->gpio); + } + + pdata->gpio_active_low = !!(flags & OF_GPIO_ACTIVE_LOW); + + pdata->type = POWER_SUPPLY_TYPE_UNKNOWN; + ret = of_property_read_string(np, "charger-type", &chargetype); + if (ret >= 0) { + if (!strncmp("unknown", chargetype, 7)) + pdata->type = POWER_SUPPLY_TYPE_UNKNOWN; + else if (!strncmp("battery", chargetype, 7)) + pdata->type = POWER_SUPPLY_TYPE_BATTERY; + else if (!strncmp("ups", chargetype, 3)) + pdata->type = POWER_SUPPLY_TYPE_UPS; + else if (!strncmp("mains", chargetype, 5)) + pdata->type = POWER_SUPPLY_TYPE_MAINS; + else if (!strncmp("usb-sdp", chargetype, 7)) + pdata->type = POWER_SUPPLY_TYPE_USB; + else if (!strncmp("usb-dcp", chargetype, 7)) + pdata->type = POWER_SUPPLY_TYPE_USB_DCP; + else if (!strncmp("usb-cdp", chargetype, 7)) + pdata->type = POWER_SUPPLY_TYPE_USB_CDP; + else if (!strncmp("usb-aca", chargetype, 7)) + pdata->type = POWER_SUPPLY_TYPE_USB_ACA; + else + dev_warn(dev, "unknown charger type %s\n", chargetype); + } + + return pdata; +} + static int gpio_charger_probe(struct platform_device *pdev) { const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data; @@ -78,8 +133,13 @@ static int gpio_charger_probe(struct platform_device *pdev) int irq; if (!pdata) { - dev_err(&pdev->dev, "No platform data\n"); - return -EINVAL; + pdata = gpio_charger_parse_dt(&pdev->dev); + if (IS_ERR(pdata)) { + ret = PTR_ERR(pdata); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "No platform data\n"); + return ret; + } } if (!gpio_is_valid(pdata->gpio)) { @@ -103,6 +163,7 @@ static int gpio_charger_probe(struct platform_device *pdev) charger->get_property = gpio_charger_get_property; charger->supplied_to = pdata->supplied_to; charger->num_supplicants = pdata->num_supplicants; + charger->of_node = pdev->dev.of_node; ret = gpio_request(pdata->gpio, dev_name(&pdev->dev)); if (ret) { @@ -189,12 +250,19 @@ static int gpio_charger_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, gpio_charger_suspend, gpio_charger_resume); +static const struct of_device_id gpio_charger_match[] = { + { .compatible = "gpio-charger" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpio_charger_match); + static struct platform_driver gpio_charger_driver = { .probe = gpio_charger_probe, .remove = gpio_charger_remove, .driver = { .name = "gpio-charger", .pm = &gpio_charger_pm_ops, + .of_match_table = gpio_charger_match, }, }; diff --git a/drivers/power/reset/axxia-reset.c b/drivers/power/reset/axxia-reset.c index 3b1f8d60178423fb26362c8d5f8311a6a966f5ff..4e4cd1c8fe50db6f002606543b6d2cdc7d73799c 100644 --- a/drivers/power/reset/axxia-reset.c +++ b/drivers/power/reset/axxia-reset.c @@ -19,14 +19,12 @@ #include #include #include +#include #include #include #include #include -#include - - #define SC_CRIT_WRITE_KEY 0x1000 #define SC_LATCH_ON_RESET 0x1004 #define SC_RESET_CONTROL 0x1008 @@ -39,7 +37,8 @@ static struct regmap *syscon; -static void do_axxia_restart(enum reboot_mode reboot_mode, const char *cmd) +static int axxia_restart_handler(struct notifier_block *this, + unsigned long mode, void *cmd) { /* Access Key (0xab) */ regmap_write(syscon, SC_CRIT_WRITE_KEY, 0xab); @@ -50,11 +49,19 @@ static void do_axxia_restart(enum reboot_mode reboot_mode, const char *cmd) /* Assert chip reset */ regmap_update_bits(syscon, SC_RESET_CONTROL, RSTCTL_RST_CHIP, RSTCTL_RST_CHIP); + + return NOTIFY_DONE; } +static struct notifier_block axxia_restart_nb = { + .notifier_call = axxia_restart_handler, + .priority = 128, +}; + static int axxia_reset_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + int err; syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); if (IS_ERR(syscon)) { @@ -62,9 +69,11 @@ static int axxia_reset_probe(struct platform_device *pdev) return PTR_ERR(syscon); } - arm_pm_restart = do_axxia_restart; + err = register_restart_handler(&axxia_restart_nb); + if (err) + dev_err(dev, "cannot register restart handler (err=%d)\n", err); - return 0; + return err; } static const struct of_device_id of_axxia_reset_match[] = { diff --git a/drivers/power/reset/brcmstb-reboot.c b/drivers/power/reset/brcmstb-reboot.c index c523ea7a90ee731b90115c0fa4de095ba026d62a..100606f9b3dccb408b7fc59ada494db73a895e1f 100644 --- a/drivers/power/reset/brcmstb-reboot.c +++ b/drivers/power/reset/brcmstb-reboot.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -26,8 +27,6 @@ #include #include -#include - #define RESET_SOURCE_ENABLE_REG 1 #define SW_MASTER_RESET_REG 2 @@ -35,7 +34,8 @@ static struct regmap *regmap; static u32 rst_src_en; static u32 sw_mstr_rst; -static void brcmstb_reboot(enum reboot_mode mode, const char *cmd) +static int brcmstb_restart_handler(struct notifier_block *this, + unsigned long mode, void *cmd) { int rc; u32 tmp; @@ -43,31 +43,38 @@ static void brcmstb_reboot(enum reboot_mode mode, const char *cmd) rc = regmap_write(regmap, rst_src_en, 1); if (rc) { pr_err("failed to write rst_src_en (%d)\n", rc); - return; + return NOTIFY_DONE; } rc = regmap_read(regmap, rst_src_en, &tmp); if (rc) { pr_err("failed to read rst_src_en (%d)\n", rc); - return; + return NOTIFY_DONE; } rc = regmap_write(regmap, sw_mstr_rst, 1); if (rc) { pr_err("failed to write sw_mstr_rst (%d)\n", rc); - return; + return NOTIFY_DONE; } rc = regmap_read(regmap, sw_mstr_rst, &tmp); if (rc) { pr_err("failed to read sw_mstr_rst (%d)\n", rc); - return; + return NOTIFY_DONE; } while (1) ; + + return NOTIFY_DONE; } +static struct notifier_block brcmstb_restart_nb = { + .notifier_call = brcmstb_restart_handler, + .priority = 128, +}; + static int brcmstb_reboot_probe(struct platform_device *pdev) { int rc; @@ -93,9 +100,12 @@ static int brcmstb_reboot_probe(struct platform_device *pdev) return -EINVAL; } - arm_pm_restart = brcmstb_reboot; + rc = register_restart_handler(&brcmstb_restart_nb); + if (rc) + dev_err(&pdev->dev, + "cannot register restart handler (err=%d)\n", rc); - return 0; + return rc; } static const struct of_device_id of_match[] = { diff --git a/drivers/power/reset/hisi-reboot.c b/drivers/power/reset/hisi-reboot.c index 0c91d0231d36c69abf7b47c315c60dd427fb6081..5385460e23bb20f17cc4e4da8eea81b9dd4bda80 100644 --- a/drivers/power/reset/hisi-reboot.c +++ b/drivers/power/reset/hisi-reboot.c @@ -14,27 +14,36 @@ #include #include #include +#include #include #include #include #include -#include static void __iomem *base; static u32 reboot_offset; -static void hisi_restart(enum reboot_mode mode, const char *cmd) +static int hisi_restart_handler(struct notifier_block *this, + unsigned long mode, void *cmd) { writel_relaxed(0xdeadbeef, base + reboot_offset); while (1) cpu_do_idle(); + + return NOTIFY_DONE; } +static struct notifier_block hisi_restart_nb = { + .notifier_call = hisi_restart_handler, + .priority = 128, +}; + static int hisi_reboot_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; + int err; base = of_iomap(np, 0); if (!base) { @@ -47,9 +56,12 @@ static int hisi_reboot_probe(struct platform_device *pdev) return -EINVAL; } - arm_pm_restart = hisi_restart; + err = register_restart_handler(&hisi_restart_nb); + if (err) + dev_err(&pdev->dev, "cannot register restart handler (err=%d)\n", + err); - return 0; + return err; } static struct of_device_id hisi_reboot_of_match[] = { diff --git a/drivers/power/reset/keystone-reset.c b/drivers/power/reset/keystone-reset.c index 86bc100818b2bd0b297d428f036e0117539a673a..faedf16c8111895a84b0724e32d2fb219b84fb38 100644 --- a/drivers/power/reset/keystone-reset.c +++ b/drivers/power/reset/keystone-reset.c @@ -12,9 +12,9 @@ #include #include +#include #include #include -#include #include #include @@ -52,7 +52,8 @@ static inline int rsctrl_enable_rspll_write(void) RSCTRL_KEY_MASK, RSCTRL_KEY); } -static void rsctrl_restart(enum reboot_mode mode, const char *cmd) +static int rsctrl_restart_handler(struct notifier_block *this, + unsigned long mode, void *cmd) { /* enable write access to RSTCTRL */ rsctrl_enable_rspll_write(); @@ -60,8 +61,15 @@ static void rsctrl_restart(enum reboot_mode mode, const char *cmd) /* reset the SOC */ regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG, RSCTRL_RESET_MASK, 0); + + return NOTIFY_DONE; } +static struct notifier_block rsctrl_restart_nb = { + .notifier_call = rsctrl_restart_handler, + .priority = 128, +}; + static struct of_device_id rsctrl_of_match[] = { {.compatible = "ti,keystone-reset", }, {}, @@ -114,8 +122,6 @@ static int rsctrl_probe(struct platform_device *pdev) if (ret) return ret; - arm_pm_restart = rsctrl_restart; - /* disable a reset isolation for all module clocks */ ret = regmap_write(pllctrl_regs, rspll_offset + RSISO_RG, 0); if (ret) @@ -147,7 +153,11 @@ static int rsctrl_probe(struct platform_device *pdev) return ret; } - return 0; + ret = register_restart_handler(&rsctrl_restart_nb); + if (ret) + dev_err(dev, "cannot register restart handler (err=%d)\n", ret); + + return ret; } static struct platform_driver rsctrl_driver = { diff --git a/drivers/power/reset/syscon-reboot.c b/drivers/power/reset/syscon-reboot.c index 815b901822cf9299b6210982e370e2aaa3a503a7..c4049f45663f4b929a679e9ea548ed7bb4d18295 100644 --- a/drivers/power/reset/syscon-reboot.c +++ b/drivers/power/reset/syscon-reboot.c @@ -68,7 +68,7 @@ static int syscon_reboot_probe(struct platform_device *pdev) return -EINVAL; ctx->restart_handler.notifier_call = syscon_restart_handle; - ctx->restart_handler.priority = 128; + ctx->restart_handler.priority = 192; err = register_restart_handler(&ctx->restart_handler); if (err) dev_err(dev, "can't register restart notifier (err=%d)\n", err); diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c index 4dc102e2b230e9476119d4b3e1d439b17151e084..9dfc9cee3232c439db6da6676a60ba920a307834 100644 --- a/drivers/power/reset/vexpress-poweroff.c +++ b/drivers/power/reset/vexpress-poweroff.c @@ -12,14 +12,14 @@ */ #include +#include #include #include #include +#include #include #include -#include - static void vexpress_reset_do(struct device *dev, const char *what) { int err = -ENOENT; @@ -43,11 +43,19 @@ static void vexpress_power_off(void) static struct device *vexpress_restart_device; -static void vexpress_restart(enum reboot_mode reboot_mode, const char *cmd) +static int vexpress_restart(struct notifier_block *this, unsigned long mode, + void *cmd) { vexpress_reset_do(vexpress_restart_device, "restart"); + + return NOTIFY_DONE; } +static struct notifier_block vexpress_restart_nb = { + .notifier_call = vexpress_restart, + .priority = 128, +}; + static ssize_t vexpress_reset_active_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -86,12 +94,28 @@ static struct of_device_id vexpress_reset_of_match[] = { {} }; +static int _vexpress_register_restart_handler(struct device *dev) +{ + int err; + + vexpress_restart_device = dev; + err = register_restart_handler(&vexpress_restart_nb); + if (err) { + dev_err(dev, "cannot register restart handler (err=%d)\n", err); + return err; + } + device_create_file(dev, &dev_attr_active); + + return 0; +} + static int vexpress_reset_probe(struct platform_device *pdev) { enum vexpress_reset_func func; const struct of_device_id *match = of_match_device(vexpress_reset_of_match, &pdev->dev); struct regmap *regmap; + int ret = 0; if (match) func = (enum vexpress_reset_func)match->data; @@ -110,18 +134,14 @@ static int vexpress_reset_probe(struct platform_device *pdev) break; case FUNC_RESET: if (!vexpress_restart_device) - vexpress_restart_device = &pdev->dev; - arm_pm_restart = vexpress_restart; - device_create_file(&pdev->dev, &dev_attr_active); + ret = _vexpress_register_restart_handler(&pdev->dev); break; case FUNC_REBOOT: - vexpress_restart_device = &pdev->dev; - arm_pm_restart = vexpress_restart; - device_create_file(&pdev->dev, &dev_attr_active); + ret = _vexpress_register_restart_handler(&pdev->dev); break; }; - return 0; + return ret; } static const struct platform_device_id vexpress_reset_id_table[] = { diff --git a/drivers/power/reset/xgene-reboot.c b/drivers/power/reset/xgene-reboot.c index 6b49be6867ab01f174de34cd28759951c61e7a2f..b0e5002f8debee0c95515bfd217e8d3a85844675 100644 --- a/drivers/power/reset/xgene-reboot.c +++ b/drivers/power/reset/xgene-reboot.c @@ -24,63 +24,67 @@ * For system shutdown, this is board specify. If a board designer * implements GPIO shutdown, use the gpio-poweroff.c driver. */ +#include #include +#include #include #include #include +#include #include #include -#include struct xgene_reboot_context { - struct platform_device *pdev; + struct device *dev; void *csr; u32 mask; + struct notifier_block restart_handler; }; -static struct xgene_reboot_context *xgene_restart_ctx; - -static void xgene_restart(enum reboot_mode mode, const char *cmd) +static int xgene_restart_handler(struct notifier_block *this, + unsigned long mode, void *cmd) { - struct xgene_reboot_context *ctx = xgene_restart_ctx; - unsigned long timeout; + struct xgene_reboot_context *ctx = + container_of(this, struct xgene_reboot_context, + restart_handler); /* Issue the reboot */ - if (ctx) - writel(ctx->mask, ctx->csr); + writel(ctx->mask, ctx->csr); + + mdelay(1000); - timeout = jiffies + HZ; - while (time_before(jiffies, timeout)) - cpu_relax(); + dev_emerg(ctx->dev, "Unable to restart system\n"); - dev_emerg(&ctx->pdev->dev, "Unable to restart system\n"); + return NOTIFY_DONE; } static int xgene_reboot_probe(struct platform_device *pdev) { struct xgene_reboot_context *ctx; + struct device *dev = &pdev->dev; + int err; - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) { - dev_err(&pdev->dev, "out of memory for context\n"); - return -ENODEV; - } + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; - ctx->csr = of_iomap(pdev->dev.of_node, 0); + ctx->csr = of_iomap(dev->of_node, 0); if (!ctx->csr) { - devm_kfree(&pdev->dev, ctx); - dev_err(&pdev->dev, "can not map resource\n"); + dev_err(dev, "can not map resource\n"); return -ENODEV; } - if (of_property_read_u32(pdev->dev.of_node, "mask", &ctx->mask)) + if (of_property_read_u32(dev->of_node, "mask", &ctx->mask)) ctx->mask = 0xFFFFFFFF; - ctx->pdev = pdev; - arm_pm_restart = xgene_restart; - xgene_restart_ctx = ctx; + ctx->dev = dev; + ctx->restart_handler.notifier_call = xgene_restart_handler; + ctx->restart_handler.priority = 128; + err = register_restart_handler(&ctx->restart_handler); + if (err) + dev_err(dev, "cannot register restart handler (err=%d)\n", err); - return 0; + return err; } static struct of_device_id xgene_reboot_of_match[] = {