Hi,
This patchset is an attempt to further cleanup mach-at91 by removing
code that can be put into a driver nowadays.
This time, the target is the reset and poweroff code, that can now be
put in drivers/power/reset.
Maxime
Maxime Ripard (18):
power: reset: Add if statement isntead of multiple depends on
AT91: setup: Switch to pr_fmt
AT91: G45: DT: Declare a second ram controller
AT91: Rework ramc mapping code
AT91: SAMA5D3: DT: Add shutdown controller
power: reset: Add AT91 reset driver
AT91: DT: Remove the old-style reset probing
AT91: soc: Introduce register_devices callback
AT91: Probe the reset driver
AT91: Call at91_register_devices in the board files
AT91: Remove reset code the machine code
power: reset: Add AT91 poweroff driver
AT91: DT: Remove poweroff DT probing
AT91: Register the poweroff driver
AT91: Remove poweroff code
AT91: pm: Remove show_reset_status function
AT91: Remove rstc and shdwnc global base addresses
AT91: Remove rstc and shdwc headers
arch/arm/boot/dts/at91sam9g45.dtsi | 8 +-
arch/arm/boot/dts/sama5d3.dtsi | 5 +
arch/arm/mach-at91/Kconfig | 8 --
arch/arm/mach-at91/Makefile | 2 -
arch/arm/mach-at91/at91_rstc.h | 53 ---------
arch/arm/mach-at91/at91_shdwc.h | 50 --------
arch/arm/mach-at91/at91sam9260.c | 45 ++++++-
arch/arm/mach-at91/at91sam9261.c | 45 ++++++-
arch/arm/mach-at91/at91sam9263.c | 45 ++++++-
arch/arm/mach-at91/at91sam9_alt_reset.S | 40 -------
arch/arm/mach-at91/at91sam9g45.c | 49 +++++++-
arch/arm/mach-at91/at91sam9g45_reset.S | 45 -------
arch/arm/mach-at91/at91sam9rl.c | 45 ++++++-
arch/arm/mach-at91/board-afeb-9260v1.c | 2 +
arch/arm/mach-at91/board-cam60.c | 2 +
arch/arm/mach-at91/board-cpu9krea.c | 2 +
arch/arm/mach-at91/board-flexibity.c | 2 +
arch/arm/mach-at91/board-sam9-l9260.c | 2 +
arch/arm/mach-at91/board-sam9260ek.c | 3 +-
arch/arm/mach-at91/board-sam9261ek.c | 3 +-
arch/arm/mach-at91/board-sam9263ek.c | 3 +-
arch/arm/mach-at91/board-sam9m10g45ek.c | 3 +-
arch/arm/mach-at91/board-sam9rlek.c | 3 +-
arch/arm/mach-at91/board-snapper9260.c | 2 +
arch/arm/mach-at91/generic.h | 10 +-
arch/arm/mach-at91/pm.c | 72 ------------
arch/arm/mach-at91/setup.c | 178 +++++-----------------------
arch/arm/mach-at91/soc.h | 1 +
drivers/power/reset/Kconfig | 31 +++--
drivers/power/reset/Makefile | 2 +
drivers/power/reset/at91-poweroff.c | 156 ++++++++++++++++++++++++
drivers/power/reset/at91-reset.c | 202 ++++++++++++++++++++++++++++++++
32 files changed, 657 insertions(+), 462 deletions(-)
delete mode 100644 arch/arm/mach-at91/at91_rstc.h
delete mode 100644 arch/arm/mach-at91/at91_shdwc.h
delete mode 100644 arch/arm/mach-at91/at91sam9_alt_reset.S
delete mode 100644 arch/arm/mach-at91/at91sam9g45_reset.S
create mode 100644 drivers/power/reset/at91-poweroff.c
create mode 100644 drivers/power/reset/at91-reset.c
--
2.0.1
Now that the reset code is a driver of its own, just let the usual DT probing
mecanism do its job, and remove the code entirely in this case.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/setup.c | 29 -----------------------------
1 file changed, 29 deletions(-)
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index cc520596f23b..71003e40f01c 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -354,34 +354,6 @@ void __init at91_ioremap_matrix(u32 base_addr)
}
#if defined(CONFIG_OF) && !defined(CONFIG_ARCH_AT91X40)
-static struct of_device_id rstc_ids[] = {
- { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_alt_restart },
- { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
- { /*sentinel*/ }
-};
-
-static void at91_dt_rstc(void)
-{
- struct device_node *np;
- const struct of_device_id *of_id;
-
- np = of_find_matching_node(NULL, rstc_ids);
- if (!np)
- panic(pr_fmt("unable to find compatible rstc node in dtb\n"));
-
- at91_rstc_base = of_iomap(np, 0);
- if (!at91_rstc_base)
- panic(pr_fmt("unable to map rstc cpu registers\n"));
-
- of_id = of_match_node(rstc_ids, np);
- if (!of_id)
- panic(pr_fmt("rtsc no restart function available\n"));
-
- arm_pm_restart = of_id->data;
-
- of_node_put(np);
-}
-
static struct of_device_id ramc_ids[] = {
{ .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
{ .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
@@ -507,7 +479,6 @@ void __init at91rm9200_dt_initialize(void)
void __init at91_dt_initialize(void)
{
- at91_dt_rstc();
at91_dt_ramc();
at91_dt_shdwc();
--
2.0.1
Register the reset device in the right SoCs so that the reset driver is
actually probed even in the old-style probing case.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/at91sam9260.c | 26 ++++++++++++++++++++++++++
arch/arm/mach-at91/at91sam9261.c | 26 ++++++++++++++++++++++++++
arch/arm/mach-at91/at91sam9263.c | 26 ++++++++++++++++++++++++++
arch/arm/mach-at91/at91sam9g45.c | 31 +++++++++++++++++++++++++++++++
arch/arm/mach-at91/at91sam9rl.c | 26 ++++++++++++++++++++++++++
5 files changed, 135 insertions(+)
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index c3d22be73b7c..9ffab0cf94cd 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/clk/at91_pmc.h>
#include <asm/proc-fns.h>
@@ -358,6 +359,30 @@ static void __init at91sam9260_initialize(void)
at91_gpio_init(at91sam9260_gpio, 3);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_RSTC,
+ .end = AT91SAM9260_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_BASE_SDRAMC,
+ .end = AT91SAM9260_BASE_SDRAMC + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static void __init at91sam9260_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -407,5 +432,6 @@ AT91_SOC_START(at91sam9260)
| (1 << AT91SAM9260_ID_IRQ2),
.ioremap_registers = at91sam9260_ioremap_registers,
.register_clocks = at91sam9260_register_clocks,
+ .register_devices = at91sam9260_register_devices,
.init = at91sam9260_initialize,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index fb164a5d04a9..41fa9b9a6f05 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/clk/at91_pmc.h>
#include <asm/proc-fns.h>
@@ -321,6 +322,30 @@ static void __init at91sam9261_initialize(void)
at91_gpio_init(at91sam9261_gpio, 3);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_RSTC,
+ .end = AT91SAM9261_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_BASE_SDRAMC,
+ .end = AT91SAM9261_BASE_SDRAMC + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static void __init at91sam9261_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -370,5 +395,6 @@ AT91_SOC_START(at91sam9261)
| (1 << AT91SAM9261_ID_IRQ2),
.ioremap_registers = at91sam9261_ioremap_registers,
.register_clocks = at91sam9261_register_clocks,
+ .register_devices = at91sam9261_register_devices,
.init = at91sam9261_initialize,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index f30290572293..0c6949c342dc 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/clk/at91_pmc.h>
#include <asm/proc-fns.h>
@@ -339,6 +340,30 @@ static void __init at91sam9263_initialize(void)
at91_gpio_init(at91sam9263_gpio, 5);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_RSTC,
+ .end = AT91SAM9263_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_BASE_SDRAMC0,
+ .end = AT91SAM9263_BASE_SDRAMC0 + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static void __init at91sam9263_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -387,5 +412,6 @@ AT91_SOC_START(at91sam9263)
.extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1),
.ioremap_registers = at91sam9263_ioremap_registers,
.register_clocks = at91sam9263_register_clocks,
+ .register_devices = at91sam9263_register_devices,
.init = at91sam9263_initialize,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 9d3d544ac19c..61c0bc1185e9 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/clk/at91_pmc.h>
+#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
@@ -388,6 +389,35 @@ static void __init at91sam9g45_initialize(void)
at91_gpio_init(at91sam9g45_gpio, 5);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9G45_BASE_RSTC,
+ .end = AT91SAM9G45_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9G45_BASE_DDRSDRC1,
+ .end = AT91SAM9G45_BASE_DDRSDRC1 + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = AT91SAM9G45_BASE_DDRSDRC0,
+ .end = AT91SAM9G45_BASE_DDRSDRC0 + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-g45-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static void __init at91sam9g45_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -436,5 +466,6 @@ AT91_SOC_START(at91sam9g45)
.extern_irq = (1 << AT91SAM9G45_ID_IRQ0),
.ioremap_registers = at91sam9g45_ioremap_registers,
.register_clocks = at91sam9g45_register_clocks,
+ .register_devices = at91sam9g45_register_devices,
.init = at91sam9g45_initialize,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index a79960f57e6a..417c8b6fb85e 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -10,6 +10,7 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/clk/at91_pmc.h>
#include <asm/proc-fns.h>
@@ -331,6 +332,30 @@ static void __init at91sam9rl_initialize(void)
at91_gpio_init(at91sam9rl_gpio, 4);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9RL_BASE_RSTC,
+ .end = AT91SAM9RL_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9RL_BASE_SDRAMC,
+ .end = AT91SAM9RL_BASE_SDRAMC + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static void __init at91sam9rl_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -381,5 +406,6 @@ AT91_SOC_START(at91sam9rl)
#if defined(CONFIG_OLD_CLK_AT91)
.register_clocks = at91sam9rl_register_clocks,
#endif
+ .register_devices = at91sam9rl_register_devices,
.init = at91sam9rl_initialize,
AT91_SOC_END
--
2.0.1
Now that the transition is over and that we probe our reset driver in every
case, we can remove the legacy code from the machine directory.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/Kconfig | 8 ------
arch/arm/mach-at91/Makefile | 2 --
arch/arm/mach-at91/at91sam9260.c | 1 -
arch/arm/mach-at91/at91sam9261.c | 1 -
arch/arm/mach-at91/at91sam9263.c | 1 -
arch/arm/mach-at91/at91sam9_alt_reset.S | 40 -----------------------------
arch/arm/mach-at91/at91sam9g45.c | 1 -
arch/arm/mach-at91/at91sam9g45_reset.S | 45 ---------------------------------
arch/arm/mach-at91/at91sam9rl.c | 1 -
arch/arm/mach-at91/generic.h | 2 --
10 files changed, 102 deletions(-)
delete mode 100644 arch/arm/mach-at91/at91sam9_alt_reset.S
delete mode 100644 arch/arm/mach-at91/at91sam9g45_reset.S
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 45b55e0f0db6..d2a1ffec5e11 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -28,14 +28,6 @@ config OLD_CLK_AT91
bool
default AT91_PMC_UNIT && AT91_USE_OLD_CLK
-config AT91_SAM9_ALT_RESET
- bool
- default !ARCH_AT91X40
-
-config AT91_SAM9G45_RESET
- bool
- default !ARCH_AT91X40
-
config AT91_SAM9_TIME
bool
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 78e9cec282f4..2947834d93c3 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -8,8 +8,6 @@ obj-n :=
obj- :=
obj-$(CONFIG_OLD_CLK_AT91) += clock.o
-obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o
-obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o
obj-$(CONFIG_AT91_SAM9_TIME) += at91sam926x_time.o
obj-$(CONFIG_SOC_AT91SAM9) += sam9_smc.o
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 9ffab0cf94cd..197c0149406a 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -351,7 +351,6 @@ static void __init at91sam9260_ioremap_registers(void)
static void __init at91sam9260_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9_alt_restart;
at91_sysirq_mask_rtt(AT91SAM9260_BASE_RTT);
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 41fa9b9a6f05..ef44977f1cae 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -314,7 +314,6 @@ static void __init at91sam9261_ioremap_registers(void)
static void __init at91sam9261_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9_alt_restart;
at91_sysirq_mask_rtt(AT91SAM9261_BASE_RTT);
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 0c6949c342dc..cb078e150a19 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -331,7 +331,6 @@ static void __init at91sam9263_ioremap_registers(void)
static void __init at91sam9263_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9_alt_restart;
at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT0);
at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT1);
diff --git a/arch/arm/mach-at91/at91sam9_alt_reset.S b/arch/arm/mach-at91/at91sam9_alt_reset.S
deleted file mode 100644
index f039538d3bdb..000000000000
--- a/arch/arm/mach-at91/at91sam9_alt_reset.S
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * reset AT91SAM9G20 as per errata
- *
- * (C) BitBox Ltd 2010
- *
- * unless the SDRAM is cleanly shutdown before we hit the
- * reset register it can be left driving the data bus and
- * killing the chance of a subsequent boot from NAND
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/linkage.h>
-#include <mach/hardware.h>
-#include <mach/at91_ramc.h>
-#include "at91_rstc.h"
-
- .arm
-
- .globl at91sam9_alt_restart
-
-at91sam9_alt_restart: ldr r0, =at91_ramc_base @ preload constants
- ldr r0, [r0]
- ldr r4, =at91_rstc_base
- ldr r1, [r4]
-
- mov r2, #1
- mov r3, #AT91_SDRAMC_LPCB_POWER_DOWN
- ldr r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST
-
- .balign 32 @ align to cache line
-
- str r2, [r0, #AT91_SDRAMC_TR] @ disable SDRAM access
- str r3, [r0, #AT91_SDRAMC_LPR] @ power down SDRAM
- str r4, [r1, #AT91_RSTC_CR] @ reset processor
-
- b .
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 61c0bc1185e9..329749eb1dff 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -380,7 +380,6 @@ static void __init at91sam9g45_ioremap_registers(void)
static void __init at91sam9g45_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9g45_restart;
at91_sysirq_mask_rtc(AT91SAM9G45_BASE_RTC);
at91_sysirq_mask_rtt(AT91SAM9G45_BASE_RTT);
diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S
deleted file mode 100644
index c40c1e2ef80f..000000000000
--- a/arch/arm/mach-at91/at91sam9g45_reset.S
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * reset AT91SAM9G45 as per errata
- *
- * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <[email protected]>
- *
- * unless the SDRAM is cleanly shutdown before we hit the
- * reset register it can be left driving the data bus and
- * killing the chance of a subsequent boot from NAND
- *
- * GPLv2 Only
- */
-
-#include <linux/linkage.h>
-#include <mach/hardware.h>
-#include <mach/at91_ramc.h>
-#include "at91_rstc.h"
- .arm
-
-/*
- * at91_ramc_base is an array void*
- * init at NULL if only one DDR controler is present in or DT
- */
- .globl at91sam9g45_restart
-
-at91sam9g45_restart:
- ldr r5, =at91_ramc_base @ preload constants
- ldr r0, [r5]
- ldr r5, [r5, #4] @ ddr1
- cmp r5, #0
- ldr r4, =at91_rstc_base
- ldr r1, [r4]
-
- mov r2, #1
- mov r3, #AT91_DDRSDRC_LPCB_POWER_DOWN
- ldr r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST
-
- .balign 32 @ align to cache line
-
- strne r2, [r5, #AT91_DDRSDRC_RTR] @ disable DDR1 access
- strne r3, [r5, #AT91_DDRSDRC_LPR] @ power down DDR1
- str r2, [r0, #AT91_DDRSDRC_RTR] @ disable DDR0 access
- str r3, [r0, #AT91_DDRSDRC_LPR] @ power down DDR0
- str r4, [r1, #AT91_RSTC_CR] @ reset processor
-
- b .
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 417c8b6fb85e..e0e1729fe0e4 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -323,7 +323,6 @@ static void __init at91sam9rl_ioremap_registers(void)
static void __init at91sam9rl_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9_alt_restart;
at91_sysirq_mask_rtc(AT91SAM9RL_BASE_RTC);
at91_sysirq_mask_rtt(AT91SAM9RL_BASE_RTT);
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 4c2c96195a50..5d5e55237c41 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -66,8 +66,6 @@ extern void at91sam9_idle(void);
/* reset */
extern void at91_ioremap_rstc(u32 base_addr);
-extern void at91sam9_alt_restart(enum reboot_mode, const char *);
-extern void at91sam9g45_restart(enum reboot_mode, const char *);
/* shutdown */
extern void at91_ioremap_shdwc(u32 base_addr);
--
2.0.1
Add a driver to handle the shutdown of the Atmel SoCs. This code used to be
(and still is) in arch/arm/mach-at91. We didn't removed it yet so that we can
convert all the boards to using this driver, before removing it entirely in a
separate patch.
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/power/reset/Kconfig | 7 ++
drivers/power/reset/Makefile | 1 +
drivers/power/reset/at91-poweroff.c | 156 ++++++++++++++++++++++++++++++++++++
3 files changed, 164 insertions(+)
create mode 100644 drivers/power/reset/at91-poweroff.c
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index b3fef01d7cbb..f9d53af50ec0 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -14,6 +14,13 @@ config POWER_RESET_AS3722
help
This driver supports turning off board via a ams AS3722 power-off.
+config POWER_RESET_AT91_POWEROFF
+ bool "Atmel AT91 poweroff driver"
+ default SOC_AT91SAM9 || SOC_SAMA5
+ help
+ This driver supports poweroff for Atmel AT91SAM9 and SAMA5
+ SoCs
+
config POWER_RESET_AT91_RESET
bool "Atmel AT91 reset driver"
default SOC_AT91SAM9 || SOC_SAMA5
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 1599214b91d9..8bf941bac3da 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
+obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o
obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c
new file mode 100644
index 000000000000..2f2a69e9bae3
--- /dev/null
+++ b/drivers/power/reset/at91-poweroff.c
@@ -0,0 +1,156 @@
+/*
+ * Atmel AT91 SAM9 SoCs reset code
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ *
+ * Maxime Ripard <[email protected]>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+
+#define AT91_SHDW_CR 0x00 /* Shut Down Control Register */
+#define AT91_SHDW_SHDW BIT(0) /* Shut Down command */
+#define AT91_SHDW_KEY (0xa5 << 24) /* KEY Password */
+
+#define AT91_SHDW_MR 0x04 /* Shut Down Mode Register */
+#define AT91_SHDW_WKMODE0 GENMASK(2, 0) /* Wake-up 0 Mode Selection */
+#define AT91_SHDW_CPTWK0_MAX 0xf /* Maximum Counter On Wake Up 0 */
+#define AT91_SHDW_CPTWK0 (AT91_SHDW_CPTWK0_MAX << 4) /* Counter On Wake Up 0 */
+#define AT91_SHDW_CPTWK0_(x) ((x) << 4)
+#define AT91_SHDW_RTTWKEN BIT(16) /* Real Time Timer Wake-up Enable */
+#define AT91_SHDW_RTCWKEN BIT(17) /* Real Time Clock Wake-up Enable */
+
+#define AT91_SHDW_SR 0x08 /* Shut Down Status Register */
+#define AT91_SHDW_WAKEUP0 BIT(0) /* Wake-up 0 Status */
+#define AT91_SHDW_RTTWK BIT(16) /* Real-time Timer Wake-up */
+#define AT91_SHDW_RTCWK BIT(17) /* Real-time Clock Wake-up [SAM9RL] */
+
+enum wakeup_type {
+ AT91_SHDW_WKMODE0_NONE = 0,
+ AT91_SHDW_WKMODE0_HIGH = 1,
+ AT91_SHDW_WKMODE0_LOW = 2,
+ AT91_SHDW_WKMODE0_ANYLEVEL = 3,
+};
+
+static const char *shdwc_wakeup_modes[] = {
+ [AT91_SHDW_WKMODE0_NONE] = "none",
+ [AT91_SHDW_WKMODE0_HIGH] = "high",
+ [AT91_SHDW_WKMODE0_LOW] = "low",
+ [AT91_SHDW_WKMODE0_ANYLEVEL] = "any",
+};
+
+static void __iomem *at91_shdwc_base;
+
+static void __init at91_wakeup_status(void)
+{
+ u32 reg = readl(at91_shdwc_base);
+ char *reason = "unknown";
+
+ /* Simple power-on, just bail out */
+ if (!reg)
+ return;
+
+ if (reg & AT91_SHDW_RTTWK)
+ reason = "RTT";
+ else if (reg & AT91_SHDW_RTCWK)
+ reason = "RTC";
+
+ pr_info("AT91: Wake-Up source: %s\n", reason);
+}
+
+static void at91_poweroff(void)
+{
+ writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, at91_shdwc_base + AT91_SHDW_CR);
+}
+
+const enum wakeup_type at91_poweroff_get_wakeup_mode(struct device_node *np)
+{
+ const char *pm;
+ int err, i;
+
+ err = of_property_read_string(np, "atmel,wakeup-mode", &pm);
+ if (err < 0)
+ return AT91_SHDW_WKMODE0_ANYLEVEL;
+
+ for (i = 0; i < ARRAY_SIZE(shdwc_wakeup_modes); i++)
+ if (!strcasecmp(pm, shdwc_wakeup_modes[i]))
+ return i;
+
+ return -ENODEV;
+}
+
+static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ enum wakeup_type wakeup_mode;
+ u32 mode = 0, tmp;
+
+ wakeup_mode = at91_poweroff_get_wakeup_mode(np);
+ if (wakeup_mode < 0) {
+ dev_warn(&pdev->dev, "shdwc unknown wakeup mode\n");
+ return;
+ }
+
+ if (!of_property_read_u32(np, "atmel,wakeup-counter", &tmp)) {
+ if (tmp > AT91_SHDW_CPTWK0_MAX) {
+ dev_warn(&pdev->dev,
+ "shdwc wakeup counter 0x%x > 0x%x reduce it to 0x%x\n",
+ tmp, AT91_SHDW_CPTWK0_MAX, AT91_SHDW_CPTWK0_MAX);
+ tmp = AT91_SHDW_CPTWK0_MAX;
+ }
+ mode |= AT91_SHDW_CPTWK0_(tmp);
+ }
+
+ if (of_property_read_bool(np, "atmel,wakeup-rtc-timer"))
+ mode |= AT91_SHDW_RTCWKEN;
+
+ if (of_property_read_bool(np, "atmel,wakeup-rtt-timer"))
+ mode |= AT91_SHDW_RTTWKEN;
+
+ writel(wakeup_mode | mode, at91_shdwc_base + AT91_SHDW_MR);
+}
+
+static int at91_poweroff_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(at91_shdwc_base)) {
+ dev_err(&pdev->dev, "Could not map reset controller address\n");
+ return PTR_ERR(at91_shdwc_base);
+ }
+
+ at91_wakeup_status();
+
+ if (pdev->dev.of_node)
+ at91_poweroff_dt_set_wakeup_mode(pdev);
+
+ pm_power_off = at91_poweroff;
+
+ return 0;
+}
+
+static struct of_device_id at91_poweroff_of_match[] = {
+ { .compatible = "atmel,at91sam9260-shdwc", },
+ { .compatible = "atmel,at91sam9rl-shdwc", },
+ { .compatible = "atmel,at91sam9x5-shdwc", },
+ { /*sentinel*/ }
+};
+
+static struct platform_driver at91_poweroff_driver = {
+ .probe = at91_poweroff_probe,
+ .driver = {
+ .name = "at91-poweroff",
+ .of_match_table = at91_poweroff_of_match,
+ },
+};
+module_platform_driver(at91_poweroff_driver);
--
2.0.1
Now that there's no user left for the global variables holding the reset and
shutdown controllers base address, we can remove these variables and their
associated mapping function.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/at91sam9260.c | 2 --
arch/arm/mach-at91/at91sam9261.c | 2 --
arch/arm/mach-at91/at91sam9263.c | 2 --
arch/arm/mach-at91/at91sam9g45.c | 2 --
arch/arm/mach-at91/at91sam9rl.c | 2 --
arch/arm/mach-at91/generic.h | 6 ------
arch/arm/mach-at91/setup.c | 18 ------------------
7 files changed, 34 deletions(-)
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 5fa1986be2aa..16dd13800b1f 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -339,8 +339,6 @@ static void __init at91sam9260_map_io(void)
static void __init at91sam9260_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9260_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9260_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9260_BASE_SDRAMC, 512);
at91sam926x_ioremap_pit(AT91SAM9260_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9260_BASE_SMC);
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 5ccc67235e7a..2c8553e63785 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -302,8 +302,6 @@ static void __init at91sam9261_map_io(void)
static void __init at91sam9261_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9261_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9261_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9261_BASE_SDRAMC, 512);
at91sam926x_ioremap_pit(AT91SAM9261_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9261_BASE_SMC);
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 4d28c3479d4b..63a47c7d7f2b 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -317,8 +317,6 @@ static void __init at91sam9263_map_io(void)
static void __init at91sam9263_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9263_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9263_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9263_BASE_SDRAMC0, 512);
at91_ioremap_ramc(1, AT91SAM9263_BASE_SDRAMC1, 512);
at91sam926x_ioremap_pit(AT91SAM9263_BASE_PIT);
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 22034c96d488..f0b78923da75 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -367,8 +367,6 @@ static void __init at91sam9g45_map_io(void)
static void __init at91sam9g45_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9G45_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9G45_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9G45_BASE_DDRSDRC1, 512);
at91_ioremap_ramc(1, AT91SAM9G45_BASE_DDRSDRC0, 512);
at91sam926x_ioremap_pit(AT91SAM9G45_BASE_PIT);
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 323a9f90931a..ea9ac0ee0895 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -311,8 +311,6 @@ static void __init at91sam9rl_map_io(void)
static void __init at91sam9rl_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9RL_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9RL_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9RL_BASE_SDRAMC, 512);
at91sam926x_ioremap_pit(AT91SAM9RL_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9RL_BASE_SMC);
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 5d5e55237c41..f42b0490ad98 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -64,12 +64,6 @@ extern void at91_irq_resume(void);
/* idle */
extern void at91sam9_idle(void);
-/* reset */
-extern void at91_ioremap_rstc(u32 base_addr);
-
-/* shutdown */
-extern void at91_ioremap_shdwc(u32 base_addr);
-
/* Matrix */
extern void at91_ioremap_matrix(u32 base_addr);
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 7124b0334bb1..fd3b6f0dd50d 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -319,24 +319,6 @@ void __init at91_map_io(void)
at91_boot_soc.map_io();
}
-void __iomem *at91_shdwc_base = NULL;
-
-void __init at91_ioremap_shdwc(u32 base_addr)
-{
- at91_shdwc_base = ioremap(base_addr, 16);
- if (!at91_shdwc_base)
- panic(pr_fmt("Impossible to ioremap at91_shdwc_base\n"));
-}
-
-void __iomem *at91_rstc_base;
-
-void __init at91_ioremap_rstc(u32 base_addr)
-{
- at91_rstc_base = ioremap(base_addr, 16);
- if (!at91_rstc_base)
- panic(pr_fmt("Impossible to ioremap at91_rstc_base\n"));
-}
-
void __iomem *at91_matrix_base;
EXPORT_SYMBOL_GPL(at91_matrix_base);
--
2.0.1
All the config option so far are depending on the POWER_RESET symbol
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/power/reset/Kconfig | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index bdcf5173e377..19d546c5edfa 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -6,15 +6,17 @@ menuconfig POWER_RESET
Say Y here to enable board reset and power off
+if POWER_RESET
+
config POWER_RESET_AS3722
bool "ams AS3722 power-off driver"
- depends on MFD_AS3722 && POWER_RESET
+ depends on MFD_AS3722
help
This driver supports turning off board via a ams AS3722 power-off.
config POWER_RESET_AXXIA
bool "LSI Axxia reset driver"
- depends on POWER_RESET && ARCH_AXXIA
+ depends on ARCH_AXXIA
help
This driver supports restart for Axxia SoC.
@@ -22,7 +24,7 @@ config POWER_RESET_AXXIA
config POWER_RESET_GPIO
bool "GPIO power-off driver"
- depends on OF_GPIO && POWER_RESET
+ depends on OF_GPIO
help
This driver supports turning off your board via a GPIO line.
If your board needs a GPIO high/low to power down, say Y and
@@ -30,13 +32,13 @@ config POWER_RESET_GPIO
config POWER_RESET_MSM
bool "Qualcomm MSM power-off driver"
- depends on POWER_RESET && ARCH_QCOM
+ depends on ARCH_QCOM
help
Power off and restart support for Qualcomm boards.
config POWER_RESET_QNAP
bool "QNAP power-off driver"
- depends on OF_GPIO && POWER_RESET && PLAT_ORION
+ depends on OF_GPIO && PLAT_ORION
help
This driver supports turning off QNAP NAS devices by sending
commands to the microcontroller which controls the main power.
@@ -54,14 +56,13 @@ config POWER_RESET_RESTART
config POWER_RESET_SUN6I
bool "Allwinner A31 SoC reset driver"
depends on ARCH_SUNXI
- depends on POWER_RESET
help
Reboot support for the Allwinner A31 SoCs.
config POWER_RESET_VEXPRESS
bool "ARM Versatile Express power-off and reset driver"
depends on ARM || ARM64
- depends on POWER_RESET && VEXPRESS_CONFIG
+ depends on VEXPRESS_CONFIG
help
Power off and reset support for the ARM Ltd. Versatile
Express boards.
@@ -69,7 +70,6 @@ config POWER_RESET_VEXPRESS
config POWER_RESET_XGENE
bool "APM SoC X-Gene reset driver"
depends on ARM64
- depends on POWER_RESET
help
Reboot support for the APM SoC X-Gene Eval boards.
@@ -80,3 +80,4 @@ config POWER_RESET_KEYSTONE
help
Reboot support for the KEYSTONE SoCs.
+endif
--
2.0.1
These headers used to provide an "API" to access the rstc and shdwc registers.
Now that no-one uses this API anymore, we can safely remove those.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/at91_rstc.h | 53 ---------------------------------
arch/arm/mach-at91/at91_shdwc.h | 50 -------------------------------
arch/arm/mach-at91/at91sam9260.c | 1 -
arch/arm/mach-at91/at91sam9261.c | 1 -
arch/arm/mach-at91/at91sam9263.c | 1 -
arch/arm/mach-at91/at91sam9rl.c | 1 -
arch/arm/mach-at91/board-sam9260ek.c | 1 -
arch/arm/mach-at91/board-sam9261ek.c | 1 -
arch/arm/mach-at91/board-sam9263ek.c | 1 -
arch/arm/mach-at91/board-sam9m10g45ek.c | 1 -
arch/arm/mach-at91/board-sam9rlek.c | 1 -
arch/arm/mach-at91/setup.c | 1 -
12 files changed, 113 deletions(-)
delete mode 100644 arch/arm/mach-at91/at91_rstc.h
delete mode 100644 arch/arm/mach-at91/at91_shdwc.h
diff --git a/arch/arm/mach-at91/at91_rstc.h b/arch/arm/mach-at91/at91_rstc.h
deleted file mode 100644
index a600e6992920..000000000000
--- a/arch/arm/mach-at91/at91_rstc.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_rstc.h
- *
- * Copyright (C) 2007 Andrew Victor
- * Copyright (C) 2007 Atmel Corporation.
- *
- * Reset Controller (RSTC) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_RSTC_H
-#define AT91_RSTC_H
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_rstc_base;
-
-#define at91_rstc_read(field) \
- __raw_readl(at91_rstc_base + field)
-
-#define at91_rstc_write(field, value) \
- __raw_writel(value, at91_rstc_base + field)
-#else
-.extern at91_rstc_base
-#endif
-
-#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
-#define AT91_RSTC_PROCRST (1 << 0) /* Processor Reset */
-#define AT91_RSTC_PERRST (1 << 2) /* Peripheral Reset */
-#define AT91_RSTC_EXTRST (1 << 3) /* External Reset */
-#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
-
-#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
-#define AT91_RSTC_URSTS (1 << 0) /* User Reset Status */
-#define AT91_RSTC_RSTTYP (7 << 8) /* Reset Type */
-#define AT91_RSTC_RSTTYP_GENERAL (0 << 8)
-#define AT91_RSTC_RSTTYP_WAKEUP (1 << 8)
-#define AT91_RSTC_RSTTYP_WATCHDOG (2 << 8)
-#define AT91_RSTC_RSTTYP_SOFTWARE (3 << 8)
-#define AT91_RSTC_RSTTYP_USER (4 << 8)
-#define AT91_RSTC_NRSTL (1 << 16) /* NRST Pin Level */
-#define AT91_RSTC_SRCMP (1 << 17) /* Software Reset Command in Progress */
-
-#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
-#define AT91_RSTC_URSTEN (1 << 0) /* User Reset Enable */
-#define AT91_RSTC_URSTIEN (1 << 4) /* User Reset Interrupt Enable */
-#define AT91_RSTC_ERSTL (0xf << 8) /* External Reset Length */
-
-#endif
diff --git a/arch/arm/mach-at91/at91_shdwc.h b/arch/arm/mach-at91/at91_shdwc.h
deleted file mode 100644
index 9e29f31ec9a6..000000000000
--- a/arch/arm/mach-at91/at91_shdwc.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_shdwc.h
- *
- * Copyright (C) 2007 Andrew Victor
- * Copyright (C) 2007 Atmel Corporation.
- *
- * Shutdown Controller (SHDWC) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_SHDWC_H
-#define AT91_SHDWC_H
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_shdwc_base;
-
-#define at91_shdwc_read(field) \
- __raw_readl(at91_shdwc_base + field)
-
-#define at91_shdwc_write(field, value) \
- __raw_writel(value, at91_shdwc_base + field)
-#endif
-
-#define AT91_SHDW_CR 0x00 /* Shut Down Control Register */
-#define AT91_SHDW_SHDW (1 << 0) /* Shut Down command */
-#define AT91_SHDW_KEY (0xa5 << 24) /* KEY Password */
-
-#define AT91_SHDW_MR 0x04 /* Shut Down Mode Register */
-#define AT91_SHDW_WKMODE0 (3 << 0) /* Wake-up 0 Mode Selection */
-#define AT91_SHDW_WKMODE0_NONE 0
-#define AT91_SHDW_WKMODE0_HIGH 1
-#define AT91_SHDW_WKMODE0_LOW 2
-#define AT91_SHDW_WKMODE0_ANYLEVEL 3
-#define AT91_SHDW_CPTWK0_MAX 0xf /* Maximum Counter On Wake Up 0 */
-#define AT91_SHDW_CPTWK0 (AT91_SHDW_CPTWK0_MAX << 4) /* Counter On Wake Up 0 */
-#define AT91_SHDW_CPTWK0_(x) ((x) << 4)
-#define AT91_SHDW_RTTWKEN (1 << 16) /* Real Time Timer Wake-up Enable */
-#define AT91_SHDW_RTCWKEN (1 << 17) /* Real Time Clock Wake-up Enable */
-
-#define AT91_SHDW_SR 0x08 /* Shut Down Status Register */
-#define AT91_SHDW_WAKEUP0 (1 << 0) /* Wake-up 0 Status */
-#define AT91_SHDW_RTTWK (1 << 16) /* Real-time Timer Wake-up */
-#define AT91_SHDW_RTCWK (1 << 17) /* Real-time Clock Wake-up [SAM9RL] */
-
-#endif
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 16dd13800b1f..624fe15ec352 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -25,7 +25,6 @@
#include <mach/hardware.h>
#include "at91_aic.h"
-#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
#include "clock.h"
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 2c8553e63785..f115f4709021 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -24,7 +24,6 @@
#include <mach/hardware.h>
#include "at91_aic.h"
-#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
#include "sam9_smc.h"
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 63a47c7d7f2b..08e0f4ec7d11 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -23,7 +23,6 @@
#include <mach/hardware.h>
#include "at91_aic.h"
-#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
#include "clock.h"
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index ea9ac0ee0895..d6ad162b9a88 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -24,7 +24,6 @@
#include <mach/hardware.h>
#include "at91_aic.h"
-#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
#include "sam9_smc.h"
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index da9c5f1f2c49..18f49c93f3f3 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -45,7 +45,6 @@
#include <mach/system_rev.h>
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index d1be10b09ab3..5a23e7211203 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -49,7 +49,6 @@
#include <mach/system_rev.h>
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 3f613d962d9b..e2aa41d19fc1 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -48,7 +48,6 @@
#include <mach/system_rev.h>
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index 33a7b19f7400..e7d793b7601e 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -46,7 +46,6 @@
#include <mach/system_rev.h>
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index 262e3f957d9f..5cb82464be1a 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -35,7 +35,6 @@
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index eb2b922a4adb..61d0b96c31e9 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -22,7 +22,6 @@
#include <mach/cpu.h>
#include <mach/at91_dbgu.h>
-#include "at91_shdwc.h"
#include "soc.h"
#include "generic.h"
#include "pm.h"
--
2.0.1
These headers used to provide an "API" to access the rstc and shdwc registers.
Now that no-one uses this API anymore, we can safely remove those.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/at91_rstc.h | 53 ---------------------------------
arch/arm/mach-at91/at91_shdwc.h | 50 -------------------------------
arch/arm/mach-at91/at91sam9260.c | 1 -
arch/arm/mach-at91/at91sam9261.c | 1 -
arch/arm/mach-at91/at91sam9263.c | 1 -
arch/arm/mach-at91/at91sam9rl.c | 1 -
arch/arm/mach-at91/board-sam9260ek.c | 1 -
arch/arm/mach-at91/board-sam9261ek.c | 1 -
arch/arm/mach-at91/board-sam9263ek.c | 1 -
arch/arm/mach-at91/board-sam9m10g45ek.c | 1 -
arch/arm/mach-at91/board-sam9rlek.c | 1 -
arch/arm/mach-at91/setup.c | 1 -
12 files changed, 113 deletions(-)
delete mode 100644 arch/arm/mach-at91/at91_rstc.h
delete mode 100644 arch/arm/mach-at91/at91_shdwc.h
diff --git a/arch/arm/mach-at91/at91_rstc.h b/arch/arm/mach-at91/at91_rstc.h
deleted file mode 100644
index a600e6992920..000000000000
--- a/arch/arm/mach-at91/at91_rstc.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_rstc.h
- *
- * Copyright (C) 2007 Andrew Victor
- * Copyright (C) 2007 Atmel Corporation.
- *
- * Reset Controller (RSTC) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_RSTC_H
-#define AT91_RSTC_H
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_rstc_base;
-
-#define at91_rstc_read(field) \
- __raw_readl(at91_rstc_base + field)
-
-#define at91_rstc_write(field, value) \
- __raw_writel(value, at91_rstc_base + field)
-#else
-.extern at91_rstc_base
-#endif
-
-#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
-#define AT91_RSTC_PROCRST (1 << 0) /* Processor Reset */
-#define AT91_RSTC_PERRST (1 << 2) /* Peripheral Reset */
-#define AT91_RSTC_EXTRST (1 << 3) /* External Reset */
-#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
-
-#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
-#define AT91_RSTC_URSTS (1 << 0) /* User Reset Status */
-#define AT91_RSTC_RSTTYP (7 << 8) /* Reset Type */
-#define AT91_RSTC_RSTTYP_GENERAL (0 << 8)
-#define AT91_RSTC_RSTTYP_WAKEUP (1 << 8)
-#define AT91_RSTC_RSTTYP_WATCHDOG (2 << 8)
-#define AT91_RSTC_RSTTYP_SOFTWARE (3 << 8)
-#define AT91_RSTC_RSTTYP_USER (4 << 8)
-#define AT91_RSTC_NRSTL (1 << 16) /* NRST Pin Level */
-#define AT91_RSTC_SRCMP (1 << 17) /* Software Reset Command in Progress */
-
-#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
-#define AT91_RSTC_URSTEN (1 << 0) /* User Reset Enable */
-#define AT91_RSTC_URSTIEN (1 << 4) /* User Reset Interrupt Enable */
-#define AT91_RSTC_ERSTL (0xf << 8) /* External Reset Length */
-
-#endif
diff --git a/arch/arm/mach-at91/at91_shdwc.h b/arch/arm/mach-at91/at91_shdwc.h
deleted file mode 100644
index 9e29f31ec9a6..000000000000
--- a/arch/arm/mach-at91/at91_shdwc.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_shdwc.h
- *
- * Copyright (C) 2007 Andrew Victor
- * Copyright (C) 2007 Atmel Corporation.
- *
- * Shutdown Controller (SHDWC) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_SHDWC_H
-#define AT91_SHDWC_H
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_shdwc_base;
-
-#define at91_shdwc_read(field) \
- __raw_readl(at91_shdwc_base + field)
-
-#define at91_shdwc_write(field, value) \
- __raw_writel(value, at91_shdwc_base + field)
-#endif
-
-#define AT91_SHDW_CR 0x00 /* Shut Down Control Register */
-#define AT91_SHDW_SHDW (1 << 0) /* Shut Down command */
-#define AT91_SHDW_KEY (0xa5 << 24) /* KEY Password */
-
-#define AT91_SHDW_MR 0x04 /* Shut Down Mode Register */
-#define AT91_SHDW_WKMODE0 (3 << 0) /* Wake-up 0 Mode Selection */
-#define AT91_SHDW_WKMODE0_NONE 0
-#define AT91_SHDW_WKMODE0_HIGH 1
-#define AT91_SHDW_WKMODE0_LOW 2
-#define AT91_SHDW_WKMODE0_ANYLEVEL 3
-#define AT91_SHDW_CPTWK0_MAX 0xf /* Maximum Counter On Wake Up 0 */
-#define AT91_SHDW_CPTWK0 (AT91_SHDW_CPTWK0_MAX << 4) /* Counter On Wake Up 0 */
-#define AT91_SHDW_CPTWK0_(x) ((x) << 4)
-#define AT91_SHDW_RTTWKEN (1 << 16) /* Real Time Timer Wake-up Enable */
-#define AT91_SHDW_RTCWKEN (1 << 17) /* Real Time Clock Wake-up Enable */
-
-#define AT91_SHDW_SR 0x08 /* Shut Down Status Register */
-#define AT91_SHDW_WAKEUP0 (1 << 0) /* Wake-up 0 Status */
-#define AT91_SHDW_RTTWK (1 << 16) /* Real-time Timer Wake-up */
-#define AT91_SHDW_RTCWK (1 << 17) /* Real-time Clock Wake-up [SAM9RL] */
-
-#endif
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 16dd13800b1f..624fe15ec352 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -25,7 +25,6 @@
#include <mach/hardware.h>
#include "at91_aic.h"
-#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
#include "clock.h"
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 2c8553e63785..f115f4709021 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -24,7 +24,6 @@
#include <mach/hardware.h>
#include "at91_aic.h"
-#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
#include "sam9_smc.h"
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 63a47c7d7f2b..08e0f4ec7d11 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -23,7 +23,6 @@
#include <mach/hardware.h>
#include "at91_aic.h"
-#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
#include "clock.h"
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index ea9ac0ee0895..d6ad162b9a88 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -24,7 +24,6 @@
#include <mach/hardware.h>
#include "at91_aic.h"
-#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
#include "sam9_smc.h"
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index da9c5f1f2c49..18f49c93f3f3 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -45,7 +45,6 @@
#include <mach/system_rev.h>
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index d1be10b09ab3..5a23e7211203 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -49,7 +49,6 @@
#include <mach/system_rev.h>
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 3f613d962d9b..e2aa41d19fc1 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -48,7 +48,6 @@
#include <mach/system_rev.h>
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index 33a7b19f7400..e7d793b7601e 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -46,7 +46,6 @@
#include <mach/system_rev.h>
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index 262e3f957d9f..5cb82464be1a 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -35,7 +35,6 @@
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index fd3b6f0dd50d..06aaf857ddc4 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -22,7 +22,6 @@
#include <mach/cpu.h>
#include <mach/at91_dbgu.h>
-#include "at91_shdwc.h"
#include "soc.h"
#include "generic.h"
#include "pm.h"
--
2.0.1
Implement the reset behaviour of the various AT91 SoCS in drivers/power/reset.
It used to be (and still is) located in arch/arm/mach-at91, and in order to
preserve bisectability is not removed yet, but every board should be converted
to use this driver instead.
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/power/reset/Kconfig | 7 ++
drivers/power/reset/Makefile | 1 +
drivers/power/reset/at91-reset.c | 202 +++++++++++++++++++++++++++++++++++++++
3 files changed, 210 insertions(+)
create mode 100644 drivers/power/reset/at91-reset.c
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 19d546c5edfa..b3fef01d7cbb 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -14,6 +14,13 @@ config POWER_RESET_AS3722
help
This driver supports turning off board via a ams AS3722 power-off.
+config POWER_RESET_AT91_RESET
+ bool "Atmel AT91 reset driver"
+ default SOC_AT91SAM9 || SOC_SAMA5
+ help
+ This driver supports restart for Atmel AT91SAM9 and SAMA5
+ SoCs
+
config POWER_RESET_AXXIA
bool "LSI Axxia reset driver"
depends on ARCH_AXXIA
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index dde2e8bbac53..1599214b91d9 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
+obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c
new file mode 100644
index 000000000000..878547410acb
--- /dev/null
+++ b/drivers/power/reset/at91-reset.c
@@ -0,0 +1,202 @@
+/*
+ * Atmel AT91 SAM9 SoCs reset code
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ *
+ * Maxime Ripard <[email protected]>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+#include <asm/system_misc.h>
+
+#include <mach/at91sam9_ddrsdr.h>
+#include <mach/at91sam9_sdramc.h>
+
+#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
+#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
+#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
+#define AT91_RSTC_EXTRST BIT(3) /* External Reset */
+#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
+
+#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
+#define AT91_RSTC_URSTS BIT(0) /* User Reset Status */
+#define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */
+#define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */
+#define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */
+
+#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
+#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
+#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
+#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
+
+enum reset_type {
+ RESET_TYPE_GENERAL = 0,
+ RESET_TYPE_WAKEUP = 1,
+ RESET_TYPE_WATCHDOG = 2,
+ RESET_TYPE_SOFTWARE = 3,
+ RESET_TYPE_USER = 4,
+};
+
+static void __iomem *at91_ramc_base[2], *at91_rstc_base;
+
+static void at91sam9_restart(enum reboot_mode mode, const char *cmd)
+{
+ asm volatile(
+ ".balign 32\n\t"
+
+ "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
+ "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
+ "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
+
+ "b .\n\t"
+ :
+ : "r" (at91_ramc_base[0]),
+ "r" (at91_rstc_base),
+ "r" (1),
+ "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
+ "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
+}
+
+static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
+{
+ asm volatile(
+ "cmp %1, #0\n\t"
+ "beq 1f\n\t"
+
+ "ldr r0, [%1]\n\t"
+ "cmp r0, #0\n\t"
+
+ ".balign 32\n\t"
+
+ "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+ " str %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+ " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+ " strne %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+ " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
+
+ " b .\n\t"
+ :
+ : "r" (at91_ramc_base[0]),
+ "r" (at91_ramc_base[1]),
+ "r" (at91_rstc_base),
+ "r" (1),
+ "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
+ "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
+ : "r0");
+}
+
+static void __init at91_reset_status(struct platform_device *pdev)
+{
+ u32 reg = readl(at91_rstc_base + AT91_RSTC_SR);
+ char *reason;
+
+ switch ((reg & AT91_RSTC_RSTTYP) >> 8) {
+ case RESET_TYPE_GENERAL:
+ reason = "general reset";
+ break;
+ case RESET_TYPE_WAKEUP:
+ reason = "wakeup";
+ break;
+ case RESET_TYPE_WATCHDOG:
+ reason = "watchdog reset";
+ break;
+ case RESET_TYPE_SOFTWARE:
+ reason = "software reset";
+ break;
+ case RESET_TYPE_USER:
+ reason = "user reset";
+ break;
+ default:
+ reason = "unknown reset";
+ break;
+ }
+
+ pr_info("AT91: Starting after %s\n", reason);
+}
+
+static struct of_device_id at91_ramc_of_match[] = {
+ { .compatible = "atmel,at91sam9260-sdramc", },
+ { .compatible = "atmel,at91sam9g45-ddramc", },
+ { /* sentinel */ }
+};
+
+static struct of_device_id at91_reset_of_match[] = {
+ { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_restart },
+ { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
+ { /* sentinel */ }
+};
+
+static int at91_reset_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ at91_rstc_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(at91_rstc_base)) {
+ dev_err(&pdev->dev, "Could not map reset controller address\n");
+ return PTR_ERR(at91_rstc_base);
+ }
+
+ if (pdev->dev.of_node) {
+ const struct of_device_id *match;
+ struct device_node *np;
+ int idx = 0;
+
+ for_each_matching_node(np, at91_ramc_of_match) {
+ at91_ramc_base[idx] = of_iomap(np, 0);
+ if (!at91_ramc_base[idx]) {
+ dev_err(&pdev->dev, "Could not map ram controller address\n");
+ return -ENODEV;
+ }
+ idx++;
+ }
+
+ match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
+ arm_pm_restart = match->data;
+ } else {
+ const struct platform_device_id *match;
+ int idx = 0;
+
+ for (idx = 0; idx < 2; idx++) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1 );
+ at91_ramc_base[idx] = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(at91_ramc_base[idx])) {
+ dev_err(&pdev->dev, "Could not map ram controller address\n");
+ return PTR_ERR(at91_rstc_base);
+ }
+ }
+
+ match = platform_get_device_id(pdev);
+ arm_pm_restart = (void (*)(enum reboot_mode, const char*))
+ match->driver_data;
+ }
+
+ at91_reset_status(pdev);
+
+ return 0;
+}
+
+static struct platform_device_id at91_reset_plat_match[] = {
+ { "at91-sam9-reset", (unsigned long)at91sam9_restart },
+ { "at91-g45-reset", (unsigned long)at91sam9g45_restart },
+ { /* sentinel */ }
+};
+
+static struct platform_driver at91_reset_driver = {
+ .probe = at91_reset_probe,
+ .driver = {
+ .name = "at91-reset",
+ .of_match_table = at91_reset_of_match,
+ },
+ .id_table = at91_reset_plat_match,
+};
+module_platform_driver(at91_reset_driver);
--
2.0.1
Now that the reset code is a driver of its own, just let the usual DT probing
mecanism do its job, and remove the code entirely in this case.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/setup.c | 29 -----------------------------
1 file changed, 29 deletions(-)
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 9c4c7fb323fb..3463b9e14418 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -354,34 +354,6 @@ void __init at91_ioremap_matrix(u32 base_addr)
}
#if defined(CONFIG_OF) && !defined(CONFIG_ARCH_AT91X40)
-static struct of_device_id rstc_ids[] = {
- { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_alt_restart },
- { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
- { /*sentinel*/ }
-};
-
-static void at91_dt_rstc(void)
-{
- struct device_node *np;
- const struct of_device_id *of_id;
-
- np = of_find_matching_node(NULL, rstc_ids);
- if (!np)
- panic(pr_fmt("unable to find compatible rstc node in dtb\n"));
-
- at91_rstc_base = of_iomap(np, 0);
- if (!at91_rstc_base)
- panic(pr_fmt("unable to map rstc cpu registers\n"));
-
- of_id = of_match_node(rstc_ids, np);
- if (!of_id)
- panic(pr_fmt("rtsc no restart function available\n"));
-
- arm_pm_restart = of_id->data;
-
- of_node_put(np);
-}
-
static struct of_device_id ramc_ids[] = {
{ .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
{ .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
@@ -505,7 +477,6 @@ void __init at91rm9200_dt_initialize(void)
void __init at91_dt_initialize(void)
{
- at91_dt_rstc();
at91_dt_ramc();
at91_dt_shdwc();
--
2.0.1
Implement the reset behaviour of the various AT91 SoCS in drivers/power/reset.
It used to be (and still is) located in arch/arm/mach-at91, and in order to
preserve bisectability is not removed yet, but every board should be converted
to use this driver instead.
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/power/reset/Kconfig | 7 ++
drivers/power/reset/Makefile | 1 +
drivers/power/reset/at91-reset.c | 202 +++++++++++++++++++++++++++++++++++++++
3 files changed, 210 insertions(+)
create mode 100644 drivers/power/reset/at91-reset.c
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 19d546c5edfa..b3fef01d7cbb 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -14,6 +14,13 @@ config POWER_RESET_AS3722
help
This driver supports turning off board via a ams AS3722 power-off.
+config POWER_RESET_AT91_RESET
+ bool "Atmel AT91 reset driver"
+ default SOC_AT91SAM9 || SOC_SAMA5
+ help
+ This driver supports restart for Atmel AT91SAM9 and SAMA5
+ SoCs
+
config POWER_RESET_AXXIA
bool "LSI Axxia reset driver"
depends on ARCH_AXXIA
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index dde2e8bbac53..1599214b91d9 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
+obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c
new file mode 100644
index 000000000000..878547410acb
--- /dev/null
+++ b/drivers/power/reset/at91-reset.c
@@ -0,0 +1,202 @@
+/*
+ * Atmel AT91 SAM9 SoCs reset code
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ *
+ * Maxime Ripard <[email protected]>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+#include <asm/system_misc.h>
+
+#include <mach/at91sam9_ddrsdr.h>
+#include <mach/at91sam9_sdramc.h>
+
+#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
+#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
+#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
+#define AT91_RSTC_EXTRST BIT(3) /* External Reset */
+#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
+
+#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
+#define AT91_RSTC_URSTS BIT(0) /* User Reset Status */
+#define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */
+#define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */
+#define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */
+
+#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
+#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
+#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
+#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
+
+enum reset_type {
+ RESET_TYPE_GENERAL = 0,
+ RESET_TYPE_WAKEUP = 1,
+ RESET_TYPE_WATCHDOG = 2,
+ RESET_TYPE_SOFTWARE = 3,
+ RESET_TYPE_USER = 4,
+};
+
+static void __iomem *at91_ramc_base[2], *at91_rstc_base;
+
+static void at91sam9_restart(enum reboot_mode mode, const char *cmd)
+{
+ asm volatile(
+ ".balign 32\n\t"
+
+ "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
+ "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
+ "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
+
+ "b .\n\t"
+ :
+ : "r" (at91_ramc_base[0]),
+ "r" (at91_rstc_base),
+ "r" (1),
+ "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
+ "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
+}
+
+static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
+{
+ asm volatile(
+ "cmp %1, #0\n\t"
+ "beq 1f\n\t"
+
+ "ldr r0, [%1]\n\t"
+ "cmp r0, #0\n\t"
+
+ ".balign 32\n\t"
+
+ "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+ " str %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+ " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+ " strne %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+ " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
+
+ " b .\n\t"
+ :
+ : "r" (at91_ramc_base[0]),
+ "r" (at91_ramc_base[1]),
+ "r" (at91_rstc_base),
+ "r" (1),
+ "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
+ "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
+ : "r0");
+}
+
+static void __init at91_reset_status(struct platform_device *pdev)
+{
+ u32 reg = readl(at91_rstc_base + AT91_RSTC_SR);
+ char *reason;
+
+ switch ((reg & AT91_RSTC_RSTTYP) >> 8) {
+ case RESET_TYPE_GENERAL:
+ reason = "general reset";
+ break;
+ case RESET_TYPE_WAKEUP:
+ reason = "wakeup";
+ break;
+ case RESET_TYPE_WATCHDOG:
+ reason = "watchdog reset";
+ break;
+ case RESET_TYPE_SOFTWARE:
+ reason = "software reset";
+ break;
+ case RESET_TYPE_USER:
+ reason = "user reset";
+ break;
+ default:
+ reason = "unknown reset";
+ break;
+ }
+
+ pr_info("AT91: Starting after %s\n", reason);
+}
+
+static struct of_device_id at91_ramc_of_match[] = {
+ { .compatible = "atmel,at91sam9260-sdramc", },
+ { .compatible = "atmel,at91sam9g45-ddramc", },
+ { /* sentinel */ }
+};
+
+static struct of_device_id at91_reset_of_match[] = {
+ { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_restart },
+ { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
+ { /* sentinel */ }
+};
+
+static int at91_reset_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ at91_rstc_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(at91_rstc_base)) {
+ dev_err(&pdev->dev, "Could not map reset controller address\n");
+ return PTR_ERR(at91_rstc_base);
+ }
+
+ if (pdev->dev.of_node) {
+ const struct of_device_id *match;
+ struct device_node *np;
+ int idx = 0;
+
+ for_each_matching_node(np, at91_ramc_of_match) {
+ at91_ramc_base[idx] = of_iomap(np, 0);
+ if (!at91_ramc_base[idx]) {
+ dev_err(&pdev->dev, "Could not map ram controller address\n");
+ return -ENODEV;
+ }
+ idx++;
+ }
+
+ match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
+ arm_pm_restart = match->data;
+ } else {
+ const struct platform_device_id *match;
+ int idx = 0;
+
+ for (idx = 0; idx < 2; idx++) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1 );
+ at91_ramc_base[idx] = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(at91_ramc_base[idx])) {
+ dev_err(&pdev->dev, "Could not map ram controller address\n");
+ return PTR_ERR(at91_rstc_base);
+ }
+ }
+
+ match = platform_get_device_id(pdev);
+ arm_pm_restart = (void (*)(enum reboot_mode, const char*))
+ match->driver_data;
+ }
+
+ at91_reset_status(pdev);
+
+ return 0;
+}
+
+static struct platform_device_id at91_reset_plat_match[] = {
+ { "at91-sam9-reset", (unsigned long)at91sam9_restart },
+ { "at91-g45-reset", (unsigned long)at91sam9g45_restart },
+ { /* sentinel */ }
+};
+
+static struct platform_driver at91_reset_driver = {
+ .probe = at91_reset_probe,
+ .driver = {
+ .name = "at91-reset",
+ .of_match_table = at91_reset_of_match,
+ },
+ .id_table = at91_reset_plat_match,
+};
+module_platform_driver(at91_reset_driver);
--
2.0.1
The SAMA5D3 has a shutdown controller identical to the sam9x5 SoC family.
Declare it in the DT.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/boot/dts/sama5d3.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index e0b15a6e8897..8bcf1c442c96 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -1178,6 +1178,11 @@
reg = <0xfffffe00 0x10>;
};
+ shutdown-controller@fffffe10 {
+ compatible = "atmel,at91sam9x5-shdwc";
+ reg = <0xfffffe10 0x10>;
+ };
+
pit: timer@fffffe30 {
compatible = "atmel,at91sam9260-pit";
reg = <0xfffffe30 0xf>;
--
2.0.1
The SAMA5D3 has a shutdown controller identical to the sam9x5 SoC family.
Declare it in the DT.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/boot/dts/sama5d3.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index e0b15a6e8897..8bcf1c442c96 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -1178,6 +1178,11 @@
reg = <0xfffffe00 0x10>;
};
+ shutdown-controller@fffffe10 {
+ compatible = "atmel,at91sam9x5-shdwc";
+ reg = <0xfffffe10 0x10>;
+ };
+
pit: timer@fffffe30 {
compatible = "atmel,at91sam9260-pit";
reg = <0xfffffe30 0xf>;
--
2.0.1
Now that there's no user left for the global variables holding the reset and
shutdown controllers base address, we can remove these variables and their
associated mapping function.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/at91sam9260.c | 2 --
arch/arm/mach-at91/at91sam9261.c | 2 --
arch/arm/mach-at91/at91sam9263.c | 2 --
arch/arm/mach-at91/at91sam9g45.c | 2 --
arch/arm/mach-at91/at91sam9rl.c | 2 --
arch/arm/mach-at91/generic.h | 6 ------
arch/arm/mach-at91/setup.c | 18 ------------------
7 files changed, 34 deletions(-)
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 5fa1986be2aa..16dd13800b1f 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -339,8 +339,6 @@ static void __init at91sam9260_map_io(void)
static void __init at91sam9260_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9260_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9260_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9260_BASE_SDRAMC, 512);
at91sam926x_ioremap_pit(AT91SAM9260_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9260_BASE_SMC);
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 5ccc67235e7a..2c8553e63785 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -302,8 +302,6 @@ static void __init at91sam9261_map_io(void)
static void __init at91sam9261_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9261_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9261_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9261_BASE_SDRAMC, 512);
at91sam926x_ioremap_pit(AT91SAM9261_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9261_BASE_SMC);
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 4d28c3479d4b..63a47c7d7f2b 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -317,8 +317,6 @@ static void __init at91sam9263_map_io(void)
static void __init at91sam9263_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9263_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9263_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9263_BASE_SDRAMC0, 512);
at91_ioremap_ramc(1, AT91SAM9263_BASE_SDRAMC1, 512);
at91sam926x_ioremap_pit(AT91SAM9263_BASE_PIT);
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 22034c96d488..f0b78923da75 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -367,8 +367,6 @@ static void __init at91sam9g45_map_io(void)
static void __init at91sam9g45_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9G45_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9G45_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9G45_BASE_DDRSDRC1, 512);
at91_ioremap_ramc(1, AT91SAM9G45_BASE_DDRSDRC0, 512);
at91sam926x_ioremap_pit(AT91SAM9G45_BASE_PIT);
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 323a9f90931a..ea9ac0ee0895 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -311,8 +311,6 @@ static void __init at91sam9rl_map_io(void)
static void __init at91sam9rl_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9RL_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9RL_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9RL_BASE_SDRAMC, 512);
at91sam926x_ioremap_pit(AT91SAM9RL_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9RL_BASE_SMC);
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 5d5e55237c41..f42b0490ad98 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -64,12 +64,6 @@ extern void at91_irq_resume(void);
/* idle */
extern void at91sam9_idle(void);
-/* reset */
-extern void at91_ioremap_rstc(u32 base_addr);
-
-/* shutdown */
-extern void at91_ioremap_shdwc(u32 base_addr);
-
/* Matrix */
extern void at91_ioremap_matrix(u32 base_addr);
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index cdd717a4fa30..eb2b922a4adb 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -319,24 +319,6 @@ void __init at91_map_io(void)
at91_boot_soc.map_io();
}
-void __iomem *at91_shdwc_base = NULL;
-
-void __init at91_ioremap_shdwc(u32 base_addr)
-{
- at91_shdwc_base = ioremap(base_addr, 16);
- if (!at91_shdwc_base)
- panic(pr_fmt("Impossible to ioremap at91_shdwc_base\n"));
-}
-
-void __iomem *at91_rstc_base;
-
-void __init at91_ioremap_rstc(u32 base_addr)
-{
- at91_rstc_base = ioremap(base_addr, 16);
- if (!at91_rstc_base)
- panic(pr_fmt("Impossible to ioremap at91_rstc_base\n"));
-}
-
void __iomem *at91_matrix_base;
EXPORT_SYMBOL_GPL(at91_matrix_base);
--
2.0.1
Adapt the ramc mapping code to handle multiple ram controllers in the DT.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/setup.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 9c4c7fb323fb..cc520596f23b 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -393,24 +393,26 @@ static void at91_dt_ramc(void)
{
struct device_node *np;
const struct of_device_id *of_id;
+ int idx = 0;
- np = of_find_matching_node(NULL, ramc_ids);
- if (!np)
- panic(pr_fmt("unable to find compatible ram controller node in dtb\n"));
+ for_each_matching_node(np, ramc_ids) {
+ at91_ramc_base[idx] = of_iomap(np, 0);
+ if (!at91_ramc_base[idx])
+ panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx);
- at91_ramc_base[0] = of_iomap(np, 0);
- if (!at91_ramc_base[0])
- panic(pr_fmt("unable to map ramc[0] cpu registers\n"));
- /* the controller may have 2 banks */
- at91_ramc_base[1] = of_iomap(np, 1);
+ idx++;
+ }
+
+ if (!idx)
+ panic(pr_fmt("unable to find compatible ram controller node in dtb\n"));
of_id = of_match_node(ramc_ids, np);
- if (!of_id)
+ if (!of_id) {
pr_warn("ramc no standby function available\n");
- else
- at91_pm_set_standby(of_id->data);
+ return;
+ }
- of_node_put(np);
+ at91_pm_set_standby(of_id->data);
}
static struct of_device_id shdwc_ids[] = {
--
2.0.1
The G45 has two identical ram controller, that are defined as a single one,
with two reg cells.
The proper way to support such a case is to have two separate DT nodes.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/boot/dts/at91sam9g45.dtsi | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index ace6bf197b70..6f648b85b725 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -75,8 +75,12 @@
ramc0: ramc@ffffe400 {
compatible = "atmel,at91sam9g45-ddramc";
- reg = <0xffffe400 0x200
- 0xffffe600 0x200>;
+ reg = <0xffffe400 0x200>;
+ };
+
+ ramc1: ramc@ffffe600 {
+ compatible = "atmel,at91sam9g45-ddramc";
+ reg = <0xffffe600 0x200>;
};
pmc: pmc@fffffc00 {
--
2.0.1
Adapt the ramc mapping code to handle multiple ram controllers in the DT.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/setup.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 06aaf857ddc4..61d0b96c31e9 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -340,24 +340,26 @@ static void at91_dt_ramc(void)
{
struct device_node *np;
const struct of_device_id *of_id;
+ int idx = 0;
- np = of_find_matching_node(NULL, ramc_ids);
- if (!np)
- panic(pr_fmt("unable to find compatible ram controller node in dtb\n"));
+ for_each_matching_node(np, ramc_ids) {
+ at91_ramc_base[idx] = of_iomap(np, 0);
+ if (!at91_ramc_base[idx])
+ panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx);
+
+ idx++;
+ }
- at91_ramc_base[0] = of_iomap(np, 0);
- if (!at91_ramc_base[0])
- panic(pr_fmt("unable to map ramc[0] cpu registers\n"));
- /* the controller may have 2 banks */
- at91_ramc_base[1] = of_iomap(np, 1);
+ if (!idx)
+ panic(pr_fmt("unable to find compatible ram controller node in dtb\n"));
of_id = of_match_node(ramc_ids, np);
- if (!of_id)
+ if (!of_id) {
pr_warn("ramc no standby function available\n");
- else
- at91_pm_set_standby(of_id->data);
+ return;
+ }
- of_node_put(np);
+ at91_pm_set_standby(of_id->data);
}
void __init at91rm9200_dt_initialize(void)
--
2.0.1
Both the reset and poweroff drivers are now implementing what the
show_reset_status function used to do. Hence, we can remove this rather hackish
function that prevents us from doing further cleanup.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/pm.c | 72 -------------------------------------------------
1 file changed, 72 deletions(-)
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index e95554532987..213606111d9a 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -34,79 +34,8 @@
#include "pm.h"
#include "gpio.h"
-/*
- * Show the reason for the previous system reset.
- */
-
-#include "at91_rstc.h"
-#include "at91_shdwc.h"
-
static void (*at91_pm_standby)(void);
-static void __init show_reset_status(void)
-{
- static char reset[] __initdata = "reset";
-
- static char general[] __initdata = "general";
- static char wakeup[] __initdata = "wakeup";
- static char watchdog[] __initdata = "watchdog";
- static char software[] __initdata = "software";
- static char user[] __initdata = "user";
- static char unknown[] __initdata = "unknown";
-
- static char signal[] __initdata = "signal";
- static char rtc[] __initdata = "rtc";
- static char rtt[] __initdata = "rtt";
- static char restore[] __initdata = "power-restored";
-
- char *reason, *r2 = reset;
- u32 reset_type, wake_type;
-
- if (!at91_shdwc_base || !at91_rstc_base)
- return;
-
- reset_type = at91_rstc_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
- wake_type = at91_shdwc_read(AT91_SHDW_SR);
-
- switch (reset_type) {
- case AT91_RSTC_RSTTYP_GENERAL:
- reason = general;
- break;
- case AT91_RSTC_RSTTYP_WAKEUP:
- /* board-specific code enabled the wakeup sources */
- reason = wakeup;
-
- /* "wakeup signal" */
- if (wake_type & AT91_SHDW_WAKEUP0)
- r2 = signal;
- else {
- r2 = reason;
- if (wake_type & AT91_SHDW_RTTWK) /* rtt wakeup */
- reason = rtt;
- else if (wake_type & AT91_SHDW_RTCWK) /* rtc wakeup */
- reason = rtc;
- else if (wake_type == 0) /* power-restored wakeup */
- reason = restore;
- else /* unknown wakeup */
- reason = unknown;
- }
- break;
- case AT91_RSTC_RSTTYP_WATCHDOG:
- reason = watchdog;
- break;
- case AT91_RSTC_RSTTYP_SOFTWARE:
- reason = software;
- break;
- case AT91_RSTC_RSTTYP_USER:
- reason = user;
- break;
- default:
- reason = unknown;
- break;
- }
- pr_info("AT91: Starting after %s %s\n", reason, r2);
-}
-
static int at91_pm_valid_state(suspend_state_t state)
{
switch (state) {
@@ -338,7 +267,6 @@ static int __init at91_pm_init(void)
suspend_set_ops(&at91_pm_ops);
- show_reset_status();
return 0;
}
arch_initcall(at91_pm_init);
--
2.0.1
Most of the printed messages are using the "AT91:" prefix in the setup.c file,
but not all of them. Moreover, those who add it hardcode it directly in the
message, while the pr_fmt macro makes it easier for us to support such a case.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/setup.c | 42 ++++++++++++++++++++++--------------------
1 file changed, 22 insertions(+), 20 deletions(-)
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index f7a07a58ebb6..9c4c7fb323fb 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -5,6 +5,8 @@
* Under GPLv2
*/
+#define pr_fmt(fmt) "AT91: " fmt
+
#include <linux/module.h>
#include <linux/io.h>
#include <linux/mm.h>
@@ -37,7 +39,7 @@ void __init at91rm9200_set_type(int type)
else
at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
- pr_info("AT91: filled in soc subtype: %s\n",
+ pr_info("filled in soc subtype: %s\n",
at91_get_soc_subtype(&at91_soc_initdata));
}
@@ -66,7 +68,7 @@ void __init at91_ioremap_ramc(int id, u32 addr, u32 size)
}
at91_ramc_base[id] = ioremap(addr, size);
if (!at91_ramc_base[id])
- panic("Impossible to ioremap ramc.%d 0x%x\n", id, addr);
+ panic(pr_fmt("Impossible to ioremap ramc.%d 0x%x\n"), id, addr);
}
static struct map_desc sram_desc[2] __initdata;
@@ -83,7 +85,7 @@ void __init at91_init_sram(int bank, unsigned long base, unsigned int length)
desc->length = length;
desc->type = MT_MEMORY_RWX_NONCACHED;
- pr_info("AT91: sram at 0x%lx of 0x%x mapped at 0x%lx\n",
+ pr_info("sram at 0x%lx of 0x%x mapped at 0x%lx\n",
base, length, desc->virtual);
iotable_init(desc, 1);
@@ -302,16 +304,16 @@ void __init at91_map_io(void)
soc_detect(AT91_BASE_DBGU1);
if (!at91_soc_is_detected())
- panic("AT91: Impossible to detect the SOC type");
+ panic(pr_fmt("Impossible to detect the SOC type"));
- pr_info("AT91: Detected soc type: %s\n",
+ pr_info("Detected soc type: %s\n",
at91_get_soc_type(&at91_soc_initdata));
if (at91_soc_initdata.subtype != AT91_SOC_SUBTYPE_NONE)
- pr_info("AT91: Detected soc subtype: %s\n",
+ pr_info("Detected soc subtype: %s\n",
at91_get_soc_subtype(&at91_soc_initdata));
if (!at91_soc_is_enabled())
- panic("AT91: Soc not enabled");
+ panic(pr_fmt("Soc not enabled"));
if (at91_boot_soc.map_io)
at91_boot_soc.map_io();
@@ -328,7 +330,7 @@ void __init at91_ioremap_shdwc(u32 base_addr)
{
at91_shdwc_base = ioremap(base_addr, 16);
if (!at91_shdwc_base)
- panic("Impossible to ioremap at91_shdwc_base\n");
+ panic(pr_fmt("Impossible to ioremap at91_shdwc_base\n"));
pm_power_off = at91sam9_poweroff;
}
@@ -338,7 +340,7 @@ void __init at91_ioremap_rstc(u32 base_addr)
{
at91_rstc_base = ioremap(base_addr, 16);
if (!at91_rstc_base)
- panic("Impossible to ioremap at91_rstc_base\n");
+ panic(pr_fmt("Impossible to ioremap at91_rstc_base\n"));
}
void __iomem *at91_matrix_base;
@@ -348,7 +350,7 @@ void __init at91_ioremap_matrix(u32 base_addr)
{
at91_matrix_base = ioremap(base_addr, 512);
if (!at91_matrix_base)
- panic("Impossible to ioremap at91_matrix_base\n");
+ panic(pr_fmt("Impossible to ioremap at91_matrix_base\n"));
}
#if defined(CONFIG_OF) && !defined(CONFIG_ARCH_AT91X40)
@@ -365,15 +367,15 @@ static void at91_dt_rstc(void)
np = of_find_matching_node(NULL, rstc_ids);
if (!np)
- panic("unable to find compatible rstc node in dtb\n");
+ panic(pr_fmt("unable to find compatible rstc node in dtb\n"));
at91_rstc_base = of_iomap(np, 0);
if (!at91_rstc_base)
- panic("unable to map rstc cpu registers\n");
+ panic(pr_fmt("unable to map rstc cpu registers\n"));
of_id = of_match_node(rstc_ids, np);
if (!of_id)
- panic("AT91: rtsc no restart function available\n");
+ panic(pr_fmt("rtsc no restart function available\n"));
arm_pm_restart = of_id->data;
@@ -394,17 +396,17 @@ static void at91_dt_ramc(void)
np = of_find_matching_node(NULL, ramc_ids);
if (!np)
- panic("unable to find compatible ram controller node in dtb\n");
+ panic(pr_fmt("unable to find compatible ram controller node in dtb\n"));
at91_ramc_base[0] = of_iomap(np, 0);
if (!at91_ramc_base[0])
- panic("unable to map ramc[0] cpu registers\n");
+ panic(pr_fmt("unable to map ramc[0] cpu registers\n"));
/* the controller may have 2 banks */
at91_ramc_base[1] = of_iomap(np, 1);
of_id = of_match_node(ramc_ids, np);
if (!of_id)
- pr_warn("AT91: ramc no standby function available\n");
+ pr_warn("ramc no standby function available\n");
else
at91_pm_set_standby(of_id->data);
@@ -450,23 +452,23 @@ static void at91_dt_shdwc(void)
np = of_find_matching_node(NULL, shdwc_ids);
if (!np) {
- pr_debug("AT91: unable to find compatible shutdown (shdwc) controller node in dtb\n");
+ pr_debug("unable to find compatible shutdown (shdwc) controller node in dtb\n");
return;
}
at91_shdwc_base = of_iomap(np, 0);
if (!at91_shdwc_base)
- panic("AT91: unable to map shdwc cpu registers\n");
+ panic(pr_fmt("unable to map shdwc cpu registers\n"));
wakeup_mode = at91_dtget_shdwc_wakeup_mode(np);
if (wakeup_mode < 0) {
- pr_warn("AT91: shdwc unknown wakeup mode\n");
+ pr_warn("shdwc unknown wakeup mode\n");
goto end;
}
if (!of_property_read_u32(np, "atmel,wakeup-counter", ®)) {
if (reg > AT91_SHDW_CPTWK0_MAX) {
- pr_warn("AT91: shdwc wakeup counter 0x%x > 0x%x reduce it to 0x%x\n",
+ pr_warn("shdwc wakeup counter 0x%x > 0x%x reduce it to 0x%x\n",
reg, AT91_SHDW_CPTWK0_MAX, AT91_SHDW_CPTWK0_MAX);
reg = AT91_SHDW_CPTWK0_MAX;
}
--
2.0.1
Both the reset and poweroff drivers are now implementing what the
show_reset_status function used to do. Hence, we can remove this rather hackish
function that prevents us from doing further cleanup.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/pm.c | 72 -------------------------------------------------
1 file changed, 72 deletions(-)
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index e95554532987..213606111d9a 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -34,79 +34,8 @@
#include "pm.h"
#include "gpio.h"
-/*
- * Show the reason for the previous system reset.
- */
-
-#include "at91_rstc.h"
-#include "at91_shdwc.h"
-
static void (*at91_pm_standby)(void);
-static void __init show_reset_status(void)
-{
- static char reset[] __initdata = "reset";
-
- static char general[] __initdata = "general";
- static char wakeup[] __initdata = "wakeup";
- static char watchdog[] __initdata = "watchdog";
- static char software[] __initdata = "software";
- static char user[] __initdata = "user";
- static char unknown[] __initdata = "unknown";
-
- static char signal[] __initdata = "signal";
- static char rtc[] __initdata = "rtc";
- static char rtt[] __initdata = "rtt";
- static char restore[] __initdata = "power-restored";
-
- char *reason, *r2 = reset;
- u32 reset_type, wake_type;
-
- if (!at91_shdwc_base || !at91_rstc_base)
- return;
-
- reset_type = at91_rstc_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
- wake_type = at91_shdwc_read(AT91_SHDW_SR);
-
- switch (reset_type) {
- case AT91_RSTC_RSTTYP_GENERAL:
- reason = general;
- break;
- case AT91_RSTC_RSTTYP_WAKEUP:
- /* board-specific code enabled the wakeup sources */
- reason = wakeup;
-
- /* "wakeup signal" */
- if (wake_type & AT91_SHDW_WAKEUP0)
- r2 = signal;
- else {
- r2 = reason;
- if (wake_type & AT91_SHDW_RTTWK) /* rtt wakeup */
- reason = rtt;
- else if (wake_type & AT91_SHDW_RTCWK) /* rtc wakeup */
- reason = rtc;
- else if (wake_type == 0) /* power-restored wakeup */
- reason = restore;
- else /* unknown wakeup */
- reason = unknown;
- }
- break;
- case AT91_RSTC_RSTTYP_WATCHDOG:
- reason = watchdog;
- break;
- case AT91_RSTC_RSTTYP_SOFTWARE:
- reason = software;
- break;
- case AT91_RSTC_RSTTYP_USER:
- reason = user;
- break;
- default:
- reason = unknown;
- break;
- }
- pr_info("AT91: Starting after %s %s\n", reason, r2);
-}
-
static int at91_pm_valid_state(suspend_state_t state)
{
switch (state) {
@@ -338,7 +267,6 @@ static int __init at91_pm_init(void)
suspend_set_ops(&at91_pm_ops);
- show_reset_status();
return 0;
}
arch_initcall(at91_pm_init);
--
2.0.1
Now that all the SoC have been converted to use the new poweroff driver, we can
remove the poweroff code defined in mach-at91.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/setup.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index ae269291d19d..cdd717a4fa30 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -321,17 +321,11 @@ void __init at91_map_io(void)
void __iomem *at91_shdwc_base = NULL;
-static void at91sam9_poweroff(void)
-{
- at91_shdwc_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
-}
-
void __init at91_ioremap_shdwc(u32 base_addr)
{
at91_shdwc_base = ioremap(base_addr, 16);
if (!at91_shdwc_base)
panic(pr_fmt("Impossible to ioremap at91_shdwc_base\n"));
- pm_power_off = at91sam9_poweroff;
}
void __iomem *at91_rstc_base;
--
2.0.1
Now that all the SoC have been converted to use the new poweroff driver, we can
remove the poweroff code defined in mach-at91.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/setup.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 69967c21d5c0..7124b0334bb1 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -321,17 +321,11 @@ void __init at91_map_io(void)
void __iomem *at91_shdwc_base = NULL;
-static void at91sam9_poweroff(void)
-{
- at91_shdwc_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
-}
-
void __init at91_ioremap_shdwc(u32 base_addr)
{
at91_shdwc_base = ioremap(base_addr, 16);
if (!at91_shdwc_base)
panic(pr_fmt("Impossible to ioremap at91_shdwc_base\n"));
- pm_power_off = at91sam9_poweroff;
}
void __iomem *at91_rstc_base;
--
2.0.1
Register the poweroff driver in the old-style SoC definition so that the driver
is loaded and provide a shutdown hook.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/at91sam9260.c | 15 +++++++++++++++
arch/arm/mach-at91/at91sam9261.c | 15 +++++++++++++++
arch/arm/mach-at91/at91sam9263.c | 15 +++++++++++++++
arch/arm/mach-at91/at91sam9g45.c | 15 +++++++++++++++
arch/arm/mach-at91/at91sam9rl.c | 15 +++++++++++++++
5 files changed, 75 insertions(+)
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 197c0149406a..5fa1986be2aa 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -377,9 +377,24 @@ static struct platform_device rstc_device = {
.num_resources = ARRAY_SIZE(rstc_resources),
};
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_SHDWC,
+ .end = AT91SAM9260_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
static void __init at91sam9260_register_devices(void)
{
platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
}
/* --------------------------------------------------------------------
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index ef44977f1cae..5ccc67235e7a 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -340,9 +340,24 @@ static struct platform_device rstc_device = {
.num_resources = ARRAY_SIZE(rstc_resources),
};
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_SHDWC,
+ .end = AT91SAM9261_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
static void __init at91sam9261_register_devices(void)
{
platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
}
/* --------------------------------------------------------------------
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index cb078e150a19..4d28c3479d4b 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -358,9 +358,24 @@ static struct platform_device rstc_device = {
.num_resources = ARRAY_SIZE(rstc_resources),
};
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_SHDWC,
+ .end = AT91SAM9263_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
static void __init at91sam9263_register_devices(void)
{
platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
}
/* --------------------------------------------------------------------
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 329749eb1dff..22034c96d488 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -412,9 +412,24 @@ static struct platform_device rstc_device = {
.num_resources = ARRAY_SIZE(rstc_resources),
};
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9G45_BASE_SHDWC,
+ .end = AT91SAM9G45_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
static void __init at91sam9g45_register_devices(void)
{
platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
}
/* --------------------------------------------------------------------
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index e0e1729fe0e4..323a9f90931a 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -350,9 +350,24 @@ static struct platform_device rstc_device = {
.num_resources = ARRAY_SIZE(rstc_resources),
};
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9RL_BASE_SHDWC,
+ .end = AT91SAM9RL_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
static void __init at91sam9rl_register_devices(void)
{
platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
}
/* --------------------------------------------------------------------
--
2.0.1
Register the poweroff driver in the old-style SoC definition so that the driver
is loaded and provide a shutdown hook.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/at91sam9260.c | 15 +++++++++++++++
arch/arm/mach-at91/at91sam9261.c | 15 +++++++++++++++
arch/arm/mach-at91/at91sam9263.c | 15 +++++++++++++++
arch/arm/mach-at91/at91sam9g45.c | 15 +++++++++++++++
arch/arm/mach-at91/at91sam9rl.c | 15 +++++++++++++++
5 files changed, 75 insertions(+)
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 197c0149406a..5fa1986be2aa 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -377,9 +377,24 @@ static struct platform_device rstc_device = {
.num_resources = ARRAY_SIZE(rstc_resources),
};
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_SHDWC,
+ .end = AT91SAM9260_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
static void __init at91sam9260_register_devices(void)
{
platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
}
/* --------------------------------------------------------------------
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index ef44977f1cae..5ccc67235e7a 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -340,9 +340,24 @@ static struct platform_device rstc_device = {
.num_resources = ARRAY_SIZE(rstc_resources),
};
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_SHDWC,
+ .end = AT91SAM9261_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
static void __init at91sam9261_register_devices(void)
{
platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
}
/* --------------------------------------------------------------------
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index cb078e150a19..4d28c3479d4b 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -358,9 +358,24 @@ static struct platform_device rstc_device = {
.num_resources = ARRAY_SIZE(rstc_resources),
};
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_SHDWC,
+ .end = AT91SAM9263_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
static void __init at91sam9263_register_devices(void)
{
platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
}
/* --------------------------------------------------------------------
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 329749eb1dff..22034c96d488 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -412,9 +412,24 @@ static struct platform_device rstc_device = {
.num_resources = ARRAY_SIZE(rstc_resources),
};
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9G45_BASE_SHDWC,
+ .end = AT91SAM9G45_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
static void __init at91sam9g45_register_devices(void)
{
platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
}
/* --------------------------------------------------------------------
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index e0e1729fe0e4..323a9f90931a 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -350,9 +350,24 @@ static struct platform_device rstc_device = {
.num_resources = ARRAY_SIZE(rstc_resources),
};
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9RL_BASE_SHDWC,
+ .end = AT91SAM9RL_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
static void __init at91sam9rl_register_devices(void)
{
platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
}
/* --------------------------------------------------------------------
--
2.0.1
Now that the poweroff code is a driver of its own, remove the DT probing in
mach-at91 and let the usual DT code do its job.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/setup.c | 77 ----------------------------------------------
1 file changed, 77 deletions(-)
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 771e0495bfe5..69967c21d5c0 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -385,82 +385,6 @@ static void at91_dt_ramc(void)
of_node_put(np);
}
-static struct of_device_id shdwc_ids[] = {
- { .compatible = "atmel,at91sam9260-shdwc", },
- { .compatible = "atmel,at91sam9rl-shdwc", },
- { .compatible = "atmel,at91sam9x5-shdwc", },
- { /*sentinel*/ }
-};
-
-static const char *shdwc_wakeup_modes[] = {
- [AT91_SHDW_WKMODE0_NONE] = "none",
- [AT91_SHDW_WKMODE0_HIGH] = "high",
- [AT91_SHDW_WKMODE0_LOW] = "low",
- [AT91_SHDW_WKMODE0_ANYLEVEL] = "any",
-};
-
-const int at91_dtget_shdwc_wakeup_mode(struct device_node *np)
-{
- const char *pm;
- int err, i;
-
- err = of_property_read_string(np, "atmel,wakeup-mode", &pm);
- if (err < 0)
- return AT91_SHDW_WKMODE0_ANYLEVEL;
-
- for (i = 0; i < ARRAY_SIZE(shdwc_wakeup_modes); i++)
- if (!strcasecmp(pm, shdwc_wakeup_modes[i]))
- return i;
-
- return -ENODEV;
-}
-
-static void at91_dt_shdwc(void)
-{
- struct device_node *np;
- int wakeup_mode;
- u32 reg;
- u32 mode = 0;
-
- np = of_find_matching_node(NULL, shdwc_ids);
- if (!np) {
- pr_debug("unable to find compatible shutdown (shdwc) controller node in dtb\n");
- return;
- }
-
- at91_shdwc_base = of_iomap(np, 0);
- if (!at91_shdwc_base)
- panic(pr_fmt("unable to map shdwc cpu registers\n"));
-
- wakeup_mode = at91_dtget_shdwc_wakeup_mode(np);
- if (wakeup_mode < 0) {
- pr_warn("shdwc unknown wakeup mode\n");
- goto end;
- }
-
- if (!of_property_read_u32(np, "atmel,wakeup-counter", ®)) {
- if (reg > AT91_SHDW_CPTWK0_MAX) {
- pr_warn("shdwc wakeup counter 0x%x > 0x%x reduce it to 0x%x\n",
- reg, AT91_SHDW_CPTWK0_MAX, AT91_SHDW_CPTWK0_MAX);
- reg = AT91_SHDW_CPTWK0_MAX;
- }
- mode |= AT91_SHDW_CPTWK0_(reg);
- }
-
- if (of_property_read_bool(np, "atmel,wakeup-rtc-timer"))
- mode |= AT91_SHDW_RTCWKEN;
-
- if (of_property_read_bool(np, "atmel,wakeup-rtt-timer"))
- mode |= AT91_SHDW_RTTWKEN;
-
- at91_shdwc_write(AT91_SHDW_MR, wakeup_mode | mode);
-
-end:
- pm_power_off = at91sam9_poweroff;
-
- of_node_put(np);
-}
-
void __init at91rm9200_dt_initialize(void)
{
at91_dt_ramc();
@@ -478,7 +402,6 @@ void __init at91rm9200_dt_initialize(void)
void __init at91_dt_initialize(void)
{
at91_dt_ramc();
- at91_dt_shdwc();
/* Init clock subsystem */
at91_dt_clock_init();
--
2.0.1
Now that the poweroff code is a driver of its own, remove the DT probing in
mach-at91 and let the usual DT code do its job.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/setup.c | 77 ----------------------------------------------
1 file changed, 77 deletions(-)
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index fe0601e0a3c0..ae269291d19d 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -387,82 +387,6 @@ static void at91_dt_ramc(void)
at91_pm_set_standby(of_id->data);
}
-static struct of_device_id shdwc_ids[] = {
- { .compatible = "atmel,at91sam9260-shdwc", },
- { .compatible = "atmel,at91sam9rl-shdwc", },
- { .compatible = "atmel,at91sam9x5-shdwc", },
- { /*sentinel*/ }
-};
-
-static const char *shdwc_wakeup_modes[] = {
- [AT91_SHDW_WKMODE0_NONE] = "none",
- [AT91_SHDW_WKMODE0_HIGH] = "high",
- [AT91_SHDW_WKMODE0_LOW] = "low",
- [AT91_SHDW_WKMODE0_ANYLEVEL] = "any",
-};
-
-const int at91_dtget_shdwc_wakeup_mode(struct device_node *np)
-{
- const char *pm;
- int err, i;
-
- err = of_property_read_string(np, "atmel,wakeup-mode", &pm);
- if (err < 0)
- return AT91_SHDW_WKMODE0_ANYLEVEL;
-
- for (i = 0; i < ARRAY_SIZE(shdwc_wakeup_modes); i++)
- if (!strcasecmp(pm, shdwc_wakeup_modes[i]))
- return i;
-
- return -ENODEV;
-}
-
-static void at91_dt_shdwc(void)
-{
- struct device_node *np;
- int wakeup_mode;
- u32 reg;
- u32 mode = 0;
-
- np = of_find_matching_node(NULL, shdwc_ids);
- if (!np) {
- pr_debug("unable to find compatible shutdown (shdwc) controller node in dtb\n");
- return;
- }
-
- at91_shdwc_base = of_iomap(np, 0);
- if (!at91_shdwc_base)
- panic(pr_fmt("unable to map shdwc cpu registers\n"));
-
- wakeup_mode = at91_dtget_shdwc_wakeup_mode(np);
- if (wakeup_mode < 0) {
- pr_warn("shdwc unknown wakeup mode\n");
- goto end;
- }
-
- if (!of_property_read_u32(np, "atmel,wakeup-counter", ®)) {
- if (reg > AT91_SHDW_CPTWK0_MAX) {
- pr_warn("shdwc wakeup counter 0x%x > 0x%x reduce it to 0x%x\n",
- reg, AT91_SHDW_CPTWK0_MAX, AT91_SHDW_CPTWK0_MAX);
- reg = AT91_SHDW_CPTWK0_MAX;
- }
- mode |= AT91_SHDW_CPTWK0_(reg);
- }
-
- if (of_property_read_bool(np, "atmel,wakeup-rtc-timer"))
- mode |= AT91_SHDW_RTCWKEN;
-
- if (of_property_read_bool(np, "atmel,wakeup-rtt-timer"))
- mode |= AT91_SHDW_RTTWKEN;
-
- at91_shdwc_write(AT91_SHDW_MR, wakeup_mode | mode);
-
-end:
- pm_power_off = at91sam9_poweroff;
-
- of_node_put(np);
-}
-
void __init at91rm9200_dt_initialize(void)
{
at91_dt_ramc();
@@ -480,7 +404,6 @@ void __init at91rm9200_dt_initialize(void)
void __init at91_dt_initialize(void)
{
at91_dt_ramc();
- at91_dt_shdwc();
/* Init clock subsystem */
at91_dt_clock_init();
--
2.0.1
Add a driver to handle the shutdown of the Atmel SoCs. This code used to be
(and still is) in arch/arm/mach-at91. We didn't removed it yet so that we can
convert all the boards to using this driver, before removing it entirely in a
separate patch.
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/power/reset/Kconfig | 7 ++
drivers/power/reset/Makefile | 1 +
drivers/power/reset/at91-poweroff.c | 156 ++++++++++++++++++++++++++++++++++++
3 files changed, 164 insertions(+)
create mode 100644 drivers/power/reset/at91-poweroff.c
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index b3fef01d7cbb..f9d53af50ec0 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -14,6 +14,13 @@ config POWER_RESET_AS3722
help
This driver supports turning off board via a ams AS3722 power-off.
+config POWER_RESET_AT91_POWEROFF
+ bool "Atmel AT91 poweroff driver"
+ default SOC_AT91SAM9 || SOC_SAMA5
+ help
+ This driver supports poweroff for Atmel AT91SAM9 and SAMA5
+ SoCs
+
config POWER_RESET_AT91_RESET
bool "Atmel AT91 reset driver"
default SOC_AT91SAM9 || SOC_SAMA5
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 1599214b91d9..8bf941bac3da 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
+obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o
obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c
new file mode 100644
index 000000000000..2f2a69e9bae3
--- /dev/null
+++ b/drivers/power/reset/at91-poweroff.c
@@ -0,0 +1,156 @@
+/*
+ * Atmel AT91 SAM9 SoCs reset code
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ *
+ * Maxime Ripard <[email protected]>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+
+#define AT91_SHDW_CR 0x00 /* Shut Down Control Register */
+#define AT91_SHDW_SHDW BIT(0) /* Shut Down command */
+#define AT91_SHDW_KEY (0xa5 << 24) /* KEY Password */
+
+#define AT91_SHDW_MR 0x04 /* Shut Down Mode Register */
+#define AT91_SHDW_WKMODE0 GENMASK(2, 0) /* Wake-up 0 Mode Selection */
+#define AT91_SHDW_CPTWK0_MAX 0xf /* Maximum Counter On Wake Up 0 */
+#define AT91_SHDW_CPTWK0 (AT91_SHDW_CPTWK0_MAX << 4) /* Counter On Wake Up 0 */
+#define AT91_SHDW_CPTWK0_(x) ((x) << 4)
+#define AT91_SHDW_RTTWKEN BIT(16) /* Real Time Timer Wake-up Enable */
+#define AT91_SHDW_RTCWKEN BIT(17) /* Real Time Clock Wake-up Enable */
+
+#define AT91_SHDW_SR 0x08 /* Shut Down Status Register */
+#define AT91_SHDW_WAKEUP0 BIT(0) /* Wake-up 0 Status */
+#define AT91_SHDW_RTTWK BIT(16) /* Real-time Timer Wake-up */
+#define AT91_SHDW_RTCWK BIT(17) /* Real-time Clock Wake-up [SAM9RL] */
+
+enum wakeup_type {
+ AT91_SHDW_WKMODE0_NONE = 0,
+ AT91_SHDW_WKMODE0_HIGH = 1,
+ AT91_SHDW_WKMODE0_LOW = 2,
+ AT91_SHDW_WKMODE0_ANYLEVEL = 3,
+};
+
+static const char *shdwc_wakeup_modes[] = {
+ [AT91_SHDW_WKMODE0_NONE] = "none",
+ [AT91_SHDW_WKMODE0_HIGH] = "high",
+ [AT91_SHDW_WKMODE0_LOW] = "low",
+ [AT91_SHDW_WKMODE0_ANYLEVEL] = "any",
+};
+
+static void __iomem *at91_shdwc_base;
+
+static void __init at91_wakeup_status(void)
+{
+ u32 reg = readl(at91_shdwc_base);
+ char *reason = "unknown";
+
+ /* Simple power-on, just bail out */
+ if (!reg)
+ return;
+
+ if (reg & AT91_SHDW_RTTWK)
+ reason = "RTT";
+ else if (reg & AT91_SHDW_RTCWK)
+ reason = "RTC";
+
+ pr_info("AT91: Wake-Up source: %s\n", reason);
+}
+
+static void at91_poweroff(void)
+{
+ writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, at91_shdwc_base + AT91_SHDW_CR);
+}
+
+const enum wakeup_type at91_poweroff_get_wakeup_mode(struct device_node *np)
+{
+ const char *pm;
+ int err, i;
+
+ err = of_property_read_string(np, "atmel,wakeup-mode", &pm);
+ if (err < 0)
+ return AT91_SHDW_WKMODE0_ANYLEVEL;
+
+ for (i = 0; i < ARRAY_SIZE(shdwc_wakeup_modes); i++)
+ if (!strcasecmp(pm, shdwc_wakeup_modes[i]))
+ return i;
+
+ return -ENODEV;
+}
+
+static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ enum wakeup_type wakeup_mode;
+ u32 mode = 0, tmp;
+
+ wakeup_mode = at91_poweroff_get_wakeup_mode(np);
+ if (wakeup_mode < 0) {
+ dev_warn(&pdev->dev, "shdwc unknown wakeup mode\n");
+ return;
+ }
+
+ if (!of_property_read_u32(np, "atmel,wakeup-counter", &tmp)) {
+ if (tmp > AT91_SHDW_CPTWK0_MAX) {
+ dev_warn(&pdev->dev,
+ "shdwc wakeup counter 0x%x > 0x%x reduce it to 0x%x\n",
+ tmp, AT91_SHDW_CPTWK0_MAX, AT91_SHDW_CPTWK0_MAX);
+ tmp = AT91_SHDW_CPTWK0_MAX;
+ }
+ mode |= AT91_SHDW_CPTWK0_(tmp);
+ }
+
+ if (of_property_read_bool(np, "atmel,wakeup-rtc-timer"))
+ mode |= AT91_SHDW_RTCWKEN;
+
+ if (of_property_read_bool(np, "atmel,wakeup-rtt-timer"))
+ mode |= AT91_SHDW_RTTWKEN;
+
+ writel(wakeup_mode | mode, at91_shdwc_base + AT91_SHDW_MR);
+}
+
+static int at91_poweroff_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(at91_shdwc_base)) {
+ dev_err(&pdev->dev, "Could not map reset controller address\n");
+ return PTR_ERR(at91_shdwc_base);
+ }
+
+ at91_wakeup_status();
+
+ if (pdev->dev.of_node)
+ at91_poweroff_dt_set_wakeup_mode(pdev);
+
+ pm_power_off = at91_poweroff;
+
+ return 0;
+}
+
+static struct of_device_id at91_poweroff_of_match[] = {
+ { .compatible = "atmel,at91sam9260-shdwc", },
+ { .compatible = "atmel,at91sam9rl-shdwc", },
+ { .compatible = "atmel,at91sam9x5-shdwc", },
+ { /*sentinel*/ }
+};
+
+static struct platform_driver at91_poweroff_driver = {
+ .probe = at91_poweroff_probe,
+ .driver = {
+ .name = "at91-poweroff",
+ .of_match_table = at91_poweroff_of_match,
+ },
+};
+module_platform_driver(at91_poweroff_driver);
--
2.0.1
Now that the transition is over and that we probe our reset driver in every
case, we can remove the legacy code from the machine directory.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/Kconfig | 8 ------
arch/arm/mach-at91/Makefile | 2 --
arch/arm/mach-at91/at91sam9260.c | 1 -
arch/arm/mach-at91/at91sam9261.c | 1 -
arch/arm/mach-at91/at91sam9263.c | 1 -
arch/arm/mach-at91/at91sam9_alt_reset.S | 40 -----------------------------
arch/arm/mach-at91/at91sam9g45.c | 1 -
arch/arm/mach-at91/at91sam9g45_reset.S | 45 ---------------------------------
arch/arm/mach-at91/at91sam9rl.c | 1 -
arch/arm/mach-at91/generic.h | 2 --
10 files changed, 102 deletions(-)
delete mode 100644 arch/arm/mach-at91/at91sam9_alt_reset.S
delete mode 100644 arch/arm/mach-at91/at91sam9g45_reset.S
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 45b55e0f0db6..d2a1ffec5e11 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -28,14 +28,6 @@ config OLD_CLK_AT91
bool
default AT91_PMC_UNIT && AT91_USE_OLD_CLK
-config AT91_SAM9_ALT_RESET
- bool
- default !ARCH_AT91X40
-
-config AT91_SAM9G45_RESET
- bool
- default !ARCH_AT91X40
-
config AT91_SAM9_TIME
bool
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 78e9cec282f4..2947834d93c3 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -8,8 +8,6 @@ obj-n :=
obj- :=
obj-$(CONFIG_OLD_CLK_AT91) += clock.o
-obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o
-obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o
obj-$(CONFIG_AT91_SAM9_TIME) += at91sam926x_time.o
obj-$(CONFIG_SOC_AT91SAM9) += sam9_smc.o
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 9ffab0cf94cd..197c0149406a 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -351,7 +351,6 @@ static void __init at91sam9260_ioremap_registers(void)
static void __init at91sam9260_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9_alt_restart;
at91_sysirq_mask_rtt(AT91SAM9260_BASE_RTT);
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 41fa9b9a6f05..ef44977f1cae 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -314,7 +314,6 @@ static void __init at91sam9261_ioremap_registers(void)
static void __init at91sam9261_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9_alt_restart;
at91_sysirq_mask_rtt(AT91SAM9261_BASE_RTT);
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 0c6949c342dc..cb078e150a19 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -331,7 +331,6 @@ static void __init at91sam9263_ioremap_registers(void)
static void __init at91sam9263_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9_alt_restart;
at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT0);
at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT1);
diff --git a/arch/arm/mach-at91/at91sam9_alt_reset.S b/arch/arm/mach-at91/at91sam9_alt_reset.S
deleted file mode 100644
index f039538d3bdb..000000000000
--- a/arch/arm/mach-at91/at91sam9_alt_reset.S
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * reset AT91SAM9G20 as per errata
- *
- * (C) BitBox Ltd 2010
- *
- * unless the SDRAM is cleanly shutdown before we hit the
- * reset register it can be left driving the data bus and
- * killing the chance of a subsequent boot from NAND
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/linkage.h>
-#include <mach/hardware.h>
-#include <mach/at91_ramc.h>
-#include "at91_rstc.h"
-
- .arm
-
- .globl at91sam9_alt_restart
-
-at91sam9_alt_restart: ldr r0, =at91_ramc_base @ preload constants
- ldr r0, [r0]
- ldr r4, =at91_rstc_base
- ldr r1, [r4]
-
- mov r2, #1
- mov r3, #AT91_SDRAMC_LPCB_POWER_DOWN
- ldr r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST
-
- .balign 32 @ align to cache line
-
- str r2, [r0, #AT91_SDRAMC_TR] @ disable SDRAM access
- str r3, [r0, #AT91_SDRAMC_LPR] @ power down SDRAM
- str r4, [r1, #AT91_RSTC_CR] @ reset processor
-
- b .
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 61c0bc1185e9..329749eb1dff 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -380,7 +380,6 @@ static void __init at91sam9g45_ioremap_registers(void)
static void __init at91sam9g45_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9g45_restart;
at91_sysirq_mask_rtc(AT91SAM9G45_BASE_RTC);
at91_sysirq_mask_rtt(AT91SAM9G45_BASE_RTT);
diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S
deleted file mode 100644
index c40c1e2ef80f..000000000000
--- a/arch/arm/mach-at91/at91sam9g45_reset.S
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * reset AT91SAM9G45 as per errata
- *
- * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <[email protected]>
- *
- * unless the SDRAM is cleanly shutdown before we hit the
- * reset register it can be left driving the data bus and
- * killing the chance of a subsequent boot from NAND
- *
- * GPLv2 Only
- */
-
-#include <linux/linkage.h>
-#include <mach/hardware.h>
-#include <mach/at91_ramc.h>
-#include "at91_rstc.h"
- .arm
-
-/*
- * at91_ramc_base is an array void*
- * init at NULL if only one DDR controler is present in or DT
- */
- .globl at91sam9g45_restart
-
-at91sam9g45_restart:
- ldr r5, =at91_ramc_base @ preload constants
- ldr r0, [r5]
- ldr r5, [r5, #4] @ ddr1
- cmp r5, #0
- ldr r4, =at91_rstc_base
- ldr r1, [r4]
-
- mov r2, #1
- mov r3, #AT91_DDRSDRC_LPCB_POWER_DOWN
- ldr r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST
-
- .balign 32 @ align to cache line
-
- strne r2, [r5, #AT91_DDRSDRC_RTR] @ disable DDR1 access
- strne r3, [r5, #AT91_DDRSDRC_LPR] @ power down DDR1
- str r2, [r0, #AT91_DDRSDRC_RTR] @ disable DDR0 access
- str r3, [r0, #AT91_DDRSDRC_LPR] @ power down DDR0
- str r4, [r1, #AT91_RSTC_CR] @ reset processor
-
- b .
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 417c8b6fb85e..e0e1729fe0e4 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -323,7 +323,6 @@ static void __init at91sam9rl_ioremap_registers(void)
static void __init at91sam9rl_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9_alt_restart;
at91_sysirq_mask_rtc(AT91SAM9RL_BASE_RTC);
at91_sysirq_mask_rtt(AT91SAM9RL_BASE_RTT);
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 4c2c96195a50..5d5e55237c41 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -66,8 +66,6 @@ extern void at91sam9_idle(void);
/* reset */
extern void at91_ioremap_rstc(u32 base_addr);
-extern void at91sam9_alt_restart(enum reboot_mode, const char *);
-extern void at91sam9g45_restart(enum reboot_mode, const char *);
/* shutdown */
extern void at91_ioremap_shdwc(u32 base_addr);
--
2.0.1
Make every board call the register_devices callback so that the devices
declared by the SoC are registered.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/board-afeb-9260v1.c | 2 ++
arch/arm/mach-at91/board-cam60.c | 2 ++
arch/arm/mach-at91/board-cpu9krea.c | 2 ++
arch/arm/mach-at91/board-flexibity.c | 2 ++
arch/arm/mach-at91/board-sam9-l9260.c | 2 ++
arch/arm/mach-at91/board-sam9260ek.c | 2 ++
arch/arm/mach-at91/board-sam9261ek.c | 2 ++
arch/arm/mach-at91/board-sam9263ek.c | 2 ++
arch/arm/mach-at91/board-sam9m10g45ek.c | 2 ++
arch/arm/mach-at91/board-sam9rlek.c | 2 ++
arch/arm/mach-at91/board-snapper9260.c | 2 ++
11 files changed, 22 insertions(+)
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index 597c649170aa..fc9621ccb606 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -167,6 +167,8 @@ static struct at91_cf_data afeb9260_cf_data = {
static void __init afeb9260_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index a30502c8d379..283655bd86c1 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -170,6 +170,8 @@ static void __init cam60_add_device_nand(void)
static void __init cam60_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index 2037f78c84e7..29a89032bb9a 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -322,6 +322,8 @@ static struct mci_platform_data __initdata cpu9krea_mci0_data = {
static void __init cpu9krea_board_init(void)
{
+ at91_register_devices();
+
/* NOR */
cpu9krea_add_device_nor();
/* Serial */
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
index 68f1ab6bd08f..79bd411b0cee 100644
--- a/arch/arm/mach-at91/board-flexibity.c
+++ b/arch/arm/mach-at91/board-flexibity.c
@@ -138,6 +138,8 @@ static struct gpio_led flexibity_leds[] = {
static void __init flexibity_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index d24dda67e2d3..70309404f366 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -187,6 +187,8 @@ static struct gpio_led ek_leds[] = {
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index 65dea12d685e..da9c5f1f2c49 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -307,6 +307,8 @@ static void __init ek_add_device_buttons(void) {}
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 4637432de08f..d1be10b09ab3 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -561,6 +561,8 @@ static struct gpio_led ek_leds[] = {
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index cd2726ee5add..3f613d962d9b 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -405,6 +405,8 @@ static struct at91_can_data ek_can_data = {
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index 1ea61328f30d..33a7b19f7400 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -450,6 +450,8 @@ static struct platform_device *devices[] __initdata = {
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DGBU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index b64648b4a1fc..262e3f957d9f 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -292,6 +292,8 @@ static void __init ek_add_device_buttons(void) {}
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index 1b870e6def0c..2a817b85569f 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -154,6 +154,8 @@ static void __init snapper9260_add_device_nand(void)
static void __init snapper9260_board_init(void)
{
+ at91_register_devices();
+
at91_add_device_i2c(snapper9260_i2c_devices,
ARRAY_SIZE(snapper9260_i2c_devices));
--
2.0.1
Some core devices should be registered by the SoC itself rather than by every
board using this SoC. Introduce a register_devices callback that should be
called during the init_machine in order to do that.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/generic.h | 2 ++
arch/arm/mach-at91/setup.c | 5 +++++
arch/arm/mach-at91/soc.h | 1 +
3 files changed, 8 insertions(+)
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 631fa3b8c16d..4c2c96195a50 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -37,6 +37,8 @@ extern int __init at91_aic5_of_init(struct device_node *node,
extern void __init at91_sysirq_mask_rtc(u32 rtc_base);
extern void __init at91_sysirq_mask_rtt(u32 rtt_base);
+ /* Devices */
+extern void __init at91_register_devices(void);
/* Timer */
extern void at91rm9200_ioremap_st(u32 addr);
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 71003e40f01c..fe0601e0a3c0 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -508,3 +508,8 @@ void __init at91_initialize(unsigned long main_clock)
pinctrl_provide_dummies();
}
+
+void __init at91_register_devices(void)
+{
+ at91_boot_soc.register_devices();
+}
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
index a1e1482c6da8..ab983f2cc7dd 100644
--- a/arch/arm/mach-at91/soc.h
+++ b/arch/arm/mach-at91/soc.h
@@ -11,6 +11,7 @@ struct at91_init_soc {
void (*map_io)(void);
void (*ioremap_registers)(void);
void (*register_clocks)(void);
+ void (*register_devices)(void);
void (*init)(void);
};
--
2.0.1
Register the reset device in the right SoCs so that the reset driver is
actually probed even in the old-style probing case.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/at91sam9260.c | 26 ++++++++++++++++++++++++++
arch/arm/mach-at91/at91sam9261.c | 26 ++++++++++++++++++++++++++
arch/arm/mach-at91/at91sam9263.c | 26 ++++++++++++++++++++++++++
arch/arm/mach-at91/at91sam9g45.c | 31 +++++++++++++++++++++++++++++++
arch/arm/mach-at91/at91sam9rl.c | 26 ++++++++++++++++++++++++++
5 files changed, 135 insertions(+)
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index c3d22be73b7c..9ffab0cf94cd 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/clk/at91_pmc.h>
#include <asm/proc-fns.h>
@@ -358,6 +359,30 @@ static void __init at91sam9260_initialize(void)
at91_gpio_init(at91sam9260_gpio, 3);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_RSTC,
+ .end = AT91SAM9260_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_BASE_SDRAMC,
+ .end = AT91SAM9260_BASE_SDRAMC + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static void __init at91sam9260_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -407,5 +432,6 @@ AT91_SOC_START(at91sam9260)
| (1 << AT91SAM9260_ID_IRQ2),
.ioremap_registers = at91sam9260_ioremap_registers,
.register_clocks = at91sam9260_register_clocks,
+ .register_devices = at91sam9260_register_devices,
.init = at91sam9260_initialize,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index fb164a5d04a9..41fa9b9a6f05 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/clk/at91_pmc.h>
#include <asm/proc-fns.h>
@@ -321,6 +322,30 @@ static void __init at91sam9261_initialize(void)
at91_gpio_init(at91sam9261_gpio, 3);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_RSTC,
+ .end = AT91SAM9261_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_BASE_SDRAMC,
+ .end = AT91SAM9261_BASE_SDRAMC + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static void __init at91sam9261_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -370,5 +395,6 @@ AT91_SOC_START(at91sam9261)
| (1 << AT91SAM9261_ID_IRQ2),
.ioremap_registers = at91sam9261_ioremap_registers,
.register_clocks = at91sam9261_register_clocks,
+ .register_devices = at91sam9261_register_devices,
.init = at91sam9261_initialize,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index f30290572293..0c6949c342dc 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/clk/at91_pmc.h>
#include <asm/proc-fns.h>
@@ -339,6 +340,30 @@ static void __init at91sam9263_initialize(void)
at91_gpio_init(at91sam9263_gpio, 5);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_RSTC,
+ .end = AT91SAM9263_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_BASE_SDRAMC0,
+ .end = AT91SAM9263_BASE_SDRAMC0 + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static void __init at91sam9263_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -387,5 +412,6 @@ AT91_SOC_START(at91sam9263)
.extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1),
.ioremap_registers = at91sam9263_ioremap_registers,
.register_clocks = at91sam9263_register_clocks,
+ .register_devices = at91sam9263_register_devices,
.init = at91sam9263_initialize,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 9d3d544ac19c..61c0bc1185e9 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/clk/at91_pmc.h>
+#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
@@ -388,6 +389,35 @@ static void __init at91sam9g45_initialize(void)
at91_gpio_init(at91sam9g45_gpio, 5);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9G45_BASE_RSTC,
+ .end = AT91SAM9G45_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9G45_BASE_DDRSDRC1,
+ .end = AT91SAM9G45_BASE_DDRSDRC1 + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = AT91SAM9G45_BASE_DDRSDRC0,
+ .end = AT91SAM9G45_BASE_DDRSDRC0 + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-g45-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static void __init at91sam9g45_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -436,5 +466,6 @@ AT91_SOC_START(at91sam9g45)
.extern_irq = (1 << AT91SAM9G45_ID_IRQ0),
.ioremap_registers = at91sam9g45_ioremap_registers,
.register_clocks = at91sam9g45_register_clocks,
+ .register_devices = at91sam9g45_register_devices,
.init = at91sam9g45_initialize,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index a79960f57e6a..417c8b6fb85e 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -10,6 +10,7 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/clk/at91_pmc.h>
#include <asm/proc-fns.h>
@@ -331,6 +332,30 @@ static void __init at91sam9rl_initialize(void)
at91_gpio_init(at91sam9rl_gpio, 4);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9RL_BASE_RSTC,
+ .end = AT91SAM9RL_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9RL_BASE_SDRAMC,
+ .end = AT91SAM9RL_BASE_SDRAMC + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static void __init at91sam9rl_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -381,5 +406,6 @@ AT91_SOC_START(at91sam9rl)
#if defined(CONFIG_OLD_CLK_AT91)
.register_clocks = at91sam9rl_register_clocks,
#endif
+ .register_devices = at91sam9rl_register_devices,
.init = at91sam9rl_initialize,
AT91_SOC_END
--
2.0.1
Make every board call the register_devices callback so that the devices
declared by the SoC are registered.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/board-afeb-9260v1.c | 2 ++
arch/arm/mach-at91/board-cam60.c | 2 ++
arch/arm/mach-at91/board-cpu9krea.c | 2 ++
arch/arm/mach-at91/board-flexibity.c | 2 ++
arch/arm/mach-at91/board-sam9-l9260.c | 2 ++
arch/arm/mach-at91/board-sam9260ek.c | 2 ++
arch/arm/mach-at91/board-sam9261ek.c | 2 ++
arch/arm/mach-at91/board-sam9263ek.c | 2 ++
arch/arm/mach-at91/board-sam9m10g45ek.c | 2 ++
arch/arm/mach-at91/board-sam9rlek.c | 2 ++
arch/arm/mach-at91/board-snapper9260.c | 2 ++
11 files changed, 22 insertions(+)
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index 597c649170aa..fc9621ccb606 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -167,6 +167,8 @@ static struct at91_cf_data afeb9260_cf_data = {
static void __init afeb9260_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index a30502c8d379..283655bd86c1 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -170,6 +170,8 @@ static void __init cam60_add_device_nand(void)
static void __init cam60_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index 2037f78c84e7..29a89032bb9a 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -322,6 +322,8 @@ static struct mci_platform_data __initdata cpu9krea_mci0_data = {
static void __init cpu9krea_board_init(void)
{
+ at91_register_devices();
+
/* NOR */
cpu9krea_add_device_nor();
/* Serial */
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
index 68f1ab6bd08f..79bd411b0cee 100644
--- a/arch/arm/mach-at91/board-flexibity.c
+++ b/arch/arm/mach-at91/board-flexibity.c
@@ -138,6 +138,8 @@ static struct gpio_led flexibity_leds[] = {
static void __init flexibity_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index d24dda67e2d3..70309404f366 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -187,6 +187,8 @@ static struct gpio_led ek_leds[] = {
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index 65dea12d685e..da9c5f1f2c49 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -307,6 +307,8 @@ static void __init ek_add_device_buttons(void) {}
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 4637432de08f..d1be10b09ab3 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -561,6 +561,8 @@ static struct gpio_led ek_leds[] = {
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index cd2726ee5add..3f613d962d9b 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -405,6 +405,8 @@ static struct at91_can_data ek_can_data = {
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index 1ea61328f30d..33a7b19f7400 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -450,6 +450,8 @@ static struct platform_device *devices[] __initdata = {
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DGBU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index b64648b4a1fc..262e3f957d9f 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -292,6 +292,8 @@ static void __init ek_add_device_buttons(void) {}
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index 1b870e6def0c..2a817b85569f 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -154,6 +154,8 @@ static void __init snapper9260_add_device_nand(void)
static void __init snapper9260_board_init(void)
{
+ at91_register_devices();
+
at91_add_device_i2c(snapper9260_i2c_devices,
ARRAY_SIZE(snapper9260_i2c_devices));
--
2.0.1
Some core devices should be registered by the SoC itself rather than by every
board using this SoC. Introduce a register_devices callback that should be
called during the init_machine in order to do that.
Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/mach-at91/generic.h | 2 ++
arch/arm/mach-at91/setup.c | 5 +++++
arch/arm/mach-at91/soc.h | 1 +
3 files changed, 8 insertions(+)
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 631fa3b8c16d..4c2c96195a50 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -37,6 +37,8 @@ extern int __init at91_aic5_of_init(struct device_node *node,
extern void __init at91_sysirq_mask_rtc(u32 rtc_base);
extern void __init at91_sysirq_mask_rtt(u32 rtt_base);
+ /* Devices */
+extern void __init at91_register_devices(void);
/* Timer */
extern void at91rm9200_ioremap_st(u32 addr);
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 3463b9e14418..771e0495bfe5 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -506,3 +506,8 @@ void __init at91_initialize(unsigned long main_clock)
pinctrl_provide_dummies();
}
+
+void __init at91_register_devices(void)
+{
+ at91_boot_soc.register_devices();
+}
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
index a1e1482c6da8..ab983f2cc7dd 100644
--- a/arch/arm/mach-at91/soc.h
+++ b/arch/arm/mach-at91/soc.h
@@ -11,6 +11,7 @@ struct at91_init_soc {
void (*map_io)(void);
void (*ioremap_registers)(void);
void (*register_clocks)(void);
+ void (*register_devices)(void);
void (*init)(void);
};
--
2.0.1
On Jul 3, 2014, at 10:14 PM, Maxime Ripard <[email protected]> wrote:
>
> Add a driver to handle the shutdown of the Atmel SoCs. This code used to be
> (and still is) in arch/arm/mach-at91. We didn't removed it yet so that we can
> convert all the boards to using this driver, before removing it entirely in a
> separate patch.
>
> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> drivers/power/reset/Kconfig | 7 ++
> drivers/power/reset/Makefile | 1 +
> drivers/power/reset/at91-poweroff.c | 156 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 164 insertions(+)
> create mode 100644 drivers/power/reset/at91-poweroff.c
>
> diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
> index b3fef01d7cbb..f9d53af50ec0 100644
> --- a/drivers/power/reset/Kconfig
> +++ b/drivers/power/reset/Kconfig
> @@ -14,6 +14,13 @@ config POWER_RESET_AS3722
> help
> This driver supports turning off board via a ams AS3722 power-off.
>
> +config POWER_RESET_AT91_POWEROFF
> + bool "Atmel AT91 poweroff driver"
> + default SOC_AT91SAM9 || SOC_SAMA5
> + help
> + This driver supports poweroff for Atmel AT91SAM9 and SAMA5
> + SoCs
> +
> config POWER_RESET_AT91_RESET
> bool "Atmel AT91 reset driver"
> default SOC_AT91SAM9 || SOC_SAMA5
> diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
> index 1599214b91d9..8bf941bac3da 100644
> --- a/drivers/power/reset/Makefile
> +++ b/drivers/power/reset/Makefile
> @@ -1,4 +1,5 @@
> obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
> +obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o
> obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
> obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
> obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
> diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c
> new file mode 100644
> index 000000000000..2f2a69e9bae3
> --- /dev/null
> +++ b/drivers/power/reset/at91-poweroff.c
> @@ -0,0 +1,156 @@
> +/*
> + * Atmel AT91 SAM9 SoCs reset code
> + *
> + * Copyright (C) 2014 Maxime Ripard
> + *
> + * Maxime Ripard <[email protected]>
> + *
As it?s mostly a copy of other people work you can not claim the copyright
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/printk.h>
> +
> +#define AT91_SHDW_CR 0x00 /* Shut Down Control Register */
> +#define AT91_SHDW_SHDW BIT(0) /* Shut Down command */
> +#define AT91_SHDW_KEY (0xa5 << 24) /* KEY Password */
> +
> +#define AT91_SHDW_MR 0x04 /* Shut Down Mode Register */
> +#define AT91_SHDW_WKMODE0 GENMASK(2, 0) /* Wake-up 0 Mode Selection */
> +#define AT91_SHDW_CPTWK0_MAX 0xf /* Maximum Counter On Wake Up 0 */
> +#define AT91_SHDW_CPTWK0 (AT91_SHDW_CPTWK0_MAX << 4) /* Counter On Wake Up 0 */
> +#define AT91_SHDW_CPTWK0_(x) ((x) << 4)
> +#define AT91_SHDW_RTTWKEN BIT(16) /* Real Time Timer Wake-up Enable */
> +#define AT91_SHDW_RTCWKEN BIT(17) /* Real Time Clock Wake-up Enable */
> +
> +#define AT91_SHDW_SR 0x08 /* Shut Down Status Register */
> +#define AT91_SHDW_WAKEUP0 BIT(0) /* Wake-up 0 Status */
> +#define AT91_SHDW_RTTWK BIT(16) /* Real-time Timer Wake-up */
> +#define AT91_SHDW_RTCWK BIT(17) /* Real-time Clock Wake-up [SAM9RL] */
> +
> +enum wakeup_type {
> + AT91_SHDW_WKMODE0_NONE = 0,
> + AT91_SHDW_WKMODE0_HIGH = 1,
> + AT91_SHDW_WKMODE0_LOW = 2,
> + AT91_SHDW_WKMODE0_ANYLEVEL = 3,
> +};
> +
> +static const char *shdwc_wakeup_modes[] = {
> + [AT91_SHDW_WKMODE0_NONE] = "none",
> + [AT91_SHDW_WKMODE0_HIGH] = "high",
> + [AT91_SHDW_WKMODE0_LOW] = "low",
> + [AT91_SHDW_WKMODE0_ANYLEVEL] = "any",
> +};
> +
> +static void __iomem *at91_shdwc_base;
> +
> +static void __init at91_wakeup_status(void)
> +{
> + u32 reg = readl(at91_shdwc_base);
> + char *reason = "unknown";
> +
> + /* Simple power-on, just bail out */
> + if (!reg)
> + return;
> +
> + if (reg & AT91_SHDW_RTTWK)
> + reason = "RTT";
> + else if (reg & AT91_SHDW_RTCWK)
> + reason = "RTC";
> +
> + pr_info("AT91: Wake-Up source: %s\n", reason);
> +}
> +
> +static void at91_poweroff(void)
> +{
> + writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, at91_shdwc_base + AT91_SHDW_CR);
> +}
> +
> +const enum wakeup_type at91_poweroff_get_wakeup_mode(struct device_node *np)
> +{
> + const char *pm;
> + int err, i;
> +
> + err = of_property_read_string(np, "atmel,wakeup-mode", &pm);
> + if (err < 0)
> + return AT91_SHDW_WKMODE0_ANYLEVEL;
> +
> + for (i = 0; i < ARRAY_SIZE(shdwc_wakeup_modes); i++)
> + if (!strcasecmp(pm, shdwc_wakeup_modes[i]))
> + return i;
> +
> + return -ENODEV;
> +}
> +
> +static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + enum wakeup_type wakeup_mode;
> + u32 mode = 0, tmp;
> +
> + wakeup_mode = at91_poweroff_get_wakeup_mode(np);
> + if (wakeup_mode < 0) {
> + dev_warn(&pdev->dev, "shdwc unknown wakeup mode\n");
> + return;
> + }
> +
> + if (!of_property_read_u32(np, "atmel,wakeup-counter", &tmp)) {
> + if (tmp > AT91_SHDW_CPTWK0_MAX) {
> + dev_warn(&pdev->dev,
> + "shdwc wakeup counter 0x%x > 0x%x reduce it to 0x%x\n",
> + tmp, AT91_SHDW_CPTWK0_MAX, AT91_SHDW_CPTWK0_MAX);
> + tmp = AT91_SHDW_CPTWK0_MAX;
> + }
> + mode |= AT91_SHDW_CPTWK0_(tmp);
> + }
> +
> + if (of_property_read_bool(np, "atmel,wakeup-rtc-timer"))
> + mode |= AT91_SHDW_RTCWKEN;
> +
> + if (of_property_read_bool(np, "atmel,wakeup-rtt-timer"))
> + mode |= AT91_SHDW_RTTWKEN;
> +
> + writel(wakeup_mode | mode, at91_shdwc_base + AT91_SHDW_MR);
> +}
> +
> +static int at91_poweroff_probe(struct platform_device *pdev)
> +{
> + struct resource *res;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(at91_shdwc_base)) {
> + dev_err(&pdev->dev, "Could not map reset controller address\n");
> + return PTR_ERR(at91_shdwc_base);
> + }
> +
> + at91_wakeup_status();
> +
> + if (pdev->dev.of_node)
> + at91_poweroff_dt_set_wakeup_mode(pdev);
> +
> + pm_power_off = at91_poweroff;
> +
> + return 0;
> +}
> +
> +static struct of_device_id at91_poweroff_of_match[] = {
> + { .compatible = "atmel,at91sam9260-shdwc", },
> + { .compatible = "atmel,at91sam9rl-shdwc", },
> + { .compatible = "atmel,at91sam9x5-shdwc", },
> + { /*sentinel*/ }
> +};
> +
> +static struct platform_driver at91_poweroff_driver = {
> + .probe = at91_poweroff_probe,
> + .driver = {
> + .name = "at91-poweroff",
> + .of_match_table = at91_poweroff_of_match,
> + },
> +};
> +module_platform_driver(at91_poweroff_driver);
> --
> 2.0.1
>
On Thu, Jul 03, 2014 at 10:31:27PM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
>
> On Jul 3, 2014, at 10:14 PM, Maxime Ripard <[email protected]> wrote:
>
> >
> > Add a driver to handle the shutdown of the Atmel SoCs. This code used to be
> > (and still is) in arch/arm/mach-at91. We didn't removed it yet so that we can
> > convert all the boards to using this driver, before removing it entirely in a
> > separate patch.
> >
> > Signed-off-by: Maxime Ripard <[email protected]>
> > ---
> > drivers/power/reset/Kconfig | 7 ++
> > drivers/power/reset/Makefile | 1 +
> > drivers/power/reset/at91-poweroff.c | 156 ++++++++++++++++++++++++++++++++++++
> > 3 files changed, 164 insertions(+)
> > create mode 100644 drivers/power/reset/at91-poweroff.c
> >
> > diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
> > index b3fef01d7cbb..f9d53af50ec0 100644
> > --- a/drivers/power/reset/Kconfig
> > +++ b/drivers/power/reset/Kconfig
> > @@ -14,6 +14,13 @@ config POWER_RESET_AS3722
> > help
> > This driver supports turning off board via a ams AS3722 power-off.
> >
> > +config POWER_RESET_AT91_POWEROFF
> > + bool "Atmel AT91 poweroff driver"
> > + default SOC_AT91SAM9 || SOC_SAMA5
> > + help
> > + This driver supports poweroff for Atmel AT91SAM9 and SAMA5
> > + SoCs
> > +
> > config POWER_RESET_AT91_RESET
> > bool "Atmel AT91 reset driver"
> > default SOC_AT91SAM9 || SOC_SAMA5
> > diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
> > index 1599214b91d9..8bf941bac3da 100644
> > --- a/drivers/power/reset/Makefile
> > +++ b/drivers/power/reset/Makefile
> > @@ -1,4 +1,5 @@
> > obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
> > +obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o
> > obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
> > obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
> > obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
> > diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c
> > new file mode 100644
> > index 000000000000..2f2a69e9bae3
> > --- /dev/null
> > +++ b/drivers/power/reset/at91-poweroff.c
> > @@ -0,0 +1,156 @@
> > +/*
> > + * Atmel AT91 SAM9 SoCs reset code
> > + *
> > + * Copyright (C) 2014 Maxime Ripard
> > + *
> > + * Maxime Ripard <[email protected]>
> > + *
>
> As it’s mostly a copy of other people work you can not claim the copyright
Yep. It was a wrongful copy and paste on my side.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Thu, Jul 03, 2014 at 10:34:17PM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
> patch 4 and 18 what is the difference?
There's none, I just messed up at sending the patches. The resend
should be on its way.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
Hi,
On Thu, Jul 03, 2014 at 10:29:58PM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
> no do this at SoC level
Since it has to be done at init_machine, I don't see any other easy
way to do this at the SoC level.
What is your suggestion?
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
NACK
On Jul 3, 2014, at 10:14 PM, Maxime Ripard <[email protected]> wrote:
>
> Implement the reset behaviour of the various AT91 SoCS in drivers/power/reset.
>
> It used to be (and still is) located in arch/arm/mach-at91, and in order to
> preserve bisectability is not removed yet, but every board should be converted
> to use this driver instead.
>
> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> drivers/power/reset/Kconfig | 7 ++
> drivers/power/reset/Makefile | 1 +
> drivers/power/reset/at91-reset.c | 202 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 210 insertions(+)
> create mode 100644 drivers/power/reset/at91-reset.c
>
> diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
> index 19d546c5edfa..b3fef01d7cbb 100644
> --- a/drivers/power/reset/Kconfig
> +++ b/drivers/power/reset/Kconfig
> @@ -14,6 +14,13 @@ config POWER_RESET_AS3722
> help
> This driver supports turning off board via a ams AS3722 power-off.
>
> +config POWER_RESET_AT91_RESET
> + bool "Atmel AT91 reset driver"
> + default SOC_AT91SAM9 || SOC_SAMA5
> + help
> + This driver supports restart for Atmel AT91SAM9 and SAMA5
> + SoCs
> +
> config POWER_RESET_AXXIA
> bool "LSI Axxia reset driver"
> depends on ARCH_AXXIA
> diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
> index dde2e8bbac53..1599214b91d9 100644
> --- a/drivers/power/reset/Makefile
> +++ b/drivers/power/reset/Makefile
> @@ -1,4 +1,5 @@
> obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
> +obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
> obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
> obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
> obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
> diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c
> new file mode 100644
> index 000000000000..878547410acb
> --- /dev/null
> +++ b/drivers/power/reset/at91-reset.c
> @@ -0,0 +1,202 @@
> +/*
> + * Atmel AT91 SAM9 SoCs reset code
> + *
> + * Copyright (C) 2014 Maxime Ripard
> + *
> + * Maxime Ripard <[email protected]>
you can not own the copyright as it?s basically a copy of other people code
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/reboot.h>
> +
> +#include <asm/system_misc.h>
> +
> +#include <mach/at91sam9_ddrsdr.h>
> +#include <mach/at91sam9_sdramc.h>
> +
> +#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
> +#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
> +#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
> +#define AT91_RSTC_EXTRST BIT(3) /* External Reset */
> +#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
> +
> +#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
> +#define AT91_RSTC_URSTS BIT(0) /* User Reset Status */
> +#define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */
> +#define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */
> +#define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */
> +
> +#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
> +#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
> +#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
> +#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
> +
> +enum reset_type {
> + RESET_TYPE_GENERAL = 0,
> + RESET_TYPE_WAKEUP = 1,
> + RESET_TYPE_WATCHDOG = 2,
> + RESET_TYPE_SOFTWARE = 3,
> + RESET_TYPE_USER = 4,
> +};
> +
> +static void __iomem *at91_ramc_base[2], *at91_rstc_base;
> +
> +static void at91sam9_restart(enum reboot_mode mode, const char *cmd)
> +{
> + asm volatile(
> + ".balign 32\n\t"
> +
> + "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
> + "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
> + "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
> +
> + "b .\n\t"
> + :
> + : "r" (at91_ramc_base[0]),
> + "r" (at91_rstc_base),
> + "r" (1),
> + "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
> +}
> +
> +static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
> +{
> + asm volatile(
> + "cmp %1, #0\n\t"
> + "beq 1f\n\t"
> +
> + "ldr r0, [%1]\n\t"
> + "cmp r0, #0\n\t"
> +
> + ".balign 32\n\t"
> +
> + "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> + " str %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> + " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> + " strne %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> + " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
> +
> + " b .\n\t"
> + :
> + : "r" (at91_ramc_base[0]),
> + "r" (at91_ramc_base[1]),
> + "r" (at91_rstc_base),
> + "r" (1),
> + "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
> + : "r0");
> +}
> +
move this to an assembly file more easy to read than a C code
> +static void __init at91_reset_status(struct platform_device *pdev)
> +{
> + u32 reg = readl(at91_rstc_base + AT91_RSTC_SR);
> + char *reason;
> +
> + switch ((reg & AT91_RSTC_RSTTYP) >> 8) {
> + case RESET_TYPE_GENERAL:
> + reason = "general reset";
> + break;
> + case RESET_TYPE_WAKEUP:
> + reason = "wakeup";
> + break;
> + case RESET_TYPE_WATCHDOG:
> + reason = "watchdog reset";
> + break;
> + case RESET_TYPE_SOFTWARE:
> + reason = "software reset";
> + break;
> + case RESET_TYPE_USER:
> + reason = "user reset";
> + break;
> + default:
> + reason = "unknown reset";
> + break;
> + }
> +
> + pr_info("AT91: Starting after %s\n", reason);
> +}
> +
> +static struct of_device_id at91_ramc_of_match[] = {
> + { .compatible = "atmel,at91sam9260-sdramc", },
> + { .compatible = "atmel,at91sam9g45-ddramc", },
> + { /* sentinel */ }
> +};
> +
> +static struct of_device_id at91_reset_of_match[] = {
> + { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_restart },
> + { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
> + { /* sentinel */ }
> +};
> +
> +static int at91_reset_probe(struct platform_device *pdev)
> +{
> + struct resource *res;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + at91_rstc_base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(at91_rstc_base)) {
> + dev_err(&pdev->dev, "Could not map reset controller address\n");
> + return PTR_ERR(at91_rstc_base);
> + }
> +
> + if (pdev->dev.of_node) {
split in 2 function more easy to ready and less indentation
> + const struct of_device_id *match;
> + struct device_node *np;
> + int idx = 0;
> +
> + for_each_matching_node(np, at91_ramc_of_match) {
> + at91_ramc_base[idx] = of_iomap(np, 0);
> + if (!at91_ramc_base[idx]) {
> + dev_err(&pdev->dev, "Could not map ram controller address\n");
> + return -ENODEV;
> + }
> + idx++;
> + }
and if you can not probe the ram controler it?s a panic not a -ENODEV
as you have an unstable platform
> +
> + match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
> + arm_pm_restart = match->data;
> + } else {
> + const struct platform_device_id *match;
> + int idx = 0;
> +
> + for (idx = 0; idx < 2; idx++) {
> + res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1 );
> + at91_ramc_base[idx] = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(at91_ramc_base[idx])) {
> + dev_err(&pdev->dev, "Could not map ram controller address\n");
> + return PTR_ERR(at91_rstc_base);
> + }
> + }
> +
> + match = platform_get_device_id(pdev);
> + arm_pm_restart = (void (*)(enum reboot_mode, const char*))
> + match->driver_data;
> + }
> +
> + at91_reset_status(pdev);
> +
> + return 0;
> +}
> +
> +static struct platform_device_id at91_reset_plat_match[] = {
> + { "at91-sam9-reset", (unsigned long)at91sam9_restart },
> + { "at91-g45-reset", (unsigned long)at91sam9g45_restart },
at91-sam9???
from the beginning of DT we put the first SoC were the reset was introduce and why do you change the DT binding?
> + { /* sentinel */ }
> +};
> +
> +static struct platform_driver at91_reset_driver = {
> + .probe = at91_reset_probe,
> + .driver = {
> + .name = "at91-reset",
> + .of_match_table = at91_reset_of_match,
> + },
> + .id_table = at91_reset_plat_match,
> +};
> +module_platform_driver(at91_reset_driver);
> --
> 2.0.1
>
On Thu, Jul 03, 2014 at 10:39:08PM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > +++ b/drivers/power/reset/at91-reset.c
> > @@ -0,0 +1,202 @@
> > +/*
> > + * Atmel AT91 SAM9 SoCs reset code
> > + *
> > + * Copyright (C) 2014 Maxime Ripard
> > + *
> > + * Maxime Ripard <[email protected]>
>
> you can not own the copyright as it’s basically a copy of other
> people code
The previous names are missing, right.
> > + *
> > + * This file is licensed under the terms of the GNU General Public
> > + * License version 2. This program is licensed "as is" without any
> > + * warranty of any kind, whether express or implied.
> > + */
> > +
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/of_address.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/reboot.h>
> > +
> > +#include <asm/system_misc.h>
> > +
> > +#include <mach/at91sam9_ddrsdr.h>
> > +#include <mach/at91sam9_sdramc.h>
> > +
> > +#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
> > +#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
> > +#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
> > +#define AT91_RSTC_EXTRST BIT(3) /* External Reset */
> > +#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
> > +
> > +#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
> > +#define AT91_RSTC_URSTS BIT(0) /* User Reset Status */
> > +#define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */
> > +#define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */
> > +#define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */
> > +
> > +#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
> > +#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
> > +#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
> > +#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
> > +
> > +enum reset_type {
> > + RESET_TYPE_GENERAL = 0,
> > + RESET_TYPE_WAKEUP = 1,
> > + RESET_TYPE_WATCHDOG = 2,
> > + RESET_TYPE_SOFTWARE = 3,
> > + RESET_TYPE_USER = 4,
> > +};
> > +
> > +static void __iomem *at91_ramc_base[2], *at91_rstc_base;
> > +
> > +static void at91sam9_restart(enum reboot_mode mode, const char *cmd)
> > +{
> > + asm volatile(
> > + ".balign 32\n\t"
> > +
> > + "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
> > + "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
> > + "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
> > +
> > + "b .\n\t"
> > + :
> > + : "r" (at91_ramc_base[0]),
> > + "r" (at91_rstc_base),
> > + "r" (1),
> > + "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
> > + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
> > +}
> > +
> > +static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
> > +{
> > + asm volatile(
> > + "cmp %1, #0\n\t"
> > + "beq 1f\n\t"
> > +
> > + "ldr r0, [%1]\n\t"
> > + "cmp r0, #0\n\t"
> > +
> > + ".balign 32\n\t"
> > +
> > + "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> > + " str %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> > + " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> > + " strne %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> > + " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
> > +
> > + " b .\n\t"
> > + :
> > + : "r" (at91_ramc_base[0]),
> > + "r" (at91_ramc_base[1]),
> > + "r" (at91_rstc_base),
> > + "r" (1),
> > + "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
> > + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
> > + : "r0");
> > +}
> > +
> move this to an assembly file more easy to read than a C code
Nope. It's a pain to pass variable to an external assembly file, and
this makes the use of global variable pretty much mandatory, which is
definitely not great.
>
> > +static void __init at91_reset_status(struct platform_device *pdev)
> > +{
> > + u32 reg = readl(at91_rstc_base + AT91_RSTC_SR);
> > + char *reason;
> > +
> > + switch ((reg & AT91_RSTC_RSTTYP) >> 8) {
> > + case RESET_TYPE_GENERAL:
> > + reason = "general reset";
> > + break;
> > + case RESET_TYPE_WAKEUP:
> > + reason = "wakeup";
> > + break;
> > + case RESET_TYPE_WATCHDOG:
> > + reason = "watchdog reset";
> > + break;
> > + case RESET_TYPE_SOFTWARE:
> > + reason = "software reset";
> > + break;
> > + case RESET_TYPE_USER:
> > + reason = "user reset";
> > + break;
> > + default:
> > + reason = "unknown reset";
> > + break;
> > + }
> > +
> > + pr_info("AT91: Starting after %s\n", reason);
> > +}
> > +
> > +static struct of_device_id at91_ramc_of_match[] = {
> > + { .compatible = "atmel,at91sam9260-sdramc", },
> > + { .compatible = "atmel,at91sam9g45-ddramc", },
> > + { /* sentinel */ }
> > +};
> > +
> > +static struct of_device_id at91_reset_of_match[] = {
> > + { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_restart },
> > + { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
> > + { /* sentinel */ }
> > +};
> > +
> > +static int at91_reset_probe(struct platform_device *pdev)
> > +{
> > + struct resource *res;
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + at91_rstc_base = devm_ioremap_resource(&pdev->dev, res);
> > + if (IS_ERR(at91_rstc_base)) {
> > + dev_err(&pdev->dev, "Could not map reset controller address\n");
> > + return PTR_ERR(at91_rstc_base);
> > + }
> > +
> > + if (pdev->dev.of_node) {
>
> split in 2 function more easy to ready and less indentation
ok.
> > + const struct of_device_id *match;
> > + struct device_node *np;
> > + int idx = 0;
> > +
> > + for_each_matching_node(np, at91_ramc_of_match) {
> > + at91_ramc_base[idx] = of_iomap(np, 0);
> > + if (!at91_ramc_base[idx]) {
> > + dev_err(&pdev->dev, "Could not map ram controller address\n");
> > + return -ENODEV;
> > + }
> > + idx++;
> > + }
>
> and if you can not probe the ram controler it’s a panic not a -ENODEV
>
> as you have an unstable platform
I don't really see why. That the pm code and the reset code won't be
able to work, it's obvious. But making the assumption that the
platforms don't have a RAM properly setup just because it doesn't have
a DT node seems quite weak.
> > +
> > + match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
> > + arm_pm_restart = match->data;
> > + } else {
> > + const struct platform_device_id *match;
> > + int idx = 0;
> > +
> > + for (idx = 0; idx < 2; idx++) {
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1 );
> > + at91_ramc_base[idx] = devm_ioremap_resource(&pdev->dev, res);
> > + if (IS_ERR(at91_ramc_base[idx])) {
> > + dev_err(&pdev->dev, "Could not map ram controller address\n");
> > + return PTR_ERR(at91_rstc_base);
> > + }
> > + }
> > +
> > + match = platform_get_device_id(pdev);
> > + arm_pm_restart = (void (*)(enum reboot_mode, const char*))
> > + match->driver_data;
> > + }
> > +
> > + at91_reset_status(pdev);
> > +
> > + return 0;
> > +}
> > +
> > +static struct platform_device_id at91_reset_plat_match[] = {
> > + { "at91-sam9-reset", (unsigned long)at91sam9_restart },
> > + { "at91-g45-reset", (unsigned long)at91sam9g45_restart },
> at91-sam9???
>
> from the beginning of DT we put the first SoC were the
> reset was introduce and why do you change the DT binding?
Except that this is not about DT probing, but the old-style board
files one.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
patch 4 and 18 what is the difference?
Best Regards,
J.
On Jul 3, 2014, at 10:14 PM, Maxime Ripard <[email protected]> wrote:
>
> Adapt the ramc mapping code to handle multiple ram controllers in the DT.
>
> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> arch/arm/mach-at91/setup.c | 26 ++++++++++++++------------
> 1 file changed, 14 insertions(+), 12 deletions(-)
>
> diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
> index 9c4c7fb323fb..cc520596f23b 100644
> --- a/arch/arm/mach-at91/setup.c
> +++ b/arch/arm/mach-at91/setup.c
> @@ -393,24 +393,26 @@ static void at91_dt_ramc(void)
> {
> struct device_node *np;
> const struct of_device_id *of_id;
> + int idx = 0;
>
> - np = of_find_matching_node(NULL, ramc_ids);
> - if (!np)
> - panic(pr_fmt("unable to find compatible ram controller node in dtb\n"));
> + for_each_matching_node(np, ramc_ids) {
> + at91_ramc_base[idx] = of_iomap(np, 0);
> + if (!at91_ramc_base[idx])
> + panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx);
>
> - at91_ramc_base[0] = of_iomap(np, 0);
> - if (!at91_ramc_base[0])
> - panic(pr_fmt("unable to map ramc[0] cpu registers\n"));
> - /* the controller may have 2 banks */
> - at91_ramc_base[1] = of_iomap(np, 1);
> + idx++;
> + }
> +
> + if (!idx)
> + panic(pr_fmt("unable to find compatible ram controller node in dtb\n"));
>
> of_id = of_match_node(ramc_ids, np);
> - if (!of_id)
> + if (!of_id) {
> pr_warn("ramc no standby function available\n");
> - else
> - at91_pm_set_standby(of_id->data);
> + return;
> + }
>
> - of_node_put(np);
> + at91_pm_set_standby(of_id->data);
> }
>
> static struct of_device_id shdwc_ids[] = {
> --
> 2.0.1
>
no do this at SoC level
Best Regards,
J.
On Jul 3, 2014, at 10:14 PM, Maxime Ripard <[email protected]> wrote:
>
> Make every board call the register_devices callback so that the devices
> declared by the SoC are registered.
>
> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> arch/arm/mach-at91/board-afeb-9260v1.c | 2 ++
> arch/arm/mach-at91/board-cam60.c | 2 ++
> arch/arm/mach-at91/board-cpu9krea.c | 2 ++
> arch/arm/mach-at91/board-flexibity.c | 2 ++
> arch/arm/mach-at91/board-sam9-l9260.c | 2 ++
> arch/arm/mach-at91/board-sam9260ek.c | 2 ++
> arch/arm/mach-at91/board-sam9261ek.c | 2 ++
> arch/arm/mach-at91/board-sam9263ek.c | 2 ++
> arch/arm/mach-at91/board-sam9m10g45ek.c | 2 ++
> arch/arm/mach-at91/board-sam9rlek.c | 2 ++
> arch/arm/mach-at91/board-snapper9260.c | 2 ++
> 11 files changed, 22 insertions(+)
>
> diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
> index 597c649170aa..fc9621ccb606 100644
> --- a/arch/arm/mach-at91/board-afeb-9260v1.c
> +++ b/arch/arm/mach-at91/board-afeb-9260v1.c
> @@ -167,6 +167,8 @@ static struct at91_cf_data afeb9260_cf_data = {
>
> static void __init afeb9260_board_init(void)
> {
> + at91_register_devices();
> +
> /* Serial */
> /* DBGU on ttyS0. (Rx & Tx only) */
> at91_register_uart(0, 0, 0);
> diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
> index a30502c8d379..283655bd86c1 100644
> --- a/arch/arm/mach-at91/board-cam60.c
> +++ b/arch/arm/mach-at91/board-cam60.c
> @@ -170,6 +170,8 @@ static void __init cam60_add_device_nand(void)
>
> static void __init cam60_board_init(void)
> {
> + at91_register_devices();
> +
> /* Serial */
> /* DBGU on ttyS0. (Rx & Tx only) */
> at91_register_uart(0, 0, 0);
> diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
> index 2037f78c84e7..29a89032bb9a 100644
> --- a/arch/arm/mach-at91/board-cpu9krea.c
> +++ b/arch/arm/mach-at91/board-cpu9krea.c
> @@ -322,6 +322,8 @@ static struct mci_platform_data __initdata cpu9krea_mci0_data = {
>
> static void __init cpu9krea_board_init(void)
> {
> + at91_register_devices();
> +
> /* NOR */
> cpu9krea_add_device_nor();
> /* Serial */
> diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
> index 68f1ab6bd08f..79bd411b0cee 100644
> --- a/arch/arm/mach-at91/board-flexibity.c
> +++ b/arch/arm/mach-at91/board-flexibity.c
> @@ -138,6 +138,8 @@ static struct gpio_led flexibity_leds[] = {
>
> static void __init flexibity_board_init(void)
> {
> + at91_register_devices();
> +
> /* Serial */
> /* DBGU on ttyS0. (Rx & Tx only) */
> at91_register_uart(0, 0, 0);
> diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
> index d24dda67e2d3..70309404f366 100644
> --- a/arch/arm/mach-at91/board-sam9-l9260.c
> +++ b/arch/arm/mach-at91/board-sam9-l9260.c
> @@ -187,6 +187,8 @@ static struct gpio_led ek_leds[] = {
>
> static void __init ek_board_init(void)
> {
> + at91_register_devices();
> +
> /* Serial */
> /* DBGU on ttyS0. (Rx & Tx only) */
> at91_register_uart(0, 0, 0);
> diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
> index 65dea12d685e..da9c5f1f2c49 100644
> --- a/arch/arm/mach-at91/board-sam9260ek.c
> +++ b/arch/arm/mach-at91/board-sam9260ek.c
> @@ -307,6 +307,8 @@ static void __init ek_add_device_buttons(void) {}
>
> static void __init ek_board_init(void)
> {
> + at91_register_devices();
> +
> /* Serial */
> /* DBGU on ttyS0. (Rx & Tx only) */
> at91_register_uart(0, 0, 0);
> diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
> index 4637432de08f..d1be10b09ab3 100644
> --- a/arch/arm/mach-at91/board-sam9261ek.c
> +++ b/arch/arm/mach-at91/board-sam9261ek.c
> @@ -561,6 +561,8 @@ static struct gpio_led ek_leds[] = {
>
> static void __init ek_board_init(void)
> {
> + at91_register_devices();
> +
> /* Serial */
> /* DBGU on ttyS0. (Rx & Tx only) */
> at91_register_uart(0, 0, 0);
> diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
> index cd2726ee5add..3f613d962d9b 100644
> --- a/arch/arm/mach-at91/board-sam9263ek.c
> +++ b/arch/arm/mach-at91/board-sam9263ek.c
> @@ -405,6 +405,8 @@ static struct at91_can_data ek_can_data = {
>
> static void __init ek_board_init(void)
> {
> + at91_register_devices();
> +
> /* Serial */
> /* DBGU on ttyS0. (Rx & Tx only) */
> at91_register_uart(0, 0, 0);
> diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
> index 1ea61328f30d..33a7b19f7400 100644
> --- a/arch/arm/mach-at91/board-sam9m10g45ek.c
> +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
> @@ -450,6 +450,8 @@ static struct platform_device *devices[] __initdata = {
>
> static void __init ek_board_init(void)
> {
> + at91_register_devices();
> +
> /* Serial */
> /* DGBU on ttyS0. (Rx & Tx only) */
> at91_register_uart(0, 0, 0);
> diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
> index b64648b4a1fc..262e3f957d9f 100644
> --- a/arch/arm/mach-at91/board-sam9rlek.c
> +++ b/arch/arm/mach-at91/board-sam9rlek.c
> @@ -292,6 +292,8 @@ static void __init ek_add_device_buttons(void) {}
>
> static void __init ek_board_init(void)
> {
> + at91_register_devices();
> +
> /* Serial */
> /* DBGU on ttyS0. (Rx & Tx only) */
> at91_register_uart(0, 0, 0);
> diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
> index 1b870e6def0c..2a817b85569f 100644
> --- a/arch/arm/mach-at91/board-snapper9260.c
> +++ b/arch/arm/mach-at91/board-snapper9260.c
> @@ -154,6 +154,8 @@ static void __init snapper9260_add_device_nand(void)
>
> static void __init snapper9260_board_init(void)
> {
> + at91_register_devices();
> +
> at91_add_device_i2c(snapper9260_i2c_devices,
> ARRAY_SIZE(snapper9260_i2c_devices));
>
> --
> 2.0.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Jul 3, 2014, at 10:59 PM, Maxime Ripard <[email protected]> wrote:
> On Thu, Jul 03, 2014 at 10:39:08PM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
>>> +++ b/drivers/power/reset/at91-reset.c
>>> @@ -0,0 +1,202 @@
>>> +/*
>>> + * Atmel AT91 SAM9 SoCs reset code
>>> + *
>>> + * Copyright (C) 2014 Maxime Ripard
>>> + *
>>> + * Maxime Ripard <[email protected]>
>>
>> you can not own the copyright as it?s basically a copy of other
>> people code
>
> The previous names are missing, right.
>
>>> + *
>>> + * This file is licensed under the terms of the GNU General Public
>>> + * License version 2. This program is licensed "as is" without any
>>> + * warranty of any kind, whether express or implied.
>>> + */
>>> +
>>> +#include <linux/io.h>
>>> +#include <linux/module.h>
>>> +#include <linux/of_address.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/reboot.h>
>>> +
>>> +#include <asm/system_misc.h>
>>> +
>>> +#include <mach/at91sam9_ddrsdr.h>
>>> +#include <mach/at91sam9_sdramc.h>
>>> +
>>> +#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
>>> +#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
>>> +#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
>>> +#define AT91_RSTC_EXTRST BIT(3) /* External Reset */
>>> +#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
>>> +
>>> +#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
>>> +#define AT91_RSTC_URSTS BIT(0) /* User Reset Status */
>>> +#define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */
>>> +#define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */
>>> +#define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */
>>> +
>>> +#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
>>> +#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
>>> +#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
>>> +#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
>>> +
>>> +enum reset_type {
>>> + RESET_TYPE_GENERAL = 0,
>>> + RESET_TYPE_WAKEUP = 1,
>>> + RESET_TYPE_WATCHDOG = 2,
>>> + RESET_TYPE_SOFTWARE = 3,
>>> + RESET_TYPE_USER = 4,
>>> +};
>>> +
>>> +static void __iomem *at91_ramc_base[2], *at91_rstc_base;
>>> +
>>> +static void at91sam9_restart(enum reboot_mode mode, const char *cmd)
>>> +{
>>> + asm volatile(
>>> + ".balign 32\n\t"
>>> +
>>> + "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
>>> + "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
>>> + "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
>>> +
>>> + "b .\n\t"
>>> + :
>>> + : "r" (at91_ramc_base[0]),
>>> + "r" (at91_rstc_base),
>>> + "r" (1),
>>> + "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
>>> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
>>> +}
>>> +
>>> +static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
>>> +{
>>> + asm volatile(
>>> + "cmp %1, #0\n\t"
>>> + "beq 1f\n\t"
>>> +
>>> + "ldr r0, [%1]\n\t"
>>> + "cmp r0, #0\n\t"
>>> +
>>> + ".balign 32\n\t"
>>> +
>>> + "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
>>> + " str %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
>>> + " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
>>> + " strne %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
>>> + " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
>>> +
>>> + " b .\n\t"
>>> + :
>>> + : "r" (at91_ramc_base[0]),
>>> + "r" (at91_ramc_base[1]),
>>> + "r" (at91_rstc_base),
>>> + "r" (1),
>>> + "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
>>> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
>>> + : "r0");
>>> +}
>>> +
>> move this to an assembly file more easy to read than a C code
>
> Nope. It's a pain to pass variable to an external assembly file, and
> this makes the use of global variable pretty much mandatory, which is
> definitely not great.
Not at all I did for the PM slow clock code just write a function and pas it as a parameter
you have 3
so basically you have to use the current and just pass at91_ramc_base[0], at91_ramc_base[1]
and at91_rstc_base
it?s 3 lignes of modification, if you have at91_ramc_base and at91_ramc_base same
so NACK
>
>>
>>> +static void __init at91_reset_status(struct platform_device *pdev)
>>> +{
>>> + u32 reg = readl(at91_rstc_base + AT91_RSTC_SR);
>>> + char *reason;
>>> +
>>> + switch ((reg & AT91_RSTC_RSTTYP) >> 8) {
>>> + case RESET_TYPE_GENERAL:
>>> + reason = "general reset";
>>> + break;
>>> + case RESET_TYPE_WAKEUP:
>>> + reason = "wakeup";
>>> + break;
>>> + case RESET_TYPE_WATCHDOG:
>>> + reason = "watchdog reset";
>>> + break;
>>> + case RESET_TYPE_SOFTWARE:
>>> + reason = "software reset";
>>> + break;
>>> + case RESET_TYPE_USER:
>>> + reason = "user reset";
>>> + break;
>>> + default:
>>> + reason = "unknown reset";
>>> + break;
>>> + }
>>> +
>>> + pr_info("AT91: Starting after %s\n", reason);
>>> +}
>>> +
>>> +static struct of_device_id at91_ramc_of_match[] = {
>>> + { .compatible = "atmel,at91sam9260-sdramc", },
>>> + { .compatible = "atmel,at91sam9g45-ddramc", },
>>> + { /* sentinel */ }
>>> +};
>>> +
>>> +static struct of_device_id at91_reset_of_match[] = {
>>> + { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_restart },
>>> + { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
>>> + { /* sentinel */ }
>>> +};
>>> +
>>> +static int at91_reset_probe(struct platform_device *pdev)
>>> +{
>>> + struct resource *res;
>>> +
>>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> + at91_rstc_base = devm_ioremap_resource(&pdev->dev, res);
>>> + if (IS_ERR(at91_rstc_base)) {
>>> + dev_err(&pdev->dev, "Could not map reset controller address\n");
>>> + return PTR_ERR(at91_rstc_base);
>>> + }
>>> +
>>> + if (pdev->dev.of_node) {
>>
>> split in 2 function more easy to ready and less indentation
>
> ok.
>
>>> + const struct of_device_id *match;
>>> + struct device_node *np;
>>> + int idx = 0;
>>> +
>>> + for_each_matching_node(np, at91_ramc_of_match) {
>>> + at91_ramc_base[idx] = of_iomap(np, 0);
>>> + if (!at91_ramc_base[idx]) {
>>> + dev_err(&pdev->dev, "Could not map ram controller address\n");
>>> + return -ENODEV;
>>> + }
>>> + idx++;
>>> + }
>>
>> and if you can not probe the ram controler it?s a panic not a -ENODEV
>>
>> as you have an unstable platform
>
> I don't really see why. That the pm code and the reset code won't be
> able to work, it's obvious. But making the assumption that the
> platforms don't have a RAM properly setup just because it doesn't have
> a DT node seems quite weak.
no as if you do not have the RAMC your reset will cause hardware issue as there is a bug
in the SoC so yes mandatory as 95% of the people will not known why there board will suddenly
do not reboot. As this specific reset in assembly was write to run from cache to fix a SoC bug
in the reset controller
>
>>> +
>>> + match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
>>> + arm_pm_restart = match->data;
>>> + } else {
>>> + const struct platform_device_id *match;
>>> + int idx = 0;
>>> +
>>> + for (idx = 0; idx < 2; idx++) {
>>> + res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1 );
>>> + at91_ramc_base[idx] = devm_ioremap_resource(&pdev->dev, res);
>>> + if (IS_ERR(at91_ramc_base[idx])) {
>>> + dev_err(&pdev->dev, "Could not map ram controller address\n");
>>> + return PTR_ERR(at91_rstc_base);
>>> + }
>>> + }
>>> +
>>> + match = platform_get_device_id(pdev);
>>> + arm_pm_restart = (void (*)(enum reboot_mode, const char*))
>>> + match->driver_data;
>>> + }
>>> +
>>> + at91_reset_status(pdev);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static struct platform_device_id at91_reset_plat_match[] = {
>>> + { "at91-sam9-reset", (unsigned long)at91sam9_restart },
>>> + { "at91-g45-reset", (unsigned long)at91sam9g45_restart },
>> at91-sam9???
>>
>> from the beginning of DT we put the first SoC were the
>> reset was introduce and why do you change the DT binding?
>
> Except that this is not about DT probing, but the old-style board
> files one.
>
except that in al the other driver such as FBDEV we use the same principle for platform_device
Best Regards,
J.
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Jul 3, 2014, at 10:59 PM, Maxime Ripard <[email protected]> wrote:
> On Thu, Jul 03, 2014 at 10:39:08PM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
>>> +++ b/drivers/power/reset/at91-reset.c
>>> @@ -0,0 +1,202 @@
>>> +/*
>>> + * Atmel AT91 SAM9 SoCs reset code
>>> + *
>>> + * Copyright (C) 2014 Maxime Ripard
>>> + *
>>> + * Maxime Ripard <[email protected]>
>>
>> you can not own the copyright as it?s basically a copy of other
>> people code
>
> The previous names are missing, right.
>
>>> + *
>>> + * This file is licensed under the terms of the GNU General Public
>>> + * License version 2. This program is licensed "as is" without any
>>> + * warranty of any kind, whether express or implied.
>>> + */
>>> +
>>> +#include <linux/io.h>
>>> +#include <linux/module.h>
>>> +#include <linux/of_address.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/reboot.h>
>>> +
>>> +#include <asm/system_misc.h>
>>> +
>>> +#include <mach/at91sam9_ddrsdr.h>
>>> +#include <mach/at91sam9_sdramc.h>
>>> +
>>> +#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
>>> +#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
>>> +#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
>>> +#define AT91_RSTC_EXTRST BIT(3) /* External Reset */
>>> +#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
>>> +
>>> +#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
>>> +#define AT91_RSTC_URSTS BIT(0) /* User Reset Status */
>>> +#define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */
>>> +#define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */
>>> +#define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */
>>> +
>>> +#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
>>> +#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
>>> +#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
>>> +#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
>>> +
>>> +enum reset_type {
>>> + RESET_TYPE_GENERAL = 0,
>>> + RESET_TYPE_WAKEUP = 1,
>>> + RESET_TYPE_WATCHDOG = 2,
>>> + RESET_TYPE_SOFTWARE = 3,
>>> + RESET_TYPE_USER = 4,
>>> +};
>>> +
>>> +static void __iomem *at91_ramc_base[2], *at91_rstc_base;
>>> +
>>> +static void at91sam9_restart(enum reboot_mode mode, const char *cmd)
>>> +{
>>> + asm volatile(
>>> + ".balign 32\n\t"
>>> +
>>> + "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
>>> + "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
>>> + "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
>>> +
>>> + "b .\n\t"
>>> + :
>>> + : "r" (at91_ramc_base[0]),
>>> + "r" (at91_rstc_base),
>>> + "r" (1),
>>> + "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
>>> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
>>> +}
>>> +
>>> +static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
>>> +{
>>> + asm volatile(
>>> + "cmp %1, #0\n\t"
>>> + "beq 1f\n\t"
>>> +
>>> + "ldr r0, [%1]\n\t"
>>> + "cmp r0, #0\n\t"
>>> +
>>> + ".balign 32\n\t"
>>> +
>>> + "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
>>> + " str %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
>>> + " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
>>> + " strne %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
>>> + " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
>>> +
>>> + " b .\n\t"
>>> + :
>>> + : "r" (at91_ramc_base[0]),
>>> + "r" (at91_ramc_base[1]),
>>> + "r" (at91_rstc_base),
>>> + "r" (1),
>>> + "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
>>> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
>>> + : "r0");
>>> +}
>>> +
>> move this to an assembly file more easy to read than a C code
>
> Nope. It's a pain to pass variable to an external assembly file, and
> this makes the use of global variable pretty much mandatory, which is
> definitely not great.
Not at all I did for the PM slow clock code just write a function and pas it as a parameter
you have 3
so basically you have to use the current and just pass at91_ramc_base[0], at91_ramc_base[1]
and at91_rstc_base
it?s 3 lignes of modification, if you have at91_ramc_base and at91_ramc_base same
so NACK
>
>>
>>> +static void __init at91_reset_status(struct platform_device *pdev)
>>> +{
>>> + u32 reg = readl(at91_rstc_base + AT91_RSTC_SR);
>>> + char *reason;
>>> +
>>> + switch ((reg & AT91_RSTC_RSTTYP) >> 8) {
>>> + case RESET_TYPE_GENERAL:
>>> + reason = "general reset";
>>> + break;
>>> + case RESET_TYPE_WAKEUP:
>>> + reason = "wakeup";
>>> + break;
>>> + case RESET_TYPE_WATCHDOG:
>>> + reason = "watchdog reset";
>>> + break;
>>> + case RESET_TYPE_SOFTWARE:
>>> + reason = "software reset";
>>> + break;
>>> + case RESET_TYPE_USER:
>>> + reason = "user reset";
>>> + break;
>>> + default:
>>> + reason = "unknown reset";
>>> + break;
>>> + }
>>> +
>>> + pr_info("AT91: Starting after %s\n", reason);
>>> +}
>>> +
>>> +static struct of_device_id at91_ramc_of_match[] = {
>>> + { .compatible = "atmel,at91sam9260-sdramc", },
>>> + { .compatible = "atmel,at91sam9g45-ddramc", },
>>> + { /* sentinel */ }
>>> +};
>>> +
>>> +static struct of_device_id at91_reset_of_match[] = {
>>> + { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_restart },
>>> + { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
>>> + { /* sentinel */ }
>>> +};
>>> +
>>> +static int at91_reset_probe(struct platform_device *pdev)
>>> +{
>>> + struct resource *res;
>>> +
>>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> + at91_rstc_base = devm_ioremap_resource(&pdev->dev, res);
>>> + if (IS_ERR(at91_rstc_base)) {
>>> + dev_err(&pdev->dev, "Could not map reset controller address\n");
>>> + return PTR_ERR(at91_rstc_base);
>>> + }
>>> +
>>> + if (pdev->dev.of_node) {
>>
>> split in 2 function more easy to ready and less indentation
>
> ok.
>
>>> + const struct of_device_id *match;
>>> + struct device_node *np;
>>> + int idx = 0;
>>> +
>>> + for_each_matching_node(np, at91_ramc_of_match) {
>>> + at91_ramc_base[idx] = of_iomap(np, 0);
>>> + if (!at91_ramc_base[idx]) {
>>> + dev_err(&pdev->dev, "Could not map ram controller address\n");
>>> + return -ENODEV;
>>> + }
>>> + idx++;
>>> + }
>>
>> and if you can not probe the ram controler it?s a panic not a -ENODEV
>>
>> as you have an unstable platform
>
> I don't really see why. That the pm code and the reset code won't be
> able to work, it's obvious. But making the assumption that the
> platforms don't have a RAM properly setup just because it doesn't have
> a DT node seems quite weak.
no as if you do not have the RAMC your reset will cause hardware issue as there is a bug
in the SoC so yes mandatory as 95% of the people will not known why there board will suddenly
do not reboot. As this specific reset in assembly was write to run from cache to fix a SoC bug
in the reset controller
>
>>> +
>>> + match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
>>> + arm_pm_restart = match->data;
>>> + } else {
>>> + const struct platform_device_id *match;
>>> + int idx = 0;
>>> +
>>> + for (idx = 0; idx < 2; idx++) {
>>> + res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1 );
>>> + at91_ramc_base[idx] = devm_ioremap_resource(&pdev->dev, res);
>>> + if (IS_ERR(at91_ramc_base[idx])) {
>>> + dev_err(&pdev->dev, "Could not map ram controller address\n");
>>> + return PTR_ERR(at91_rstc_base);
>>> + }
>>> + }
>>> +
>>> + match = platform_get_device_id(pdev);
>>> + arm_pm_restart = (void (*)(enum reboot_mode, const char*))
>>> + match->driver_data;
>>> + }
>>> +
>>> + at91_reset_status(pdev);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static struct platform_device_id at91_reset_plat_match[] = {
>>> + { "at91-sam9-reset", (unsigned long)at91sam9_restart },
>>> + { "at91-g45-reset", (unsigned long)at91sam9g45_restart },
>> at91-sam9???
>>
>> from the beginning of DT we put the first SoC were the
>> reset was introduce and why do you change the DT binding?
>
> Except that this is not about DT probing, but the old-style board
> files one.
>
except that in al the other driver such as FBDEV we use the same principle for platform_device
Best Regards,
J.
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Fri, 4 Jul 2014 11:08:20 +0800
Jean-Christophe PLAGNIOL-VILLARD <[email protected]> wrote:
>
> On Jul 3, 2014, at 10:59 PM, Maxime Ripard <[email protected]> wrote:
>
> > On Thu, Jul 03, 2014 at 10:39:08PM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
> >>> +++ b/drivers/power/reset/at91-reset.c
> >>> @@ -0,0 +1,202 @@
> >>> +/*
> >>> + * Atmel AT91 SAM9 SoCs reset code
> >>> + *
> >>> + * Copyright (C) 2014 Maxime Ripard
> >>> + *
> >>> + * Maxime Ripard <[email protected]>
> >>
> >> you can not own the copyright as it’s basically a copy of other
> >> people code
> >
> > The previous names are missing, right.
> >
> >>> + *
> >>> + * This file is licensed under the terms of the GNU General Public
> >>> + * License version 2. This program is licensed "as is" without any
> >>> + * warranty of any kind, whether express or implied.
> >>> + */
> >>> +
> >>> +#include <linux/io.h>
> >>> +#include <linux/module.h>
> >>> +#include <linux/of_address.h>
> >>> +#include <linux/platform_device.h>
> >>> +#include <linux/reboot.h>
> >>> +
> >>> +#include <asm/system_misc.h>
> >>> +
> >>> +#include <mach/at91sam9_ddrsdr.h>
> >>> +#include <mach/at91sam9_sdramc.h>
> >>> +
> >>> +#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
> >>> +#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
> >>> +#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
> >>> +#define AT91_RSTC_EXTRST BIT(3) /* External Reset */
> >>> +#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
> >>> +
> >>> +#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
> >>> +#define AT91_RSTC_URSTS BIT(0) /* User Reset Status */
> >>> +#define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */
> >>> +#define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */
> >>> +#define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */
> >>> +
> >>> +#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
> >>> +#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
> >>> +#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
> >>> +#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
> >>> +
> >>> +enum reset_type {
> >>> + RESET_TYPE_GENERAL = 0,
> >>> + RESET_TYPE_WAKEUP = 1,
> >>> + RESET_TYPE_WATCHDOG = 2,
> >>> + RESET_TYPE_SOFTWARE = 3,
> >>> + RESET_TYPE_USER = 4,
> >>> +};
> >>> +
> >>> +static void __iomem *at91_ramc_base[2], *at91_rstc_base;
> >>> +
> >>> +static void at91sam9_restart(enum reboot_mode mode, const char *cmd)
> >>> +{
> >>> + asm volatile(
> >>> + ".balign 32\n\t"
> >>> +
> >>> + "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
> >>> + "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
> >>> + "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
> >>> +
> >>> + "b .\n\t"
> >>> + :
> >>> + : "r" (at91_ramc_base[0]),
> >>> + "r" (at91_rstc_base),
> >>> + "r" (1),
> >>> + "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
> >>> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
> >>> +}
> >>> +
> >>> +static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
> >>> +{
> >>> + asm volatile(
> >>> + "cmp %1, #0\n\t"
> >>> + "beq 1f\n\t"
> >>> +
> >>> + "ldr r0, [%1]\n\t"
> >>> + "cmp r0, #0\n\t"
> >>> +
> >>> + ".balign 32\n\t"
> >>> +
> >>> + "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> >>> + " str %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> >>> + " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> >>> + " strne %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> >>> + " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
> >>> +
> >>> + " b .\n\t"
> >>> + :
> >>> + : "r" (at91_ramc_base[0]),
> >>> + "r" (at91_ramc_base[1]),
> >>> + "r" (at91_rstc_base),
> >>> + "r" (1),
> >>> + "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
> >>> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
> >>> + : "r0");
> >>> +}
> >>> +
> >> move this to an assembly file more easy to read than a C code
> >
> > Nope. It's a pain to pass variable to an external assembly file, and
> > this makes the use of global variable pretty much mandatory, which is
> > definitely not great.
>
> Not at all I did for the PM slow clock code just write a function and pas it as a parameter
> you have 3
>
> so basically you have to use the current and just pass at91_ramc_base[0], at91_ramc_base[1]
> and at91_rstc_base
> it’s 3 lignes of modification, if you have at91_ramc_base and at91_ramc_base same
>
Yes, retrieving function parameters from assembly code is not that
complicated (the first 4 pointer values are accessible through r0-r3),
but then you'll have to store your assembly file somewhere.
Subsystem directories (drivers/xxx) are supposed to be architecture
agnostics, and I'm not sure subsystem maintainers will accept these
assembly files in their directory.
ITOH, leaving these assembly files in arch/arm/mach-at91 will just
spread the code over linux src tree and will definitely not help other
people find out the relationship between these files.
Regarding the readability concern, I think some comments could help
understanding what's being done here.
Best Regards,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
On Fri, Jul 04, 2014 at 10:40:56AM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
>
> On Jul 3, 2014, at 10:59 PM, Maxime Ripard <[email protected]> wrote:
>
> > On Thu, Jul 03, 2014 at 10:39:08PM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
> >>> +++ b/drivers/power/reset/at91-reset.c
> >>> @@ -0,0 +1,202 @@
> >>> +/*
> >>> + * Atmel AT91 SAM9 SoCs reset code
> >>> + *
> >>> + * Copyright (C) 2014 Maxime Ripard
> >>> + *
> >>> + * Maxime Ripard <[email protected]>
> >>
> >> you can not own the copyright as it’s basically a copy of other
> >> people code
> >
> > The previous names are missing, right.
> >
> >>> + *
> >>> + * This file is licensed under the terms of the GNU General Public
> >>> + * License version 2. This program is licensed "as is" without any
> >>> + * warranty of any kind, whether express or implied.
> >>> + */
> >>> +
> >>> +#include <linux/io.h>
> >>> +#include <linux/module.h>
> >>> +#include <linux/of_address.h>
> >>> +#include <linux/platform_device.h>
> >>> +#include <linux/reboot.h>
> >>> +
> >>> +#include <asm/system_misc.h>
> >>> +
> >>> +#include <mach/at91sam9_ddrsdr.h>
> >>> +#include <mach/at91sam9_sdramc.h>
> >>> +
> >>> +#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
> >>> +#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
> >>> +#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
> >>> +#define AT91_RSTC_EXTRST BIT(3) /* External Reset */
> >>> +#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
> >>> +
> >>> +#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
> >>> +#define AT91_RSTC_URSTS BIT(0) /* User Reset Status */
> >>> +#define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */
> >>> +#define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */
> >>> +#define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */
> >>> +
> >>> +#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
> >>> +#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
> >>> +#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
> >>> +#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
> >>> +
> >>> +enum reset_type {
> >>> + RESET_TYPE_GENERAL = 0,
> >>> + RESET_TYPE_WAKEUP = 1,
> >>> + RESET_TYPE_WATCHDOG = 2,
> >>> + RESET_TYPE_SOFTWARE = 3,
> >>> + RESET_TYPE_USER = 4,
> >>> +};
> >>> +
> >>> +static void __iomem *at91_ramc_base[2], *at91_rstc_base;
> >>> +
> >>> +static void at91sam9_restart(enum reboot_mode mode, const char *cmd)
> >>> +{
> >>> + asm volatile(
> >>> + ".balign 32\n\t"
> >>> +
> >>> + "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
> >>> + "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
> >>> + "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
> >>> +
> >>> + "b .\n\t"
> >>> + :
> >>> + : "r" (at91_ramc_base[0]),
> >>> + "r" (at91_rstc_base),
> >>> + "r" (1),
> >>> + "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
> >>> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
> >>> +}
> >>> +
> >>> +static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
> >>> +{
> >>> + asm volatile(
> >>> + "cmp %1, #0\n\t"
> >>> + "beq 1f\n\t"
> >>> +
> >>> + "ldr r0, [%1]\n\t"
> >>> + "cmp r0, #0\n\t"
> >>> +
> >>> + ".balign 32\n\t"
> >>> +
> >>> + "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> >>> + " str %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> >>> + " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> >>> + " strne %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> >>> + " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
> >>> +
> >>> + " b .\n\t"
> >>> + :
> >>> + : "r" (at91_ramc_base[0]),
> >>> + "r" (at91_ramc_base[1]),
> >>> + "r" (at91_rstc_base),
> >>> + "r" (1),
> >>> + "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
> >>> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
> >>> + : "r0");
> >>> +}
> >>> +
> >> move this to an assembly file more easy to read than a C code
> >
> > Nope. It's a pain to pass variable to an external assembly file, and
> > this makes the use of global variable pretty much mandatory, which is
> > definitely not great.
>
> Not at all I did for the PM slow clock code just write a function and pas it as a parameter
> you have 3
>
> so basically you have to use the current and just pass at91_ramc_base[0], at91_ramc_base[1]
> and at91_rstc_base
> it’s 3 lignes of modification, if you have at91_ramc_base and at91_ramc_base same
>
> so NACK
There's also a strong pattern for doing inline assembly in the kernel:
$ git grep "asm volatile" -- drivers/ | wc -l
130
$ find drivers/ -name *.S
9
Most of them being code where we don't have any other choice (FIQ/NMI
handlers, etc.)
Plus, the code is actually much simpler using inline assembly. You
don't have to worry about all the register allocation, you don't have
to worry about the arguments themselves.
I admit that I forgot to reintroduce all the comments that where
there. It's an issue, it will be fixed, but I really don't see what a
separate assembly files bring.
> >
> >>
> >>> +static void __init at91_reset_status(struct platform_device *pdev)
> >>> +{
> >>> + u32 reg = readl(at91_rstc_base + AT91_RSTC_SR);
> >>> + char *reason;
> >>> +
> >>> + switch ((reg & AT91_RSTC_RSTTYP) >> 8) {
> >>> + case RESET_TYPE_GENERAL:
> >>> + reason = "general reset";
> >>> + break;
> >>> + case RESET_TYPE_WAKEUP:
> >>> + reason = "wakeup";
> >>> + break;
> >>> + case RESET_TYPE_WATCHDOG:
> >>> + reason = "watchdog reset";
> >>> + break;
> >>> + case RESET_TYPE_SOFTWARE:
> >>> + reason = "software reset";
> >>> + break;
> >>> + case RESET_TYPE_USER:
> >>> + reason = "user reset";
> >>> + break;
> >>> + default:
> >>> + reason = "unknown reset";
> >>> + break;
> >>> + }
> >>> +
> >>> + pr_info("AT91: Starting after %s\n", reason);
> >>> +}
> >>> +
> >>> +static struct of_device_id at91_ramc_of_match[] = {
> >>> + { .compatible = "atmel,at91sam9260-sdramc", },
> >>> + { .compatible = "atmel,at91sam9g45-ddramc", },
> >>> + { /* sentinel */ }
> >>> +};
> >>> +
> >>> +static struct of_device_id at91_reset_of_match[] = {
> >>> + { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_restart },
> >>> + { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
> >>> + { /* sentinel */ }
> >>> +};
> >>> +
> >>> +static int at91_reset_probe(struct platform_device *pdev)
> >>> +{
> >>> + struct resource *res;
> >>> +
> >>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >>> + at91_rstc_base = devm_ioremap_resource(&pdev->dev, res);
> >>> + if (IS_ERR(at91_rstc_base)) {
> >>> + dev_err(&pdev->dev, "Could not map reset controller address\n");
> >>> + return PTR_ERR(at91_rstc_base);
> >>> + }
> >>> +
> >>> + if (pdev->dev.of_node) {
> >>
> >> split in 2 function more easy to ready and less indentation
> >
> > ok.
> >
> >>> + const struct of_device_id *match;
> >>> + struct device_node *np;
> >>> + int idx = 0;
> >>> +
> >>> + for_each_matching_node(np, at91_ramc_of_match) {
> >>> + at91_ramc_base[idx] = of_iomap(np, 0);
> >>> + if (!at91_ramc_base[idx]) {
> >>> + dev_err(&pdev->dev, "Could not map ram controller address\n");
> >>> + return -ENODEV;
> >>> + }
> >>> + idx++;
> >>> + }
> >>
> >> and if you can not probe the ram controler it’s a panic not a -ENODEV
> >>
> >> as you have an unstable platform
> >
> > I don't really see why. That the pm code and the reset code won't be
> > able to work, it's obvious. But making the assumption that the
> > platforms don't have a RAM properly setup just because it doesn't have
> > a DT node seems quite weak.
>
> no as if you do not have the RAMC your reset will cause hardware
> issue as there is a bug in the SoC
No, because the reset hook won't be installed. So it will never
trigger any bug, since it won't do anything.
> so yes mandatory as 95% of the people will not known why there board
> will suddenly do not reboot.
Well, there's an error message in the boot logs.
> As this specific reset in assembly was write to run from cache to
> fix a SoC bug in the reset controller
Yes. I know.
So, to sum things up, just because you can't reboot, you don't want to
run at all?
Should we also panic when the reset driver is not compiled in then?
> >
> >>> +
> >>> + match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
> >>> + arm_pm_restart = match->data;
> >>> + } else {
> >>> + const struct platform_device_id *match;
> >>> + int idx = 0;
> >>> +
> >>> + for (idx = 0; idx < 2; idx++) {
> >>> + res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1 );
> >>> + at91_ramc_base[idx] = devm_ioremap_resource(&pdev->dev, res);
> >>> + if (IS_ERR(at91_ramc_base[idx])) {
> >>> + dev_err(&pdev->dev, "Could not map ram controller address\n");
> >>> + return PTR_ERR(at91_rstc_base);
> >>> + }
> >>> + }
> >>> +
> >>> + match = platform_get_device_id(pdev);
> >>> + arm_pm_restart = (void (*)(enum reboot_mode, const char*))
> >>> + match->driver_data;
> >>> + }
> >>> +
> >>> + at91_reset_status(pdev);
> >>> +
> >>> + return 0;
> >>> +}
> >>> +
> >>> +static struct platform_device_id at91_reset_plat_match[] = {
> >>> + { "at91-sam9-reset", (unsigned long)at91sam9_restart },
> >>> + { "at91-g45-reset", (unsigned long)at91sam9g45_restart },
> >> at91-sam9???
> >>
> >> from the beginning of DT we put the first SoC were the
> >> reset was introduce and why do you change the DT binding?
> >
> > Except that this is not about DT probing, but the old-style board
> > files one.
> >
>
> except that in al the other driver such as FBDEV we use the same
> principle for platform_device
Ok. I was trying to keep the former naming of the former restart
functions, but it also makes sense.
I'll change this.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Fri, Jul 04, 2014 at 09:14:43AM +0200, Boris BREZILLON wrote:
> On Fri, 4 Jul 2014 11:08:20 +0800
> Jean-Christophe PLAGNIOL-VILLARD <[email protected]> wrote:
>
> >
> > On Jul 3, 2014, at 10:59 PM, Maxime Ripard <[email protected]> wrote:
> >
> > > On Thu, Jul 03, 2014 at 10:39:08PM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > >>> +++ b/drivers/power/reset/at91-reset.c
> > >>> @@ -0,0 +1,202 @@
> > >>> +/*
> > >>> + * Atmel AT91 SAM9 SoCs reset code
> > >>> + *
> > >>> + * Copyright (C) 2014 Maxime Ripard
> > >>> + *
> > >>> + * Maxime Ripard <[email protected]>
> > >>
> > >> you can not own the copyright as it’s basically a copy of other
> > >> people code
> > >
> > > The previous names are missing, right.
> > >
> > >>> + *
> > >>> + * This file is licensed under the terms of the GNU General Public
> > >>> + * License version 2. This program is licensed "as is" without any
> > >>> + * warranty of any kind, whether express or implied.
> > >>> + */
> > >>> +
> > >>> +#include <linux/io.h>
> > >>> +#include <linux/module.h>
> > >>> +#include <linux/of_address.h>
> > >>> +#include <linux/platform_device.h>
> > >>> +#include <linux/reboot.h>
> > >>> +
> > >>> +#include <asm/system_misc.h>
> > >>> +
> > >>> +#include <mach/at91sam9_ddrsdr.h>
> > >>> +#include <mach/at91sam9_sdramc.h>
> > >>> +
> > >>> +#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
> > >>> +#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
> > >>> +#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
> > >>> +#define AT91_RSTC_EXTRST BIT(3) /* External Reset */
> > >>> +#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
> > >>> +
> > >>> +#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
> > >>> +#define AT91_RSTC_URSTS BIT(0) /* User Reset Status */
> > >>> +#define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */
> > >>> +#define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */
> > >>> +#define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */
> > >>> +
> > >>> +#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
> > >>> +#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
> > >>> +#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
> > >>> +#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
> > >>> +
> > >>> +enum reset_type {
> > >>> + RESET_TYPE_GENERAL = 0,
> > >>> + RESET_TYPE_WAKEUP = 1,
> > >>> + RESET_TYPE_WATCHDOG = 2,
> > >>> + RESET_TYPE_SOFTWARE = 3,
> > >>> + RESET_TYPE_USER = 4,
> > >>> +};
> > >>> +
> > >>> +static void __iomem *at91_ramc_base[2], *at91_rstc_base;
> > >>> +
> > >>> +static void at91sam9_restart(enum reboot_mode mode, const char *cmd)
> > >>> +{
> > >>> + asm volatile(
> > >>> + ".balign 32\n\t"
> > >>> +
> > >>> + "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
> > >>> + "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
> > >>> + "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
> > >>> +
> > >>> + "b .\n\t"
> > >>> + :
> > >>> + : "r" (at91_ramc_base[0]),
> > >>> + "r" (at91_rstc_base),
> > >>> + "r" (1),
> > >>> + "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
> > >>> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
> > >>> +}
> > >>> +
> > >>> +static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
> > >>> +{
> > >>> + asm volatile(
> > >>> + "cmp %1, #0\n\t"
> > >>> + "beq 1f\n\t"
> > >>> +
> > >>> + "ldr r0, [%1]\n\t"
> > >>> + "cmp r0, #0\n\t"
> > >>> +
> > >>> + ".balign 32\n\t"
> > >>> +
> > >>> + "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> > >>> + " str %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> > >>> + " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> > >>> + " strne %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> > >>> + " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
> > >>> +
> > >>> + " b .\n\t"
> > >>> + :
> > >>> + : "r" (at91_ramc_base[0]),
> > >>> + "r" (at91_ramc_base[1]),
> > >>> + "r" (at91_rstc_base),
> > >>> + "r" (1),
> > >>> + "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
> > >>> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
> > >>> + : "r0");
> > >>> +}
> > >>> +
> > >> move this to an assembly file more easy to read than a C code
> > >
> > > Nope. It's a pain to pass variable to an external assembly file, and
> > > this makes the use of global variable pretty much mandatory, which is
> > > definitely not great.
> >
> > Not at all I did for the PM slow clock code just write a function and pas it as a parameter
> > you have 3
> >
> > so basically you have to use the current and just pass at91_ramc_base[0], at91_ramc_base[1]
> > and at91_rstc_base
> > it’s 3 lignes of modification, if you have at91_ramc_base and at91_ramc_base same
> >
>
> Yes, retrieving function parameters from assembly code is not that
> complicated (the first 4 pointer values are accessible through r0-r3),
> but then you'll have to store your assembly file somewhere.
Like I was saying, there's a strong preference for the inline
assembly...
> Subsystem directories (drivers/xxx) are supposed to be architecture
> agnostics, and I'm not sure subsystem maintainers will accept these
> assembly files in their directory.
... and I've told that some maintainers don't even want assembly files
in their maintainance area.
> ITOH, leaving these assembly files in arch/arm/mach-at91 will just
> spread the code over linux src tree and will definitely not help other
> people find out the relationship between these files.
Given that the end-goal is to remove most (if not all) of mach-at91,
it seems a bit backward to me.
> Regarding the readability concern, I think some comments could help
> understanding what's being done here.
Yep, I have been a bit too eager to send the patches, and forgot to
reintroduce the comments that were there in the first place.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On 16:52 Thu 03 Jul , Maxime Ripard wrote:
> Hi,
>
> On Thu, Jul 03, 2014 at 10:29:58PM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > no do this at SoC level
>
> Since it has to be done at init_machine, I don't see any other easy
> way to do this at the SoC level.
>
> What is your suggestion?
do it earlier as there is not driver it will not change anything
On 11:06 Fri 04 Jul , Maxime Ripard wrote:
> On Fri, Jul 04, 2014 at 09:14:43AM +0200, Boris BREZILLON wrote:
> > On Fri, 4 Jul 2014 11:08:20 +0800
> > Jean-Christophe PLAGNIOL-VILLARD <[email protected]> wrote:
> >
> > >
> > > On Jul 3, 2014, at 10:59 PM, Maxime Ripard <[email protected]> wrote:
> > >
> > > > On Thu, Jul 03, 2014 at 10:39:08PM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > > >>> +++ b/drivers/power/reset/at91-reset.c
> > > >>> @@ -0,0 +1,202 @@
> > > >>> +/*
> > > >>> + * Atmel AT91 SAM9 SoCs reset code
> > > >>> + *
> > > >>> + * Copyright (C) 2014 Maxime Ripard
> > > >>> + *
> > > >>> + * Maxime Ripard <[email protected]>
> > > >>
> > > >> you can not own the copyright as it’s basically a copy of other
> > > >> people code
> > > >
> > > > The previous names are missing, right.
> > > >
> > > >>> + *
> > > >>> + * This file is licensed under the terms of the GNU General Public
> > > >>> + * License version 2. This program is licensed "as is" without any
> > > >>> + * warranty of any kind, whether express or implied.
> > > >>> + */
> > > >>> +
> > > >>> +#include <linux/io.h>
> > > >>> +#include <linux/module.h>
> > > >>> +#include <linux/of_address.h>
> > > >>> +#include <linux/platform_device.h>
> > > >>> +#include <linux/reboot.h>
> > > >>> +
> > > >>> +#include <asm/system_misc.h>
> > > >>> +
> > > >>> +#include <mach/at91sam9_ddrsdr.h>
> > > >>> +#include <mach/at91sam9_sdramc.h>
> > > >>> +
> > > >>> +#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
> > > >>> +#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
> > > >>> +#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
> > > >>> +#define AT91_RSTC_EXTRST BIT(3) /* External Reset */
> > > >>> +#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
> > > >>> +
> > > >>> +#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
> > > >>> +#define AT91_RSTC_URSTS BIT(0) /* User Reset Status */
> > > >>> +#define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */
> > > >>> +#define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */
> > > >>> +#define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */
> > > >>> +
> > > >>> +#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
> > > >>> +#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
> > > >>> +#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
> > > >>> +#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
> > > >>> +
> > > >>> +enum reset_type {
> > > >>> + RESET_TYPE_GENERAL = 0,
> > > >>> + RESET_TYPE_WAKEUP = 1,
> > > >>> + RESET_TYPE_WATCHDOG = 2,
> > > >>> + RESET_TYPE_SOFTWARE = 3,
> > > >>> + RESET_TYPE_USER = 4,
> > > >>> +};
> > > >>> +
> > > >>> +static void __iomem *at91_ramc_base[2], *at91_rstc_base;
> > > >>> +
> > > >>> +static void at91sam9_restart(enum reboot_mode mode, const char *cmd)
> > > >>> +{
> > > >>> + asm volatile(
> > > >>> + ".balign 32\n\t"
> > > >>> +
> > > >>> + "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
> > > >>> + "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
> > > >>> + "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
> > > >>> +
> > > >>> + "b .\n\t"
> > > >>> + :
> > > >>> + : "r" (at91_ramc_base[0]),
> > > >>> + "r" (at91_rstc_base),
> > > >>> + "r" (1),
> > > >>> + "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
> > > >>> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
> > > >>> +}
> > > >>> +
> > > >>> +static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
> > > >>> +{
> > > >>> + asm volatile(
> > > >>> + "cmp %1, #0\n\t"
> > > >>> + "beq 1f\n\t"
> > > >>> +
> > > >>> + "ldr r0, [%1]\n\t"
> > > >>> + "cmp r0, #0\n\t"
> > > >>> +
> > > >>> + ".balign 32\n\t"
> > > >>> +
> > > >>> + "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> > > >>> + " str %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> > > >>> + " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> > > >>> + " strne %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
> > > >>> + " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
> > > >>> +
> > > >>> + " b .\n\t"
> > > >>> + :
> > > >>> + : "r" (at91_ramc_base[0]),
> > > >>> + "r" (at91_ramc_base[1]),
> > > >>> + "r" (at91_rstc_base),
> > > >>> + "r" (1),
> > > >>> + "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
> > > >>> + "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
> > > >>> + : "r0");
> > > >>> +}
> > > >>> +
> > > >> move this to an assembly file more easy to read than a C code
> > > >
> > > > Nope. It's a pain to pass variable to an external assembly file, and
> > > > this makes the use of global variable pretty much mandatory, which is
> > > > definitely not great.
> > >
> > > Not at all I did for the PM slow clock code just write a function and pas it as a parameter
> > > you have 3
> > >
> > > so basically you have to use the current and just pass at91_ramc_base[0], at91_ramc_base[1]
> > > and at91_rstc_base
> > > it’s 3 lignes of modification, if you have at91_ramc_base and at91_ramc_base same
> > >
> >
> > Yes, retrieving function parameters from assembly code is not that
> > complicated (the first 4 pointer values are accessible through r0-r3),
> > but then you'll have to store your assembly file somewhere.
>
> Like I was saying, there's a strong preference for the inline
> assembly...
inline is horrible to read and maintain NACK
keep it in an assembly file it's so easy to read and follow
and you just have to move the file existing to the driver/power
Best Regards,
J.
>
> > Subsystem directories (drivers/xxx) are supposed to be architecture
> > agnostics, and I'm not sure subsystem maintainers will accept these
> > assembly files in their directory.
>
> ... and I've told that some maintainers don't even want assembly files
> in their maintainance area.
>
> > ITOH, leaving these assembly files in arch/arm/mach-at91 will just
> > spread the code over linux src tree and will definitely not help other
> > people find out the relationship between these files.
>
> Given that the end-goal is to remove most (if not all) of mach-at91,
> it seems a bit backward to me.
>
> > Regarding the readability concern, I think some comments could help
> > understanding what's being done here.
>
> Yep, I have been a bit too eager to send the patches, and forgot to
> reintroduce the comments that were there in the first place.
>
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com
On Mon, Jul 07, 2014 at 08:40:01PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > > > >> move this to an assembly file more easy to read than a C code
> > > > >
> > > > > Nope. It's a pain to pass variable to an external assembly file, and
> > > > > this makes the use of global variable pretty much mandatory, which is
> > > > > definitely not great.
> > > >
> > > > Not at all I did for the PM slow clock code just write a function and pas it as a parameter
> > > > you have 3
> > > >
> > > > so basically you have to use the current and just pass at91_ramc_base[0], at91_ramc_base[1]
> > > > and at91_rstc_base
> > > > it’s 3 lignes of modification, if you have at91_ramc_base and at91_ramc_base same
> > > >
> > >
> > > Yes, retrieving function parameters from assembly code is not that
> > > complicated (the first 4 pointer values are accessible through r0-r3),
> > > but then you'll have to store your assembly file somewhere.
> >
> > Like I was saying, there's a strong preference for the inline
> > assembly...
>
> inline is horrible to read and maintain NACK
>
> keep it in an assembly file it's so easy to read and follow
>
> and you just have to move the file existing to the driver/power
Well, the whole rest of the kernel community feels otherwise.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Mon, Jul 07, 2014 at 08:42:39PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 16:52 Thu 03 Jul , Maxime Ripard wrote:
> > Hi,
> >
> > On Thu, Jul 03, 2014 at 10:29:58PM +0800, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > > no do this at SoC level
> >
> > Since it has to be done at init_machine, I don't see any other easy
> > way to do this at the SoC level.
> >
> > What is your suggestion?
>
> do it earlier as there is not driver it will not change anything
My question remains. When should I do so?
at91_initialize is too early to register any devices.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Tue, Jul 08, 2014 at 10:08:14AM +0200, Maxime Ripard wrote:
> On Mon, Jul 07, 2014 at 08:40:01PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > > > > >> move this to an assembly file more easy to read than a C code
> > > > > >
> > > > > > Nope. It's a pain to pass variable to an external assembly file, and
> > > > > > this makes the use of global variable pretty much mandatory, which is
> > > > > > definitely not great.
> > > > >
> > > > > Not at all I did for the PM slow clock code just write a function and pas it as a parameter
> > > > > you have 3
> > > > >
> > > > > so basically you have to use the current and just pass at91_ramc_base[0], at91_ramc_base[1]
> > > > > and at91_rstc_base
> > > > > it’s 3 lignes of modification, if you have at91_ramc_base and at91_ramc_base same
> > > > >
> > > >
> > > > Yes, retrieving function parameters from assembly code is not that
> > > > complicated (the first 4 pointer values are accessible through r0-r3),
> > > > but then you'll have to store your assembly file somewhere.
> > >
> > > Like I was saying, there's a strong preference for the inline
> > > assembly...
> >
> > inline is horrible to read and maintain NACK
> >
> > keep it in an assembly file it's so easy to read and follow
> >
> > and you just have to move the file existing to the driver/power
>
> Well, the whole rest of the kernel community feels otherwise.
Thinking a bit more about this, would using symbolic names instead of
the indices in the inline assembly work for you?
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com