From 75da01e127f7db3b23effa6118336d303e7572a7 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 31 Jan 2013 11:25:52 +0000 Subject: ARM: KVM: vgic: force EOIed LRs to the empty state The VGIC doesn't guarantee that an EOIed LR that has been configured to generate a maintenance interrupt will appear as empty. While the code recovers from this situation, it is better to clean the LR and flag it as empty so it can be quickly recycled. Signed-off-by: Marc Zyngier --- arch/arm/kvm/vgic.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c index c9a17316e9fe..76ea1aa5e7d2 100644 --- a/arch/arm/kvm/vgic.c +++ b/arch/arm/kvm/vgic.c @@ -883,8 +883,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) lr, irq, vgic_cpu->vgic_lr[lr]); BUG_ON(!test_bit(lr, vgic_cpu->lr_used)); vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT; - - goto out; + return true; } /* Try to use another LR for this interrupt */ @@ -898,7 +897,6 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) vgic_cpu->vgic_irq_lr_map[irq] = lr; set_bit(lr, vgic_cpu->lr_used); -out: if (!vgic_irq_is_edge(vcpu, irq)) vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI; @@ -1054,6 +1052,13 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) } else { vgic_cpu_irq_clear(vcpu, irq); } + + /* + * Despite being EOIed, the LR may not have + * been marked as empty. + */ + set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr); + vgic_cpu->vgic_lr[lr] &= ~GICH_LR_ACTIVE_BIT; } } -- cgit v1.2.3 From 33c83cb3c1d84b76c8270abe5487e77f83a81b22 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 1 Feb 2013 18:28:30 +0000 Subject: ARM: KVM: vgic: take distributor lock on sync_hwstate path Now that the maintenance interrupt handling is actually out of the handler itself, the code becomes quite racy as we can get preempted while we process the state. Wrapping this code around the distributor lock ensures that we're not preempted and relatively race-free. Signed-off-by: Marc Zyngier --- arch/arm/kvm/vgic.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c index 76ea1aa5e7d2..0e4cfe123b38 100644 --- a/arch/arm/kvm/vgic.c +++ b/arch/arm/kvm/vgic.c @@ -1016,21 +1016,6 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) kvm_debug("MISR = %08x\n", vgic_cpu->vgic_misr); - /* - * We do not need to take the distributor lock here, since the only - * action we perform is clearing the irq_active_bit for an EOIed - * level interrupt. There is a potential race with - * the queuing of an interrupt in __kvm_vgic_flush_hwstate(), where we - * check if the interrupt is already active. Two possibilities: - * - * - The queuing is occurring on the same vcpu: cannot happen, - * as we're already in the context of this vcpu, and - * executing the handler - * - The interrupt has been migrated to another vcpu, and we - * ignore this interrupt for this run. Big deal. It is still - * pending though, and will get considered when this vcpu - * exits. - */ if (vgic_cpu->vgic_misr & GICH_MISR_EOI) { /* * Some level interrupts have been EOIed. Clear their @@ -1069,9 +1054,8 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) } /* - * Sync back the VGIC state after a guest run. We do not really touch - * the distributor here (the irq_pending_on_cpu bit is safe to set), - * so there is no need for taking its lock. + * Sync back the VGIC state after a guest run. The distributor lock is + * needed so we don't get preempted in the middle of the state processing. */ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu) { @@ -1117,10 +1101,14 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu) void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu) { + struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + if (!irqchip_in_kernel(vcpu->kvm)) return; + spin_lock(&dist->lock); __kvm_vgic_sync_hwstate(vcpu); + spin_unlock(&dist->lock); } int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu) -- cgit v1.2.3 From 97916777d6904e24b86eac77da58ef7cb09d539d Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Fri, 28 Dec 2012 10:37:27 -0800 Subject: ARM: EXYNOS: skip wakeup interrupt registration for exynos5250 if pinctrl is enabled Skip the wakeup interrupt registration for Exynos5250 if pinctrl support is enabled for Exynos5250. Signed-off-by: Thomas Abraham Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index d63d399c7bae..bdd957978d9b 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -822,6 +822,7 @@ static int __init exynos_init_irq_eint(void) static const struct of_device_id exynos_pinctrl_ids[] = { { .compatible = "samsung,exynos4210-pinctrl", }, { .compatible = "samsung,exynos4x12-pinctrl", }, + { .compatible = "samsung,exynos5250-pinctrl", }, }; struct device_node *pctrl_np, *wkup_np; const char *wkup_compat = "samsung,exynos4210-wakeup-eint"; -- cgit v1.2.3 From 13872ebb915b547b3c0a1fc04f549a1475bb7989 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 13 Mar 2013 04:10:57 -0600 Subject: ARM: OMAP1: fix USB host on 1710 There is a long-standing bug that OHCI USB host controller does not respond on 1710, because of wrong clock definitions. See e.g. http://marc.info/?l=linux-omap&m=119634441229321&w=2. All register reads return just zeroes: [ 1.896606] ohci ohci: OMAP OHCI [ 1.912597] ohci ohci: new USB bus registered, assigned bus number 1 [ 1.933776] ohci ohci: irq 38, io mem 0xfffba000 [ 2.012573] ohci ohci: init err (00000000 0000) [ 2.030334] ohci ohci: can't start [ 2.046661] ohci ohci: startup error -75 [ 2.063201] ohci ohci: USB bus 1 deregistered After some experiments, it seems that when changing the usb_dc_ck / SOFT_REQ enable bit from USB_REQ_EN_SHIFT to SOFT_USB_OTG_DPLL_REQ_SHIFT (like done also on 7XX), the USB appears to work: [ 2.183959] ohci ohci: OMAP OHCI [ 2.198242] ohci ohci: new USB bus registered, assigned bus number 1 [ 2.215820] ohci ohci: irq 38, io mem 0xfffba000 [ 2.324798] hub 1-0:1.0: USB hub found [ 2.361267] hub 1-0:1.0: 3 ports detected The patch is tested on Nokia 770. Signed-off-by: Aaro Koskinen Signed-off-by: Paul Walmsley --- arch/arm/mach-omap1/clock_data.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c index cb7c6ae2e3fc..6c4f766365a2 100644 --- a/arch/arm/mach-omap1/clock_data.c +++ b/arch/arm/mach-omap1/clock_data.c @@ -538,15 +538,6 @@ static struct clk usb_hhc_ck16xx = { }; static struct clk usb_dc_ck = { - .name = "usb_dc_ck", - .ops = &clkops_generic, - /* Direct from ULPD, no parent */ - .rate = 48000000, - .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG), - .enable_bit = USB_REQ_EN_SHIFT, -}; - -static struct clk usb_dc_ck7xx = { .name = "usb_dc_ck", .ops = &clkops_generic, /* Direct from ULPD, no parent */ @@ -727,8 +718,7 @@ static struct omap_clk omap_clks[] = { CLK(NULL, "usb_clko", &usb_clko, CK_16XX | CK_1510 | CK_310), CLK(NULL, "usb_hhc_ck", &usb_hhc_ck1510, CK_1510 | CK_310), CLK(NULL, "usb_hhc_ck", &usb_hhc_ck16xx, CK_16XX), - CLK(NULL, "usb_dc_ck", &usb_dc_ck, CK_16XX), - CLK(NULL, "usb_dc_ck", &usb_dc_ck7xx, CK_7XX), + CLK(NULL, "usb_dc_ck", &usb_dc_ck, CK_16XX | CK_7XX), CLK(NULL, "mclk", &mclk_1510, CK_1510 | CK_310), CLK(NULL, "mclk", &mclk_16xx, CK_16XX), CLK(NULL, "bclk", &bclk_1510, CK_1510 | CK_310), -- cgit v1.2.3 From 71b37071f02e20345dcc0d570c69896da795e1e6 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 13 Mar 2013 04:11:23 -0600 Subject: ARM: OMAP4: clock data: lock USB DPLL on boot Some versions of the u-boot bootloader do not lock the USB DPLL and when the USB DPLL is not locked, then it is observed that the L3INIT power domain does not transition to retention state during kernel suspend on OMAP4 devices. Fix this by locking the USB DPLL at 960 MHz on kernel boot. Signed-off-by: Jon Hunter Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/cclock44xx_data.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c index 3d58f335f173..015bcdc34b4a 100644 --- a/arch/arm/mach-omap2/cclock44xx_data.c +++ b/arch/arm/mach-omap2/cclock44xx_data.c @@ -52,6 +52,13 @@ */ #define OMAP4_DPLL_ABE_DEFFREQ 98304000 +/* + * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section + * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred + * locked frequency for the USB DPLL is 960MHz. + */ +#define OMAP4_DPLL_USB_DEFFREQ 960000000 + /* Root clocks */ DEFINE_CLK_FIXED_RATE(extalt_clkin_ck, CLK_IS_ROOT, 59000000, 0x0); @@ -1705,5 +1712,13 @@ int __init omap4xxx_clk_init(void) if (rc) pr_err("%s: failed to configure ABE DPLL!\n", __func__); + /* + * Lock USB DPLL on OMAP4 devices so that the L3INIT power + * domain can transition to retention state when not in use. + */ + rc = clk_set_rate(&dpll_usb_ck, OMAP4_DPLL_USB_DEFFREQ); + if (rc) + pr_err("%s: failed to configure USB DPLL!\n", __func__); + return 0; } -- cgit v1.2.3 From 092bc089c249de0fa0f0c98b28dea6e5f1367b6e Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Mon, 11 Mar 2013 21:49:00 +0200 Subject: ARM: OMAP3: hwmod data: keep MIDLEMODE in force-standby for musb For some unknown reason, allowing hwmod to control MIDLEMODE causes core_pwrdm to not hit idle states for musb in DM3730 at least. I've verified that setting any MIDLEMODE value other than "force standby" before enabling the device causes subsequent suspend attempts to fail with core_pwrdm not entering idle states, even if the driver is unloaded and "force standby" is restored before suspend attempt. To recover from this, soft reset can be used, but that's not suitable solution for suspend. Keeping the register set at force standby (reset value) makes it work and device still functions properly, as musb has driver-controlled OTG_FORCESTDBY register that controls MSTANDBY signal. Note that TI PSP kernels also have similar workarounds. This patch also fixes HWMOD_SWSUP_MSTANDBY documentation to match the actual flag name. Signed-off-by: Grazvydas Ignotas Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 7 +++++-- arch/arm/mach-omap2/omap_hwmod.h | 9 +++++++-- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 7 ++++++- 3 files changed, 18 insertions(+), 5 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index c2c798c08c2b..a202a4785104 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1368,7 +1368,9 @@ static void _enable_sysc(struct omap_hwmod *oh) } if (sf & SYSC_HAS_MIDLEMODE) { - if (oh->flags & HWMOD_SWSUP_MSTANDBY) { + if (oh->flags & HWMOD_FORCE_MSTANDBY) { + idlemode = HWMOD_IDLEMODE_FORCE; + } else if (oh->flags & HWMOD_SWSUP_MSTANDBY) { idlemode = HWMOD_IDLEMODE_NO; } else { if (sf & SYSC_HAS_ENAWAKEUP) @@ -1440,7 +1442,8 @@ static void _idle_sysc(struct omap_hwmod *oh) } if (sf & SYSC_HAS_MIDLEMODE) { - if (oh->flags & HWMOD_SWSUP_MSTANDBY) { + if ((oh->flags & HWMOD_SWSUP_MSTANDBY) || + (oh->flags & HWMOD_FORCE_MSTANDBY)) { idlemode = HWMOD_IDLEMODE_FORCE; } else { if (sf & SYSC_HAS_ENAWAKEUP) diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h index d43d9b608eda..d5dc935f6060 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -427,8 +427,8 @@ struct omap_hwmod_omap4_prcm { * * HWMOD_SWSUP_SIDLE: omap_hwmod code should manually bring module in and out * of idle, rather than relying on module smart-idle - * HWMOD_SWSUP_MSTDBY: omap_hwmod code should manually bring module in and out - * of standby, rather than relying on module smart-standby + * HWMOD_SWSUP_MSTANDBY: omap_hwmod code should manually bring module in and + * out of standby, rather than relying on module smart-standby * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for * SDRAM controller, etc. XXX probably belongs outside the main hwmod file * XXX Should be HWMOD_SETUP_NO_RESET @@ -459,6 +459,10 @@ struct omap_hwmod_omap4_prcm { * correctly, or this is being abused to deal with some PM latency * issues -- but we're currently suffering from a shortage of * folks who are able to track these issues down properly. + * HWMOD_FORCE_MSTANDBY: Always keep MIDLEMODE bits cleared so that device + * is kept in force-standby mode. Failing to do so causes PM problems + * with musb on OMAP3630 at least. Note that musb has a dedicated register + * to control MSTANDBY signal when MIDLEMODE is set to force-standby. */ #define HWMOD_SWSUP_SIDLE (1 << 0) #define HWMOD_SWSUP_MSTANDBY (1 << 1) @@ -471,6 +475,7 @@ struct omap_hwmod_omap4_prcm { #define HWMOD_16BIT_REG (1 << 8) #define HWMOD_EXT_OPT_MAIN_CLK (1 << 9) #define HWMOD_BLOCK_WFI (1 << 10) +#define HWMOD_FORCE_MSTANDBY (1 << 11) /* * omap_hwmod._int_flags definitions diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index ac7e03ec952f..5112d04e7b79 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1707,9 +1707,14 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = { * Erratum ID: i479 idle_req / idle_ack mechanism potentially * broken when autoidle is enabled * workaround is to disable the autoidle bit at module level. + * + * Enabling the device in any other MIDLEMODE setting but force-idle + * causes core_pwrdm not enter idle states at least on OMAP3630. + * Note that musb has OTG_FORCESTDBY register that controls MSTANDBY + * signal when MIDLEMODE is set to force-idle. */ .flags = HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE - | HWMOD_SWSUP_MSTANDBY, + | HWMOD_FORCE_MSTANDBY, }; /* usb_otg_hs */ -- cgit v1.2.3 From 92702df3570e1ccfa050e135e50c450502251b79 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 12 Feb 2013 20:28:12 +0000 Subject: ARM: OMAP4: PM: fix PM regression introduced by recent clock cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 17b7e7d33530e2bbd3bdc90f4db09b91cfdde2bb ("ARM: OMAP4: clock/hwmod data: start to remove some IP block control "clocks"") introduced a regression preventing the L3INIT clockdomain of OMAP4 systems from entering idle. This in turn prevented these systems from entering full chip clock-stop. The regression was caused by the incorrect removal of a so-called "optional functional clock" from the OMAP4 clock data. This wasn't caught for two reasons. First, I missed the retention entry failure in the branch test logs: http://www.pwsan.com/omap/testlogs/cleanup_a_3.9/20130126014242/pm/4460pandaes/4460pandaes_log.txt Second, the integration data for the OCP2SCP PHY IP block, added by commit 0c6688753f9912c6a7013549ec31c8844020bbc1 ("ARM: OMAP4: hwmod data: add remaining USB-related IP blocks"), should have associated this clock with the IP block, but did not. Fix by adding back the so-called "optional" functional clock to the clock data, and by linking that clock to the OCP2SCP PHY IP block integration hwmod data. The problem patch was discovered by J, Keerthy . Cc: Keerthy Cc: BenoƮt Cousson Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/cclock44xx_data.c | 5 +++++ arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c index 015bcdc34b4a..0c6834ae1fc4 100644 --- a/arch/arm/mach-omap2/cclock44xx_data.c +++ b/arch/arm/mach-omap2/cclock44xx_data.c @@ -1018,6 +1018,10 @@ DEFINE_CLK_OMAP_MUX(hsmmc2_fclk, "l3_init_clkdm", hsmmc1_fclk_sel, OMAP4430_CM_L3INIT_MMC2_CLKCTRL, OMAP4430_CLKSEL_MASK, hsmmc1_fclk_parents, func_dmic_abe_gfclk_ops); +DEFINE_CLK_GATE(ocp2scp_usb_phy_phy_48m, "func_48m_fclk", &func_48m_fclk, 0x0, + OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, + OMAP4430_OPTFCLKEN_PHY_48M_SHIFT, 0x0, NULL); + DEFINE_CLK_GATE(sha2md5_fck, "l3_div_ck", &l3_div_ck, 0x0, OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); @@ -1545,6 +1549,7 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "per_mcbsp4_gfclk", &per_mcbsp4_gfclk, CK_443X), CLK(NULL, "hsmmc1_fclk", &hsmmc1_fclk, CK_443X), CLK(NULL, "hsmmc2_fclk", &hsmmc2_fclk, CK_443X), + CLK(NULL, "ocp2scp_usb_phy_phy_48m", &ocp2scp_usb_phy_phy_48m, CK_443X), CLK(NULL, "sha2md5_fck", &sha2md5_fck, CK_443X), CLK(NULL, "slimbus1_fclk_1", &slimbus1_fclk_1, CK_443X), CLK(NULL, "slimbus1_fclk_0", &slimbus1_fclk_0, CK_443X), diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 0e47d2e1687c..9e0576569e07 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -2714,6 +2714,10 @@ static struct omap_ocp2scp_dev ocp2scp_dev_attr[] = { { } }; +static struct omap_hwmod_opt_clk ocp2scp_usb_phy_opt_clks[] = { + { .role = "48mhz", .clk = "ocp2scp_usb_phy_phy_48m" }, +}; + /* ocp2scp_usb_phy */ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = { .name = "ocp2scp_usb_phy", @@ -2728,6 +2732,8 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = { }, }, .dev_attr = ocp2scp_dev_attr, + .opt_clks = ocp2scp_usb_phy_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(ocp2scp_usb_phy_opt_clks), }; /* -- cgit v1.2.3 From 605c357bb40ce412c086f3a928d07c1d4349b95b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 15 Mar 2013 19:16:52 -0500 Subject: ARM: ep93xx: Fix wait for UART FIFO to be empty Commit 210dce5f "ARM: ep93xx: properly wait for UART FIFO to be empty" Removed the timeout loop while waiting for the uart transmit fifo to empty. Some bootloaders leave the uart in a state where there might be bytes in the uart that are not transmitted when execution is handed over to the kernel. This results in a deadlocked system while waiting for the fifo to empty. Add back the timeout wait to prevent the deadlock. Increase the wait time to hopefully prevent the decompressor corruption that lead to commit 210dce5f. This corruption was probably due to a slow uart baudrate. The 10* increase in the wait time should be enough for all cases. Signed-off-by: H Hartley Sweeten Acked-by: Florian Fainelli Signed-off-by: Ryan Mallon --- arch/arm/mach-ep93xx/include/mach/uncompress.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-ep93xx/include/mach/uncompress.h b/arch/arm/mach-ep93xx/include/mach/uncompress.h index d2afb4dd82ab..b5cc77d2380b 100644 --- a/arch/arm/mach-ep93xx/include/mach/uncompress.h +++ b/arch/arm/mach-ep93xx/include/mach/uncompress.h @@ -47,9 +47,13 @@ static void __raw_writel(unsigned int value, unsigned int ptr) static inline void putc(int c) { - /* Transmit fifo not full? */ - while (__raw_readb(PHYS_UART_FLAG) & UART_FLAG_TXFF) - ; + int i; + + for (i = 0; i < 10000; i++) { + /* Transmit fifo not full? */ + if (!(__raw_readb(PHYS_UART_FLAG) & UART_FLAG_TXFF)) + break; + } __raw_writeb(c, PHYS_UART_DATA); } -- cgit v1.2.3 From e651eab0af88aa7a281fe9e8c36c0846552aa7fc Mon Sep 17 00:00:00 2001 From: Sricharan R Date: Mon, 18 Mar 2013 12:24:04 +0100 Subject: ARM: 7677/1: LPAE: Fix mapping in alloc_init_section for unaligned addresses With LPAE enabled, alloc_init_section() does not map the entire address space for unaligned addresses. The issue also reproduced with CMA + LPAE. CMA tries to map 16MB with page granularity mappings during boot. alloc_init_pte() is called and out of 16MB, only 2MB gets mapped and rest remains unaccessible. Because of this OMAP5 boot is broken with CMA + LPAE enabled. Fix the issue by ensuring that the entire addresses are mapped. Signed-off-by: R Sricharan Cc: Catalin Marinas Cc: Christoffer Dall Cc: Santosh Shilimkar Tested-by: Laura Abbott Acked-by: Catalin Marinas Acked-by: Christoffer Dall Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 73 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 26 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index e95a996ab78f..78978945492a 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -598,39 +598,60 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, } while (pte++, addr += PAGE_SIZE, addr != end); } -static void __init alloc_init_section(pud_t *pud, unsigned long addr, - unsigned long end, phys_addr_t phys, - const struct mem_type *type) +static void __init map_init_section(pmd_t *pmd, unsigned long addr, + unsigned long end, phys_addr_t phys, + const struct mem_type *type) { - pmd_t *pmd = pmd_offset(pud, addr); - +#ifndef CONFIG_ARM_LPAE /* - * Try a section mapping - end, addr and phys must all be aligned - * to a section boundary. Note that PMDs refer to the individual - * L1 entries, whereas PGDs refer to a group of L1 entries making - * up one logical pointer to an L2 table. + * In classic MMU format, puds and pmds are folded in to + * the pgds. pmd_offset gives the PGD entry. PGDs refer to a + * group of L1 entries making up one logical pointer to + * an L2 table (2MB), where as PMDs refer to the individual + * L1 entries (1MB). Hence increment to get the correct + * offset for odd 1MB sections. + * (See arch/arm/include/asm/pgtable-2level.h) */ - if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) { - pmd_t *p = pmd; - -#ifndef CONFIG_ARM_LPAE - if (addr & SECTION_SIZE) - pmd++; + if (addr & SECTION_SIZE) + pmd++; #endif + do { + *pmd = __pmd(phys | type->prot_sect); + phys += SECTION_SIZE; + } while (pmd++, addr += SECTION_SIZE, addr != end); - do { - *pmd = __pmd(phys | type->prot_sect); - phys += SECTION_SIZE; - } while (pmd++, addr += SECTION_SIZE, addr != end); + flush_pmd_entry(pmd); +} - flush_pmd_entry(p); - } else { +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, + unsigned long end, phys_addr_t phys, + const struct mem_type *type) +{ + pmd_t *pmd = pmd_offset(pud, addr); + unsigned long next; + + do { /* - * No need to loop; pte's aren't interested in the - * individual L1 entries. + * With LPAE, we must loop over to map + * all the pmds for the given range. */ - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type); - } + next = pmd_addr_end(addr, end); + + /* + * Try a section mapping - addr, next and phys must all be + * aligned to a section boundary. + */ + if (type->prot_sect && + ((addr | next | phys) & ~SECTION_MASK) == 0) { + map_init_section(pmd, addr, next, phys, type); + } else { + alloc_init_pte(pmd, addr, next, + __phys_to_pfn(phys), type); + } + + phys += next - addr; + + } while (pmd++, addr = next, addr != end); } static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, @@ -641,7 +662,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, do { next = pud_addr_end(addr, end); - alloc_init_section(pud, addr, next, phys, type); + alloc_init_pmd(pud, addr, next, phys, type); phys += next - addr; } while (pud++, addr = next, addr != end); } -- cgit v1.2.3 From c40e3641670eb6ebfdb71d4b0c775416ef95f4f0 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 18 Mar 2013 19:44:14 +0100 Subject: ARM: 7679/1: Clear IDIVT hwcap if CONFIG_ARM_THUMB=n Don't advertise support for the SDIV/UDIV thumb instructions if the kernel is not compiled with support for thumb userspace. This is in line with how we remove the THUMB hwcap in these configurations. Acked-by: Will Deacon Cc: Stepan Moskovchenko Signed-off-by: Stephen Boyd Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 3f6cbb2e3eda..e2c8bbffb0b1 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -484,7 +484,7 @@ static void __init setup_processor(void) list->elf_name, ENDIANNESS); elf_hwcap = list->elf_hwcap; #ifndef CONFIG_ARM_THUMB - elf_hwcap &= ~HWCAP_THUMB; + elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT); #endif feat_v6_fixup(); -- cgit v1.2.3 From 8164f7af88d9ad3a757bd14f634b23997ee77f6b Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 18 Mar 2013 19:44:15 +0100 Subject: ARM: 7680/1: Detect support for SDIV/UDIV from ISAR0 register The ISAR0 register indicates support for the SDIV and UDIV instructions in both the Thumb and ARM instruction set. Read the register to detect the supported instructions and update the elf_hwcap mask as appropriate. This is better than adding more and more cpuid checks in proc-v7.S for each new cpu variant that supports these instructions. Acked-by: Will Deacon Cc: Stepan Moskovchenko Signed-off-by: Stephen Boyd Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 20 ++++++++++++++++++++ arch/arm/mm/proc-v7.S | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index e2c8bbffb0b1..f3ac13f69b7a 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -353,6 +353,23 @@ void __init early_print(const char *str, ...) printk("%s", buf); } +static void __init cpuid_init_hwcaps(void) +{ + unsigned int divide_instrs; + + if (cpu_architecture() < CPU_ARCH_ARMv7) + return; + + divide_instrs = (read_cpuid_ext(CPUID_EXT_ISAR0) & 0x0f000000) >> 24; + + switch (divide_instrs) { + case 2: + elf_hwcap |= HWCAP_IDIVA; + case 1: + elf_hwcap |= HWCAP_IDIVT; + } +} + static void __init feat_v6_fixup(void) { int id = read_cpuid_id(); @@ -483,6 +500,9 @@ static void __init setup_processor(void) snprintf(elf_platform, ELF_PLATFORM_SIZE, "%s%c", list->elf_name, ENDIANNESS); elf_hwcap = list->elf_hwcap; + + cpuid_init_hwcaps(); + #ifndef CONFIG_ARM_THUMB elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT); #endif diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 3a3c015f8d5c..bcd3d48922fb 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -420,7 +420,7 @@ __v7_pj4b_proc_info: __v7_ca7mp_proc_info: .long 0x410fc070 .long 0xff0ffff0 - __v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV + __v7_proc __v7_ca7mp_setup .size __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info /* @@ -430,7 +430,7 @@ __v7_ca7mp_proc_info: __v7_ca15mp_proc_info: .long 0x410fc0f0 .long 0xff0ffff0 - __v7_proc __v7_ca15mp_setup, hwcaps = HWCAP_IDIV + __v7_proc __v7_ca15mp_setup .size __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info /* -- cgit v1.2.3 From 120ecfafabec382c4feb79ff159ef42a39b6d33b Mon Sep 17 00:00:00 2001 From: Stepan Moskovchenko Date: Mon, 18 Mar 2013 19:44:16 +0100 Subject: ARM: 7678/1: Work around faulty ISAR0 register in some Krait CPUs Some early versions of the Krait CPU design incorrectly indicate that they only support the UDIV and SDIV instructions in Thumb mode when they actually support them in ARM and Thumb mode. It seems that these CPUs follow the DDI0406B ARM ARM which has two possible values for the divide instructions field, instead of the DDI0406C document which has three possible values. Work around this problem by checking the MIDR against Krait CPUs with this faulty ISAR0 register and force the hwcaps to indicate support in both modes. [sboyd: Rewrote commit text to reflect real reasoning now that we autodetect udiv/sdiv] Signed-off-by: Stepan Moskovchenko Acked-by: Will Deacon Signed-off-by: Stephen Boyd Signed-off-by: Russell King --- arch/arm/mm/proc-v7.S | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index bcd3d48922fb..f584d3f5b37c 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -433,6 +433,21 @@ __v7_ca15mp_proc_info: __v7_proc __v7_ca15mp_setup .size __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info + /* + * Qualcomm Inc. Krait processors. + */ + .type __krait_proc_info, #object +__krait_proc_info: + .long 0x510f0400 @ Required ID value + .long 0xff0ffc00 @ Mask for ID + /* + * Some Krait processors don't indicate support for SDIV and UDIV + * instructions in the ARM instruction set, even though they actually + * do support them. + */ + __v7_proc __v7_setup, hwcaps = HWCAP_IDIV + .size __krait_proc_info, . - __krait_proc_info + /* * Match any ARMv7 processor core. */ -- cgit v1.2.3 From 68a154fc53ddd3f7b33e482847a411bf54a50855 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Wed, 20 Mar 2013 17:30:30 +0100 Subject: ARM: 7681/1: hw_breakpoint: use warn_once to avoid spam from reset_ctrl_regs() CPU debug features like hardware break, watchpoints can be used only when the debug mode is enabled and available. Unfortunately on OMAP4 based devices, after a CPU power cycle, the debug feature gets disabled which leads to a flood of messages coming from reset_ctrl_regs() which gets called on every CPU_PM_EXIT with CPUidle enabled. So make use of warn_once() so that system is usable. Thanks to Will for pointers and Lokesh for the analysis of the issue. Tested-by: Lokesh Vutla Signed-off-by: Santosh Shilimkar Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/hw_breakpoint.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 96093b75ab90..5dc1aa6f0f7d 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -966,7 +966,7 @@ static void reset_ctrl_regs(void *unused) } if (err) { - pr_warning("CPU %d debug is powered down!\n", cpu); + pr_warn_once("CPU %d debug is powered down!\n", cpu); cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu)); return; } @@ -987,7 +987,7 @@ clear_vcr: isb(); if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) { - pr_warning("CPU %d failed to disable vector catch\n", cpu); + pr_warn_once("CPU %d failed to disable vector catch\n", cpu); return; } @@ -1007,7 +1007,7 @@ clear_vcr: } if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) { - pr_warning("CPU %d failed to clear debug register pairs\n", cpu); + pr_warn_once("CPU %d failed to clear debug register pairs\n", cpu); return; } -- cgit v1.2.3 From 4080d2d11a2d572228c2b8d02406e997b87ba6a5 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 14 Mar 2013 20:31:37 -0700 Subject: ARM: msm: Stop counting before reprogramming clockevent If the clockevent is forcibly reprogrammed to have a different match value we mistakenly assume the timer is not ticking and program a new match value while the timer is running. Although we clear the timer before programming a new match, it's better to stop the timer before clearing it so that we're sure the proper amount of ticks are counted. Failure to do so can lead to missed ticks and system hangs. Signed-off-by: Stephen Boyd Signed-off-by: David Brown --- arch/arm/mach-msm/timer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 2969027f02fa..f9fd77e8f1f5 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -62,7 +62,10 @@ static int msm_timer_set_next_event(unsigned long cycles, { u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); - writel_relaxed(0, event_base + TIMER_CLEAR); + ctrl &= ~TIMER_ENABLE_EN; + writel_relaxed(ctrl, event_base + TIMER_ENABLE); + + writel_relaxed(ctrl, event_base + TIMER_CLEAR); writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); return 0; -- cgit v1.2.3 From 2f3edfd7e27ad4206acbc2ae99c9df5f46353024 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 26 Mar 2013 16:46:07 +0800 Subject: ARM: imx: fix sync issue between imx_cpu_die and imx_cpu_kill There is a sync issue with hotplug operation. It's possible that when imx_cpu_kill gets running on primary core, the imx_cpu_die execution on the core which is to be killed hasn't been finished yet. The problem will very likely be hit when running suspend without no_console_suspend setting on kernel cmdline. It uses cpu jumping argument register to sync imx_cpu_die and imx_cpu_kill. The register will be set in imx_cpu_die and imx_cpu_kill will wait for the register being cleared to actually kill the cpu. Signed-off-by: Shawn Guo Cc: --- arch/arm/mach-imx/common.h | 2 ++ arch/arm/mach-imx/hotplug.c | 12 ++++++++++++ arch/arm/mach-imx/src.c | 12 ++++++++++++ 3 files changed, 26 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 5a800bfcec5b..5bf4a97ab241 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -110,6 +110,8 @@ void tzic_handle_irq(struct pt_regs *); extern void imx_enable_cpu(int cpu, bool enable); extern void imx_set_cpu_jump(int cpu, void *jump_addr); +extern u32 imx_get_cpu_arg(int cpu); +extern void imx_set_cpu_arg(int cpu, u32 arg); extern void v7_cpu_resume(void); extern u32 *pl310_get_save_ptr(void); #ifdef CONFIG_SMP diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index 7bc5fe15dda2..361a253e2b63 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c @@ -46,11 +46,23 @@ static inline void cpu_enter_lowpower(void) void imx_cpu_die(unsigned int cpu) { cpu_enter_lowpower(); + /* + * We use the cpu jumping argument register to sync with + * imx_cpu_kill() which is running on cpu0 and waiting for + * the register being cleared to kill the cpu. + */ + imx_set_cpu_arg(cpu, ~0); cpu_do_idle(); } int imx_cpu_kill(unsigned int cpu) { + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (imx_get_cpu_arg(cpu) == 0) + if (time_after(jiffies, timeout)) + return 0; imx_enable_cpu(cpu, false); + imx_set_cpu_arg(cpu, 0); return 1; } diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c index e15f1555c59b..09a742f8c7ab 100644 --- a/arch/arm/mach-imx/src.c +++ b/arch/arm/mach-imx/src.c @@ -43,6 +43,18 @@ void imx_set_cpu_jump(int cpu, void *jump_addr) src_base + SRC_GPR1 + cpu * 8); } +u32 imx_get_cpu_arg(int cpu) +{ + cpu = cpu_logical_map(cpu); + return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4); +} + +void imx_set_cpu_arg(int cpu, u32 arg) +{ + cpu = cpu_logical_map(cpu); + writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4); +} + void imx_src_prepare_restart(void) { u32 val; -- cgit v1.2.3 From ff931c821bab6713a52b768b0cd7ee7e90713b36 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 21 Mar 2013 16:34:52 +0530 Subject: ARM: OMAP: clocks: Delay clk inits atleast until slab is initialized clk inits on OMAP happen quite early, even before slab is available. The dependency comes from the fact that the timer init code starts to use clocks and hwmod and we need clocks to be initialized by then. There are various problems doing clk inits this early, one is, not being able to do dynamic clk registrations and hence the dependency on clk-private.h. The other is, inability to debug early kernel crashes without enabling DEBUG_LL and earlyprintk. Doing early clk init also exposed another instance of a kernel panic due to a BUG() when CONFIG_DEBUG_SLAB is enabled. [ 0.000000] Kernel BUG at c01174f8 [verbose debug info unavailable] [ 0.000000] Internal error: Oops - BUG: 0 [#1] SMP ARM [ 0.000000] Modules linked in: [ 0.000000] CPU: 0 Not tainted (3.9.0-rc1-12179-g72d48f9 #6) [ 0.000000] PC is at __kmalloc+0x1d4/0x248 [ 0.000000] LR is at __clk_init+0x2e0/0x364 [ 0.000000] pc : [] lr : [] psr: 600001d3 [ 0.000000] sp : c076ff28 ip : c065cefc fp : c0441f54 [ 0.000000] r10: 0000001c r9 : 000080d0 r8 : c076ffd4 [ 0.000000] r7 : c074b578 r6 : c0794d88 r5 : 00000040 r4 : 00000000 [ 0.000000] r3 : 00000000 r2 : c07cac70 r1 : 000080d0 r0 : 0000001c [ 0.000000] Flags: nZCv IRQs off FIQs off Mode SVC_32 ISA ARM Segment kernel [ 0.000000] Control: 10c53c7d Table: 8000404a DAC: 00000017 [ 0.000000] Process swapper (pid: 0, stack limit = 0xc076e240) [ 0.000000] Stack: (0xc076ff28 to 0xc0770000) [ 0.000000] ff20: 22222222 c0794ec8 c06546e8 00000000 00000040 c0794d88 [ 0.000000] ff40: c074b578 c076ffd4 c07951c8 c076e000 00000000 c0441f54 c074b578 c076ffd4 [ 0.000000] ff60: c0793828 00000040 c0794d88 c074b578 c076ffd4 c0776900 c076e000 c07272ac [ 0.000000] ff80: 2f800000 c074c968 c07f93d0 c0719780 c076ffa0 c076ff98 00000000 00000000 [ 0.000000] ffa0: 00000000 00000000 00000000 00000001 c074cd6c c077b1ec 8000406a c0715724 [ 0.000000] ffc0: 00000000 00000000 00000000 00000000 00000000 c074c968 10c53c7d c0776974 [ 0.000000] ffe0: c074cd6c c077b1ec 8000406a 411fc092 00000000 80008074 00000000 00000000 [ 0.000000] [] (__kmalloc+0x1d4/0x248) from [] (__clk_init+0x2e0/0x364) [ 0.000000] [] (__clk_init+0x2e0/0x364) from [] (omap4xxx_clk_init+0xbc/0x140) [ 0.000000] [] (omap4xxx_clk_init+0xbc/0x140) from [] (setup_arch+0x15c/0x284) [ 0.000000] [] (setup_arch+0x15c/0x284) from [] (start_kernel+0x7c/0x334) [ 0.000000] [] (start_kernel+0x7c/0x334) from [<80008074>] (0x80008074) [ 0.000000] Code: e5883004 e1a00006 e28dd00c e8bd8ff0 (e7f001f2) [ 0.000000] ---[ end trace 1b75b31a2719ed1c ]--- [ 0.000000] Kernel panic - not syncing: Attempted to kill the idle task! It was a know issue, that slab allocations would fail when common clock core tries to cache parent pointers for mux clocks on OMAP, and hence a patch 'clk: Allow late cache allocation for clk->parents, commit 7975059d' was added to work this problem around. A BUG() within kmalloc() with CONFIG_DEBUG_SLAB enabled was completely overlooked causing this regression. More details on the issue reported can be found here, http://www.mail-archive.com/linux-omap@vger.kernel.org/msg85932.html With all these issues around clk inits happening way too early, it makes sense to at least move them to a point where dynamic memory allocations are possible. So move them to a point just before the timer code starts using clocks and hwmod. This should at least pave way for clk inits on OMAP moving to dynamic clock registrations instead of using the static macros defined in clk-private.h. The issue with kernel panic while CONFIG_DEBUG_SLAB is enabled was reported by Piotr Haber and Tony Lindgren and this patch fixes the reported issue as well. Reported-by: Piotr Haber Reported-by: Tony Lindgren Signed-off-by: Rajendra Nayak Acked-by: Santosh Shilimkar Reviewed-by: Mike Turquette Acked-by: Paul Walmsley Cc: stable@vger.kernel.org # v3.8 Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/common.h | 3 +++ arch/arm/mach-omap2/io.c | 18 ++++++++++++------ arch/arm/mach-omap2/timer.c | 4 ++++ 3 files changed, 19 insertions(+), 6 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index 40f4a03d728f..d6ba13e1c540 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -293,5 +293,8 @@ extern void omap_reserve(void); struct omap_hwmod; extern int omap_dss_reset(struct omap_hwmod *); +/* SoC specific clock initializer */ +extern int (*omap_clk_init)(void); + #endif /* __ASSEMBLER__ */ #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */ diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 2c3fdd65387b..5c445ca1e271 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -54,6 +54,12 @@ #include "prm3xxx.h" #include "prm44xx.h" +/* + * omap_clk_init: points to a function that does the SoC-specific + * clock initializations + */ +int (*omap_clk_init)(void); + /* * The machine specific code may provide the extra mapping besides the * default mapping provided here. @@ -397,7 +403,7 @@ void __init omap2420_init_early(void) omap242x_clockdomains_init(); omap2420_hwmod_init(); omap_hwmod_init_postsetup(); - omap2420_clk_init(); + omap_clk_init = omap2420_clk_init; } void __init omap2420_init_late(void) @@ -427,7 +433,7 @@ void __init omap2430_init_early(void) omap243x_clockdomains_init(); omap2430_hwmod_init(); omap_hwmod_init_postsetup(); - omap2430_clk_init(); + omap_clk_init = omap2430_clk_init; } void __init omap2430_init_late(void) @@ -462,7 +468,7 @@ void __init omap3_init_early(void) omap3xxx_clockdomains_init(); omap3xxx_hwmod_init(); omap_hwmod_init_postsetup(); - omap3xxx_clk_init(); + omap_clk_init = omap3xxx_clk_init; } void __init omap3430_init_early(void) @@ -500,7 +506,7 @@ void __init ti81xx_init_early(void) omap3xxx_clockdomains_init(); omap3xxx_hwmod_init(); omap_hwmod_init_postsetup(); - omap3xxx_clk_init(); + omap_clk_init = omap3xxx_clk_init; } void __init omap3_init_late(void) @@ -568,7 +574,7 @@ void __init am33xx_init_early(void) am33xx_clockdomains_init(); am33xx_hwmod_init(); omap_hwmod_init_postsetup(); - am33xx_clk_init(); + omap_clk_init = am33xx_clk_init; } #endif @@ -593,7 +599,7 @@ void __init omap4430_init_early(void) omap44xx_clockdomains_init(); omap44xx_hwmod_init(); omap_hwmod_init_postsetup(); - omap4xxx_clk_init(); + omap_clk_init = omap4xxx_clk_init; } void __init omap4430_init_late(void) diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 2bdd4cf17a8f..f62b509ed08d 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -547,6 +547,8 @@ static inline void __init realtime_counter_init(void) clksrc_nr, clksrc_src) \ void __init omap##name##_gptimer_timer_init(void) \ { \ + if (omap_clk_init) \ + omap_clk_init(); \ omap_dmtimer_init(); \ omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \ omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src); \ @@ -556,6 +558,8 @@ void __init omap##name##_gptimer_timer_init(void) \ clksrc_nr, clksrc_src) \ void __init omap##name##_sync32k_timer_init(void) \ { \ + if (omap_clk_init) \ + omap_clk_init(); \ omap_dmtimer_init(); \ omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \ /* Enable the use of clocksource="gp_timer" kernel parameter */ \ -- cgit v1.2.3 From e73081d9afd4b5fe285d2a585a73d9c6f73ab0dd Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 26 Mar 2013 10:26:15 +0000 Subject: ARM: ux500: Apply the TCPM and TCDM locations and sizes to dbx5x0 DT This fixes a regression introduced by commit: 05ec260 mfd:db8500-prcmu: update resource passing All DBx5x0 based SoCs have access to two Tightly Coupled Memory (TCM) locations based on the PRCMU itself. One area from program memory (TCPM) and one for data memory (TCDM). The PRCMU needs to know where these are in order to function correctly. However, these are currently passed though platform device resources, which can only be obtained if Device Tree booting isn't in use. Thus we must also support them in DT by supplying them through the PRCMU node. Signed-off-by: Lee Jones Signed-off-by: Linus Walleij --- arch/arm/boot/dts/dbx5x0.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi index 9de93096601a..aaa63d0a8096 100644 --- a/arch/arm/boot/dts/dbx5x0.dtsi +++ b/arch/arm/boot/dts/dbx5x0.dtsi @@ -191,8 +191,8 @@ prcmu: prcmu@80157000 { compatible = "stericsson,db8500-prcmu"; - reg = <0x80157000 0x1000>; - reg-names = "prcmu"; + reg = <0x80157000 0x1000>, <0x801b0000 0x8000>, <0x801b8000 0x1000>; + reg-names = "prcmu", "prcmu-tcpm", "prcmu-tcdm"; interrupts = <0 47 0x4>; #address-cells = <1>; #size-cells = <1>; -- cgit v1.2.3 From 26135256d3e7d4d12c6268623edc1740888c041f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 27 Mar 2013 10:47:38 +0000 Subject: ARM: ux500: Stop passing ios_handler() as an MMCI power controlling call-back This fixes a regression introduced during the v3.9 merge window. Now MMCI on/off functionality is using the regulator framework from the MMCI driver, if we provide the ios_handler call-back we essentially duplicate functionality, which causes a large mess and lots of booting issues. Signed-off-by: Lee Jones Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-sdi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 051b62c27102..7f2cb6c5e2c1 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -81,7 +81,6 @@ static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = { #endif struct mmci_platform_data mop500_sdi0_data = { - .ios_handler = mop500_sdi0_ios_handler, .ocr_mask = MMC_VDD_29_30, .f_max = 50000000, .capabilities = MMC_CAP_4_BIT_DATA | -- cgit v1.2.3 From 265c3c0a64df50c0e8fe55cfe8af8851ed5feca5 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 27 Mar 2013 14:13:53 +0000 Subject: ARM: ux500: Enable the clock controlling Ethernet on Snowball This fixes a regression introduced by common clk enablement. On some u8500 based boards, the FMSC clock which is usually used for flash, is wired up to the SMSC911x Ethernet driver. However, the SMSC911x doesn't have common clk support yet, rendering it unusable. Prior to the introduction of common clk the FMSC clock was default on; however, common clk disables all clocks by default and insists drivers take responsibility to enable theirs. This fix enables the FMSC clock on Snowball, subsequently turning on the SMSC911x Ethernet chip. It will be removed when the driver is compatible with common clk. Signed-off-by: Lee Jones Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500.c | 12 ++++++++++++ arch/arm/mach-ux500/board-mop500.h | 1 + arch/arm/mach-ux500/cpu-db8500.c | 5 +++-- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index b03457881c4b..87d2d7b38ce9 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -439,6 +440,15 @@ static void mop500_prox_deactivate(struct device *dev) regulator_put(prox_regulator); } +void mop500_snowball_ethernet_clock_enable(void) +{ + struct clk *clk; + + clk = clk_get_sys("fsmc", NULL); + if (!IS_ERR(clk)) + clk_prepare_enable(clk); +} + static struct cryp_platform_data u8500_cryp1_platform_data = { .mem_to_engine = { .dir = STEDMA40_MEM_TO_PERIPH, @@ -683,6 +693,8 @@ static void __init snowball_init_machine(void) mop500_audio_init(parent); mop500_uart_init(parent); + mop500_snowball_ethernet_clock_enable(); + /* This board has full regulator constraints */ regulator_has_full_constraints(); } diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index eaa605f5d90d..d38951be70df 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -104,6 +104,7 @@ void __init mop500_pinmaps_init(void); void __init snowball_pinmaps_init(void); void __init hrefv60_pinmaps_init(void); void mop500_audio_init(struct device *parent); +void mop500_snowball_ethernet_clock_enable(void); int __init mop500_uib_init(void); void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 19235cf7bbe3..f1a581844372 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -312,9 +312,10 @@ static void __init u8500_init_machine(void) /* Pinmaps must be in place before devices register */ if (of_machine_is_compatible("st-ericsson,mop500")) mop500_pinmaps_init(); - else if (of_machine_is_compatible("calaosystems,snowball-a9500")) + else if (of_machine_is_compatible("calaosystems,snowball-a9500")) { snowball_pinmaps_init(); - else if (of_machine_is_compatible("st-ericsson,hrefv60+")) + mop500_snowball_ethernet_clock_enable(); + } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) hrefv60_pinmaps_init(); else if (of_machine_is_compatible("st-ericsson,ccu9540")) {} /* TODO: Add pinmaps for ccu9540 board. */ -- cgit v1.2.3 From a3d9052c6296ad3398d3ad649c3c682c3e7ecfa6 Mon Sep 17 00:00:00 2001 From: Mac Lin Date: Mon, 25 Mar 2013 17:23:33 +0800 Subject: ARM: cns3xxx: fix mapping of private memory region Since commit 0536bdf33faf (ARM: move iotable mappings within the vmalloc region), the Cavium CNS3xxx cannot boot anymore. This is caused by the pre-defined iotable mappings is not in the vmalloc region. This patch move the iotable mappings into the vmalloc region, and merge the MPCore private memory region (containing the SCU, the GIC and the TWD) as a single region. Signed-off-by: Mac Lin Signed-off-by: Anton Vorontsov Cc: stable@vger.kernel.org [v3.3+] --- arch/arm/mach-cns3xxx/core.c | 16 +++------------- arch/arm/mach-cns3xxx/include/mach/cns3xxx.h | 16 ++++++++-------- 2 files changed, 11 insertions(+), 21 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c index e698f26cc0cb..52e4bb5cf12d 100644 --- a/arch/arm/mach-cns3xxx/core.c +++ b/arch/arm/mach-cns3xxx/core.c @@ -22,19 +22,9 @@ static struct map_desc cns3xxx_io_desc[] __initdata = { { - .virtual = CNS3XXX_TC11MP_TWD_BASE_VIRT, - .pfn = __phys_to_pfn(CNS3XXX_TC11MP_TWD_BASE), - .length = SZ_4K, - .type = MT_DEVICE, - }, { - .virtual = CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT, - .pfn = __phys_to_pfn(CNS3XXX_TC11MP_GIC_CPU_BASE), - .length = SZ_4K, - .type = MT_DEVICE, - }, { - .virtual = CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT, - .pfn = __phys_to_pfn(CNS3XXX_TC11MP_GIC_DIST_BASE), - .length = SZ_4K, + .virtual = CNS3XXX_TC11MP_SCU_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_TC11MP_SCU_BASE), + .length = SZ_8K, .type = MT_DEVICE, }, { .virtual = CNS3XXX_TIMER1_2_3_BASE_VIRT, diff --git a/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h b/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h index 191c8e57f289..b1021aafa481 100644 --- a/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h +++ b/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h @@ -94,10 +94,10 @@ #define RTC_INTR_STS_OFFSET 0x34 #define CNS3XXX_MISC_BASE 0x76000000 /* Misc Control */ -#define CNS3XXX_MISC_BASE_VIRT 0xFFF07000 /* Misc Control */ +#define CNS3XXX_MISC_BASE_VIRT 0xFB000000 /* Misc Control */ #define CNS3XXX_PM_BASE 0x77000000 /* Power Management Control */ -#define CNS3XXX_PM_BASE_VIRT 0xFFF08000 +#define CNS3XXX_PM_BASE_VIRT 0xFB001000 #define PM_CLK_GATE_OFFSET 0x00 #define PM_SOFT_RST_OFFSET 0x04 @@ -109,7 +109,7 @@ #define PM_PLL_HM_PD_OFFSET 0x1C #define CNS3XXX_UART0_BASE 0x78000000 /* UART 0 */ -#define CNS3XXX_UART0_BASE_VIRT 0xFFF09000 +#define CNS3XXX_UART0_BASE_VIRT 0xFB002000 #define CNS3XXX_UART1_BASE 0x78400000 /* UART 1 */ #define CNS3XXX_UART1_BASE_VIRT 0xFFF0A000 @@ -130,7 +130,7 @@ #define CNS3XXX_I2S_BASE_VIRT 0xFFF10000 #define CNS3XXX_TIMER1_2_3_BASE 0x7C800000 /* Timer */ -#define CNS3XXX_TIMER1_2_3_BASE_VIRT 0xFFF10800 +#define CNS3XXX_TIMER1_2_3_BASE_VIRT 0xFB003000 #define TIMER1_COUNTER_OFFSET 0x00 #define TIMER1_AUTO_RELOAD_OFFSET 0x04 @@ -227,16 +227,16 @@ * Testchip peripheral and fpga gic regions */ #define CNS3XXX_TC11MP_SCU_BASE 0x90000000 /* IRQ, Test chip */ -#define CNS3XXX_TC11MP_SCU_BASE_VIRT 0xFF000000 +#define CNS3XXX_TC11MP_SCU_BASE_VIRT 0xFB004000 #define CNS3XXX_TC11MP_GIC_CPU_BASE 0x90000100 /* Test chip interrupt controller CPU interface */ -#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT 0xFF000100 +#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x100) #define CNS3XXX_TC11MP_TWD_BASE 0x90000600 -#define CNS3XXX_TC11MP_TWD_BASE_VIRT 0xFF000600 +#define CNS3XXX_TC11MP_TWD_BASE_VIRT (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x600) #define CNS3XXX_TC11MP_GIC_DIST_BASE 0x90001000 /* Test chip interrupt controller distributor */ -#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT 0xFF001000 +#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x1000) #define CNS3XXX_TC11MP_L220_BASE 0x92002000 /* L220 registers */ #define CNS3XXX_TC11MP_L220_BASE_VIRT 0xFF002000 -- cgit v1.2.3 From 55985e15b80beb339d3e332f00a26003deff14e6 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 2 Apr 2013 01:29:29 +0200 Subject: ARM: mxs: Slow down the I2C clock speed Slow down the I2C clock speed on M28 and SPS1 as it turns out the I2C block in i.MX28 can not operate stable enough with the bus running at 400kHz. Note that the driver used by Freescale runs the bus at 250kHz when 400kHz speed is selected, but the mainline Linux kernel runs the bus at actual 400kHz and that's where it is occasionally unstable. Play safe and run the bus at 100kHz. Signed-off-by: Marek Vasut Cc: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx28-m28evk.dts | 1 - arch/arm/boot/dts/imx28-sps1.dts | 1 - 2 files changed, 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts index 6ce3d17c3a29..fd36e1cca104 100644 --- a/arch/arm/boot/dts/imx28-m28evk.dts +++ b/arch/arm/boot/dts/imx28-m28evk.dts @@ -152,7 +152,6 @@ i2c0: i2c@80058000 { pinctrl-names = "default"; pinctrl-0 = <&i2c0_pins_a>; - clock-frequency = <400000>; status = "okay"; sgtl5000: codec@0a { diff --git a/arch/arm/boot/dts/imx28-sps1.dts b/arch/arm/boot/dts/imx28-sps1.dts index e6cde8aa7fff..6c6a5442800a 100644 --- a/arch/arm/boot/dts/imx28-sps1.dts +++ b/arch/arm/boot/dts/imx28-sps1.dts @@ -70,7 +70,6 @@ i2c0: i2c@80058000 { pinctrl-names = "default"; pinctrl-0 = <&i2c0_pins_a>; - clock-frequency = <400000>; status = "okay"; rtc: rtc@51 { -- cgit v1.2.3 From 698613b63817f2f6ca79831cd1c37aae67025323 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 3 Apr 2013 16:33:26 +0100 Subject: ARM: iWMMXt: always enable iWMMXt support with PJ4 CPUs Jason Cooper reports these build errors: arch/arm/kernel/built-in.o: In function `iwmmxt_do': /.../arch/arm/kernel/pj4-cp0.c:36: undefined reference to `iwmmxt_task_release' /.../arch/arm/kernel/pj4-cp0.c:40: undefined reference to `iwmmxt_task_switch' make: *** [vmlinux] Error 1 This is caused because the PJ4 code explicitly references the iWMMXt code, but doesn't require it to be built. Fix this by ensuring that iWMMXt is always enabled with PJ4. Reported-by: Jason Cooper Signed-off-by: Russell King --- arch/arm/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 13b739469c51..12ea3b3d49a9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1183,9 +1183,9 @@ config ARM_NR_BANKS default 8 config IWMMXT - bool "Enable iWMMXt support" + bool "Enable iWMMXt support" if !CPU_PJ4 depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4 - default y if PXA27x || PXA3xx || ARCH_MMP + default y if PXA27x || PXA3xx || ARCH_MMP || CPU_PJ4 help Enable support for iWMMXt context switching at run time if running on a CPU that supports it. -- cgit v1.2.3 From 6e7aceeb7c70b9ebad79bcfe91fcf738826e8e6d Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 25 Mar 2013 17:02:48 +0100 Subject: ARM: 7682/1: cache-l2x0: fix masking of RTL revision numbering and set_debug init Commit b8db6b8 (ARM: 7547/4: cache-l2x0: add support for Aurora L2 cache ctrl) moved the masking of the part ID which caused the RTL version to be lost. Commit 6248d06 (ARM: 7545/1: cache-l2x0: make outer_cache_fns a field of l2x0_of_data) changed how .set_debug is initialized. Both commits break commit 74ddcdb (ARM: 7608/1: l2x0: Only set .set_debug on PL310 r3p0 and earlier) which uses the RTL version to conditionally set .set_debug function pointer. Commit b8db6b8 also caused the printed cache ID to be missing the version information. Fix this by reverting how the part number is masked so the RTL version info is maintained. The cache-id-part DT property does not set the RTL bits so masking them should have no effect. Also, re-arrange the order of the function pointer init so the .set_debug function can be overridden. Reported-by: Paolo Pisati Signed-off-by: Rob Herring Cc: Gregory CLEMENT Cc: Yehuda Yitschak Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index c2f37390308a..c465faca51b0 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -299,7 +299,7 @@ static void l2x0_unlock(u32 cache_id) int lockregs; int i; - switch (cache_id) { + switch (cache_id & L2X0_CACHE_ID_PART_MASK) { case L2X0_CACHE_ID_PART_L310: lockregs = 8; break; @@ -333,15 +333,14 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) if (cache_id_part_number_from_dt) cache_id = cache_id_part_number_from_dt; else - cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID) - & L2X0_CACHE_ID_PART_MASK; + cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID); aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); aux &= aux_mask; aux |= aux_val; /* Determine the number of ways */ - switch (cache_id) { + switch (cache_id & L2X0_CACHE_ID_PART_MASK) { case L2X0_CACHE_ID_PART_L310: if (aux & (1 << 16)) ways = 16; @@ -725,7 +724,6 @@ static const struct l2x0_of_data pl310_data = { .flush_all = l2x0_flush_all, .inv_all = l2x0_inv_all, .disable = l2x0_disable, - .set_debug = pl310_set_debug, }, }; @@ -814,9 +812,8 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) data->save(); of_init = true; - l2x0_init(l2x0_base, aux_val, aux_mask); - memcpy(&outer_cache, &data->outer_cache, sizeof(outer_cache)); + l2x0_init(l2x0_base, aux_val, aux_mask); return 0; } -- cgit v1.2.3 From 93dc68876b608da041fe40ed39424b0fcd5aa2fb Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 26 Mar 2013 23:35:04 +0100 Subject: ARM: 7684/1: errata: Workaround for Cortex-A15 erratum 798181 (TLBI/DSB operations) On Cortex-A15 (r0p0..r3p2) the TLBI/DSB are not adequately shooting down all use of the old entries. This patch implements the erratum workaround which consists of: 1. Dummy TLBIMVAIS and DSB on the CPU doing the TLBI operation. 2. Send IPI to the CPUs that are running the same mm (and ASID) as the one being invalidated (or all the online CPUs for global pages). 3. CPU receiving the IPI executes a DMB and CLREX (part of the exception return code already). Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/Kconfig | 10 ++++++ arch/arm/include/asm/highmem.h | 7 ++++ arch/arm/include/asm/mmu_context.h | 2 ++ arch/arm/include/asm/tlbflush.h | 15 +++++++++ arch/arm/kernel/smp_tlb.c | 66 ++++++++++++++++++++++++++++++++++++++ arch/arm/mm/context.c | 3 +- 6 files changed, 102 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 12ea3b3d49a9..1cacda426a0e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1439,6 +1439,16 @@ config ARM_ERRATA_775420 to deadlock. This workaround puts DSB before executing ISB if an abort may occur on cache maintenance. +config ARM_ERRATA_798181 + bool "ARM errata: TLBI/DSB failure on Cortex-A15" + depends on CPU_V7 && SMP + help + On Cortex-A15 (r0p0..r3p2) the TLBI*IS/DSB operations are not + adequately shooting down all use of the old entries. This + option enables the Linux kernel workaround for this erratum + which sends an IPI to the CPUs that are running the same ASID + as the one being invalidated. + endmenu source "arch/arm/common/Kconfig" diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h index 8c5e828f484d..91b99abe7a95 100644 --- a/arch/arm/include/asm/highmem.h +++ b/arch/arm/include/asm/highmem.h @@ -41,6 +41,13 @@ extern void kunmap_high(struct page *page); #endif #endif +/* + * Needed to be able to broadcast the TLB invalidation for kmap. + */ +#ifdef CONFIG_ARM_ERRATA_798181 +#undef ARCH_NEEDS_KMAP_HIGH_GET +#endif + #ifdef ARCH_NEEDS_KMAP_HIGH_GET extern void *kmap_high_get(struct page *page); #else diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h index 863a6611323c..a7b85e0d0cc1 100644 --- a/arch/arm/include/asm/mmu_context.h +++ b/arch/arm/include/asm/mmu_context.h @@ -27,6 +27,8 @@ void __check_vmalloc_seq(struct mm_struct *mm); void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk); #define init_new_context(tsk,mm) ({ atomic64_set(&mm->context.id, 0); 0; }) +DECLARE_PER_CPU(atomic64_t, active_asids); + #else /* !CONFIG_CPU_HAS_ASID */ #ifdef CONFIG_MMU diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index 4db8c8820f0d..9e9c041358ca 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -450,6 +450,21 @@ static inline void local_flush_bp_all(void) isb(); } +#ifdef CONFIG_ARM_ERRATA_798181 +static inline void dummy_flush_tlb_a15_erratum(void) +{ + /* + * Dummy TLBIMVAIS. Using the unmapped address 0 and ASID 0. + */ + asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0)); + dsb(); +} +#else +static inline void dummy_flush_tlb_a15_erratum(void) +{ +} +#endif + /* * flush_pmd_entry * diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c index bd0300531399..e82e1d248772 100644 --- a/arch/arm/kernel/smp_tlb.c +++ b/arch/arm/kernel/smp_tlb.c @@ -12,6 +12,7 @@ #include #include +#include /**********************************************************************/ @@ -69,12 +70,72 @@ static inline void ipi_flush_bp_all(void *ignored) local_flush_bp_all(); } +#ifdef CONFIG_ARM_ERRATA_798181 +static int erratum_a15_798181(void) +{ + unsigned int midr = read_cpuid_id(); + + /* Cortex-A15 r0p0..r3p2 affected */ + if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2) + return 0; + return 1; +} +#else +static int erratum_a15_798181(void) +{ + return 0; +} +#endif + +static void ipi_flush_tlb_a15_erratum(void *arg) +{ + dmb(); +} + +static void broadcast_tlb_a15_erratum(void) +{ + if (!erratum_a15_798181()) + return; + + dummy_flush_tlb_a15_erratum(); + smp_call_function_many(cpu_online_mask, ipi_flush_tlb_a15_erratum, + NULL, 1); +} + +static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm) +{ + int cpu; + cpumask_t mask = { CPU_BITS_NONE }; + + if (!erratum_a15_798181()) + return; + + dummy_flush_tlb_a15_erratum(); + for_each_online_cpu(cpu) { + if (cpu == smp_processor_id()) + continue; + /* + * We only need to send an IPI if the other CPUs are running + * the same ASID as the one being invalidated. There is no + * need for locking around the active_asids check since the + * switch_mm() function has at least one dmb() (as required by + * this workaround) in case a context switch happens on + * another CPU after the condition below. + */ + if (atomic64_read(&mm->context.id) == + atomic64_read(&per_cpu(active_asids, cpu))) + cpumask_set_cpu(cpu, &mask); + } + smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1); +} + void flush_tlb_all(void) { if (tlb_ops_need_broadcast()) on_each_cpu(ipi_flush_tlb_all, NULL, 1); else local_flush_tlb_all(); + broadcast_tlb_a15_erratum(); } void flush_tlb_mm(struct mm_struct *mm) @@ -83,6 +144,7 @@ void flush_tlb_mm(struct mm_struct *mm) on_each_cpu_mask(mm_cpumask(mm), ipi_flush_tlb_mm, mm, 1); else local_flush_tlb_mm(mm); + broadcast_tlb_mm_a15_erratum(mm); } void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) @@ -95,6 +157,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) &ta, 1); } else local_flush_tlb_page(vma, uaddr); + broadcast_tlb_mm_a15_erratum(vma->vm_mm); } void flush_tlb_kernel_page(unsigned long kaddr) @@ -105,6 +168,7 @@ void flush_tlb_kernel_page(unsigned long kaddr) on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1); } else local_flush_tlb_kernel_page(kaddr); + broadcast_tlb_a15_erratum(); } void flush_tlb_range(struct vm_area_struct *vma, @@ -119,6 +183,7 @@ void flush_tlb_range(struct vm_area_struct *vma, &ta, 1); } else local_flush_tlb_range(vma, start, end); + broadcast_tlb_mm_a15_erratum(vma->vm_mm); } void flush_tlb_kernel_range(unsigned long start, unsigned long end) @@ -130,6 +195,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end) on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1); } else local_flush_tlb_kernel_range(start, end); + broadcast_tlb_a15_erratum(); } void flush_bp_all(void) diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index a5a4b2bc42ba..2ac37372ef52 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -48,7 +48,7 @@ static DEFINE_RAW_SPINLOCK(cpu_asid_lock); static atomic64_t asid_generation = ATOMIC64_INIT(ASID_FIRST_VERSION); static DECLARE_BITMAP(asid_map, NUM_USER_ASIDS); -static DEFINE_PER_CPU(atomic64_t, active_asids); +DEFINE_PER_CPU(atomic64_t, active_asids); static DEFINE_PER_CPU(u64, reserved_asids); static cpumask_t tlb_flush_pending; @@ -215,6 +215,7 @@ void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk) if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) { local_flush_bp_all(); local_flush_tlb_all(); + dummy_flush_tlb_a15_erratum(); } atomic64_set(&per_cpu(active_asids, cpu), asid); -- cgit v1.2.3 From 6f3d90e55660ba42301b5e9c7eed332cc9f70fd7 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 28 Mar 2013 11:17:55 +0100 Subject: ARM: 7685/1: delay: use private ticks_per_jiffy field for timer-based delay ops Commit 70264367a243 ("ARM: 7653/2: do not scale loops_per_jiffy when using a constant delay clock") fixed a problem with our timer-based delay loop, where loops_per_jiffy is scaled by cpufreq yet used directly by the timer delay ops. This patch fixes the problem in a more elegant way by keeping a private ticks_per_jiffy field in the delay ops, independent of loops_per_jiffy and therefore not subject to scaling. The loop-based delay continues to use loops_per_jiffy directly, as it should. Acked-by: Nicolas Pitre Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/delay.h | 2 +- arch/arm/kernel/smp.c | 3 --- arch/arm/lib/delay.c | 8 +++++--- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h index 720799fd3a81..dff714d886d5 100644 --- a/arch/arm/include/asm/delay.h +++ b/arch/arm/include/asm/delay.h @@ -24,7 +24,7 @@ extern struct arm_delay_ops { void (*delay)(unsigned long); void (*const_udelay)(unsigned long); void (*udelay)(unsigned long); - bool const_clock; + unsigned long ticks_per_jiffy; } arm_delay_ops; #define __delay(n) arm_delay_ops.delay(n) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 79078edbb9bc..1f2ccccaf009 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -673,9 +673,6 @@ static int cpufreq_callback(struct notifier_block *nb, if (freq->flags & CPUFREQ_CONST_LOOPS) return NOTIFY_OK; - if (arm_delay_ops.const_clock) - return NOTIFY_OK; - if (!per_cpu(l_p_j_ref, cpu)) { per_cpu(l_p_j_ref, cpu) = per_cpu(cpu_data, cpu).loops_per_jiffy; diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c index 6b93f6a1a3c7..64dbfa57204a 100644 --- a/arch/arm/lib/delay.c +++ b/arch/arm/lib/delay.c @@ -58,7 +58,7 @@ static void __timer_delay(unsigned long cycles) static void __timer_const_udelay(unsigned long xloops) { unsigned long long loops = xloops; - loops *= loops_per_jiffy; + loops *= arm_delay_ops.ticks_per_jiffy; __timer_delay(loops >> UDELAY_SHIFT); } @@ -73,11 +73,13 @@ void __init register_current_timer_delay(const struct delay_timer *timer) pr_info("Switching to timer-based delay loop\n"); delay_timer = timer; lpj_fine = timer->freq / HZ; - loops_per_jiffy = lpj_fine; + + /* cpufreq may scale loops_per_jiffy, so keep a private copy */ + arm_delay_ops.ticks_per_jiffy = lpj_fine; arm_delay_ops.delay = __timer_delay; arm_delay_ops.const_udelay = __timer_const_udelay; arm_delay_ops.udelay = __timer_udelay; - arm_delay_ops.const_clock = true; + delay_calibrated = true; } else { pr_info("Ignoring duplicate/late registration of read_current_timer delay\n"); -- cgit v1.2.3 From b21e023ba4003fe4b5c32540e4aee5991c019e92 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 2 Apr 2013 22:11:46 +0100 Subject: ARM: 7689/1: add unwind annotations to ftrace asm Add unwind annotations to the ftrace assembly code so that the function tracer's stacktracing options (func_stack_trace, etc.) work when CONFIG_ARM_UNWIND is enabled. Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 3248cde504ed..fefd7f971437 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -276,7 +276,13 @@ ENDPROC(ftrace_graph_caller_old) */ .macro mcount_enter +/* + * This pad compensates for the push {lr} at the call site. Note that we are + * unable to unwind through a function which does not otherwise save its lr. + */ + UNWIND(.pad #4) stmdb sp!, {r0-r3, lr} + UNWIND(.save {r0-r3, lr}) .endm .macro mcount_get_lr reg @@ -289,6 +295,7 @@ ENDPROC(ftrace_graph_caller_old) .endm ENTRY(__gnu_mcount_nc) +UNWIND(.fnstart) #ifdef CONFIG_DYNAMIC_FTRACE mov ip, lr ldmia sp!, {lr} @@ -296,17 +303,22 @@ ENTRY(__gnu_mcount_nc) #else __mcount #endif +UNWIND(.fnend) ENDPROC(__gnu_mcount_nc) #ifdef CONFIG_DYNAMIC_FTRACE ENTRY(ftrace_caller) +UNWIND(.fnstart) __ftrace_caller +UNWIND(.fnend) ENDPROC(ftrace_caller) #endif #ifdef CONFIG_FUNCTION_GRAPH_TRACER ENTRY(ftrace_graph_caller) +UNWIND(.fnstart) __ftrace_graph_caller +UNWIND(.fnend) ENDPROC(ftrace_graph_caller) #endif -- cgit v1.2.3 From 4e1db26a0b42e2b6e27c05d68adcc01709c2eed2 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Wed, 3 Apr 2013 12:24:45 +0100 Subject: ARM: 7690/1: mm: fix CONFIG_LPAE typos CONFIG_LPAE doesn't exist: the correct option is CONFIG_ARM_LPAE, so fix up the two typos under arch/arm/. The fix to head.S is slightly scary, but this is just for setting up an early io-mapping for the serial port when running on a big-endian, LPAE system. Since these systems don't exist in the wild (at least, I have no access to one outside of kvmtool, which doesn't provide a serial port suitable for earlyprintk), then we can revisit the code later if it causes any problems. Signed-off-by: Paul Bolle Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/head.S | 2 +- arch/arm/kernel/setup.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index e0eb9a1cae77..8bac553fe213 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -267,7 +267,7 @@ __create_page_tables: addne r6, r6, #1 << SECTION_SHIFT strne r6, [r3] -#if defined(CONFIG_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8) +#if defined(CONFIG_ARM_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8) sub r4, r4, #4 @ Fixup page table pointer @ for 64-bit descriptors #endif diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index f3ac13f69b7a..d343a6c3a6d1 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -544,7 +544,7 @@ int __init arm_add_memory(phys_addr_t start, phys_addr_t size) size -= start & ~PAGE_MASK; bank->start = PAGE_ALIGN(start); -#ifndef CONFIG_LPAE +#ifndef CONFIG_ARM_LPAE if (bank->start + size < bank->start) { printk(KERN_CRIT "Truncating memory at 0x%08llx to fit in " "32-bit physical address space\n", (long long)start); -- cgit v1.2.3 From cab1e0a36c9dd0b0671fb84197ed294513f5adc1 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Fri, 29 Mar 2013 16:20:09 +0100 Subject: ARM: clk-imx35: Bugfix iomux clock This patch enables iomuxc_gate clock. It is necessary to be able to reconfigure iomux pads. Without this clock enabled, the clk_disable_unused function will disable this clock and the iomux pads are not configurable anymore. This happens at every boot. After a reboot (watchdog system reset) the clock is not enabled again, so all iomux pad reconfigurations in boot code are without effect. The iomux pads should be always configurable, so this patch always enables it. Signed-off-by: Markus Pargmann Cc: stable@vger.kernel.org Signed-off-by: Sascha Hauer Signed-off-by: Shawn Guo --- arch/arm/mach-imx/clk-imx35.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c index e13a8fa5e62c..b95898a3912c 100644 --- a/arch/arm/mach-imx/clk-imx35.c +++ b/arch/arm/mach-imx/clk-imx35.c @@ -265,6 +265,7 @@ int __init mx35_clocks_init(void) clk_prepare_enable(clk[iim_gate]); clk_prepare_enable(clk[emi_gate]); clk_prepare_enable(clk[max_gate]); + clk_prepare_enable(clk[iomuxc_gate]); /* * SCC is needed to boot via mmc after a watchdog reset. The clock code -- cgit v1.2.3 From 75498083e25e96932ad998ffdeadb17234c68d3a Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Fri, 29 Mar 2013 16:20:10 +0100 Subject: ARM: imx35 Bugfix admux clock The admux clock seems to be the audmux clock as tests show. audmux does not work without this clock enabled. Currently imx35 does not register a clock device for audmux. This patch adds this registration. imx-audmux driver already handles a clock device, so no changes are necessary there. Signed-off-by: Markus Pargmann Cc: stable@vger.kernel.org Signed-off-by: Sascha Hauer Signed-off-by: Shawn Guo --- arch/arm/mach-imx/clk-imx35.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c index b95898a3912c..2193c834f55c 100644 --- a/arch/arm/mach-imx/clk-imx35.c +++ b/arch/arm/mach-imx/clk-imx35.c @@ -257,6 +257,7 @@ int __init mx35_clocks_init(void) clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0"); clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0"); clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0"); + clk_register_clkdev(clk[admux_gate], "audmux", NULL); clk_prepare_enable(clk[spba_gate]); clk_prepare_enable(clk[gpio1_gate]); -- cgit v1.2.3 From 2bb4b70b1dbb45f0c1a3ba98066e6635d8aa3fe0 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 3 Apr 2013 23:50:09 +0800 Subject: ARM: imx: provide twd clock lookup from device tree While booting from device tree, imx6q used to provide twd clock lookup by calling clk_register_clkdev() in clock driver. However, the commit bd60345 (ARM: use device tree to get smp_twd clock) forces DT boot to look up the clock from device tree. It causes the failure below when twd driver tries to get the clock, and hence kernel has to calibrate the local timer frequency. smp_twd: clock not found -2 ... Calibrating local timer... 396.13MHz. Fix the regression by providing twd clock lookup from device tree, and remove the unused twd clk_register_clkdev() call from clock driver. Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl.dtsi | 1 + arch/arm/mach-imx/clk-imx6q.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 06ec460b4581..281a223591ff 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -91,6 +91,7 @@ compatible = "arm,cortex-a9-twd-timer"; reg = <0x00a00600 0x20>; interrupts = <1 13 0xf01>; + clocks = <&clks 15>; }; L2: l2-cache@00a02000 { diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 2f9ff93a4e61..22a3021a455b 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -443,7 +443,6 @@ int __init mx6q_clocks_init(void) clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0"); clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0"); - clk_register_clkdev(clk[twd], NULL, "smp_twd"); clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL); clk_register_clkdev(clk[ahb], "ahb", NULL); clk_register_clkdev(clk[cko1], "cko1", NULL); -- cgit v1.2.3 From e8094b2c17126c7dfdeafa296f206a4a3b122d23 Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Thu, 4 Apr 2013 16:03:29 +0200 Subject: ARM i.MX6: Fix ldb_di clock selection According to the recent i.MX6 Quad technical reference manual, mode 0x4 (100b) of the CCM_CS2DCR register (address 0x020C402C) bits [11-9] and [14-12] select the PLL3 clock, and not the PLL3 PFD1 540M clock. In our code, the PLL3 root clock is named 'pll3_usb_otg', select this instead of the 540M clock. Signed-off-by: Dirk Behme Signed-off-by: Shawn Guo --- arch/arm/mach-imx/clk-imx6q.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 22a3021a455b..d38e54f5b6d7 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -115,7 +115,7 @@ static const char *gpu2d_core_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd0_352m" static const char *gpu3d_core_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", }; static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd9_720m", }; static const char *ipu_sels[] = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", }; -static const char *ldb_di_sels[] = { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_pfd1_540m", }; +static const char *ldb_di_sels[] = { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", }; static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", }; static const char *ipu1_di0_sels[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; static const char *ipu1_di1_sels[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; -- cgit v1.2.3 From b530f742ac27460d41d35b638ad6aad92044a982 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 8 Apr 2013 21:39:45 +0900 Subject: ARM: S3C24XX: Correct NR_IRQS definition for s3c2440 Due to NR_IRQS being incorrectly defined not all IRQ domains can be registered for S3C2440. It causes following errors on a s3c2440 SoC based board: NR_IRQS:89 S3C2440: IRQ Support irq: clearing pending status 00000002 ------------[ cut here ]------------ WARNING: at kernel/irq/irqdomain.c:234 0xc0056ed0() ... irq: could not create irq-domain ... s3c2410-wdt s3c2410-wdt: failed to install irq (-22) s3c2410-wdt: probe of s3c2410-wdt failed with error -22 ... samsung-uart s3c2440-uart.0: cannot get irq 74 Fix this by increasing NR_IRQS to at least (IRQ_S3C2443_AC97 + 1) if CPU_S3C2440 is selected, so the subintc IRQ domain gets properly registered. Signed-off-by: Tomasz Figa Signed-off-by: Sylwester Nawrocki Acked-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/include/mach/irqs.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-s3c24xx/include/mach/irqs.h b/arch/arm/mach-s3c24xx/include/mach/irqs.h index b7a9f4d469e8..1e73f5fa8659 100644 --- a/arch/arm/mach-s3c24xx/include/mach/irqs.h +++ b/arch/arm/mach-s3c24xx/include/mach/irqs.h @@ -188,10 +188,8 @@ #if defined(CONFIG_CPU_S3C2416) #define NR_IRQS (IRQ_S3C2416_I2S1 + 1) -#elif defined(CONFIG_CPU_S3C2443) -#define NR_IRQS (IRQ_S3C2443_AC97+1) #else -#define NR_IRQS (IRQ_S3C2440_AC97+1) +#define NR_IRQS (IRQ_S3C2443_AC97 + 1) #endif /* compatibility define. */ -- cgit v1.2.3 From 646dd2f0a980949b05042792fbadd72b735c3eda Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 9 Apr 2013 23:52:21 +0900 Subject: ARM: S3C24XX: Fix interrupt pending register offset of the EINT controller The external pending interrupt register address (EINTPEND) offset is 0xa8, not 0x08. Without this patch the external interrupts are not properly acknowledged, which may lead to an interrupt storm and the system hang as soon as any external interrupt is requested. Signed-off-by: Sylwester Nawrocki Reviewed-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-s3c24xx/irq.c b/arch/arm/mach-s3c24xx/irq.c index cb9f5e011e73..d8ba9bee4c7e 100644 --- a/arch/arm/mach-s3c24xx/irq.c +++ b/arch/arm/mach-s3c24xx/irq.c @@ -500,7 +500,7 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np, base = (void *)0xfd000000; intc->reg_mask = base + 0xa4; - intc->reg_pending = base + 0x08; + intc->reg_pending = base + 0xa8; irq_num = 20; irq_start = S3C2410_IRQ(32); irq_offset = 4; -- cgit v1.2.3 From f5f83c71ffc5bda1c1ade5e8b1a8a1d40208860c Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Tue, 23 Apr 2013 22:46:53 +0900 Subject: ARM: EXYNOS: Create virtual I/O mapping for Chip-ID controller using device tree On device tree enabled exynos platforms, retrieve the physical base address of the chip-id controller from device tree and create a virtual I/O mapping for the chip-id controller. This helps to remove the chip-id controller entry from the statically defined I/O mapping tables. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.c | 53 +++++++++++++++++++-------------- arch/arm/mach-exynos/include/mach/map.h | 1 - 2 files changed, 30 insertions(+), 24 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 02e35abd136b..e720352f85cb 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -119,17 +119,6 @@ static struct map_desc exynos_iodesc[] __initdata = { }, }; -#ifdef CONFIG_ARCH_EXYNOS5 -static struct map_desc exynos5440_iodesc[] __initdata = { - { - .virtual = (unsigned long)S5P_VA_CHIPID, - .pfn = __phys_to_pfn(EXYNOS5440_PA_CHIPID), - .length = SZ_4K, - .type = MT_DEVICE, - }, -}; -#endif - static struct map_desc exynos4_iodesc[] __initdata = { { .virtual = (unsigned long)S3C_VA_SYS, @@ -320,6 +309,31 @@ void __init exynos_init_late(void) exynos_pm_late_initcall(); } +#ifdef CONFIG_OF +int __init exynos_fdt_map_chipid(unsigned long node, const char *uname, + int depth, void *data) +{ + struct map_desc iodesc; + __be32 *reg; + unsigned long len; + + if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") && + !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock")) + return 0; + + reg = of_get_flat_dt_prop(node, "reg", &len); + if (reg == NULL || len != (sizeof(unsigned long) * 2)) + return 0; + + iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0])); + iodesc.length = be32_to_cpu(reg[1]) - 1; + iodesc.virtual = (unsigned long)S5P_VA_CHIPID; + iodesc.type = MT_DEVICE; + iotable_init(&iodesc, 1); + return 1; +} +#endif + /* * exynos_map_io * @@ -328,19 +342,12 @@ void __init exynos_init_late(void) void __init exynos_init_io(struct map_desc *mach_desc, int size) { - struct map_desc *iodesc = exynos_iodesc; - int iodesc_sz = ARRAY_SIZE(exynos_iodesc); -#if defined(CONFIG_OF) && defined(CONFIG_ARCH_EXYNOS5) - unsigned long root = of_get_flat_dt_root(); - - /* initialize the io descriptors we need for initialization */ - if (of_flat_dt_is_compatible(root, "samsung,exynos5440")) { - iodesc = exynos5440_iodesc; - iodesc_sz = ARRAY_SIZE(exynos5440_iodesc); - } +#ifdef CONFIG_OF + if (initial_boot_params) + of_scan_flat_dt(exynos_fdt_map_chipid, NULL); + else #endif - - iotable_init(iodesc, iodesc_sz); + iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc)); if (mach_desc) iotable_init(mach_desc, size); diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 7f99b7b187d6..be7abc7ceb67 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -53,7 +53,6 @@ #define EXYNOS4_PA_ONENAND_DMA 0x0C600000 #define EXYNOS_PA_CHIPID 0x10000000 -#define EXYNOS5440_PA_CHIPID 0x00160000 #define EXYNOS4_PA_SYSCON 0x10010000 #define EXYNOS5_PA_SYSCON 0x10050100 -- cgit v1.2.3 From 096ee6adcfb79a13ae04150023725c8a67e00ae8 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Tue, 23 Apr 2013 22:46:58 +0900 Subject: ARM: dts: Add chip-id controller node on Exynos4/5 SoC Add chip-id controller nodes for Exynos4 and Exynos5 SoCs. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4.dtsi | 5 +++++ arch/arm/boot/dts/exynos5250.dtsi | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index b8771c5cb2a3..7cfbbd3b7732 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -38,6 +38,11 @@ i2c7 = &i2c_7; }; + chipid@10000000 { + compatible = "samsung,exynos4210-chipid"; + reg = <0x10000000 0x100>; + }; + pd_mfc: mfc-power-domain@10023C40 { compatible = "samsung,exynos4210-pd"; reg = <0x10023C40 0x20>; diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index af66e6b7bc77..53c37f0b763f 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -51,6 +51,11 @@ pinctrl3 = &pinctrl_3; }; + chipid@10000000 { + compatible = "samsung,exynos4210-chipid"; + reg = <0x10000000 0x100>; + }; + pd_gsc: gsc-power-domain@0x10044000 { compatible = "samsung,exynos4210-pd"; reg = <0x10044000 0x20>; -- cgit v1.2.3 From 97a4a1ba0eb0c8fd20cabf8a3ca857de9658ee21 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Tue, 16 Apr 2013 16:29:01 +0000 Subject: ARM: dts: Add i2c-arbitrator bus for exynos5250-snow We need to use the i2c-arbitrator to talk to any of the devices on i2c bus 4 on exynos5250-snow so that we don't confuse the embedded controller (EC). Add the i2c-arbitrator to the device tree. As we add future devices (keyboard, sbs, tps65090) we'll add them on top of this. The arbitrated bus is numbered 104 simply as a convenience to make it easier for people poking around to guess that it might have something to do with the physical bus 4. The addition is split between the cros5250-common and the snow device tree file since not all cros5250-class devices use arbitration. Signed-off-by: Doug Anderson Acked-by: Kukjin Kim Signed-off-by: Olof Johansson --- arch/arm/boot/dts/cros5250-common.dtsi | 3 ++- arch/arm/boot/dts/exynos5250-snow.dts | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/boot/dts/cros5250-common.dtsi b/arch/arm/boot/dts/cros5250-common.dtsi index 8a5b3a6cdc58..0a61bbb9102f 100644 --- a/arch/arm/boot/dts/cros5250-common.dtsi +++ b/arch/arm/boot/dts/cros5250-common.dtsi @@ -193,7 +193,8 @@ }; i2c@12CA0000 { - status = "disabled"; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <66000>; }; i2c@12CB0000 { diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index 581ffae27e13..fa85f58553f5 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -16,6 +16,10 @@ model = "Google Snow"; compatible = "google,snow", "samsung,exynos5250"; + aliases { + i2c104 = &i2c_104; + }; + pinctrl@11400000 { sd3_clk: sd3-clk { samsung,pin-drv = <0>; @@ -44,6 +48,27 @@ }; }; + i2c-arbitrator { + compatible = "i2c-arb-gpio-challenge"; + #address-cells = <1>; + #size-cells = <0>; + + i2c-parent = <&{/i2c@12CA0000}>; + + our-claim-gpio = <&gpf0 3 1>; + their-claim-gpios = <&gpe0 4 1>; + slew-delay-us = <10>; + wait-retry-us = <3000>; + wait-free-us = <50000>; + + /* Use ID 104 as a hint that we're on physical bus 4 */ + i2c_104: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + /* * On Snow we've got SIP WiFi and so can keep drive strengths low to * reduce EMI. -- cgit v1.2.3 From 61d4f0523ae7590c48b3dd4739b3fccb9b93021a Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Tue, 16 Apr 2013 16:29:02 +0000 Subject: ARM: dts: Add sbs-battery for exynos5250-snow Now that we have i2c-arbitrator in place on bus 4 we can add the sbs-battery driver. Future devices will be added onto bus 4 once drivers are in good shape. Signed-off-by: Doug Anderson Acked-by: Kukjin Kim Signed-off-by: Olof Johansson --- arch/arm/boot/dts/exynos5250-snow.dts | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index fa85f58553f5..c1151431f0d1 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -66,6 +66,12 @@ reg = <0>; #address-cells = <1>; #size-cells = <0>; + + battery: sbs-battery@b { + compatible = "sbs,sbs-battery"; + reg = <0xb>; + sbs,poll-retry-count = <1>; + }; }; }; -- cgit v1.2.3 From a4591dcf743ac841f9a7d81399405b8fe77c87bf Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Sat, 27 Apr 2013 15:14:10 -0700 Subject: ARM: exynos: dts: cros5250: add EC device Add basic EC information to device tree, currently only describing the keyboard and keymap. Reviewed-by: Doug Anderson Acked-by: Kukjin Kim Signed-off-by: Olof Johansson --- arch/arm/boot/dts/exynos5250-snow.dts | 96 +++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index c1151431f0d1..bf4744bab445 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -72,6 +72,102 @@ reg = <0xb>; sbs,poll-retry-count = <1>; }; + + ec: embedded-controller { + compatible = "google,cros-ec-i2c"; + reg = <0x1e>; + interrupts = <6 0>; + interrupt-parent = <&gpx1>; + wakeup-source; + + keyboard-controller { + compatible = "google,cros-ec-keyb"; + keypad,num-rows = <8>; + keypad,num-columns = <13>; + google,needs-ghost-filter; + linux,keymap = <0x0001003a /* CAPSLK */ + 0x0002003b /* F1 */ + 0x00030030 /* B */ + 0x00040044 /* F10 */ + 0x00060031 /* N */ + 0x0008000d /* = */ + 0x000a0064 /* R_ALT */ + + 0x01010001 /* ESC */ + 0x0102003e /* F4 */ + 0x01030022 /* G */ + 0x01040041 /* F7 */ + 0x01060023 /* H */ + 0x01080028 /* ' */ + 0x01090043 /* F9 */ + 0x010b000e /* BKSPACE */ + + 0x0200001d /* L_CTRL */ + 0x0201000f /* TAB */ + 0x0202003d /* F3 */ + 0x02030014 /* T */ + 0x02040040 /* F6 */ + 0x0205001b /* ] */ + 0x02060015 /* Y */ + 0x02070056 /* 102ND */ + 0x0208001a /* [ */ + 0x02090042 /* F8 */ + + 0x03010029 /* GRAVE */ + 0x0302003c /* F2 */ + 0x03030006 /* 5 */ + 0x0304003f /* F5 */ + 0x03060007 /* 6 */ + 0x0308000c /* - */ + 0x030b002b /* \ */ + + 0x04000061 /* R_CTRL */ + 0x0401001e /* A */ + 0x04020020 /* D */ + 0x04030021 /* F */ + 0x0404001f /* S */ + 0x04050025 /* K */ + 0x04060024 /* J */ + 0x04080027 /* ; */ + 0x04090026 /* L */ + 0x040b001c /* ENTER */ + + 0x0501002c /* Z */ + 0x0502002e /* C */ + 0x0503002f /* V */ + 0x0504002d /* X */ + 0x05050033 /* , */ + 0x05060032 /* M */ + 0x0507002a /* L_SHIFT */ + 0x05080035 /* / */ + 0x05090034 /* . */ + 0x050B0039 /* SPACE */ + + 0x06010002 /* 1 */ + 0x06020004 /* 3 */ + 0x06030005 /* 4 */ + 0x06040003 /* 2 */ + 0x06050009 /* 8 */ + 0x06060008 /* 7 */ + 0x0608000b /* 0 */ + 0x0609000a /* 9 */ + 0x060a0038 /* L_ALT */ + 0x060b006c /* DOWN */ + 0x060c006a /* RIGHT */ + + 0x07010010 /* Q */ + 0x07020012 /* E */ + 0x07030013 /* R */ + 0x07040011 /* W */ + 0x07050017 /* I */ + 0x07060016 /* U */ + 0x07070036 /* R_SHIFT */ + 0x07080019 /* P */ + 0x07090018 /* O */ + 0x070b0067 /* UP */ + 0x070c0069>; /* LEFT */ + }; + }; }; }; -- cgit v1.2.3