From 76ee875c2f48c57cbafa35d9c3b34e7202a45a83 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sun, 11 Nov 2018 22:45:38 +0100 Subject: power: reset: gpio-poweroff: add ability to specific active and inactive delays Similar to gpio-reset allow to specify active and inactive delays while keeping the 100ms defaults that were used previously all the time. The dt-properties are named the same as in gpio-reset but get an "-ms" suffix as properties should contain such a suffix specifying its unit. Signed-off-by: Heiko Stuebner Reviewed-by: Rob Herring Reviewed-by: Moritz Fischer Signed-off-by: Sebastian Reichel --- drivers/power/reset/gpio-poweroff.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/power/reset') diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c index 38206c39b3bf..52525b6c18db 100644 --- a/drivers/power/reset/gpio-poweroff.c +++ b/drivers/power/reset/gpio-poweroff.c @@ -26,6 +26,8 @@ */ static struct gpio_desc *reset_gpio; static u32 timeout = DEFAULT_TIMEOUT_MS; +static u32 active_delay = 100; +static u32 inactive_delay = 100; static void gpio_poweroff_do_poweroff(void) { @@ -33,10 +35,11 @@ static void gpio_poweroff_do_poweroff(void) /* drive it active, also inactive->active edge */ gpiod_direction_output(reset_gpio, 1); - mdelay(100); + mdelay(active_delay); + /* drive inactive, also active->inactive edge */ gpiod_set_value_cansleep(reset_gpio, 0); - mdelay(100); + mdelay(inactive_delay); /* drive it active, also inactive->active edge */ gpiod_set_value_cansleep(reset_gpio, 1); @@ -66,6 +69,9 @@ static int gpio_poweroff_probe(struct platform_device *pdev) else flags = GPIOD_OUT_LOW; + device_property_read_u32(&pdev->dev, "active-delay-ms", &active_delay); + device_property_read_u32(&pdev->dev, "inactive-delay-ms", + &inactive_delay); device_property_read_u32(&pdev->dev, "timeout-ms", &timeout); reset_gpio = devm_gpiod_get(&pdev->dev, NULL, flags); -- cgit 1.4.1 From 9afe62509b329dbd973b8fdcdf168ddc5b5098cb Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 9 Nov 2018 20:57:00 +0100 Subject: power: reset: ocelot: switch the SI to boot mode Switch the SI to boot mode so on a warm reboot, the SI is able to access the flash. Signed-off-by: Alexandre Belloni Signed-off-by: Sebastian Reichel --- drivers/power/reset/ocelot-reset.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/power/reset') diff --git a/drivers/power/reset/ocelot-reset.c b/drivers/power/reset/ocelot-reset.c index 5a13a5cc8188..419952c61fd0 100644 --- a/drivers/power/reset/ocelot-reset.c +++ b/drivers/power/reset/ocelot-reset.c @@ -26,6 +26,13 @@ struct ocelot_reset_context { #define SOFT_CHIP_RST BIT(0) +#define ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL 0x24 +#define IF_SI_OWNER_MASK GENMASK(1, 0) +#define IF_SI_OWNER_SISL 0 +#define IF_SI_OWNER_SIBM 1 +#define IF_SI_OWNER_SIMC 2 +#define IF_SI_OWNER_OFFSET 4 + static int ocelot_restart_handle(struct notifier_block *this, unsigned long mode, void *cmd) { @@ -37,6 +44,11 @@ static int ocelot_restart_handle(struct notifier_block *this, regmap_update_bits(ctx->cpu_ctrl, ICPU_CFG_CPU_SYSTEM_CTRL_RESET, CORE_RST_PROTECT, 0); + /* Make the SI back to boot mode */ + regmap_update_bits(ctx->cpu_ctrl, ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL, + IF_SI_OWNER_MASK << IF_SI_OWNER_OFFSET, + IF_SI_OWNER_SIBM << IF_SI_OWNER_OFFSET); + writel(SOFT_CHIP_RST, ctx->base); pr_emerg("Unable to restart system\n"); -- cgit 1.4.1 From 996463fdb8cdec453a8b56ab6956da40a5af1360 Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Mon, 5 Nov 2018 11:14:23 +0000 Subject: power: reset: at91-poweroff: use one poweroff function for at91-poweroff Use only one poweroff function and adapt it to work for both scenarios (with LPDDR or not). The assignement of pm_power_off was moved at the end of probe after all initializations are OK. This patch adapt the idea from commit 4e018c1e9b05 ("power: reset: at91-poweroff: use only one poweroff function"). Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-poweroff.c | 49 ++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 22 deletions(-) (limited to 'drivers/power/reset') diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c index fb2fc8f741a1..82533f4c72fc 100644 --- a/drivers/power/reset/at91-poweroff.c +++ b/drivers/power/reset/at91-poweroff.c @@ -75,11 +75,6 @@ static void __init at91_wakeup_status(struct platform_device *pdev) } static void at91_poweroff(void) -{ - writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, at91_shdwc_base + AT91_SHDW_CR); -} - -static void at91_lpddr_poweroff(void) { asm volatile( /* Align to cache lines */ @@ -89,9 +84,11 @@ static void at91_lpddr_poweroff(void) " ldr r6, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t" /* Power down SDRAM0 */ + " tst %0, #0\n\t" + " beq 1f\n\t" " str %1, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t" /* Shutdown CPU */ - " str %3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t" + "1: str %3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t" " b .\n\t" : @@ -177,34 +174,42 @@ static int __init at91_poweroff_probe(struct platform_device *pdev) if (pdev->dev.of_node) at91_poweroff_dt_set_wakeup_mode(pdev); - pm_power_off = at91_poweroff; - np = of_find_compatible_node(NULL, NULL, "atmel,sama5d3-ddramc"); - if (!np) - return 0; + if (np) { + mpddrc_base = of_iomap(np, 0); + of_node_put(np); - mpddrc_base = of_iomap(np, 0); - of_node_put(np); + if (!mpddrc_base) { + ret = -ENOMEM; + goto clk_disable; + } - if (!mpddrc_base) - return 0; + ddr_type = readl(mpddrc_base + AT91_DDRSDRC_MDR) & + AT91_DDRSDRC_MD; + if (ddr_type != AT91_DDRSDRC_MD_LPDDR2 && + ddr_type != AT91_DDRSDRC_MD_LPDDR3) { + iounmap(mpddrc_base); + mpddrc_base = NULL; + } + } - ddr_type = readl(mpddrc_base + AT91_DDRSDRC_MDR) & AT91_DDRSDRC_MD; - if ((ddr_type == AT91_DDRSDRC_MD_LPDDR2) || - (ddr_type == AT91_DDRSDRC_MD_LPDDR3)) - pm_power_off = at91_lpddr_poweroff; - else - iounmap(mpddrc_base); + pm_power_off = at91_poweroff; return 0; + +clk_disable: + clk_disable_unprepare(sclk); + return ret; } static int __exit at91_poweroff_remove(struct platform_device *pdev) { - if (pm_power_off == at91_poweroff || - pm_power_off == at91_lpddr_poweroff) + if (pm_power_off == at91_poweroff) pm_power_off = NULL; + if (mpddrc_base) + iounmap(mpddrc_base); + clk_disable_unprepare(sclk); return 0; -- cgit 1.4.1 From e6ae9a05a41abdb80b4d93574e84609a35cfb98c Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Mon, 5 Nov 2018 11:14:31 +0000 Subject: power: reset: at91-poweroff: remove at91_ramc_of_match Remove at91_ramc_of_match[] since it is not used anywhere in this code. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-poweroff.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/power/reset') diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c index 82533f4c72fc..d3d87af24e55 100644 --- a/drivers/power/reset/at91-poweroff.c +++ b/drivers/power/reset/at91-poweroff.c @@ -215,11 +215,6 @@ static int __exit at91_poweroff_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id at91_ramc_of_match[] = { - { .compatible = "atmel,sama5d3-ddramc", }, - { /* sentinel */ } -}; - static const struct of_device_id at91_poweroff_of_match[] = { { .compatible = "atmel,at91sam9260-shdwc", }, { .compatible = "atmel,at91sam9rl-shdwc", }, -- cgit 1.4.1 From caa6e150f8fbcf4011cb7f3b30448f1b1de63b4f Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 6 Dec 2018 17:29:46 +0000 Subject: power: reset: at91-poweroff: move shdwc related data to one structure Move SHDWC realted data to only one structure to have them grouped. Inspired from commit 9be74f0d39c1 ("power: reset: at91-poweroff: make mpddrc_base part of struct shdwc"). Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-poweroff.c | 48 +++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'drivers/power/reset') diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c index d3d87af24e55..9e74e131c675 100644 --- a/drivers/power/reset/at91-poweroff.c +++ b/drivers/power/reset/at91-poweroff.c @@ -51,14 +51,16 @@ static const char *shdwc_wakeup_modes[] = { [AT91_SHDW_WKMODE0_ANYLEVEL] = "any", }; -static void __iomem *at91_shdwc_base; -static struct clk *sclk; -static void __iomem *mpddrc_base; +static struct shdwc { + struct clk *sclk; + void __iomem *shdwc_base; + void __iomem *mpddrc_base; +} at91_shdwc; static void __init at91_wakeup_status(struct platform_device *pdev) { const char *reason; - u32 reg = readl(at91_shdwc_base + AT91_SHDW_SR); + u32 reg = readl(at91_shdwc.shdwc_base + AT91_SHDW_SR); /* Simple power-on, just bail out */ if (!reg) @@ -92,9 +94,9 @@ static void at91_poweroff(void) " b .\n\t" : - : "r" (mpddrc_base), + : "r" (at91_shdwc.mpddrc_base), "r" cpu_to_le32(AT91_DDRSDRC_LPDDR2_PWOFF), - "r" (at91_shdwc_base), + "r" (at91_shdwc.shdwc_base), "r" cpu_to_le32(AT91_SHDW_KEY | AT91_SHDW_SHDW) : "r6"); } @@ -144,7 +146,7 @@ static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev) if (of_property_read_bool(np, "atmel,wakeup-rtt-timer")) mode |= AT91_SHDW_RTTWKEN; - writel(wakeup_mode | mode, at91_shdwc_base + AT91_SHDW_MR); + writel(wakeup_mode | mode, at91_shdwc.shdwc_base + AT91_SHDW_MR); } static int __init at91_poweroff_probe(struct platform_device *pdev) @@ -155,15 +157,15 @@ static int __init at91_poweroff_probe(struct platform_device *pdev) int ret; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(at91_shdwc_base)) - return PTR_ERR(at91_shdwc_base); + at91_shdwc.shdwc_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(at91_shdwc.shdwc_base)) + return PTR_ERR(at91_shdwc.shdwc_base); - sclk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(sclk)) - return PTR_ERR(sclk); + at91_shdwc.sclk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(at91_shdwc.sclk)) + return PTR_ERR(at91_shdwc.sclk); - ret = clk_prepare_enable(sclk); + ret = clk_prepare_enable(at91_shdwc.sclk); if (ret) { dev_err(&pdev->dev, "Could not enable slow clock\n"); return ret; @@ -176,20 +178,20 @@ static int __init at91_poweroff_probe(struct platform_device *pdev) np = of_find_compatible_node(NULL, NULL, "atmel,sama5d3-ddramc"); if (np) { - mpddrc_base = of_iomap(np, 0); + at91_shdwc.mpddrc_base = of_iomap(np, 0); of_node_put(np); - if (!mpddrc_base) { + if (!at91_shdwc.mpddrc_base) { ret = -ENOMEM; goto clk_disable; } - ddr_type = readl(mpddrc_base + AT91_DDRSDRC_MDR) & + ddr_type = readl(at91_shdwc.mpddrc_base + AT91_DDRSDRC_MDR) & AT91_DDRSDRC_MD; if (ddr_type != AT91_DDRSDRC_MD_LPDDR2 && ddr_type != AT91_DDRSDRC_MD_LPDDR3) { - iounmap(mpddrc_base); - mpddrc_base = NULL; + iounmap(at91_shdwc.mpddrc_base); + at91_shdwc.mpddrc_base = NULL; } } @@ -198,7 +200,7 @@ static int __init at91_poweroff_probe(struct platform_device *pdev) return 0; clk_disable: - clk_disable_unprepare(sclk); + clk_disable_unprepare(at91_shdwc.sclk); return ret; } @@ -207,10 +209,10 @@ static int __exit at91_poweroff_remove(struct platform_device *pdev) if (pm_power_off == at91_poweroff) pm_power_off = NULL; - if (mpddrc_base) - iounmap(mpddrc_base); + if (at91_shdwc.mpddrc_base) + iounmap(at91_shdwc.mpddrc_base); - clk_disable_unprepare(sclk); + clk_disable_unprepare(at91_shdwc.sclk); return 0; } -- cgit 1.4.1