From patchwork Sat Sep 29 05:17:15 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Warren X-Patchwork-Id: 1527961 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id E71513FE80 for ; Sat, 29 Sep 2012 05:20:34 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1THpQs-0003QG-MS; Sat, 29 Sep 2012 05:17:42 +0000 Received: from avon.wwwdotorg.org ([2001:470:1f0f:bd7::2]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1THpQn-0003Pz-Vd; Sat, 29 Sep 2012 05:17:40 +0000 Received: from severn.wwwdotorg.org (unknown [192.168.65.5]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by avon.wwwdotorg.org (Postfix) with ESMTPS id 0169E62E0; Fri, 28 Sep 2012 23:18:33 -0600 (MDT) Received: from dart.wifi.foxrun.wwwdotorg.org (unknown [192.168.62.30]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by severn.wwwdotorg.org (Postfix) with ESMTPSA id BB3A9E40F5; Fri, 28 Sep 2012 23:17:32 -0600 (MDT) From: Stephen Warren To: Stephen Warren Subject: [PATCH V2] ARM: bcm2835: implement machine restart hook Date: Fri, 28 Sep 2012 23:17:15 -0600 Message-Id: <1348895835-18245-1-git-send-email-swarren@wwwdotorg.org> X-Mailer: git-send-email 1.7.9.5 X-NVConfidentiality: public X-Virus-Scanned: clamav-milter 0.96.5 at avon.wwwdotorg.org X-Virus-Status: Clean X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.8 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: devicetree-discuss@lists.ozlabs.org, linux-rpi-kernel@lists.infradead.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org 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 --- 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 #include #include +#include #include #include #include @@ -23,6 +25,48 @@ #include +#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