diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-15 20:36:45 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-15 20:36:45 -0500 |
| commit | 7051d8e6308640aaee2f9d45d0ceaad3a4ee8a78 (patch) | |
| tree | b3d15e9232ca6956e255c7e1dd7c3276903440f0 | |
| parent | d3255ec483ca048192f6e8a8789e08e32b379b84 (diff) | |
| parent | b81180b3fd4814af0459a5b6aeb1ee188fea98dc (diff) | |
Merge tag 'for-v3.19' of git://git.infradead.org/battery-2.6
Pull power supply updates from Sebastian Reichel::
"Power supply and reset changes for the v3.19 series
- update power/reset drivers to use kernel restart handler
- add power off driver for i.mx6
- add DT support for gpio-charger"
* tag 'for-v3.19' of git://git.infradead.org/battery-2.6:
power: reset: adjust priority of simple syscon reboot driver
power: ds2782_battery: Simplify the PM hooks
power/reset: brcmstb: Register with kernel restart handler
power/reset: hisi: Register with kernel restart handler
power/reset: keystone: Register with kernel restart handler
power/reset: axxia: Register with kernel restart handler
power/reset: xgene: Register with kernel restart handler
power/reset: xgene: Use mdelay instead of jiffies based timeout
power/reset: xgene: Use local variable dev instead of pdev->dev
power/reset: xgene: Drop devm_kfree
power/reset: xgene: Return -ENOMEM if out of memory
power/reset: vexpress: Register with kernel restart handler
power: reset: imx-snvs-poweroff: add power off driver for i.mx6
power: gpio-charger: add device tree support
dt-bindings: document gpio-charger bindings
| -rw-r--r-- | Documentation/devicetree/bindings/power_supply/gpio-charger.txt | 27 | ||||
| -rw-r--r-- | drivers/power/ds2782_battery.c | 8 | ||||
| -rw-r--r-- | drivers/power/gpio-charger.c | 72 | ||||
| -rw-r--r-- | drivers/power/reset/axxia-reset.c | 21 | ||||
| -rw-r--r-- | drivers/power/reset/brcmstb-reboot.c | 28 | ||||
| -rw-r--r-- | drivers/power/reset/hisi-reboot.c | 20 | ||||
| -rw-r--r-- | drivers/power/reset/keystone-reset.c | 20 | ||||
| -rw-r--r-- | drivers/power/reset/syscon-reboot.c | 2 | ||||
| -rw-r--r-- | drivers/power/reset/vexpress-poweroff.c | 40 | ||||
| -rw-r--r-- | drivers/power/reset/xgene-reboot.c | 56 |
10 files changed, 225 insertions, 69 deletions
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 000000000000..adbb5dc5b6e9 --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/gpio-charger.txt | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | gpio-charger | ||
| 2 | |||
| 3 | Required properties : | ||
| 4 | - compatible : "gpio-charger" | ||
| 5 | - gpios : GPIO indicating the charger presence. | ||
| 6 | See GPIO binding in bindings/gpio/gpio.txt . | ||
| 7 | - charger-type : power supply type, one of | ||
| 8 | unknown | ||
| 9 | battery | ||
| 10 | ups | ||
| 11 | mains | ||
| 12 | usb-sdp (USB standard downstream port) | ||
| 13 | usb-dcp (USB dedicated charging port) | ||
| 14 | usb-cdp (USB charging downstream port) | ||
| 15 | usb-aca (USB accessory charger adapter) | ||
| 16 | |||
| 17 | Example: | ||
| 18 | |||
| 19 | usb_charger: charger { | ||
| 20 | compatible = "gpio-charger"; | ||
| 21 | charger-type = "usb-sdp"; | ||
| 22 | gpios = <&gpf0 2 0 0 0>; | ||
| 23 | } | ||
| 24 | |||
| 25 | battery { | ||
| 26 | power-supplies = <&usb_charger>; | ||
| 27 | }; | ||
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index 041f9b638d28..39694883d3bf 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c | |||
| @@ -351,13 +351,9 @@ static int ds278x_resume(struct device *dev) | |||
| 351 | schedule_delayed_work(&info->bat_work, DS278x_DELAY); | 351 | schedule_delayed_work(&info->bat_work, DS278x_DELAY); |
| 352 | return 0; | 352 | return 0; |
| 353 | } | 353 | } |
| 354 | #endif /* CONFIG_PM_SLEEP */ | ||
| 354 | 355 | ||
| 355 | static SIMPLE_DEV_PM_OPS(ds278x_battery_pm_ops, ds278x_suspend, ds278x_resume); | 356 | static SIMPLE_DEV_PM_OPS(ds278x_battery_pm_ops, ds278x_suspend, ds278x_resume); |
| 356 | #define DS278X_BATTERY_PM_OPS (&ds278x_battery_pm_ops) | ||
| 357 | |||
| 358 | #else | ||
| 359 | #define DS278X_BATTERY_PM_OPS NULL | ||
| 360 | #endif /* CONFIG_PM_SLEEP */ | ||
| 361 | 357 | ||
| 362 | enum ds278x_num_id { | 358 | enum ds278x_num_id { |
| 363 | DS2782 = 0, | 359 | DS2782 = 0, |
| @@ -460,7 +456,7 @@ MODULE_DEVICE_TABLE(i2c, ds278x_id); | |||
| 460 | static struct i2c_driver ds278x_battery_driver = { | 456 | static struct i2c_driver ds278x_battery_driver = { |
| 461 | .driver = { | 457 | .driver = { |
| 462 | .name = "ds2782-battery", | 458 | .name = "ds2782-battery", |
| 463 | .pm = DS278X_BATTERY_PM_OPS, | 459 | .pm = &ds278x_battery_pm_ops, |
| 464 | }, | 460 | }, |
| 465 | .probe = ds278x_battery_probe, | 461 | .probe = ds278x_battery_probe, |
| 466 | .remove = ds278x_battery_remove, | 462 | .remove = ds278x_battery_remove, |
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c index 3ee889fe0021..aef74bdf7ab3 100644 --- a/drivers/power/gpio-charger.c +++ b/drivers/power/gpio-charger.c | |||
| @@ -22,6 +22,8 @@ | |||
| 22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
| 23 | #include <linux/power_supply.h> | 23 | #include <linux/power_supply.h> |
| 24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 25 | #include <linux/of.h> | ||
| 26 | #include <linux/of_gpio.h> | ||
| 25 | 27 | ||
| 26 | #include <linux/power/gpio-charger.h> | 28 | #include <linux/power/gpio-charger.h> |
| 27 | 29 | ||
| @@ -69,6 +71,59 @@ static enum power_supply_property gpio_charger_properties[] = { | |||
| 69 | POWER_SUPPLY_PROP_ONLINE, | 71 | POWER_SUPPLY_PROP_ONLINE, |
| 70 | }; | 72 | }; |
| 71 | 73 | ||
| 74 | static | ||
| 75 | struct gpio_charger_platform_data *gpio_charger_parse_dt(struct device *dev) | ||
| 76 | { | ||
| 77 | struct device_node *np = dev->of_node; | ||
| 78 | struct gpio_charger_platform_data *pdata; | ||
| 79 | const char *chargetype; | ||
| 80 | enum of_gpio_flags flags; | ||
| 81 | int ret; | ||
| 82 | |||
| 83 | if (!np) | ||
| 84 | return ERR_PTR(-ENOENT); | ||
| 85 | |||
| 86 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
| 87 | if (!pdata) | ||
| 88 | return ERR_PTR(-ENOMEM); | ||
| 89 | |||
| 90 | pdata->name = np->name; | ||
| 91 | |||
| 92 | pdata->gpio = of_get_gpio_flags(np, 0, &flags); | ||
| 93 | if (pdata->gpio < 0) { | ||
| 94 | if (pdata->gpio != -EPROBE_DEFER) | ||
| 95 | dev_err(dev, "could not get charger gpio\n"); | ||
| 96 | return ERR_PTR(pdata->gpio); | ||
| 97 | } | ||
| 98 | |||
| 99 | pdata->gpio_active_low = !!(flags & OF_GPIO_ACTIVE_LOW); | ||
| 100 | |||
| 101 | pdata->type = POWER_SUPPLY_TYPE_UNKNOWN; | ||
| 102 | ret = of_property_read_string(np, "charger-type", &chargetype); | ||
| 103 | if (ret >= 0) { | ||
| 104 | if (!strncmp("unknown", chargetype, 7)) | ||
| 105 | pdata->type = POWER_SUPPLY_TYPE_UNKNOWN; | ||
| 106 | else if (!strncmp("battery", chargetype, 7)) | ||
| 107 | pdata->type = POWER_SUPPLY_TYPE_BATTERY; | ||
| 108 | else if (!strncmp("ups", chargetype, 3)) | ||
| 109 | pdata->type = POWER_SUPPLY_TYPE_UPS; | ||
| 110 | else if (!strncmp("mains", chargetype, 5)) | ||
| 111 | pdata->type = POWER_SUPPLY_TYPE_MAINS; | ||
| 112 | else if (!strncmp("usb-sdp", chargetype, 7)) | ||
| 113 | pdata->type = POWER_SUPPLY_TYPE_USB; | ||
| 114 | else if (!strncmp("usb-dcp", chargetype, 7)) | ||
| 115 | pdata->type = POWER_SUPPLY_TYPE_USB_DCP; | ||
| 116 | else if (!strncmp("usb-cdp", chargetype, 7)) | ||
| 117 | pdata->type = POWER_SUPPLY_TYPE_USB_CDP; | ||
| 118 | else if (!strncmp("usb-aca", chargetype, 7)) | ||
| 119 | pdata->type = POWER_SUPPLY_TYPE_USB_ACA; | ||
| 120 | else | ||
| 121 | dev_warn(dev, "unknown charger type %s\n", chargetype); | ||
| 122 | } | ||
| 123 | |||
| 124 | return pdata; | ||
| 125 | } | ||
| 126 | |||
| 72 | static int gpio_charger_probe(struct platform_device *pdev) | 127 | static int gpio_charger_probe(struct platform_device *pdev) |
| 73 | { | 128 | { |
| 74 | const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data; | 129 | const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data; |
| @@ -78,8 +133,13 @@ static int gpio_charger_probe(struct platform_device *pdev) | |||
| 78 | int irq; | 133 | int irq; |
| 79 | 134 | ||
| 80 | if (!pdata) { | 135 | if (!pdata) { |
| 81 | dev_err(&pdev->dev, "No platform data\n"); | 136 | pdata = gpio_charger_parse_dt(&pdev->dev); |
| 82 | return -EINVAL; | 137 | if (IS_ERR(pdata)) { |
| 138 | ret = PTR_ERR(pdata); | ||
| 139 | if (ret != -EPROBE_DEFER) | ||
| 140 | dev_err(&pdev->dev, "No platform data\n"); | ||
| 141 | return ret; | ||
| 142 | } | ||
| 83 | } | 143 | } |
| 84 | 144 | ||
| 85 | if (!gpio_is_valid(pdata->gpio)) { | 145 | if (!gpio_is_valid(pdata->gpio)) { |
| @@ -103,6 +163,7 @@ static int gpio_charger_probe(struct platform_device *pdev) | |||
| 103 | charger->get_property = gpio_charger_get_property; | 163 | charger->get_property = gpio_charger_get_property; |
| 104 | charger->supplied_to = pdata->supplied_to; | 164 | charger->supplied_to = pdata->supplied_to; |
| 105 | charger->num_supplicants = pdata->num_supplicants; | 165 | charger->num_supplicants = pdata->num_supplicants; |
| 166 | charger->of_node = pdev->dev.of_node; | ||
| 106 | 167 | ||
| 107 | ret = gpio_request(pdata->gpio, dev_name(&pdev->dev)); | 168 | ret = gpio_request(pdata->gpio, dev_name(&pdev->dev)); |
| 108 | if (ret) { | 169 | if (ret) { |
| @@ -189,12 +250,19 @@ static int gpio_charger_resume(struct device *dev) | |||
| 189 | static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, | 250 | static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, |
| 190 | gpio_charger_suspend, gpio_charger_resume); | 251 | gpio_charger_suspend, gpio_charger_resume); |
| 191 | 252 | ||
| 253 | static const struct of_device_id gpio_charger_match[] = { | ||
| 254 | { .compatible = "gpio-charger" }, | ||
| 255 | { } | ||
| 256 | }; | ||
| 257 | MODULE_DEVICE_TABLE(of, gpio_charger_match); | ||
| 258 | |||
| 192 | static struct platform_driver gpio_charger_driver = { | 259 | static struct platform_driver gpio_charger_driver = { |
| 193 | .probe = gpio_charger_probe, | 260 | .probe = gpio_charger_probe, |
| 194 | .remove = gpio_charger_remove, | 261 | .remove = gpio_charger_remove, |
| 195 | .driver = { | 262 | .driver = { |
| 196 | .name = "gpio-charger", | 263 | .name = "gpio-charger", |
| 197 | .pm = &gpio_charger_pm_ops, | 264 | .pm = &gpio_charger_pm_ops, |
| 265 | .of_match_table = gpio_charger_match, | ||
| 198 | }, | 266 | }, |
| 199 | }; | 267 | }; |
| 200 | 268 | ||
diff --git a/drivers/power/reset/axxia-reset.c b/drivers/power/reset/axxia-reset.c index 3b1f8d601784..4e4cd1c8fe50 100644 --- a/drivers/power/reset/axxia-reset.c +++ b/drivers/power/reset/axxia-reset.c | |||
| @@ -19,14 +19,12 @@ | |||
| 19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
| 20 | #include <linux/mfd/syscon.h> | 20 | #include <linux/mfd/syscon.h> |
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/notifier.h> | ||
| 22 | #include <linux/of.h> | 23 | #include <linux/of.h> |
| 23 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
| 24 | #include <linux/reboot.h> | 25 | #include <linux/reboot.h> |
| 25 | #include <linux/regmap.h> | 26 | #include <linux/regmap.h> |
| 26 | 27 | ||
| 27 | #include <asm/system_misc.h> | ||
| 28 | |||
| 29 | |||
| 30 | #define SC_CRIT_WRITE_KEY 0x1000 | 28 | #define SC_CRIT_WRITE_KEY 0x1000 |
| 31 | #define SC_LATCH_ON_RESET 0x1004 | 29 | #define SC_LATCH_ON_RESET 0x1004 |
| 32 | #define SC_RESET_CONTROL 0x1008 | 30 | #define SC_RESET_CONTROL 0x1008 |
| @@ -39,7 +37,8 @@ | |||
| 39 | 37 | ||
| 40 | static struct regmap *syscon; | 38 | static struct regmap *syscon; |
| 41 | 39 | ||
| 42 | static void do_axxia_restart(enum reboot_mode reboot_mode, const char *cmd) | 40 | static int axxia_restart_handler(struct notifier_block *this, |
| 41 | unsigned long mode, void *cmd) | ||
| 43 | { | 42 | { |
| 44 | /* Access Key (0xab) */ | 43 | /* Access Key (0xab) */ |
| 45 | regmap_write(syscon, SC_CRIT_WRITE_KEY, 0xab); | 44 | 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) | |||
| 50 | /* Assert chip reset */ | 49 | /* Assert chip reset */ |
| 51 | regmap_update_bits(syscon, SC_RESET_CONTROL, | 50 | regmap_update_bits(syscon, SC_RESET_CONTROL, |
| 52 | RSTCTL_RST_CHIP, RSTCTL_RST_CHIP); | 51 | RSTCTL_RST_CHIP, RSTCTL_RST_CHIP); |
| 52 | |||
| 53 | return NOTIFY_DONE; | ||
| 53 | } | 54 | } |
| 54 | 55 | ||
| 56 | static struct notifier_block axxia_restart_nb = { | ||
| 57 | .notifier_call = axxia_restart_handler, | ||
| 58 | .priority = 128, | ||
| 59 | }; | ||
| 60 | |||
| 55 | static int axxia_reset_probe(struct platform_device *pdev) | 61 | static int axxia_reset_probe(struct platform_device *pdev) |
| 56 | { | 62 | { |
| 57 | struct device *dev = &pdev->dev; | 63 | struct device *dev = &pdev->dev; |
| 64 | int err; | ||
| 58 | 65 | ||
| 59 | syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); | 66 | syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); |
| 60 | if (IS_ERR(syscon)) { | 67 | if (IS_ERR(syscon)) { |
| @@ -62,9 +69,11 @@ static int axxia_reset_probe(struct platform_device *pdev) | |||
| 62 | return PTR_ERR(syscon); | 69 | return PTR_ERR(syscon); |
| 63 | } | 70 | } |
| 64 | 71 | ||
| 65 | arm_pm_restart = do_axxia_restart; | 72 | err = register_restart_handler(&axxia_restart_nb); |
| 73 | if (err) | ||
| 74 | dev_err(dev, "cannot register restart handler (err=%d)\n", err); | ||
| 66 | 75 | ||
| 67 | return 0; | 76 | return err; |
| 68 | } | 77 | } |
| 69 | 78 | ||
| 70 | static const struct of_device_id of_axxia_reset_match[] = { | 79 | 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 c523ea7a90ee..100606f9b3dc 100644 --- a/drivers/power/reset/brcmstb-reboot.c +++ b/drivers/power/reset/brcmstb-reboot.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 18 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
| 19 | #include <linux/notifier.h> | ||
| 19 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
| 20 | #include <linux/of_irq.h> | 21 | #include <linux/of_irq.h> |
| 21 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
| @@ -26,8 +27,6 @@ | |||
| 26 | #include <linux/smp.h> | 27 | #include <linux/smp.h> |
| 27 | #include <linux/mfd/syscon.h> | 28 | #include <linux/mfd/syscon.h> |
| 28 | 29 | ||
| 29 | #include <asm/system_misc.h> | ||
| 30 | |||
| 31 | #define RESET_SOURCE_ENABLE_REG 1 | 30 | #define RESET_SOURCE_ENABLE_REG 1 |
| 32 | #define SW_MASTER_RESET_REG 2 | 31 | #define SW_MASTER_RESET_REG 2 |
| 33 | 32 | ||
| @@ -35,7 +34,8 @@ static struct regmap *regmap; | |||
| 35 | static u32 rst_src_en; | 34 | static u32 rst_src_en; |
| 36 | static u32 sw_mstr_rst; | 35 | static u32 sw_mstr_rst; |
| 37 | 36 | ||
| 38 | static void brcmstb_reboot(enum reboot_mode mode, const char *cmd) | 37 | static int brcmstb_restart_handler(struct notifier_block *this, |
| 38 | unsigned long mode, void *cmd) | ||
| 39 | { | 39 | { |
| 40 | int rc; | 40 | int rc; |
| 41 | u32 tmp; | 41 | u32 tmp; |
| @@ -43,31 +43,38 @@ static void brcmstb_reboot(enum reboot_mode mode, const char *cmd) | |||
| 43 | rc = regmap_write(regmap, rst_src_en, 1); | 43 | rc = regmap_write(regmap, rst_src_en, 1); |
| 44 | if (rc) { | 44 | if (rc) { |
| 45 | pr_err("failed to write rst_src_en (%d)\n", rc); | 45 | pr_err("failed to write rst_src_en (%d)\n", rc); |
| 46 | return; | 46 | return NOTIFY_DONE; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | rc = regmap_read(regmap, rst_src_en, &tmp); | 49 | rc = regmap_read(regmap, rst_src_en, &tmp); |
| 50 | if (rc) { | 50 | if (rc) { |
| 51 | pr_err("failed to read rst_src_en (%d)\n", rc); | 51 | pr_err("failed to read rst_src_en (%d)\n", rc); |
| 52 | return; | 52 | return NOTIFY_DONE; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | rc = regmap_write(regmap, sw_mstr_rst, 1); | 55 | rc = regmap_write(regmap, sw_mstr_rst, 1); |
| 56 | if (rc) { | 56 | if (rc) { |
| 57 | pr_err("failed to write sw_mstr_rst (%d)\n", rc); | 57 | pr_err("failed to write sw_mstr_rst (%d)\n", rc); |
| 58 | return; | 58 | return NOTIFY_DONE; |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | rc = regmap_read(regmap, sw_mstr_rst, &tmp); | 61 | rc = regmap_read(regmap, sw_mstr_rst, &tmp); |
| 62 | if (rc) { | 62 | if (rc) { |
| 63 | pr_err("failed to read sw_mstr_rst (%d)\n", rc); | 63 | pr_err("failed to read sw_mstr_rst (%d)\n", rc); |
| 64 | return; | 64 | return NOTIFY_DONE; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | while (1) | 67 | while (1) |
| 68 | ; | 68 | ; |
| 69 | |||
| 70 | return NOTIFY_DONE; | ||
| 69 | } | 71 | } |
| 70 | 72 | ||
| 73 | static struct notifier_block brcmstb_restart_nb = { | ||
| 74 | .notifier_call = brcmstb_restart_handler, | ||
| 75 | .priority = 128, | ||
| 76 | }; | ||
| 77 | |||
| 71 | static int brcmstb_reboot_probe(struct platform_device *pdev) | 78 | static int brcmstb_reboot_probe(struct platform_device *pdev) |
| 72 | { | 79 | { |
| 73 | int rc; | 80 | int rc; |
| @@ -93,9 +100,12 @@ static int brcmstb_reboot_probe(struct platform_device *pdev) | |||
| 93 | return -EINVAL; | 100 | return -EINVAL; |
| 94 | } | 101 | } |
| 95 | 102 | ||
| 96 | arm_pm_restart = brcmstb_reboot; | 103 | rc = register_restart_handler(&brcmstb_restart_nb); |
| 104 | if (rc) | ||
| 105 | dev_err(&pdev->dev, | ||
| 106 | "cannot register restart handler (err=%d)\n", rc); | ||
| 97 | 107 | ||
| 98 | return 0; | 108 | return rc; |
| 99 | } | 109 | } |
| 100 | 110 | ||
| 101 | static const struct of_device_id of_match[] = { | 111 | 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 0c91d0231d36..5385460e23bb 100644 --- a/drivers/power/reset/hisi-reboot.c +++ b/drivers/power/reset/hisi-reboot.c | |||
| @@ -14,27 +14,36 @@ | |||
| 14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
| 15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/notifier.h> | ||
| 17 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
| 18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 19 | #include <linux/reboot.h> | 20 | #include <linux/reboot.h> |
| 20 | 21 | ||
| 21 | #include <asm/proc-fns.h> | 22 | #include <asm/proc-fns.h> |
| 22 | #include <asm/system_misc.h> | ||
| 23 | 23 | ||
| 24 | static void __iomem *base; | 24 | static void __iomem *base; |
| 25 | static u32 reboot_offset; | 25 | static u32 reboot_offset; |
| 26 | 26 | ||
| 27 | static void hisi_restart(enum reboot_mode mode, const char *cmd) | 27 | static int hisi_restart_handler(struct notifier_block *this, |
| 28 | unsigned long mode, void *cmd) | ||
| 28 | { | 29 | { |
| 29 | writel_relaxed(0xdeadbeef, base + reboot_offset); | 30 | writel_relaxed(0xdeadbeef, base + reboot_offset); |
| 30 | 31 | ||
| 31 | while (1) | 32 | while (1) |
| 32 | cpu_do_idle(); | 33 | cpu_do_idle(); |
| 34 | |||
| 35 | return NOTIFY_DONE; | ||
| 33 | } | 36 | } |
| 34 | 37 | ||
| 38 | static struct notifier_block hisi_restart_nb = { | ||
| 39 | .notifier_call = hisi_restart_handler, | ||
| 40 | .priority = 128, | ||
| 41 | }; | ||
| 42 | |||
| 35 | static int hisi_reboot_probe(struct platform_device *pdev) | 43 | static int hisi_reboot_probe(struct platform_device *pdev) |
| 36 | { | 44 | { |
| 37 | struct device_node *np = pdev->dev.of_node; | 45 | struct device_node *np = pdev->dev.of_node; |
| 46 | int err; | ||
| 38 | 47 | ||
| 39 | base = of_iomap(np, 0); | 48 | base = of_iomap(np, 0); |
| 40 | if (!base) { | 49 | if (!base) { |
| @@ -47,9 +56,12 @@ static int hisi_reboot_probe(struct platform_device *pdev) | |||
| 47 | return -EINVAL; | 56 | return -EINVAL; |
| 48 | } | 57 | } |
| 49 | 58 | ||
| 50 | arm_pm_restart = hisi_restart; | 59 | err = register_restart_handler(&hisi_restart_nb); |
| 60 | if (err) | ||
| 61 | dev_err(&pdev->dev, "cannot register restart handler (err=%d)\n", | ||
| 62 | err); | ||
| 51 | 63 | ||
| 52 | return 0; | 64 | return err; |
| 53 | } | 65 | } |
| 54 | 66 | ||
| 55 | static struct of_device_id hisi_reboot_of_match[] = { | 67 | 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 86bc100818b2..faedf16c8111 100644 --- a/drivers/power/reset/keystone-reset.c +++ b/drivers/power/reset/keystone-reset.c | |||
| @@ -12,9 +12,9 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/notifier.h> | ||
| 15 | #include <linux/reboot.h> | 16 | #include <linux/reboot.h> |
| 16 | #include <linux/regmap.h> | 17 | #include <linux/regmap.h> |
| 17 | #include <asm/system_misc.h> | ||
| 18 | #include <linux/mfd/syscon.h> | 18 | #include <linux/mfd/syscon.h> |
| 19 | #include <linux/of_platform.h> | 19 | #include <linux/of_platform.h> |
| 20 | 20 | ||
| @@ -52,7 +52,8 @@ static inline int rsctrl_enable_rspll_write(void) | |||
| 52 | RSCTRL_KEY_MASK, RSCTRL_KEY); | 52 | RSCTRL_KEY_MASK, RSCTRL_KEY); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | static void rsctrl_restart(enum reboot_mode mode, const char *cmd) | 55 | static int rsctrl_restart_handler(struct notifier_block *this, |
| 56 | unsigned long mode, void *cmd) | ||
| 56 | { | 57 | { |
| 57 | /* enable write access to RSTCTRL */ | 58 | /* enable write access to RSTCTRL */ |
| 58 | rsctrl_enable_rspll_write(); | 59 | rsctrl_enable_rspll_write(); |
| @@ -60,8 +61,15 @@ static void rsctrl_restart(enum reboot_mode mode, const char *cmd) | |||
| 60 | /* reset the SOC */ | 61 | /* reset the SOC */ |
| 61 | regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG, | 62 | regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG, |
| 62 | RSCTRL_RESET_MASK, 0); | 63 | RSCTRL_RESET_MASK, 0); |
| 64 | |||
| 65 | return NOTIFY_DONE; | ||
| 63 | } | 66 | } |
| 64 | 67 | ||
| 68 | static struct notifier_block rsctrl_restart_nb = { | ||
| 69 | .notifier_call = rsctrl_restart_handler, | ||
| 70 | .priority = 128, | ||
| 71 | }; | ||
| 72 | |||
| 65 | static struct of_device_id rsctrl_of_match[] = { | 73 | static struct of_device_id rsctrl_of_match[] = { |
| 66 | {.compatible = "ti,keystone-reset", }, | 74 | {.compatible = "ti,keystone-reset", }, |
| 67 | {}, | 75 | {}, |
| @@ -114,8 +122,6 @@ static int rsctrl_probe(struct platform_device *pdev) | |||
| 114 | if (ret) | 122 | if (ret) |
| 115 | return ret; | 123 | return ret; |
| 116 | 124 | ||
| 117 | arm_pm_restart = rsctrl_restart; | ||
| 118 | |||
| 119 | /* disable a reset isolation for all module clocks */ | 125 | /* disable a reset isolation for all module clocks */ |
| 120 | ret = regmap_write(pllctrl_regs, rspll_offset + RSISO_RG, 0); | 126 | ret = regmap_write(pllctrl_regs, rspll_offset + RSISO_RG, 0); |
| 121 | if (ret) | 127 | if (ret) |
| @@ -147,7 +153,11 @@ static int rsctrl_probe(struct platform_device *pdev) | |||
| 147 | return ret; | 153 | return ret; |
| 148 | } | 154 | } |
| 149 | 155 | ||
| 150 | return 0; | 156 | ret = register_restart_handler(&rsctrl_restart_nb); |
| 157 | if (ret) | ||
| 158 | dev_err(dev, "cannot register restart handler (err=%d)\n", ret); | ||
| 159 | |||
| 160 | return ret; | ||
| 151 | } | 161 | } |
| 152 | 162 | ||
| 153 | static struct platform_driver rsctrl_driver = { | 163 | static struct platform_driver rsctrl_driver = { |
diff --git a/drivers/power/reset/syscon-reboot.c b/drivers/power/reset/syscon-reboot.c index 815b901822cf..c4049f45663f 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) | |||
| 68 | return -EINVAL; | 68 | return -EINVAL; |
| 69 | 69 | ||
| 70 | ctx->restart_handler.notifier_call = syscon_restart_handle; | 70 | ctx->restart_handler.notifier_call = syscon_restart_handle; |
| 71 | ctx->restart_handler.priority = 128; | 71 | ctx->restart_handler.priority = 192; |
| 72 | err = register_restart_handler(&ctx->restart_handler); | 72 | err = register_restart_handler(&ctx->restart_handler); |
| 73 | if (err) | 73 | if (err) |
| 74 | dev_err(dev, "can't register restart notifier (err=%d)\n", err); | 74 | 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 4dc102e2b230..9dfc9cee3232 100644 --- a/drivers/power/reset/vexpress-poweroff.c +++ b/drivers/power/reset/vexpress-poweroff.c | |||
| @@ -12,14 +12,14 @@ | |||
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
| 15 | #include <linux/notifier.h> | ||
| 15 | #include <linux/of.h> | 16 | #include <linux/of.h> |
| 16 | #include <linux/of_device.h> | 17 | #include <linux/of_device.h> |
| 17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
| 19 | #include <linux/reboot.h> | ||
| 18 | #include <linux/stat.h> | 20 | #include <linux/stat.h> |
| 19 | #include <linux/vexpress.h> | 21 | #include <linux/vexpress.h> |
| 20 | 22 | ||
| 21 | #include <asm/system_misc.h> | ||
| 22 | |||
| 23 | static void vexpress_reset_do(struct device *dev, const char *what) | 23 | static void vexpress_reset_do(struct device *dev, const char *what) |
| 24 | { | 24 | { |
| 25 | int err = -ENOENT; | 25 | int err = -ENOENT; |
| @@ -43,11 +43,19 @@ static void vexpress_power_off(void) | |||
| 43 | 43 | ||
| 44 | static struct device *vexpress_restart_device; | 44 | static struct device *vexpress_restart_device; |
| 45 | 45 | ||
| 46 | static void vexpress_restart(enum reboot_mode reboot_mode, const char *cmd) | 46 | static int vexpress_restart(struct notifier_block *this, unsigned long mode, |
| 47 | void *cmd) | ||
| 47 | { | 48 | { |
| 48 | vexpress_reset_do(vexpress_restart_device, "restart"); | 49 | vexpress_reset_do(vexpress_restart_device, "restart"); |
| 50 | |||
| 51 | return NOTIFY_DONE; | ||
| 49 | } | 52 | } |
| 50 | 53 | ||
| 54 | static struct notifier_block vexpress_restart_nb = { | ||
| 55 | .notifier_call = vexpress_restart, | ||
| 56 | .priority = 128, | ||
| 57 | }; | ||
| 58 | |||
| 51 | static ssize_t vexpress_reset_active_show(struct device *dev, | 59 | static ssize_t vexpress_reset_active_show(struct device *dev, |
| 52 | struct device_attribute *attr, char *buf) | 60 | struct device_attribute *attr, char *buf) |
| 53 | { | 61 | { |
| @@ -86,12 +94,28 @@ static struct of_device_id vexpress_reset_of_match[] = { | |||
| 86 | {} | 94 | {} |
| 87 | }; | 95 | }; |
| 88 | 96 | ||
| 97 | static int _vexpress_register_restart_handler(struct device *dev) | ||
| 98 | { | ||
| 99 | int err; | ||
| 100 | |||
| 101 | vexpress_restart_device = dev; | ||
| 102 | err = register_restart_handler(&vexpress_restart_nb); | ||
| 103 | if (err) { | ||
| 104 | dev_err(dev, "cannot register restart handler (err=%d)\n", err); | ||
| 105 | return err; | ||
| 106 | } | ||
| 107 | device_create_file(dev, &dev_attr_active); | ||
| 108 | |||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 89 | static int vexpress_reset_probe(struct platform_device *pdev) | 112 | static int vexpress_reset_probe(struct platform_device *pdev) |
| 90 | { | 113 | { |
| 91 | enum vexpress_reset_func func; | 114 | enum vexpress_reset_func func; |
| 92 | const struct of_device_id *match = | 115 | const struct of_device_id *match = |
| 93 | of_match_device(vexpress_reset_of_match, &pdev->dev); | 116 | of_match_device(vexpress_reset_of_match, &pdev->dev); |
| 94 | struct regmap *regmap; | 117 | struct regmap *regmap; |
| 118 | int ret = 0; | ||
| 95 | 119 | ||
| 96 | if (match) | 120 | if (match) |
| 97 | func = (enum vexpress_reset_func)match->data; | 121 | func = (enum vexpress_reset_func)match->data; |
| @@ -110,18 +134,14 @@ static int vexpress_reset_probe(struct platform_device *pdev) | |||
| 110 | break; | 134 | break; |
| 111 | case FUNC_RESET: | 135 | case FUNC_RESET: |
| 112 | if (!vexpress_restart_device) | 136 | if (!vexpress_restart_device) |
| 113 | vexpress_restart_device = &pdev->dev; | 137 | ret = _vexpress_register_restart_handler(&pdev->dev); |
| 114 | arm_pm_restart = vexpress_restart; | ||
| 115 | device_create_file(&pdev->dev, &dev_attr_active); | ||
| 116 | break; | 138 | break; |
| 117 | case FUNC_REBOOT: | 139 | case FUNC_REBOOT: |
| 118 | vexpress_restart_device = &pdev->dev; | 140 | ret = _vexpress_register_restart_handler(&pdev->dev); |
| 119 | arm_pm_restart = vexpress_restart; | ||
| 120 | device_create_file(&pdev->dev, &dev_attr_active); | ||
| 121 | break; | 141 | break; |
| 122 | }; | 142 | }; |
| 123 | 143 | ||
| 124 | return 0; | 144 | return ret; |
| 125 | } | 145 | } |
| 126 | 146 | ||
| 127 | static const struct platform_device_id vexpress_reset_id_table[] = { | 147 | 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 6b49be6867ab..b0e5002f8deb 100644 --- a/drivers/power/reset/xgene-reboot.c +++ b/drivers/power/reset/xgene-reboot.c | |||
| @@ -24,63 +24,67 @@ | |||
| 24 | * For system shutdown, this is board specify. If a board designer | 24 | * For system shutdown, this is board specify. If a board designer |
| 25 | * implements GPIO shutdown, use the gpio-poweroff.c driver. | 25 | * implements GPIO shutdown, use the gpio-poweroff.c driver. |
| 26 | */ | 26 | */ |
| 27 | #include <linux/delay.h> | ||
| 27 | #include <linux/io.h> | 28 | #include <linux/io.h> |
| 29 | #include <linux/notifier.h> | ||
| 28 | #include <linux/of_device.h> | 30 | #include <linux/of_device.h> |
| 29 | #include <linux/of_address.h> | 31 | #include <linux/of_address.h> |
| 30 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
| 33 | #include <linux/reboot.h> | ||
| 31 | #include <linux/stat.h> | 34 | #include <linux/stat.h> |
| 32 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 33 | #include <asm/system_misc.h> | ||
| 34 | 36 | ||
| 35 | struct xgene_reboot_context { | 37 | struct xgene_reboot_context { |
| 36 | struct platform_device *pdev; | 38 | struct device *dev; |
| 37 | void *csr; | 39 | void *csr; |
| 38 | u32 mask; | 40 | u32 mask; |
| 41 | struct notifier_block restart_handler; | ||
| 39 | }; | 42 | }; |
| 40 | 43 | ||
| 41 | static struct xgene_reboot_context *xgene_restart_ctx; | 44 | static int xgene_restart_handler(struct notifier_block *this, |
| 42 | 45 | unsigned long mode, void *cmd) | |
| 43 | static void xgene_restart(enum reboot_mode mode, const char *cmd) | ||
| 44 | { | 46 | { |
| 45 | struct xgene_reboot_context *ctx = xgene_restart_ctx; | 47 | struct xgene_reboot_context *ctx = |
| 46 | unsigned long timeout; | 48 | container_of(this, struct xgene_reboot_context, |
| 49 | restart_handler); | ||
| 47 | 50 | ||
| 48 | /* Issue the reboot */ | 51 | /* Issue the reboot */ |
| 49 | if (ctx) | 52 | writel(ctx->mask, ctx->csr); |
| 50 | writel(ctx->mask, ctx->csr); | 53 | |
| 54 | mdelay(1000); | ||
| 51 | 55 | ||
| 52 | timeout = jiffies + HZ; | 56 | dev_emerg(ctx->dev, "Unable to restart system\n"); |
| 53 | while (time_before(jiffies, timeout)) | ||
| 54 | cpu_relax(); | ||
| 55 | 57 | ||
| 56 | dev_emerg(&ctx->pdev->dev, "Unable to restart system\n"); | 58 | return NOTIFY_DONE; |
| 57 | } | 59 | } |
| 58 | 60 | ||
| 59 | static int xgene_reboot_probe(struct platform_device *pdev) | 61 | static int xgene_reboot_probe(struct platform_device *pdev) |
| 60 | { | 62 | { |
| 61 | struct xgene_reboot_context *ctx; | 63 | struct xgene_reboot_context *ctx; |
| 64 | struct device *dev = &pdev->dev; | ||
| 65 | int err; | ||
| 62 | 66 | ||
| 63 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); | 67 | ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); |
| 64 | if (!ctx) { | 68 | if (!ctx) |
| 65 | dev_err(&pdev->dev, "out of memory for context\n"); | 69 | return -ENOMEM; |
| 66 | return -ENODEV; | ||
| 67 | } | ||
| 68 | 70 | ||
| 69 | ctx->csr = of_iomap(pdev->dev.of_node, 0); | 71 | ctx->csr = of_iomap(dev->of_node, 0); |
| 70 | if (!ctx->csr) { | 72 | if (!ctx->csr) { |
| 71 | devm_kfree(&pdev->dev, ctx); | 73 | dev_err(dev, "can not map resource\n"); |
| 72 | dev_err(&pdev->dev, "can not map resource\n"); | ||
| 73 | return -ENODEV; | 74 | return -ENODEV; |
| 74 | } | 75 | } |
| 75 | 76 | ||
| 76 | if (of_property_read_u32(pdev->dev.of_node, "mask", &ctx->mask)) | 77 | if (of_property_read_u32(dev->of_node, "mask", &ctx->mask)) |
| 77 | ctx->mask = 0xFFFFFFFF; | 78 | ctx->mask = 0xFFFFFFFF; |
| 78 | 79 | ||
| 79 | ctx->pdev = pdev; | 80 | ctx->dev = dev; |
| 80 | arm_pm_restart = xgene_restart; | 81 | ctx->restart_handler.notifier_call = xgene_restart_handler; |
| 81 | xgene_restart_ctx = ctx; | 82 | ctx->restart_handler.priority = 128; |
| 83 | err = register_restart_handler(&ctx->restart_handler); | ||
| 84 | if (err) | ||
| 85 | dev_err(dev, "cannot register restart handler (err=%d)\n", err); | ||
| 82 | 86 | ||
| 83 | return 0; | 87 | return err; |
| 84 | } | 88 | } |
| 85 | 89 | ||
| 86 | static struct of_device_id xgene_reboot_of_match[] = { | 90 | static struct of_device_id xgene_reboot_of_match[] = { |
