All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
To: Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
	linux-rpi-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Subject: [PATCH V2] ARM: bcm2835: implement machine restart hook
Date: Fri, 28 Sep 2012 23:17:15 -0600	[thread overview]
Message-ID: <1348895835-18245-1-git-send-email-swarren@wwwdotorg.org> (raw)

Implement the machine restart hook using the SoC's watchdog timer module.
To support this, define a DT binding for the watchdog module, and add it
to the device tree.

The downstream rpi-split branch contains a full watchdog timer driver
implementation, which also implements the restart hook. However, the
restart function is largely separate from the watchdog driver, so for
simplicity, the restart hook is implemented here directly in the main
machine source file.

Overall structure (separate setup/restart) functions derived from the
picoxcell ARM support.

Watchdog register IO sequence taken from code by Simon Arlott. Note that
the watchdog module is not documented in BCM2835-ARM-Peripherals.pdf.

Signed-off-by: Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
---
v2:
* s/-wdog/-wdt/ in compatible value given precedent in other bindings.
* Fix node name in DT binding example.
---
 .../bindings/watchdog/brcm,bcm2835-pm-wdog.txt     |   13 ++++++
 arch/arm/boot/dts/bcm2835.dtsi                     |    5 +++
 arch/arm/mach-bcm2835/bcm2835.c                    |   46 ++++++++++++++++++++
 3 files changed, 64 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt

diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt b/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt
new file mode 100644
index 0000000..d209366
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt
@@ -0,0 +1,13 @@
+BCM2835 Watchdog timer
+
+Required properties:
+
+- compatible : should be "brcm,bcm2835-pm-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Example:
+
+watchdog {
+	compatible = "brcm,bcm2835-pm-wdt";
+	reg = <0x7e100000 0x28>;
+};
diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
index 0b61939..5c5cbaf 100644
--- a/arch/arm/boot/dts/bcm2835.dtsi
+++ b/arch/arm/boot/dts/bcm2835.dtsi
@@ -29,6 +29,11 @@
 			#interrupt-cells = <2>;
 		};
 
+		watchdog {
+			compatible = "brcm,bcm2835-pm-wdt";
+			reg = <0x7e100000 0x28>;
+		};
+
 		uart@20201000 {
 			compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
 			reg = <0x7e201000 0x1000>;
diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c
index f6fea49..c4dd210 100644
--- a/arch/arm/mach-bcm2835/bcm2835.c
+++ b/arch/arm/mach-bcm2835/bcm2835.c
@@ -12,8 +12,10 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/irqchip/bcm2835.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/bcm2835_timer.h>
 #include <linux/clk/bcm2835.h>
@@ -23,6 +25,48 @@
 
 #include <mach/bcm2835_soc.h>
 
+#define PM_RSTC				0x1c
+#define PM_WDOG				0x24
+
+#define PM_PASSWORD			0x5a000000
+#define PM_RSTC_WRCFG_MASK		0x00000030
+#define PM_RSTC_WRCFG_FULL_RESET	0x00000020
+
+static void __iomem *wdt_regs;
+
+/*
+ * The machine restart method can be called from an atomic context so we won't
+ * be able to ioremap the regs then.
+ */
+static void bcm2835_setup_restart(void)
+{
+	struct device_node *np = of_find_compatible_node(NULL, NULL,
+						"brcm,bcm2835-pm-wdt");
+	if (WARN(!np, "unable to setup watchdog restart"))
+		return;
+
+	wdt_regs = of_iomap(np, 0);
+	WARN(!wdt_regs, "failed to remap watchdog regs");
+}
+
+static void bcm2835_restart(char mode, const char *cmd)
+{
+	u32 val;
+
+	if (!wdt_regs)
+		return;
+
+	/* use a timeout of 10 ticks (~150us) */
+	writel_relaxed(10 | PM_PASSWORD, wdt_regs + PM_WDOG);
+	val = readl_relaxed(wdt_regs + PM_RSTC);
+	val &= ~PM_RSTC_WRCFG_MASK;
+	val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
+	writel_relaxed(val, wdt_regs + PM_RSTC);
+
+	/* No sleeping, possibly atomic. */
+	mdelay(1);
+}
+
 static struct map_desc io_map __initdata = {
 	.virtual = BCM2835_PERIPH_VIRT,
 	.pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS),
@@ -39,6 +83,7 @@ void __init bcm2835_init(void)
 {
 	int ret;
 
+	bcm2835_setup_restart();
 	bcm2835_init_clocks();
 
 	ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
@@ -60,5 +105,6 @@ DT_MACHINE_START(BCM2835, "BCM2835")
 	.handle_irq = bcm2835_handle_irq,
 	.init_machine = bcm2835_init,
 	.timer = &bcm2835_timer,
+	.restart = bcm2835_restart,
 	.dt_compat = bcm2835_compat
 MACHINE_END
-- 
1.7.9.5

WARNING: multiple messages have this Message-ID (diff)
From: swarren@wwwdotorg.org (Stephen Warren)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH V2] ARM: bcm2835: implement machine restart hook
Date: Fri, 28 Sep 2012 23:17:15 -0600	[thread overview]
Message-ID: <1348895835-18245-1-git-send-email-swarren@wwwdotorg.org> (raw)

Implement the machine restart hook using the SoC's watchdog timer module.
To support this, define a DT binding for the watchdog module, and add it
to the device tree.

The downstream rpi-split branch contains a full watchdog timer driver
implementation, which also implements the restart hook. However, the
restart function is largely separate from the watchdog driver, so for
simplicity, the restart hook is implemented here directly in the main
machine source file.

Overall structure (separate setup/restart) functions derived from the
picoxcell ARM support.

Watchdog register IO sequence taken from code by Simon Arlott. Note that
the watchdog module is not documented in BCM2835-ARM-Peripherals.pdf.

Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
---
v2:
* s/-wdog/-wdt/ in compatible value given precedent in other bindings.
* Fix node name in DT binding example.
---
 .../bindings/watchdog/brcm,bcm2835-pm-wdog.txt     |   13 ++++++
 arch/arm/boot/dts/bcm2835.dtsi                     |    5 +++
 arch/arm/mach-bcm2835/bcm2835.c                    |   46 ++++++++++++++++++++
 3 files changed, 64 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt

diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt b/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt
new file mode 100644
index 0000000..d209366
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt
@@ -0,0 +1,13 @@
+BCM2835 Watchdog timer
+
+Required properties:
+
+- compatible : should be "brcm,bcm2835-pm-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Example:
+
+watchdog {
+	compatible = "brcm,bcm2835-pm-wdt";
+	reg = <0x7e100000 0x28>;
+};
diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
index 0b61939..5c5cbaf 100644
--- a/arch/arm/boot/dts/bcm2835.dtsi
+++ b/arch/arm/boot/dts/bcm2835.dtsi
@@ -29,6 +29,11 @@
 			#interrupt-cells = <2>;
 		};
 
+		watchdog {
+			compatible = "brcm,bcm2835-pm-wdt";
+			reg = <0x7e100000 0x28>;
+		};
+
 		uart at 20201000 {
 			compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
 			reg = <0x7e201000 0x1000>;
diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c
index f6fea49..c4dd210 100644
--- a/arch/arm/mach-bcm2835/bcm2835.c
+++ b/arch/arm/mach-bcm2835/bcm2835.c
@@ -12,8 +12,10 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/irqchip/bcm2835.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/bcm2835_timer.h>
 #include <linux/clk/bcm2835.h>
@@ -23,6 +25,48 @@
 
 #include <mach/bcm2835_soc.h>
 
+#define PM_RSTC				0x1c
+#define PM_WDOG				0x24
+
+#define PM_PASSWORD			0x5a000000
+#define PM_RSTC_WRCFG_MASK		0x00000030
+#define PM_RSTC_WRCFG_FULL_RESET	0x00000020
+
+static void __iomem *wdt_regs;
+
+/*
+ * The machine restart method can be called from an atomic context so we won't
+ * be able to ioremap the regs then.
+ */
+static void bcm2835_setup_restart(void)
+{
+	struct device_node *np = of_find_compatible_node(NULL, NULL,
+						"brcm,bcm2835-pm-wdt");
+	if (WARN(!np, "unable to setup watchdog restart"))
+		return;
+
+	wdt_regs = of_iomap(np, 0);
+	WARN(!wdt_regs, "failed to remap watchdog regs");
+}
+
+static void bcm2835_restart(char mode, const char *cmd)
+{
+	u32 val;
+
+	if (!wdt_regs)
+		return;
+
+	/* use a timeout of 10 ticks (~150us) */
+	writel_relaxed(10 | PM_PASSWORD, wdt_regs + PM_WDOG);
+	val = readl_relaxed(wdt_regs + PM_RSTC);
+	val &= ~PM_RSTC_WRCFG_MASK;
+	val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
+	writel_relaxed(val, wdt_regs + PM_RSTC);
+
+	/* No sleeping, possibly atomic. */
+	mdelay(1);
+}
+
 static struct map_desc io_map __initdata = {
 	.virtual = BCM2835_PERIPH_VIRT,
 	.pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS),
@@ -39,6 +83,7 @@ void __init bcm2835_init(void)
 {
 	int ret;
 
+	bcm2835_setup_restart();
 	bcm2835_init_clocks();
 
 	ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
@@ -60,5 +105,6 @@ DT_MACHINE_START(BCM2835, "BCM2835")
 	.handle_irq = bcm2835_handle_irq,
 	.init_machine = bcm2835_init,
 	.timer = &bcm2835_timer,
+	.restart = bcm2835_restart,
 	.dt_compat = bcm2835_compat
 MACHINE_END
-- 
1.7.9.5

             reply	other threads:[~2012-09-29  5:17 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-29  5:17 Stephen Warren [this message]
2012-09-29  5:17 ` [PATCH V2] ARM: bcm2835: implement machine restart hook Stephen Warren

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1348895835-18245-1-git-send-email-swarren@wwwdotorg.org \
    --to=swarren-3lzwwm7+weoh9zmkesr00q@public.gmane.org \
    --cc=devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org \
    --cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=linux-rpi-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.