ARM: restart-notifier support for some architectures
Subsystems (5)
Heiko Stübner
maintainercover ARM: restart-notifier support for some architectures
This series provides restart-notifier integration for the architectures I care about - S3C24XX and Rockchip.
It of course depends on "kernel: Add support for restart notifier call chain" from Guenter Roeck.
Samsung machines can generally be reset using their watchdog, but some also provide a special software-reset register in their system controller.
The rockchip reset integration of course also depends on the core clock support series, currently still under review.
Heiko Stuebner (3):
watchdog: s3c2410: add restart notifier
clk: samsung: register restart notifiers for s3c2412 and s3c2443
clk: rockchip: add restart notifier
drivers/clk/rockchip/clk-rk3188.c | 2 ++ drivers/clk/rockchip/clk-rk3288.c | 2 ++ drivers/clk/rockchip/clk.c | 23 +++++++++++++++++++++++ drivers/clk/rockchip/clk.h | 1 + drivers/clk/samsung/clk-s3c2412.c | 28 ++++++++++++++++++++++++++++ drivers/clk/samsung/clk-s3c2443.c | 18 ++++++++++++++++++ drivers/watchdog/s3c2410_wdt.c | 33 +++++++++++++++++++++++++++++++++ 7 files changed, 107 insertions(+)
Signature · 1 line
1.9.0
Heiko Stübner
maintainerRFC PATCH 1/3 watchdog: s3c2410: add restart notifier
On a lot of Samsung systems the watchdog is responsible for restarting the system and until now this code was contained in plat-samsung/watchdog-reset.c .
With the introduction of the restart notifiers, this code can now move into driver itself, removing the need for arch-specific code.
Tested on a S3C2442 based GTA02
--- drivers/watchdog/s3c2410_wdt.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
drivers/watchdog/s3c2410_wdt.c +33 -0
@@ -41,6 +41,7 @@#include <linux/of.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> +#include <linux/reboot.h> #define S3C2410_WTCON 0x00#define S3C2410_WTDAT 0x04
@@ -438,6 +439,31 @@ static inline void s3c2410wdt_cpufreq_deregister(struct s3c2410_wdt *wdt) }#endif +static struct s3c2410_wdt *s3c2410wdt_restart_ctx; +static int s3c2410wdt_restart_notify (struct notifier_block *this, +unsigned long mode,void *cmd) +{ +void __iomem *wdt_base = s3c2410wdt_restart_ctx->reg_base; + +/* disable watchdog, to be safe */ +writel (0 , wdt_base +S3C2410_WTCON ); + +/* put initial values into count and data */ +writel (0x80 , wdt_base +S3C2410_WTCNT ); +writel (0x80 , wdt_base +S3C2410_WTDAT ); + +/* set the watchdog to go and reset... */ +writel (S3C2410_WTCON_ENABLE |S3C2410_WTCON_DIV16 | +S3C2410_WTCON_RSTEN |S3C2410_WTCON_PRESCALE (0x20 ), + wdt_base +S3C2410_WTCON ); + +return NOTIFY_DONE ; +} + +static struct notifier_block s3c2410wdt_restart_notifier = { + .notifier_call = s3c2410wdt_restart_notify, +}; +static inline unsigned int s3c2410wdt_get_bootstatus (struct s3c2410_wdt *wdt) {unsigned int rst_stat;
@@ -592,6 +618,11 @@ static int s3c2410wdt_probe(struct platform_device *pdev)platform_set_drvdata (pdev, wdt); + s3c2410wdt_restart_ctx = wdt; + ret =register_restart_notifier (&s3c2410wdt_restart_notifier); +if (ret) +pr_err ("cannot register restart notifier, %d\n" , ret); +/* print out a statement of readiness */ wtcon =readl (wdt->reg_base +S3C2410_WTCON );
@@ -621,6 +652,8 @@ static int s3c2410wdt_remove(struct platform_device *dev)int ret;struct s3c2410_wdt *wdt =platform_get_drvdata (dev); +unregister_restart_notifier (&s3c2410wdt_restart_notifier); + ret =s3c2410wdt_mask_and_disable_reset (wdt, true);if (ret <0 )return ret;
Signature · 1 line
1.9.0
RFC PATCH 1/3 watchdog: s3c2410: add restart notifier
Hi Heiko,
Quoted 25 lines · Heiko St?bner
On a lot of Samsung systems the watchdog is responsible for restarting the system and until now this code was contained in
plat-samsung/watchdog-reset.c.With the introduction of the restart notifiers, this code can now move into driver itself, removing the need for arch-specific code.
Tested on a S3C2442 based GTA02
Signed-off-by Heiko Stuebner <[email protected]>--- drivers/watchdog/s3c2410_wdt.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)drivers/watchdog/s3c2410_wdt.c +1
-0@@ -41,6 +41,7 @@#include <linux/of.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> +#include <linux/reboot.h> #define S3C2410_WTCON 0x00#define S3C2410_WTDAT 0x04
drivers/watchdog/s3c2410_wdt.c static inline void s3c2410wdt_cpufreq_deregister(struct s3c2410_wdt *wdt) · line 442
Quoted 4 lines
drivers/watchdog/s3c2410_wdt.c +1
-0@@ -438,6 +439,31 @@ static inline void s3c2410wdt_cpufreq_deregister(struct s3c2410_wdt *wdt) }#endif +static struct s3c2410_wdt *s3c2410wdt_restart_ctx;
This isn't the most elegant way to store context data. Maybe you could embed the notifier_block struct into s3c2410_wdt struct and then use container of to retrieve it from s3c2410wdt_restart_notify()?
Quoted 6 lines
drivers/watchdog/s3c2410_wdt.c +6
-0+static int s3c2410wdt_restart_notify (struct notifier_block *this, +unsigned long mode,void *cmd) +{ +void __iomem *wdt_base = s3c2410wdt_restart_ctx->reg_base; + +/* disable watchdog, to be safe */
drivers/watchdog/s3c2410_wdt.c static inline void s3c2410wdt_cpufreq_deregister(struct s3c2410_wdt *wdt) · line 458
Quoted 10 lines
drivers/watchdog/s3c2410_wdt.c +10
-0+writel (0 , wdt_base +S3C2410_WTCON ); + +/* put initial values into count and data */ +writel (0x80 , wdt_base +S3C2410_WTCNT ); +writel (0x80 , wdt_base +S3C2410_WTDAT ); + +/* set the watchdog to go and reset... */ +writel (S3C2410_WTCON_ENABLE |S3C2410_WTCON_DIV16 | +S3C2410_WTCON_RSTEN |S3C2410_WTCON_PRESCALE (0x20 ), + wdt_base +S3C2410_WTCON );
I wonder whether you shouldn't wait a bit here for the reset to be actually triggered.
Best regards,
Tomasz
Guenter Roeck
maintainerRFC PATCH 1/3 watchdog: s3c2410: add restart notifier
Quoted 31 lines · Tomasz Figa
Hi Heiko,
Quoted 28 lines · Heiko St?bner
On a lot of Samsung systems the watchdog is responsible for restarting the system and until now this code was contained in
plat-samsung/watchdog-reset.c.With the introduction of the restart notifiers, this code can now move into driver itself, removing the need for arch-specific code.
Tested on a S3C2442 based GTA02
Signed-off-by Heiko Stuebner <[email protected]>--- drivers/watchdog/s3c2410_wdt.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)drivers/watchdog/s3c2410_wdt.c +1
-0@@ -41,6 +41,7 @@#include <linux/of.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> +#include <linux/reboot.h> #define S3C2410_WTCON 0x00#define S3C2410_WTDAT 0x04@@ -438,6 +439,31 @@ static inline void s3c2410wdt_cpufreq_deregister(struct s3c2410_wdt *wdt) }#endif
Quoted 6 lines
drivers/watchdog/s3c2410_wdt.c static inline void s3c2410wdt_cpufreq_deregister(struct s3c2410_wdt *wdt) · line 442
Quoted 1 line
drivers/watchdog/s3c2410_wdt.c +1
-0+static struct s3c2410_wdt *s3c2410wdt_restart_ctx;This isn't the most elegant way to store context data. Maybe you could embed the
notifier_blockstruct intos3c2410_wdtstruct and then use container of to retrieve it froms3c2410wdt_restart_notify()?
Excellent idea. I'll do that for the moxart handler as well.
Guenter
Heiko Stübner
maintainerRFC PATCH 2/3 clk: samsung: register restart notifiers for s3c2412 and s3c2443
In reply to Heiko StübnerS3C2412, S3C2443 and their derivatives contain a special software-reset register in their system-controller.
Therefore register a restart-notifier for those.
Tested on a s3c2416-based board, s3c2412 compile-tested.
--- drivers/clk/samsung/clk-s3c2412.c | 28 ++++++++++++++++++++++++++++ drivers/clk/samsung/clk-s3c2443.c | 18 ++++++++++++++++++ 2 files changed, 46 insertions(+)
drivers/clk/samsung/clk-s3c2412.c +28 -0
@@ -14,6 +14,7 @@#include <linux/of.h> #include <linux/of_address.h> #include <linux/syscore_ops.h> +#include <linux/reboot.h> #include <dt-bindings/clock/s3c2412.h>
@@ -26,6 +27,7 @@#define CLKCON 0x0c#define CLKDIVN 0x14#define CLKSRC 0x1c +#define SWRST 0x30/* list of PLLs to be registered */ enum s3c2412_plls {
@@ -204,6 +206,27 @@ struct samsung_clock_alias s3c2412_aliases[] __initdata = { ALIAS(MSYSCLK, NULL, "fclk"), }; +static int s3c2412_restart_notify (struct notifier_block *this, +unsigned long mode,void *cmd) +{ +/* errata "Watch-dog/Software Reset Problem" specifies that +* this reset must be done with the SYSCLK sourced from +* EXTCLK instead of FOUT to avoid a glitch in the reset +* mechanism. +* +* See the watchdog section of the S3C2412 manual for more +* information on this fix. +*/ + +__raw_writel (0x00 , reg_base +CLKSRC ); +__raw_writel (0x533C2412 , reg_base +SWRST ); +return NOTIFY_DONE ; +} + +static struct notifier_block s3c2412_restart_notifier = { + .notifier_call = s3c2412_restart_notify, +}; +/* * fixed rate clocks generated outside the soc * Only necessary until the devicetree-move is complete
@@ -233,6 +256,7 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, unsigned long ext_f, void __iomem *base) { struct samsung_clk_provider *ctx; +int ret; reg_base = base;if (np) {
@@ -265,6 +289,10 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, ARRAY_SIZE(s3c2412_aliases));s3c2412_clk_sleep_init (); + + ret =register_restart_notifier (&s3c2412_restart_notifier); +if (ret) +pr_warn ("cannot register restart notifier, %d\n" , ret); }static void __init s3c2412_clk_init (struct device_node *np)
drivers/clk/samsung/clk-s3c2443.c +18 -0
@@ -14,6 +14,7 @@#include <linux/of.h> #include <linux/of_address.h> #include <linux/syscore_ops.h> +#include <linux/reboot.h> #include <dt-bindings/clock/s3c2443.h>
@@ -33,6 +34,7 @@#define HCLKCON 0x30#define PCLKCON 0x34#define SCLKCON 0x38 +#define SWRST 0x44/* the soc types */ enum supported_socs {
@@ -354,6 +356,17 @@ struct samsung_clock_alias s3c2450_aliases[] __initdata = { ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"), }; +static int s3c2443_restart_notify (struct notifier_block *this, +unsigned long mode,void *cmd) +{ +__raw_writel (0x533c2443 , reg_base +SWRST ); +return NOTIFY_DONE ; +} + +static struct notifier_block s3c2443_restart_notifier = { + .notifier_call = s3c2443_restart_notify, +}; +/* * fixed rate clocks generated outside the soc * Only necessary until the devicetree-move is complete
@@ -378,6 +391,7 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, void __iomem *base) {struct samsung_clk_provider *ctx; +int ret; reg_base = base;if (np) {
@@ -445,6 +459,10 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, }s3c2443_clk_sleep_init (); + + ret =register_restart_notifier (&s3c2443_restart_notifier); +if (ret) +pr_warn ("cannot register restart notifier, %d\n" , ret); }static void __init s3c2416_clk_init (struct device_node *np)
Signature · 1 line
1.9.0
RFC PATCH 2/3 clk: samsung: register restart notifiers for s3c2412 and s3c2443
Hi Heiko,
Quoted 4 lines · Heiko St?bner
S3C2412, S3C2443 and their derivatives contain a special software-reset register in their system-controller.
Therefore register a restart-notifier for those.
I wonder if we really need to differentiate between these SoCs instead of just using the watchdog reset for all of them. If there is no reason to prefer software reset, then some code could be removed and things would be more unified.
Best regards,
Tomasz
Guenter Roeck
maintainerRFC PATCH 2/3 clk: samsung: register restart notifiers for s3c2412 and s3c2443
Quoted 6 lines · Tomasz Figa
Hi Heiko,
Quoted 3 lines · Heiko St?bner
S3C2412, S3C2443 and their derivatives contain a special software-reset register in their system-controller.
Quoted 7 lines
Quoted 1 line
Therefore register a restart-notifier for those.
I wonder if we really need to differentiate between these SoCs instead of just using the watchdog reset for all of them. If there is no reason to prefer software reset, then some code could be removed and things would be more unified.
Depends if the other method is always available. If not, it might make sense to register this handler with lower priority to have a fallback.
Guenter
Heiko Stübner
maintainerRFC PATCH 3/3 clk: rockchip: add restart notifier
In reply to Heiko StübnerAdd infrastructure to write the correct value to the restart register and register the restart notifier for both rk3188 (including rk3066) and rk3188.
--- drivers/clk/rockchip/clk-rk3188.c | 2 ++ drivers/clk/rockchip/clk-rk3288.c | 2 ++ drivers/clk/rockchip/clk.c | 23 +++++++++++++++++++++++ drivers/clk/rockchip/clk.h | 1 + 4 files changed, 28 insertions(+)
drivers/clk/rockchip/clk-rk3188.c +2 -0
@@ -631,6 +631,8 @@ static void __init rk3188_common_clk_init(struct device_node *np)rockchip_register_softrst (np,9 , reg_base +RK2928_SOFTRST_CON (0 ),ROCKCHIP_SOFTRST_HIWORD_MASK ); + +rockchip_register_restart_notifier (RK2928_GLB_SRST_FST ); }static void __init rk3066a_clk_init (struct device_node *np)
drivers/clk/rockchip/clk-rk3288.c +2 -0
@@ -713,5 +713,7 @@ static void __init rk3288_clk_init(struct device_node *np)rockchip_register_softrst (np,9 , reg_base +RK3288_SOFTRST_CON (0 ),ROCKCHIP_SOFTRST_HIWORD_MASK ); + +rockchip_register_restart_notifier (RK3288_GLB_SRST_FST ); }CLK_OF_DECLARE (rk3288_cru,"rockchip,rk3288-cru" , rk3288_clk_init);
drivers/clk/rockchip/clk.c +23 -0
@@ -25,6 +25,7 @@#include <linux/clk-provider.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> +#include <linux/reboot.h> #include "clk.h" /**
@@ -242,3 +243,25 @@ void __init rockchip_clk_register_branches(rockchip_clk_add_lookup (clk, list->id); } } + +static unsigned int reg_restart; +static int rockchip_restart_notify (struct notifier_block *this, +unsigned long mode,void *cmd) +{ +writel (0xfdb9 , reg_base + reg_restart); +return NOTIFY_DONE ; +} + +static struct notifier_block rockchip_restart_notifier = { + .notifier_call = rockchip_restart_notify, +}; + +void __init rockchip_register_restart_notifier (unsigned int reg) +{ +int ret; + + reg_restart = reg; + ret =register_restart_notifier (&rockchip_restart_notifier); +if (ret) +pr_err ("cannot register restart notifier, %d\n" , ret); +}
drivers/clk/rockchip/clk.h +1 -0
@@ -329,6 +329,7 @@ void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, unsigned int nr_clk);void rockchip_clk_register_plls (struct rockchip_pll_clock *pll_list,unsigned int nr_pll,int grf_lock_offset); +void rockchip_register_restart_notifier (unsigned int reg);#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
Signature · 1 line
1.9.0