Message ID | 20210727092554.1059305-4-kernel@esmil.dk |
---|---|
State | Accepted |
Commit | 80698507e0b20817ab850538080b01c3e0a5314f |
Headers | show |
Series | BeagleV Starlight reset support | expand |
Hi, On Tue, Jul 27, 2021 at 11:25:53AM +0200, Emil Renner Berthing wrote: > The only way to reset the BeagleV Starlight v0.9 board[1] properly is to > tell the PMIC to reset itself which will then assert the external reset > lines of the SoC, USB hub and ethernet phy. > > This adds a driver to register a reset handler to do just that. > > [1] https://github.com/beagleboard/beaglev-starlight > > Signed-off-by: Emil Renner Berthing <kernel@esmil.dk> > Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com> > --- Thanks, queued. -- Sebastian > drivers/power/reset/Kconfig | 6 ++ > drivers/power/reset/Makefile | 1 + > drivers/power/reset/tps65086-restart.c | 98 ++++++++++++++++++++++++++ > 3 files changed, 105 insertions(+) > create mode 100644 drivers/power/reset/tps65086-restart.c > > diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig > index 4d1192062508..4b563db3ab3e 100644 > --- a/drivers/power/reset/Kconfig > +++ b/drivers/power/reset/Kconfig > @@ -204,6 +204,12 @@ config POWER_RESET_ST > help > Reset support for STMicroelectronics boards. > > +config POWER_RESET_TPS65086 > + bool "TPS65086 restart driver" > + depends on MFD_TPS65086 > + help > + This driver adds support for resetting the TPS65086 PMIC on restart. > + > config POWER_RESET_VERSATILE > bool "ARM Versatile family reboot driver" > depends on ARM > diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile > index cf3f4d02d8a5..f606a2f60539 100644 > --- a/drivers/power/reset/Makefile > +++ b/drivers/power/reset/Makefile > @@ -23,6 +23,7 @@ obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o > obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o > obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o > obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o > +obj-$(CONFIG_POWER_RESET_TPS65086) += tps65086-restart.o > obj-$(CONFIG_POWER_RESET_VERSATILE) += arm-versatile-reboot.o > obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o > obj-$(CONFIG_POWER_RESET_XGENE) += xgene-reboot.o > diff --git a/drivers/power/reset/tps65086-restart.c b/drivers/power/reset/tps65086-restart.c > new file mode 100644 > index 000000000000..78b89f745a3d > --- /dev/null > +++ b/drivers/power/reset/tps65086-restart.c > @@ -0,0 +1,98 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) 2021 Emil Renner Berthing > + */ > + > +#include <linux/mfd/tps65086.h> > +#include <linux/mod_devicetable.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/reboot.h> > + > +struct tps65086_restart { > + struct notifier_block handler; > + struct device *dev; > +}; > + > +static int tps65086_restart_notify(struct notifier_block *this, > + unsigned long mode, void *cmd) > +{ > + struct tps65086_restart *tps65086_restart = > + container_of(this, struct tps65086_restart, handler); > + struct tps65086 *tps65086 = dev_get_drvdata(tps65086_restart->dev->parent); > + int ret; > + > + ret = regmap_write(tps65086->regmap, TPS65086_FORCESHUTDN, 1); > + if (ret) { > + dev_err(tps65086_restart->dev, "%s: error writing to tps65086 pmic: %d\n", > + __func__, ret); > + return NOTIFY_DONE; > + } > + > + /* give it a little time */ > + mdelay(200); > + > + WARN_ON(1); > + > + return NOTIFY_DONE; > +} > + > +static int tps65086_restart_probe(struct platform_device *pdev) > +{ > + struct tps65086_restart *tps65086_restart; > + int ret; > + > + tps65086_restart = devm_kzalloc(&pdev->dev, sizeof(*tps65086_restart), GFP_KERNEL); > + if (!tps65086_restart) > + return -ENOMEM; > + > + platform_set_drvdata(pdev, tps65086_restart); > + > + tps65086_restart->handler.notifier_call = tps65086_restart_notify; > + tps65086_restart->handler.priority = 192; > + tps65086_restart->dev = &pdev->dev; > + > + ret = register_restart_handler(&tps65086_restart->handler); > + if (ret) { > + dev_err(&pdev->dev, "%s: cannot register restart handler: %d\n", > + __func__, ret); > + return -ENODEV; > + } > + > + return 0; > +} > + > +static int tps65086_restart_remove(struct platform_device *pdev) > +{ > + struct tps65086_restart *tps65086_restart = platform_get_drvdata(pdev); > + int ret; > + > + ret = unregister_restart_handler(&tps65086_restart->handler); > + if (ret) { > + dev_err(&pdev->dev, "%s: cannot unregister restart handler: %d\n", > + __func__, ret); > + return -ENODEV; > + } > + > + return 0; > +} > + > +static const struct platform_device_id tps65086_restart_id_table[] = { > + { "tps65086-reset", }, > + { /* sentinel */ } > +}; > +MODULE_DEVICE_TABLE(platform, tps65086_restart_id_table); > + > +static struct platform_driver tps65086_restart_driver = { > + .driver = { > + .name = "tps65086-restart", > + }, > + .probe = tps65086_restart_probe, > + .remove = tps65086_restart_remove, > + .id_table = tps65086_restart_id_table, > +}; > +module_platform_driver(tps65086_restart_driver); > + > +MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>"); > +MODULE_DESCRIPTION("TPS65086 restart driver"); > +MODULE_LICENSE("GPL v2"); > -- > 2.32.0 >
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 4d1192062508..4b563db3ab3e 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -204,6 +204,12 @@ config POWER_RESET_ST help Reset support for STMicroelectronics boards. +config POWER_RESET_TPS65086 + bool "TPS65086 restart driver" + depends on MFD_TPS65086 + help + This driver adds support for resetting the TPS65086 PMIC on restart. + config POWER_RESET_VERSATILE bool "ARM Versatile family reboot driver" depends on ARM diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index cf3f4d02d8a5..f606a2f60539 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o +obj-$(CONFIG_POWER_RESET_TPS65086) += tps65086-restart.o obj-$(CONFIG_POWER_RESET_VERSATILE) += arm-versatile-reboot.o obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o obj-$(CONFIG_POWER_RESET_XGENE) += xgene-reboot.o diff --git a/drivers/power/reset/tps65086-restart.c b/drivers/power/reset/tps65086-restart.c new file mode 100644 index 000000000000..78b89f745a3d --- /dev/null +++ b/drivers/power/reset/tps65086-restart.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Emil Renner Berthing + */ + +#include <linux/mfd/tps65086.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/reboot.h> + +struct tps65086_restart { + struct notifier_block handler; + struct device *dev; +}; + +static int tps65086_restart_notify(struct notifier_block *this, + unsigned long mode, void *cmd) +{ + struct tps65086_restart *tps65086_restart = + container_of(this, struct tps65086_restart, handler); + struct tps65086 *tps65086 = dev_get_drvdata(tps65086_restart->dev->parent); + int ret; + + ret = regmap_write(tps65086->regmap, TPS65086_FORCESHUTDN, 1); + if (ret) { + dev_err(tps65086_restart->dev, "%s: error writing to tps65086 pmic: %d\n", + __func__, ret); + return NOTIFY_DONE; + } + + /* give it a little time */ + mdelay(200); + + WARN_ON(1); + + return NOTIFY_DONE; +} + +static int tps65086_restart_probe(struct platform_device *pdev) +{ + struct tps65086_restart *tps65086_restart; + int ret; + + tps65086_restart = devm_kzalloc(&pdev->dev, sizeof(*tps65086_restart), GFP_KERNEL); + if (!tps65086_restart) + return -ENOMEM; + + platform_set_drvdata(pdev, tps65086_restart); + + tps65086_restart->handler.notifier_call = tps65086_restart_notify; + tps65086_restart->handler.priority = 192; + tps65086_restart->dev = &pdev->dev; + + ret = register_restart_handler(&tps65086_restart->handler); + if (ret) { + dev_err(&pdev->dev, "%s: cannot register restart handler: %d\n", + __func__, ret); + return -ENODEV; + } + + return 0; +} + +static int tps65086_restart_remove(struct platform_device *pdev) +{ + struct tps65086_restart *tps65086_restart = platform_get_drvdata(pdev); + int ret; + + ret = unregister_restart_handler(&tps65086_restart->handler); + if (ret) { + dev_err(&pdev->dev, "%s: cannot unregister restart handler: %d\n", + __func__, ret); + return -ENODEV; + } + + return 0; +} + +static const struct platform_device_id tps65086_restart_id_table[] = { + { "tps65086-reset", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, tps65086_restart_id_table); + +static struct platform_driver tps65086_restart_driver = { + .driver = { + .name = "tps65086-restart", + }, + .probe = tps65086_restart_probe, + .remove = tps65086_restart_remove, + .id_table = tps65086_restart_id_table, +}; +module_platform_driver(tps65086_restart_driver); + +MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>"); +MODULE_DESCRIPTION("TPS65086 restart driver"); +MODULE_LICENSE("GPL v2");