From patchwork Mon Mar 11 18:07:59 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johan Hovold X-Patchwork-Id: 226635 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-la0-x23a.google.com (mail-la0-x23a.google.com [IPv6:2a00:1450:4010:c03::23a]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 2726A2C02C1 for ; Tue, 12 Mar 2013 05:11:25 +1100 (EST) Received: by mail-la0-f58.google.com with SMTP id ek20sf1942171lab.13 for ; Mon, 11 Mar 2013 11:11:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20120806; h=x-received:mime-version:x-beenthere:x-received:received-spf :x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:x-original-sender:x-original-authentication-results :reply-to:precedence:mailing-list:list-id:x-google-group-id :list-post:list-help:list-archive:sender:list-subscribe :list-unsubscribe:content-type; bh=cEq9+UnR34tRaS3MjIFmEir5byihn5R41+Jbh3fFZzo=; b=BbuxMulSHe6V4M57XZUjW3nDqblnOhp97PmYUI/YsCHAB6ZLE7lYXD6vPAqhJgouCY eevDEN68jGUafnZG3p6JkCl91mNBvdYPr+0s5MBCjZcEp57pVtwhQK91anFMUR1I/e0s r5TkjgaguYMKtPhlaAzqIP7Pf1TT0GUlMQWQTr98JGljNmnLY8atRmmvHWDEKzdHMyrC cM6H9pcUHRuatDhfagptpB65h2d1mzuG1bjFkx1PIxWpkG2MfdVEi/Pt3V/9A0LLgyhP Paf0meuW8UIoexN4lGXwQEjNOHa1h1/8hkmWjFkgWuX+Gg8Fka2LBDjxLNvCg7HY/d9d kH0g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:mime-version:x-beenthere:x-received:received-spf :x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:x-original-sender:x-original-authentication-results :reply-to:precedence:mailing-list:list-id:x-google-group-id :list-post:list-help:list-archive:sender:list-subscribe :list-unsubscribe:content-type; bh=cEq9+UnR34tRaS3MjIFmEir5byihn5R41+Jbh3fFZzo=; b=NuTGJ3RJDRQPcFzIv1hiyXbP64ydGj1yLHhfLGdt5+WrNboRY5efW+KaA3p8uHZM4E 96UIKLbajkVywDDcgCmjWtL7XChGaI5rHVd5LZjbDx/x290sk/nYgwh2Rsfur2TqWfwB 3OoPjwYJziDrzdsoJEojVrmO3eVxYYgh1SSOYSWdoN+FUAyBiT5S8ma7Ig7z851S4izM E9VBsH9Z8WWIaWpsZrqQA2z9I7e/iExILdp6e3ZQ+Bpavy/f6iHFV4MAJWMV0kVC5V8Q G0CR7K7DO5jsdWEF0VrdMaIdUiVW+jDoFlWkotlpsKnXZQASnRji+LKKs4jjVqji9wZY hZHw== X-Received: by 10.180.73.10 with SMTP id h10mr1308530wiv.0.1363025482107; Mon, 11 Mar 2013 11:11:22 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: rtc-linux@googlegroups.com Received: by 10.180.76.4 with SMTP id g4ls667595wiw.51.canary; Mon, 11 Mar 2013 11:11:21 -0700 (PDT) X-Received: by 10.205.113.193 with SMTP id ex1mr609474bkc.5.1363025481519; Mon, 11 Mar 2013 11:11:21 -0700 (PDT) Received: from mail-lb0-f171.google.com (mail-lb0-f171.google.com [209.85.217.171]) by gmr-mx.google.com with ESMTPS id u1si1380180bkv.1.2013.03.11.11.11.21 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 11 Mar 2013 11:11:21 -0700 (PDT) Received-SPF: pass (google.com: domain of jhovold@gmail.com designates 209.85.217.171 as permitted sender) client-ip=209.85.217.171; Received: by mail-lb0-f171.google.com with SMTP id gg13so3379981lbb.30 for ; Mon, 11 Mar 2013 11:11:21 -0700 (PDT) X-Received: by 10.112.28.101 with SMTP id a5mr5023317lbh.0.1363025481010; Mon, 11 Mar 2013 11:11:21 -0700 (PDT) Received: from omicron.terra (c83-179-13-247.cust.tele2.se. [83.179.13.247]) by mx.google.com with ESMTPS id ng6sm7685209lab.2.2013.03.11.11.11.18 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 11 Mar 2013 11:11:19 -0700 (PDT) Received: from johan by omicron.terra with local (Exim 4.80.1) (envelope-from ) id 1UF7B7-0004dI-RR; Mon, 11 Mar 2013 19:10:29 +0100 From: Johan Hovold To: Nicolas Ferre Cc: Jean-Christophe Plagniol-Villard , Andrew Victor , Alessandro Zummo , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, rtc-linux@googlegroups.com, Johan Hovold Subject: [rtc-linux] [PATCH v2 5/5] ARM: at91: fix hanged boot Date: Mon, 11 Mar 2013 19:07:59 +0100 Message-Id: <1363025279-17615-6-git-send-email-jhovold@gmail.com> X-Mailer: git-send-email 1.8.1.5 In-Reply-To: <1363025279-17615-1-git-send-email-jhovold@gmail.com> References: <20130311180611.GF8797@localhost> <1363025279-17615-1-git-send-email-jhovold@gmail.com> X-Original-Sender: jhovold@gmail.com X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of jhovold@gmail.com designates 209.85.217.171 as permitted sender) smtp.mail=jhovold@gmail.com; dkim=pass header.i=@gmail.com Reply-To: rtc-linux@googlegroups.com Precedence: list Mailing-list: list rtc-linux@googlegroups.com; contact rtc-linux+owners@googlegroups.com List-ID: X-Google-Group-Id: 712029733259 List-Post: , List-Help: , List-Archive: Sender: rtc-linux@googlegroups.com List-Subscribe: , List-Unsubscribe: , Make sure the RTC and RTT-interrupts are masked at boot by adding a new SOC-initialiser and helpers functions. This fixes hanged boot on all AT91 SOCs but RM9200, for example, after a reset during an RTC-update or if an RTC or RTT-alarm goes off after a non-clean shutdown. The RTC and RTT-peripherals are powered by backup power (VDDBU) (on all AT91 SOCs but RM9200) and are not reset on wake-up, user, watchdog or software reset. This means that their interrupts may be enabled during early boot if, for example, they where not disabled during a previous shutdown (e.g. due to a buggy driver or a non-clean shutdown such as a user reset). Furthermore, an RTC or RTT-alarm may also be active. The RTC and RTT-interrupts use the shared system-interrupt line, and if an interrupt occurs before a handler (e.g. RTC-driver) has been installed this leads to the system interrupt being disabled and prevents the system from booting. Note that when boot hangs due to an early RTC or RTT-interrupt, the only way to get the system to start again is to remove the backup power (e.g. battery) or to disable the interrupt manually from the bootloader. In particular, a user reset is not sufficient. Tested on at91sam9263 and at91sam9g45. Signed-off-by: Johan Hovold --- arch/arm/mach-at91/at91sam9260.c | 6 +++ arch/arm/mach-at91/at91sam9261.c | 6 +++ arch/arm/mach-at91/at91sam9263.c | 7 ++++ arch/arm/mach-at91/at91sam9g45.c | 7 ++++ arch/arm/mach-at91/at91sam9rl.c | 7 ++++ arch/arm/mach-at91/generic.h | 2 + arch/arm/mach-at91/setup.c | 88 ++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-at91/soc.h | 1 + 8 files changed, 124 insertions(+) diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index b67cd53..c47a0db 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -342,6 +342,11 @@ static void __init at91sam9260_ioremap_registers(void) at91_ioremap_matrix(AT91SAM9260_BASE_MATRIX); } +static void __init at91sam9260_sysirq_mask(void) +{ + at91_sysirq_mask_rtt(AT91SAM9260_BASE_RTT); +} + static void __init at91sam9260_initialize(void) { arm_pm_idle = at91sam9_idle; @@ -400,5 +405,6 @@ AT91_SOC_START(sam9260) .default_irq_priority = at91sam9260_default_irq_priority, .ioremap_registers = at91sam9260_ioremap_registers, .register_clocks = at91sam9260_register_clocks, + .sysirq_mask = at91sam9260_sysirq_mask, .init = at91sam9260_initialize, AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 0204f4c..396e4cb 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -286,6 +286,11 @@ static void __init at91sam9261_ioremap_registers(void) at91_ioremap_matrix(AT91SAM9261_BASE_MATRIX); } +static void __init at91sam9261_sysirq_mask(void) +{ + at91_sysirq_mask_rtt(AT91SAM9261_BASE_RTT); +} + static void __init at91sam9261_initialize(void) { arm_pm_idle = at91sam9_idle; @@ -344,5 +349,6 @@ AT91_SOC_START(sam9261) .default_irq_priority = at91sam9261_default_irq_priority, .ioremap_registers = at91sam9261_ioremap_registers, .register_clocks = at91sam9261_register_clocks, + .sysirq_mask = at91sam9261_sysirq_mask, .init = at91sam9261_initialize, AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index c0cbb81..a0166a3 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -325,6 +325,12 @@ static void __init at91sam9263_ioremap_registers(void) at91_ioremap_matrix(AT91SAM9263_BASE_MATRIX); } +static void __init at91sam9263_sysirq_mask(void) +{ + at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT0); + at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT1); +} + static void __init at91sam9263_initialize(void) { arm_pm_idle = at91sam9_idle; @@ -382,5 +388,6 @@ AT91_SOC_START(sam9263) .default_irq_priority = at91sam9263_default_irq_priority, .ioremap_registers = at91sam9263_ioremap_registers, .register_clocks = at91sam9263_register_clocks, + .sysirq_mask = at91sam9263_sysirq_mask, .init = at91sam9263_initialize, AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index b4968aa..3d5498e 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -370,6 +370,12 @@ static void __init at91sam9g45_ioremap_registers(void) at91_ioremap_matrix(AT91SAM9G45_BASE_MATRIX); } +static void __init at91sam9g45_sysirq_mask(void) +{ + at91_sysirq_mask_rtc(AT91SAM9G45_BASE_RTC); + at91_sysirq_mask_rtt(AT91SAM9G45_BASE_RTT); +} + static void __init at91sam9g45_initialize(void) { arm_pm_idle = at91sam9_idle; @@ -427,5 +433,6 @@ AT91_SOC_START(sam9g45) .default_irq_priority = at91sam9g45_default_irq_priority, .ioremap_registers = at91sam9g45_ioremap_registers, .register_clocks = at91sam9g45_register_clocks, + .sysirq_mask = at91sam9g45_sysirq_mask, .init = at91sam9g45_initialize, AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index 3de3e04..bde999f 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -289,6 +289,12 @@ static void __init at91sam9rl_ioremap_registers(void) at91_ioremap_matrix(AT91SAM9RL_BASE_MATRIX); } +static void __init at91sam9rl_sysirq_mask(void) +{ + at91_sysirq_mask_rtc(AT91SAM9RL_BASE_RTC); + at91_sysirq_mask_rtt(AT91SAM9RL_BASE_RTT); +} + static void __init at91sam9rl_initialize(void) { arm_pm_idle = at91sam9_idle; @@ -346,5 +352,6 @@ AT91_SOC_START(sam9rl) .default_irq_priority = at91sam9rl_default_irq_priority, .ioremap_registers = at91sam9rl_ioremap_registers, .register_clocks = at91sam9rl_register_clocks, + .sysirq_mask = at91sam9rl_sysirq_mask, .init = at91sam9rl_initialize, AT91_SOC_END diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index fc593d6..90a854d 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -33,6 +33,8 @@ extern int __init at91_aic_of_init(struct device_node *node, struct device_node *parent); extern int __init at91_aic5_of_init(struct device_node *node, struct device_node *parent); +extern void __init at91_sysirq_mask_rtc(u32 rtc_base); +extern void __init at91_sysirq_mask_rtt(u32 rtt_base); /* Timer */ diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 4b67847..4c5790f 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include "at91_shdwc.h" #include "soc.h" @@ -311,6 +313,39 @@ void __init at91_ioremap_matrix(u32 base_addr) panic("Impossible to ioremap at91_matrix_base\n"); } +void __init __at91_sysirq_mask_rtc(void __iomem *rtc_base) +{ + u32 mask; + + mask = __raw_readl(rtc_base + AT91_RTC_IMR); + if (mask) { + pr_info("AT91: Disabling rtc irq\n"); + __raw_writel(mask, rtc_base + AT91_RTC_IDR); + } +} + +void __init __at91_sysirq_mask_rtt(void __iomem *rtt_base) +{ + u32 mr; + + mr = __raw_readl(rtt_base + AT91_RTT_MR); + if (mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)) { + pr_info("AT91: Disabling rtt irq\n"); + mr &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); + __raw_writel(mr, rtt_base + AT91_RTT_MR); + } +} + +void __init at91_sysirq_mask_rtc(u32 rtc_base) +{ + __at91_sysirq_mask_rtc(AT91_IO_P2V(rtc_base)); +} + +void __init at91_sysirq_mask_rtt(u32 rtt_base) +{ + __at91_sysirq_mask_rtt(AT91_IO_P2V(rtt_base)); +} + #if defined(CONFIG_OF) static struct of_device_id rstc_ids[] = { { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_alt_restart }, @@ -440,6 +475,54 @@ end: of_node_put(np); } +static struct of_device_id sysirq_mask_rtc_ids[] = { + { .compatible = "atmel,at91sam9g45-rtc" }, + { /* sentinel */ } +}; + +static void at91_dt_sysirq_mask_rtc(void) +{ + struct device_node *np; + void __iomem *base; + + for_each_matching_node(np, sysirq_mask_rtc_ids) { + base = of_iomap(np, 0); + if (!base) { + pr_warn("AT91: unable to map rtc cpu registers\n"); + continue; + } + __at91_sysirq_mask_rtc(base); + iounmap(base); + } +} + +static struct of_device_id sysirq_mask_rtt_ids[] = { + { .compatible = "atmel,at91sam9260-rtt" }, + { /* sentinel */ } +}; + +static void at91_dt_sysirq_mask_rtt(void) +{ + struct device_node *np; + void __iomem *base; + + for_each_matching_node(np, sysirq_mask_rtt_ids) { + base = of_iomap(np, 0); + if (!base) { + pr_warn("AT91: unable to map rtt cpu registers\n"); + continue; + } + __at91_sysirq_mask_rtt(base); + iounmap(base); + } +} + +static void at91_dt_sysirq_mask(void) +{ + at91_dt_sysirq_mask_rtc(); + at91_dt_sysirq_mask_rtt(); +} + void __init at91rm9200_dt_initialize(void) { at91_dt_ramc(); @@ -467,6 +550,8 @@ void __init at91_dt_initialize(void) if (at91_boot_soc.init) at91_boot_soc.init(); + + at91_dt_sysirq_mask(); } #endif @@ -482,5 +567,8 @@ void __init at91_initialize(unsigned long main_clock) at91_boot_soc.init(); + if (at91_boot_soc.sysirq_mask) + at91_boot_soc.sysirq_mask(); + pinctrl_provide_dummies(); } diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h index 9c6d3d4..134f4c4 100644 --- a/arch/arm/mach-at91/soc.h +++ b/arch/arm/mach-at91/soc.h @@ -10,6 +10,7 @@ struct at91_init_soc { void (*map_io)(void); void (*ioremap_registers)(void); void (*register_clocks)(void); + void (*sysirq_mask)(void); void (*init)(void); };