Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

power: reset: Add a driver for the ep93xx reset

Implement the reset behaviour of the various EP93xx SoCS
in drivers/power/reset.

It used to be located in arch/arm/mach-ep93xx.

Signed-off-by: Nikita Shubin <nikita.shubin@maquefel.me>
Tested-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
Acked-by: Sebastian Reichel <sre@kernel.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

authored by

Nikita Shubin and committed by
Arnd Bergmann
9fa7cdb4 035f9007

+95
+10
drivers/power/reset/Kconfig
··· 75 75 Say Y here if you have a Broadcom STB board and you wish 76 76 to have restart support. 77 77 78 + config POWER_RESET_EP93XX 79 + bool "Cirrus EP93XX reset driver" if COMPILE_TEST 80 + depends on MFD_SYSCON 81 + default ARCH_EP93XX 82 + help 83 + This driver provides restart support for Cirrus EP93XX SoC. 84 + 85 + Say Y here if you have a Cirrus EP93XX SoC and you wish 86 + to have restart support. 87 + 78 88 config POWER_RESET_GEMINI_POWEROFF 79 89 bool "Cortina Gemini power-off driver" 80 90 depends on ARCH_GEMINI || COMPILE_TEST
+1
drivers/power/reset/Makefile
··· 7 7 obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o 8 8 obj-$(CONFIG_POWER_RESET_BRCMKONA) += brcm-kona-reset.o 9 9 obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o 10 + obj-$(CONFIG_POWER_RESET_EP93XX) += ep93xx-restart.o 10 11 obj-$(CONFIG_POWER_RESET_GEMINI_POWEROFF) += gemini-poweroff.o 11 12 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o 12 13 obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
+84
drivers/power/reset/ep93xx-restart.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Cirrus EP93xx SoC reset driver 4 + * 5 + * Copyright (C) 2021 Nikita Shubin <nikita.shubin@maquefel.me> 6 + */ 7 + 8 + #include <linux/bits.h> 9 + #include <linux/container_of.h> 10 + #include <linux/delay.h> 11 + #include <linux/errno.h> 12 + #include <linux/mfd/syscon.h> 13 + #include <linux/module.h> 14 + #include <linux/mod_devicetable.h> 15 + #include <linux/notifier.h> 16 + #include <linux/reboot.h> 17 + #include <linux/slab.h> 18 + 19 + #include <linux/soc/cirrus/ep93xx.h> 20 + 21 + #define EP93XX_SYSCON_DEVCFG 0x80 22 + #define EP93XX_SYSCON_DEVCFG_SWRST BIT(31) 23 + 24 + struct ep93xx_restart { 25 + struct ep93xx_regmap_adev *aux_dev; 26 + struct notifier_block restart_handler; 27 + }; 28 + 29 + static int ep93xx_restart_handle(struct notifier_block *this, 30 + unsigned long mode, void *cmd) 31 + { 32 + struct ep93xx_restart *priv = 33 + container_of(this, struct ep93xx_restart, restart_handler); 34 + struct ep93xx_regmap_adev *aux = priv->aux_dev; 35 + 36 + /* Issue the reboot */ 37 + aux->update_bits(aux->map, aux->lock, EP93XX_SYSCON_DEVCFG, 38 + EP93XX_SYSCON_DEVCFG_SWRST, EP93XX_SYSCON_DEVCFG_SWRST); 39 + aux->update_bits(aux->map, aux->lock, EP93XX_SYSCON_DEVCFG, 40 + EP93XX_SYSCON_DEVCFG_SWRST, 0); 41 + 42 + return NOTIFY_DONE; 43 + } 44 + 45 + static int ep93xx_reboot_probe(struct auxiliary_device *adev, 46 + const struct auxiliary_device_id *id) 47 + { 48 + struct ep93xx_regmap_adev *rdev = to_ep93xx_regmap_adev(adev); 49 + struct device *dev = &adev->dev; 50 + struct ep93xx_restart *priv; 51 + int err; 52 + 53 + if (!rdev->update_bits) 54 + return -ENODEV; 55 + 56 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 57 + if (!priv) 58 + return -ENOMEM; 59 + 60 + priv->aux_dev = rdev; 61 + 62 + priv->restart_handler.notifier_call = ep93xx_restart_handle; 63 + priv->restart_handler.priority = 128; 64 + 65 + err = register_restart_handler(&priv->restart_handler); 66 + if (err) 67 + return dev_err_probe(dev, err, "can't register restart notifier\n"); 68 + 69 + return 0; 70 + } 71 + 72 + static const struct auxiliary_device_id ep93xx_reboot_ids[] = { 73 + { 74 + .name = "soc_ep93xx.reset-ep93xx", 75 + }, 76 + { /* sentinel */ } 77 + }; 78 + MODULE_DEVICE_TABLE(auxiliary, ep93xx_reboot_ids); 79 + 80 + static struct auxiliary_driver ep93xx_reboot_driver = { 81 + .probe = ep93xx_reboot_probe, 82 + .id_table = ep93xx_reboot_ids, 83 + }; 84 + module_auxiliary_driver(ep93xx_reboot_driver);