From e3c83c2db458f1e040c5b4bb19773c458e0240a8 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 25 Apr 2012 13:05:24 +1000 Subject: ARM: OMAP2+: INTC: fix suspend abort, set IRQCHIP_SKIP_SET_WAKE Without an ->irq_set_wake() method in an irq_chip, calls to enable_irq_wake() will fail. This also causes these interrupts to not be able to abort suspend (via check_wakeup_irqs() in late suspend.) Currently, we don't implement ->irq_set_wake() for INTC interrupts because they default to be wakeup enabled by setting the GRPSEL bits in PM init. Even though there is no ->irq_set_wake(), we want enable_irq_wake() to succeed so these interrupts can abort suspend when necessary. To fix, set IRQCHIP_SKIP_SET_WAKE flag for all the INTC interrupts which avoids trying to check irq_chip->irq_set_wake() and failing when it doesn't exist. Longer term, we need to implement ->irq_set_wake() for the INTC which can manage the appropriate GRPSEL bits. Signed-off-by: NeilBrown [khilman@ti.com: rework changelog] Acked-by: Santosh Shilimkar Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/irq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 65f0d2571c9a..b0790a995dc9 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -148,6 +148,7 @@ omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) ct->chip.irq_ack = omap_mask_ack_irq; ct->chip.irq_mask = irq_gc_mask_disable_reg; ct->chip.irq_unmask = irq_gc_unmask_enable_reg; + ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE; ct->regs.ack = INTC_CONTROL; ct->regs.enable = INTC_MIR_CLEAR0; -- cgit v1.2.3 From 99b59df04899a048d1a3ed8bc2b1263779816868 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 27 Apr 2012 16:05:51 -0700 Subject: ARM: OMAP3: PM: fix shared PRCM interrupts: leave disabled at boot By default, request_irq() will auto-enable the requested IRQ. For PRCM interrupts, we may want to avoid that until the PM core code is fully ready to handle the interrupts. This is particularily true for IO pad interrupts on OMAP3, which are shared between the hwmod core and the PRM core. In order to avoid PRCM IO-chain interrupts until the PM core is ready to handle them, ready, set the IRQ_NOAUTOEN flag for the PRCM IO-chain interrupt, which means it will remain disabled after request_irq(). Then, explicitly enable the PRCM interrupts after the request_irq() in the PM core (but not in the hwmod core.) Special thanks to Tero Kristo for suggesting to isolate the fix to only the IO-chain interrupt on OMAP3 instead of all PRCM interrupts. Cc: Tero Kristo Acked-by: Paul Walmsley Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/pm34xx.c | 1 + arch/arm/mach-omap2/prm2xxx_3xxx.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 703bd1099259..4f44ee517f78 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -729,6 +729,7 @@ static int __init omap3_pm_init(void) ret = request_irq(omap_prcm_event_to_irq("io"), _prcm_int_handle_io, IRQF_SHARED | IRQF_NO_SUSPEND, "pm_io", omap3_pm_init); + enable_irq(omap_prcm_event_to_irq("io")); if (ret) { pr_err("pm: Failed to request pm_io irq\n"); diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index 9ce765407ad5..21cb74003a56 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "common.h" #include @@ -303,8 +304,15 @@ void omap3xxx_prm_restore_irqen(u32 *saved_mask) static int __init omap3xxx_prcm_init(void) { - if (cpu_is_omap34xx()) - return omap_prcm_register_chain_handler(&omap3_prcm_irq_setup); - return 0; + int ret = 0; + + if (cpu_is_omap34xx()) { + ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup); + if (!ret) + irq_set_status_flags(omap_prcm_event_to_irq("io"), + IRQ_NOAUTOEN); + } + + return ret; } subsys_initcall(omap3xxx_prcm_init); -- cgit v1.2.3 From 1ce029968718477149e7f1fb245a8e82c690cc4a Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Mon, 30 Apr 2012 16:57:09 -0700 Subject: arm: omap3: am35x: Don't mark missing features as present The Chip Identification register on the am35x family of SoCs has bits 12, 7:5, and 3:2 marked as reserved and are read as zeroes. Unfortunately, on other omap SoCs, a 0 bit means a feature is "Full Use" so the OMAP3_CHECK_FEATURE() macro called by omap3_check_features() will incorrectly interpret those zeroes to mean that a feature is present even though it isn't. To fix that, the feature bits that are incorrectly set (namely, OMAP3_HAS_IVA and OMAP3_HAS_ISP) need to be cleared after all of the calls to OMAP3_CHECK_FEATURE() in omap3_check_features() are made. Signed-off-by: Mark A. Greer [khilman@ti.com: use soc_is_am35xx() instead of cpu_is_am35xx()] Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/id.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index f611e3097157..38ae74f8e77a 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -246,6 +246,17 @@ void __init omap3xxx_check_features(void) omap_features |= OMAP3_HAS_SDRC; + /* + * am35x fixups: + * - The am35x Chip ID register has bits 12, 7:5, and 3:2 marked as + * reserved and therefore return 0 when read. Unfortunately, + * OMAP3_CHECK_FEATURE() will interpret some of those zeroes to + * mean that a feature is present even though it isn't so clear + * the incorrectly set feature bits. + */ + if (soc_is_am35xx()) + omap_features &= ~(OMAP3_HAS_IVA | OMAP3_HAS_ISP); + /* * TODO: Get additional info (where applicable) * e.g. Size of L2 cache. -- cgit v1.2.3 From 1d8a0e963ac532e038d93ab0d30bbfad072f3bf8 Mon Sep 17 00:00:00 2001 From: Juan Gutierrez Date: Sun, 13 May 2012 15:33:04 +0300 Subject: ARM: OMAP: enable mailbox irq per instance The machine-specific omap2_mbox_startup is called only once to initialize the whole mbox module, and as a result, enabling the mbox irq at that point only works for the very first mailbox instance opened. Instead, this patch makes sure enable_irq() is called every time a new mbox instance is opened. In addition, we're now enabling the mbox's irq only after its notifier_block is registered, to avoid possible race of receiving an interrupt without invoking the user's notifier callback. Signed-off-by: Juan Gutierrez Signed-off-by: Suman Anna [ohad@wizery.com: slightly reworded the commit log] Signed-off-by: Ohad Ben-Cohen --- arch/arm/mach-omap2/mailbox.c | 2 -- arch/arm/plat-omap/mailbox.c | 13 +++++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index 415a6f1cf419..f727034216a7 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/arch/arm/mach-omap2/mailbox.c @@ -83,8 +83,6 @@ static int omap2_mbox_startup(struct omap_mbox *mbox) l = mbox_read_reg(MAILBOX_REVISION); pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f)); - omap2_mbox_enable_irq(mbox, IRQ_RX); - return 0; } diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index ad32621aa52e..5e13c3884aa4 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -282,6 +282,8 @@ static int omap_mbox_startup(struct omap_mbox *mbox) } mbox->rxq = mq; mq->mbox = mbox; + + omap_mbox_enable_irq(mbox, IRQ_RX); } mutex_unlock(&mbox_configured_lock); return 0; @@ -305,6 +307,7 @@ static void omap_mbox_fini(struct omap_mbox *mbox) mutex_lock(&mbox_configured_lock); if (!--mbox->use_count) { + omap_mbox_disable_irq(mbox, IRQ_RX); free_irq(mbox->irq, mbox); tasklet_kill(&mbox->txq->tasklet); flush_work_sync(&mbox->rxq->work); @@ -338,13 +341,15 @@ struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) if (!mbox) return ERR_PTR(-ENOENT); - ret = omap_mbox_startup(mbox); - if (ret) - return ERR_PTR(-ENODEV); - if (nb) blocking_notifier_chain_register(&mbox->notifier, nb); + ret = omap_mbox_startup(mbox); + if (ret) { + blocking_notifier_chain_unregister(&mbox->notifier, nb); + return ERR_PTR(-ENODEV); + } + return mbox; } EXPORT_SYMBOL(omap_mbox_get); -- cgit v1.2.3 From 778d02e9b3b7188ce37ff542e54ff5df723659e6 Mon Sep 17 00:00:00 2001 From: Juan Gutierrez Date: Sun, 13 May 2012 15:33:07 +0300 Subject: ARM: OMAP4: fix irq and clock name for dsp-iommu Irq and clock names were wrong for dsp iommu configuration for omap4. - Renamed tesla_ick to dsp_fck: This is required because the new naming convention introduced by: commit 0e43327 "OMAP4 clock: Fix clock names and align with hwmod names" - Renamed INT_44XX_DSP_MMU to OMAP44XX_IRQ_TESLA_MMU. Naming convention adopted since: commit e927f8d "omap4: Add auto-generated irq and dma headers" - dsp-iommu is enabled by default. Signed-off-by: Juan Gutierrez Signed-off-by: Ohad Ben-Cohen --- arch/arm/mach-omap2/omap-iommu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c index ac49384d0285..1be8bcb52e93 100644 --- a/arch/arm/mach-omap2/omap-iommu.c +++ b/arch/arm/mach-omap2/omap-iommu.c @@ -73,19 +73,17 @@ static struct iommu_device omap4_devices[] = { .da_end = 0xFFFFF000, }, }, -#if defined(CONFIG_MPU_TESLA_IOMMU) { .base = OMAP4_MMU2_BASE, - .irq = INT_44XX_DSP_MMU, + .irq = OMAP44XX_IRQ_TESLA_MMU, .pdata = { .name = "tesla", .nr_tlb_entries = 32, - .clk_name = "tesla_ick", + .clk_name = "dsp_fck", .da_start = 0x0, .da_end = 0xFFFFF000, }, }, -#endif }; #define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices) static struct platform_device *omap4_iommu_pdev[NR_OMAP4_IOMMU_DEVICES]; -- cgit v1.2.3 From 7548c09a475039b5e9179615ac4c1c58b930cdb5 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Wed, 4 Apr 2012 15:44:38 +0300 Subject: ARM: OMAP4: hwspinlocks_init() should be static Sparse found out that hwspinlocks_init() wasn't marked static, and it should've been. Signed-off-by: Ohad Ben-Cohen --- arch/arm/mach-omap2/hwspinlock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/hwspinlock.c b/arch/arm/mach-omap2/hwspinlock.c index 454dfce125ca..8763c8520dc2 100644 --- a/arch/arm/mach-omap2/hwspinlock.c +++ b/arch/arm/mach-omap2/hwspinlock.c @@ -28,7 +28,7 @@ static struct hwspinlock_pdata omap_hwspinlock_pdata __initdata = { .base_id = 0, }; -int __init hwspinlocks_init(void) +static int __init hwspinlocks_init(void) { int retval = 0; struct omap_hwmod *oh; -- cgit v1.2.3 From c040be003f16a1bdd7997cc4ab7fc5fd43acb03b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 16 May 2012 12:01:40 +0200 Subject: ARM i.MX5: fix gpt peripheral clock path - The gpt peripheral clk parent is per_root, not ipg - The register for selectin per_lp_apm and per_root is MXC_CCM_CBCMR, not MXC_CCM_CBCDR Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/clk-imx51-imx53.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c index b8a382defb23..1e7828d6be95 100644 --- a/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/arch/arm/mach-imx/clk-imx51-imx53.c @@ -94,12 +94,12 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, periph_apm_sel, ARRAY_SIZE(periph_apm_sel)); clk[main_bus] = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1, main_bus_sel, ARRAY_SIZE(main_bus_sel)); - clk[per_lp_apm] = imx_clk_mux("per_lp_apm", MXC_CCM_CBCDR, 1, 1, + clk[per_lp_apm] = imx_clk_mux("per_lp_apm", MXC_CCM_CBCMR, 1, 1, per_lp_apm_sel, ARRAY_SIZE(per_lp_apm_sel)); clk[per_pred1] = imx_clk_divider("per_pred1", "per_lp_apm", MXC_CCM_CBCDR, 6, 2); clk[per_pred2] = imx_clk_divider("per_pred2", "per_pred1", MXC_CCM_CBCDR, 3, 3); clk[per_podf] = imx_clk_divider("per_podf", "per_pred2", MXC_CCM_CBCDR, 0, 3); - clk[per_root] = imx_clk_mux("per_root", MXC_CCM_CBCDR, 1, 0, + clk[per_root] = imx_clk_mux("per_root", MXC_CCM_CBCMR, 0, 1, per_root_sel, ARRAY_SIZE(per_root_sel)); clk[ahb] = imx_clk_divider("ahb", "main_bus", MXC_CCM_CBCDR, 10, 3); clk[ahb_max] = imx_clk_gate2("ahb_max", "ahb", MXC_CCM_CCGR0, 28); @@ -162,7 +162,7 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk[pwm1_hf_gate] = imx_clk_gate2("pwm1_hf_gate", "ipg", MXC_CCM_CCGR2, 12); clk[pwm2_ipg_gate] = imx_clk_gate2("pwm2_ipg_gate", "ipg", MXC_CCM_CCGR2, 14); clk[pwm2_hf_gate] = imx_clk_gate2("pwm2_hf_gate", "ipg", MXC_CCM_CCGR2, 16); - clk[gpt_gate] = imx_clk_gate2("gpt_gate", "ipg", MXC_CCM_CCGR2, 18); + clk[gpt_gate] = imx_clk_gate2("gpt_gate", "per_root", MXC_CCM_CCGR2, 18); clk[fec_gate] = imx_clk_gate2("fec_gate", "ipg", MXC_CCM_CCGR2, 24); clk[usboh3_gate] = imx_clk_gate2("usboh3_gate", "ipg", MXC_CCM_CCGR2, 26); clk[usboh3_per_gate] = imx_clk_gate2("usboh3_per_gate", "usboh3_podf", MXC_CCM_CCGR2, 28); -- cgit v1.2.3 From 1f152b48eaaf4918047e84777b01a6d687f066e9 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Tue, 15 May 2012 15:34:40 +0800 Subject: ARM: i.MX: change timer clock from ipg to perclk Contrary to the ipg clock the perclk rate is not changed or gated in low power mode, so we choose perclk for gpt. With the port to the common clock framework as a side effect the timer used the rate returned from the peripheral clock but the hardware was still programmed to use the ipg clock, so this patch only changes the hardware to really use the clock it already assumed. Signed-off-by: Richard Zhao Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/time.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c index 99f958ca6cb8..d865f7960baf 100644 --- a/arch/arm/plat-mxc/time.c +++ b/arch/arm/plat-mxc/time.c @@ -58,6 +58,7 @@ /* MX31, MX35, MX25, MX5 */ #define V2_TCTL_WAITEN (1 << 3) /* Wait enable mode */ #define V2_TCTL_CLK_IPG (1 << 6) +#define V2_TCTL_CLK_PER (2 << 6) #define V2_TCTL_FRR (1 << 9) #define V2_IR 0x0c #define V2_TSTAT 0x08 @@ -309,7 +310,7 @@ void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq) __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */ if (timer_is_v2()) - tctl_val = V2_TCTL_CLK_IPG | V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN; + tctl_val = V2_TCTL_CLK_PER | V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN; else tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN; -- cgit v1.2.3 From 2cfb45188a997ba4c3348e98a999b36663a4646f Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 16 May 2012 12:29:53 +0200 Subject: ARM i.MX: remove now unnecessary argument from mxc_timer_init As the timer code now does a clk_get to get its clock we don't need the struct clk argument anymore. This also changes the alternative EPIT timer to do a clk_get. Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/clk-imx1.c | 3 +-- arch/arm/mach-imx/clk-imx21.c | 4 ++-- arch/arm/mach-imx/clk-imx25.c | 2 +- arch/arm/mach-imx/clk-imx27.c | 3 +-- arch/arm/mach-imx/clk-imx31.c | 3 +-- arch/arm/mach-imx/clk-imx35.c | 6 ++---- arch/arm/mach-imx/clk-imx51-imx53.c | 6 ++---- arch/arm/mach-imx/clk-imx6q.c | 2 +- arch/arm/plat-mxc/epit.c | 11 ++++++++++- arch/arm/plat-mxc/include/mach/common.h | 4 ++-- arch/arm/plat-mxc/time.c | 21 ++++++++++----------- 11 files changed, 33 insertions(+), 32 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/clk-imx1.c b/arch/arm/mach-imx/clk-imx1.c index 0f0beb580b73..516ddee1948e 100644 --- a/arch/arm/mach-imx/clk-imx1.c +++ b/arch/arm/mach-imx/clk-imx1.c @@ -108,8 +108,7 @@ int __init mx1_clocks_init(unsigned long fref) clk_register_clkdev(clk[clk32], NULL, "mxc_rtc.0"); clk_register_clkdev(clk[clko], "clko", NULL); - mxc_timer_init(NULL, MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR), - MX1_TIM1_INT); + mxc_timer_init(MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR), MX1_TIM1_INT); return 0; } diff --git a/arch/arm/mach-imx/clk-imx21.c b/arch/arm/mach-imx/clk-imx21.c index 4e4f384ee8dd..ea13e61bd5f3 100644 --- a/arch/arm/mach-imx/clk-imx21.c +++ b/arch/arm/mach-imx/clk-imx21.c @@ -180,7 +180,7 @@ int __init mx21_clocks_init(unsigned long lref, unsigned long href) clk_register_clkdev(clk[sdhc1_ipg_gate], "sdhc1", NULL); clk_register_clkdev(clk[sdhc2_ipg_gate], "sdhc2", NULL); - mxc_timer_init(NULL, MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR), - MX21_INT_GPT1); + mxc_timer_init(MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR), MX21_INT_GPT1); + return 0; } diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c index d9833bb5fd61..fdd8cc87c9fe 100644 --- a/arch/arm/mach-imx/clk-imx25.c +++ b/arch/arm/mach-imx/clk-imx25.c @@ -243,6 +243,6 @@ int __init mx25_clocks_init(void) clk_register_clkdev(clk[sdma_ahb], "ahb", "imx35-sdma"); clk_register_clkdev(clk[iim_ipg], "iim", NULL); - mxc_timer_init(NULL, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54); + mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54); return 0; } diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c index 50a7ebd8d1b2..295cbd7c08dc 100644 --- a/arch/arm/mach-imx/clk-imx27.c +++ b/arch/arm/mach-imx/clk-imx27.c @@ -263,8 +263,7 @@ int __init mx27_clocks_init(unsigned long fref) clk_register_clkdev(clk[ssi1_baud_gate], "bitrate" , "imx-ssi.0"); clk_register_clkdev(clk[ssi2_baud_gate], "bitrate" , "imx-ssi.1"); - mxc_timer_init(NULL, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), - MX27_INT_GPT1); + mxc_timer_init(MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), MX27_INT_GPT1); clk_prepare_enable(clk[emi_ahb_gate]); diff --git a/arch/arm/mach-imx/clk-imx31.c b/arch/arm/mach-imx/clk-imx31.c index a854b9cae5ea..c9a06d800f8e 100644 --- a/arch/arm/mach-imx/clk-imx31.c +++ b/arch/arm/mach-imx/clk-imx31.c @@ -175,8 +175,7 @@ int __init mx31_clocks_init(unsigned long fref) mx31_revision(); clk_disable_unprepare(clk[iim_gate]); - mxc_timer_init(NULL, MX31_IO_ADDRESS(MX31_GPT1_BASE_ADDR), - MX31_INT_GPT); + mxc_timer_init(MX31_IO_ADDRESS(MX31_GPT1_BASE_ADDR), MX31_INT_GPT); return 0; } diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c index a9e60bf7dd75..920a8cc42726 100644 --- a/arch/arm/mach-imx/clk-imx35.c +++ b/arch/arm/mach-imx/clk-imx35.c @@ -267,11 +267,9 @@ int __init mx35_clocks_init() imx_print_silicon_rev("i.MX35", mx35_revision()); #ifdef CONFIG_MXC_USE_EPIT - epit_timer_init(&epit1_clk, - MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1); + epit_timer_init(MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1); #else - mxc_timer_init(NULL, MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), - MX35_INT_GPT); + mxc_timer_init(MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT); #endif return 0; diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c index 1e7828d6be95..c1739f6078d5 100644 --- a/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/arch/arm/mach-imx/clk-imx51-imx53.c @@ -329,8 +329,7 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, clk_set_rate(clk[esdhc_b_podf], 166250000); /* System timer */ - mxc_timer_init(NULL, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), - MX51_INT_GPT); + mxc_timer_init(MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), MX51_INT_GPT); clk_prepare_enable(clk[iim_gate]); imx_print_silicon_rev("i.MX51", mx51_revision()); @@ -412,8 +411,7 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, clk_set_rate(clk[esdhc_b_podf], 200000000); /* System timer */ - mxc_timer_init(NULL, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR), - MX53_INT_GPT); + mxc_timer_init(MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR), MX53_INT_GPT); clk_prepare_enable(clk[iim_gate]); imx_print_silicon_rev("i.MX53", mx53_revision()); diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index f40a35da2e5c..24324f2dac95 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -433,7 +433,7 @@ int __init mx6q_clocks_init(void) base = of_iomap(np, 0); WARN_ON(!base); irq = irq_of_parse_and_map(np, 0); - mxc_timer_init(NULL, base, irq); + mxc_timer_init(base, irq); return 0; } diff --git a/arch/arm/plat-mxc/epit.c b/arch/arm/plat-mxc/epit.c index 9129c9e7d532..88726f4dbbfa 100644 --- a/arch/arm/plat-mxc/epit.c +++ b/arch/arm/plat-mxc/epit.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -201,8 +202,16 @@ static int __init epit_clockevent_init(struct clk *timer_clk) return 0; } -void __init epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq) +void __init epit_timer_init(void __iomem *base, int irq) { + struct clk *timer_clk; + + timer_clk = clk_get_sys("imx-epit.0", NULL); + if (IS_ERR(timer_clk)) { + pr_err("i.MX epit: unable to get clk\n"); + return; + } + clk_prepare_enable(timer_clk); timer_base = base; diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index 0319c4a0cafa..da02540f4bd4 100644 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -53,8 +53,8 @@ extern void imx35_soc_init(void); extern void imx50_soc_init(void); extern void imx51_soc_init(void); extern void imx53_soc_init(void); -extern void epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq); -extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int); +extern void epit_timer_init(void __iomem *base, int irq); +extern void mxc_timer_init(void __iomem *, int); extern int mx1_clocks_init(unsigned long fref); extern int mx21_clocks_init(unsigned long lref, unsigned long fref); extern int mx25_clocks_init(void); diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c index d865f7960baf..00e8e659e667 100644 --- a/arch/arm/plat-mxc/time.c +++ b/arch/arm/plat-mxc/time.c @@ -281,23 +281,22 @@ static int __init mxc_clockevent_init(struct clk *timer_clk) return 0; } -void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq) +void __init mxc_timer_init(void __iomem *base, int irq) { uint32_t tctl_val; + struct clk *timer_clk; struct clk *timer_ipg_clk; - if (!timer_clk) { - timer_clk = clk_get_sys("imx-gpt.0", "per"); - if (IS_ERR(timer_clk)) { - pr_err("i.MX timer: unable to get clk\n"); - return; - } - - timer_ipg_clk = clk_get_sys("imx-gpt.0", "ipg"); - if (!IS_ERR(timer_ipg_clk)) - clk_prepare_enable(timer_ipg_clk); + timer_clk = clk_get_sys("imx-gpt.0", "per"); + if (IS_ERR(timer_clk)) { + pr_err("i.MX timer: unable to get clk\n"); + return; } + timer_ipg_clk = clk_get_sys("imx-gpt.0", "ipg"); + if (!IS_ERR(timer_ipg_clk)) + clk_prepare_enable(timer_ipg_clk); + clk_prepare_enable(timer_clk); timer_base = base; -- cgit v1.2.3 From b0286f20c36d0c1e7537489daddaf574abf403dd Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Mon, 14 May 2012 13:04:47 +0800 Subject: ARM: imx6q: prepare and enable init on clks directly instead of clk_get first This also removes the usboh3 clk from the initially turned on clocks which leaked in from an internal development tree. Signed-off-by: Richard Zhao Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/clk-imx6q.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 24324f2dac95..7b4751dbe749 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -122,10 +122,6 @@ static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5 "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0", "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_audio", }; -static const char * const clks_init_on[] __initconst = { - "mmdc_ch0_axi", "mmdc_ch1_axi", "usboh3", -}; - enum mx6q_clks { dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m, pll3_pfd0_720m, pll3_pfd1_540m, pll3_pfd2_508m, pll3_pfd3_454m, @@ -160,11 +156,14 @@ enum mx6q_clks { static struct clk *clk[clk_max]; +static enum mx6q_clks const clks_init_on[] __initconst = { + mmdc_ch0_axi, mmdc_ch1_axi, +}; + int __init mx6q_clocks_init(void) { struct device_node *np; void __iomem *base; - struct clk *c; int i, irq; clk[dummy] = imx_clk_fixed("dummy", 0); @@ -419,15 +418,8 @@ int __init mx6q_clocks_init(void) clk_register_clkdev(clk[dummy], NULL, "20bc000.wdog"); clk_register_clkdev(clk[dummy], NULL, "20c0000.wdog"); - for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) { - c = clk_get_sys(clks_init_on[i], NULL); - if (IS_ERR(c)) { - pr_err("%s: failed to get clk %s", __func__, - clks_init_on[i]); - return PTR_ERR(c); - } - clk_prepare_enable(c); - } + for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) + clk_prepare_enable(clk[clks_init_on[i]]); np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); base = of_iomap(np, 0); -- cgit v1.2.3 From d0e05bb3d611c7c3d37cadd8c1016ee2e22beefa Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 18 May 2012 10:20:33 +0900 Subject: sh: mach-se: Migrate 7724SE off of deprecated dynamic IRQ API. The generic hardirq layer provides all of the routines that we need these days, so we don't require any of the dynamic IRQ API wrapping, and can call in to irq_alloc_descs() directly. Signed-off-by: Paul Mundt --- arch/sh/boards/mach-se/7724/irq.c | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) (limited to 'arch') diff --git a/arch/sh/boards/mach-se/7724/irq.c b/arch/sh/boards/mach-se/7724/irq.c index c6342ce7768d..5d1d3ec9a6cd 100644 --- a/arch/sh/boards/mach-se/7724/irq.c +++ b/arch/sh/boards/mach-se/7724/irq.c @@ -17,8 +17,10 @@ #include #include #include -#include -#include +#include +#include +#include +#include #include struct fpga_irq { @@ -111,7 +113,7 @@ static void se7724_irq_demux(unsigned int irq, struct irq_desc *desc) */ void __init init_se7724_IRQ(void) { - int i, nid = cpu_to_node(boot_cpu_data); + int irq_base, i; __raw_writew(0xffff, IRQ0_MR); /* mask all */ __raw_writew(0xffff, IRQ1_MR); /* mask all */ @@ -121,28 +123,16 @@ void __init init_se7724_IRQ(void) __raw_writew(0x0000, IRQ2_SR); /* clear irq */ __raw_writew(0x002a, IRQ_MODE); /* set irq type */ - for (i = 0; i < SE7724_FPGA_IRQ_NR; i++) { - int irq, wanted; - - wanted = SE7724_FPGA_IRQ_BASE + i; - - irq = create_irq_nr(wanted, nid); - if (unlikely(irq == 0)) { - pr_err("%s: failed hooking irq %d for FPGA\n", - __func__, wanted); - return; - } - - if (unlikely(irq != wanted)) { - pr_err("%s: got irq %d but wanted %d, bailing.\n", - __func__, irq, wanted); - destroy_irq(irq); - return; - } + irq_base = irq_alloc_descs(SE7724_FPGA_IRQ_BASE, SE7724_FPGA_IRQ_BASE, + SE7724_FPGA_IRQ_NR, numa_node_id()); + if (IS_ERR_VALUE(irq_base)) { + pr_err("%s: failed hooking irqs for FPGA\n", __func__); + return; + } - irq_set_chip_and_handler_name(irq, &se7724_irq_chip, + for (i = 0; i < SE7724_FPGA_IRQ_NR; i++) + irq_set_chip_and_handler_name(irq_base + i, &se7724_irq_chip, handle_level_irq, "level"); - } irq_set_chained_handler(IRQ0_IRQ, se7724_irq_demux); irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); -- cgit v1.2.3 From 051f923d922d105f4d32e64cba1ed6f5a749d530 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 18 May 2012 23:20:09 +0900 Subject: sh: hd64461: Migrate off of deprecated dynamic IRQ API. Switches from create_irq_nr() to irq_alloc_descs(). Signed-off-by: Paul Mundt --- arch/sh/cchips/hd6446x/hd64461.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) (limited to 'arch') diff --git a/arch/sh/cchips/hd6446x/hd64461.c b/arch/sh/cchips/hd6446x/hd64461.c index eb4ea4d44d59..e9735616bdc8 100644 --- a/arch/sh/cchips/hd6446x/hd64461.c +++ b/arch/sh/cchips/hd6446x/hd64461.c @@ -73,10 +73,7 @@ static void hd64461_irq_demux(unsigned int irq, struct irq_desc *desc) int __init setup_hd64461(void) { - int i, nid = cpu_to_node(boot_cpu_data); - - if (!MACH_HD64461) - return 0; + int irq_base, i; printk(KERN_INFO "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n", @@ -89,28 +86,16 @@ int __init setup_hd64461(void) #endif __raw_writew(0xffff, HD64461_NIMR); - /* IRQ 80 -> 95 belongs to HD64461 */ - for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) { - unsigned int irq; - - irq = create_irq_nr(i, nid); - if (unlikely(irq == 0)) { - pr_err("%s: failed hooking irq %d for HD64461\n", - __func__, i); - return -EBUSY; - } - - if (unlikely(irq != i)) { - pr_err("%s: got irq %d but wanted %d, bailing.\n", - __func__, irq, i); - destroy_irq(irq); - return -EINVAL; - } - - irq_set_chip_and_handler(i, &hd64461_irq_chip, - handle_level_irq); + irq_base = irq_alloc_descs(HD64461_IRQBASE, HD64461_IRQBASE, 16, -1); + if (IS_ERR_VALUE(irq_base)) { + pr_err("%s: failed hooking irqs for HD64461\n", __func__); + return irq_base; } + for (i = 0; i < 16; i++) + irq_set_chip_and_handler(irq_base + i, &hd64461_irq_chip, + handle_level_irq); + irq_set_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux); irq_set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW); -- cgit v1.2.3 From 3b1267b90f6b7c080024101696c0454f455761f4 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 18 May 2012 23:36:44 +0900 Subject: sh: dreamcast: Migrate off of deprecated dynamic IRQ API. Switches from create_irq_nr() to irq_alloc_descs(). Signed-off-by: Paul Mundt --- arch/sh/boards/mach-dreamcast/irq.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/sh/boards/mach-dreamcast/irq.c b/arch/sh/boards/mach-dreamcast/irq.c index f63d323f411f..2789647abebe 100644 --- a/arch/sh/boards/mach-dreamcast/irq.c +++ b/arch/sh/boards/mach-dreamcast/irq.c @@ -8,10 +8,11 @@ * This file is part of the LinuxDC project (www.linuxdc.org) * Released under the terms of the GNU GPL v2.0 */ - #include #include -#include +#include +#include +#include #include /* @@ -141,26 +142,15 @@ int systemasic_irq_demux(int irq) void systemasic_irq_init(void) { - int i, nid = cpu_to_node(boot_cpu_data); - - /* Assign all virtual IRQs to the System ASIC int. handler */ - for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) { - unsigned int irq; - - irq = create_irq_nr(i, nid); - if (unlikely(irq == 0)) { - pr_err("%s: failed hooking irq %d for systemasic\n", - __func__, i); - return; - } + int irq_base, i; - if (unlikely(irq != i)) { - pr_err("%s: got irq %d but wanted %d, bailing.\n", - __func__, irq, i); - destroy_irq(irq); - return; - } + irq_base = irq_alloc_descs(HW_EVENT_IRQ_BASE, HW_EVENT_IRQ_BASE, + HW_EVENT_IRQ_MAX - HW_EVENT_IRQ_BASE, -1); + if (IS_ERR_VALUE(irq_base)) { + pr_err("%s: failed hooking irqs\n", __func__); + return; + } + for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) irq_set_chip_and_handler(i, &systemasic_int, handle_level_irq); - } } -- cgit v1.2.3 From 76b386624576eb00a7c7cad0e713952121708598 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 May 2012 13:59:35 +0900 Subject: sh: Kill off now unused arch_probe_nr_irqs(). Now that legacy pre-allocation is done away with, we can just use the generic stub in kernel/softirq.c. Signed-off-by: Paul Mundt --- arch/sh/kernel/irq.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'arch') diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index dadce735f746..063af10ff3c1 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -231,16 +231,6 @@ void __init init_IRQ(void) irq_ctx_init(smp_processor_id()); } -#ifdef CONFIG_SPARSE_IRQ -int __init arch_probe_nr_irqs(void) -{ - /* - * No pre-allocated IRQs. - */ - return 0; -} -#endif - #ifdef CONFIG_HOTPLUG_CPU static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu) { -- cgit v1.2.3 From 49453264997f232008efae457553d82381f9614f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 May 2012 15:03:46 +0900 Subject: sh64: Convert to unwinder API. This switches over to use the sh unwinder API which brings it all in line with the general sh routines (which we shuffle around at the same time), and lets us kill off more sh64-specific cruft. Signed-off-by: Paul Mundt --- arch/sh/include/asm/kdebug.h | 2 ++ arch/sh/kernel/cpu/sh5/unwind.c | 63 +++++++++++++++++++++++++++-------------- arch/sh/kernel/dumpstack.c | 58 +++++++++++++++++++++++++++++++++++++ arch/sh/kernel/traps_32.c | 50 -------------------------------- arch/sh/kernel/traps_64.c | 26 ----------------- 5 files changed, 101 insertions(+), 98 deletions(-) (limited to 'arch') diff --git a/arch/sh/include/asm/kdebug.h b/arch/sh/include/asm/kdebug.h index a6201f10c273..8d6a831e7ba1 100644 --- a/arch/sh/include/asm/kdebug.h +++ b/arch/sh/include/asm/kdebug.h @@ -10,6 +10,8 @@ enum die_val { DIE_SSTEP, }; +/* arch/sh/kernel/dumpstack.c */ extern void printk_address(unsigned long address, int reliable); +extern void dump_mem(const char *str, unsigned long bottom, unsigned long top); #endif /* __ASM_SH_KDEBUG_H */ diff --git a/arch/sh/kernel/cpu/sh5/unwind.c b/arch/sh/kernel/cpu/sh5/unwind.c index b205b25eaf45..10aed41757fc 100644 --- a/arch/sh/kernel/cpu/sh5/unwind.c +++ b/arch/sh/kernel/cpu/sh5/unwind.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include static u8 regcache[63]; @@ -199,8 +201,11 @@ static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc, return 0; } -/* Don't put this on the stack since we'll want to call sh64_unwind - * when we're close to underflowing the stack anyway. */ +/* + * Don't put this on the stack since we'll want to call in to + * sh64_unwinder_dump() when we're close to underflowing the stack + * anyway. + */ static struct pt_regs here_regs; extern const char syscall_ret; @@ -208,17 +213,19 @@ extern const char ret_from_syscall; extern const char ret_from_exception; extern const char ret_from_irq; -static void sh64_unwind_inner(struct pt_regs *regs); +static void sh64_unwind_inner(const struct stacktrace_ops *ops, + void *data, struct pt_regs *regs); -static void unwind_nested (unsigned long pc, unsigned long fp) +static inline void unwind_nested(const struct stacktrace_ops *ops, void *data, + unsigned long pc, unsigned long fp) { if ((fp >= __MEMORY_START) && - ((fp & 7) == 0)) { - sh64_unwind_inner((struct pt_regs *) fp); - } + ((fp & 7) == 0)) + sh64_unwind_inner(ops, data, (struct pt_regs *)fp); } -static void sh64_unwind_inner(struct pt_regs *regs) +static void sh64_unwind_inner(const struct stacktrace_ops *ops, + void *data, struct pt_regs *regs) { unsigned long pc, fp; int ofs = 0; @@ -232,29 +239,29 @@ static void sh64_unwind_inner(struct pt_regs *regs) int cond; unsigned long next_fp, next_pc; - if (pc == ((unsigned long) &syscall_ret & ~1)) { + if (pc == ((unsigned long)&syscall_ret & ~1)) { printk("SYSCALL\n"); - unwind_nested(pc,fp); + unwind_nested(ops, data, pc, fp); return; } - if (pc == ((unsigned long) &ret_from_syscall & ~1)) { + if (pc == ((unsigned long)&ret_from_syscall & ~1)) { printk("SYSCALL (PREEMPTED)\n"); - unwind_nested(pc,fp); + unwind_nested(ops, data, pc, fp); return; } /* In this case, the PC is discovered by lookup_prev_stack_frame but it has 4 taken off it to look like the 'caller' */ - if (pc == ((unsigned long) &ret_from_exception & ~1)) { + if (pc == ((unsigned long)&ret_from_exception & ~1)) { printk("EXCEPTION\n"); - unwind_nested(pc,fp); + unwind_nested(ops, data, pc, fp); return; } - if (pc == ((unsigned long) &ret_from_irq & ~1)) { + if (pc == ((unsigned long)&ret_from_irq & ~1)) { printk("IRQ\n"); - unwind_nested(pc,fp); + unwind_nested(ops, data, pc, fp); return; } @@ -263,8 +270,7 @@ static void sh64_unwind_inner(struct pt_regs *regs) pc -= ofs; - printk("[<%08lx>] ", pc); - print_symbol("%s\n", pc); + ops->address(data, pc, 1); if (first_pass) { /* If the innermost frame is a leaf function, it's @@ -287,10 +293,13 @@ static void sh64_unwind_inner(struct pt_regs *regs) } printk("\n"); - } -void sh64_unwind(struct pt_regs *regs) +static void sh64_unwinder_dump(struct task_struct *task, + struct pt_regs *regs, + unsigned long *sp, + const struct stacktrace_ops *ops, + void *data) { if (!regs) { /* @@ -320,7 +329,17 @@ void sh64_unwind(struct pt_regs *regs) ); } - printk("\nCall Trace:\n"); - sh64_unwind_inner(regs); + sh64_unwind_inner(ops, data, regs); } +static struct unwinder sh64_unwinder = { + .name = "sh64-unwinder", + .dump = sh64_unwinder_dump, + .rating = 150, +}; + +static int __init sh64_unwinder_init(void) +{ + return unwinder_register(&sh64_unwinder); +} +early_initcall(sh64_unwinder_init); diff --git a/arch/sh/kernel/dumpstack.c b/arch/sh/kernel/dumpstack.c index 694158b9a50f..7617dc4129ac 100644 --- a/arch/sh/kernel/dumpstack.c +++ b/arch/sh/kernel/dumpstack.c @@ -2,13 +2,48 @@ * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs * Copyright (C) 2009 Matt Fleming + * Copyright (C) 2002 - 2012 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. */ #include #include #include +#include +#include +#include #include #include +void dump_mem(const char *str, unsigned long bottom, unsigned long top) +{ + unsigned long p; + int i; + + printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top); + + for (p = bottom & ~31; p < top; ) { + printk("%04lx: ", p & 0xffff); + + for (i = 0; i < 8; i++, p += 4) { + unsigned int val; + + if (p < bottom || p >= top) + printk(" "); + else { + if (__get_user(val, (unsigned int __user *)p)) { + printk("\n"); + return; + } + printk("%08x ", val); + } + } + printk("\n"); + } +} + void printk_address(unsigned long address, int reliable) { printk(" [<%p>] %s%pS\n", (void *) address, @@ -106,3 +141,26 @@ void show_trace(struct task_struct *tsk, unsigned long *sp, debug_show_held_locks(tsk); } + +void show_stack(struct task_struct *tsk, unsigned long *sp) +{ + unsigned long stack; + + if (!tsk) + tsk = current; + if (tsk == current) + sp = (unsigned long *)current_stack_pointer; + else + sp = (unsigned long *)tsk->thread.sp; + + stack = (unsigned long)sp; + dump_mem("Stack: ", stack, THREAD_SIZE + + (unsigned long)task_stack_page(tsk)); + show_trace(tsk, sp, NULL); +} + +void dump_stack(void) +{ + show_stack(NULL, NULL); +} +EXPORT_SYMBOL(dump_stack); diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index a37175deb73f..b8f5a51841ec 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -48,33 +48,6 @@ #define TRAP_ILLEGAL_SLOT_INST 13 #endif -static void dump_mem(const char *str, unsigned long bottom, unsigned long top) -{ - unsigned long p; - int i; - - printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top); - - for (p = bottom & ~31; p < top; ) { - printk("%04lx: ", p & 0xffff); - - for (i = 0; i < 8; i++, p += 4) { - unsigned int val; - - if (p < bottom || p >= top) - printk(" "); - else { - if (__get_user(val, (unsigned int __user *)p)) { - printk("\n"); - return; - } - printk("%08x ", val); - } - } - printk("\n"); - } -} - static DEFINE_SPINLOCK(die_lock); void die(const char * str, struct pt_regs * regs, long err) @@ -900,26 +873,3 @@ void __init trap_init(void) set_exception_table_vec(TRAP_UBC, breakpoint_trap_handler); #endif } - -void show_stack(struct task_struct *tsk, unsigned long *sp) -{ - unsigned long stack; - - if (!tsk) - tsk = current; - if (tsk == current) - sp = (unsigned long *)current_stack_pointer; - else - sp = (unsigned long *)tsk->thread.sp; - - stack = (unsigned long)sp; - dump_mem("Stack: ", stack, THREAD_SIZE + - (unsigned long)task_stack_page(tsk)); - show_trace(tsk, sp, NULL); -} - -void dump_stack(void) -{ - show_stack(NULL, NULL); -} -EXPORT_SYMBOL(dump_stack); diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c index 8dae93ed8aff..ba95d63e623d 100644 --- a/arch/sh/kernel/traps_64.c +++ b/arch/sh/kernel/traps_64.c @@ -253,32 +253,6 @@ int do_unknown_trapa(unsigned long scId, struct pt_regs *regs) return -ENOSYS; } -void show_stack(struct task_struct *tsk, unsigned long *sp) -{ -#ifdef CONFIG_KALLSYMS - extern void sh64_unwind(struct pt_regs *regs); - struct pt_regs *regs; - - regs = tsk ? tsk->thread.kregs : NULL; - - sh64_unwind(regs); -#else - printk(KERN_ERR "Can't backtrace on sh64 without CONFIG_KALLSYMS\n"); -#endif -} - -void show_task(unsigned long *sp) -{ - show_stack(NULL, sp); -} - -void dump_stack(void) -{ - show_task(NULL); -} -/* Needed by any user of WARN_ON in view of the defn in include/asm-sh/bug.h */ -EXPORT_SYMBOL(dump_stack); - static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name, unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk) { -- cgit v1.2.3 From 3a898c0f36f9fe312cb6e98865a6833110e67cb2 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 May 2012 15:05:29 +0900 Subject: sh64: Ensure KALLSYMS is enabled for unwinder use. Since sh64 depends on kallsyms unconditionally for its stack unwinding to be of any use, make sure it's selected. In practice we don't have any case where it's disabled anyways, so moving to this to a select is fine. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 3e723aaa5e18..931310b49bce 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -55,6 +55,7 @@ config SUPERH32 config SUPERH64 def_bool ARCH = "sh64" + select KALLSYMS config ARCH_DEFCONFIG string -- cgit v1.2.3 From b98b35815f40f01337e25e3f0d10d57b7cec5126 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 May 2012 15:24:39 +0900 Subject: sh: mach-x3proto: Migrate to linear irq domain. In the interest of getting off of the create_irq() API we can get all of the functionality we're interested in through a linear IRQ domain. Fairly straightforward conversion utilizing a single linear domain. Signed-off-by: Paul Mundt --- arch/sh/boards/Kconfig | 1 + arch/sh/boards/mach-x3proto/gpio.c | 57 +++++++++++++++++++++----------------- 2 files changed, 32 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index d893411022d5..f2024a91319f 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -292,6 +292,7 @@ config SH_X3PROTO bool "SH-X3 Prototype board" depends on CPU_SUBTYPE_SHX3 select NO_IOPORT if !PCI + select IRQ_DOMAIN config SH_MAGIC_PANEL_R2 bool "Magic Panel R2" diff --git a/arch/sh/boards/mach-x3proto/gpio.c b/arch/sh/boards/mach-x3proto/gpio.c index f33b2b57019c..3ea65e9b56e8 100644 --- a/arch/sh/boards/mach-x3proto/gpio.c +++ b/arch/sh/boards/mach-x3proto/gpio.c @@ -3,7 +3,7 @@ * * Renesas SH-X3 Prototype Baseboard GPIO Support. * - * Copyright (C) 2010 Paul Mundt + * Copyright (C) 2010 - 2012 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -26,7 +27,7 @@ #define KEYDETR 0xb81c0004 static DEFINE_SPINLOCK(x3proto_gpio_lock); -static unsigned int x3proto_gpio_irq_map[NR_BASEBOARD_GPIOS] = { 0, }; +static struct irq_domain *x3proto_irq_domain; static int x3proto_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { @@ -49,7 +50,14 @@ static int x3proto_gpio_get(struct gpio_chip *chip, unsigned gpio) static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) { - return x3proto_gpio_irq_map[gpio]; + int virq; + + if (gpio < chip->ngpio) + virq = irq_create_mapping(x3proto_irq_domain, gpio); + else + virq = -ENXIO; + + return virq; } static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) @@ -62,9 +70,8 @@ static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) chip->irq_mask_ack(data); mask = __raw_readw(KEYDETR); - for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS) - generic_handle_irq(x3proto_gpio_to_irq(NULL, pin)); + generic_handle_irq(irq_linear_revmap(x3proto_irq_domain, pin)); chip->irq_unmask(data); } @@ -78,10 +85,23 @@ struct gpio_chip x3proto_gpio_chip = { .ngpio = NR_BASEBOARD_GPIOS, }; +static int x3proto_gpio_irq_map(struct irq_domain *domain, unsigned int virq, + irq_hw_number_t hwirq) +{ + irq_set_chip_and_handler_name(virq, &dummy_irq_chip, handle_simple_irq, + "gpio"); + + return 0; +} + +static struct irq_domain_ops x3proto_gpio_irq_ops = { + .map = x3proto_gpio_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + int __init x3proto_gpio_setup(void) { - int ilsel; - int ret, i; + int ilsel, ret; ilsel = ilsel_enable(ILSEL_KEY); if (unlikely(ilsel < 0)) @@ -91,21 +111,10 @@ int __init x3proto_gpio_setup(void) if (unlikely(ret)) goto err_gpio; - for (i = 0; i < NR_BASEBOARD_GPIOS; i++) { - unsigned long flags; - int irq = create_irq(); - - if (unlikely(irq < 0)) { - ret = -EINVAL; - goto err_irq; - } - - spin_lock_irqsave(&x3proto_gpio_lock, flags); - x3proto_gpio_irq_map[i] = irq; - irq_set_chip_and_handler_name(irq, &dummy_irq_chip, - handle_simple_irq, "gpio"); - spin_unlock_irqrestore(&x3proto_gpio_lock, flags); - } + x3proto_irq_domain = irq_domain_add_linear(NULL, NR_BASEBOARD_GPIOS, + &x3proto_gpio_irq_ops, NULL); + if (unlikely(!x3proto_irq_domain)) + goto err_irq; pr_info("registering '%s' support, handling GPIOs %u -> %u, " "bound to IRQ %u\n", @@ -119,10 +128,6 @@ int __init x3proto_gpio_setup(void) return 0; err_irq: - for (; i >= 0; --i) - if (x3proto_gpio_irq_map[i]) - destroy_irq(x3proto_gpio_irq_map[i]); - ret = gpiochip_remove(&x3proto_gpio_chip); if (unlikely(ret)) pr_err("Failed deregistering GPIO\n"); -- cgit v1.2.3 From 5df38b9b7676e4e46c5c13e75f023ffb82542980 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 May 2012 18:24:32 +0900 Subject: sh: se722: Move FPGA IRQs to irqdomain and generic irq chip. This implements a total rewrite of the rather buggy SE7722 FPGA IRQ code, utilizing a linear irq domain as well as the generic irq chip type. While the interaction between the two APIs is a bit clunky (ie, revmap lookup for gc irq_base), they work well enough together that it's easy enough to work with going forward. While we're at it, deal with irq_mask_ack/unmask of the chained IRQ in the demux handler to prevent smc91x screaming about spurious interrupts. There's also some more improvement that can be made to the irqdomain code to create backing irqdescs for the entire linear range in one bang instead of iterating over the number of hwirqs and doing it irq-at-a-time. This is easily dealt with at a later point, though. Signed-off-by: Paul Mundt --- arch/sh/boards/Kconfig | 2 + arch/sh/boards/mach-se/7722/irq.c | 131 ++++++++++++++++++++++------------ arch/sh/boards/mach-se/7722/setup.c | 6 +- arch/sh/include/mach-se/mach/se7722.h | 10 +-- 4 files changed, 94 insertions(+), 55 deletions(-) (limited to 'arch') diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index f2024a91319f..525b9e32cd14 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -44,6 +44,8 @@ config SH_7721_SOLUTION_ENGINE config SH_7722_SOLUTION_ENGINE bool "SolutionEngine7722" select SOLUTION_ENGINE + select GENERIC_IRQ_CHIP + select IRQ_DOMAIN depends on CPU_SUBTYPE_SH7722 help Select 7722 SolutionEngine if configuring for a Hitachi SH772 diff --git a/arch/sh/boards/mach-se/7722/irq.c b/arch/sh/boards/mach-se/7722/irq.c index aac92f21ebd2..f5e2af1bf040 100644 --- a/arch/sh/boards/mach-se/7722/irq.c +++ b/arch/sh/boards/mach-se/7722/irq.c @@ -1,79 +1,96 @@ /* - * linux/arch/sh/boards/se/7722/irq.c + * Hitachi UL SolutionEngine 7722 FPGA IRQ Support. * * Copyright (C) 2007 Nobuhiro Iwamatsu - * - * Hitachi UL SolutionEngine 7722 Support. + * Copyright (C) 2012 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. */ +#define DRV_NAME "SE7722-FPGA" +#define pr_fmt(fmt) DRV_NAME ": " fmt + +#define irq_reg_readl ioread16 +#define irq_reg_writel iowrite16 + #include #include #include -#include -#include +#include +#include +#include +#include #include -unsigned int se7722_fpga_irq[SE7722_FPGA_IRQ_NR] = { 0, }; +#define IRQ01_BASE_ADDR 0x11800000 +#define IRQ01_MODE_REG 0 +#define IRQ01_STS_REG 4 +#define IRQ01_MASK_REG 8 -static void disable_se7722_irq(struct irq_data *data) -{ - unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); - __raw_writew(__raw_readw(IRQ01_MASK) | 1 << bit, IRQ01_MASK); -} +static void __iomem *se7722_irq_regs; +struct irq_domain *se7722_irq_domain; -static void enable_se7722_irq(struct irq_data *data) +static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc) { - unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); - __raw_writew(__raw_readw(IRQ01_MASK) & ~(1 << bit), IRQ01_MASK); -} + struct irq_data *data = irq_get_irq_data(irq); + struct irq_chip *chip = irq_data_get_irq_chip(data); + unsigned long mask; + int bit; -static struct irq_chip se7722_irq_chip __read_mostly = { - .name = "SE7722-FPGA", - .irq_mask = disable_se7722_irq, - .irq_unmask = enable_se7722_irq, -}; + chip->irq_mask_ack(data); -static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc) + mask = ioread16(se7722_irq_regs + IRQ01_STS_REG); + + for_each_set_bit(bit, &mask, SE7722_FPGA_IRQ_NR) + generic_handle_irq(irq_linear_revmap(se7722_irq_domain, bit)); + + chip->irq_unmask(data); +} + +static void __init se7722_domain_init(void) { - unsigned short intv = __raw_readw(IRQ01_STS); - unsigned int ext_irq = 0; + int i; - intv &= (1 << SE7722_FPGA_IRQ_NR) - 1; + se7722_irq_domain = irq_domain_add_linear(NULL, SE7722_FPGA_IRQ_NR, + &irq_domain_simple_ops, NULL); + if (unlikely(!se7722_irq_domain)) { + printk("Failed to get IRQ domain\n"); + return; + } - for (; intv; intv >>= 1, ext_irq++) { - if (!(intv & 1)) - continue; + for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) { + int irq = irq_create_mapping(se7722_irq_domain, i); - generic_handle_irq(se7722_fpga_irq[ext_irq]); + if (unlikely(irq == 0)) { + printk("Failed to allocate IRQ %d\n", i); + return; + } } } -/* - * Initialize IRQ setting - */ -void __init init_se7722_IRQ(void) +static void __init se7722_gc_init(void) { - int i, irq; + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + unsigned int irq_base; - __raw_writew(0, IRQ01_MASK); /* disable all irqs */ - __raw_writew(0x2000, 0xb03fffec); /* mrshpc irq enable */ + irq_base = irq_linear_revmap(se7722_irq_domain, 0); - for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) { - irq = create_irq(); - if (irq < 0) - return; - se7722_fpga_irq[i] = irq; + gc = irq_alloc_generic_chip(DRV_NAME, 1, irq_base, se7722_irq_regs, + handle_level_irq); + if (unlikely(!gc)) + return; - irq_set_chip_and_handler_name(se7722_fpga_irq[i], - &se7722_irq_chip, - handle_level_irq, - "level"); + ct = gc->chip_types; + ct->chip.irq_mask = irq_gc_mask_set_bit; + ct->chip.irq_unmask = irq_gc_mask_clr_bit; - irq_set_chip_data(se7722_fpga_irq[i], (void *)i); - } + ct->regs.mask = IRQ01_MASK_REG; + + irq_setup_generic_chip(gc, IRQ_MSK(SE7722_FPGA_IRQ_NR), + IRQ_GC_INIT_MASK_CACHE, + IRQ_NOREQUEST | IRQ_NOPROBE, 0); irq_set_chained_handler(IRQ0_IRQ, se7722_irq_demux); irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); @@ -81,3 +98,25 @@ void __init init_se7722_IRQ(void) irq_set_chained_handler(IRQ1_IRQ, se7722_irq_demux); irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW); } + +/* + * Initialize FPGA IRQs + */ +void __init init_se7722_IRQ(void) +{ + se7722_irq_regs = ioremap(IRQ01_BASE_ADDR, SZ_16); + if (unlikely(!se7722_irq_regs)) { + printk("Failed to remap IRQ01 regs\n"); + return; + } + + /* + * All FPGA IRQs disabled by default + */ + iowrite16(0, se7722_irq_regs + IRQ01_MASK_REG); + + __raw_writew(0x2000, 0xb03fffec); /* mrshpc irq enable */ + + se7722_domain_init(); + se7722_gc_init(); +} diff --git a/arch/sh/boards/mach-se/7722/setup.c b/arch/sh/boards/mach-se/7722/setup.c index e1963fecd761..2ec0111fdf9b 100644 --- a/arch/sh/boards/mach-se/7722/setup.c +++ b/arch/sh/boards/mach-se/7722/setup.c @@ -2,6 +2,7 @@ * linux/arch/sh/boards/se/7722/setup.c * * Copyright (C) 2007 Nobuhiro Iwamatsu + * Copyright (C) 2012 Paul Mundt * * Hitachi UL SolutionEngine 7722 Support. * @@ -15,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -142,10 +144,10 @@ static int __init se7722_devices_setup(void) /* Wire-up dynamic vectors */ cf_ide_resources[2].start = cf_ide_resources[2].end = - se7722_fpga_irq[SE7722_FPGA_IRQ_MRSHPC0]; + irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_MRSHPC0); smc91x_eth_resources[1].start = smc91x_eth_resources[1].end = - se7722_fpga_irq[SE7722_FPGA_IRQ_SMC]; + irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_SMC); return platform_add_devices(se7722_devices, ARRAY_SIZE(se7722_devices)); } diff --git a/arch/sh/include/mach-se/mach/se7722.h b/arch/sh/include/mach-se/mach/se7722.h index 16505bfb8a9e..5508dc42e4d2 100644 --- a/arch/sh/include/mach-se/mach/se7722.h +++ b/arch/sh/include/mach-se/mach/se7722.h @@ -80,12 +80,6 @@ #define IRQ0_IRQ 32 #define IRQ1_IRQ 33 -#define IRQ01_MODE 0xb1800000 -#define IRQ01_STS 0xb1800004 -#define IRQ01_MASK 0xb1800008 - -/* Bits in IRQ01_* registers */ - #define SE7722_FPGA_IRQ_USB 0 /* IRQ0 */ #define SE7722_FPGA_IRQ_SMC 1 /* IRQ0 */ #define SE7722_FPGA_IRQ_MRSHPC0 2 /* IRQ1 */ @@ -94,8 +88,10 @@ #define SE7722_FPGA_IRQ_MRSHPC3 5 /* IRQ1 */ #define SE7722_FPGA_IRQ_NR 6 +struct irq_domain; + /* arch/sh/boards/se/7722/irq.c */ -extern unsigned int se7722_fpga_irq[]; +extern struct irq_domain *se7722_irq_domain; void init_se7722_IRQ(void); -- cgit v1.2.3 From 197b58e6651426bec8b2582013258b52cd15a444 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 May 2012 19:07:18 +0900 Subject: sh: se7343: Move CPLD IRQs to irqdomain and generic irq chip. Follows the se7722 change, see there for more information. Signed-off-by: Paul Mundt --- arch/sh/boards/Kconfig | 2 + arch/sh/boards/mach-se/7343/irq.c | 129 ++++++++++++++++++++++------------ arch/sh/boards/mach-se/7343/setup.c | 10 +-- arch/sh/include/mach-se/mach/se7343.h | 7 +- 4 files changed, 97 insertions(+), 51 deletions(-) (limited to 'arch') diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 525b9e32cd14..1a280048e2c3 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -81,6 +81,8 @@ config SH_7780_SOLUTION_ENGINE config SH_7343_SOLUTION_ENGINE bool "SolutionEngine7343" select SOLUTION_ENGINE + select GENERIC_IRQ_CHIP + select IRQ_DOMAIN depends on CPU_SUBTYPE_SH7343 help Select 7343 SolutionEngine if configuring for a Hitachi diff --git a/arch/sh/boards/mach-se/7343/irq.c b/arch/sh/boards/mach-se/7343/irq.c index fd45ffc48340..7646bf0486c2 100644 --- a/arch/sh/boards/mach-se/7343/irq.c +++ b/arch/sh/boards/mach-se/7343/irq.c @@ -1,86 +1,129 @@ /* - * linux/arch/sh/boards/se/7343/irq.c + * Hitachi UL SolutionEngine 7343 FPGA IRQ Support. * * Copyright (C) 2008 Yoshihiro Shimoda + * Copyright (C) 2012 Paul Mundt * - * Based on linux/arch/sh/boards/se/7722/irq.c + * Based on linux/arch/sh/boards/se/7343/irq.c * Copyright (C) 2007 Nobuhiro Iwamatsu * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. */ +#define DRV_NAME "SE7343-FPGA" +#define pr_fmt(fmt) DRV_NAME ": " fmt + +#define irq_reg_readl ioread16 +#define irq_reg_writel iowrite16 + #include #include #include +#include #include +#include #include -unsigned int se7343_fpga_irq[SE7343_FPGA_IRQ_NR] = { 0, }; +#define PA_CPLD_BASE_ADDR 0x11400000 +#define PA_CPLD_ST_REG 0x08 /* CPLD Interrupt status register */ +#define PA_CPLD_IMSK_REG 0x0a /* CPLD Interrupt mask register */ -static void disable_se7343_irq(struct irq_data *data) -{ - unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); - __raw_writew(__raw_readw(PA_CPLD_IMSK) | 1 << bit, PA_CPLD_IMSK); -} +static void __iomem *se7343_irq_regs; +struct irq_domain *se7343_irq_domain; -static void enable_se7343_irq(struct irq_data *data) +static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc) { - unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); - __raw_writew(__raw_readw(PA_CPLD_IMSK) & ~(1 << bit), PA_CPLD_IMSK); -} + struct irq_data *data = irq_get_irq_data(irq); + struct irq_chip *chip = irq_data_get_irq_chip(data); + unsigned long mask; + int bit; -static struct irq_chip se7343_irq_chip __read_mostly = { - .name = "SE7343-FPGA", - .irq_mask = disable_se7343_irq, - .irq_unmask = enable_se7343_irq, -}; + chip->irq_mask_ack(data); -static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc) + mask = ioread16(se7343_irq_regs + PA_CPLD_ST_REG); + + for_each_set_bit(bit, &mask, SE7343_FPGA_IRQ_NR) + generic_handle_irq(irq_linear_revmap(se7343_irq_domain, bit)); + + chip->irq_unmask(data); +} + +static void __init se7343_domain_init(void) { - unsigned short intv = __raw_readw(PA_CPLD_ST); - unsigned int ext_irq = 0; + int i; - intv &= (1 << SE7343_FPGA_IRQ_NR) - 1; + se7343_irq_domain = irq_domain_add_linear(NULL, SE7343_FPGA_IRQ_NR, + &irq_domain_simple_ops, NULL); + if (unlikely(!se7343_irq_domain)) { + printk("Failed to get IRQ domain\n"); + return; + } - for (; intv; intv >>= 1, ext_irq++) { - if (!(intv & 1)) - continue; + for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) { + int irq = irq_create_mapping(se7343_irq_domain, i); - generic_handle_irq(se7343_fpga_irq[ext_irq]); + if (unlikely(irq == 0)) { + printk("Failed to allocate IRQ %d\n", i); + return; + } } } -/* - * Initialize IRQ setting - */ -void __init init_7343se_IRQ(void) +static void __init se7343_gc_init(void) { - int i, irq; + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + unsigned int irq_base; - __raw_writew(0, PA_CPLD_IMSK); /* disable all irqs */ - __raw_writew(0x2000, 0xb03fffec); /* mrshpc irq enable */ + irq_base = irq_linear_revmap(se7343_irq_domain, 0); - for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) { - irq = create_irq(); - if (irq < 0) - return; - se7343_fpga_irq[i] = irq; + gc = irq_alloc_generic_chip(DRV_NAME, 1, irq_base, se7343_irq_regs, + handle_level_irq); + if (unlikely(!gc)) + return; - irq_set_chip_and_handler_name(se7343_fpga_irq[i], - &se7343_irq_chip, - handle_level_irq, - "level"); + ct = gc->chip_types; + ct->chip.irq_mask = irq_gc_mask_set_bit; + ct->chip.irq_unmask = irq_gc_mask_clr_bit; - irq_set_chip_data(se7343_fpga_irq[i], (void *)i); - } + ct->regs.mask = PA_CPLD_IMSK_REG; + + irq_setup_generic_chip(gc, IRQ_MSK(SE7343_FPGA_IRQ_NR), + IRQ_GC_INIT_MASK_CACHE, + IRQ_NOREQUEST | IRQ_NOPROBE, 0); irq_set_chained_handler(IRQ0_IRQ, se7343_irq_demux); irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); + irq_set_chained_handler(IRQ1_IRQ, se7343_irq_demux); irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW); + irq_set_chained_handler(IRQ4_IRQ, se7343_irq_demux); irq_set_irq_type(IRQ4_IRQ, IRQ_TYPE_LEVEL_LOW); + irq_set_chained_handler(IRQ5_IRQ, se7343_irq_demux); irq_set_irq_type(IRQ5_IRQ, IRQ_TYPE_LEVEL_LOW); } + +/* + * Initialize IRQ setting + */ +void __init init_7343se_IRQ(void) +{ + se7343_irq_regs = ioremap(PA_CPLD_BASE_ADDR, SZ_16); + if (unlikely(!se7343_irq_regs)) { + pr_err("Failed to remap CPLD\n"); + return; + } + + /* + * All FPGA IRQs disabled by default + */ + iowrite16(0, se7343_irq_regs + PA_CPLD_IMSK_REG); + + __raw_writew(0x2000, 0xb03fffec); /* mrshpc irq enable */ + + se7343_domain_init(); + se7343_gc_init(); +} diff --git a/arch/sh/boards/mach-se/7343/setup.c b/arch/sh/boards/mach-se/7343/setup.c index d2370af56d77..8ce4f2a202a8 100644 --- a/arch/sh/boards/mach-se/7343/setup.c +++ b/arch/sh/boards/mach-se/7343/setup.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -145,11 +146,12 @@ static struct platform_device *sh7343se_platform_devices[] __initdata = { static int __init sh7343se_devices_setup(void) { /* Wire-up dynamic vectors */ - serial_platform_data[0].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTA]; - serial_platform_data[1].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTB]; - + serial_platform_data[0].irq = irq_find_mapping(se7343_irq_domain, + SE7343_FPGA_IRQ_UARTA); + serial_platform_data[1].irq = irq_find_mapping(se7343_irq_domain, + SE7343_FPGA_IRQ_UARTB); usb_resources[2].start = usb_resources[2].end = - se7343_fpga_irq[SE7343_FPGA_IRQ_USB]; + irq_find_mapping(se7343_irq_domain, SE7343_FPGA_IRQ_USB); return platform_add_devices(sh7343se_platform_devices, ARRAY_SIZE(sh7343se_platform_devices)); diff --git a/arch/sh/include/mach-se/mach/se7343.h b/arch/sh/include/mach-se/mach/se7343.h index 8d8170d6cc43..2ec6f75a44de 100644 --- a/arch/sh/include/mach-se/mach/se7343.h +++ b/arch/sh/include/mach-se/mach/se7343.h @@ -49,9 +49,6 @@ #define PA_LED 0xb0C00000 /* LED */ #define LED_SHIFT 0 #define PA_DIPSW 0xb0900000 /* Dip switch 31 */ -#define PA_CPLD_MODESET 0xb1400004 /* CPLD Mode set register */ -#define PA_CPLD_ST 0xb1400008 /* CPLD Interrupt status register */ -#define PA_CPLD_IMSK 0xb140000a /* CPLD Interrupt mask register */ /* Area 5 */ #define PA_EXT5 0x14000000 #define PA_EXT5_SIZE 0x04000000 @@ -134,8 +131,10 @@ #define SE7343_FPGA_IRQ_NR 12 +struct irq_domain; + /* arch/sh/boards/se/7343/irq.c */ -extern unsigned int se7343_fpga_irq[]; +extern struct irq_domain *se7343_irq_domain; void init_7343se_IRQ(void); -- cgit v1.2.3 From 151766fce8bee0e3e6076c8b829f9fcc0a2412ae Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Sat, 28 Apr 2012 14:30:40 +0800 Subject: Revert "x86/platform: Add a wallclock_init func to x86_platforms ops" This reverts commit cf8ff6b6ab0e99dd3058852f4ec76a6140abadec. Just found this commit is a function duplicatation of commit 6b617e22 "x86/platform: Add a wallclock_init func to x86_init.timers ops". Let's revert it and sorry for the noise. Signed-off-by: Feng Tang Cc: Ingo Molnar Cc: H. Peter Anvin Cc: Jacob Pan Cc: Alan Cox Cc: Dirk Brandewie Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/x86_init.h | 2 -- arch/x86/kernel/setup.c | 2 -- arch/x86/kernel/x86_init.c | 2 -- 3 files changed, 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index c090af10ac7d..42d2ae18dab2 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -156,7 +156,6 @@ struct x86_cpuinit_ops { /** * struct x86_platform_ops - platform specific runtime functions * @calibrate_tsc: calibrate TSC - * @wallclock_init: init the wallclock device * @get_wallclock: get time from HW clock like RTC etc. * @set_wallclock: set time back to HW clock * @is_untracked_pat_range exclude from PAT logic @@ -167,7 +166,6 @@ struct x86_cpuinit_ops { */ struct x86_platform_ops { unsigned long (*calibrate_tsc)(void); - void (*wallclock_init)(void); unsigned long (*get_wallclock)(void); int (*set_wallclock)(unsigned long nowtime); void (*iommu_shutdown)(void); diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 366c688d619e..58a07b10812c 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1027,8 +1027,6 @@ void __init setup_arch(char **cmdline_p) x86_init.timers.wallclock_init(); - x86_platform.wallclock_init(); - mcheck_init(); arch_init_ideal_nops(); diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 35c5e543f550..9f3167e891ef 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -29,7 +29,6 @@ void __init x86_init_uint_noop(unsigned int unused) { } void __init x86_init_pgd_noop(pgd_t *unused) { } int __init iommu_init_noop(void) { return 0; } void iommu_shutdown_noop(void) { } -void wallclock_init_noop(void) { } /* * The platform setup functions are preset with the default functions @@ -101,7 +100,6 @@ static int default_i8042_detect(void) { return 1; }; struct x86_platform_ops x86_platform = { .calibrate_tsc = native_calibrate_tsc, - .wallclock_init = wallclock_init_noop, .get_wallclock = mach_get_cmos_time, .set_wallclock = mach_set_rtc_mmss, .iommu_shutdown = iommu_shutdown_noop, -- cgit v1.2.3 From f841d792e38f75f5e25b0b66f7b5d235d180a735 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 30 Mar 2012 23:11:35 +0800 Subject: x86: Return IRQ_SET_MASK_OK_NOCOPY from irq affinity functions The interrupt chip irq_set_affinity() functions copy the affinity mask to irq_data->affinity but return 0, i.e. IRQ_SET_MASK_OK. IRQ_SET_MASK_OK causes the core code to do another redundant copy. Return IRQ_SET_MASK_OK_NOCOPY to avoid this. Signed-off-by: Jiang Liu Cc: Suresh Siddha Cc: Yinghai Lu Cc: Naga Chumbalkar Cc: Jacob Pan Cc: Cliff Wickman Cc: Jiang Liu Cc: Keping Chen Link: http://lkml.kernel.org/r/1333120296-13563-4-git-send-email-jiang.liu@huawei.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/io_apic.c | 9 +++++---- arch/x86/platform/uv/uv_irq.c | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index ac96561d1a99..bce2001b2644 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2270,6 +2270,7 @@ ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, /* Only the high 8 bits are valid. */ dest = SET_APIC_LOGICAL_ID(dest); __target_IO_APIC_irq(irq, dest, data->chip_data); + ret = IRQ_SET_MASK_OK_NOCOPY; } raw_spin_unlock_irqrestore(&ioapic_lock, flags); return ret; @@ -3092,7 +3093,7 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) __write_msi_msg(data->msi_desc, &msg); - return 0; + return IRQ_SET_MASK_OK_NOCOPY; } #endif /* CONFIG_SMP */ @@ -3214,7 +3215,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask, dmar_msi_write(irq, &msg); - return 0; + return IRQ_SET_MASK_OK_NOCOPY; } #endif /* CONFIG_SMP */ @@ -3267,7 +3268,7 @@ static int hpet_msi_set_affinity(struct irq_data *data, hpet_msi_write(data->handler_data, &msg); - return 0; + return IRQ_SET_MASK_OK_NOCOPY; } #endif /* CONFIG_SMP */ @@ -3340,7 +3341,7 @@ ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) return -1; target_ht_irq(data->irq, dest, cfg->vector); - return 0; + return IRQ_SET_MASK_OK_NOCOPY; } #endif diff --git a/arch/x86/platform/uv/uv_irq.c b/arch/x86/platform/uv/uv_irq.c index f25c2765a5c9..a22c41656b52 100644 --- a/arch/x86/platform/uv/uv_irq.c +++ b/arch/x86/platform/uv/uv_irq.c @@ -222,7 +222,7 @@ uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask, if (cfg->move_in_progress) send_cleanup_vector(cfg); - return 0; + return IRQ_SET_MASK_OK_NOCOPY; } /* -- cgit v1.2.3 From 00633d7c7a0243940fc616bee573bcf497db79b9 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Wed, 4 Jan 2012 15:33:17 -0800 Subject: ARM: OMAP3: clock data: cleanup AM3[35]x SoC detection Use the more generic SoC family soc_is_am35xx() instead of the specific cpu_is_omap3517() (which is being removed.) Acked-by: Vaibhav Hiremath Tested-by: Vaibhav Hiremath Tested-by: Mark A. Greer Cc: Paul Walmsley Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/clock3xxx_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 4e1a3b0e8cc8..1efdec236ae8 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3514,7 +3514,7 @@ int __init omap3xxx_clk_init(void) struct omap_clk *c; u32 cpu_clkflg = 0; - if (cpu_is_omap3517()) { + if (soc_is_am35xx()) { cpu_mask = RATE_IN_34XX; cpu_clkflg = CK_AM35XX; } else if (cpu_is_omap3630()) { -- cgit v1.2.3 From 96f3994929c05a21d757a83613d2710b780ea2b4 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 11 May 2012 16:38:11 -0700 Subject: ARM: OMAP: SoC detection: remove unused cpu_is macros Remove multiple unused cpu_is_omap35xx macros. In particular, the cpu_is_omap35* macros for 3503, 3515, 3525 are removed because they are using omap_has_* feature checks and we want to remove specific feature detection from SoC family detection. There are no longer any cpu_is_* checks that depend on specific IP detection. Acked-by: Vaibhav Hiremath Tested-by: Vaibhav Hiremath Tested-by: Mark A. Greer Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/cpu.h | 33 --------------------------------- 1 file changed, 33 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h index 4bdf14ec6747..0f8a201cee68 100644 --- a/arch/arm/plat-omap/include/plat/cpu.h +++ b/arch/arm/plat-omap/include/plat/cpu.h @@ -250,8 +250,6 @@ IS_AM_SUBCLASS(335x, 0x335) * cpu_is_omap2423(): True for OMAP2423 * cpu_is_omap2430(): True for OMAP2430 * cpu_is_omap3430(): True for OMAP3430 - * cpu_is_omap3505(): True for OMAP3505 - * cpu_is_omap3517(): True for OMAP3517 */ #define GET_OMAP_TYPE ((omap_rev() >> 16) & 0xffff) @@ -275,8 +273,6 @@ IS_OMAP_TYPE(2422, 0x2422) IS_OMAP_TYPE(2423, 0x2423) IS_OMAP_TYPE(2430, 0x2430) IS_OMAP_TYPE(3430, 0x3430) -IS_OMAP_TYPE(3505, 0x3517) -IS_OMAP_TYPE(3517, 0x3517) #define cpu_is_omap310() 0 #define cpu_is_omap730() 0 @@ -291,12 +287,6 @@ IS_OMAP_TYPE(3517, 0x3517) #define cpu_is_omap2422() 0 #define cpu_is_omap2423() 0 #define cpu_is_omap2430() 0 -#define cpu_is_omap3503() 0 -#define cpu_is_omap3515() 0 -#define cpu_is_omap3525() 0 -#define cpu_is_omap3530() 0 -#define cpu_is_omap3505() 0 -#define cpu_is_omap3517() 0 #define cpu_is_omap3430() 0 #define cpu_is_omap3630() 0 @@ -348,31 +338,12 @@ IS_OMAP_TYPE(3517, 0x3517) #if defined(CONFIG_ARCH_OMAP3) # undef cpu_is_omap3430 -# undef cpu_is_omap3503 -# undef cpu_is_omap3515 -# undef cpu_is_omap3525 -# undef cpu_is_omap3530 -# undef cpu_is_omap3505 -# undef cpu_is_omap3517 # undef cpu_is_ti81xx # undef cpu_is_ti816x # undef cpu_is_ti814x # undef cpu_is_am33xx # undef cpu_is_am335x # define cpu_is_omap3430() is_omap3430() -# define cpu_is_omap3503() (cpu_is_omap3430() && \ - (!omap3_has_iva()) && \ - (!omap3_has_sgx())) -# define cpu_is_omap3515() (cpu_is_omap3430() && \ - (!omap3_has_iva()) && \ - (omap3_has_sgx())) -# define cpu_is_omap3525() (cpu_is_omap3430() && \ - (!omap3_has_sgx()) && \ - (omap3_has_iva())) -# define cpu_is_omap3530() (cpu_is_omap3430()) -# define cpu_is_omap3517() is_omap3517() -# define cpu_is_omap3505() (cpu_is_omap3517() && \ - !omap3_has_sgx()) # undef cpu_is_omap3630 # define cpu_is_omap3630() is_omap363x() # define cpu_is_ti81xx() is_ti81xx() @@ -420,10 +391,6 @@ IS_OMAP_TYPE(3517, 0x3517) #define OMAP3630_REV_ES1_1 (OMAP363X_CLASS | (0x1 << 8)) #define OMAP3630_REV_ES1_2 (OMAP363X_CLASS | (0x2 << 8)) -#define OMAP3517_CLASS 0x35170034 -#define OMAP3517_REV_ES1_0 OMAP3517_CLASS -#define OMAP3517_REV_ES1_1 (OMAP3517_CLASS | (0x1 << 8)) - #define TI816X_CLASS 0x81600034 #define TI8168_REV_ES1_0 TI816X_CLASS #define TI8168_REV_ES1_1 (TI816X_CLASS | (0x1 << 8)) -- cgit v1.2.3 From 3ef7cf1839061b275ee1fc59c042194dc452b7e2 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 21 May 2012 16:09:06 -0300 Subject: ARM: mx31_3ds: Fix build due to missing IMX_HAVE_PLATFORM_IMX_SSI commit 5fb86e5 (ARM: mx31_3ds: Add sound support) missed to select IMX_HAVE_PLATFORM_IMX_SSI, which causes the following build error when only mx31_3ds is selected: arch/arm/mach-imx/built-in.o: In function `mx31_3ds_init': mach-mx31_3ds.c:(.init.text+0x15dc): undefined reference to `imx_add_imx_ssi' mach-mx31_3ds.c:(.init.text+0x16b8): undefined reference to `imx31_imx_ssi_data' Select IMX_HAVE_PLATFORM_IMX_SSI to fix it. Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 7561eca131b0..8abcee3c34d0 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -467,6 +467,7 @@ config MACH_MX31_3DS select IMX_HAVE_PLATFORM_IMX2_WDT select IMX_HAVE_PLATFORM_IMX_I2C select IMX_HAVE_PLATFORM_IMX_KEYPAD + select IMX_HAVE_PLATFORM_IMX_SSI select IMX_HAVE_PLATFORM_IMX_UART select IMX_HAVE_PLATFORM_IPU_CORE select IMX_HAVE_PLATFORM_MXC_EHCI -- cgit v1.2.3 From 1064f8893ee1d16178d983928912057352362dc2 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 2 May 2012 22:08:07 +0200 Subject: ARM: imx: only specify i2c device type once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first argument of I2C_BOARD_INFO is used to assign .type, so drop second assignment. Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/mach-cpuimx35.c | 1 - arch/arm/mach-imx/mach-cpuimx51sd.c | 1 - 2 files changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c index 8ecc872b2547..b1a4796548b5 100644 --- a/arch/arm/mach-imx/mach-cpuimx35.c +++ b/arch/arm/mach-imx/mach-cpuimx35.c @@ -70,7 +70,6 @@ static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = { I2C_BOARD_INFO("pcf8563", 0x51), }, { I2C_BOARD_INFO("tsc2007", 0x48), - .type = "tsc2007", .platform_data = &tsc2007_info, .irq = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO), }, diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c index 9fbe923c8b08..89eb93cec601 100644 --- a/arch/arm/mach-imx/mach-cpuimx51sd.c +++ b/arch/arm/mach-imx/mach-cpuimx51sd.c @@ -124,7 +124,6 @@ static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = { I2C_BOARD_INFO("pcf8563", 0x51), }, { I2C_BOARD_INFO("tsc2007", 0x49), - .type = "tsc2007", .platform_data = &tsc2007_info, .irq = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO), }, -- cgit v1.2.3 From f90da3c7a52ac0c8f07f4d6cd0a7f7677e831916 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 May 2012 16:58:03 +0200 Subject: ARM: imx: only call l2x0_init if it's available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a build failure with CONFIG_CACHE_L2X0=n: arch/arm/mach-imx/built-in.o: In function `imx3_init_l2x0': imx53-dt.c:(.init.text+0x190): undefined reference to `l2x0_init' make[2]: *** [.tmp_vmlinux1] Error 1 make[1]: *** [sub-make] Error 2 make: *** [all] Error 2 When the l2 cache isn't enabled the quirk introduced in 9524705 (MX35: Fix bogus L2 cache settings) doesn't need to be done either. Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/mm-imx3.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c index 74127389e7ab..6a80496d72dc 100644 --- a/arch/arm/mach-imx/mm-imx3.c +++ b/arch/arm/mach-imx/mm-imx3.c @@ -81,6 +81,7 @@ static void __iomem *imx3_ioremap_caller(unsigned long phys_addr, size_t size, void __init imx3_init_l2x0(void) { +#ifdef CONFIG_CACHE_L2X0 void __iomem *l2x0_base; void __iomem *clkctl_base; @@ -110,6 +111,7 @@ void __init imx3_init_l2x0(void) } l2x0_init(l2x0_base, 0x00030024, 0x00000000); +#endif } #ifdef CONFIG_SOC_IMX31 -- cgit v1.2.3 From 2e1ae9c07df5956ebab19144aa0da58ea37c9f69 Mon Sep 17 00:00:00 2001 From: Liu Yu-B13201 Date: Thu, 15 Mar 2012 10:52:13 +0000 Subject: KVM: PPC: Factor out guest epapr initialization epapr paravirtualization support is now a Kconfig selectable option Signed-off-by: Liu Yu [stuart.yoder@freescale.com: misc minor fixes, description update] Signed-off-by: Stuart Yoder Signed-off-by: Alexander Graf --- arch/powerpc/include/asm/epapr_hcalls.h | 2 ++ arch/powerpc/kernel/Makefile | 1 + arch/powerpc/kernel/epapr_hcalls.S | 25 ++++++++++++++++ arch/powerpc/kernel/epapr_paravirt.c | 52 +++++++++++++++++++++++++++++++++ arch/powerpc/kernel/kvm.c | 28 ++---------------- arch/powerpc/kernel/kvm_emul.S | 10 ------- arch/powerpc/platforms/Kconfig | 9 ++++++ 7 files changed, 92 insertions(+), 35 deletions(-) create mode 100644 arch/powerpc/kernel/epapr_hcalls.S create mode 100644 arch/powerpc/kernel/epapr_paravirt.c (limited to 'arch') diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h index 976835d8f22e..bf2c06c33871 100644 --- a/arch/powerpc/include/asm/epapr_hcalls.h +++ b/arch/powerpc/include/asm/epapr_hcalls.h @@ -153,6 +153,8 @@ #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5" #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4" +extern bool epapr_paravirt_enabled; +extern u32 epapr_hypercall_start[]; /* * We use "uintptr_t" to define a register because it's guaranteed to be a diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 83afacd3ba7b..bb282dd81612 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -128,6 +128,7 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),) obj-y += ppc_save_regs.o endif +obj-$(CONFIG_EPAPR_PARAVIRT) += epapr_paravirt.o epapr_hcalls.o obj-$(CONFIG_KVM_GUEST) += kvm.o kvm_emul.o # Disable GCOV in odd or sensitive code diff --git a/arch/powerpc/kernel/epapr_hcalls.S b/arch/powerpc/kernel/epapr_hcalls.S new file mode 100644 index 000000000000..697b390ebfd8 --- /dev/null +++ b/arch/powerpc/kernel/epapr_hcalls.S @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Hypercall entry point. Will be patched with device tree instructions. */ +.global epapr_hypercall_start +epapr_hypercall_start: + li r3, -1 + nop + nop + nop + blr diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c new file mode 100644 index 000000000000..028aeae370b6 --- /dev/null +++ b/arch/powerpc/kernel/epapr_paravirt.c @@ -0,0 +1,52 @@ +/* + * ePAPR para-virtualization support. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (C) 2012 Freescale Semiconductor, Inc. + */ + +#include +#include +#include +#include + +bool epapr_paravirt_enabled; + +static int __init epapr_paravirt_init(void) +{ + struct device_node *hyper_node; + const u32 *insts; + int len, i; + + hyper_node = of_find_node_by_path("/hypervisor"); + if (!hyper_node) + return -ENODEV; + + insts = of_get_property(hyper_node, "hcall-instructions", &len); + if (!insts) + return -ENODEV; + + if (len % 4 || len > (4 * 4)) + return -ENODEV; + + for (i = 0; i < (len / 4); i++) + patch_instruction(epapr_hypercall_start + i, insts[i]); + + epapr_paravirt_enabled = true; + + return 0; +} + +early_initcall(epapr_paravirt_init); diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c index 62bdf2389669..1c13307e0308 100644 --- a/arch/powerpc/kernel/kvm.c +++ b/arch/powerpc/kernel/kvm.c @@ -31,6 +31,7 @@ #include #include #include +#include #define KVM_MAGIC_PAGE (-4096L) #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x) @@ -726,7 +727,7 @@ unsigned long kvm_hypercall(unsigned long *in, unsigned long register r11 asm("r11") = nr; unsigned long register r12 asm("r12"); - asm volatile("bl kvm_hypercall_start" + asm volatile("bl epapr_hypercall_start" : "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6), "=r"(r7), "=r"(r8), "=r"(r9), "=r"(r10), "=r"(r11), "=r"(r12) @@ -747,29 +748,6 @@ unsigned long kvm_hypercall(unsigned long *in, } EXPORT_SYMBOL_GPL(kvm_hypercall); -static int kvm_para_setup(void) -{ - extern u32 kvm_hypercall_start; - struct device_node *hyper_node; - u32 *insts; - int len, i; - - hyper_node = of_find_node_by_path("/hypervisor"); - if (!hyper_node) - return -1; - - insts = (u32*)of_get_property(hyper_node, "hcall-instructions", &len); - if (len % 4) - return -1; - if (len > (4 * 4)) - return -1; - - for (i = 0; i < (len / 4); i++) - kvm_patch_ins(&(&kvm_hypercall_start)[i], insts[i]); - - return 0; -} - static __init void kvm_free_tmp(void) { unsigned long start, end; @@ -791,7 +769,7 @@ static int __init kvm_guest_init(void) if (!kvm_para_available()) goto free_tmp; - if (kvm_para_setup()) + if (!epapr_paravirt_enabled) goto free_tmp; if (kvm_para_has_feature(KVM_FEATURE_MAGIC_PAGE)) diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S index e291cf3cf954..62ceb2ac82cf 100644 --- a/arch/powerpc/kernel/kvm_emul.S +++ b/arch/powerpc/kernel/kvm_emul.S @@ -24,16 +24,6 @@ #include #include -/* Hypercall entry point. Will be patched with device tree instructions. */ - -.global kvm_hypercall_start -kvm_hypercall_start: - li r3, -1 - nop - nop - nop - blr - #define KVM_MAGIC_PAGE (-4096) #ifdef CONFIG_64BIT diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index a35ca44ade66..e7a896acd982 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -25,6 +25,7 @@ source "arch/powerpc/platforms/wsp/Kconfig" config KVM_GUEST bool "KVM Guest support" default n + select EPAPR_PARAVIRT ---help--- This option enables various optimizations for running under the KVM hypervisor. Overhead for the kernel when not running inside KVM should @@ -32,6 +33,14 @@ config KVM_GUEST In case of doubt, say Y +config EPAPR_PARAVIRT + bool "ePAPR para-virtualization support" + default n + help + Enables ePAPR para-virtualization support for guests. + + In case of doubt, say Y + config PPC_NATIVE bool depends on 6xx || PPC64 -- cgit v1.2.3 From 32fad281c0680ed0ccade7dda85a2121cf9b1d06 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 4 May 2012 02:32:53 +0000 Subject: KVM: PPC: Book3S HV: Make the guest hash table size configurable This adds a new ioctl to enable userspace to control the size of the guest hashed page table (HPT) and to clear it out when resetting the guest. The KVM_PPC_ALLOCATE_HTAB ioctl is a VM ioctl and takes as its parameter a pointer to a u32 containing the desired order of the HPT (log base 2 of the size in bytes), which is updated on successful return to the actual order of the HPT which was allocated. There must be no vcpus running at the time of this ioctl. To enforce this, we now keep a count of the number of vcpus running in kvm->arch.vcpus_running. If the ioctl is called when a HPT has already been allocated, we don't reallocate the HPT but just clear it out. We first clear the kvm->arch.rma_setup_done flag, which has two effects: (a) since we hold the kvm->lock mutex, it will prevent any vcpus from starting to run until we're done, and (b) it means that the first vcpu to run after we're done will re-establish the VRMA if necessary. If userspace doesn't call this ioctl before running the first vcpu, the kernel will allocate a default-sized HPT at that point. We do it then rather than when creating the VM, as the code did previously, so that userspace has a chance to do the ioctl if it wants. When allocating the HPT, we can allocate either from the kernel page allocator, or from the preallocated pool. If userspace is asking for a different size from the preallocated HPTs, we first try to allocate using the kernel page allocator. Then we try to allocate from the preallocated pool, and then if that fails, we try allocating decreasing sizes from the kernel page allocator, down to the minimum size allowed (256kB). Note that the kernel page allocator limits allocations to 1 << CONFIG_FORCE_MAX_ZONEORDER pages, which by default corresponds to 16MB (on 64-bit powerpc, at least). Signed-off-by: Paul Mackerras [agraf: fix module compilation] Signed-off-by: Alexander Graf --- Documentation/virtual/kvm/api.txt | 36 +++++++++ arch/powerpc/include/asm/kvm_book3s_64.h | 7 +- arch/powerpc/include/asm/kvm_host.h | 4 + arch/powerpc/include/asm/kvm_ppc.h | 3 +- arch/powerpc/kvm/book3s_64_mmu_hv.c | 123 ++++++++++++++++++++++++------- arch/powerpc/kvm/book3s_hv.c | 40 +++++++--- arch/powerpc/kvm/book3s_hv_builtin.c | 5 +- arch/powerpc/kvm/book3s_hv_rm_mmu.c | 15 ++-- arch/powerpc/kvm/powerpc.c | 18 +++++ include/linux/kvm.h | 3 + 10 files changed, 200 insertions(+), 54 deletions(-) (limited to 'arch') diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 930126698a0f..310fe508d9cd 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -1930,6 +1930,42 @@ The "pte_enc" field provides a value that can OR'ed into the hash PTE's RPN field (ie, it needs to be shifted left by 12 to OR it into the hash PTE second double word). + +4.75 KVM_PPC_ALLOCATE_HTAB + +Capability: KVM_CAP_PPC_ALLOC_HTAB +Architectures: powerpc +Type: vm ioctl +Parameters: Pointer to u32 containing hash table order (in/out) +Returns: 0 on success, -1 on error + +This requests the host kernel to allocate an MMU hash table for a +guest using the PAPR paravirtualization interface. This only does +anything if the kernel is configured to use the Book 3S HV style of +virtualization. Otherwise the capability doesn't exist and the ioctl +returns an ENOTTY error. The rest of this description assumes Book 3S +HV. + +There must be no vcpus running when this ioctl is called; if there +are, it will do nothing and return an EBUSY error. + +The parameter is a pointer to a 32-bit unsigned integer variable +containing the order (log base 2) of the desired size of the hash +table, which must be between 18 and 46. On successful return from the +ioctl, it will have been updated with the order of the hash table that +was allocated. + +If no hash table has been allocated when any vcpu is asked to run +(with the KVM_RUN ioctl), the host kernel will allocate a +default-sized hash table (16 MB). + +If this ioctl is called when a hash table has already been allocated, +the kernel will clear out the existing hash table (zero all HPTEs) and +return the hash table order in the parameter. (If the guest is using +the virtualized real-mode area (VRMA) facility, the kernel will +re-create the VMRA HPTEs on the next KVM_RUN of any vcpu.) + + 5. The kvm_run structure ------------------------ diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h index b0c08b142770..0dd1d86d3e31 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h @@ -36,11 +36,8 @@ static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu) #define SPAPR_TCE_SHIFT 12 #ifdef CONFIG_KVM_BOOK3S_64_HV -/* For now use fixed-size 16MB page table */ -#define HPT_ORDER 24 -#define HPT_NPTEG (1ul << (HPT_ORDER - 7)) /* 128B per pteg */ -#define HPT_NPTE (HPT_NPTEG << 3) /* 8 PTEs per PTEG */ -#define HPT_HASH_MASK (HPT_NPTEG - 1) +#define KVM_DEFAULT_HPT_ORDER 24 /* 16MB HPT by default */ +extern int kvm_hpt_order; /* order of preallocated HPTs */ #endif #define VRMA_VSID 0x1ffffffUL /* 1TB VSID reserved for VRMA */ diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index d848cdc49715..dd783beb88b3 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -237,6 +237,10 @@ struct kvm_arch { unsigned long vrma_slb_v; int rma_setup_done; int using_mmu_notifiers; + u32 hpt_order; + atomic_t vcpus_running; + unsigned long hpt_npte; + unsigned long hpt_mask; spinlock_t slot_phys_lock; unsigned long *slot_phys[KVM_MEM_SLOTS_NUM]; int slot_npages[KVM_MEM_SLOTS_NUM]; diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index f68c22fa2fce..0124937a23b9 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -119,7 +119,8 @@ extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu); extern int kvmppc_kvm_pv(struct kvm_vcpu *vcpu); extern void kvmppc_map_magic(struct kvm_vcpu *vcpu); -extern long kvmppc_alloc_hpt(struct kvm *kvm); +extern long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp); +extern long kvmppc_alloc_reset_hpt(struct kvm *kvm, u32 *htab_orderp); extern void kvmppc_free_hpt(struct kvm *kvm); extern long kvmppc_prepare_vrma(struct kvm *kvm, struct kvm_userspace_memory_region *mem); diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 80a577517584..d03eb6f7b058 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -37,56 +37,121 @@ /* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */ #define MAX_LPID_970 63 -long kvmppc_alloc_hpt(struct kvm *kvm) +/* Power architecture requires HPT is at least 256kB */ +#define PPC_MIN_HPT_ORDER 18 + +long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp) { unsigned long hpt; - long lpid; struct revmap_entry *rev; struct kvmppc_linear_info *li; + long order = kvm_hpt_order; - /* Allocate guest's hashed page table */ - li = kvm_alloc_hpt(); - if (li) { - /* using preallocated memory */ - hpt = (ulong)li->base_virt; - kvm->arch.hpt_li = li; - } else { - /* using dynamic memory */ + if (htab_orderp) { + order = *htab_orderp; + if (order < PPC_MIN_HPT_ORDER) + order = PPC_MIN_HPT_ORDER; + } + + /* + * If the user wants a different size from default, + * try first to allocate it from the kernel page allocator. + */ + hpt = 0; + if (order != kvm_hpt_order) { hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT| - __GFP_NOWARN, HPT_ORDER - PAGE_SHIFT); + __GFP_NOWARN, order - PAGE_SHIFT); + if (!hpt) + --order; } + /* Next try to allocate from the preallocated pool */ if (!hpt) { - pr_err("kvm_alloc_hpt: Couldn't alloc HPT\n"); - return -ENOMEM; + li = kvm_alloc_hpt(); + if (li) { + hpt = (ulong)li->base_virt; + kvm->arch.hpt_li = li; + order = kvm_hpt_order; + } } + + /* Lastly try successively smaller sizes from the page allocator */ + while (!hpt && order > PPC_MIN_HPT_ORDER) { + hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT| + __GFP_NOWARN, order - PAGE_SHIFT); + if (!hpt) + --order; + } + + if (!hpt) + return -ENOMEM; + kvm->arch.hpt_virt = hpt; + kvm->arch.hpt_order = order; + /* HPTEs are 2**4 bytes long */ + kvm->arch.hpt_npte = 1ul << (order - 4); + /* 128 (2**7) bytes in each HPTEG */ + kvm->arch.hpt_mask = (1ul << (order - 7)) - 1; /* Allocate reverse map array */ - rev = vmalloc(sizeof(struct revmap_entry) * HPT_NPTE); + rev = vmalloc(sizeof(struct revmap_entry) * kvm->arch.hpt_npte); if (!rev) { pr_err("kvmppc_alloc_hpt: Couldn't alloc reverse map array\n"); goto out_freehpt; } kvm->arch.revmap = rev; + kvm->arch.sdr1 = __pa(hpt) | (order - 18); - lpid = kvmppc_alloc_lpid(); - if (lpid < 0) - goto out_freeboth; + pr_info("KVM guest htab at %lx (order %ld), LPID %x\n", + hpt, order, kvm->arch.lpid); - kvm->arch.sdr1 = __pa(hpt) | (HPT_ORDER - 18); - kvm->arch.lpid = lpid; - - pr_info("KVM guest htab at %lx, LPID %lx\n", hpt, lpid); + if (htab_orderp) + *htab_orderp = order; return 0; - out_freeboth: - vfree(rev); out_freehpt: - free_pages(hpt, HPT_ORDER - PAGE_SHIFT); + if (kvm->arch.hpt_li) + kvm_release_hpt(kvm->arch.hpt_li); + else + free_pages(hpt, order - PAGE_SHIFT); return -ENOMEM; } +long kvmppc_alloc_reset_hpt(struct kvm *kvm, u32 *htab_orderp) +{ + long err = -EBUSY; + long order; + + mutex_lock(&kvm->lock); + if (kvm->arch.rma_setup_done) { + kvm->arch.rma_setup_done = 0; + /* order rma_setup_done vs. vcpus_running */ + smp_mb(); + if (atomic_read(&kvm->arch.vcpus_running)) { + kvm->arch.rma_setup_done = 1; + goto out; + } + } + if (kvm->arch.hpt_virt) { + order = kvm->arch.hpt_order; + /* Set the entire HPT to 0, i.e. invalid HPTEs */ + memset((void *)kvm->arch.hpt_virt, 0, 1ul << order); + /* + * Set the whole last_vcpu array to an invalid vcpu number. + * This ensures that each vcpu will flush its TLB on next entry. + */ + memset(kvm->arch.last_vcpu, 0xff, sizeof(kvm->arch.last_vcpu)); + *htab_orderp = order; + err = 0; + } else { + err = kvmppc_alloc_hpt(kvm, htab_orderp); + order = *htab_orderp; + } + out: + mutex_unlock(&kvm->lock); + return err; +} + void kvmppc_free_hpt(struct kvm *kvm) { kvmppc_free_lpid(kvm->arch.lpid); @@ -94,7 +159,8 @@ void kvmppc_free_hpt(struct kvm *kvm) if (kvm->arch.hpt_li) kvm_release_hpt(kvm->arch.hpt_li); else - free_pages(kvm->arch.hpt_virt, HPT_ORDER - PAGE_SHIFT); + free_pages(kvm->arch.hpt_virt, + kvm->arch.hpt_order - PAGE_SHIFT); } /* Bits in first HPTE dword for pagesize 4k, 64k or 16M */ @@ -119,6 +185,7 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, unsigned long psize; unsigned long hp0, hp1; long ret; + struct kvm *kvm = vcpu->kvm; psize = 1ul << porder; npages = memslot->npages >> (porder - PAGE_SHIFT); @@ -127,8 +194,8 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, if (npages > 1ul << (40 - porder)) npages = 1ul << (40 - porder); /* Can't use more than 1 HPTE per HPTEG */ - if (npages > HPT_NPTEG) - npages = HPT_NPTEG; + if (npages > kvm->arch.hpt_mask + 1) + npages = kvm->arch.hpt_mask + 1; hp0 = HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16)) | HPTE_V_BOLTED | hpte0_pgsize_encoding(psize); @@ -138,7 +205,7 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, for (i = 0; i < npages; ++i) { addr = i << porder; /* can't use hpt_hash since va > 64 bits */ - hash = (i ^ (VRMA_VSID ^ (VRMA_VSID << 25))) & HPT_HASH_MASK; + hash = (i ^ (VRMA_VSID ^ (VRMA_VSID << 25))) & kvm->arch.hpt_mask; /* * We assume that the hash table is empty and no * vcpus are using it at this stage. Since we create diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index c6af1d623839..d084e412b3c5 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -56,7 +56,7 @@ /* #define EXIT_DEBUG_INT */ static void kvmppc_end_cede(struct kvm_vcpu *vcpu); -static int kvmppc_hv_setup_rma(struct kvm_vcpu *vcpu); +static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { @@ -1068,11 +1068,15 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu) return -EINTR; } - /* On the first time here, set up VRMA or RMA */ + atomic_inc(&vcpu->kvm->arch.vcpus_running); + /* Order vcpus_running vs. rma_setup_done, see kvmppc_alloc_reset_hpt */ + smp_mb(); + + /* On the first time here, set up HTAB and VRMA or RMA */ if (!vcpu->kvm->arch.rma_setup_done) { - r = kvmppc_hv_setup_rma(vcpu); + r = kvmppc_hv_setup_htab_rma(vcpu); if (r) - return r; + goto out; } flush_fp_to_thread(current); @@ -1090,6 +1094,9 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu) kvmppc_core_prepare_to_enter(vcpu); } } while (r == RESUME_GUEST); + + out: + atomic_dec(&vcpu->kvm->arch.vcpus_running); return r; } @@ -1305,7 +1312,7 @@ void kvmppc_core_commit_memory_region(struct kvm *kvm, { } -static int kvmppc_hv_setup_rma(struct kvm_vcpu *vcpu) +static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) { int err = 0; struct kvm *kvm = vcpu->kvm; @@ -1324,6 +1331,15 @@ static int kvmppc_hv_setup_rma(struct kvm_vcpu *vcpu) if (kvm->arch.rma_setup_done) goto out; /* another vcpu beat us to it */ + /* Allocate hashed page table (if not done already) and reset it */ + if (!kvm->arch.hpt_virt) { + err = kvmppc_alloc_hpt(kvm, NULL); + if (err) { + pr_err("KVM: Couldn't alloc HPT\n"); + goto out; + } + } + /* Look up the memslot for guest physical address 0 */ memslot = gfn_to_memslot(kvm, 0); @@ -1435,13 +1451,14 @@ static int kvmppc_hv_setup_rma(struct kvm_vcpu *vcpu) int kvmppc_core_init_vm(struct kvm *kvm) { - long r; - unsigned long lpcr; + unsigned long lpcr, lpid; - /* Allocate hashed page table */ - r = kvmppc_alloc_hpt(kvm); - if (r) - return r; + /* Allocate the guest's logical partition ID */ + + lpid = kvmppc_alloc_lpid(); + if (lpid < 0) + return -ENOMEM; + kvm->arch.lpid = lpid; INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables); @@ -1451,7 +1468,6 @@ int kvmppc_core_init_vm(struct kvm *kvm) if (cpu_has_feature(CPU_FTR_ARCH_201)) { /* PPC970; HID4 is effectively the LPCR */ - unsigned long lpid = kvm->arch.lpid; kvm->arch.host_lpid = 0; kvm->arch.host_lpcr = lpcr = mfspr(SPRN_HID4); lpcr &= ~((3 << HID4_LPID1_SH) | (0xful << HID4_LPID5_SH)); diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index e1b60f56f2a1..fb4eac290fef 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -25,6 +25,9 @@ static void __init kvm_linear_init_one(ulong size, int count, int type); static struct kvmppc_linear_info *kvm_alloc_linear(int type); static void kvm_release_linear(struct kvmppc_linear_info *ri); +int kvm_hpt_order = KVM_DEFAULT_HPT_ORDER; +EXPORT_SYMBOL_GPL(kvm_hpt_order); + /*************** RMA *************/ /* @@ -209,7 +212,7 @@ static void kvm_release_linear(struct kvmppc_linear_info *ri) void __init kvm_linear_init(void) { /* HPT */ - kvm_linear_init_one(1 << HPT_ORDER, kvm_hpt_count, KVM_LINEAR_HPT); + kvm_linear_init_one(1 << kvm_hpt_order, kvm_hpt_count, KVM_LINEAR_HPT); /* RMA */ /* Only do this on PPC970 in HV mode */ diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index cec4daddbf31..5c70d19494f9 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c @@ -237,7 +237,7 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags, /* Find and lock the HPTEG slot to use */ do_insert: - if (pte_index >= HPT_NPTE) + if (pte_index >= kvm->arch.hpt_npte) return H_PARAMETER; if (likely((flags & H_EXACT) == 0)) { pte_index &= ~7UL; @@ -352,7 +352,7 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags, unsigned long v, r, rb; struct revmap_entry *rev; - if (pte_index >= HPT_NPTE) + if (pte_index >= kvm->arch.hpt_npte) return H_PARAMETER; hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) @@ -419,7 +419,8 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu) i = 4; break; } - if (req != 1 || flags == 3 || pte_index >= HPT_NPTE) { + if (req != 1 || flags == 3 || + pte_index >= kvm->arch.hpt_npte) { /* parameter error */ args[j] = ((0xa0 | flags) << 56) + pte_index; ret = H_PARAMETER; @@ -521,7 +522,7 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags, struct revmap_entry *rev; unsigned long v, r, rb, mask, bits; - if (pte_index >= HPT_NPTE) + if (pte_index >= kvm->arch.hpt_npte) return H_PARAMETER; hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); @@ -583,7 +584,7 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags, int i, n = 1; struct revmap_entry *rev = NULL; - if (pte_index >= HPT_NPTE) + if (pte_index >= kvm->arch.hpt_npte) return H_PARAMETER; if (flags & H_READ_4) { pte_index &= ~3; @@ -678,7 +679,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v, somask = (1UL << 28) - 1; vsid = (slb_v & ~SLB_VSID_B) >> SLB_VSID_SHIFT; } - hash = (vsid ^ ((eaddr & somask) >> pshift)) & HPT_HASH_MASK; + hash = (vsid ^ ((eaddr & somask) >> pshift)) & kvm->arch.hpt_mask; avpn = slb_v & ~(somask >> 16); /* also includes B */ avpn |= (eaddr & somask) >> 16; @@ -723,7 +724,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v, if (val & HPTE_V_SECONDARY) break; val |= HPTE_V_SECONDARY; - hash = hash ^ HPT_HASH_MASK; + hash = hash ^ kvm->arch.hpt_mask; } return -1; } diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 1493c8de947b..87f4dc886076 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -246,6 +246,7 @@ int kvm_dev_ioctl_check_extension(long ext) #endif #ifdef CONFIG_PPC_BOOK3S_64 case KVM_CAP_SPAPR_TCE: + case KVM_CAP_PPC_ALLOC_HTAB: r = 1; break; #endif /* CONFIG_PPC_BOOK3S_64 */ @@ -802,6 +803,23 @@ long kvm_arch_vm_ioctl(struct file *filp, r = -EFAULT; break; } + + case KVM_PPC_ALLOCATE_HTAB: { + struct kvm *kvm = filp->private_data; + u32 htab_order; + + r = -EFAULT; + if (get_user(htab_order, (u32 __user *)argp)) + break; + r = kvmppc_alloc_reset_hpt(kvm, &htab_order); + if (r) + break; + r = -EFAULT; + if (put_user(htab_order, (u32 __user *)argp)) + break; + r = 0; + break; + } #endif /* CONFIG_KVM_BOOK3S_64_HV */ #ifdef CONFIG_PPC_BOOK3S_64 diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 09f2b3aa2da7..2ce09aa7d3b3 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -617,6 +617,7 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_SIGNAL_MSI 77 #define KVM_CAP_PPC_GET_SMMU_INFO 78 #define KVM_CAP_S390_COW 79 +#define KVM_CAP_PPC_ALLOC_HTAB 80 #ifdef KVM_CAP_IRQ_ROUTING @@ -828,6 +829,8 @@ struct kvm_s390_ucas_mapping { #define KVM_SIGNAL_MSI _IOW(KVMIO, 0xa5, struct kvm_msi) /* Available with KVM_CAP_PPC_GET_SMMU_INFO */ #define KVM_PPC_GET_SMMU_INFO _IOR(KVMIO, 0xa6, struct kvm_ppc_smmu_info) +/* Available with KVM_CAP_PPC_ALLOC_HTAB */ +#define KVM_PPC_ALLOCATE_HTAB _IOWR(KVMIO, 0xa7, __u32) /* * ioctls for vcpu fds -- cgit v1.2.3 From 21bd000abff7d587229dbbee6f8c17f3aad9f9d8 Mon Sep 17 00:00:00 2001 From: Bharat Bhushan Date: Sun, 20 May 2012 23:21:23 +0000 Subject: KVM: PPC: booke: Added DECAR support Added the decrementer auto-reload support. DECAR is readable on e500v2/e500mc and later cpus. Signed-off-by: Bharat Bhushan Signed-off-by: Alexander Graf --- arch/powerpc/include/asm/kvm_host.h | 2 ++ arch/powerpc/kvm/booke.c | 5 +++++ arch/powerpc/kvm/booke_emulate.c | 3 +++ arch/powerpc/kvm/e500_emulate.c | 3 +++ 4 files changed, 13 insertions(+) (limited to 'arch') diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index dd783beb88b3..50ea12fd7bf5 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -418,7 +418,9 @@ struct kvm_vcpu_arch { ulong mcsrr1; ulong mcsr; u32 dec; +#ifdef CONFIG_BOOKE u32 decar; +#endif u32 tbl; u32 tbu; u32 tcr; diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 72f13f4a06e0..86681eec60b1 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -1267,6 +1267,11 @@ void kvmppc_decrementer_func(unsigned long data) { struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data; + if (vcpu->arch.tcr & TCR_ARE) { + vcpu->arch.dec = vcpu->arch.decar; + kvmppc_emulate_dec(vcpu); + } + kvmppc_set_tsr_bits(vcpu, TSR_DIS); } diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c index 6c76397f2af4..9eb9809eb13e 100644 --- a/arch/powerpc/kvm/booke_emulate.c +++ b/arch/powerpc/kvm/booke_emulate.c @@ -129,6 +129,9 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) kvmppc_set_tcr(vcpu, spr_val); break; + case SPRN_DECAR: + vcpu->arch.decar = spr_val; + break; /* * Note: SPRG4-7 are user-readable. * These values are loaded into the real SPRGs when resuming the diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c index 8b99e076dc81..e04b0ef55ce0 100644 --- a/arch/powerpc/kvm/e500_emulate.c +++ b/arch/powerpc/kvm/e500_emulate.c @@ -269,6 +269,9 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) *spr_val = vcpu->arch.shared->mas7_3 >> 32; break; #endif + case SPRN_DECAR: + *spr_val = vcpu->arch.decar; + break; case SPRN_TLB0CFG: *spr_val = vcpu->arch.tlbcfg[0]; break; -- cgit v1.2.3 From d35b1075afc0172caa44b57b56a2b9b57e06d32e Mon Sep 17 00:00:00 2001 From: Bharat Bhushan Date: Sun, 20 May 2012 23:21:53 +0000 Subject: KVM: PPC: Not optimizing MSR_CE and MSR_ME with paravirt. If there is pending critical or machine check interrupt then guest would like to capture it when guest enable MSR.CE and MSR_ME respectively. Also as mostly MSR_CE and MSR_ME are updated with rfi/rfci/rfmii which anyway traps so removing the the paravirt optimization for MSR.CE and MSR.ME. Signed-off-by: Bharat Bhushan Signed-off-by: Alexander Graf --- Documentation/virtual/kvm/ppc-pv.txt | 2 -- arch/powerpc/kernel/kvm_emul.S | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/Documentation/virtual/kvm/ppc-pv.txt b/Documentation/virtual/kvm/ppc-pv.txt index 6e7c37050930..4911cf95c67e 100644 --- a/Documentation/virtual/kvm/ppc-pv.txt +++ b/Documentation/virtual/kvm/ppc-pv.txt @@ -109,8 +109,6 @@ The following bits are safe to be set inside the guest: MSR_EE MSR_RI - MSR_CR - MSR_ME If any other bit changes in the MSR, please still use mtmsr(d). diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S index 62ceb2ac82cf..e100ff324a85 100644 --- a/arch/powerpc/kernel/kvm_emul.S +++ b/arch/powerpc/kernel/kvm_emul.S @@ -122,7 +122,7 @@ kvm_emulate_mtmsrd_len: .long (kvm_emulate_mtmsrd_end - kvm_emulate_mtmsrd) / 4 -#define MSR_SAFE_BITS (MSR_EE | MSR_CE | MSR_ME | MSR_RI) +#define MSR_SAFE_BITS (MSR_EE | MSR_RI) #define MSR_CRITICAL_BITS ~MSR_SAFE_BITS .global kvm_emulate_mtmsr -- cgit v1.2.3 From b86aeafc766b71f6d55e54ed2c77fdf7f56ec1ba Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Wed, 25 Apr 2012 16:06:20 +0530 Subject: ARM: OMAP2+: SmartReflex: move the smartreflex header to include/linux/power Move the smartreflex header file (arch/arm/mach-omap2/smartreflex.h) in a new header file include/linux/power/smartreflex.h. This change makes the SmartReflex implementation ready for the move to drivers/. Signed-off-by: Jean Pihet Signed-off-by: J Keerthy Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 4 +- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 3 +- arch/arm/mach-omap2/smartreflex-class3.c | 3 +- arch/arm/mach-omap2/smartreflex.c | 3 +- arch/arm/mach-omap2/smartreflex.h | 256 ---------------------------- arch/arm/mach-omap2/sr_device.c | 2 +- include/linux/power/smartreflex.h | 257 +++++++++++++++++++++++++++++ 7 files changed, 264 insertions(+), 264 deletions(-) delete mode 100644 arch/arm/mach-omap2/smartreflex.h create mode 100644 include/linux/power/smartreflex.h (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index fd48797fa95a..8c7241b7279c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -14,6 +14,8 @@ * * XXX these should be marked initdata for multi-OMAP kernels */ +#include + #include #include #include @@ -29,8 +31,6 @@ #include #include "omap_hwmod_common_data.h" - -#include "smartreflex.h" #include "prm-regbits-34xx.h" #include "cm-regbits-34xx.h" #include "wd_timer.h" diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 950454a3fa31..0b3af8233f21 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -19,6 +19,7 @@ */ #include +#include #include #include @@ -32,8 +33,6 @@ #include #include "omap_hwmod_common_data.h" - -#include "smartreflex.h" #include "cm1_44xx.h" #include "cm2_44xx.h" #include "prm44xx.h" diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c index 955566eefac4..ab8cf83e853e 100644 --- a/arch/arm/mach-omap2/smartreflex-class3.c +++ b/arch/arm/mach-omap2/smartreflex-class3.c @@ -11,7 +11,8 @@ * published by the Free Software Foundation. */ -#include "smartreflex.h" +#include +#include "voltage.h" static int sr_class3_enable(struct voltagedomain *voltdm) { diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index 008fbd7b9352..98309d32ba98 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -25,11 +25,10 @@ #include #include #include +#include #include "common.h" - #include "pm.h" -#include "smartreflex.h" #define SMARTREFLEX_NAME_LEN 16 #define NVALUE_NAME_LEN 40 diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h deleted file mode 100644 index 5809141171f8..000000000000 --- a/arch/arm/mach-omap2/smartreflex.h +++ /dev/null @@ -1,256 +0,0 @@ -/* - * OMAP Smartreflex Defines and Routines - * - * Author: Thara Gopinath - * - * Copyright (C) 2010 Texas Instruments, Inc. - * Thara Gopinath - * - * Copyright (C) 2008 Nokia Corporation - * Kalle Jokiniemi - * - * Copyright (C) 2007 Texas Instruments, Inc. - * Lesly A M - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __ASM_ARM_OMAP_SMARTREFLEX_H -#define __ASM_ARM_OMAP_SMARTREFLEX_H - -#include - -#include "voltage.h" - -/* - * Different Smartreflex IPs version. The v1 is the 65nm version used in - * OMAP3430. The v2 is the update for the 45nm version of the IP - * used in OMAP3630 and OMAP4430 - */ -#define SR_TYPE_V1 1 -#define SR_TYPE_V2 2 - -/* SMART REFLEX REG ADDRESS OFFSET */ -#define SRCONFIG 0x00 -#define SRSTATUS 0x04 -#define SENVAL 0x08 -#define SENMIN 0x0C -#define SENMAX 0x10 -#define SENAVG 0x14 -#define AVGWEIGHT 0x18 -#define NVALUERECIPROCAL 0x1c -#define SENERROR_V1 0x20 -#define ERRCONFIG_V1 0x24 -#define IRQ_EOI 0x20 -#define IRQSTATUS_RAW 0x24 -#define IRQSTATUS 0x28 -#define IRQENABLE_SET 0x2C -#define IRQENABLE_CLR 0x30 -#define SENERROR_V2 0x34 -#define ERRCONFIG_V2 0x38 - -/* Bit/Shift Positions */ - -/* SRCONFIG */ -#define SRCONFIG_ACCUMDATA_SHIFT 22 -#define SRCONFIG_SRCLKLENGTH_SHIFT 12 -#define SRCONFIG_SENNENABLE_V1_SHIFT 5 -#define SRCONFIG_SENPENABLE_V1_SHIFT 3 -#define SRCONFIG_SENNENABLE_V2_SHIFT 1 -#define SRCONFIG_SENPENABLE_V2_SHIFT 0 -#define SRCONFIG_CLKCTRL_SHIFT 0 - -#define SRCONFIG_ACCUMDATA_MASK (0x3ff << 22) - -#define SRCONFIG_SRENABLE BIT(11) -#define SRCONFIG_SENENABLE BIT(10) -#define SRCONFIG_ERRGEN_EN BIT(9) -#define SRCONFIG_MINMAXAVG_EN BIT(8) -#define SRCONFIG_DELAYCTRL BIT(2) - -/* AVGWEIGHT */ -#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT 2 -#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT 0 - -/* NVALUERECIPROCAL */ -#define NVALUERECIPROCAL_SENPGAIN_SHIFT 20 -#define NVALUERECIPROCAL_SENNGAIN_SHIFT 16 -#define NVALUERECIPROCAL_RNSENP_SHIFT 8 -#define NVALUERECIPROCAL_RNSENN_SHIFT 0 - -/* ERRCONFIG */ -#define ERRCONFIG_ERRWEIGHT_SHIFT 16 -#define ERRCONFIG_ERRMAXLIMIT_SHIFT 8 -#define ERRCONFIG_ERRMINLIMIT_SHIFT 0 - -#define SR_ERRWEIGHT_MASK (0x07 << 16) -#define SR_ERRMAXLIMIT_MASK (0xff << 8) -#define SR_ERRMINLIMIT_MASK (0xff << 0) - -#define ERRCONFIG_VPBOUNDINTEN_V1 BIT(31) -#define ERRCONFIG_VPBOUNDINTST_V1 BIT(30) -#define ERRCONFIG_MCUACCUMINTEN BIT(29) -#define ERRCONFIG_MCUACCUMINTST BIT(28) -#define ERRCONFIG_MCUVALIDINTEN BIT(27) -#define ERRCONFIG_MCUVALIDINTST BIT(26) -#define ERRCONFIG_MCUBOUNDINTEN BIT(25) -#define ERRCONFIG_MCUBOUNDINTST BIT(24) -#define ERRCONFIG_MCUDISACKINTEN BIT(23) -#define ERRCONFIG_VPBOUNDINTST_V2 BIT(23) -#define ERRCONFIG_MCUDISACKINTST BIT(22) -#define ERRCONFIG_VPBOUNDINTEN_V2 BIT(22) - -#define ERRCONFIG_STATUS_V1_MASK (ERRCONFIG_VPBOUNDINTST_V1 | \ - ERRCONFIG_MCUACCUMINTST | \ - ERRCONFIG_MCUVALIDINTST | \ - ERRCONFIG_MCUBOUNDINTST | \ - ERRCONFIG_MCUDISACKINTST) -/* IRQSTATUS */ -#define IRQSTATUS_MCUACCUMINT BIT(3) -#define IRQSTATUS_MCVALIDINT BIT(2) -#define IRQSTATUS_MCBOUNDSINT BIT(1) -#define IRQSTATUS_MCUDISABLEACKINT BIT(0) - -/* IRQENABLE_SET and IRQENABLE_CLEAR */ -#define IRQENABLE_MCUACCUMINT BIT(3) -#define IRQENABLE_MCUVALIDINT BIT(2) -#define IRQENABLE_MCUBOUNDSINT BIT(1) -#define IRQENABLE_MCUDISABLEACKINT BIT(0) - -/* Common Bit values */ - -#define SRCLKLENGTH_12MHZ_SYSCLK 0x3c -#define SRCLKLENGTH_13MHZ_SYSCLK 0x41 -#define SRCLKLENGTH_19MHZ_SYSCLK 0x60 -#define SRCLKLENGTH_26MHZ_SYSCLK 0x82 -#define SRCLKLENGTH_38MHZ_SYSCLK 0xC0 - -/* - * 3430 specific values. Maybe these should be passed from board file or - * pmic structures. - */ -#define OMAP3430_SR_ACCUMDATA 0x1f4 - -#define OMAP3430_SR1_SENPAVGWEIGHT 0x03 -#define OMAP3430_SR1_SENNAVGWEIGHT 0x03 - -#define OMAP3430_SR2_SENPAVGWEIGHT 0x01 -#define OMAP3430_SR2_SENNAVGWEIGHT 0x01 - -#define OMAP3430_SR_ERRWEIGHT 0x04 -#define OMAP3430_SR_ERRMAXLIMIT 0x02 - -/** - * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass - * pmic specific info to smartreflex driver - * - * @sr_pmic_init: API to initialize smartreflex on the PMIC side. - */ -struct omap_sr_pmic_data { - void (*sr_pmic_init) (void); -}; - -/** - * struct omap_smartreflex_dev_attr - Smartreflex Device attribute. - * - * @sensor_voltdm_name: Name of voltdomain of SR instance - */ -struct omap_smartreflex_dev_attr { - const char *sensor_voltdm_name; -}; - -#ifdef CONFIG_OMAP_SMARTREFLEX -/* - * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR. - * The smartreflex class driver should pass the class type. - * Should be used to populate the class_type field of the - * omap_smartreflex_class_data structure. - */ -#define SR_CLASS1 0x1 -#define SR_CLASS2 0x2 -#define SR_CLASS3 0x3 - -/** - * struct omap_sr_class_data - Smartreflex class driver info - * - * @enable: API to enable a particular class smaartreflex. - * @disable: API to disable a particular class smartreflex. - * @configure: API to configure a particular class smartreflex. - * @notify: API to notify the class driver about an event in SR. - * Not needed for class3. - * @notify_flags: specify the events to be notified to the class driver - * @class_type: specify which smartreflex class. - * Can be used by the SR driver to take any class - * based decisions. - */ -struct omap_sr_class_data { - int (*enable)(struct voltagedomain *voltdm); - int (*disable)(struct voltagedomain *voltdm, int is_volt_reset); - int (*configure)(struct voltagedomain *voltdm); - int (*notify)(struct voltagedomain *voltdm, u32 status); - u8 notify_flags; - u8 class_type; -}; - -/** - * struct omap_sr_nvalue_table - Smartreflex n-target value info - * - * @efuse_offs: The offset of the efuse where n-target values are stored. - * @nvalue: The n-target value. - */ -struct omap_sr_nvalue_table { - u32 efuse_offs; - u32 nvalue; -}; - -/** - * struct omap_sr_data - Smartreflex platform data. - * - * @ip_type: Smartreflex IP type. - * @senp_mod: SENPENABLE value for the sr - * @senn_mod: SENNENABLE value for sr - * @nvalue_count: Number of distinct nvalues in the nvalue table - * @enable_on_init: whether this sr module needs to enabled at - * boot up or not. - * @nvalue_table: table containing the efuse offsets and nvalues - * corresponding to them. - * @voltdm: Pointer to the voltage domain associated with the SR - */ -struct omap_sr_data { - int ip_type; - u32 senp_mod; - u32 senn_mod; - int nvalue_count; - bool enable_on_init; - struct omap_sr_nvalue_table *nvalue_table; - struct voltagedomain *voltdm; -}; - -/* Smartreflex module enable/disable interface */ -void omap_sr_enable(struct voltagedomain *voltdm); -void omap_sr_disable(struct voltagedomain *voltdm); -void omap_sr_disable_reset_volt(struct voltagedomain *voltdm); - -/* API to register the pmic specific data with the smartreflex driver. */ -void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data); - -/* Smartreflex driver hooks to be called from Smartreflex class driver */ -int sr_enable(struct voltagedomain *voltdm, unsigned long volt); -void sr_disable(struct voltagedomain *voltdm); -int sr_configure_errgen(struct voltagedomain *voltdm); -int sr_disable_errgen(struct voltagedomain *voltdm); -int sr_configure_minmax(struct voltagedomain *voltdm); - -/* API to register the smartreflex class driver with the smartreflex driver */ -int sr_register_class(struct omap_sr_class_data *class_data); -#else -static inline void omap_sr_enable(struct voltagedomain *voltdm) {} -static inline void omap_sr_disable(struct voltagedomain *voltdm) {} -static inline void omap_sr_disable_reset_volt( - struct voltagedomain *voltdm) {} -static inline void omap_sr_register_pmic( - struct omap_sr_pmic_data *pmic_data) {} -#endif -#endif diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c index a503e1e8358c..86e438e75105 100644 --- a/arch/arm/mach-omap2/sr_device.c +++ b/arch/arm/mach-omap2/sr_device.c @@ -17,6 +17,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include @@ -24,7 +25,6 @@ #include -#include "smartreflex.h" #include "voltage.h" #include "control.h" #include "pm.h" diff --git a/include/linux/power/smartreflex.h b/include/linux/power/smartreflex.h new file mode 100644 index 000000000000..69eb270c6297 --- /dev/null +++ b/include/linux/power/smartreflex.h @@ -0,0 +1,257 @@ +/* + * OMAP Smartreflex Defines and Routines + * + * Author: Thara Gopinath + * + * Copyright (C) 2010 Texas Instruments, Inc. + * Thara Gopinath + * + * Copyright (C) 2008 Nokia Corporation + * Kalle Jokiniemi + * + * Copyright (C) 2007 Texas Instruments, Inc. + * Lesly A M + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __POWER_SMARTREFLEX_H +#define __POWER_SMARTREFLEX_H + +#include +#include + +#include + +/* + * Different Smartreflex IPs version. The v1 is the 65nm version used in + * OMAP3430. The v2 is the update for the 45nm version of the IP + * used in OMAP3630 and OMAP4430 + */ +#define SR_TYPE_V1 1 +#define SR_TYPE_V2 2 + +/* SMART REFLEX REG ADDRESS OFFSET */ +#define SRCONFIG 0x00 +#define SRSTATUS 0x04 +#define SENVAL 0x08 +#define SENMIN 0x0C +#define SENMAX 0x10 +#define SENAVG 0x14 +#define AVGWEIGHT 0x18 +#define NVALUERECIPROCAL 0x1c +#define SENERROR_V1 0x20 +#define ERRCONFIG_V1 0x24 +#define IRQ_EOI 0x20 +#define IRQSTATUS_RAW 0x24 +#define IRQSTATUS 0x28 +#define IRQENABLE_SET 0x2C +#define IRQENABLE_CLR 0x30 +#define SENERROR_V2 0x34 +#define ERRCONFIG_V2 0x38 + +/* Bit/Shift Positions */ + +/* SRCONFIG */ +#define SRCONFIG_ACCUMDATA_SHIFT 22 +#define SRCONFIG_SRCLKLENGTH_SHIFT 12 +#define SRCONFIG_SENNENABLE_V1_SHIFT 5 +#define SRCONFIG_SENPENABLE_V1_SHIFT 3 +#define SRCONFIG_SENNENABLE_V2_SHIFT 1 +#define SRCONFIG_SENPENABLE_V2_SHIFT 0 +#define SRCONFIG_CLKCTRL_SHIFT 0 + +#define SRCONFIG_ACCUMDATA_MASK (0x3ff << 22) + +#define SRCONFIG_SRENABLE BIT(11) +#define SRCONFIG_SENENABLE BIT(10) +#define SRCONFIG_ERRGEN_EN BIT(9) +#define SRCONFIG_MINMAXAVG_EN BIT(8) +#define SRCONFIG_DELAYCTRL BIT(2) + +/* AVGWEIGHT */ +#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT 2 +#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT 0 + +/* NVALUERECIPROCAL */ +#define NVALUERECIPROCAL_SENPGAIN_SHIFT 20 +#define NVALUERECIPROCAL_SENNGAIN_SHIFT 16 +#define NVALUERECIPROCAL_RNSENP_SHIFT 8 +#define NVALUERECIPROCAL_RNSENN_SHIFT 0 + +/* ERRCONFIG */ +#define ERRCONFIG_ERRWEIGHT_SHIFT 16 +#define ERRCONFIG_ERRMAXLIMIT_SHIFT 8 +#define ERRCONFIG_ERRMINLIMIT_SHIFT 0 + +#define SR_ERRWEIGHT_MASK (0x07 << 16) +#define SR_ERRMAXLIMIT_MASK (0xff << 8) +#define SR_ERRMINLIMIT_MASK (0xff << 0) + +#define ERRCONFIG_VPBOUNDINTEN_V1 BIT(31) +#define ERRCONFIG_VPBOUNDINTST_V1 BIT(30) +#define ERRCONFIG_MCUACCUMINTEN BIT(29) +#define ERRCONFIG_MCUACCUMINTST BIT(28) +#define ERRCONFIG_MCUVALIDINTEN BIT(27) +#define ERRCONFIG_MCUVALIDINTST BIT(26) +#define ERRCONFIG_MCUBOUNDINTEN BIT(25) +#define ERRCONFIG_MCUBOUNDINTST BIT(24) +#define ERRCONFIG_MCUDISACKINTEN BIT(23) +#define ERRCONFIG_VPBOUNDINTST_V2 BIT(23) +#define ERRCONFIG_MCUDISACKINTST BIT(22) +#define ERRCONFIG_VPBOUNDINTEN_V2 BIT(22) + +#define ERRCONFIG_STATUS_V1_MASK (ERRCONFIG_VPBOUNDINTST_V1 | \ + ERRCONFIG_MCUACCUMINTST | \ + ERRCONFIG_MCUVALIDINTST | \ + ERRCONFIG_MCUBOUNDINTST | \ + ERRCONFIG_MCUDISACKINTST) +/* IRQSTATUS */ +#define IRQSTATUS_MCUACCUMINT BIT(3) +#define IRQSTATUS_MCVALIDINT BIT(2) +#define IRQSTATUS_MCBOUNDSINT BIT(1) +#define IRQSTATUS_MCUDISABLEACKINT BIT(0) + +/* IRQENABLE_SET and IRQENABLE_CLEAR */ +#define IRQENABLE_MCUACCUMINT BIT(3) +#define IRQENABLE_MCUVALIDINT BIT(2) +#define IRQENABLE_MCUBOUNDSINT BIT(1) +#define IRQENABLE_MCUDISABLEACKINT BIT(0) + +/* Common Bit values */ + +#define SRCLKLENGTH_12MHZ_SYSCLK 0x3c +#define SRCLKLENGTH_13MHZ_SYSCLK 0x41 +#define SRCLKLENGTH_19MHZ_SYSCLK 0x60 +#define SRCLKLENGTH_26MHZ_SYSCLK 0x82 +#define SRCLKLENGTH_38MHZ_SYSCLK 0xC0 + +/* + * 3430 specific values. Maybe these should be passed from board file or + * pmic structures. + */ +#define OMAP3430_SR_ACCUMDATA 0x1f4 + +#define OMAP3430_SR1_SENPAVGWEIGHT 0x03 +#define OMAP3430_SR1_SENNAVGWEIGHT 0x03 + +#define OMAP3430_SR2_SENPAVGWEIGHT 0x01 +#define OMAP3430_SR2_SENNAVGWEIGHT 0x01 + +#define OMAP3430_SR_ERRWEIGHT 0x04 +#define OMAP3430_SR_ERRMAXLIMIT 0x02 + +/** + * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass + * pmic specific info to smartreflex driver + * + * @sr_pmic_init: API to initialize smartreflex on the PMIC side. + */ +struct omap_sr_pmic_data { + void (*sr_pmic_init) (void); +}; + +/** + * struct omap_smartreflex_dev_attr - Smartreflex Device attribute. + * + * @sensor_voltdm_name: Name of voltdomain of SR instance + */ +struct omap_smartreflex_dev_attr { + const char *sensor_voltdm_name; +}; + +#ifdef CONFIG_OMAP_SMARTREFLEX +/* + * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR. + * The smartreflex class driver should pass the class type. + * Should be used to populate the class_type field of the + * omap_smartreflex_class_data structure. + */ +#define SR_CLASS1 0x1 +#define SR_CLASS2 0x2 +#define SR_CLASS3 0x3 + +/** + * struct omap_sr_class_data - Smartreflex class driver info + * + * @enable: API to enable a particular class smaartreflex. + * @disable: API to disable a particular class smartreflex. + * @configure: API to configure a particular class smartreflex. + * @notify: API to notify the class driver about an event in SR. + * Not needed for class3. + * @notify_flags: specify the events to be notified to the class driver + * @class_type: specify which smartreflex class. + * Can be used by the SR driver to take any class + * based decisions. + */ +struct omap_sr_class_data { + int (*enable)(struct voltagedomain *voltdm); + int (*disable)(struct voltagedomain *voltdm, int is_volt_reset); + int (*configure)(struct voltagedomain *voltdm); + int (*notify)(struct voltagedomain *voltdm, u32 status); + u8 notify_flags; + u8 class_type; +}; + +/** + * struct omap_sr_nvalue_table - Smartreflex n-target value info + * + * @efuse_offs: The offset of the efuse where n-target values are stored. + * @nvalue: The n-target value. + */ +struct omap_sr_nvalue_table { + u32 efuse_offs; + u32 nvalue; +}; + +/** + * struct omap_sr_data - Smartreflex platform data. + * + * @ip_type: Smartreflex IP type. + * @senp_mod: SENPENABLE value for the sr + * @senn_mod: SENNENABLE value for sr + * @nvalue_count: Number of distinct nvalues in the nvalue table + * @enable_on_init: whether this sr module needs to enabled at + * boot up or not. + * @nvalue_table: table containing the efuse offsets and nvalues + * corresponding to them. + * @voltdm: Pointer to the voltage domain associated with the SR + */ +struct omap_sr_data { + int ip_type; + u32 senp_mod; + u32 senn_mod; + int nvalue_count; + bool enable_on_init; + struct omap_sr_nvalue_table *nvalue_table; + struct voltagedomain *voltdm; +}; + +/* Smartreflex module enable/disable interface */ +void omap_sr_enable(struct voltagedomain *voltdm); +void omap_sr_disable(struct voltagedomain *voltdm); +void omap_sr_disable_reset_volt(struct voltagedomain *voltdm); + +/* API to register the pmic specific data with the smartreflex driver. */ +void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data); + +/* Smartreflex driver hooks to be called from Smartreflex class driver */ +int sr_enable(struct voltagedomain *voltdm, unsigned long volt); +void sr_disable(struct voltagedomain *voltdm); +int sr_configure_errgen(struct voltagedomain *voltdm); +int sr_disable_errgen(struct voltagedomain *voltdm); +int sr_configure_minmax(struct voltagedomain *voltdm); + +/* API to register the smartreflex class driver with the smartreflex driver */ +int sr_register_class(struct omap_sr_class_data *class_data); +#else +static inline void omap_sr_enable(struct voltagedomain *voltdm) {} +static inline void omap_sr_disable(struct voltagedomain *voltdm) {} +static inline void omap_sr_disable_reset_volt( + struct voltagedomain *voltdm) {} +static inline void omap_sr_register_pmic( + struct omap_sr_pmic_data *pmic_data) {} +#endif +#endif -- cgit v1.2.3 From 80821c9c90427dd0f9274a82f9d69e43300d10bb Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Tue, 24 Apr 2012 10:22:12 +0530 Subject: ARM: OMAP3+: SmartReflex: class drivers should use struct omap_sr * Convert SmartReflex "class" functions to take a struct omap_sr *, rather than a struct voltagedomain *. SmartReflex code should be driver code and not tightly coupled to OMAP subarchitecture-specific structures. Based on Paul's original code for the SmartReflex driver conversion. Signed-off-by: Jean Pihet Signed-off-by: J Keerthy Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/smartreflex-class3.c | 24 ++++++++++----------- arch/arm/mach-omap2/smartreflex.c | 37 ++++++-------------------------- include/linux/power/smartreflex.h | 31 ++++++++++++++++++++++---- 3 files changed, 46 insertions(+), 46 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c index ab8cf83e853e..9381654e869b 100644 --- a/arch/arm/mach-omap2/smartreflex-class3.c +++ b/arch/arm/mach-omap2/smartreflex-class3.c @@ -14,34 +14,34 @@ #include #include "voltage.h" -static int sr_class3_enable(struct voltagedomain *voltdm) +static int sr_class3_enable(struct omap_sr *sr) { - unsigned long volt = voltdm_get_voltage(voltdm); + unsigned long volt = voltdm_get_voltage(sr->voltdm); if (!volt) { pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n", - __func__, voltdm->name); + __func__, sr->voltdm->name); return -ENODATA; } - omap_vp_enable(voltdm); - return sr_enable(voltdm, volt); + omap_vp_enable(sr->voltdm); + return sr_enable(sr->voltdm, volt); } -static int sr_class3_disable(struct voltagedomain *voltdm, int is_volt_reset) +static int sr_class3_disable(struct omap_sr *sr, int is_volt_reset) { - sr_disable_errgen(voltdm); - omap_vp_disable(voltdm); - sr_disable(voltdm); + sr_disable_errgen(sr->voltdm); + omap_vp_disable(sr->voltdm); + sr_disable(sr->voltdm); if (is_volt_reset) - voltdm_reset(voltdm); + voltdm_reset(sr->voltdm); return 0; } -static int sr_class3_configure(struct voltagedomain *voltdm) +static int sr_class3_configure(struct omap_sr *sr) { - return sr_configure_errgen(voltdm); + return sr_configure_errgen(sr->voltdm); } /* SR class3 structure */ diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index 98309d32ba98..82bdd2838a17 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -34,29 +34,6 @@ #define NVALUE_NAME_LEN 40 #define SR_DISABLE_TIMEOUT 200 -struct omap_sr { - struct list_head node; - struct platform_device *pdev; - struct omap_sr_nvalue_table *nvalue_table; - struct voltagedomain *voltdm; - struct dentry *dbg_dir; - unsigned int irq; - int srid; - int ip_type; - int nvalue_count; - bool autocomp_active; - u32 clk_length; - u32 err_weight; - u32 err_minlimit; - u32 err_maxlimit; - u32 accum_data; - u32 senn_avgweight; - u32 senp_avgweight; - u32 senp_mod; - u32 senn_mod; - void __iomem *base; -}; - /* sr_list contains all the instances of smartreflex module */ static LIST_HEAD(sr_list); @@ -147,7 +124,7 @@ static irqreturn_t sr_interrupt(int irq, void *data) } if (sr_class->notify) - sr_class->notify(sr_info->voltdm, status); + sr_class->notify(sr_info, status); return IRQ_HANDLED; } @@ -225,7 +202,7 @@ static void sr_start_vddautocomp(struct omap_sr *sr) return; } - if (!sr_class->enable(sr->voltdm)) + if (!sr_class->enable(sr)) sr->autocomp_active = true; } @@ -239,7 +216,7 @@ static void sr_stop_vddautocomp(struct omap_sr *sr) } if (sr->autocomp_active) { - sr_class->disable(sr->voltdm, 1); + sr_class->disable(sr, 1); sr->autocomp_active = false; } } @@ -654,7 +631,7 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt) return 0; /* Configure SR */ - ret = sr_class->configure(voltdm); + ret = sr_class->configure(sr); if (ret) return ret; @@ -772,7 +749,7 @@ void omap_sr_enable(struct voltagedomain *voltdm) return; } - sr_class->enable(voltdm); + sr_class->enable(sr); } /** @@ -805,7 +782,7 @@ void omap_sr_disable(struct voltagedomain *voltdm) return; } - sr_class->disable(voltdm, 0); + sr_class->disable(sr, 0); } /** @@ -838,7 +815,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm) return; } - sr_class->disable(voltdm, 1); + sr_class->disable(sr, 1); } /** diff --git a/include/linux/power/smartreflex.h b/include/linux/power/smartreflex.h index 69eb270c6297..4224698cf8bd 100644 --- a/include/linux/power/smartreflex.h +++ b/include/linux/power/smartreflex.h @@ -143,6 +143,29 @@ #define OMAP3430_SR_ERRWEIGHT 0x04 #define OMAP3430_SR_ERRMAXLIMIT 0x02 +struct omap_sr { + struct list_head node; + struct platform_device *pdev; + struct omap_sr_nvalue_table *nvalue_table; + struct voltagedomain *voltdm; + struct dentry *dbg_dir; + unsigned int irq; + int srid; + int ip_type; + int nvalue_count; + bool autocomp_active; + u32 clk_length; + u32 err_weight; + u32 err_minlimit; + u32 err_maxlimit; + u32 accum_data; + u32 senn_avgweight; + u32 senp_avgweight; + u32 senp_mod; + u32 senn_mod; + void __iomem *base; +}; + /** * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass * pmic specific info to smartreflex driver @@ -187,10 +210,10 @@ struct omap_smartreflex_dev_attr { * based decisions. */ struct omap_sr_class_data { - int (*enable)(struct voltagedomain *voltdm); - int (*disable)(struct voltagedomain *voltdm, int is_volt_reset); - int (*configure)(struct voltagedomain *voltdm); - int (*notify)(struct voltagedomain *voltdm, u32 status); + int (*enable)(struct omap_sr *sr); + int (*disable)(struct omap_sr *sr, int is_volt_reset); + int (*configure)(struct omap_sr *sr); + int (*notify)(struct omap_sr *sr, u32 status); u8 notify_flags; u8 class_type; }; -- cgit v1.2.3 From 8b765d727d711650ab3521411fd48a0d8f62a84c Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Tue, 24 Apr 2012 10:41:27 +0530 Subject: ARM: OMAP2+: smartreflex: Use the names from hwmod data instead of voltage domains. Associate a name with each SmartReflex instance from the hwmod data, rather than attempting to reuse the name of a voltage domain. The name from hwmod better reflects the smartreflex integration in the system. Also have the name passed to the drivers using pdata, which helps to remove any dependencies on SoC-specific structures. Signed-off-by: Jean Pihet Signed-off-by: J Keerthy Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/smartreflex-class3.c | 4 +- arch/arm/mach-omap2/smartreflex.c | 65 +++++++++++++------------------- arch/arm/mach-omap2/sr_device.c | 1 + include/linux/power/smartreflex.h | 3 ++ 4 files changed, 32 insertions(+), 41 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c index 9381654e869b..1da8f03c479e 100644 --- a/arch/arm/mach-omap2/smartreflex-class3.c +++ b/arch/arm/mach-omap2/smartreflex-class3.c @@ -19,8 +19,8 @@ static int sr_class3_enable(struct omap_sr *sr) unsigned long volt = voltdm_get_voltage(sr->voltdm); if (!volt) { - pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n", - __func__, sr->voltdm->name); + pr_warning("%s: Curr voltage unknown. Cannot enable %s\n", + __func__, sr->name); return -ENODATA; } diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index 82bdd2838a17..2edd1e2e4622 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -183,7 +183,7 @@ static void sr_set_regfields(struct omap_sr *sr) sr->err_weight = OMAP3430_SR_ERRWEIGHT; sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT; sr->accum_data = OMAP3430_SR_ACCUMDATA; - if (!(strcmp(sr->voltdm->name, "mpu"))) { + if (!(strcmp(sr->name, "sr1"))) { sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT; sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT; } else { @@ -234,19 +234,13 @@ static void sr_stop_vddautocomp(struct omap_sr *sr) */ static int sr_late_init(struct omap_sr *sr_info) { - char *name; struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data; struct resource *mem; int ret = 0; if (sr_class->notify && sr_class->notify_flags && sr_info->irq) { - name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name); - if (name == NULL) { - ret = -ENOMEM; - goto error; - } ret = request_irq(sr_info->irq, sr_interrupt, - 0, name, sr_info); + 0, sr_info->name, sr_info); if (ret) goto error; disable_irq(sr_info->irq); @@ -265,7 +259,6 @@ error: dev_err(&sr_info->pdev->dev, "%s: ERROR in registering" "interrupt handler. Smartreflex will" "not function as desired\n", __func__); - kfree(name); kfree(sr_info); return ret; @@ -395,8 +388,7 @@ int sr_configure_errgen(struct voltagedomain *voltdm) struct omap_sr *sr = _sr_lookup(voltdm); if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for sr_%s not found\n", - __func__, voltdm->name); + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); return PTR_ERR(sr); } @@ -463,8 +455,7 @@ int sr_disable_errgen(struct voltagedomain *voltdm) struct omap_sr *sr = _sr_lookup(voltdm); if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for sr_%s not found\n", - __func__, voltdm->name); + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); return PTR_ERR(sr); } @@ -514,8 +505,7 @@ int sr_configure_minmax(struct voltagedomain *voltdm) struct omap_sr *sr = _sr_lookup(voltdm); if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for sr_%s not found\n", - __func__, voltdm->name); + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); return PTR_ERR(sr); } @@ -600,8 +590,7 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt) int ret; if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for sr_%s not found\n", - __func__, voltdm->name); + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); return PTR_ERR(sr); } @@ -654,8 +643,7 @@ void sr_disable(struct voltagedomain *voltdm) struct omap_sr *sr = _sr_lookup(voltdm); if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for sr_%s not found\n", - __func__, voltdm->name); + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); return; } @@ -735,8 +723,7 @@ void omap_sr_enable(struct voltagedomain *voltdm) struct omap_sr *sr = _sr_lookup(voltdm); if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for sr_%s not found\n", - __func__, voltdm->name); + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); return; } @@ -768,8 +755,7 @@ void omap_sr_disable(struct voltagedomain *voltdm) struct omap_sr *sr = _sr_lookup(voltdm); if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for sr_%s not found\n", - __func__, voltdm->name); + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); return; } @@ -801,8 +787,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm) struct omap_sr *sr = _sr_lookup(voltdm); if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for sr_%s not found\n", - __func__, voltdm->name); + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); return; } @@ -889,7 +874,6 @@ static int __init omap_sr_probe(struct platform_device *pdev) struct dentry *nvalue_dir; struct omap_volt_data *volt_data; int i, ret = 0; - char *name; sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL); if (!sr_info) { @@ -926,6 +910,14 @@ static int __init omap_sr_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_irq_safe(&pdev->dev); + sr_info->name = kasprintf(GFP_KERNEL, "%s", pdata->name); + if (!sr_info->name) { + dev_err(&pdev->dev, "%s: Unable to alloc SR instance name\n", + __func__); + ret = -ENOMEM; + goto err_release_region; + } + sr_info->pdev = pdev; sr_info->srid = pdev->id; sr_info->voltdm = pdata->voltdm; @@ -973,20 +965,12 @@ static int __init omap_sr_probe(struct platform_device *pdev) } } - name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name); - if (!name) { - dev_err(&pdev->dev, "%s: Unable to alloc debugfs name\n", - __func__); - ret = -ENOMEM; - goto err_iounmap; - } - sr_info->dbg_dir = debugfs_create_dir(name, sr_dbg_dir); - kfree(name); + sr_info->dbg_dir = debugfs_create_dir(sr_info->name, sr_dbg_dir); if (IS_ERR_OR_NULL(sr_info->dbg_dir)) { dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n", __func__); ret = PTR_ERR(sr_info->dbg_dir); - goto err_iounmap; + goto err_free_name; } (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, @@ -1008,10 +992,10 @@ static int __init omap_sr_probe(struct platform_device *pdev) omap_voltage_get_volttable(sr_info->voltdm, &volt_data); if (!volt_data) { - dev_warn(&pdev->dev, "%s: No Voltage table for the" - " corresponding vdd vdd_%s. Cannot create debugfs" + dev_warn(&pdev->dev, "%s: %s: No Voltage table for the" + " corresponding vdd. Cannot create debugfs" "entries for n-values\n", - __func__, sr_info->voltdm->name); + __func__, sr_info->name); ret = -ENODATA; goto err_debugfs; } @@ -1029,6 +1013,8 @@ static int __init omap_sr_probe(struct platform_device *pdev) err_debugfs: debugfs_remove_recursive(sr_info->dbg_dir); +err_free_name: + kfree(sr_info->name); err_iounmap: list_del(&sr_info->node); iounmap(sr_info->base); @@ -1065,6 +1051,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev) list_del(&sr_info->node); iounmap(sr_info->base); + kfree(sr_info->name); kfree(sr_info); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(mem->start, resource_size(mem)); diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c index 86e438e75105..e081174f28af 100644 --- a/arch/arm/mach-omap2/sr_device.c +++ b/arch/arm/mach-omap2/sr_device.c @@ -93,6 +93,7 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user) goto exit; } + sr_data->name = oh->name; sr_data->ip_type = oh->class->rev; sr_data->senn_mod = 0x1; sr_data->senp_mod = 0x1; diff --git a/include/linux/power/smartreflex.h b/include/linux/power/smartreflex.h index 4224698cf8bd..884eaeea96be 100644 --- a/include/linux/power/smartreflex.h +++ b/include/linux/power/smartreflex.h @@ -144,6 +144,7 @@ #define OMAP3430_SR_ERRMAXLIMIT 0x02 struct omap_sr { + char *name; struct list_head node; struct platform_device *pdev; struct omap_sr_nvalue_table *nvalue_table; @@ -232,6 +233,7 @@ struct omap_sr_nvalue_table { /** * struct omap_sr_data - Smartreflex platform data. * + * @name: instance name * @ip_type: Smartreflex IP type. * @senp_mod: SENPENABLE value for the sr * @senn_mod: SENNENABLE value for sr @@ -243,6 +245,7 @@ struct omap_sr_nvalue_table { * @voltdm: Pointer to the voltage domain associated with the SR */ struct omap_sr_data { + const char *name; int ip_type; u32 senp_mod; u32 senn_mod; -- cgit v1.2.3 From 1fcd3069d4944ad0532f41fbc4957ba24552a92f Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Tue, 24 Apr 2012 10:47:14 +0530 Subject: ARM: OMAP3: hwmod: rename the smartreflex entries Change the name field value to better reflect the smartreflex integration in the system. Signed-off-by: Jean Pihet Signed-off-by: J Keerthy Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 8 ++++---- arch/arm/mach-omap2/smartreflex.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 8c7241b7279c..0d611d3d0d03 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1325,7 +1325,7 @@ static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = { }; static struct omap_hwmod omap34xx_sr1_hwmod = { - .name = "sr1", + .name = "smartreflex_mpu_iva", .class = &omap34xx_smartreflex_hwmod_class, .main_clk = "sr1_fck", .prcm = { @@ -1343,7 +1343,7 @@ static struct omap_hwmod omap34xx_sr1_hwmod = { }; static struct omap_hwmod omap36xx_sr1_hwmod = { - .name = "sr1", + .name = "smartreflex_mpu_iva", .class = &omap36xx_smartreflex_hwmod_class, .main_clk = "sr1_fck", .prcm = { @@ -1370,7 +1370,7 @@ static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = { }; static struct omap_hwmod omap34xx_sr2_hwmod = { - .name = "sr2", + .name = "smartreflex_core", .class = &omap34xx_smartreflex_hwmod_class, .main_clk = "sr2_fck", .prcm = { @@ -1388,7 +1388,7 @@ static struct omap_hwmod omap34xx_sr2_hwmod = { }; static struct omap_hwmod omap36xx_sr2_hwmod = { - .name = "sr2", + .name = "smartreflex_core", .class = &omap36xx_smartreflex_hwmod_class, .main_clk = "sr2_fck", .prcm = { diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index 2edd1e2e4622..d8592771838f 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -183,7 +183,7 @@ static void sr_set_regfields(struct omap_sr *sr) sr->err_weight = OMAP3430_SR_ERRWEIGHT; sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT; sr->accum_data = OMAP3430_SR_ACCUMDATA; - if (!(strcmp(sr->name, "sr1"))) { + if (!(strcmp(sr->name, "smartreflex_mpu_iva"))) { sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT; sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT; } else { -- cgit v1.2.3 From 50e4a7d0b26c86628300edf4625cc5ff16a7a227 Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Tue, 24 Apr 2012 10:56:40 +0530 Subject: ARM: OMAP2+: SmartReflex: introduce a busy loop condition test macro Now that omap_test_timeout is only accessible from mach-omap2/, introduce a similar function for SR. This change makes the SmartReflex implementation ready for the move to drivers/. Signed-off-by: Jean Pihet Signed-off-by: J Keerthy Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/smartreflex.c | 12 ++++++------ include/linux/power/smartreflex.h | 23 ++++++++++++++++++++++- 2 files changed, 28 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index d8592771838f..acef08d837cc 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -289,9 +289,9 @@ static void sr_v1_disable(struct omap_sr *sr) * Wait for SR to be disabled. * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us. */ - omap_test_timeout((sr_read_reg(sr, ERRCONFIG_V1) & - ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT, - timeout); + sr_test_cond_timeout((sr_read_reg(sr, ERRCONFIG_V1) & + ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT, + timeout); if (timeout >= SR_DISABLE_TIMEOUT) dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n", @@ -334,9 +334,9 @@ static void sr_v2_disable(struct omap_sr *sr) * Wait for SR to be disabled. * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us. */ - omap_test_timeout((sr_read_reg(sr, IRQSTATUS) & - IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT, - timeout); + sr_test_cond_timeout((sr_read_reg(sr, IRQSTATUS) & + IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT, + timeout); if (timeout >= SR_DISABLE_TIMEOUT) dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n", diff --git a/include/linux/power/smartreflex.h b/include/linux/power/smartreflex.h index 884eaeea96be..78b795ea2709 100644 --- a/include/linux/power/smartreflex.h +++ b/include/linux/power/smartreflex.h @@ -22,7 +22,7 @@ #include #include - +#include #include /* @@ -167,6 +167,27 @@ struct omap_sr { void __iomem *base; }; +/** + * test_cond_timeout - busy-loop, testing a condition + * @cond: condition to test until it evaluates to true + * @timeout: maximum number of microseconds in the timeout + * @index: loop index (integer) + * + * Loop waiting for @cond to become true or until at least @timeout + * microseconds have passed. To use, define some integer @index in the + * calling code. After running, if @index == @timeout, then the loop has + * timed out. + * + * Copied from omap_test_timeout */ +#define sr_test_cond_timeout(cond, timeout, index) \ +({ \ + for (index = 0; index < timeout; index++) { \ + if (cond) \ + break; \ + udelay(1); \ + } \ +}) + /** * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass * pmic specific info to smartreflex driver -- cgit v1.2.3 From fa60be6e3f9362bd841e26b9366f0db7b761a042 Mon Sep 17 00:00:00 2001 From: J Keerthy Date: Wed, 25 Apr 2012 11:14:31 +0530 Subject: ARM: OMAP2+: Voltage: Move the omap_volt_data structure to plat Move the omap_volt_data structure from mach-omap2/ directory to arch/arm/plat-omap/include/plat/ so that it is accessible from both mach-omap2 and drivers directories. Signed-off-by: J Keerthy Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/voltage.h | 21 ++------------------- arch/arm/plat-omap/include/plat/voltage.h | 21 ++++++++++++++++++++- 2 files changed, 22 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h index 16a1b092cf36..34ef504adafd 100644 --- a/arch/arm/mach-omap2/voltage.h +++ b/arch/arm/mach-omap2/voltage.h @@ -16,6 +16,8 @@ #include +#include + #include "vc.h" #include "vp.h" @@ -90,25 +92,6 @@ struct voltagedomain { struct omap_volt_data *volt_data; }; -/** - * struct omap_volt_data - Omap voltage specific data. - * @voltage_nominal: The possible voltage value in uV - * @sr_efuse_offs: The offset of the efuse register(from system - * control module base address) from where to read - * the n-target value for the smartreflex module. - * @sr_errminlimit: Error min limit value for smartreflex. This value - * differs at differnet opp and thus is linked - * with voltage. - * @vp_errorgain: Error gain value for the voltage processor. This - * field also differs according to the voltage/opp. - */ -struct omap_volt_data { - u32 volt_nominal; - u32 sr_efuse_offs; - u8 sr_errminlimit; - u8 vp_errgain; -}; - /** * struct omap_voltdm_pmic - PMIC specific data required by voltage driver. * @slew_rate: PMIC slew rate (in uv/us) diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h index 0a6a482ec014..5be4d5def427 100644 --- a/arch/arm/plat-omap/include/plat/voltage.h +++ b/arch/arm/plat-omap/include/plat/voltage.h @@ -11,10 +11,29 @@ #ifndef __ARCH_ARM_OMAP_VOLTAGE_H #define __ARCH_ARM_OMAP_VOLTAGE_H +/** + * struct omap_volt_data - Omap voltage specific data. + * @voltage_nominal: The possible voltage value in uV + * @sr_efuse_offs: The offset of the efuse register(from system + * control module base address) from where to read + * the n-target value for the smartreflex module. + * @sr_errminlimit: Error min limit value for smartreflex. This value + * differs at differnet opp and thus is linked + * with voltage. + * @vp_errorgain: Error gain value for the voltage processor. This + * field also differs according to the voltage/opp. + */ +struct omap_volt_data { + u32 volt_nominal; + u32 sr_efuse_offs; + u8 sr_errminlimit; + u8 vp_errgain; +}; struct voltagedomain; struct voltagedomain *voltdm_lookup(const char *name); int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt); unsigned long voltdm_get_voltage(struct voltagedomain *voltdm); - +struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm, + unsigned long volt); #endif -- cgit v1.2.3 From 5e7f2e12e4ea14a34fb9b5941d60a4464fc8d40a Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Wed, 25 Apr 2012 11:19:44 +0530 Subject: ARM: OMAP2+: SmartReflex: Use per-OPP data structure The SmartReflex driver incorrectly treats some per-OPP data as data common to all OPPs (e.g., ERRMINLIMIT). Move this data into a per-OPP data structure. Furthermore, in order to make the SmartReflex implementation ready for the move to drivers/, remove the dependency from the SR driver code to the voltage layer by querying the data tables only from the SR device init code. Based on Paul's original code for the SmartReflex driver conversion. Signed-off-by: Jean Pihet Signed-off-by: J Keerthy Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/smartreflex.c | 38 ++++++++++++++++++-------------------- arch/arm/mach-omap2/sr_device.c | 36 ++++++++++++++++++++++++++++++------ include/linux/power/smartreflex.h | 8 ++++++-- 3 files changed, 54 insertions(+), 28 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index acef08d837cc..20075de13868 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -347,22 +347,23 @@ static void sr_v2_disable(struct omap_sr *sr) sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT); } -static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs) +static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row( + struct omap_sr *sr, u32 efuse_offs) { int i; if (!sr->nvalue_table) { dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n", __func__); - return 0; + return NULL; } for (i = 0; i < sr->nvalue_count; i++) { if (sr->nvalue_table[i].efuse_offs == efuse_offs) - return sr->nvalue_table[i].nvalue; + return &sr->nvalue_table[i]; } - return 0; + return NULL; } /* Public Functions */ @@ -586,7 +587,7 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt) { struct omap_volt_data *volt_data; struct omap_sr *sr = _sr_lookup(voltdm); - u32 nvalue_reciprocal; + struct omap_sr_nvalue_table *nvalue_row; int ret; if (IS_ERR(sr)) { @@ -602,16 +603,16 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt) return PTR_ERR(volt_data); } - nvalue_reciprocal = sr_retrieve_nvalue(sr, volt_data->sr_efuse_offs); + nvalue_row = sr_retrieve_nvalue_row(sr, volt_data->sr_efuse_offs); - if (!nvalue_reciprocal) { - dev_warn(&sr->pdev->dev, "%s: NVALUE = 0 at voltage %ld\n", - __func__, volt); + if (!nvalue_row) { + dev_warn(&sr->pdev->dev, "%s: failure getting SR data for this voltage %ld\n", + __func__, volt); return -ENODATA; } /* errminlimit is opp dependent and hence linked to voltage */ - sr->err_minlimit = volt_data->sr_errminlimit; + sr->err_minlimit = nvalue_row->errminlimit; pm_runtime_get_sync(&sr->pdev->dev); @@ -624,7 +625,7 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt) if (ret) return ret; - sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal); + sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue); /* SRCONFIG - enable SR */ sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE); @@ -872,7 +873,6 @@ static int __init omap_sr_probe(struct platform_device *pdev) struct omap_sr_data *pdata = pdev->dev.platform_data; struct resource *mem, *irq; struct dentry *nvalue_dir; - struct omap_volt_data *volt_data; int i, ret = 0; sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL); @@ -990,12 +990,10 @@ static int __init omap_sr_probe(struct platform_device *pdev) goto err_debugfs; } - omap_voltage_get_volttable(sr_info->voltdm, &volt_data); - if (!volt_data) { - dev_warn(&pdev->dev, "%s: %s: No Voltage table for the" - " corresponding vdd. Cannot create debugfs" - "entries for n-values\n", - __func__, sr_info->name); + if (sr_info->nvalue_count == 0 || !sr_info->nvalue_table) { + dev_warn(&pdev->dev, "%s: %s: No Voltage table for the corresponding vdd. Cannot create debugfs entries for n-values\n", + __func__, sr_info->name); + ret = -ENODATA; goto err_debugfs; } @@ -1003,8 +1001,8 @@ static int __init omap_sr_probe(struct platform_device *pdev) for (i = 0; i < sr_info->nvalue_count; i++) { char name[NVALUE_NAME_LEN + 1]; - snprintf(name, sizeof(name), "volt_%d", - volt_data[i].volt_nominal); + snprintf(name, sizeof(name), "volt_%lu", + sr_info->nvalue_table[i].volt_nominal); (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir, &(sr_info->nvalue_table[i].nvalue)); } diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c index e081174f28af..e107e3915a8a 100644 --- a/arch/arm/mach-omap2/sr_device.c +++ b/arch/arm/mach-omap2/sr_device.c @@ -36,7 +36,10 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data, struct omap_sr_data *sr_data) { struct omap_sr_nvalue_table *nvalue_table; - int i, count = 0; + int i, j, count = 0; + + sr_data->nvalue_count = 0; + sr_data->nvalue_table = NULL; while (volt_data[count].volt_nominal) count++; @@ -44,8 +47,14 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data, nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count, GFP_KERNEL); - for (i = 0; i < count; i++) { + if (!nvalue_table) { + pr_err("OMAP: SmartReflex: cannot allocate memory for n-value table\n"); + return; + } + + for (i = 0, j = 0; i < count; i++) { u32 v; + /* * In OMAP4 the efuse registers are 24 bit aligned. * A __raw_readl will fail for non-32 bit aligned address @@ -58,15 +67,30 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data, omap_ctrl_readb(offset + 1) << 8 | omap_ctrl_readb(offset + 2) << 16; } else { - v = omap_ctrl_readl(volt_data[i].sr_efuse_offs); + v = omap_ctrl_readl(volt_data[i].sr_efuse_offs); } - nvalue_table[i].efuse_offs = volt_data[i].sr_efuse_offs; - nvalue_table[i].nvalue = v; + /* + * Many OMAP SoCs don't have the eFuse values set. + * For example, pretty much all OMAP3xxx before + * ES3.something. + * + * XXX There needs to be some way for board files or + * userspace to add these in. + */ + if (v == 0) + continue; + + nvalue_table[j].nvalue = v; + nvalue_table[j].efuse_offs = volt_data[i].sr_efuse_offs; + nvalue_table[j].errminlimit = volt_data[i].sr_errminlimit; + nvalue_table[j].volt_nominal = volt_data[i].volt_nominal; + + j++; } sr_data->nvalue_table = nvalue_table; - sr_data->nvalue_count = count; + sr_data->nvalue_count = j; } static int __init sr_dev_init(struct omap_hwmod *oh, void *user) diff --git a/include/linux/power/smartreflex.h b/include/linux/power/smartreflex.h index 78b795ea2709..222f90183712 100644 --- a/include/linux/power/smartreflex.h +++ b/include/linux/power/smartreflex.h @@ -243,12 +243,16 @@ struct omap_sr_class_data { /** * struct omap_sr_nvalue_table - Smartreflex n-target value info * - * @efuse_offs: The offset of the efuse where n-target values are stored. - * @nvalue: The n-target value. + * @efuse_offs: The offset of the efuse where n-target values are stored. + * @nvalue: The n-target value. + * @errminlimit: The value of the ERRMINLIMIT bitfield for this n-target + * @volt_nominal: microvolts DC that the VDD is initially programmed to */ struct omap_sr_nvalue_table { u32 efuse_offs; u32 nvalue; + u32 errminlimit; + unsigned long volt_nominal; }; /** -- cgit v1.2.3 From 308d1bd0a7e6fedafacc389b134ef54458e39f4d Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Tue, 24 Apr 2012 23:41:54 +0530 Subject: ARM: OMAP2+: SmartReflex: Create per-opp debugfs node for errminlimit Remove the global errminlimit debugfs entry and create per-voltage entries from the data tables. Signed-off-by: Jean Pihet Signed-off-by: J Keerthy Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/smartreflex.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index 20075de13868..515041ccccb8 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -979,8 +979,6 @@ static int __init omap_sr_probe(struct platform_device *pdev) &sr_info->err_weight); (void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir, &sr_info->err_maxlimit); - (void) debugfs_create_x32("errminlimit", S_IRUGO, sr_info->dbg_dir, - &sr_info->err_minlimit); nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir); if (IS_ERR_OR_NULL(nvalue_dir)) { @@ -1005,6 +1003,11 @@ static int __init omap_sr_probe(struct platform_device *pdev) sr_info->nvalue_table[i].volt_nominal); (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir, &(sr_info->nvalue_table[i].nvalue)); + snprintf(name, sizeof(name), "errminlimit_%lu", + sr_info->nvalue_table[i].volt_nominal); + (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir, + &(sr_info->nvalue_table[i].errminlimit)); + } return ret; -- cgit v1.2.3 From 7fb149ffe357d6ad672cf9325181530b4c478a81 Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Tue, 24 Apr 2012 11:38:50 +0530 Subject: ARM: OMAP2+: SmartReflex: add POWER_AVS Kconfig options Add a Kconfig menu (POWER_AVS) and rename the Kconfig options for the OMAP SmartReflex implementation: CONFIG_OMAP_SMARTREFLEX renames to CONFIG_POWER_AVS_OMAP CONFIG_OMAP_SMARTREFLEX_CLASS3 renames to CONFIG_POWER_AVS_OMAP_CLASS3 This change makes the SmartReflex implementation ready for the move to drivers/. Signed-off-by: Jean Pihet Signed-off-by: J Keerthy Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/Makefile | 5 +++-- arch/arm/mach-omap2/pm.h | 2 +- arch/arm/plat-omap/Kconfig | 45 ++++++++++++++++++++++++++------------- include/linux/power/smartreflex.h | 2 +- 4 files changed, 35 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 385c083d24b2..518444acc90f 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -69,8 +69,9 @@ obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o \ obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o \ cpuidle44xx.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o -obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o -obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o + +obj-$(CONFIG_POWER_AVS_OMAP) += sr_device.o smartreflex.o +obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) += smartreflex-class3.o AFLAGS_sleep24xx.o :=-Wa,-march=armv6 AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec) diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 78564895e914..9fac67d6c985 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -88,7 +88,7 @@ extern void enable_omap3630_toggle_l2_on_restore(void); static inline void enable_omap3630_toggle_l2_on_restore(void) { } #endif /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */ -#ifdef CONFIG_OMAP_SMARTREFLEX +#ifdef CONFIG_POWER_AVS_OMAP extern int omap_devinit_smartreflex(void); extern void omap_enable_smartreflex_on_init(void); #else diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index ad95c7a5d009..bba384dfbcf6 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -45,37 +45,52 @@ config OMAP_DEBUG_LEDS depends on OMAP_DEBUG_DEVICES default y if LEDS_CLASS -config OMAP_SMARTREFLEX - bool "SmartReflex support" - depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM +menuconfig POWER_AVS + tristate "Adaptive Voltage Scaling class support" help - Say Y if you want to enable SmartReflex. + AVS(Adaptive Voltage Scaling) is a power management technique which + finely controls the operating voltage of a device in order to optimize + (i.e. reduce) its power consumption. + At a given operating point the voltage is adapted depending on + static factors (chip manufacturing process) and dynamic factors + (temperature depending performance). + AVS is also called SmartReflex on OMAP devices. + + Say Y here to enable Adaptive Voltage Scaling class support. + +if POWER_AVS - SmartReflex can perform continuous dynamic voltage - scaling around the nominal operating point voltage - according to silicon characteristics and operating - conditions. Enabling SmartReflex reduces power - consumption. +config POWER_AVS_OMAP + bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2" + depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM + help + Say Y to enable AVS support on OMAP containing the version 1 or + version 2 of the SmartReflex IP. + V1 is the 65nm version used in OMAP3430. + V2 is the update for the 45nm version of the IP used in OMAP3630 + and OMAP4430 Please note, that by default SmartReflex is only - initialized. To enable the automatic voltage - compensation for vdd mpu and vdd core from user space, + initialized and not enabled. To enable the automatic voltage + compensation for vdd mpu and vdd core from user space, user must write 1 to - /debug/voltage/vdd_/smartreflex/autocomp, - where X is mpu or core for OMAP3. + /debug/smartreflex/sr_/autocomp, + where X is mpu_iva or core for OMAP3. Optionally autocompensation can be enabled in the kernel by default during system init via the enable_on_init flag which an be passed as platform data to the smartreflex driver. -config OMAP_SMARTREFLEX_CLASS3 +config POWER_AVS_OMAP_CLASS3 bool "Class 3 mode of Smartreflex Implementation" - depends on OMAP_SMARTREFLEX && TWL4030_CORE + depends on POWER_AVS_OMAP && TWL4030_CORE help Say Y to enable Class 3 implementation of Smartreflex Class 3 implementation of Smartreflex employs continuous hardware voltage calibration. +endif # POWER_AVS + config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP diff --git a/include/linux/power/smartreflex.h b/include/linux/power/smartreflex.h index 222f90183712..3101e62a1213 100644 --- a/include/linux/power/smartreflex.h +++ b/include/linux/power/smartreflex.h @@ -207,7 +207,7 @@ struct omap_smartreflex_dev_attr { const char *sensor_voltdm_name; }; -#ifdef CONFIG_OMAP_SMARTREFLEX +#ifdef CONFIG_POWER_AVS_OMAP /* * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR. * The smartreflex class driver should pass the class type. -- cgit v1.2.3 From 21ff63ad131218048525fbd37d065ce61f03bcbd Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Wed, 25 Apr 2012 16:43:17 +0530 Subject: ARM: OMAP: SmartReflex: Move smartreflex driver to drivers/ After a clean-up of the interfaces the OMAP Smartreflex IP driver is now a generic driver. Move it to drivers/power/avs/. The build is controlled by the following Kconfig options: . CONFIG_POWER_AVS: general knob for Adaptive Voltage Scaling support, . CONFIG_POWER_AVS_OMAP: AVS(Adaptive Voltage Scaling) support on OMAP containing the version 1 or version 2 of the SmartReflex IP, . CONFIG_POWER_AVS_OMAP_CLASS3: Class 3 implementation of Smartreflex. Signed-off-by: Jean Pihet Signed-off-by: J Keerthy Acked-by: Rafael J. Wysocki Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/Makefile | 4 +- arch/arm/mach-omap2/smartreflex.c | 1129 ------------------------------------- arch/arm/plat-omap/Kconfig | 22 +- drivers/power/Kconfig | 2 + drivers/power/Makefile | 1 + drivers/power/avs/Kconfig | 12 + drivers/power/avs/Makefile | 1 + drivers/power/avs/smartreflex.c | 1126 ++++++++++++++++++++++++++++++++++++ 8 files changed, 1147 insertions(+), 1150 deletions(-) delete mode 100644 arch/arm/mach-omap2/smartreflex.c create mode 100644 drivers/power/avs/Kconfig create mode 100644 drivers/power/avs/Makefile create mode 100644 drivers/power/avs/smartreflex.c (limited to 'arch') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 518444acc90f..f8ee10a06f46 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -70,8 +70,8 @@ obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o \ cpuidle44xx.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o -obj-$(CONFIG_POWER_AVS_OMAP) += sr_device.o smartreflex.o -obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) += smartreflex-class3.o +obj-$(CONFIG_POWER_AVS_OMAP) += sr_device.o +obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) += smartreflex-class3.o AFLAGS_sleep24xx.o :=-Wa,-march=armv6 AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec) diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c deleted file mode 100644 index 515041ccccb8..000000000000 --- a/arch/arm/mach-omap2/smartreflex.c +++ /dev/null @@ -1,1129 +0,0 @@ -/* - * OMAP SmartReflex Voltage Control - * - * Author: Thara Gopinath - * - * Copyright (C) 2010 Texas Instruments, Inc. - * Thara Gopinath - * - * Copyright (C) 2008 Nokia Corporation - * Kalle Jokiniemi - * - * Copyright (C) 2007 Texas Instruments, Inc. - * Lesly A M - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "pm.h" - -#define SMARTREFLEX_NAME_LEN 16 -#define NVALUE_NAME_LEN 40 -#define SR_DISABLE_TIMEOUT 200 - -/* sr_list contains all the instances of smartreflex module */ -static LIST_HEAD(sr_list); - -static struct omap_sr_class_data *sr_class; -static struct omap_sr_pmic_data *sr_pmic_data; -static struct dentry *sr_dbg_dir; - -static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value) -{ - __raw_writel(value, (sr->base + offset)); -} - -static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask, - u32 value) -{ - u32 reg_val; - - /* - * Smartreflex error config register is special as it contains - * certain status bits which if written a 1 into means a clear - * of those bits. So in order to make sure no accidental write of - * 1 happens to those status bits, do a clear of them in the read - * value. This mean this API doesn't rewrite values in these bits - * if they are currently set, but does allow the caller to write - * those bits. - */ - if (sr->ip_type == SR_TYPE_V1 && offset == ERRCONFIG_V1) - mask |= ERRCONFIG_STATUS_V1_MASK; - else if (sr->ip_type == SR_TYPE_V2 && offset == ERRCONFIG_V2) - mask |= ERRCONFIG_VPBOUNDINTST_V2; - - reg_val = __raw_readl(sr->base + offset); - reg_val &= ~mask; - - value &= mask; - - reg_val |= value; - - __raw_writel(reg_val, (sr->base + offset)); -} - -static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset) -{ - return __raw_readl(sr->base + offset); -} - -static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm) -{ - struct omap_sr *sr_info; - - if (!voltdm) { - pr_err("%s: Null voltage domain passed!\n", __func__); - return ERR_PTR(-EINVAL); - } - - list_for_each_entry(sr_info, &sr_list, node) { - if (voltdm == sr_info->voltdm) - return sr_info; - } - - return ERR_PTR(-ENODATA); -} - -static irqreturn_t sr_interrupt(int irq, void *data) -{ - struct omap_sr *sr_info = data; - u32 status = 0; - - switch (sr_info->ip_type) { - case SR_TYPE_V1: - /* Read the status bits */ - status = sr_read_reg(sr_info, ERRCONFIG_V1); - - /* Clear them by writing back */ - sr_write_reg(sr_info, ERRCONFIG_V1, status); - break; - case SR_TYPE_V2: - /* Read the status bits */ - status = sr_read_reg(sr_info, IRQSTATUS); - - /* Clear them by writing back */ - sr_write_reg(sr_info, IRQSTATUS, status); - break; - default: - dev_err(&sr_info->pdev->dev, "UNKNOWN IP type %d\n", - sr_info->ip_type); - return IRQ_NONE; - } - - if (sr_class->notify) - sr_class->notify(sr_info, status); - - return IRQ_HANDLED; -} - -static void sr_set_clk_length(struct omap_sr *sr) -{ - struct clk *sys_ck; - u32 sys_clk_speed; - - if (cpu_is_omap34xx()) - sys_ck = clk_get(NULL, "sys_ck"); - else - sys_ck = clk_get(NULL, "sys_clkin_ck"); - - if (IS_ERR(sys_ck)) { - dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n", - __func__); - return; - } - - sys_clk_speed = clk_get_rate(sys_ck); - clk_put(sys_ck); - - switch (sys_clk_speed) { - case 12000000: - sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK; - break; - case 13000000: - sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK; - break; - case 19200000: - sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK; - break; - case 26000000: - sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK; - break; - case 38400000: - sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK; - break; - default: - dev_err(&sr->pdev->dev, "%s: Invalid sysclk value: %d\n", - __func__, sys_clk_speed); - break; - } -} - -static void sr_set_regfields(struct omap_sr *sr) -{ - /* - * For time being these values are defined in smartreflex.h - * and populated during init. May be they can be moved to board - * file or pmic specific data structure. In that case these structure - * fields will have to be populated using the pdata or pmic structure. - */ - if (cpu_is_omap34xx() || cpu_is_omap44xx()) { - sr->err_weight = OMAP3430_SR_ERRWEIGHT; - sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT; - sr->accum_data = OMAP3430_SR_ACCUMDATA; - if (!(strcmp(sr->name, "smartreflex_mpu_iva"))) { - sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT; - sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT; - } else { - sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT; - sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT; - } - } -} - -static void sr_start_vddautocomp(struct omap_sr *sr) -{ - if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) { - dev_warn(&sr->pdev->dev, - "%s: smartreflex class driver not registered\n", - __func__); - return; - } - - if (!sr_class->enable(sr)) - sr->autocomp_active = true; -} - -static void sr_stop_vddautocomp(struct omap_sr *sr) -{ - if (!sr_class || !(sr_class->disable)) { - dev_warn(&sr->pdev->dev, - "%s: smartreflex class driver not registered\n", - __func__); - return; - } - - if (sr->autocomp_active) { - sr_class->disable(sr, 1); - sr->autocomp_active = false; - } -} - -/* - * This function handles the intializations which have to be done - * only when both sr device and class driver regiter has - * completed. This will be attempted to be called from both sr class - * driver register and sr device intializtion API's. Only one call - * will ultimately succeed. - * - * Currently this function registers interrupt handler for a particular SR - * if smartreflex class driver is already registered and has - * requested for interrupts and the SR interrupt line in present. - */ -static int sr_late_init(struct omap_sr *sr_info) -{ - struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data; - struct resource *mem; - int ret = 0; - - if (sr_class->notify && sr_class->notify_flags && sr_info->irq) { - ret = request_irq(sr_info->irq, sr_interrupt, - 0, sr_info->name, sr_info); - if (ret) - goto error; - disable_irq(sr_info->irq); - } - - if (pdata && pdata->enable_on_init) - sr_start_vddautocomp(sr_info); - - return ret; - -error: - iounmap(sr_info->base); - mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0); - release_mem_region(mem->start, resource_size(mem)); - list_del(&sr_info->node); - dev_err(&sr_info->pdev->dev, "%s: ERROR in registering" - "interrupt handler. Smartreflex will" - "not function as desired\n", __func__); - kfree(sr_info); - - return ret; -} - -static void sr_v1_disable(struct omap_sr *sr) -{ - int timeout = 0; - int errconf_val = ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST | - ERRCONFIG_MCUBOUNDINTST; - - /* Enable MCUDisableAcknowledge interrupt */ - sr_modify_reg(sr, ERRCONFIG_V1, - ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN); - - /* SRCONFIG - disable SR */ - sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0); - - /* Disable all other SR interrupts and clear the status as needed */ - if (sr_read_reg(sr, ERRCONFIG_V1) & ERRCONFIG_VPBOUNDINTST_V1) - errconf_val |= ERRCONFIG_VPBOUNDINTST_V1; - sr_modify_reg(sr, ERRCONFIG_V1, - (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN | - ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1), - errconf_val); - - /* - * Wait for SR to be disabled. - * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us. - */ - sr_test_cond_timeout((sr_read_reg(sr, ERRCONFIG_V1) & - ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT, - timeout); - - if (timeout >= SR_DISABLE_TIMEOUT) - dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n", - __func__); - - /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */ - sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN, - ERRCONFIG_MCUDISACKINTST); -} - -static void sr_v2_disable(struct omap_sr *sr) -{ - int timeout = 0; - - /* Enable MCUDisableAcknowledge interrupt */ - sr_write_reg(sr, IRQENABLE_SET, IRQENABLE_MCUDISABLEACKINT); - - /* SRCONFIG - disable SR */ - sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0); - - /* - * Disable all other SR interrupts and clear the status - * write to status register ONLY on need basis - only if status - * is set. - */ - if (sr_read_reg(sr, ERRCONFIG_V2) & ERRCONFIG_VPBOUNDINTST_V2) - sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2, - ERRCONFIG_VPBOUNDINTST_V2); - else - sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2, - 0x0); - sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT | - IRQENABLE_MCUVALIDINT | - IRQENABLE_MCUBOUNDSINT)); - sr_write_reg(sr, IRQSTATUS, (IRQSTATUS_MCUACCUMINT | - IRQSTATUS_MCVALIDINT | - IRQSTATUS_MCBOUNDSINT)); - - /* - * Wait for SR to be disabled. - * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us. - */ - sr_test_cond_timeout((sr_read_reg(sr, IRQSTATUS) & - IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT, - timeout); - - if (timeout >= SR_DISABLE_TIMEOUT) - dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n", - __func__); - - /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */ - sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT); - sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT); -} - -static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row( - struct omap_sr *sr, u32 efuse_offs) -{ - int i; - - if (!sr->nvalue_table) { - dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n", - __func__); - return NULL; - } - - for (i = 0; i < sr->nvalue_count; i++) { - if (sr->nvalue_table[i].efuse_offs == efuse_offs) - return &sr->nvalue_table[i]; - } - - return NULL; -} - -/* Public Functions */ - -/** - * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the - * error generator module. - * @voltdm: VDD pointer to which the SR module to be configured belongs to. - * - * This API is to be called from the smartreflex class driver to - * configure the error generator module inside the smartreflex module. - * SR settings if using the ERROR module inside Smartreflex. - * SR CLASS 3 by default uses only the ERROR module where as - * SR CLASS 2 can choose between ERROR module and MINMAXAVG - * module. Returns 0 on success and error value in case of failure. - */ -int sr_configure_errgen(struct voltagedomain *voltdm) -{ - u32 sr_config, sr_errconfig, errconfig_offs; - u32 vpboundint_en, vpboundint_st; - u32 senp_en = 0, senn_en = 0; - u8 senp_shift, senn_shift; - struct omap_sr *sr = _sr_lookup(voltdm); - - if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); - return PTR_ERR(sr); - } - - if (!sr->clk_length) - sr_set_clk_length(sr); - - senp_en = sr->senp_mod; - senn_en = sr->senn_mod; - - sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) | - SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN; - - switch (sr->ip_type) { - case SR_TYPE_V1: - sr_config |= SRCONFIG_DELAYCTRL; - senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT; - senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT; - errconfig_offs = ERRCONFIG_V1; - vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1; - vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1; - break; - case SR_TYPE_V2: - senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT; - senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT; - errconfig_offs = ERRCONFIG_V2; - vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2; - vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2; - break; - default: - dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" - "module without specifying the ip\n", __func__); - return -EINVAL; - } - - sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift)); - sr_write_reg(sr, SRCONFIG, sr_config); - sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) | - (sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) | - (sr->err_minlimit << ERRCONFIG_ERRMINLIMIT_SHIFT); - sr_modify_reg(sr, errconfig_offs, (SR_ERRWEIGHT_MASK | - SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK), - sr_errconfig); - - /* Enabling the interrupts if the ERROR module is used */ - sr_modify_reg(sr, errconfig_offs, (vpboundint_en | vpboundint_st), - vpboundint_en); - - return 0; -} - -/** - * sr_disable_errgen() - Disables SmartReflex AVS module's errgen component - * @voltdm: VDD pointer to which the SR module to be configured belongs to. - * - * This API is to be called from the smartreflex class driver to - * disable the error generator module inside the smartreflex module. - * - * Returns 0 on success and error value in case of failure. - */ -int sr_disable_errgen(struct voltagedomain *voltdm) -{ - u32 errconfig_offs; - u32 vpboundint_en, vpboundint_st; - struct omap_sr *sr = _sr_lookup(voltdm); - - if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); - return PTR_ERR(sr); - } - - switch (sr->ip_type) { - case SR_TYPE_V1: - errconfig_offs = ERRCONFIG_V1; - vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1; - vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1; - break; - case SR_TYPE_V2: - errconfig_offs = ERRCONFIG_V2; - vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2; - vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2; - break; - default: - dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" - "module without specifying the ip\n", __func__); - return -EINVAL; - } - - /* Disable the interrupts of ERROR module */ - sr_modify_reg(sr, errconfig_offs, vpboundint_en | vpboundint_st, 0); - - /* Disable the Sensor and errorgen */ - sr_modify_reg(sr, SRCONFIG, SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN, 0); - - return 0; -} - -/** - * sr_configure_minmax() - Configures the smrtreflex to perform AVS using the - * minmaxavg module. - * @voltdm: VDD pointer to which the SR module to be configured belongs to. - * - * This API is to be called from the smartreflex class driver to - * configure the minmaxavg module inside the smartreflex module. - * SR settings if using the ERROR module inside Smartreflex. - * SR CLASS 3 by default uses only the ERROR module where as - * SR CLASS 2 can choose between ERROR module and MINMAXAVG - * module. Returns 0 on success and error value in case of failure. - */ -int sr_configure_minmax(struct voltagedomain *voltdm) -{ - u32 sr_config, sr_avgwt; - u32 senp_en = 0, senn_en = 0; - u8 senp_shift, senn_shift; - struct omap_sr *sr = _sr_lookup(voltdm); - - if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); - return PTR_ERR(sr); - } - - if (!sr->clk_length) - sr_set_clk_length(sr); - - senp_en = sr->senp_mod; - senn_en = sr->senn_mod; - - sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) | - SRCONFIG_SENENABLE | - (sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT); - - switch (sr->ip_type) { - case SR_TYPE_V1: - sr_config |= SRCONFIG_DELAYCTRL; - senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT; - senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT; - break; - case SR_TYPE_V2: - senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT; - senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT; - break; - default: - dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" - "module without specifying the ip\n", __func__); - return -EINVAL; - } - - sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift)); - sr_write_reg(sr, SRCONFIG, sr_config); - sr_avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) | - (sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT); - sr_write_reg(sr, AVGWEIGHT, sr_avgwt); - - /* - * Enabling the interrupts if MINMAXAVG module is used. - * TODO: check if all the interrupts are mandatory - */ - switch (sr->ip_type) { - case SR_TYPE_V1: - sr_modify_reg(sr, ERRCONFIG_V1, - (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN | - ERRCONFIG_MCUBOUNDINTEN), - (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST | - ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST | - ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST)); - break; - case SR_TYPE_V2: - sr_write_reg(sr, IRQSTATUS, - IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT | - IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT); - sr_write_reg(sr, IRQENABLE_SET, - IRQENABLE_MCUACCUMINT | IRQENABLE_MCUVALIDINT | - IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT); - break; - default: - dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" - "module without specifying the ip\n", __func__); - return -EINVAL; - } - - return 0; -} - -/** - * sr_enable() - Enables the smartreflex module. - * @voltdm: VDD pointer to which the SR module to be configured belongs to. - * @volt: The voltage at which the Voltage domain associated with - * the smartreflex module is operating at. - * This is required only to program the correct Ntarget value. - * - * This API is to be called from the smartreflex class driver to - * enable a smartreflex module. Returns 0 on success. Returns error - * value if the voltage passed is wrong or if ntarget value is wrong. - */ -int sr_enable(struct voltagedomain *voltdm, unsigned long volt) -{ - struct omap_volt_data *volt_data; - struct omap_sr *sr = _sr_lookup(voltdm); - struct omap_sr_nvalue_table *nvalue_row; - int ret; - - if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); - return PTR_ERR(sr); - } - - volt_data = omap_voltage_get_voltdata(sr->voltdm, volt); - - if (IS_ERR(volt_data)) { - dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table" - "for nominal voltage %ld\n", __func__, volt); - return PTR_ERR(volt_data); - } - - nvalue_row = sr_retrieve_nvalue_row(sr, volt_data->sr_efuse_offs); - - if (!nvalue_row) { - dev_warn(&sr->pdev->dev, "%s: failure getting SR data for this voltage %ld\n", - __func__, volt); - return -ENODATA; - } - - /* errminlimit is opp dependent and hence linked to voltage */ - sr->err_minlimit = nvalue_row->errminlimit; - - pm_runtime_get_sync(&sr->pdev->dev); - - /* Check if SR is already enabled. If yes do nothing */ - if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) - return 0; - - /* Configure SR */ - ret = sr_class->configure(sr); - if (ret) - return ret; - - sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue); - - /* SRCONFIG - enable SR */ - sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE); - return 0; -} - -/** - * sr_disable() - Disables the smartreflex module. - * @voltdm: VDD pointer to which the SR module to be configured belongs to. - * - * This API is to be called from the smartreflex class driver to - * disable a smartreflex module. - */ -void sr_disable(struct voltagedomain *voltdm) -{ - struct omap_sr *sr = _sr_lookup(voltdm); - - if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); - return; - } - - /* Check if SR clocks are already disabled. If yes do nothing */ - if (pm_runtime_suspended(&sr->pdev->dev)) - return; - - /* - * Disable SR if only it is indeed enabled. Else just - * disable the clocks. - */ - if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) { - switch (sr->ip_type) { - case SR_TYPE_V1: - sr_v1_disable(sr); - break; - case SR_TYPE_V2: - sr_v2_disable(sr); - break; - default: - dev_err(&sr->pdev->dev, "UNKNOWN IP type %d\n", - sr->ip_type); - } - } - - pm_runtime_put_sync_suspend(&sr->pdev->dev); -} - -/** - * sr_register_class() - API to register a smartreflex class parameters. - * @class_data: The structure containing various sr class specific data. - * - * This API is to be called by the smartreflex class driver to register itself - * with the smartreflex driver during init. Returns 0 on success else the - * error value. - */ -int sr_register_class(struct omap_sr_class_data *class_data) -{ - struct omap_sr *sr_info; - - if (!class_data) { - pr_warning("%s:, Smartreflex class data passed is NULL\n", - __func__); - return -EINVAL; - } - - if (sr_class) { - pr_warning("%s: Smartreflex class driver already registered\n", - __func__); - return -EBUSY; - } - - sr_class = class_data; - - /* - * Call into late init to do intializations that require - * both sr driver and sr class driver to be initiallized. - */ - list_for_each_entry(sr_info, &sr_list, node) - sr_late_init(sr_info); - - return 0; -} - -/** - * omap_sr_enable() - API to enable SR clocks and to call into the - * registered smartreflex class enable API. - * @voltdm: VDD pointer to which the SR module to be configured belongs to. - * - * This API is to be called from the kernel in order to enable - * a particular smartreflex module. This API will do the initial - * configurations to turn on the smartreflex module and in turn call - * into the registered smartreflex class enable API. - */ -void omap_sr_enable(struct voltagedomain *voltdm) -{ - struct omap_sr *sr = _sr_lookup(voltdm); - - if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); - return; - } - - if (!sr->autocomp_active) - return; - - if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) { - dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not" - "registered\n", __func__); - return; - } - - sr_class->enable(sr); -} - -/** - * omap_sr_disable() - API to disable SR without resetting the voltage - * processor voltage - * @voltdm: VDD pointer to which the SR module to be configured belongs to. - * - * This API is to be called from the kernel in order to disable - * a particular smartreflex module. This API will in turn call - * into the registered smartreflex class disable API. This API will tell - * the smartreflex class disable not to reset the VP voltage after - * disabling smartreflex. - */ -void omap_sr_disable(struct voltagedomain *voltdm) -{ - struct omap_sr *sr = _sr_lookup(voltdm); - - if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); - return; - } - - if (!sr->autocomp_active) - return; - - if (!sr_class || !(sr_class->disable)) { - dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not" - "registered\n", __func__); - return; - } - - sr_class->disable(sr, 0); -} - -/** - * omap_sr_disable_reset_volt() - API to disable SR and reset the - * voltage processor voltage - * @voltdm: VDD pointer to which the SR module to be configured belongs to. - * - * This API is to be called from the kernel in order to disable - * a particular smartreflex module. This API will in turn call - * into the registered smartreflex class disable API. This API will tell - * the smartreflex class disable to reset the VP voltage after - * disabling smartreflex. - */ -void omap_sr_disable_reset_volt(struct voltagedomain *voltdm) -{ - struct omap_sr *sr = _sr_lookup(voltdm); - - if (IS_ERR(sr)) { - pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); - return; - } - - if (!sr->autocomp_active) - return; - - if (!sr_class || !(sr_class->disable)) { - dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not" - "registered\n", __func__); - return; - } - - sr_class->disable(sr, 1); -} - -/** - * omap_sr_register_pmic() - API to register pmic specific info. - * @pmic_data: The structure containing pmic specific data. - * - * This API is to be called from the PMIC specific code to register with - * smartreflex driver pmic specific info. Currently the only info required - * is the smartreflex init on the PMIC side. - */ -void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data) -{ - if (!pmic_data) { - pr_warning("%s: Trying to register NULL PMIC data structure" - "with smartreflex\n", __func__); - return; - } - - sr_pmic_data = pmic_data; -} - -/* PM Debug FS entries to enable and disable smartreflex. */ -static int omap_sr_autocomp_show(void *data, u64 *val) -{ - struct omap_sr *sr_info = data; - - if (!sr_info) { - pr_warning("%s: omap_sr struct not found\n", __func__); - return -EINVAL; - } - - *val = sr_info->autocomp_active; - - return 0; -} - -static int omap_sr_autocomp_store(void *data, u64 val) -{ - struct omap_sr *sr_info = data; - - if (!sr_info) { - pr_warning("%s: omap_sr struct not found\n", __func__); - return -EINVAL; - } - - /* Sanity check */ - if (val > 1) { - pr_warning("%s: Invalid argument %lld\n", __func__, val); - return -EINVAL; - } - - /* control enable/disable only if there is a delta in value */ - if (sr_info->autocomp_active != val) { - if (!val) - sr_stop_vddautocomp(sr_info); - else - sr_start_vddautocomp(sr_info); - } - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show, - omap_sr_autocomp_store, "%llu\n"); - -static int __init omap_sr_probe(struct platform_device *pdev) -{ - struct omap_sr *sr_info; - struct omap_sr_data *pdata = pdev->dev.platform_data; - struct resource *mem, *irq; - struct dentry *nvalue_dir; - int i, ret = 0; - - sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL); - if (!sr_info) { - dev_err(&pdev->dev, "%s: unable to allocate sr_info\n", - __func__); - return -ENOMEM; - } - - platform_set_drvdata(pdev, sr_info); - - if (!pdata) { - dev_err(&pdev->dev, "%s: platform data missing\n", __func__); - ret = -EINVAL; - goto err_free_devinfo; - } - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "%s: no mem resource\n", __func__); - ret = -ENODEV; - goto err_free_devinfo; - } - - mem = request_mem_region(mem->start, resource_size(mem), - dev_name(&pdev->dev)); - if (!mem) { - dev_err(&pdev->dev, "%s: no mem region\n", __func__); - ret = -EBUSY; - goto err_free_devinfo; - } - - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - - pm_runtime_enable(&pdev->dev); - pm_runtime_irq_safe(&pdev->dev); - - sr_info->name = kasprintf(GFP_KERNEL, "%s", pdata->name); - if (!sr_info->name) { - dev_err(&pdev->dev, "%s: Unable to alloc SR instance name\n", - __func__); - ret = -ENOMEM; - goto err_release_region; - } - - sr_info->pdev = pdev; - sr_info->srid = pdev->id; - sr_info->voltdm = pdata->voltdm; - sr_info->nvalue_table = pdata->nvalue_table; - sr_info->nvalue_count = pdata->nvalue_count; - sr_info->senn_mod = pdata->senn_mod; - sr_info->senp_mod = pdata->senp_mod; - sr_info->autocomp_active = false; - sr_info->ip_type = pdata->ip_type; - sr_info->base = ioremap(mem->start, resource_size(mem)); - if (!sr_info->base) { - dev_err(&pdev->dev, "%s: ioremap fail\n", __func__); - ret = -ENOMEM; - goto err_release_region; - } - - if (irq) - sr_info->irq = irq->start; - - sr_set_clk_length(sr_info); - sr_set_regfields(sr_info); - - list_add(&sr_info->node, &sr_list); - - /* - * Call into late init to do intializations that require - * both sr driver and sr class driver to be initiallized. - */ - if (sr_class) { - ret = sr_late_init(sr_info); - if (ret) { - pr_warning("%s: Error in SR late init\n", __func__); - goto err_iounmap; - } - } - - dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__); - if (!sr_dbg_dir) { - sr_dbg_dir = debugfs_create_dir("smartreflex", NULL); - if (IS_ERR_OR_NULL(sr_dbg_dir)) { - ret = PTR_ERR(sr_dbg_dir); - pr_err("%s:sr debugfs dir creation failed(%d)\n", - __func__, ret); - goto err_iounmap; - } - } - - sr_info->dbg_dir = debugfs_create_dir(sr_info->name, sr_dbg_dir); - if (IS_ERR_OR_NULL(sr_info->dbg_dir)) { - dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n", - __func__); - ret = PTR_ERR(sr_info->dbg_dir); - goto err_free_name; - } - - (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, - sr_info->dbg_dir, (void *)sr_info, &pm_sr_fops); - (void) debugfs_create_x32("errweight", S_IRUGO, sr_info->dbg_dir, - &sr_info->err_weight); - (void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir, - &sr_info->err_maxlimit); - - nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir); - if (IS_ERR_OR_NULL(nvalue_dir)) { - dev_err(&pdev->dev, "%s: Unable to create debugfs directory" - "for n-values\n", __func__); - ret = PTR_ERR(nvalue_dir); - goto err_debugfs; - } - - if (sr_info->nvalue_count == 0 || !sr_info->nvalue_table) { - dev_warn(&pdev->dev, "%s: %s: No Voltage table for the corresponding vdd. Cannot create debugfs entries for n-values\n", - __func__, sr_info->name); - - ret = -ENODATA; - goto err_debugfs; - } - - for (i = 0; i < sr_info->nvalue_count; i++) { - char name[NVALUE_NAME_LEN + 1]; - - snprintf(name, sizeof(name), "volt_%lu", - sr_info->nvalue_table[i].volt_nominal); - (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir, - &(sr_info->nvalue_table[i].nvalue)); - snprintf(name, sizeof(name), "errminlimit_%lu", - sr_info->nvalue_table[i].volt_nominal); - (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir, - &(sr_info->nvalue_table[i].errminlimit)); - - } - - return ret; - -err_debugfs: - debugfs_remove_recursive(sr_info->dbg_dir); -err_free_name: - kfree(sr_info->name); -err_iounmap: - list_del(&sr_info->node); - iounmap(sr_info->base); -err_release_region: - release_mem_region(mem->start, resource_size(mem)); -err_free_devinfo: - kfree(sr_info); - - return ret; -} - -static int __devexit omap_sr_remove(struct platform_device *pdev) -{ - struct omap_sr_data *pdata = pdev->dev.platform_data; - struct omap_sr *sr_info; - struct resource *mem; - - if (!pdata) { - dev_err(&pdev->dev, "%s: platform data missing\n", __func__); - return -EINVAL; - } - - sr_info = _sr_lookup(pdata->voltdm); - if (IS_ERR(sr_info)) { - dev_warn(&pdev->dev, "%s: omap_sr struct not found\n", - __func__); - return PTR_ERR(sr_info); - } - - if (sr_info->autocomp_active) - sr_stop_vddautocomp(sr_info); - if (sr_info->dbg_dir) - debugfs_remove_recursive(sr_info->dbg_dir); - - list_del(&sr_info->node); - iounmap(sr_info->base); - kfree(sr_info->name); - kfree(sr_info); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(mem->start, resource_size(mem)); - - return 0; -} - -static void __devexit omap_sr_shutdown(struct platform_device *pdev) -{ - struct omap_sr_data *pdata = pdev->dev.platform_data; - struct omap_sr *sr_info; - - if (!pdata) { - dev_err(&pdev->dev, "%s: platform data missing\n", __func__); - return; - } - - sr_info = _sr_lookup(pdata->voltdm); - if (IS_ERR(sr_info)) { - dev_warn(&pdev->dev, "%s: omap_sr struct not found\n", - __func__); - return; - } - - if (sr_info->autocomp_active) - sr_stop_vddautocomp(sr_info); - - return; -} - -static struct platform_driver smartreflex_driver = { - .remove = __devexit_p(omap_sr_remove), - .shutdown = __devexit_p(omap_sr_shutdown), - .driver = { - .name = "smartreflex", - }, -}; - -static int __init sr_init(void) -{ - int ret = 0; - - /* - * sr_init is a late init. If by then a pmic specific API is not - * registered either there is no need for anything to be done on - * the PMIC side or somebody has forgotten to register a PMIC - * handler. Warn for the second condition. - */ - if (sr_pmic_data && sr_pmic_data->sr_pmic_init) - sr_pmic_data->sr_pmic_init(); - else - pr_warning("%s: No PMIC hook to init smartreflex\n", __func__); - - ret = platform_driver_probe(&smartreflex_driver, omap_sr_probe); - if (ret) { - pr_err("%s: platform driver register failed for SR\n", - __func__); - return ret; - } - - return 0; -} -late_initcall(sr_init); - -static void __exit sr_exit(void) -{ - platform_driver_unregister(&smartreflex_driver); -} -module_exit(sr_exit); - -MODULE_DESCRIPTION("OMAP Smartreflex Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRIVER_NAME); -MODULE_AUTHOR("Texas Instruments Inc"); diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index bba384dfbcf6..816dec062f3c 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -45,26 +45,12 @@ config OMAP_DEBUG_LEDS depends on OMAP_DEBUG_DEVICES default y if LEDS_CLASS -menuconfig POWER_AVS - tristate "Adaptive Voltage Scaling class support" - help - AVS(Adaptive Voltage Scaling) is a power management technique which - finely controls the operating voltage of a device in order to optimize - (i.e. reduce) its power consumption. - At a given operating point the voltage is adapted depending on - static factors (chip manufacturing process) and dynamic factors - (temperature depending performance). - AVS is also called SmartReflex on OMAP devices. - - Say Y here to enable Adaptive Voltage Scaling class support. - -if POWER_AVS - config POWER_AVS_OMAP bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2" - depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM + depends on POWER_AVS && (ARCH_OMAP3 || ARCH_OMAP4) && PM help - Say Y to enable AVS support on OMAP containing the version 1 or + Say Y to enable AVS(Adaptive Voltage Scaling) + support on OMAP containing the version 1 or version 2 of the SmartReflex IP. V1 is the 65nm version used in OMAP3430. V2 is the update for the 45nm version of the IP used in OMAP3630 @@ -89,8 +75,6 @@ config POWER_AVS_OMAP_CLASS3 Class 3 implementation of Smartreflex employs continuous hardware voltage calibration. -endif # POWER_AVS - config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 99dc29f2f2f2..d416773771ef 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -308,3 +308,5 @@ config AB8500_BATTERY_THERM_ON_BATCTRL Say Y to enable battery temperature measurements using thermistor connected on BATCTRL ADC. endif # POWER_SUPPLY + +source "drivers/power/avs/Kconfig" diff --git a/drivers/power/Makefile b/drivers/power/Makefile index b6b243416c0e..ee58afb1e71f 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -43,4 +43,5 @@ obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o +obj-$(CONFIG_POWER_AVS) += avs/ obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o diff --git a/drivers/power/avs/Kconfig b/drivers/power/avs/Kconfig new file mode 100644 index 000000000000..18493f7a8f6f --- /dev/null +++ b/drivers/power/avs/Kconfig @@ -0,0 +1,12 @@ +menuconfig POWER_AVS + tristate "Adaptive Voltage Scaling class support" + help + AVS is a power management technique which finely controls the + operating voltage of a device in order to optimize (i.e. reduce) + its power consumption. + At a given operating point the voltage is adapted depending on + static factors (chip manufacturing process) and dynamic factors + (temperature depending performance). + AVS is also called SmartReflex on OMAP devices. + + Say Y here to enable Adaptive Voltage Scaling class support. diff --git a/drivers/power/avs/Makefile b/drivers/power/avs/Makefile new file mode 100644 index 000000000000..0843386a6c19 --- /dev/null +++ b/drivers/power/avs/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_POWER_AVS_OMAP) += smartreflex.o diff --git a/drivers/power/avs/smartreflex.c b/drivers/power/avs/smartreflex.c new file mode 100644 index 000000000000..44efc6e202af --- /dev/null +++ b/drivers/power/avs/smartreflex.c @@ -0,0 +1,1126 @@ +/* + * OMAP SmartReflex Voltage Control + * + * Author: Thara Gopinath + * + * Copyright (C) 2012 Texas Instruments, Inc. + * Thara Gopinath + * + * Copyright (C) 2008 Nokia Corporation + * Kalle Jokiniemi + * + * Copyright (C) 2007 Texas Instruments, Inc. + * Lesly A M + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SMARTREFLEX_NAME_LEN 16 +#define NVALUE_NAME_LEN 40 +#define SR_DISABLE_TIMEOUT 200 + +/* sr_list contains all the instances of smartreflex module */ +static LIST_HEAD(sr_list); + +static struct omap_sr_class_data *sr_class; +static struct omap_sr_pmic_data *sr_pmic_data; +static struct dentry *sr_dbg_dir; + +static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value) +{ + __raw_writel(value, (sr->base + offset)); +} + +static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask, + u32 value) +{ + u32 reg_val; + + /* + * Smartreflex error config register is special as it contains + * certain status bits which if written a 1 into means a clear + * of those bits. So in order to make sure no accidental write of + * 1 happens to those status bits, do a clear of them in the read + * value. This mean this API doesn't rewrite values in these bits + * if they are currently set, but does allow the caller to write + * those bits. + */ + if (sr->ip_type == SR_TYPE_V1 && offset == ERRCONFIG_V1) + mask |= ERRCONFIG_STATUS_V1_MASK; + else if (sr->ip_type == SR_TYPE_V2 && offset == ERRCONFIG_V2) + mask |= ERRCONFIG_VPBOUNDINTST_V2; + + reg_val = __raw_readl(sr->base + offset); + reg_val &= ~mask; + + value &= mask; + + reg_val |= value; + + __raw_writel(reg_val, (sr->base + offset)); +} + +static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset) +{ + return __raw_readl(sr->base + offset); +} + +static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm) +{ + struct omap_sr *sr_info; + + if (!voltdm) { + pr_err("%s: Null voltage domain passed!\n", __func__); + return ERR_PTR(-EINVAL); + } + + list_for_each_entry(sr_info, &sr_list, node) { + if (voltdm == sr_info->voltdm) + return sr_info; + } + + return ERR_PTR(-ENODATA); +} + +static irqreturn_t sr_interrupt(int irq, void *data) +{ + struct omap_sr *sr_info = data; + u32 status = 0; + + switch (sr_info->ip_type) { + case SR_TYPE_V1: + /* Read the status bits */ + status = sr_read_reg(sr_info, ERRCONFIG_V1); + + /* Clear them by writing back */ + sr_write_reg(sr_info, ERRCONFIG_V1, status); + break; + case SR_TYPE_V2: + /* Read the status bits */ + status = sr_read_reg(sr_info, IRQSTATUS); + + /* Clear them by writing back */ + sr_write_reg(sr_info, IRQSTATUS, status); + break; + default: + dev_err(&sr_info->pdev->dev, "UNKNOWN IP type %d\n", + sr_info->ip_type); + return IRQ_NONE; + } + + if (sr_class->notify) + sr_class->notify(sr_info, status); + + return IRQ_HANDLED; +} + +static void sr_set_clk_length(struct omap_sr *sr) +{ + struct clk *sys_ck; + u32 sys_clk_speed; + + if (cpu_is_omap34xx()) + sys_ck = clk_get(NULL, "sys_ck"); + else + sys_ck = clk_get(NULL, "sys_clkin_ck"); + + if (IS_ERR(sys_ck)) { + dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n", + __func__); + return; + } + + sys_clk_speed = clk_get_rate(sys_ck); + clk_put(sys_ck); + + switch (sys_clk_speed) { + case 12000000: + sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK; + break; + case 13000000: + sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK; + break; + case 19200000: + sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK; + break; + case 26000000: + sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK; + break; + case 38400000: + sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK; + break; + default: + dev_err(&sr->pdev->dev, "%s: Invalid sysclk value: %d\n", + __func__, sys_clk_speed); + break; + } +} + +static void sr_set_regfields(struct omap_sr *sr) +{ + /* + * For time being these values are defined in smartreflex.h + * and populated during init. May be they can be moved to board + * file or pmic specific data structure. In that case these structure + * fields will have to be populated using the pdata or pmic structure. + */ + if (cpu_is_omap34xx() || cpu_is_omap44xx()) { + sr->err_weight = OMAP3430_SR_ERRWEIGHT; + sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT; + sr->accum_data = OMAP3430_SR_ACCUMDATA; + if (!(strcmp(sr->name, "smartreflex_mpu_iva"))) { + sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT; + sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT; + } else { + sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT; + sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT; + } + } +} + +static void sr_start_vddautocomp(struct omap_sr *sr) +{ + if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) { + dev_warn(&sr->pdev->dev, + "%s: smartreflex class driver not registered\n", + __func__); + return; + } + + if (!sr_class->enable(sr)) + sr->autocomp_active = true; +} + +static void sr_stop_vddautocomp(struct omap_sr *sr) +{ + if (!sr_class || !(sr_class->disable)) { + dev_warn(&sr->pdev->dev, + "%s: smartreflex class driver not registered\n", + __func__); + return; + } + + if (sr->autocomp_active) { + sr_class->disable(sr, 1); + sr->autocomp_active = false; + } +} + +/* + * This function handles the intializations which have to be done + * only when both sr device and class driver regiter has + * completed. This will be attempted to be called from both sr class + * driver register and sr device intializtion API's. Only one call + * will ultimately succeed. + * + * Currently this function registers interrupt handler for a particular SR + * if smartreflex class driver is already registered and has + * requested for interrupts and the SR interrupt line in present. + */ +static int sr_late_init(struct omap_sr *sr_info) +{ + struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data; + struct resource *mem; + int ret = 0; + + if (sr_class->notify && sr_class->notify_flags && sr_info->irq) { + ret = request_irq(sr_info->irq, sr_interrupt, + 0, sr_info->name, sr_info); + if (ret) + goto error; + disable_irq(sr_info->irq); + } + + if (pdata && pdata->enable_on_init) + sr_start_vddautocomp(sr_info); + + return ret; + +error: + iounmap(sr_info->base); + mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0); + release_mem_region(mem->start, resource_size(mem)); + list_del(&sr_info->node); + dev_err(&sr_info->pdev->dev, "%s: ERROR in registering" + "interrupt handler. Smartreflex will" + "not function as desired\n", __func__); + kfree(sr_info); + + return ret; +} + +static void sr_v1_disable(struct omap_sr *sr) +{ + int timeout = 0; + int errconf_val = ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST | + ERRCONFIG_MCUBOUNDINTST; + + /* Enable MCUDisableAcknowledge interrupt */ + sr_modify_reg(sr, ERRCONFIG_V1, + ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN); + + /* SRCONFIG - disable SR */ + sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0); + + /* Disable all other SR interrupts and clear the status as needed */ + if (sr_read_reg(sr, ERRCONFIG_V1) & ERRCONFIG_VPBOUNDINTST_V1) + errconf_val |= ERRCONFIG_VPBOUNDINTST_V1; + sr_modify_reg(sr, ERRCONFIG_V1, + (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN | + ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1), + errconf_val); + + /* + * Wait for SR to be disabled. + * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us. + */ + sr_test_cond_timeout((sr_read_reg(sr, ERRCONFIG_V1) & + ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT, + timeout); + + if (timeout >= SR_DISABLE_TIMEOUT) + dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n", + __func__); + + /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */ + sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN, + ERRCONFIG_MCUDISACKINTST); +} + +static void sr_v2_disable(struct omap_sr *sr) +{ + int timeout = 0; + + /* Enable MCUDisableAcknowledge interrupt */ + sr_write_reg(sr, IRQENABLE_SET, IRQENABLE_MCUDISABLEACKINT); + + /* SRCONFIG - disable SR */ + sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0); + + /* + * Disable all other SR interrupts and clear the status + * write to status register ONLY on need basis - only if status + * is set. + */ + if (sr_read_reg(sr, ERRCONFIG_V2) & ERRCONFIG_VPBOUNDINTST_V2) + sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2, + ERRCONFIG_VPBOUNDINTST_V2); + else + sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2, + 0x0); + sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT | + IRQENABLE_MCUVALIDINT | + IRQENABLE_MCUBOUNDSINT)); + sr_write_reg(sr, IRQSTATUS, (IRQSTATUS_MCUACCUMINT | + IRQSTATUS_MCVALIDINT | + IRQSTATUS_MCBOUNDSINT)); + + /* + * Wait for SR to be disabled. + * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us. + */ + sr_test_cond_timeout((sr_read_reg(sr, IRQSTATUS) & + IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT, + timeout); + + if (timeout >= SR_DISABLE_TIMEOUT) + dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n", + __func__); + + /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */ + sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT); + sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT); +} + +static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row( + struct omap_sr *sr, u32 efuse_offs) +{ + int i; + + if (!sr->nvalue_table) { + dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n", + __func__); + return NULL; + } + + for (i = 0; i < sr->nvalue_count; i++) { + if (sr->nvalue_table[i].efuse_offs == efuse_offs) + return &sr->nvalue_table[i]; + } + + return NULL; +} + +/* Public Functions */ + +/** + * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the + * error generator module. + * @voltdm: VDD pointer to which the SR module to be configured belongs to. + * + * This API is to be called from the smartreflex class driver to + * configure the error generator module inside the smartreflex module. + * SR settings if using the ERROR module inside Smartreflex. + * SR CLASS 3 by default uses only the ERROR module where as + * SR CLASS 2 can choose between ERROR module and MINMAXAVG + * module. Returns 0 on success and error value in case of failure. + */ +int sr_configure_errgen(struct voltagedomain *voltdm) +{ + u32 sr_config, sr_errconfig, errconfig_offs; + u32 vpboundint_en, vpboundint_st; + u32 senp_en = 0, senn_en = 0; + u8 senp_shift, senn_shift; + struct omap_sr *sr = _sr_lookup(voltdm); + + if (IS_ERR(sr)) { + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); + return PTR_ERR(sr); + } + + if (!sr->clk_length) + sr_set_clk_length(sr); + + senp_en = sr->senp_mod; + senn_en = sr->senn_mod; + + sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) | + SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN; + + switch (sr->ip_type) { + case SR_TYPE_V1: + sr_config |= SRCONFIG_DELAYCTRL; + senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT; + senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT; + errconfig_offs = ERRCONFIG_V1; + vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1; + vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1; + break; + case SR_TYPE_V2: + senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT; + senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT; + errconfig_offs = ERRCONFIG_V2; + vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2; + vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2; + break; + default: + dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" + "module without specifying the ip\n", __func__); + return -EINVAL; + } + + sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift)); + sr_write_reg(sr, SRCONFIG, sr_config); + sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) | + (sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) | + (sr->err_minlimit << ERRCONFIG_ERRMINLIMIT_SHIFT); + sr_modify_reg(sr, errconfig_offs, (SR_ERRWEIGHT_MASK | + SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK), + sr_errconfig); + + /* Enabling the interrupts if the ERROR module is used */ + sr_modify_reg(sr, errconfig_offs, (vpboundint_en | vpboundint_st), + vpboundint_en); + + return 0; +} + +/** + * sr_disable_errgen() - Disables SmartReflex AVS module's errgen component + * @voltdm: VDD pointer to which the SR module to be configured belongs to. + * + * This API is to be called from the smartreflex class driver to + * disable the error generator module inside the smartreflex module. + * + * Returns 0 on success and error value in case of failure. + */ +int sr_disable_errgen(struct voltagedomain *voltdm) +{ + u32 errconfig_offs; + u32 vpboundint_en, vpboundint_st; + struct omap_sr *sr = _sr_lookup(voltdm); + + if (IS_ERR(sr)) { + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); + return PTR_ERR(sr); + } + + switch (sr->ip_type) { + case SR_TYPE_V1: + errconfig_offs = ERRCONFIG_V1; + vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1; + vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1; + break; + case SR_TYPE_V2: + errconfig_offs = ERRCONFIG_V2; + vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2; + vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2; + break; + default: + dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" + "module without specifying the ip\n", __func__); + return -EINVAL; + } + + /* Disable the interrupts of ERROR module */ + sr_modify_reg(sr, errconfig_offs, vpboundint_en | vpboundint_st, 0); + + /* Disable the Sensor and errorgen */ + sr_modify_reg(sr, SRCONFIG, SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN, 0); + + return 0; +} + +/** + * sr_configure_minmax() - Configures the smrtreflex to perform AVS using the + * minmaxavg module. + * @voltdm: VDD pointer to which the SR module to be configured belongs to. + * + * This API is to be called from the smartreflex class driver to + * configure the minmaxavg module inside the smartreflex module. + * SR settings if using the ERROR module inside Smartreflex. + * SR CLASS 3 by default uses only the ERROR module where as + * SR CLASS 2 can choose between ERROR module and MINMAXAVG + * module. Returns 0 on success and error value in case of failure. + */ +int sr_configure_minmax(struct voltagedomain *voltdm) +{ + u32 sr_config, sr_avgwt; + u32 senp_en = 0, senn_en = 0; + u8 senp_shift, senn_shift; + struct omap_sr *sr = _sr_lookup(voltdm); + + if (IS_ERR(sr)) { + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); + return PTR_ERR(sr); + } + + if (!sr->clk_length) + sr_set_clk_length(sr); + + senp_en = sr->senp_mod; + senn_en = sr->senn_mod; + + sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) | + SRCONFIG_SENENABLE | + (sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT); + + switch (sr->ip_type) { + case SR_TYPE_V1: + sr_config |= SRCONFIG_DELAYCTRL; + senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT; + senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT; + break; + case SR_TYPE_V2: + senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT; + senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT; + break; + default: + dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" + "module without specifying the ip\n", __func__); + return -EINVAL; + } + + sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift)); + sr_write_reg(sr, SRCONFIG, sr_config); + sr_avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) | + (sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT); + sr_write_reg(sr, AVGWEIGHT, sr_avgwt); + + /* + * Enabling the interrupts if MINMAXAVG module is used. + * TODO: check if all the interrupts are mandatory + */ + switch (sr->ip_type) { + case SR_TYPE_V1: + sr_modify_reg(sr, ERRCONFIG_V1, + (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN | + ERRCONFIG_MCUBOUNDINTEN), + (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST | + ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST | + ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST)); + break; + case SR_TYPE_V2: + sr_write_reg(sr, IRQSTATUS, + IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT | + IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT); + sr_write_reg(sr, IRQENABLE_SET, + IRQENABLE_MCUACCUMINT | IRQENABLE_MCUVALIDINT | + IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT); + break; + default: + dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" + "module without specifying the ip\n", __func__); + return -EINVAL; + } + + return 0; +} + +/** + * sr_enable() - Enables the smartreflex module. + * @voltdm: VDD pointer to which the SR module to be configured belongs to. + * @volt: The voltage at which the Voltage domain associated with + * the smartreflex module is operating at. + * This is required only to program the correct Ntarget value. + * + * This API is to be called from the smartreflex class driver to + * enable a smartreflex module. Returns 0 on success. Returns error + * value if the voltage passed is wrong or if ntarget value is wrong. + */ +int sr_enable(struct voltagedomain *voltdm, unsigned long volt) +{ + struct omap_volt_data *volt_data; + struct omap_sr *sr = _sr_lookup(voltdm); + struct omap_sr_nvalue_table *nvalue_row; + int ret; + + if (IS_ERR(sr)) { + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); + return PTR_ERR(sr); + } + + volt_data = omap_voltage_get_voltdata(sr->voltdm, volt); + + if (IS_ERR(volt_data)) { + dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table" + "for nominal voltage %ld\n", __func__, volt); + return PTR_ERR(volt_data); + } + + nvalue_row = sr_retrieve_nvalue_row(sr, volt_data->sr_efuse_offs); + + if (!nvalue_row) { + dev_warn(&sr->pdev->dev, "%s: failure getting SR data for this voltage %ld\n", + __func__, volt); + return -ENODATA; + } + + /* errminlimit is opp dependent and hence linked to voltage */ + sr->err_minlimit = nvalue_row->errminlimit; + + pm_runtime_get_sync(&sr->pdev->dev); + + /* Check if SR is already enabled. If yes do nothing */ + if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) + return 0; + + /* Configure SR */ + ret = sr_class->configure(sr); + if (ret) + return ret; + + sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue); + + /* SRCONFIG - enable SR */ + sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE); + return 0; +} + +/** + * sr_disable() - Disables the smartreflex module. + * @voltdm: VDD pointer to which the SR module to be configured belongs to. + * + * This API is to be called from the smartreflex class driver to + * disable a smartreflex module. + */ +void sr_disable(struct voltagedomain *voltdm) +{ + struct omap_sr *sr = _sr_lookup(voltdm); + + if (IS_ERR(sr)) { + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); + return; + } + + /* Check if SR clocks are already disabled. If yes do nothing */ + if (pm_runtime_suspended(&sr->pdev->dev)) + return; + + /* + * Disable SR if only it is indeed enabled. Else just + * disable the clocks. + */ + if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) { + switch (sr->ip_type) { + case SR_TYPE_V1: + sr_v1_disable(sr); + break; + case SR_TYPE_V2: + sr_v2_disable(sr); + break; + default: + dev_err(&sr->pdev->dev, "UNKNOWN IP type %d\n", + sr->ip_type); + } + } + + pm_runtime_put_sync_suspend(&sr->pdev->dev); +} + +/** + * sr_register_class() - API to register a smartreflex class parameters. + * @class_data: The structure containing various sr class specific data. + * + * This API is to be called by the smartreflex class driver to register itself + * with the smartreflex driver during init. Returns 0 on success else the + * error value. + */ +int sr_register_class(struct omap_sr_class_data *class_data) +{ + struct omap_sr *sr_info; + + if (!class_data) { + pr_warning("%s:, Smartreflex class data passed is NULL\n", + __func__); + return -EINVAL; + } + + if (sr_class) { + pr_warning("%s: Smartreflex class driver already registered\n", + __func__); + return -EBUSY; + } + + sr_class = class_data; + + /* + * Call into late init to do intializations that require + * both sr driver and sr class driver to be initiallized. + */ + list_for_each_entry(sr_info, &sr_list, node) + sr_late_init(sr_info); + + return 0; +} + +/** + * omap_sr_enable() - API to enable SR clocks and to call into the + * registered smartreflex class enable API. + * @voltdm: VDD pointer to which the SR module to be configured belongs to. + * + * This API is to be called from the kernel in order to enable + * a particular smartreflex module. This API will do the initial + * configurations to turn on the smartreflex module and in turn call + * into the registered smartreflex class enable API. + */ +void omap_sr_enable(struct voltagedomain *voltdm) +{ + struct omap_sr *sr = _sr_lookup(voltdm); + + if (IS_ERR(sr)) { + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); + return; + } + + if (!sr->autocomp_active) + return; + + if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) { + dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not" + "registered\n", __func__); + return; + } + + sr_class->enable(sr); +} + +/** + * omap_sr_disable() - API to disable SR without resetting the voltage + * processor voltage + * @voltdm: VDD pointer to which the SR module to be configured belongs to. + * + * This API is to be called from the kernel in order to disable + * a particular smartreflex module. This API will in turn call + * into the registered smartreflex class disable API. This API will tell + * the smartreflex class disable not to reset the VP voltage after + * disabling smartreflex. + */ +void omap_sr_disable(struct voltagedomain *voltdm) +{ + struct omap_sr *sr = _sr_lookup(voltdm); + + if (IS_ERR(sr)) { + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); + return; + } + + if (!sr->autocomp_active) + return; + + if (!sr_class || !(sr_class->disable)) { + dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not" + "registered\n", __func__); + return; + } + + sr_class->disable(sr, 0); +} + +/** + * omap_sr_disable_reset_volt() - API to disable SR and reset the + * voltage processor voltage + * @voltdm: VDD pointer to which the SR module to be configured belongs to. + * + * This API is to be called from the kernel in order to disable + * a particular smartreflex module. This API will in turn call + * into the registered smartreflex class disable API. This API will tell + * the smartreflex class disable to reset the VP voltage after + * disabling smartreflex. + */ +void omap_sr_disable_reset_volt(struct voltagedomain *voltdm) +{ + struct omap_sr *sr = _sr_lookup(voltdm); + + if (IS_ERR(sr)) { + pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); + return; + } + + if (!sr->autocomp_active) + return; + + if (!sr_class || !(sr_class->disable)) { + dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not" + "registered\n", __func__); + return; + } + + sr_class->disable(sr, 1); +} + +/** + * omap_sr_register_pmic() - API to register pmic specific info. + * @pmic_data: The structure containing pmic specific data. + * + * This API is to be called from the PMIC specific code to register with + * smartreflex driver pmic specific info. Currently the only info required + * is the smartreflex init on the PMIC side. + */ +void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data) +{ + if (!pmic_data) { + pr_warning("%s: Trying to register NULL PMIC data structure" + "with smartreflex\n", __func__); + return; + } + + sr_pmic_data = pmic_data; +} + +/* PM Debug FS entries to enable and disable smartreflex. */ +static int omap_sr_autocomp_show(void *data, u64 *val) +{ + struct omap_sr *sr_info = data; + + if (!sr_info) { + pr_warning("%s: omap_sr struct not found\n", __func__); + return -EINVAL; + } + + *val = sr_info->autocomp_active; + + return 0; +} + +static int omap_sr_autocomp_store(void *data, u64 val) +{ + struct omap_sr *sr_info = data; + + if (!sr_info) { + pr_warning("%s: omap_sr struct not found\n", __func__); + return -EINVAL; + } + + /* Sanity check */ + if (val > 1) { + pr_warning("%s: Invalid argument %lld\n", __func__, val); + return -EINVAL; + } + + /* control enable/disable only if there is a delta in value */ + if (sr_info->autocomp_active != val) { + if (!val) + sr_stop_vddautocomp(sr_info); + else + sr_start_vddautocomp(sr_info); + } + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show, + omap_sr_autocomp_store, "%llu\n"); + +static int __init omap_sr_probe(struct platform_device *pdev) +{ + struct omap_sr *sr_info; + struct omap_sr_data *pdata = pdev->dev.platform_data; + struct resource *mem, *irq; + struct dentry *nvalue_dir; + int i, ret = 0; + + sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL); + if (!sr_info) { + dev_err(&pdev->dev, "%s: unable to allocate sr_info\n", + __func__); + return -ENOMEM; + } + + platform_set_drvdata(pdev, sr_info); + + if (!pdata) { + dev_err(&pdev->dev, "%s: platform data missing\n", __func__); + ret = -EINVAL; + goto err_free_devinfo; + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) { + dev_err(&pdev->dev, "%s: no mem resource\n", __func__); + ret = -ENODEV; + goto err_free_devinfo; + } + + mem = request_mem_region(mem->start, resource_size(mem), + dev_name(&pdev->dev)); + if (!mem) { + dev_err(&pdev->dev, "%s: no mem region\n", __func__); + ret = -EBUSY; + goto err_free_devinfo; + } + + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + + pm_runtime_enable(&pdev->dev); + pm_runtime_irq_safe(&pdev->dev); + + sr_info->name = kasprintf(GFP_KERNEL, "%s", pdata->name); + if (!sr_info->name) { + dev_err(&pdev->dev, "%s: Unable to alloc SR instance name\n", + __func__); + ret = -ENOMEM; + goto err_release_region; + } + + sr_info->pdev = pdev; + sr_info->srid = pdev->id; + sr_info->voltdm = pdata->voltdm; + sr_info->nvalue_table = pdata->nvalue_table; + sr_info->nvalue_count = pdata->nvalue_count; + sr_info->senn_mod = pdata->senn_mod; + sr_info->senp_mod = pdata->senp_mod; + sr_info->autocomp_active = false; + sr_info->ip_type = pdata->ip_type; + sr_info->base = ioremap(mem->start, resource_size(mem)); + if (!sr_info->base) { + dev_err(&pdev->dev, "%s: ioremap fail\n", __func__); + ret = -ENOMEM; + goto err_release_region; + } + + if (irq) + sr_info->irq = irq->start; + + sr_set_clk_length(sr_info); + sr_set_regfields(sr_info); + + list_add(&sr_info->node, &sr_list); + + /* + * Call into late init to do intializations that require + * both sr driver and sr class driver to be initiallized. + */ + if (sr_class) { + ret = sr_late_init(sr_info); + if (ret) { + pr_warning("%s: Error in SR late init\n", __func__); + goto err_iounmap; + } + } + + dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__); + if (!sr_dbg_dir) { + sr_dbg_dir = debugfs_create_dir("smartreflex", NULL); + if (IS_ERR_OR_NULL(sr_dbg_dir)) { + ret = PTR_ERR(sr_dbg_dir); + pr_err("%s:sr debugfs dir creation failed(%d)\n", + __func__, ret); + goto err_iounmap; + } + } + + sr_info->dbg_dir = debugfs_create_dir(sr_info->name, sr_dbg_dir); + if (IS_ERR_OR_NULL(sr_info->dbg_dir)) { + dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n", + __func__); + ret = PTR_ERR(sr_info->dbg_dir); + goto err_free_name; + } + + (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, + sr_info->dbg_dir, (void *)sr_info, &pm_sr_fops); + (void) debugfs_create_x32("errweight", S_IRUGO, sr_info->dbg_dir, + &sr_info->err_weight); + (void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir, + &sr_info->err_maxlimit); + + nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir); + if (IS_ERR_OR_NULL(nvalue_dir)) { + dev_err(&pdev->dev, "%s: Unable to create debugfs directory" + "for n-values\n", __func__); + ret = PTR_ERR(nvalue_dir); + goto err_debugfs; + } + + if (sr_info->nvalue_count == 0 || !sr_info->nvalue_table) { + dev_warn(&pdev->dev, "%s: %s: No Voltage table for the corresponding vdd. Cannot create debugfs entries for n-values\n", + __func__, sr_info->name); + + ret = -ENODATA; + goto err_debugfs; + } + + for (i = 0; i < sr_info->nvalue_count; i++) { + char name[NVALUE_NAME_LEN + 1]; + + snprintf(name, sizeof(name), "volt_%lu", + sr_info->nvalue_table[i].volt_nominal); + (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir, + &(sr_info->nvalue_table[i].nvalue)); + snprintf(name, sizeof(name), "errminlimit_%lu", + sr_info->nvalue_table[i].volt_nominal); + (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir, + &(sr_info->nvalue_table[i].errminlimit)); + + } + + return ret; + +err_debugfs: + debugfs_remove_recursive(sr_info->dbg_dir); +err_free_name: + kfree(sr_info->name); +err_iounmap: + list_del(&sr_info->node); + iounmap(sr_info->base); +err_release_region: + release_mem_region(mem->start, resource_size(mem)); +err_free_devinfo: + kfree(sr_info); + + return ret; +} + +static int __devexit omap_sr_remove(struct platform_device *pdev) +{ + struct omap_sr_data *pdata = pdev->dev.platform_data; + struct omap_sr *sr_info; + struct resource *mem; + + if (!pdata) { + dev_err(&pdev->dev, "%s: platform data missing\n", __func__); + return -EINVAL; + } + + sr_info = _sr_lookup(pdata->voltdm); + if (IS_ERR(sr_info)) { + dev_warn(&pdev->dev, "%s: omap_sr struct not found\n", + __func__); + return PTR_ERR(sr_info); + } + + if (sr_info->autocomp_active) + sr_stop_vddautocomp(sr_info); + if (sr_info->dbg_dir) + debugfs_remove_recursive(sr_info->dbg_dir); + + list_del(&sr_info->node); + iounmap(sr_info->base); + kfree(sr_info->name); + kfree(sr_info); + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(mem->start, resource_size(mem)); + + return 0; +} + +static void __devexit omap_sr_shutdown(struct platform_device *pdev) +{ + struct omap_sr_data *pdata = pdev->dev.platform_data; + struct omap_sr *sr_info; + + if (!pdata) { + dev_err(&pdev->dev, "%s: platform data missing\n", __func__); + return; + } + + sr_info = _sr_lookup(pdata->voltdm); + if (IS_ERR(sr_info)) { + dev_warn(&pdev->dev, "%s: omap_sr struct not found\n", + __func__); + return; + } + + if (sr_info->autocomp_active) + sr_stop_vddautocomp(sr_info); + + return; +} + +static struct platform_driver smartreflex_driver = { + .remove = __devexit_p(omap_sr_remove), + .shutdown = __devexit_p(omap_sr_shutdown), + .driver = { + .name = "smartreflex", + }, +}; + +static int __init sr_init(void) +{ + int ret = 0; + + /* + * sr_init is a late init. If by then a pmic specific API is not + * registered either there is no need for anything to be done on + * the PMIC side or somebody has forgotten to register a PMIC + * handler. Warn for the second condition. + */ + if (sr_pmic_data && sr_pmic_data->sr_pmic_init) + sr_pmic_data->sr_pmic_init(); + else + pr_warning("%s: No PMIC hook to init smartreflex\n", __func__); + + ret = platform_driver_probe(&smartreflex_driver, omap_sr_probe); + if (ret) { + pr_err("%s: platform driver register failed for SR\n", + __func__); + return ret; + } + + return 0; +} +late_initcall(sr_init); + +static void __exit sr_exit(void) +{ + platform_driver_unregister(&smartreflex_driver); +} +module_exit(sr_exit); + +MODULE_DESCRIPTION("OMAP Smartreflex Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRIVER_NAME); +MODULE_AUTHOR("Texas Instruments Inc"); -- cgit v1.2.3 From eb774a09017e39a3255e144465d150877b6e6e2f Mon Sep 17 00:00:00 2001 From: Rafal Prylowski Date: Thu, 12 Apr 2012 14:14:12 +0200 Subject: ep93xx: IDE driver platform support code Add IDE driver platform support code for ep93xx. Signed-off-by: Rafal Prylowski Acked-by: H Hartley Sweeten Signed-off-by: Ryan Mallon --- arch/arm/mach-ep93xx/core.c | 96 ++++++++++++++++++++++++++++ arch/arm/mach-ep93xx/include/mach/platform.h | 3 + arch/arm/mach-ep93xx/soc.h | 1 + 3 files changed, 100 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 4dd07a0e3604..4afe52aaaff3 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -797,6 +797,102 @@ static struct platform_device ep93xx_wdt_device = { .resource = ep93xx_wdt_resources, }; +/************************************************************************* + * EP93xx IDE + *************************************************************************/ +static struct resource ep93xx_ide_resources[] = { + DEFINE_RES_MEM(EP93XX_IDE_PHYS_BASE, 0x38), + DEFINE_RES_IRQ(IRQ_EP93XX_EXT3), +}; + +static struct platform_device ep93xx_ide_device = { + .name = "ep93xx-ide", + .id = -1, + .dev = { + .dma_mask = &ep93xx_ide_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(ep93xx_ide_resources), + .resource = ep93xx_ide_resources, +}; + +void __init ep93xx_register_ide(void) +{ + platform_device_register(&ep93xx_ide_device); +} + +int ep93xx_ide_acquire_gpio(struct platform_device *pdev) +{ + int err; + int i; + + err = gpio_request(EP93XX_GPIO_LINE_EGPIO2, dev_name(&pdev->dev)); + if (err) + return err; + err = gpio_request(EP93XX_GPIO_LINE_EGPIO15, dev_name(&pdev->dev)); + if (err) + goto fail_egpio15; + for (i = 2; i < 8; i++) { + err = gpio_request(EP93XX_GPIO_LINE_E(i), dev_name(&pdev->dev)); + if (err) + goto fail_gpio_e; + } + for (i = 4; i < 8; i++) { + err = gpio_request(EP93XX_GPIO_LINE_G(i), dev_name(&pdev->dev)); + if (err) + goto fail_gpio_g; + } + for (i = 0; i < 8; i++) { + err = gpio_request(EP93XX_GPIO_LINE_H(i), dev_name(&pdev->dev)); + if (err) + goto fail_gpio_h; + } + + /* GPIO ports E[7:2], G[7:4] and H used by IDE */ + ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_EONIDE | + EP93XX_SYSCON_DEVCFG_GONIDE | + EP93XX_SYSCON_DEVCFG_HONIDE); + return 0; + +fail_gpio_h: + for (--i; i >= 0; --i) + gpio_free(EP93XX_GPIO_LINE_H(i)); + i = 8; +fail_gpio_g: + for (--i; i >= 4; --i) + gpio_free(EP93XX_GPIO_LINE_G(i)); + i = 8; +fail_gpio_e: + for (--i; i >= 2; --i) + gpio_free(EP93XX_GPIO_LINE_E(i)); + gpio_free(EP93XX_GPIO_LINE_EGPIO15); +fail_egpio15: + gpio_free(EP93XX_GPIO_LINE_EGPIO2); + return err; +} +EXPORT_SYMBOL(ep93xx_ide_acquire_gpio); + +void ep93xx_ide_release_gpio(struct platform_device *pdev) +{ + int i; + + for (i = 2; i < 8; i++) + gpio_free(EP93XX_GPIO_LINE_E(i)); + for (i = 4; i < 8; i++) + gpio_free(EP93XX_GPIO_LINE_G(i)); + for (i = 0; i < 8; i++) + gpio_free(EP93XX_GPIO_LINE_H(i)); + gpio_free(EP93XX_GPIO_LINE_EGPIO15); + gpio_free(EP93XX_GPIO_LINE_EGPIO2); + + + /* GPIO ports E[7:2], G[7:4] and H used by GPIO */ + ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_EONIDE | + EP93XX_SYSCON_DEVCFG_GONIDE | + EP93XX_SYSCON_DEVCFG_HONIDE); +} +EXPORT_SYMBOL(ep93xx_ide_release_gpio); + void __init ep93xx_init_devices(void) { /* Disallow access to MaverickCrunch initially */ diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index 1ecb040d98bf..33a5122c6dc8 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -48,6 +48,9 @@ void ep93xx_register_i2s(void); int ep93xx_i2s_acquire(void); void ep93xx_i2s_release(void); void ep93xx_register_ac97(void); +void ep93xx_register_ide(void); +int ep93xx_ide_acquire_gpio(struct platform_device *pdev); +void ep93xx_ide_release_gpio(struct platform_device *pdev); void ep93xx_init_devices(void); extern struct sys_timer ep93xx_timer; diff --git a/arch/arm/mach-ep93xx/soc.h b/arch/arm/mach-ep93xx/soc.h index 979fba722926..7bf7ff8beae7 100644 --- a/arch/arm/mach-ep93xx/soc.h +++ b/arch/arm/mach-ep93xx/soc.h @@ -69,6 +69,7 @@ #define EP93XX_BOOT_ROM_BASE EP93XX_AHB_IOMEM(0x00090000) +#define EP93XX_IDE_PHYS_BASE EP93XX_AHB_PHYS(0x000a0000) #define EP93XX_IDE_BASE EP93XX_AHB_IOMEM(0x000a0000) #define EP93XX_VIC1_BASE EP93XX_AHB_IOMEM(0x000b0000) -- cgit v1.2.3 From 762be29733d5b02b4359691f64c0cc968cd23c93 Mon Sep 17 00:00:00 2001 From: Rafal Prylowski Date: Thu, 12 Apr 2012 14:15:15 +0200 Subject: ep93xx: Add IDE support to edb93xx boards Add IDE support to edb93xx boards. Signed-off-by: Rafal Prylowski Acked-by: H Hartley Sweeten Signed-off-by: Ryan Mallon --- arch/arm/mach-ep93xx/edb93xx.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index d74c5cddb98b..9005ea698f1e 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c @@ -233,6 +233,29 @@ static void __init edb93xx_register_fb(void) } +/************************************************************************* + * EDB93xx IDE + *************************************************************************/ +static int __init edb93xx_has_ide(void) +{ + /* + * Although EDB9312 and EDB9315 do have IDE capability, they have + * INTRQ line wired as pull-up, which makes using IDE interface + * problematic. + */ + return machine_is_edb9312() || machine_is_edb9315() || + machine_is_edb9315a(); +} + +static void __init edb93xx_register_ide(void) +{ + if (!edb93xx_has_ide()) + return; + + ep93xx_register_ide(); +} + + static void __init edb93xx_init_machine(void) { ep93xx_init_devices(); @@ -243,6 +266,7 @@ static void __init edb93xx_init_machine(void) edb93xx_register_i2s(); edb93xx_register_pwm(); edb93xx_register_fb(); + edb93xx_register_ide(); } -- cgit v1.2.3 From bedfb7adc7f7e2f344b21584905b2357147ba27e Mon Sep 17 00:00:00 2001 From: Oleg Matcovschi Date: Tue, 15 May 2012 14:35:08 -0700 Subject: ARM: OMAP: dma: Clear status registers on enable/disable irq Use omap_disable_channel_irq() function instead of directly accessing CICR register in various functions. The omap_disable_chanel_irq() function now clears pending interrupts and disables interrupt on channel. Functions omap2_enable_irq_lch()/omap2_disable_irq_lch() clear interrupt status register. Signed-off-by: Oleg Matcovschi Tested-by: Jarkko Nikula [tony@atomide.com: updated comments to clarify CICR access] Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 59 +++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index cb16ade437cb..7fe626761e53 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -573,22 +573,25 @@ EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); static inline void omap_enable_channel_irq(int lch) { - u32 status; - /* Clear CSR */ if (cpu_class_is_omap1()) - status = p->dma_read(CSR, lch); - else if (cpu_class_is_omap2()) + p->dma_read(CSR, lch); + else p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); /* Enable some nice interrupts. */ p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch); } -static void omap_disable_channel_irq(int lch) +static inline void omap_disable_channel_irq(int lch) { - if (cpu_class_is_omap2()) - p->dma_write(0, CICR, lch); + /* disable channel interrupts */ + p->dma_write(0, CICR, lch); + /* Clear CSR */ + if (cpu_class_is_omap1()) + p->dma_read(CSR, lch); + else + p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); } void omap_enable_dma_irq(int lch, u16 bits) @@ -632,14 +635,14 @@ static inline void disable_lnk(int lch) l = p->dma_read(CLNK_CTRL, lch); /* Disable interrupts */ + omap_disable_channel_irq(lch); + if (cpu_class_is_omap1()) { - p->dma_write(0, CICR, lch); /* Set the STOP_LNK bit */ l |= 1 << 14; } if (cpu_class_is_omap2()) { - omap_disable_channel_irq(lch); /* Clear the ENABLE_LNK bit */ l &= ~(1 << 15); } @@ -657,6 +660,9 @@ static inline void omap2_enable_irq_lch(int lch) return; spin_lock_irqsave(&dma_chan_lock, flags); + /* clear IRQ STATUS */ + p->dma_write(1 << lch, IRQSTATUS_L0, lch); + /* Enable interrupt */ val = p->dma_read(IRQENABLE_L0, lch); val |= 1 << lch; p->dma_write(val, IRQENABLE_L0, lch); @@ -672,9 +678,12 @@ static inline void omap2_disable_irq_lch(int lch) return; spin_lock_irqsave(&dma_chan_lock, flags); + /* Disable interrupt */ val = p->dma_read(IRQENABLE_L0, lch); val &= ~(1 << lch); p->dma_write(val, IRQENABLE_L0, lch); + /* clear IRQ STATUS */ + p->dma_write(1 << lch, IRQSTATUS_L0, lch); spin_unlock_irqrestore(&dma_chan_lock, flags); } @@ -745,11 +754,8 @@ int omap_request_dma(int dev_id, const char *dev_name, } if (cpu_class_is_omap2()) { - omap2_enable_irq_lch(free_ch); omap_enable_channel_irq(free_ch); - /* Clear the CSR register and IRQ status register */ - p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch); - p->dma_write(1 << free_ch, IRQSTATUS_L0, 0); + omap2_enable_irq_lch(free_ch); } *dma_ch_out = free_ch; @@ -768,27 +774,19 @@ void omap_free_dma(int lch) return; } - if (cpu_class_is_omap1()) { - /* Disable all DMA interrupts for the channel. */ - p->dma_write(0, CICR, lch); - /* Make sure the DMA transfer is stopped. */ - p->dma_write(0, CCR, lch); - } - - if (cpu_class_is_omap2()) { + /* Disable interrupt for logical channel */ + if (cpu_class_is_omap2()) omap2_disable_irq_lch(lch); - /* Clear the CSR register and IRQ status register */ - p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); - p->dma_write(1 << lch, IRQSTATUS_L0, lch); + /* Disable all DMA interrupts for the channel. */ + omap_disable_channel_irq(lch); - /* Disable all DMA interrupts for the channel. */ - p->dma_write(0, CICR, lch); + /* Make sure the DMA transfer is stopped. */ + p->dma_write(0, CCR, lch); - /* Make sure the DMA transfer is stopped. */ - p->dma_write(0, CCR, lch); + /* Clear registers */ + if (cpu_class_is_omap2()) omap_clear_dma(lch); - } spin_lock_irqsave(&dma_chan_lock, flags); dma_chan[lch].dev_id = -1; @@ -943,8 +941,7 @@ void omap_stop_dma(int lch) u32 l; /* Disable all interrupts on the channel */ - if (cpu_class_is_omap1()) - p->dma_write(0, CICR, lch); + omap_disable_channel_irq(lch); l = p->dma_read(CCR, lch); if (IS_DMA_ERRATA(DMA_ERRATA_i541) && -- cgit v1.2.3 From a22ab1c4bac78d5789dc51c1730463f845b3262f Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 4 Jun 2012 00:56:15 -0700 Subject: ARM: OMAP3: There is no FS USB controller on omap3 We should not select ARCH_OMAP_OTG as the hardware does not have the legacy FS (Full Speed) USB interface. Cc: linux-usb@vger.kernel.org Cc: Kyungmin Park Acked-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 4cf5142f22cc..0e4dd6746875 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -76,7 +76,6 @@ config SOC_OMAP3430 bool "OMAP3430 support" depends on ARCH_OMAP3 default y - select ARCH_OMAP_OTG config SOC_TI81XX bool "TI81XX support" -- cgit v1.2.3 From fe57ab06052234ad954617e7e1f212154d37859e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 4 Jun 2012 00:56:15 -0700 Subject: ARM: OMAP2: Remove legacy USB FS support The FS (Full Speed) USB controller is available on 2420 and 2430, but not being used. Out of the 2420 based boards only Nokia N8X0 are seeing active development and they have external HS (High Speed) TUSB controller. On omap 2430sdp there is MUSB HS controller, so there's no need to use the legacy USB FS controller. That leaves only H4 and Apollon boards that could use the FS USB controller. As both H4 and Apollon boards are old proprietary development boards, it's unlikely that we have any active developers working on those boards using the USB. So remove the FS USB support for omap2 machines. Patches are welcome if somebody wants to instead fix it all up to the current standards. Cc: linux-usb@vger.kernel.org Cc: Kyungmin Park Acked-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 2 - arch/arm/mach-omap2/Makefile | 3 - arch/arm/mach-omap2/board-2430sdp.c | 11 -- arch/arm/mach-omap2/board-apollon.c | 18 -- arch/arm/mach-omap2/board-h4.c | 13 -- arch/arm/mach-omap2/usb-fs.c | 359 ------------------------------------ 6 files changed, 406 deletions(-) delete mode 100644 arch/arm/mach-omap2/usb-fs.c (limited to 'arch') diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 0e4dd6746875..042f157a8f94 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -64,13 +64,11 @@ config SOC_OMAP2420 depends on ARCH_OMAP2 default y select OMAP_DM_TIMER - select ARCH_OMAP_OTG config SOC_OMAP2430 bool "OMAP2430 support" depends on ARCH_OMAP2 default y - select ARCH_OMAP_OTG config SOC_OMAP3430 bool "OMAP3430 support" diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index fa742f3c2629..664224fb7405 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -244,9 +244,6 @@ obj-y += $(omap-flash-y) $(omap-flash-m) omap-hsmmc-$(CONFIG_MMC_OMAP_HS) := hsmmc.o obj-y += $(omap-hsmmc-m) $(omap-hsmmc-y) - -usbfs-$(CONFIG_ARCH_OMAP_OTG) := usb-fs.o -obj-y += $(usbfs-m) $(usbfs-y) obj-y += usb-musb.o obj-y += omap_phy_internal.o diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 99ca6bad5c30..6523aeabf9f2 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -254,16 +254,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = { {} /* Terminator */ }; -static struct omap_usb_config sdp2430_usb_config __initdata = { - .otg = 1, -#ifdef CONFIG_USB_GADGET_OMAP - .hmc_mode = 0x0, -#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - .hmc_mode = 0x1, -#endif - .pins[0] = 3, -}; - #ifdef CONFIG_OMAP_MUX static struct omap_board_mux board_mux[] __initdata = { { .reg_offset = OMAP_MUX_TERMINATOR }, @@ -280,7 +270,6 @@ static void __init omap_2430sdp_init(void) omap_serial_init(); omap_sdrc_init(NULL, NULL); omap_hsmmc_init(mmc); - omap2_usbfs_init(&sdp2430_usb_config); omap_mux_init_signal("usb0hs_stp", OMAP_PULL_ENA | OMAP_PULL_UP); usb_musb_init(NULL); diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 502c31e123be..519bcd3079e8 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -35,7 +35,6 @@ #include #include -#include #include #include "common.h" #include @@ -253,13 +252,6 @@ out: clk_put(gpmc_fck); } -static struct omap_usb_config apollon_usb_config __initdata = { - .register_dev = 1, - .hmc_mode = 0x14, /* 0:dev 1:host1 2:disable */ - - .pins[0] = 6, -}; - static struct panel_generic_dpi_data apollon_panel_data = { .name = "apollon", }; @@ -297,15 +289,6 @@ static void __init apollon_led_init(void) gpio_request_array(apollon_gpio_leds, ARRAY_SIZE(apollon_gpio_leds)); } -static void __init apollon_usb_init(void) -{ - /* USB device */ - /* DEVICE_SUSPEND */ - omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0); - gpio_request_one(12, GPIOF_OUT_INIT_LOW, "USB suspend"); - omap2_usbfs_init(&apollon_usb_config); -} - #ifdef CONFIG_OMAP_MUX static struct omap_board_mux board_mux[] __initdata = { { .reg_offset = OMAP_MUX_TERMINATOR }, @@ -321,7 +304,6 @@ static void __init omap_apollon_init(void) apollon_init_smc91x(); apollon_led_init(); apollon_flash_init(); - apollon_usb_init(); /* REVISIT: where's the correct place */ omap_mux_init_signal("sys_nirq", OMAP_PULL_ENA | OMAP_PULL_UP); diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 876becf8205a..ace20482e3e1 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -32,7 +32,6 @@ #include #include -#include #include #include "common.h" #include @@ -329,17 +328,6 @@ static void __init h4_init_flash(void) h4_flash_resource.end = base + SZ_64M - 1; } -static struct omap_usb_config h4_usb_config __initdata = { - /* S1.10 OFF -- usb "download port" - * usb0 switched to Mini-B port and isp1105 transceiver; - * S2.POS3 = ON, S2.POS4 = OFF ... to enable battery charging - */ - .register_dev = 1, - .pins[0] = 3, -/* .hmc_mode = 0x14,*/ /* 0:dev 1:host 2:disable */ - .hmc_mode = 0x00, /* 0:dev|otg 1:disable 2:disable */ -}; - static struct at24_platform_data m24c01 = { .byte_len = SZ_1K / 8, .page_size = 16, @@ -381,7 +369,6 @@ static void __init omap_h4_init(void) ARRAY_SIZE(h4_i2c_board_info)); platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices)); - omap2_usbfs_init(&h4_usb_config); omap_serial_init(); omap_sdrc_init(NULL, NULL); h4_init_flash(); diff --git a/arch/arm/mach-omap2/usb-fs.c b/arch/arm/mach-omap2/usb-fs.c deleted file mode 100644 index 1481078763b8..000000000000 --- a/arch/arm/mach-omap2/usb-fs.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Platform level USB initialization for FS USB OTG controller on omap1 and 24xx - * - * Copyright (C) 2004 Texas Instruments, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include "control.h" -#include "mux.h" - -#define INT_USB_IRQ_GEN INT_24XX_USB_IRQ_GEN -#define INT_USB_IRQ_NISO INT_24XX_USB_IRQ_NISO -#define INT_USB_IRQ_ISO INT_24XX_USB_IRQ_ISO -#define INT_USB_IRQ_HGEN INT_24XX_USB_IRQ_HGEN -#define INT_USB_IRQ_OTG INT_24XX_USB_IRQ_OTG - -#if defined(CONFIG_ARCH_OMAP2) - -#ifdef CONFIG_USB_GADGET_OMAP - -static struct resource udc_resources[] = { - /* order is significant! */ - { /* registers */ - .start = UDC_BASE, - .end = UDC_BASE + 0xff, - .flags = IORESOURCE_MEM, - }, { /* general IRQ */ - .start = INT_USB_IRQ_GEN, - .flags = IORESOURCE_IRQ, - }, { /* PIO IRQ */ - .start = INT_USB_IRQ_NISO, - .flags = IORESOURCE_IRQ, - }, { /* SOF IRQ */ - .start = INT_USB_IRQ_ISO, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 udc_dmamask = ~(u32)0; - -static struct platform_device udc_device = { - .name = "omap_udc", - .id = -1, - .dev = { - .dma_mask = &udc_dmamask, - .coherent_dma_mask = 0xffffffff, - }, - .num_resources = ARRAY_SIZE(udc_resources), - .resource = udc_resources, -}; - -static inline void udc_device_init(struct omap_usb_config *pdata) -{ - pdata->udc_device = &udc_device; -} - -#else - -static inline void udc_device_init(struct omap_usb_config *pdata) -{ -} - -#endif - -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - -/* The dmamask must be set for OHCI to work */ -static u64 ohci_dmamask = ~(u32)0; - -static struct resource ohci_resources[] = { - { - .start = OMAP_OHCI_BASE, - .end = OMAP_OHCI_BASE + 0xff, - .flags = IORESOURCE_MEM, - }, - { - .start = INT_USB_IRQ_HGEN, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device ohci_device = { - .name = "ohci", - .id = -1, - .dev = { - .dma_mask = &ohci_dmamask, - .coherent_dma_mask = 0xffffffff, - }, - .num_resources = ARRAY_SIZE(ohci_resources), - .resource = ohci_resources, -}; - -static inline void ohci_device_init(struct omap_usb_config *pdata) -{ - pdata->ohci_device = &ohci_device; -} - -#else - -static inline void ohci_device_init(struct omap_usb_config *pdata) -{ -} - -#endif - -#if defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG) - -static struct resource otg_resources[] = { - /* order is significant! */ - { - .start = OTG_BASE, - .end = OTG_BASE + 0xff, - .flags = IORESOURCE_MEM, - }, { - .start = INT_USB_IRQ_OTG, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device otg_device = { - .name = "omap_otg", - .id = -1, - .num_resources = ARRAY_SIZE(otg_resources), - .resource = otg_resources, -}; - -static inline void otg_device_init(struct omap_usb_config *pdata) -{ - pdata->otg_device = &otg_device; -} - -#else - -static inline void otg_device_init(struct omap_usb_config *pdata) -{ -} - -#endif - -static void omap2_usb_devconf_clear(u8 port, u32 mask) -{ - u32 r; - - r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - r &= ~USBTXWRMODEI(port, mask); - omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); -} - -static void omap2_usb_devconf_set(u8 port, u32 mask) -{ - u32 r; - - r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - r |= USBTXWRMODEI(port, mask); - omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); -} - -static void omap2_usb2_disable_5pinbitll(void) -{ - u32 r; - - r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - r &= ~(USBTXWRMODEI(2, USB_BIDIR_TLL) | USBT2TLL5PI); - omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); -} - -static void omap2_usb2_enable_5pinunitll(void) -{ - u32 r; - - r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - r |= USBTXWRMODEI(2, USB_UNIDIR_TLL) | USBT2TLL5PI; - omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); -} - -static u32 __init omap2_usb0_init(unsigned nwires, unsigned is_device) -{ - u32 syscon1 = 0; - - omap2_usb_devconf_clear(0, USB_BIDIR_TLL); - - if (nwires == 0) - return 0; - - if (is_device) - omap_mux_init_signal("usb0_puen", 0); - - omap_mux_init_signal("usb0_dat", 0); - omap_mux_init_signal("usb0_txen", 0); - omap_mux_init_signal("usb0_se0", 0); - if (nwires != 3) - omap_mux_init_signal("usb0_rcv", 0); - - switch (nwires) { - case 3: - syscon1 = 2; - omap2_usb_devconf_set(0, USB_BIDIR); - break; - case 4: - syscon1 = 1; - omap2_usb_devconf_set(0, USB_BIDIR); - break; - case 6: - syscon1 = 3; - omap_mux_init_signal("usb0_vp", 0); - omap_mux_init_signal("usb0_vm", 0); - omap2_usb_devconf_set(0, USB_UNIDIR); - break; - default: - printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", - 0, nwires); - } - - return syscon1 << 16; -} - -static u32 __init omap2_usb1_init(unsigned nwires) -{ - u32 syscon1 = 0; - - omap2_usb_devconf_clear(1, USB_BIDIR_TLL); - - if (nwires == 0) - return 0; - - /* NOTE: board-specific code must set up pin muxing for usb1, - * since each signal could come out on either of two balls. - */ - - switch (nwires) { - case 2: - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM - */ - syscon1 = 1; - omap2_usb_devconf_set(1, USB_BIDIR_TLL); - break; - case 3: - syscon1 = 2; - omap2_usb_devconf_set(1, USB_BIDIR); - break; - case 4: - syscon1 = 1; - omap2_usb_devconf_set(1, USB_BIDIR); - break; - case 6: - default: - printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", - 1, nwires); - } - - return syscon1 << 20; -} - -static u32 __init omap2_usb2_init(unsigned nwires, unsigned alt_pingroup) -{ - u32 syscon1 = 0; - - omap2_usb2_disable_5pinbitll(); - alt_pingroup = 0; - - /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ - if (alt_pingroup || nwires == 0) - return 0; - - omap_mux_init_signal("usb2_dat", 0); - omap_mux_init_signal("usb2_se0", 0); - if (nwires > 2) - omap_mux_init_signal("usb2_txen", 0); - if (nwires > 3) - omap_mux_init_signal("usb2_rcv", 0); - - switch (nwires) { - case 2: - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM - */ - syscon1 = 1; - omap2_usb_devconf_set(2, USB_BIDIR_TLL); - break; - case 3: - syscon1 = 2; - omap2_usb_devconf_set(2, USB_BIDIR); - break; - case 4: - syscon1 = 1; - omap2_usb_devconf_set(2, USB_BIDIR); - break; - case 5: - /* NOTE: board-specific code must mux this setting depending - * on TLL link using DP/DM. Something must also - * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED} - * 2420: hdq_sio.usb2_tllse0 or vlynq_rx0.usb2_tllse0 - * 2430: hdq_sio.usb2_tllse0 or sdmmc2_dat0.usb2_tllse0 - */ - - syscon1 = 3; - omap2_usb2_enable_5pinunitll(); - break; - case 6: - default: - printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", - 2, nwires); - } - - return syscon1 << 24; -} - -void __init omap2_usbfs_init(struct omap_usb_config *pdata) -{ - struct clk *ick; - - if (!cpu_is_omap24xx()) - return; - - ick = clk_get(NULL, "usb_l4_ick"); - if (IS_ERR(ick)) - return; - - clk_enable(ick); - pdata->usb0_init = omap2_usb0_init; - pdata->usb1_init = omap2_usb1_init; - pdata->usb2_init = omap2_usb2_init; - udc_device_init(pdata); - ohci_device_init(pdata); - otg_device_init(pdata); - omap_otg_init(pdata); - clk_disable(ick); - clk_put(ick); -} - -#endif -- cgit v1.2.3 From b924b2047045844644e04b3c6e8308b2114afe7e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 4 Jun 2012 00:56:15 -0700 Subject: ARM: OMAP: Make FS USB omap1 only As the FS USB code is not being actively used for omap2+ there's no point keeping it around for omap2+. Let's make the FS USB platform init code omap1 only so we can remove the last user of omap_read/write for omap2+, and simplify things for further USB, DMA, and device tree related work. While at it, also group the mach includes for the related drivers. Cc: linux-usb@vger.kernel.org Cc: Kyungmin Park Acked-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-ams-delta.c | 2 +- arch/arm/mach-omap1/board-generic.c | 4 +- arch/arm/mach-omap1/board-h2.c | 2 +- arch/arm/mach-omap1/board-h3.c | 2 +- arch/arm/mach-omap1/board-htcherald.c | 2 +- arch/arm/mach-omap1/board-innovator.c | 2 +- arch/arm/mach-omap1/board-nokia770.c | 2 +- arch/arm/mach-omap1/board-osk.c | 2 +- arch/arm/mach-omap1/board-palmte.c | 2 +- arch/arm/mach-omap1/board-palmtt.c | 2 +- arch/arm/mach-omap1/board-palmz71.c | 2 +- arch/arm/mach-omap1/board-sx1.c | 2 +- arch/arm/mach-omap1/board-voiceblue.c | 3 +- arch/arm/mach-omap1/clock_data.c | 3 +- arch/arm/mach-omap1/include/mach/usb.h | 165 +++++++++++++++++++++++++++ arch/arm/mach-omap1/usb.c | 116 ++++++++++++++++++- arch/arm/plat-omap/Makefile | 2 +- arch/arm/plat-omap/include/plat/board.h | 38 ------- arch/arm/plat-omap/include/plat/usb.h | 196 +------------------------------- arch/arm/plat-omap/usb.c | 145 ----------------------- drivers/usb/gadget/Kconfig | 2 +- drivers/usb/gadget/omap_udc.c | 3 +- drivers/usb/host/Kconfig | 2 +- drivers/usb/host/ohci-omap.c | 7 +- drivers/usb/otg/isp1301_omap.c | 2 +- 25 files changed, 310 insertions(+), 400 deletions(-) create mode 100644 arch/arm/mach-omap1/include/mach/usb.h delete mode 100644 arch/arm/plat-omap/usb.c (limited to 'arch') diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index f2f8a5847018..c53469802c03 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -37,12 +37,12 @@ #include #include #include -#include #include #include #include #include +#include #include "iomap.h" #include "common.h" diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c index e75e2d55a2d7..6ec385e2b98e 100644 --- a/arch/arm/mach-omap1/board-generic.c +++ b/arch/arm/mach-omap1/board-generic.c @@ -23,8 +23,10 @@ #include #include -#include #include + +#include + #include "common.h" /* assume no Mini-AB port */ diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index a28e989a63f4..44a4ab195fbc 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -40,11 +40,11 @@ #include #include #include -#include #include #include #include +#include #include "common.h" #include "board-h2.h" diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 108a8640fc6f..86cb5a04a404 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -40,13 +40,13 @@ #include #include -#include #include #include #include #include #include +#include #include "common.h" #include "board-h3.h" diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c index 118a9d4a4c54..b3f6e943e661 100644 --- a/arch/arm/mach-omap1/board-htcherald.c +++ b/arch/arm/mach-omap1/board-htcherald.c @@ -44,10 +44,10 @@ #include #include #include -#include #include #include +#include #include "common.h" diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index 7970223a559d..f21c2966daad 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c @@ -35,11 +35,11 @@ #include #include #include -#include #include #include #include +#include #include "iomap.h" #include "common.h" diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 7212ae97f44a..4007a372481b 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -34,6 +33,7 @@ #include #include +#include #include "common.h" diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index da8d872d3d1c..8784705edb60 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -45,11 +45,11 @@ #include #include -#include #include #include #include +#include #include "common.h" diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index 949b62a73693..26bcb9defcdc 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include @@ -43,6 +42,7 @@ #include #include +#include #include "common.h" diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c index 7f1e1cf2bf46..4d099446dfa8 100644 --- a/arch/arm/mach-omap1/board-palmtt.c +++ b/arch/arm/mach-omap1/board-palmtt.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -43,6 +42,7 @@ #include #include +#include #include "common.h" diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c index 3c71c6bace2c..cc71a26723ef 100644 --- a/arch/arm/mach-omap1/board-palmz71.c +++ b/arch/arm/mach-omap1/board-palmz71.c @@ -37,7 +37,6 @@ #include #include -#include #include #include #include @@ -45,6 +44,7 @@ #include #include +#include #include "common.h" diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c index 3b7b82b13684..8c665bd16ac2 100644 --- a/arch/arm/mach-omap1/board-sx1.c +++ b/arch/arm/mach-omap1/board-sx1.c @@ -37,13 +37,13 @@ #include #include #include -#include #include #include #include #include #include +#include #include "common.h" diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index afd67f0ec495..3497769eb353 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c @@ -35,9 +35,10 @@ #include #include #include -#include +#include #include +#include #include "common.h" diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c index c6ce93f71d08..c007d80dfb62 100644 --- a/arch/arm/mach-omap1/clock_data.c +++ b/arch/arm/mach-omap1/clock_data.c @@ -25,10 +25,11 @@ #include #include #include +#include #include /* for omap_sram_reprogram_clock() */ -#include /* for OTG_BASE */ #include +#include /* for OTG_BASE */ #include "iomap.h" #include "clock.h" diff --git a/arch/arm/mach-omap1/include/mach/usb.h b/arch/arm/mach-omap1/include/mach/usb.h new file mode 100644 index 000000000000..753cd5ce6949 --- /dev/null +++ b/arch/arm/mach-omap1/include/mach/usb.h @@ -0,0 +1,165 @@ +/* + * FIXME correct answer depends on hmc_mode, + * as does (on omap1) any nonzero value for config->otg port number + */ +#ifdef CONFIG_USB_GADGET_OMAP +#define is_usb0_device(config) 1 +#else +#define is_usb0_device(config) 0 +#endif + +struct omap_usb_config { + /* Configure drivers according to the connectors on your board: + * - "A" connector (rectagular) + * ... for host/OHCI use, set "register_host". + * - "B" connector (squarish) or "Mini-B" + * ... for device/gadget use, set "register_dev". + * - "Mini-AB" connector (very similar to Mini-B) + * ... for OTG use as device OR host, initialize "otg" + */ + unsigned register_host:1; + unsigned register_dev:1; + u8 otg; /* port number, 1-based: usb1 == 2 */ + + u8 hmc_mode; + + /* implicitly true if otg: host supports remote wakeup? */ + u8 rwc; + + /* signaling pins used to talk to transceiver on usbN: + * 0 == usbN unused + * 2 == usb0-only, using internal transceiver + * 3 == 3 wire bidirectional + * 4 == 4 wire bidirectional + * 6 == 6 wire unidirectional (or TLL) + */ + u8 pins[3]; + + struct platform_device *udc_device; + struct platform_device *ohci_device; + struct platform_device *otg_device; + + u32 (*usb0_init)(unsigned nwires, unsigned is_device); + u32 (*usb1_init)(unsigned nwires); + u32 (*usb2_init)(unsigned nwires, unsigned alt_pingroup); + + int (*ocpi_enable)(void); +}; + +void omap_otg_init(struct omap_usb_config *config); + +#if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE) +void omap1_usb_init(struct omap_usb_config *pdata); +#else +static inline void omap1_usb_init(struct omap_usb_config *pdata) +{ +} +#endif + +#define OMAP1_OTG_BASE 0xfffb0400 +#define OMAP1_UDC_BASE 0xfffb4000 +#define OMAP1_OHCI_BASE 0xfffba000 + +#define OMAP2_OHCI_BASE 0x4805e000 +#define OMAP2_UDC_BASE 0x4805e200 +#define OMAP2_OTG_BASE 0x4805e300 +#define OTG_BASE OMAP1_OTG_BASE +#define UDC_BASE OMAP1_UDC_BASE +#define OMAP_OHCI_BASE OMAP1_OHCI_BASE + +/* + * OTG and transceiver registers, for OMAPs starting with ARM926 + */ +#define OTG_REV (OTG_BASE + 0x00) +#define OTG_SYSCON_1 (OTG_BASE + 0x04) +# define USB2_TRX_MODE(w) (((w)>>24)&0x07) +# define USB1_TRX_MODE(w) (((w)>>20)&0x07) +# define USB0_TRX_MODE(w) (((w)>>16)&0x07) +# define OTG_IDLE_EN (1 << 15) +# define HST_IDLE_EN (1 << 14) +# define DEV_IDLE_EN (1 << 13) +# define OTG_RESET_DONE (1 << 2) +# define OTG_SOFT_RESET (1 << 1) +#define OTG_SYSCON_2 (OTG_BASE + 0x08) +# define OTG_EN (1 << 31) +# define USBX_SYNCHRO (1 << 30) +# define OTG_MST16 (1 << 29) +# define SRP_GPDATA (1 << 28) +# define SRP_GPDVBUS (1 << 27) +# define SRP_GPUVBUS(w) (((w)>>24)&0x07) +# define A_WAIT_VRISE(w) (((w)>>20)&0x07) +# define B_ASE_BRST(w) (((w)>>16)&0x07) +# define SRP_DPW (1 << 14) +# define SRP_DATA (1 << 13) +# define SRP_VBUS (1 << 12) +# define OTG_PADEN (1 << 10) +# define HMC_PADEN (1 << 9) +# define UHOST_EN (1 << 8) +# define HMC_TLLSPEED (1 << 7) +# define HMC_TLLATTACH (1 << 6) +# define OTG_HMC(w) (((w)>>0)&0x3f) +#define OTG_CTRL (OTG_BASE + 0x0c) +# define OTG_USB2_EN (1 << 29) +# define OTG_USB2_DP (1 << 28) +# define OTG_USB2_DM (1 << 27) +# define OTG_USB1_EN (1 << 26) +# define OTG_USB1_DP (1 << 25) +# define OTG_USB1_DM (1 << 24) +# define OTG_USB0_EN (1 << 23) +# define OTG_USB0_DP (1 << 22) +# define OTG_USB0_DM (1 << 21) +# define OTG_ASESSVLD (1 << 20) +# define OTG_BSESSEND (1 << 19) +# define OTG_BSESSVLD (1 << 18) +# define OTG_VBUSVLD (1 << 17) +# define OTG_ID (1 << 16) +# define OTG_DRIVER_SEL (1 << 15) +# define OTG_A_SETB_HNPEN (1 << 12) +# define OTG_A_BUSREQ (1 << 11) +# define OTG_B_HNPEN (1 << 9) +# define OTG_B_BUSREQ (1 << 8) +# define OTG_BUSDROP (1 << 7) +# define OTG_PULLDOWN (1 << 5) +# define OTG_PULLUP (1 << 4) +# define OTG_DRV_VBUS (1 << 3) +# define OTG_PD_VBUS (1 << 2) +# define OTG_PU_VBUS (1 << 1) +# define OTG_PU_ID (1 << 0) +#define OTG_IRQ_EN (OTG_BASE + 0x10) /* 16-bit */ +# define DRIVER_SWITCH (1 << 15) +# define A_VBUS_ERR (1 << 13) +# define A_REQ_TMROUT (1 << 12) +# define A_SRP_DETECT (1 << 11) +# define B_HNP_FAIL (1 << 10) +# define B_SRP_TMROUT (1 << 9) +# define B_SRP_DONE (1 << 8) +# define B_SRP_STARTED (1 << 7) +# define OPRT_CHG (1 << 0) +#define OTG_IRQ_SRC (OTG_BASE + 0x14) /* 16-bit */ + // same bits as in IRQ_EN +#define OTG_OUTCTRL (OTG_BASE + 0x18) /* 16-bit */ +# define OTGVPD (1 << 14) +# define OTGVPU (1 << 13) +# define OTGPUID (1 << 12) +# define USB2VDR (1 << 10) +# define USB2PDEN (1 << 9) +# define USB2PUEN (1 << 8) +# define USB1VDR (1 << 6) +# define USB1PDEN (1 << 5) +# define USB1PUEN (1 << 4) +# define USB0VDR (1 << 2) +# define USB0PDEN (1 << 1) +# define USB0PUEN (1 << 0) +#define OTG_TEST (OTG_BASE + 0x20) /* 16-bit */ +#define OTG_VENDOR_CODE (OTG_BASE + 0xfc) /* 16-bit */ + +/*-------------------------------------------------------------------------*/ + +/* OMAP1 */ +#define USB_TRANSCEIVER_CTRL (0xfffe1000 + 0x0064) +# define CONF_USB2_UNI_R (1 << 8) +# define CONF_USB1_UNI_R (1 << 7) +# define CONF_USB_PORT0_R(x) (((x)>>4)&0x7) +# define CONF_USB0_ISOLATE_R (1 << 3) +# define CONF_USB_PWRDN_DM_R (1 << 2) +# define CONF_USB_PWRDN_DP_R (1 << 1) diff --git a/arch/arm/mach-omap1/usb.c b/arch/arm/mach-omap1/usb.c index e61afd922766..65f88176fba8 100644 --- a/arch/arm/mach-omap1/usb.c +++ b/arch/arm/mach-omap1/usb.c @@ -27,7 +27,8 @@ #include #include -#include + +#include #include "common.h" @@ -55,6 +56,119 @@ #define INT_USB_IRQ_HGEN INT_USB_HHC_1 #define INT_USB_IRQ_OTG IH2_BASE + 8 +#ifdef CONFIG_ARCH_OMAP_OTG + +void __init +omap_otg_init(struct omap_usb_config *config) +{ + u32 syscon; + int alt_pingroup = 0; + + /* NOTE: no bus or clock setup (yet?) */ + + syscon = omap_readl(OTG_SYSCON_1) & 0xffff; + if (!(syscon & OTG_RESET_DONE)) + pr_debug("USB resets not complete?\n"); + + //omap_writew(0, OTG_IRQ_EN); + + /* pin muxing and transceiver pinouts */ + if (config->pins[0] > 2) /* alt pingroup 2 */ + alt_pingroup = 1; + syscon |= config->usb0_init(config->pins[0], is_usb0_device(config)); + syscon |= config->usb1_init(config->pins[1]); + syscon |= config->usb2_init(config->pins[2], alt_pingroup); + pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1)); + omap_writel(syscon, OTG_SYSCON_1); + + syscon = config->hmc_mode; + syscon |= USBX_SYNCHRO | (4 << 16) /* B_ASE0_BRST */; +#ifdef CONFIG_USB_OTG + if (config->otg) + syscon |= OTG_EN; +#endif + if (cpu_class_is_omap1()) + pr_debug("USB_TRANSCEIVER_CTRL = %03x\n", + omap_readl(USB_TRANSCEIVER_CTRL)); + pr_debug("OTG_SYSCON_2 = %08x\n", omap_readl(OTG_SYSCON_2)); + omap_writel(syscon, OTG_SYSCON_2); + + printk("USB: hmc %d", config->hmc_mode); + if (!alt_pingroup) + printk(", usb2 alt %d wires", config->pins[2]); + else if (config->pins[0]) + printk(", usb0 %d wires%s", config->pins[0], + is_usb0_device(config) ? " (dev)" : ""); + if (config->pins[1]) + printk(", usb1 %d wires", config->pins[1]); + if (!alt_pingroup && config->pins[2]) + printk(", usb2 %d wires", config->pins[2]); + if (config->otg) + printk(", Mini-AB on usb%d", config->otg - 1); + printk("\n"); + + if (cpu_class_is_omap1()) { + u16 w; + + /* leave USB clocks/controllers off until needed */ + w = omap_readw(ULPD_SOFT_REQ); + w &= ~SOFT_USB_CLK_REQ; + omap_writew(w, ULPD_SOFT_REQ); + + w = omap_readw(ULPD_CLOCK_CTRL); + w &= ~USB_MCLK_EN; + w |= DIS_USB_PVCI_CLK; + omap_writew(w, ULPD_CLOCK_CTRL); + } + syscon = omap_readl(OTG_SYSCON_1); + syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN; + +#ifdef CONFIG_USB_GADGET_OMAP + if (config->otg || config->register_dev) { + struct platform_device *udc_device = config->udc_device; + int status; + + syscon &= ~DEV_IDLE_EN; + udc_device->dev.platform_data = config; + status = platform_device_register(udc_device); + if (status) + pr_debug("can't register UDC device, %d\n", status); + } +#endif + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) + if (config->otg || config->register_host) { + struct platform_device *ohci_device = config->ohci_device; + int status; + + syscon &= ~HST_IDLE_EN; + ohci_device->dev.platform_data = config; + status = platform_device_register(ohci_device); + if (status) + pr_debug("can't register OHCI device, %d\n", status); + } +#endif + +#ifdef CONFIG_USB_OTG + if (config->otg) { + struct platform_device *otg_device = config->otg_device; + int status; + + syscon &= ~OTG_IDLE_EN; + otg_device->dev.platform_data = config; + status = platform_device_register(otg_device); + if (status) + pr_debug("can't register OTG device, %d\n", status); + } +#endif + pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1)); + omap_writel(syscon, OTG_SYSCON_1); +} + +#else +void omap_otg_init(struct omap_usb_config *config) {} +#endif + #ifdef CONFIG_USB_GADGET_OMAP static struct resource udc_resources[] = { diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index ed8605f01155..6d87532871cd 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -4,7 +4,7 @@ # Common support obj-y := common.o sram.o clock.o devices.o dma.o mux.o \ - usb.o fb.o counter_32k.o + fb.o counter_32k.o obj-m := obj-n := obj- := diff --git a/arch/arm/plat-omap/include/plat/board.h b/arch/arm/plat-omap/include/plat/board.h index 4814c5b65306..e62f20a5c0af 100644 --- a/arch/arm/plat-omap/include/plat/board.h +++ b/arch/arm/plat-omap/include/plat/board.h @@ -57,44 +57,6 @@ struct omap_camera_sensor_config { int (*power_off)(void * data); }; -struct omap_usb_config { - /* Configure drivers according to the connectors on your board: - * - "A" connector (rectagular) - * ... for host/OHCI use, set "register_host". - * - "B" connector (squarish) or "Mini-B" - * ... for device/gadget use, set "register_dev". - * - "Mini-AB" connector (very similar to Mini-B) - * ... for OTG use as device OR host, initialize "otg" - */ - unsigned register_host:1; - unsigned register_dev:1; - u8 otg; /* port number, 1-based: usb1 == 2 */ - - u8 hmc_mode; - - /* implicitly true if otg: host supports remote wakeup? */ - u8 rwc; - - /* signaling pins used to talk to transceiver on usbN: - * 0 == usbN unused - * 2 == usb0-only, using internal transceiver - * 3 == 3 wire bidirectional - * 4 == 4 wire bidirectional - * 6 == 6 wire unidirectional (or TLL) - */ - u8 pins[3]; - - struct platform_device *udc_device; - struct platform_device *ohci_device; - struct platform_device *otg_device; - - u32 (*usb0_init)(unsigned nwires, unsigned is_device); - u32 (*usb1_init)(unsigned nwires); - u32 (*usb2_init)(unsigned nwires, unsigned alt_pingroup); - - int (*ocpi_enable)(void); -}; - struct omap_lcd_config { char panel_name[16]; char ctrl_name[16]; diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h index 762eeb0626c1..548a4c8d63df 100644 --- a/arch/arm/plat-omap/include/plat/usb.h +++ b/arch/arm/plat-omap/include/plat/usb.h @@ -44,6 +44,8 @@ struct usbhs_omap_board_data { struct regulator *regulator[OMAP3_HS_USB_PORTS]; }; +#ifdef CONFIG_ARCH_OMAP2PLUS + struct ehci_hcd_omap_platform_data { enum usbhs_omap_port_mode port_mode[OMAP3_HS_USB_PORTS]; int reset_gpio_port[OMAP3_HS_USB_PORTS]; @@ -64,26 +66,6 @@ struct usbhs_omap_platform_data { }; /*-------------------------------------------------------------------------*/ -#define OMAP1_OTG_BASE 0xfffb0400 -#define OMAP1_UDC_BASE 0xfffb4000 -#define OMAP1_OHCI_BASE 0xfffba000 - -#define OMAP2_OHCI_BASE 0x4805e000 -#define OMAP2_UDC_BASE 0x4805e200 -#define OMAP2_OTG_BASE 0x4805e300 - -#ifdef CONFIG_ARCH_OMAP1 - -#define OTG_BASE OMAP1_OTG_BASE -#define UDC_BASE OMAP1_UDC_BASE -#define OMAP_OHCI_BASE OMAP1_OHCI_BASE - -#else - -#define OTG_BASE OMAP2_OTG_BASE -#define UDC_BASE OMAP2_UDC_BASE -#define OMAP_OHCI_BASE OMAP2_OHCI_BASE - struct omap_musb_board_data { u8 interface_type; u8 mode; @@ -107,44 +89,6 @@ extern int omap4430_phy_init(struct device *dev); extern int omap4430_phy_exit(struct device *dev); extern int omap4430_phy_suspend(struct device *dev, int suspend); -/* - * NOTE: Please update omap USB drivers to use ioremap + read/write - */ - -#define OMAP2_L4_IO_OFFSET 0xb2000000 -#define OMAP2_L4_IO_ADDRESS(pa) IOMEM((pa) + OMAP2_L4_IO_OFFSET) - -static inline u8 omap_readb(u32 pa) -{ - return __raw_readb(OMAP2_L4_IO_ADDRESS(pa)); -} - -static inline u16 omap_readw(u32 pa) -{ - return __raw_readw(OMAP2_L4_IO_ADDRESS(pa)); -} - -static inline u32 omap_readl(u32 pa) -{ - return __raw_readl(OMAP2_L4_IO_ADDRESS(pa)); -} - -static inline void omap_writeb(u8 v, u32 pa) -{ - __raw_writeb(v, OMAP2_L4_IO_ADDRESS(pa)); -} - - -static inline void omap_writew(u16 v, u32 pa) -{ - __raw_writew(v, OMAP2_L4_IO_ADDRESS(pa)); -} - -static inline void omap_writel(u32 v, u32 pa) -{ - __raw_writel(v, OMAP2_L4_IO_ADDRESS(pa)); -} - #endif extern void am35x_musb_reset(void); @@ -153,142 +97,6 @@ extern void am35x_musb_clear_irq(void); extern void am35x_set_mode(u8 musb_mode); extern void ti81xx_musb_phy_power(u8 on); -/* - * FIXME correct answer depends on hmc_mode, - * as does (on omap1) any nonzero value for config->otg port number - */ -#ifdef CONFIG_USB_GADGET_OMAP -#define is_usb0_device(config) 1 -#else -#define is_usb0_device(config) 0 -#endif - -void omap_otg_init(struct omap_usb_config *config); - -#if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE) -void omap1_usb_init(struct omap_usb_config *pdata); -#else -static inline void omap1_usb_init(struct omap_usb_config *pdata) -{ -} -#endif - -#if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP_OTG_MODULE) -void omap2_usbfs_init(struct omap_usb_config *pdata); -#else -static inline void omap2_usbfs_init(struct omap_usb_config *pdata) -{ -} -#endif - -/*-------------------------------------------------------------------------*/ - -/* - * OTG and transceiver registers, for OMAPs starting with ARM926 - */ -#define OTG_REV (OTG_BASE + 0x00) -#define OTG_SYSCON_1 (OTG_BASE + 0x04) -# define USB2_TRX_MODE(w) (((w)>>24)&0x07) -# define USB1_TRX_MODE(w) (((w)>>20)&0x07) -# define USB0_TRX_MODE(w) (((w)>>16)&0x07) -# define OTG_IDLE_EN (1 << 15) -# define HST_IDLE_EN (1 << 14) -# define DEV_IDLE_EN (1 << 13) -# define OTG_RESET_DONE (1 << 2) -# define OTG_SOFT_RESET (1 << 1) -#define OTG_SYSCON_2 (OTG_BASE + 0x08) -# define OTG_EN (1 << 31) -# define USBX_SYNCHRO (1 << 30) -# define OTG_MST16 (1 << 29) -# define SRP_GPDATA (1 << 28) -# define SRP_GPDVBUS (1 << 27) -# define SRP_GPUVBUS(w) (((w)>>24)&0x07) -# define A_WAIT_VRISE(w) (((w)>>20)&0x07) -# define B_ASE_BRST(w) (((w)>>16)&0x07) -# define SRP_DPW (1 << 14) -# define SRP_DATA (1 << 13) -# define SRP_VBUS (1 << 12) -# define OTG_PADEN (1 << 10) -# define HMC_PADEN (1 << 9) -# define UHOST_EN (1 << 8) -# define HMC_TLLSPEED (1 << 7) -# define HMC_TLLATTACH (1 << 6) -# define OTG_HMC(w) (((w)>>0)&0x3f) -#define OTG_CTRL (OTG_BASE + 0x0c) -# define OTG_USB2_EN (1 << 29) -# define OTG_USB2_DP (1 << 28) -# define OTG_USB2_DM (1 << 27) -# define OTG_USB1_EN (1 << 26) -# define OTG_USB1_DP (1 << 25) -# define OTG_USB1_DM (1 << 24) -# define OTG_USB0_EN (1 << 23) -# define OTG_USB0_DP (1 << 22) -# define OTG_USB0_DM (1 << 21) -# define OTG_ASESSVLD (1 << 20) -# define OTG_BSESSEND (1 << 19) -# define OTG_BSESSVLD (1 << 18) -# define OTG_VBUSVLD (1 << 17) -# define OTG_ID (1 << 16) -# define OTG_DRIVER_SEL (1 << 15) -# define OTG_A_SETB_HNPEN (1 << 12) -# define OTG_A_BUSREQ (1 << 11) -# define OTG_B_HNPEN (1 << 9) -# define OTG_B_BUSREQ (1 << 8) -# define OTG_BUSDROP (1 << 7) -# define OTG_PULLDOWN (1 << 5) -# define OTG_PULLUP (1 << 4) -# define OTG_DRV_VBUS (1 << 3) -# define OTG_PD_VBUS (1 << 2) -# define OTG_PU_VBUS (1 << 1) -# define OTG_PU_ID (1 << 0) -#define OTG_IRQ_EN (OTG_BASE + 0x10) /* 16-bit */ -# define DRIVER_SWITCH (1 << 15) -# define A_VBUS_ERR (1 << 13) -# define A_REQ_TMROUT (1 << 12) -# define A_SRP_DETECT (1 << 11) -# define B_HNP_FAIL (1 << 10) -# define B_SRP_TMROUT (1 << 9) -# define B_SRP_DONE (1 << 8) -# define B_SRP_STARTED (1 << 7) -# define OPRT_CHG (1 << 0) -#define OTG_IRQ_SRC (OTG_BASE + 0x14) /* 16-bit */ - // same bits as in IRQ_EN -#define OTG_OUTCTRL (OTG_BASE + 0x18) /* 16-bit */ -# define OTGVPD (1 << 14) -# define OTGVPU (1 << 13) -# define OTGPUID (1 << 12) -# define USB2VDR (1 << 10) -# define USB2PDEN (1 << 9) -# define USB2PUEN (1 << 8) -# define USB1VDR (1 << 6) -# define USB1PDEN (1 << 5) -# define USB1PUEN (1 << 4) -# define USB0VDR (1 << 2) -# define USB0PDEN (1 << 1) -# define USB0PUEN (1 << 0) -#define OTG_TEST (OTG_BASE + 0x20) /* 16-bit */ -#define OTG_VENDOR_CODE (OTG_BASE + 0xfc) /* 16-bit */ - -/*-------------------------------------------------------------------------*/ - -/* OMAP1 */ -#define USB_TRANSCEIVER_CTRL (0xfffe1000 + 0x0064) -# define CONF_USB2_UNI_R (1 << 8) -# define CONF_USB1_UNI_R (1 << 7) -# define CONF_USB_PORT0_R(x) (((x)>>4)&0x7) -# define CONF_USB0_ISOLATE_R (1 << 3) -# define CONF_USB_PWRDN_DM_R (1 << 2) -# define CONF_USB_PWRDN_DP_R (1 << 1) - -/* OMAP2 */ -# define USB_UNIDIR 0x0 -# define USB_UNIDIR_TLL 0x1 -# define USB_BIDIR 0x2 -# define USB_BIDIR_TLL 0x3 -# define USBTXWRMODEI(port, x) ((x) << (22 - (port * 2))) -# define USBT2TLL5PI (1 << 17) -# define USB0PUENACTLOI (1 << 16) -# define USBSTANDBYCTRL (1 << 15) /* AM35x */ /* USB 2.0 PHY Control */ #define CONF2_PHY_GPIOMODE (1 << 23) diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c deleted file mode 100644 index daa0327381b5..000000000000 --- a/arch/arm/plat-omap/usb.c +++ /dev/null @@ -1,145 +0,0 @@ - /* - * arch/arm/plat-omap/usb.c -- platform level USB initialization - * - * Copyright (C) 2004 Texas Instruments, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#undef DEBUG - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#ifdef CONFIG_ARCH_OMAP_OTG - -void __init -omap_otg_init(struct omap_usb_config *config) -{ - u32 syscon; - int alt_pingroup = 0; - - /* NOTE: no bus or clock setup (yet?) */ - - syscon = omap_readl(OTG_SYSCON_1) & 0xffff; - if (!(syscon & OTG_RESET_DONE)) - pr_debug("USB resets not complete?\n"); - - //omap_writew(0, OTG_IRQ_EN); - - /* pin muxing and transceiver pinouts */ - if (config->pins[0] > 2) /* alt pingroup 2 */ - alt_pingroup = 1; - syscon |= config->usb0_init(config->pins[0], is_usb0_device(config)); - syscon |= config->usb1_init(config->pins[1]); - syscon |= config->usb2_init(config->pins[2], alt_pingroup); - pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1)); - omap_writel(syscon, OTG_SYSCON_1); - - syscon = config->hmc_mode; - syscon |= USBX_SYNCHRO | (4 << 16) /* B_ASE0_BRST */; -#ifdef CONFIG_USB_OTG - if (config->otg) - syscon |= OTG_EN; -#endif - if (cpu_class_is_omap1()) - pr_debug("USB_TRANSCEIVER_CTRL = %03x\n", - omap_readl(USB_TRANSCEIVER_CTRL)); - pr_debug("OTG_SYSCON_2 = %08x\n", omap_readl(OTG_SYSCON_2)); - omap_writel(syscon, OTG_SYSCON_2); - - printk("USB: hmc %d", config->hmc_mode); - if (!alt_pingroup) - printk(", usb2 alt %d wires", config->pins[2]); - else if (config->pins[0]) - printk(", usb0 %d wires%s", config->pins[0], - is_usb0_device(config) ? " (dev)" : ""); - if (config->pins[1]) - printk(", usb1 %d wires", config->pins[1]); - if (!alt_pingroup && config->pins[2]) - printk(", usb2 %d wires", config->pins[2]); - if (config->otg) - printk(", Mini-AB on usb%d", config->otg - 1); - printk("\n"); - - if (cpu_class_is_omap1()) { - u16 w; - - /* leave USB clocks/controllers off until needed */ - w = omap_readw(ULPD_SOFT_REQ); - w &= ~SOFT_USB_CLK_REQ; - omap_writew(w, ULPD_SOFT_REQ); - - w = omap_readw(ULPD_CLOCK_CTRL); - w &= ~USB_MCLK_EN; - w |= DIS_USB_PVCI_CLK; - omap_writew(w, ULPD_CLOCK_CTRL); - } - syscon = omap_readl(OTG_SYSCON_1); - syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN; - -#ifdef CONFIG_USB_GADGET_OMAP - if (config->otg || config->register_dev) { - struct platform_device *udc_device = config->udc_device; - int status; - - syscon &= ~DEV_IDLE_EN; - udc_device->dev.platform_data = config; - status = platform_device_register(udc_device); - if (status) - pr_debug("can't register UDC device, %d\n", status); - } -#endif - -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - if (config->otg || config->register_host) { - struct platform_device *ohci_device = config->ohci_device; - int status; - - syscon &= ~HST_IDLE_EN; - ohci_device->dev.platform_data = config; - status = platform_device_register(ohci_device); - if (status) - pr_debug("can't register OHCI device, %d\n", status); - } -#endif - -#ifdef CONFIG_USB_OTG - if (config->otg) { - struct platform_device *otg_device = config->otg_device; - int status; - - syscon &= ~OTG_IDLE_EN; - otg_device->dev.platform_data = config; - status = platform_device_register(otg_device); - if (status) - pr_debug("can't register OTG device, %d\n", status); - } -#endif - pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1)); - omap_writel(syscon, OTG_SYSCON_1); -} - -#else -void omap_otg_init(struct omap_usb_config *config) {} -#endif diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index bddc8fd9a7be..271ca161d7ef 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -185,7 +185,7 @@ config USB_FUSB300 config USB_OMAP tristate "OMAP USB Device Controller" - depends on ARCH_OMAP + depends on ARCH_OMAP1 select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG select USB_OTG_UTILS if ARCH_OMAP help diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 7ba32469c5bd..2acf06cd9225 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -44,7 +44,8 @@ #include #include -#include + +#include #include "omap_udc.h" diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 83e58df29fe3..dcfaaa91a3fb 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -308,7 +308,7 @@ config USB_OHCI_HCD config USB_OHCI_HCD_OMAP1 bool "OHCI support for OMAP1/2 chips" - depends on USB_OHCI_HCD && (ARCH_OMAP1 || ARCH_OMAP2) + depends on USB_OHCI_HCD && ARCH_OMAP1 default y ---help--- Enables support for the OHCI controller on OMAP1/2 chips. diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 9ce35d0d9d5d..b02c344e2cc9 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -20,14 +20,15 @@ #include #include -#include #include #include #include -#include #include -#include + +#include +#include +#include /* OMAP-1510 OHCI has its own MMU for DMA */ diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index 70cf5d7bca48..e0558dfcfafc 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c @@ -36,9 +36,9 @@ #include #include -#include #include +#include #ifndef DEBUG #undef VERBOSE -- cgit v1.2.3 From 4d04317f6efab7359ae56e50cc9c60e9804b5015 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 4 Jun 2012 00:13:25 -0700 Subject: ARM: OMAP: Fix lis3lv02d accelerometer to use gpio_to_irq Commit 3b511201 (ARM: OMAP: rx51: Platform support for lis3lv02d accelerometer) added support for lis3lv02d accelerometer. The patch was still using OMAP_GPIO_IRQ which no longer exists. Fix it by using gpio_to_irq(). Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-rx51-peripherals.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index ff53deccecab..df2534de3361 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -144,7 +144,6 @@ static struct lis3lv02d_platform_data rx51_lis3lv02d_data = { .release_resources = lis302_release, .st_min_limits = {-32, 3, 3}, .st_max_limits = {-3, 32, 32}, - .irq2 = OMAP_GPIO_IRQ(LIS302_IRQ2_GPIO), }; #endif @@ -1030,7 +1029,6 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_3[] = { { I2C_BOARD_INFO("lis3lv02d", 0x1d), .platform_data = &rx51_lis3lv02d_data, - .irq = OMAP_GPIO_IRQ(LIS302_IRQ1_GPIO), }, #endif }; @@ -1056,6 +1054,10 @@ static int __init rx51_i2c_init(void) omap_pmic_init(1, 2200, "twl5030", INT_34XX_SYS_NIRQ, &rx51_twldata); omap_register_i2c_bus(2, 100, rx51_peripherals_i2c_board_info_2, ARRAY_SIZE(rx51_peripherals_i2c_board_info_2)); +#if defined(CONFIG_SENSORS_LIS3_I2C) || defined(CONFIG_SENSORS_LIS3_I2C_MODULE) + rx51_lis3lv02d_data.irq2 = gpio_to_irq(LIS302_IRQ2_GPIO); + rx51_peripherals_i2c_board_info_3[0].irq = gpio_to_irq(LIS302_IRQ1_GPIO); +#endif omap_register_i2c_bus(3, 400, rx51_peripherals_i2c_board_info_3, ARRAY_SIZE(rx51_peripherals_i2c_board_info_3)); return 0; -- cgit v1.2.3 From 6cc90d6de16532fe68b54ee6967894f7ca83affa Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 4 Jun 2012 12:21:21 +0200 Subject: ARM i.MX pllv2: use standard register set unconditionally The i.MX5 PLL has two different register sets for setting the rate. One is used for the standard case and and is used for DVFS. Which one of them is used depends on a hardware input of the PLL. Current implementation reads back from the hardware which setting is used. This is bogus: If we ever want to implement DVFS we have to program both register sets and not only the one which happens to be used at the moment. For now, just use the standard register set uncondionally. Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/clk-pllv2.c | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/clk-pllv2.c b/arch/arm/mach-imx/clk-pllv2.c index 4685919deb63..1b0307195a6e 100644 --- a/arch/arm/mach-imx/clk-pllv2.c +++ b/arch/arm/mach-imx/clk-pllv2.c @@ -78,7 +78,7 @@ static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { long mfi, mfn, mfd, pdf, ref_clk, mfn_abs; - unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl; + unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, dbl; void __iomem *pllbase; s64 temp; struct clk_pllv2 *pll = to_clk_pllv2(hw); @@ -86,18 +86,12 @@ static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw, pllbase = pll->base; dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); - pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM; dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN; - if (pll_hfsm == 0) { - dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP); - dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD); - dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN); - } else { - dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP); - dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD); - dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN); - } + dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP); + dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD); + dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN); + pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK; mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET; mfi = (mfi <= 5) ? 5 : mfi; @@ -132,7 +126,7 @@ static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, long mfi, pdf, mfn, mfd = 999999; s64 temp64; unsigned long quad_parent_rate; - unsigned long pll_hfsm, dp_ctl; + unsigned long dp_ctl; pllbase = pll->base; @@ -151,18 +145,11 @@ static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); /* use dpdck0_2 */ __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL); - pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM; - if (pll_hfsm == 0) { - reg = mfi << 4 | pdf; - __raw_writel(reg, pllbase + MXC_PLL_DP_OP); - __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD); - __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN); - } else { - reg = mfi << 4 | pdf; - __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP); - __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD); - __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN); - } + + reg = mfi << 4 | pdf; + __raw_writel(reg, pllbase + MXC_PLL_DP_OP); + __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD); + __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN); return 0; } -- cgit v1.2.3 From 9ca41bccc39f5ebbbb515dfadb2e0f912168c8bd Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 4 Jun 2012 14:51:32 +0200 Subject: ARM i.MX pllv2: make round_rate accurate in round_rate we made the assumption that we can set arbitrary frequencies and thus returned the input rate. This is not correct, for certain frequencies after setting a frequency with set_rate, recalc_rate will return different values. To fix this, introduce set_rate/recalc_rate functions which work on variables instead of registers directly. This way we can call these in round_rate to get the exact rate which we would get if we call set_rate with this value. Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/clk-pllv2.c | 78 ++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 24 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/clk-pllv2.c b/arch/arm/mach-imx/clk-pllv2.c index 1b0307195a6e..0440379e3628 100644 --- a/arch/arm/mach-imx/clk-pllv2.c +++ b/arch/arm/mach-imx/clk-pllv2.c @@ -74,24 +74,15 @@ struct clk_pllv2 { void __iomem *base; }; -static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) +static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate, + u32 dp_ctl, u32 dp_op, u32 dp_mfd, u32 dp_mfn) { long mfi, mfn, mfd, pdf, ref_clk, mfn_abs; - unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, dbl; - void __iomem *pllbase; + unsigned long dbl; s64 temp; - struct clk_pllv2 *pll = to_clk_pllv2(hw); - - pllbase = pll->base; - dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN; - dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP); - dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD); - dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN); - pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK; mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET; mfi = (mfi <= 5) ? 5 : mfi; @@ -117,18 +108,30 @@ static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw, return temp; } -static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, +static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { + u32 dp_op, dp_mfd, dp_mfn, dp_ctl; + void __iomem *pllbase; struct clk_pllv2 *pll = to_clk_pllv2(hw); + + pllbase = pll->base; + + dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); + dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP); + dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD); + dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN); + + return __clk_pllv2_recalc_rate(parent_rate, dp_ctl, dp_op, dp_mfd, dp_mfn); +} + +static int __clk_pllv2_set_rate(unsigned long rate, unsigned long parent_rate, + u32 *dp_op, u32 *dp_mfd, u32 *dp_mfn) +{ u32 reg; - void __iomem *pllbase; long mfi, pdf, mfn, mfd = 999999; s64 temp64; unsigned long quad_parent_rate; - unsigned long dp_ctl; - - pllbase = pll->base; quad_parent_rate = 4 * parent_rate; pdf = mfi = -1; @@ -138,18 +141,41 @@ static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, return -EINVAL; pdf--; - temp64 = rate * (pdf+1) - quad_parent_rate * mfi; - do_div(temp64, quad_parent_rate/1000000); + temp64 = rate * (pdf + 1) - quad_parent_rate * mfi; + do_div(temp64, quad_parent_rate / 1000000); mfn = (long)temp64; + reg = mfi << 4 | pdf; + + *dp_op = reg; + *dp_mfd = mfd; + *dp_mfn = mfn; + + return 0; +} + +static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_pllv2 *pll = to_clk_pllv2(hw); + void __iomem *pllbase; + u32 dp_ctl, dp_op, dp_mfd, dp_mfn; + int ret; + + pllbase = pll->base; + + + ret = __clk_pllv2_set_rate(rate, parent_rate, &dp_op, &dp_mfd, &dp_mfn); + if (ret) + return ret; + dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); /* use dpdck0_2 */ __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL); - reg = mfi << 4 | pdf; - __raw_writel(reg, pllbase + MXC_PLL_DP_OP); - __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD); - __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN); + __raw_writel(dp_op, pllbase + MXC_PLL_DP_OP); + __raw_writel(dp_mfd, pllbase + MXC_PLL_DP_MFD); + __raw_writel(dp_mfn, pllbase + MXC_PLL_DP_MFN); return 0; } @@ -157,7 +183,11 @@ static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, static long clk_pllv2_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - return rate; + u32 dp_op, dp_mfd, dp_mfn; + + __clk_pllv2_set_rate(rate, *prate, &dp_op, &dp_mfd, &dp_mfn); + return __clk_pllv2_recalc_rate(*prate, MXC_PLL_DP_CTL_DPDCK0_2_EN, + dp_op, dp_mfd, dp_mfn); } static int clk_pllv2_prepare(struct clk_hw *hw) -- cgit v1.2.3 From cdd781ab1906d039c2a93078385645d2d5af8491 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 4 Jun 2012 14:58:07 +0200 Subject: ARM i.MX53: Fix PLL4 base address MX53_DPLL4_BASE accidently returned the base address of PLL3. Fix this. Signed-off-by: Sascha Hauer Cc: stable@vger.kernel.org --- arch/arm/mach-imx/crm-regs-imx5.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/crm-regs-imx5.h b/arch/arm/mach-imx/crm-regs-imx5.h index 5e11ba7daee2..5e3f1f0f4cab 100644 --- a/arch/arm/mach-imx/crm-regs-imx5.h +++ b/arch/arm/mach-imx/crm-regs-imx5.h @@ -23,7 +23,7 @@ #define MX53_DPLL1_BASE MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR) #define MX53_DPLL2_BASE MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR) #define MX53_DPLL3_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR) -#define MX53_DPLL4_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR) +#define MX53_DPLL4_BASE MX53_IO_ADDRESS(MX53_PLL4_BASE_ADDR) /* PLL Register Offsets */ #define MXC_PLL_DP_CTL 0x00 -- cgit v1.2.3 From 76eb9a30db4bc8fd172f9155247264b5f2686d7b Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 20 Feb 2012 14:20:06 +0800 Subject: ACPI, x86: fix Dell M6600 ACPI reboot regression via DMI Dell Precision M6600 is known to require PCI reboot, so add it to the reboot blacklist in pci_reboot_dmi_table[]. https://bugzilla.kernel.org/show_bug.cgi?id=42749 cc: x86@kernel.org Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- arch/x86/kernel/reboot.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 79c45af81604..412db5716d91 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -451,6 +451,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"), }, }, + { /* Handle problems with rebooting on the Precision M6600. */ + .callback = set_pci_reboot, + .ident = "Dell OptiPlex 990", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"), + }, + }, { } }; -- cgit v1.2.3 From 2ce2e4b2b56dd564d27e7aadb92ed0c2342a9c57 Mon Sep 17 00:00:00 2001 From: Robert Lee Date: Mon, 21 May 2012 17:50:24 -0500 Subject: ARM: imx: Modify IMX_IO_P2V macro A change is needed in the IMX_IO_P2V macro to allow all imx5 platforms to use common definitions when accessing registers of peripherals on the AIPS2 bus. With this change, IMX_IO_P2V(MX50_AIPS2_BASE_ADDR) == IMX_IO_P2V(MX51_AIPS2_BASE_ADDR) == IMX_IO_P2V(MX53_AIPS2_BASE_ADDR). This change was tested for mapping conflicts using the iop2v script found at git://git.pengutronix.de/git/ukl/imx-iop2v.git and by performing a bootup of a default build using imx_v6_v7_defconfig on a imx51 babbage board and imx53 loco board. The comments were modified to reflect the output given by the script which shows the virtual address mappings. Signed-off-by: Robert Lee Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/include/mach/hardware.h | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h index 0630513554de..071afd0b9283 100644 --- a/arch/arm/plat-mxc/include/mach/hardware.h +++ b/arch/arm/plat-mxc/include/mach/hardware.h @@ -50,7 +50,7 @@ * IO 0x00200000+0x100000 -> 0xf4000000+0x100000 * mx21: * AIPI 0x10000000+0x100000 -> 0xf4400000+0x100000 - * SAHB1 0x80000000+0x100000 -> 0xf4000000+0x100000 + * SAHB1 0x80000000+0x100000 -> 0xf5000000+0x100000 * X_MEMC 0xdf000000+0x004000 -> 0xf5f00000+0x004000 * mx25: * AIPS1 0x43f00000+0x100000 -> 0xf5300000+0x100000 @@ -58,47 +58,50 @@ * AVIC 0x68000000+0x100000 -> 0xf5800000+0x100000 * mx27: * AIPI 0x10000000+0x100000 -> 0xf4400000+0x100000 - * SAHB1 0x80000000+0x100000 -> 0xf4000000+0x100000 + * SAHB1 0x80000000+0x100000 -> 0xf5000000+0x100000 * X_MEMC 0xd8000000+0x100000 -> 0xf5c00000+0x100000 * mx31: * AIPS1 0x43f00000+0x100000 -> 0xf5300000+0x100000 * AIPS2 0x53f00000+0x100000 -> 0xf5700000+0x100000 * AVIC 0x68000000+0x100000 -> 0xf5800000+0x100000 - * X_MEMC 0xb8000000+0x010000 -> 0xf4c00000+0x010000 + * X_MEMC 0xb8000000+0x010000 -> 0xf5c00000+0x010000 * SPBA0 0x50000000+0x100000 -> 0xf5400000+0x100000 * mx35: * AIPS1 0x43f00000+0x100000 -> 0xf5300000+0x100000 * AIPS2 0x53f00000+0x100000 -> 0xf5700000+0x100000 * AVIC 0x68000000+0x100000 -> 0xf5800000+0x100000 - * X_MEMC 0xb8000000+0x010000 -> 0xf4c00000+0x010000 + * X_MEMC 0xb8000000+0x010000 -> 0xf5c00000+0x010000 * SPBA0 0x50000000+0x100000 -> 0xf5400000+0x100000 * mx50: * TZIC 0x0fffc000+0x004000 -> 0xf4bfc000+0x004000 - * SPBA0 0x50000000+0x100000 -> 0xf5400000+0x100000 * AIPS1 0x53f00000+0x100000 -> 0xf5700000+0x100000 + * SPBA0 0x50000000+0x100000 -> 0xf5400000+0x100000 * AIPS2 0x63f00000+0x100000 -> 0xf5300000+0x100000 * mx51: - * TZIC 0xe0000000+0x004000 -> 0xf5000000+0x004000 + * TZIC 0x0fffc000+0x004000 -> 0xf4bfc000+0x004000 * IRAM 0x1ffe0000+0x020000 -> 0xf4fe0000+0x020000 + * DEBUG 0x60000000+0x100000 -> 0xf5000000+0x100000 * SPBA0 0x70000000+0x100000 -> 0xf5400000+0x100000 * AIPS1 0x73f00000+0x100000 -> 0xf5700000+0x100000 - * AIPS2 0x83f00000+0x100000 -> 0xf4300000+0x100000 + * AIPS2 0x83f00000+0x100000 -> 0xf5300000+0x100000 * mx53: * TZIC 0x0fffc000+0x004000 -> 0xf4bfc000+0x004000 + * DEBUG 0x40000000+0x100000 -> 0xf5000000+0x100000 * SPBA0 0x50000000+0x100000 -> 0xf5400000+0x100000 * AIPS1 0x53f00000+0x100000 -> 0xf5700000+0x100000 * AIPS2 0x63f00000+0x100000 -> 0xf5300000+0x100000 * mx6q: - * SCU 0x00a00000+0x001000 -> 0xf4000000+0x001000 + * SCU 0x00a00000+0x004000 -> 0xf4000000+0x004000 * CCM 0x020c4000+0x004000 -> 0xf42c4000+0x004000 - * ANATOP 0x020c8000+0x001000 -> 0xf42c8000+0x001000 + * ANATOP 0x020c8000+0x004000 -> 0xf42c8000+0x004000 * UART4 0x021f0000+0x004000 -> 0xf42f0000+0x004000 */ #define IMX_IO_P2V(x) ( \ - 0xf4000000 + \ + (((x) & 0x80000000) >> 7) | \ + (0xf4000000 + \ (((x) & 0x50000000) >> 6) + \ (((x) & 0x0b000000) >> 4) + \ - (((x) & 0x000fffff))) + (((x) & 0x000fffff)))) #define IMX_IO_ADDRESS(x) IOMEM(IMX_IO_P2V(x)) -- cgit v1.2.3 From eee4f4003824b0887251a3ba4493217371816a57 Mon Sep 17 00:00:00 2001 From: Robert Lee Date: Mon, 21 May 2012 17:50:25 -0500 Subject: ARM: imx: Add comments to tzic_enable_waker() Add additional comments to the tzic_enable_wake() funciton to clarify its intended usage. Signed-off-by: Robert Lee Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/tzic.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c index 98308ec1f321..a45dbea5e176 100644 --- a/arch/arm/plat-mxc/tzic.c +++ b/arch/arm/plat-mxc/tzic.c @@ -190,6 +190,10 @@ void __init tzic_init_irq(void __iomem *irqbase) * tzic_enable_wake() - enable wakeup interrupt * * @return 0 if successful; non-zero otherwise + * + * This function provides an interrupt synchronization point that is required + * by tzic enabled platforms before entering imx specific low power modes (ie, + * those low power modes beyond the WAIT_CLOCKED basic ARM WFI only mode). */ int tzic_enable_wake(void) { -- cgit v1.2.3 From 565fa91f236524b6ba4872903dc9cc9c874493e6 Mon Sep 17 00:00:00 2001 From: Robert Lee Date: Mon, 21 May 2012 17:50:26 -0500 Subject: ARM: imx: clean and consolidate imx5 suspend and idle code The imx5 idle code that existed in mm-imx5.c is moved to pm-imx5.c. The imx5_pm_init call is now exported and called during the MACHINE_START late_init in supported imx5 platforms. Remove various enabling/disabling of the gpc_dvfs clock and enable it once during initialization. This is a very low power clock that must be enabled during low power operations. There are only two "suspend_state_t" imx5 low power modes ever used. STOP_POWER_OFF for suspend to mem and WAIT_UNCLOCKED_POWER_OFF for idle and suspend to standby. The latter mode only requires 500 nanoseconds of extra hardware exit time beyond a basic WFI operation (WAIT_CLOCKED mode) so no other idle mode is necessary. Given this information, it is more efficient to keep the registers in the often used WAIT_UNCLOCKED_POWER_OFF state and only to and from the STOP_POWER_OFF register state as needed when suspend to mem is required. Signed-off-by: Robert Lee Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/mm-imx5.c | 21 +---------- arch/arm/mach-imx/pm-imx5.c | 67 ++++++++++++++++++++------------- arch/arm/plat-mxc/include/mach/common.h | 3 +- 3 files changed, 44 insertions(+), 47 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c index feeee17da96b..d84421e1467d 100644 --- a/arch/arm/mach-imx/mm-imx5.c +++ b/arch/arm/mach-imx/mm-imx5.c @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -24,24 +23,6 @@ #include #include -static struct clk *gpc_dvfs_clk; - -static void imx5_idle(void) -{ - /* gpc clock is needed for SRPG */ - if (gpc_dvfs_clk == NULL) { - gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs"); - if (IS_ERR(gpc_dvfs_clk)) - return; - clk_prepare(gpc_dvfs_clk); - } - clk_enable(gpc_dvfs_clk); - mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); - if (!tzic_enable_wake()) - cpu_do_idle(); - clk_disable(gpc_dvfs_clk); -} - /* * Define the MX50 memory map. */ @@ -105,7 +86,6 @@ void __init imx51_init_early(void) mxc_set_cpu_type(MXC_CPU_MX51); mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR)); mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR)); - arm_pm_idle = imx5_idle; } void __init imx53_init_early(void) @@ -241,4 +221,5 @@ void __init imx53_soc_init(void) void __init imx51_init_late(void) { mx51_neon_fixup(); + imx51_pm_init(); } diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c index e26a9cb05ed8..baf93214f899 100644 --- a/arch/arm/mach-imx/pm-imx5.c +++ b/arch/arm/mach-imx/pm-imx5.c @@ -13,18 +13,27 @@ #include #include #include +#include #include #include #include #include "crm-regs-imx5.h" -static struct clk *gpc_dvfs_clk; +/* + * The WAIT_UNCLOCKED_POWER_OFF state only requires <= 500ns to exit. + * This is also the lowest power state possible without affecting + * non-cpu parts of the system. For these reasons, imx5 should default + * to always using this state for cpu idling. The PM_SUSPEND_STANDBY also + * uses this state and needs to take no action when registers remain confgiured + * for this state. + */ +#define IMX5_DEFAULT_CPU_IDLE_STATE WAIT_UNCLOCKED_POWER_OFF /* * set cpu low power mode before WFI instruction. This function is called * mx5 because it can be used for mx50, mx51, and mx53. */ -void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode) +static void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode) { u32 plat_lpc, arm_srpgcr, ccm_clpcr; u32 empgc0, empgc1; @@ -87,11 +96,6 @@ void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode) } } -static int mx5_suspend_prepare(void) -{ - return clk_prepare_enable(gpc_dvfs_clk); -} - static int mx5_suspend_enter(suspend_state_t state) { switch (state) { @@ -99,7 +103,7 @@ static int mx5_suspend_enter(suspend_state_t state) mx5_cpu_lp_set(STOP_POWER_OFF); break; case PM_SUSPEND_STANDBY: - mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); + /* DEFAULT_IDLE_STATE already configured */ break; default: return -EINVAL; @@ -114,12 +118,10 @@ static int mx5_suspend_enter(suspend_state_t state) __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR); } cpu_do_idle(); - return 0; -} -static void mx5_suspend_finish(void) -{ - clk_disable_unprepare(gpc_dvfs_clk); + /* return registers to default idle state */ + mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE); + return 0; } static int mx5_pm_valid(suspend_state_t state) @@ -129,25 +131,38 @@ static int mx5_pm_valid(suspend_state_t state) static const struct platform_suspend_ops mx5_suspend_ops = { .valid = mx5_pm_valid, - .prepare = mx5_suspend_prepare, .enter = mx5_suspend_enter, - .finish = mx5_suspend_finish, }; -static int __init mx5_pm_init(void) +static void imx5_pm_idle(void) { - if (!cpu_is_mx51() && !cpu_is_mx53()) - return 0; + if (likely(!tzic_enable_wake())) + cpu_do_idle(); +} + +static int __init imx5_pm_common_init(void) +{ + int ret; + struct clk *gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs"); + + if (IS_ERR(gpc_dvfs_clk)) + return PTR_ERR(gpc_dvfs_clk); - if (gpc_dvfs_clk == NULL) - gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs"); + ret = clk_prepare_enable(gpc_dvfs_clk); + if (ret) + return ret; - if (!IS_ERR(gpc_dvfs_clk)) { - if (cpu_is_mx51()) - suspend_set_ops(&mx5_suspend_ops); - } else - return -EPERM; + arm_pm_idle = imx5_pm_idle; + + /* Set the registers to the default cpu idle state. */ + mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE); return 0; } -device_initcall(mx5_pm_init); + +void __init imx51_pm_init(void) +{ + int ret = imx5_pm_common_init(); + if (!ret) + suspend_set_ops(&mx5_suspend_ops); +} diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index cf663d84e7c1..f65d068e1820 100644 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -95,7 +95,6 @@ enum mx3_cpu_pwr_mode { }; extern void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode); -extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode); extern void imx_print_silicon_rev(const char *cpu, int srev); void avic_handle_irq(struct pt_regs *); @@ -146,8 +145,10 @@ extern void imx6q_clock_map_io(void); #ifdef CONFIG_PM extern void imx6q_pm_init(void); +extern void imx51_pm_init(void); #else static inline void imx6q_pm_init(void) {} +static inline void imx51_pm_init(void) {} #endif #ifdef CONFIG_NEON -- cgit v1.2.3 From aa96a18d22dc7ad4dbc98cb0f4b2967a9fc979ca Mon Sep 17 00:00:00 2001 From: Robert Lee Date: Mon, 21 May 2012 17:50:27 -0500 Subject: ARM: imx: Enable imx53 low power idle Add various functionality needed to enable a imx53 low power idle state. This includes adding the imx53 gpc_dvfs clock and making a common imx5_late_init function and initializing all imx53 MACHINE_STATE late_init calls to imx5_late_init. Signed-off-by: Robert Lee Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/clk-imx51-imx53.c | 2 +- arch/arm/mach-imx/imx53-dt.c | 1 + arch/arm/mach-imx/mach-mx53_ard.c | 1 + arch/arm/mach-imx/mach-mx53_evk.c | 1 + arch/arm/mach-imx/mach-mx53_loco.c | 1 + arch/arm/mach-imx/mach-mx53_smd.c | 1 + arch/arm/mach-imx/mm-imx5.c | 5 +++++ arch/arm/mach-imx/pm-imx5.c | 5 +++++ arch/arm/plat-mxc/include/mach/common.h | 3 +++ 9 files changed, 19 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c index fcd94f3b0f0e..8a2e7194b221 100644 --- a/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/arch/arm/mach-imx/clk-imx51-imx53.c @@ -279,6 +279,7 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk_register_clkdev(clk[dummy], NULL, "imx-keypad"); clk_register_clkdev(clk[tve_gate], NULL, "imx-tve.0"); clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx-tve.0"); + clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL); /* Set SDHC parents to be PLL2 */ clk_set_parent(clk[esdhc_a_sel], clk[pll2_sw]); @@ -336,7 +337,6 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, clk_register_clkdev(clk[mx51_mipi], "mipi_hsp", NULL); clk_register_clkdev(clk[vpu_gate], NULL, "imx51-vpu.0"); clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0"); - clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL); clk_register_clkdev(clk[ipu_gate], "bus", "imx51-ipu"); clk_register_clkdev(clk[ipu_di0_gate], "di0", "imx51-ipu"); clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx51-ipu"); diff --git a/arch/arm/mach-imx/imx53-dt.c b/arch/arm/mach-imx/imx53-dt.c index eb04b6248e48..481c3e96ad7f 100644 --- a/arch/arm/mach-imx/imx53-dt.c +++ b/arch/arm/mach-imx/imx53-dt.c @@ -147,6 +147,7 @@ DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)") .handle_irq = imx53_handle_irq, .timer = &imx53_timer, .init_machine = imx53_dt_init, + .init_late = imx53_init_late, .dt_compat = imx53_dt_board_compat, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx53_ard.c b/arch/arm/mach-imx/mach-mx53_ard.c index 05641980dc5e..f1e83d6d2dfc 100644 --- a/arch/arm/mach-imx/mach-mx53_ard.c +++ b/arch/arm/mach-imx/mach-mx53_ard.c @@ -266,5 +266,6 @@ MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board") .handle_irq = imx53_handle_irq, .timer = &mx53_ard_timer, .init_machine = mx53_ard_board_init, + .init_late = imx53_init_late, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx53_evk.c b/arch/arm/mach-imx/mach-mx53_evk.c index 5a72188b9cdb..8387496ef5ec 100644 --- a/arch/arm/mach-imx/mach-mx53_evk.c +++ b/arch/arm/mach-imx/mach-mx53_evk.c @@ -174,5 +174,6 @@ MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board") .handle_irq = imx53_handle_irq, .timer = &mx53_evk_timer, .init_machine = mx53_evk_board_init, + .init_late = imx53_init_late, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx53_loco.c b/arch/arm/mach-imx/mach-mx53_loco.c index 37f67cac15a4..e266f3f0f080 100644 --- a/arch/arm/mach-imx/mach-mx53_loco.c +++ b/arch/arm/mach-imx/mach-mx53_loco.c @@ -316,5 +316,6 @@ MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board") .handle_irq = imx53_handle_irq, .timer = &mx53_loco_timer, .init_machine = mx53_loco_board_init, + .init_late = imx53_init_late, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx53_smd.c b/arch/arm/mach-imx/mach-mx53_smd.c index 8e972c5c3e13..4f4c1b93ea66 100644 --- a/arch/arm/mach-imx/mach-mx53_smd.c +++ b/arch/arm/mach-imx/mach-mx53_smd.c @@ -163,5 +163,6 @@ MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board") .handle_irq = imx53_handle_irq, .timer = &mx53_smd_timer, .init_machine = mx53_smd_board_init, + .init_late = imx53_init_late, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c index d84421e1467d..cc7e7ca52908 100644 --- a/arch/arm/mach-imx/mm-imx5.c +++ b/arch/arm/mach-imx/mm-imx5.c @@ -223,3 +223,8 @@ void __init imx51_init_late(void) mx51_neon_fixup(); imx51_pm_init(); } + +void __init imx53_init_late(void) +{ + imx53_pm_init(); +} diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c index baf93214f899..b3dcd8e50d5b 100644 --- a/arch/arm/mach-imx/pm-imx5.c +++ b/arch/arm/mach-imx/pm-imx5.c @@ -166,3 +166,8 @@ void __init imx51_pm_init(void) if (!ret) suspend_set_ops(&mx5_suspend_ops); } + +void __init imx53_pm_init(void) +{ + imx5_pm_common_init(); +} diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index f65d068e1820..3314e6952556 100644 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -54,6 +54,7 @@ extern void imx50_soc_init(void); extern void imx51_soc_init(void); extern void imx53_soc_init(void); extern void imx51_init_late(void); +extern void imx53_init_late(void); extern void epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq); extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int); extern int mx1_clocks_init(unsigned long fref); @@ -146,9 +147,11 @@ extern void imx6q_clock_map_io(void); #ifdef CONFIG_PM extern void imx6q_pm_init(void); extern void imx51_pm_init(void); +extern void imx53_pm_init(void); #else static inline void imx6q_pm_init(void) {} static inline void imx51_pm_init(void) {} +static inline void imx53_pm_init(void) {} #endif #ifdef CONFIG_NEON -- cgit v1.2.3 From 2da50e6284caadd92ded697e41fb200358f64261 Mon Sep 17 00:00:00 2001 From: Robert Lee Date: Mon, 21 May 2012 17:50:28 -0500 Subject: ARM: imx: Add common imx cpuidle init functionality. Add common cpuidle init functionality that can be used by various imx platforms. Signed-off-by: Robert Lee Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/Makefile | 1 + arch/arm/plat-mxc/cpuidle.c | 80 ++++++++++++++++++++++++++++++++ arch/arm/plat-mxc/include/mach/cpuidle.h | 22 +++++++++ 3 files changed, 103 insertions(+) create mode 100644 arch/arm/plat-mxc/cpuidle.c create mode 100644 arch/arm/plat-mxc/include/mach/cpuidle.h (limited to 'arch') diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index e81290c27c65..63b064b5c1d5 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_MXC_ULPI) += ulpi.o obj-$(CONFIG_MXC_USE_EPIT) += epit.o obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o +obj-$(CONFIG_CPU_IDLE) += cpuidle.o ifdef CONFIG_SND_IMX_SOC obj-y += ssi-fiq.o obj-y += ssi-fiq-ksym.o diff --git a/arch/arm/plat-mxc/cpuidle.c b/arch/arm/plat-mxc/cpuidle.c new file mode 100644 index 000000000000..d4cb511a44a8 --- /dev/null +++ b/arch/arm/plat-mxc/cpuidle.c @@ -0,0 +1,80 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright 2012 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include + +static struct cpuidle_device __percpu * imx_cpuidle_devices; + +static void __init imx_cpuidle_devices_uninit(void) +{ + int cpu_id; + struct cpuidle_device *dev; + + for_each_possible_cpu(cpu_id) { + dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id); + cpuidle_unregister_device(dev); + } + + free_percpu(imx_cpuidle_devices); +} + +int __init imx_cpuidle_init(struct cpuidle_driver *drv) +{ + struct cpuidle_device *dev; + int cpu_id, ret; + + if (drv->state_count > CPUIDLE_STATE_MAX) { + pr_err("%s: state_count exceeds maximum\n", __func__); + return -EINVAL; + } + + ret = cpuidle_register_driver(drv); + if (ret) { + pr_err("%s: Failed to register cpuidle driver with error: %d\n", + __func__, ret); + return ret; + } + + imx_cpuidle_devices = alloc_percpu(struct cpuidle_device); + if (imx_cpuidle_devices == NULL) { + ret = -ENOMEM; + goto unregister_drv; + } + + /* initialize state data for each cpuidle_device */ + for_each_possible_cpu(cpu_id) { + dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id); + dev->cpu = cpu_id; + dev->state_count = drv->state_count; + + ret = cpuidle_register_device(dev); + if (ret) { + pr_err("%s: Failed to register cpu %u, error: %d\n", + __func__, cpu_id, ret); + goto uninit; + } + } + + return 0; + +uninit: + imx_cpuidle_devices_uninit(); + +unregister_drv: + cpuidle_unregister_driver(drv); + return ret; +} diff --git a/arch/arm/plat-mxc/include/mach/cpuidle.h b/arch/arm/plat-mxc/include/mach/cpuidle.h new file mode 100644 index 000000000000..bc932d1af372 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/cpuidle.h @@ -0,0 +1,22 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright 2012 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include + +#ifdef CONFIG_CPU_IDLE +extern int imx_cpuidle_init(struct cpuidle_driver *drv); +#else +static inline int imx_cpuidle_init(struct cpuidle_driver *drv) +{ + return -ENODEV; +} +#endif -- cgit v1.2.3 From ccc12b32dc8c8e88a5b35f8df34ec7c80f2e10b0 Mon Sep 17 00:00:00 2001 From: Robert Lee Date: Mon, 21 May 2012 17:50:29 -0500 Subject: ARM: imx: Add imx5 cpuidle Add cpuidle driver for imx5 platform. Signed-off-by: Robert Lee Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/pm-imx5.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c index b3dcd8e50d5b..19621ed1ffa5 100644 --- a/arch/arm/mach-imx/pm-imx5.c +++ b/arch/arm/mach-imx/pm-imx5.c @@ -12,10 +12,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include "crm-regs-imx5.h" @@ -134,12 +136,48 @@ static const struct platform_suspend_ops mx5_suspend_ops = { .enter = mx5_suspend_enter, }; -static void imx5_pm_idle(void) +static inline int imx5_cpu_do_idle(void) { - if (likely(!tzic_enable_wake())) + int ret = tzic_enable_wake(); + + if (likely(!ret)) cpu_do_idle(); + + return ret; +} + +static void imx5_pm_idle(void) +{ + imx5_cpu_do_idle(); +} + +static int imx5_cpuidle_enter(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int idx) +{ + int ret; + + ret = imx5_cpu_do_idle(); + if (ret < 0) + return ret; + + return idx; } +static struct cpuidle_driver imx5_cpuidle_driver = { + .name = "imx5_cpuidle", + .owner = THIS_MODULE, + .en_core_tk_irqen = 1, + .states[0] = { + .enter = imx5_cpuidle_enter, + .exit_latency = 2, + .target_residency = 1, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "IMX5 SRPG", + .desc = "CPU state retained,powered off", + }, + .state_count = 1, +}; + static int __init imx5_pm_common_init(void) { int ret; @@ -157,6 +195,7 @@ static int __init imx5_pm_common_init(void) /* Set the registers to the default cpu idle state. */ mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE); + imx_cpuidle_init(&imx5_cpuidle_driver); return 0; } -- cgit v1.2.3 From b9d18dc3a05d59894d60d5e173ebfb89a4b91bdf Mon Sep 17 00:00:00 2001 From: Robert Lee Date: Mon, 21 May 2012 17:50:30 -0500 Subject: ARM: imx: Add imx6q cpuidle driver Add basic imx6q cpuidle driver. For now, only basic WFI state is supported. Deeper idle states will be added in the future. Signed-off-by: Robert Lee Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/mach-imx6q.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index b47e98b7d539..d4ca2c470142 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -12,7 +12,9 @@ #include #include +#include #include +#include #include #include #include @@ -24,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -31,8 +34,10 @@ #include #include #include +#include #include + void imx6q_restart(char mode, const char *cmd) { struct device_node *np; @@ -129,6 +134,19 @@ static void __init imx6q_init_machine(void) imx6q_pm_init(); } +static struct cpuidle_driver imx6q_cpuidle_driver = { + .name = "imx6q_cpuidle", + .owner = THIS_MODULE, + .en_core_tk_irqen = 1, + .states[0] = ARM_CPUIDLE_WFI_STATE, + .state_count = 1, +}; + +static void __init imx6q_init_late(void) +{ + imx_cpuidle_init(&imx6q_cpuidle_driver); +} + static void __init imx6q_map_io(void) { imx_lluart_map_io(); @@ -186,6 +204,7 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)") .handle_irq = imx6q_handle_irq, .timer = &imx6q_timer, .init_machine = imx6q_init_machine, + .init_late = imx6q_init_late, .dt_compat = imx6q_dt_compat, .restart = imx6q_restart, MACHINE_END -- cgit v1.2.3 From d0a9001dce0ea24751b1f6336f2881ac906cabbb Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Thu, 10 May 2012 14:23:01 +0530 Subject: ARM: OMAP2+: am33xx: Add low level debugging support Add support for low level debugging on AM335X EVM (AM33XX family). Currently only support for UART1 console, which is used on AM335X EVM is added. Signed-off-by: Afzal Mohammed Signed-off-by: Vaibhav Hiremath Reviewed-by: Kevin Hilman Cc: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/include/mach/debug-macro.S | 17 ++++++++++++++++- arch/arm/plat-omap/include/plat/serial.h | 4 ++++ arch/arm/plat-omap/include/plat/uncompress.h | 6 ++++++ 3 files changed, 26 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/include/mach/debug-macro.S b/arch/arm/mach-omap2/include/mach/debug-macro.S index cdfc2a1f0e75..d7f844a99a7b 100644 --- a/arch/arm/mach-omap2/include/mach/debug-macro.S +++ b/arch/arm/mach-omap2/include/mach/debug-macro.S @@ -72,6 +72,8 @@ omap_uart_lsr: .word 0 beq 82f @ configure UART2 cmp \rp, #TI81XXUART3 @ ti81Xx UART offsets different beq 83f @ configure UART3 + cmp \rp, #AM33XXUART1 @ AM33XX UART offsets different + beq 84f @ configure UART1 cmp \rp, #ZOOM_UART @ only on zoom2/3 beq 95f @ configure ZOOM_UART @@ -100,7 +102,9 @@ omap_uart_lsr: .word 0 b 98f 83: mov \rp, #UART_OFFSET(TI81XX_UART3_BASE) b 98f - +84: ldr \rp, =AM33XX_UART1_BASE + and \rp, \rp, #0x00ffffff + b 97f 95: ldr \rp, =ZOOM_UART_BASE str \rp, [\tmp, #0] @ omap_uart_phys ldr \rp, =ZOOM_UART_VIRT @@ -109,6 +113,17 @@ omap_uart_lsr: .word 0 str \rp, [\tmp, #8] @ omap_uart_lsr b 10b + /* AM33XX: Store both phys and virt address for the uart */ +97: add \rp, \rp, #0x44000000 @ phys base + str \rp, [\tmp, #0] @ omap_uart_phys + sub \rp, \rp, #0x44000000 @ phys base + add \rp, \rp, #0xf9000000 @ virt base + str \rp, [\tmp, #4] @ omap_uart_virt + mov \rp, #(UART_LSR << OMAP_PORT_SHIFT) + str \rp, [\tmp, #8] @ omap_uart_lsr + + b 10b + /* Store both phys and virt address for the uart */ 98: add \rp, \rp, #0x48000000 @ phys base str \rp, [\tmp, #0] @ omap_uart_phys diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h index b073e5f2b190..28e2d250c2fd 100644 --- a/arch/arm/plat-omap/include/plat/serial.h +++ b/arch/arm/plat-omap/include/plat/serial.h @@ -60,6 +60,9 @@ /* AM3505/3517 UART4 */ #define AM35XX_UART4_BASE 0x4809E000 /* Only on AM3505/3517 */ +/* AM33XX serial port */ +#define AM33XX_UART1_BASE 0x44E09000 + /* External port on Zoom2/3 */ #define ZOOM_UART_BASE 0x10000000 #define ZOOM_UART_VIRT 0xfa400000 @@ -93,6 +96,7 @@ #define TI81XXUART1 81 #define TI81XXUART2 82 #define TI81XXUART3 83 +#define AM33XXUART1 84 #define ZOOM_UART 95 /* Only on zoom2/3 */ /* This is only used by 8250.c for omap1510 */ diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h index cc3f11ba7a99..ac4323390213 100644 --- a/arch/arm/plat-omap/include/plat/uncompress.h +++ b/arch/arm/plat-omap/include/plat/uncompress.h @@ -103,6 +103,10 @@ static inline void flush(void) _DEBUG_LL_ENTRY(mach, TI81XX_UART##p##_BASE, OMAP_PORT_SHIFT, \ TI81XXUART##p) +#define DEBUG_LL_AM33XX(p, mach) \ + _DEBUG_LL_ENTRY(mach, AM33XX_UART##p##_BASE, OMAP_PORT_SHIFT, \ + AM33XXUART##p) + static inline void __arch_decomp_setup(unsigned long arch_id) { int port = 0; @@ -183,6 +187,8 @@ static inline void __arch_decomp_setup(unsigned long arch_id) /* TI8148 base boards using UART1 */ DEBUG_LL_TI81XX(1, ti8148evm); + /* AM33XX base boards using UART1 */ + DEBUG_LL_AM33XX(1, am335xevm); } while (0); } -- cgit v1.2.3 From 18847b42f8d157201550015296a222a9009a04da Mon Sep 17 00:00:00 2001 From: Javier Martin Date: Fri, 1 Jun 2012 09:45:33 +0200 Subject: ARM i.MX27 Visstrim M10: fix gpio handling. Some GPIOs in Visstrim M10 are used without being registered. This leads to USB and video malfunctions. This patch registers those GPIOs to solve the issue. Signed-off-by: Javier Martin Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/mach-imx27_visstrim_m10.c | 36 ++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c index f7b074f496f0..2c6a783d4c04 100644 --- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c +++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c @@ -107,6 +107,8 @@ static const int visstrim_m10_pins[] __initconst = { PB23_PF_USB_PWR, PB24_PF_USB_OC, /* CSI */ + TVP5150_RSTN | GPIO_GPIO | GPIO_OUT, + TVP5150_PWDN | GPIO_GPIO | GPIO_OUT, PB10_PF_CSI_D0, PB11_PF_CSI_D1, PB12_PF_CSI_D2, @@ -121,6 +123,24 @@ static const int visstrim_m10_pins[] __initconst = { PB21_PF_CSI_HSYNC, }; +static const struct gpio visstrim_m10_gpios[] __initconst = { + { + .gpio = TVP5150_RSTN, + .flags = GPIOF_DIR_OUT | GPIOF_INIT_HIGH, + .label = "tvp5150_rstn", + }, + { + .gpio = TVP5150_PWDN, + .flags = GPIOF_DIR_OUT | GPIOF_INIT_LOW, + .label = "tvp5150_pwdn", + }, + { + .gpio = OTG_PHY_CS_GPIO, + .flags = GPIOF_DIR_OUT | GPIOF_INIT_LOW, + .label = "usbotg_cs", + }, +}; + /* Camera */ static int visstrim_camera_power(struct device *dev, int on) { @@ -164,13 +184,6 @@ static void __init visstrim_camera_init(void) struct platform_device *pdev; int dma; - /* Initialize tvp5150 gpios */ - mxc_gpio_mode(TVP5150_RSTN | GPIO_GPIO | GPIO_OUT); - mxc_gpio_mode(TVP5150_PWDN | GPIO_GPIO | GPIO_OUT); - gpio_set_value(TVP5150_RSTN, 1); - gpio_set_value(TVP5150_PWDN, 0); - ndelay(1); - gpio_set_value(TVP5150_PWDN, 1); ndelay(1); gpio_set_value(TVP5150_RSTN, 0); @@ -351,10 +364,6 @@ static struct i2c_board_info visstrim_m10_i2c_devices[] = { /* USB OTG */ static int otg_phy_init(struct platform_device *pdev) { - gpio_set_value(OTG_PHY_CS_GPIO, 0); - - mdelay(10); - return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED); } @@ -380,6 +389,11 @@ static void __init visstrim_m10_board_init(void) if (ret) pr_err("Failed to setup pins (%d)\n", ret); + ret = gpio_request_array(visstrim_m10_gpios, + ARRAY_SIZE(visstrim_m10_gpios)); + if (ret) + pr_err("Failed to request gpios (%d)\n", ret); + imx27_add_imx_ssi(0, &visstrim_m10_ssi_pdata); imx27_add_imx_uart0(&uart_pdata); -- cgit v1.2.3 From 08f3098928c991560408e8c71d4af8b1a3ff2d67 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Fri, 11 May 2012 00:38:49 +0530 Subject: ARM: OMAP2+: am33xx: Add AM335XEVM machine support This patch adds minimal support for AM335X machine init. During last merge window, two separate patches supporting am33xx machine init had been submitted, 1. Link to earlier Baseport patch submission (Legacy): http://www.mail-archive.com/linux-omap@vger.kernel.org/msg59325.html 2. Link to earlier DT based machine init support patch submission: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg61398.html And both had got accepted at that time, but got missed during merge window. But now, since we have taken decision to make am33xx as a separate class and not to follow omap3 family, these patches needs to changes accordingly (only changes), - Combine both the patches, since early init and timer init used in board-generic.c file requires them. - Remove dependency on AM3517EVM, and only use DT approach for machine init. - Change the config option (as changed recently) CONFIG_SOC_OMAPAM33XX --> CONFIG_SOC_AM33XX Signed-off-by: Vaibhav Hiremath Signed-off-by: Vaibhav Hiremath Cc: Benoit Cousson Cc: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-generic.c | 18 ++++++++++++++++++ arch/arm/mach-omap2/common.h | 2 ++ arch/arm/mach-omap2/io.c | 10 ++++++++++ arch/arm/mach-omap2/irq.c | 2 +- arch/arm/mach-omap2/timer.c | 5 +++++ 5 files changed, 36 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 202934657867..2f2abfb82d84 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -112,6 +112,24 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)") MACHINE_END #endif +#ifdef CONFIG_SOC_AM33XX +static const char *am33xx_boards_compat[] __initdata = { + "ti,am33xx", + NULL, +}; + +DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)") + .reserve = omap_reserve, + .map_io = am33xx_map_io, + .init_early = am33xx_init_early, + .init_irq = omap_init_irq, + .handle_irq = omap3_intc_handle_irq, + .init_machine = omap_generic_init, + .timer = &omap3_am33xx_timer, + .dt_compat = am33xx_boards_compat, +MACHINE_END +#endif + #ifdef CONFIG_ARCH_OMAP4 static const char *omap4_boards_compat[] __initdata = { "ti,omap4", diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index be9dfd1abe60..56f687bebd0a 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -120,6 +120,7 @@ extern void omap2_init_common_infrastructure(void); extern struct sys_timer omap2_timer; extern struct sys_timer omap3_timer; extern struct sys_timer omap3_secure_timer; +extern struct sys_timer omap3_am33xx_timer; extern struct sys_timer omap4_timer; void omap2420_init_early(void); @@ -130,6 +131,7 @@ void omap3630_init_early(void); void omap3_init_early(void); /* Do not use this one */ void am35xx_init_early(void); void ti81xx_init_early(void); +void am33xx_init_early(void); void omap4430_init_early(void); void omap3_init_late(void); /* Do not use this one */ void omap4430_init_late(void); diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 8d014ba04abc..5d6b2346bf75 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -477,6 +477,16 @@ void __init ti81xx_init_late(void) } #endif +#ifdef CONFIG_SOC_AM33XX +void __init am33xx_init_early(void) +{ + omap2_set_globals_am33xx(); + omap3xxx_check_revision(); + ti81xx_check_features(); + omap_common_init_early(); +} +#endif + #ifdef CONFIG_ARCH_OMAP4 void __init omap4430_init_early(void) { diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index fdc4303be563..428685f65060 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -279,7 +279,7 @@ int __init omap_intc_of_init(struct device_node *node, return 0; } -#ifdef CONFIG_ARCH_OMAP3 +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)]; void omap_intc_save_context(void) diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 840929bd9dae..ea6a0eb13f05 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -368,6 +368,11 @@ OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE, OMAP_SYS_TIMER(3_secure) #endif +#ifdef CONFIG_SOC_AM33XX +OMAP_SYS_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, 2, OMAP4_MPU_SOURCE) +OMAP_SYS_TIMER(3_am33xx) +#endif + #ifdef CONFIG_ARCH_OMAP4 #ifdef CONFIG_LOCAL_TIMERS static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, -- cgit v1.2.3 From 51ce29196dee3084387aa4448d75edc282a91685 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Tue, 5 Jun 2012 16:42:38 +0800 Subject: ARM: dts: update memory size on brownstone The memory size on brownstone should be 128MB, not 64MB. Signed-off-by: Haojian Zhuang --- arch/arm/boot/dts/mmp2-brownstone.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/mmp2-brownstone.dts b/arch/arm/boot/dts/mmp2-brownstone.dts index 153a4b2d12b5..c9b4f27d191e 100644 --- a/arch/arm/boot/dts/mmp2-brownstone.dts +++ b/arch/arm/boot/dts/mmp2-brownstone.dts @@ -11,7 +11,7 @@ /include/ "mmp2.dtsi" / { - model = "Marvell MMP2 Aspenite Development Board"; + model = "Marvell MMP2 Brownstone Development Board"; compatible = "mrvl,mmp2-brownstone", "mrvl,mmp2"; chosen { @@ -19,7 +19,7 @@ }; memory { - reg = <0x00000000 0x04000000>; + reg = <0x00000000 0x08000000>; }; soc { -- cgit v1.2.3 From 10bd21c0547ba2834374ccdddbc6a984eeed432c Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Tue, 5 Jun 2012 17:42:23 +0800 Subject: ARM: mmp: fix missing cascade_irq in irq handler While supporting board in non-DT mode, icu_data[i]->cascade_irq isn't assigned with correct value. Signed-off-by: Haojian Zhuang --- arch/arm/mach-mmp/irq.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-mmp/irq.c b/arch/arm/mach-mmp/irq.c index fcfe0e3bd701..e60c7d98922b 100644 --- a/arch/arm/mach-mmp/irq.c +++ b/arch/arm/mach-mmp/irq.c @@ -241,6 +241,7 @@ void __init mmp2_init_icu(void) icu_data[1].clr_mfp_irq_base = IRQ_MMP2_PMIC_BASE; icu_data[1].clr_mfp_hwirq = IRQ_MMP2_PMIC - IRQ_MMP2_PMIC_BASE; icu_data[1].nr_irqs = 2; + icu_data[1].cascade_irq = 4; icu_data[1].virq_base = IRQ_MMP2_PMIC_BASE; icu_data[1].domain = irq_domain_add_legacy(NULL, icu_data[1].nr_irqs, icu_data[1].virq_base, 0, @@ -249,6 +250,7 @@ void __init mmp2_init_icu(void) icu_data[2].reg_status = mmp_icu_base + 0x154; icu_data[2].reg_mask = mmp_icu_base + 0x16c; icu_data[2].nr_irqs = 2; + icu_data[2].cascade_irq = 5; icu_data[2].virq_base = IRQ_MMP2_RTC_BASE; icu_data[2].domain = irq_domain_add_legacy(NULL, icu_data[2].nr_irqs, icu_data[2].virq_base, 0, @@ -257,6 +259,7 @@ void __init mmp2_init_icu(void) icu_data[3].reg_status = mmp_icu_base + 0x180; icu_data[3].reg_mask = mmp_icu_base + 0x17c; icu_data[3].nr_irqs = 3; + icu_data[3].cascade_irq = 9; icu_data[3].virq_base = IRQ_MMP2_KEYPAD_BASE; icu_data[3].domain = irq_domain_add_legacy(NULL, icu_data[3].nr_irqs, icu_data[3].virq_base, 0, @@ -265,6 +268,7 @@ void __init mmp2_init_icu(void) icu_data[4].reg_status = mmp_icu_base + 0x158; icu_data[4].reg_mask = mmp_icu_base + 0x170; icu_data[4].nr_irqs = 5; + icu_data[4].cascade_irq = 17; icu_data[4].virq_base = IRQ_MMP2_TWSI_BASE; icu_data[4].domain = irq_domain_add_legacy(NULL, icu_data[4].nr_irqs, icu_data[4].virq_base, 0, @@ -273,6 +277,7 @@ void __init mmp2_init_icu(void) icu_data[5].reg_status = mmp_icu_base + 0x15c; icu_data[5].reg_mask = mmp_icu_base + 0x174; icu_data[5].nr_irqs = 15; + icu_data[5].cascade_irq = 35; icu_data[5].virq_base = IRQ_MMP2_MISC_BASE; icu_data[5].domain = irq_domain_add_legacy(NULL, icu_data[5].nr_irqs, icu_data[5].virq_base, 0, @@ -281,6 +286,7 @@ void __init mmp2_init_icu(void) icu_data[6].reg_status = mmp_icu_base + 0x160; icu_data[6].reg_mask = mmp_icu_base + 0x178; icu_data[6].nr_irqs = 2; + icu_data[6].cascade_irq = 51; icu_data[6].virq_base = IRQ_MMP2_MIPI_HSI1_BASE; icu_data[6].domain = irq_domain_add_legacy(NULL, icu_data[6].nr_irqs, icu_data[6].virq_base, 0, @@ -289,6 +295,7 @@ void __init mmp2_init_icu(void) icu_data[7].reg_status = mmp_icu_base + 0x188; icu_data[7].reg_mask = mmp_icu_base + 0x184; icu_data[7].nr_irqs = 2; + icu_data[7].cascade_irq = 55; icu_data[7].virq_base = IRQ_MMP2_MIPI_HSI0_BASE; icu_data[7].domain = irq_domain_add_legacy(NULL, icu_data[7].nr_irqs, icu_data[7].virq_base, 0, -- cgit v1.2.3 From 91930652a23de0873a157aa1d9962cb878d64451 Mon Sep 17 00:00:00 2001 From: "Govindraj.R" Date: Tue, 5 Jun 2012 04:04:11 -0700 Subject: OMAP2+: UART: Add mechanism to probe uart pins and configure rx wakeup The commit (bce492c0 ARM: OMAP2+: UART: Fix incorrect population of default uart pads) removed default uart pads that where getting populated and which was making rx pin wakeup capable. If uart pads were used in different mode by any other module then it would fail since the default pads took over all the uart pins forcefully. With removal of default pads the rx_pad wakeup for console uart while waking up from off mode is broken. Utilise the mux api available to probe the availability of mux pins in uart mode and probe for availability of uart pin in mux mode0 if uart is available as uart pin itself then configure rx pin as wakeup capable. This patch itself doesn't cater to all boards. Boards using uart rx wakeup mechanism should ensure the usage of omap_serial_init_port by configuring required uart ports and pass necessary mux data, till then this probing of uart pins can cater to enabling of rx pad wakeup to most of the boards. This patch can also throw some boot warning from _omap_mux_get_by_name if pin is requested for availability is not present while dynamically probing the uart pins availability such boot warnings can be addressed only when board files are patched with omap_serial_init_port calls passing the right pads needed for a given port. Discussion Threads for reference: http://www.spinics.net/lists/linux-omap/msg69859.html http://www.spinics.net/lists/linux-omap/msg68659.html Cc: Felipe Balbi Cc: Kevin Hilman Cc: Russ Dill Cc: Paul Walmsley Cc: Ameya Palande Signed-off-by: Govindraj.R [tony@atomide.com: updated to fix compile when CONFIG_OMAP_MUX is not set] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/mux.c | 3 +- arch/arm/mach-omap2/mux.h | 11 ++++++++ arch/arm/mach-omap2/serial.c | 67 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 75 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 80e55c5c9998..4b46b91cca5c 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -217,8 +217,7 @@ static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition, return -ENODEV; } -static int __init -omap_mux_get_by_name(const char *muxname, +int __init omap_mux_get_by_name(const char *muxname, struct omap_mux_partition **found_partition, struct omap_mux **found_mux) { diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h index 69fe060a0b75..471e62a74a16 100644 --- a/arch/arm/mach-omap2/mux.h +++ b/arch/arm/mach-omap2/mux.h @@ -59,6 +59,7 @@ #define OMAP_PIN_OFF_WAKEUPENABLE OMAP_WAKEUP_EN #define OMAP_MODE_GPIO(x) (((x) & OMAP_MUX_MODE7) == OMAP_MUX_MODE4) +#define OMAP_MODE_UART(x) (((x) & OMAP_MUX_MODE7) == OMAP_MUX_MODE0) /* Flags for omapX_mux_init */ #define OMAP_PACKAGE_MASK 0xffff @@ -225,8 +226,18 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads); */ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state); +int omap_mux_get_by_name(const char *muxname, + struct omap_mux_partition **found_partition, + struct omap_mux **found_mux); #else +static inline int omap_mux_get_by_name(const char *muxname, + struct omap_mux_partition **found_partition, + struct omap_mux **found_mux) +{ + return 0; +} + static inline int omap_mux_init_gpio(int gpio, int val) { return 0; diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 292d4aaca068..c1b93c752d70 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -57,6 +57,7 @@ struct omap_uart_state { struct list_head node; struct omap_hwmod *oh; + struct omap_device_pad default_omap_uart_pads[2]; }; static LIST_HEAD(uart_list); @@ -126,11 +127,70 @@ static void omap_uart_set_smartidle(struct platform_device *pdev) {} #endif /* CONFIG_PM */ #ifdef CONFIG_OMAP_MUX -static void omap_serial_fill_default_pads(struct omap_board_data *bdata) + +#define OMAP_UART_DEFAULT_PAD_NAME_LEN 28 +static char rx_pad_name[OMAP_UART_DEFAULT_PAD_NAME_LEN], + tx_pad_name[OMAP_UART_DEFAULT_PAD_NAME_LEN] __initdata; + +static void __init +omap_serial_fill_uart_tx_rx_pads(struct omap_board_data *bdata, + struct omap_uart_state *uart) +{ + uart->default_omap_uart_pads[0].name = rx_pad_name; + uart->default_omap_uart_pads[0].flags = OMAP_DEVICE_PAD_REMUX | + OMAP_DEVICE_PAD_WAKEUP; + uart->default_omap_uart_pads[0].enable = OMAP_PIN_INPUT | + OMAP_MUX_MODE0; + uart->default_omap_uart_pads[0].idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0; + uart->default_omap_uart_pads[1].name = tx_pad_name; + uart->default_omap_uart_pads[1].enable = OMAP_PIN_OUTPUT | + OMAP_MUX_MODE0; + bdata->pads = uart->default_omap_uart_pads; + bdata->pads_cnt = ARRAY_SIZE(uart->default_omap_uart_pads); +} + +static void __init omap_serial_check_wakeup(struct omap_board_data *bdata, + struct omap_uart_state *uart) { + struct omap_mux_partition *tx_partition = NULL, *rx_partition = NULL; + struct omap_mux *rx_mux = NULL, *tx_mux = NULL; + char *rx_fmt, *tx_fmt; + int uart_nr = bdata->id + 1; + + if (bdata->id != 2) { + rx_fmt = "uart%d_rx.uart%d_rx"; + tx_fmt = "uart%d_tx.uart%d_tx"; + } else { + rx_fmt = "uart%d_rx_irrx.uart%d_rx_irrx"; + tx_fmt = "uart%d_tx_irtx.uart%d_tx_irtx"; + } + + snprintf(rx_pad_name, OMAP_UART_DEFAULT_PAD_NAME_LEN, rx_fmt, + uart_nr, uart_nr); + snprintf(tx_pad_name, OMAP_UART_DEFAULT_PAD_NAME_LEN, tx_fmt, + uart_nr, uart_nr); + + if (omap_mux_get_by_name(rx_pad_name, &rx_partition, &rx_mux) >= 0 && + omap_mux_get_by_name + (tx_pad_name, &tx_partition, &tx_mux) >= 0) { + u16 tx_mode, rx_mode; + + tx_mode = omap_mux_read(tx_partition, tx_mux->reg_offset); + rx_mode = omap_mux_read(rx_partition, rx_mux->reg_offset); + + /* + * Check if uart is used in default tx/rx mode i.e. in mux mode0 + * if yes then configure rx pin for wake up capability + */ + if (OMAP_MODE_UART(rx_mode) && OMAP_MODE_UART(tx_mode)) + omap_serial_fill_uart_tx_rx_pads(bdata, uart); + } } #else -static void omap_serial_fill_default_pads(struct omap_board_data *bdata) {} +static void __init omap_serial_check_wakeup(struct omap_board_data *bdata, + struct omap_uart_state *uart) +{ +} #endif static char *cmdline_find_option(char *str) @@ -287,8 +347,7 @@ void __init omap_serial_board_init(struct omap_uart_port_info *info) bdata.pads = NULL; bdata.pads_cnt = 0; - if (cpu_is_omap44xx() || cpu_is_omap34xx()) - omap_serial_fill_default_pads(&bdata); + omap_serial_check_wakeup(&bdata, uart); if (!info) omap_serial_init_port(&bdata, NULL); -- cgit v1.2.3 From 569ba7d2083681abbfc2f6d6550e74e64833dada Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 30 May 2012 21:58:46 +0200 Subject: s390/kvm: get rid of duplicate instruction After commit 5e8010cb50d3de7202641c0088c211f7c9593ebc s390: replace TIF_SIE with PF_VCPU there is no need to load the thread info before sie_loop where it is also loaded. Get rid of this duplicate instruction. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/entry64.S | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 229fe1d07749..bf80a5921173 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -974,7 +974,6 @@ ENTRY(sie64a) stg %r3,__SF_EMPTY+8(%r15) # save guest register save area xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0 lmg %r0,%r13,0(%r3) # load guest gprs 0-13 - lg %r14,__LC_THREAD_INFO # pointer thread_info struct sie_loop: lg %r14,__LC_THREAD_INFO # pointer thread_info struct tm __TI_flags+7(%r14),_TIF_EXIT_SIE -- cgit v1.2.3 From 524b24ada792b40e1eb2eae59f7a096f26c3b788 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 4 Jun 2012 12:11:41 +0200 Subject: s390/smp: remove redundant check condition code "status stored" for sigp sense running always implies that only the "not running" status bit is set. Therefore no need to check if it is set. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 15cca26ccb6c..c78074c6cc1d 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -158,8 +158,8 @@ static inline int pcpu_running(struct pcpu *pcpu) if (__pcpu_sigp(pcpu->address, sigp_sense_running, 0, &pcpu->status) != sigp_status_stored) return 1; - /* Check for running status */ - return !(pcpu->status & 0x400); + /* Status stored condition code is equivalent to cpu not running. */ + return 0; } /* -- cgit v1.2.3 From a9ae32c3d9a6557f24db0e186bf2f84205780b8a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 4 Jun 2012 12:55:15 +0200 Subject: s390/smp/kvm: unifiy sigp definitions The smp and the kvm code have different defines for the sigp order codes. Let's just have a single place where these are defined. Also move the sigp condition code and sigp cpu status bits to the new sigp.h header file. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/sigp.h | 31 +++++++++++++++++++ arch/s390/kernel/smp.c | 72 +++++++++++++++----------------------------- arch/s390/kvm/sigp.c | 46 ++++++---------------------- 3 files changed, 64 insertions(+), 85 deletions(-) create mode 100644 arch/s390/include/asm/sigp.h (limited to 'arch') diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h new file mode 100644 index 000000000000..7306270b5b84 --- /dev/null +++ b/arch/s390/include/asm/sigp.h @@ -0,0 +1,31 @@ +#ifndef __S390_ASM_SIGP_H +#define __S390_ASM_SIGP_H + +/* SIGP order codes */ +#define SIGP_SENSE 1 +#define SIGP_EXTERNAL_CALL 2 +#define SIGP_EMERGENCY_SIGNAL 3 +#define SIGP_STOP 5 +#define SIGP_RESTART 6 +#define SIGP_STOP_AND_STORE_STATUS 9 +#define SIGP_INITIAL_CPU_RESET 11 +#define SIGP_SET_PREFIX 13 +#define SIGP_STORE_STATUS_AT_ADDRESS 14 +#define SIGP_SET_ARCHITECTURE 18 +#define SIGP_SENSE_RUNNING 21 + +/* SIGP condition codes */ +#define SIGP_CC_ORDER_CODE_ACCEPTED 0 +#define SIGP_CC_STATUS_STORED 1 +#define SIGP_CC_BUSY 2 +#define SIGP_CC_NOT_OPERATIONAL 3 + +/* SIGP cpu status bits */ + +#define SIGP_STATUS_CHECK_STOP 0x00000010UL +#define SIGP_STATUS_STOPPED 0x00000040UL +#define SIGP_STATUS_INVALID_PARAMETER 0x00000100UL +#define SIGP_STATUS_INCORRECT_STATE 0x00000200UL +#define SIGP_STATUS_NOT_RUNNING 0x00000400UL + +#endif /* __S390_ASM_SIGP_H */ diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index c78074c6cc1d..6e4047e4b498 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -44,33 +44,9 @@ #include #include #include +#include #include "entry.h" -enum { - sigp_sense = 1, - sigp_external_call = 2, - sigp_emergency_signal = 3, - sigp_start = 4, - sigp_stop = 5, - sigp_restart = 6, - sigp_stop_and_store_status = 9, - sigp_initial_cpu_reset = 11, - sigp_cpu_reset = 12, - sigp_set_prefix = 13, - sigp_store_status_at_address = 14, - sigp_store_extended_status_at_address = 15, - sigp_set_architecture = 18, - sigp_conditional_emergency_signal = 19, - sigp_sense_running = 21, -}; - -enum { - sigp_order_code_accepted = 0, - sigp_status_stored = 1, - sigp_busy = 2, - sigp_not_operational = 3, -}; - enum { ec_schedule = 0, ec_call_function, @@ -124,7 +100,7 @@ static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status) while (1) { cc = __pcpu_sigp(addr, order, parm, status); - if (cc != sigp_busy) + if (cc != SIGP_CC_BUSY) return cc; cpu_relax(); } @@ -136,7 +112,7 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) for (retry = 0; ; retry++) { cc = __pcpu_sigp(pcpu->address, order, parm, &pcpu->status); - if (cc != sigp_busy) + if (cc != SIGP_CC_BUSY) break; if (retry >= 3) udelay(10); @@ -146,8 +122,8 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) static inline int pcpu_stopped(struct pcpu *pcpu) { - if (__pcpu_sigp(pcpu->address, sigp_sense, - 0, &pcpu->status) != sigp_status_stored) + if (__pcpu_sigp(pcpu->address, SIGP_SENSE, + 0, &pcpu->status) != SIGP_CC_STATUS_STORED) return 0; /* Check for stopped and check stop state */ return !!(pcpu->status & 0x50); @@ -155,8 +131,8 @@ static inline int pcpu_stopped(struct pcpu *pcpu) static inline int pcpu_running(struct pcpu *pcpu) { - if (__pcpu_sigp(pcpu->address, sigp_sense_running, - 0, &pcpu->status) != sigp_status_stored) + if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING, + 0, &pcpu->status) != SIGP_CC_STATUS_STORED) return 1; /* Status stored condition code is equivalent to cpu not running. */ return 0; @@ -181,7 +157,7 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit) set_bit(ec_bit, &pcpu->ec_mask); order = pcpu_running(pcpu) ? - sigp_external_call : sigp_emergency_signal; + SIGP_EXTERNAL_CALL : SIGP_EMERGENCY_SIGNAL; pcpu_sigp_retry(pcpu, order, 0); } @@ -214,7 +190,7 @@ static int __cpuinit pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) goto out; #endif lowcore_ptr[cpu] = lc; - pcpu_sigp_retry(pcpu, sigp_set_prefix, (u32)(unsigned long) lc); + pcpu_sigp_retry(pcpu, SIGP_SET_PREFIX, (u32)(unsigned long) lc); return 0; out: if (pcpu != &pcpu_devices[0]) { @@ -229,7 +205,7 @@ out: static void pcpu_free_lowcore(struct pcpu *pcpu) { - pcpu_sigp_retry(pcpu, sigp_set_prefix, 0); + pcpu_sigp_retry(pcpu, SIGP_SET_PREFIX, 0); lowcore_ptr[pcpu - pcpu_devices] = NULL; #ifndef CONFIG_64BIT if (MACHINE_HAS_IEEE) { @@ -288,7 +264,7 @@ static void pcpu_start_fn(struct pcpu *pcpu, void (*func)(void *), void *data) lc->restart_fn = (unsigned long) func; lc->restart_data = (unsigned long) data; lc->restart_source = -1UL; - pcpu_sigp_retry(pcpu, sigp_restart, 0); + pcpu_sigp_retry(pcpu, SIGP_RESTART, 0); } /* @@ -309,7 +285,7 @@ static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *), if (pcpu->address == restart.source) func(data); /* should not return */ /* Stop target cpu (if func returns this stops the current cpu). */ - pcpu_sigp_retry(pcpu, sigp_stop, 0); + pcpu_sigp_retry(pcpu, SIGP_STOP, 0); /* Restart func on the target cpu and stop the current cpu. */ memcpy_absolute(&lc->restart_stack, &restart, sizeof(restart)); asm volatile( @@ -388,8 +364,8 @@ void smp_emergency_stop(cpumask_t *cpumask) for_each_cpu(cpu, cpumask) { struct pcpu *pcpu = pcpu_devices + cpu; set_bit(ec_stop_cpu, &pcpu->ec_mask); - while (__pcpu_sigp(pcpu->address, sigp_emergency_signal, - 0, NULL) == sigp_busy && + while (__pcpu_sigp(pcpu->address, SIGP_EMERGENCY_SIGNAL, + 0, NULL) == SIGP_CC_BUSY && get_clock() < end) cpu_relax(); } @@ -425,7 +401,7 @@ void smp_send_stop(void) /* stop all processors */ for_each_cpu(cpu, &cpumask) { struct pcpu *pcpu = pcpu_devices + cpu; - pcpu_sigp_retry(pcpu, sigp_stop, 0); + pcpu_sigp_retry(pcpu, SIGP_STOP, 0); while (!pcpu_stopped(pcpu)) cpu_relax(); } @@ -436,7 +412,7 @@ void smp_send_stop(void) */ void smp_stop_cpu(void) { - pcpu_sigp_retry(pcpu_devices + smp_processor_id(), sigp_stop, 0); + pcpu_sigp_retry(pcpu_devices + smp_processor_id(), SIGP_STOP, 0); for (;;) ; } @@ -590,7 +566,7 @@ static void __init smp_get_save_area(int cpu, u16 address) } #endif /* Get the registers of a non-boot cpu. */ - __pcpu_sigp_relax(address, sigp_stop_and_store_status, 0, NULL); + __pcpu_sigp_relax(address, SIGP_STOP_AND_STORE_STATUS, 0, NULL); memcpy_real(save_area, lc + SAVE_AREA_BASE, sizeof(*save_area)); } @@ -599,8 +575,8 @@ int smp_store_status(int cpu) struct pcpu *pcpu; pcpu = pcpu_devices + cpu; - if (__pcpu_sigp_relax(pcpu->address, sigp_stop_and_store_status, - 0, NULL) != sigp_order_code_accepted) + if (__pcpu_sigp_relax(pcpu->address, SIGP_STOP_AND_STORE_STATUS, + 0, NULL) != SIGP_CC_ORDER_CODE_ACCEPTED) return -EIO; return 0; } @@ -621,8 +597,8 @@ static struct sclp_cpu_info *smp_get_cpu_info(void) if (info && (use_sigp_detection || sclp_get_cpu_info(info))) { use_sigp_detection = 1; for (address = 0; address <= MAX_CPU_ADDRESS; address++) { - if (__pcpu_sigp_relax(address, sigp_sense, 0, NULL) == - sigp_not_operational) + if (__pcpu_sigp_relax(address, SIGP_SENSE, 0, NULL) == + SIGP_CC_NOT_OPERATIONAL) continue; info->cpu[info->configured].address = address; info->configured++; @@ -734,8 +710,8 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) pcpu = pcpu_devices + cpu; if (pcpu->state != CPU_STATE_CONFIGURED) return -EIO; - if (pcpu_sigp_retry(pcpu, sigp_initial_cpu_reset, 0) != - sigp_order_code_accepted) + if (pcpu_sigp_retry(pcpu, SIGP_INITIAL_CPU_RESET, 0) != + SIGP_CC_ORDER_CODE_ACCEPTED) return -EIO; rc = pcpu_alloc_lowcore(pcpu, cpu); @@ -795,7 +771,7 @@ void __cpu_die(unsigned int cpu) void __noreturn cpu_die(void) { idle_task_exit(); - pcpu_sigp_retry(pcpu_devices + smp_processor_id(), sigp_stop, 0); + pcpu_sigp_retry(pcpu_devices + smp_processor_id(), SIGP_STOP, 0); for (;;) ; } diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 0ad4cf238391..fda1d64f15ee 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -15,38 +15,10 @@ #include #include #include +#include #include "gaccess.h" #include "kvm-s390.h" -/* sigp order codes */ -#define SIGP_SENSE 0x01 -#define SIGP_EXTERNAL_CALL 0x02 -#define SIGP_EMERGENCY 0x03 -#define SIGP_START 0x04 -#define SIGP_STOP 0x05 -#define SIGP_RESTART 0x06 -#define SIGP_STOP_STORE_STATUS 0x09 -#define SIGP_INITIAL_CPU_RESET 0x0b -#define SIGP_CPU_RESET 0x0c -#define SIGP_SET_PREFIX 0x0d -#define SIGP_STORE_STATUS_ADDR 0x0e -#define SIGP_SET_ARCH 0x12 -#define SIGP_SENSE_RUNNING 0x15 - -/* cpu status bits */ -#define SIGP_STAT_EQUIPMENT_CHECK 0x80000000UL -#define SIGP_STAT_NOT_RUNNING 0x00000400UL -#define SIGP_STAT_INCORRECT_STATE 0x00000200UL -#define SIGP_STAT_INVALID_PARAMETER 0x00000100UL -#define SIGP_STAT_EXT_CALL_PENDING 0x00000080UL -#define SIGP_STAT_STOPPED 0x00000040UL -#define SIGP_STAT_OPERATOR_INTERV 0x00000020UL -#define SIGP_STAT_CHECK_STOP 0x00000010UL -#define SIGP_STAT_INOPERATIVE 0x00000004UL -#define SIGP_STAT_INVALID_ORDER 0x00000002UL -#define SIGP_STAT_RECEIVER_CHECK 0x00000001UL - - static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, u64 *reg) { @@ -65,7 +37,7 @@ static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, rc = 1; /* status stored */ } else { *reg &= 0xffffffff00000000UL; - *reg |= SIGP_STAT_STOPPED; + *reg |= SIGP_STATUS_STOPPED; rc = 1; /* status stored */ } spin_unlock(&fi->lock); @@ -235,7 +207,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, address = address & 0x7fffe000u; if (copy_from_guest_absolute(vcpu, &tmp, address, 1) || copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1)) { - *reg |= SIGP_STAT_INVALID_PARAMETER; + *reg |= SIGP_STATUS_INVALID_PARAMETER; return 1; /* invalid parameter */ } @@ -249,7 +221,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, if (li == NULL) { rc = 1; /* incorrect state */ - *reg &= SIGP_STAT_INCORRECT_STATE; + *reg &= SIGP_STATUS_INCORRECT_STATE; kfree(inti); goto out_fi; } @@ -258,7 +230,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, /* cpu must be in stopped state */ if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { rc = 1; /* incorrect state */ - *reg &= SIGP_STAT_INCORRECT_STATE; + *reg &= SIGP_STATUS_INCORRECT_STATE; kfree(inti); goto out_li; } @@ -300,7 +272,7 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr, } else { /* not running */ *reg &= 0xffffffff00000000UL; - *reg |= SIGP_STAT_NOT_RUNNING; + *reg |= SIGP_STATUS_NOT_RUNNING; rc = 0; } } @@ -375,7 +347,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) vcpu->stat.instruction_sigp_external_call++; rc = __sigp_external_call(vcpu, cpu_addr); break; - case SIGP_EMERGENCY: + case SIGP_EMERGENCY_SIGNAL: vcpu->stat.instruction_sigp_emergency++; rc = __sigp_emergency(vcpu, cpu_addr); break; @@ -383,12 +355,12 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) vcpu->stat.instruction_sigp_stop++; rc = __sigp_stop(vcpu, cpu_addr, ACTION_STOP_ON_STOP); break; - case SIGP_STOP_STORE_STATUS: + case SIGP_STOP_AND_STORE_STATUS: vcpu->stat.instruction_sigp_stop++; rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP | ACTION_STOP_ON_STOP); break; - case SIGP_SET_ARCH: + case SIGP_SET_ARCHITECTURE: vcpu->stat.instruction_sigp_arch++; rc = __sigp_set_arch(vcpu, parameter); break; -- cgit v1.2.3 From a095a8a9d5c2ffa15589298aabb64c75c39bf9be Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 4 Jun 2012 14:07:47 +0200 Subject: s390/smp: use sigp cpu status definitions We got them from the kvm code, so let's use them. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 6e4047e4b498..53ac2344ca7a 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -125,8 +125,7 @@ static inline int pcpu_stopped(struct pcpu *pcpu) if (__pcpu_sigp(pcpu->address, SIGP_SENSE, 0, &pcpu->status) != SIGP_CC_STATUS_STORED) return 0; - /* Check for stopped and check stop state */ - return !!(pcpu->status & 0x50); + return !!(pcpu->status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); } static inline int pcpu_running(struct pcpu *pcpu) -- cgit v1.2.3 From eb546195a7d8bc492ec6865980bf767474e74d87 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 4 Jun 2012 15:05:43 +0200 Subject: s390/sigp: use sigp order code defines in assembly code Use sigp order code defines in assembly code as well. With this change all places that use sigp constants should have been converted to use self describing defines instead of directly using constants. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/base.S | 3 ++- arch/s390/kernel/entry.S | 5 +++-- arch/s390/kernel/entry64.S | 5 +++-- arch/s390/kernel/head_kdump.S | 6 ++++-- arch/s390/kernel/reipl.S | 3 ++- arch/s390/kernel/reipl64.S | 3 ++- arch/s390/kernel/relocate_kernel.S | 3 ++- arch/s390/kernel/relocate_kernel64.S | 5 +++-- arch/s390/kernel/smp.c | 8 +++++--- arch/s390/kernel/swsusp_asm64.S | 13 +++++++------ 10 files changed, 33 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S index c880ff72db44..8c20d0efd483 100644 --- a/arch/s390/kernel/base.S +++ b/arch/s390/kernel/base.S @@ -9,6 +9,7 @@ #include #include #include +#include #ifdef CONFIG_64BIT @@ -100,7 +101,7 @@ ENTRY(diag308_reset) .Lrestart_part2: lhi %r0,0 # Load r0 with zero lhi %r1,2 # Use mode 2 = ESAME (dump) - sigp %r1,%r0,0x12 # Switch to ESAME mode + sigp %r1,%r0,SIGP_SET_ARCHITECTURE # Switch to ESAME mode sam64 # Switch to 64 bit addressing mode larl %r4,.Lctlregs # Restore control registers lctlg %c0,%c15,0(%r4) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 1ae93b573d7d..3787f9e6907a 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -18,6 +18,7 @@ #include #include #include +#include __PT_R0 = __PT_GPRS __PT_R1 = __PT_GPRS + 4 @@ -726,12 +727,12 @@ ENTRY(restart_int_handler) lm %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu ltr %r3,%r3 # test source cpu address jm 1f # negative -> skip source stop -0: sigp %r4,%r3,1 # sigp sense to source cpu +0: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu brc 10,0b # wait for status stored 1: basr %r14,%r1 # call function stap __SF_EMPTY(%r15) # store cpu address lh %r3,__SF_EMPTY(%r15) -2: sigp %r4,%r3,5 # sigp stop to current cpu +2: sigp %r4,%r3,SIGP_STOP # sigp stop to current cpu brc 2,2b 3: j 3b diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index bf80a5921173..d5f02e480e51 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -18,6 +18,7 @@ #include #include #include +#include __PT_R0 = __PT_GPRS __PT_R1 = __PT_GPRS + 8 @@ -753,12 +754,12 @@ ENTRY(restart_int_handler) lmg %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu ltgr %r3,%r3 # test source cpu address jm 1f # negative -> skip source stop -0: sigp %r4,%r3,1 # sigp sense to source cpu +0: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu brc 10,0b # wait for status stored 1: basr %r14,%r1 # call function stap __SF_EMPTY(%r15) # store cpu address llgh %r3,__SF_EMPTY(%r15) -2: sigp %r4,%r3,5 # sigp stop to current cpu +2: sigp %r4,%r3,SIGP_STOP # sigp stop to current cpu brc 2,2b 3: j 3b diff --git a/arch/s390/kernel/head_kdump.S b/arch/s390/kernel/head_kdump.S index 796c976b5fdc..acaaaf4b7055 100644 --- a/arch/s390/kernel/head_kdump.S +++ b/arch/s390/kernel/head_kdump.S @@ -5,6 +5,8 @@ * Author(s): Michael Holzheu */ +#include + #define DATAMOVER_ADDR 0x4000 #define COPY_PAGE_ADDR 0x6000 @@ -19,7 +21,7 @@ .align 2 .Lep_startup_kdump: lhi %r1,2 # mode 2 = esame (dump) - sigp %r1,%r0,0x12 # Switch to esame mode + sigp %r1,%r0,SIGP_SET_ARCHITECTURE # Switch to esame mode sam64 # Switch to 64 bit addressing basr %r13,0 .Lbase: @@ -88,7 +90,7 @@ startup_kdump_relocated: sam31 # Switch to 31 bit addr mode sr %r1,%r1 # Erase register r1 sr %r2,%r2 # Erase register r2 - sigp %r1,%r2,0x12 # Switch to 31 bit arch mode + sigp %r1,%r2,SIGP_SET_ARCHITECTURE # Switch to 31 bit arch mode lpsw 0 # Start new kernel... .align 8 .Lrestart_psw: diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S index ad67c214be04..1c5e9e3e2aa4 100644 --- a/arch/s390/kernel/reipl.S +++ b/arch/s390/kernel/reipl.S @@ -8,6 +8,7 @@ #include #include +#include # # store_status: Empty implementation until kdump is supported on 31 bit @@ -60,7 +61,7 @@ ENTRY(do_reipl_asm) bas %r14,.Ldisab-.Lpg0(%r13) .L003: st %r1,__LC_SUBCHANNEL_ID lpsw 0 - sigp 0,0,0(6) + sigp 0,0,SIGP_RESTART .Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13) lpsw .Ldispsw-.Lpg0(%r13) .align 8 diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S index 36b32658fb24..02f5a73d1820 100644 --- a/arch/s390/kernel/reipl64.S +++ b/arch/s390/kernel/reipl64.S @@ -6,6 +6,7 @@ #include #include +#include # # store_status @@ -106,7 +107,7 @@ ENTRY(do_reipl_asm) .L003: st %r1,__LC_SUBCHANNEL_ID lhi %r1,0 # mode 0 = esa slr %r0,%r0 # set cpuid to zero - sigp %r1,%r0,0x12 # switch to esa mode + sigp %r1,%r0,SIGP_SET_ARCHITECTURE # switch to esa mode lpsw 0 .Ldisab: sll %r14,1 srl %r14,1 # need to kill hi bit to avoid specification exceptions. diff --git a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S index c91d70aede91..bfad96a64222 100644 --- a/arch/s390/kernel/relocate_kernel.S +++ b/arch/s390/kernel/relocate_kernel.S @@ -9,6 +9,7 @@ */ #include +#include /* * moves the new kernel to its destination... @@ -93,7 +94,7 @@ ENTRY(relocate_kernel) .no_diag308: sr %r1,%r1 # clear %r1 sr %r2,%r2 # clear %r2 - sigp %r1,%r2,0x12 # set cpuid to zero + sigp %r1,%r2,SIGP_SET_ARCHITECTURE # set cpuid to zero lpsw 0 # hopefully start new kernel... .align 8 diff --git a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S index 7c3ce589a7f0..35508f335688 100644 --- a/arch/s390/kernel/relocate_kernel64.S +++ b/arch/s390/kernel/relocate_kernel64.S @@ -9,6 +9,7 @@ */ #include +#include /* * moves the new kernel to its destination... @@ -45,7 +46,7 @@ ENTRY(relocate_kernel) diag %r0,%r0,0x308 .back: lhi %r1,1 # mode 1 = esame - sigp %r1,%r0,0x12 # switch to esame mode + sigp %r1,%r0,SIGP_SET_ARCHITECTURE # switch to esame mode sam64 # switch to 64 bit addressing mode basr %r13,0 .back_base: @@ -96,7 +97,7 @@ ENTRY(relocate_kernel) sam31 # 31 bit mode sr %r1,%r1 # erase register r1 sr %r2,%r2 # erase register r2 - sigp %r1,%r2,0x12 # set cpuid to zero + sigp %r1,%r2,SIGP_SET_ARCHITECTURE # set cpuid to zero lpsw 0 # hopefully start new kernel... .align 8 diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 53ac2344ca7a..e01408429ad6 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -288,11 +288,13 @@ static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *), /* Restart func on the target cpu and stop the current cpu. */ memcpy_absolute(&lc->restart_stack, &restart, sizeof(restart)); asm volatile( - "0: sigp 0,%0,6 # sigp restart to target cpu\n" + "0: sigp 0,%0,%2 # sigp restart to target cpu\n" " brc 2,0b # busy, try again\n" - "1: sigp 0,%1,5 # sigp stop to current cpu\n" + "1: sigp 0,%1,%3 # sigp stop to current cpu\n" " brc 2,1b # busy, try again\n" - : : "d" (pcpu->address), "d" (restart.source) : "0", "1", "cc"); + : : "d" (pcpu->address), "d" (restart.source), + "K" (SIGP_RESTART), "K" (SIGP_STOP) + : "0", "1", "cc"); for (;;) ; } diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S index dd70ef046058..d4ca4e0617b5 100644 --- a/arch/s390/kernel/swsusp_asm64.S +++ b/arch/s390/kernel/swsusp_asm64.S @@ -12,6 +12,7 @@ #include #include #include +#include /* * Save register context in absolute 0 lowcore and call swsusp_save() to @@ -163,7 +164,7 @@ ENTRY(swsusp_arch_resume) diag %r0,%r0,0x308 restart_entry: lhi %r1,1 - sigp %r1,%r0,0x12 + sigp %r1,%r0,SIGP_SET_ARCHITECTURE sam64 larl %r1,.Lnew_pgm_check_psw lpswe 0(%r1) @@ -179,7 +180,7 @@ pgm_check_entry: larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */ mvc __LC_RST_NEW_PSW(16,%r0),0(%r4) 3: - sigp %r9,%r1,11 /* sigp initial cpu reset */ + sigp %r9,%r1,SIGP_INITIAL_CPU_RESET /* sigp initial cpu reset */ brc 8,4f /* accepted */ brc 2,3b /* busy, try again */ @@ -190,16 +191,16 @@ pgm_check_entry: larl %r3,_sclp_print_early lghi %r1,0 sam31 - sigp %r1,%r0,0x12 + sigp %r1,%r0,SIGP_SET_ARCHITECTURE basr %r14,%r3 larl %r3,.Ldisabled_wait_31 lpsw 0(%r3) 4: /* Switch to suspend CPU */ - sigp %r9,%r1,6 /* sigp restart to suspend CPU */ + sigp %r9,%r1,SIGP_RESTART /* sigp restart to suspend CPU */ brc 2,4b /* busy, try again */ 5: - sigp %r9,%r2,5 /* sigp stop to current resume CPU */ + sigp %r9,%r2,SIGP_STOP /* sigp stop to current resume CPU */ brc 2,5b /* busy, try again */ 6: j 6b @@ -207,7 +208,7 @@ restart_suspend: larl %r1,.Lresume_cpu llgh %r2,0(%r1) 7: - sigp %r9,%r2,1 /* sigp sense, wait for resume CPU */ + sigp %r9,%r2,SIGP_SENSE /* sigp sense, wait for resume CPU */ brc 8,7b /* accepted, status 0, still running */ brc 2,7b /* busy, try again */ tmll %r9,0x40 /* Test if resume CPU is stopped */ -- cgit v1.2.3 From 8d4ecfcb6bd19c562e60f80f13cf222db5b4a073 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 4 Jun 2012 19:31:00 +0200 Subject: s390/ccwgroup: remove unused ccwgroup_device member The creator_id is no longer used. Just get rid of it. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/ccwgroup.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h index f2ef34f6d6e5..01a905eb11e0 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h @@ -6,14 +6,12 @@ struct ccw_driver; /** * struct ccwgroup_device - ccw group device - * @creator_id: unique number of the driver * @state: online/offline state * @count: number of attached slave devices * @dev: embedded device structure * @cdev: variable number of slave devices, allocated as needed */ struct ccwgroup_device { - unsigned long creator_id; enum { CCWGROUP_OFFLINE, CCWGROUP_ONLINE, -- cgit v1.2.3 From c1a7b32a14138f908df52d7c53b5ce3415ec6b50 Mon Sep 17 00:00:00 2001 From: Takuya Yoshikawa Date: Sun, 20 May 2012 13:15:07 +0900 Subject: KVM: Avoid wasting pages for small lpage_info arrays lpage_info is created for each large level even when the memory slot is not for RAM. This means that when we add one slot for a PCI device, we end up allocating at least KVM_NR_PAGE_SIZES - 1 pages by vmalloc(). To make things worse, there is an increasing number of devices which would result in more pages being wasted this way. This patch mitigates this problem by using kvm_kvzalloc(). Signed-off-by: Takuya Yoshikawa Signed-off-by: Avi Kivity --- arch/x86/kvm/x86.c | 4 ++-- include/linux/kvm_host.h | 3 +++ virt/kvm/kvm_main.c | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index be6d54929fa7..f12a52408cda 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6304,7 +6304,7 @@ void kvm_arch_free_memslot(struct kvm_memory_slot *free, for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) { if (!dont || free->arch.lpage_info[i] != dont->arch.lpage_info[i]) { - vfree(free->arch.lpage_info[i]); + kvm_kvfree(free->arch.lpage_info[i]); free->arch.lpage_info[i] = NULL; } } @@ -6323,7 +6323,7 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages) slot->base_gfn, level) + 1; slot->arch.lpage_info[i] = - vzalloc(lpages * sizeof(*slot->arch.lpage_info[i])); + kvm_kvzalloc(lpages * sizeof(*slot->arch.lpage_info[i])); if (!slot->arch.lpage_info[i]) goto out_free; diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index c4464356b35b..19b83f6efa49 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -535,6 +535,9 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu); void kvm_free_physmem(struct kvm *kvm); +void *kvm_kvzalloc(unsigned long size); +void kvm_kvfree(const void *addr); + #ifndef __KVM_HAVE_ARCH_VM_ALLOC static inline struct kvm *kvm_arch_alloc_vm(void) { diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 1148c96a4817..02cb440f802d 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -520,7 +520,7 @@ out_err_nodisable: * Avoid using vmalloc for a small buffer. * Should not be used when the size is statically known. */ -static void *kvm_kvzalloc(unsigned long size) +void *kvm_kvzalloc(unsigned long size) { if (size > PAGE_SIZE) return vzalloc(size); @@ -528,7 +528,7 @@ static void *kvm_kvzalloc(unsigned long size) return kzalloc(size, GFP_KERNEL); } -static void kvm_kvfree(const void *addr) +void kvm_kvfree(const void *addr) { if (is_vmalloc_addr(addr)) vfree(addr); -- cgit v1.2.3 From aaf07bc291c828189ae5221b370905a89bbb859d Mon Sep 17 00:00:00 2001 From: Xudong Hao Date: Mon, 28 May 2012 19:33:34 +0800 Subject: KVM: VMX: Add EPT A/D bits definitions Signed-off-by: Haitao Shan Signed-off-by: Xudong Hao Signed-off-by: Avi Kivity --- arch/x86/include/asm/vmx.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 31f180c21ce9..de007c272730 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -404,6 +404,7 @@ enum vmcs_field { #define VMX_EPTP_WB_BIT (1ull << 14) #define VMX_EPT_2MB_PAGE_BIT (1ull << 16) #define VMX_EPT_1GB_PAGE_BIT (1ull << 17) +#define VMX_EPT_AD_BIT (1ull << 21) #define VMX_EPT_EXTENT_INDIVIDUAL_BIT (1ull << 24) #define VMX_EPT_EXTENT_CONTEXT_BIT (1ull << 25) #define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26) @@ -415,11 +416,14 @@ enum vmcs_field { #define VMX_EPT_MAX_GAW 0x4 #define VMX_EPT_MT_EPTE_SHIFT 3 #define VMX_EPT_GAW_EPTP_SHIFT 3 +#define VMX_EPT_AD_ENABLE_BIT (1ull << 6) #define VMX_EPT_DEFAULT_MT 0x6ull #define VMX_EPT_READABLE_MASK 0x1ull #define VMX_EPT_WRITABLE_MASK 0x2ull #define VMX_EPT_EXECUTABLE_MASK 0x4ull #define VMX_EPT_IPAT_BIT (1ull << 6) +#define VMX_EPT_ACCESS_BIT (1ull << 8) +#define VMX_EPT_DIRTY_BIT (1ull << 9) #define VMX_EPT_IDENTITY_PAGETABLE_ADDR 0xfffbc000ul -- cgit v1.2.3 From 83c3a3312235220476d3c207f67bd17be6e17ff9 Mon Sep 17 00:00:00 2001 From: Xudong Hao Date: Mon, 28 May 2012 19:33:35 +0800 Subject: KVM: VMX: Add parameter to control A/D bits support, default is on Add kernel parameter to control A/D bits support, it's on by default. Signed-off-by: Haitao Shan Signed-off-by: Xudong Hao Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch') diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 32eb58866292..18590e003bd2 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -71,6 +71,9 @@ static bool __read_mostly enable_unrestricted_guest = 1; module_param_named(unrestricted_guest, enable_unrestricted_guest, bool, S_IRUGO); +static bool __read_mostly enable_ept_ad_bits = 1; +module_param_named(eptad, enable_ept_ad_bits, bool, S_IRUGO); + static bool __read_mostly emulate_invalid_guest_state = 0; module_param(emulate_invalid_guest_state, bool, S_IRUGO); @@ -789,6 +792,11 @@ static inline bool cpu_has_vmx_ept_4levels(void) return vmx_capability.ept & VMX_EPT_PAGE_WALK_4_BIT; } +static inline bool cpu_has_vmx_ept_ad_bits(void) +{ + return vmx_capability.ept & VMX_EPT_AD_BIT; +} + static inline bool cpu_has_vmx_invept_individual_addr(void) { return vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT; @@ -2645,8 +2653,12 @@ static __init int hardware_setup(void) !cpu_has_vmx_ept_4levels()) { enable_ept = 0; enable_unrestricted_guest = 0; + enable_ept_ad_bits = 0; } + if (!cpu_has_vmx_ept_ad_bits()) + enable_ept_ad_bits = 0; + if (!cpu_has_vmx_unrestricted_guest()) enable_unrestricted_guest = 0; -- cgit v1.2.3 From b38f99347871d7fc49e6367395dce0d757f6ab8d Mon Sep 17 00:00:00 2001 From: Xudong Hao Date: Mon, 28 May 2012 19:33:36 +0800 Subject: KVM: VMX: Enable EPT A/D bits if supported by turning on relevant bit in EPTP In EPT page structure entry, Enable EPT A/D bits if processor supported. Signed-off-by: Haitao Shan Signed-off-by: Xudong Hao Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 18590e003bd2..d392e5427ca0 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3039,6 +3039,8 @@ static u64 construct_eptp(unsigned long root_hpa) /* TODO write the value reading from MSR */ eptp = VMX_EPT_DEFAULT_MT | VMX_EPT_DEFAULT_GAW << VMX_EPT_GAW_EPTP_SHIFT; + if (enable_ept_ad_bits) + eptp |= VMX_EPT_AD_ENABLE_BIT; eptp |= (root_hpa & PAGE_MASK); return eptp; -- cgit v1.2.3 From 3f6d8c8a478dd1ab2a4944b0d65474df06ecd882 Mon Sep 17 00:00:00 2001 From: Xudong Hao Date: Tue, 22 May 2012 11:23:15 +0800 Subject: KVM: VMX: Use EPT Access bit in response to memory notifiers Signed-off-by: Haitao Shan Signed-off-by: Xudong Hao Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 14 ++++++++------ arch/x86/kvm/vmx.c | 6 ++++-- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index be3cea4407ff..d07e436b7a42 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1242,7 +1242,8 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp, int young = 0; /* - * Emulate the accessed bit for EPT, by checking if this page has + * In case of absence of EPT Access and Dirty Bits supports, + * emulate the accessed bit for EPT, by checking if this page has * an EPT mapping, and clearing it if it does. On the next access, * a new EPT mapping will be established. * This has some overhead, but not as much as the cost of swapping @@ -1253,11 +1254,12 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp, for (sptep = rmap_get_first(*rmapp, &iter); sptep; sptep = rmap_get_next(&iter)) { - BUG_ON(!(*sptep & PT_PRESENT_MASK)); + BUG_ON(!is_shadow_present_pte(*sptep)); - if (*sptep & PT_ACCESSED_MASK) { + if (*sptep & shadow_accessed_mask) { young = 1; - clear_bit(PT_ACCESSED_SHIFT, (unsigned long *)sptep); + clear_bit((ffs(shadow_accessed_mask) - 1), + (unsigned long *)sptep); } } @@ -1281,9 +1283,9 @@ static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp, for (sptep = rmap_get_first(*rmapp, &iter); sptep; sptep = rmap_get_next(&iter)) { - BUG_ON(!(*sptep & PT_PRESENT_MASK)); + BUG_ON(!is_shadow_present_pte(*sptep)); - if (*sptep & PT_ACCESSED_MASK) { + if (*sptep & shadow_accessed_mask) { young = 1; break; } diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index d392e5427ca0..396148ab089b 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -7289,8 +7289,10 @@ static int __init vmx_init(void) vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); if (enable_ept) { - kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull, - VMX_EPT_EXECUTABLE_MASK); + kvm_mmu_set_mask_ptes(0ull, + (enable_ept_ad_bits) ? VMX_EPT_ACCESS_BIT : 0ull, + (enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull, + 0ull, VMX_EPT_EXECUTABLE_MASK); ept_set_mmio_spte_mask(); kvm_enable_tdp(); } else -- cgit v1.2.3 From a6bb7929677aacfce3f864c3cdacaa7d527945d5 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 17 May 2012 13:14:08 +0300 Subject: KVM: ia64: Mark ia64 KVM as BROKEN Practically all patches to ia64 KVM are build fixes; numerous warnings remain; the last patch from the maintainer was committed more than three years ago. It is clear that no one is using this thing. Mark as BROKEN to ensure people don't get hit by pointless build problems. Signed-off-by: Avi Kivity Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- arch/ia64/kvm/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig index 9806e55f91be..df5351e3eed7 100644 --- a/arch/ia64/kvm/Kconfig +++ b/arch/ia64/kvm/Kconfig @@ -19,6 +19,7 @@ if VIRTUALIZATION config KVM tristate "Kernel-based Virtual Machine (KVM) support" + depends on BROKEN depends on HAVE_KVM && MODULES && EXPERIMENTAL # for device assignment: depends on PCI -- cgit v1.2.3 From 1952639665e92481c34c34c3e2a71bf3e66ba362 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 4 Jun 2012 14:53:23 +0300 Subject: KVM: MMU: do not iterate over all VMs in mmu_shrink() mmu_shrink() needlessly iterates over all VMs even though it will not attempt to free mmu pages from more than one on them. Fix that and also check used mmu pages count outside of VM lock to skip inactive VMs faster. Signed-off-by: Gleb Natapov Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index d07e436b7a42..1ca7164a74f1 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -3944,7 +3944,6 @@ static void kvm_mmu_remove_some_alloc_mmu_pages(struct kvm *kvm, static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc) { struct kvm *kvm; - struct kvm *kvm_freed = NULL; int nr_to_scan = sc->nr_to_scan; if (nr_to_scan == 0) @@ -3956,22 +3955,30 @@ static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc) int idx; LIST_HEAD(invalid_list); + /* + * n_used_mmu_pages is accessed without holding kvm->mmu_lock + * here. We may skip a VM instance errorneosly, but we do not + * want to shrink a VM that only started to populate its MMU + * anyway. + */ + if (kvm->arch.n_used_mmu_pages > 0) { + if (!nr_to_scan--) + break; + continue; + } + idx = srcu_read_lock(&kvm->srcu); spin_lock(&kvm->mmu_lock); - if (!kvm_freed && nr_to_scan > 0 && - kvm->arch.n_used_mmu_pages > 0) { - kvm_mmu_remove_some_alloc_mmu_pages(kvm, - &invalid_list); - kvm_freed = kvm; - } - nr_to_scan--; + kvm_mmu_remove_some_alloc_mmu_pages(kvm, &invalid_list); kvm_mmu_commit_zap_page(kvm, &invalid_list); + spin_unlock(&kvm->mmu_lock); srcu_read_unlock(&kvm->srcu, idx); + + list_move_tail(&kvm->vm_list, &vm_list); + break; } - if (kvm_freed) - list_move_tail(&kvm_freed->vm_list, &vm_list); raw_spin_unlock(&kvm_lock); -- cgit v1.2.3 From b246dd5df139501b974bd6b28f7815e53b3a792f Mon Sep 17 00:00:00 2001 From: Orit Wasserman Date: Thu, 31 May 2012 14:49:22 +0300 Subject: KVM: VMX: Fix KVM_SET_SREGS with big real mode segments For example migration between Westmere and Nehelem hosts, caught in big real mode. The code that fixes the segments for real mode guest was moved from enter_rmode to vmx_set_segments. enter_rmode calls vmx_set_segments for each segment. Signed-off-by: Orit Wasserman Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 70 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 396148ab089b..f78662ec8677 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -618,6 +618,10 @@ static void kvm_cpu_vmxon(u64 addr); static void kvm_cpu_vmxoff(void); static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3); static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr); +static void vmx_set_segment(struct kvm_vcpu *vcpu, + struct kvm_segment *var, int seg); +static void vmx_get_segment(struct kvm_vcpu *vcpu, + struct kvm_segment *var, int seg); static DEFINE_PER_CPU(struct vmcs *, vmxarea); static DEFINE_PER_CPU(struct vmcs *, current_vmcs); @@ -2782,6 +2786,7 @@ static void enter_rmode(struct kvm_vcpu *vcpu) { unsigned long flags; struct vcpu_vmx *vmx = to_vmx(vcpu); + struct kvm_segment var; if (enable_unrestricted_guest) return; @@ -2825,20 +2830,23 @@ static void enter_rmode(struct kvm_vcpu *vcpu) if (emulate_invalid_guest_state) goto continue_rmode; - vmcs_write16(GUEST_SS_SELECTOR, vmcs_readl(GUEST_SS_BASE) >> 4); - vmcs_write32(GUEST_SS_LIMIT, 0xffff); - vmcs_write32(GUEST_SS_AR_BYTES, 0xf3); + vmx_get_segment(vcpu, &var, VCPU_SREG_SS); + vmx_set_segment(vcpu, &var, VCPU_SREG_SS); + + vmx_get_segment(vcpu, &var, VCPU_SREG_CS); + vmx_set_segment(vcpu, &var, VCPU_SREG_CS); + + vmx_get_segment(vcpu, &var, VCPU_SREG_ES); + vmx_set_segment(vcpu, &var, VCPU_SREG_ES); - vmcs_write32(GUEST_CS_AR_BYTES, 0xf3); - vmcs_write32(GUEST_CS_LIMIT, 0xffff); - if (vmcs_readl(GUEST_CS_BASE) == 0xffff0000) - vmcs_writel(GUEST_CS_BASE, 0xf0000); - vmcs_write16(GUEST_CS_SELECTOR, vmcs_readl(GUEST_CS_BASE) >> 4); + vmx_get_segment(vcpu, &var, VCPU_SREG_DS); + vmx_set_segment(vcpu, &var, VCPU_SREG_DS); - fix_rmode_seg(VCPU_SREG_ES, &vmx->rmode.es); - fix_rmode_seg(VCPU_SREG_DS, &vmx->rmode.ds); - fix_rmode_seg(VCPU_SREG_GS, &vmx->rmode.gs); - fix_rmode_seg(VCPU_SREG_FS, &vmx->rmode.fs); + vmx_get_segment(vcpu, &var, VCPU_SREG_GS); + vmx_set_segment(vcpu, &var, VCPU_SREG_GS); + + vmx_get_segment(vcpu, &var, VCPU_SREG_FS); + vmx_set_segment(vcpu, &var, VCPU_SREG_FS); continue_rmode: kvm_mmu_reset_context(vcpu); @@ -3243,6 +3251,44 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu, vmcs_write32(sf->ar_bytes, ar); __clear_bit(VCPU_EXREG_CPL, (ulong *)&vcpu->arch.regs_avail); + + /* + * Fix segments for real mode guest in hosts that don't have + * "unrestricted_mode" or it was disabled. + * This is done to allow migration of the guests from hosts with + * unrestricted guest like Westmere to older host that don't have + * unrestricted guest like Nehelem. + */ + if (!enable_unrestricted_guest && vmx->rmode.vm86_active) { + switch (seg) { + case VCPU_SREG_CS: + vmcs_write32(GUEST_CS_AR_BYTES, 0xf3); + vmcs_write32(GUEST_CS_LIMIT, 0xffff); + if (vmcs_readl(GUEST_CS_BASE) == 0xffff0000) + vmcs_writel(GUEST_CS_BASE, 0xf0000); + vmcs_write16(GUEST_CS_SELECTOR, + vmcs_readl(GUEST_CS_BASE) >> 4); + break; + case VCPU_SREG_ES: + fix_rmode_seg(VCPU_SREG_ES, &vmx->rmode.es); + break; + case VCPU_SREG_DS: + fix_rmode_seg(VCPU_SREG_DS, &vmx->rmode.ds); + break; + case VCPU_SREG_GS: + fix_rmode_seg(VCPU_SREG_GS, &vmx->rmode.gs); + break; + case VCPU_SREG_FS: + fix_rmode_seg(VCPU_SREG_FS, &vmx->rmode.fs); + break; + case VCPU_SREG_SS: + vmcs_write16(GUEST_SS_SELECTOR, + vmcs_readl(GUEST_SS_BASE) >> 4); + vmcs_write32(GUEST_SS_LIMIT, 0xffff); + vmcs_write32(GUEST_SS_AR_BYTES, 0xf3); + break; + } + } } static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) -- cgit v1.2.3 From 4ee0444bebf3d0399c93841d98826ade193e6330 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 29 May 2012 15:15:56 +0800 Subject: hexagon: SMP: Remove call to ipi_call_lock()/ipi_call_unlock() ipi_call_lock/unlock() lock resp. unlock call_function.lock. This lock protects only the call_function data structure itself, but it's completely unrelated to cpu_online_mask. The mask to which the IPIs are sent is calculated before call_function.lock is taken in smp_call_function_many(), so the locking around set_cpu_online() is pointless and can be removed. [ tglx: Massaged changelog ] Signed-off-by: Yong Zhang Cc: ralf@linux-mips.org Cc: sshtylyov@mvista.com Cc: david.daney@cavium.com Cc: nikunj@linux.vnet.ibm.com Cc: paulmck@linux.vnet.ibm.com Cc: axboe@kernel.dk Cc: Richard Kuo Cc: linux-hexagon@vger.kernel.org Link: http://lkml.kernel.org/r/1338275765-3217-2-git-send-email-yong.zhang0@gmail.com Acked-by: Srivatsa S. Bhat Acked-by: Peter Zijlstra Signed-off-by: Thomas Gleixner --- arch/hexagon/kernel/smp.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c index f7264621e58d..149fbefc1a4d 100644 --- a/arch/hexagon/kernel/smp.c +++ b/arch/hexagon/kernel/smp.c @@ -180,9 +180,7 @@ void __cpuinit start_secondary(void) notify_cpu_starting(cpu); - ipi_call_lock(); set_cpu_online(cpu, true); - ipi_call_unlock(); local_irq_enable(); -- cgit v1.2.3 From 4cbd19fcf9d49f28766415b96eb6201bc263d817 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 29 May 2012 15:15:57 +0800 Subject: mn10300: SMP: Remove call to ipi_call_lock()/ipi_call_unlock() ipi_call_lock/unlock() lock resp. unlock call_function.lock. This lock protects only the call_function data structure itself, but it's completely unrelated to cpu_online_mask. The mask to which the IPIs are sent is calculated before call_function.lock is taken in smp_call_function_many(), so the locking around set_cpu_online() is pointless and can be removed. [ tglx: Massaged changelog ] Signed-off-by: Yong Zhang Cc: ralf@linux-mips.org Cc: sshtylyov@mvista.com Cc: david.daney@cavium.com Cc: nikunj@linux.vnet.ibm.com Cc: paulmck@linux.vnet.ibm.com Cc: axboe@kernel.dk Cc: peterz@infradead.org Cc: David Howells Cc: Koichi Yasutake Cc: linux-am33-list@redhat.com Link: http://lkml.kernel.org/r/1338275765-3217-3-git-send-email-yong.zhang0@gmail.com Acked-by: Srivatsa S. Bhat Acked-by: Peter Zijlstra Signed-off-by: Thomas Gleixner --- arch/mn10300/kernel/smp.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c index 090d35d36973..e62c223e4c45 100644 --- a/arch/mn10300/kernel/smp.c +++ b/arch/mn10300/kernel/smp.c @@ -876,9 +876,7 @@ static void __init smp_online(void) notify_cpu_starting(cpu); - ipi_call_lock(); set_cpu_online(cpu, true); - ipi_call_unlock(); local_irq_enable(); } -- cgit v1.2.3 From ac4216d6922f90c459d531e051c832dadde3a8f7 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 29 May 2012 15:15:58 +0800 Subject: parisc: Smp: remove call to ipi_call_lock()/ipi_call_unlock() ipi_call_lock/unlock() lock resp. unlock call_function.lock. This lock protects only the call_function data structure itself, but it's completely unrelated to cpu_online_mask. The mask to which the IPIs are sent is calculated before call_function.lock is taken in smp_call_function_many(), so the locking around set_cpu_online() is pointless and can be removed. [ tglx: Massaged changelog ] Signed-off-by: Yong Zhang Cc: ralf@linux-mips.org Cc: sshtylyov@mvista.com Cc: david.daney@cavium.com Cc: nikunj@linux.vnet.ibm.com Cc: paulmck@linux.vnet.ibm.com Cc: axboe@kernel.dk Cc: peterz@infradead.org Cc: James E.J. Bottomley Cc: Helge Deller Cc: linux-parisc@vger.kernel.org Link: http://lkml.kernel.org/r/1338275765-3217-4-git-send-email-yong.zhang0@gmail.com Acked-by: Srivatsa S. Bhat Acked-by: Peter Zijlstra Signed-off-by: Thomas Gleixner --- arch/parisc/kernel/smp.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index a47828d31fe6..6266730efd61 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -300,9 +300,7 @@ smp_cpu_init(int cpunum) notify_cpu_starting(cpunum); - ipi_call_lock(); set_cpu_online(cpunum, true); - ipi_call_unlock(); /* Initialise the idle task for this CPU */ atomic_inc(&init_mm.mm_count); -- cgit v1.2.3 From 46ce7fbfdbe0be6aaf0e816331aac08a74a00e5a Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 29 May 2012 15:15:59 +0800 Subject: S390: Smp: remove call to ipi_call_lock()/ipi_call_unlock() ipi_call_lock/unlock() lock resp. unlock call_function.lock. This lock protects only the call_function data structure itself, but it's completely unrelated to cpu_online_mask. The mask to which the IPIs are sent is calculated before call_function.lock is taken in smp_call_function_many(), so the locking around set_cpu_online() is pointless and can be removed. [ tglx: Massaged changelog ] Signed-off-by: Yong Zhang Cc: ralf@linux-mips.org Cc: sshtylyov@mvista.com Cc: david.daney@cavium.com Cc: nikunj@linux.vnet.ibm.com Cc: paulmck@linux.vnet.ibm.com Cc: axboe@kernel.dk Cc: peterz@infradead.org Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Link: http://lkml.kernel.org/r/1338275765-3217-5-git-send-email-yong.zhang0@gmail.com Acked-by: Srivatsa S. Bhat Acked-by: Peter Zijlstra Signed-off-by: Thomas Gleixner --- arch/s390/kernel/smp.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 15cca26ccb6c..8dca9c248ac7 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -717,9 +717,7 @@ static void __cpuinit smp_start_secondary(void *cpuvoid) init_cpu_vtimer(); pfault_init(); notify_cpu_starting(smp_processor_id()); - ipi_call_lock(); set_cpu_online(smp_processor_id(), true); - ipi_call_unlock(); local_irq_enable(); /* cpu_idle will call schedule for us */ cpu_idle(); -- cgit v1.2.3 From 8efdfc3a4ed009c978dab6609d15fb958e7cff12 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 29 May 2012 15:16:00 +0800 Subject: tile: SMP: Remove call to ipi_call_lock()/ipi_call_unlock() ipi_call_lock/unlock() lock resp. unlock call_function.lock. This lock protects only the call_function data structure itself, but it's completely unrelated to cpu_online_mask. The mask to which the IPIs are sent is calculated before call_function.lock is taken in smp_call_function_many(), so the locking around set_cpu_online() is pointless and can be removed. [ tglx: Massaged changelog ] Signed-off-by: Yong Zhang Cc: ralf@linux-mips.org Cc: sshtylyov@mvista.com Cc: david.daney@cavium.com Cc: nikunj@linux.vnet.ibm.com Cc: paulmck@linux.vnet.ibm.com Cc: axboe@kernel.dk Cc: peterz@infradead.org Cc: Chris Metcalf Link: http://lkml.kernel.org/r/1338275765-3217-6-git-send-email-yong.zhang0@gmail.com Acked-by: Srivatsa S. Bhat Acked-by: Peter Zijlstra Signed-off-by: Thomas Gleixner --- arch/tile/kernel/smpboot.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'arch') diff --git a/arch/tile/kernel/smpboot.c b/arch/tile/kernel/smpboot.c index 84873fbe8f27..e686c5ac90be 100644 --- a/arch/tile/kernel/smpboot.c +++ b/arch/tile/kernel/smpboot.c @@ -198,17 +198,7 @@ void __cpuinit online_secondary(void) notify_cpu_starting(smp_processor_id()); - /* - * We need to hold call_lock, so there is no inconsistency - * between the time smp_call_function() determines number of - * IPI recipients, and the time when the determination is made - * for which cpus receive the IPI. Holding this - * lock helps us to not include this cpu in a currently in progress - * smp_call_function(). - */ - ipi_call_lock(); set_cpu_online(smp_processor_id(), 1); - ipi_call_unlock(); __get_cpu_var(cpu_state) = CPU_ONLINE; /* Set up tile-specific state for this cpu. */ -- cgit v1.2.3 From 3b6f70fd7dd4e19fc674ec99e389bf0da5589525 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 29 May 2012 15:16:01 +0800 Subject: x86-smp-remove-call-to-ipi_call_lock-ipi_call_unlock ipi_call_lock/unlock() lock resp. unlock call_function.lock. This lock protects only the call_function data structure itself, but it's completely unrelated to cpu_online_mask. The mask to which the IPIs are sent is calculated before call_function.lock is taken in smp_call_function_many(), so the locking around set_cpu_online() is pointless and can be removed. [ tglx: Massaged changelog ] Signed-off-by: Yong Zhang Cc: ralf@linux-mips.org Cc: sshtylyov@mvista.com Cc: david.daney@cavium.com Cc: nikunj@linux.vnet.ibm.com Cc: paulmck@linux.vnet.ibm.com Cc: axboe@kernel.dk Cc: peterz@infradead.org Cc: Konrad Rzeszutek Wilk Cc: Jeremy Fitzhardinge Cc: Ingo Molnar Cc: "H. Peter Anvin" Link: http://lkml.kernel.org/r/1338275765-3217-7-git-send-email-yong.zhang0@gmail.com Acked-by: Srivatsa S. Bhat Acked-by: Peter Zijlstra Signed-off-by: Thomas Gleixner --- arch/x86/kernel/smpboot.c | 9 --------- arch/x86/xen/smp.c | 2 -- 2 files changed, 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f56f96da77f5..b2fd28ff84b5 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -255,22 +255,13 @@ notrace static void __cpuinit start_secondary(void *unused) check_tsc_sync_target(); /* - * We need to hold call_lock, so there is no inconsistency - * between the time smp_call_function() determines number of - * IPI recipients, and the time when the determination is made - * for which cpus receive the IPI. Holding this - * lock helps us to not include this cpu in a currently in progress - * smp_call_function(). - * * We need to hold vector_lock so there the set of online cpus * does not change while we are assigning vectors to cpus. Holding * this lock ensures we don't half assign or remove an irq from a cpu. */ - ipi_call_lock(); lock_vector_lock(); set_cpu_online(smp_processor_id(), true); unlock_vector_lock(); - ipi_call_unlock(); per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; x86_platform.nmi_init(); diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index afb250d22a6b..f58dca7a6e52 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -80,9 +80,7 @@ static void __cpuinit cpu_bringup(void) notify_cpu_starting(cpu); - ipi_call_lock(); set_cpu_online(cpu, true); - ipi_call_unlock(); this_cpu_write(cpu_state, CPU_ONLINE); -- cgit v1.2.3 From 459165e25030c0023cb54f73c14261a3d2f4a244 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 29 May 2012 15:16:02 +0800 Subject: ia64: SMP: Remove call to ipi_call_lock_irq()/ipi_call_unlock_irq() ipi_call_lock/unlock() lock resp. unlock call_function.lock. This lock protects only the call_function data structure itself, but it's completely unrelated to cpu_online_mask. The mask to which the IPIs are sent is calculated before call_function.lock is taken in smp_call_function_many(), so the locking around set_cpu_online() is pointless and can be removed. [ tglx: Massaged changelog ] Signed-off-by: Yong Zhang Cc: ralf@linux-mips.org Cc: sshtylyov@mvista.com Cc: david.daney@cavium.com Cc: nikunj@linux.vnet.ibm.com Cc: paulmck@linux.vnet.ibm.com Cc: axboe@kernel.dk Cc: peterz@infradead.org Cc: Tony Luck Cc: Fenghua Yu Cc: linux-ia64@vger.kernel.org Link: http://lkml.kernel.org/r/1338275765-3217-8-git-send-email-yong.zhang0@gmail.com Acked-by: Srivatsa S. Bhat Acked-by: Peter Zijlstra Signed-off-by: Thomas Gleixner --- arch/ia64/kernel/smpboot.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 1113b8aba07f..963d2db53bfa 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -382,7 +382,6 @@ smp_callin (void) set_numa_node(cpu_to_node_map[cpuid]); set_numa_mem(local_memory_node(cpu_to_node_map[cpuid])); - ipi_call_lock_irq(); spin_lock(&vector_lock); /* Setup the per cpu irq handling data structures */ __setup_vector_irq(cpuid); @@ -390,7 +389,6 @@ smp_callin (void) set_cpu_online(cpuid, true); per_cpu(cpu_state, cpuid) = CPU_ONLINE; spin_unlock(&vector_lock); - ipi_call_unlock_irq(); smp_setup_percpu_timer(); -- cgit v1.2.3 From bc6833009583bd5b096ef7aa2bb006854a5a2dce Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 29 May 2012 16:27:33 +0800 Subject: SPARC: SMP: Remove call to ipi_call_lock_irq()/ipi_call_unlock_irq() ipi_call_lock/unlock() lock resp. unlock call_function.lock. This lock protects only the call_function data structure itself, but it's completely unrelated to cpu_online_mask. The mask to which the IPIs are sent is calculated before call_function.lock is taken in smp_call_function_many(), so the locking around set_cpu_online() is pointless and can be removed. Delay irq enable to after set_cpu_online(). [ tglx: Massaged changelog ] Signed-off-by: Yong Zhang Cc: ralf@linux-mips.org Cc: sshtylyov@mvista.com Cc: david.daney@cavium.com Cc: nikunj@linux.vnet.ibm.com Cc: paulmck@linux.vnet.ibm.com Cc: axboe@kernel.dk Cc: peterz@infradead.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/20120529082732.GA4250@zhy Acked-by: "David S. Miller" Acked-by: Srivatsa S. Bhat Acked-by: Peter Zijlstra Signed-off-by: Thomas Gleixner --- arch/sparc/kernel/smp_64.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index f591598d92f6..781bcb10b8bd 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -103,8 +103,6 @@ void __cpuinit smp_callin(void) if (cheetah_pcache_forced_on) cheetah_enable_pcache(); - local_irq_enable(); - callin_flag = 1; __asm__ __volatile__("membar #Sync\n\t" "flush %%g6" : : : "memory"); @@ -124,9 +122,8 @@ void __cpuinit smp_callin(void) while (!cpumask_test_cpu(cpuid, &smp_commenced_mask)) rmb(); - ipi_call_lock_irq(); set_cpu_online(cpuid, true); - ipi_call_unlock_irq(); + local_irq_enable(); /* idle thread is expected to have preempt disabled */ preempt_disable(); @@ -1308,9 +1305,7 @@ int __cpu_disable(void) mdelay(1); local_irq_disable(); - ipi_call_lock(); set_cpu_online(cpu, false); - ipi_call_unlock(); cpu_map_rebuild(); -- cgit v1.2.3 From 72ec61a9e8347375e37c05e23511173d8451c3d4 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 29 May 2012 15:16:04 +0800 Subject: POWERPC: Smp: remove call to ipi_call_lock()/ipi_call_unlock() ipi_call_lock/unlock() lock resp. unlock call_function.lock. This lock protects only the call_function data structure itself, but it's completely unrelated to cpu_online_mask. The mask to which the IPIs are sent is calculated before call_function.lock is taken in smp_call_function_many(), so the locking around set_cpu_online() is pointless and can be removed. [ tglx: Massaged changelog ] Signed-off-by: Yong Zhang Cc: ralf@linux-mips.org Cc: sshtylyov@mvista.com Cc: david.daney@cavium.com Cc: nikunj@linux.vnet.ibm.com Cc: paulmck@linux.vnet.ibm.com Cc: axboe@kernel.dk Cc: peterz@infradead.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1338275765-3217-10-git-send-email-yong.zhang0@gmail.com Acked-by: Srivatsa S. Bhat Acked-by: Peter Zijlstra Signed-off-by: Thomas Gleixner --- arch/powerpc/kernel/smp.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index e4cb34322de4..e1417c42155c 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -571,7 +571,6 @@ void __devinit start_secondary(void *unused) if (system_state == SYSTEM_RUNNING) vdso_data->processorCount++; #endif - ipi_call_lock(); notify_cpu_starting(cpu); set_cpu_online(cpu, true); /* Update sibling maps */ @@ -601,7 +600,6 @@ void __devinit start_secondary(void *unused) of_node_put(np); } of_node_put(l2_cache); - ipi_call_unlock(); local_irq_enable(); -- cgit v1.2.3 From 43cc7e86f3200b094e2960b732623aeec00b482d Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 15 May 2012 17:26:16 +0200 Subject: smp: Remove num_booting_cpus() No users. Signed-off-by: Thomas Gleixner Cc: Srivatsa S. Bhat Cc: Rusty Russell --- arch/m32r/include/asm/smp.h | 5 ----- arch/x86/include/asm/smp.h | 5 ----- include/linux/smp.h | 1 - 3 files changed, 11 deletions(-) (limited to 'arch') diff --git a/arch/m32r/include/asm/smp.h b/arch/m32r/include/asm/smp.h index cf7829a61551..c689b828dfe2 100644 --- a/arch/m32r/include/asm/smp.h +++ b/arch/m32r/include/asm/smp.h @@ -79,11 +79,6 @@ static __inline__ int cpu_number_map(int cpu) return cpu; } -static __inline__ unsigned int num_booting_cpus(void) -{ - return cpumask_weight(&cpu_callout_map); -} - extern void smp_send_timer(void); extern unsigned long send_IPI_mask_phys(const cpumask_t*, int, int); diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index f48394513c37..2ffa95dc2333 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -169,11 +169,6 @@ void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle); void smp_store_cpu_info(int id); #define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu) -/* We don't mark CPUs online until __cpu_up(), so we need another measure */ -static inline int num_booting_cpus(void) -{ - return cpumask_weight(cpu_callout_mask); -} #else /* !CONFIG_SMP */ #define wbinvd_on_cpu(cpu) wbinvd() static inline int wbinvd_on_all_cpus(void) diff --git a/include/linux/smp.h b/include/linux/smp.h index a34d4f15430d..dd6f06be3c9f 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -177,7 +177,6 @@ static inline int up_smp_call_function(smp_call_func_t func, void *info) } while (0) static inline void smp_send_reschedule(int cpu) { } -#define num_booting_cpus() 1 #define smp_prepare_boot_cpu() do {} while (0) #define smp_call_function_many(mask, func, info, wait) \ (up_smp_call_function(func, info)) -- cgit v1.2.3 From 7db971b235480849aa5b9209b67b62e987b3181b Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Sun, 3 Jun 2012 01:11:34 +0300 Subject: x86/platform: Introduce APIC post-initialization callback Some subarchitectures (such as vSMP) need to slightly adjust the underlying APIC structure. Add an APIC post-initialization callback to 'struct x86_platform_ops' for this purpose and use it for adjusting the APIC structure on vSMP systems. Signed-off-by: Ido Yariv Acked-by: Shai Fultheim Link: http://lkml.kernel.org/r/1338675095-27260-1-git-send-email-ido@wizery.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/x86_init.h | 2 ++ arch/x86/kernel/apic/probe_32.c | 3 +++ arch/x86/kernel/apic/probe_64.c | 11 ++--------- arch/x86/kernel/vsmp_64.c | 13 +++++++++++++ 4 files changed, 20 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index c090af10ac7d..c377d9ccb696 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -164,6 +164,7 @@ struct x86_cpuinit_ops { * @i8042_detect pre-detect if i8042 controller exists * @save_sched_clock_state: save state for sched_clock() on suspend * @restore_sched_clock_state: restore state for sched_clock() on resume + * @apic_post_init: adjust apic if neeeded */ struct x86_platform_ops { unsigned long (*calibrate_tsc)(void); @@ -177,6 +178,7 @@ struct x86_platform_ops { int (*i8042_detect)(void); void (*save_sched_clock_state)(void); void (*restore_sched_clock_state)(void); + void (*apic_post_init)(void); }; struct pci_dev; diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 1b291da09e60..8616d5198e16 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -208,6 +208,9 @@ void __init default_setup_apic_routing(void) if (apic->setup_apic_routing) apic->setup_apic_routing(); + + if (x86_platform.apic_post_init) + x86_platform.apic_post_init(); } void __init generic_apic_probe(void) diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index 3fe986698929..1793dba7a741 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c @@ -23,11 +23,6 @@ #include #include -static int apicid_phys_pkg_id(int initial_apic_id, int index_msb) -{ - return hard_smp_processor_id() >> index_msb; -} - /* * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. */ @@ -48,10 +43,8 @@ void __init default_setup_apic_routing(void) } } - if (is_vsmp_box()) { - /* need to update phys_pkg_id */ - apic->phys_pkg_id = apicid_phys_pkg_id; - } + if (x86_platform.apic_post_init) + x86_platform.apic_post_init(); } /* Same for both flat and physical. */ diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c index 8eeb55a551b4..59eea855f451 100644 --- a/arch/x86/kernel/vsmp_64.c +++ b/arch/x86/kernel/vsmp_64.c @@ -187,12 +187,25 @@ static void __init vsmp_cap_cpus(void) #endif } +static int apicid_phys_pkg_id(int initial_apic_id, int index_msb) +{ + return hard_smp_processor_id() >> index_msb; +} + +static void vsmp_apic_post_init(void) +{ + /* need to update phys_pkg_id */ + apic->phys_pkg_id = apicid_phys_pkg_id; +} + void __init vsmp_init(void) { detect_vsmp_box(); if (!is_vsmp_box()) return; + x86_platform.apic_post_init = vsmp_apic_post_init; + vsmp_cap_cpus(); set_vsmp_pv_ops(); -- cgit v1.2.3 From c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 21 May 2012 19:50:07 -0700 Subject: x86/debug: Add KERN_ to bare printks, convert printks to pr_ Use a more current logging style: - Bare printks should have a KERN_ for consistency's sake - Add pr_fmt where appropriate - Neaten some macro definitions - Convert some Ok output to OK - Use "%s: ", __func__ in pr_fmt for summit - Convert some printks to pr_ Message output is not identical in all cases. Signed-off-by: Joe Perches Cc: levinsasha928@gmail.com Link: http://lkml.kernel.org/r/1337655007.24226.10.camel@joe2Laptop [ merged two similar patches, tidied up the changelog ] Signed-off-by: Ingo Molnar --- arch/x86/include/asm/floppy.h | 2 +- arch/x86/include/asm/pci_x86.h | 8 ++- arch/x86/include/asm/pgtable-2level.h | 4 +- arch/x86/include/asm/pgtable-3level.h | 6 +-- arch/x86/include/asm/pgtable_64.h | 8 +-- arch/x86/kernel/alternative.c | 17 +++--- arch/x86/kernel/amd_nb.c | 10 ++-- arch/x86/kernel/apic/io_apic.c | 38 ++++++------- arch/x86/kernel/apic/summit_32.c | 22 ++++---- arch/x86/kernel/apm_32.c | 29 +++++----- arch/x86/kernel/cpu/bugs.c | 20 +++---- arch/x86/kernel/cpu/mcheck/mce.c | 22 ++++---- arch/x86/kernel/cpu/perf_event_intel.c | 14 ++--- arch/x86/kernel/dumpstack.c | 4 +- arch/x86/kernel/dumpstack_32.c | 24 ++++----- arch/x86/kernel/dumpstack_64.c | 20 +++---- arch/x86/kernel/irq.c | 4 +- arch/x86/kernel/module.c | 32 ++++++----- arch/x86/kernel/pci-calgary_64.c | 34 ++++++------ arch/x86/kernel/process.c | 34 ++++++------ arch/x86/kernel/process_64.c | 8 +-- arch/x86/kernel/reboot.c | 14 +++-- arch/x86/kernel/signal.c | 5 +- arch/x86/kernel/smpboot.c | 97 ++++++++++++++++------------------ arch/x86/kernel/traps.c | 19 +++---- arch/x86/kernel/tsc.c | 50 +++++++++--------- arch/x86/kernel/vm86_32.c | 6 ++- arch/x86/kernel/vsyscall_64.c | 17 +++--- arch/x86/kernel/xsave.c | 12 +++-- 29 files changed, 301 insertions(+), 279 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/floppy.h b/arch/x86/include/asm/floppy.h index dbe82a5c5eac..d3d74698dce9 100644 --- a/arch/x86/include/asm/floppy.h +++ b/arch/x86/include/asm/floppy.h @@ -99,7 +99,7 @@ static irqreturn_t floppy_hardint(int irq, void *dev_id) virtual_dma_residue += virtual_dma_count; virtual_dma_count = 0; #ifdef TRACE_FLPY_INT - printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n", + printk(KERN_DEBUG "count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n", virtual_dma_count, virtual_dma_residue, calls, bytes, dma_wait); calls = 0; diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index b3a531746026..5ad24a89b19b 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h @@ -7,9 +7,13 @@ #undef DEBUG #ifdef DEBUG -#define DBG(x...) printk(x) +#define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__) #else -#define DBG(x...) +#define DBG(fmt, ...) \ +do { \ + if (0) \ + printk(fmt, ##__VA_ARGS__); \ +} while (0) #endif #define PCI_PROBE_BIOS 0x0001 diff --git a/arch/x86/include/asm/pgtable-2level.h b/arch/x86/include/asm/pgtable-2level.h index 98391db840c6..f2b489cf1602 100644 --- a/arch/x86/include/asm/pgtable-2level.h +++ b/arch/x86/include/asm/pgtable-2level.h @@ -2,9 +2,9 @@ #define _ASM_X86_PGTABLE_2LEVEL_H #define pte_ERROR(e) \ - printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low) + pr_err("%s:%d: bad pte %08lx\n", __FILE__, __LINE__, (e).pte_low) #define pgd_ERROR(e) \ - printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) + pr_err("%s:%d: bad pgd %08lx\n", __FILE__, __LINE__, pgd_val(e)) /* * Certain architectures need to do special things when PTEs diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 43876f16caf1..f824cfbaa9d4 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -9,13 +9,13 @@ */ #define pte_ERROR(e) \ - printk("%s:%d: bad pte %p(%08lx%08lx).\n", \ + pr_err("%s:%d: bad pte %p(%08lx%08lx)\n", \ __FILE__, __LINE__, &(e), (e).pte_high, (e).pte_low) #define pmd_ERROR(e) \ - printk("%s:%d: bad pmd %p(%016Lx).\n", \ + pr_err("%s:%d: bad pmd %p(%016Lx)\n", \ __FILE__, __LINE__, &(e), pmd_val(e)) #define pgd_ERROR(e) \ - printk("%s:%d: bad pgd %p(%016Lx).\n", \ + pr_err("%s:%d: bad pgd %p(%016Lx)\n", \ __FILE__, __LINE__, &(e), pgd_val(e)) /* Rules for using set_pte: the pte being assigned *must* be diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 975f709e09ae..8251be02301e 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -26,16 +26,16 @@ extern pgd_t init_level4_pgt[]; extern void paging_init(void); #define pte_ERROR(e) \ - printk("%s:%d: bad pte %p(%016lx).\n", \ + pr_err("%s:%d: bad pte %p(%016lx)\n", \ __FILE__, __LINE__, &(e), pte_val(e)) #define pmd_ERROR(e) \ - printk("%s:%d: bad pmd %p(%016lx).\n", \ + pr_err("%s:%d: bad pmd %p(%016lx)\n", \ __FILE__, __LINE__, &(e), pmd_val(e)) #define pud_ERROR(e) \ - printk("%s:%d: bad pud %p(%016lx).\n", \ + pr_err("%s:%d: bad pud %p(%016lx)\n", \ __FILE__, __LINE__, &(e), pud_val(e)) #define pgd_ERROR(e) \ - printk("%s:%d: bad pgd %p(%016lx).\n", \ + pr_err("%s:%d: bad pgd %p(%016lx)\n", \ __FILE__, __LINE__, &(e), pgd_val(e)) struct mm_struct; diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 1f84794f0759..1729d720299a 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -1,3 +1,5 @@ +#define pr_fmt(fmt) "SMP alternatives: " fmt + #include #include #include @@ -63,8 +65,11 @@ static int __init setup_noreplace_paravirt(char *str) __setup("noreplace-paravirt", setup_noreplace_paravirt); #endif -#define DPRINTK(fmt, args...) if (debug_alternative) \ - printk(KERN_DEBUG fmt, args) +#define DPRINTK(fmt, ...) \ +do { \ + if (debug_alternative) \ + printk(KERN_DEBUG fmt, ##__VA_ARGS__); \ +} while (0) /* * Each GENERIC_NOPX is of X bytes, and defined as an array of bytes @@ -428,7 +433,7 @@ void alternatives_smp_switch(int smp) * If this still occurs then you should see a hang * or crash shortly after this line: */ - printk("lockdep: fixing up alternatives.\n"); + pr_info("lockdep: fixing up alternatives\n"); #endif if (noreplace_smp || smp_alt_once || skip_smp_alternatives) @@ -444,14 +449,14 @@ void alternatives_smp_switch(int smp) if (smp == smp_mode) { /* nothing */ } else if (smp) { - printk(KERN_INFO "SMP alternatives: switching to SMP code\n"); + pr_info("switching to SMP code\n"); clear_cpu_cap(&boot_cpu_data, X86_FEATURE_UP); clear_cpu_cap(&cpu_data(0), X86_FEATURE_UP); list_for_each_entry(mod, &smp_alt_modules, next) alternatives_smp_lock(mod->locks, mod->locks_end, mod->text, mod->text_end); } else { - printk(KERN_INFO "SMP alternatives: switching to UP code\n"); + pr_info("switching to UP code\n"); set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP); set_cpu_cap(&cpu_data(0), X86_FEATURE_UP); list_for_each_entry(mod, &smp_alt_modules, next) @@ -546,7 +551,7 @@ void __init alternative_instructions(void) #ifdef CONFIG_SMP if (smp_alt_once) { if (1 == num_possible_cpus()) { - printk(KERN_INFO "SMP alternatives: switching to UP code\n"); + pr_info("switching to UP code\n"); set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP); set_cpu_cap(&cpu_data(0), X86_FEATURE_UP); diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index be16854591cc..f29f6dd6bc08 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -2,6 +2,9 @@ * Shared support code for AMD K8 northbridges and derivates. * Copyright 2006 Andi Kleen, SUSE Labs. Subject to GPLv2. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -258,7 +261,7 @@ void amd_flush_garts(void) } spin_unlock_irqrestore(&gart_lock, flags); if (!flushed) - printk("nothing to flush?\n"); + pr_notice("nothing to flush?\n"); } EXPORT_SYMBOL_GPL(amd_flush_garts); @@ -269,11 +272,10 @@ static __init int init_amd_nbs(void) err = amd_cache_northbridges(); if (err < 0) - printk(KERN_NOTICE "AMD NB: Cannot enumerate AMD northbridges.\n"); + pr_notice("Cannot enumerate AMD northbridges\n"); if (amd_cache_gart() < 0) - printk(KERN_NOTICE "AMD NB: Cannot initialize GART flush words, " - "GART support disabled.\n"); + pr_notice("Cannot initialize GART flush words, GART support disabled\n"); return err; } diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index ac96561d1a99..5155d6f806f5 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -448,8 +448,8 @@ static int __add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pi entry = alloc_irq_pin_list(node); if (!entry) { - printk(KERN_ERR "can not alloc irq_pin_list (%d,%d,%d)\n", - node, apic, pin); + pr_err("can not alloc irq_pin_list (%d,%d,%d)\n", + node, apic, pin); return -ENOMEM; } entry->apic = apic; @@ -661,7 +661,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) ioapic_mask_entry(apic, pin); entry = ioapic_read_entry(apic, pin); if (entry.irr) - printk(KERN_ERR "Unable to reset IRR for apic: %d, pin :%d\n", + pr_err("Unable to reset IRR for apic: %d, pin :%d\n", mpc_ioapic_id(apic), pin); } @@ -895,7 +895,7 @@ static int irq_polarity(int idx) } case 2: /* reserved */ { - printk(KERN_WARNING "broken BIOS!!\n"); + pr_warn("broken BIOS!!\n"); polarity = 1; break; } @@ -906,7 +906,7 @@ static int irq_polarity(int idx) } default: /* invalid */ { - printk(KERN_WARNING "broken BIOS!!\n"); + pr_warn("broken BIOS!!\n"); polarity = 1; break; } @@ -948,7 +948,7 @@ static int irq_trigger(int idx) } default: { - printk(KERN_WARNING "broken BIOS!!\n"); + pr_warn("broken BIOS!!\n"); trigger = 1; break; } @@ -962,7 +962,7 @@ static int irq_trigger(int idx) } case 2: /* reserved */ { - printk(KERN_WARNING "broken BIOS!!\n"); + pr_warn("broken BIOS!!\n"); trigger = 1; break; } @@ -973,7 +973,7 @@ static int irq_trigger(int idx) } default: /* invalid */ { - printk(KERN_WARNING "broken BIOS!!\n"); + pr_warn("broken BIOS!!\n"); trigger = 0; break; } @@ -991,7 +991,7 @@ static int pin_2_irq(int idx, int apic, int pin) * Debugging check, we are in big trouble if this message pops up! */ if (mp_irqs[idx].dstirq != pin) - printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n"); + pr_err("broken BIOS or MPTABLE parser, ayiee!!\n"); if (test_bit(bus, mp_bus_not_pci)) { irq = mp_irqs[idx].srcbusirq; @@ -1521,7 +1521,6 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx) reg_03.raw = io_apic_read(ioapic_idx, 3); raw_spin_unlock_irqrestore(&ioapic_lock, flags); - printk("\n"); printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(ioapic_idx)); printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); @@ -1578,7 +1577,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx) i, ir_entry->index ); - printk("%1d %1d %1d %1d %1d " + pr_cont("%1d %1d %1d %1d %1d " "%1d %1d %X %02X\n", ir_entry->format, ir_entry->mask, @@ -1598,7 +1597,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx) i, entry.dest ); - printk("%1d %1d %1d %1d %1d " + pr_cont("%1d %1d %1d %1d %1d " "%1d %1d %02X\n", entry.mask, entry.trigger, @@ -1651,8 +1650,8 @@ __apicdebuginit(void) print_IO_APICs(void) continue; printk(KERN_DEBUG "IRQ%d ", irq); for_each_irq_pin(entry, cfg->irq_2_pin) - printk("-> %d:%d", entry->apic, entry->pin); - printk("\n"); + pr_cont("-> %d:%d", entry->apic, entry->pin); + pr_cont("\n"); } printk(KERN_INFO ".................................... done.\n"); @@ -1665,9 +1664,9 @@ __apicdebuginit(void) print_APIC_field(int base) printk(KERN_DEBUG); for (i = 0; i < 8; i++) - printk(KERN_CONT "%08x", apic_read(base + i*0x10)); + pr_cont("%08x", apic_read(base + i*0x10)); - printk(KERN_CONT "\n"); + pr_cont("\n"); } __apicdebuginit(void) print_local_APIC(void *dummy) @@ -1769,7 +1768,7 @@ __apicdebuginit(void) print_local_APIC(void *dummy) printk(KERN_DEBUG "... APIC EILVT%d: %08x\n", i, v); } } - printk("\n"); + pr_cont("\n"); } __apicdebuginit(void) print_local_APICs(int maxcpu) @@ -2065,7 +2064,7 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void) reg_00.raw = io_apic_read(ioapic_idx, 0); raw_spin_unlock_irqrestore(&ioapic_lock, flags); if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx)) - printk("could not set ID!\n"); + pr_cont("could not set ID!\n"); else apic_printk(APIC_VERBOSE, " ok.\n"); } @@ -3563,7 +3562,8 @@ static int __init io_apic_get_unique_id(int ioapic, int apic_id) /* Sanity check */ if (reg_00.bits.ID != apic_id) { - printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic); + pr_err("IOAPIC[%d]: Unable to change apic_id!\n", + ioapic); return -1; } } diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index 659897c00755..e97d542ccdd0 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c @@ -26,6 +26,8 @@ * */ +#define pr_fmt(fmt) "summit: %s: " fmt, __func__ + #include #include #include @@ -235,8 +237,8 @@ static int summit_apic_id_registered(void) static void summit_setup_apic_routing(void) { - printk("Enabling APIC mode: Summit. Using %d I/O APICs\n", - nr_ioapics); + pr_info("Enabling APIC mode: Summit. Using %d I/O APICs\n", + nr_ioapics); } static int summit_cpu_present_to_apicid(int mps_cpu) @@ -275,7 +277,7 @@ static unsigned int summit_cpu_mask_to_apicid(const struct cpumask *cpumask) int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu); if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { - printk("%s: Not a valid mask!\n", __func__); + pr_err("Not a valid mask!\n"); return BAD_APICID; } apicid |= new_apicid; @@ -355,7 +357,7 @@ static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus) } } if (i == rio_table_hdr->num_rio_dev) { - printk(KERN_ERR "%s: Couldn't find owner Cyclone for Winnipeg!\n", __func__); + pr_err("Couldn't find owner Cyclone for Winnipeg!\n"); return last_bus; } @@ -366,7 +368,7 @@ static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus) } } if (i == rio_table_hdr->num_scal_dev) { - printk(KERN_ERR "%s: Couldn't find owner Twister for Cyclone!\n", __func__); + pr_err("Couldn't find owner Twister for Cyclone!\n"); return last_bus; } @@ -396,7 +398,7 @@ static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus) num_buses = 9; break; default: - printk(KERN_INFO "%s: Unsupported Winnipeg type!\n", __func__); + pr_info("Unsupported Winnipeg type!\n"); return last_bus; } @@ -411,13 +413,15 @@ static int build_detail_arrays(void) int i, scal_detail_size, rio_detail_size; if (rio_table_hdr->num_scal_dev > MAX_NUMNODES) { - printk(KERN_WARNING "%s: MAX_NUMNODES too low! Defined as %d, but system has %d nodes.\n", __func__, MAX_NUMNODES, rio_table_hdr->num_scal_dev); + pr_warn("MAX_NUMNODES too low! Defined as %d, but system has %d nodes\n", + MAX_NUMNODES, rio_table_hdr->num_scal_dev); return 0; } switch (rio_table_hdr->version) { default: - printk(KERN_WARNING "%s: Invalid Rio Grande Table Version: %d\n", __func__, rio_table_hdr->version); + pr_warn("Invalid Rio Grande Table Version: %d\n", + rio_table_hdr->version); return 0; case 2: scal_detail_size = 11; @@ -462,7 +466,7 @@ void setup_summit(void) offset = *((unsigned short *)(ptr + offset)); } if (!rio_table_hdr) { - printk(KERN_ERR "%s: Unable to locate Rio Grande Table in EBDA - bailing!\n", __func__); + pr_err("Unable to locate Rio Grande Table in EBDA - bailing!\n"); return; } diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 07b0c0db466c..d65464e43503 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -201,6 +201,8 @@ * http://www.microsoft.com/whdc/archive/amp_12.mspx] */ +#define pr_fmt(fmt) "apm: " fmt + #include #include @@ -485,11 +487,11 @@ static void apm_error(char *str, int err) if (error_table[i].key == err) break; if (i < ERROR_COUNT) - printk(KERN_NOTICE "apm: %s: %s\n", str, error_table[i].msg); + pr_notice("%s: %s\n", str, error_table[i].msg); else if (err < 0) - printk(KERN_NOTICE "apm: %s: linux error code %i\n", str, err); + pr_notice("%s: linux error code %i\n", str, err); else - printk(KERN_NOTICE "apm: %s: unknown error code %#2.2x\n", + pr_notice("%s: unknown error code %#2.2x\n", str, err); } @@ -1184,7 +1186,7 @@ static void queue_event(apm_event_t event, struct apm_user *sender) static int notified; if (notified++ == 0) - printk(KERN_ERR "apm: an event queue overflowed\n"); + pr_err("an event queue overflowed\n"); if (++as->event_tail >= APM_MAX_EVENTS) as->event_tail = 0; } @@ -1447,7 +1449,7 @@ static void apm_mainloop(void) static int check_apm_user(struct apm_user *as, const char *func) { if (as == NULL || as->magic != APM_BIOS_MAGIC) { - printk(KERN_ERR "apm: %s passed bad filp\n", func); + pr_err("%s passed bad filp\n", func); return 1; } return 0; @@ -1586,7 +1588,7 @@ static int do_release(struct inode *inode, struct file *filp) as1 = as1->next) ; if (as1 == NULL) - printk(KERN_ERR "apm: filp not in user list\n"); + pr_err("filp not in user list\n"); else as1->next = as->next; } @@ -1600,11 +1602,9 @@ static int do_open(struct inode *inode, struct file *filp) struct apm_user *as; as = kmalloc(sizeof(*as), GFP_KERNEL); - if (as == NULL) { - printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n", - sizeof(*as)); + if (as == NULL) return -ENOMEM; - } + as->magic = APM_BIOS_MAGIC; as->event_tail = as->event_head = 0; as->suspends_pending = as->standbys_pending = 0; @@ -2313,16 +2313,16 @@ static int __init apm_init(void) } if (apm_info.disabled) { - printk(KERN_NOTICE "apm: disabled on user request.\n"); + pr_notice("disabled on user request.\n"); return -ENODEV; } if ((num_online_cpus() > 1) && !power_off && !smp) { - printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n"); + pr_notice("disabled - APM is not SMP safe.\n"); apm_info.disabled = 1; return -ENODEV; } if (!acpi_disabled) { - printk(KERN_NOTICE "apm: overridden by ACPI.\n"); + pr_notice("overridden by ACPI.\n"); apm_info.disabled = 1; return -ENODEV; } @@ -2356,8 +2356,7 @@ static int __init apm_init(void) kapmd_task = kthread_create(apm, NULL, "kapmd"); if (IS_ERR(kapmd_task)) { - printk(KERN_ERR "apm: disabled - Unable to start kernel " - "thread.\n"); + pr_err("disabled - Unable to start kernel thread\n"); err = PTR_ERR(kapmd_task); kapmd_task = NULL; remove_proc_entry("apm", NULL); diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 46674fbb62ba..c97bb7b5a9f8 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -55,8 +55,8 @@ static void __init check_fpu(void) if (!boot_cpu_data.hard_math) { #ifndef CONFIG_MATH_EMULATION - printk(KERN_EMERG "No coprocessor found and no math emulation present.\n"); - printk(KERN_EMERG "Giving up.\n"); + pr_emerg("No coprocessor found and no math emulation present\n"); + pr_emerg("Giving up\n"); for (;;) ; #endif return; @@ -86,7 +86,7 @@ static void __init check_fpu(void) boot_cpu_data.fdiv_bug = fdiv_bug; if (boot_cpu_data.fdiv_bug) - printk(KERN_WARNING "Hmm, FPU with FDIV bug.\n"); + pr_warn("Hmm, FPU with FDIV bug\n"); } static void __init check_hlt(void) @@ -94,16 +94,16 @@ static void __init check_hlt(void) if (boot_cpu_data.x86 >= 5 || paravirt_enabled()) return; - printk(KERN_INFO "Checking 'hlt' instruction... "); + pr_info("Checking 'hlt' instruction... "); if (!boot_cpu_data.hlt_works_ok) { - printk("disabled\n"); + pr_cont("disabled\n"); return; } halt(); halt(); halt(); halt(); - printk(KERN_CONT "OK.\n"); + pr_cont("OK\n"); } /* @@ -116,7 +116,7 @@ static void __init check_popad(void) #ifndef CONFIG_X86_POPAD_OK int res, inp = (int) &res; - printk(KERN_INFO "Checking for popad bug... "); + pr_info("Checking for popad bug... "); __asm__ __volatile__( "movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx " : "=&a" (res) @@ -127,9 +127,9 @@ static void __init check_popad(void) * CPU hard. Too bad. */ if (res != 12345678) - printk(KERN_CONT "Buggy.\n"); + pr_cont("Buggy\n"); else - printk(KERN_CONT "OK.\n"); + pr_cont("OK\n"); #endif } @@ -161,7 +161,7 @@ void __init check_bugs(void) { identify_boot_cpu(); #ifndef CONFIG_SMP - printk(KERN_INFO "CPU: "); + pr_info("CPU: "); print_cpu_info(&boot_cpu_data); #endif check_config(); diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 0a687fd185e6..5623b4b5d511 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -7,6 +7,9 @@ * Copyright 2008 Intel Corporation * Author: Andi Kleen */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -210,7 +213,7 @@ static void drain_mcelog_buffer(void) cpu_relax(); if (!m->finished && retries >= 4) { - pr_err("MCE: skipping error being logged currently!\n"); + pr_err("skipping error being logged currently!\n"); break; } } @@ -1167,8 +1170,9 @@ int memory_failure(unsigned long pfn, int vector, int flags) { /* mce_severity() should not hand us an ACTION_REQUIRED error */ BUG_ON(flags & MF_ACTION_REQUIRED); - printk(KERN_ERR "Uncorrected memory error in page 0x%lx ignored\n" - "Rebuild kernel with CONFIG_MEMORY_FAILURE=y for smarter handling\n", pfn); + pr_err("Uncorrected memory error in page 0x%lx ignored\n" + "Rebuild kernel with CONFIG_MEMORY_FAILURE=y for smarter handling\n", + pfn); return 0; } @@ -1358,11 +1362,10 @@ static int __cpuinit __mcheck_cpu_cap_init(void) b = cap & MCG_BANKCNT_MASK; if (!banks) - printk(KERN_INFO "mce: CPU supports %d MCE banks\n", b); + pr_info("CPU supports %d MCE banks\n", b); if (b > MAX_NR_BANKS) { - printk(KERN_WARNING - "MCE: Using only %u machine check banks out of %u\n", + pr_warn("Using only %u machine check banks out of %u\n", MAX_NR_BANKS, b); b = MAX_NR_BANKS; } @@ -1419,7 +1422,7 @@ static void __mcheck_cpu_init_generic(void) static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) { if (c->x86_vendor == X86_VENDOR_UNKNOWN) { - pr_info("MCE: unknown CPU type - not enabling MCE support.\n"); + pr_info("unknown CPU type - not enabling MCE support\n"); return -EOPNOTSUPP; } @@ -1574,7 +1577,7 @@ static void __mcheck_cpu_init_timer(void) /* Handle unconfigured int18 (should never happen) */ static void unexpected_machine_check(struct pt_regs *regs, long error_code) { - printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", + pr_err("CPU#%d: Unexpected int18 (Machine Check)\n", smp_processor_id()); } @@ -1893,8 +1896,7 @@ static int __init mcheck_enable(char *str) get_option(&str, &monarch_timeout); } } else { - printk(KERN_INFO "mce argument %s ignored. Please use /sys\n", - str); + pr_info("mce argument %s ignored. Please use /sys\n", str); return 0; } return 1; diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 166546ec6aef..9e3f5d6e3d20 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -5,6 +5,8 @@ * among events on a single PMU. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -1000,7 +1002,7 @@ static void intel_pmu_reset(void) local_irq_save(flags); - printk("clearing PMU state on CPU#%d\n", smp_processor_id()); + pr_info("clearing PMU state on CPU#%d\n", smp_processor_id()); for (idx = 0; idx < x86_pmu.num_counters; idx++) { checking_wrmsrl(x86_pmu_config_addr(idx), 0ull); @@ -1638,14 +1640,14 @@ static __init void intel_clovertown_quirk(void) * But taken together it might just make sense to not enable PEBS on * these chips. */ - printk(KERN_WARNING "PEBS disabled due to CPU errata.\n"); + pr_warn("PEBS disabled due to CPU errata\n"); x86_pmu.pebs = 0; x86_pmu.pebs_constraints = NULL; } static __init void intel_sandybridge_quirk(void) { - printk(KERN_WARNING "PEBS disabled due to CPU errata.\n"); + pr_warn("PEBS disabled due to CPU errata\n"); x86_pmu.pebs = 0; x86_pmu.pebs_constraints = NULL; } @@ -1667,8 +1669,8 @@ static __init void intel_arch_events_quirk(void) /* disable event that reported as not presend by cpuid */ for_each_set_bit(bit, x86_pmu.events_mask, ARRAY_SIZE(intel_arch_events_map)) { intel_perfmon_event_map[intel_arch_events_map[bit].id] = 0; - printk(KERN_WARNING "CPUID marked event: \'%s\' unavailable\n", - intel_arch_events_map[bit].name); + pr_warn("CPUID marked event: \'%s\' unavailable\n", + intel_arch_events_map[bit].name); } } @@ -1687,7 +1689,7 @@ static __init void intel_nehalem_quirk(void) intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89; ebx.split.no_branch_misses_retired = 0; x86_pmu.events_maskl = ebx.full; - printk(KERN_INFO "CPU erratum AAJ80 worked around\n"); + pr_info("CPU erratum AAJ80 worked around\n"); } } diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 571246d81edf..87d3b5d663cd 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -27,8 +27,8 @@ static int die_counter; void printk_address(unsigned long address, int reliable) { - printk(" [<%p>] %s%pB\n", (void *) address, - reliable ? "" : "? ", (void *) address); + pr_cont(" [<%p>] %s%pB\n", + (void *)address, reliable ? "" : "? ", (void *)address); } #ifdef CONFIG_FUNCTION_GRAPH_TRACER diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index e0b1d783daab..3a8aced11ae9 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c @@ -73,11 +73,11 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, if (kstack_end(stack)) break; if (i && ((i % STACKSLOTS_PER_LINE) == 0)) - printk(KERN_CONT "\n"); - printk(KERN_CONT " %08lx", *stack++); + pr_cont("\n"); + pr_cont(" %08lx", *stack++); touch_nmi_watchdog(); } - printk(KERN_CONT "\n"); + pr_cont("\n"); show_trace_log_lvl(task, regs, sp, bp, log_lvl); } @@ -89,9 +89,9 @@ void show_regs(struct pt_regs *regs) print_modules(); __show_regs(regs, !user_mode_vm(regs)); - printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)\n", - TASK_COMM_LEN, current->comm, task_pid_nr(current), - current_thread_info(), current, task_thread_info(current)); + pr_emerg("Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)\n", + TASK_COMM_LEN, current->comm, task_pid_nr(current), + current_thread_info(), current, task_thread_info(current)); /* * When in-kernel, we also print out the stack and code at the * time of the fault.. @@ -102,10 +102,10 @@ void show_regs(struct pt_regs *regs) unsigned char c; u8 *ip; - printk(KERN_EMERG "Stack:\n"); + pr_emerg("Stack:\n"); show_stack_log_lvl(NULL, regs, ®s->sp, 0, KERN_EMERG); - printk(KERN_EMERG "Code: "); + pr_emerg("Code:"); ip = (u8 *)regs->ip - code_prologue; if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { @@ -116,16 +116,16 @@ void show_regs(struct pt_regs *regs) for (i = 0; i < code_len; i++, ip++) { if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { - printk(KERN_CONT " Bad EIP value."); + pr_cont(" Bad EIP value."); break; } if (ip == (u8 *)regs->ip) - printk(KERN_CONT "<%02x> ", c); + pr_cont(" <%02x>", c); else - printk(KERN_CONT "%02x ", c); + pr_cont(" %02x", c); } } - printk(KERN_CONT "\n"); + pr_cont("\n"); } int is_valid_bugaddr(unsigned long ip) diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 791b76122aa8..c582e9c5bd1a 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -228,20 +228,20 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, if (stack >= irq_stack && stack <= irq_stack_end) { if (stack == irq_stack_end) { stack = (unsigned long *) (irq_stack_end[-1]); - printk(KERN_CONT " "); + pr_cont(" "); } } else { if (((long) stack & (THREAD_SIZE-1)) == 0) break; } if (i && ((i % STACKSLOTS_PER_LINE) == 0)) - printk(KERN_CONT "\n"); - printk(KERN_CONT " %016lx", *stack++); + pr_cont("\n"); + pr_cont(" %016lx", *stack++); touch_nmi_watchdog(); } preempt_enable(); - printk(KERN_CONT "\n"); + pr_cont("\n"); show_trace_log_lvl(task, regs, sp, bp, log_lvl); } @@ -256,8 +256,8 @@ void show_regs(struct pt_regs *regs) printk("CPU %d ", cpu); print_modules(); __show_regs(regs, 1); - printk("Process %s (pid: %d, threadinfo %p, task %p)\n", - cur->comm, cur->pid, task_thread_info(cur), cur); + printk(KERN_DEFAULT "Process %s (pid: %d, threadinfo %p, task %p)\n", + cur->comm, cur->pid, task_thread_info(cur), cur); /* * When in-kernel, we also print out the stack and code at the @@ -284,16 +284,16 @@ void show_regs(struct pt_regs *regs) for (i = 0; i < code_len; i++, ip++) { if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { - printk(KERN_CONT " Bad RIP value."); + pr_cont(" Bad RIP value."); break; } if (ip == (u8 *)regs->ip) - printk(KERN_CONT "<%02x> ", c); + pr_cont("<%02x> ", c); else - printk(KERN_CONT "%02x ", c); + pr_cont("%02x ", c); } } - printk(KERN_CONT "\n"); + pr_cont("\n"); } int is_valid_bugaddr(unsigned long ip) diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 3dafc6003b7c..1f5f1d5d2a02 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -294,9 +294,9 @@ void fixup_irqs(void) raw_spin_unlock(&desc->lock); if (break_affinity && set_affinity) - printk("Broke affinity for irq %i\n", irq); + pr_notice("Broke affinity for irq %i\n", irq); else if (!set_affinity) - printk("Cannot set affinity for irq %i\n", irq); + pr_notice("Cannot set affinity for irq %i\n", irq); } /* diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index f21fd94ac897..202494d2ec6e 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -15,6 +15,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -30,9 +33,14 @@ #include #if 0 -#define DEBUGP printk +#define DEBUGP(fmt, ...) \ + printk(KERN_DEBUG fmt, ##__VA_ARGS__) #else -#define DEBUGP(fmt...) +#define DEBUGP(fmt, ...) \ +do { \ + if (0) \ + printk(KERN_DEBUG fmt, ##__VA_ARGS__); \ +} while (0) #endif void *module_alloc(unsigned long size) @@ -56,8 +64,8 @@ int apply_relocate(Elf32_Shdr *sechdrs, Elf32_Sym *sym; uint32_t *location; - DEBUGP("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); + DEBUGP("Applying relocate section %u to %u\n", + relsec, sechdrs[relsec].sh_info); for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { /* This is where to make the change */ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr @@ -77,7 +85,7 @@ int apply_relocate(Elf32_Shdr *sechdrs, *location += sym->st_value - (uint32_t)location; break; default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", + pr_err("%s: Unknown relocation: %u\n", me->name, ELF32_R_TYPE(rel[i].r_info)); return -ENOEXEC; } @@ -97,8 +105,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, void *loc; u64 val; - DEBUGP("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); + DEBUGP("Applying relocate section %u to %u\n", + relsec, sechdrs[relsec].sh_info); for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { /* This is where to make the change */ loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr @@ -110,8 +118,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, + ELF64_R_SYM(rel[i].r_info); DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n", - (int)ELF64_R_TYPE(rel[i].r_info), - sym->st_value, rel[i].r_addend, (u64)loc); + (int)ELF64_R_TYPE(rel[i].r_info), + sym->st_value, rel[i].r_addend, (u64)loc); val = sym->st_value + rel[i].r_addend; @@ -140,7 +148,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, #endif break; default: - printk(KERN_ERR "module %s: Unknown rela relocation: %llu\n", + pr_err("%s: Unknown rela relocation: %llu\n", me->name, ELF64_R_TYPE(rel[i].r_info)); return -ENOEXEC; } @@ -148,9 +156,9 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, return 0; overflow: - printk(KERN_ERR "overflow in relocation type %d val %Lx\n", + pr_err("overflow in relocation type %d val %Lx\n", (int)ELF64_R_TYPE(rel[i].r_info), val); - printk(KERN_ERR "`%s' likely not compiled with -mcmodel=kernel\n", + pr_err("`%s' likely not compiled with -mcmodel=kernel\n", me->name); return -ENOEXEC; } diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index b72838bae64a..299d49302e7d 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -22,6 +22,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define pr_fmt(fmt) "Calgary: " fmt + #include #include #include @@ -245,7 +247,7 @@ static unsigned long iommu_range_alloc(struct device *dev, offset = iommu_area_alloc(tbl->it_map, tbl->it_size, 0, npages, 0, boundary_size, 0); if (offset == ~0UL) { - printk(KERN_WARNING "Calgary: IOMMU full.\n"); + pr_warn("IOMMU full\n"); spin_unlock_irqrestore(&tbl->it_lock, flags); if (panic_on_overflow) panic("Calgary: fix the allocator.\n"); @@ -271,8 +273,8 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl, entry = iommu_range_alloc(dev, tbl, npages); if (unlikely(entry == DMA_ERROR_CODE)) { - printk(KERN_WARNING "Calgary: failed to allocate %u pages in " - "iommu %p\n", npages, tbl); + pr_warn("failed to allocate %u pages in iommu %p\n", + npages, tbl); return DMA_ERROR_CODE; } @@ -561,8 +563,7 @@ static void calgary_tce_cache_blast(struct iommu_table *tbl) i++; } while ((val & 0xff) != 0xff && i < 100); if (i == 100) - printk(KERN_WARNING "Calgary: PCI bus not quiesced, " - "continuing anyway\n"); + pr_warn("PCI bus not quiesced, continuing anyway\n"); /* invalidate TCE cache */ target = calgary_reg(bbar, tar_offset(tbl->it_busno)); @@ -604,8 +605,7 @@ begin: i++; } while ((val64 & 0xff) != 0xff && i < 100); if (i == 100) - printk(KERN_WARNING "CalIOC2: PCI bus not quiesced, " - "continuing anyway\n"); + pr_warn("CalIOC2: PCI bus not quiesced, continuing anyway\n"); /* 3. poll Page Migration DEBUG for SoftStopFault */ target = calgary_reg(bbar, phb_offset(bus) | PHB_PAGE_MIG_DEBUG); @@ -617,8 +617,7 @@ begin: if (++count < 100) goto begin; else { - printk(KERN_WARNING "CalIOC2: too many SoftStopFaults, " - "aborting TCE cache flush sequence!\n"); + pr_warn("CalIOC2: too many SoftStopFaults, aborting TCE cache flush sequence!\n"); return; /* pray for the best */ } } @@ -840,8 +839,8 @@ static void calgary_dump_error_regs(struct iommu_table *tbl) plssr = be32_to_cpu(readl(target)); /* If no error, the agent ID in the CSR is not valid */ - printk(KERN_EMERG "Calgary: DMA error on Calgary PHB 0x%x, " - "0x%08x@CSR 0x%08x@PLSSR\n", tbl->it_busno, csr, plssr); + pr_emerg("DMA error on Calgary PHB 0x%x, 0x%08x@CSR 0x%08x@PLSSR\n", + tbl->it_busno, csr, plssr); } static void calioc2_dump_error_regs(struct iommu_table *tbl) @@ -867,22 +866,21 @@ static void calioc2_dump_error_regs(struct iommu_table *tbl) target = calgary_reg(bbar, phboff | 0x800); mck = be32_to_cpu(readl(target)); - printk(KERN_EMERG "Calgary: DMA error on CalIOC2 PHB 0x%x\n", - tbl->it_busno); + pr_emerg("DMA error on CalIOC2 PHB 0x%x\n", tbl->it_busno); - printk(KERN_EMERG "Calgary: 0x%08x@CSR 0x%08x@PLSSR 0x%08x@CSMR 0x%08x@MCK\n", - csr, plssr, csmr, mck); + pr_emerg("0x%08x@CSR 0x%08x@PLSSR 0x%08x@CSMR 0x%08x@MCK\n", + csr, plssr, csmr, mck); /* dump rest of error regs */ - printk(KERN_EMERG "Calgary: "); + pr_emerg(""); for (i = 0; i < ARRAY_SIZE(errregs); i++) { /* err regs are at 0x810 - 0x870 */ erroff = (0x810 + (i * 0x10)); target = calgary_reg(bbar, phboff | erroff); errregs[i] = be32_to_cpu(readl(target)); - printk("0x%08x@0x%lx ", errregs[i], erroff); + pr_cont("0x%08x@0x%lx ", errregs[i], erroff); } - printk("\n"); + pr_cont("\n"); /* root complex status */ target = calgary_reg(bbar, phboff | PHB_ROOT_COMPLEX_STATUS); diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 735279e54e59..ef6a8456f719 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -1,3 +1,5 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -145,16 +147,14 @@ void show_regs_common(void) /* Board Name is optional */ board = dmi_get_system_info(DMI_BOARD_NAME); - printk(KERN_CONT "\n"); - printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s", - current->pid, current->comm, print_tainted(), - init_utsname()->release, - (int)strcspn(init_utsname()->version, " "), - init_utsname()->version); - printk(KERN_CONT " %s %s", vendor, product); - if (board) - printk(KERN_CONT "/%s", board); - printk(KERN_CONT "\n"); + printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s %s %s%s%s\n", + current->pid, current->comm, print_tainted(), + init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), + init_utsname()->version, + vendor, product, + board ? "/" : "", + board ? board : ""); } void flush_thread(void) @@ -645,7 +645,7 @@ static void amd_e400_idle(void) amd_e400_c1e_detected = true; if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) mark_tsc_unstable("TSC halt in AMD C1E"); - printk(KERN_INFO "System has AMD C1E enabled\n"); + pr_info("System has AMD C1E enabled\n"); } } @@ -659,8 +659,7 @@ static void amd_e400_idle(void) */ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE, &cpu); - printk(KERN_INFO "Switch to broadcast mode on CPU%d\n", - cpu); + pr_info("Switch to broadcast mode on CPU%d\n", cpu); } clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); @@ -681,8 +680,7 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP if (pm_idle == poll_idle && smp_num_siblings > 1) { - printk_once(KERN_WARNING "WARNING: polling idle and HT enabled," - " performance may degrade.\n"); + pr_warn_once("WARNING: polling idle and HT enabled, performance may degrade\n"); } #endif if (pm_idle) @@ -692,11 +690,11 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) /* * One CPU supports mwait => All CPUs supports mwait */ - printk(KERN_INFO "using mwait in idle threads.\n"); + pr_info("using mwait in idle threads\n"); pm_idle = mwait_idle; } else if (cpu_has_amd_erratum(amd_erratum_400)) { /* E400: APIC timer interrupt does not wake up CPU from C1e */ - printk(KERN_INFO "using AMD E400 aware idle routine\n"); + pr_info("using AMD E400 aware idle routine\n"); pm_idle = amd_e400_idle; } else pm_idle = default_idle; @@ -715,7 +713,7 @@ static int __init idle_setup(char *str) return -EINVAL; if (!strcmp(str, "poll")) { - printk("using polling idle threads.\n"); + pr_info("using polling idle threads\n"); pm_idle = poll_idle; boot_option_idle_override = IDLE_POLL; } else if (!strcmp(str, "mwait")) { diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 61cdf7fdf099..85151f3e36e2 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -117,10 +117,10 @@ void release_thread(struct task_struct *dead_task) { if (dead_task->mm) { if (dead_task->mm->context.size) { - printk("WARNING: dead process %8s still has LDT? <%p/%d>\n", - dead_task->comm, - dead_task->mm->context.ldt, - dead_task->mm->context.size); + pr_warn("WARNING: dead process %8s still has LDT? <%p/%d>\n", + dead_task->comm, + dead_task->mm->context.ldt, + dead_task->mm->context.size); BUG(); } } diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 79c45af81604..ab3f06260712 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -1,3 +1,5 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -152,7 +154,8 @@ static int __init set_bios_reboot(const struct dmi_system_id *d) { if (reboot_type != BOOT_BIOS) { reboot_type = BOOT_BIOS; - printk(KERN_INFO "%s series board detected. Selecting BIOS-method for reboots.\n", d->ident); + pr_info("%s series board detected. Selecting %s-method for reboots.\n", + "BIOS", d->ident); } return 0; } @@ -207,8 +210,8 @@ static int __init set_pci_reboot(const struct dmi_system_id *d) { if (reboot_type != BOOT_CF9) { reboot_type = BOOT_CF9; - printk(KERN_INFO "%s series board detected. " - "Selecting PCI-method for reboots.\n", d->ident); + pr_info("%s series board detected. Selecting %s-method for reboots.\n", + "PCI", d->ident); } return 0; } @@ -217,7 +220,8 @@ static int __init set_kbd_reboot(const struct dmi_system_id *d) { if (reboot_type != BOOT_KBD) { reboot_type = BOOT_KBD; - printk(KERN_INFO "%s series board detected. Selecting KBD-method for reboot.\n", d->ident); + pr_info("%s series board detected. Selecting %s-method for reboot.\n", + "KBD", d->ident); } return 0; } @@ -668,7 +672,7 @@ static void __machine_emergency_restart(int emergency) static void native_machine_restart(char *__unused) { - printk("machine restart\n"); + pr_notice("machine restart\n"); if (!reboot_force) machine_shutdown(); diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 21af737053aa..b280908a376e 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -6,6 +6,9 @@ * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes * 2000-2002 x86-64 support by Andi Kleen */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -814,7 +817,7 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where) me->comm, me->pid, where, frame, regs->ip, regs->sp, regs->orig_ax); print_vma_addr(" in ", regs->ip); - printk(KERN_CONT "\n"); + pr_cont("\n"); } force_sig(SIGSEGV, me); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index fd019d78b1f4..456d64806c8f 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1,4 +1,4 @@ -/* + /* * x86 SMP booting functions * * (c) 1995 Alan Cox, Building #3 @@ -39,6 +39,8 @@ * Glauber Costa : i386 and x86_64 integration */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -184,7 +186,7 @@ static void __cpuinit smp_callin(void) * boards) */ - pr_debug("CALLIN, before setup_local_APIC().\n"); + pr_debug("CALLIN, before setup_local_APIC()\n"); if (apic->smp_callin_clear_local_apic) apic->smp_callin_clear_local_apic(); setup_local_APIC(); @@ -420,17 +422,16 @@ static void impress_friends(void) /* * Allow the user to impress friends. */ - pr_debug("Before bogomips.\n"); + pr_debug("Before bogomips\n"); for_each_possible_cpu(cpu) if (cpumask_test_cpu(cpu, cpu_callout_mask)) bogosum += cpu_data(cpu).loops_per_jiffy; - printk(KERN_INFO - "Total of %d processors activated (%lu.%02lu BogoMIPS).\n", + pr_info("Total of %d processors activated (%lu.%02lu BogoMIPS)\n", num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100); - pr_debug("Before bogocount - setting activated=1.\n"); + pr_debug("Before bogocount - setting activated=1\n"); } void __inquire_remote_apic(int apicid) @@ -440,18 +441,17 @@ void __inquire_remote_apic(int apicid) int timeout; u32 status; - printk(KERN_INFO "Inquiring remote APIC 0x%x...\n", apicid); + pr_info("Inquiring remote APIC 0x%x...\n", apicid); for (i = 0; i < ARRAY_SIZE(regs); i++) { - printk(KERN_INFO "... APIC 0x%x %s: ", apicid, names[i]); + pr_info("... APIC 0x%x %s: ", apicid, names[i]); /* * Wait for idle. */ status = safe_apic_wait_icr_idle(); if (status) - printk(KERN_CONT - "a previous APIC delivery may have failed\n"); + pr_cont("a previous APIC delivery may have failed\n"); apic_icr_write(APIC_DM_REMRD | regs[i], apicid); @@ -464,10 +464,10 @@ void __inquire_remote_apic(int apicid) switch (status) { case APIC_ICR_RR_VALID: status = apic_read(APIC_RRR); - printk(KERN_CONT "%08x\n", status); + pr_cont("%08x\n", status); break; default: - printk(KERN_CONT "failed\n"); + pr_cont("failed\n"); } } } @@ -501,12 +501,12 @@ wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip) apic_write(APIC_ESR, 0); accept_status = (apic_read(APIC_ESR) & 0xEF); } - pr_debug("NMI sent.\n"); + pr_debug("NMI sent\n"); if (send_status) - printk(KERN_ERR "APIC never delivered???\n"); + pr_err("APIC never delivered???\n"); if (accept_status) - printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status); + pr_err("APIC delivery error (%lx)\n", accept_status); return (send_status | accept_status); } @@ -528,7 +528,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) apic_read(APIC_ESR); } - pr_debug("Asserting INIT.\n"); + pr_debug("Asserting INIT\n"); /* * Turn INIT on target chip @@ -544,7 +544,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) mdelay(10); - pr_debug("Deasserting INIT.\n"); + pr_debug("Deasserting INIT\n"); /* Target chip */ /* Send IPI */ @@ -577,14 +577,14 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) /* * Run STARTUP IPI loop. */ - pr_debug("#startup loops: %d.\n", num_starts); + pr_debug("#startup loops: %d\n", num_starts); for (j = 1; j <= num_starts; j++) { - pr_debug("Sending STARTUP #%d.\n", j); + pr_debug("Sending STARTUP #%d\n", j); if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ apic_write(APIC_ESR, 0); apic_read(APIC_ESR); - pr_debug("After apic_write.\n"); + pr_debug("After apic_write\n"); /* * STARTUP IPI @@ -601,7 +601,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) */ udelay(300); - pr_debug("Startup point 1.\n"); + pr_debug("Startup point 1\n"); pr_debug("Waiting for send to finish...\n"); send_status = safe_apic_wait_icr_idle(); @@ -616,12 +616,12 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) if (send_status || accept_status) break; } - pr_debug("After Startup.\n"); + pr_debug("After Startup\n"); if (send_status) - printk(KERN_ERR "APIC never delivered???\n"); + pr_err("APIC never delivered???\n"); if (accept_status) - printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status); + pr_err("APIC delivery error (%lx)\n", accept_status); return (send_status | accept_status); } @@ -635,11 +635,11 @@ static void __cpuinit announce_cpu(int cpu, int apicid) if (system_state == SYSTEM_BOOTING) { if (node != current_node) { if (current_node > (-1)) - pr_cont(" Ok.\n"); + pr_cont(" OK\n"); current_node = node; pr_info("Booting Node %3d, Processors ", node); } - pr_cont(" #%d%s", cpu, cpu == (nr_cpu_ids - 1) ? " Ok.\n" : ""); + pr_cont(" #%d%s", cpu, cpu == (nr_cpu_ids - 1) ? " OK\n" : ""); return; } else pr_info("Booting Node %d Processor %d APIC 0x%x\n", @@ -719,9 +719,9 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) /* * allow APs to start initializing. */ - pr_debug("Before Callout %d.\n", cpu); + pr_debug("Before Callout %d\n", cpu); cpumask_set_cpu(cpu, cpu_callout_mask); - pr_debug("After Callout %d.\n", cpu); + pr_debug("After Callout %d\n", cpu); /* * Wait 5s total for a response @@ -749,7 +749,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) pr_err("CPU%d: Stuck ??\n", cpu); else /* trampoline code not run */ - pr_err("CPU%d: Not responding.\n", cpu); + pr_err("CPU%d: Not responding\n", cpu); if (apic->inquire_remote_apic) apic->inquire_remote_apic(apicid); } @@ -794,7 +794,7 @@ int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle) if (apicid == BAD_APICID || apicid == boot_cpu_physical_apicid || !physid_isset(apicid, phys_cpu_present_map) || !apic->apic_id_valid(apicid)) { - printk(KERN_ERR "%s: bad cpu %d\n", __func__, cpu); + pr_err("%s: bad cpu %d\n", __func__, cpu); return -EINVAL; } @@ -875,9 +875,8 @@ static int __init smp_sanity_check(unsigned max_cpus) unsigned int cpu; unsigned nr; - printk(KERN_WARNING - "More than 8 CPUs detected - skipping them.\n" - "Use CONFIG_X86_BIGSMP.\n"); + pr_warn("More than 8 CPUs detected - skipping them\n" + "Use CONFIG_X86_BIGSMP\n"); nr = 0; for_each_present_cpu(cpu) { @@ -898,8 +897,7 @@ static int __init smp_sanity_check(unsigned max_cpus) #endif if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) { - printk(KERN_WARNING - "weird, boot CPU (#%d) not listed by the BIOS.\n", + pr_warn("weird, boot CPU (#%d) not listed by the BIOS\n", hard_smp_processor_id()); physid_set(hard_smp_processor_id(), phys_cpu_present_map); @@ -911,11 +909,10 @@ static int __init smp_sanity_check(unsigned max_cpus) */ if (!smp_found_config && !acpi_lapic) { preempt_enable(); - printk(KERN_NOTICE "SMP motherboard not detected.\n"); + pr_notice("SMP motherboard not detected\n"); disable_smp(); if (APIC_init_uniprocessor()) - printk(KERN_NOTICE "Local APIC not detected." - " Using dummy APIC emulation.\n"); + pr_notice("Local APIC not detected. Using dummy APIC emulation.\n"); return -1; } @@ -924,9 +921,8 @@ static int __init smp_sanity_check(unsigned max_cpus) * CPU too, but we do it for the sake of robustness anyway. */ if (!apic->check_phys_apicid_present(boot_cpu_physical_apicid)) { - printk(KERN_NOTICE - "weird, boot CPU (#%d) not listed by the BIOS.\n", - boot_cpu_physical_apicid); + pr_notice("weird, boot CPU (#%d) not listed by the BIOS\n", + boot_cpu_physical_apicid); physid_set(hard_smp_processor_id(), phys_cpu_present_map); } preempt_enable(); @@ -939,8 +935,7 @@ static int __init smp_sanity_check(unsigned max_cpus) if (!disable_apic) { pr_err("BIOS bug, local APIC #%d not detected!...\n", boot_cpu_physical_apicid); - pr_err("... forcing use of dummy APIC emulation." - "(tell your hw vendor)\n"); + pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n"); } smpboot_clear_io_apic(); disable_ioapic_support(); @@ -953,7 +948,7 @@ static int __init smp_sanity_check(unsigned max_cpus) * If SMP should be disabled, then really disable it! */ if (!max_cpus) { - printk(KERN_INFO "SMP mode deactivated.\n"); + pr_info("SMP mode deactivated\n"); smpboot_clear_io_apic(); connect_bsp_APIC(); @@ -1005,7 +1000,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) if (smp_sanity_check(max_cpus) < 0) { - printk(KERN_INFO "SMP disabled\n"); + pr_info("SMP disabled\n"); disable_smp(); goto out; } @@ -1043,7 +1038,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) * Set up local APIC timer on boot CPU. */ - printk(KERN_INFO "CPU%d: ", 0); + pr_info("CPU%d: ", 0); print_cpu_info(&cpu_data(0)); x86_init.timers.setup_percpu_clockev(); @@ -1093,7 +1088,7 @@ void __init native_smp_prepare_boot_cpu(void) void __init native_smp_cpus_done(unsigned int max_cpus) { - pr_debug("Boot done.\n"); + pr_debug("Boot done\n"); nmi_selftest(); impress_friends(); @@ -1154,8 +1149,7 @@ __init void prefill_possible_map(void) /* nr_cpu_ids could be reduced via nr_cpus= */ if (possible > nr_cpu_ids) { - printk(KERN_WARNING - "%d Processors exceeds NR_CPUS limit of %d\n", + pr_warn("%d Processors exceeds NR_CPUS limit of %d\n", possible, nr_cpu_ids); possible = nr_cpu_ids; } @@ -1164,13 +1158,12 @@ __init void prefill_possible_map(void) if (!setup_max_cpus) #endif if (possible > i) { - printk(KERN_WARNING - "%d Processors exceeds max_cpus limit of %u\n", + pr_warn("%d Processors exceeds max_cpus limit of %u\n", possible, setup_max_cpus); possible = i; } - printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n", + pr_info("Allowing %d CPUs, %d hotplug CPUs\n", possible, max_t(int, possible - num_processors, 0)); for (i = 0; i < possible; i++) diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 05b31d92f69c..b481341c9369 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -9,6 +9,9 @@ /* * Handle hardware traps and faults. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -143,12 +146,11 @@ trap_signal: #ifdef CONFIG_X86_64 if (show_unhandled_signals && unhandled_signal(tsk, signr) && printk_ratelimit()) { - printk(KERN_INFO - "%s[%d] trap %s ip:%lx sp:%lx error:%lx", - tsk->comm, tsk->pid, str, - regs->ip, regs->sp, error_code); + pr_info("%s[%d] trap %s ip:%lx sp:%lx error:%lx", + tsk->comm, tsk->pid, str, + regs->ip, regs->sp, error_code); print_vma_addr(" in ", regs->ip); - printk("\n"); + pr_cont("\n"); } #endif @@ -269,12 +271,11 @@ do_general_protection(struct pt_regs *regs, long error_code) if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && printk_ratelimit()) { - printk(KERN_INFO - "%s[%d] general protection ip:%lx sp:%lx error:%lx", + pr_info("%s[%d] general protection ip:%lx sp:%lx error:%lx", tsk->comm, task_pid_nr(tsk), regs->ip, regs->sp, error_code); print_vma_addr(" in ", regs->ip); - printk("\n"); + pr_cont("\n"); } force_sig(SIGSEGV, tsk); @@ -570,7 +571,7 @@ do_spurious_interrupt_bug(struct pt_regs *regs, long error_code) conditional_sti(regs); #if 0 /* No need to warn about this any longer. */ - printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n"); + pr_info("Ignoring P6 Local APIC Spurious Interrupt Bug...\n"); #endif } diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index fc0a147e3727..cfa5d4f7ca56 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -1,3 +1,5 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -84,8 +86,7 @@ EXPORT_SYMBOL_GPL(check_tsc_unstable); #ifdef CONFIG_X86_TSC int __init notsc_setup(char *str) { - printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, " - "cannot disable TSC completely.\n"); + pr_warn("Kernel compiled with CONFIG_X86_TSC, cannot disable TSC completely\n"); tsc_disabled = 1; return 1; } @@ -373,7 +374,7 @@ static unsigned long quick_pit_calibrate(void) goto success; } } - printk("Fast TSC calibration failed\n"); + pr_err("Fast TSC calibration failed\n"); return 0; success: @@ -392,7 +393,7 @@ success: */ delta *= PIT_TICK_RATE; do_div(delta, i*256*1000); - printk("Fast TSC calibration using PIT\n"); + pr_info("Fast TSC calibration using PIT\n"); return delta; } @@ -487,9 +488,8 @@ unsigned long native_calibrate_tsc(void) * use the reference value, as it is more precise. */ if (delta >= 90 && delta <= 110) { - printk(KERN_INFO - "TSC: PIT calibration matches %s. %d loops\n", - hpet ? "HPET" : "PMTIMER", i + 1); + pr_info("PIT calibration matches %s. %d loops\n", + hpet ? "HPET" : "PMTIMER", i + 1); return tsc_ref_min; } @@ -511,38 +511,36 @@ unsigned long native_calibrate_tsc(void) */ if (tsc_pit_min == ULONG_MAX) { /* PIT gave no useful value */ - printk(KERN_WARNING "TSC: Unable to calibrate against PIT\n"); + pr_warn("Unable to calibrate against PIT\n"); /* We don't have an alternative source, disable TSC */ if (!hpet && !ref1 && !ref2) { - printk("TSC: No reference (HPET/PMTIMER) available\n"); + pr_notice("No reference (HPET/PMTIMER) available\n"); return 0; } /* The alternative source failed as well, disable TSC */ if (tsc_ref_min == ULONG_MAX) { - printk(KERN_WARNING "TSC: HPET/PMTIMER calibration " - "failed.\n"); + pr_warn("HPET/PMTIMER calibration failed\n"); return 0; } /* Use the alternative source */ - printk(KERN_INFO "TSC: using %s reference calibration\n", - hpet ? "HPET" : "PMTIMER"); + pr_info("using %s reference calibration\n", + hpet ? "HPET" : "PMTIMER"); return tsc_ref_min; } /* We don't have an alternative source, use the PIT calibration value */ if (!hpet && !ref1 && !ref2) { - printk(KERN_INFO "TSC: Using PIT calibration value\n"); + pr_info("Using PIT calibration value\n"); return tsc_pit_min; } /* The alternative source failed, use the PIT calibration value */ if (tsc_ref_min == ULONG_MAX) { - printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed. " - "Using PIT calibration\n"); + pr_warn("HPET/PMTIMER calibration failed. Using PIT calibration.\n"); return tsc_pit_min; } @@ -551,9 +549,9 @@ unsigned long native_calibrate_tsc(void) * the PIT value as we know that there are PMTIMERs around * running at double speed. At least we let the user know: */ - printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n", - hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min); - printk(KERN_INFO "TSC: Using PIT calibration value\n"); + pr_warn("PIT calibration deviates from %s: %lu %lu\n", + hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min); + pr_info("Using PIT calibration value\n"); return tsc_pit_min; } @@ -785,7 +783,7 @@ void mark_tsc_unstable(char *reason) tsc_unstable = 1; sched_clock_stable = 0; disable_sched_clock_irqtime(); - printk(KERN_INFO "Marking TSC unstable due to %s\n", reason); + pr_info("Marking TSC unstable due to %s\n", reason); /* Change only the rating, when not registered */ if (clocksource_tsc.mult) clocksource_mark_unstable(&clocksource_tsc); @@ -912,9 +910,9 @@ static void tsc_refine_calibration_work(struct work_struct *work) goto out; tsc_khz = freq; - printk(KERN_INFO "Refined TSC clocksource calibration: " - "%lu.%03lu MHz.\n", (unsigned long)tsc_khz / 1000, - (unsigned long)tsc_khz % 1000); + pr_info("Refined TSC clocksource calibration: %lu.%03lu MHz\n", + (unsigned long)tsc_khz / 1000, + (unsigned long)tsc_khz % 1000); out: clocksource_register_khz(&clocksource_tsc, tsc_khz); @@ -970,9 +968,9 @@ void __init tsc_init(void) return; } - printk("Detected %lu.%03lu MHz processor.\n", - (unsigned long)cpu_khz / 1000, - (unsigned long)cpu_khz % 1000); + pr_info("Detected %lu.%03lu MHz processor\n", + (unsigned long)cpu_khz / 1000, + (unsigned long)cpu_khz % 1000); /* * Secondary CPUs do not run through tsc_init(), so set up diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 255f58ae71e8..54abcc0baf23 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -28,6 +28,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -137,14 +139,14 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs) local_irq_enable(); if (!current->thread.vm86_info) { - printk("no vm86_info: BAD\n"); + pr_alert("no vm86_info: BAD\n"); do_exit(SIGSEGV); } set_flags(regs->pt.flags, VEFLAGS, X86_EFLAGS_VIF | current->thread.v86mask); tmp = copy_vm86_regs_to_user(¤t->thread.vm86_info->regs, regs); tmp += put_user(current->thread.screen_bitmap, ¤t->thread.vm86_info->screen_bitmap); if (tmp) { - printk("vm86: could not access userspace vm86_info\n"); + pr_alert("could not access userspace vm86_info\n"); do_exit(SIGSEGV); } diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index 7515cf0e1805..acdc125ad44e 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c @@ -18,6 +18,8 @@ * use the vDSO. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -111,18 +113,13 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm, static void warn_bad_vsyscall(const char *level, struct pt_regs *regs, const char *message) { - static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); - struct task_struct *tsk; - - if (!show_unhandled_signals || !__ratelimit(&rs)) + if (!show_unhandled_signals) return; - tsk = current; - - printk("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n", - level, tsk->comm, task_pid_nr(tsk), - message, regs->ip, regs->cs, - regs->sp, regs->ax, regs->si, regs->di); + pr_notice_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n", + level, current->comm, task_pid_nr(current), + message, regs->ip, regs->cs, + regs->sp, regs->ax, regs->si, regs->di); } static int addr_to_vsyscall_nr(unsigned long addr) diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index bd18149b2b0f..3d3e20709119 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -3,6 +3,9 @@ * * Author: Suresh Siddha */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -162,7 +165,7 @@ int save_i387_xstate(void __user *buf) BUG_ON(sig_xstate_size < xstate_size); if ((unsigned long)buf % 64) - printk("save_i387_xstate: bad fpstate %p\n", buf); + pr_err("%s: bad fpstate %p\n", __func__, buf); if (!used_math()) return 0; @@ -422,7 +425,7 @@ static void __init xstate_enable_boot_cpu(void) pcntxt_mask = eax + ((u64)edx << 32); if ((pcntxt_mask & XSTATE_FPSSE) != XSTATE_FPSSE) { - printk(KERN_ERR "FP/SSE not shown under xsave features 0x%llx\n", + pr_err("FP/SSE not shown under xsave features 0x%llx\n", pcntxt_mask); BUG(); } @@ -445,9 +448,8 @@ static void __init xstate_enable_boot_cpu(void) setup_xstate_init(); - printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%llx, " - "cntxt size 0x%x\n", - pcntxt_mask, xstate_size); + pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n", + pcntxt_mask, xstate_size); } /* -- cgit v1.2.3 From 332afa656e76458ee9cf0f0d123016a0658539e4 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 21 May 2012 16:58:01 -0700 Subject: x86/irq: Update irq_cfg domain unless the new affinity is a subset of the current domain Until now, irq_cfg domain is mostly static. Either all CPU's (used by flat mode) or one CPU (first CPU in the irq afffinity mask) to which irq is being migrated (this is used by the rest of apic modes). Upcoming x2apic cluster mode optimization patch allows the irq to be sent to any CPU in the x2apic cluster (if supported by the HW). So irq_cfg domain changes on the fly (depending on which CPU in the x2apic cluster is online). Instead of checking for any intersection between the new irq affinity mask and the current irq_cfg domain, check if the new irq affinity mask is a subset of the current irq_cfg domain. Otherwise proceed with updating the irq_cfg domain aswell as assigning vector's on all the CPUs specified in the new mask. This also cleans up a workaround in updating irq_cfg domain for legacy irq's that are handled by the IO-APIC. Signed-off-by: Suresh Siddha Cc: yinghai@kernel.org Cc: gorcunov@openvz.org Cc: agordeev@redhat.com Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1337644682-19854-1-git-send-email-suresh.b.siddha@intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic/io_apic.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index ac96561d1a99..910a3118438b 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1126,8 +1126,7 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask) old_vector = cfg->vector; if (old_vector) { cpumask_and(tmp_mask, mask, cpu_online_mask); - cpumask_and(tmp_mask, cfg->domain, tmp_mask); - if (!cpumask_empty(tmp_mask)) { + if (cpumask_subset(tmp_mask, cfg->domain)) { free_cpumask_var(tmp_mask); return 0; } @@ -1141,6 +1140,11 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask) apic->vector_allocation_domain(cpu, tmp_mask); + if (cpumask_subset(tmp_mask, cfg->domain)) { + free_cpumask_var(tmp_mask); + return 0; + } + vector = current_vector; offset = current_offset; next: @@ -1346,13 +1350,6 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg, if (!IO_APIC_IRQ(irq)) return; - /* - * For legacy irqs, cfg->domain starts with cpu 0 for legacy - * controllers like 8259. Now that IO-APIC can handle this irq, update - * the cfg->domain. - */ - if (irq < legacy_pic->nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain)) - apic->vector_allocation_domain(0, cfg->domain); if (assign_irq_vector(irq, cfg, apic->target_cpus())) return; -- cgit v1.2.3 From 0b8255e660a0c229ebfe8f9fde12a8d4d34c50e0 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 21 May 2012 16:58:02 -0700 Subject: x86/x2apic/cluster: Use all the members of one cluster specified in the smp_affinity mask for the interrupt destination If the HW implements round-robin interrupt delivery, this enables multiple cpu's (which are part of the user specified interrupt smp_affinity mask and belong to the same x2apic cluster) to service the interrupt. Also if the platform supports Power Aware Interrupt Routing, then this enables the interrupt to be routed to an idle cpu or a busy cpu depending on the perf/power bias tunable. We are now grouping all the cpu's in a cluster to one vector domain. So that will limit the total number of interrupt sources handled by Linux. Previously we support "cpu-count * available-vectors-per-cpu" interrupt sources but this will now reduce to "cpu-count/16 * available-vectors-per-cpu". Signed-off-by: Suresh Siddha Cc: yinghai@kernel.org Cc: gorcunov@openvz.org Cc: agordeev@redhat.com Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1337644682-19854-2-git-send-email-suresh.b.siddha@intel.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/x2apic.h | 9 ------ arch/x86/kernel/apic/x2apic_cluster.c | 56 ++++++++++++++++++++++++----------- arch/x86/kernel/apic/x2apic_phys.c | 9 ++++++ 3 files changed, 48 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/x2apic.h b/arch/x86/include/asm/x2apic.h index 92e54abf89e0..7a5a832a99b6 100644 --- a/arch/x86/include/asm/x2apic.h +++ b/arch/x86/include/asm/x2apic.h @@ -28,15 +28,6 @@ static int x2apic_apic_id_registered(void) return 1; } -/* - * For now each logical cpu is in its own vector allocation domain. - */ -static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - cpumask_clear(retmask); - cpumask_set_cpu(cpu, retmask); -} - static void __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest) { diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index ff35cff0e1a7..90d999c7f2ea 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -98,34 +98,47 @@ static void x2apic_send_IPI_all(int vector) static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask) { - /* - * We're using fixed IRQ delivery, can only return one logical APIC ID. - * May as well be the first. - */ int cpu = cpumask_first(cpumask); + u32 dest = 0; + int i; - if ((unsigned)cpu < nr_cpu_ids) - return per_cpu(x86_cpu_to_logical_apicid, cpu); - else + if (cpu > nr_cpu_ids) return BAD_APICID; + + for_each_cpu_and(i, cpumask, per_cpu(cpus_in_cluster, cpu)) + dest |= per_cpu(x86_cpu_to_logical_apicid, i); + + return dest; } static unsigned int x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, const struct cpumask *andmask) { - int cpu; + u32 dest = 0; + u16 cluster; + int i; - /* - * We're using fixed IRQ delivery, can only return one logical APIC ID. - * May as well be the first. - */ - for_each_cpu_and(cpu, cpumask, andmask) { - if (cpumask_test_cpu(cpu, cpu_online_mask)) - break; + for_each_cpu_and(i, cpumask, andmask) { + if (!cpumask_test_cpu(i, cpu_online_mask)) + continue; + dest = per_cpu(x86_cpu_to_logical_apicid, i); + cluster = x2apic_cluster(i); + break; } - return per_cpu(x86_cpu_to_logical_apicid, cpu); + if (!dest) + return BAD_APICID; + + for_each_cpu_and(i, cpumask, andmask) { + if (!cpumask_test_cpu(i, cpu_online_mask)) + continue; + if (cluster != x2apic_cluster(i)) + continue; + dest |= per_cpu(x86_cpu_to_logical_apicid, i); + } + + return dest; } static void init_x2apic_ldr(void) @@ -208,6 +221,15 @@ static int x2apic_cluster_probe(void) return 0; } +/* + * Each x2apic cluster is an allocation domain. + */ +static void cluster_vector_allocation_domain(int cpu, struct cpumask *retmask) +{ + cpumask_clear(retmask); + cpumask_copy(retmask, per_cpu(cpus_in_cluster, cpu)); +} + static struct apic apic_x2apic_cluster = { .name = "cluster x2apic", @@ -225,7 +247,7 @@ static struct apic apic_x2apic_cluster = { .check_apicid_used = NULL, .check_apicid_present = NULL, - .vector_allocation_domain = x2apic_vector_allocation_domain, + .vector_allocation_domain = cluster_vector_allocation_domain, .init_apic_ldr = init_x2apic_ldr, .ioapic_phys_id_map = NULL, diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index c17e982db275..93b25706f177 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -120,6 +120,15 @@ static int x2apic_phys_probe(void) return apic == &apic_x2apic_phys; } +/* + * Each logical cpu is in its own vector allocation domain. + */ +static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask) +{ + cpumask_clear(retmask); + cpumask_set_cpu(cpu, retmask); +} + static struct apic apic_x2apic_phys = { .name = "physical x2apic", -- cgit v1.2.3 From 49d0c7a0a425a89190b7c3b1445faba9eb227bec Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Tue, 5 Jun 2012 13:23:15 +0200 Subject: x86/apic: Trivial whitespace fixes Signed-off-by: Alexander Gordeev Cc: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120605112310.GA11443@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic/apic_flat_64.c | 2 +- arch/x86/kernel/apic/io_apic.c | 4 ++-- arch/x86/kernel/apic/x2apic_cluster.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index 0e881c46e8c8..de279b32ceb1 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -92,7 +92,7 @@ static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector) } static void - flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) +flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) { unsigned long mask = cpumask_bits(cpumask)[0]; int cpu = smp_processor_id(); diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 910a3118438b..74c569791e75 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1363,7 +1363,7 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg, cfg->vector, irq, attr->trigger, attr->polarity, dest); if (setup_ioapic_entry(irq, &entry, dest, cfg->vector, attr)) { - pr_warn("Failed to setup ioapic entry for ioapic %d, pin %d\n", + pr_warn("Failed to setup ioapic entry for ioapic %d, pin %d\n", mpc_ioapic_id(attr->ioapic), attr->ioapic_pin); __clear_irq_vector(irq, cfg); @@ -1466,7 +1466,7 @@ void setup_IO_APIC_irq_extra(u32 gsi) * Set up the timer pin, possibly with the 8259A-master behind. */ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx, - unsigned int pin, int vector) + unsigned int pin, int vector) { struct IO_APIC_route_entry entry; diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 90d999c7f2ea..2919e45d30c3 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -81,7 +81,7 @@ static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector) } static void - x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) +x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) { __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLBUT); } -- cgit v1.2.3 From bf721d3a3bc7a731add45c8078b142b494ab413e Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Tue, 5 Jun 2012 13:23:29 +0200 Subject: x86/apic: Factor out default target_cpus() operation Signed-off-by: Alexander Gordeev Cc: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120605112324.GA11449@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apic.h | 5 +++++ arch/x86/include/asm/x2apic.h | 9 --------- arch/x86/kernel/apic/apic_flat_64.c | 14 ++------------ arch/x86/kernel/apic/apic_numachip.c | 7 +------ arch/x86/kernel/apic/bigsmp_32.c | 11 +---------- arch/x86/kernel/apic/x2apic_cluster.c | 2 +- arch/x86/kernel/apic/x2apic_phys.c | 2 +- arch/x86/kernel/apic/x2apic_uv_x.c | 7 +------ 8 files changed, 12 insertions(+), 45 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index eaff4790ed96..fc38195d6405 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -537,6 +537,11 @@ static inline const struct cpumask *default_target_cpus(void) #endif } +static inline const struct cpumask *online_target_cpus(void) +{ + return cpu_online_mask; +} + DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid); diff --git a/arch/x86/include/asm/x2apic.h b/arch/x86/include/asm/x2apic.h index 7a5a832a99b6..f90f0a587c66 100644 --- a/arch/x86/include/asm/x2apic.h +++ b/arch/x86/include/asm/x2apic.h @@ -9,15 +9,6 @@ #include #include -/* - * Need to use more than cpu 0, because we need more vectors - * when MSI-X are used. - */ -static const struct cpumask *x2apic_target_cpus(void) -{ - return cpu_online_mask; -} - static int x2apic_apic_id_valid(int apicid) { return 1; diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index de279b32ceb1..61ac1afeff07 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -36,11 +36,6 @@ static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) return 1; } -static const struct cpumask *flat_target_cpus(void) -{ - return cpu_online_mask; -} - static void flat_vector_allocation_domain(int cpu, struct cpumask *retmask) { /* Careful. Some cpus do not strictly honor the set of cpus @@ -186,7 +181,7 @@ static struct apic apic_flat = { .irq_delivery_mode = dest_LowestPrio, .irq_dest_mode = 1, /* logical */ - .target_cpus = flat_target_cpus, + .target_cpus = online_target_cpus, .disable_esr = 0, .dest_logical = APIC_DEST_LOGICAL, .check_apicid_used = NULL, @@ -262,11 +257,6 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) return 0; } -static const struct cpumask *physflat_target_cpus(void) -{ - return cpu_online_mask; -} - static void physflat_vector_allocation_domain(int cpu, struct cpumask *retmask) { cpumask_clear(retmask); @@ -345,7 +335,7 @@ static struct apic apic_physflat = { .irq_delivery_mode = dest_Fixed, .irq_dest_mode = 0, /* physical */ - .target_cpus = physflat_target_cpus, + .target_cpus = online_target_cpus, .disable_esr = 0, .dest_logical = 0, .check_apicid_used = NULL, diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index 6ec6d5d297c3..3255a60fcc95 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -72,11 +72,6 @@ static int numachip_phys_pkg_id(int initial_apic_id, int index_msb) return initial_apic_id >> index_msb; } -static const struct cpumask *numachip_target_cpus(void) -{ - return cpu_online_mask; -} - static void numachip_vector_allocation_domain(int cpu, struct cpumask *retmask) { cpumask_clear(retmask); @@ -253,7 +248,7 @@ static struct apic apic_numachip __refconst = { .irq_delivery_mode = dest_Fixed, .irq_dest_mode = 0, /* physical */ - .target_cpus = numachip_target_cpus, + .target_cpus = online_target_cpus, .disable_esr = 0, .dest_logical = 0, .check_apicid_used = NULL, diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index 31fbdbfbf960..c288e81e00ff 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c @@ -26,15 +26,6 @@ static int bigsmp_apic_id_registered(void) return 1; } -static const struct cpumask *bigsmp_target_cpus(void) -{ -#ifdef CONFIG_SMP - return cpu_online_mask; -#else - return cpumask_of(0); -#endif -} - static unsigned long bigsmp_check_apicid_used(physid_mask_t *map, int apicid) { return 0; @@ -205,7 +196,7 @@ static struct apic apic_bigsmp = { /* phys delivery to target CPU: */ .irq_dest_mode = 0, - .target_cpus = bigsmp_target_cpus, + .target_cpus = default_target_cpus, .disable_esr = 1, .dest_logical = 0, .check_apicid_used = bigsmp_check_apicid_used, diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 2919e45d30c3..612622c47dfb 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -241,7 +241,7 @@ static struct apic apic_x2apic_cluster = { .irq_delivery_mode = dest_LowestPrio, .irq_dest_mode = 1, /* logical */ - .target_cpus = x2apic_target_cpus, + .target_cpus = online_target_cpus, .disable_esr = 0, .dest_logical = APIC_DEST_LOGICAL, .check_apicid_used = NULL, diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index 93b25706f177..b1a8b39e3c3f 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -140,7 +140,7 @@ static struct apic apic_x2apic_phys = { .irq_delivery_mode = dest_Fixed, .irq_dest_mode = 0, /* physical */ - .target_cpus = x2apic_target_cpus, + .target_cpus = online_target_cpus, .disable_esr = 0, .dest_logical = 0, .check_apicid_used = NULL, diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index c6d03f7a4401..16efb92bfea5 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -185,11 +185,6 @@ EXPORT_SYMBOL_GPL(uv_possible_blades); unsigned long sn_rtc_cycles_per_second; EXPORT_SYMBOL(sn_rtc_cycles_per_second); -static const struct cpumask *uv_target_cpus(void) -{ - return cpu_online_mask; -} - static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask) { cpumask_clear(retmask); @@ -362,7 +357,7 @@ static struct apic __refdata apic_x2apic_uv_x = { .irq_delivery_mode = dest_Fixed, .irq_dest_mode = 0, /* physical */ - .target_cpus = uv_target_cpus, + .target_cpus = online_target_cpus, .disable_esr = 0, .dest_logical = APIC_DEST_LOGICAL, .check_apicid_used = NULL, -- cgit v1.2.3 From 6398268d2bc454735f11e08705e858f9fdf5c750 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Tue, 5 Jun 2012 13:23:44 +0200 Subject: x86/apic: Factor out default cpu_mask_to_apicid() operations Signed-off-by: Alexander Gordeev Cc: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120605112340.GA11454@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apic.h | 13 +++++++++--- arch/x86/kernel/apic/apic.c | 28 +++++++++++++++++++++++++ arch/x86/kernel/apic/apic_flat_64.c | 40 ++++-------------------------------- arch/x86/kernel/apic/apic_noop.c | 4 ++-- arch/x86/kernel/apic/apic_numachip.c | 36 ++------------------------------ arch/x86/kernel/apic/bigsmp_32.c | 30 ++------------------------- arch/x86/kernel/apic/probe_32.c | 4 ++-- arch/x86/kernel/apic/x2apic_phys.c | 36 ++------------------------------ 8 files changed, 52 insertions(+), 139 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index fc38195d6405..bef571769e68 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -592,14 +592,14 @@ static inline int default_phys_pkg_id(int cpuid_apic, int index_msb) #endif static inline unsigned int -default_cpu_mask_to_apicid(const struct cpumask *cpumask) +flat_cpu_mask_to_apicid(const struct cpumask *cpumask) { return cpumask_bits(cpumask)[0] & APIC_ALL_CPUS; } static inline unsigned int -default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) +flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask) { unsigned long mask1 = cpumask_bits(cpumask)[0]; unsigned long mask2 = cpumask_bits(andmask)[0]; @@ -608,6 +608,13 @@ default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, return (unsigned int)(mask1 & mask2 & mask3); } +extern unsigned int +default_cpu_mask_to_apicid(const struct cpumask *cpumask); + +extern unsigned int +default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask); + static inline unsigned long default_check_apicid_used(physid_mask_t *map, int apicid) { return physid_isset(apicid, *map); diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 39a222e094af..96a2608252f1 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -2123,6 +2123,34 @@ void default_init_apic_ldr(void) apic_write(APIC_LDR, val); } +unsigned int default_cpu_mask_to_apicid(const struct cpumask *cpumask) +{ + int cpu; + + /* + * We're using fixed IRQ delivery, can only return one phys APIC ID. + * May as well be the first. + */ + cpu = cpumask_first(cpumask); + if (likely((unsigned)cpu < nr_cpu_ids)) + return per_cpu(x86_cpu_to_apicid, cpu); + + return BAD_APICID; +} + +unsigned int +default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask) +{ + int cpu; + + for_each_cpu_and(cpu, cpumask, andmask) { + if (cpumask_test_cpu(cpu, cpu_online_mask)) + break; + } + return per_cpu(x86_cpu_to_apicid, cpu); +} + /* * Power management */ diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index 61ac1afeff07..55b97ce4fa19 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -205,8 +205,8 @@ static struct apic apic_flat = { .set_apic_id = set_apic_id, .apic_id_mask = 0xFFu << 24, - .cpu_mask_to_apicid = default_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, + .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, .send_IPI_mask = flat_send_IPI_mask, .send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself, @@ -284,38 +284,6 @@ static void physflat_send_IPI_all(int vector) physflat_send_IPI_mask(cpu_online_mask, vector); } -static unsigned int physflat_cpu_mask_to_apicid(const struct cpumask *cpumask) -{ - int cpu; - - /* - * We're using fixed IRQ delivery, can only return one phys APIC ID. - * May as well be the first. - */ - cpu = cpumask_first(cpumask); - if ((unsigned)cpu < nr_cpu_ids) - return per_cpu(x86_cpu_to_apicid, cpu); - else - return BAD_APICID; -} - -static unsigned int -physflat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) -{ - int cpu; - - /* - * We're using fixed IRQ delivery, can only return one phys APIC ID. - * May as well be the first. - */ - for_each_cpu_and(cpu, cpumask, andmask) { - if (cpumask_test_cpu(cpu, cpu_online_mask)) - break; - } - return per_cpu(x86_cpu_to_apicid, cpu); -} - static int physflat_probe(void) { if (apic == &apic_physflat || num_possible_cpus() > 8) @@ -360,8 +328,8 @@ static struct apic apic_physflat = { .set_apic_id = set_apic_id, .apic_id_mask = 0xFFu << 24, - .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = physflat_cpu_mask_to_apicid_and, + .cpu_mask_to_apicid = default_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, .send_IPI_mask = physflat_send_IPI_mask, .send_IPI_mask_allbutself = physflat_send_IPI_mask_allbutself, diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index a6e4c6e06c08..7c3dd4fe0686 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c @@ -159,8 +159,8 @@ struct apic apic_noop = { .set_apic_id = NULL, .apic_id_mask = 0x0F << 24, - .cpu_mask_to_apicid = default_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, + .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, .send_IPI_mask = noop_send_IPI_mask, .send_IPI_mask_allbutself = noop_send_IPI_mask_allbutself, diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index 3255a60fcc95..dba4bf2ed566 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -152,38 +152,6 @@ static void numachip_send_IPI_self(int vector) __default_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL); } -static unsigned int numachip_cpu_mask_to_apicid(const struct cpumask *cpumask) -{ - int cpu; - - /* - * We're using fixed IRQ delivery, can only return one phys APIC ID. - * May as well be the first. - */ - cpu = cpumask_first(cpumask); - if (likely((unsigned)cpu < nr_cpu_ids)) - return per_cpu(x86_cpu_to_apicid, cpu); - - return BAD_APICID; -} - -static unsigned int -numachip_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) -{ - int cpu; - - /* - * We're using fixed IRQ delivery, can only return one phys APIC ID. - * May as well be the first. - */ - for_each_cpu_and(cpu, cpumask, andmask) { - if (cpumask_test_cpu(cpu, cpu_online_mask)) - break; - } - return per_cpu(x86_cpu_to_apicid, cpu); -} - static int __init numachip_probe(void) { return apic == &apic_numachip; @@ -272,8 +240,8 @@ static struct apic apic_numachip __refconst = { .set_apic_id = set_apic_id, .apic_id_mask = 0xffU << 24, - .cpu_mask_to_apicid = numachip_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = numachip_cpu_mask_to_apicid_and, + .cpu_mask_to_apicid = default_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, .send_IPI_mask = numachip_send_IPI_mask, .send_IPI_mask_allbutself = numachip_send_IPI_mask_allbutself, diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index c288e81e00ff..907aa3d112a6 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c @@ -96,32 +96,6 @@ static int bigsmp_check_phys_apicid_present(int phys_apicid) return 1; } -/* As we are using single CPU as destination, pick only one CPU here */ -static unsigned int bigsmp_cpu_mask_to_apicid(const struct cpumask *cpumask) -{ - int cpu = cpumask_first(cpumask); - - if (cpu < nr_cpu_ids) - return cpu_physical_id(cpu); - return BAD_APICID; -} - -static unsigned int bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) -{ - int cpu; - - /* - * We're using fixed IRQ delivery, can only return one phys APIC ID. - * May as well be the first. - */ - for_each_cpu_and(cpu, cpumask, andmask) { - if (cpumask_test_cpu(cpu, cpu_online_mask)) - return cpu_physical_id(cpu); - } - return BAD_APICID; -} - static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) { return cpuid_apic >> index_msb; @@ -220,8 +194,8 @@ static struct apic apic_bigsmp = { .set_apic_id = NULL, .apic_id_mask = 0xFF << 24, - .cpu_mask_to_apicid = bigsmp_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = bigsmp_cpu_mask_to_apicid_and, + .cpu_mask_to_apicid = default_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, .send_IPI_mask = bigsmp_send_IPI_mask, .send_IPI_mask_allbutself = NULL, diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 1b291da09e60..71b6ac48ab26 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -123,8 +123,8 @@ static struct apic apic_default = { .set_apic_id = NULL, .apic_id_mask = 0x0F << 24, - .cpu_mask_to_apicid = default_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, + .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, .send_IPI_mask = default_send_IPI_mask_logical, .send_IPI_mask_allbutself = default_send_IPI_mask_allbutself_logical, diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index b1a8b39e3c3f..f730269edef2 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -76,38 +76,6 @@ static void x2apic_send_IPI_all(int vector) __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC); } -static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask) -{ - /* - * We're using fixed IRQ delivery, can only return one phys APIC ID. - * May as well be the first. - */ - int cpu = cpumask_first(cpumask); - - if ((unsigned)cpu < nr_cpu_ids) - return per_cpu(x86_cpu_to_apicid, cpu); - else - return BAD_APICID; -} - -static unsigned int -x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) -{ - int cpu; - - /* - * We're using fixed IRQ delivery, can only return one phys APIC ID. - * May as well be the first. - */ - for_each_cpu_and(cpu, cpumask, andmask) { - if (cpumask_test_cpu(cpu, cpu_online_mask)) - break; - } - - return per_cpu(x86_cpu_to_apicid, cpu); -} - static void init_x2apic_ldr(void) { } @@ -164,8 +132,8 @@ static struct apic apic_x2apic_phys = { .set_apic_id = x2apic_set_apic_id, .apic_id_mask = 0xFFFFFFFFu, - .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = x2apic_cpu_mask_to_apicid_and, + .cpu_mask_to_apicid = default_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, .send_IPI_mask = x2apic_send_IPI_mask, .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself, -- cgit v1.2.3 From f968cabcb1cd0c253fa25850970e5376f9eef065 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 6 Jun 2012 01:42:20 -0700 Subject: ARM: OMAP: Fix MMC_OMAP build when only MMC_OMAP_HS is selected If CONFIG_MMC_OMAP is not set and CONFIG_MMC_OMAP_HS is set, we can get error: redefinition of `omap242x_init_mmc' error. Fix it by removing MMC_OMAP_HS from MMC_OMAP ifdefs as they do not depend on each other. While at it, also prettify the formatting a bit. Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/mmc.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h index a7754a886d42..5493bd95da5e 100644 --- a/arch/arm/plat-omap/include/plat/mmc.h +++ b/arch/arm/plat-omap/include/plat/mmc.h @@ -172,8 +172,7 @@ struct omap_mmc_platform_data { extern void omap_mmc_notify_cover_event(struct device *dev, int slot, int is_closed); -#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ - defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers); void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data); @@ -185,7 +184,6 @@ static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, static inline void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data) { } - #endif extern int omap_msdi_reset(struct omap_hwmod *oh); -- cgit v1.2.3 From 00d6bfaf20e723e3f4c9aa6bc0fb6636785a0701 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 6 Jun 2012 01:42:20 -0700 Subject: ARM: OMAP3: Fix omap3_l3_block_irq warning when CONFIG_BUG is not set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we will get: arch/arm/mach-omap2/omap_l3_smx.c: In function ‘omap3_l3_block_irq’: arch/arm/mach-omap2/omap_l3_smx.c:156: warning: unused variable ‘address’ arch/arm/mach-omap2/omap_l3_smx.c:155: warning: unused variable ‘multi’ arch/arm/mach-omap2/omap_l3_smx.c:154: warning: unused variable ‘initid’ arch/arm/mach-omap2/omap_l3_smx.c:153: warning: unused variable ‘code’ arch/arm/mach-omap2/omap_l3_smx.c: At top level: arch/arm/mach-omap2/omap_l3_smx.c:68: warning: ‘omap3_l3_code_string’ defined but not used arch/arm/mach-omap2/omap_l3_smx.c:90: warning: ‘omap3_l3_initiator_string’ defined but not used Fix it by always showing the L3 error. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_l3_smx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_l3_smx.c b/arch/arm/mach-omap2/omap_l3_smx.c index a05a62f9ee5b..acc216491b8a 100644 --- a/arch/arm/mach-omap2/omap_l3_smx.c +++ b/arch/arm/mach-omap2/omap_l3_smx.c @@ -155,10 +155,11 @@ static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3, u8 multi = error & L3_ERROR_LOG_MULTI; u32 address = omap3_l3_decode_addr(error_addr); - WARN(true, "%s seen by %s %s at address %x\n", + pr_err("%s seen by %s %s at address %x\n", omap3_l3_code_string(code), omap3_l3_initiator_string(initid), multi ? "Multiple Errors" : "", address); + WARN_ON(1); return IRQ_HANDLED; } -- cgit v1.2.3 From febe9e02d63ed8a42e7e9c75ea16117821f90f07 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 6 Jun 2012 01:42:20 -0700 Subject: ARM: OMAP2+: Fix compile for CONFIG_TIDSPBRIDGE platform init code Commit 7f28427b (ARM: OMAP2+: Move omap_dsp_reserve_sdram_memblock() to mach-omap2) moved DSP platform init code, but failed to include memblock.h causing: arch/arm/mach-omap2/dsp.c: In function 'omap_dsp_reserve_sdram_memblock': arch/arm/mach-omap2/dsp.c:58: error: implicit declaration of function 'arm_memblock_steal' Reported-by: Russell King Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/dsp.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/dsp.c b/arch/arm/mach-omap2/dsp.c index 845309f146fe..88ffa1e645cd 100644 --- a/arch/arm/mach-omap2/dsp.c +++ b/arch/arm/mach-omap2/dsp.c @@ -20,6 +20,9 @@ #include #include + +#include + #include "cm2xxx_3xxx.h" #include "prm2xxx_3xxx.h" #ifdef CONFIG_BRIDGE_DVFS -- cgit v1.2.3 From fbd24153c48b8425b09c161a020483cd77da870e Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 30 May 2012 18:40:03 -0600 Subject: x86/early_printk: Replace obsolete simple_strtoul() usage with kstrtoint() Change early_serial_init() to call kstrtoul() instead of calling obsoleted simple_strtoul(). Signed-off-by: Shuah Khan Cc: Joe Perches Link: http://lkml.kernel.org/r/1338424803.3569.5.camel@lorien2 Signed-off-by: Ingo Molnar --- arch/x86/kernel/early_printk.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 9b9f18b49918..5e4771266f1a 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -119,7 +119,7 @@ static __init void early_serial_init(char *s) unsigned char c; unsigned divisor; unsigned baud = DEFAULT_BAUD; - char *e; + ssize_t ret; if (*s == ',') ++s; @@ -127,14 +127,14 @@ static __init void early_serial_init(char *s) if (*s) { unsigned port; if (!strncmp(s, "0x", 2)) { - early_serial_base = simple_strtoul(s, &e, 16); + ret = kstrtoint(s, 16, &early_serial_base); } else { static const int __initconst bases[] = { 0x3f8, 0x2f8 }; if (!strncmp(s, "ttyS", 4)) s += 4; - port = simple_strtoul(s, &e, 10); - if (port > 1 || s == e) + ret = kstrtouint(s, 10, &port); + if (ret || port > 1) port = 0; early_serial_base = bases[port]; } @@ -149,8 +149,8 @@ static __init void early_serial_init(char *s) outb(0x3, early_serial_base + MCR); /* DTR + RTS */ if (*s) { - baud = simple_strtoul(s, &e, 0); - if (baud == 0 || s == e) + ret = kstrtouint(s, 0, &baud); + if (ret || baud == 0) baud = DEFAULT_BAUD; } -- cgit v1.2.3 From bacef661acdb634170a8faddbc1cf28e8f8b9eee Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 25 May 2012 16:20:31 +0100 Subject: x86-64/efi: Use EFI to deal with platform wall clock Other than ix86, x86-64 on EFI so far didn't set the {g,s}et_wallclock accessors to the EFI routines, thus incorrectly using raw RTC accesses instead. Simply removing the #ifdef around the respective code isn't enough, however: While so far early get-time calls were done in physical mode, this doesn't work properly for x86-64, as virtual addresses would still need to be set up for all runtime regions (which wasn't the case on the system I have access to), so instead the patch moves the call to efi_enter_virtual_mode() ahead (which in turn allows to drop all code related to calling efi-get-time in physical mode). Additionally the earlier calling of efi_set_executable() requires the CPA code to cope, i.e. during early boot it must be avoided to call cpa_flush_array(), as the first thing this function does is a BUG_ON(irqs_disabled()). Also make the two EFI functions in question here static - they're not being referenced elsewhere. Signed-off-by: Jan Beulich Tested-by: Matt Fleming Acked-by: Matthew Garrett Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/4FBFBF5F020000780008637F@nat28.tlf.novell.com Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 10 ++++++---- arch/x86/platform/efi/efi.c | 30 ++++-------------------------- include/linux/efi.h | 2 -- init/main.c | 8 ++++---- 4 files changed, 14 insertions(+), 36 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index e1ebde315210..ee09aca63998 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -919,11 +919,13 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, /* * On success we use clflush, when the CPU supports it to - * avoid the wbindv. If the CPU does not support it and in the - * error case we fall back to cpa_flush_all (which uses - * wbindv): + * avoid the wbindv. If the CPU does not support it, in the + * error case, and during early boot (for EFI) we fall back + * to cpa_flush_all (which uses wbinvd): */ - if (!ret && cpu_has_clflush) { + if (early_boot_irqs_disabled) + __cpa_flush_all((void *)(long)cache); + else if (!ret && cpu_has_clflush) { if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) { cpa_flush_array(addr, numpages, cache, cpa.flags, pages); diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 92660edaa1e7..2dc29f51e75a 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -234,22 +234,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map( return status; } -static efi_status_t __init phys_efi_get_time(efi_time_t *tm, - efi_time_cap_t *tc) -{ - unsigned long flags; - efi_status_t status; - - spin_lock_irqsave(&rtc_lock, flags); - efi_call_phys_prelog(); - status = efi_call_phys2(efi_phys.get_time, virt_to_phys(tm), - virt_to_phys(tc)); - efi_call_phys_epilog(); - spin_unlock_irqrestore(&rtc_lock, flags); - return status; -} - -int efi_set_rtc_mmss(unsigned long nowtime) +static int efi_set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes; efi_status_t status; @@ -278,7 +263,7 @@ int efi_set_rtc_mmss(unsigned long nowtime) return 0; } -unsigned long efi_get_time(void) +static unsigned long efi_get_time(void) { efi_status_t status; efi_time_t eft; @@ -621,18 +606,13 @@ static int __init efi_runtime_init(void) } /* * We will only need *early* access to the following - * two EFI runtime services before set_virtual_address_map + * EFI runtime service before set_virtual_address_map * is invoked. */ - efi_phys.get_time = (efi_get_time_t *)runtime->get_time; efi_phys.set_virtual_address_map = (efi_set_virtual_address_map_t *) runtime->set_virtual_address_map; - /* - * Make efi_get_time can be called before entering - * virtual mode. - */ - efi.get_time = phys_efi_get_time; + early_iounmap(runtime, sizeof(efi_runtime_services_t)); return 0; @@ -720,12 +700,10 @@ void __init efi_init(void) efi_enabled = 0; return; } -#ifdef CONFIG_X86_32 if (efi_native) { x86_platform.get_wallclock = efi_get_time; x86_platform.set_wallclock = efi_set_rtc_mmss; } -#endif #if EFI_DEBUG print_efi_memmap(); diff --git a/include/linux/efi.h b/include/linux/efi.h index ec45ccd8708a..103adc6d7e3a 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -503,8 +503,6 @@ extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); extern int __init efi_uart_console_only (void); extern void efi_initialize_iomem_resources(struct resource *code_resource, struct resource *data_resource, struct resource *bss_resource); -extern unsigned long efi_get_time(void); -extern int efi_set_rtc_mmss(unsigned long nowtime); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; diff --git a/init/main.c b/init/main.c index 1ca6b32c4828..eef30128321a 100644 --- a/init/main.c +++ b/init/main.c @@ -460,6 +460,10 @@ static void __init mm_init(void) percpu_init_late(); pgtable_cache_init(); vmalloc_init(); +#ifdef CONFIG_X86 + if (efi_enabled) + efi_enter_virtual_mode(); +#endif } asmlinkage void __init start_kernel(void) @@ -601,10 +605,6 @@ asmlinkage void __init start_kernel(void) calibrate_delay(); pidmap_init(); anon_vma_init(); -#ifdef CONFIG_X86 - if (efi_enabled) - efi_enter_virtual_mode(); -#endif thread_info_cache_init(); cred_init(); fork_init(totalram_pages); -- cgit v1.2.3 From a737f256bf14adf94920aa70d150ab4dcd145109 Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Sun, 3 Jun 2012 21:17:48 +0300 Subject: KVM: Cleanup the kvm_print functions and introduce pr_XX wrappers Introduces a couple of print functions, which are essentially wrappers around standard printk functions, with a KVM: prefix. Functions introduced or modified are: - kvm_err(fmt, ...) - kvm_info(fmt, ...) - kvm_debug(fmt, ...) - kvm_pr_unimpl(fmt, ...) - pr_unimpl(vcpu, fmt, ...) -> vcpu_unimpl(vcpu, fmt, ...) Signed-off-by: Christoffer Dall Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 6 +++--- arch/x86/kvm/vmx.c | 2 +- arch/x86/kvm/x86.c | 54 ++++++++++++++++++++++++------------------------ include/linux/kvm_host.h | 18 ++++++++++------ 4 files changed, 43 insertions(+), 37 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index f75af406b268..7a418783259d 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3185,8 +3185,8 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) break; case MSR_IA32_DEBUGCTLMSR: if (!boot_cpu_has(X86_FEATURE_LBRV)) { - pr_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTL 0x%llx, nop\n", - __func__, data); + vcpu_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTL 0x%llx, nop\n", + __func__, data); break; } if (data & DEBUGCTL_RESERVED_BITS) @@ -3205,7 +3205,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) case MSR_VM_CR: return svm_set_vm_cr(vcpu, data); case MSR_VM_IGNNE: - pr_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data); + vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data); break; default: return kvm_set_msr_common(vcpu, ecx, data); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index f78662ec8677..eeeb4a25aed6 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4549,7 +4549,7 @@ static int handle_cr(struct kvm_vcpu *vcpu) break; } vcpu->run->exit_reason = 0; - pr_unimpl(vcpu, "unhandled control register: op %d cr %d\n", + vcpu_unimpl(vcpu, "unhandled control register: op %d cr %d\n", (int)(exit_qualification >> 4) & 3, cr); return 0; } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f12a52408cda..a01a4241bc6b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1437,8 +1437,8 @@ static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data) break; } default: - pr_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x " - "data 0x%llx\n", msr, data); + vcpu_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x " + "data 0x%llx\n", msr, data); return 1; } return 0; @@ -1470,8 +1470,8 @@ static int set_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 data) case HV_X64_MSR_TPR: return kvm_hv_vapic_msr_write(vcpu, APIC_TASKPRI, data); default: - pr_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x " - "data 0x%llx\n", msr, data); + vcpu_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x " + "data 0x%llx\n", msr, data); return 1; } @@ -1551,15 +1551,15 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) data &= ~(u64)0x100; /* ignore ignne emulation enable */ data &= ~(u64)0x8; /* ignore TLB cache disable */ if (data != 0) { - pr_unimpl(vcpu, "unimplemented HWCR wrmsr: 0x%llx\n", - data); + vcpu_unimpl(vcpu, "unimplemented HWCR wrmsr: 0x%llx\n", + data); return 1; } break; case MSR_FAM10H_MMIO_CONF_BASE: if (data != 0) { - pr_unimpl(vcpu, "unimplemented MMIO_CONF_BASE wrmsr: " - "0x%llx\n", data); + vcpu_unimpl(vcpu, "unimplemented MMIO_CONF_BASE wrmsr: " + "0x%llx\n", data); return 1; } break; @@ -1574,8 +1574,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) thus reserved and should throw a #GP */ return 1; } - pr_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTLMSR 0x%llx, nop\n", - __func__, data); + vcpu_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTLMSR 0x%llx, nop\n", + __func__, data); break; case MSR_IA32_UCODE_REV: case MSR_IA32_UCODE_WRITE: @@ -1671,8 +1671,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) case MSR_K7_EVNTSEL2: case MSR_K7_EVNTSEL3: if (data != 0) - pr_unimpl(vcpu, "unimplemented perfctr wrmsr: " - "0x%x data 0x%llx\n", msr, data); + vcpu_unimpl(vcpu, "unimplemented perfctr wrmsr: " + "0x%x data 0x%llx\n", msr, data); break; /* at least RHEL 4 unconditionally writes to the perfctr registers, * so we ignore writes to make it happy. @@ -1681,8 +1681,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) case MSR_K7_PERFCTR1: case MSR_K7_PERFCTR2: case MSR_K7_PERFCTR3: - pr_unimpl(vcpu, "unimplemented perfctr wrmsr: " - "0x%x data 0x%llx\n", msr, data); + vcpu_unimpl(vcpu, "unimplemented perfctr wrmsr: " + "0x%x data 0x%llx\n", msr, data); break; case MSR_P6_PERFCTR0: case MSR_P6_PERFCTR1: @@ -1693,8 +1693,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) return kvm_pmu_set_msr(vcpu, msr, data); if (pr || data != 0) - pr_unimpl(vcpu, "disabled perfctr wrmsr: " - "0x%x data 0x%llx\n", msr, data); + vcpu_unimpl(vcpu, "disabled perfctr wrmsr: " + "0x%x data 0x%llx\n", msr, data); break; case MSR_K7_CLK_CTL: /* @@ -1720,7 +1720,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) /* Drop writes to this legacy MSR -- see rdmsr * counterpart for further detail. */ - pr_unimpl(vcpu, "ignored wrmsr: 0x%x data %llx\n", msr, data); + vcpu_unimpl(vcpu, "ignored wrmsr: 0x%x data %llx\n", msr, data); break; case MSR_AMD64_OSVW_ID_LENGTH: if (!guest_cpuid_has_osvw(vcpu)) @@ -1738,12 +1738,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) if (kvm_pmu_msr(vcpu, msr)) return kvm_pmu_set_msr(vcpu, msr, data); if (!ignore_msrs) { - pr_unimpl(vcpu, "unhandled wrmsr: 0x%x data %llx\n", - msr, data); + vcpu_unimpl(vcpu, "unhandled wrmsr: 0x%x data %llx\n", + msr, data); return 1; } else { - pr_unimpl(vcpu, "ignored wrmsr: 0x%x data %llx\n", - msr, data); + vcpu_unimpl(vcpu, "ignored wrmsr: 0x%x data %llx\n", + msr, data); break; } } @@ -1846,7 +1846,7 @@ static int get_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) data = kvm->arch.hv_hypercall; break; default: - pr_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr); + vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr); return 1; } @@ -1877,7 +1877,7 @@ static int get_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) data = vcpu->arch.hv_vapic; break; default: - pr_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr); + vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr); return 1; } *pdata = data; @@ -2030,10 +2030,10 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) if (kvm_pmu_msr(vcpu, msr)) return kvm_pmu_get_msr(vcpu, msr, pdata); if (!ignore_msrs) { - pr_unimpl(vcpu, "unhandled rdmsr: 0x%x\n", msr); + vcpu_unimpl(vcpu, "unhandled rdmsr: 0x%x\n", msr); return 1; } else { - pr_unimpl(vcpu, "ignored rdmsr: 0x%x\n", msr); + vcpu_unimpl(vcpu, "ignored rdmsr: 0x%x\n", msr); data = 0; } break; @@ -4116,7 +4116,7 @@ static unsigned long emulator_get_cr(struct x86_emulate_ctxt *ctxt, int cr) value = kvm_get_cr8(vcpu); break; default: - vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr); + kvm_err("%s: unexpected cr %u\n", __func__, cr); return 0; } @@ -4145,7 +4145,7 @@ static int emulator_set_cr(struct x86_emulate_ctxt *ctxt, int cr, ulong val) res = kvm_set_cr8(vcpu, val); break; default: - vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr); + kvm_err("%s: unexpected cr %u\n", __func__, cr); res = -1; } diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 19b83f6efa49..27ac8a4767fa 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -314,13 +314,19 @@ struct kvm { long tlbs_dirty; }; -/* The guest did something we don't support. */ -#define pr_unimpl(vcpu, fmt, ...) \ - pr_err_ratelimited("kvm: %i: cpu%i " fmt, \ - current->tgid, (vcpu)->vcpu_id , ## __VA_ARGS__) +#define kvm_err(fmt, ...) \ + pr_err("kvm [%i]: " fmt, task_pid_nr(current), ## __VA_ARGS__) +#define kvm_info(fmt, ...) \ + pr_info("kvm [%i]: " fmt, task_pid_nr(current), ## __VA_ARGS__) +#define kvm_debug(fmt, ...) \ + pr_debug("kvm [%i]: " fmt, task_pid_nr(current), ## __VA_ARGS__) +#define kvm_pr_unimpl(fmt, ...) \ + pr_err_ratelimited("kvm [%i]: " fmt, \ + task_tgid_nr(current), ## __VA_ARGS__) -#define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt) -#define vcpu_printf(vcpu, fmt...) kvm_printf(vcpu->kvm, fmt) +/* The guest did something we don't support. */ +#define vcpu_unimpl(vcpu, fmt, ...) \ + kvm_pr_unimpl("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__) static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i) { -- cgit v1.2.3 From 79f702a6d18c75760c68202007265b2310d6f44e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 3 Jun 2012 11:34:08 +0300 Subject: KVM: disable uninitialized var warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I see this in 3.5-rc1: arch/x86/kvm/mmu.c: In function ‘kvm_test_age_rmapp’: arch/x86/kvm/mmu.c:1271: warning: ‘iter.desc’ may be used uninitialized in this function The line in question was introduced by commit 1e3f42f03c38c29c1814199a6f0a2f01b919ea3f static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp, unsigned long data) { - u64 *spte; + u64 *sptep; + struct rmap_iterator iter; <- line 1271 int young = 0; /* The reason I think is that the compiler assumes that the rmap value could be 0, so static u64 *rmap_get_first(unsigned long rmap, struct rmap_iterator *iter) { if (!rmap) return NULL; if (!(rmap & 1)) { iter->desc = NULL; return (u64 *)rmap; } iter->desc = (struct pte_list_desc *)(rmap & ~1ul); iter->pos = 0; return iter->desc->sptes[iter->pos]; } will not initialize iter.desc, but the compiler isn't smart enough to see that for (sptep = rmap_get_first(*rmapp, &iter); sptep; sptep = rmap_get_next(&iter)) { will immediately exit in this case. I checked by adding if (!*rmapp) goto out; on top which is clearly equivalent but disables the warning. This patch uses uninitialized_var to disable the warning without increasing code size. Signed-off-by: Michael S. Tsirkin Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 1ca7164a74f1..24dd43d45ae4 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1238,7 +1238,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp, unsigned long data) { u64 *sptep; - struct rmap_iterator iter; + struct rmap_iterator uninitialized_var(iter); int young = 0; /* -- cgit v1.2.3 From 5a425294ee7d4ab5a374248e85838dfd450caf75 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 5 Jun 2012 15:30:31 +0200 Subject: perf/x86: Fix Intel shared extra MSR allocation Zheng Yan reported that event group validation can wreck event state when Intel extra_reg allocation changes event state. Validation shouldn't change any persistent state. Cloning events in validate_{event,group}() isn't really pretty either, so add a few special cases to avoid modifying the event state. The code is restructured to minimize the special case impact. Reported-by: Zheng Yan Acked-by: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1338903031.28282.175.camel@twins Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 1 + arch/x86/kernel/cpu/perf_event.h | 1 + arch/x86/kernel/cpu/perf_event_intel.c | 92 +++++++++++++++++++++++----------- 3 files changed, 66 insertions(+), 28 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index e049d6da0183..cb608383e4f6 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1496,6 +1496,7 @@ static struct cpu_hw_events *allocate_fake_cpuc(void) if (!cpuc->shared_regs) goto error; } + cpuc->is_fake = 1; return cpuc; error: free_fake_cpuc(cpuc); diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 6638aaf54493..83794d8e6af0 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -117,6 +117,7 @@ struct cpu_hw_events { struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ unsigned int group_flag; + int is_fake; /* * Intel DebugStore bits diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 166546ec6aef..965baa2fa790 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1119,27 +1119,33 @@ intel_bts_constraints(struct perf_event *event) return NULL; } -static bool intel_try_alt_er(struct perf_event *event, int orig_idx) +static int intel_alt_er(int idx) { if (!(x86_pmu.er_flags & ERF_HAS_RSP_1)) - return false; + return idx; - if (event->hw.extra_reg.idx == EXTRA_REG_RSP_0) { - event->hw.config &= ~INTEL_ARCH_EVENT_MASK; - event->hw.config |= 0x01bb; - event->hw.extra_reg.idx = EXTRA_REG_RSP_1; - event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1; - } else if (event->hw.extra_reg.idx == EXTRA_REG_RSP_1) { + if (idx == EXTRA_REG_RSP_0) + return EXTRA_REG_RSP_1; + + if (idx == EXTRA_REG_RSP_1) + return EXTRA_REG_RSP_0; + + return idx; +} + +static void intel_fixup_er(struct perf_event *event, int idx) +{ + event->hw.extra_reg.idx = idx; + + if (idx == EXTRA_REG_RSP_0) { event->hw.config &= ~INTEL_ARCH_EVENT_MASK; event->hw.config |= 0x01b7; - event->hw.extra_reg.idx = EXTRA_REG_RSP_0; event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0; + } else if (idx == EXTRA_REG_RSP_1) { + event->hw.config &= ~INTEL_ARCH_EVENT_MASK; + event->hw.config |= 0x01bb; + event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1; } - - if (event->hw.extra_reg.idx == orig_idx) - return false; - - return true; } /* @@ -1157,14 +1163,18 @@ __intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc, struct event_constraint *c = &emptyconstraint; struct er_account *era; unsigned long flags; - int orig_idx = reg->idx; + int idx = reg->idx; - /* already allocated shared msr */ - if (reg->alloc) + /* + * reg->alloc can be set due to existing state, so for fake cpuc we + * need to ignore this, otherwise we might fail to allocate proper fake + * state for this extra reg constraint. Also see the comment below. + */ + if (reg->alloc && !cpuc->is_fake) return NULL; /* call x86_get_event_constraint() */ again: - era = &cpuc->shared_regs->regs[reg->idx]; + era = &cpuc->shared_regs->regs[idx]; /* * we use spin_lock_irqsave() to avoid lockdep issues when * passing a fake cpuc @@ -1173,6 +1183,29 @@ again: if (!atomic_read(&era->ref) || era->config == reg->config) { + /* + * If its a fake cpuc -- as per validate_{group,event}() we + * shouldn't touch event state and we can avoid doing so + * since both will only call get_event_constraints() once + * on each event, this avoids the need for reg->alloc. + * + * Not doing the ER fixup will only result in era->reg being + * wrong, but since we won't actually try and program hardware + * this isn't a problem either. + */ + if (!cpuc->is_fake) { + if (idx != reg->idx) + intel_fixup_er(event, idx); + + /* + * x86_schedule_events() can call get_event_constraints() + * multiple times on events in the case of incremental + * scheduling(). reg->alloc ensures we only do the ER + * allocation once. + */ + reg->alloc = 1; + } + /* lock in msr value */ era->config = reg->config; era->reg = reg->reg; @@ -1180,17 +1213,17 @@ again: /* one more user */ atomic_inc(&era->ref); - /* no need to reallocate during incremental event scheduling */ - reg->alloc = 1; - /* * need to call x86_get_event_constraint() * to check if associated event has constraints */ c = NULL; - } else if (intel_try_alt_er(event, orig_idx)) { - raw_spin_unlock_irqrestore(&era->lock, flags); - goto again; + } else { + idx = intel_alt_er(idx); + if (idx != reg->idx) { + raw_spin_unlock_irqrestore(&era->lock, flags); + goto again; + } } raw_spin_unlock_irqrestore(&era->lock, flags); @@ -1204,11 +1237,14 @@ __intel_shared_reg_put_constraints(struct cpu_hw_events *cpuc, struct er_account *era; /* - * only put constraint if extra reg was actually - * allocated. Also takes care of event which do - * not use an extra shared reg + * Only put constraint if extra reg was actually allocated. Also takes + * care of event which do not use an extra shared reg. + * + * Also, if this is a fake cpuc we shouldn't touch any event state + * (reg->alloc) and we don't care about leaving inconsistent cpuc state + * either since it'll be thrown out. */ - if (!reg->alloc) + if (!reg->alloc || cpuc->is_fake) return; era = &cpuc->shared_regs->regs[reg->idx]; -- cgit v1.2.3 From 0780c927a02492f917a74f51f3c801c76a637c57 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 5 Jun 2012 10:26:43 +0200 Subject: perf/x86: Implement cycles:p for SNB/IVB Now that there's finally a chip with working PEBS (IvyBridge), we can enable the hardware and implement cycles:p for SNB/IVB. Cc: Stephane Eranian Requested-and-tested-by: Linus Torvalds Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1338884803.28282.153.camel@twins Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.h | 1 + arch/x86/kernel/cpu/perf_event_intel.c | 50 ++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 83794d8e6af0..7241e2fc3c17 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -365,6 +365,7 @@ struct x86_pmu { int pebs_record_size; void (*drain_pebs)(struct pt_regs *regs); struct event_constraint *pebs_constraints; + void (*pebs_aliases)(struct perf_event *event); /* * Intel LBR diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 965baa2fa790..2312c1ff1b19 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1336,15 +1336,9 @@ static void intel_put_event_constraints(struct cpu_hw_events *cpuc, intel_put_shared_regs_event_constraints(cpuc, event); } -static int intel_pmu_hw_config(struct perf_event *event) +static void intel_pebs_aliases_core2(struct perf_event *event) { - int ret = x86_pmu_hw_config(event); - - if (ret) - return ret; - - if (event->attr.precise_ip && - (event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { + if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { /* * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P * (0x003c) so that we can use it with PEBS. @@ -1365,10 +1359,48 @@ static int intel_pmu_hw_config(struct perf_event *event) */ u64 alt_config = X86_CONFIG(.event=0xc0, .inv=1, .cmask=16); + alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK); + event->hw.config = alt_config; + } +} + +static void intel_pebs_aliases_snb(struct perf_event *event) +{ + if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { + /* + * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P + * (0x003c) so that we can use it with PEBS. + * + * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't + * PEBS capable. However we can use UOPS_RETIRED.ALL + * (0x01c2), which is a PEBS capable event, to get the same + * count. + * + * UOPS_RETIRED.ALL counts the number of cycles that retires + * CNTMASK micro-ops. By setting CNTMASK to a value (16) + * larger than the maximum number of micro-ops that can be + * retired per cycle (4) and then inverting the condition, we + * count all cycles that retire 16 or less micro-ops, which + * is every cycle. + * + * Thereby we gain a PEBS capable cycle counter. + */ + u64 alt_config = X86_CONFIG(.event=0xc2, .umask=0x01, .inv=1, .cmask=16); alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK); event->hw.config = alt_config; } +} + +static int intel_pmu_hw_config(struct perf_event *event) +{ + int ret = x86_pmu_hw_config(event); + + if (ret) + return ret; + + if (event->attr.precise_ip && x86_pmu.pebs_aliases) + x86_pmu.pebs_aliases(event); if (intel_pmu_needs_lbr_smpl(event)) { ret = intel_pmu_setup_lbr_filter(event); @@ -1643,6 +1675,7 @@ static __initconst const struct x86_pmu intel_pmu = { .max_period = (1ULL << 31) - 1, .get_event_constraints = intel_get_event_constraints, .put_event_constraints = intel_put_event_constraints, + .pebs_aliases = intel_pebs_aliases_core2, .format_attrs = intel_arch3_formats_attr, @@ -1885,6 +1918,7 @@ __init int intel_pmu_init(void) x86_pmu.event_constraints = intel_snb_event_constraints; x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints; + x86_pmu.pebs_aliases = intel_pebs_aliases_snb; x86_pmu.extra_regs = intel_snb_extra_regs; /* all extra regs are per-cpu when HT is on */ x86_pmu.er_flags |= ERF_HAS_RSP_1; -- cgit v1.2.3 From 47a8863dbb11745446314ca126593789ab74d93a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 5 Jun 2012 10:26:43 +0200 Subject: perf/x86: Enable/Add IvyBridge hardware support Implement rudimentary IVB perf support. The SDM states its identical to SNB with exception of the exact event tables, but a quick look suggests they're similar enough. Also mark SNB-EP as broken for now. Requested-and-tested-by: Linus Torvalds Cc: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1338884803.28282.153.camel@twins Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 2312c1ff1b19..187c294bc658 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1909,8 +1909,9 @@ __init int intel_pmu_init(void) break; case 42: /* SandyBridge */ - x86_add_quirk(intel_sandybridge_quirk); case 45: /* SandyBridge, "Romely-EP" */ + x86_add_quirk(intel_sandybridge_quirk); + case 58: /* IvyBridge */ memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids)); -- cgit v1.2.3 From 212d95dfdb66e5c81879b08e4f7fbfc8498b1ab5 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 5 Jun 2012 10:26:43 +0200 Subject: perf/x86: Update SNB PEBS constraints Afaict there's no need to (incompletely) iterate the MEM_UOPS_RETIRED.* umask state. Signed-off-by: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1338884803.28282.153.camel@twins Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel_ds.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 5a3edc27f6e5..35e2192df9f4 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -400,14 +400,7 @@ struct event_constraint intel_snb_pebs_event_constraints[] = { INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.* */ - INTEL_UEVENT_CONSTRAINT(0x11d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_LOADS */ - INTEL_UEVENT_CONSTRAINT(0x12d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_STORES */ - INTEL_UEVENT_CONSTRAINT(0x21d0, 0xf), /* MEM_UOP_RETIRED.LOCK_LOADS */ - INTEL_UEVENT_CONSTRAINT(0x22d0, 0xf), /* MEM_UOP_RETIRED.LOCK_STORES */ - INTEL_UEVENT_CONSTRAINT(0x41d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_LOADS */ - INTEL_UEVENT_CONSTRAINT(0x42d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_STORES */ - INTEL_UEVENT_CONSTRAINT(0x81d0, 0xf), /* MEM_UOP_RETIRED.ANY_LOADS */ - INTEL_UEVENT_CONSTRAINT(0x82d0, 0xf), /* MEM_UOP_RETIRED.ANY_STORES */ + INTEL_EVENT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ INTEL_UEVENT_CONSTRAINT(0x02d4, 0xf), /* MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS */ -- cgit v1.2.3 From 1c2ac3fde3e35279958e7b0408e2dcf866465301 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 14 May 2012 15:25:34 +0200 Subject: perf/x86: Fix wrmsrl() debug wrapper Move the wrmslr() debug wrapper to the common header now that all the include games are gone. Also clean it up a bit to avoid multiple evaluation of the argument. Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-l4gkfnivwv4yi5mqxjlovymx@git.kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 11 ----------- arch/x86/kernel/cpu/perf_event.h | 12 ++++++++++++ 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index c4706cf9c011..43c2017347e7 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -35,17 +35,6 @@ #include "perf_event.h" -#if 0 -#undef wrmsrl -#define wrmsrl(msr, val) \ -do { \ - trace_printk("wrmsrl(%lx, %lx)\n", (unsigned long)(msr),\ - (unsigned long)(val)); \ - native_write_msr((msr), (u32)((u64)(val)), \ - (u32)((u64)(val) >> 32)); \ -} while (0) -#endif - struct x86_pmu x86_pmu __read_mostly; DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 7241e2fc3c17..23b5710b1747 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -14,6 +14,18 @@ #include +#if 0 +#undef wrmsrl +#define wrmsrl(msr, val) \ +do { \ + unsigned int _msr = (msr); \ + u64 _val = (val); \ + trace_printk("wrmsrl(%x, %Lx)\n", (unsigned int)(_msr), \ + (unsigned long long)(_val)); \ + native_write_msr((_msr), (u32)(_val), (u32)(_val >> 32)); \ +} while (0) +#endif + /* * | NHM/WSM | SNB | * register ------------------------------- -- cgit v1.2.3 From 1ff4d58a192aea7f245981e2579765f961f6eb9c Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jun 2012 17:56:50 -0700 Subject: x86: Add rdpmcl() Add a version of rdpmc() that directly reads into a u64 Signed-off-by: Andi Kleen Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1338944211-28275-4-git-send-email-andi@firstfloor.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/msr.h | 2 ++ arch/x86/include/asm/paravirt.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 084ef95274cd..e489c1475be9 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -237,6 +237,8 @@ do { \ (high) = (u32)(_l >> 32); \ } while (0) +#define rdpmcl(counter, val) ((val) = native_read_pmc(counter)) + #define rdtscp(low, high, aux) \ do { \ unsigned long long _val = native_read_tscp(&(aux)); \ diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 6cbbabf52707..14ce05dfe04e 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -252,6 +252,8 @@ do { \ high = _l >> 32; \ } while (0) +#define rdpmcl(counter, val) ((val) = paravirt_read_pmc(counter)) + static inline unsigned long long paravirt_rdtscp(unsigned int *aux) { return PVOP_CALL1(u64, pv_cpu_ops.read_tscp, aux); -- cgit v1.2.3 From c48b60538c3ba05a7a2713c4791b25405525431b Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Thu, 1 Mar 2012 17:28:14 -0500 Subject: perf/x86: Use rdpmc() rather than rdmsr() when possible in the kernel The rdpmc instruction is faster than the equivelant rdmsr call, so use it when possible in the kernel. The perfctr kernel patches did this, after extensive testing showed rdpmc to always be faster (One can look in etc/costs in the perfctr-2.6 package to see a historical list of the overhead). I have done some tests on a 3.2 kernel, the kernel module I used was included in the first posting of this patch: rdmsr rdpmc Core2 T9900: 203.9 cycles 30.9 cycles AMD fam0fh: 56.2 cycles 9.8 cycles Atom 6/28/2: 129.7 cycles 50.6 cycles The speedup of using rdpmc is large. [ It's probably possible (and desirable) to do this without requiring a new field in the hw_perf_event structure, but the fixed events make this tricky. ] Signed-off-by: Vince Weaver Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/alpine.DEB.2.00.1203011724030.26934@cl320.eecs.utk.edu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 4 +++- include/linux/perf_event.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 43c2017347e7..000a4746c7ce 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -75,7 +75,7 @@ u64 x86_perf_event_update(struct perf_event *event) */ again: prev_raw_count = local64_read(&hwc->prev_count); - rdmsrl(hwc->event_base, new_raw_count); + rdpmcl(hwc->event_base_rdpmc, new_raw_count); if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, new_raw_count) != prev_raw_count) @@ -819,9 +819,11 @@ static inline void x86_assign_hw_event(struct perf_event *event, } else if (hwc->idx >= X86_PMC_IDX_FIXED) { hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL; hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0 + (hwc->idx - X86_PMC_IDX_FIXED); + hwc->event_base_rdpmc = (hwc->idx - X86_PMC_IDX_FIXED) | 1<<30; } else { hwc->config_base = x86_pmu_config_addr(hwc->idx); hwc->event_base = x86_pmu_event_addr(hwc->idx); + hwc->event_base_rdpmc = x86_pmu_addr_offset(hwc->idx); } } diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 45db49f64bb4..1ce887abcc5c 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -677,6 +677,7 @@ struct hw_perf_event { u64 last_tag; unsigned long config_base; unsigned long event_base; + int event_base_rdpmc; int idx; int last_cpu; -- cgit v1.2.3 From 70ab7003dec58afeae7f5d681dfa309b3a259f03 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jun 2012 17:56:48 -0700 Subject: perf/x86: Don't assume there can be only 4 PEBS events On Sandy Bridge in non HT mode there are 8 counters available. Since every counter can write a PEBS record assuming there are 4 max is incorrect. Use the reported counter number -- with an upper limit for a static array -- instead. Also I made the warning messages a bit more informational. Signed-off-by: Andi Kleen Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1338944211-28275-2-git-send-email-andi@firstfloor.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.h | 3 ++- arch/x86/kernel/cpu/perf_event_intel.c | 2 ++ arch/x86/kernel/cpu/perf_event_intel_ds.c | 8 ++++---- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 23b5710b1747..3df3de9452a9 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -69,7 +69,7 @@ struct amd_nb { }; /* The maximal number of PEBS events: */ -#define MAX_PEBS_EVENTS 4 +#define MAX_PEBS_EVENTS 8 /* * A debug store configuration. @@ -378,6 +378,7 @@ struct x86_pmu { void (*drain_pebs)(struct pt_regs *regs); struct event_constraint *pebs_constraints; void (*pebs_aliases)(struct perf_event *event); + int max_pebs_events; /* * Intel LBR diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 187c294bc658..e23e71f25264 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1800,6 +1800,8 @@ __init int intel_pmu_init(void) x86_pmu.events_maskl = ebx.full; x86_pmu.events_mask_len = eax.split.mask_length; + x86_pmu.max_pebs_events = min_t(unsigned, MAX_PEBS_EVENTS, x86_pmu.num_counters); + /* * Quirk: v2 perfmon does not report fixed-purpose events, so * assume at least 3 events: diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 35e2192df9f4..026373edef7f 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -620,7 +620,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) * Should not happen, we program the threshold at 1 and do not * set a reset value. */ - WARN_ON_ONCE(n > 1); + WARN_ONCE(n > 1, "bad leftover pebs %d\n", n); at += n - 1; __intel_pmu_pebs_event(event, iregs, at); @@ -651,10 +651,10 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) * Should not happen, we program the threshold at 1 and do not * set a reset value. */ - WARN_ON_ONCE(n > MAX_PEBS_EVENTS); + WARN_ONCE(n > x86_pmu.max_pebs_events, "Unexpected number of pebs records %d\n", n); for ( ; at < top; at++) { - for_each_set_bit(bit, (unsigned long *)&at->status, MAX_PEBS_EVENTS) { + for_each_set_bit(bit, (unsigned long *)&at->status, x86_pmu.max_pebs_events) { event = cpuc->events[bit]; if (!test_bit(bit, cpuc->active_mask)) continue; @@ -670,7 +670,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) break; } - if (!event || bit >= MAX_PEBS_EVENTS) + if (!event || bit >= x86_pmu.max_pebs_events) continue; __intel_pmu_pebs_event(event, iregs, at); -- cgit v1.2.3 From 4bfaddf15bac7afa7048d105864dab65c5d1f9e7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 4 Jun 2012 21:26:30 +0000 Subject: x86 bpf_jit: support BPF_S_ANC_ALU_XOR_X instruction commit ffe06c17afbb (filter: add XOR operation) added generic support for XOR operation. This patch implements the XOR instruction in x86 jit. Signed-off-by: Eric Dumazet Cc: Jiri Pirko Signed-off-by: David S. Miller --- arch/x86/net/bpf_jit_comp.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 0597f95b6da6..33643a8bcbbb 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -309,6 +309,10 @@ void bpf_jit_compile(struct sk_filter *fp) else EMIT1_off32(0x0d, K); /* or imm32,%eax */ break; + case BPF_S_ANC_ALU_XOR_X: /* A ^= X; */ + seen |= SEEN_XREG; + EMIT2(0x31, 0xd8); /* xor %ebx,%eax */ + break; case BPF_S_ALU_LSH_X: /* A <<= X; */ seen |= SEEN_XREG; EMIT4(0x89, 0xd9, 0xd3, 0xe0); /* mov %ebx,%ecx; shl %cl,%eax */ -- cgit v1.2.3 From d7ce8a5f63838d99726ec81f666075d65361325b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 6 Jun 2012 10:20:21 -0700 Subject: sparc bpf_jit: support BPF_S_ANC_ALU_XOR_X instruction Signed-off-by: David S. Miller --- arch/sparc/net/bpf_jit_comp.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c index 1a69244e785b..e9073e9501b3 100644 --- a/arch/sparc/net/bpf_jit_comp.c +++ b/arch/sparc/net/bpf_jit_comp.c @@ -96,6 +96,7 @@ static void bpf_flush_icache(void *start_, void *end_) #define AND F3(2, 0x01) #define ANDCC F3(2, 0x11) #define OR F3(2, 0x02) +#define XOR F3(2, 0x03) #define SUB F3(2, 0x04) #define SUBCC F3(2, 0x14) #define MUL F3(2, 0x0a) /* umul */ @@ -462,6 +463,9 @@ void bpf_jit_compile(struct sk_filter *fp) case BPF_S_ALU_OR_K: /* A |= K */ emit_alu_K(OR, K); break; + case BPF_S_ANC_ALU_XOR_X: /* A ^= X; */ + emit_alu_X(XOR); + break; case BPF_S_ALU_LSH_X: /* A <<= X */ emit_alu_X(SLL); break; -- cgit v1.2.3 From 24214449b00b94328e239d3c35cda3e6fe0f931b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 4 May 2012 18:28:21 +0200 Subject: x86, amd_nb: Export model 0x10 and later PCI id Add the F3 PCI id of F15h, model 0x10 to pci_ids.h and to the amd_nb code which generates the list of northbridges on an AMD box. Shorten define name while at it so that it fits into pci_ids.h. Acked-by: Clemens Ladisch Cc: Bjorn Helgaas Acked-by: Andreas Herrmann Signed-off-by: Borislav Petkov --- arch/x86/kernel/amd_nb.c | 1 + drivers/hwmon/k10temp.c | 5 +---- include/linux/pci_ids.h | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index be16854591cc..153a0ee88fb1 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -16,6 +16,7 @@ const struct pci_device_id amd_nb_misc_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) }, {} }; EXPORT_SYMBOL(amd_nb_misc_ids); diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index 7356b5ec8f67..f2fe8078633b 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c @@ -33,9 +33,6 @@ static bool force; module_param(force, bool, 0444); MODULE_PARM_DESC(force, "force loading on processors with erratum 319"); -/* PCI-IDs for Northbridge devices not used anywhere else */ -#define PCI_DEVICE_ID_AMD_15H_M10H_NB_F3 0x1403 - /* CPUID function 0x80000001, ebx */ #define CPUID_PKGTYPE_MASK 0xf0000000 #define CPUID_PKGTYPE_F 0x00000000 @@ -213,7 +210,7 @@ static DEFINE_PCI_DEVICE_TABLE(k10temp_id_table) = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) }, - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_NB_F3) }, + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) }, {} }; MODULE_DEVICE_TABLE(pci, k10temp_id_table); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ab741b0d0074..05fd02e44993 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -517,6 +517,7 @@ #define PCI_DEVICE_ID_AMD_11H_NB_DRAM 0x1302 #define PCI_DEVICE_ID_AMD_11H_NB_MISC 0x1303 #define PCI_DEVICE_ID_AMD_11H_NB_LINK 0x1304 +#define PCI_DEVICE_ID_AMD_15H_M10H_F3 0x1403 #define PCI_DEVICE_ID_AMD_15H_NB_F0 0x1600 #define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 #define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 -- cgit v1.2.3 From 92e26e2a1a7d5fe6538e4a676f9c383966f894a7 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 2 May 2012 16:20:49 +0200 Subject: x86, MCE, AMD: Remove shared banks sysfs linking The code used to create a symlink on all non-BSP cores of a node when the MCi_MISCj bank is present once per node. (This is generally the case with bank 4 on AMD). However, these sysfs links cause a bunch of problems with cpu off-/onlining testing and are, as such, a bit overengineered. IOW, there's nothing wrong with having normal sysfs files for the shared banks since the corresponding MSRs are replicated across each core anyway. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 105 +++-------------------------------- 1 file changed, 7 insertions(+), 98 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index f4873a64f46d..2a5dd30f9969 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -60,7 +60,6 @@ struct threshold_block { struct threshold_bank { struct kobject *kobj; struct threshold_block *blocks; - cpumask_var_t cpus; }; static DEFINE_PER_CPU(struct threshold_bank * [NR_BANKS], threshold_banks); @@ -224,8 +223,6 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) if (!block) per_cpu(bank_map, cpu) |= (1 << bank); - if (shared_bank[bank] && c->cpu_core_id) - break; memset(&b, 0, sizeof(b)); b.cpu = cpu; @@ -555,89 +552,35 @@ local_allocate_threshold_blocks(int cpu, unsigned int bank) MSR_IA32_MC0_MISC + bank * 4); } -/* symlinks sibling shared banks to first core. first core owns dir/files. */ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) { - int i, err = 0; - struct threshold_bank *b = NULL; struct device *dev = per_cpu(mce_device, cpu); + struct threshold_bank *b = NULL; char name[32]; + int err = 0; sprintf(name, "threshold_bank%i", bank); -#ifdef CONFIG_SMP - if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) { /* symlink */ - i = cpumask_first(cpu_llc_shared_mask(cpu)); - - /* first core not up yet */ - if (cpu_data(i).cpu_core_id) - goto out; - - /* already linked */ - if (per_cpu(threshold_banks, cpu)[bank]) - goto out; - - b = per_cpu(threshold_banks, i)[bank]; - - if (!b) - goto out; - - err = sysfs_create_link(&dev->kobj, b->kobj, name); - if (err) - goto out; - - cpumask_copy(b->cpus, cpu_llc_shared_mask(cpu)); - per_cpu(threshold_banks, cpu)[bank] = b; - - goto out; - } -#endif - b = kzalloc(sizeof(struct threshold_bank), GFP_KERNEL); if (!b) { err = -ENOMEM; goto out; } - if (!zalloc_cpumask_var(&b->cpus, GFP_KERNEL)) { - kfree(b); - err = -ENOMEM; - goto out; - } b->kobj = kobject_create_and_add(name, &dev->kobj); - if (!b->kobj) + if (!b->kobj) { + err = -EINVAL; goto out_free; - -#ifndef CONFIG_SMP - cpumask_setall(b->cpus); -#else - cpumask_set_cpu(cpu, b->cpus); -#endif + } per_cpu(threshold_banks, cpu)[bank] = b; err = local_allocate_threshold_blocks(cpu, bank); - if (err) - goto out_free; - - for_each_cpu(i, b->cpus) { - if (i == cpu) - continue; - - dev = per_cpu(mce_device, i); - if (dev) - err = sysfs_create_link(&dev->kobj,b->kobj, name); - if (err) - goto out; - - per_cpu(threshold_banks, i)[bank] = b; - } - - goto out; + if (!err) + goto out; out_free: per_cpu(threshold_banks, cpu)[bank] = NULL; - free_cpumask_var(b->cpus); kfree(b); out: return err; @@ -660,12 +603,6 @@ static __cpuinit int threshold_create_device(unsigned int cpu) return err; } -/* - * let's be hotplug friendly. - * in case of multiple core processors, the first core always takes ownership - * of shared sysfs dir/files, and rest of the cores will be symlinked to it. - */ - static void deallocate_threshold_block(unsigned int cpu, unsigned int bank) { @@ -689,9 +626,6 @@ static void deallocate_threshold_block(unsigned int cpu, static void threshold_remove_bank(unsigned int cpu, int bank) { struct threshold_bank *b; - struct device *dev; - char name[32]; - int i = 0; b = per_cpu(threshold_banks, cpu)[bank]; if (!b) @@ -699,36 +633,11 @@ static void threshold_remove_bank(unsigned int cpu, int bank) if (!b->blocks) goto free_out; - sprintf(name, "threshold_bank%i", bank); - -#ifdef CONFIG_SMP - /* sibling symlink */ - if (shared_bank[bank] && b->blocks->cpu != cpu) { - dev = per_cpu(mce_device, cpu); - sysfs_remove_link(&dev->kobj, name); - per_cpu(threshold_banks, cpu)[bank] = NULL; - - return; - } -#endif - - /* remove all sibling symlinks before unregistering */ - for_each_cpu(i, b->cpus) { - if (i == cpu) - continue; - - dev = per_cpu(mce_device, i); - if (dev) - sysfs_remove_link(&dev->kobj, name); - per_cpu(threshold_banks, i)[bank] = NULL; - } - deallocate_threshold_block(cpu, bank); free_out: kobject_del(b->kobj); kobject_put(b->kobj); - free_cpumask_var(b->cpus); kfree(b); per_cpu(threshold_banks, cpu)[bank] = NULL; } -- cgit v1.2.3 From 26ab256eaac7af26ecd9ba893b5159a3b38c8a1c Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 2 May 2012 16:43:02 +0200 Subject: x86, MCE, AMD: Remove local_allocate_... wrapper It is unneeded now so drop it. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 2a5dd30f9969..7fd02cac962b 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -61,6 +61,7 @@ struct threshold_bank { struct kobject *kobj; struct threshold_block *blocks; }; + static DEFINE_PER_CPU(struct threshold_bank * [NR_BANKS], threshold_banks); static unsigned char shared_bank[NR_BANKS] = { @@ -545,13 +546,6 @@ out_free: return err; } -static __cpuinit long -local_allocate_threshold_blocks(int cpu, unsigned int bank) -{ - return allocate_threshold_blocks(cpu, bank, 0, - MSR_IA32_MC0_MISC + bank * 4); -} - static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) { struct device *dev = per_cpu(mce_device, cpu); @@ -575,7 +569,8 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) per_cpu(threshold_banks, cpu)[bank] = b; - err = local_allocate_threshold_blocks(cpu, bank); + err = allocate_threshold_blocks(cpu, bank, 0, + MSR_IA32_MC0_MISC + bank * 4); if (!err) goto out; -- cgit v1.2.3 From 019f34fccfd5cf5ff1e722dafd9fe2bd54434e66 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 2 May 2012 17:16:59 +0200 Subject: x86, MCE, AMD: Move shared bank to node descriptor Well, instead of having a real bank 4 on the BSP of each node and symlinks on the remaining cores, we push it up into the amd_northbridge descriptor which now contains a pointer to the northbridge bank 4 because the bank is one per northbridge and, as such, belongs in the NB descriptor anyway. Each time we hotplug CPUs, we use the northbridge pointer to copy the shared bank into the per-CPU array of threshold_banks pointers, or destroy it when the last CPU on the node goes offline, or create it when the first comes online. Signed-off-by: Borislav Petkov --- arch/x86/include/asm/amd_nb.h | 21 +++++++ arch/x86/kernel/cpu/mcheck/mce_amd.c | 107 ++++++++++++++++++++++++++++------- 2 files changed, 108 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h index 49ad773f4b9f..b3341e9cd8fd 100644 --- a/arch/x86/include/asm/amd_nb.h +++ b/arch/x86/include/asm/amd_nb.h @@ -26,10 +26,31 @@ struct amd_l3_cache { u8 subcaches[4]; }; +struct threshold_block { + unsigned int block; + unsigned int bank; + unsigned int cpu; + u32 address; + u16 interrupt_enable; + bool interrupt_capable; + u16 threshold_limit; + struct kobject kobj; + struct list_head miscj; +}; + +struct threshold_bank { + struct kobject *kobj; + struct threshold_block *blocks; + + /* initialized to the number of CPUs on the node sharing this bank */ + atomic_t cpus; +}; + struct amd_northbridge { struct pci_dev *misc; struct pci_dev *link; struct amd_l3_cache l3_cache; + struct threshold_bank *bank4; }; struct amd_northbridge_info { diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 7fd02cac962b..d67c9e56d609 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -45,23 +46,6 @@ #define MASK_BLKPTR_LO 0xFF000000 #define MCG_XBLK_ADDR 0xC0000400 -struct threshold_block { - unsigned int block; - unsigned int bank; - unsigned int cpu; - u32 address; - u16 interrupt_enable; - bool interrupt_capable; - u16 threshold_limit; - struct kobject kobj; - struct list_head miscj; -}; - -struct threshold_bank { - struct kobject *kobj; - struct threshold_block *blocks; -}; - static DEFINE_PER_CPU(struct threshold_bank * [NR_BANKS], threshold_banks); static unsigned char shared_bank[NR_BANKS] = { @@ -546,15 +530,62 @@ out_free: return err; } +static __cpuinit int __threshold_add_blocks(struct threshold_bank *b) +{ + struct list_head *head = &b->blocks->miscj; + struct threshold_block *pos = NULL; + struct threshold_block *tmp = NULL; + int err = 0; + + err = kobject_add(&b->blocks->kobj, b->kobj, b->blocks->kobj.name); + if (err) + return err; + + list_for_each_entry_safe(pos, tmp, head, miscj) { + + err = kobject_add(&pos->kobj, b->kobj, pos->kobj.name); + if (err) { + list_for_each_entry_safe_reverse(pos, tmp, head, miscj) + kobject_del(&pos->kobj); + + return err; + } + } + return err; +} + static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) { struct device *dev = per_cpu(mce_device, cpu); + struct amd_northbridge *nb = NULL; struct threshold_bank *b = NULL; char name[32]; int err = 0; sprintf(name, "threshold_bank%i", bank); + if (shared_bank[bank]) { + + nb = node_to_amd_nb(amd_get_nb_id(cpu)); + WARN_ON(!nb); + + /* threshold descriptor already initialized on this node? */ + if (nb->bank4) { + /* yes, use it */ + b = nb->bank4; + err = kobject_add(b->kobj, &dev->kobj, name); + if (err) + goto out; + + per_cpu(threshold_banks, cpu)[bank] = b; + atomic_inc(&b->cpus); + + err = __threshold_add_blocks(b); + + goto out; + } + } + b = kzalloc(sizeof(struct threshold_bank), GFP_KERNEL); if (!b) { err = -ENOMEM; @@ -569,15 +600,23 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) per_cpu(threshold_banks, cpu)[bank] = b; + if (shared_bank[bank]) { + atomic_set(&b->cpus, 1); + + /* nb is already initialized, see above */ + WARN_ON(nb->bank4); + nb->bank4 = b; + } + err = allocate_threshold_blocks(cpu, bank, 0, MSR_IA32_MC0_MISC + bank * 4); if (!err) goto out; -out_free: - per_cpu(threshold_banks, cpu)[bank] = NULL; + out_free: kfree(b); -out: + + out: return err; } @@ -618,16 +657,44 @@ static void deallocate_threshold_block(unsigned int cpu, per_cpu(threshold_banks, cpu)[bank]->blocks = NULL; } +static void __threshold_remove_blocks(struct threshold_bank *b) +{ + struct threshold_block *pos = NULL; + struct threshold_block *tmp = NULL; + + kobject_del(b->kobj); + + list_for_each_entry_safe(pos, tmp, &b->blocks->miscj, miscj) + kobject_del(&pos->kobj); +} + static void threshold_remove_bank(unsigned int cpu, int bank) { + struct amd_northbridge *nb; struct threshold_bank *b; b = per_cpu(threshold_banks, cpu)[bank]; if (!b) return; + if (!b->blocks) goto free_out; + if (shared_bank[bank]) { + if (!atomic_dec_and_test(&b->cpus)) { + __threshold_remove_blocks(b); + per_cpu(threshold_banks, cpu)[bank] = NULL; + return; + } else { + /* + * the last CPU on this node using the shared bank is + * going away, remove that bank now. + */ + nb = node_to_amd_nb(amd_get_nb_id(cpu)); + nb->bank4 = NULL; + } + } + deallocate_threshold_block(cpu, bank); free_out: -- cgit v1.2.3 From 18c20f373b76a64270a991396b06542abaf9f530 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 27 Apr 2012 12:31:34 +0200 Subject: x86, MCE, AMD: Print decimal thresholding values If one sets the threshold limit, say to 25: $ echo 25 > machinecheck0/threshold_bank4/misc0/threshold_limit and then reads it back again, it gives $ cat machinecheck0/threshold_bank4/misc0/threshold_limit 19 which is actually 0x19 but we don't know that. Make all output decimal. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index d67c9e56d609..0b1bb0e15881 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -308,7 +308,7 @@ struct threshold_attr { #define SHOW_FIELDS(name) \ static ssize_t show_ ## name(struct threshold_block *b, char *buf) \ { \ - return sprintf(buf, "%lx\n", (unsigned long) b->name); \ + return sprintf(buf, "%lu\n", (unsigned long) b->name); \ } SHOW_FIELDS(interrupt_enable) SHOW_FIELDS(threshold_limit) @@ -379,7 +379,7 @@ static ssize_t show_error_count(struct threshold_block *b, char *buf) struct threshold_block_cross_cpu tbcc = { .tb = b, }; smp_call_function_single(b->cpu, local_error_count_handler, &tbcc, 1); - return sprintf(buf, "%lx\n", tbcc.retval); + return sprintf(buf, "%lu\n", tbcc.retval); } static ssize_t store_error_count(struct threshold_block *b, -- cgit v1.2.3 From 2c9c42fa98c283961b7f6b6542fb4bf0c0539e15 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 27 Apr 2012 12:53:59 +0200 Subject: x86, MCE, AMD: Cleanup reading of error_count We have rdmsr_on_cpu() now so remove locally defined solution in favor of the generic one. No functionality change. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 0b1bb0e15881..a7204ef37223 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -359,27 +359,14 @@ store_threshold_limit(struct threshold_block *b, const char *buf, size_t size) return size; } -struct threshold_block_cross_cpu { - struct threshold_block *tb; - long retval; -}; - -static void local_error_count_handler(void *_tbcc) -{ - struct threshold_block_cross_cpu *tbcc = _tbcc; - struct threshold_block *b = tbcc->tb; - u32 low, high; - - rdmsr(b->address, low, high); - tbcc->retval = (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit); -} - static ssize_t show_error_count(struct threshold_block *b, char *buf) { - struct threshold_block_cross_cpu tbcc = { .tb = b, }; + u32 lo, hi; + + rdmsr_on_cpu(b->cpu, b->address, &lo, &hi); - smp_call_function_single(b->cpu, local_error_count_handler, &tbcc, 1); - return sprintf(buf, "%lu\n", tbcc.retval); + return sprintf(buf, "%u\n", ((hi & THRESHOLD_MAX) - + (THRESHOLD_MAX - b->threshold_limit))); } static ssize_t store_error_count(struct threshold_block *b, -- cgit v1.2.3 From 6e927361bd403dbf5f6a2668a2a07df1f1b2daff Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 27 Apr 2012 15:37:25 +0200 Subject: x86, MCE, AMD: Make error_count read only Until now, writing to error count caused the code to reset the thresholding bank to the current thresholding limit and start counting errors from the beginning. This is misleading and unclear, and can be accomplished by writing the old thresholding limit into ->threshold_limit. Make error_count read-only with the functionality to show the current error count. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index a7204ef37223..e5ed2c7cb4de 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -369,14 +369,10 @@ static ssize_t show_error_count(struct threshold_block *b, char *buf) (THRESHOLD_MAX - b->threshold_limit))); } -static ssize_t store_error_count(struct threshold_block *b, - const char *buf, size_t count) -{ - struct thresh_restart tr = { .b = b, .reset = 1, .old_limit = 0 }; - - smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1); - return 1; -} +static struct threshold_attr error_count = { + .attr = {.name = __stringify(error_count), .mode = 0444 }, + .show = show_error_count, +}; #define RW_ATTR(val) \ static struct threshold_attr val = { \ @@ -387,7 +383,6 @@ static struct threshold_attr val = { \ RW_ATTR(interrupt_enable); RW_ATTR(threshold_limit); -RW_ATTR(error_count); static struct attribute *default_attrs[] = { &threshold_limit.attr, -- cgit v1.2.3 From 336d335a963a5a4f5d7f915b4d74ada5d7b4d05b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 4 May 2012 17:05:27 +0200 Subject: x86, MCE, AMD: Give proper names to the thresholding banks Having the banks numbered is ok but having real names which mean something to the user makes a lot more sense: /sys/devices/system/machinecheck/machinecheck0/ |-- bank0 |-- bank1 |-- bank2 |-- bank3 |-- bank4 |-- bank5 |-- bank6 |-- check_interval |-- cmci_disabled |-- combined_unit | |-- combined_unit | |-- error_count | |-- threshold_limit |-- dont_log_ce |-- execution_unit | |-- execution_unit | |-- error_count | |-- threshold_limit |-- ignore_ce |-- insn_fetch | |-- insn_fetch | |-- error_count | |-- threshold_limit |-- load_store | |-- load_store | |-- error_count | |-- threshold_limit |-- monarch_timeout |-- northbridge | |-- dram | | |-- error_count | | |-- interrupt_enable | | |-- threshold_limit | |-- ht_links | | |-- error_count | | |-- interrupt_enable | | |-- threshold_limit | |-- l3_cache | |-- error_count | |-- interrupt_enable | |-- threshold_limit ... Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index e5ed2c7cb4de..e20bdf8d7c59 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -46,6 +46,15 @@ #define MASK_BLKPTR_LO 0xFF000000 #define MCG_XBLK_ADDR 0xC0000400 +static const char * const th_names[] = { + "load_store", + "insn_fetch", + "combined_unit", + "", + "northbridge", + "execution_unit", +}; + static DEFINE_PER_CPU(struct threshold_bank * [NR_BANKS], threshold_banks); static unsigned char shared_bank[NR_BANKS] = { @@ -68,6 +77,26 @@ struct thresh_restart { u16 old_limit; }; +static const char * const bank4_names(struct threshold_block *b) +{ + switch (b->address) { + /* MSR4_MISC0 */ + case 0x00000413: + return "dram"; + + case 0xc0000408: + return "ht_links"; + + case 0xc0000409: + return "l3_cache"; + + default: + WARN(1, "Funny MSR: 0x%08x\n", b->address); + return ""; + } +}; + + static bool lvt_interrupt_supported(unsigned int bank, u32 msr_high_bits) { /* @@ -481,7 +510,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu, err = kobject_init_and_add(&b->kobj, &threshold_ktype, per_cpu(threshold_banks, cpu)[bank]->kobj, - "misc%i", block); + (bank == 4 ? bank4_names(b) : th_names[bank])); if (err) goto out_free; recurse: @@ -541,11 +570,9 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) struct device *dev = per_cpu(mce_device, cpu); struct amd_northbridge *nb = NULL; struct threshold_bank *b = NULL; - char name[32]; + const char *name = th_names[bank]; int err = 0; - sprintf(name, "threshold_bank%i", bank); - if (shared_bank[bank]) { nb = node_to_amd_nb(amd_get_nb_id(cpu)); -- cgit v1.2.3 From 11122570193a429f72014703ce6b849640f8d7e5 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 7 May 2012 18:22:16 +0200 Subject: x86, MCE, AMD: Update copyrights and boilerplate Jacob is doing something else now so add myself as the loser who provides support. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index e20bdf8d7c59..671b95a2ffb5 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -1,15 +1,17 @@ /* - * (c) 2005, 2006 Advanced Micro Devices, Inc. + * (c) 2005-2012 Advanced Micro Devices, Inc. * Your use of this code is subject to the terms and conditions of the * GNU general public license version 2. See "COPYING" or * http://www.gnu.org/licenses/gpl.html * * Written by Jacob Shin - AMD, Inc. * - * Support : jacob.shin@amd.com + * Support: borislav.petkov@amd.com * * April 2006 * - added support for AMD Family 0x10 processors + * May 2012 + * - major scrubbing * * All MC4_MISCi registers are shared between multi-cores */ -- cgit v1.2.3 From aa29cab3f12b14020011bcad28cc11f50725d68f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 20 May 2012 14:11:24 -0300 Subject: ARM: mx31: Add pinctrl_provide_dummies() commit a2aa65a (ARM: imx: enable pinctrl dummy states) missed to add pinctrl_provide_dummies() for mx31. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/mach-imx/mm-imx3.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c index 967ed5b35a45..0b211f63981f 100644 --- a/arch/arm/mach-imx/mm-imx3.c +++ b/arch/arm/mach-imx/mm-imx3.c @@ -179,6 +179,8 @@ void __init imx31_soc_init(void) mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0); mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0); + pinctrl_provide_dummies(); + if (to_version == 1) { strncpy(imx31_sdma_pdata.fw_name, "sdma-imx31-to1.bin", strlen(imx31_sdma_pdata.fw_name)); -- cgit v1.2.3 From eb5558dd46dab1e3023f052f99979b0e2bfd1b19 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 20 May 2012 14:21:09 -0300 Subject: ARM: mx51: Add pinctrl_provide_dummies() commit a2aa65a (ARM: imx: enable pinctrl dummy states) missed to add pinctrl_provide_dummies() for mx51. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/mach-imx/mm-imx5.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c index feeee17da96b..1d003053d562 100644 --- a/arch/arm/mach-imx/mm-imx5.c +++ b/arch/arm/mach-imx/mm-imx5.c @@ -202,6 +202,8 @@ void __init imx51_soc_init(void) mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH); mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH); + pinctrl_provide_dummies(); + /* i.mx51 has the i.mx35 type sdma */ imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata); -- cgit v1.2.3 From 602bf40971d7f9a1ec0b7ba2b7e6427849828651 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 22 May 2012 22:13:46 +0800 Subject: ARM: imx6: exit coherency when shutting down a cpu There is a system hang issue on imx6q which can easily be seen with running a cpu hotplug stress testing (hotplug secondary cores from user space via sysfs interface for thousands iterations). It turns out that the issue is caused by coherency of the cpu that is being shut down. When shutting down a cpu, we need to have the cpu exit coherency to prevent it from receiving cache, TLB, or BTB maintenance operations broadcast by other CPUs in the cluster. Copy cpu_enter_lowpower() and cpu_leave_lowpower() from mach-vexpress to have coherency properly handled in platform_cpu_die(), thus fix the issue. Signed-off-by: Shawn Guo Cc: stable@kernel.org --- arch/arm/mach-imx/hotplug.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index 89493abd497c..20ed2d56c1af 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c @@ -12,6 +12,7 @@ #include #include +#include #include int platform_cpu_kill(unsigned int cpu) @@ -19,6 +20,44 @@ int platform_cpu_kill(unsigned int cpu) return 1; } +static inline void cpu_enter_lowpower(void) +{ + unsigned int v; + + flush_cache_all(); + asm volatile( + "mcr p15, 0, %1, c7, c5, 0\n" + " mcr p15, 0, %1, c7, c10, 4\n" + /* + * Turn off coherency + */ + " mrc p15, 0, %0, c1, c0, 1\n" + " bic %0, %0, %3\n" + " mcr p15, 0, %0, c1, c0, 1\n" + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, %2\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "r" (0), "Ir" (CR_C), "Ir" (0x40) + : "cc"); +} + +static inline void cpu_leave_lowpower(void) +{ + unsigned int v; + + asm volatile( + "mrc p15, 0, %0, c1, c0, 0\n" + " orr %0, %0, %1\n" + " mcr p15, 0, %0, c1, c0, 0\n" + " mrc p15, 0, %0, c1, c0, 1\n" + " orr %0, %0, %2\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : "Ir" (CR_C), "Ir" (0x40) + : "cc"); +} + /* * platform-specific code to shutdown a CPU * @@ -26,9 +65,10 @@ int platform_cpu_kill(unsigned int cpu) */ void platform_cpu_die(unsigned int cpu) { - flush_cache_all(); + cpu_enter_lowpower(); imx_enable_cpu(cpu, false); cpu_do_idle(); + cpu_leave_lowpower(); /* We should never return from idle */ panic("cpu %d unexpectedly exit from shutdown\n", cpu); -- cgit v1.2.3 From 7fbb98c5cb07563d3ee08714073a8e5452a96be2 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 7 Jun 2012 10:21:21 -0400 Subject: x86: Save cr2 in NMI in case NMIs take a page fault Avi Kivity reported that page faults in NMIs could cause havic if the NMI preempted another page fault handler: The recent changes to NMI allow exceptions to take place in NMI handlers, but I think that a #PF (say, due to access to vmalloc space) is still problematic. Consider the sequence #PF (cr2 set by processor) NMI ... #PF (cr2 clobbered) do_page_fault() IRET ... IRET do_page_fault() address = read_cr2() The last line reads the overwritten cr2 value. Originally I wrote a patch to solve this by saving the cr2 on the stack. Brian Gerst suggested to save it in the r12 register as both r12 and rbx are saved by the do_nmi handler as required by the C standard. But rbx is already used for saving if swapgs needs to be run on exit of the NMI handler. Link: http://lkml.kernel.org/r/4FBB8C40.6080304@redhat.com Link: http://lkml.kernel.org/r/1337763411.13348.140.camel@gandalf.stny.rr.com Reported-by: Avi Kivity Cc: Linus Torvalds Cc: H. Peter Anvin Cc: Thomas Gleixner Suggested-by: Brian Gerst Signed-off-by: Steven Rostedt --- arch/x86/kernel/entry_64.S | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 7d65133b51be..111f6bbd8b38 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1758,10 +1758,30 @@ end_repeat_nmi: */ call save_paranoid DEFAULT_FRAME 0 + + /* + * Save off the CR2 register. If we take a page fault in the NMI then + * it could corrupt the CR2 value. If the NMI preempts a page fault + * handler before it was able to read the CR2 register, and then the + * NMI itself takes a page fault, the page fault that was preempted + * will read the information from the NMI page fault and not the + * origin fault. Save it off and restore it if it changes. + * Use the r12 callee-saved register. + */ + movq %cr2, %r12 + /* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */ movq %rsp,%rdi movq $-1,%rsi call do_nmi + + /* Did the NMI take a page fault? Restore cr2 if it did */ + movq %cr2, %rcx + cmpq %rcx, %r12 + je 1f + movq %r12, %cr2 +1: + testl %ebx,%ebx /* swapgs needed? */ jnz nmi_restore nmi_swapgs: -- cgit v1.2.3 From 1f975f78c84c852e09463a2dfa57e3174e5c719e Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 1 Jun 2012 16:52:35 +0200 Subject: x86, pvops: Remove hooks for {rd,wr}msr_safe_regs There were paravirt_ops hooks for the full register set variant of {rd,wr}msr_safe which are actually not used by anyone anymore. Remove them to make the code cleaner and avoid silent breakages when the pvops members were uninitialized. This has been boot-tested natively and under Xen with PVOPS enabled and disabled on one machine. Signed-off-by: Andre Przywara Link: http://lkml.kernel.org/r/1338562358-28182-2-git-send-email-bp@amd64.org Acked-by: Konrad Rzeszutek Wilk Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/msr.h | 67 +++++++++++++++-------------------- arch/x86/include/asm/paravirt.h | 39 -------------------- arch/x86/include/asm/paravirt_types.h | 2 -- arch/x86/kernel/paravirt.c | 2 -- arch/x86/lib/msr-reg-export.c | 4 +-- arch/x86/lib/msr-reg.S | 10 +++--- arch/x86/xen/enlighten.c | 2 -- 7 files changed, 35 insertions(+), 91 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 084ef95274cd..81860cc012d1 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -115,8 +115,8 @@ notrace static inline int native_write_msr_safe(unsigned int msr, extern unsigned long long native_read_tsc(void); -extern int native_rdmsr_safe_regs(u32 regs[8]); -extern int native_wrmsr_safe_regs(u32 regs[8]); +extern int rdmsr_safe_regs(u32 regs[8]); +extern int wrmsr_safe_regs(u32 regs[8]); static __always_inline unsigned long long __native_read_tsc(void) { @@ -187,43 +187,6 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p) return err; } -static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) -{ - u32 gprs[8] = { 0 }; - int err; - - gprs[1] = msr; - gprs[7] = 0x9c5a203a; - - err = native_rdmsr_safe_regs(gprs); - - *p = gprs[0] | ((u64)gprs[2] << 32); - - return err; -} - -static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val) -{ - u32 gprs[8] = { 0 }; - - gprs[0] = (u32)val; - gprs[1] = msr; - gprs[2] = val >> 32; - gprs[7] = 0x9c5a203a; - - return native_wrmsr_safe_regs(gprs); -} - -static inline int rdmsr_safe_regs(u32 regs[8]) -{ - return native_rdmsr_safe_regs(regs); -} - -static inline int wrmsr_safe_regs(u32 regs[8]) -{ - return native_wrmsr_safe_regs(regs); -} - #define rdtscl(low) \ ((low) = (u32)__native_read_tsc()) @@ -248,6 +211,32 @@ do { \ #endif /* !CONFIG_PARAVIRT */ +static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) +{ + u32 gprs[8] = { 0 }; + int err; + + gprs[1] = msr; + gprs[7] = 0x9c5a203a; + + err = rdmsr_safe_regs(gprs); + + *p = gprs[0] | ((u64)gprs[2] << 32); + + return err; +} + +static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val) +{ + u32 gprs[8] = { 0 }; + + gprs[0] = (u32)val; + gprs[1] = msr; + gprs[2] = val >> 32; + gprs[7] = 0x9c5a203a; + + return wrmsr_safe_regs(gprs); +} #define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val), \ (u32)((val) >> 32)) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 6cbbabf52707..ebb0cdb60a89 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -128,21 +128,11 @@ static inline u64 paravirt_read_msr(unsigned msr, int *err) return PVOP_CALL2(u64, pv_cpu_ops.read_msr, msr, err); } -static inline int paravirt_rdmsr_regs(u32 *regs) -{ - return PVOP_CALL1(int, pv_cpu_ops.rdmsr_regs, regs); -} - static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high) { return PVOP_CALL3(int, pv_cpu_ops.write_msr, msr, low, high); } -static inline int paravirt_wrmsr_regs(u32 *regs) -{ - return PVOP_CALL1(int, pv_cpu_ops.wrmsr_regs, regs); -} - /* These should all do BUG_ON(_err), but our headers are too tangled. */ #define rdmsr(msr, val1, val2) \ do { \ @@ -176,9 +166,6 @@ do { \ _err; \ }) -#define rdmsr_safe_regs(regs) paravirt_rdmsr_regs(regs) -#define wrmsr_safe_regs(regs) paravirt_wrmsr_regs(regs) - static inline int rdmsrl_safe(unsigned msr, unsigned long long *p) { int err; @@ -186,32 +173,6 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p) *p = paravirt_read_msr(msr, &err); return err; } -static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) -{ - u32 gprs[8] = { 0 }; - int err; - - gprs[1] = msr; - gprs[7] = 0x9c5a203a; - - err = paravirt_rdmsr_regs(gprs); - - *p = gprs[0] | ((u64)gprs[2] << 32); - - return err; -} - -static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val) -{ - u32 gprs[8] = { 0 }; - - gprs[0] = (u32)val; - gprs[1] = msr; - gprs[2] = val >> 32; - gprs[7] = 0x9c5a203a; - - return paravirt_wrmsr_regs(gprs); -} static inline u64 paravirt_read_tsc(void) { diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index 8e8b9a4987ee..8613cbb7ba41 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -153,9 +153,7 @@ struct pv_cpu_ops { /* MSR, PMC and TSR operations. err = 0/-EFAULT. wrmsr returns 0/-EFAULT. */ u64 (*read_msr)(unsigned int msr, int *err); - int (*rdmsr_regs)(u32 *regs); int (*write_msr)(unsigned int msr, unsigned low, unsigned high); - int (*wrmsr_regs)(u32 *regs); u64 (*read_tsc)(void); u64 (*read_pmc)(int counter); diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 9ce885996fd7..17fff18a1031 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -352,9 +352,7 @@ struct pv_cpu_ops pv_cpu_ops = { #endif .wbinvd = native_wbinvd, .read_msr = native_read_msr_safe, - .rdmsr_regs = native_rdmsr_safe_regs, .write_msr = native_write_msr_safe, - .wrmsr_regs = native_wrmsr_safe_regs, .read_tsc = native_read_tsc, .read_pmc = native_read_pmc, .read_tscp = native_read_tscp, diff --git a/arch/x86/lib/msr-reg-export.c b/arch/x86/lib/msr-reg-export.c index a311cc59b65d..8d6ef78b5d01 100644 --- a/arch/x86/lib/msr-reg-export.c +++ b/arch/x86/lib/msr-reg-export.c @@ -1,5 +1,5 @@ #include #include -EXPORT_SYMBOL(native_rdmsr_safe_regs); -EXPORT_SYMBOL(native_wrmsr_safe_regs); +EXPORT_SYMBOL(rdmsr_safe_regs); +EXPORT_SYMBOL(wrmsr_safe_regs); diff --git a/arch/x86/lib/msr-reg.S b/arch/x86/lib/msr-reg.S index 69fa10623f21..f6d13eefad10 100644 --- a/arch/x86/lib/msr-reg.S +++ b/arch/x86/lib/msr-reg.S @@ -6,13 +6,13 @@ #ifdef CONFIG_X86_64 /* - * int native_{rdmsr,wrmsr}_safe_regs(u32 gprs[8]); + * int {rdmsr,wrmsr}_safe_regs(u32 gprs[8]); * * reg layout: u32 gprs[eax, ecx, edx, ebx, esp, ebp, esi, edi] * */ .macro op_safe_regs op -ENTRY(native_\op\()_safe_regs) +ENTRY(\op\()_safe_regs) CFI_STARTPROC pushq_cfi %rbx pushq_cfi %rbp @@ -45,13 +45,13 @@ ENTRY(native_\op\()_safe_regs) _ASM_EXTABLE(1b, 3b) CFI_ENDPROC -ENDPROC(native_\op\()_safe_regs) +ENDPROC(\op\()_safe_regs) .endm #else /* X86_32 */ .macro op_safe_regs op -ENTRY(native_\op\()_safe_regs) +ENTRY(\op\()_safe_regs) CFI_STARTPROC pushl_cfi %ebx pushl_cfi %ebp @@ -92,7 +92,7 @@ ENTRY(native_\op\()_safe_regs) _ASM_EXTABLE(1b, 3b) CFI_ENDPROC -ENDPROC(native_\op\()_safe_regs) +ENDPROC(\op\()_safe_regs) .endm #endif diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index e74df9548a02..60f1131eb94f 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1116,9 +1116,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .wbinvd = native_wbinvd, .read_msr = native_read_msr_safe, - .rdmsr_regs = native_rdmsr_safe_regs, .write_msr = xen_write_msr_safe, - .wrmsr_regs = native_wrmsr_safe_regs, .read_tsc = native_read_tsc, .read_pmc = native_read_pmc, -- cgit v1.2.3 From ecd431d95aa04257e977fd6878e4203ce462e7e9 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 1 Jun 2012 16:52:36 +0200 Subject: x86, cpu: Fix show_msr MSR accessing function There's no real reason why, when showing the MSRs on a CPU at boottime, we should be using the AMD-specific variant. Simply use the generic safe one which handles #GPs just fine. Cc: Yinghai Lu Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1338562358-28182-3-git-send-email-bp@amd64.org Acked-by: Konrad Rzeszutek Wilk Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 6b9333b429ba..5bbc082c47ad 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -947,7 +947,7 @@ static void __cpuinit __print_cpu_msr(void) index_max = msr_range_array[i].max; for (index = index_min; index < index_max; index++) { - if (rdmsrl_amd_safe(index, &val)) + if (rdmsrl_safe(index, &val)) continue; printk(KERN_INFO " MSR%08x: %016llx\n", index, val); } -- cgit v1.2.3 From 169e9cbd77db23fe50bc8ba68bf081adb67b4220 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 1 Jun 2012 16:52:37 +0200 Subject: x86, cpu, amd: Fix crash as Xen Dom0 on AMD Trinity systems f7f286a910221 ("x86/amd: Re-enable CPU topology extensions in case BIOS has disabled it") wrongfully added code which used the AMD-specific {rd,wr}msr variants for no real reason. This caused boot panics on xen which wasn't initializing the {rd,wr}msr_safe_regs pv_ops members properly. This, in turn, caused a heated discussion leading to us reviewing all uses of the AMD-specific variants and removing them where unneeded (almost everywhere except an obscure K8 BIOS fix, see 6b0f43ddfa358). Finally, this patch switches to the standard {rd,wr}msr*_safe* variants which should've been used in the first place anyway and avoided unneeded excitation with xen. Signed-off-by: Andre Przywara Link: http://lkml.kernel.org/r/1338562358-28182-4-git-send-email-bp@amd64.org Cc: Andreas Herrmann Link: [Boris: correct and expand commit message] Signed-off-by: Borislav Petkov Acked-by: Konrad Rzeszutek Wilk Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/amd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 146bb6218eec..80ccd99542e6 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -586,9 +586,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) !cpu_has(c, X86_FEATURE_TOPOEXT)) { u64 val; - if (!rdmsrl_amd_safe(0xc0011005, &val)) { + if (!rdmsrl_safe(0xc0011005, &val)) { val |= 1ULL << 54; - wrmsrl_amd_safe(0xc0011005, val); + checking_wrmsrl(0xc0011005, val); rdmsrl(0xc0011005, val); if (val & (1ULL << 54)) { set_cpu_cap(c, X86_FEATURE_TOPOEXT); -- cgit v1.2.3 From 2c929ce6f1ed1302be225512b433e6a6554f71a4 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 1 Jun 2012 16:52:38 +0200 Subject: x86, cpu, amd: Deprecate AMD-specific MSR variants Now that all users of {rd,wr}msr_amd_safe have been fixed, deprecate its use by making them private to amd.c and adding warnings when used on anything else beside K8. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1338562358-28182-5-git-send-email-bp@amd64.org Acked-by: Konrad Rzeszutek Wilk Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/msr.h | 27 --------------------------- arch/x86/kernel/cpu/amd.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 27 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 81860cc012d1..cb33b5f00267 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -211,33 +211,6 @@ do { \ #endif /* !CONFIG_PARAVIRT */ -static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) -{ - u32 gprs[8] = { 0 }; - int err; - - gprs[1] = msr; - gprs[7] = 0x9c5a203a; - - err = rdmsr_safe_regs(gprs); - - *p = gprs[0] | ((u64)gprs[2] << 32); - - return err; -} - -static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val) -{ - u32 gprs[8] = { 0 }; - - gprs[0] = (u32)val; - gprs[1] = msr; - gprs[2] = val >> 32; - gprs[7] = 0x9c5a203a; - - return wrmsr_safe_regs(gprs); -} - #define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val), \ (u32)((val) >> 32)) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 80ccd99542e6..c928eb26ada6 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -19,6 +19,39 @@ #include "cpu.h" +static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) +{ + struct cpuinfo_x86 *c = &cpu_data(smp_processor_id()); + u32 gprs[8] = { 0 }; + int err; + + WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__); + + gprs[1] = msr; + gprs[7] = 0x9c5a203a; + + err = rdmsr_safe_regs(gprs); + + *p = gprs[0] | ((u64)gprs[2] << 32); + + return err; +} + +static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val) +{ + struct cpuinfo_x86 *c = &cpu_data(smp_processor_id()); + u32 gprs[8] = { 0 }; + + WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__); + + gprs[0] = (u32)val; + gprs[1] = msr; + gprs[2] = val >> 32; + gprs[7] = 0x9c5a203a; + + return wrmsr_safe_regs(gprs); +} + #ifdef CONFIG_X86_32 /* * B step AMD K6 before B 9730xxxx have hardware bugs that can cause -- cgit v1.2.3 From 350ab15bb2ffe7103bc6bf6c634f3c5b286eaf2a Mon Sep 17 00:00:00 2001 From: Jaccon Bastiaansen Date: Mon, 30 Apr 2012 11:53:43 +0200 Subject: ARM i.MX imx21ads: Fix overlapping static i/o mappings The statically defined I/O memory regions for the i.MX21 on chip peripherals and the on board I/O peripherals of the i.MX21ADS board overlap. This results in a kernel crash during startup. This is fixed by reducing the memory range for the on board I/O peripherals to the actually required range. Signed-off-by: Jaccon Bastiaansen Signed-off-by: Sascha Hauer Cc: stable --- arch/arm/mach-imx/mach-mx21ads.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c index e432d4acee1f..4460d25faae1 100644 --- a/arch/arm/mach-imx/mach-mx21ads.c +++ b/arch/arm/mach-imx/mach-mx21ads.c @@ -32,7 +32,7 @@ * Memory-mapped I/O on MX21ADS base board */ #define MX21ADS_MMIO_BASE_ADDR 0xf5000000 -#define MX21ADS_MMIO_SIZE SZ_16M +#define MX21ADS_MMIO_SIZE 0xc00000 #define MX21ADS_REG_ADDR(offset) (void __force __iomem *) \ (MX21ADS_MMIO_BASE_ADDR + (offset)) -- cgit v1.2.3 From 715c85b1fc824e9cd0ea07d6ceb80d2262f32e90 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 7 Jun 2012 13:32:04 -0700 Subject: x86, cpu: Rename checking_wrmsrl() to wrmsrl_safe() Rename checking_wrmsrl() to wrmsrl_safe(), to match the naming convention used by all the other MSR access functions/macros. Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/msr.h | 2 +- arch/x86/kernel/cpu/amd.c | 4 ++-- arch/x86/kernel/cpu/perf_event.c | 2 +- arch/x86/kernel/cpu/perf_event_intel.c | 6 +++--- arch/x86/kernel/cpu/perf_event_p4.c | 14 +++++++------- arch/x86/kernel/cpu/perf_event_p6.c | 4 ++-- arch/x86/kernel/process_64.c | 4 ++-- arch/x86/vdso/vdso32-setup.c | 6 +++--- 8 files changed, 21 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index cb33b5f00267..fe83d74a920d 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -211,7 +211,7 @@ do { \ #endif /* !CONFIG_PARAVIRT */ -#define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val), \ +#define wrmsrl_safe(msr, val) wrmsr_safe((msr), (u32)(val), \ (u32)((val) >> 32)) #define write_tsc(val1, val2) wrmsr(MSR_IA32_TSC, (val1), (val2)) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index c928eb26ada6..9d92e19039f0 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -621,7 +621,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) if (!rdmsrl_safe(0xc0011005, &val)) { val |= 1ULL << 54; - checking_wrmsrl(0xc0011005, val); + wrmsrl_safe(0xc0011005, val); rdmsrl(0xc0011005, val); if (val & (1ULL << 54)) { set_cpu_cap(c, X86_FEATURE_TOPOEXT); @@ -712,7 +712,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) err = rdmsrl_safe(MSR_AMD64_MCx_MASK(4), &mask); if (err == 0) { mask |= (1 << 10); - checking_wrmsrl(MSR_AMD64_MCx_MASK(4), mask); + wrmsrl_safe(MSR_AMD64_MCx_MASK(4), mask); } } diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index e049d6da0183..4e3ba9cb5a4e 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -222,7 +222,7 @@ static bool check_hw_exists(void) * that don't trap on the MSR access and always return 0s. */ val = 0xabcdUL; - ret = checking_wrmsrl(x86_pmu_event_addr(0), val); + ret = wrmsrl_safe(x86_pmu_event_addr(0), val); ret |= rdmsrl_safe(x86_pmu_event_addr(0), &val_new); if (ret || val != val_new) goto msr_fail; diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 166546ec6aef..7789aa37c746 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1003,11 +1003,11 @@ static void intel_pmu_reset(void) printk("clearing PMU state on CPU#%d\n", smp_processor_id()); for (idx = 0; idx < x86_pmu.num_counters; idx++) { - checking_wrmsrl(x86_pmu_config_addr(idx), 0ull); - checking_wrmsrl(x86_pmu_event_addr(idx), 0ull); + wrmsrl_safe(x86_pmu_config_addr(idx), 0ull); + wrmsrl_safe(x86_pmu_event_addr(idx), 0ull); } for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) - checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); + wrmsrl_safe(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); if (ds) ds->bts_index = ds->bts_buffer_base; diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 47124a73dd73..6c82e4037989 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -895,8 +895,8 @@ static void p4_pmu_disable_pebs(void) * So at moment let leave metrics turned on forever -- it's * ok for now but need to be revisited! * - * (void)checking_wrmsrl(MSR_IA32_PEBS_ENABLE, (u64)0); - * (void)checking_wrmsrl(MSR_P4_PEBS_MATRIX_VERT, (u64)0); + * (void)wrmsrl_safe(MSR_IA32_PEBS_ENABLE, (u64)0); + * (void)wrmsrl_safe(MSR_P4_PEBS_MATRIX_VERT, (u64)0); */ } @@ -909,7 +909,7 @@ static inline void p4_pmu_disable_event(struct perf_event *event) * state we need to clear P4_CCCR_OVF, otherwise interrupt get * asserted again and again */ - (void)checking_wrmsrl(hwc->config_base, + (void)wrmsrl_safe(hwc->config_base, (u64)(p4_config_unpack_cccr(hwc->config)) & ~P4_CCCR_ENABLE & ~P4_CCCR_OVF & ~P4_CCCR_RESERVED); } @@ -943,8 +943,8 @@ static void p4_pmu_enable_pebs(u64 config) bind = &p4_pebs_bind_map[idx]; - (void)checking_wrmsrl(MSR_IA32_PEBS_ENABLE, (u64)bind->metric_pebs); - (void)checking_wrmsrl(MSR_P4_PEBS_MATRIX_VERT, (u64)bind->metric_vert); + (void)wrmsrl_safe(MSR_IA32_PEBS_ENABLE, (u64)bind->metric_pebs); + (void)wrmsrl_safe(MSR_P4_PEBS_MATRIX_VERT, (u64)bind->metric_vert); } static void p4_pmu_enable_event(struct perf_event *event) @@ -978,8 +978,8 @@ static void p4_pmu_enable_event(struct perf_event *event) */ p4_pmu_enable_pebs(hwc->config); - (void)checking_wrmsrl(escr_addr, escr_conf); - (void)checking_wrmsrl(hwc->config_base, + (void)wrmsrl_safe(escr_addr, escr_conf); + (void)wrmsrl_safe(hwc->config_base, (cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE); } diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index 32bcfc7dd230..e4dd0f7a0453 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -71,7 +71,7 @@ p6_pmu_disable_event(struct perf_event *event) if (cpuc->enabled) val |= ARCH_PERFMON_EVENTSEL_ENABLE; - (void)checking_wrmsrl(hwc->config_base, val); + (void)wrmsrl_safe(hwc->config_base, val); } static void p6_pmu_enable_event(struct perf_event *event) @@ -84,7 +84,7 @@ static void p6_pmu_enable_event(struct perf_event *event) if (cpuc->enabled) val |= ARCH_PERFMON_EVENTSEL_ENABLE; - (void)checking_wrmsrl(hwc->config_base, val); + (void)wrmsrl_safe(hwc->config_base, val); } PMU_FORMAT_ATTR(event, "config:0-7" ); diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 61cdf7fdf099..3e215ba68766 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -466,7 +466,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) task->thread.gs = addr; if (doit) { load_gs_index(0); - ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); + ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr); } } put_cpu(); @@ -494,7 +494,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) /* set the selector to 0 to not confuse __switch_to */ loadsegment(fs, 0); - ret = checking_wrmsrl(MSR_FS_BASE, addr); + ret = wrmsrl_safe(MSR_FS_BASE, addr); } } put_cpu(); diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c index 66e6d9359826..0faad646f5fd 100644 --- a/arch/x86/vdso/vdso32-setup.c +++ b/arch/x86/vdso/vdso32-setup.c @@ -205,9 +205,9 @@ void syscall32_cpu_init(void) { /* Load these always in case some future AMD CPU supports SYSENTER from compat mode too. */ - checking_wrmsrl(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS); - checking_wrmsrl(MSR_IA32_SYSENTER_ESP, 0ULL); - checking_wrmsrl(MSR_IA32_SYSENTER_EIP, (u64)ia32_sysenter_target); + wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS); + wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL); + wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)ia32_sysenter_target); wrmsrl(MSR_CSTAR, ia32_cstar_target); } -- cgit v1.2.3 From 8e56130dcbcc0608c2531c61f93175e36a300e58 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 6 Jun 2012 17:20:10 -0500 Subject: ARM: highbank: Add smc calls to enable/disable the L2 Linux runs in non-secure mode on highbank, so we need secure monitor calls to enable and disable the PL310. Rather than invent new smc calls, the same calling convention used by OMAP is used here. Signed-off-by: Rob Herring Signed-off-by: Olof Johansson --- arch/arm/mach-highbank/Makefile | 6 +++++- arch/arm/mach-highbank/core.h | 1 + arch/arm/mach-highbank/highbank.c | 14 ++++++++++++++ arch/arm/mach-highbank/smc.S | 27 +++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-highbank/smc.S (limited to 'arch') diff --git a/arch/arm/mach-highbank/Makefile b/arch/arm/mach-highbank/Makefile index f8437dd238c2..ded4652ada80 100644 --- a/arch/arm/mach-highbank/Makefile +++ b/arch/arm/mach-highbank/Makefile @@ -1,4 +1,8 @@ -obj-y := clock.o highbank.o system.o +obj-y := clock.o highbank.o system.o smc.o + +plus_sec := $(call as-instr,.arch_extension sec,+sec) +AFLAGS_smc.o :=-Wa,-march=armv7-a$(plus_sec) + obj-$(CONFIG_DEBUG_HIGHBANK_UART) += lluart.o obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-highbank/core.h b/arch/arm/mach-highbank/core.h index d8e2d0be64ac..141ed5171826 100644 --- a/arch/arm/mach-highbank/core.h +++ b/arch/arm/mach-highbank/core.h @@ -8,3 +8,4 @@ extern void highbank_lluart_map_io(void); static inline void highbank_lluart_map_io(void) {} #endif +extern void highbank_smc1(int fn, int arg); diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 410a112bb52e..8777612b1a42 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -85,10 +85,24 @@ const static struct of_device_id irq_match[] = { {} }; +#ifdef CONFIG_CACHE_L2X0 +static void highbank_l2x0_disable(void) +{ + /* Disable PL310 L2 Cache controller */ + highbank_smc1(0x102, 0x0); +} +#endif + static void __init highbank_init_irq(void) { of_irq_init(irq_match); + +#ifdef CONFIG_CACHE_L2X0 + /* Enable PL310 L2 Cache controller */ + highbank_smc1(0x102, 0x1); l2x0_of_init(0, ~0UL); + outer_cache.disable = highbank_l2x0_disable; +#endif } static void __init highbank_timer_init(void) diff --git a/arch/arm/mach-highbank/smc.S b/arch/arm/mach-highbank/smc.S new file mode 100644 index 000000000000..407d17baaaa9 --- /dev/null +++ b/arch/arm/mach-highbank/smc.S @@ -0,0 +1,27 @@ +/* + * Copied from omap44xx-smc.S Copyright (C) 2010 Texas Instruments, Inc. + * Copyright 2012 Calxeda, Inc. + * + * This program is free software,you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +/* + * This is common routine to manage secure monitor API + * used to modify the PL310 secure registers. + * 'r0' contains the value to be modified and 'r12' contains + * the monitor API number. + * Function signature : void highbank_smc1(u32 fn, u32 arg) + */ + +ENTRY(highbank_smc1) + stmfd sp!, {r4-r11, lr} + mov r12, r0 + mov r0, r1 + dsb + smc #0 + ldmfd sp!, {r4-r11, pc} +ENDPROC(highbank_smc1) -- cgit v1.2.3 From 9d8e10667624ea6411f04495aef1fa4a8a778ee8 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 7 Jun 2012 15:14:49 +0200 Subject: x86/apic: Factor out default vector_allocation_domain() operation Signed-off-by: Alexander Gordeev Acked-by: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120607131449.GC4759@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apic.h | 21 +++++++++++++++++++++ arch/x86/kernel/apic/apic_flat_64.c | 22 +--------------------- arch/x86/kernel/apic/apic_noop.c | 3 +-- arch/x86/kernel/apic/apic_numachip.c | 8 +------- arch/x86/kernel/apic/bigsmp_32.c | 8 +------- arch/x86/kernel/apic/es7000_32.c | 19 ++----------------- arch/x86/kernel/apic/numaq_32.c | 16 +--------------- arch/x86/kernel/apic/probe_32.c | 17 +---------------- arch/x86/kernel/apic/summit_32.c | 16 +--------------- arch/x86/kernel/apic/x2apic_phys.c | 11 +---------- arch/x86/kernel/apic/x2apic_uv_x.c | 8 +------- 11 files changed, 32 insertions(+), 117 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index bef571769e68..feb2dbdae9ec 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -615,6 +615,27 @@ extern unsigned int default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, const struct cpumask *andmask); +static inline void +flat_vector_allocation_domain(int cpu, struct cpumask *retmask) +{ + /* Careful. Some cpus do not strictly honor the set of cpus + * specified in the interrupt destination when using lowest + * priority interrupt delivery mode. + * + * In particular there was a hyperthreading cpu observed to + * deliver interrupts to the wrong hyperthread when only one + * hyperthread was specified in the interrupt desitination. + */ + cpumask_clear(retmask); + cpumask_bits(retmask)[0] = APIC_ALL_CPUS; +} + +static inline void +default_vector_allocation_domain(int cpu, struct cpumask *retmask) +{ + cpumask_copy(retmask, cpumask_of(cpu)); +} + static inline unsigned long default_check_apicid_used(physid_mask_t *map, int apicid) { return physid_isset(apicid, *map); diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index 55b97ce4fa19..bddc92566d0a 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -36,20 +36,6 @@ static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) return 1; } -static void flat_vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - /* Careful. Some cpus do not strictly honor the set of cpus - * specified in the interrupt destination when using lowest - * priority interrupt delivery mode. - * - * In particular there was a hyperthreading cpu observed to - * deliver interrupts to the wrong hyperthread when only one - * hyperthread was specified in the interrupt desitination. - */ - cpumask_clear(retmask); - cpumask_bits(retmask)[0] = APIC_ALL_CPUS; -} - /* * Set up the logical destination ID. * @@ -257,12 +243,6 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) return 0; } -static void physflat_vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - cpumask_clear(retmask); - cpumask_set_cpu(cpu, retmask); -} - static void physflat_send_IPI_mask(const struct cpumask *cpumask, int vector) { default_send_IPI_mask_sequence_phys(cpumask, vector); @@ -309,7 +289,7 @@ static struct apic apic_physflat = { .check_apicid_used = NULL, .check_apicid_present = NULL, - .vector_allocation_domain = physflat_vector_allocation_domain, + .vector_allocation_domain = default_vector_allocation_domain, /* not needed, but shouldn't hurt: */ .init_apic_ldr = flat_init_apic_ldr, diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index 7c3dd4fe0686..3e43cf528939 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c @@ -104,8 +104,7 @@ static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask) { if (cpu != 0) pr_warning("APIC: Vector allocated for non-BSP cpu\n"); - cpumask_clear(retmask); - cpumask_set_cpu(cpu, retmask); + cpumask_copy(retmask, cpumask_of(cpu)); } static u32 noop_apic_read(u32 reg) diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index dba4bf2ed566..c028132ad358 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -72,12 +72,6 @@ static int numachip_phys_pkg_id(int initial_apic_id, int index_msb) return initial_apic_id >> index_msb; } -static void numachip_vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - cpumask_clear(retmask); - cpumask_set_cpu(cpu, retmask); -} - static int __cpuinit numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip) { union numachip_csr_g3_ext_irq_gen int_gen; @@ -222,7 +216,7 @@ static struct apic apic_numachip __refconst = { .check_apicid_used = NULL, .check_apicid_present = NULL, - .vector_allocation_domain = numachip_vector_allocation_domain, + .vector_allocation_domain = default_vector_allocation_domain, .init_apic_ldr = flat_init_apic_ldr, .ioapic_phys_id_map = NULL, diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index 907aa3d112a6..df342fe4d6aa 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c @@ -142,12 +142,6 @@ static const struct dmi_system_id bigsmp_dmi_table[] = { { } /* NULL entry stops DMI scanning */ }; -static void bigsmp_vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - cpumask_clear(retmask); - cpumask_set_cpu(cpu, retmask); -} - static int probe_bigsmp(void) { if (def_to_bigsmp) @@ -176,7 +170,7 @@ static struct apic apic_bigsmp = { .check_apicid_used = bigsmp_check_apicid_used, .check_apicid_present = bigsmp_check_apicid_present, - .vector_allocation_domain = bigsmp_vector_allocation_domain, + .vector_allocation_domain = default_vector_allocation_domain, .init_apic_ldr = bigsmp_init_apic_ldr, .ioapic_phys_id_map = bigsmp_ioapic_phys_id_map, diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index db4ab1be3c79..3c42865757e2 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -394,21 +394,6 @@ static void es7000_enable_apic_mode(void) WARN(1, "Command failed, status = %x\n", mip_status); } -static void es7000_vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - /* Careful. Some cpus do not strictly honor the set of cpus - * specified in the interrupt destination when using lowest - * priority interrupt delivery mode. - * - * In particular there was a hyperthreading cpu observed to - * deliver interrupts to the wrong hyperthread when only one - * hyperthread was specified in the interrupt desitination. - */ - cpumask_clear(retmask); - cpumask_bits(retmask)[0] = APIC_ALL_CPUS; -} - - static void es7000_wait_for_init_deassert(atomic_t *deassert) { while (!atomic_read(deassert)) @@ -638,7 +623,7 @@ static struct apic __refdata apic_es7000_cluster = { .check_apicid_used = es7000_check_apicid_used, .check_apicid_present = es7000_check_apicid_present, - .vector_allocation_domain = es7000_vector_allocation_domain, + .vector_allocation_domain = flat_vector_allocation_domain, .init_apic_ldr = es7000_init_apic_ldr_cluster, .ioapic_phys_id_map = es7000_ioapic_phys_id_map, @@ -705,7 +690,7 @@ static struct apic __refdata apic_es7000 = { .check_apicid_used = es7000_check_apicid_used, .check_apicid_present = es7000_check_apicid_present, - .vector_allocation_domain = es7000_vector_allocation_domain, + .vector_allocation_domain = flat_vector_allocation_domain, .init_apic_ldr = es7000_init_apic_ldr, .ioapic_phys_id_map = es7000_ioapic_phys_id_map, diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index f00a68cca37a..eb2d466fd81a 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c @@ -441,20 +441,6 @@ static int probe_numaq(void) return found_numaq; } -static void numaq_vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - /* Careful. Some cpus do not strictly honor the set of cpus - * specified in the interrupt destination when using lowest - * priority interrupt delivery mode. - * - * In particular there was a hyperthreading cpu observed to - * deliver interrupts to the wrong hyperthread when only one - * hyperthread was specified in the interrupt desitination. - */ - cpumask_clear(retmask); - cpumask_bits(retmask)[0] = APIC_ALL_CPUS; -} - static void numaq_setup_portio_remap(void) { int num_quads = num_online_nodes(); @@ -491,7 +477,7 @@ static struct apic __refdata apic_numaq = { .check_apicid_used = numaq_check_apicid_used, .check_apicid_present = numaq_check_apicid_present, - .vector_allocation_domain = numaq_vector_allocation_domain, + .vector_allocation_domain = flat_vector_allocation_domain, .init_apic_ldr = numaq_init_apic_ldr, .ioapic_phys_id_map = numaq_ioapic_phys_id_map, diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 71b6ac48ab26..2c6f003b2e4b 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -66,21 +66,6 @@ static void setup_apic_flat_routing(void) #endif } -static void default_vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - /* - * Careful. Some cpus do not strictly honor the set of cpus - * specified in the interrupt destination when using lowest - * priority interrupt delivery mode. - * - * In particular there was a hyperthreading cpu observed to - * deliver interrupts to the wrong hyperthread when only one - * hyperthread was specified in the interrupt desitination. - */ - cpumask_clear(retmask); - cpumask_bits(retmask)[0] = APIC_ALL_CPUS; -} - /* should be called last. */ static int probe_default(void) { @@ -105,7 +90,7 @@ static struct apic apic_default = { .check_apicid_used = default_check_apicid_used, .check_apicid_present = default_check_apicid_present, - .vector_allocation_domain = default_vector_allocation_domain, + .vector_allocation_domain = flat_vector_allocation_domain, .init_apic_ldr = default_init_apic_ldr, .ioapic_phys_id_map = default_ioapic_phys_id_map, diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index 659897c00755..35d254c1fec2 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c @@ -320,20 +320,6 @@ static int probe_summit(void) return 0; } -static void summit_vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - /* Careful. Some cpus do not strictly honor the set of cpus - * specified in the interrupt destination when using lowest - * priority interrupt delivery mode. - * - * In particular there was a hyperthreading cpu observed to - * deliver interrupts to the wrong hyperthread when only one - * hyperthread was specified in the interrupt desitination. - */ - cpumask_clear(retmask); - cpumask_bits(retmask)[0] = APIC_ALL_CPUS; -} - #ifdef CONFIG_X86_SUMMIT_NUMA static struct rio_table_hdr *rio_table_hdr; static struct scal_detail *scal_devs[MAX_NUMNODES]; @@ -509,7 +495,7 @@ static struct apic apic_summit = { .check_apicid_used = summit_check_apicid_used, .check_apicid_present = summit_check_apicid_present, - .vector_allocation_domain = summit_vector_allocation_domain, + .vector_allocation_domain = flat_vector_allocation_domain, .init_apic_ldr = summit_init_apic_ldr, .ioapic_phys_id_map = summit_ioapic_phys_id_map, diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index f730269edef2..f109388a0e80 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -88,15 +88,6 @@ static int x2apic_phys_probe(void) return apic == &apic_x2apic_phys; } -/* - * Each logical cpu is in its own vector allocation domain. - */ -static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - cpumask_clear(retmask); - cpumask_set_cpu(cpu, retmask); -} - static struct apic apic_x2apic_phys = { .name = "physical x2apic", @@ -114,7 +105,7 @@ static struct apic apic_x2apic_phys = { .check_apicid_used = NULL, .check_apicid_present = NULL, - .vector_allocation_domain = x2apic_vector_allocation_domain, + .vector_allocation_domain = default_vector_allocation_domain, .init_apic_ldr = init_x2apic_ldr, .ioapic_phys_id_map = NULL, diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 16efb92bfea5..df89a7d78748 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -185,12 +185,6 @@ EXPORT_SYMBOL_GPL(uv_possible_blades); unsigned long sn_rtc_cycles_per_second; EXPORT_SYMBOL(sn_rtc_cycles_per_second); -static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - cpumask_clear(retmask); - cpumask_set_cpu(cpu, retmask); -} - static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_rip) { #ifdef CONFIG_SMP @@ -363,7 +357,7 @@ static struct apic __refdata apic_x2apic_uv_x = { .check_apicid_used = NULL, .check_apicid_present = NULL, - .vector_allocation_domain = uv_vector_allocation_domain, + .vector_allocation_domain = default_vector_allocation_domain, .init_apic_ldr = uv_init_apic_ldr, .ioapic_phys_id_map = NULL, -- cgit v1.2.3 From 1bccd58bfffc5a677051937b332b71f0686187c1 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 7 Jun 2012 15:15:15 +0200 Subject: x86/apic: Try to spread IRQ vectors to different priority levels When assigning a new vector it is primarially done by adding 8 to the previously given out vector number. Hence, two consequently allocated vector numbers would likely fall into the same priority level. Try to spread vector numbers to different priority levels better by changing the step from 8 to 16. Signed-off-by: Alexander Gordeev Acked-by: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120607131514.GD4759@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic/io_apic.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 74c569791e75..05af3d341aaa 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1112,7 +1112,7 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask) * 0x80, because int 0x80 is hm, kind of importantish. ;) */ static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START; - static int current_offset = VECTOR_OFFSET_START % 8; + static int current_offset = VECTOR_OFFSET_START % 16; unsigned int old_vector; int cpu, err; cpumask_var_t tmp_mask; @@ -1148,10 +1148,9 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask) vector = current_vector; offset = current_offset; next: - vector += 8; + vector += 16; if (vector >= first_system_vector) { - /* If out of vectors on large boxen, must share them. */ - offset = (offset + 1) % 8; + offset = (offset + 1) % 16; vector = FIRST_EXTERNAL_VECTOR + offset; } if (unlikely(current_vector == vector)) -- cgit v1.2.3 From 8637e38aff14d048b649075114023023a2e80fba Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 7 Jun 2012 15:15:44 +0200 Subject: x86/apic: Avoid useless scanning thru a cpumask in assign_irq_vector() In case of static vector allocation domains (i.e. flat) if all vector numbers are exhausted, an attempt to assign a new vector will lead to useless scans through all CPUs in the cpumask, even though it is known that each new pass would fail. Make this corner case less painful by letting report whether the vector allocation domain depends on passed arguments or not and stop scanning early. The same could have been achived by introducing a static flag to the apic operations. But let's allow vector_allocation_domain() have more intelligence here and decide dynamically, in case we would need it in the future. Signed-off-by: Alexander Gordeev Acked-by: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120607131542.GE4759@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apic.h | 8 +++++--- arch/x86/kernel/apic/apic_noop.c | 3 ++- arch/x86/kernel/apic/io_apic.c | 12 +++++++++--- 3 files changed, 16 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index feb2dbdae9ec..e3fecd50d5ca 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -306,7 +306,7 @@ struct apic { unsigned long (*check_apicid_used)(physid_mask_t *map, int apicid); unsigned long (*check_apicid_present)(int apicid); - void (*vector_allocation_domain)(int cpu, struct cpumask *retmask); + bool (*vector_allocation_domain)(int cpu, struct cpumask *retmask); void (*init_apic_ldr)(void); void (*ioapic_phys_id_map)(physid_mask_t *phys_map, physid_mask_t *retmap); @@ -615,7 +615,7 @@ extern unsigned int default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, const struct cpumask *andmask); -static inline void +static inline bool flat_vector_allocation_domain(int cpu, struct cpumask *retmask) { /* Careful. Some cpus do not strictly honor the set of cpus @@ -628,12 +628,14 @@ flat_vector_allocation_domain(int cpu, struct cpumask *retmask) */ cpumask_clear(retmask); cpumask_bits(retmask)[0] = APIC_ALL_CPUS; + return false; } -static inline void +static inline bool default_vector_allocation_domain(int cpu, struct cpumask *retmask) { cpumask_copy(retmask, cpumask_of(cpu)); + return true; } static inline unsigned long default_check_apicid_used(physid_mask_t *map, int apicid) diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index 3e43cf528939..ac9edf247b15 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c @@ -100,11 +100,12 @@ static unsigned long noop_check_apicid_present(int bit) return physid_isset(bit, phys_cpu_present_map); } -static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask) +static bool noop_vector_allocation_domain(int cpu, struct cpumask *retmask) { if (cpu != 0) pr_warning("APIC: Vector allocated for non-BSP cpu\n"); cpumask_copy(retmask, cpumask_of(cpu)); + return true; } static u32 noop_apic_read(u32 reg) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 05af3d341aaa..4061a7dee5c9 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1137,8 +1137,9 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask) for_each_cpu_and(cpu, mask, cpu_online_mask) { int new_cpu; int vector, offset; + bool more_domains; - apic->vector_allocation_domain(cpu, tmp_mask); + more_domains = apic->vector_allocation_domain(cpu, tmp_mask); if (cpumask_subset(tmp_mask, cfg->domain)) { free_cpumask_var(tmp_mask); @@ -1153,8 +1154,13 @@ next: offset = (offset + 1) % 16; vector = FIRST_EXTERNAL_VECTOR + offset; } - if (unlikely(current_vector == vector)) - continue; + + if (unlikely(current_vector == vector)) { + if (more_domains) + continue; + else + break; + } if (test_bit(vector, used_vectors)) goto next; -- cgit v1.2.3 From ff164324123c0fe181d8de7dadcc7b3fbe25f2cf Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 7 Jun 2012 15:15:59 +0200 Subject: x86/apic: Make cpu_mask_to_apicid() operations return error code Current cpu_mask_to_apicid() and cpu_mask_to_apicid_and() implementations have few shortcomings: 1. A value returned by cpu_mask_to_apicid() is written to hardware registers unconditionally. Should BAD_APICID get ever returned it will be written to a hardware too. But the value of BAD_APICID is not universal across all hardware in all modes and might cause unexpected results, i.e. interrupts might get routed to CPUs that are not configured to receive it. 2. Because the value of BAD_APICID is not universal it is counter- intuitive to return it for a hardware where it does not make sense (i.e. x2apic). 3. cpu_mask_to_apicid_and() operation is thought as an complement to cpu_mask_to_apicid() that only applies a AND mask on top of a cpumask being passed. Yet, as consequence of 18374d8 commit the two operations are inconsistent in that of: cpu_mask_to_apicid() should not get a offline CPU with the cpumask cpu_mask_to_apicid_and() should not fail and return BAD_APICID These limitations are impossible to realize just from looking at the operations prototypes. Most of these shortcomings are resolved by returning a error code instead of BAD_APICID. As the result, faults are reported back early rather than possibilities to cause a unexpected behaviour exist (in case of [1]). The only exception is setup_timer_IRQ0_pin() routine. Although obviously controversial to this fix, its existing behaviour is preserved to not break the fragile check_timer() and would better addressed in a separate fix. Signed-off-by: Alexander Gordeev Acked-by: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120607131559.GF4759@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apic.h | 44 ++++++++++++------ arch/x86/kernel/apic/apic.c | 33 +++++++------ arch/x86/kernel/apic/es7000_32.c | 21 +++++---- arch/x86/kernel/apic/io_apic.c | 88 +++++++++++++++++++++++------------ arch/x86/kernel/apic/numaq_32.c | 14 ++++-- arch/x86/kernel/apic/summit_32.c | 22 +++++---- arch/x86/kernel/apic/x2apic_cluster.c | 24 ++++++---- arch/x86/kernel/apic/x2apic_uv_x.c | 27 +++++++---- arch/x86/platform/uv/uv_irq.c | 7 ++- drivers/iommu/intel_irq_remapping.c | 13 ++++-- 10 files changed, 188 insertions(+), 105 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index e3fecd50d5ca..ae91f9c7e360 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -331,9 +331,11 @@ struct apic { unsigned long (*set_apic_id)(unsigned int id); unsigned long apic_id_mask; - unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask); - unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, - const struct cpumask *andmask); + int (*cpu_mask_to_apicid)(const struct cpumask *cpumask, + unsigned int *apicid); + int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, + const struct cpumask *andmask, + unsigned int *apicid); /* ipi */ void (*send_IPI_mask)(const struct cpumask *mask, int vector); @@ -591,29 +593,45 @@ static inline int default_phys_pkg_id(int cpuid_apic, int index_msb) #endif -static inline unsigned int -flat_cpu_mask_to_apicid(const struct cpumask *cpumask) +static inline int +__flat_cpu_mask_to_apicid(unsigned long cpu_mask, unsigned int *apicid) { - return cpumask_bits(cpumask)[0] & APIC_ALL_CPUS; + cpu_mask &= APIC_ALL_CPUS; + if (likely(cpu_mask)) { + *apicid = (unsigned int)cpu_mask; + return 0; + } else { + return -EINVAL; + } } -static inline unsigned int +static inline int +flat_cpu_mask_to_apicid(const struct cpumask *cpumask, + unsigned int *apicid) +{ + return __flat_cpu_mask_to_apicid(cpumask_bits(cpumask)[0], apicid); +} + +static inline int flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) + const struct cpumask *andmask, + unsigned int *apicid) { unsigned long mask1 = cpumask_bits(cpumask)[0]; unsigned long mask2 = cpumask_bits(andmask)[0]; unsigned long mask3 = cpumask_bits(cpu_online_mask)[0]; - return (unsigned int)(mask1 & mask2 & mask3); + return __flat_cpu_mask_to_apicid(mask1 & mask2 & mask3, apicid); } -extern unsigned int -default_cpu_mask_to_apicid(const struct cpumask *cpumask); +extern int +default_cpu_mask_to_apicid(const struct cpumask *cpumask, + unsigned int *apicid); -extern unsigned int +extern int default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask); + const struct cpumask *andmask, + unsigned int *apicid); static inline bool flat_vector_allocation_domain(int cpu, struct cpumask *retmask) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 96a2608252f1..b8d92606f84f 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -2123,24 +2123,26 @@ void default_init_apic_ldr(void) apic_write(APIC_LDR, val); } -unsigned int default_cpu_mask_to_apicid(const struct cpumask *cpumask) +static inline int __default_cpu_to_apicid(int cpu, unsigned int *apicid) { - int cpu; - - /* - * We're using fixed IRQ delivery, can only return one phys APIC ID. - * May as well be the first. - */ - cpu = cpumask_first(cpumask); - if (likely((unsigned)cpu < nr_cpu_ids)) - return per_cpu(x86_cpu_to_apicid, cpu); + if (likely((unsigned int)cpu < nr_cpu_ids)) { + *apicid = per_cpu(x86_cpu_to_apicid, cpu); + return 0; + } else { + return -EINVAL; + } +} - return BAD_APICID; +int default_cpu_mask_to_apicid(const struct cpumask *cpumask, + unsigned int *apicid) +{ + int cpu = cpumask_first(cpumask); + return __default_cpu_to_apicid(cpu, apicid); } -unsigned int -default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) +int default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask, + unsigned int *apicid) { int cpu; @@ -2148,7 +2150,8 @@ default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, if (cpumask_test_cpu(cpu, cpu_online_mask)) break; } - return per_cpu(x86_cpu_to_apicid, cpu); + + return __default_cpu_to_apicid(cpu, apicid); } /* diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 3c42865757e2..515ebb00a9fc 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -525,7 +525,8 @@ static int es7000_check_phys_apicid_present(int cpu_physical_apicid) return 1; } -static unsigned int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask) +static int +es7000_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) { unsigned int round = 0; int cpu, uninitialized_var(apicid); @@ -539,31 +540,33 @@ static unsigned int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask) if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { WARN(1, "Not a valid mask!"); - return BAD_APICID; + return -EINVAL; } apicid = new_apicid; round++; } - return apicid; + *dest_id = apicid; + return 0; } -static unsigned int +static int es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask, - const struct cpumask *andmask) + const struct cpumask *andmask, + unsigned int *apicid) { - int apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); + *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); cpumask_var_t cpumask; if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) - return apicid; + return 0; cpumask_and(cpumask, inmask, andmask); cpumask_and(cpumask, cpumask, cpu_online_mask); - apicid = es7000_cpu_mask_to_apicid(cpumask); + es7000_cpu_mask_to_apicid(cpumask, apicid); free_cpumask_var(cpumask); - return apicid; + return 0; } static int es7000_phys_pkg_id(int cpuid_apic, int index_msb) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 4061a7dee5c9..0deb773404e5 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1359,7 +1359,14 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg, if (assign_irq_vector(irq, cfg, apic->target_cpus())) return; - dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); + if (apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus(), + &dest)) { + pr_warn("Failed to obtain apicid for ioapic %d, pin %d\n", + mpc_ioapic_id(attr->ioapic), attr->ioapic_pin); + __clear_irq_vector(irq, cfg); + + return; + } apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> " @@ -1474,6 +1481,7 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx, unsigned int pin, int vector) { struct IO_APIC_route_entry entry; + unsigned int dest; if (irq_remapping_enabled) return; @@ -1484,9 +1492,12 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx, * We use logical delivery to get the timer IRQ * to the first CPU. */ + if (unlikely(apic->cpu_mask_to_apicid(apic->target_cpus(), &dest))) + dest = BAD_APICID; + entry.dest_mode = apic->irq_dest_mode; entry.mask = 0; /* don't mask IRQ for edge */ - entry.dest = apic->cpu_mask_to_apicid(apic->target_cpus()); + entry.dest = dest; entry.delivery_mode = apic->irq_delivery_mode; entry.polarity = 0; entry.trigger = 0; @@ -2245,16 +2256,25 @@ int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, unsigned int *dest_id) { struct irq_cfg *cfg = data->chip_data; + unsigned int irq = data->irq; + int err; if (!cpumask_intersects(mask, cpu_online_mask)) - return -1; + return -EINVAL; - if (assign_irq_vector(data->irq, data->chip_data, mask)) - return -1; + err = assign_irq_vector(irq, cfg, mask); + if (err) + return err; + + err = apic->cpu_mask_to_apicid_and(mask, cfg->domain, dest_id); + if (err) { + if (assign_irq_vector(irq, cfg, data->affinity)) + pr_err("Failed to recover vector for irq %d\n", irq); + return err; + } cpumask_copy(data->affinity, mask); - *dest_id = apic->cpu_mask_to_apicid_and(mask, cfg->domain); return 0; } @@ -3040,7 +3060,10 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, if (err) return err; - dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); + err = apic->cpu_mask_to_apicid_and(cfg->domain, + apic->target_cpus(), &dest); + if (err) + return err; if (irq_remapped(cfg)) { compose_remapped_msi_msg(pdev, irq, dest, msg, hpet_id); @@ -3361,6 +3384,8 @@ static struct irq_chip ht_irq_chip = { int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) { struct irq_cfg *cfg; + struct ht_irq_msg msg; + unsigned dest; int err; if (disable_apic) @@ -3368,36 +3393,37 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) cfg = irq_cfg(irq); err = assign_irq_vector(irq, cfg, apic->target_cpus()); - if (!err) { - struct ht_irq_msg msg; - unsigned dest; + if (err) + return err; - dest = apic->cpu_mask_to_apicid_and(cfg->domain, - apic->target_cpus()); + err = apic->cpu_mask_to_apicid_and(cfg->domain, + apic->target_cpus(), &dest); + if (err) + return err; - msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); + msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); - msg.address_lo = - HT_IRQ_LOW_BASE | - HT_IRQ_LOW_DEST_ID(dest) | - HT_IRQ_LOW_VECTOR(cfg->vector) | - ((apic->irq_dest_mode == 0) ? - HT_IRQ_LOW_DM_PHYSICAL : - HT_IRQ_LOW_DM_LOGICAL) | - HT_IRQ_LOW_RQEOI_EDGE | - ((apic->irq_delivery_mode != dest_LowestPrio) ? - HT_IRQ_LOW_MT_FIXED : - HT_IRQ_LOW_MT_ARBITRATED) | - HT_IRQ_LOW_IRQ_MASKED; + msg.address_lo = + HT_IRQ_LOW_BASE | + HT_IRQ_LOW_DEST_ID(dest) | + HT_IRQ_LOW_VECTOR(cfg->vector) | + ((apic->irq_dest_mode == 0) ? + HT_IRQ_LOW_DM_PHYSICAL : + HT_IRQ_LOW_DM_LOGICAL) | + HT_IRQ_LOW_RQEOI_EDGE | + ((apic->irq_delivery_mode != dest_LowestPrio) ? + HT_IRQ_LOW_MT_FIXED : + HT_IRQ_LOW_MT_ARBITRATED) | + HT_IRQ_LOW_IRQ_MASKED; - write_ht_irq_msg(irq, &msg); + write_ht_irq_msg(irq, &msg); - irq_set_chip_and_handler_name(irq, &ht_irq_chip, - handle_edge_irq, "edge"); + irq_set_chip_and_handler_name(irq, &ht_irq_chip, + handle_edge_irq, "edge"); - dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq); - } - return err; + dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq); + + return 0; } #endif /* CONFIG_HT_IRQ */ diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index eb2d466fd81a..2b55514c328b 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c @@ -406,16 +406,20 @@ static inline int numaq_check_phys_apicid_present(int phys_apicid) * We use physical apicids here, not logical, so just return the default * physical broadcast to stop people from breaking us */ -static unsigned int numaq_cpu_mask_to_apicid(const struct cpumask *cpumask) +static int +numaq_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) { - return 0x0F; + *apicid = 0x0F; + return 0; } -static inline unsigned int +static int numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) + const struct cpumask *andmask, + unsigned int *apicid) { - return 0x0F; + *apicid = 0x0F; + return 0; } /* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */ diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index 35d254c1fec2..5766d84f12d6 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c @@ -263,7 +263,8 @@ static int summit_check_phys_apicid_present(int physical_apicid) return 1; } -static unsigned int summit_cpu_mask_to_apicid(const struct cpumask *cpumask) +static int +summit_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) { unsigned int round = 0; int cpu, apicid = 0; @@ -276,30 +277,33 @@ static unsigned int summit_cpu_mask_to_apicid(const struct cpumask *cpumask) if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { printk("%s: Not a valid mask!\n", __func__); - return BAD_APICID; + return -EINVAL; } apicid |= new_apicid; round++; } - return apicid; + *dest_id = apicid; + return 0; } -static unsigned int summit_cpu_mask_to_apicid_and(const struct cpumask *inmask, - const struct cpumask *andmask) +static int +summit_cpu_mask_to_apicid_and(const struct cpumask *inmask, + const struct cpumask *andmask, + unsigned int *apicid) { - int apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); + *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); cpumask_var_t cpumask; if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) - return apicid; + return 0; cpumask_and(cpumask, inmask, andmask); cpumask_and(cpumask, cpumask, cpu_online_mask); - apicid = summit_cpu_mask_to_apicid(cpumask); + summit_cpu_mask_to_apicid(cpumask, apicid); free_cpumask_var(cpumask); - return apicid; + return 0; } /* diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 612622c47dfb..5f86f79335f4 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -96,24 +96,26 @@ static void x2apic_send_IPI_all(int vector) __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC); } -static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask) +static int +x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) { int cpu = cpumask_first(cpumask); - u32 dest = 0; int i; - if (cpu > nr_cpu_ids) - return BAD_APICID; + if (cpu >= nr_cpu_ids) + return -EINVAL; + *apicid = 0; for_each_cpu_and(i, cpumask, per_cpu(cpus_in_cluster, cpu)) - dest |= per_cpu(x86_cpu_to_logical_apicid, i); + *apicid |= per_cpu(x86_cpu_to_logical_apicid, i); - return dest; + return 0; } -static unsigned int +static int x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) + const struct cpumask *andmask, + unsigned int *apicid) { u32 dest = 0; u16 cluster; @@ -128,7 +130,7 @@ x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, } if (!dest) - return BAD_APICID; + return -EINVAL; for_each_cpu_and(i, cpumask, andmask) { if (!cpumask_test_cpu(i, cpu_online_mask)) @@ -138,7 +140,9 @@ x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, dest |= per_cpu(x86_cpu_to_logical_apicid, i); } - return dest; + *apicid = dest; + + return 0; } static void init_x2apic_ldr(void) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index df89a7d78748..2f3030fef31e 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -269,23 +269,31 @@ static void uv_init_apic_ldr(void) { } -static unsigned int uv_cpu_mask_to_apicid(const struct cpumask *cpumask) +static inline int __uv_cpu_to_apicid(int cpu, unsigned int *apicid) +{ + if (likely((unsigned int)cpu < nr_cpu_ids)) { + *apicid = per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits; + return 0; + } else { + return -EINVAL; + } +} + +static int +uv_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) { /* * We're using fixed IRQ delivery, can only return one phys APIC ID. * May as well be the first. */ int cpu = cpumask_first(cpumask); - - if ((unsigned)cpu < nr_cpu_ids) - return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits; - else - return BAD_APICID; + return __uv_cpu_to_apicid(cpu, apicid); } -static unsigned int +static int uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) + const struct cpumask *andmask, + unsigned int *apicid) { int cpu; @@ -297,7 +305,8 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, if (cpumask_test_cpu(cpu, cpu_online_mask)) break; } - return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits; + + return __uv_cpu_to_apicid(cpu, apicid); } static unsigned int x2apic_get_apic_id(unsigned long x) diff --git a/arch/x86/platform/uv/uv_irq.c b/arch/x86/platform/uv/uv_irq.c index f25c2765a5c9..dd1ff39a464c 100644 --- a/arch/x86/platform/uv/uv_irq.c +++ b/arch/x86/platform/uv/uv_irq.c @@ -135,6 +135,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, unsigned long mmr_value; struct uv_IO_APIC_route_entry *entry; int mmr_pnode, err; + unsigned int dest; BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long)); @@ -143,6 +144,10 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, if (err != 0) return err; + err = apic->cpu_mask_to_apicid(eligible_cpu, &dest); + if (err != 0) + return err; + if (limit == UV_AFFINITY_CPU) irq_set_status_flags(irq, IRQ_NO_BALANCING); else @@ -159,7 +164,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, entry->polarity = 0; entry->trigger = 0; entry->mask = 0; - entry->dest = apic->cpu_mask_to_apicid(eligible_cpu); + entry->dest = dest; mmr_pnode = uv_blade_to_pnode(mmr_blade); uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value); diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 6d347064b8b0..dafbad06390a 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -924,6 +924,7 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, struct irq_cfg *cfg = data->chip_data; unsigned int dest, irq = data->irq; struct irte irte; + int err; if (!cpumask_intersects(mask, cpu_online_mask)) return -EINVAL; @@ -931,10 +932,16 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, if (get_irte(irq, &irte)) return -EBUSY; - if (assign_irq_vector(irq, cfg, mask)) - return -EBUSY; + err = assign_irq_vector(irq, cfg, mask); + if (err) + return err; - dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask); + err = apic->cpu_mask_to_apicid_and(cfg->domain, mask, &dest); + if (err) { + if (assign_irq_vector(irq, cfg, data->affinity)); + pr_err("Failed to recover vector for irq %d\n", irq); + return err; + } irte.vector = cfg->vector; irte.dest_id = IRTE_DEST(dest); -- cgit v1.2.3 From 4988a40c3981212fa8c64da68722affc1cb6697a Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 7 Jun 2012 15:16:25 +0200 Subject: x86/apic: Make cpu_mask_to_apicid() operations check cpu_online_mask Currently cpu_mask_to_apicid() should not get a offline CPU with the cpumask. Otherwise some apic drivers might try to access non-existent per-cpu variables (i.e. x2apic). In that regard cpu_mask_to_apicid() and cpu_mask_to_apicid_and() operations are inconsistent. This fix makes the two operations do not rely on calling functions and always return the apicid for only online CPUs. As result, the meaning and implementations of cpu_mask_to_apicid() and cpu_mask_to_apicid_and() operations become straight. Signed-off-by: Alexander Gordeev Acked-by: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120607131624.GG4759@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apic.h | 6 ++---- arch/x86/kernel/apic/apic.c | 2 +- arch/x86/kernel/apic/es7000_32.c | 3 +-- arch/x86/kernel/apic/summit_32.c | 3 +-- arch/x86/kernel/apic/x2apic_cluster.c | 2 +- arch/x86/kernel/apic/x2apic_uv_x.c | 2 +- 6 files changed, 7 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index ae91f9c7e360..1ed3eead2039 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -596,7 +596,7 @@ static inline int default_phys_pkg_id(int cpuid_apic, int index_msb) static inline int __flat_cpu_mask_to_apicid(unsigned long cpu_mask, unsigned int *apicid) { - cpu_mask &= APIC_ALL_CPUS; + cpu_mask = cpu_mask & APIC_ALL_CPUS & cpumask_bits(cpu_online_mask)[0]; if (likely(cpu_mask)) { *apicid = (unsigned int)cpu_mask; return 0; @@ -619,9 +619,7 @@ flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, { unsigned long mask1 = cpumask_bits(cpumask)[0]; unsigned long mask2 = cpumask_bits(andmask)[0]; - unsigned long mask3 = cpumask_bits(cpu_online_mask)[0]; - - return __flat_cpu_mask_to_apicid(mask1 & mask2 & mask3, apicid); + return __flat_cpu_mask_to_apicid(mask1 & mask2, apicid); } extern int diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index b8d92606f84f..7e9bbe73bc5a 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -2136,7 +2136,7 @@ static inline int __default_cpu_to_apicid(int cpu, unsigned int *apicid) int default_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) { - int cpu = cpumask_first(cpumask); + int cpu = cpumask_first_and(cpumask, cpu_online_mask); return __default_cpu_to_apicid(cpu, apicid); } diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 515ebb00a9fc..b35cfb9b6962 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -534,7 +534,7 @@ es7000_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) /* * The cpus in the mask must all be on the apic cluster. */ - for_each_cpu(cpu, cpumask) { + for_each_cpu_and(cpu, cpumask, cpu_online_mask) { int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu); if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { @@ -561,7 +561,6 @@ es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask, return 0; cpumask_and(cpumask, inmask, andmask); - cpumask_and(cpumask, cpumask, cpu_online_mask); es7000_cpu_mask_to_apicid(cpumask, apicid); free_cpumask_var(cpumask); diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index 5766d84f12d6..79d360f6729e 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c @@ -272,7 +272,7 @@ summit_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) /* * The cpus in the mask must all be on the apic cluster. */ - for_each_cpu(cpu, cpumask) { + for_each_cpu_and(cpu, cpumask, cpu_online_mask) { int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu); if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { @@ -298,7 +298,6 @@ summit_cpu_mask_to_apicid_and(const struct cpumask *inmask, return 0; cpumask_and(cpumask, inmask, andmask); - cpumask_and(cpumask, cpumask, cpu_online_mask); summit_cpu_mask_to_apicid(cpumask, apicid); free_cpumask_var(cpumask); diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 5f86f79335f4..23a46cf5b6fd 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -99,7 +99,7 @@ static void x2apic_send_IPI_all(int vector) static int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) { - int cpu = cpumask_first(cpumask); + int cpu = cpumask_first_and(cpumask, cpu_online_mask); int i; if (cpu >= nr_cpu_ids) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 2f3030fef31e..307aa076bd62 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -286,7 +286,7 @@ uv_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) * We're using fixed IRQ delivery, can only return one phys APIC ID. * May as well be the first. */ - int cpu = cpumask_first(cpumask); + int cpu = cpumask_first_and(cpumask, cpu_online_mask); return __uv_cpu_to_apicid(cpu, apicid); } -- cgit v1.2.3 From 7eb9ba5ed312ec6ed9d22259c5da1acb7cf4bd29 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Fri, 8 Jun 2012 15:02:57 +0530 Subject: uprobes: Pass probed vaddr to arch_uprobe_analyze_insn() On RISC architectures like powerpc, instructions are fixed size. Instruction analysis on such platforms is just a matter of (insn % 4). Pass the vaddr at which the uprobe is to be inserted so that arch_uprobe_analyze_insn() can flag misaligned registration requests. Signed-off-by: Ananth N Mavinakaynahalli Cc: michael@ellerman.id.au Cc: antonb@thinktux.localdomain Cc: Paul Mackerras Cc: benh@kernel.crashing.org Cc: peterz@infradead.org Cc: Srikar Dronamraju Cc: Jim Keniston Cc: oleg@redhat.com Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/20120608093257.GG13409@in.ibm.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/uprobes.h | 2 +- arch/x86/kernel/uprobes.c | 3 ++- kernel/events/uprobes.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h index 1e9bed14f7ae..f3971bbcd1de 100644 --- a/arch/x86/include/asm/uprobes.h +++ b/arch/x86/include/asm/uprobes.h @@ -48,7 +48,7 @@ struct arch_uprobe_task { #endif }; -extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm); +extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs); extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs); extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk); diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index dc4e910a7d96..36fd42091fa7 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -409,9 +409,10 @@ static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, * arch_uprobe_analyze_insn - instruction analysis including validity and fixups. * @mm: the probed address space. * @arch_uprobe: the probepoint information. + * @addr: virtual address at which to install the probepoint * Return 0 on success or a -ve number on error. */ -int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm) +int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) { int ret; struct insn insn; diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 8c5e043cd309..b52376d02332 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -706,7 +706,7 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) return -EEXIST; - ret = arch_uprobe_analyze_insn(&uprobe->arch, mm); + ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, addr); if (ret) return ret; -- cgit v1.2.3 From c7d65a78fc18ed70353baeb7497ec71a7c775ac5 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 7 Jun 2012 11:03:00 -0400 Subject: x86: Remove cmpxchg from i386 NMI nesting code I've been informed by someone on LWN called 'slashdot' that some i386 machines do not support a true cmpxchg. The cmpxchg used by the i386 NMI nesting code must be a true cmpxchg as disabling interrupts will not work for NMIs (which is the work around for i386s that do not have a true cmpxchg). This 'slashdot' character also suggested a fix to the issue. As the state of the nesting NMIs goes as follows: NOT_RUNNING -> EXECUTING EXECUTING -> NOT_RUNNING EXECUTING -> LATCHED LATCHED -> EXECUTING Having these states as enum values of: NOT_RUNNING = 0 EXECUTING = 1 LATCHED = 2 Instead of a cmpxchg to make EXECUTING -> NOT_RUNNING a dec_and_test() would work as well. If the dec_and_test brings the state to NOT_RUNNING, that is the same as a cmpxchg succeeding to change EXECUTING to NOT_RUNNING. If a nested NMI were to come in and change it to LATCHED, the dec_and_test() would convert the state to EXECUTING (what we want it to be in such a case anyway). I asked 'slashdot' to post this as a patch, but it never came to be. I decided to do the work instead. Thanks to H. Peter Anvin for suggesting to use this_cpu_dec_and_return() instead of local_dec_and_test(&__get_cpu_var()). Link: http://lwn.net/Articles/484932/ Cc: H. Peter Anvin Signed-off-by: Steven Rostedt --- arch/x86/kernel/nmi.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index a0b2f84457be..a15a88800661 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -365,8 +365,9 @@ static __kprobes void default_do_nmi(struct pt_regs *regs) #ifdef CONFIG_X86_32 /* * For i386, NMIs use the same stack as the kernel, and we can - * add a workaround to the iret problem in C. Simply have 3 states - * the NMI can be in. + * add a workaround to the iret problem in C (preventing nested + * NMIs if an NMI takes a trap). Simply have 3 states the NMI + * can be in: * * 1) not running * 2) executing @@ -383,13 +384,20 @@ static __kprobes void default_do_nmi(struct pt_regs *regs) * If an NMI hits a breakpoint that executes an iret, another * NMI can preempt it. We do not want to allow this new NMI * to run, but we want to execute it when the first one finishes. - * We set the state to "latched", and the first NMI will perform - * an cmpxchg on the state, and if it doesn't successfully - * reset the state to "not running" it will restart the next - * NMI. + * We set the state to "latched", and the exit of the first NMI will + * perform a dec_return, if the result is zero (NOT_RUNNING), then + * it will simply exit the NMI handler. If not, the dec_return + * would have set the state to NMI_EXECUTING (what we want it to + * be when we are running). In this case, we simply jump back + * to rerun the NMI handler again, and restart the 'latched' NMI. + * + * No trap (breakpoint or page fault) should be hit before nmi_restart, + * thus there is no race between the first check of state for NOT_RUNNING + * and setting it to NMI_EXECUTING. The HW will prevent nested NMIs + * at this point. */ enum nmi_states { - NMI_NOT_RUNNING, + NMI_NOT_RUNNING = 0, NMI_EXECUTING, NMI_LATCHED, }; @@ -397,18 +405,17 @@ static DEFINE_PER_CPU(enum nmi_states, nmi_state); #define nmi_nesting_preprocess(regs) \ do { \ - if (__get_cpu_var(nmi_state) != NMI_NOT_RUNNING) { \ - __get_cpu_var(nmi_state) = NMI_LATCHED; \ + if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) { \ + this_cpu_write(nmi_state, NMI_LATCHED); \ return; \ } \ - nmi_restart: \ - __get_cpu_var(nmi_state) = NMI_EXECUTING; \ - } while (0) + this_cpu_write(nmi_state, NMI_EXECUTING); \ + } while (0); \ + nmi_restart: #define nmi_nesting_postprocess() \ do { \ - if (cmpxchg(&__get_cpu_var(nmi_state), \ - NMI_EXECUTING, NMI_NOT_RUNNING) != NMI_EXECUTING) \ + if (this_cpu_dec_return(nmi_state)) \ goto nmi_restart; \ } while (0) #else /* x86_64 */ -- cgit v1.2.3 From 70fb74a5420f9caa3e001d65004e4b669124283e Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 7 Jun 2012 11:54:37 -0400 Subject: x86: Save cr2 in NMI in case NMIs take a page fault (for i386) Avi Kivity reported that page faults in NMIs could cause havic if the NMI preempted another page fault handler: The recent changes to NMI allow exceptions to take place in NMI handlers, but I think that a #PF (say, due to access to vmalloc space) is still problematic. Consider the sequence #PF (cr2 set by processor) NMI ... #PF (cr2 clobbered) do_page_fault() IRET ... IRET do_page_fault() address = read_cr2() The last line reads the overwritten cr2 value. This is the i386 version, which has the luxury of doing the work in C code. Link: http://lkml.kernel.org/r/4FBB8C40.6080304@redhat.com Reported-by: Avi Kivity Cc: Linus Torvalds Cc: H. Peter Anvin Cc: Thomas Gleixner Signed-off-by: Steven Rostedt --- arch/x86/kernel/nmi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index a15a88800661..f84f5c57de35 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -395,6 +395,14 @@ static __kprobes void default_do_nmi(struct pt_regs *regs) * thus there is no race between the first check of state for NOT_RUNNING * and setting it to NMI_EXECUTING. The HW will prevent nested NMIs * at this point. + * + * In case the NMI takes a page fault, we need to save off the CR2 + * because the NMI could have preempted another page fault and corrupt + * the CR2 that is about to be read. As nested NMIs must be restarted + * and they can not take breakpoints or page faults, the update of the + * CR2 must be done before converting the nmi state back to NOT_RUNNING. + * Otherwise, there would be a race of another nested NMI coming in + * after setting state to NOT_RUNNING but before updating the nmi_cr2. */ enum nmi_states { NMI_NOT_RUNNING = 0, @@ -402,6 +410,7 @@ enum nmi_states { NMI_LATCHED, }; static DEFINE_PER_CPU(enum nmi_states, nmi_state); +static DEFINE_PER_CPU(unsigned long, nmi_cr2); #define nmi_nesting_preprocess(regs) \ do { \ @@ -410,11 +419,14 @@ static DEFINE_PER_CPU(enum nmi_states, nmi_state); return; \ } \ this_cpu_write(nmi_state, NMI_EXECUTING); \ + this_cpu_write(nmi_cr2, read_cr2()); \ } while (0); \ nmi_restart: #define nmi_nesting_postprocess() \ do { \ + if (unlikely(this_cpu_read(nmi_cr2) != read_cr2())) \ + write_cr2(this_cpu_read(nmi_cr2)); \ if (this_cpu_dec_return(nmi_state)) \ goto nmi_restart; \ } while (0) -- cgit v1.2.3 From 056c78d3a28ab7c8438b42f4d0915030ca8f51b9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 9 Jan 2012 11:42:39 +0100 Subject: ARM: nomadik: register GPIOs dynamically Register the NHK8815 GPIO devices dynamically like the Ux500 does it. Acked-by: Arnd Bergmann Signed-off-by: Linus Walleij --- arch/arm/mach-nomadik/cpu-8815.c | 114 ++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 67 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index 27f43a46985e..b79b3846935a 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -35,86 +35,66 @@ #include "clock.h" #include "cpu-8815.h" -#define __MEM_4K_RESOURCE(x) \ - .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} - -/* The 8815 has 4 GPIO blocks, let's register them immediately */ - -#define GPIO_RESOURCE(block) \ - { \ - .start = NOMADIK_GPIO##block##_BASE, \ - .end = NOMADIK_GPIO##block##_BASE + SZ_4K - 1, \ - .flags = IORESOURCE_MEM, \ - }, \ - { \ - .start = IRQ_GPIO##block, \ - .end = IRQ_GPIO##block, \ - .flags = IORESOURCE_IRQ, \ - } - -#define GPIO_DEVICE(block) \ - { \ - .name = "gpio", \ - .id = block, \ - .num_resources = 2, \ - .resource = &cpu8815_gpio_resources[block * 2], \ - .dev = { \ - .platform_data = &cpu8815_gpio[block], \ - }, \ - } +static AMBA_APB_DEVICE(cpu8815_amba_rng, "rng", 0, NOMADIK_RNG_BASE, { }, NULL); -static struct nmk_gpio_platform_data cpu8815_gpio[] = { - { - .name = "GPIO-0-31", - .first_gpio = 0, - .first_irq = NOMADIK_GPIO_TO_IRQ(0), - }, { - .name = "GPIO-32-63", - .first_gpio = 32, - .first_irq = NOMADIK_GPIO_TO_IRQ(32), - }, { - .name = "GPIO-64-95", - .first_gpio = 64, - .first_irq = NOMADIK_GPIO_TO_IRQ(64), - }, { - .name = "GPIO-96-127", /* 124..127 not routed to pin */ - .first_gpio = 96, - .first_irq = NOMADIK_GPIO_TO_IRQ(96), - } +static struct amba_device *amba_devs[] __initdata = { + &cpu8815_amba_rng_device }; -static struct resource cpu8815_gpio_resources[] = { - GPIO_RESOURCE(0), - GPIO_RESOURCE(1), - GPIO_RESOURCE(2), - GPIO_RESOURCE(3), +/* The 8815 has 4 GPIO blocks, let's register them immediately */ +static resource_size_t __initdata cpu8815_gpio_base[] = { + NOMADIK_GPIO0_BASE, + NOMADIK_GPIO1_BASE, + NOMADIK_GPIO2_BASE, + NOMADIK_GPIO3_BASE, }; -static struct platform_device cpu8815_platform_gpio[] = { - GPIO_DEVICE(0), - GPIO_DEVICE(1), - GPIO_DEVICE(2), - GPIO_DEVICE(3), -}; +static struct platform_device * +cpu8815_add_gpio(int id, resource_size_t addr, int irq, + struct nmk_gpio_platform_data *pdata) +{ + struct resource resources[] = { + { + .start = addr, + .end = addr + 127, + .flags = IORESOURCE_MEM, + }, + { + .start = irq, + .end = irq, + .flags = IORESOURCE_IRQ, + } + }; + + return platform_device_register_resndata(NULL, "gpio", id, + resources, ARRAY_SIZE(resources), + pdata, sizeof(*pdata)); +} -static AMBA_APB_DEVICE(cpu8815_amba_rng, "rng", 0, NOMADIK_RNG_BASE, { }, NULL); +void cpu8815_add_gpios(resource_size_t *base, int num, int irq, + struct nmk_gpio_platform_data *pdata) +{ + int first = 0; + int i; -static struct platform_device *platform_devs[] __initdata = { - cpu8815_platform_gpio + 0, - cpu8815_platform_gpio + 1, - cpu8815_platform_gpio + 2, - cpu8815_platform_gpio + 3, -}; + for (i = 0; i < num; i++, first += 32, irq++) { + pdata->first_gpio = first; + pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first); + pdata->num_gpio = 32; -static struct amba_device *amba_devs[] __initdata = { - &cpu8815_amba_rng_device -}; + cpu8815_add_gpio(i, base[i], irq, pdata); + } +} static int __init cpu8815_init(void) { int i; + struct nmk_gpio_platform_data pdata = { + /* No custom data yet */ + }; - platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); + cpu8815_add_gpios(cpu8815_gpio_base, ARRAY_SIZE(cpu8815_gpio_base), + IRQ_GPIO0, &pdata); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) amba_device_register(amba_devs[i], &iomem_resource); return 0; -- cgit v1.2.3 From 7c77852d2f22cebd5ca7c4ded4c47284e67ed9b5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 9 Jan 2012 12:40:02 +0100 Subject: ARM: nomadik: register AMBA devices dynamically This makes AMBA devices on the Nomadik main CPU die register dynamically, and refactor the registration of the RNG to use this. Acked-by: Arnd Bergmann Signed-off-by: Linus Walleij --- arch/arm/mach-nomadik/board-nhk8815.c | 17 ++--------------- arch/arm/mach-nomadik/cpu-8815.c | 13 ++++--------- 2 files changed, 6 insertions(+), 24 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index 2e8d3e176bc7..43b844eb9244 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -185,17 +185,6 @@ static void __init nhk8815_onenand_init(void) #endif } -static AMBA_APB_DEVICE(uart0, "uart0", 0, NOMADIK_UART0_BASE, - { IRQ_UART0 }, NULL); - -static AMBA_APB_DEVICE(uart1, "uart1", 0, NOMADIK_UART1_BASE, - { IRQ_UART1 }, NULL); - -static struct amba_device *amba_devs[] __initdata = { - &uart0_device, - &uart1_device, -}; - static struct resource nhk8815_eth_resources[] = { { .name = "smc91x-regs", @@ -255,15 +244,13 @@ static struct sys_timer nomadik_timer = { static void __init nhk8815_platform_init(void) { - int i; - cpu8815_platform_init(); nhk8815_onenand_init(); platform_add_devices(nhk8815_platform_devices, ARRAY_SIZE(nhk8815_platform_devices)); - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) - amba_device_register(amba_devs[i], &iomem_resource); + amba_apb_device_add(NULL, "uart0", NOMADIK_UART0_BASE, SZ_4K, IRQ_UART0, 0, NULL, 0); + amba_apb_device_add(NULL, "uart1", NOMADIK_UART1_BASE, SZ_4K, IRQ_UART1, 0, NULL, 0); } MACHINE_START(NOMADIK, "NHK8815") diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index b79b3846935a..c0f28a6d0d06 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #include #include @@ -35,12 +38,6 @@ #include "clock.h" #include "cpu-8815.h" -static AMBA_APB_DEVICE(cpu8815_amba_rng, "rng", 0, NOMADIK_RNG_BASE, { }, NULL); - -static struct amba_device *amba_devs[] __initdata = { - &cpu8815_amba_rng_device -}; - /* The 8815 has 4 GPIO blocks, let's register them immediately */ static resource_size_t __initdata cpu8815_gpio_base[] = { NOMADIK_GPIO0_BASE, @@ -88,15 +85,13 @@ void cpu8815_add_gpios(resource_size_t *base, int num, int irq, static int __init cpu8815_init(void) { - int i; struct nmk_gpio_platform_data pdata = { /* No custom data yet */ }; cpu8815_add_gpios(cpu8815_gpio_base, ARRAY_SIZE(cpu8815_gpio_base), IRQ_GPIO0, &pdata); - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) - amba_device_register(amba_devs[i], &iomem_resource); + amba_apb_device_add(NULL, "rng", NOMADIK_RNG_BASE, SZ_4K, 0, 0, NULL, 0); return 0; } arch_initcall(cpu8815_init); -- cgit v1.2.3 From b5111d9ed4cba9a29ee454db162c4a88c6b944bf Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 9 Jan 2012 14:17:01 +0100 Subject: ARM: nomadik: register PL031 RTC This registers the PL031 derivate found in the Nomadik 8815 SoCs. Acked-by: Arnd Bergmann Signed-off-by: Linus Walleij --- arch/arm/mach-nomadik/cpu-8815.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index c0f28a6d0d06..88511fef7987 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -92,6 +92,7 @@ static int __init cpu8815_init(void) cpu8815_add_gpios(cpu8815_gpio_base, ARRAY_SIZE(cpu8815_gpio_base), IRQ_GPIO0, &pdata); amba_apb_device_add(NULL, "rng", NOMADIK_RNG_BASE, SZ_4K, 0, 0, NULL, 0); + amba_apb_device_add(NULL, "rtc-pl031", NOMADIK_RTC_BASE, SZ_4K, IRQ_RTC_RTT, 0, NULL, 0); return 0; } arch_initcall(cpu8815_init); -- cgit v1.2.3 From 4a31bd28e86ac50eb620f6b5b36464c45b5fa38f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 11 Jan 2012 13:52:34 +0100 Subject: ARM: nomadik: convert to generic clock Remove more custom stuff by simply converting the Nomadik machine to use generic clocks and move the driver to drivers/clk. Acked-by: Arnd Bergmann Cc: Mike Turquette Signed-off-by: Linus Walleij --- arch/arm/Kconfig | 2 +- arch/arm/mach-nomadik/Makefile | 2 - arch/arm/mach-nomadik/clock.c | 75 ------------------------------- arch/arm/mach-nomadik/clock.h | 15 ------- arch/arm/mach-nomadik/cpu-8815.c | 4 +- drivers/clk/Makefile | 1 + drivers/clk/clk-nomadik.c | 47 +++++++++++++++++++ include/linux/platform_data/clk-nomadik.h | 2 + 8 files changed, 53 insertions(+), 95 deletions(-) delete mode 100644 arch/arm/mach-nomadik/clock.c delete mode 100644 arch/arm/mach-nomadik/clock.h create mode 100644 drivers/clk/clk-nomadik.c create mode 100644 include/linux/platform_data/clk-nomadik.h (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b649c5904a4f..e58bda6b6dde 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -912,7 +912,7 @@ config ARCH_NOMADIK select ARM_AMBA select ARM_VIC select CPU_ARM926T - select CLKDEV_LOOKUP + select COMMON_CLK select GENERIC_CLOCKEVENTS select PINCTRL select MIGHT_HAVE_CACHE_L2X0 diff --git a/arch/arm/mach-nomadik/Makefile b/arch/arm/mach-nomadik/Makefile index a6bbd1a7b4e7..a42c9a33d3bf 100644 --- a/arch/arm/mach-nomadik/Makefile +++ b/arch/arm/mach-nomadik/Makefile @@ -7,8 +7,6 @@ # Object file lists. -obj-y += clock.o - # Cpu revision obj-$(CONFIG_NOMADIK_8815) += cpu-8815.o diff --git a/arch/arm/mach-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c deleted file mode 100644 index 48a59f24e10c..000000000000 --- a/arch/arm/mach-nomadik/clock.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * linux/arch/arm/mach-nomadik/clock.c - * - * Copyright (C) 2009 Alessandro Rubini - */ -#include -#include -#include -#include -#include -#include "clock.h" - -/* - * The nomadik board uses generic clocks, but the serial pl011 file - * calls clk_enable(), clk_disable(), clk_get_rate(), so we provide them - */ -unsigned long clk_get_rate(struct clk *clk) -{ - return clk->rate; -} -EXPORT_SYMBOL(clk_get_rate); - -/* enable and disable do nothing */ -int clk_enable(struct clk *clk) -{ - return 0; -} -EXPORT_SYMBOL(clk_enable); - -void clk_disable(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_disable); - -static struct clk clk_24 = { - .rate = 2400000, -}; - -static struct clk clk_48 = { - .rate = 48 * 1000 * 1000, -}; - -/* - * Catch-all default clock to satisfy drivers using the clk API. We don't - * model the actual hardware clocks yet. - */ -static struct clk clk_default; - -#define CLK(_clk, dev) \ - { \ - .clk = _clk, \ - .dev_id = dev, \ - } - -static struct clk_lookup lookups[] = { - { - .con_id = "apb_pclk", - .clk = &clk_default, - }, - CLK(&clk_24, "mtu0"), - CLK(&clk_24, "mtu1"), - CLK(&clk_48, "uart0"), - CLK(&clk_48, "uart1"), - CLK(&clk_default, "gpio.0"), - CLK(&clk_default, "gpio.1"), - CLK(&clk_default, "gpio.2"), - CLK(&clk_default, "gpio.3"), - CLK(&clk_default, "rng"), -}; - -int __init clk_init(void) -{ - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); - return 0; -} diff --git a/arch/arm/mach-nomadik/clock.h b/arch/arm/mach-nomadik/clock.h deleted file mode 100644 index 78da2e7c3985..000000000000 --- a/arch/arm/mach-nomadik/clock.h +++ /dev/null @@ -1,15 +0,0 @@ - -/* - * linux/arch/arm/mach-nomadik/clock.h - * - * Copyright (C) 2009 Alessandro Rubini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -struct clk { - unsigned long rate; -}; - -int __init clk_init(void); diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index 88511fef7987..6fd8e46567a4 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,6 @@ #include #include -#include "clock.h" #include "cpu-8815.h" /* The 8815 has 4 GPIO blocks, let's register them immediately */ @@ -123,7 +123,7 @@ void __init cpu8815_init_irq(void) * Init clocks here so that they are available for system timer * initialization. */ - clk_init(); + nomadik_clk_init(); } /* diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index b9a5158a30b1..26b6b92942e1 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -3,5 +3,6 @@ obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ clk-mux.o clk-divider.o clk-fixed-factor.o # SoCs specific +obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o obj-$(CONFIG_ARCH_MXS) += mxs/ obj-$(CONFIG_PLAT_SPEAR) += spear/ diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c new file mode 100644 index 000000000000..517a8ff7121e --- /dev/null +++ b/drivers/clk/clk-nomadik.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include + +/* + * The Nomadik clock tree is described in the STN8815A12 DB V4.2 + * reference manual for the chip, page 94 ff. + */ + +void __init nomadik_clk_init(void) +{ + struct clk *clk; + + clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0); + clk_register_clkdev(clk, "apb_pclk", NULL); + clk_register_clkdev(clk, NULL, "gpio.0"); + clk_register_clkdev(clk, NULL, "gpio.1"); + clk_register_clkdev(clk, NULL, "gpio.2"); + clk_register_clkdev(clk, NULL, "gpio.3"); + clk_register_clkdev(clk, NULL, "rng"); + + /* + * The 2.4 MHz TIMCLK reference clock is active at boot time, this is + * actually the MXTALCLK @19.2 MHz divided by 8. This clock is used + * by the timers and watchdog. See page 105 ff. + */ + clk = clk_register_fixed_rate(NULL, "TIMCLK", NULL, CLK_IS_ROOT, + 2400000); + clk_register_clkdev(clk, NULL, "mtu0"); + clk_register_clkdev(clk, NULL, "mtu1"); + + /* + * At boot time, PLL2 is set to generate a set of fixed clocks, + * one of them is CLK48, the 48 MHz clock, routed to the UART, MMC/SD + * I2C, IrDA, USB and SSP blocks. + */ + clk = clk_register_fixed_rate(NULL, "CLK48", NULL, CLK_IS_ROOT, + 48000000); + clk_register_clkdev(clk, NULL, "uart0"); + clk_register_clkdev(clk, NULL, "uart1"); + clk_register_clkdev(clk, NULL, "mmci"); + clk_register_clkdev(clk, NULL, "ssp"); + clk_register_clkdev(clk, NULL, "nmk-i2c.0"); + clk_register_clkdev(clk, NULL, "nmk-i2c.1"); +} diff --git a/include/linux/platform_data/clk-nomadik.h b/include/linux/platform_data/clk-nomadik.h new file mode 100644 index 000000000000..5713c87b2477 --- /dev/null +++ b/include/linux/platform_data/clk-nomadik.h @@ -0,0 +1,2 @@ +/* Minimal platform data header */ +void nomadik_clk_init(void); -- cgit v1.2.3 From 661d414cb4492590f70f01c29212213947aea364 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 25 Jan 2012 14:34:52 +0100 Subject: ARM: nomadik: register all three I2C busses The Nomadik has two dedicated I2C bus blocks for I2C0 and I2C1, and a bitbanged GPIO connection on two pins for the USB portions of the STw4811 chip. Register all three as bit-banged GPIO for the moment. Acked-by: Arnd Bergmann Signed-off-by: Linus Walleij --- arch/arm/mach-nomadik/i2c-8815nhk.c | 38 ++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-nomadik/i2c-8815nhk.c b/arch/arm/mach-nomadik/i2c-8815nhk.c index 0fc2f6f1cc97..6d14454d4609 100644 --- a/arch/arm/mach-nomadik/i2c-8815nhk.c +++ b/arch/arm/mach-nomadik/i2c-8815nhk.c @@ -5,6 +5,7 @@ #include #include #include +#include /* * There are two busses in the 8815NHK. @@ -12,19 +13,27 @@ * use bit-bang through GPIO by now, to keep things simple */ +/* I2C0 connected to the STw4811 power management chip */ static struct i2c_gpio_platform_data nhk8815_i2c_data0 = { /* keep defaults for timeouts; pins are push-pull bidirectional */ .scl_pin = 62, .sda_pin = 63, }; +/* I2C1 connected to various sensors */ static struct i2c_gpio_platform_data nhk8815_i2c_data1 = { /* keep defaults for timeouts; pins are push-pull bidirectional */ .scl_pin = 53, .sda_pin = 54, }; -/* first bus: GPIO XX and YY */ +/* I2C2 connected to the USB portions of the STw4811 only */ +static struct i2c_gpio_platform_data nhk8815_i2c_data2 = { + /* keep defaults for timeouts; pins are push-pull bidirectional */ + .scl_pin = 73, + .sda_pin = 74, +}; + static struct platform_device nhk8815_i2c_dev0 = { .name = "i2c-gpio", .id = 0, @@ -32,7 +41,7 @@ static struct platform_device nhk8815_i2c_dev0 = { .platform_data = &nhk8815_i2c_data0, }, }; -/* second bus: GPIO XX and YY */ + static struct platform_device nhk8815_i2c_dev1 = { .name = "i2c-gpio", .id = 1, @@ -41,15 +50,29 @@ static struct platform_device nhk8815_i2c_dev1 = { }, }; +static struct platform_device nhk8815_i2c_dev2 = { + .name = "i2c-gpio", + .id = 2, + .dev = { + .platform_data = &nhk8815_i2c_data2, + }, +}; + +static pin_cfg_t cpu8815_pins_i2c[] = { + PIN_CFG_INPUT(62, GPIO, PULLUP), + PIN_CFG_INPUT(63, GPIO, PULLUP), + PIN_CFG_INPUT(53, GPIO, PULLUP), + PIN_CFG_INPUT(54, GPIO, PULLUP), + PIN_CFG_INPUT(73, GPIO, PULLUP), + PIN_CFG_INPUT(74, GPIO, PULLUP), +}; + static int __init nhk8815_i2c_init(void) { - nmk_gpio_set_mode(nhk8815_i2c_data0.scl_pin, NMK_GPIO_ALT_GPIO); - nmk_gpio_set_mode(nhk8815_i2c_data0.sda_pin, NMK_GPIO_ALT_GPIO); + nmk_config_pins(cpu8815_pins_i2c, ARRAY_SIZE(cpu8815_pins_i2c)); platform_device_register(&nhk8815_i2c_dev0); - - nmk_gpio_set_mode(nhk8815_i2c_data1.scl_pin, NMK_GPIO_ALT_GPIO); - nmk_gpio_set_mode(nhk8815_i2c_data1.sda_pin, NMK_GPIO_ALT_GPIO); platform_device_register(&nhk8815_i2c_dev1); + platform_device_register(&nhk8815_i2c_dev2); return 0; } @@ -58,6 +81,7 @@ static void __exit nhk8815_i2c_exit(void) { platform_device_unregister(&nhk8815_i2c_dev0); platform_device_unregister(&nhk8815_i2c_dev1); + platform_device_unregister(&nhk8815_i2c_dev2); return; } -- cgit v1.2.3 From d088f671e413ec1a58ebf9adc288ca93346f9b8e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 25 Jan 2012 14:37:58 +0100 Subject: ARM: nomadik: register the I2C devices Add board data to register all the Nomadik I2C devices. Acked-by: Arnd Bergmann Signed-off-by: Linus Walleij --- arch/arm/mach-nomadik/board-nhk8815.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index 43b844eb9244..029a741fd9f2 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -242,6 +243,30 @@ static struct sys_timer nomadik_timer = { .init = nomadik_timer_init, }; +static struct i2c_board_info __initdata nhk8815_i2c0_devices[] = { + { + I2C_BOARD_INFO("stw4811", 0x2d), + }, +}; + +static struct i2c_board_info __initdata nhk8815_i2c1_devices[] = { + { + I2C_BOARD_INFO("camera", 0x10), + }, + { + I2C_BOARD_INFO("stw5095", 0x1a), + }, + { + I2C_BOARD_INFO("lis3lv02dl", 0x1d), + }, +}; + +static struct i2c_board_info __initdata nhk8815_i2c2_devices[] = { + { + I2C_BOARD_INFO("stw4811-usb", 0x2d), + }, +}; + static void __init nhk8815_platform_init(void) { cpu8815_platform_init(); @@ -251,6 +276,13 @@ static void __init nhk8815_platform_init(void) amba_apb_device_add(NULL, "uart0", NOMADIK_UART0_BASE, SZ_4K, IRQ_UART0, 0, NULL, 0); amba_apb_device_add(NULL, "uart1", NOMADIK_UART1_BASE, SZ_4K, IRQ_UART1, 0, NULL, 0); + + i2c_register_board_info(0, nhk8815_i2c0_devices, + ARRAY_SIZE(nhk8815_i2c0_devices)); + i2c_register_board_info(1, nhk8815_i2c1_devices, + ARRAY_SIZE(nhk8815_i2c1_devices)); + i2c_register_board_info(2, nhk8815_i2c2_devices, + ARRAY_SIZE(nhk8815_i2c2_devices)); } MACHINE_START(NOMADIK, "NHK8815") -- cgit v1.2.3 From 171af7dcb8812f173f0a5a4ab79a88598586d394 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 9 Apr 2012 22:57:09 +0200 Subject: ARM: nomadik: register the MMC/SD device This registers the MMC device for the Nomadik so we can access MMC/SD cards, which is pretty nice. Acked-by: Arnd Bergmann Signed-off-by: Linus Walleij --- arch/arm/mach-nomadik/board-nhk8815.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index 029a741fd9f2..f4535a7dadf5 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -186,6 +187,29 @@ static void __init nhk8815_onenand_init(void) #endif } +static struct mmci_platform_data mmcsd_plat_data = { + .ocr_mask = MMC_VDD_29_30, + .f_max = 48000000, + .gpio_wp = -1, + .gpio_cd = 111, + .cd_invert = true, + .capabilities = MMC_CAP_MMC_HIGHSPEED | + MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA, +}; + +static int __init nhk8815_mmcsd_init(void) +{ + int ret; + + ret = gpio_request(112, "card detect bias"); + if (ret) + return ret; + gpio_direction_output(112, 0); + amba_apb_device_add(NULL, "mmci", NOMADIK_SDI_BASE, SZ_4K, IRQ_SDMMC, 0, &mmcsd_plat_data, 0x10180180); + return 0; +} +module_init(nhk8815_mmcsd_init); + static struct resource nhk8815_eth_resources[] = { { .name = "smc91x-regs", -- cgit v1.2.3 From 688df8f0b57ae2db5c4b998a59737618b9031592 Mon Sep 17 00:00:00 2001 From: Todor Colov Date: Sun, 10 Jun 2012 15:44:08 +0300 Subject: arm: ep93xx: Enable i2c support for ep9302 Enable i2c support for ep9302. i2c support is needed when external RTC is used. Signed-off-by: Todor Colov Signed-off-by: Ryan Mallon --- arch/arm/mach-ep93xx/edb93xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index d74c5cddb98b..3bb8e56969a5 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c @@ -91,8 +91,8 @@ static void __init edb93xx_register_i2c(void) ep93xx_register_i2c(&edb93xx_i2c_gpio_data, edb93xxa_i2c_board_info, ARRAY_SIZE(edb93xxa_i2c_board_info)); - } else if (machine_is_edb9307() || machine_is_edb9312() || - machine_is_edb9315()) { + } else if (machine_is_edb9302() || machine_is_edb9307() + || machine_is_edb9312() || machine_is_edb9315()) { ep93xx_register_i2c(&edb93xx_i2c_gpio_data, edb93xx_i2c_board_info, ARRAY_SIZE(edb93xx_i2c_board_info)); -- cgit v1.2.3 From 601722157b3f6be73623644eeae6f14940f0bd8f Mon Sep 17 00:00:00 2001 From: Qiao Zhou Date: Mon, 4 Jun 2012 10:41:03 +0800 Subject: ARM: MMP: add pxa910-ssp into ssp_id_table add pxa910-ssp into ssp_id_table, and fix pxa-ssp compiling issue under mach-mmp architect. Signed-off-by: Qiao Zhou Acked-by: Haojian Zhuang Signed-off-by: Mark Brown --- arch/arm/plat-pxa/ssp.c | 1 + include/linux/pxa2xx_ssp.h | 1 + include/linux/spi/pxa2xx_spi.h | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c index 58b79809d20c..584c9bf8ed2d 100644 --- a/arch/arm/plat-pxa/ssp.c +++ b/arch/arm/plat-pxa/ssp.c @@ -193,6 +193,7 @@ static const struct platform_device_id ssp_id_table[] = { { "pxa25x-nssp", PXA25x_NSSP }, { "pxa27x-ssp", PXA27x_SSP }, { "pxa168-ssp", PXA168_SSP }, + { "pxa910-ssp", PXA910_SSP }, { }, }; diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h index 44835fb39793..f9fe15ec2b51 100644 --- a/include/linux/pxa2xx_ssp.h +++ b/include/linux/pxa2xx_ssp.h @@ -161,6 +161,7 @@ enum pxa_ssp_type { PXA25x_NSSP, /* pxa 255, 26x (including ASSP) */ PXA27x_SSP, PXA168_SSP, + PXA910_SSP, CE4100_SSP, }; diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h index d3e1075f7b60..c73d1445c77e 100644 --- a/include/linux/spi/pxa2xx_spi.h +++ b/include/linux/spi/pxa2xx_spi.h @@ -43,7 +43,7 @@ struct pxa2xx_spi_chip { void (*cs_control)(u32 command); }; -#ifdef CONFIG_ARCH_PXA +#if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP) #include #include -- cgit v1.2.3 From e2b297fcf17fc03734e93387fb8195c782286b35 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Sun, 10 Jun 2012 21:13:41 -0600 Subject: perf/x86: Convert obsolete simple_strtoul() usage to kstrtoul() Signed-off-by: Shuah Khan Cc: Peter Zijlstra Cc: Frederic Weisbecker Link: http://lkml.kernel.org/r/1339384421.3025.8.camel@lorien2 Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 000a4746c7ce..766c76d5ec4c 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1640,7 +1640,12 @@ static ssize_t set_attr_rdpmc(struct device *cdev, struct device_attribute *attr, const char *buf, size_t count) { - unsigned long val = simple_strtoul(buf, NULL, 0); + unsigned long val; + ssize_t ret; + + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; if (!!val != !!x86_pmu.attr_rdpmc) { x86_pmu.attr_rdpmc = !!val; -- cgit v1.2.3 From 110c1e1f1bf61e5dca53ff5c9dc75243ce87c002 Mon Sep 17 00:00:00 2001 From: Ravikiran Thirumalai Date: Sun, 3 Jun 2012 01:11:35 +0300 Subject: x86/vsmp: Ignore IOAPIC IRQ affinity if possible vSMP can route interrupts more optimally based on internal knowledge the OS does not have. In order to support this optimization, all CPUs must be able to handle all possible IOAPIC interrupts. Fix this by setting the vector allocation domain for all CPUs and by enabling this feature in vSMP. Signed-off-by: Ravikiran Thirumalai Signed-off-by: Shai Fultheim [ Rebased, simplified, and reworded the commit message. ] Signed-off-by: Ido Yariv Signed-off-by: Ingo Molnar --- arch/x86/kernel/vsmp_64.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c index 59eea855f451..6b96a7374f94 100644 --- a/arch/x86/kernel/vsmp_64.c +++ b/arch/x86/kernel/vsmp_64.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -95,6 +96,15 @@ static void __init set_vsmp_pv_ops(void) ctl = readl(address + 4); printk(KERN_INFO "vSMP CTL: capabilities:0x%08x control:0x%08x\n", cap, ctl); + + /* If possible, let the vSMP foundation route the interrupt optimally */ +#ifdef CONFIG_SMP + if (cap & ctl & BIT(8)) { + ctl &= ~BIT(8); + no_irq_affinity = 1; + } +#endif + if (cap & ctl & (1 << 4)) { /* Setup irq ops and turn on vSMP IRQ fastpath handling */ pv_irq_ops.irq_disable = PV_CALLEE_SAVE(vsmp_irq_disable); @@ -102,12 +112,11 @@ static void __init set_vsmp_pv_ops(void) pv_irq_ops.save_fl = PV_CALLEE_SAVE(vsmp_save_fl); pv_irq_ops.restore_fl = PV_CALLEE_SAVE(vsmp_restore_fl); pv_init_ops.patch = vsmp_patch; - ctl &= ~(1 << 4); - writel(ctl, address + 4); - ctl = readl(address + 4); - printk(KERN_INFO "vSMP CTL: control set to:0x%08x\n", ctl); } + writel(ctl, address + 4); + ctl = readl(address + 4); + pr_info("vSMP CTL: control set to:0x%08x\n", ctl); early_iounmap(address, 8); } @@ -192,10 +201,20 @@ static int apicid_phys_pkg_id(int initial_apic_id, int index_msb) return hard_smp_processor_id() >> index_msb; } +/* + * In vSMP, all cpus should be capable of handling interrupts, regardless of + * the APIC used. + */ +static void fill_vector_allocation_domain(int cpu, struct cpumask *retmask) +{ + cpumask_setall(retmask); +} + static void vsmp_apic_post_init(void) { /* need to update phys_pkg_id */ apic->phys_pkg_id = apicid_phys_pkg_id; + apic->vector_allocation_domain = fill_vector_allocation_domain; } void __init vsmp_init(void) -- cgit v1.2.3 From a15687c487662c1cdcaf9d6f89270b616ccbad02 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 19 Apr 2012 00:39:19 +0200 Subject: ARM: nomadik: bump all IRQ numbers by one Since the VIC was converted to use generic IRQ domains IRQ 0 is silently ignored. This IRQ is used on the Nomadik so we're missing it now. Bump all IRQ numbers by one since they are now decoupled from the hardware IRQ numbers. Cc: Grant Likely Acked-by: Rob Herring Signed-off-by: Linus Walleij --- arch/arm/mach-nomadik/include/mach/irqs.h | 85 +++++++++++++++---------------- 1 file changed, 42 insertions(+), 43 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-nomadik/include/mach/irqs.h b/arch/arm/mach-nomadik/include/mach/irqs.h index 8faabc560398..a118e615f865 100644 --- a/arch/arm/mach-nomadik/include/mach/irqs.h +++ b/arch/arm/mach-nomadik/include/mach/irqs.h @@ -22,56 +22,56 @@ #include -#define IRQ_VIC_START 0 /* first VIC interrupt is 0 */ +#define IRQ_VIC_START 1 /* first VIC interrupt is 1 */ /* * Interrupt numbers generic for all Nomadik Chip cuts */ -#define IRQ_WATCHDOG 0 -#define IRQ_SOFTINT 1 -#define IRQ_CRYPTO 2 -#define IRQ_OWM 3 -#define IRQ_MTU0 4 -#define IRQ_MTU1 5 -#define IRQ_GPIO0 6 -#define IRQ_GPIO1 7 -#define IRQ_GPIO2 8 -#define IRQ_GPIO3 9 -#define IRQ_RTC_RTT 10 -#define IRQ_SSP 11 -#define IRQ_UART0 12 -#define IRQ_DMA1 13 -#define IRQ_CLCD_MDIF 14 -#define IRQ_DMA0 15 -#define IRQ_PWRFAIL 16 -#define IRQ_UART1 17 -#define IRQ_FIRDA 18 -#define IRQ_MSP0 19 -#define IRQ_I2C0 20 -#define IRQ_I2C1 21 -#define IRQ_SDMMC 22 -#define IRQ_USBOTG 23 -#define IRQ_SVA_IT0 24 -#define IRQ_SVA_IT1 25 -#define IRQ_SAA_IT0 26 -#define IRQ_SAA_IT1 27 -#define IRQ_UART2 28 -#define IRQ_MSP2 31 -#define IRQ_L2CC 48 -#define IRQ_HPI 49 -#define IRQ_SKE 50 -#define IRQ_KP 51 -#define IRQ_MEMST 54 -#define IRQ_SGA_IT 58 -#define IRQ_USBM 60 -#define IRQ_MSP1 62 +#define IRQ_WATCHDOG 1 +#define IRQ_SOFTINT 2 +#define IRQ_CRYPTO 3 +#define IRQ_OWM 4 +#define IRQ_MTU0 5 +#define IRQ_MTU1 6 +#define IRQ_GPIO0 7 +#define IRQ_GPIO1 8 +#define IRQ_GPIO2 9 +#define IRQ_GPIO3 10 +#define IRQ_RTC_RTT 11 +#define IRQ_SSP 12 +#define IRQ_UART0 13 +#define IRQ_DMA1 14 +#define IRQ_CLCD_MDIF 15 +#define IRQ_DMA0 16 +#define IRQ_PWRFAIL 17 +#define IRQ_UART1 18 +#define IRQ_FIRDA 19 +#define IRQ_MSP0 20 +#define IRQ_I2C0 21 +#define IRQ_I2C1 22 +#define IRQ_SDMMC 23 +#define IRQ_USBOTG 24 +#define IRQ_SVA_IT0 25 +#define IRQ_SVA_IT1 26 +#define IRQ_SAA_IT0 27 +#define IRQ_SAA_IT1 28 +#define IRQ_UART2 29 +#define IRQ_MSP2 30 +#define IRQ_L2CC 49 +#define IRQ_HPI 50 +#define IRQ_SKE 51 +#define IRQ_KP 52 +#define IRQ_MEMST 55 +#define IRQ_SGA_IT 59 +#define IRQ_USBM 61 +#define IRQ_MSP1 63 -#define NOMADIK_SOC_NR_IRQS 64 +#define NOMADIK_GPIO_OFFSET (IRQ_VIC_START+64) /* After chip-specific IRQ numbers we have the GPIO ones */ #define NOMADIK_NR_GPIO 128 /* last 4 not wired to pins */ -#define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + NOMADIK_SOC_NR_IRQS) -#define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - NOMADIK_SOC_NR_IRQS) +#define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + NOMADIK_GPIO_OFFSET) +#define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - NOMADIK_GPIO_OFFSET) #define NR_IRQS NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO) /* Following two are used by entry_macro.S, to access our dual-vic */ @@ -79,4 +79,3 @@ #define VIC_REG_IRQSR1 0x20 #endif /* __ASM_ARCH_IRQS_H */ - -- cgit v1.2.3 From 9c278d52903709543b4716b0e0d03ec58b179308 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 20 May 2012 07:46:40 +0900 Subject: ARM: EXYNOS: Add HSOTG support to Origen S3C-HSOTG device is added to Origen board. Signed-off-by: Sachin Kamat Signed-off-by: Tushar Behera Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/Kconfig | 1 + arch/arm/mach-exynos/mach-origen.c | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 573be57d3d28..da025c8542bd 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -326,6 +326,7 @@ config MACH_ORIGEN select S3C_DEV_WDT select S3C_DEV_HSMMC select S3C_DEV_HSMMC2 + select S3C_DEV_USB_HSOTG select S5P_DEV_FIMC0 select S5P_DEV_FIMC1 select S5P_DEV_FIMC2 diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index f5572be9d7bf..9ed0229db8ae 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -499,6 +500,9 @@ static void __init origen_ohci_init(void) exynos4_ohci_set_platdata(pdata); } +/* USB OTG */ +static struct s3c_hsotg_plat origen_hsotg_pdata; + static struct gpio_keys_button origen_gpio_keys_table[] = { { .code = KEY_MENU, @@ -655,6 +659,7 @@ static struct platform_device *origen_devices[] __initdata = { &s3c_device_hsmmc0, &s3c_device_i2c0, &s3c_device_rtc, + &s3c_device_usb_hsotg, &s3c_device_wdt, &s5p_device_ehci, &s5p_device_fimc0, @@ -744,6 +749,7 @@ static void __init origen_machine_init(void) origen_ehci_init(); origen_ohci_init(); + s3c_hsotg_set_platdata(&origen_hsotg_pdata); clk_xusbxti.rate = 24000000; s5p_tv_setup(); -- cgit v1.2.3 From fb395c39307268baa324c2cdd009cd9b58fcf2ec Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 20 May 2012 07:46:44 +0900 Subject: ARM: EXYNOS: Add HSOTG support to SMDKV310 S3C-HSOTG device is added to SMDKV310 board. Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/Kconfig | 1 + arch/arm/mach-exynos/mach-smdkv310.c | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index da025c8542bd..f5fb6eaf9d85 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -207,6 +207,7 @@ config MACH_SMDKV310 select S3C_DEV_HSMMC1 select S3C_DEV_HSMMC2 select S3C_DEV_HSMMC3 + select S3C_DEV_USB_HSOTG select SAMSUNG_DEV_BACKLIGHT select EXYNOS_DEV_DRM select EXYNOS_DEV_SYSMMU diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c index 262e9e446a96..7b1b86663e51 100644 --- a/arch/arm/mach-exynos/mach-smdkv310.c +++ b/arch/arm/mach-exynos/mach-smdkv310.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -271,6 +272,9 @@ static void __init smdkv310_ohci_init(void) exynos4_ohci_set_platdata(pdata); } +/* USB OTG */ +static struct s3c_hsotg_plat smdkv310_hsotg_pdata; + static struct platform_device *smdkv310_devices[] __initdata = { &s3c_device_hsmmc0, &s3c_device_hsmmc1, @@ -279,6 +283,7 @@ static struct platform_device *smdkv310_devices[] __initdata = { &s3c_device_i2c1, &s5p_device_i2c_hdmiphy, &s3c_device_rtc, + &s3c_device_usb_hsotg, &s3c_device_wdt, &s5p_device_ehci, &s5p_device_fimc0, @@ -390,6 +395,7 @@ static void __init smdkv310_machine_init(void) smdkv310_ehci_init(); smdkv310_ohci_init(); + s3c_hsotg_set_platdata(&smdkv310_hsotg_pdata); clk_xusbxti.rate = 24000000; platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices)); -- cgit v1.2.3 From a9140aa51dede09cefd51a6f578a100572e693b3 Mon Sep 17 00:00:00 2001 From: "hdoyu@nvidia.com" Date: Wed, 16 May 2012 19:47:44 +0000 Subject: ARM: dt: tegra{20,30}.dtsi: Rename "mc" to "memory-controller" Use a more plain english name. Signed-off-by: Hiroshi DOYU [swarren: remove redundant unit address from tegra30.dtsi change] Signed-off-by: Stephen Warren --- arch/arm/boot/dts/tegra20.dtsi | 2 +- arch/arm/boot/dts/tegra30.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index c417d67e9027..2d503d62ea3e 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -164,7 +164,7 @@ reg = <0x7000e400 0x400>; }; - mc { + memory-controller@0x7000f000 { compatible = "nvidia,tegra20-mc"; reg = <0x7000f000 0x024 0x7000f03c 0x3c4>; diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index 2dcc09e784b5..19479393842e 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -167,7 +167,7 @@ reg = <0x7000e400 0x400>; }; - mc { + memory-controller { compatible = "nvidia,tegra30-mc"; reg = <0x7000f000 0x010 0x7000f03c 0x1b4 -- cgit v1.2.3 From bfb3fe12667244d2c51699608a1591f1fdb774e5 Mon Sep 17 00:00:00 2001 From: "hdoyu@nvidia.com" Date: Wed, 16 May 2012 19:47:46 +0000 Subject: ARM: dt: tegra20: Rename "emc" to "memory-controller" Use a more plain english name. Signed-off-by: Hiroshi DOYU [swarren: also rename the node in tegra-seaboard.dts] Signed-off-by: Stephen Warren --- arch/arm/boot/dts/tegra-seaboard.dts | 2 +- arch/arm/boot/dts/tegra20.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts index 89cb7f2acd92..743ef653afc3 100644 --- a/arch/arm/boot/dts/tegra-seaboard.dts +++ b/arch/arm/boot/dts/tegra-seaboard.dts @@ -334,7 +334,7 @@ }; }; - emc { + memory-controller@0x7000f400 { emc-table@190000 { reg = <190000>; compatible = "nvidia,tegra20-emc-table"; diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 2d503d62ea3e..59116b852434 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -177,7 +177,7 @@ 0x58000000 0x02000000>; /* GART aperture */ }; - emc { + memory-controller@0x7000f400 { compatible = "nvidia,tegra20-emc"; reg = <0x7000f400 0x200>; #address-cells = <1>; -- cgit v1.2.3 From b4e395b2cb5ce871f23a176fed74316a7de64a97 Mon Sep 17 00:00:00 2001 From: Prashant Gaikwad Date: Tue, 5 Jun 2012 09:44:40 +0530 Subject: ARM: tegra: Remove flow controller programming This particular code had no effect on WFI execution. It only asserts/de-asserts signal to tegra "legacy" CPU idle stats monitor, which we are no longer using (cpufreq is based on kernel s/w idle stats instead). Signed-off-by: Prashant Gaikwad Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/cpuidle.c | 6 +++--- arch/arm/mach-tegra/sleep.S | 29 ----------------------------- 2 files changed, 3 insertions(+), 32 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c index d83a8c0296f5..566e2f88899b 100644 --- a/arch/arm/mach-tegra/cpuidle.c +++ b/arch/arm/mach-tegra/cpuidle.c @@ -27,9 +27,9 @@ #include #include -#include +#include -extern void tegra_cpu_wfi(void); +#include static int tegra_idle_enter_lp3(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index); @@ -64,7 +64,7 @@ static int tegra_idle_enter_lp3(struct cpuidle_device *dev, enter = ktime_get(); - tegra_cpu_wfi(); + cpu_do_idle(); exit = ktime_sub(ktime_get(), enter); us = ktime_to_us(exit); diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S index 5b20197bae7f..d29b156a8011 100644 --- a/arch/arm/mach-tegra/sleep.S +++ b/arch/arm/mach-tegra/sleep.S @@ -62,32 +62,3 @@ movw \reg, #:lower16:\val movt \reg, #:upper16:\val .endm - -/* - * tegra_cpu_wfi - * - * puts current CPU in clock-gated wfi using the flow controller - * - * corrupts r0-r3 - * must be called with MMU on - */ - -ENTRY(tegra_cpu_wfi) - cpu_id r0 - cpu_to_halt_reg r1, r0 - cpu_to_csr_reg r2, r0 - mov32 r0, TEGRA_FLOW_CTRL_VIRT - mov r3, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG - str r3, [r0, r2] @ clear event & interrupt status - mov r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT | FLOW_CTRL_JTAG_RESUME - str r3, [r0, r1] @ put flow controller in wait irq mode - dsb - wfi - mov r3, #0 - str r3, [r0, r1] @ clear flow controller halt status - mov r3, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG - str r3, [r0, r2] @ clear event & interrupt status - dsb - mov pc, lr -ENDPROC(tegra_cpu_wfi) - -- cgit v1.2.3 From 02e35c461daf78a093012ae2eb07535939f95c16 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 21 May 2012 16:45:19 -0600 Subject: ARM: dt: tegra: remove legacy support-8bit property The driver supports the new bus-width property, so remove the legacy support-8bit property. Signed-off-by: Stephen Warren --- arch/arm/boot/dts/tegra-cardhu.dts | 1 - arch/arm/boot/dts/tegra-harmony.dts | 1 - arch/arm/boot/dts/tegra-paz00.dts | 1 - arch/arm/boot/dts/tegra-seaboard.dts | 1 - arch/arm/boot/dts/tegra-ventana.dts | 1 - 5 files changed, 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/tegra-cardhu.dts b/arch/arm/boot/dts/tegra-cardhu.dts index 36321bceec46..c169bced131e 100644 --- a/arch/arm/boot/dts/tegra-cardhu.dts +++ b/arch/arm/boot/dts/tegra-cardhu.dts @@ -144,7 +144,6 @@ sdhci@78000600 { status = "okay"; - support-8bit; bus-width = <8>; }; diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts index 7de701365fce..f146dbf6f7f8 100644 --- a/arch/arm/boot/dts/tegra-harmony.dts +++ b/arch/arm/boot/dts/tegra-harmony.dts @@ -307,7 +307,6 @@ cd-gpios = <&gpio 58 0>; /* gpio PH2 */ wp-gpios = <&gpio 59 0>; /* gpio PH3 */ power-gpios = <&gpio 70 0>; /* gpio PI6 */ - support-8bit; bus-width = <8>; }; diff --git a/arch/arm/boot/dts/tegra-paz00.dts b/arch/arm/boot/dts/tegra-paz00.dts index bfeb117d5aea..684a9e1ff7e9 100644 --- a/arch/arm/boot/dts/tegra-paz00.dts +++ b/arch/arm/boot/dts/tegra-paz00.dts @@ -301,7 +301,6 @@ sdhci@c8000600 { status = "okay"; - support-8bit; bus-width = <8>; }; diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts index 743ef653afc3..b797901d040d 100644 --- a/arch/arm/boot/dts/tegra-seaboard.dts +++ b/arch/arm/boot/dts/tegra-seaboard.dts @@ -397,7 +397,6 @@ sdhci@c8000600 { status = "okay"; - support-8bit; bus-width = <8>; }; diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts index 445343b0fbdd..be90544e6b59 100644 --- a/arch/arm/boot/dts/tegra-ventana.dts +++ b/arch/arm/boot/dts/tegra-ventana.dts @@ -314,7 +314,6 @@ sdhci@c8000600 { status = "okay"; - support-8bit; bus-width = <8>; }; -- cgit v1.2.3 From 0336553e4a8c1fefc11aa5656cebf2ce80657322 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 21 May 2012 14:51:19 -0600 Subject: ASoC: tegra: simplify Kconfig dependencies The Tegra ASoC machine drivers only depend on Tegra architecture support to compile, not specific board support. Remove Kconfig dependencies on any particular board. This is required since Kconfig options for boards are going away given the migration to device tree. Signed-off-by: Stephen Warren Acked-by: Mark Brown --- arch/arm/mach-tegra/Kconfig | 3 --- sound/soc/tegra/Kconfig | 10 +--------- 2 files changed, 1 insertion(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 6a113a9bb87a..7c407393cd07 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -63,7 +63,6 @@ comment "Tegra board type" config MACH_HARMONY bool "Harmony board" depends on ARCH_TEGRA_2x_SOC - select MACH_HAS_SND_SOC_TEGRA_WM8903 if SND_SOC help Support for nVidia Harmony development platform @@ -71,7 +70,6 @@ config MACH_KAEN bool "Kaen board" depends on ARCH_TEGRA_2x_SOC select MACH_SEABOARD - select MACH_HAS_SND_SOC_TEGRA_WM8903 if SND_SOC help Support for the Kaen version of Seaboard @@ -84,7 +82,6 @@ config MACH_PAZ00 config MACH_SEABOARD bool "Seaboard board" depends on ARCH_TEGRA_2x_SOC - select MACH_HAS_SND_SOC_TEGRA_WM8903 if SND_SOC help Support for nVidia Seaboard development platform. It will also be included for some of the derivative boards that diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index c1c8e955f4d3..76dc230f2bb0 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -58,17 +58,9 @@ config SND_SOC_TEGRA_WM8753 Say Y or M here if you want to add support for SoC audio on Tegra boards using the WM8753 codec, such as Whistler. -config MACH_HAS_SND_SOC_TEGRA_WM8903 - bool - help - Machines that use the SND_SOC_TEGRA_WM8903 driver should select - this config option, in order to allow the user to enable - SND_SOC_TEGRA_WM8903. - config SND_SOC_TEGRA_WM8903 tristate "SoC Audio support for Tegra boards using a WM8903 codec" depends on SND_SOC_TEGRA && I2C - depends on MACH_HAS_SND_SOC_TEGRA_WM8903 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC select SND_SOC_WM8903 @@ -79,7 +71,7 @@ config SND_SOC_TEGRA_WM8903 config SND_SOC_TEGRA_TRIMSLICE tristate "SoC Audio support for TrimSlice board" - depends on SND_SOC_TEGRA && MACH_TRIMSLICE && I2C + depends on SND_SOC_TEGRA && I2C select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC select SND_SOC_TLV320AIC23 help -- cgit v1.2.3 From 6a5278d0715c5dfd42151bb6d7444db3f2ceed52 Mon Sep 17 00:00:00 2001 From: Prashant Gaikwad Date: Tue, 5 Jun 2012 09:59:35 +0530 Subject: ARM: tegra: add clk_prepare/clk_unprepare Use clk_prepare/clk_unprepare as required by the generic clk framework. Tested on Ventana and Cardhu. Signed-off-by: Prashant Gaikwad Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/cpu-tegra.c | 6 +++--- arch/arm/mach-tegra/dma.c | 2 +- arch/arm/mach-tegra/pcie.c | 6 +++--- arch/arm/mach-tegra/powergate.c | 4 ++-- arch/arm/mach-tegra/timer.c | 4 ++-- arch/arm/mach-tegra/usb_phy.c | 16 ++++++++-------- 6 files changed, 19 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index 7a065f0cf633..ceb52db1e2f1 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c @@ -189,8 +189,8 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) return PTR_ERR(emc_clk); } - clk_enable(emc_clk); - clk_enable(cpu_clk); + clk_prepare_enable(emc_clk); + clk_prepare_enable(cpu_clk); cpufreq_frequency_table_cpuinfo(policy, freq_table); cpufreq_frequency_table_get_attr(freq_table, policy->cpu); @@ -212,7 +212,7 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) static int tegra_cpu_exit(struct cpufreq_policy *policy) { cpufreq_frequency_table_cpuinfo(policy, freq_table); - clk_disable(emc_clk); + clk_disable_unprepare(emc_clk); clk_put(emc_clk); clk_put(cpu_clk); return 0; diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c index abea4f6e2dd5..2698d7d5c9ca 100644 --- a/arch/arm/mach-tegra/dma.c +++ b/arch/arm/mach-tegra/dma.c @@ -720,7 +720,7 @@ int __init tegra_dma_init(void) ret = PTR_ERR(c); goto fail; } - ret = clk_enable(c); + ret = clk_prepare_enable(c); if (ret != 0) { pr_err("Unable to enable clock for APB DMA\n"); goto fail; diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c index 0e09137506ec..d3ad5150d660 100644 --- a/arch/arm/mach-tegra/pcie.c +++ b/arch/arm/mach-tegra/pcie.c @@ -723,9 +723,9 @@ static int tegra_pcie_power_regate(void) tegra_pcie_xclk_clamp(false); - clk_enable(tegra_pcie.afi_clk); - clk_enable(tegra_pcie.pex_clk); - return clk_enable(tegra_pcie.pll_e); + clk_prepare_enable(tegra_pcie.afi_clk); + clk_prepare_enable(tegra_pcie.pex_clk); + return clk_prepare_enable(tegra_pcie.pll_e); } static int tegra_pcie_clocks_get(void) diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c index f5b12fb4ff12..15d506501ccc 100644 --- a/arch/arm/mach-tegra/powergate.c +++ b/arch/arm/mach-tegra/powergate.c @@ -146,7 +146,7 @@ int tegra_powergate_sequence_power_up(int id, struct clk *clk) if (ret) goto err_power; - ret = clk_enable(clk); + ret = clk_prepare_enable(clk); if (ret) goto err_clk; @@ -162,7 +162,7 @@ int tegra_powergate_sequence_power_up(int id, struct clk *clk) return 0; err_clamp: - clk_disable(clk); + clk_disable_unprepare(clk); err_clk: tegra_powergate_power_off(id); err_power: diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index 315672c7bd48..57b5bdc13b9b 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c @@ -189,7 +189,7 @@ static void __init tegra_init_timer(void) " Assuming 12Mhz input clock.\n"); rate = 12000000; } else { - clk_enable(clk); + clk_prepare_enable(clk); rate = clk_get_rate(clk); } @@ -201,7 +201,7 @@ static void __init tegra_init_timer(void) if (IS_ERR(clk)) pr_warn("Unable to get rtc-tegra clock\n"); else - clk_enable(clk); + clk_prepare_enable(clk); switch (rate) { case 12000000: diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c index 54e353c8e304..022b33a05c3a 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c @@ -247,7 +247,7 @@ static void utmip_pad_power_on(struct tegra_usb_phy *phy) unsigned long val, flags; void __iomem *base = phy->pad_regs; - clk_enable(phy->pad_clk); + clk_prepare_enable(phy->pad_clk); spin_lock_irqsave(&utmip_pad_lock, flags); @@ -259,7 +259,7 @@ static void utmip_pad_power_on(struct tegra_usb_phy *phy) spin_unlock_irqrestore(&utmip_pad_lock, flags); - clk_disable(phy->pad_clk); + clk_disable_unprepare(phy->pad_clk); } static int utmip_pad_power_off(struct tegra_usb_phy *phy) @@ -272,7 +272,7 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy) return -EINVAL; } - clk_enable(phy->pad_clk); + clk_prepare_enable(phy->pad_clk); spin_lock_irqsave(&utmip_pad_lock, flags); @@ -284,7 +284,7 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy) spin_unlock_irqrestore(&utmip_pad_lock, flags); - clk_disable(phy->pad_clk); + clk_disable_unprepare(phy->pad_clk); return 0; } @@ -580,7 +580,7 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) msleep(5); gpio_direction_output(config->reset_gpio, 1); - clk_enable(phy->clk); + clk_prepare_enable(phy->clk); msleep(1); val = readl(base + USB_SUSP_CTRL); @@ -689,7 +689,7 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, err = PTR_ERR(phy->pll_u); goto err0; } - clk_enable(phy->pll_u); + clk_prepare_enable(phy->pll_u); parent_rate = clk_get_rate(clk_get_parent(phy->pll_u)); for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) { @@ -735,7 +735,7 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, return phy; err1: - clk_disable(phy->pll_u); + clk_disable_unprepare(phy->pll_u); clk_put(phy->pll_u); err0: kfree(phy); @@ -810,7 +810,7 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy) clk_put(phy->clk); else utmip_pad_close(phy); - clk_disable(phy->pll_u); + clk_disable_unprepare(phy->pll_u); clk_put(phy->pll_u); kfree(phy); } -- cgit v1.2.3 From dbebe1589d3a86658f32e74396611452c5f34481 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 21 May 2012 15:02:57 -0600 Subject: ARM: tegra: defconfig updates Enable: * SND_SOC_TEGRA_WM8753 (new feature) * TPS65910 (Cardhu regulator) * CONFIG_I2C_MUX (dependency of:) * CONFIG_I2C_MUX_PINCTRL (for Seaboard) Remove some deleted options: * MACH_KAEN * MACH_VENTANA * MACH_WARIO Signed-off-by: Laxman Dewangan Signed-off-by: Stephen Warren --- arch/arm/configs/tegra_defconfig | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index 1198dd61c7c4..4be9c1e80ee6 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -1,4 +1,6 @@ CONFIG_EXPERIMENTAL=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_CGROUPS=y @@ -25,14 +27,9 @@ CONFIG_ARCH_TEGRA=y CONFIG_ARCH_TEGRA_2x_SOC=y CONFIG_ARCH_TEGRA_3x_SOC=y CONFIG_MACH_HARMONY=y -CONFIG_MACH_KAEN=y CONFIG_MACH_PAZ00=y CONFIG_MACH_TRIMSLICE=y -CONFIG_MACH_WARIO=y -CONFIG_MACH_VENTANA=y CONFIG_TEGRA_EMC_SCALING_ENABLE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y CONFIG_PREEMPT=y CONFIG_AEABI=y @@ -103,19 +100,24 @@ CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y # CONFIG_I2C_COMPAT is not set +CONFIG_I2C_MUX=y +CONFIG_I2C_MUX_PINCTRL=y CONFIG_I2C_TEGRA=y CONFIG_SPI=y CONFIG_SPI_TEGRA=y +CONFIG_GPIO_TPS65910=y CONFIG_POWER_SUPPLY=y CONFIG_BATTERY_SBS=y CONFIG_SENSORS_LM90=y CONFIG_MFD_TPS6586X=y +CONFIG_MFD_TPS65910=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_GPIO=y CONFIG_REGULATOR_TPS62360=y CONFIG_REGULATOR_TPS6586X=y +CONFIG_REGULATOR_TPS65910=y CONFIG_SOUND=y CONFIG_SND=y # CONFIG_SND_SUPPORT_OLD_API is not set @@ -126,6 +128,7 @@ CONFIG_SND=y # CONFIG_SND_USB is not set CONFIG_SND_SOC=y CONFIG_SND_SOC_TEGRA=y +CONFIG_SND_SOC_TEGRA_WM8753=y CONFIG_SND_SOC_TEGRA_WM8903=y CONFIG_SND_SOC_TEGRA_TRIMSLICE=y CONFIG_SND_SOC_TEGRA_ALC5632=y -- cgit v1.2.3 From ae10ccdc3093486f8c2369d227583f9d79f628e5 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Mon, 4 Jun 2012 15:00:04 +0800 Subject: ACPI: Make acpi_skip_timer_override cover all source_irq==0 cases Currently when acpi_skip_timer_override is set, it only cover the (source_irq == 0 && global_irq == 2) cases. While there is also platform which need use this option and its global_irq is not 2. This patch will extend acpi_skip_timer_override to cover all timer overriding cases as long as the source irq is 0. This is the first part of a fix to kernel bug bugzilla 40002: "IRQ 0 assigned to VGA" https://bugzilla.kernel.org/show_bug.cgi?id=40002 Reported-and-tested-by: Szymon Kowalczyk Signed-off-by: Feng Tang Signed-off-by: Len Brown --- arch/x86/kernel/acpi/boot.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 8afb69319815..e7c698e9c7ec 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -422,12 +422,14 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header, return 0; } - if (intsrc->source_irq == 0 && intsrc->global_irq == 2) { + if (intsrc->source_irq == 0) { if (acpi_skip_timer_override) { - printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); + printk(PREFIX "BIOS IRQ0 override ignored.\n"); return 0; } - if (acpi_fix_pin2_polarity && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) { + + if ((intsrc->global_irq == 2) && acpi_fix_pin2_polarity + && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) { intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK; printk(PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n"); } @@ -1334,7 +1336,7 @@ static int __init dmi_disable_acpi(const struct dmi_system_id *d) } /* - * Force ignoring BIOS IRQ0 pin2 override + * Force ignoring BIOS IRQ0 override */ static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) { @@ -1344,7 +1346,7 @@ static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) */ if (!acpi_skip_timer_override) { WARN(1, KERN_ERR "ati_ixp4x0 quirk not complete.\n"); - pr_notice("%s detected: Ignoring BIOS IRQ0 pin2 override\n", + pr_notice("%s detected: Ignoring BIOS IRQ0 override\n", d->ident); acpi_skip_timer_override = 1; } @@ -1438,7 +1440,7 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = { * is enabled. This input is incorrectly designated the * ISA IRQ 0 via an interrupt source override even though * it is wired to the output of the master 8259A and INTIN0 - * is not connected at all. Force ignoring BIOS IRQ0 pin2 + * is not connected at all. Force ignoring BIOS IRQ0 * override in that cases. */ { -- cgit v1.2.3 From 7f68b4c2e158019c2ec494b5cfbd9c83b4e5b253 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Mon, 4 Jun 2012 15:00:05 +0800 Subject: ACPI: Remove one board specific WARN when ignoring timer overriding Current WARN msg is only for the ati_ixp4x0 board, while this function is used by mulitple platforms. So this one board specific warning is not appropriate any more. Signed-off-by: Feng Tang Signed-off-by: Len Brown --- arch/x86/kernel/acpi/boot.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index e7c698e9c7ec..3a6afba6eca7 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1340,12 +1340,7 @@ static int __init dmi_disable_acpi(const struct dmi_system_id *d) */ static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) { - /* - * The ati_ixp4x0_rev() early PCI quirk should have set - * the acpi_skip_timer_override flag already: - */ if (!acpi_skip_timer_override) { - WARN(1, KERN_ERR "ati_ixp4x0 quirk not complete.\n"); pr_notice("%s detected: Ignoring BIOS IRQ0 override\n", d->ident); acpi_skip_timer_override = 1; -- cgit v1.2.3 From f6b54f083cc66cf9b11d2120d8df3c2ad4e0836d Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Mon, 4 Jun 2012 15:00:06 +0800 Subject: ACPI: Add a quirk for "AMILO PRO V2030" to ignore the timer overriding This is the 2nd part of fix for kernel bugzilla 40002: "IRQ 0 assigned to VGA" https://bugzilla.kernel.org/show_bug.cgi?id=40002 The root cause is the buggy FW, whose ACPI tables assign the GSI 16 to 2 irqs 0 and 16(VGA), and the VGA is the right owner of GSI 16. So add a quirk to ignore the irq0 overriding GSI 16 for the FUJITSU SIEMENS AMILO PRO V2030 platform will solve this issue. Reported-and-tested-by: Szymon Kowalczyk Signed-off-by: Feng Tang Signed-off-by: Len Brown --- arch/x86/kernel/acpi/boot.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 3a6afba6eca7..b2297e58c6ed 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1470,6 +1470,14 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6715b"), }, }, + { + .callback = dmi_ignore_irq0_timer_override, + .ident = "FUJITSU SIEMENS", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"), + }, + }, {} }; -- cgit v1.2.3 From 80feb89a0a1381642f1cce9036ef3bb22f13b40a Mon Sep 17 00:00:00 2001 From: Takuya Yoshikawa Date: Tue, 29 May 2012 23:54:26 +0900 Subject: KVM: MMU: Remove unused parameter from mmu_memory_cache_alloc() Size is not needed to return one from pre-allocated objects. Signed-off-by: Takuya Yoshikawa Signed-off-by: Marcelo Tosatti --- arch/x86/kvm/mmu.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 24dd43d45ae4..b32a11dc884c 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -652,8 +652,7 @@ static void mmu_free_memory_caches(struct kvm_vcpu *vcpu) mmu_page_header_cache); } -static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc, - size_t size) +static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) { void *p; @@ -664,8 +663,7 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc, static struct pte_list_desc *mmu_alloc_pte_list_desc(struct kvm_vcpu *vcpu) { - return mmu_memory_cache_alloc(&vcpu->arch.mmu_pte_list_desc_cache, - sizeof(struct pte_list_desc)); + return mmu_memory_cache_alloc(&vcpu->arch.mmu_pte_list_desc_cache); } static void mmu_free_pte_list_desc(struct pte_list_desc *pte_list_desc) @@ -1403,12 +1401,10 @@ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, u64 *parent_pte, int direct) { struct kvm_mmu_page *sp; - sp = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_header_cache, - sizeof *sp); - sp->spt = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache, PAGE_SIZE); + sp = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_header_cache); + sp->spt = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache); if (!direct) - sp->gfns = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache, - PAGE_SIZE); + sp->gfns = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache); set_page_private(virt_to_page(sp->spt), (unsigned long)sp); list_add(&sp->link, &vcpu->kvm->arch.active_mmu_pages); bitmap_zero(sp->slot_bitmap, KVM_MEM_SLOTS_NUM); -- cgit v1.2.3 From f242e50eee1ec7692c4854d94e8cd543991cce71 Mon Sep 17 00:00:00 2001 From: Ola Lilja Date: Thu, 7 Jun 2012 14:00:46 +0200 Subject: mfd/ab8500: Move platform-data for ab8500-codec into mfd-driver The platform-data used by the Ux500 ASoC-driver is moved from the machine-driver context into the codec-driver context. This means adding the platform-data for 'ab8500-codec' into the main AB8500 platform-data. Signed-off-by: Ola Lilja Signed-off-by: Mark Brown --- arch/arm/mach-ux500/board-mop500.c | 14 +++++++++ include/linux/mfd/abx500/ab8500-codec.h | 52 +++++++++++++++++++++++++++++++++ include/linux/mfd/abx500/ab8500.h | 2 ++ 3 files changed, 68 insertions(+) create mode 100644 include/linux/mfd/abx500/ab8500-codec.h (limited to 'arch') diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 9c74ac545849..c8a8fde777bb 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,18 @@ static struct ab8500_gpio_platform_data ab8500_gpio_pdata = { 0x7A, 0x00, 0x00}, }; +/* ab8500-codec */ +static struct ab8500_codec_platform_data ab8500_codec_pdata = { + .amics = { + .mic1_type = AMIC_TYPE_DIFFERENTIAL, + .mic2_type = AMIC_TYPE_DIFFERENTIAL, + .mic1a_micbias = AMIC_MICBIAS_VAMIC1, + .mic1b_micbias = AMIC_MICBIAS_VAMIC1, + .mic2_micbias = AMIC_MICBIAS_VAMIC2 + }, + .ear_cmv = EAR_CMV_0_95V +}; + static struct gpio_keys_button snowball_key_array[] = { { .gpio = 32, @@ -195,6 +208,7 @@ static struct ab8500_platform_data ab8500_platdata = { .regulator = ab8500_regulators, .num_regulator = ARRAY_SIZE(ab8500_regulators), .gpio = &ab8500_gpio_pdata, + .codec = &ab8500_codec_pdata, }; static struct resource ab8500_resources[] = { diff --git a/include/linux/mfd/abx500/ab8500-codec.h b/include/linux/mfd/abx500/ab8500-codec.h new file mode 100644 index 000000000000..dc6529202cdd --- /dev/null +++ b/include/linux/mfd/abx500/ab8500-codec.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Ola Lilja + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef AB8500_CORE_CODEC_H +#define AB8500_CORE_CODEC_H + +/* Mic-types */ +enum amic_type { + AMIC_TYPE_SINGLE_ENDED, + AMIC_TYPE_DIFFERENTIAL +}; + +/* Mic-biases */ +enum amic_micbias { + AMIC_MICBIAS_VAMIC1, + AMIC_MICBIAS_VAMIC2 +}; + +/* Bias-voltage */ +enum ear_cm_voltage { + EAR_CMV_0_95V, + EAR_CMV_1_10V, + EAR_CMV_1_27V, + EAR_CMV_1_58V +}; + +/* Analog microphone settings */ +struct amic_settings { + enum amic_type mic1_type; + enum amic_type mic2_type; + enum amic_micbias mic1a_micbias; + enum amic_micbias mic1b_micbias; + enum amic_micbias mic2_micbias; +}; + +/* Platform data structure for the audio-parts of the AB8500 */ +struct ab8500_codec_platform_data { + struct amic_settings amics; + enum ear_cm_voltage ear_cmv; +}; + +#endif diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index 91dd3ef63e99..bc9b84b60ec6 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -266,6 +266,7 @@ struct ab8500 { struct regulator_reg_init; struct regulator_init_data; struct ab8500_gpio_platform_data; +struct ab8500_codec_platform_data; /** * struct ab8500_platform_data - AB8500 platform data @@ -284,6 +285,7 @@ struct ab8500_platform_data { int num_regulator; struct regulator_init_data *regulator; struct ab8500_gpio_platform_data *gpio; + struct ab8500_codec_platform_data *codec; }; extern int __devinit ab8500_init(struct ab8500 *ab8500, -- cgit v1.2.3 From 65df57743924c3d13e1fa1bcf5bf70fe874fcdfd Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Thu, 24 May 2012 11:13:42 +0200 Subject: crypto: sha1 - use Kbuild supplied flags for AVX test Commit ea4d26ae ("raid5: add AVX optimized RAID5 checksumming") introduced x86/ arch wide defines for AFLAGS and CFLAGS indicating AVX support in binutils based on the same test we have in x86/crypto/ right now. To minimize duplication drop our implementation in favour to the one in x86/. Signed-off-by: Mathias Krause Signed-off-by: Herbert Xu --- arch/x86/crypto/Makefile | 7 ------- arch/x86/crypto/sha1_ssse3_asm.S | 2 +- arch/x86/crypto/sha1_ssse3_glue.c | 6 +++--- 3 files changed, 4 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index e191ac048b59..479f95a744f7 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -34,12 +34,5 @@ salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o serpent-sse2-x86_64-y := serpent-sse2-x86_64-asm_64.o serpent_sse2_glue.o aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o - ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o - -# enable AVX support only when $(AS) can actually assemble the instructions -ifeq ($(call as-instr,vpxor %xmm0$(comma)%xmm1$(comma)%xmm2,yes,no),yes) -AFLAGS_sha1_ssse3_asm.o += -DSHA1_ENABLE_AVX_SUPPORT -CFLAGS_sha1_ssse3_glue.o += -DSHA1_ENABLE_AVX_SUPPORT -endif sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o diff --git a/arch/x86/crypto/sha1_ssse3_asm.S b/arch/x86/crypto/sha1_ssse3_asm.S index b2c2f57d70e8..49d6987a73d9 100644 --- a/arch/x86/crypto/sha1_ssse3_asm.S +++ b/arch/x86/crypto/sha1_ssse3_asm.S @@ -468,7 +468,7 @@ W_PRECALC_SSSE3 */ SHA1_VECTOR_ASM sha1_transform_ssse3 -#ifdef SHA1_ENABLE_AVX_SUPPORT +#ifdef CONFIG_AS_AVX .macro W_PRECALC_AVX diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c index f916499d0abe..4a11a9d72451 100644 --- a/arch/x86/crypto/sha1_ssse3_glue.c +++ b/arch/x86/crypto/sha1_ssse3_glue.c @@ -35,7 +35,7 @@ asmlinkage void sha1_transform_ssse3(u32 *digest, const char *data, unsigned int rounds); -#ifdef SHA1_ENABLE_AVX_SUPPORT +#ifdef CONFIG_AS_AVX asmlinkage void sha1_transform_avx(u32 *digest, const char *data, unsigned int rounds); #endif @@ -184,7 +184,7 @@ static struct shash_alg alg = { } }; -#ifdef SHA1_ENABLE_AVX_SUPPORT +#ifdef CONFIG_AS_AVX static bool __init avx_usable(void) { u64 xcr0; @@ -209,7 +209,7 @@ static int __init sha1_ssse3_mod_init(void) if (cpu_has_ssse3) sha1_transform_asm = sha1_transform_ssse3; -#ifdef SHA1_ENABLE_AVX_SUPPORT +#ifdef CONFIG_AS_AVX /* allow AVX to override SSSE3, it's a little faster */ if (avx_usable()) sha1_transform_asm = sha1_transform_avx; -- cgit v1.2.3 From 107778b592576c0c8e8d2ca7a2aa5415a4908223 Mon Sep 17 00:00:00 2001 From: Johannes Goetzfried Date: Mon, 28 May 2012 15:54:24 +0200 Subject: crypto: twofish - add x86_64/avx assembler implementation This patch adds a x86_64/avx assembler implementation of the Twofish block cipher. The implementation processes eight blocks in parallel (two 4 block chunk AVX operations). The table-lookups are done in general-purpose registers. For small blocksizes the 3way-parallel functions from the twofish-x86_64-3way module are called. A good performance increase is provided for blocksizes greater or equal to 128B. Patch has been tested with tcrypt and automated filesystem tests. Tcrypt benchmark results: Intel Core i5-2500 CPU (fam:6, model:42, step:7) twofish-avx-x86_64 vs. twofish-x86_64-3way 128bit key: (lrw:256bit) (xts:256bit) size ecb-enc ecb-dec cbc-enc cbc-dec ctr-enc ctr-dec lrw-enc lrw-dec xts-enc xts-dec 16B 0.96x 0.97x 1.00x 0.95x 0.97x 0.97x 0.96x 0.95x 0.95x 0.98x 64B 0.99x 0.99x 1.00x 0.99x 0.98x 0.98x 0.99x 0.98x 0.99x 0.98x 256B 1.20x 1.21x 1.00x 1.19x 1.15x 1.14x 1.19x 1.20x 1.18x 1.19x 1024B 1.29x 1.30x 1.00x 1.28x 1.23x 1.24x 1.26x 1.28x 1.26x 1.27x 8192B 1.31x 1.32x 1.00x 1.31x 1.25x 1.25x 1.28x 1.29x 1.28x 1.30x 256bit key: (lrw:384bit) (xts:512bit) size ecb-enc ecb-dec cbc-enc cbc-dec ctr-enc ctr-dec lrw-enc lrw-dec xts-enc xts-dec 16B 0.96x 0.96x 1.00x 0.96x 0.97x 0.98x 0.95x 0.95x 0.95x 0.96x 64B 1.00x 0.99x 1.00x 0.98x 0.98x 1.01x 0.98x 0.98x 0.98x 0.98x 256B 1.20x 1.21x 1.00x 1.21x 1.15x 1.15x 1.19x 1.20x 1.18x 1.19x 1024B 1.29x 1.30x 1.00x 1.28x 1.23x 1.23x 1.26x 1.27x 1.26x 1.27x 8192B 1.31x 1.33x 1.00x 1.31x 1.26x 1.26x 1.29x 1.29x 1.28x 1.30x twofish-avx-x86_64 vs aes-asm (8kB block): 128bit 256bit ecb-enc 1.19x 1.63x ecb-dec 1.18x 1.62x cbc-enc 0.75x 1.03x cbc-dec 1.23x 1.67x ctr-enc 1.24x 1.65x ctr-dec 1.24x 1.65x lrw-enc 1.15x 1.53x lrw-dec 1.14x 1.52x xts-enc 1.16x 1.56x xts-dec 1.16x 1.56x Signed-off-by: Johannes Goetzfried Signed-off-by: Herbert Xu --- arch/x86/crypto/Makefile | 2 + arch/x86/crypto/twofish-avx-x86_64-asm_64.S | 301 ++++++++ arch/x86/crypto/twofish_avx_glue.c | 1086 +++++++++++++++++++++++++++ arch/x86/crypto/twofish_glue_3way.c | 2 + crypto/Kconfig | 24 + crypto/tcrypt.c | 23 + crypto/testmgr.c | 60 ++ 7 files changed, 1498 insertions(+) create mode 100644 arch/x86/crypto/twofish-avx-x86_64-asm_64.S create mode 100644 arch/x86/crypto/twofish_avx_glue.c (limited to 'arch') diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 479f95a744f7..3420feef0c70 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_CRYPTO_CAMELLIA_X86_64) += camellia-x86_64.o obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o +obj-$(CONFIG_CRYPTO_TWOFISH_AVX_X86_64) += twofish-avx-x86_64.o obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o obj-$(CONFIG_CRYPTO_SERPENT_SSE2_X86_64) += serpent-sse2-x86_64.o obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o @@ -30,6 +31,7 @@ camellia-x86_64-y := camellia-x86_64-asm_64.o camellia_glue.o blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o +twofish-avx-x86_64-y := twofish-avx-x86_64-asm_64.o twofish_avx_glue.o salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o serpent-sse2-x86_64-y := serpent-sse2-x86_64-asm_64.o serpent_sse2_glue.o diff --git a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S new file mode 100644 index 000000000000..fc31b89ba4c3 --- /dev/null +++ b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S @@ -0,0 +1,301 @@ +/* + * Twofish Cipher 8-way parallel algorithm (AVX/x86_64) + * + * Copyright (C) 2012 Johannes Goetzfried + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + */ + +.file "twofish-avx-x86_64-asm_64.S" +.text + +/* structure of crypto context */ +#define s0 0 +#define s1 1024 +#define s2 2048 +#define s3 3072 +#define w 4096 +#define k 4128 + +/********************************************************************** + 8-way AVX twofish + **********************************************************************/ +#define CTX %rdi + +#define RA1 %xmm0 +#define RB1 %xmm1 +#define RC1 %xmm2 +#define RD1 %xmm3 + +#define RA2 %xmm4 +#define RB2 %xmm5 +#define RC2 %xmm6 +#define RD2 %xmm7 + +#define RX %xmm8 +#define RY %xmm9 + +#define RK1 %xmm10 +#define RK2 %xmm11 + +#define RID1 %rax +#define RID1b %al +#define RID2 %rbx +#define RID2b %bl + +#define RGI1 %rdx +#define RGI1bl %dl +#define RGI1bh %dh +#define RGI2 %rcx +#define RGI2bl %cl +#define RGI2bh %ch + +#define RGS1 %r8 +#define RGS1d %r8d +#define RGS2 %r9 +#define RGS2d %r9d +#define RGS3 %r10 +#define RGS3d %r10d + + +#define lookup_32bit(t0, t1, t2, t3, src, dst) \ + movb src ## bl, RID1b; \ + movb src ## bh, RID2b; \ + movl t0(CTX, RID1, 4), dst ## d; \ + xorl t1(CTX, RID2, 4), dst ## d; \ + shrq $16, src; \ + movb src ## bl, RID1b; \ + movb src ## bh, RID2b; \ + xorl t2(CTX, RID1, 4), dst ## d; \ + xorl t3(CTX, RID2, 4), dst ## d; + +#define G(a, x, t0, t1, t2, t3) \ + vmovq a, RGI1; \ + vpsrldq $8, a, x; \ + vmovq x, RGI2; \ + \ + lookup_32bit(t0, t1, t2, t3, RGI1, RGS1); \ + shrq $16, RGI1; \ + lookup_32bit(t0, t1, t2, t3, RGI1, RGS2); \ + shlq $32, RGS2; \ + orq RGS1, RGS2; \ + \ + lookup_32bit(t0, t1, t2, t3, RGI2, RGS1); \ + shrq $16, RGI2; \ + lookup_32bit(t0, t1, t2, t3, RGI2, RGS3); \ + shlq $32, RGS3; \ + orq RGS1, RGS3; \ + \ + vmovq RGS2, x; \ + vpinsrq $1, RGS3, x, x; + +#define encround(a, b, c, d, x, y) \ + G(a, x, s0, s1, s2, s3); \ + G(b, y, s1, s2, s3, s0); \ + vpaddd x, y, x; \ + vpaddd y, x, y; \ + vpaddd x, RK1, x; \ + vpaddd y, RK2, y; \ + vpxor x, c, c; \ + vpsrld $1, c, x; \ + vpslld $(32 - 1), c, c; \ + vpor c, x, c; \ + vpslld $1, d, x; \ + vpsrld $(32 - 1), d, d; \ + vpor d, x, d; \ + vpxor d, y, d; + +#define decround(a, b, c, d, x, y) \ + G(a, x, s0, s1, s2, s3); \ + G(b, y, s1, s2, s3, s0); \ + vpaddd x, y, x; \ + vpaddd y, x, y; \ + vpaddd y, RK2, y; \ + vpxor d, y, d; \ + vpsrld $1, d, y; \ + vpslld $(32 - 1), d, d; \ + vpor d, y, d; \ + vpslld $1, c, y; \ + vpsrld $(32 - 1), c, c; \ + vpor c, y, c; \ + vpaddd x, RK1, x; \ + vpxor x, c, c; + +#define encrypt_round(n, a, b, c, d) \ + vbroadcastss (k+4*(2*(n)))(CTX), RK1; \ + vbroadcastss (k+4*(2*(n)+1))(CTX), RK2; \ + encround(a ## 1, b ## 1, c ## 1, d ## 1, RX, RY); \ + encround(a ## 2, b ## 2, c ## 2, d ## 2, RX, RY); + +#define decrypt_round(n, a, b, c, d) \ + vbroadcastss (k+4*(2*(n)))(CTX), RK1; \ + vbroadcastss (k+4*(2*(n)+1))(CTX), RK2; \ + decround(a ## 1, b ## 1, c ## 1, d ## 1, RX, RY); \ + decround(a ## 2, b ## 2, c ## 2, d ## 2, RX, RY); + +#define encrypt_cycle(n) \ + encrypt_round((2*n), RA, RB, RC, RD); \ + encrypt_round(((2*n) + 1), RC, RD, RA, RB); + +#define decrypt_cycle(n) \ + decrypt_round(((2*n) + 1), RC, RD, RA, RB); \ + decrypt_round((2*n), RA, RB, RC, RD); + + +#define transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ + vpunpckldq x1, x0, t0; \ + vpunpckhdq x1, x0, t2; \ + vpunpckldq x3, x2, t1; \ + vpunpckhdq x3, x2, x3; \ + \ + vpunpcklqdq t1, t0, x0; \ + vpunpckhqdq t1, t0, x1; \ + vpunpcklqdq x3, t2, x2; \ + vpunpckhqdq x3, t2, x3; + +#define inpack_blocks(in, x0, x1, x2, x3, wkey, t0, t1, t2) \ + vpxor (0*4*4)(in), wkey, x0; \ + vpxor (1*4*4)(in), wkey, x1; \ + vpxor (2*4*4)(in), wkey, x2; \ + vpxor (3*4*4)(in), wkey, x3; \ + \ + transpose_4x4(x0, x1, x2, x3, t0, t1, t2) + +#define outunpack_blocks(out, x0, x1, x2, x3, wkey, t0, t1, t2) \ + transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ + \ + vpxor x0, wkey, x0; \ + vmovdqu x0, (0*4*4)(out); \ + vpxor x1, wkey, x1; \ + vmovdqu x1, (1*4*4)(out); \ + vpxor x2, wkey, x2; \ + vmovdqu x2, (2*4*4)(out); \ + vpxor x3, wkey, x3; \ + vmovdqu x3, (3*4*4)(out); + +#define outunpack_xor_blocks(out, x0, x1, x2, x3, wkey, t0, t1, t2) \ + transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ + \ + vpxor x0, wkey, x0; \ + vpxor (0*4*4)(out), x0, x0; \ + vmovdqu x0, (0*4*4)(out); \ + vpxor x1, wkey, x1; \ + vpxor (1*4*4)(out), x1, x1; \ + vmovdqu x1, (1*4*4)(out); \ + vpxor x2, wkey, x2; \ + vpxor (2*4*4)(out), x2, x2; \ + vmovdqu x2, (2*4*4)(out); \ + vpxor x3, wkey, x3; \ + vpxor (3*4*4)(out), x3, x3; \ + vmovdqu x3, (3*4*4)(out); + +.align 8 +.global __twofish_enc_blk_8way +.type __twofish_enc_blk_8way,@function; + +__twofish_enc_blk_8way: + /* input: + * %rdi: ctx, CTX + * %rsi: dst + * %rdx: src + * %rcx: bool, if true: xor output + */ + + pushq %rbx; + pushq %rcx; + + vmovdqu w(CTX), RK1; + + leaq (4*4*4)(%rdx), %rax; + inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RK1, RX, RY, RK2); + inpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX, RY, RK2); + + xorq RID1, RID1; + xorq RID2, RID2; + + encrypt_cycle(0); + encrypt_cycle(1); + encrypt_cycle(2); + encrypt_cycle(3); + encrypt_cycle(4); + encrypt_cycle(5); + encrypt_cycle(6); + encrypt_cycle(7); + + vmovdqu (w+4*4)(CTX), RK1; + + popq %rcx; + popq %rbx; + + leaq (4*4*4)(%rsi), %rax; + leaq (4*4*4)(%rax), %rdx; + + testb %cl, %cl; + jnz __enc_xor8; + + outunpack_blocks(%rsi, RC1, RD1, RA1, RB1, RK1, RX, RY, RK2); + outunpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX, RY, RK2); + + ret; + +__enc_xor8: + outunpack_xor_blocks(%rsi, RC1, RD1, RA1, RB1, RK1, RX, RY, RK2); + outunpack_xor_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX, RY, RK2); + + ret; + +.align 8 +.global twofish_dec_blk_8way +.type twofish_dec_blk_8way,@function; + +twofish_dec_blk_8way: + /* input: + * %rdi: ctx, CTX + * %rsi: dst + * %rdx: src + */ + + pushq %rbx; + + vmovdqu (w+4*4)(CTX), RK1; + + leaq (4*4*4)(%rdx), %rax; + inpack_blocks(%rdx, RC1, RD1, RA1, RB1, RK1, RX, RY, RK2); + inpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX, RY, RK2); + + xorq RID1, RID1; + xorq RID2, RID2; + + decrypt_cycle(7); + decrypt_cycle(6); + decrypt_cycle(5); + decrypt_cycle(4); + decrypt_cycle(3); + decrypt_cycle(2); + decrypt_cycle(1); + decrypt_cycle(0); + + vmovdqu (w)(CTX), RK1; + + popq %rbx; + + leaq (4*4*4)(%rsi), %rax; + outunpack_blocks(%rsi, RA1, RB1, RC1, RD1, RK1, RX, RY, RK2); + outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX, RY, RK2); + + ret; diff --git a/arch/x86/crypto/twofish_avx_glue.c b/arch/x86/crypto/twofish_avx_glue.c new file mode 100644 index 000000000000..599f19e4bef6 --- /dev/null +++ b/arch/x86/crypto/twofish_avx_glue.c @@ -0,0 +1,1086 @@ +/* + * Glue Code for AVX assembler version of Twofish Cipher + * + * Copyright (C) 2012 Johannes Goetzfried + * + * + * Glue code based on serpent_sse2_glue.c by: + * Copyright (C) 2011 Jussi Kivilinna + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define TWOFISH_PARALLEL_BLOCKS 8 + +/* regular block cipher functions from twofish_x86_64 module */ +asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst, + const u8 *src); +asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst, + const u8 *src); + +/* 3-way parallel cipher functions from twofish_x86_64-3way module */ +asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, + const u8 *src, bool xor); +asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst, + const u8 *src); + +static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, + const u8 *src) +{ + __twofish_enc_blk_3way(ctx, dst, src, false); +} + +static inline void twofish_enc_blk_3way_xor(struct twofish_ctx *ctx, u8 *dst, + const u8 *src) +{ + __twofish_enc_blk_3way(ctx, dst, src, true); +} + +/* 8-way parallel cipher functions */ +asmlinkage void __twofish_enc_blk_8way(struct twofish_ctx *ctx, u8 *dst, + const u8 *src, bool xor); +asmlinkage void twofish_dec_blk_8way(struct twofish_ctx *ctx, u8 *dst, + const u8 *src); + +static inline void twofish_enc_blk_xway(struct twofish_ctx *ctx, u8 *dst, + const u8 *src) +{ + __twofish_enc_blk_8way(ctx, dst, src, false); +} + +static inline void twofish_enc_blk_xway_xor(struct twofish_ctx *ctx, u8 *dst, + const u8 *src) +{ + __twofish_enc_blk_8way(ctx, dst, src, true); +} + +static inline void twofish_dec_blk_xway(struct twofish_ctx *ctx, u8 *dst, + const u8 *src) +{ + twofish_dec_blk_8way(ctx, dst, src); +} + + + +struct async_twofish_ctx { + struct cryptd_ablkcipher *cryptd_tfm; +}; + +static inline bool twofish_fpu_begin(bool fpu_enabled, unsigned int nbytes) +{ + if (fpu_enabled) + return true; + + /* AVX is only used when chunk to be processed is large enough, so + * do not enable FPU until it is necessary. + */ + if (nbytes < TF_BLOCK_SIZE * TWOFISH_PARALLEL_BLOCKS) + return false; + + kernel_fpu_begin(); + return true; +} + +static inline void twofish_fpu_end(bool fpu_enabled) +{ + if (fpu_enabled) + kernel_fpu_end(); +} + +static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk, + bool enc) +{ + bool fpu_enabled = false; + struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = TF_BLOCK_SIZE; + unsigned int nbytes; + int err; + + err = blkcipher_walk_virt(desc, walk); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + + while ((nbytes = walk->nbytes)) { + u8 *wsrc = walk->src.virt.addr; + u8 *wdst = walk->dst.virt.addr; + + fpu_enabled = twofish_fpu_begin(fpu_enabled, nbytes); + + /* Process multi-block batch */ + if (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS) { + do { + if (enc) + twofish_enc_blk_xway(ctx, wdst, wsrc); + else + twofish_dec_blk_xway(ctx, wdst, wsrc); + + wsrc += bsize * TWOFISH_PARALLEL_BLOCKS; + wdst += bsize * TWOFISH_PARALLEL_BLOCKS; + nbytes -= bsize * TWOFISH_PARALLEL_BLOCKS; + } while (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS); + + if (nbytes < bsize) + goto done; + } + + /* Process three block batch */ + if (nbytes >= bsize * 3) { + do { + if (enc) + twofish_enc_blk_3way(ctx, wdst, wsrc); + else + twofish_dec_blk_3way(ctx, wdst, wsrc); + + wsrc += bsize * 3; + wdst += bsize * 3; + nbytes -= bsize * 3; + } while (nbytes >= bsize * 3); + + if (nbytes < bsize) + goto done; + } + + /* Handle leftovers */ + do { + if (enc) + twofish_enc_blk(ctx, wdst, wsrc); + else + twofish_dec_blk(ctx, wdst, wsrc); + + wsrc += bsize; + wdst += bsize; + nbytes -= bsize; + } while (nbytes >= bsize); + +done: + err = blkcipher_walk_done(desc, walk, nbytes); + } + + twofish_fpu_end(fpu_enabled); + return err; +} + +static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + + blkcipher_walk_init(&walk, dst, src, nbytes); + return ecb_crypt(desc, &walk, true); +} + +static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + + blkcipher_walk_init(&walk, dst, src, nbytes); + return ecb_crypt(desc, &walk, false); +} + +static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = TF_BLOCK_SIZE; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 *iv = (u128 *)walk->iv; + + do { + u128_xor(dst, src, iv); + twofish_enc_blk(ctx, (u8 *)dst, (u8 *)dst); + iv = dst; + + src += 1; + dst += 1; + nbytes -= bsize; + } while (nbytes >= bsize); + + u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv); + return nbytes; +} + +static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + + while ((nbytes = walk.nbytes)) { + nbytes = __cbc_encrypt(desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + return err; +} + +static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = TF_BLOCK_SIZE; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 ivs[TWOFISH_PARALLEL_BLOCKS - 1]; + u128 last_iv; + int i; + + /* Start of the last block. */ + src += nbytes / bsize - 1; + dst += nbytes / bsize - 1; + + last_iv = *src; + + /* Process multi-block batch */ + if (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS) { + do { + nbytes -= bsize * (TWOFISH_PARALLEL_BLOCKS - 1); + src -= TWOFISH_PARALLEL_BLOCKS - 1; + dst -= TWOFISH_PARALLEL_BLOCKS - 1; + + for (i = 0; i < TWOFISH_PARALLEL_BLOCKS - 1; i++) + ivs[i] = src[i]; + + twofish_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src); + + for (i = 0; i < TWOFISH_PARALLEL_BLOCKS - 1; i++) + u128_xor(dst + (i + 1), dst + (i + 1), ivs + i); + + nbytes -= bsize; + if (nbytes < bsize) + goto done; + + u128_xor(dst, dst, src - 1); + src -= 1; + dst -= 1; + } while (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS); + + if (nbytes < bsize) + goto done; + } + + /* Process three block batch */ + if (nbytes >= bsize * 3) { + do { + nbytes -= bsize * (3 - 1); + src -= 3 - 1; + dst -= 3 - 1; + + ivs[0] = src[0]; + ivs[1] = src[1]; + + twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src); + + u128_xor(dst + 1, dst + 1, ivs + 0); + u128_xor(dst + 2, dst + 2, ivs + 1); + + nbytes -= bsize; + if (nbytes < bsize) + goto done; + + u128_xor(dst, dst, src - 1); + src -= 1; + dst -= 1; + } while (nbytes >= bsize * 3); + + if (nbytes < bsize) + goto done; + } + + /* Handle leftovers */ + for (;;) { + twofish_dec_blk(ctx, (u8 *)dst, (u8 *)src); + + nbytes -= bsize; + if (nbytes < bsize) + break; + + u128_xor(dst, dst, src - 1); + src -= 1; + dst -= 1; + } + +done: + u128_xor(dst, dst, (u128 *)walk->iv); + *(u128 *)walk->iv = last_iv; + + return nbytes; +} + +static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + bool fpu_enabled = false; + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + + while ((nbytes = walk.nbytes)) { + fpu_enabled = twofish_fpu_begin(fpu_enabled, nbytes); + nbytes = __cbc_decrypt(desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + twofish_fpu_end(fpu_enabled); + return err; +} + +static inline void u128_to_be128(be128 *dst, const u128 *src) +{ + dst->a = cpu_to_be64(src->a); + dst->b = cpu_to_be64(src->b); +} + +static inline void be128_to_u128(u128 *dst, const be128 *src) +{ + dst->a = be64_to_cpu(src->a); + dst->b = be64_to_cpu(src->b); +} + +static inline void u128_inc(u128 *i) +{ + i->b++; + if (!i->b) + i->a++; +} + +static void ctr_crypt_final(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + u8 *ctrblk = walk->iv; + u8 keystream[TF_BLOCK_SIZE]; + u8 *src = walk->src.virt.addr; + u8 *dst = walk->dst.virt.addr; + unsigned int nbytes = walk->nbytes; + + twofish_enc_blk(ctx, keystream, ctrblk); + crypto_xor(keystream, src, nbytes); + memcpy(dst, keystream, nbytes); + + crypto_inc(ctrblk, TF_BLOCK_SIZE); +} + +static unsigned int __ctr_crypt(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = TF_BLOCK_SIZE; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 ctrblk; + be128 ctrblocks[TWOFISH_PARALLEL_BLOCKS]; + int i; + + be128_to_u128(&ctrblk, (be128 *)walk->iv); + + /* Process multi-block batch */ + if (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS) { + do { + /* create ctrblks for parallel encrypt */ + for (i = 0; i < TWOFISH_PARALLEL_BLOCKS; i++) { + if (dst != src) + dst[i] = src[i]; + + u128_to_be128(&ctrblocks[i], &ctrblk); + u128_inc(&ctrblk); + } + + twofish_enc_blk_xway_xor(ctx, (u8 *)dst, + (u8 *)ctrblocks); + + src += TWOFISH_PARALLEL_BLOCKS; + dst += TWOFISH_PARALLEL_BLOCKS; + nbytes -= bsize * TWOFISH_PARALLEL_BLOCKS; + } while (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS); + + if (nbytes < bsize) + goto done; + } + + /* Process three block batch */ + if (nbytes >= bsize * 3) { + do { + if (dst != src) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + } + + /* create ctrblks for parallel encrypt */ + u128_to_be128(&ctrblocks[0], &ctrblk); + u128_inc(&ctrblk); + u128_to_be128(&ctrblocks[1], &ctrblk); + u128_inc(&ctrblk); + u128_to_be128(&ctrblocks[2], &ctrblk); + u128_inc(&ctrblk); + + twofish_enc_blk_3way_xor(ctx, (u8 *)dst, + (u8 *)ctrblocks); + + src += 3; + dst += 3; + nbytes -= bsize * 3; + } while (nbytes >= bsize * 3); + + if (nbytes < bsize) + goto done; + } + + /* Handle leftovers */ + do { + if (dst != src) + *dst = *src; + + u128_to_be128(&ctrblocks[0], &ctrblk); + u128_inc(&ctrblk); + + twofish_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks); + u128_xor(dst, dst, (u128 *)ctrblocks); + + src += 1; + dst += 1; + nbytes -= bsize; + } while (nbytes >= bsize); + +done: + u128_to_be128((be128 *)walk->iv, &ctrblk); + return nbytes; +} + +static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + bool fpu_enabled = false; + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt_block(desc, &walk, TF_BLOCK_SIZE); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + + while ((nbytes = walk.nbytes) >= TF_BLOCK_SIZE) { + fpu_enabled = twofish_fpu_begin(fpu_enabled, nbytes); + nbytes = __ctr_crypt(desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + twofish_fpu_end(fpu_enabled); + + if (walk.nbytes) { + ctr_crypt_final(desc, &walk); + err = blkcipher_walk_done(desc, &walk, 0); + } + + return err; +} + +struct crypt_priv { + struct twofish_ctx *ctx; + bool fpu_enabled; +}; + +static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) +{ + const unsigned int bsize = TF_BLOCK_SIZE; + struct crypt_priv *ctx = priv; + int i; + + ctx->fpu_enabled = twofish_fpu_begin(ctx->fpu_enabled, nbytes); + + if (nbytes == bsize * TWOFISH_PARALLEL_BLOCKS) { + twofish_enc_blk_xway(ctx->ctx, srcdst, srcdst); + return; + } + + for (i = 0; i < nbytes / (bsize * 3); i++, srcdst += bsize * 3) + twofish_enc_blk_3way(ctx->ctx, srcdst, srcdst); + + nbytes %= bsize * 3; + + for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) + twofish_enc_blk(ctx->ctx, srcdst, srcdst); +} + +static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) +{ + const unsigned int bsize = TF_BLOCK_SIZE; + struct crypt_priv *ctx = priv; + int i; + + ctx->fpu_enabled = twofish_fpu_begin(ctx->fpu_enabled, nbytes); + + if (nbytes == bsize * TWOFISH_PARALLEL_BLOCKS) { + twofish_dec_blk_xway(ctx->ctx, srcdst, srcdst); + return; + } + + for (i = 0; i < nbytes / (bsize * 3); i++, srcdst += bsize * 3) + twofish_dec_blk_3way(ctx->ctx, srcdst, srcdst); + + nbytes %= bsize * 3; + + for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) + twofish_dec_blk(ctx->ctx, srcdst, srcdst); +} + +struct twofish_lrw_ctx { + struct lrw_table_ctx lrw_table; + struct twofish_ctx twofish_ctx; +}; + +static int lrw_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen) +{ + struct twofish_lrw_ctx *ctx = crypto_tfm_ctx(tfm); + int err; + + err = __twofish_setkey(&ctx->twofish_ctx, key, + keylen - TF_BLOCK_SIZE, &tfm->crt_flags); + if (err) + return err; + + return lrw_init_table(&ctx->lrw_table, key + keylen - + TF_BLOCK_SIZE); +} + +static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct twofish_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[TWOFISH_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->twofish_ctx, + .fpu_enabled = false, + }; + struct lrw_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .table_ctx = &ctx->lrw_table, + .crypt_ctx = &crypt_ctx, + .crypt_fn = encrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = lrw_crypt(desc, dst, src, nbytes, &req); + twofish_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct twofish_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[TWOFISH_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->twofish_ctx, + .fpu_enabled = false, + }; + struct lrw_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .table_ctx = &ctx->lrw_table, + .crypt_ctx = &crypt_ctx, + .crypt_fn = decrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = lrw_crypt(desc, dst, src, nbytes, &req); + twofish_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static void lrw_exit_tfm(struct crypto_tfm *tfm) +{ + struct twofish_lrw_ctx *ctx = crypto_tfm_ctx(tfm); + + lrw_free_table(&ctx->lrw_table); +} + +struct twofish_xts_ctx { + struct twofish_ctx tweak_ctx; + struct twofish_ctx crypt_ctx; +}; + +static int xts_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen) +{ + struct twofish_xts_ctx *ctx = crypto_tfm_ctx(tfm); + u32 *flags = &tfm->crt_flags; + int err; + + /* key consists of keys of equal size concatenated, therefore + * the length must be even + */ + if (keylen % 2) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + /* first half of xts-key is for crypt */ + err = __twofish_setkey(&ctx->crypt_ctx, key, keylen / 2, flags); + if (err) + return err; + + /* second half of xts-key is for tweak */ + return __twofish_setkey(&ctx->tweak_ctx, + key + keylen / 2, keylen / 2, flags); +} + +static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct twofish_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[TWOFISH_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->crypt_ctx, + .fpu_enabled = false, + }; + struct xts_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .tweak_ctx = &ctx->tweak_ctx, + .tweak_fn = XTS_TWEAK_CAST(twofish_enc_blk), + .crypt_ctx = &crypt_ctx, + .crypt_fn = encrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = xts_crypt(desc, dst, src, nbytes, &req); + twofish_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct twofish_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[TWOFISH_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->crypt_ctx, + .fpu_enabled = false, + }; + struct xts_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .tweak_ctx = &ctx->tweak_ctx, + .tweak_fn = XTS_TWEAK_CAST(twofish_enc_blk), + .crypt_ctx = &crypt_ctx, + .crypt_fn = decrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = xts_crypt(desc, dst, src, nbytes, &req); + twofish_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int key_len) +{ + struct async_twofish_ctx *ctx = crypto_ablkcipher_ctx(tfm); + struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base; + int err; + + crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); + crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm) + & CRYPTO_TFM_REQ_MASK); + err = crypto_ablkcipher_setkey(child, key, key_len); + crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child) + & CRYPTO_TFM_RES_MASK); + return err; +} + +static int __ablk_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_twofish_ctx *ctx = crypto_ablkcipher_ctx(tfm); + struct blkcipher_desc desc; + + desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); + desc.info = req->info; + desc.flags = 0; + + return crypto_blkcipher_crt(desc.tfm)->encrypt( + &desc, req->dst, req->src, req->nbytes); +} + +static int ablk_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_twofish_ctx *ctx = crypto_ablkcipher_ctx(tfm); + + if (!irq_fpu_usable()) { + struct ablkcipher_request *cryptd_req = + ablkcipher_request_ctx(req); + + memcpy(cryptd_req, req, sizeof(*req)); + ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); + + return crypto_ablkcipher_encrypt(cryptd_req); + } else { + return __ablk_encrypt(req); + } +} + +static int ablk_decrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_twofish_ctx *ctx = crypto_ablkcipher_ctx(tfm); + + if (!irq_fpu_usable()) { + struct ablkcipher_request *cryptd_req = + ablkcipher_request_ctx(req); + + memcpy(cryptd_req, req, sizeof(*req)); + ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); + + return crypto_ablkcipher_decrypt(cryptd_req); + } else { + struct blkcipher_desc desc; + + desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); + desc.info = req->info; + desc.flags = 0; + + return crypto_blkcipher_crt(desc.tfm)->decrypt( + &desc, req->dst, req->src, req->nbytes); + } +} + +static void ablk_exit(struct crypto_tfm *tfm) +{ + struct async_twofish_ctx *ctx = crypto_tfm_ctx(tfm); + + cryptd_free_ablkcipher(ctx->cryptd_tfm); +} + +static int ablk_init(struct crypto_tfm *tfm) +{ + struct async_twofish_ctx *ctx = crypto_tfm_ctx(tfm); + struct cryptd_ablkcipher *cryptd_tfm; + char drv_name[CRYPTO_MAX_ALG_NAME]; + + snprintf(drv_name, sizeof(drv_name), "__driver-%s", + crypto_tfm_alg_driver_name(tfm)); + + cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); + if (IS_ERR(cryptd_tfm)) + return PTR_ERR(cryptd_tfm); + + ctx->cryptd_tfm = cryptd_tfm; + tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + + crypto_ablkcipher_reqsize(&cryptd_tfm->base); + + return 0; +} + +static struct crypto_alg twofish_algs[10] = { { + .cra_name = "__ecb-twofish-avx", + .cra_driver_name = "__driver-ecb-twofish-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[0].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = TF_MIN_KEY_SIZE, + .max_keysize = TF_MAX_KEY_SIZE, + .setkey = twofish_setkey, + .encrypt = ecb_encrypt, + .decrypt = ecb_decrypt, + }, + }, +}, { + .cra_name = "__cbc-twofish-avx", + .cra_driver_name = "__driver-cbc-twofish-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[1].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = TF_MIN_KEY_SIZE, + .max_keysize = TF_MAX_KEY_SIZE, + .setkey = twofish_setkey, + .encrypt = cbc_encrypt, + .decrypt = cbc_decrypt, + }, + }, +}, { + .cra_name = "__ctr-twofish-avx", + .cra_driver_name = "__driver-ctr-twofish-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[2].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = TF_MIN_KEY_SIZE, + .max_keysize = TF_MAX_KEY_SIZE, + .ivsize = TF_BLOCK_SIZE, + .setkey = twofish_setkey, + .encrypt = ctr_crypt, + .decrypt = ctr_crypt, + }, + }, +}, { + .cra_name = "__lrw-twofish-avx", + .cra_driver_name = "__driver-lrw-twofish-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct twofish_lrw_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[3].cra_list), + .cra_exit = lrw_exit_tfm, + .cra_u = { + .blkcipher = { + .min_keysize = TF_MIN_KEY_SIZE + + TF_BLOCK_SIZE, + .max_keysize = TF_MAX_KEY_SIZE + + TF_BLOCK_SIZE, + .ivsize = TF_BLOCK_SIZE, + .setkey = lrw_twofish_setkey, + .encrypt = lrw_encrypt, + .decrypt = lrw_decrypt, + }, + }, +}, { + .cra_name = "__xts-twofish-avx", + .cra_driver_name = "__driver-xts-twofish-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct twofish_xts_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[4].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = TF_MIN_KEY_SIZE * 2, + .max_keysize = TF_MAX_KEY_SIZE * 2, + .ivsize = TF_BLOCK_SIZE, + .setkey = xts_twofish_setkey, + .encrypt = xts_encrypt, + .decrypt = xts_decrypt, + }, + }, +}, { + .cra_name = "ecb(twofish)", + .cra_driver_name = "ecb-twofish-avx", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[5].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = TF_MIN_KEY_SIZE, + .max_keysize = TF_MAX_KEY_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +}, { + .cra_name = "cbc(twofish)", + .cra_driver_name = "cbc-twofish-avx", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[6].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = TF_MIN_KEY_SIZE, + .max_keysize = TF_MAX_KEY_SIZE, + .ivsize = TF_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = __ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +}, { + .cra_name = "ctr(twofish)", + .cra_driver_name = "ctr-twofish-avx", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[7].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = TF_MIN_KEY_SIZE, + .max_keysize = TF_MAX_KEY_SIZE, + .ivsize = TF_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_encrypt, + .geniv = "chainiv", + }, + }, +}, { + .cra_name = "lrw(twofish)", + .cra_driver_name = "lrw-twofish-avx", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[8].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = TF_MIN_KEY_SIZE + + TF_BLOCK_SIZE, + .max_keysize = TF_MAX_KEY_SIZE + + TF_BLOCK_SIZE, + .ivsize = TF_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +}, { + .cra_name = "xts(twofish)", + .cra_driver_name = "xts-twofish-avx", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(twofish_algs[9].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = TF_MIN_KEY_SIZE * 2, + .max_keysize = TF_MAX_KEY_SIZE * 2, + .ivsize = TF_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +} }; + +static int __init twofish_init(void) +{ + u64 xcr0; + + if (!cpu_has_avx || !cpu_has_osxsave) { + printk(KERN_INFO "AVX instructions are not detected.\n"); + return -ENODEV; + } + + xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK); + if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) { + printk(KERN_INFO "AVX detected but unusable.\n"); + return -ENODEV; + } + + return crypto_register_algs(twofish_algs, ARRAY_SIZE(twofish_algs)); +} + +static void __exit twofish_exit(void) +{ + crypto_unregister_algs(twofish_algs, ARRAY_SIZE(twofish_algs)); +} + +module_init(twofish_init); +module_exit(twofish_exit); + +MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("twofish"); diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c index 922ab24cce31..77e4e55a2660 100644 --- a/arch/x86/crypto/twofish_glue_3way.c +++ b/arch/x86/crypto/twofish_glue_3way.c @@ -45,8 +45,10 @@ asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst, /* 3-way parallel cipher functions */ asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, const u8 *src, bool xor); +EXPORT_SYMBOL_GPL(__twofish_enc_blk_3way); asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst, const u8 *src); +EXPORT_SYMBOL_GPL(twofish_dec_blk_3way); static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, const u8 *src) diff --git a/crypto/Kconfig b/crypto/Kconfig index 8e84225c096b..e00a4e49e013 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -913,6 +913,30 @@ config CRYPTO_TWOFISH_X86_64_3WAY See also: +config CRYPTO_TWOFISH_AVX_X86_64 + tristate "Twofish cipher algorithm (x86_64/AVX)" + depends on X86 && 64BIT + select CRYPTO_ALGAPI + select CRYPTO_CRYPTD + select CRYPTO_TWOFISH_COMMON + select CRYPTO_TWOFISH_X86_64 + select CRYPTO_TWOFISH_X86_64_3WAY + select CRYPTO_LRW + select CRYPTO_XTS + help + Twofish cipher algorithm (x86_64/AVX). + + Twofish was submitted as an AES (Advanced Encryption Standard) + candidate cipher by researchers at CounterPane Systems. It is a + 16 round block cipher supporting key sizes of 128, 192, and 256 + bits. + + This module provides the Twofish cipher algorithm that processes + eight blocks parallel using the AVX Instruction Set. + + See also: + + comment "Compression" config CRYPTO_DEFLATE diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 750cce44bad6..2af879786e75 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -1566,6 +1566,29 @@ static int do_test(int m) speed_template_32_64); break; + case 504: + test_acipher_speed("ecb(twofish)", ENCRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("ecb(twofish)", DECRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("cbc(twofish)", ENCRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("cbc(twofish)", DECRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("ctr(twofish)", ENCRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("ctr(twofish)", DECRYPT, sec, NULL, 0, + speed_template_16_24_32); + test_acipher_speed("lrw(twofish)", ENCRYPT, sec, NULL, 0, + speed_template_32_40_48); + test_acipher_speed("lrw(twofish)", DECRYPT, sec, NULL, 0, + speed_template_32_40_48); + test_acipher_speed("xts(twofish)", ENCRYPT, sec, NULL, 0, + speed_template_32_48_64); + test_acipher_speed("xts(twofish)", DECRYPT, sec, NULL, 0, + speed_template_32_48_64); + break; + case 1000: test_available(); break; diff --git a/crypto/testmgr.c b/crypto/testmgr.c index eb6d20f8ec5d..73b3ec6fe1a2 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -1548,6 +1548,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "__cbc-twofish-avx", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "__driver-cbc-aes-aesni", .test = alg_test_null, @@ -1578,6 +1593,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "__driver-cbc-twofish-avx", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "__driver-ecb-aes-aesni", .test = alg_test_null, @@ -1608,6 +1638,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "__driver-ecb-twofish-avx", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "__ghash-pclmulqdqni", .test = alg_test_null, @@ -1805,6 +1850,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "cryptd(__driver-ecb-twofish-avx)", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "cryptd(__ghash-pclmulqdqni)", .test = alg_test_null, -- cgit v1.2.3 From 7efe4076725aeb01722445b56613681aa492c8d6 Mon Sep 17 00:00:00 2001 From: Johannes Goetzfried Date: Tue, 12 Jun 2012 16:47:43 +0800 Subject: crypto: serpent - add x86_64/avx assembler implementation This patch adds a x86_64/avx assembler implementation of the Serpent block cipher. The implementation is very similar to the sse2 implementation and processes eight blocks in parallel. Because of the new non-destructive three operand syntax all move-instructions can be removed and therefore a little performance increase is provided. Patch has been tested with tcrypt and automated filesystem tests. Tcrypt benchmark results: Intel Core i5-2500 CPU (fam:6, model:42, step:7) serpent-avx-x86_64 vs. serpent-sse2-x86_64 128bit key: (lrw:256bit) (xts:256bit) size ecb-enc ecb-dec cbc-enc cbc-dec ctr-enc ctr-dec lrw-enc lrw-dec xts-enc xts-dec 16B 1.03x 1.01x 1.01x 1.01x 1.00x 1.00x 1.00x 1.00x 1.00x 1.01x 64B 1.00x 1.00x 1.00x 1.00x 1.00x 0.99x 1.00x 1.01x 1.00x 1.00x 256B 1.05x 1.03x 1.00x 1.02x 1.05x 1.06x 1.05x 1.02x 1.05x 1.02x 1024B 1.05x 1.02x 1.00x 1.02x 1.05x 1.06x 1.05x 1.03x 1.05x 1.02x 8192B 1.05x 1.02x 1.00x 1.02x 1.06x 1.06x 1.04x 1.03x 1.04x 1.02x 256bit key: (lrw:384bit) (xts:512bit) size ecb-enc ecb-dec cbc-enc cbc-dec ctr-enc ctr-dec lrw-enc lrw-dec xts-enc xts-dec 16B 1.01x 1.00x 1.01x 1.01x 1.00x 1.00x 0.99x 1.03x 1.01x 1.01x 64B 1.00x 1.00x 1.00x 1.00x 1.00x 1.00x 1.00x 1.01x 1.00x 1.02x 256B 1.05x 1.02x 1.00x 1.02x 1.05x 1.02x 1.04x 1.05x 1.05x 1.02x 1024B 1.06x 1.02x 1.00x 1.02x 1.07x 1.06x 1.05x 1.04x 1.05x 1.02x 8192B 1.05x 1.02x 1.00x 1.02x 1.06x 1.06x 1.04x 1.05x 1.05x 1.02x serpent-avx-x86_64 vs aes-asm (8kB block): 128bit 256bit ecb-enc 1.26x 1.73x ecb-dec 1.20x 1.64x cbc-enc 0.33x 0.45x cbc-dec 1.24x 1.67x ctr-enc 1.32x 1.76x ctr-dec 1.32x 1.76x lrw-enc 1.20x 1.60x lrw-dec 1.15x 1.54x xts-enc 1.22x 1.64x xts-dec 1.17x 1.57x Signed-off-by: Johannes Goetzfried Signed-off-by: Herbert Xu --- arch/x86/crypto/Makefile | 2 + arch/x86/crypto/serpent-avx-x86_64-asm_64.S | 704 +++++++++++++++++++++ arch/x86/crypto/serpent_avx_glue.c | 949 ++++++++++++++++++++++++++++ crypto/Kconfig | 20 + crypto/testmgr.c | 60 ++ 5 files changed, 1735 insertions(+) create mode 100644 arch/x86/crypto/serpent-avx-x86_64-asm_64.S create mode 100644 arch/x86/crypto/serpent_avx_glue.c (limited to 'arch') diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 3420feef0c70..83caa4b948c8 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o obj-$(CONFIG_CRYPTO_TWOFISH_AVX_X86_64) += twofish-avx-x86_64.o obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o obj-$(CONFIG_CRYPTO_SERPENT_SSE2_X86_64) += serpent-sse2-x86_64.o +obj-$(CONFIG_CRYPTO_SERPENT_AVX_X86_64) += serpent-avx-x86_64.o obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o @@ -34,6 +35,7 @@ twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o twofish-avx-x86_64-y := twofish-avx-x86_64-asm_64.o twofish_avx_glue.o salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o serpent-sse2-x86_64-y := serpent-sse2-x86_64-asm_64.o serpent_sse2_glue.o +serpent-avx-x86_64-y := serpent-avx-x86_64-asm_64.o serpent_avx_glue.o aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o diff --git a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S new file mode 100644 index 000000000000..0ed47a124bac --- /dev/null +++ b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S @@ -0,0 +1,704 @@ +/* + * Serpent Cipher 8-way parallel algorithm (x86_64/AVX) + * + * Copyright (C) 2012 Johannes Goetzfried + * + * + * Based on arch/x86/crypto/serpent-sse2-x86_64-asm_64.S by + * Copyright (C) 2011 Jussi Kivilinna + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + */ + +.file "serpent-avx-x86_64-asm_64.S" +.text + +#define CTX %rdi + +/********************************************************************** + 8-way AVX serpent + **********************************************************************/ +#define RA1 %xmm0 +#define RB1 %xmm1 +#define RC1 %xmm2 +#define RD1 %xmm3 +#define RE1 %xmm4 + +#define tp %xmm5 + +#define RA2 %xmm6 +#define RB2 %xmm7 +#define RC2 %xmm8 +#define RD2 %xmm9 +#define RE2 %xmm10 + +#define RNOT %xmm11 + +#define RK0 %xmm12 +#define RK1 %xmm13 +#define RK2 %xmm14 +#define RK3 %xmm15 + + +#define S0_1(x0, x1, x2, x3, x4) \ + vpor x0, x3, tp; \ + vpxor x3, x0, x0; \ + vpxor x2, x3, x4; \ + vpxor RNOT, x4, x4; \ + vpxor x1, tp, x3; \ + vpand x0, x1, x1; \ + vpxor x4, x1, x1; \ + vpxor x0, x2, x2; +#define S0_2(x0, x1, x2, x3, x4) \ + vpxor x3, x0, x0; \ + vpor x0, x4, x4; \ + vpxor x2, x0, x0; \ + vpand x1, x2, x2; \ + vpxor x2, x3, x3; \ + vpxor RNOT, x1, x1; \ + vpxor x4, x2, x2; \ + vpxor x2, x1, x1; + +#define S1_1(x0, x1, x2, x3, x4) \ + vpxor x0, x1, tp; \ + vpxor x3, x0, x0; \ + vpxor RNOT, x3, x3; \ + vpand tp, x1, x4; \ + vpor tp, x0, x0; \ + vpxor x2, x3, x3; \ + vpxor x3, x0, x0; \ + vpxor x3, tp, x1; +#define S1_2(x0, x1, x2, x3, x4) \ + vpxor x4, x3, x3; \ + vpor x4, x1, x1; \ + vpxor x2, x4, x4; \ + vpand x0, x2, x2; \ + vpxor x1, x2, x2; \ + vpor x0, x1, x1; \ + vpxor RNOT, x0, x0; \ + vpxor x2, x0, x0; \ + vpxor x1, x4, x4; + +#define S2_1(x0, x1, x2, x3, x4) \ + vpxor RNOT, x3, x3; \ + vpxor x0, x1, x1; \ + vpand x2, x0, tp; \ + vpxor x3, tp, tp; \ + vpor x0, x3, x3; \ + vpxor x1, x2, x2; \ + vpxor x1, x3, x3; \ + vpand tp, x1, x1; +#define S2_2(x0, x1, x2, x3, x4) \ + vpxor x2, tp, tp; \ + vpand x3, x2, x2; \ + vpor x1, x3, x3; \ + vpxor RNOT, tp, tp; \ + vpxor tp, x3, x3; \ + vpxor tp, x0, x4; \ + vpxor x2, tp, x0; \ + vpor x2, x1, x1; + +#define S3_1(x0, x1, x2, x3, x4) \ + vpxor x3, x1, tp; \ + vpor x0, x3, x3; \ + vpand x0, x1, x4; \ + vpxor x2, x0, x0; \ + vpxor tp, x2, x2; \ + vpand x3, tp, x1; \ + vpxor x3, x2, x2; \ + vpor x4, x0, x0; \ + vpxor x3, x4, x4; +#define S3_2(x0, x1, x2, x3, x4) \ + vpxor x0, x1, x1; \ + vpand x3, x0, x0; \ + vpand x4, x3, x3; \ + vpxor x2, x3, x3; \ + vpor x1, x4, x4; \ + vpand x1, x2, x2; \ + vpxor x3, x4, x4; \ + vpxor x3, x0, x0; \ + vpxor x2, x3, x3; + +#define S4_1(x0, x1, x2, x3, x4) \ + vpand x0, x3, tp; \ + vpxor x3, x0, x0; \ + vpxor x2, tp, tp; \ + vpor x3, x2, x2; \ + vpxor x1, x0, x0; \ + vpxor tp, x3, x4; \ + vpor x0, x2, x2; \ + vpxor x1, x2, x2; +#define S4_2(x0, x1, x2, x3, x4) \ + vpand x0, x1, x1; \ + vpxor x4, x1, x1; \ + vpand x2, x4, x4; \ + vpxor tp, x2, x2; \ + vpxor x0, x4, x4; \ + vpor x1, tp, x3; \ + vpxor RNOT, x1, x1; \ + vpxor x0, x3, x3; + +#define S5_1(x0, x1, x2, x3, x4) \ + vpor x0, x1, tp; \ + vpxor tp, x2, x2; \ + vpxor RNOT, x3, x3; \ + vpxor x0, x1, x4; \ + vpxor x2, x0, x0; \ + vpand x4, tp, x1; \ + vpor x3, x4, x4; \ + vpxor x0, x4, x4; +#define S5_2(x0, x1, x2, x3, x4) \ + vpand x3, x0, x0; \ + vpxor x3, x1, x1; \ + vpxor x2, x3, x3; \ + vpxor x1, x0, x0; \ + vpand x4, x2, x2; \ + vpxor x2, x1, x1; \ + vpand x0, x2, x2; \ + vpxor x2, x3, x3; + +#define S6_1(x0, x1, x2, x3, x4) \ + vpxor x0, x3, x3; \ + vpxor x2, x1, tp; \ + vpxor x0, x2, x2; \ + vpand x3, x0, x0; \ + vpor x3, tp, tp; \ + vpxor RNOT, x1, x4; \ + vpxor tp, x0, x0; \ + vpxor x2, tp, x1; +#define S6_2(x0, x1, x2, x3, x4) \ + vpxor x4, x3, x3; \ + vpxor x0, x4, x4; \ + vpand x0, x2, x2; \ + vpxor x1, x4, x4; \ + vpxor x3, x2, x2; \ + vpand x1, x3, x3; \ + vpxor x0, x3, x3; \ + vpxor x2, x1, x1; + +#define S7_1(x0, x1, x2, x3, x4) \ + vpxor RNOT, x1, tp; \ + vpxor RNOT, x0, x0; \ + vpand x2, tp, x1; \ + vpxor x3, x1, x1; \ + vpor tp, x3, x3; \ + vpxor x2, tp, x4; \ + vpxor x3, x2, x2; \ + vpxor x0, x3, x3; \ + vpor x1, x0, x0; +#define S7_2(x0, x1, x2, x3, x4) \ + vpand x0, x2, x2; \ + vpxor x4, x0, x0; \ + vpxor x3, x4, x4; \ + vpand x0, x3, x3; \ + vpxor x1, x4, x4; \ + vpxor x4, x2, x2; \ + vpxor x1, x3, x3; \ + vpor x0, x4, x4; \ + vpxor x1, x4, x4; + +#define SI0_1(x0, x1, x2, x3, x4) \ + vpxor x0, x1, x1; \ + vpor x1, x3, tp; \ + vpxor x1, x3, x4; \ + vpxor RNOT, x0, x0; \ + vpxor tp, x2, x2; \ + vpxor x0, tp, x3; \ + vpand x1, x0, x0; \ + vpxor x2, x0, x0; +#define SI0_2(x0, x1, x2, x3, x4) \ + vpand x3, x2, x2; \ + vpxor x4, x3, x3; \ + vpxor x3, x2, x2; \ + vpxor x3, x1, x1; \ + vpand x0, x3, x3; \ + vpxor x0, x1, x1; \ + vpxor x2, x0, x0; \ + vpxor x3, x4, x4; + +#define SI1_1(x0, x1, x2, x3, x4) \ + vpxor x3, x1, x1; \ + vpxor x2, x0, tp; \ + vpxor RNOT, x2, x2; \ + vpor x1, x0, x4; \ + vpxor x3, x4, x4; \ + vpand x1, x3, x3; \ + vpxor x2, x1, x1; \ + vpand x4, x2, x2; +#define SI1_2(x0, x1, x2, x3, x4) \ + vpxor x1, x4, x4; \ + vpor x3, x1, x1; \ + vpxor tp, x3, x3; \ + vpxor tp, x2, x2; \ + vpor x4, tp, x0; \ + vpxor x4, x2, x2; \ + vpxor x0, x1, x1; \ + vpxor x1, x4, x4; + +#define SI2_1(x0, x1, x2, x3, x4) \ + vpxor x1, x2, x2; \ + vpxor RNOT, x3, tp; \ + vpor x2, tp, tp; \ + vpxor x3, x2, x2; \ + vpxor x0, x3, x4; \ + vpxor x1, tp, x3; \ + vpor x2, x1, x1; \ + vpxor x0, x2, x2; +#define SI2_2(x0, x1, x2, x3, x4) \ + vpxor x4, x1, x1; \ + vpor x3, x4, x4; \ + vpxor x3, x2, x2; \ + vpxor x2, x4, x4; \ + vpand x1, x2, x2; \ + vpxor x3, x2, x2; \ + vpxor x4, x3, x3; \ + vpxor x0, x4, x4; + +#define SI3_1(x0, x1, x2, x3, x4) \ + vpxor x1, x2, x2; \ + vpand x2, x1, tp; \ + vpxor x0, tp, tp; \ + vpor x1, x0, x0; \ + vpxor x3, x1, x4; \ + vpxor x3, x0, x0; \ + vpor tp, x3, x3; \ + vpxor x2, tp, x1; +#define SI3_2(x0, x1, x2, x3, x4) \ + vpxor x3, x1, x1; \ + vpxor x2, x0, x0; \ + vpxor x3, x2, x2; \ + vpand x1, x3, x3; \ + vpxor x0, x1, x1; \ + vpand x2, x0, x0; \ + vpxor x3, x4, x4; \ + vpxor x0, x3, x3; \ + vpxor x1, x0, x0; + +#define SI4_1(x0, x1, x2, x3, x4) \ + vpxor x3, x2, x2; \ + vpand x1, x0, tp; \ + vpxor x2, tp, tp; \ + vpor x3, x2, x2; \ + vpxor RNOT, x0, x4; \ + vpxor tp, x1, x1; \ + vpxor x2, tp, x0; \ + vpand x4, x2, x2; +#define SI4_2(x0, x1, x2, x3, x4) \ + vpxor x0, x2, x2; \ + vpor x4, x0, x0; \ + vpxor x3, x0, x0; \ + vpand x2, x3, x3; \ + vpxor x3, x4, x4; \ + vpxor x1, x3, x3; \ + vpand x0, x1, x1; \ + vpxor x1, x4, x4; \ + vpxor x3, x0, x0; + +#define SI5_1(x0, x1, x2, x3, x4) \ + vpor x2, x1, tp; \ + vpxor x1, x2, x2; \ + vpxor x3, tp, tp; \ + vpand x1, x3, x3; \ + vpxor x3, x2, x2; \ + vpor x0, x3, x3; \ + vpxor RNOT, x0, x0; \ + vpxor x2, x3, x3; \ + vpor x0, x2, x2; +#define SI5_2(x0, x1, x2, x3, x4) \ + vpxor tp, x1, x4; \ + vpxor x4, x2, x2; \ + vpand x0, x4, x4; \ + vpxor tp, x0, x0; \ + vpxor x3, tp, x1; \ + vpand x2, x0, x0; \ + vpxor x3, x2, x2; \ + vpxor x2, x0, x0; \ + vpxor x4, x2, x2; \ + vpxor x3, x4, x4; + +#define SI6_1(x0, x1, x2, x3, x4) \ + vpxor x2, x0, x0; \ + vpand x3, x0, tp; \ + vpxor x3, x2, x2; \ + vpxor x2, tp, tp; \ + vpxor x1, x3, x3; \ + vpor x0, x2, x2; \ + vpxor x3, x2, x2; \ + vpand tp, x3, x3; +#define SI6_2(x0, x1, x2, x3, x4) \ + vpxor RNOT, tp, tp; \ + vpxor x1, x3, x3; \ + vpand x2, x1, x1; \ + vpxor tp, x0, x4; \ + vpxor x4, x3, x3; \ + vpxor x2, x4, x4; \ + vpxor x1, tp, x0; \ + vpxor x0, x2, x2; + +#define SI7_1(x0, x1, x2, x3, x4) \ + vpand x0, x3, tp; \ + vpxor x2, x0, x0; \ + vpor x3, x2, x2; \ + vpxor x1, x3, x4; \ + vpxor RNOT, x0, x0; \ + vpor tp, x1, x1; \ + vpxor x0, x4, x4; \ + vpand x2, x0, x0; \ + vpxor x1, x0, x0; +#define SI7_2(x0, x1, x2, x3, x4) \ + vpand x2, x1, x1; \ + vpxor x2, tp, x3; \ + vpxor x3, x4, x4; \ + vpand x3, x2, x2; \ + vpor x0, x3, x3; \ + vpxor x4, x1, x1; \ + vpxor x4, x3, x3; \ + vpand x0, x4, x4; \ + vpxor x2, x4, x4; + +#define get_key(i, j, t) \ + vbroadcastss (4*(i)+(j))*4(CTX), t; + +#define K2(x0, x1, x2, x3, x4, i) \ + get_key(i, 0, RK0); \ + get_key(i, 1, RK1); \ + get_key(i, 2, RK2); \ + get_key(i, 3, RK3); \ + vpxor RK0, x0 ## 1, x0 ## 1; \ + vpxor RK1, x1 ## 1, x1 ## 1; \ + vpxor RK2, x2 ## 1, x2 ## 1; \ + vpxor RK3, x3 ## 1, x3 ## 1; \ + vpxor RK0, x0 ## 2, x0 ## 2; \ + vpxor RK1, x1 ## 2, x1 ## 2; \ + vpxor RK2, x2 ## 2, x2 ## 2; \ + vpxor RK3, x3 ## 2, x3 ## 2; + +#define LK2(x0, x1, x2, x3, x4, i) \ + vpslld $13, x0 ## 1, x4 ## 1; \ + vpsrld $(32 - 13), x0 ## 1, x0 ## 1; \ + vpor x4 ## 1, x0 ## 1, x0 ## 1; \ + vpxor x0 ## 1, x1 ## 1, x1 ## 1; \ + vpslld $3, x2 ## 1, x4 ## 1; \ + vpsrld $(32 - 3), x2 ## 1, x2 ## 1; \ + vpor x4 ## 1, x2 ## 1, x2 ## 1; \ + vpxor x2 ## 1, x1 ## 1, x1 ## 1; \ + vpslld $13, x0 ## 2, x4 ## 2; \ + vpsrld $(32 - 13), x0 ## 2, x0 ## 2; \ + vpor x4 ## 2, x0 ## 2, x0 ## 2; \ + vpxor x0 ## 2, x1 ## 2, x1 ## 2; \ + vpslld $3, x2 ## 2, x4 ## 2; \ + vpsrld $(32 - 3), x2 ## 2, x2 ## 2; \ + vpor x4 ## 2, x2 ## 2, x2 ## 2; \ + vpxor x2 ## 2, x1 ## 2, x1 ## 2; \ + vpslld $1, x1 ## 1, x4 ## 1; \ + vpsrld $(32 - 1), x1 ## 1, x1 ## 1; \ + vpor x4 ## 1, x1 ## 1, x1 ## 1; \ + vpslld $3, x0 ## 1, x4 ## 1; \ + vpxor x2 ## 1, x3 ## 1, x3 ## 1; \ + vpxor x4 ## 1, x3 ## 1, x3 ## 1; \ + get_key(i, 1, RK1); \ + vpslld $1, x1 ## 2, x4 ## 2; \ + vpsrld $(32 - 1), x1 ## 2, x1 ## 2; \ + vpor x4 ## 2, x1 ## 2, x1 ## 2; \ + vpslld $3, x0 ## 2, x4 ## 2; \ + vpxor x2 ## 2, x3 ## 2, x3 ## 2; \ + vpxor x4 ## 2, x3 ## 2, x3 ## 2; \ + get_key(i, 3, RK3); \ + vpslld $7, x3 ## 1, x4 ## 1; \ + vpsrld $(32 - 7), x3 ## 1, x3 ## 1; \ + vpor x4 ## 1, x3 ## 1, x3 ## 1; \ + vpslld $7, x1 ## 1, x4 ## 1; \ + vpxor x1 ## 1, x0 ## 1, x0 ## 1; \ + vpxor x3 ## 1, x0 ## 1, x0 ## 1; \ + vpxor x3 ## 1, x2 ## 1, x2 ## 1; \ + vpxor x4 ## 1, x2 ## 1, x2 ## 1; \ + get_key(i, 0, RK0); \ + vpslld $7, x3 ## 2, x4 ## 2; \ + vpsrld $(32 - 7), x3 ## 2, x3 ## 2; \ + vpor x4 ## 2, x3 ## 2, x3 ## 2; \ + vpslld $7, x1 ## 2, x4 ## 2; \ + vpxor x1 ## 2, x0 ## 2, x0 ## 2; \ + vpxor x3 ## 2, x0 ## 2, x0 ## 2; \ + vpxor x3 ## 2, x2 ## 2, x2 ## 2; \ + vpxor x4 ## 2, x2 ## 2, x2 ## 2; \ + get_key(i, 2, RK2); \ + vpxor RK1, x1 ## 1, x1 ## 1; \ + vpxor RK3, x3 ## 1, x3 ## 1; \ + vpslld $5, x0 ## 1, x4 ## 1; \ + vpsrld $(32 - 5), x0 ## 1, x0 ## 1; \ + vpor x4 ## 1, x0 ## 1, x0 ## 1; \ + vpslld $22, x2 ## 1, x4 ## 1; \ + vpsrld $(32 - 22), x2 ## 1, x2 ## 1; \ + vpor x4 ## 1, x2 ## 1, x2 ## 1; \ + vpxor RK0, x0 ## 1, x0 ## 1; \ + vpxor RK2, x2 ## 1, x2 ## 1; \ + vpxor RK1, x1 ## 2, x1 ## 2; \ + vpxor RK3, x3 ## 2, x3 ## 2; \ + vpslld $5, x0 ## 2, x4 ## 2; \ + vpsrld $(32 - 5), x0 ## 2, x0 ## 2; \ + vpor x4 ## 2, x0 ## 2, x0 ## 2; \ + vpslld $22, x2 ## 2, x4 ## 2; \ + vpsrld $(32 - 22), x2 ## 2, x2 ## 2; \ + vpor x4 ## 2, x2 ## 2, x2 ## 2; \ + vpxor RK0, x0 ## 2, x0 ## 2; \ + vpxor RK2, x2 ## 2, x2 ## 2; + +#define KL2(x0, x1, x2, x3, x4, i) \ + vpxor RK0, x0 ## 1, x0 ## 1; \ + vpxor RK2, x2 ## 1, x2 ## 1; \ + vpsrld $5, x0 ## 1, x4 ## 1; \ + vpslld $(32 - 5), x0 ## 1, x0 ## 1; \ + vpor x4 ## 1, x0 ## 1, x0 ## 1; \ + vpxor RK3, x3 ## 1, x3 ## 1; \ + vpxor RK1, x1 ## 1, x1 ## 1; \ + vpsrld $22, x2 ## 1, x4 ## 1; \ + vpslld $(32 - 22), x2 ## 1, x2 ## 1; \ + vpor x4 ## 1, x2 ## 1, x2 ## 1; \ + vpxor x3 ## 1, x2 ## 1, x2 ## 1; \ + vpxor RK0, x0 ## 2, x0 ## 2; \ + vpxor RK2, x2 ## 2, x2 ## 2; \ + vpsrld $5, x0 ## 2, x4 ## 2; \ + vpslld $(32 - 5), x0 ## 2, x0 ## 2; \ + vpor x4 ## 2, x0 ## 2, x0 ## 2; \ + vpxor RK3, x3 ## 2, x3 ## 2; \ + vpxor RK1, x1 ## 2, x1 ## 2; \ + vpsrld $22, x2 ## 2, x4 ## 2; \ + vpslld $(32 - 22), x2 ## 2, x2 ## 2; \ + vpor x4 ## 2, x2 ## 2, x2 ## 2; \ + vpxor x3 ## 2, x2 ## 2, x2 ## 2; \ + vpxor x3 ## 1, x0 ## 1, x0 ## 1; \ + vpslld $7, x1 ## 1, x4 ## 1; \ + vpxor x1 ## 1, x0 ## 1, x0 ## 1; \ + vpxor x4 ## 1, x2 ## 1, x2 ## 1; \ + vpsrld $1, x1 ## 1, x4 ## 1; \ + vpslld $(32 - 1), x1 ## 1, x1 ## 1; \ + vpor x4 ## 1, x1 ## 1, x1 ## 1; \ + vpxor x3 ## 2, x0 ## 2, x0 ## 2; \ + vpslld $7, x1 ## 2, x4 ## 2; \ + vpxor x1 ## 2, x0 ## 2, x0 ## 2; \ + vpxor x4 ## 2, x2 ## 2, x2 ## 2; \ + vpsrld $1, x1 ## 2, x4 ## 2; \ + vpslld $(32 - 1), x1 ## 2, x1 ## 2; \ + vpor x4 ## 2, x1 ## 2, x1 ## 2; \ + vpsrld $7, x3 ## 1, x4 ## 1; \ + vpslld $(32 - 7), x3 ## 1, x3 ## 1; \ + vpor x4 ## 1, x3 ## 1, x3 ## 1; \ + vpxor x0 ## 1, x1 ## 1, x1 ## 1; \ + vpslld $3, x0 ## 1, x4 ## 1; \ + vpxor x4 ## 1, x3 ## 1, x3 ## 1; \ + vpsrld $7, x3 ## 2, x4 ## 2; \ + vpslld $(32 - 7), x3 ## 2, x3 ## 2; \ + vpor x4 ## 2, x3 ## 2, x3 ## 2; \ + vpxor x0 ## 2, x1 ## 2, x1 ## 2; \ + vpslld $3, x0 ## 2, x4 ## 2; \ + vpxor x4 ## 2, x3 ## 2, x3 ## 2; \ + vpsrld $13, x0 ## 1, x4 ## 1; \ + vpslld $(32 - 13), x0 ## 1, x0 ## 1; \ + vpor x4 ## 1, x0 ## 1, x0 ## 1; \ + vpxor x2 ## 1, x1 ## 1, x1 ## 1; \ + vpxor x2 ## 1, x3 ## 1, x3 ## 1; \ + vpsrld $3, x2 ## 1, x4 ## 1; \ + vpslld $(32 - 3), x2 ## 1, x2 ## 1; \ + vpor x4 ## 1, x2 ## 1, x2 ## 1; \ + vpsrld $13, x0 ## 2, x4 ## 2; \ + vpslld $(32 - 13), x0 ## 2, x0 ## 2; \ + vpor x4 ## 2, x0 ## 2, x0 ## 2; \ + vpxor x2 ## 2, x1 ## 2, x1 ## 2; \ + vpxor x2 ## 2, x3 ## 2, x3 ## 2; \ + vpsrld $3, x2 ## 2, x4 ## 2; \ + vpslld $(32 - 3), x2 ## 2, x2 ## 2; \ + vpor x4 ## 2, x2 ## 2, x2 ## 2; + +#define S(SBOX, x0, x1, x2, x3, x4) \ + SBOX ## _1(x0 ## 1, x1 ## 1, x2 ## 1, x3 ## 1, x4 ## 1); \ + SBOX ## _2(x0 ## 1, x1 ## 1, x2 ## 1, x3 ## 1, x4 ## 1); \ + SBOX ## _1(x0 ## 2, x1 ## 2, x2 ## 2, x3 ## 2, x4 ## 2); \ + SBOX ## _2(x0 ## 2, x1 ## 2, x2 ## 2, x3 ## 2, x4 ## 2); + +#define SP(SBOX, x0, x1, x2, x3, x4, i) \ + get_key(i, 0, RK0); \ + SBOX ## _1(x0 ## 1, x1 ## 1, x2 ## 1, x3 ## 1, x4 ## 1); \ + get_key(i, 2, RK2); \ + SBOX ## _2(x0 ## 1, x1 ## 1, x2 ## 1, x3 ## 1, x4 ## 1); \ + get_key(i, 3, RK3); \ + SBOX ## _1(x0 ## 2, x1 ## 2, x2 ## 2, x3 ## 2, x4 ## 2); \ + get_key(i, 1, RK1); \ + SBOX ## _2(x0 ## 2, x1 ## 2, x2 ## 2, x3 ## 2, x4 ## 2); \ + +#define transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ + vpunpckldq x1, x0, t0; \ + vpunpckhdq x1, x0, t2; \ + vpunpckldq x3, x2, t1; \ + vpunpckhdq x3, x2, x3; \ + \ + vpunpcklqdq t1, t0, x0; \ + vpunpckhqdq t1, t0, x1; \ + vpunpcklqdq x3, t2, x2; \ + vpunpckhqdq x3, t2, x3; + +#define read_blocks(in, x0, x1, x2, x3, t0, t1, t2) \ + vmovdqu (0*4*4)(in), x0; \ + vmovdqu (1*4*4)(in), x1; \ + vmovdqu (2*4*4)(in), x2; \ + vmovdqu (3*4*4)(in), x3; \ + \ + transpose_4x4(x0, x1, x2, x3, t0, t1, t2) + +#define write_blocks(out, x0, x1, x2, x3, t0, t1, t2) \ + transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ + \ + vmovdqu x0, (0*4*4)(out); \ + vmovdqu x1, (1*4*4)(out); \ + vmovdqu x2, (2*4*4)(out); \ + vmovdqu x3, (3*4*4)(out); + +#define xor_blocks(out, x0, x1, x2, x3, t0, t1, t2) \ + transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ + \ + vpxor (0*4*4)(out), x0, x0; \ + vmovdqu x0, (0*4*4)(out); \ + vpxor (1*4*4)(out), x1, x1; \ + vmovdqu x1, (1*4*4)(out); \ + vpxor (2*4*4)(out), x2, x2; \ + vmovdqu x2, (2*4*4)(out); \ + vpxor (3*4*4)(out), x3, x3; \ + vmovdqu x3, (3*4*4)(out); + +.align 8 +.global __serpent_enc_blk_8way +.type __serpent_enc_blk_8way,@function; + +__serpent_enc_blk_8way: + /* input: + * %rdi: ctx, CTX + * %rsi: dst + * %rdx: src + * %rcx: bool, if true: xor output + */ + + vpcmpeqd RNOT, RNOT, RNOT; + + leaq (4*4*4)(%rdx), %rax; + read_blocks(%rdx, RA1, RB1, RC1, RD1, RK0, RK1, RK2); + read_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2); + + K2(RA, RB, RC, RD, RE, 0); + S(S0, RA, RB, RC, RD, RE); LK2(RC, RB, RD, RA, RE, 1); + S(S1, RC, RB, RD, RA, RE); LK2(RE, RD, RA, RC, RB, 2); + S(S2, RE, RD, RA, RC, RB); LK2(RB, RD, RE, RC, RA, 3); + S(S3, RB, RD, RE, RC, RA); LK2(RC, RA, RD, RB, RE, 4); + S(S4, RC, RA, RD, RB, RE); LK2(RA, RD, RB, RE, RC, 5); + S(S5, RA, RD, RB, RE, RC); LK2(RC, RA, RD, RE, RB, 6); + S(S6, RC, RA, RD, RE, RB); LK2(RD, RB, RA, RE, RC, 7); + S(S7, RD, RB, RA, RE, RC); LK2(RC, RA, RE, RD, RB, 8); + S(S0, RC, RA, RE, RD, RB); LK2(RE, RA, RD, RC, RB, 9); + S(S1, RE, RA, RD, RC, RB); LK2(RB, RD, RC, RE, RA, 10); + S(S2, RB, RD, RC, RE, RA); LK2(RA, RD, RB, RE, RC, 11); + S(S3, RA, RD, RB, RE, RC); LK2(RE, RC, RD, RA, RB, 12); + S(S4, RE, RC, RD, RA, RB); LK2(RC, RD, RA, RB, RE, 13); + S(S5, RC, RD, RA, RB, RE); LK2(RE, RC, RD, RB, RA, 14); + S(S6, RE, RC, RD, RB, RA); LK2(RD, RA, RC, RB, RE, 15); + S(S7, RD, RA, RC, RB, RE); LK2(RE, RC, RB, RD, RA, 16); + S(S0, RE, RC, RB, RD, RA); LK2(RB, RC, RD, RE, RA, 17); + S(S1, RB, RC, RD, RE, RA); LK2(RA, RD, RE, RB, RC, 18); + S(S2, RA, RD, RE, RB, RC); LK2(RC, RD, RA, RB, RE, 19); + S(S3, RC, RD, RA, RB, RE); LK2(RB, RE, RD, RC, RA, 20); + S(S4, RB, RE, RD, RC, RA); LK2(RE, RD, RC, RA, RB, 21); + S(S5, RE, RD, RC, RA, RB); LK2(RB, RE, RD, RA, RC, 22); + S(S6, RB, RE, RD, RA, RC); LK2(RD, RC, RE, RA, RB, 23); + S(S7, RD, RC, RE, RA, RB); LK2(RB, RE, RA, RD, RC, 24); + S(S0, RB, RE, RA, RD, RC); LK2(RA, RE, RD, RB, RC, 25); + S(S1, RA, RE, RD, RB, RC); LK2(RC, RD, RB, RA, RE, 26); + S(S2, RC, RD, RB, RA, RE); LK2(RE, RD, RC, RA, RB, 27); + S(S3, RE, RD, RC, RA, RB); LK2(RA, RB, RD, RE, RC, 28); + S(S4, RA, RB, RD, RE, RC); LK2(RB, RD, RE, RC, RA, 29); + S(S5, RB, RD, RE, RC, RA); LK2(RA, RB, RD, RC, RE, 30); + S(S6, RA, RB, RD, RC, RE); LK2(RD, RE, RB, RC, RA, 31); + S(S7, RD, RE, RB, RC, RA); K2(RA, RB, RC, RD, RE, 32); + + leaq (4*4*4)(%rsi), %rax; + + testb %cl, %cl; + jnz __enc_xor8; + + write_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2); + write_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2); + + ret; + +__enc_xor8: + xor_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2); + xor_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2); + + ret; + +.align 8 +.global serpent_dec_blk_8way +.type serpent_dec_blk_8way,@function; + +serpent_dec_blk_8way: + /* input: + * %rdi: ctx, CTX + * %rsi: dst + * %rdx: src + */ + + vpcmpeqd RNOT, RNOT, RNOT; + + leaq (4*4*4)(%rdx), %rax; + read_blocks(%rdx, RA1, RB1, RC1, RD1, RK0, RK1, RK2); + read_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2); + + K2(RA, RB, RC, RD, RE, 32); + SP(SI7, RA, RB, RC, RD, RE, 31); KL2(RB, RD, RA, RE, RC, 31); + SP(SI6, RB, RD, RA, RE, RC, 30); KL2(RA, RC, RE, RB, RD, 30); + SP(SI5, RA, RC, RE, RB, RD, 29); KL2(RC, RD, RA, RE, RB, 29); + SP(SI4, RC, RD, RA, RE, RB, 28); KL2(RC, RA, RB, RE, RD, 28); + SP(SI3, RC, RA, RB, RE, RD, 27); KL2(RB, RC, RD, RE, RA, 27); + SP(SI2, RB, RC, RD, RE, RA, 26); KL2(RC, RA, RE, RD, RB, 26); + SP(SI1, RC, RA, RE, RD, RB, 25); KL2(RB, RA, RE, RD, RC, 25); + SP(SI0, RB, RA, RE, RD, RC, 24); KL2(RE, RC, RA, RB, RD, 24); + SP(SI7, RE, RC, RA, RB, RD, 23); KL2(RC, RB, RE, RD, RA, 23); + SP(SI6, RC, RB, RE, RD, RA, 22); KL2(RE, RA, RD, RC, RB, 22); + SP(SI5, RE, RA, RD, RC, RB, 21); KL2(RA, RB, RE, RD, RC, 21); + SP(SI4, RA, RB, RE, RD, RC, 20); KL2(RA, RE, RC, RD, RB, 20); + SP(SI3, RA, RE, RC, RD, RB, 19); KL2(RC, RA, RB, RD, RE, 19); + SP(SI2, RC, RA, RB, RD, RE, 18); KL2(RA, RE, RD, RB, RC, 18); + SP(SI1, RA, RE, RD, RB, RC, 17); KL2(RC, RE, RD, RB, RA, 17); + SP(SI0, RC, RE, RD, RB, RA, 16); KL2(RD, RA, RE, RC, RB, 16); + SP(SI7, RD, RA, RE, RC, RB, 15); KL2(RA, RC, RD, RB, RE, 15); + SP(SI6, RA, RC, RD, RB, RE, 14); KL2(RD, RE, RB, RA, RC, 14); + SP(SI5, RD, RE, RB, RA, RC, 13); KL2(RE, RC, RD, RB, RA, 13); + SP(SI4, RE, RC, RD, RB, RA, 12); KL2(RE, RD, RA, RB, RC, 12); + SP(SI3, RE, RD, RA, RB, RC, 11); KL2(RA, RE, RC, RB, RD, 11); + SP(SI2, RA, RE, RC, RB, RD, 10); KL2(RE, RD, RB, RC, RA, 10); + SP(SI1, RE, RD, RB, RC, RA, 9); KL2(RA, RD, RB, RC, RE, 9); + SP(SI0, RA, RD, RB, RC, RE, 8); KL2(RB, RE, RD, RA, RC, 8); + SP(SI7, RB, RE, RD, RA, RC, 7); KL2(RE, RA, RB, RC, RD, 7); + SP(SI6, RE, RA, RB, RC, RD, 6); KL2(RB, RD, RC, RE, RA, 6); + SP(SI5, RB, RD, RC, RE, RA, 5); KL2(RD, RA, RB, RC, RE, 5); + SP(SI4, RD, RA, RB, RC, RE, 4); KL2(RD, RB, RE, RC, RA, 4); + SP(SI3, RD, RB, RE, RC, RA, 3); KL2(RE, RD, RA, RC, RB, 3); + SP(SI2, RE, RD, RA, RC, RB, 2); KL2(RD, RB, RC, RA, RE, 2); + SP(SI1, RD, RB, RC, RA, RE, 1); KL2(RE, RB, RC, RA, RD, 1); + S(SI0, RE, RB, RC, RA, RD); K2(RC, RD, RB, RE, RA, 0); + + leaq (4*4*4)(%rsi), %rax; + write_blocks(%rsi, RC1, RD1, RB1, RE1, RK0, RK1, RK2); + write_blocks(%rax, RC2, RD2, RB2, RE2, RK0, RK1, RK2); + + ret; diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c new file mode 100644 index 000000000000..0dc7a26535e5 --- /dev/null +++ b/arch/x86/crypto/serpent_avx_glue.c @@ -0,0 +1,949 @@ +/* + * Glue Code for AVX assembler versions of Serpent Cipher + * + * Copyright (C) 2012 Johannes Goetzfried + * + * + * Glue code based on serpent_sse2_glue.c by: + * Copyright (C) 2011 Jussi Kivilinna + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct async_serpent_ctx { + struct cryptd_ablkcipher *cryptd_tfm; +}; + +static inline bool serpent_fpu_begin(bool fpu_enabled, unsigned int nbytes) +{ + if (fpu_enabled) + return true; + + /* AVX is only used when chunk to be processed is large enough, so + * do not enable FPU until it is necessary. + */ + if (nbytes < SERPENT_BLOCK_SIZE * SERPENT_PARALLEL_BLOCKS) + return false; + + kernel_fpu_begin(); + return true; +} + +static inline void serpent_fpu_end(bool fpu_enabled) +{ + if (fpu_enabled) + kernel_fpu_end(); +} + +static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk, + bool enc) +{ + bool fpu_enabled = false; + struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = SERPENT_BLOCK_SIZE; + unsigned int nbytes; + int err; + + err = blkcipher_walk_virt(desc, walk); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + + while ((nbytes = walk->nbytes)) { + u8 *wsrc = walk->src.virt.addr; + u8 *wdst = walk->dst.virt.addr; + + fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes); + + /* Process multi-block batch */ + if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) { + do { + if (enc) + serpent_enc_blk_xway(ctx, wdst, wsrc); + else + serpent_dec_blk_xway(ctx, wdst, wsrc); + + wsrc += bsize * SERPENT_PARALLEL_BLOCKS; + wdst += bsize * SERPENT_PARALLEL_BLOCKS; + nbytes -= bsize * SERPENT_PARALLEL_BLOCKS; + } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS); + + if (nbytes < bsize) + goto done; + } + + /* Handle leftovers */ + do { + if (enc) + __serpent_encrypt(ctx, wdst, wsrc); + else + __serpent_decrypt(ctx, wdst, wsrc); + + wsrc += bsize; + wdst += bsize; + nbytes -= bsize; + } while (nbytes >= bsize); + +done: + err = blkcipher_walk_done(desc, walk, nbytes); + } + + serpent_fpu_end(fpu_enabled); + return err; +} + +static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + + blkcipher_walk_init(&walk, dst, src, nbytes); + return ecb_crypt(desc, &walk, true); +} + +static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + + blkcipher_walk_init(&walk, dst, src, nbytes); + return ecb_crypt(desc, &walk, false); +} + +static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = SERPENT_BLOCK_SIZE; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 *iv = (u128 *)walk->iv; + + do { + u128_xor(dst, src, iv); + __serpent_encrypt(ctx, (u8 *)dst, (u8 *)dst); + iv = dst; + + src += 1; + dst += 1; + nbytes -= bsize; + } while (nbytes >= bsize); + + u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv); + return nbytes; +} + +static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + + while ((nbytes = walk.nbytes)) { + nbytes = __cbc_encrypt(desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + return err; +} + +static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = SERPENT_BLOCK_SIZE; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 ivs[SERPENT_PARALLEL_BLOCKS - 1]; + u128 last_iv; + int i; + + /* Start of the last block. */ + src += nbytes / bsize - 1; + dst += nbytes / bsize - 1; + + last_iv = *src; + + /* Process multi-block batch */ + if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) { + do { + nbytes -= bsize * (SERPENT_PARALLEL_BLOCKS - 1); + src -= SERPENT_PARALLEL_BLOCKS - 1; + dst -= SERPENT_PARALLEL_BLOCKS - 1; + + for (i = 0; i < SERPENT_PARALLEL_BLOCKS - 1; i++) + ivs[i] = src[i]; + + serpent_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src); + + for (i = 0; i < SERPENT_PARALLEL_BLOCKS - 1; i++) + u128_xor(dst + (i + 1), dst + (i + 1), ivs + i); + + nbytes -= bsize; + if (nbytes < bsize) + goto done; + + u128_xor(dst, dst, src - 1); + src -= 1; + dst -= 1; + } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS); + + if (nbytes < bsize) + goto done; + } + + /* Handle leftovers */ + for (;;) { + __serpent_decrypt(ctx, (u8 *)dst, (u8 *)src); + + nbytes -= bsize; + if (nbytes < bsize) + break; + + u128_xor(dst, dst, src - 1); + src -= 1; + dst -= 1; + } + +done: + u128_xor(dst, dst, (u128 *)walk->iv); + *(u128 *)walk->iv = last_iv; + + return nbytes; +} + +static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + bool fpu_enabled = false; + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + + while ((nbytes = walk.nbytes)) { + fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes); + nbytes = __cbc_decrypt(desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + serpent_fpu_end(fpu_enabled); + return err; +} + +static inline void u128_to_be128(be128 *dst, const u128 *src) +{ + dst->a = cpu_to_be64(src->a); + dst->b = cpu_to_be64(src->b); +} + +static inline void be128_to_u128(u128 *dst, const be128 *src) +{ + dst->a = be64_to_cpu(src->a); + dst->b = be64_to_cpu(src->b); +} + +static inline void u128_inc(u128 *i) +{ + i->b++; + if (!i->b) + i->a++; +} + +static void ctr_crypt_final(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + u8 *ctrblk = walk->iv; + u8 keystream[SERPENT_BLOCK_SIZE]; + u8 *src = walk->src.virt.addr; + u8 *dst = walk->dst.virt.addr; + unsigned int nbytes = walk->nbytes; + + __serpent_encrypt(ctx, keystream, ctrblk); + crypto_xor(keystream, src, nbytes); + memcpy(dst, keystream, nbytes); + + crypto_inc(ctrblk, SERPENT_BLOCK_SIZE); +} + +static unsigned int __ctr_crypt(struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = SERPENT_BLOCK_SIZE; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 ctrblk; + be128 ctrblocks[SERPENT_PARALLEL_BLOCKS]; + int i; + + be128_to_u128(&ctrblk, (be128 *)walk->iv); + + /* Process multi-block batch */ + if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) { + do { + /* create ctrblks for parallel encrypt */ + for (i = 0; i < SERPENT_PARALLEL_BLOCKS; i++) { + if (dst != src) + dst[i] = src[i]; + + u128_to_be128(&ctrblocks[i], &ctrblk); + u128_inc(&ctrblk); + } + + serpent_enc_blk_xway_xor(ctx, (u8 *)dst, + (u8 *)ctrblocks); + + src += SERPENT_PARALLEL_BLOCKS; + dst += SERPENT_PARALLEL_BLOCKS; + nbytes -= bsize * SERPENT_PARALLEL_BLOCKS; + } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS); + + if (nbytes < bsize) + goto done; + } + + /* Handle leftovers */ + do { + if (dst != src) + *dst = *src; + + u128_to_be128(&ctrblocks[0], &ctrblk); + u128_inc(&ctrblk); + + __serpent_encrypt(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks); + u128_xor(dst, dst, (u128 *)ctrblocks); + + src += 1; + dst += 1; + nbytes -= bsize; + } while (nbytes >= bsize); + +done: + u128_to_be128((be128 *)walk->iv, &ctrblk); + return nbytes; +} + +static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + bool fpu_enabled = false; + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt_block(desc, &walk, SERPENT_BLOCK_SIZE); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + + while ((nbytes = walk.nbytes) >= SERPENT_BLOCK_SIZE) { + fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes); + nbytes = __ctr_crypt(desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + serpent_fpu_end(fpu_enabled); + + if (walk.nbytes) { + ctr_crypt_final(desc, &walk); + err = blkcipher_walk_done(desc, &walk, 0); + } + + return err; +} + +struct crypt_priv { + struct serpent_ctx *ctx; + bool fpu_enabled; +}; + +static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) +{ + const unsigned int bsize = SERPENT_BLOCK_SIZE; + struct crypt_priv *ctx = priv; + int i; + + ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes); + + if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) { + serpent_enc_blk_xway(ctx->ctx, srcdst, srcdst); + return; + } + + for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) + __serpent_encrypt(ctx->ctx, srcdst, srcdst); +} + +static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) +{ + const unsigned int bsize = SERPENT_BLOCK_SIZE; + struct crypt_priv *ctx = priv; + int i; + + ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes); + + if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) { + serpent_dec_blk_xway(ctx->ctx, srcdst, srcdst); + return; + } + + for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) + __serpent_decrypt(ctx->ctx, srcdst, srcdst); +} + +struct serpent_lrw_ctx { + struct lrw_table_ctx lrw_table; + struct serpent_ctx serpent_ctx; +}; + +static int lrw_serpent_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen) +{ + struct serpent_lrw_ctx *ctx = crypto_tfm_ctx(tfm); + int err; + + err = __serpent_setkey(&ctx->serpent_ctx, key, keylen - + SERPENT_BLOCK_SIZE); + if (err) + return err; + + return lrw_init_table(&ctx->lrw_table, key + keylen - + SERPENT_BLOCK_SIZE); +} + +static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct serpent_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[SERPENT_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->serpent_ctx, + .fpu_enabled = false, + }; + struct lrw_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .table_ctx = &ctx->lrw_table, + .crypt_ctx = &crypt_ctx, + .crypt_fn = encrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = lrw_crypt(desc, dst, src, nbytes, &req); + serpent_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct serpent_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[SERPENT_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->serpent_ctx, + .fpu_enabled = false, + }; + struct lrw_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .table_ctx = &ctx->lrw_table, + .crypt_ctx = &crypt_ctx, + .crypt_fn = decrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = lrw_crypt(desc, dst, src, nbytes, &req); + serpent_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static void lrw_exit_tfm(struct crypto_tfm *tfm) +{ + struct serpent_lrw_ctx *ctx = crypto_tfm_ctx(tfm); + + lrw_free_table(&ctx->lrw_table); +} + +struct serpent_xts_ctx { + struct serpent_ctx tweak_ctx; + struct serpent_ctx crypt_ctx; +}; + +static int xts_serpent_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen) +{ + struct serpent_xts_ctx *ctx = crypto_tfm_ctx(tfm); + u32 *flags = &tfm->crt_flags; + int err; + + /* key consists of keys of equal size concatenated, therefore + * the length must be even + */ + if (keylen % 2) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + /* first half of xts-key is for crypt */ + err = __serpent_setkey(&ctx->crypt_ctx, key, keylen / 2); + if (err) + return err; + + /* second half of xts-key is for tweak */ + return __serpent_setkey(&ctx->tweak_ctx, key + keylen / 2, keylen / 2); +} + +static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct serpent_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[SERPENT_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->crypt_ctx, + .fpu_enabled = false, + }; + struct xts_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .tweak_ctx = &ctx->tweak_ctx, + .tweak_fn = XTS_TWEAK_CAST(__serpent_encrypt), + .crypt_ctx = &crypt_ctx, + .crypt_fn = encrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = xts_crypt(desc, dst, src, nbytes, &req); + serpent_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct serpent_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + be128 buf[SERPENT_PARALLEL_BLOCKS]; + struct crypt_priv crypt_ctx = { + .ctx = &ctx->crypt_ctx, + .fpu_enabled = false, + }; + struct xts_crypt_req req = { + .tbuf = buf, + .tbuflen = sizeof(buf), + + .tweak_ctx = &ctx->tweak_ctx, + .tweak_fn = XTS_TWEAK_CAST(__serpent_encrypt), + .crypt_ctx = &crypt_ctx, + .crypt_fn = decrypt_callback, + }; + int ret; + + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + ret = xts_crypt(desc, dst, src, nbytes, &req); + serpent_fpu_end(crypt_ctx.fpu_enabled); + + return ret; +} + +static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int key_len) +{ + struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); + struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base; + int err; + + crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); + crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm) + & CRYPTO_TFM_REQ_MASK); + err = crypto_ablkcipher_setkey(child, key, key_len); + crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child) + & CRYPTO_TFM_RES_MASK); + return err; +} + +static int __ablk_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); + struct blkcipher_desc desc; + + desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); + desc.info = req->info; + desc.flags = 0; + + return crypto_blkcipher_crt(desc.tfm)->encrypt( + &desc, req->dst, req->src, req->nbytes); +} + +static int ablk_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); + + if (!irq_fpu_usable()) { + struct ablkcipher_request *cryptd_req = + ablkcipher_request_ctx(req); + + memcpy(cryptd_req, req, sizeof(*req)); + ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); + + return crypto_ablkcipher_encrypt(cryptd_req); + } else { + return __ablk_encrypt(req); + } +} + +static int ablk_decrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); + + if (!irq_fpu_usable()) { + struct ablkcipher_request *cryptd_req = + ablkcipher_request_ctx(req); + + memcpy(cryptd_req, req, sizeof(*req)); + ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); + + return crypto_ablkcipher_decrypt(cryptd_req); + } else { + struct blkcipher_desc desc; + + desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); + desc.info = req->info; + desc.flags = 0; + + return crypto_blkcipher_crt(desc.tfm)->decrypt( + &desc, req->dst, req->src, req->nbytes); + } +} + +static void ablk_exit(struct crypto_tfm *tfm) +{ + struct async_serpent_ctx *ctx = crypto_tfm_ctx(tfm); + + cryptd_free_ablkcipher(ctx->cryptd_tfm); +} + +static int ablk_init(struct crypto_tfm *tfm) +{ + struct async_serpent_ctx *ctx = crypto_tfm_ctx(tfm); + struct cryptd_ablkcipher *cryptd_tfm; + char drv_name[CRYPTO_MAX_ALG_NAME]; + + snprintf(drv_name, sizeof(drv_name), "__driver-%s", + crypto_tfm_alg_driver_name(tfm)); + + cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); + if (IS_ERR(cryptd_tfm)) + return PTR_ERR(cryptd_tfm); + + ctx->cryptd_tfm = cryptd_tfm; + tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + + crypto_ablkcipher_reqsize(&cryptd_tfm->base); + + return 0; +} + +static struct crypto_alg serpent_algs[10] = { { + .cra_name = "__ecb-serpent-avx", + .cra_driver_name = "__driver-ecb-serpent-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[0].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE, + .setkey = serpent_setkey, + .encrypt = ecb_encrypt, + .decrypt = ecb_decrypt, + }, + }, +}, { + .cra_name = "__cbc-serpent-avx", + .cra_driver_name = "__driver-cbc-serpent-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[1].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE, + .setkey = serpent_setkey, + .encrypt = cbc_encrypt, + .decrypt = cbc_decrypt, + }, + }, +}, { + .cra_name = "__ctr-serpent-avx", + .cra_driver_name = "__driver-ctr-serpent-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[2].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = serpent_setkey, + .encrypt = ctr_crypt, + .decrypt = ctr_crypt, + }, + }, +}, { + .cra_name = "__lrw-serpent-avx", + .cra_driver_name = "__driver-lrw-serpent-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct serpent_lrw_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[3].cra_list), + .cra_exit = lrw_exit_tfm, + .cra_u = { + .blkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE + + SERPENT_BLOCK_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE + + SERPENT_BLOCK_SIZE, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = lrw_serpent_setkey, + .encrypt = lrw_encrypt, + .decrypt = lrw_decrypt, + }, + }, +}, { + .cra_name = "__xts-serpent-avx", + .cra_driver_name = "__driver-xts-serpent-avx", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct serpent_xts_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[4].cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE * 2, + .max_keysize = SERPENT_MAX_KEY_SIZE * 2, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = xts_serpent_setkey, + .encrypt = xts_encrypt, + .decrypt = xts_decrypt, + }, + }, +}, { + .cra_name = "ecb(serpent)", + .cra_driver_name = "ecb-serpent-avx", + .cra_priority = 500, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[5].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +}, { + .cra_name = "cbc(serpent)", + .cra_driver_name = "cbc-serpent-avx", + .cra_priority = 500, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[6].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = __ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +}, { + .cra_name = "ctr(serpent)", + .cra_driver_name = "ctr-serpent-avx", + .cra_priority = 500, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[7].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_encrypt, + .geniv = "chainiv", + }, + }, +}, { + .cra_name = "lrw(serpent)", + .cra_driver_name = "lrw-serpent-avx", + .cra_priority = 500, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[8].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE + + SERPENT_BLOCK_SIZE, + .max_keysize = SERPENT_MAX_KEY_SIZE + + SERPENT_BLOCK_SIZE, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +}, { + .cra_name = "xts(serpent)", + .cra_driver_name = "xts-serpent-avx", + .cra_priority = 500, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_algs[9].cra_list), + .cra_init = ablk_init, + .cra_exit = ablk_exit, + .cra_u = { + .ablkcipher = { + .min_keysize = SERPENT_MIN_KEY_SIZE * 2, + .max_keysize = SERPENT_MAX_KEY_SIZE * 2, + .ivsize = SERPENT_BLOCK_SIZE, + .setkey = ablk_set_key, + .encrypt = ablk_encrypt, + .decrypt = ablk_decrypt, + }, + }, +} }; + +static int __init serpent_init(void) +{ + u64 xcr0; + + if (!cpu_has_avx || !cpu_has_osxsave) { + printk(KERN_INFO "AVX instructions are not detected.\n"); + return -ENODEV; + } + + xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK); + if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) { + printk(KERN_INFO "AVX detected but unusable.\n"); + return -ENODEV; + } + + return crypto_register_algs(serpent_algs, ARRAY_SIZE(serpent_algs)); +} + +static void __exit serpent_exit(void) +{ + crypto_unregister_algs(serpent_algs, ARRAY_SIZE(serpent_algs)); +} + +module_init(serpent_init); +module_exit(serpent_exit); + +MODULE_DESCRIPTION("Serpent Cipher Algorithm, AVX optimized"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("serpent"); diff --git a/crypto/Kconfig b/crypto/Kconfig index e00a4e49e013..2c1c2dfcc02a 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -821,6 +821,26 @@ config CRYPTO_SERPENT_SSE2_586 See also: +config CRYPTO_SERPENT_AVX_X86_64 + tristate "Serpent cipher algorithm (x86_64/AVX)" + depends on X86 && 64BIT + select CRYPTO_ALGAPI + select CRYPTO_CRYPTD + select CRYPTO_SERPENT + select CRYPTO_LRW + select CRYPTO_XTS + help + Serpent cipher algorithm, by Anderson, Biham & Knudsen. + + Keys are allowed to be from 0 to 256 bits in length, in steps + of 8 bits. + + This module provides the Serpent cipher algorithm that processes + eight blocks parallel using the AVX instruction set. + + See also: + + config CRYPTO_TEA tristate "TEA, XTEA and XETA cipher algorithms" select CRYPTO_ALGAPI diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 73b3ec6fe1a2..36748a5996e2 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -1534,6 +1534,21 @@ static int alg_test_null(const struct alg_test_desc *desc, /* Please keep this list sorted by algorithm name. */ static const struct alg_test_desc alg_test_descs[] = { { + .alg = "__cbc-serpent-avx", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } + }, { .alg = "__cbc-serpent-sse2", .test = alg_test_null, .suite = { @@ -1578,6 +1593,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "__driver-cbc-serpent-avx", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "__driver-cbc-serpent-sse2", .test = alg_test_null, @@ -1623,6 +1653,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "__driver-ecb-serpent-avx", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "__driver-ecb-serpent-sse2", .test = alg_test_null, @@ -1835,6 +1880,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "cryptd(__driver-ecb-serpent-avx)", + .test = alg_test_null, + .suite = { + .cipher = { + .enc = { + .vecs = NULL, + .count = 0 + }, + .dec = { + .vecs = NULL, + .count = 0 + } + } + } }, { .alg = "cryptd(__driver-ecb-serpent-sse2)", .test = alg_test_null, -- cgit v1.2.3 From 83452c6a43d06dfbc7f78b0eafe6664c95a3895c Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:18 +0200 Subject: x86/PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Cc: x86@kernel.org Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- arch/x86/kernel/quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 03920a15a632..1b27de563561 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -512,7 +512,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, #if defined(CONFIG_PCI) && defined(CONFIG_NUMA) /* Set correct numa_node information for AMD NB functions */ -static void __init quirk_amd_nb_node(struct pci_dev *dev) +static void __devinit quirk_amd_nb_node(struct pci_dev *dev) { struct pci_dev *nb_ht; unsigned int devfn; -- cgit v1.2.3 From 8ff255afb022b8e183c7aa1ecc4ba8d0563e1e17 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:20 +0200 Subject: alpha/PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- arch/alpha/kernel/pci.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 1a629636cc16..026d49f28de3 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -59,15 +59,13 @@ struct pci_controller *pci_isa_hose; * Quirks. */ -static void __init -quirk_isa_bridge(struct pci_dev *dev) +static void __devinit quirk_isa_bridge(struct pci_dev *dev) { dev->class = PCI_CLASS_BRIDGE_ISA << 8; } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge); -static void __init -quirk_cypress(struct pci_dev *dev) +static void __devinit quirk_cypress(struct pci_dev *dev) { /* The Notorious Cy82C693 chip. */ @@ -106,8 +104,7 @@ quirk_cypress(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, quirk_cypress); /* Called for each device after PCI setup is done. */ -static void __init -pcibios_fixup_final(struct pci_dev *dev) +static void __devinit pcibios_fixup_final(struct pci_dev *dev) { unsigned int class = dev->class >> 8; -- cgit v1.2.3 From f39acb1f00059a7fada1971dcd6374fbff9b3238 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:21 +0200 Subject: arm/PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Cc: Russell King Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- arch/arm/kernel/bios32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 25552508c3fd..1c1a0e237a33 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -253,7 +253,7 @@ static void __devinit pci_fixup_cy82c693(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_fixup_cy82c693); -static void __init pci_fixup_it8152(struct pci_dev *dev) +static void __devinit pci_fixup_it8152(struct pci_dev *dev) { int i; /* fixup for ITE 8152 devices */ -- cgit v1.2.3 From a9149164280718ac244d5b5a246de5746f6aad4b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:22 +0200 Subject: frv/PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Cc: David Howells Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- arch/frv/mb93090-mb00/pci-vdk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c index 6b0b82ff4419..d04ed14bbf0c 100644 --- a/arch/frv/mb93090-mb00/pci-vdk.c +++ b/arch/frv/mb93090-mb00/pci-vdk.c @@ -268,7 +268,7 @@ static void __init pci_fixup_umc_ide(struct pci_dev *d) d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; } -static void __init pci_fixup_ide_bases(struct pci_dev *d) +static void __devinit pci_fixup_ide_bases(struct pci_dev *d) { int i; @@ -287,7 +287,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d) } } -static void __init pci_fixup_ide_trash(struct pci_dev *d) +static void __devinit pci_fixup_ide_trash(struct pci_dev *d) { int i; -- cgit v1.2.3 From 78d80c5a720ea370defa3e3124c0f7f7179bdfe5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 23 May 2012 21:18:46 +0200 Subject: serial/amba-pl011: move custom pin control to driver We had a boot regression in Ux500 in the merge window because two orthogonal pin control schemes for the PL011 were merged at the same time: - One using the .init() and .exit() hooks into the platform for Ux500 putting the pins into default vs sleep state respectively as the port was started/stopped. commit a09806607fd20bed2f8c41fe22793386790a14aa "ARM: ux500: switch to using pinctrl for uart0" - One hogging the default setting at PL011 probe() commit 258e055111d3cde2607e0d04eb91da2f7a59b591 "serial: amba-pl011: adopt pinctrl support" To get a solution that works for both let's scrap the stuff in the platform callbacks, instead have the driver itself select default and sleep states when the port is started/stopped. Hopefully this works for all clients. Platform callbacks are bad for device tree migration anyway, so this rids us of another problem in Ux500. Cc: Shawn Guo Cc: Russell King Reported-by: Lee Jones Signed-off-by: Linus Walleij Tested-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-ux500/board-mop500.c | 54 +------------------------------------- drivers/tty/serial/amba-pl011.c | 45 ++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 57 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 9c74ac545849..1509a3cb5833 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -580,43 +580,12 @@ static void ux500_uart0_reset(void) udelay(1); } -/* This needs to be referenced by callbacks */ -struct pinctrl *u0_p; -struct pinctrl_state *u0_def; -struct pinctrl_state *u0_sleep; - -static void ux500_uart0_init(void) -{ - int ret; - - if (IS_ERR(u0_p) || IS_ERR(u0_def)) - return; - - ret = pinctrl_select_state(u0_p, u0_def); - if (ret) - pr_err("could not set UART0 defstate\n"); -} - -static void ux500_uart0_exit(void) -{ - int ret; - - if (IS_ERR(u0_p) || IS_ERR(u0_sleep)) - return; - - ret = pinctrl_select_state(u0_p, u0_sleep); - if (ret) - pr_err("could not set UART0 idlestate\n"); -} - static struct amba_pl011_data uart0_plat = { #ifdef CONFIG_STE_DMA40 .dma_filter = stedma40_filter, .dma_rx_param = &uart0_dma_cfg_rx, .dma_tx_param = &uart0_dma_cfg_tx, #endif - .init = ux500_uart0_init, - .exit = ux500_uart0_exit, .reset = ux500_uart0_reset, }; @@ -638,28 +607,7 @@ static struct amba_pl011_data uart2_plat = { static void __init mop500_uart_init(struct device *parent) { - struct amba_device *uart0_device; - - uart0_device = db8500_add_uart0(parent, &uart0_plat); - if (uart0_device) { - u0_p = pinctrl_get(&uart0_device->dev); - if (IS_ERR(u0_p)) - dev_err(&uart0_device->dev, - "could not get UART0 pinctrl\n"); - else { - u0_def = pinctrl_lookup_state(u0_p, - PINCTRL_STATE_DEFAULT); - if (IS_ERR(u0_def)) { - dev_err(&uart0_device->dev, - "could not get UART0 defstate\n"); - } - u0_sleep = pinctrl_lookup_state(u0_p, - PINCTRL_STATE_SLEEP); - if (IS_ERR(u0_sleep)) - dev_err(&uart0_device->dev, - "could not get UART0 idlestate\n"); - } - } + db8500_add_uart0(parent, &uart0_plat); db8500_add_uart1(parent, &uart1_plat); db8500_add_uart2(parent, &uart2_plat); } diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 4ad721fb8405..c17923ec6e95 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -133,6 +133,10 @@ struct pl011_dmatx_data { struct uart_amba_port { struct uart_port port; struct clk *clk; + /* Two optional pin states - default & sleep */ + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + struct pinctrl_state *pins_sleep; const struct vendor_data *vendor; unsigned int dmacr; /* dma control reg */ unsigned int im; /* interrupt mask */ @@ -1312,6 +1316,14 @@ static int pl011_startup(struct uart_port *port) unsigned int cr; int retval; + /* Optionaly enable pins to be muxed in and configured */ + if (!IS_ERR(uap->pins_default)) { + retval = pinctrl_select_state(uap->pinctrl, uap->pins_default); + if (retval) + dev_err(port->dev, + "could not set default pins\n"); + } + retval = clk_prepare(uap->clk); if (retval) goto out; @@ -1420,6 +1432,7 @@ static void pl011_shutdown(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int cr; + int retval; /* * disable all interrupts @@ -1462,6 +1475,14 @@ static void pl011_shutdown(struct uart_port *port) */ clk_disable(uap->clk); clk_unprepare(uap->clk); + /* Optionally let pins go into sleep states */ + if (!IS_ERR(uap->pins_sleep)) { + retval = pinctrl_select_state(uap->pinctrl, uap->pins_sleep); + if (retval) + dev_err(port->dev, + "could not set pins to sleep state\n"); + } + if (uap->port.dev->platform_data) { struct amba_pl011_data *plat; @@ -1792,6 +1813,14 @@ static int __init pl011_console_setup(struct console *co, char *options) if (!uap) return -ENODEV; + /* Allow pins to be muxed in and configured */ + if (!IS_ERR(uap->pins_default)) { + ret = pinctrl_select_state(uap->pinctrl, uap->pins_default); + if (ret) + dev_err(uap->port.dev, + "could not set default pins\n"); + } + ret = clk_prepare(uap->clk); if (ret) return ret; @@ -1844,7 +1873,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) { struct uart_amba_port *uap; struct vendor_data *vendor = id->data; - struct pinctrl *pinctrl; void __iomem *base; int i, ret; @@ -1869,11 +1897,20 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) goto free; } - pinctrl = devm_pinctrl_get_select_default(&dev->dev); - if (IS_ERR(pinctrl)) { - ret = PTR_ERR(pinctrl); + uap->pinctrl = devm_pinctrl_get(&dev->dev); + if (IS_ERR(uap->pinctrl)) { + ret = PTR_ERR(uap->pinctrl); goto unmap; } + uap->pins_default = pinctrl_lookup_state(uap->pinctrl, + PINCTRL_STATE_DEFAULT); + if (IS_ERR(uap->pins_default)) + dev_err(&dev->dev, "could not get default pinstate\n"); + + uap->pins_sleep = pinctrl_lookup_state(uap->pinctrl, + PINCTRL_STATE_SLEEP); + if (IS_ERR(uap->pins_sleep)) + dev_dbg(&dev->dev, "could not get sleep pinstate\n"); uap->clk = clk_get(&dev->dev, NULL); if (IS_ERR(uap->clk)) { -- cgit v1.2.3 From 33a264ddcded2120fc0baa7afe4bcc5b4df3c416 Mon Sep 17 00:00:00 2001 From: Benoît Thébaudeau Date: Tue, 12 Jun 2012 19:46:43 +0200 Subject: ARM: imx: cleanup otg_mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup the code for the otg_mode command line param: * Use the bool type as it applies here. * Qualify otg_mode_host with __initdata since this variable is only used in this context. * The __setup functions are not supposed to return a status code, but a boolean indicating whether the param has been handled. See obsolete_checksetup() in init/main.c. Signed-off-by: Benoît Thébaudeau Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/mach-cpuimx27.c | 8 ++++---- arch/arm/mach-imx/mach-cpuimx35.c | 8 ++++---- arch/arm/mach-imx/mach-cpuimx51sd.c | 8 ++++---- arch/arm/mach-imx/mach-eukrea_cpuimx25.c | 8 ++++---- arch/arm/mach-imx/mach-mx27_3ds.c | 8 ++++---- arch/arm/mach-imx/mach-mx31_3ds.c | 8 ++++---- arch/arm/mach-imx/mach-mx35_3ds.c | 8 ++++---- arch/arm/mach-imx/mach-mx51_babbage.c | 8 ++++---- arch/arm/mach-imx/mach-pca100.c | 8 ++++---- arch/arm/mach-imx/mach-pcm037.c | 8 ++++---- arch/arm/mach-imx/mach-pcm043.c | 8 ++++---- 11 files changed, 44 insertions(+), 44 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c index d085aea08709..dbbb97074876 100644 --- a/arch/arm/mach-imx/mach-cpuimx27.c +++ b/arch/arm/mach-imx/mach-cpuimx27.c @@ -233,18 +233,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = { .phy_mode = FSL_USB2_PHY_ULPI, }; -static int otg_mode_host; +static bool otg_mode_host __initdata; static int __init eukrea_cpuimx27_otg_mode(char *options) { if (!strcmp(options, "host")) - otg_mode_host = 1; + otg_mode_host = true; else if (!strcmp(options, "device")) - otg_mode_host = 0; + otg_mode_host = false; else pr_info("otg_mode neither \"host\" nor \"device\". " "Defaulting to device\n"); - return 0; + return 1; } __setup("otg_mode=", eukrea_cpuimx27_otg_mode); diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c index c515f8ede1a1..c754adc2bd50 100644 --- a/arch/arm/mach-imx/mach-cpuimx35.c +++ b/arch/arm/mach-imx/mach-cpuimx35.c @@ -142,18 +142,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = { .workaround = FLS_USB2_WORKAROUND_ENGCM09152, }; -static int otg_mode_host; +static bool otg_mode_host __initdata; static int __init eukrea_cpuimx35_otg_mode(char *options) { if (!strcmp(options, "host")) - otg_mode_host = 1; + otg_mode_host = true; else if (!strcmp(options, "device")) - otg_mode_host = 0; + otg_mode_host = false; else pr_info("otg_mode neither \"host\" nor \"device\". " "Defaulting to device\n"); - return 0; + return 1; } __setup("otg_mode=", eukrea_cpuimx35_otg_mode); diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c index ac50f1671e38..2e3243ee899d 100644 --- a/arch/arm/mach-imx/mach-cpuimx51sd.c +++ b/arch/arm/mach-imx/mach-cpuimx51sd.c @@ -218,18 +218,18 @@ static const struct mxc_usbh_platform_data usbh1_config __initconst = { .portsc = MXC_EHCI_MODE_ULPI, }; -static int otg_mode_host; +static bool otg_mode_host __initdata; static int __init eukrea_cpuimx51sd_otg_mode(char *options) { if (!strcmp(options, "host")) - otg_mode_host = 1; + otg_mode_host = true; else if (!strcmp(options, "device")) - otg_mode_host = 0; + otg_mode_host = false; else pr_info("otg_mode neither \"host\" nor \"device\". " "Defaulting to device\n"); - return 0; + return 1; } __setup("otg_mode=", eukrea_cpuimx51sd_otg_mode); diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c index d1e04e676e33..77a9edd6b843 100644 --- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c +++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c @@ -109,18 +109,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = { .workaround = FLS_USB2_WORKAROUND_ENGCM09152, }; -static int otg_mode_host; +static bool otg_mode_host __initdata; static int __init eukrea_cpuimx25_otg_mode(char *options) { if (!strcmp(options, "host")) - otg_mode_host = 1; + otg_mode_host = true; else if (!strcmp(options, "device")) - otg_mode_host = 0; + otg_mode_host = false; else pr_info("otg_mode neither \"host\" nor \"device\". " "Defaulting to device\n"); - return 0; + return 1; } __setup("otg_mode=", eukrea_cpuimx25_otg_mode); diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c index c6d385c52257..cc4f83c76ace 100644 --- a/arch/arm/mach-imx/mach-mx27_3ds.c +++ b/arch/arm/mach-imx/mach-mx27_3ds.c @@ -241,18 +241,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = { .phy_mode = FSL_USB2_PHY_ULPI, }; -static int otg_mode_host; +static bool otg_mode_host __initdata; static int __init mx27_3ds_otg_mode(char *options) { if (!strcmp(options, "host")) - otg_mode_host = 1; + otg_mode_host = true; else if (!strcmp(options, "device")) - otg_mode_host = 0; + otg_mode_host = false; else pr_info("otg_mode neither \"host\" nor \"device\". " "Defaulting to device\n"); - return 0; + return 1; } __setup("otg_mode=", mx27_3ds_otg_mode); diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c index 4eafdf275ea2..ebcadd2e6be0 100644 --- a/arch/arm/mach-imx/mach-mx31_3ds.c +++ b/arch/arm/mach-imx/mach-mx31_3ds.c @@ -671,18 +671,18 @@ static const struct fsl_usb2_platform_data usbotg_pdata __initconst = { .phy_mode = FSL_USB2_PHY_ULPI, }; -static int otg_mode_host; +static bool otg_mode_host __initdata; static int __init mx31_3ds_otg_mode(char *options) { if (!strcmp(options, "host")) - otg_mode_host = 1; + otg_mode_host = true; else if (!strcmp(options, "device")) - otg_mode_host = 0; + otg_mode_host = false; else pr_info("otg_mode neither \"host\" nor \"device\". " "Defaulting to device\n"); - return 0; + return 1; } __setup("otg_mode=", mx31_3ds_otg_mode); diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c index 28aa19476de7..af92e5e03163 100644 --- a/arch/arm/mach-imx/mach-mx35_3ds.c +++ b/arch/arm/mach-imx/mach-mx35_3ds.c @@ -540,18 +540,18 @@ static const struct mxc_usbh_platform_data usb_host_pdata __initconst = { .portsc = MXC_EHCI_MODE_SERIAL, }; -static int otg_mode_host; +static bool otg_mode_host __initdata; static int __init mx35_3ds_otg_mode(char *options) { if (!strcmp(options, "host")) - otg_mode_host = 1; + otg_mode_host = true; else if (!strcmp(options, "device")) - otg_mode_host = 0; + otg_mode_host = false; else pr_info("otg_mode neither \"host\" nor \"device\". " "Defaulting to device\n"); - return 0; + return 1; } __setup("otg_mode=", mx35_3ds_otg_mode); diff --git a/arch/arm/mach-imx/mach-mx51_babbage.c b/arch/arm/mach-imx/mach-mx51_babbage.c index dde397014d4b..3ca6902dfc34 100644 --- a/arch/arm/mach-imx/mach-mx51_babbage.c +++ b/arch/arm/mach-imx/mach-mx51_babbage.c @@ -307,18 +307,18 @@ static const struct mxc_usbh_platform_data usbh1_config __initconst = { .portsc = MXC_EHCI_MODE_ULPI, }; -static int otg_mode_host; +static bool otg_mode_host __initdata; static int __init babbage_otg_mode(char *options) { if (!strcmp(options, "host")) - otg_mode_host = 1; + otg_mode_host = true; else if (!strcmp(options, "device")) - otg_mode_host = 0; + otg_mode_host = false; else pr_info("otg_mode neither \"host\" nor \"device\". " "Defaulting to device\n"); - return 0; + return 1; } __setup("otg_mode=", babbage_otg_mode); diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c index 541152e450c4..9fe7a1b32d68 100644 --- a/arch/arm/mach-imx/mach-pca100.c +++ b/arch/arm/mach-imx/mach-pca100.c @@ -298,18 +298,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = { .phy_mode = FSL_USB2_PHY_ULPI, }; -static int otg_mode_host; +static bool otg_mode_host __initdata; static int __init pca100_otg_mode(char *options) { if (!strcmp(options, "host")) - otg_mode_host = 1; + otg_mode_host = true; else if (!strcmp(options, "device")) - otg_mode_host = 0; + otg_mode_host = false; else pr_info("otg_mode neither \"host\" nor \"device\". " "Defaulting to device\n"); - return 0; + return 1; } __setup("otg_mode=", pca100_otg_mode); diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c index 0a40004154f2..debc286a41d7 100644 --- a/arch/arm/mach-imx/mach-pcm037.c +++ b/arch/arm/mach-imx/mach-pcm037.c @@ -557,18 +557,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = { .phy_mode = FSL_USB2_PHY_ULPI, }; -static int otg_mode_host; +static bool otg_mode_host __initdata; static int __init pcm037_otg_mode(char *options) { if (!strcmp(options, "host")) - otg_mode_host = 1; + otg_mode_host = true; else if (!strcmp(options, "device")) - otg_mode_host = 0; + otg_mode_host = false; else pr_info("otg_mode neither \"host\" nor \"device\". " "Defaulting to device\n"); - return 0; + return 1; } __setup("otg_mode=", pcm037_otg_mode); diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c index 73585f55cca0..a8f4a0087b8c 100644 --- a/arch/arm/mach-imx/mach-pcm043.c +++ b/arch/arm/mach-imx/mach-pcm043.c @@ -330,18 +330,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = { .phy_mode = FSL_USB2_PHY_UTMI, }; -static int otg_mode_host; +static bool otg_mode_host __initdata; static int __init pcm043_otg_mode(char *options) { if (!strcmp(options, "host")) - otg_mode_host = 1; + otg_mode_host = true; else if (!strcmp(options, "device")) - otg_mode_host = 0; + otg_mode_host = false; else pr_info("otg_mode neither \"host\" nor \"device\". " "Defaulting to device\n"); - return 0; + return 1; } __setup("otg_mode=", pcm043_otg_mode); -- cgit v1.2.3 From 2f74759056797054122cdc70844137f70bb3f626 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Thu, 7 Jun 2012 22:20:18 +0900 Subject: x86/alternatives: Use atomic_xchg() instead atomic_dec_and_test() for stop_machine_text_poke() stop_machine_text_poke() uses atomic_dec_and_test() to select one of the CPUs executing that function to actually modify the code. Since the variable is initialized to 1, subsequent CPUs will make the variable go negative. Since going negative is uncommon/unexpected in typical dec_and_test usage change this user to atomic_xchg(). This was found using a patch that warns on dec_and_test going negative. Signed-off-by: OGAWA Hirofumi Acked-by: Steven Rostedt [ Rewrote changelog ] Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/87zk8fgsx9.fsf@devron.myhome.or.jp Signed-off-by: Ingo Molnar --- arch/x86/kernel/alternative.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 1f84794f0759..53231a045d3d 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -664,7 +664,7 @@ static int __kprobes stop_machine_text_poke(void *data) struct text_poke_param *p; int i; - if (atomic_dec_and_test(&stop_machine_first)) { + if (atomic_xchg(&stop_machine_first, 0)) { for (i = 0; i < tpp->nparams; i++) { p = &tpp->params[i]; text_poke(p->addr, p->opcode, p->len); -- cgit v1.2.3 From b918c62e086b2130a7bae44110ca516ef10bfe5a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:11 -0700 Subject: PCI: replace struct pci_bus secondary/subordinate with busn_res Replace the struct pci_bus secondary/subordinate members with the struct resource busn_res. Later we'll build a resource tree of these bus numbers. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/alpha/kernel/pci.c | 2 +- arch/arm/kernel/bios32.c | 2 +- arch/ia64/pci/pci.c | 2 +- arch/microblaze/pci/pci-common.c | 4 +-- arch/mips/pci/pci.c | 2 +- arch/powerpc/kernel/pci-common.c | 6 ++-- arch/powerpc/kernel/pci_64.c | 2 +- arch/powerpc/kernel/pci_of_scan.c | 2 +- arch/powerpc/platforms/powernv/pci-ioda.c | 8 ++--- arch/powerpc/platforms/pseries/pci_dlpar.c | 2 +- arch/sh/drivers/pci/pci.c | 2 +- arch/sparc/kernel/pci.c | 6 ++-- arch/tile/kernel/pci.c | 4 +-- arch/x86/pci/acpi.c | 2 +- arch/xtensa/kernel/pci.c | 2 +- drivers/iommu/intel-iommu.c | 2 +- drivers/net/ethernet/broadcom/tg3.c | 4 +-- drivers/parisc/dino.c | 10 +++--- drivers/parisc/iosapic.c | 2 +- drivers/parisc/lba_pci.c | 22 ++++++------ drivers/pci/hotplug/acpiphp_glue.c | 8 ++--- drivers/pci/hotplug/cpci_hotplug_pci.c | 6 ++-- drivers/pci/hotplug/pciehp_pci.c | 4 +-- drivers/pci/hotplug/shpchp_pci.c | 6 ++-- drivers/pci/hotplug/shpchp_sysfs.c | 6 ++-- drivers/pci/iov.c | 4 +-- drivers/pci/pci.c | 2 +- drivers/pci/probe.c | 58 +++++++++++++++--------------- drivers/pci/setup-bus.c | 24 ++++++------- drivers/pcmcia/cardbus.c | 2 +- drivers/pcmcia/yenta_socket.c | 26 +++++++------- 31 files changed, 117 insertions(+), 117 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 1a629636cc16..53229a496311 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -359,7 +359,7 @@ common_init_pci(void) hose, &resources); hose->bus = bus; hose->need_domain_info = need_domain_info; - next_busno = bus->subordinate + 1; + next_busno = bus->busn_res.end + 1; /* Don't allow 8-bit bus number overflow inside the hose - reserve some space for bridges. */ if (next_busno > 224) { diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 25552508c3fd..f07710849b58 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -461,7 +461,7 @@ static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head) if (!sys->bus) panic("PCI: unable to scan bus!"); - busnr = sys->bus->subordinate + 1; + busnr = sys->bus->busn_res.end + 1; list_add(&sys->node, head); } else { diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 524df4295c90..3ca9bed7dc50 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -384,7 +384,7 @@ pci_acpi_scan_root(struct acpi_pci_root *root) return NULL; } - pbus->subordinate = pci_scan_child_bus(pbus); + pbus->busn_res.end = pci_scan_child_bus(pbus); return pbus; out3: diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index ed22bfc5db14..9b32483cd0c0 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -1506,10 +1506,10 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose) pci_free_resource_list(&resources); return; } - bus->secondary = hose->first_busno; + bus->busn_res.start = hose->first_busno; hose->bus = bus; - hose->last_busno = bus->subordinate; + hose->last_busno = bus->busn_res.end; } static int __init pcibios_init(void) diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 271e8c4a54c7..0a9bf778edb5 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -102,7 +102,7 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose) need_domain_info = need_domain_info || hose->index; hose->need_domain_info = need_domain_info; if (bus) { - next_busno = bus->subordinate + 1; + next_busno = bus->busn_res.end + 1; /* Don't allow 8-bit bus number overflow inside the hose - reserve some space for bridges. */ if (next_busno > 224) { diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 8e78e93c8185..3532b535698a 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1646,7 +1646,7 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) pci_free_resource_list(&resources); return; } - bus->secondary = hose->first_busno; + bus->busn_res.start = hose->first_busno; hose->bus = bus; /* Get probe mode and perform scan */ @@ -1655,12 +1655,12 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) mode = ppc_md.pci_probe_mode(bus); pr_debug(" probe mode: %d\n", mode); if (mode == PCI_PROBE_DEVTREE) { - bus->subordinate = hose->last_busno; + bus->busn_res.end = hose->last_busno; of_scan_bus(node, bus); } if (mode == PCI_PROBE_NORMAL) - hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); + hose->last_busno = bus->busn_res.end = pci_scan_child_bus(bus); /* Platform gets a chance to do some global fixups before * we proceed to resource allocation diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 94a54f61d341..4ff190ff24a0 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -236,7 +236,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { bus = pci_bus_b(ln); - if (in_bus >= bus->number && in_bus <= bus->subordinate) + if (in_bus >= bus->number && in_bus <= bus->busn_res.end) break; bus = NULL; } diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 89dde171a6fa..a36281aa98f3 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -240,7 +240,7 @@ void __devinit of_scan_pci_bridge(struct pci_dev *dev) } bus->primary = dev->bus->number; - bus->subordinate = busrange[1]; + bus->busn_res.end = busrange[1]; bus->bridge_ctl = 0; /* parse ranges property */ diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index fbdd74dac3ac..9cda6a1ad0cf 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -589,7 +589,7 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb, dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER; fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER; parent = pe->pbus->self; - count = pe->pbus->subordinate - pe->pbus->secondary + 1; + count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1; switch(count) { case 1: bcomp = OpalPciBusAll; break; case 2: bcomp = OpalPciBus7Bits; break; @@ -816,11 +816,11 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev, pe->pdev = NULL; pe->tce32_seg = -1; pe->mve_number = -1; - pe->rid = bus->secondary << 8; + pe->rid = bus->busn_res.start << 8; pe->dma_weight = 0; - pe_info(pe, "Secondary busses %d..%d associated with PE\n", - bus->secondary, bus->subordinate); + pe_info(pe, "Secondary busses %pR associated with PE\n", + &bus->busn_res); if (pnv_ioda_configure_pe(phb, pe)) { /* XXX What do we do here ? */ diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 8b7bafa489c2..3ccebc83dc02 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -121,7 +121,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus) if (!num) return; pcibios_setup_bus_devices(bus); - max = bus->secondary; + max = bus->busn_res.start; for (pass=0; pass < 2; pass++) list_for_each_entry(dev, &bus->devices, bus_list) { if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 9d10a3cb8797..43068dcb451c 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -59,7 +59,7 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose) need_domain_info = need_domain_info || hose->index; hose->need_domain_info = need_domain_info; if (bus) { - next_busno = bus->subordinate + 1; + next_busno = bus->busn_res.end + 1; /* Don't allow 8-bit bus number overflow inside the hose - reserve some space for bridges. */ if (next_busno > 224) { diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index fdaf21811670..c85bfd788f74 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -535,7 +535,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, } bus->primary = dev->bus->number; - bus->subordinate = busrange[1]; + bus->busn_res.end = busrange[1]; bus->bridge_ctl = 0; /* parse ranges property, or cook one up by hand for Simba */ @@ -693,8 +693,8 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, pci_free_resource_list(&resources); return NULL; } - bus->secondary = pbm->pci_first_busno; - bus->subordinate = pbm->pci_last_busno; + bus->busn_res.start = pbm->pci_first_busno; + bus->busn_res.end = pbm->pci_last_busno; pci_of_scan_bus(pbm, node, bus); pci_bus_add_devices(bus); diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index b56d12bf5900..54cc8d77c90c 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c @@ -329,7 +329,7 @@ int __init pcibios_init(void) */ bus = pci_scan_bus(0, controller->ops, controller); controller->root_bus = bus; - controller->last_busno = bus->subordinate; + controller->last_busno = bus->busn_res.end; } } @@ -366,7 +366,7 @@ int __init pcibios_init(void) */ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && (PCI_SLOT(dev->devfn) == 0)) { - next_bus = dev->subordinate; + next_bus = dev->busn_res.end; controllers[i].mem_resources[0] = *next_bus->resource[0]; controllers[i].mem_resources[1] = diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index fc09c2754e08..350fe63c8a42 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -440,7 +440,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd, &resources); if (bus) { - bus->subordinate = pci_scan_child_bus(bus); + bus->busn_res.end = pci_scan_child_bus(bus); pci_set_host_bridge_release( to_pci_host_bridge(bus->bridge), release_pci_root_info, info); diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index eb30e356f5be..9c57c1e6870c 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c @@ -187,7 +187,7 @@ static int __init pcibios_init(void) bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno, pci_ctrl->ops, pci_ctrl, &resources); pci_ctrl->bus = bus; - pci_ctrl->last_busno = bus->subordinate; + pci_ctrl->last_busno = bus->busn_res.end; if (next_busno <= pci_ctrl->last_busno) next_busno = pci_ctrl->last_busno+1; } diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index b12af2ff8c54..2fb7d1598a68 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -661,7 +661,7 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) if (drhd->devices[i] && drhd->devices[i]->subordinate && drhd->devices[i]->subordinate->number <= bus && - drhd->devices[i]->subordinate->subordinate >= bus) + drhd->devices[i]->subordinate->busn_res.end >= bus) return drhd->iommu; } diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index edeeb516807a..09fa3c687a1f 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -14168,7 +14168,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (bridge->subordinate && (bridge->subordinate->number <= tp->pdev->bus->number) && - (bridge->subordinate->subordinate >= + (bridge->subordinate->busn_res.end >= tp->pdev->bus->number)) { tg3_flag_set(tp, 5701_DMA_BUG); pci_dev_put(bridge); @@ -14196,7 +14196,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (bridge && bridge->subordinate && (bridge->subordinate->number <= tp->pdev->bus->number) && - (bridge->subordinate->subordinate >= + (bridge->subordinate->busn_res.end >= tp->pdev->bus->number)) { tg3_flag_set(tp, 40BIT_DMA_BUG); pci_dev_put(bridge); diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 432d4bbcc62a..70517b0f94e6 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -174,7 +174,7 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3); void __iomem *base_addr = d->hba.base_addr; unsigned long flags; @@ -209,7 +209,7 @@ static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) { struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3); void __iomem *base_addr = d->hba.base_addr; unsigned long flags; @@ -554,7 +554,7 @@ dino_fixup_bus(struct pci_bus *bus) struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge)); DBG(KERN_WARNING "%s(0x%p) bus %d platform_data 0x%p\n", - __func__, bus, bus->secondary, + __func__, bus, bus->busn_res.start, bus->bridge->platform_data); /* Firmware doesn't set up card-mode dino, so we have to */ @@ -998,12 +998,12 @@ static int __init dino_probe(struct parisc_device *dev) return 0; } - bus->subordinate = pci_scan_child_bus(bus); + bus->busn_res.end = pci_scan_child_bus(bus); /* This code *depends* on scanning being single threaded * if it isn't, this global bus number count will fail */ - dino_current_bus = bus->subordinate + 1; + dino_current_bus = bus->busn_res.end + 1; pci_bus_assign_resources(bus); pci_bus_add_devices(bus); return 0; diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 1f9e9fefb8e7..83380c8fcb6b 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -532,7 +532,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) intr_slot = PCI_SLOT(pcidev->devfn); } DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n", - pcidev->bus->secondary, intr_slot, intr_pin); + pcidev->bus->busn_res.start, intr_slot, intr_pin); return irt_find_irqline(isi, intr_slot, intr_pin); } diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 052fa230bc77..cd8f9ce8720f 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -189,8 +189,8 @@ lba_dump_res(struct resource *r, int d) static int lba_device_present(u8 bus, u8 dfn, struct lba_device *d) { - u8 first_bus = d->hba.hba_bus->secondary; - u8 last_sub_bus = d->hba.hba_bus->subordinate; + u8 first_bus = d->hba.hba_bus->busn_res.start; + u8 last_sub_bus = d->hba.hba_bus->busn_res.end; if ((bus < first_bus) || (bus > last_sub_bus) || @@ -364,7 +364,7 @@ lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size) static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 tok = LBA_CFG_TOK(local_bus, devfn); void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; @@ -380,7 +380,7 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int return 0; } - if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->secondary, devfn, d)) { + if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->busn_res.start, devfn, d)) { DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __func__, tok, pos); /* either don't want to look or know device isn't present. */ *data = ~0U; @@ -431,7 +431,7 @@ lba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size) static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data) { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 tok = LBA_CFG_TOK(local_bus,devfn); if ((pos > 255) || (devfn > 255)) @@ -444,7 +444,7 @@ static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int return 0; } - if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d))) { + if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->busn_res.start, devfn, d))) { DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __func__, tok, pos,data); return 1; /* New Workaround */ } @@ -481,7 +481,7 @@ static struct pci_ops elroy_cfg_ops = { static int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 tok = LBA_CFG_TOK(local_bus, devfn); void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; @@ -514,7 +514,7 @@ static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, i { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 tok = LBA_CFG_TOK(local_bus,devfn); if ((pos > 255) || (devfn > 255)) @@ -636,7 +636,7 @@ lba_fixup_bus(struct pci_bus *bus) struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge)); DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n", - bus, bus->secondary, bus->bridge->platform_data); + bus, (int)bus->busn_res.start, bus->bridge->platform_data); /* ** Properly Setup MMIO resources for this bus. @@ -1511,7 +1511,7 @@ lba_driver_probe(struct parisc_device *dev) return 0; } - lba_bus->subordinate = pci_scan_child_bus(lba_bus); + lba_bus->busn_res.end = pci_scan_child_bus(lba_bus); /* This is in lieu of calling pci_assign_unassigned_resources() */ if (is_pdc_pat()) { @@ -1541,7 +1541,7 @@ lba_driver_probe(struct parisc_device *dev) lba_dev->flags |= LBA_FLAG_SKIP_PROBE; } - lba_next_bus = lba_bus->subordinate + 1; + lba_next_bus = lba_res->busn_res.end + 1; pci_bus_add_devices(lba_bus); /* Whew! Finally done! Tell services we got this one covered. */ diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 806c44fa645a..62d0ae4dfcad 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -100,11 +100,11 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val, PCI_PRIMARY_BUS, &buses); - if (((buses >> 8) & 0xff) != bus->secondary) { + if (((buses >> 8) & 0xff) != bus->busn_res.start) { buses = (buses & 0xff000000) | ((unsigned int)(bus->primary) << 0) - | ((unsigned int)(bus->secondary) << 8) - | ((unsigned int)(bus->subordinate) << 16); + | ((unsigned int)(bus->busn_res.start) << 8) + | ((unsigned int)(bus->busn_res.end) << 16); pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); } return NOTIFY_OK; @@ -692,7 +692,7 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) * bus->subordinate value because it could have * padding in it. */ - max = bus->secondary; + max = bus->busn_res.start; list_for_each(tmp, &bus->children) { n = pci_bus_max_busnr(pci_bus_b(tmp)); diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index ae853ccd0cd5..42f3a61db87c 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -292,8 +292,8 @@ int __ref cpci_configure_slot(struct slot *slot) (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { /* Find an unused bus number for the new bridge */ struct pci_bus *child; - unsigned char busnr, start = parent->secondary; - unsigned char end = parent->subordinate; + unsigned char busnr, start = parent->busn_res.start; + unsigned char end = parent->busn_res.end; for (busnr = start; busnr <= end; busnr++) { if (!pci_find_bus(pci_domain_nr(parent), @@ -312,7 +312,7 @@ int __ref cpci_configure_slot(struct slot *slot) pci_dev_put(dev); continue; } - child->subordinate = pci_do_scan_bus(child); + child->busn_res.end = pci_do_scan_bus(child); pci_bus_size_bridges(child); } pci_dev_put(dev); diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 47d9dc06b109..b898f06b588d 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -37,8 +37,8 @@ static int __ref pciehp_add_bridge(struct pci_dev *dev) { struct pci_bus *parent = dev->bus; - int pass, busnr, start = parent->secondary; - int end = parent->subordinate; + int pass, busnr, start = parent->busn_res.start; + int end = parent->busn_res.end; for (busnr = start; busnr <= end; busnr++) { if (!pci_find_bus(pci_domain_nr(parent), busnr)) diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index df7e4bfadae3..d021eb031b3c 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -64,8 +64,8 @@ int __ref shpchp_configure_device(struct slot *p_slot) (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { /* Find an unused bus number for the new bridge */ struct pci_bus *child; - unsigned char busnr, start = parent->secondary; - unsigned char end = parent->subordinate; + unsigned char busnr, start = parent->busn_res.start; + unsigned char end = parent->busn_res.end; for (busnr = start; busnr <= end; busnr++) { if (!pci_find_bus(pci_domain_nr(parent), busnr)) @@ -84,7 +84,7 @@ int __ref shpchp_configure_device(struct slot *p_slot) pci_dev_put(dev); continue; } - child->subordinate = pci_do_scan_bus(child); + child->busn_res.end = pci_do_scan_bus(child); pci_bus_size_bridges(child); } pci_configure_slot(dev); diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index efa30da1ae8f..eeb23ceae4a8 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c @@ -73,13 +73,13 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha } } out += sprintf(out, "Free resources: bus numbers\n"); - for (busnr = bus->secondary; busnr <= bus->subordinate; busnr++) { + for (busnr = bus->busn_res.start; busnr <= bus->busn_res.end; busnr++) { if (!pci_find_bus(pci_domain_nr(bus), busnr)) break; } - if (busnr < bus->subordinate) + if (busnr < bus->busn_res.end) out += sprintf(out, "start = %8.8x, length = %8.8x\n", - busnr, (bus->subordinate - busnr)); + busnr, (int)(bus->busn_res.end - busnr)); return out - buf; } diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 6554e1a0f634..e873060fb35b 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -47,7 +47,7 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) if (!child) return NULL; - child->subordinate = busnr; + child->busn_res.end = busnr; child->dev.parent = bus->bridge; rc = pci_bus_add_child(child); if (rc) { @@ -327,7 +327,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) iov->offset = offset; iov->stride = stride; - if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->subordinate) { + if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->busn_res.end) { dev_err(&dev->dev, "SR-IOV: bus number out of range\n"); return -ENOMEM; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 447e83472c01..aeda6e9c245c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -110,7 +110,7 @@ unsigned char pci_bus_max_busnr(struct pci_bus* bus) struct list_head *tmp; unsigned char max, n; - max = bus->subordinate; + max = bus->busn_res.end; list_for_each(tmp, &bus->children) { n = pci_bus_max_busnr(pci_bus_b(tmp)); if(n > max) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 658ac977cb56..651b096134dc 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -381,8 +381,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */ return; - dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n", - child->secondary, child->subordinate, + dev_info(&dev->dev, "PCI bridge to %pR%s\n", + &child->busn_res, dev->transparent ? " (subtractive decode)" : ""); pci_bus_remove_resources(child); @@ -599,9 +599,9 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, * Set up the primary, secondary and subordinate * bus numbers. */ - child->number = child->secondary = busnr; - child->primary = parent->secondary; - child->subordinate = 0xff; + child->number = child->busn_res.start = busnr; + child->primary = parent->busn_res.start; + child->busn_res.end = 0xff; if (!bridge) return child; @@ -643,8 +643,8 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max) if (!pcibios_assign_all_busses()) return; - while (parent->parent && parent->subordinate < max) { - parent->subordinate = max; + while (parent->parent && parent->busn_res.end < max) { + parent->busn_res.end = max; pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max); parent = parent->parent; } @@ -718,15 +718,15 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, if (!child) goto out; child->primary = primary; - child->subordinate = subordinate; + child->busn_res.end = subordinate; child->bridge_ctl = bctl; } cmax = pci_scan_child_bus(child); if (cmax > max) max = cmax; - if (child->subordinate > max) - max = child->subordinate; + if (child->busn_res.end > max) + max = child->busn_res.end; } else { /* * We need to assign a number to this bus which we always @@ -759,8 +759,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, } buses = (buses & 0xff000000) | ((unsigned int)(child->primary) << 0) - | ((unsigned int)(child->secondary) << 8) - | ((unsigned int)(child->subordinate) << 16); + | ((unsigned int)(child->busn_res.start) << 8) + | ((unsigned int)(child->busn_res.end) << 16); /* * yenta.c forces a secondary latency timer of 176. @@ -805,8 +805,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, break; while (parent->parent) { if ((!pcibios_assign_all_busses()) && - (parent->subordinate > max) && - (parent->subordinate <= max+i)) { + (parent->busn_res.end > max) && + (parent->busn_res.end <= max+i)) { j = 1; } parent = parent->parent; @@ -827,7 +827,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, /* * Set the subordinate bus number to its real value. */ - child->subordinate = max; + child->busn_res.end = max; pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max); } @@ -837,19 +837,19 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, /* Has only triggered on CardBus, fixup is in yenta_socket */ while (bus->parent) { - if ((child->subordinate > bus->subordinate) || - (child->number > bus->subordinate) || + if ((child->busn_res.end > bus->busn_res.end) || + (child->number > bus->busn_res.end) || (child->number < bus->number) || - (child->subordinate < bus->number)) { - dev_info(&child->dev, "[bus %02x-%02x] %s " - "hidden behind%s bridge %s [bus %02x-%02x]\n", - child->number, child->subordinate, - (bus->number > child->subordinate && - bus->subordinate < child->number) ? + (child->busn_res.end < bus->number)) { + dev_info(&child->dev, "%pR %s " + "hidden behind%s bridge %s %pR\n", + &child->busn_res, + (bus->number > child->busn_res.end && + bus->busn_res.end < child->number) ? "wholly" : "partially", bus->self->transparent ? " transparent" : "", dev_name(&bus->dev), - bus->number, bus->subordinate); + &bus->busn_res); } bus = bus->parent; } @@ -1548,7 +1548,7 @@ EXPORT_SYMBOL_GPL(pcie_bus_configure_settings); unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) { - unsigned int devfn, pass, max = bus->secondary; + unsigned int devfn, pass, max = bus->busn_res.start; struct pci_dev *dev; dev_dbg(&bus->dev, "scanning bus\n"); @@ -1642,7 +1642,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, /* Create legacy_io and legacy_mem files for this bus */ pci_create_legacy_files(b); - b->number = b->secondary = bus; + b->number = b->busn_res.start = bus; if (parent) dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev)); @@ -1693,7 +1693,7 @@ struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus, if (!b) return NULL; - b->subordinate = pci_scan_child_bus(b); + b->busn_res.end = pci_scan_child_bus(b); pci_bus_add_devices(b); return b; } @@ -1710,7 +1710,7 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, pci_add_resource(&resources, &iomem_resource); b = pci_create_root_bus(parent, bus, ops, sysdata, &resources); if (b) - b->subordinate = pci_scan_child_bus(b); + b->busn_res.end = pci_scan_child_bus(b); else pci_free_resource_list(&resources); return b; @@ -1727,7 +1727,7 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops, pci_add_resource(&resources, &iomem_resource); b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources); if (b) { - b->subordinate = pci_scan_child_bus(b); + b->busn_res.end = pci_scan_child_bus(b); pci_bus_add_devices(b); } else { pci_free_resource_list(&resources); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 8fa2d4be88de..192172c87b77 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -404,8 +404,8 @@ void pci_setup_cardbus(struct pci_bus *bus) struct resource *res; struct pci_bus_region region; - dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n", - bus->secondary, bus->subordinate); + dev_info(&bridge->dev, "CardBus bridge to %pR\n", + &bus->busn_res); res = bus->resource[0]; pcibios_resource_to_bus(bridge, ®ion, res); @@ -553,8 +553,8 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type) { struct pci_dev *bridge = bus->self; - dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", - bus->secondary, bus->subordinate); + dev_info(&bridge->dev, "PCI bridge to %pR\n", + &bus->busn_res); if (type & IORESOURCE_IO) pci_setup_bridge_io(bus); @@ -745,8 +745,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, if (!size0 && !size1) { if (b_res->start || b_res->end) dev_info(&bus->self->dev, "disabling bridge window " - "%pR to [bus %02x-%02x] (unused)\n", b_res, - bus->secondary, bus->subordinate); + "%pR to %pR (unused)\n", b_res, + &bus->busn_res); b_res->flags = 0; return; } @@ -757,8 +757,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, if (size1 > size0 && realloc_head) { add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096); dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " - "%pR to [bus %02x-%02x] add_size %lx\n", b_res, - bus->secondary, bus->subordinate, size1-size0); + "%pR to %pR add_size %lx\n", b_res, + &bus->busn_res, size1-size0); } } @@ -863,8 +863,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, if (!size0 && !size1) { if (b_res->start || b_res->end) dev_info(&bus->self->dev, "disabling bridge window " - "%pR to [bus %02x-%02x] (unused)\n", b_res, - bus->secondary, bus->subordinate); + "%pR to %pR (unused)\n", b_res, + &bus->busn_res); b_res->flags = 0; return 1; } @@ -874,8 +874,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, if (size1 > size0 && realloc_head) { add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align); dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " - "%pR to [bus %02x-%02x] add_size %llx\n", b_res, - bus->secondary, bus->subordinate, (unsigned long long)size1-size0); + "%pR to %pR add_size %llx\n", b_res, + &bus->busn_res, (unsigned long long)size1-size0); } return 1; } diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 6e75153c5b4f..24caeaf50529 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -73,7 +73,7 @@ int __ref cb_alloc(struct pcmcia_socket *s) s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); pci_fixup_cardbus(bus); - max = bus->secondary; + max = bus->busn_res.start; for (pass = 0; pass < 2; pass++) list_for_each_entry(dev, &bus->devices, bus_list) if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index d07f9ac8c41d..667678db1153 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -1048,8 +1048,8 @@ static void yenta_config_init(struct yenta_socket *socket) config_writeb(socket, PCI_LATENCY_TIMER, 168); config_writel(socket, PCI_PRIMARY_BUS, (176 << 24) | /* sec. latency timer */ - (dev->subordinate->subordinate << 16) | /* subordinate bus */ - (dev->subordinate->secondary << 8) | /* secondary bus */ + ((unsigned int)dev->subordinate->busn_res.end << 16) | /* subordinate bus */ + ((unsigned int)dev->subordinate->busn_res.start << 8) | /* secondary bus */ dev->subordinate->primary); /* primary bus */ /* @@ -1086,14 +1086,14 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) struct pci_bus *bridge_to_fix = cardbus_bridge->parent; /* Check bus numbers are already set up correctly: */ - if (bridge_to_fix->subordinate >= cardbus_bridge->subordinate) + if (bridge_to_fix->busn_res.end >= cardbus_bridge->busn_res.end) return; /* The subordinate number is ok, nothing to do */ if (!bridge_to_fix->parent) return; /* Root bridges are ok */ /* stay within the limits of the bus range of the parent: */ - upper_limit = bridge_to_fix->parent->subordinate; + upper_limit = bridge_to_fix->parent->busn_res.end; /* check the bus ranges of all silbling bridges to prevent overlap */ list_for_each(tmp, &bridge_to_fix->parent->children) { @@ -1104,36 +1104,36 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) * current upper limit, set the new upper limit to * the bus number below the silbling's range: */ - if (silbling->secondary > bridge_to_fix->subordinate - && silbling->secondary <= upper_limit) - upper_limit = silbling->secondary - 1; + if (silbling->busn_res.start > bridge_to_fix->busn_res.end + && silbling->busn_res.start <= upper_limit) + upper_limit = silbling->busn_res.start - 1; } /* Show that the wanted subordinate number is not possible: */ - if (cardbus_bridge->subordinate > upper_limit) + if (cardbus_bridge->busn_res.end > upper_limit) dev_printk(KERN_WARNING, &cardbus_bridge->dev, "Upper limit for fixing this " "bridge's parent bridge: #%02x\n", upper_limit); /* If we have room to increase the bridge's subordinate number, */ - if (bridge_to_fix->subordinate < upper_limit) { + if (bridge_to_fix->busn_res.end < upper_limit) { /* use the highest number of the hidden bus, within limits */ unsigned char subordinate_to_assign = - min(cardbus_bridge->subordinate, upper_limit); + min_t(int, cardbus_bridge->busn_res.end, upper_limit); dev_printk(KERN_INFO, &bridge_to_fix->dev, "Raising subordinate bus# of parent " "bus (#%02x) from #%02x to #%02x\n", bridge_to_fix->number, - bridge_to_fix->subordinate, subordinate_to_assign); + (int)bridge_to_fix->busn_res.end, subordinate_to_assign); /* Save the new subordinate in the bus struct of the bridge */ - bridge_to_fix->subordinate = subordinate_to_assign; + bridge_to_fix->busn_res.end = subordinate_to_assign; /* and update the PCI config space with the new subordinate */ pci_write_config_byte(bridge_to_fix->self, - PCI_SUBORDINATE_BUS, bridge_to_fix->subordinate); + PCI_SUBORDINATE_BUS, bridge_to_fix->busn_res.end); } } -- cgit v1.2.3 From 5c1d81d160cc46e36fdd06702885c98c2643b4c5 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: x86/PCI: use _CRS bus number aperture for host bridges from ACPI Add the host bridge bus number aperture from _CRS to the resource list. Like the MMIO and I/O port apertures, this will be used when assigning resources to hot-added devices or in the case of conflicts. Note that we always use the _CRS bus number aperture, even if we're ignoring _CRS otherwise. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/acpi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 350fe63c8a42..2bb885afe103 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -12,7 +12,6 @@ struct pci_root_info { char name[16]; unsigned int res_num; struct resource *res; - int busnum; struct pci_sysdata sd; }; @@ -347,7 +346,9 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, { size_t size; + sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum); info->bridge = device; + info->res_num = 0; acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, info); @@ -360,8 +361,6 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, if (!info->res) return; - sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum); - acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, info); } @@ -426,6 +425,8 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) } else { probe_pci_root_info(info, device, busnum, domain); + /* insert busn res at first */ + pci_add_resource(&resources, &root->secondary); /* * _CRS with no apertures is normal, so only fall back to * defaults or native bridge info if we're ignoring _CRS. @@ -440,7 +441,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd, &resources); if (bus) { - bus->busn_res.end = pci_scan_child_bus(bus); + pci_scan_child_bus(bus); pci_set_host_bridge_release( to_pci_host_bridge(bus->bridge), release_pci_root_info, info); -- cgit v1.2.3 From a10bb128b64fe03198c4930f4483dda55c5c84eb Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: x86/PCI: put busn resource in pci_root_info for native host bridge drivers Add the host bridge bus number aperture to the resource list. Like the MMIO and I/O port apertures, this will be used when assigning resources to hot-added devices or in the case of conflicts. [bhelgaas: changelog, tidy printk] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/amd_bus.c | 7 +++---- arch/x86/pci/bus_numa.c | 22 +++++++++++++++++++--- arch/x86/pci/bus_numa.h | 3 +-- 3 files changed, 23 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index 5aed49bff058..e9e6ed5cdf94 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c @@ -121,7 +121,6 @@ static int __init early_fill_mp_bus_info(void) link = (reg >> 8) & 0x03; info = alloc_pci_root_info(min_bus, max_bus, node, link); - sprintf(info->name, "PCI Bus #%02x", min_bus); } /* get the default node and link for left over res */ @@ -300,9 +299,9 @@ static int __init early_fill_mp_bus_info(void) int busnum; struct pci_root_res *root_res; - busnum = info->bus_min; - printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n", - info->bus_min, info->bus_max, info->node, info->link); + busnum = info->busn.start; + printk(KERN_DEBUG "bus: %pR on node %x link %x\n", + &info->busn, info->node, info->link); list_for_each_entry(root_res, &info->resources, list) printk(KERN_DEBUG "bus: %02x %pR\n", busnum, &root_res->res); diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c index 306579f7d0fd..d37e2fec97e5 100644 --- a/arch/x86/pci/bus_numa.c +++ b/arch/x86/pci/bus_numa.c @@ -14,7 +14,7 @@ static struct pci_root_info *x86_find_pci_root_info(int bus) return NULL; list_for_each_entry(info, &pci_root_infos, list) - if (info->bus_min == bus) + if (info->busn.start == bus) return info; return NULL; @@ -24,6 +24,8 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources) { struct pci_root_info *info = x86_find_pci_root_info(bus); struct pci_root_res *root_res; + struct pci_host_bridge_window *window; + bool found = false; if (!info) goto default_resources; @@ -31,6 +33,16 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources) printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n", bus); + /* already added by acpi ? */ + list_for_each_entry(window, resources, list) + if (window->res->flags & IORESOURCE_BUS) { + found = true; + break; + } + + if (!found) + pci_add_resource(resources, &info->busn); + list_for_each_entry(root_res, &info->resources, list) { struct resource *res; struct resource *root; @@ -66,9 +78,13 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max, if (!info) return info; + sprintf(info->name, "PCI Bus #%02x", bus_min); + INIT_LIST_HEAD(&info->resources); - info->bus_min = bus_min; - info->bus_max = bus_max; + info->busn.name = info->name; + info->busn.start = bus_min; + info->busn.end = bus_max; + info->busn.flags = IORESOURCE_BUS; info->node = node; info->link = link; diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h index 226a466b2b2b..ff8f65b04574 100644 --- a/arch/x86/pci/bus_numa.h +++ b/arch/x86/pci/bus_numa.h @@ -13,8 +13,7 @@ struct pci_root_info { struct list_head list; char name[12]; struct list_head resources; - int bus_min; - int bus_max; + struct resource busn; int node; int link; }; -- cgit v1.2.3 From 2661b819a10d432aa6f508630ff72e31367d4f21 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: ia64/PCI: register busn_res for root buses Add the host bridge bus number aperture from _CRS to the resource list. Like the MMIO and I/O port apertures, this is used when assigning resources to hot-added devices or in the case of conflicts. [bhelgaas: changelog] CC: Tony Luck CC: Fenghua Yu CC: linux-ia64@vger.kernel.org Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/ia64/pci/pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 3ca9bed7dc50..d173a88d744a 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -351,6 +351,8 @@ pci_acpi_scan_root(struct acpi_pci_root *root) #endif INIT_LIST_HEAD(&info.resources); + /* insert busn resource at first */ + pci_add_resource(&info.resources, &root->secondary); acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, &windows); if (windows) { @@ -384,7 +386,7 @@ pci_acpi_scan_root(struct acpi_pci_root *root) return NULL; } - pbus->busn_res.end = pci_scan_child_bus(pbus); + pci_scan_child_bus(pbus); return pbus; out3: -- cgit v1.2.3 From 3f1b540d460589e20df882aa2c86808d113890a8 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: sparc/PCI: register busn_res for root buses Add the host bridge bus number aperture to the resource list. Like the MMIO and I/O port apertures, this is used when assigning resources to hot-added devices or in the case of conflicts. [bhelgaas: changelog, fix "pci_last_busn" typo] Acked-by: "David S. Miller" CC: sparclinux@vger.kernel.org Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/sparc/kernel/pci.c | 8 +++++--- arch/sparc/kernel/pci_impl.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index c85bfd788f74..4f92a9aba358 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -535,7 +535,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, } bus->primary = dev->bus->number; - bus->busn_res.end = busrange[1]; + pci_bus_insert_busn_res(bus, busrange[0], busrange[1]); bus->bridge_ctl = 0; /* parse ranges property, or cook one up by hand for Simba */ @@ -685,6 +685,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, pbm->io_space.start); pci_add_resource_offset(&resources, &pbm->mem_space, pbm->mem_space.start); + pbm->busn.start = pbm->pci_first_busno; + pbm->busn.end = pbm->pci_last_busno; + pbm->busn.flags = IORESOURCE_BUS; + pci_add_resource(&resources, &pbm->busn); bus = pci_create_root_bus(parent, pbm->pci_first_busno, pbm->pci_ops, pbm, &resources); if (!bus) { @@ -693,8 +697,6 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, pci_free_resource_list(&resources); return NULL; } - bus->busn_res.start = pbm->pci_first_busno; - bus->busn_res.end = pbm->pci_last_busno; pci_of_scan_bus(pbm, node, bus); pci_bus_add_devices(bus); diff --git a/arch/sparc/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h index 6beb60df31d0..918a2031c8bb 100644 --- a/arch/sparc/kernel/pci_impl.h +++ b/arch/sparc/kernel/pci_impl.h @@ -97,6 +97,7 @@ struct pci_pbm_info { /* PBM I/O and Memory space resources. */ struct resource io_space; struct resource mem_space; + struct resource busn; /* Base of PCI Config space, can be per-PBM or shared. */ unsigned long config_space; -- cgit v1.2.3 From be8e60d8bed118b19bd7038ac2f6ac6688d072d9 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:12 -0700 Subject: powerpc/PCI: register busn_res for root buses Add the host bridge bus number aperture to the resource list. Like the MMIO and I/O port apertures, this is used when assigning resources to hot-added devices or in the case of conflicts. [bhelgaas: changelog] CC: Paul Mackerras CC: linuxppc-dev@lists.ozlabs.org CC: Benjamin Herrenschmidt Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/powerpc/include/asm/pci-bridge.h | 1 + arch/powerpc/kernel/pci-common.c | 17 +++++++++++------ arch/powerpc/kernel/pci_of_scan.c | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index ac39e6a3b25a..8cccbee61519 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -30,6 +30,7 @@ struct pci_controller { int first_busno; int last_busno; int self_busno; + struct resource busn; void __iomem *io_base_virt; #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 3532b535698a..7320f3685523 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1637,6 +1637,11 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) /* Wire up PHB bus resources */ pcibios_setup_phb_resources(hose, &resources); + hose->busn.start = hose->first_busno; + hose->busn.end = hose->last_busno; + hose->busn.flags = IORESOURCE_BUS; + pci_add_resource(&resources, &hose->busn); + /* Create an empty bus for the toplevel */ bus = pci_create_root_bus(hose->parent, hose->first_busno, hose->ops, hose, &resources); @@ -1646,7 +1651,6 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) pci_free_resource_list(&resources); return; } - bus->busn_res.start = hose->first_busno; hose->bus = bus; /* Get probe mode and perform scan */ @@ -1654,13 +1658,14 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) if (node && ppc_md.pci_probe_mode) mode = ppc_md.pci_probe_mode(bus); pr_debug(" probe mode: %d\n", mode); - if (mode == PCI_PROBE_DEVTREE) { - bus->busn_res.end = hose->last_busno; + if (mode == PCI_PROBE_DEVTREE) of_scan_bus(node, bus); - } - if (mode == PCI_PROBE_NORMAL) - hose->last_busno = bus->busn_res.end = pci_scan_child_bus(bus); + if (mode == PCI_PROBE_NORMAL) { + pci_bus_update_busn_res_end(bus, 255); + hose->last_busno = pci_scan_child_bus(bus); + pci_bus_update_busn_res_end(bus, hose->last_busno); + } /* Platform gets a chance to do some global fixups before * we proceed to resource allocation diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index a36281aa98f3..ae5ea5e04d65 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -240,7 +240,7 @@ void __devinit of_scan_pci_bridge(struct pci_dev *dev) } bus->primary = dev->bus->number; - bus->busn_res.end = busrange[1]; + pci_bus_insert_busn_res(bus, busrange[0], busrange[1]); bus->bridge_ctl = 0; /* parse ranges property */ -- cgit v1.2.3 From b17c0e6f665023ae729ca112516c7b6f3b71f9d3 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 17 May 2012 18:51:13 -0700 Subject: tile/PCI: use pci_scan_root_bus instead pci_scan_bus It will update busn_res accordingly, so we get that for last_busno. Acked-by: Chris Metcalf Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/tile/kernel/pci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index 54cc8d77c90c..87422ed7b834 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c @@ -310,6 +310,7 @@ int __init pcibios_init(void) if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) { struct pci_controller *controller = &controllers[i]; struct pci_bus *bus; + LIST_HEAD(resources); if (tile_init_irqs(i, controller)) { pr_err("PCI: Could not initialize IRQs\n"); @@ -327,7 +328,9 @@ int __init pcibios_init(void) * This is inlined in linux/pci.h and calls into * pci_scan_bus_parented() in probe.c. */ - bus = pci_scan_bus(0, controller->ops, controller); + pci_add_resource(&resources, &ioport_resource); + pci_add_resource(&resources, &iomem_resource); + bus = pci_scan_root_bus(NULL, 0, controller->ops, controller, &resources); controller->root_bus = bus; controller->last_busno = bus->busn_res.end; } -- cgit v1.2.3 From 00763e41138267a307531397f9745835aecb8c7b Mon Sep 17 00:00:00 2001 From: Xudong Hao Date: Thu, 7 Jun 2012 18:26:07 +0800 Subject: KVM: x86: change PT_FIRST_AVAIL_BITS_SHIFT to avoid conflict with EPT Dirty bit EPT Dirty bit use bit 9 as Intel SDM definition, to avoid conflict, change PT_FIRST_AVAIL_BITS_SHIFT to 10. Signed-off-by: Xudong Hao Signed-off-by: Xiantao Zhang Signed-off-by: Marcelo Tosatti --- arch/x86/kvm/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index b32a11dc884c..3b53d9e08bfc 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -90,7 +90,7 @@ module_param(dbg, bool, 0644); #define PTE_PREFETCH_NUM 8 -#define PT_FIRST_AVAIL_BITS_SHIFT 9 +#define PT_FIRST_AVAIL_BITS_SHIFT 10 #define PT64_SECOND_AVAIL_BITS_SHIFT 52 #define PT64_LEVEL_BITS 9 -- cgit v1.2.3 From 61bde82caee95426bf1ad53fefc8dc691b8ba37c Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 11 Jun 2012 16:06:57 +0200 Subject: KVM: s390: Set CPU in stopped state on initial cpu reset The initial cpu reset sets the cpu in the stopped state. Several places check for the cpu state (e.g. sigp set prefix) and not setting the STOPPED state triggered errors with newer guest kernels after reboot. Signed-off-by: Christian Borntraeger Signed-off-by: Cornelia Huck Signed-off-by: Marcelo Tosatti --- arch/s390/kvm/kvm-s390.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 664766d0c83c..ace93603d861 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -347,6 +347,7 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu) vcpu->arch.guest_fpregs.fpc = 0; asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc)); vcpu->arch.sie_block->gbea = 1; + atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags); } int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) -- cgit v1.2.3 From cd1834591fe9564720ac4b0193bf1c790fe89f0d Mon Sep 17 00:00:00 2001 From: Heinz Graalfs Date: Mon, 11 Jun 2012 16:06:59 +0200 Subject: KVM: s390: Perform early event mask processing during boot For processing under KVM it is required to detect the actual SCLP console type in order to set it as preferred console. Signed-off-by: Heinz Graalfs Acked-by: Heiko Carstens Acked-by: Peter Oberparleiter Signed-off-by: Cornelia Huck Signed-off-by: Marcelo Tosatti --- arch/s390/include/asm/sclp.h | 2 ++ arch/s390/kernel/setup.c | 12 +++++++++--- drivers/s390/char/sclp.c | 10 ---------- drivers/s390/char/sclp.h | 10 ++++++++++ drivers/s390/char/sclp_cmd.c | 38 ++++++++++++++++++++++++++++++++++++++ drivers/s390/kvm/kvm_virtio.c | 3 ++- 6 files changed, 61 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index bf238c55740b..173f07aaeb2b 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -55,5 +55,7 @@ int sclp_chp_configure(struct chp_id chpid); int sclp_chp_deconfigure(struct chp_id chpid); int sclp_chp_read_info(struct sclp_chp_info *info); void sclp_get_ipl_info(struct sclp_ipl_info *info); +bool sclp_has_linemode(void); +bool sclp_has_vt220(void); #endif /* _ASM_S390_SCLP_H */ diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 489d1d8d96b0..e86bca6f975c 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -63,6 +63,7 @@ #include #include #include +#include #include "entry.h" long psw_kernel_bits = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY | @@ -138,9 +139,14 @@ __setup("condev=", condev_setup); static void __init set_preferred_console(void) { - if (MACHINE_IS_KVM) - add_preferred_console("hvc", 0, NULL); - else if (CONSOLE_IS_3215 || CONSOLE_IS_SCLP) + if (MACHINE_IS_KVM) { + if (sclp_has_vt220()) + add_preferred_console("ttyS", 1, NULL); + else if (sclp_has_linemode()) + add_preferred_console("ttyS", 0, NULL); + else + add_preferred_console("hvc", 0, NULL); + } else if (CONSOLE_IS_3215 || CONSOLE_IS_SCLP) add_preferred_console("ttyS", 0, NULL); else if (CONSOLE_IS_3270) add_preferred_console("tty3270", 0, NULL); diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 30f29a0020a1..3fcc000efc53 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -654,16 +654,6 @@ sclp_remove_processed(struct sccb_header *sccb) EXPORT_SYMBOL(sclp_remove_processed); -struct init_sccb { - struct sccb_header header; - u16 _reserved; - u16 mask_length; - sccb_mask_t receive_mask; - sccb_mask_t send_mask; - sccb_mask_t sclp_receive_mask; - sccb_mask_t sclp_send_mask; -} __attribute__((packed)); - /* Prepare init mask request. Called while sclp_lock is locked. */ static inline void __sclp_make_init_req(u32 receive_mask, u32 send_mask) diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 49a1bb52bc87..d7e97ae9ef6d 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -88,6 +88,16 @@ struct sccb_header { u16 response_code; } __attribute__((packed)); +struct init_sccb { + struct sccb_header header; + u16 _reserved; + u16 mask_length; + sccb_mask_t receive_mask; + sccb_mask_t send_mask; + sccb_mask_t sclp_receive_mask; + sccb_mask_t sclp_send_mask; +} __attribute__((packed)); + extern u64 sclp_facilities; #define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL) #define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL) diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 766cb7b19b40..71ea923c322d 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -48,6 +48,7 @@ struct read_info_sccb { u8 _reserved5[4096 - 112]; /* 112-4095 */ } __attribute__((packed, aligned(PAGE_SIZE))); +static struct init_sccb __initdata early_event_mask_sccb __aligned(PAGE_SIZE); static struct read_info_sccb __initdata early_read_info_sccb; static int __initdata early_read_info_sccb_valid; @@ -104,6 +105,19 @@ static void __init sclp_read_info_early(void) } } +static void __init sclp_event_mask_early(void) +{ + struct init_sccb *sccb = &early_event_mask_sccb; + int rc; + + do { + memset(sccb, 0, sizeof(*sccb)); + sccb->header.length = sizeof(*sccb); + sccb->mask_length = sizeof(sccb_mask_t); + rc = sclp_cmd_sync_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); + } while (rc == -EBUSY); +} + void __init sclp_facilities_detect(void) { struct read_info_sccb *sccb; @@ -119,6 +133,30 @@ void __init sclp_facilities_detect(void) rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; rzm <<= 20; + + sclp_event_mask_early(); +} + +bool __init sclp_has_linemode(void) +{ + struct init_sccb *sccb = &early_event_mask_sccb; + + if (sccb->header.response_code != 0x20) + return 0; + if (sccb->sclp_send_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)) + return 1; + return 0; +} + +bool __init sclp_has_vt220(void) +{ + struct init_sccb *sccb = &early_event_mask_sccb; + + if (sccb->header.response_code != 0x20) + return 0; + if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) + return 1; + return 0; } unsigned long long sclp_get_rnmax(void) diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index d74e9ae6dfb3..d3bdae49512f 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -468,7 +469,7 @@ static __init int early_put_chars(u32 vtermno, const char *buf, int count) static int __init s390_virtio_console_init(void) { - if (!MACHINE_IS_KVM) + if (sclp_has_vt220() || sclp_has_linemode()) return -ENODEV; return virtio_cons_early_init(early_put_chars); } -- cgit v1.2.3 From d691af000274ae9658695c2a63a76b30890a8983 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 12 Jun 2012 16:50:55 +0800 Subject: crypto: s390 - clean up DES code a bit more Commit 98971f8439b1bb9a61682fe24a865ddd25167a6b ("crypto: s390 - cleanup DES code") should have also removed crypto_des.h. That file is unused and unneeded since that commit. So let's clean up that file too. Signed-off-by: Paul Bolle Acked-by: Jan Glauber Signed-off-by: Herbert Xu --- arch/s390/crypto/crypto_des.h | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 arch/s390/crypto/crypto_des.h (limited to 'arch') diff --git a/arch/s390/crypto/crypto_des.h b/arch/s390/crypto/crypto_des.h deleted file mode 100644 index 6210457ceebb..000000000000 --- a/arch/s390/crypto/crypto_des.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Cryptographic API. - * - * Function for checking keys for the DES and Tripple DES Encryption - * algorithms. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ -#ifndef __CRYPTO_DES_H__ -#define __CRYPTO_DES_H__ - -extern int crypto_des_check_key(const u8*, unsigned int, u32*); - -#endif /*__CRYPTO_DES_H__*/ -- cgit v1.2.3 From 3387e7d69048f5ab02729825f9611754850d9a87 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Thu, 14 Jun 2012 10:09:03 +0800 Subject: crypto: serpent-sse2/avx - allow both to be built into kernel Rename serpent-avx assembler functions so that they do not collide with serpent-sse2 assembler functions when linking both versions in to same kernel image. Reported-by: Randy Dunlap Cc: Johannes Goetzfried Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/serpent-avx-x86_64-asm_64.S | 12 +++--- arch/x86/crypto/serpent_avx_glue.c | 2 +- arch/x86/crypto/serpent_sse2_glue.c | 2 +- arch/x86/include/asm/serpent-avx.h | 32 +++++++++++++++ arch/x86/include/asm/serpent-sse2.h | 63 +++++++++++++++++++++++++++++ arch/x86/include/asm/serpent.h | 63 ----------------------------- 6 files changed, 103 insertions(+), 71 deletions(-) create mode 100644 arch/x86/include/asm/serpent-avx.h create mode 100644 arch/x86/include/asm/serpent-sse2.h delete mode 100644 arch/x86/include/asm/serpent.h (limited to 'arch') diff --git a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S index 0ed47a124bac..504106bf04a2 100644 --- a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S +++ b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S @@ -579,10 +579,10 @@ vmovdqu x3, (3*4*4)(out); .align 8 -.global __serpent_enc_blk_8way -.type __serpent_enc_blk_8way,@function; +.global __serpent_enc_blk_8way_avx +.type __serpent_enc_blk_8way_avx,@function; -__serpent_enc_blk_8way: +__serpent_enc_blk_8way_avx: /* input: * %rdi: ctx, CTX * %rsi: dst @@ -647,10 +647,10 @@ __enc_xor8: ret; .align 8 -.global serpent_dec_blk_8way -.type serpent_dec_blk_8way,@function; +.global serpent_dec_blk_8way_avx +.type serpent_dec_blk_8way_avx,@function; -serpent_dec_blk_8way: +serpent_dec_blk_8way_avx: /* input: * %rdi: ctx, CTX * %rsi: dst diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c index 0dc7a26535e5..dd81bab4f11a 100644 --- a/arch/x86/crypto/serpent_avx_glue.c +++ b/arch/x86/crypto/serpent_avx_glue.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c index 4b21be85e0a1..deecd25c1299 100644 --- a/arch/x86/crypto/serpent_sse2_glue.c +++ b/arch/x86/crypto/serpent_sse2_glue.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/include/asm/serpent-avx.h b/arch/x86/include/asm/serpent-avx.h new file mode 100644 index 000000000000..432deedd2945 --- /dev/null +++ b/arch/x86/include/asm/serpent-avx.h @@ -0,0 +1,32 @@ +#ifndef ASM_X86_SERPENT_AVX_H +#define ASM_X86_SERPENT_AVX_H + +#include +#include + +#define SERPENT_PARALLEL_BLOCKS 8 + +asmlinkage void __serpent_enc_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst, + const u8 *src, bool xor); +asmlinkage void serpent_dec_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst, + const u8 *src); + +static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_8way_avx(ctx, dst, src, false); +} + +static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_8way_avx(ctx, dst, src, true); +} + +static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + serpent_dec_blk_8way_avx(ctx, dst, src); +} + +#endif diff --git a/arch/x86/include/asm/serpent-sse2.h b/arch/x86/include/asm/serpent-sse2.h new file mode 100644 index 000000000000..e6e77dffbdab --- /dev/null +++ b/arch/x86/include/asm/serpent-sse2.h @@ -0,0 +1,63 @@ +#ifndef ASM_X86_SERPENT_SSE2_H +#define ASM_X86_SERPENT_SSE2_H + +#include +#include + +#ifdef CONFIG_X86_32 + +#define SERPENT_PARALLEL_BLOCKS 4 + +asmlinkage void __serpent_enc_blk_4way(struct serpent_ctx *ctx, u8 *dst, + const u8 *src, bool xor); +asmlinkage void serpent_dec_blk_4way(struct serpent_ctx *ctx, u8 *dst, + const u8 *src); + +static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_4way(ctx, dst, src, false); +} + +static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_4way(ctx, dst, src, true); +} + +static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + serpent_dec_blk_4way(ctx, dst, src); +} + +#else + +#define SERPENT_PARALLEL_BLOCKS 8 + +asmlinkage void __serpent_enc_blk_8way(struct serpent_ctx *ctx, u8 *dst, + const u8 *src, bool xor); +asmlinkage void serpent_dec_blk_8way(struct serpent_ctx *ctx, u8 *dst, + const u8 *src); + +static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_8way(ctx, dst, src, false); +} + +static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_8way(ctx, dst, src, true); +} + +static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + serpent_dec_blk_8way(ctx, dst, src); +} + +#endif + +#endif diff --git a/arch/x86/include/asm/serpent.h b/arch/x86/include/asm/serpent.h deleted file mode 100644 index d3ef63fe0c81..000000000000 --- a/arch/x86/include/asm/serpent.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef ASM_X86_SERPENT_H -#define ASM_X86_SERPENT_H - -#include -#include - -#ifdef CONFIG_X86_32 - -#define SERPENT_PARALLEL_BLOCKS 4 - -asmlinkage void __serpent_enc_blk_4way(struct serpent_ctx *ctx, u8 *dst, - const u8 *src, bool xor); -asmlinkage void serpent_dec_blk_4way(struct serpent_ctx *ctx, u8 *dst, - const u8 *src); - -static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - __serpent_enc_blk_4way(ctx, dst, src, false); -} - -static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - __serpent_enc_blk_4way(ctx, dst, src, true); -} - -static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - serpent_dec_blk_4way(ctx, dst, src); -} - -#else - -#define SERPENT_PARALLEL_BLOCKS 8 - -asmlinkage void __serpent_enc_blk_8way(struct serpent_ctx *ctx, u8 *dst, - const u8 *src, bool xor); -asmlinkage void serpent_dec_blk_8way(struct serpent_ctx *ctx, u8 *dst, - const u8 *src); - -static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - __serpent_enc_blk_8way(ctx, dst, src, false); -} - -static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - __serpent_enc_blk_8way(ctx, dst, src, true); -} - -static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - serpent_dec_blk_8way(ctx, dst, src); -} - -#endif - -#endif -- cgit v1.2.3 From db218b3d55627ef515d3b32888b269ed319c4c8d Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 14 Jun 2012 14:05:24 +0900 Subject: sh64: Use generic unaligned access control/counters. This switches over from the special-casing that sh64 had and to the model that's being employed for sh32. Signed-off-by: Paul Mundt --- arch/sh/kernel/traps_64.c | 150 ++++++++++++---------------------------------- 1 file changed, 37 insertions(+), 113 deletions(-) (limited to 'arch') diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c index ba95d63e623d..488c1cd557f1 100644 --- a/arch/sh/kernel/traps_64.c +++ b/arch/sh/kernel/traps_64.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -264,20 +264,20 @@ static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_na die_if_no_fixup(str, regs, error_code); } -static int read_opcode(unsigned long long pc, unsigned long *result_opcode, int from_user_mode) +static int read_opcode(reg_size_t pc, insn_size_t *result_opcode, int from_user_mode) { int get_user_error; unsigned long aligned_pc; - unsigned long opcode; + insn_size_t opcode; if ((pc & 3) == 1) { /* SHmedia */ aligned_pc = pc & ~3; if (from_user_mode) { - if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) { + if (!access_ok(VERIFY_READ, aligned_pc, sizeof(insn_size_t))) { get_user_error = -EFAULT; } else { - get_user_error = __get_user(opcode, (unsigned long *)aligned_pc); + get_user_error = __get_user(opcode, (insn_size_t *)aligned_pc); *result_opcode = opcode; } return get_user_error; @@ -285,7 +285,7 @@ static int read_opcode(unsigned long long pc, unsigned long *result_opcode, int /* If the fault was in the kernel, we can either read * this directly, or if not, we fault. */ - *result_opcode = *(unsigned long *) aligned_pc; + *result_opcode = *(insn_size_t *)aligned_pc; return 0; } } else if ((pc & 1) == 0) { @@ -311,17 +311,23 @@ static int address_is_sign_extended(__u64 a) #endif } +/* return -1 for fault, 0 for OK */ static int generate_and_check_address(struct pt_regs *regs, - __u32 opcode, + insn_size_t opcode, int displacement_not_indexed, int width_shift, __u64 *address) { - /* return -1 for fault, 0 for OK */ - __u64 base_address, addr; int basereg; + switch (1 << width_shift) { + case 1: inc_unaligned_byte_access(); break; + case 2: inc_unaligned_word_access(); break; + case 4: inc_unaligned_dword_access(); break; + case 8: inc_unaligned_multi_access(); break; + } + basereg = (opcode >> 20) & 0x3f; base_address = regs->regs[basereg]; if (displacement_not_indexed) { @@ -338,28 +344,28 @@ static int generate_and_check_address(struct pt_regs *regs, } /* Check sign extended */ - if (!address_is_sign_extended(addr)) { + if (!address_is_sign_extended(addr)) return -1; - } /* Check accessible. For misaligned access in the kernel, assume the address is always accessible (and if not, just fault when the load/store gets done.) */ if (user_mode(regs)) { - if (addr >= TASK_SIZE) { + inc_unaligned_user_access(); + + if (addr >= TASK_SIZE) return -1; - } - /* Do access_ok check later - it depends on whether it's a load or a store. */ - } + } else + inc_unaligned_kernel_access(); *address = addr; + + perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, addr); + unaligned_fixups_notify(current, opcode, regs); + return 0; } -static int user_mode_unaligned_fixup_count = 10; -static int user_mode_unaligned_fixup_enable = 1; -static int kernel_mode_unaligned_fixup_count = 32; - static void misaligned_kernel_word_load(__u64 address, int do_sign_extend, __u64 *result) { unsigned short x; @@ -389,7 +395,7 @@ static void misaligned_kernel_word_store(__u64 address, __u64 value) } static int misaligned_load(struct pt_regs *regs, - __u32 opcode, + insn_size_t opcode, int displacement_not_indexed, int width_shift, int do_sign_extend) @@ -401,11 +407,8 @@ static int misaligned_load(struct pt_regs *regs, error = generate_and_check_address(regs, opcode, displacement_not_indexed, width_shift, &address); - if (error < 0) { + if (error < 0) return error; - } - - perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address); destreg = (opcode >> 4) & 0x3f; if (user_mode(regs)) { @@ -464,11 +467,10 @@ static int misaligned_load(struct pt_regs *regs, } return 0; - } static int misaligned_store(struct pt_regs *regs, - __u32 opcode, + insn_size_t opcode, int displacement_not_indexed, int width_shift) { @@ -479,11 +481,8 @@ static int misaligned_store(struct pt_regs *regs, error = generate_and_check_address(regs, opcode, displacement_not_indexed, width_shift, &address); - if (error < 0) { + if (error < 0) return error; - } - - perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address); srcreg = (opcode >> 4) & 0x3f; if (user_mode(regs)) { @@ -537,13 +536,12 @@ static int misaligned_store(struct pt_regs *regs, } return 0; - } /* Never need to fix up misaligned FPU accesses within the kernel since that's a real error. */ static int misaligned_fpu_load(struct pt_regs *regs, - __u32 opcode, + insn_size_t opcode, int displacement_not_indexed, int width_shift, int do_paired_load) @@ -555,11 +553,8 @@ static int misaligned_fpu_load(struct pt_regs *regs, error = generate_and_check_address(regs, opcode, displacement_not_indexed, width_shift, &address); - if (error < 0) { + if (error < 0) return error; - } - - perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, address); destreg = (opcode >> 4) & 0x3f; if (user_mode(regs)) { @@ -615,12 +610,10 @@ static int misaligned_fpu_load(struct pt_regs *regs, die ("Misaligned FPU load inside kernel", regs, 0); return -1; } - - } static int misaligned_fpu_store(struct pt_regs *regs, - __u32 opcode, + insn_size_t opcode, int displacement_not_indexed, int width_shift, int do_paired_load) @@ -632,11 +625,8 @@ static int misaligned_fpu_store(struct pt_regs *regs, error = generate_and_check_address(regs, opcode, displacement_not_indexed, width_shift, &address); - if (error < 0) { + if (error < 0) return error; - } - - perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, address); srcreg = (opcode >> 4) & 0x3f; if (user_mode(regs)) { @@ -697,11 +687,13 @@ static int misaligned_fpu_store(struct pt_regs *regs, static int misaligned_fixup(struct pt_regs *regs) { - unsigned long opcode; + insn_size_t opcode; int error; int major, minor; + unsigned int user_action; - if (!user_mode_unaligned_fixup_enable) + user_action = unaligned_user_action(); + if (!(user_action & UM_FIXUP)) return -1; error = read_opcode(regs->pc, &opcode, user_mode(regs)); @@ -711,23 +703,6 @@ static int misaligned_fixup(struct pt_regs *regs) major = (opcode >> 26) & 0x3f; minor = (opcode >> 16) & 0xf; - if (user_mode(regs) && (user_mode_unaligned_fixup_count > 0)) { - --user_mode_unaligned_fixup_count; - /* Only do 'count' worth of these reports, to remove a potential DoS against syslog */ - printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n", - current->comm, task_pid_nr(current), (__u32)regs->pc, opcode); - } else if (!user_mode(regs) && (kernel_mode_unaligned_fixup_count > 0)) { - --kernel_mode_unaligned_fixup_count; - if (in_interrupt()) { - printk("Fixing up unaligned kernelspace access in interrupt pc=0x%08x ins=0x%08lx\n", - (__u32)regs->pc, opcode); - } else { - printk("Fixing up unaligned kernelspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n", - current->comm, task_pid_nr(current), (__u32)regs->pc, opcode); - } - } - - switch (major) { case (0x84>>2): /* LD.W */ error = misaligned_load(regs, opcode, 1, 1, 1); @@ -855,57 +830,6 @@ static int misaligned_fixup(struct pt_regs *regs) } -static ctl_table unaligned_table[] = { - { - .procname = "kernel_reports", - .data = &kernel_mode_unaligned_fixup_count, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, - { - .procname = "user_reports", - .data = &user_mode_unaligned_fixup_count, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, - { - .procname = "user_enable", - .data = &user_mode_unaligned_fixup_enable, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec}, - {} -}; - -static ctl_table unaligned_root[] = { - { - .procname = "unaligned_fixup", - .mode = 0555, - .child = unaligned_table - }, - {} -}; - -static ctl_table sh64_root[] = { - { - .procname = "sh64", - .mode = 0555, - .child = unaligned_root - }, - {} -}; -static struct ctl_table_header *sysctl_header; -static int __init init_sysctl(void) -{ - sysctl_header = register_sysctl_table(sh64_root); - return 0; -} - -__initcall(init_sysctl); - - asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs) { u64 peek_real_address_q(u64 addr); -- cgit v1.2.3 From 37c9ee0161332291c8d13bc40084d24c744ed842 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 14 Jun 2012 14:12:18 +0900 Subject: sh64: Kill off old exception debugging helpers. There's not much here that we can't get at through alternate means (aside from the TLB contents, but that doesn't belong here anyways). Most of this information is already provided by the sh32 routines, which we'll consolidate on next. Signed-off-by: Paul Mundt --- arch/sh/kernel/traps_64.c | 12 --- arch/sh/lib64/Makefile | 2 +- arch/sh/lib64/dbg.c | 248 ---------------------------------------------- 3 files changed, 1 insertion(+), 261 deletions(-) delete mode 100644 arch/sh/lib64/dbg.c (limited to 'arch') diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c index 488c1cd557f1..c902c29400a3 100644 --- a/arch/sh/kernel/traps_64.c +++ b/arch/sh/kernel/traps_64.c @@ -32,15 +32,6 @@ #include #include -#undef DEBUG_EXCEPTION -#ifdef DEBUG_EXCEPTION -/* implemented in ../lib/dbg.c */ -extern void show_excp_regs(char *fname, int trapnr, int signr, - struct pt_regs *regs); -#else -#define show_excp_regs(a, b, c, d) -#endif - static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name, unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk); @@ -239,7 +230,6 @@ DO_ERROR(12, SIGILL, "reserved instruction", reserved_inst, current) /* Called with interrupts disabled */ asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs) { - show_excp_regs(__func__, -1, -1, regs); die_if_kernel("exception", regs, ex); } @@ -256,8 +246,6 @@ int do_unknown_trapa(unsigned long scId, struct pt_regs *regs) static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name, unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk) { - show_excp_regs(fn_name, trapnr, signr, regs); - if (user_mode(regs)) force_sig(signr, tsk); diff --git a/arch/sh/lib64/Makefile b/arch/sh/lib64/Makefile index 1fee75aa1f98..69779ff741df 100644 --- a/arch/sh/lib64/Makefile +++ b/arch/sh/lib64/Makefile @@ -10,7 +10,7 @@ # # Panic should really be compiled as PIC -lib-y := udelay.o dbg.o panic.o memcpy.o memset.o \ +lib-y := udelay.o panic.o memcpy.o memset.o \ copy_user_memcpy.o copy_page.o strcpy.o strlen.o # Extracted from libgcc diff --git a/arch/sh/lib64/dbg.c b/arch/sh/lib64/dbg.c deleted file mode 100644 index 6152a6a6d9c6..000000000000 --- a/arch/sh/lib64/dbg.c +++ /dev/null @@ -1,248 +0,0 @@ -/*-------------------------------------------------------------------------- --- --- Identity : Linux50 Debug Funcions --- --- File : arch/sh/lib64/dbg.c --- --- Copyright 2000, 2001 STMicroelectronics Limited. --- Copyright 2004 Richard Curnow (evt_debug etc) --- ---------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include -#include - -typedef u64 regType_t; - -static regType_t getConfigReg(u64 id) -{ - register u64 reg __asm__("r2"); - asm volatile ("getcfg %1, 0, %0":"=r" (reg):"r"(id)); - return (reg); -} - -/* ======================================================================= */ - -static char *szTab[] = { "4k", "64k", "1M", "512M" }; -static char *protTab[] = { "----", - "---R", - "--X-", - "--XR", - "-W--", - "-W-R", - "-WX-", - "-WXR", - "U---", - "U--R", - "U-X-", - "U-XR", - "UW--", - "UW-R", - "UWX-", - "UWXR" -}; -#define ITLB_BASE 0x00000000 -#define DTLB_BASE 0x00800000 -#define MAX_TLBs 64 -/* PTE High */ -#define GET_VALID(pte) ((pte) & 0x1) -#define GET_SHARED(pte) ((pte) & 0x2) -#define GET_ASID(pte) ((pte >> 2) & 0x0ff) -#define GET_EPN(pte) ((pte) & 0xfffff000) - -/* PTE Low */ -#define GET_CBEHAVIOR(pte) ((pte) & 0x3) -#define GET_PAGE_SIZE(pte) szTab[((pte >> 3) & 0x3)] -#define GET_PROTECTION(pte) protTab[((pte >> 6) & 0xf)] -#define GET_PPN(pte) ((pte) & 0xfffff000) - -#define PAGE_1K_MASK 0x00000000 -#define PAGE_4K_MASK 0x00000010 -#define PAGE_64K_MASK 0x00000080 -#define MMU_PAGESIZE_MASK (PAGE_64K_MASK | PAGE_4K_MASK) -#define PAGE_1MB_MASK MMU_PAGESIZE_MASK -#define PAGE_1K (1024) -#define PAGE_4K (1024 * 4) -#define PAGE_64K (1024 * 64) -#define PAGE_1MB (1024 * 1024) - -#define HOW_TO_READ_TLB_CONTENT \ - "[ ID] PPN EPN ASID Share CB P.Size PROT.\n" - -void print_single_tlb(unsigned long tlb, int single_print) -{ - regType_t pteH; - regType_t pteL; - unsigned int valid, shared, asid, epn, cb, ppn; - char *pSize; - char *pProt; - - /* - ** in case of single print is true, this implies: - ** 1) print the TLB in any case also if NOT VALID - ** 2) print out the header - */ - - pteH = getConfigReg(tlb); - valid = GET_VALID(pteH); - if (single_print) - printk(HOW_TO_READ_TLB_CONTENT); - else if (!valid) - return; - - pteL = getConfigReg(tlb + 1); - - shared = GET_SHARED(pteH); - asid = GET_ASID(pteH); - epn = GET_EPN(pteH); - cb = GET_CBEHAVIOR(pteL); - pSize = GET_PAGE_SIZE(pteL); - pProt = GET_PROTECTION(pteL); - ppn = GET_PPN(pteL); - printk("[%c%2ld] 0x%08x 0x%08x %03d %02x %02x %4s %s\n", - ((valid) ? ' ' : 'u'), ((tlb & 0x0ffff) / TLB_STEP), - ppn, epn, asid, shared, cb, pSize, pProt); -} - -void print_dtlb(void) -{ - int count; - unsigned long tlb; - - printk(" ================= SH-5 D-TLBs Status ===================\n"); - printk(HOW_TO_READ_TLB_CONTENT); - tlb = DTLB_BASE; - for (count = 0; count < MAX_TLBs; count++, tlb += TLB_STEP) - print_single_tlb(tlb, 0); - printk - (" =============================================================\n"); -} - -void print_itlb(void) -{ - int count; - unsigned long tlb; - - printk(" ================= SH-5 I-TLBs Status ===================\n"); - printk(HOW_TO_READ_TLB_CONTENT); - tlb = ITLB_BASE; - for (count = 0; count < MAX_TLBs; count++, tlb += TLB_STEP) - print_single_tlb(tlb, 0); - printk - (" =============================================================\n"); -} - -void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs) -{ - - unsigned long long ah, al, bh, bl, ch, cl; - - printk("\n"); - printk("EXCEPTION - %s: task %d; Linux trap # %d; signal = %d\n", - ((from) ? from : "???"), current->pid, trapnr, signr); - - asm volatile ("getcon " __EXPEVT ", %0":"=r"(ah)); - asm volatile ("getcon " __EXPEVT ", %0":"=r"(al)); - ah = (ah) >> 32; - al = (al) & 0xffffffff; - asm volatile ("getcon " __KCR1 ", %0":"=r"(bh)); - asm volatile ("getcon " __KCR1 ", %0":"=r"(bl)); - bh = (bh) >> 32; - bl = (bl) & 0xffffffff; - asm volatile ("getcon " __INTEVT ", %0":"=r"(ch)); - asm volatile ("getcon " __INTEVT ", %0":"=r"(cl)); - ch = (ch) >> 32; - cl = (cl) & 0xffffffff; - printk("EXPE: %08Lx%08Lx KCR1: %08Lx%08Lx INTE: %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - asm volatile ("getcon " __PEXPEVT ", %0":"=r"(ah)); - asm volatile ("getcon " __PEXPEVT ", %0":"=r"(al)); - ah = (ah) >> 32; - al = (al) & 0xffffffff; - asm volatile ("getcon " __PSPC ", %0":"=r"(bh)); - asm volatile ("getcon " __PSPC ", %0":"=r"(bl)); - bh = (bh) >> 32; - bl = (bl) & 0xffffffff; - asm volatile ("getcon " __PSSR ", %0":"=r"(ch)); - asm volatile ("getcon " __PSSR ", %0":"=r"(cl)); - ch = (ch) >> 32; - cl = (cl) & 0xffffffff; - printk("PEXP: %08Lx%08Lx PSPC: %08Lx%08Lx PSSR: %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->pc) >> 32; - al = (regs->pc) & 0xffffffff; - bh = (regs->regs[18]) >> 32; - bl = (regs->regs[18]) & 0xffffffff; - ch = (regs->regs[15]) >> 32; - cl = (regs->regs[15]) & 0xffffffff; - printk("PC : %08Lx%08Lx LINK: %08Lx%08Lx SP : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->sr) >> 32; - al = (regs->sr) & 0xffffffff; - asm volatile ("getcon " __TEA ", %0":"=r"(bh)); - asm volatile ("getcon " __TEA ", %0":"=r"(bl)); - bh = (bh) >> 32; - bl = (bl) & 0xffffffff; - asm volatile ("getcon " __KCR0 ", %0":"=r"(ch)); - asm volatile ("getcon " __KCR0 ", %0":"=r"(cl)); - ch = (ch) >> 32; - cl = (cl) & 0xffffffff; - printk("SR : %08Lx%08Lx TEA : %08Lx%08Lx KCR0: %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[0]) >> 32; - al = (regs->regs[0]) & 0xffffffff; - bh = (regs->regs[1]) >> 32; - bl = (regs->regs[1]) & 0xffffffff; - ch = (regs->regs[2]) >> 32; - cl = (regs->regs[2]) & 0xffffffff; - printk("R0 : %08Lx%08Lx R1 : %08Lx%08Lx R2 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[3]) >> 32; - al = (regs->regs[3]) & 0xffffffff; - bh = (regs->regs[4]) >> 32; - bl = (regs->regs[4]) & 0xffffffff; - ch = (regs->regs[5]) >> 32; - cl = (regs->regs[5]) & 0xffffffff; - printk("R3 : %08Lx%08Lx R4 : %08Lx%08Lx R5 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[6]) >> 32; - al = (regs->regs[6]) & 0xffffffff; - bh = (regs->regs[7]) >> 32; - bl = (regs->regs[7]) & 0xffffffff; - ch = (regs->regs[8]) >> 32; - cl = (regs->regs[8]) & 0xffffffff; - printk("R6 : %08Lx%08Lx R7 : %08Lx%08Lx R8 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[9]) >> 32; - al = (regs->regs[9]) & 0xffffffff; - bh = (regs->regs[10]) >> 32; - bl = (regs->regs[10]) & 0xffffffff; - ch = (regs->regs[11]) >> 32; - cl = (regs->regs[11]) & 0xffffffff; - printk("R9 : %08Lx%08Lx R10 : %08Lx%08Lx R11 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - printk("....\n"); - - ah = (regs->tregs[0]) >> 32; - al = (regs->tregs[0]) & 0xffffffff; - bh = (regs->tregs[1]) >> 32; - bl = (regs->tregs[1]) & 0xffffffff; - ch = (regs->tregs[2]) >> 32; - cl = (regs->tregs[2]) & 0xffffffff; - printk("T0 : %08Lx%08Lx T1 : %08Lx%08Lx T2 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - printk("....\n"); - - print_dtlb(); - print_itlb(); -} -- cgit v1.2.3 From 5f857bce21cfd0531dc7d4daac74d976caf6166b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 14 Jun 2012 14:18:51 +0900 Subject: sh: Consolidate die definitions for trap handlers. This kills off the _64 versions and consolidates on the more robust _32 versions instead. Signed-off-by: Paul Mundt --- arch/sh/include/asm/bug.h | 4 +++ arch/sh/kernel/traps.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++ arch/sh/kernel/traps_32.c | 71 ----------------------------------------------- arch/sh/kernel/traps_64.c | 31 --------------------- 4 files changed, 75 insertions(+), 102 deletions(-) (limited to 'arch') diff --git a/arch/sh/include/asm/bug.h b/arch/sh/include/asm/bug.h index 2b87d86bfc41..dcf278075429 100644 --- a/arch/sh/include/asm/bug.h +++ b/arch/sh/include/asm/bug.h @@ -110,6 +110,10 @@ do { \ #include struct pt_regs; + +/* arch/sh/kernel/traps.c */ extern void die(const char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn)); +extern void die_if_kernel(const char *str, struct pt_regs *regs, long err); +extern void die_if_no_fixup(const char *str, struct pt_regs *regs, long err); #endif /* __ASM_SH_BUG_H */ diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index a87e58a9e38f..72246bc06884 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -6,9 +6,80 @@ #include #include #include +#include +#include +#include #include #include +static DEFINE_SPINLOCK(die_lock); + +void die(const char *str, struct pt_regs *regs, long err) +{ + static int die_counter; + + oops_enter(); + + spin_lock_irq(&die_lock); + console_verbose(); + bust_spinlocks(1); + + printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); + print_modules(); + show_regs(regs); + + printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm, + task_pid_nr(current), task_stack_page(current) + 1); + + if (!user_mode(regs) || in_interrupt()) + dump_mem("Stack: ", regs->regs[15], THREAD_SIZE + + (unsigned long)task_stack_page(current)); + + notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV); + + bust_spinlocks(0); + add_taint(TAINT_DIE); + spin_unlock_irq(&die_lock); + oops_exit(); + + if (kexec_should_crash(current)) + crash_kexec(regs); + + if (in_interrupt()) + panic("Fatal exception in interrupt"); + + if (panic_on_oops) + panic("Fatal exception"); + + do_exit(SIGSEGV); +} + +void die_if_kernel(const char *str, struct pt_regs *regs, long err) +{ + if (!user_mode(regs)) + die(str, regs, err); +} + +/* + * try and fix up kernelspace address errors + * - userspace errors just cause EFAULT to be returned, resulting in SEGV + * - kernel/userspace interfaces cause a jump to an appropriate handler + * - other kernel errors are bad + */ +void die_if_no_fixup(const char *str, struct pt_regs *regs, long err) +{ + if (!user_mode(regs)) { + const struct exception_table_entry *fixup; + fixup = search_exception_tables(regs->pc); + if (fixup) { + regs->pc = fixup->fixup; + return; + } + + die(str, regs, err); + } +} + #ifdef CONFIG_GENERIC_BUG static void handle_BUG(struct pt_regs *regs) { diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index b8f5a51841ec..5f513a64dedf 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -16,13 +16,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -48,75 +46,6 @@ #define TRAP_ILLEGAL_SLOT_INST 13 #endif -static DEFINE_SPINLOCK(die_lock); - -void die(const char * str, struct pt_regs * regs, long err) -{ - static int die_counter; - - oops_enter(); - - spin_lock_irq(&die_lock); - console_verbose(); - bust_spinlocks(1); - - printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); - print_modules(); - show_regs(regs); - - printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm, - task_pid_nr(current), task_stack_page(current) + 1); - - if (!user_mode(regs) || in_interrupt()) - dump_mem("Stack: ", regs->regs[15], THREAD_SIZE + - (unsigned long)task_stack_page(current)); - - notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV); - - bust_spinlocks(0); - add_taint(TAINT_DIE); - spin_unlock_irq(&die_lock); - oops_exit(); - - if (kexec_should_crash(current)) - crash_kexec(regs); - - if (in_interrupt()) - panic("Fatal exception in interrupt"); - - if (panic_on_oops) - panic("Fatal exception"); - - do_exit(SIGSEGV); -} - -static inline void die_if_kernel(const char *str, struct pt_regs *regs, - long err) -{ - if (!user_mode(regs)) - die(str, regs, err); -} - -/* - * try and fix up kernelspace address errors - * - userspace errors just cause EFAULT to be returned, resulting in SEGV - * - kernel/userspace interfaces cause a jump to an appropriate handler - * - other kernel errors are bad - */ -static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) -{ - if (!user_mode(regs)) { - const struct exception_table_entry *fixup; - fixup = search_exception_tables(regs->pc); - if (fixup) { - regs->pc = fixup->fixup; - return; - } - - die(str, regs, err); - } -} - static inline void sign_extend(unsigned int count, unsigned char *dst) { #ifdef __LITTLE_ENDIAN__ diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c index c902c29400a3..75bef61892d2 100644 --- a/arch/sh/kernel/traps_64.c +++ b/arch/sh/kernel/traps_64.c @@ -41,37 +41,6 @@ asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \ do_unhandled_exception(trapnr, signr, str, __stringify(name), error_code, regs, current); \ } -static DEFINE_SPINLOCK(die_lock); - -void die(const char * str, struct pt_regs * regs, long err) -{ - console_verbose(); - spin_lock_irq(&die_lock); - printk("%s: %lx\n", str, (err & 0xffffff)); - show_regs(regs); - spin_unlock_irq(&die_lock); - do_exit(SIGSEGV); -} - -static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) -{ - if (!user_mode(regs)) - die(str, regs, err); -} - -static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) -{ - if (!user_mode(regs)) { - const struct exception_table_entry *fixup; - fixup = search_exception_tables(regs->pc); - if (fixup) { - regs->pc = fixup->fixup; - return; - } - die(str, regs, err); - } -} - DO_ERROR(13, SIGILL, "illegal slot instruction", illegal_slot_inst, current) DO_ERROR(87, SIGSEGV, "address error (exec)", address_error_exec, current) -- cgit v1.2.3 From 0375a73c6f1be69d5a9b439a7e95b92e54b3c09b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 14 Jun 2012 14:46:36 +0900 Subject: sh64: Attempt to make reserved insn trap handler resemble C. This has been long overdue. No functional changes. Signed-off-by: Paul Mundt --- arch/sh/kernel/traps_64.c | 386 +++++++++++++++++++++++----------------------- 1 file changed, 195 insertions(+), 191 deletions(-) (limited to 'arch') diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c index 75bef61892d2..f87d20da1791 100644 --- a/arch/sh/kernel/traps_64.c +++ b/arch/sh/kernel/traps_64.c @@ -32,195 +32,6 @@ #include #include -static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name, - unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk); - -#define DO_ERROR(trapnr, signr, str, name, tsk) \ -asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \ -{ \ - do_unhandled_exception(trapnr, signr, str, __stringify(name), error_code, regs, current); \ -} - -DO_ERROR(13, SIGILL, "illegal slot instruction", illegal_slot_inst, current) -DO_ERROR(87, SIGSEGV, "address error (exec)", address_error_exec, current) - - -/* Implement misaligned load/store handling for kernel (and optionally for user - mode too). Limitation : only SHmedia mode code is handled - there is no - handling at all for misaligned accesses occurring in SHcompact code yet. */ - -static int misaligned_fixup(struct pt_regs *regs); - -asmlinkage void do_address_error_load(unsigned long error_code, struct pt_regs *regs) -{ - if (misaligned_fixup(regs) < 0) { - do_unhandled_exception(7, SIGSEGV, "address error(load)", - "do_address_error_load", - error_code, regs, current); - } - return; -} - -asmlinkage void do_address_error_store(unsigned long error_code, struct pt_regs *regs) -{ - if (misaligned_fixup(regs) < 0) { - do_unhandled_exception(8, SIGSEGV, "address error(store)", - "do_address_error_store", - error_code, regs, current); - } - return; -} - -#if defined(CONFIG_SH64_ID2815_WORKAROUND) - -#define OPCODE_INVALID 0 -#define OPCODE_USER_VALID 1 -#define OPCODE_PRIV_VALID 2 - -/* getcon/putcon - requires checking which control register is referenced. */ -#define OPCODE_CTRL_REG 3 - -/* Table of valid opcodes for SHmedia mode. - Form a 10-bit value by concatenating the major/minor opcodes i.e. - opcode[31:26,20:16]. The 6 MSBs of this value index into the following - array. The 4 LSBs select the bit-pair in the entry (bits 1:0 correspond to - LSBs==4'b0000 etc). */ -static unsigned long shmedia_opcode_table[64] = { - 0x55554044,0x54445055,0x15141514,0x14541414,0x00000000,0x10001000,0x01110055,0x04050015, - 0x00000444,0xc0000000,0x44545515,0x40405555,0x55550015,0x10005555,0x55555505,0x04050000, - 0x00000555,0x00000404,0x00040445,0x15151414,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000055,0x40404444,0x00000404,0xc0009495,0x00000000,0x00000000,0x00000000,0x00000000, - 0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, - 0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, - 0x80005050,0x04005055,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, - 0x81055554,0x00000404,0x55555555,0x55555555,0x00000000,0x00000000,0x00000000,0x00000000 -}; - -void do_reserved_inst(unsigned long error_code, struct pt_regs *regs) -{ - /* Workaround SH5-101 cut2 silicon defect #2815 : - in some situations, inter-mode branches from SHcompact -> SHmedia - which should take ITLBMISS or EXECPROT exceptions at the target - falsely take RESINST at the target instead. */ - - unsigned long opcode = 0x6ff4fff0; /* guaranteed reserved opcode */ - unsigned long pc, aligned_pc; - int get_user_error; - int trapnr = 12; - int signr = SIGILL; - char *exception_name = "reserved_instruction"; - - pc = regs->pc; - if ((pc & 3) == 1) { - /* SHmedia : check for defect. This requires executable vmas - to be readable too. */ - aligned_pc = pc & ~3; - if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) { - get_user_error = -EFAULT; - } else { - get_user_error = __get_user(opcode, (unsigned long *)aligned_pc); - } - if (get_user_error >= 0) { - unsigned long index, shift; - unsigned long major, minor, combined; - unsigned long reserved_field; - reserved_field = opcode & 0xf; /* These bits are currently reserved as zero in all valid opcodes */ - major = (opcode >> 26) & 0x3f; - minor = (opcode >> 16) & 0xf; - combined = (major << 4) | minor; - index = major; - shift = minor << 1; - if (reserved_field == 0) { - int opcode_state = (shmedia_opcode_table[index] >> shift) & 0x3; - switch (opcode_state) { - case OPCODE_INVALID: - /* Trap. */ - break; - case OPCODE_USER_VALID: - /* Restart the instruction : the branch to the instruction will now be from an RTE - not from SHcompact so the silicon defect won't be triggered. */ - return; - case OPCODE_PRIV_VALID: - if (!user_mode(regs)) { - /* Should only ever get here if a module has - SHcompact code inside it. If so, the same fix up is needed. */ - return; /* same reason */ - } - /* Otherwise, user mode trying to execute a privileged instruction - - fall through to trap. */ - break; - case OPCODE_CTRL_REG: - /* If in privileged mode, return as above. */ - if (!user_mode(regs)) return; - /* In user mode ... */ - if (combined == 0x9f) { /* GETCON */ - unsigned long regno = (opcode >> 20) & 0x3f; - if (regno >= 62) { - return; - } - /* Otherwise, reserved or privileged control register, => trap */ - } else if (combined == 0x1bf) { /* PUTCON */ - unsigned long regno = (opcode >> 4) & 0x3f; - if (regno >= 62) { - return; - } - /* Otherwise, reserved or privileged control register, => trap */ - } else { - /* Trap */ - } - break; - default: - /* Fall through to trap. */ - break; - } - } - /* fall through to normal resinst processing */ - } else { - /* Error trying to read opcode. This typically means a - real fault, not a RESINST any more. So change the - codes. */ - trapnr = 87; - exception_name = "address error (exec)"; - signr = SIGSEGV; - } - } - - do_unhandled_exception(trapnr, signr, exception_name, "do_reserved_inst", error_code, regs, current); -} - -#else /* CONFIG_SH64_ID2815_WORKAROUND */ - -/* If the workaround isn't needed, this is just a straightforward reserved - instruction */ -DO_ERROR(12, SIGILL, "reserved instruction", reserved_inst, current) - -#endif /* CONFIG_SH64_ID2815_WORKAROUND */ - -/* Called with interrupts disabled */ -asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs) -{ - die_if_kernel("exception", regs, ex); -} - -int do_unknown_trapa(unsigned long scId, struct pt_regs *regs) -{ - /* Syscall debug */ - printk("System call ID error: [0x1#args:8 #syscall:16 0x%lx]\n", scId); - - die_if_kernel("unknown trapa", regs, scId); - - return -ENOSYS; -} - -static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name, - unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk) -{ - if (user_mode(regs)) - force_sig(signr, tsk); - - die_if_no_fixup(str, regs, error_code); -} - static int read_opcode(reg_size_t pc, insn_size_t *result_opcode, int from_user_mode) { int get_user_error; @@ -784,7 +595,201 @@ static int misaligned_fixup(struct pt_regs *regs) regs->pc += 4; /* Skip the instruction that's just been emulated */ return 0; } +} + +static void do_unhandled_exception(int signr, char *str, unsigned long error, + struct pt_regs *regs) +{ + if (user_mode(regs)) + force_sig(signr, current); + + die_if_no_fixup(str, regs, error); +} + +#define DO_ERROR(signr, str, name) \ +asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \ +{ \ + do_unhandled_exception(signr, str, error_code, regs); \ +} + +DO_ERROR(SIGILL, "illegal slot instruction", illegal_slot_inst) +DO_ERROR(SIGSEGV, "address error (exec)", address_error_exec) + +#if defined(CONFIG_SH64_ID2815_WORKAROUND) + +#define OPCODE_INVALID 0 +#define OPCODE_USER_VALID 1 +#define OPCODE_PRIV_VALID 2 + +/* getcon/putcon - requires checking which control register is referenced. */ +#define OPCODE_CTRL_REG 3 + +/* Table of valid opcodes for SHmedia mode. + Form a 10-bit value by concatenating the major/minor opcodes i.e. + opcode[31:26,20:16]. The 6 MSBs of this value index into the following + array. The 4 LSBs select the bit-pair in the entry (bits 1:0 correspond to + LSBs==4'b0000 etc). */ +static unsigned long shmedia_opcode_table[64] = { + 0x55554044,0x54445055,0x15141514,0x14541414,0x00000000,0x10001000,0x01110055,0x04050015, + 0x00000444,0xc0000000,0x44545515,0x40405555,0x55550015,0x10005555,0x55555505,0x04050000, + 0x00000555,0x00000404,0x00040445,0x15151414,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000055,0x40404444,0x00000404,0xc0009495,0x00000000,0x00000000,0x00000000,0x00000000, + 0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, + 0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, + 0x80005050,0x04005055,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, + 0x81055554,0x00000404,0x55555555,0x55555555,0x00000000,0x00000000,0x00000000,0x00000000 +}; + +/* Workaround SH5-101 cut2 silicon defect #2815 : + in some situations, inter-mode branches from SHcompact -> SHmedia + which should take ITLBMISS or EXECPROT exceptions at the target + falsely take RESINST at the target instead. */ +void do_reserved_inst(unsigned long error_code, struct pt_regs *regs) +{ + insn_size_t opcode = 0x6ff4fff0; /* guaranteed reserved opcode */ + unsigned long pc, aligned_pc; + unsigned long index, shift; + unsigned long major, minor, combined; + unsigned long reserved_field; + int opcode_state; + int get_user_error; + int signr = SIGILL; + char *exception_name = "reserved_instruction"; + + pc = regs->pc; + + /* SHcompact is not handled */ + if (unlikely((pc & 3) == 0)) + goto out; + + /* SHmedia : check for defect. This requires executable vmas + to be readable too. */ + aligned_pc = pc & ~3; + if (!access_ok(VERIFY_READ, aligned_pc, sizeof(insn_size_t))) + get_user_error = -EFAULT; + else + get_user_error = __get_user(opcode, (insn_size_t *)aligned_pc); + + if (get_user_error < 0) { + /* + * Error trying to read opcode. This typically means a + * real fault, not a RESINST any more. So change the + * codes. + */ + exception_name = "address error (exec)"; + signr = SIGSEGV; + goto out; + } + + /* These bits are currently reserved as zero in all valid opcodes */ + reserved_field = opcode & 0xf; + if (unlikely(reserved_field)) + goto out; /* invalid opcode */ + + major = (opcode >> 26) & 0x3f; + minor = (opcode >> 16) & 0xf; + combined = (major << 4) | minor; + index = major; + shift = minor << 1; + opcode_state = (shmedia_opcode_table[index] >> shift) & 0x3; + switch (opcode_state) { + case OPCODE_INVALID: + /* Trap. */ + break; + case OPCODE_USER_VALID: + /* + * Restart the instruction: the branch to the instruction + * will now be from an RTE not from SHcompact so the + * silicon defect won't be triggered. + */ + return; + case OPCODE_PRIV_VALID: + if (!user_mode(regs)) { + /* + * Should only ever get here if a module has + * SHcompact code inside it. If so, the same fix + * up is needed. + */ + return; /* same reason */ + } + + /* + * Otherwise, user mode trying to execute a privileged + * instruction - fall through to trap. + */ + break; + case OPCODE_CTRL_REG: + /* If in privileged mode, return as above. */ + if (!user_mode(regs)) + return; + + /* In user mode ... */ + if (combined == 0x9f) { /* GETCON */ + unsigned long regno = (opcode >> 20) & 0x3f; + + if (regno >= 62) + return; + + /* reserved/privileged control register => trap */ + } else if (combined == 0x1bf) { /* PUTCON */ + unsigned long regno = (opcode >> 4) & 0x3f; + + if (regno >= 62) + return; + + /* reserved/privileged control register => trap */ + } + + break; + default: + /* Fall through to trap. */ + break; + } +out: + do_unhandled_exception(signr, exception_name, error_code, regs); +} + +#else /* CONFIG_SH64_ID2815_WORKAROUND */ + +/* If the workaround isn't needed, this is just a straightforward reserved + instruction */ +DO_ERROR(SIGILL, "reserved instruction", reserved_inst) + +#endif /* CONFIG_SH64_ID2815_WORKAROUND */ + +/* Called with interrupts disabled */ +asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs) +{ + die_if_kernel("exception", regs, ex); +} + +asmlinkage int do_unknown_trapa(unsigned long scId, struct pt_regs *regs) +{ + /* Syscall debug */ + printk("System call ID error: [0x1#args:8 #syscall:16 0x%lx]\n", scId); + + die_if_kernel("unknown trapa", regs, scId); + + return -ENOSYS; +} + +/* Implement misaligned load/store handling for kernel (and optionally for user + mode too). Limitation : only SHmedia mode code is handled - there is no + handling at all for misaligned accesses occurring in SHcompact code yet. */ + +asmlinkage void do_address_error_load(unsigned long error_code, struct pt_regs *regs) +{ + if (misaligned_fixup(regs) < 0) + do_unhandled_exception(SIGSEGV, "address error(load)", + error_code, regs); +} + +asmlinkage void do_address_error_store(unsigned long error_code, struct pt_regs *regs) +{ + if (misaligned_fixup(regs) < 0) + do_unhandled_exception(SIGSEGV, "address error(store)", + error_code, regs); } asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs) @@ -797,10 +802,9 @@ asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs) of access we make to them - just go direct to their physical addresses. */ exp_cause = peek_real_address_q(DM_EXP_CAUSE_PHY); - if (exp_cause & ~4) { + if (exp_cause & ~4) printk("DM.EXP_CAUSE had unexpected bits set (=%08lx)\n", (unsigned long)(exp_cause & 0xffffffff)); - } show_state(); /* Clear all DEBUGINT causes */ poke_real_address_q(DM_EXP_CAUSE_PHY, 0x0); -- cgit v1.2.3 From 0412ddc82223ea2bb3a9db21355e5fe0862a97e5 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 14 Jun 2012 15:05:53 +0900 Subject: sh64: Fix up section mismatch warnings. WARNING: vmlinux.o(.cpuinit.text+0x280): Section mismatch in reference from the function cpu_probe() to the function .init.text:sh64_tlb_init() The function __cpuinit cpu_probe() references a function __init sh64_tlb_init(). If sh64_tlb_init is only used by cpu_probe then annotate sh64_tlb_init with a matching annotation. sh64_tlb_init() simply needs to be __cpuinit annotated, so fix that up. Signed-off-by: Paul Mundt --- arch/sh/mm/tlb-sh5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sh/mm/tlb-sh5.c b/arch/sh/mm/tlb-sh5.c index 3aea25dc431a..ff1c40a31cbc 100644 --- a/arch/sh/mm/tlb-sh5.c +++ b/arch/sh/mm/tlb-sh5.c @@ -17,7 +17,7 @@ /** * sh64_tlb_init - Perform initial setup for the DTLB and ITLB. */ -int __init sh64_tlb_init(void) +int __cpuinit sh64_tlb_init(void) { /* Assign some sane DTLB defaults */ cpu_data->dtlb.entries = 64; -- cgit v1.2.3 From fbe765680d1fe9d08187ea4dad5041a7955a2c3a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 5 Jun 2012 09:59:52 +0200 Subject: s390/smp: make absolute lowcore / cpu restart parameter accesses more robust Setting the cpu restart parameters is done in three different fashions: - directly setting the four parameters individually - copying the four parameters with memcpy (using 4 * sizeof(long)) - copying the four parameters using a private structure In addition code in entry*.S relies on a certain order of the restart members of struct _lowcore. Make all of this more robust to future changes by adding a mem_absolute_assign(dest, val) define, which assigns val to dest using absolute addressing mode. Also the load multiple instructions in entry*.S have been split into separate load instruction so the order of the struct _lowcore members doesn't matter anymore. In addition move the prototypes of memcpy_real/absolute from uaccess.h to processor.h. These memcpy* variants are not related to uaccess at all. string.h doesn't seem to match as well, so lets use processor.h. Also replace the eight byte array in struct _lowcore which represents a misaliged u64 with a u64. The compiler will always create code that handles the misaligned u64 correctly. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/lowcore.h | 7 +------ arch/s390/include/asm/processor.h | 10 ++++++++++ arch/s390/include/asm/uaccess.h | 2 -- arch/s390/kernel/asm-offsets.c | 2 ++ arch/s390/kernel/entry.S | 4 +++- arch/s390/kernel/entry64.S | 4 +++- arch/s390/kernel/ipl.c | 15 ++++++--------- arch/s390/kernel/os_info.c | 2 +- arch/s390/kernel/setup.c | 13 ++++++------- arch/s390/kernel/smp.c | 16 +++++++--------- 10 files changed, 39 insertions(+), 36 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 47853debb3b9..a47c6e221a95 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -302,12 +302,7 @@ struct _lowcore { */ __u64 ipib; /* 0x0e00 */ __u32 ipib_checksum; /* 0x0e08 */ - /* - * Because the vmcore_info pointer is not 8 byte aligned it never - * should not be accessed directly. For accessing the pointer, first - * copy it to a local pointer variable. - */ - __u8 vmcore_info[8]; /* 0x0e0c */ + __u64 vmcore_info; /* 0x0e0c */ __u8 pad_0x0e14[0x0e18-0x0e14]; /* 0x0e14 */ __u64 os_info; /* 0x0e18 */ __u8 pad_0x0e20[0x0f00-0x0e20]; /* 0x0e20 */ diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 20d0585cf905..f1700c5c8884 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -348,4 +348,14 @@ extern void (*s390_base_ext_handler_fn)(void); ".previous\n" #endif +extern int memcpy_real(void *, void *, size_t); +extern void memcpy_absolute(void *, void *, size_t); + +#define mem_assign_absolute(dest, val) { \ + __typeof__(dest) __tmp = (val); \ + \ + BUILD_BUG_ON(sizeof(__tmp) != sizeof(val)); \ + memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \ +} + #endif /* __ASM_S390_PROCESSOR_H */ diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 1f3a79bcd262..7e7285179aad 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -381,8 +381,6 @@ clear_user(void __user *to, unsigned long n) return n; } -extern int memcpy_real(void *, void *, size_t); -extern void memcpy_absolute(void *, void *, size_t); extern int copy_to_user_real(void __user *dest, void *src, size_t count); extern int copy_from_user_real(void *dest, void __user *src, size_t count); diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 83e6edf5cf17..0e974ddd156b 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -131,6 +131,8 @@ int main(void) DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack)); DEFINE(__LC_RESTART_STACK, offsetof(struct _lowcore, restart_stack)); DEFINE(__LC_RESTART_FN, offsetof(struct _lowcore, restart_fn)); + DEFINE(__LC_RESTART_DATA, offsetof(struct _lowcore, restart_data)); + DEFINE(__LC_RESTART_SOURCE, offsetof(struct _lowcore, restart_source)); DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce)); DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 3787f9e6907a..4ea53cd7c8c3 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -724,7 +724,9 @@ ENTRY(restart_int_handler) mvc __PT_PSW(8,%r15),__LC_RST_OLD_PSW # store restart old psw ahi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15) - lm %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu + l %r1,__LC_RESTART_FN # load fn, parm & source cpu + l %r2,__LC_RESTART_DATA + l %r3,__LC_RESTART_SOURCE ltr %r3,%r3 # test source cpu address jm 1f # negative -> skip source stop 0: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index d5f02e480e51..2813e831ba32 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -751,7 +751,9 @@ ENTRY(restart_int_handler) mvc __PT_PSW(16,%r15),__LC_RST_OLD_PSW # store restart old psw aghi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15) - lmg %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu + lg %r1,__LC_RESTART_FN # load fn, parm & source cpu + lg %r2,__LC_RESTART_DATA + lg %r3,__LC_RESTART_SOURCE ltgr %r3,%r3 # test source cpu address jm 1f # negative -> skip source stop 0: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 2f6cfd460cb6..25241cd8ddd8 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -1528,15 +1528,12 @@ static struct shutdown_action __refdata dump_action = { static void dump_reipl_run(struct shutdown_trigger *trigger) { - struct { - void *addr; - __u32 csum; - } __packed ipib; - - ipib.csum = csum_partial(reipl_block_actual, - reipl_block_actual->hdr.len, 0); - ipib.addr = reipl_block_actual; - memcpy_absolute(&S390_lowcore.ipib, &ipib, sizeof(ipib)); + unsigned long ipib = (unsigned long) &reipl_block_actual; + unsigned int csum; + + csum = csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0); + mem_assign_absolute(S390_lowcore.ipib, ipib); + mem_assign_absolute(S390_lowcore.ipib_checksum, csum); dump_run(trigger); } diff --git a/arch/s390/kernel/os_info.c b/arch/s390/kernel/os_info.c index 95fa5ac6c4ce..46480d81df00 100644 --- a/arch/s390/kernel/os_info.c +++ b/arch/s390/kernel/os_info.c @@ -60,7 +60,7 @@ void __init os_info_init(void) os_info.version_minor = OS_INFO_VERSION_MINOR; os_info.magic = OS_INFO_MAGIC; os_info.csum = os_info_csum(&os_info); - memcpy_absolute(&S390_lowcore.os_info, &ptr, sizeof(ptr)); + mem_assign_absolute(S390_lowcore.os_info, (unsigned long) ptr); } #ifdef CONFIG_CRASH_DUMP diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 489d1d8d96b0..49158cb19274 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -430,10 +430,11 @@ static void __init setup_lowcore(void) lc->restart_source = -1UL; /* Setup absolute zero lowcore */ - memcpy_absolute(&S390_lowcore.restart_stack, &lc->restart_stack, - 4 * sizeof(unsigned long)); - memcpy_absolute(&S390_lowcore.restart_psw, &lc->restart_psw, - sizeof(lc->restart_psw)); + mem_assign_absolute(S390_lowcore.restart_stack, lc->restart_stack); + mem_assign_absolute(S390_lowcore.restart_fn, lc->restart_fn); + mem_assign_absolute(S390_lowcore.restart_data, lc->restart_data); + mem_assign_absolute(S390_lowcore.restart_source, lc->restart_source); + mem_assign_absolute(S390_lowcore.restart_psw, lc->restart_psw); set_prefix((u32)(unsigned long) lc); lowcore_ptr[0] = lc; @@ -598,9 +599,7 @@ static void __init setup_memory_end(void) static void __init setup_vmcoreinfo(void) { #ifdef CONFIG_KEXEC - unsigned long ptr = paddr_vmcoreinfo_note(); - - memcpy_absolute(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr)); + mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note()); #endif } diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index e01408429ad6..dc602a61233f 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -273,26 +273,24 @@ static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *), void *data, unsigned long stack) { struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices]; - struct { - unsigned long stack; - void *func; - void *data; - unsigned long source; - } restart = { stack, func, data, stap() }; + unsigned long source_cpu = stap(); __load_psw_mask(psw_kernel_bits); - if (pcpu->address == restart.source) + if (pcpu->address == source_cpu) func(data); /* should not return */ /* Stop target cpu (if func returns this stops the current cpu). */ pcpu_sigp_retry(pcpu, SIGP_STOP, 0); /* Restart func on the target cpu and stop the current cpu. */ - memcpy_absolute(&lc->restart_stack, &restart, sizeof(restart)); + mem_assign_absolute(lc->restart_stack, stack); + mem_assign_absolute(lc->restart_fn, (unsigned long) func); + mem_assign_absolute(lc->restart_data, (unsigned long) data); + mem_assign_absolute(lc->restart_source, source_cpu); asm volatile( "0: sigp 0,%0,%2 # sigp restart to target cpu\n" " brc 2,0b # busy, try again\n" "1: sigp 0,%1,%3 # sigp stop to current cpu\n" " brc 2,1b # busy, try again\n" - : : "d" (pcpu->address), "d" (restart.source), + : : "d" (pcpu->address), "d" (source_cpu), "K" (SIGP_RESTART), "K" (SIGP_STOP) : "0", "1", "cc"); for (;;) ; -- cgit v1.2.3 From b8fd7331208e52a0a932209584bde80fd4ec09b9 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:49 -0500 Subject: ARM: OMAP: Remove unnecessary clk structure In the plat/dmtimer.h there is a structure named "clk" declared. This structure is not used and appears to be left over from previous code. Hence, remove this unused structure. Verified that both omap1 and omap2plus kernel configurations build with this change. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/dmtimer.h | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 5da73562e486..5fdfaa481259 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -71,7 +71,6 @@ struct omap_timer_capability_dev_attr { }; struct omap_dm_timer; -struct clk; struct timer_regs { u32 tidr; -- cgit v1.2.3 From 26fe4e454bfee3248bc7f7bab38b4888db33528e Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:50 -0500 Subject: ARM: OMAP2+: Remove unused max number of timers definition The OMAP2+ timer code has a definition for the maximum number of timers that OMAP2+ devices have. This defintion is not used anywhere in the code and appears to be left over. Furthermore the definition is not accurate for OMAP4 devices that only have 11 timers available because the 12th timer is reserved as a secure timer and for OMAP3 devices the 12th timer is not available on secure devices. Therefore, remove this definition. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/timer.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 840929bd9dae..c030dfeee76a 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -69,9 +69,6 @@ #define OMAP3_SECURE_TIMER 1 #endif -/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */ -#define MAX_GPTIMER_ID 12 - static u32 sys_timer_reserved; /* Clockevent code */ -- cgit v1.2.3 From b7b4ff764f7bf903e47eebdab661b1c38e791c6d Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:51 -0500 Subject: ARM: OMAP2+: Add dmtimer platform function to reserve systimers During early boot, one or two dmtimers are reserved by the kernel as system timers (for clocksource and clockevents). These timers are marked as reserved and the dmtimer driver is notified which timers have been reserved via the platform data information. For OMAP2+ devices the timers reserved may vary depending on device and compile flags. Therefore, it is not easy to assume which timers we be reserved for the system timers. In order to migrate the dmtimer driver to support device-tree we need a way to pass the timers reserved for system timers to the dmtimer driver. Using the platform data structure will not work in the same way as it is currently used because the platform data structure will be stored statically in the dmtimer itself and the platform data will be selected via the device-tree match device function (of_match_device). There are a couple ways to workaround this. One option is to store the system timers reserved for the kernel in the device-tree and query them on boot. The downside of this approach is that it adds some delay to parse the DT blob to search for the system timers. Secondly, for OMAP3 devices we have a dependency on compile time flags and the device-tree would not be aware of that kernel compile flags and so we would need to address that. The second option is to add a function to the dmtimer code to reserved the system timers during boot and so the dmtimer knows exactly which timers are being used for system timers. This also allows us to remove the "reserved" member from the timer platform data. This seemed like the simpler approach and so was implemented here. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/timer.c | 9 ++------- arch/arm/plat-omap/dmtimer.c | 18 +++++++++++++++++- arch/arm/plat-omap/include/plat/dmtimer.h | 3 +-- 3 files changed, 20 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index c030dfeee76a..b0b208077c96 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -69,8 +69,6 @@ #define OMAP3_SECURE_TIMER 1 #endif -static u32 sys_timer_reserved; - /* Clockevent code */ static struct omap_dm_timer clkev; @@ -177,7 +175,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, omap_hwmod_enable(oh); - sys_timer_reserved |= (1 << (gptimer_id - 1)); + if (omap_dm_timer_reserve_systimer(gptimer_id)) + return -ENODEV; if (gptimer_id != 12) { struct clk *src; @@ -501,10 +500,6 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused) pdata->set_timer_src = omap2_dm_timer_set_src; pdata->timer_ip_version = oh->class->rev; - /* Mark clocksource and clockevent timers as reserved */ - if ((sys_timer_reserved >> (id - 1)) & 0x1) - pdata->reserved = 1; - pwrdm = omap_hwmod_get_pwrdm(oh); pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm); #ifdef CONFIG_PM diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 3b0cfeb33d05..f5b5c89ac7c2 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -45,6 +45,7 @@ #include +static u32 omap_reserved_systimers; static LIST_HEAD(omap_timer_list); static DEFINE_SPINLOCK(dm_timer_lock); @@ -152,6 +153,21 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer) return ret; } +static inline u32 omap_dm_timer_reserved_systimer(int id) +{ + return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0; +} + +int omap_dm_timer_reserve_systimer(int id) +{ + if (omap_dm_timer_reserved_systimer(id)) + return -ENODEV; + + omap_reserved_systimers |= (1 << (id - 1)); + + return 0; +} + struct omap_dm_timer *omap_dm_timer_request(void) { struct omap_dm_timer *timer = NULL, *t; @@ -674,7 +690,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) timer->id = pdev->id; timer->irq = irq->start; - timer->reserved = pdata->reserved; + timer->reserved = omap_dm_timer_reserved_systimer(timer->id); timer->pdev = pdev; timer->loses_context = pdata->loses_context; timer->get_context_loss_count = pdata->get_context_loss_count; diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 5fdfaa481259..1e5ce5d56240 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -98,13 +98,12 @@ struct dmtimer_platform_data { int (*set_timer_src)(struct platform_device *pdev, int source); int timer_ip_version; u32 needs_manual_reset:1; - bool reserved; - bool loses_context; int (*get_context_loss_count)(struct device *dev); }; +int omap_dm_timer_reserve_systimer(int id); struct omap_dm_timer *omap_dm_timer_request(void); struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id); int omap_dm_timer_free(struct omap_dm_timer *timer); -- cgit v1.2.3 From d1c1691be5290bf7e5b11b63b6fda0d63a9f4937 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:52 -0500 Subject: ARM: OMAP: Add DMTIMER capability variable to represent timer features Although the OMAP timers share a common hardware design, there are some differences between the timer instances in a given device. For example, a timer maybe in a power domain that can be powered-of, so can lose its logic state and need restoring where as another may be in power domain that is always be on. Another example, is a timer may support different clock sources to drive the timer. This information is passed to the dmtimer via the following platform data structure. struct dmtimer_platform_data { int (*set_timer_src)(struct platform_device *pdev, int source); int timer_ip_version; u32 needs_manual_reset:1; bool loses_context; int (*get_context_loss_count)(struct device *dev); }; The above structure uses multiple variables to represent the timer features. HWMOD also stores the timer capabilities using a bit-mask that represents the features supported. By using the same format for representing the timer features in the platform data as used by HWMOD, we can ... 1. Use the flags defined in the plat/dmtimer.h to represent the features supported. 2. For devices using HWMOD, we can retrieve the features supported from HWMOD. 3. Eventually, simplify the platform data structure to be ... struct dmtimer_platform_data { int (*set_timer_src)(struct platform_device *pdev, int source); u32 timer_capability; } Another benefit from doing this, is that it will simplify the migration of the dmtimer driver to device-tree. For example, in the current OMAP2+ timer code the "loses_context" variable is configured at runtime by calling an architecture specific function. For device tree this creates a problem, because we would need to call the architecture specific function from within the dmtimer driver. However, such attributes do not need to be queried at runtime and we can look up the attributes via HWMOD or device-tree. This changes a new "capability" variable to the platform data and timer structure so we can start removing and simplifying the platform data structure. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/timer.c | 3 +++ arch/arm/plat-omap/dmtimer.c | 1 + arch/arm/plat-omap/include/plat/dmtimer.h | 2 ++ 3 files changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index b0b208077c96..d8a5dc3d695f 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -500,6 +500,9 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused) pdata->set_timer_src = omap2_dm_timer_set_src; pdata->timer_ip_version = oh->class->rev; + if (timer_dev_attr) + pdata->timer_capability = timer_dev_attr->timer_capability; + pwrdm = omap_hwmod_get_pwrdm(oh); pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm); #ifdef CONFIG_PM diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index f5b5c89ac7c2..30742d8e6819 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -694,6 +694,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) timer->pdev = pdev; timer->loses_context = pdata->loses_context; timer->get_context_loss_count = pdata->get_context_loss_count; + timer->capability = pdata->timer_capability; /* Skip pm_runtime_enable for OMAP1 */ if (!pdata->needs_manual_reset) { diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 1e5ce5d56240..48e54caf9001 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -101,6 +101,7 @@ struct dmtimer_platform_data { bool loses_context; int (*get_context_loss_count)(struct device *dev); + u32 timer_capability; }; int omap_dm_timer_reserve_systimer(int id); @@ -273,6 +274,7 @@ struct omap_dm_timer { bool loses_context; int ctx_loss_count; int revision; + u32 capability; struct platform_device *pdev; struct list_head node; -- cgit v1.2.3 From 139486fa0c219914cf4a2b41df3e4c525afb1eee Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:53 -0500 Subject: ARM: OMAP2+: HWMOD: Correct timer device attributes Fix the following issues with the timer device attributes for OMAP2+ devices: 1. For OMAP24xx devices, timers 2-8 have the ALWAYS-ON attribute indicating that these timers are in an ALWAYS-ON power domain. This is not the case only timer1 is in an ALWAYS-ON power domain. 2. For OMAP3xxx devices, timers 2-7 have the ALWAYS-ON attribute indicating that these timers are in an ALWAYS-ON power domain. This is not the case only timer1 and timer12 are in an ALWAYS-ON power domain. 3. For OMAP3xxx devices, timer12 does not have the ALWAYS-ON attribute but is in an always-on power domain. Signed-off-by: Jon Hunter Acked-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c | 7 ------- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 8 +------- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 6 ------ 3 files changed, 1 insertion(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c index 83eafd96ecaa..7814e83fd03f 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c @@ -257,7 +257,6 @@ struct omap_hwmod omap2xxx_timer2_hwmod = { .idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap2xxx_timer_hwmod_class, }; @@ -276,7 +275,6 @@ struct omap_hwmod omap2xxx_timer3_hwmod = { .idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap2xxx_timer_hwmod_class, }; @@ -295,7 +293,6 @@ struct omap_hwmod omap2xxx_timer4_hwmod = { .idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap2xxx_timer_hwmod_class, }; @@ -314,7 +311,6 @@ struct omap_hwmod omap2xxx_timer5_hwmod = { .idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap2xxx_timer_hwmod_class, }; @@ -333,7 +329,6 @@ struct omap_hwmod omap2xxx_timer6_hwmod = { .idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap2xxx_timer_hwmod_class, }; @@ -352,7 +347,6 @@ struct omap_hwmod omap2xxx_timer7_hwmod = { .idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap2xxx_timer_hwmod_class, }; @@ -371,7 +365,6 @@ struct omap_hwmod omap2xxx_timer8_hwmod = { .idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap2xxx_timer_hwmod_class, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index b26d3c9bca16..7b330944b3f7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -150,7 +150,7 @@ static struct omap_hwmod_class omap3xxx_timer_hwmod_class = { /* secure timers dev attribute */ static struct omap_timer_capability_dev_attr capability_secure_dev_attr = { - .timer_capability = OMAP_TIMER_SECURE, + .timer_capability = OMAP_TIMER_ALWON | OMAP_TIMER_SECURE, }; /* always-on timers dev attribute */ @@ -195,7 +195,6 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = { .idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap3xxx_timer_1ms_hwmod_class, }; @@ -213,7 +212,6 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = { .idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap3xxx_timer_hwmod_class, }; @@ -231,7 +229,6 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = { .idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap3xxx_timer_hwmod_class, }; @@ -249,7 +246,6 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = { .idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap3xxx_timer_hwmod_class, }; @@ -267,7 +263,6 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = { .idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap3xxx_timer_hwmod_class, }; @@ -285,7 +280,6 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = { .idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT, }, }, - .dev_attr = &capability_alwon_dev_attr, .class = &omap3xxx_timer_hwmod_class, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 950454a3fa31..ebf9657460dd 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -2943,7 +2943,6 @@ static struct omap_hwmod omap44xx_timer2_hwmod = { .modulemode = MODULEMODE_SWCTRL, }, }, - .dev_attr = &capability_alwon_dev_attr, }; /* timer3 */ @@ -2965,7 +2964,6 @@ static struct omap_hwmod omap44xx_timer3_hwmod = { .modulemode = MODULEMODE_SWCTRL, }, }, - .dev_attr = &capability_alwon_dev_attr, }; /* timer4 */ @@ -2987,7 +2985,6 @@ static struct omap_hwmod omap44xx_timer4_hwmod = { .modulemode = MODULEMODE_SWCTRL, }, }, - .dev_attr = &capability_alwon_dev_attr, }; /* timer5 */ @@ -3009,7 +3006,6 @@ static struct omap_hwmod omap44xx_timer5_hwmod = { .modulemode = MODULEMODE_SWCTRL, }, }, - .dev_attr = &capability_alwon_dev_attr, }; /* timer6 */ @@ -3032,7 +3028,6 @@ static struct omap_hwmod omap44xx_timer6_hwmod = { .modulemode = MODULEMODE_SWCTRL, }, }, - .dev_attr = &capability_alwon_dev_attr, }; /* timer7 */ @@ -3054,7 +3049,6 @@ static struct omap_hwmod omap44xx_timer7_hwmod = { .modulemode = MODULEMODE_SWCTRL, }, }, - .dev_attr = &capability_alwon_dev_attr, }; /* timer8 */ -- cgit v1.2.3 From 67d2e760ae1909f3a3c444a063961e35a54b7bb0 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:54 -0500 Subject: ARM: OMAP2+: Fix external clock support for dmtimers Currently, the dmtimer determines whether an timer can support an external clock source (sys_altclk) for driving the timer by the IP version. Only OMAP24xx devices can support an external clock source, but the IP version between OMAP24xx and OMAP3xxx is common and so this incorrectly indicates that OMAP3 devices can use an external clock source. Rather than use the IP version, just let the clock framework handle this. If the "alt_ck" does not exist for a timer then the clock framework will fail to find the clock and hence will return an error. By doing this we can eliminate the "timer_ip_version" variable passed as part of the platform data and simplify the code. We can also remove the timer IP version from the HWMOD data because the dmtimer driver uses the TIDR register to determine the IP version. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c | 1 - arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 2 -- arch/arm/mach-omap2/timer.c | 12 ++---------- arch/arm/plat-omap/include/plat/dmtimer.h | 7 ------- 4 files changed, 2 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c index 7814e83fd03f..afad69c6ba6e 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c @@ -68,7 +68,6 @@ static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = { struct omap_hwmod_class omap2xxx_timer_hwmod_class = { .name = "timer", .sysc = &omap2xxx_timer_sysc, - .rev = OMAP_TIMER_IP_VERSION_1, }; /* diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 7b330944b3f7..0ea53bcc7d18 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -129,7 +129,6 @@ static struct omap_hwmod_class_sysconfig omap3xxx_timer_1ms_sysc = { static struct omap_hwmod_class omap3xxx_timer_1ms_hwmod_class = { .name = "timer", .sysc = &omap3xxx_timer_1ms_sysc, - .rev = OMAP_TIMER_IP_VERSION_1, }; static struct omap_hwmod_class_sysconfig omap3xxx_timer_sysc = { @@ -145,7 +144,6 @@ static struct omap_hwmod_class_sysconfig omap3xxx_timer_sysc = { static struct omap_hwmod_class omap3xxx_timer_hwmod_class = { .name = "timer", .sysc = &omap3xxx_timer_sysc, - .rev = OMAP_TIMER_IP_VERSION_1, }; /* secure timers dev attribute */ diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index d8a5dc3d695f..8c046d9d8ae8 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -397,7 +397,6 @@ OMAP_SYS_TIMER(4) static int omap2_dm_timer_set_src(struct platform_device *pdev, int source) { int ret; - struct dmtimer_platform_data *pdata = pdev->dev.platform_data; struct clk *fclk, *parent; char *parent_name = NULL; @@ -418,14 +417,8 @@ static int omap2_dm_timer_set_src(struct platform_device *pdev, int source) break; case OMAP_TIMER_SRC_EXT_CLK: - if (pdata->timer_ip_version == OMAP_TIMER_IP_VERSION_1) { - parent_name = "alt_ck"; - break; - } - dev_err(&pdev->dev, "%s: %d: invalid clk src.\n", - __func__, __LINE__); - clk_put(fclk); - return -EINVAL; + parent_name = "alt_ck"; + break; } parent = clk_get(&pdev->dev, parent_name); @@ -498,7 +491,6 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused) sscanf(oh->name, "timer%2d", &id); pdata->set_timer_src = omap2_dm_timer_set_src; - pdata->timer_ip_version = oh->class->rev; if (timer_dev_attr) pdata->timer_capability = timer_dev_attr->timer_capability; diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 48e54caf9001..362cf97d721c 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -55,12 +55,6 @@ #define OMAP_TIMER_TRIGGER_OVERFLOW 0x01 #define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE 0x02 -/* - * IP revision identifier so that Highlander IP - * in OMAP4 can be distinguished. - */ -#define OMAP_TIMER_IP_VERSION_1 0x1 - /* timer capabilities used in hwmod database */ #define OMAP_TIMER_SECURE 0x80000000 #define OMAP_TIMER_ALWON 0x40000000 @@ -96,7 +90,6 @@ struct timer_regs { struct dmtimer_platform_data { int (*set_timer_src)(struct platform_device *pdev, int source); - int timer_ip_version; u32 needs_manual_reset:1; bool loses_context; -- cgit v1.2.3 From 1c2d076b589225e51e022d85bb9f25dca26530f3 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:55 -0500 Subject: ARM: OMAP: Remove loses_context variable from timer platform data The platform data variable loses_context is used to determine if the timer may lose its logic state during power transitions and so needs to be restored. This information is also provided in the HWMOD device attributes for OMAP2+ devices via the OMAP_TIMER_ALWON flag. When this flag is set the timer will not lose context. So use the HWMOD device attributes to determine this. For OMAP1 devices, loses_context is never set and so set the OMAP_TIMER_ALWON flag for OMAP1 timers to ensure that code is equivalent. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/timer.c | 1 + arch/arm/mach-omap2/timer.c | 3 --- arch/arm/plat-omap/dmtimer.c | 8 ++++---- arch/arm/plat-omap/include/plat/dmtimer.h | 3 --- 4 files changed, 5 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap1/timer.c b/arch/arm/mach-omap1/timer.c index 64c65bcb2d67..b4bf48c188fb 100644 --- a/arch/arm/mach-omap1/timer.c +++ b/arch/arm/mach-omap1/timer.c @@ -141,6 +141,7 @@ static int __init omap1_dm_timer_init(void) pdata->set_timer_src = omap1_dm_timer_set_src; pdata->needs_manual_reset = 1; + pdata->timer_capability = OMAP_TIMER_ALWON; ret = platform_device_add_data(pdev, pdata, sizeof(*pdata)); if (ret) { diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 8c046d9d8ae8..9b6880a33793 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -462,7 +462,6 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused) struct dmtimer_platform_data *pdata; struct platform_device *pdev; struct omap_timer_capability_dev_attr *timer_dev_attr; - struct powerdomain *pwrdm; pr_debug("%s: %s\n", __func__, oh->name); @@ -495,8 +494,6 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused) if (timer_dev_attr) pdata->timer_capability = timer_dev_attr->timer_capability; - pwrdm = omap_hwmod_get_pwrdm(oh); - pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm); #ifdef CONFIG_PM pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count; #endif diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 30742d8e6819..7aa12785e238 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -341,7 +341,7 @@ int omap_dm_timer_start(struct omap_dm_timer *timer) omap_dm_timer_enable(timer); - if (timer->loses_context) { + if (!(timer->capability & OMAP_TIMER_ALWON)) { u32 ctx_loss_cnt_after = timer->get_context_loss_count(&timer->pdev->dev); if (ctx_loss_cnt_after != timer->ctx_loss_count) @@ -374,7 +374,8 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer) __omap_dm_timer_stop(timer, timer->posted, rate); - if (timer->loses_context && timer->get_context_loss_count) + if (!(timer->capability & OMAP_TIMER_ALWON) && + timer->get_context_loss_count) timer->ctx_loss_count = timer->get_context_loss_count(&timer->pdev->dev); @@ -447,7 +448,7 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, omap_dm_timer_enable(timer); - if (timer->loses_context) { + if (!(timer->capability & OMAP_TIMER_ALWON)) { u32 ctx_loss_cnt_after = timer->get_context_loss_count(&timer->pdev->dev); if (ctx_loss_cnt_after != timer->ctx_loss_count) @@ -692,7 +693,6 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) timer->irq = irq->start; timer->reserved = omap_dm_timer_reserved_systimer(timer->id); timer->pdev = pdev; - timer->loses_context = pdata->loses_context; timer->get_context_loss_count = pdata->get_context_loss_count; timer->capability = pdata->timer_capability; diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 362cf97d721c..0a7ed31954ea 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -91,8 +91,6 @@ struct timer_regs { struct dmtimer_platform_data { int (*set_timer_src)(struct platform_device *pdev, int source); u32 needs_manual_reset:1; - bool loses_context; - int (*get_context_loss_count)(struct device *dev); u32 timer_capability; }; @@ -264,7 +262,6 @@ struct omap_dm_timer { unsigned reserved:1; unsigned posted:1; struct timer_regs context; - bool loses_context; int ctx_loss_count; int revision; u32 capability; -- cgit v1.2.3 From 0b30ec1cb7f1b0134b16670f886baaf3521b083c Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:56 -0500 Subject: ARM: OMAP: Remove timer function pointer for context loss counter For OMAP2+ devices, a function pointer that returns the number of times a timer power domain has lost context is passed to the dmtimer driver. This function pointer is only populated for OMAP2+ devices and it is pointing to a platform function. Given that this is a platform function, we can simplify the code by removing the function pointer and referencing the function directly. We can use the OMAP_TIMER_ALWON flag to determine if we need to call this function for OMAP1 and OMAP2+ devices. The benefit of this change is the we can remove the function pointer from the platform data and simplifies the dmtimer migration to device-tree. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/timer.c | 3 --- arch/arm/plat-omap/dmtimer.c | 17 +++++++---------- arch/arm/plat-omap/include/plat/dmtimer.h | 3 --- 3 files changed, 7 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 9b6880a33793..0e17a0d9690b 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -494,9 +494,6 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused) if (timer_dev_attr) pdata->timer_capability = timer_dev_attr->timer_capability; -#ifdef CONFIG_PM - pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count; -#endif pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata), NULL, 0, 0); diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 7aa12785e238..7875eefd0474 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -42,6 +42,7 @@ #include #include +#include #include @@ -342,9 +343,8 @@ int omap_dm_timer_start(struct omap_dm_timer *timer) omap_dm_timer_enable(timer); if (!(timer->capability & OMAP_TIMER_ALWON)) { - u32 ctx_loss_cnt_after = - timer->get_context_loss_count(&timer->pdev->dev); - if (ctx_loss_cnt_after != timer->ctx_loss_count) + if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) != + timer->ctx_loss_count) omap_timer_restore_context(timer); } @@ -374,10 +374,9 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer) __omap_dm_timer_stop(timer, timer->posted, rate); - if (!(timer->capability & OMAP_TIMER_ALWON) && - timer->get_context_loss_count) + if (!(timer->capability & OMAP_TIMER_ALWON)) timer->ctx_loss_count = - timer->get_context_loss_count(&timer->pdev->dev); + omap_pm_get_dev_context_loss_count(&timer->pdev->dev); /* * Since the register values are computed and written within @@ -449,9 +448,8 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, omap_dm_timer_enable(timer); if (!(timer->capability & OMAP_TIMER_ALWON)) { - u32 ctx_loss_cnt_after = - timer->get_context_loss_count(&timer->pdev->dev); - if (ctx_loss_cnt_after != timer->ctx_loss_count) + if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) != + timer->ctx_loss_count) omap_timer_restore_context(timer); } @@ -693,7 +691,6 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) timer->irq = irq->start; timer->reserved = omap_dm_timer_reserved_systimer(timer->id); timer->pdev = pdev; - timer->get_context_loss_count = pdata->get_context_loss_count; timer->capability = pdata->timer_capability; /* Skip pm_runtime_enable for OMAP1 */ diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 0a7ed31954ea..e11c9ea7ec53 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -91,7 +91,6 @@ struct timer_regs { struct dmtimer_platform_data { int (*set_timer_src)(struct platform_device *pdev, int source); u32 needs_manual_reset:1; - int (*get_context_loss_count)(struct device *dev); u32 timer_capability; }; @@ -267,8 +266,6 @@ struct omap_dm_timer { u32 capability; struct platform_device *pdev; struct list_head node; - - int (*get_context_loss_count)(struct device *dev); }; int omap_dm_timer_prepare(struct omap_dm_timer *timer); -- cgit v1.2.3 From 6615975bc58a1234bd401a7ff231dae85631fd58 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:57 -0500 Subject: ARM: OMAP: Add flag to indicate if a timer needs a manual reset For OMAP1 devices, it is necessary to perform a manual reset of the timer. Currently, this is indicating by setting the "needs_manual_reset" variable in the platform data. Instead of using an extra variable to indicate this add a new timer capabilities flag to indicate this and remove the "needs_manual_reset" member from the platform data. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/timer.c | 4 ++-- arch/arm/plat-omap/dmtimer.c | 9 +++------ arch/arm/plat-omap/include/plat/dmtimer.h | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap1/timer.c b/arch/arm/mach-omap1/timer.c index b4bf48c188fb..aa81593db1af 100644 --- a/arch/arm/mach-omap1/timer.c +++ b/arch/arm/mach-omap1/timer.c @@ -140,8 +140,8 @@ static int __init omap1_dm_timer_init(void) } pdata->set_timer_src = omap1_dm_timer_set_src; - pdata->needs_manual_reset = 1; - pdata->timer_capability = OMAP_TIMER_ALWON; + pdata->timer_capability = OMAP_TIMER_ALWON | + OMAP_TIMER_NEEDS_RESET; ret = platform_device_add_data(pdev, pdata, sizeof(*pdata)); if (ret) { diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 7875eefd0474..e3e22b3dc5c2 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -135,7 +135,6 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) int omap_dm_timer_prepare(struct omap_dm_timer *timer) { - struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data; int ret; timer->fclk = clk_get(&timer->pdev->dev, "fck"); @@ -145,7 +144,7 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer) return -EINVAL; } - if (pdata->needs_manual_reset) + if (timer->capability & OMAP_TIMER_NEEDS_RESET) omap_dm_timer_reset(timer); ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); @@ -363,13 +362,11 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_start); int omap_dm_timer_stop(struct omap_dm_timer *timer) { unsigned long rate = 0; - struct dmtimer_platform_data *pdata; if (unlikely(!timer)) return -EINVAL; - pdata = timer->pdev->dev.platform_data; - if (!pdata->needs_manual_reset) + if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) rate = clk_get_rate(timer->fclk); __omap_dm_timer_stop(timer, timer->posted, rate); @@ -694,7 +691,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) timer->capability = pdata->timer_capability; /* Skip pm_runtime_enable for OMAP1 */ - if (!pdata->needs_manual_reset) { + if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) { pm_runtime_enable(&pdev->dev); pm_runtime_irq_safe(&pdev->dev); } diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index e11c9ea7ec53..c039e84bca7e 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -59,6 +59,7 @@ #define OMAP_TIMER_SECURE 0x80000000 #define OMAP_TIMER_ALWON 0x40000000 #define OMAP_TIMER_HAS_PWM 0x20000000 +#define OMAP_TIMER_NEEDS_RESET 0x10000000 struct omap_timer_capability_dev_attr { u32 timer_capability; @@ -90,7 +91,6 @@ struct timer_regs { struct dmtimer_platform_data { int (*set_timer_src)(struct platform_device *pdev, int source); - u32 needs_manual_reset:1; u32 timer_capability; }; -- cgit v1.2.3 From bca4580845cbffb455d77783fc7e58a94b3904e0 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:58 -0500 Subject: ARM: OMAP1: Fix dmtimer support OMAP1 dmtimer support is currently broken. When a dmtimer is requested by the omap_dm_timer_request() function fails to allocate a dmtimer because the call to clk_get() inside omap_dm_timer_prepare fails. The clk_get() fails simply because the clock data for the OMAP1 dmtimers is not present. Ideally this should be fixed by moving OMAP1 dmtimers to use the clock framework. For now simply fix this by using the "TIMER_NEEDS_RESET" flag to identify an OMAP1 device and avoid calling clk_get(). Although this is not the ideal fix and should be corrected, this flag has already been use for the same purpose in omap_dm_timer_stop(). Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index e3e22b3dc5c2..6510e5e7b7e3 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -137,11 +137,17 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer) { int ret; - timer->fclk = clk_get(&timer->pdev->dev, "fck"); - if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) { - timer->fclk = NULL; - dev_err(&timer->pdev->dev, ": No fclk handle.\n"); - return -EINVAL; + /* + * FIXME: OMAP1 devices do not use the clock framework for dmtimers so + * do not call clk_get() for these devices. + */ + if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) { + timer->fclk = clk_get(&timer->pdev->dev, "fck"); + if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) { + timer->fclk = NULL; + dev_err(&timer->pdev->dev, ": No fclk handle.\n"); + return -EINVAL; + } } if (timer->capability & OMAP_TIMER_NEEDS_RESET) -- cgit v1.2.3 From 2b2d35230099613365ad6000f4d71086130b9e71 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:59 -0500 Subject: ARM: OMAP2+: Move dmtimer clock set function to dmtimer driver OMAP1 uses an architecture specific function for setting the dmtimer clock source, where as the OMAP2+ devices use the clock framework. Eventually OMAP1 device should also use the clock framework and hence we should not any architecture specific functions. For now move the OMAP2+ function for configuring the clock source into the dmtimer driver. Therefore, we do no longer need to specify an architecture specific function for setting the clock source for OMAP2+ devices. This will simplify device tree migration of the dmtimers for OMAP2+ devices. From now on, only OMAP1 devices should specify an architecture specific function for setting the clock source via the platform data set_dmtimer_src() function pointer. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/timer.c | 55 ------------------------------- arch/arm/plat-omap/dmtimer.c | 46 +++++++++++++++++++++++++- arch/arm/plat-omap/include/plat/dmtimer.h | 1 + 3 files changed, 46 insertions(+), 56 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 0e17a0d9690b..8fe75a81e12d 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -389,59 +389,6 @@ static void __init omap4_timer_init(void) OMAP_SYS_TIMER(4) #endif -/** - * omap2_dm_timer_set_src - change the timer input clock source - * @pdev: timer platform device pointer - * @source: array index of parent clock source - */ -static int omap2_dm_timer_set_src(struct platform_device *pdev, int source) -{ - int ret; - struct clk *fclk, *parent; - char *parent_name = NULL; - - fclk = clk_get(&pdev->dev, "fck"); - if (IS_ERR_OR_NULL(fclk)) { - dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n", - __func__, __LINE__); - return -EINVAL; - } - - switch (source) { - case OMAP_TIMER_SRC_SYS_CLK: - parent_name = "sys_ck"; - break; - - case OMAP_TIMER_SRC_32_KHZ: - parent_name = "32k_ck"; - break; - - case OMAP_TIMER_SRC_EXT_CLK: - parent_name = "alt_ck"; - break; - } - - parent = clk_get(&pdev->dev, parent_name); - if (IS_ERR_OR_NULL(parent)) { - dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n", - __func__, __LINE__, parent_name); - clk_put(fclk); - return -EINVAL; - } - - ret = clk_set_parent(fclk, parent); - if (IS_ERR_VALUE(ret)) { - dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n", - __func__, parent_name); - ret = -EINVAL; - } - - clk_put(parent); - clk_put(fclk); - - return ret; -} - /** * omap_timer_init - build and register timer device with an * associated timer hwmod @@ -489,8 +436,6 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused) */ sscanf(oh->name, "timer%2d", &id); - pdata->set_timer_src = omap2_dm_timer_set_src; - if (timer_dev_attr) pdata->timer_capability = timer_dev_attr->timer_capability; diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 6510e5e7b7e3..6a7088972c55 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -397,6 +397,8 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_stop); int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) { int ret; + char *parent_name = NULL; + struct clk *fclk, *parent; struct dmtimer_platform_data *pdata; if (unlikely(!timer)) @@ -407,7 +409,49 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) if (source < 0 || source >= 3) return -EINVAL; - ret = pdata->set_timer_src(timer->pdev, source); + /* + * FIXME: Used for OMAP1 devices only because they do not currently + * use the clock framework to set the parent clock. To be removed + * once OMAP1 migrated to using clock framework for dmtimers + */ + if (pdata->set_timer_src) + return pdata->set_timer_src(timer->pdev, source); + + fclk = clk_get(&timer->pdev->dev, "fck"); + if (IS_ERR_OR_NULL(fclk)) { + pr_err("%s: fck not found\n", __func__); + return -EINVAL; + } + + switch (source) { + case OMAP_TIMER_SRC_SYS_CLK: + parent_name = "sys_ck"; + break; + + case OMAP_TIMER_SRC_32_KHZ: + parent_name = "32k_ck"; + break; + + case OMAP_TIMER_SRC_EXT_CLK: + parent_name = "alt_ck"; + break; + } + + parent = clk_get(&timer->pdev->dev, parent_name); + if (IS_ERR_OR_NULL(parent)) { + pr_err("%s: %s not found\n", __func__, parent_name); + ret = -EINVAL; + goto out; + } + + ret = clk_set_parent(fclk, parent); + if (IS_ERR_VALUE(ret)) + pr_err("%s: failed to set %s as parent\n", __func__, + parent_name); + + clk_put(parent); +out: + clk_put(fclk); return ret; } diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index c039e84bca7e..19e7fa577bd0 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -90,6 +90,7 @@ struct timer_regs { }; struct dmtimer_platform_data { + /* set_timer_src - Only used for OMAP1 devices */ int (*set_timer_src)(struct platform_device *pdev, int source); u32 timer_capability; }; -- cgit v1.2.3 From c59b537d87068be8c357a0150f6172a2dc8cdf82 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:35:00 -0500 Subject: ARM: OMAP2+: Simplify dmtimer clock aliases The OMAP dmtimer driver allows you to dynamically configure the functional clock that drives the timer logic. The dmtimer driver uses the device name and a "con-id" string to search for the appropriate functional clock. Currently, we define a clock alias for each functional clock source each timer supports. Some functional clock sources are common to all of the timers on a device and so for these clock sources we can use a single alias with a unique con-id string. The possible functional clock sources for an OMAP device are a 32kHz clock, a system (MHz range) clock and (for OMAP2 only) an external clock. By defining a unique con-id name for each of these (timer_32k_ck, timer_sys_ck and timer_ext_ck) we can eliminate a lot of the clock aliases for timers. This reduces code, speeds-up searches and clock initialisation time. Signed-off-by: Jon Hunter Acked-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clock2420_data.c | 39 +++--------------------------------- arch/arm/mach-omap2/clock2430_data.c | 39 +++--------------------------------- arch/arm/mach-omap2/clock3xxx_data.c | 26 ++---------------------- arch/arm/mach-omap2/clock44xx_data.c | 34 +++++++++++-------------------- arch/arm/plat-omap/dmtimer.c | 6 +++--- 5 files changed, 23 insertions(+), 121 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index bace9308a4db..861767ed1a3a 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -1901,42 +1901,9 @@ static struct omap_clk omap2420_clks[] = { CLK(NULL, "pka_ick", &pka_ick, CK_242X), CLK(NULL, "usb_fck", &usb_fck, CK_242X), CLK("musb-hdrc", "fck", &osc_ck, CK_242X), - CLK("omap_timer.1", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.2", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.3", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.4", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.5", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.6", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.7", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.8", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.9", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.10", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.11", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.12", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.1", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.2", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.3", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.4", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.5", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.6", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.7", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.8", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.9", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.10", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.11", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.12", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.1", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.2", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.3", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.4", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.5", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.6", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.7", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.8", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.9", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.10", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.11", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.12", "alt_ck", &alt_ck, CK_243X), + CLK(NULL, "timer_32k_ck", &func_32k_ck, CK_243X), + CLK(NULL, "timer_sys_ck", &sys_ck, CK_243X), + CLK(NULL, "timer_ext_ck", &alt_ck, CK_243X), }; /* diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 3b4d09a50399..5577810dbc26 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -2000,42 +2000,9 @@ static struct omap_clk omap2430_clks[] = { CLK(NULL, "mdm_intc_ick", &mdm_intc_ick, CK_243X), CLK("omap_hsmmc.0", "mmchsdb_fck", &mmchsdb1_fck, CK_243X), CLK("omap_hsmmc.1", "mmchsdb_fck", &mmchsdb2_fck, CK_243X), - CLK("omap_timer.1", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.2", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.3", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.4", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.5", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.6", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.7", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.8", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.9", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.10", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.11", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.12", "32k_ck", &func_32k_ck, CK_243X), - CLK("omap_timer.1", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.2", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.3", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.4", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.5", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.6", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.7", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.8", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.9", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.10", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.11", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.12", "sys_ck", &sys_ck, CK_243X), - CLK("omap_timer.1", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.2", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.3", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.4", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.5", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.6", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.7", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.8", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.9", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.10", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.11", "alt_ck", &alt_ck, CK_243X), - CLK("omap_timer.12", "alt_ck", &alt_ck, CK_243X), + CLK(NULL, "timer_32k_ck", &func_32k_ck, CK_243X), + CLK(NULL, "timer_sys_ck", &sys_ck, CK_243X), + CLK(NULL, "timer_ext_ck", &alt_ck, CK_243X), }; /* diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 4e1a3b0e8cc8..64b2b1fafddd 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3482,30 +3482,8 @@ static struct omap_clk omap3xxx_clks[] = { CLK("musb-am35x", "fck", &hsotgusb_fck_am35xx, CK_AM35XX), CLK(NULL, "hecc_ck", &hecc_ck, CK_AM35XX), CLK(NULL, "uart4_ick", &uart4_ick_am35xx, CK_AM35XX), - CLK("omap_timer.1", "32k_ck", &omap_32k_fck, CK_3XXX), - CLK("omap_timer.2", "32k_ck", &omap_32k_fck, CK_3XXX), - CLK("omap_timer.3", "32k_ck", &omap_32k_fck, CK_3XXX), - CLK("omap_timer.4", "32k_ck", &omap_32k_fck, CK_3XXX), - CLK("omap_timer.5", "32k_ck", &omap_32k_fck, CK_3XXX), - CLK("omap_timer.6", "32k_ck", &omap_32k_fck, CK_3XXX), - CLK("omap_timer.7", "32k_ck", &omap_32k_fck, CK_3XXX), - CLK("omap_timer.8", "32k_ck", &omap_32k_fck, CK_3XXX), - CLK("omap_timer.9", "32k_ck", &omap_32k_fck, CK_3XXX), - CLK("omap_timer.10", "32k_ck", &omap_32k_fck, CK_3XXX), - CLK("omap_timer.11", "32k_ck", &omap_32k_fck, CK_3XXX), - CLK("omap_timer.12", "32k_ck", &omap_32k_fck, CK_3XXX), - CLK("omap_timer.1", "sys_ck", &sys_ck, CK_3XXX), - CLK("omap_timer.2", "sys_ck", &sys_ck, CK_3XXX), - CLK("omap_timer.3", "sys_ck", &sys_ck, CK_3XXX), - CLK("omap_timer.4", "sys_ck", &sys_ck, CK_3XXX), - CLK("omap_timer.5", "sys_ck", &sys_ck, CK_3XXX), - CLK("omap_timer.6", "sys_ck", &sys_ck, CK_3XXX), - CLK("omap_timer.7", "sys_ck", &sys_ck, CK_3XXX), - CLK("omap_timer.8", "sys_ck", &sys_ck, CK_3XXX), - CLK("omap_timer.9", "sys_ck", &sys_ck, CK_3XXX), - CLK("omap_timer.10", "sys_ck", &sys_ck, CK_3XXX), - CLK("omap_timer.11", "sys_ck", &sys_ck, CK_3XXX), - CLK("omap_timer.12", "sys_ck", &sys_ck, CK_3XXX), + CLK(NULL, "timer_32k_ck", &omap_32k_fck, CK_3XXX), + CLK(NULL, "timer_sys_ck", &sys_ck, CK_3XXX), }; diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 2172f6603848..51f7424c7caa 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -3380,28 +3380,18 @@ static struct omap_clk omap44xx_clks[] = { CLK("usbhs_omap", "usbhost_ick", &dummy_ck, CK_443X), CLK("usbhs_omap", "usbtll_fck", &dummy_ck, CK_443X), CLK("omap_wdt", "ick", &dummy_ck, CK_443X), - CLK("omap_timer.1", "32k_ck", &sys_32k_ck, CK_443X), - CLK("omap_timer.2", "32k_ck", &sys_32k_ck, CK_443X), - CLK("omap_timer.3", "32k_ck", &sys_32k_ck, CK_443X), - CLK("omap_timer.4", "32k_ck", &sys_32k_ck, CK_443X), - CLK("omap_timer.5", "32k_ck", &sys_32k_ck, CK_443X), - CLK("omap_timer.6", "32k_ck", &sys_32k_ck, CK_443X), - CLK("omap_timer.7", "32k_ck", &sys_32k_ck, CK_443X), - CLK("omap_timer.8", "32k_ck", &sys_32k_ck, CK_443X), - CLK("omap_timer.9", "32k_ck", &sys_32k_ck, CK_443X), - CLK("omap_timer.10", "32k_ck", &sys_32k_ck, CK_443X), - CLK("omap_timer.11", "32k_ck", &sys_32k_ck, CK_443X), - CLK("omap_timer.1", "sys_ck", &sys_clkin_ck, CK_443X), - CLK("omap_timer.2", "sys_ck", &sys_clkin_ck, CK_443X), - CLK("omap_timer.3", "sys_ck", &sys_clkin_ck, CK_443X), - CLK("omap_timer.4", "sys_ck", &sys_clkin_ck, CK_443X), - CLK("omap_timer.9", "sys_ck", &sys_clkin_ck, CK_443X), - CLK("omap_timer.10", "sys_ck", &sys_clkin_ck, CK_443X), - CLK("omap_timer.11", "sys_ck", &sys_clkin_ck, CK_443X), - CLK("omap_timer.5", "sys_ck", &syc_clk_div_ck, CK_443X), - CLK("omap_timer.6", "sys_ck", &syc_clk_div_ck, CK_443X), - CLK("omap_timer.7", "sys_ck", &syc_clk_div_ck, CK_443X), - CLK("omap_timer.8", "sys_ck", &syc_clk_div_ck, CK_443X), + CLK(NULL, "timer_32k_ck", &sys_32k_ck, CK_443X), + CLK("omap_timer.1", "timer_sys_ck", &sys_clkin_ck, CK_443X), + CLK("omap_timer.2", "timer_sys_ck", &sys_clkin_ck, CK_443X), + CLK("omap_timer.3", "timer_sys_ck", &sys_clkin_ck, CK_443X), + CLK("omap_timer.4", "timer_sys_ck", &sys_clkin_ck, CK_443X), + CLK("omap_timer.9", "timer_sys_ck", &sys_clkin_ck, CK_443X), + CLK("omap_timer.10", "timer_sys_ck", &sys_clkin_ck, CK_443X), + CLK("omap_timer.11", "timer_sys_ck", &sys_clkin_ck, CK_443X), + CLK("omap_timer.5", "timer_sys_ck", &syc_clk_div_ck, CK_443X), + CLK("omap_timer.6", "timer_sys_ck", &syc_clk_div_ck, CK_443X), + CLK("omap_timer.7", "timer_sys_ck", &syc_clk_div_ck, CK_443X), + CLK("omap_timer.8", "timer_sys_ck", &syc_clk_div_ck, CK_443X), }; int __init omap4xxx_clk_init(void) diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 6a7088972c55..54ed4e6e429e 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -425,15 +425,15 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) switch (source) { case OMAP_TIMER_SRC_SYS_CLK: - parent_name = "sys_ck"; + parent_name = "timer_sys_ck"; break; case OMAP_TIMER_SRC_32_KHZ: - parent_name = "32k_ck"; + parent_name = "timer_32k_ck"; break; case OMAP_TIMER_SRC_EXT_CLK: - parent_name = "alt_ck"; + parent_name = "timer_ext_ck"; break; } -- cgit v1.2.3 From c35f77417ebfc7c21c02aa9c8c30aa4cecf331d6 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Mon, 11 Jun 2012 12:56:45 +0300 Subject: x86: Define early read-mostly per-cpu macros Some read-mostly per-cpu data may need to be declared or defined early, so it can be initialized and accessed before per_cpu areas are allocated. Only the data that resides in the per_cpu areas should be read-mostly, as there is little benefit in optimizing cache lines on initialization. Signed-off-by: Ido Yariv [ Added the missing declarations in !SMP code. ] Signed-off-by: Vlad Zolotarov Acked-by: Shai Fultheim Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/46188571.ddB8aVQYWo@vlad Signed-off-by: Ingo Molnar --- arch/x86/include/asm/percpu.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index d9b8e3f7f42a..1104afaba52b 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -551,6 +551,12 @@ DECLARE_PER_CPU(unsigned long, this_cpu_off); { [0 ... NR_CPUS-1] = _initvalue }; \ __typeof__(_type) *_name##_early_ptr __refdata = _name##_early_map +#define DEFINE_EARLY_PER_CPU_READ_MOSTLY(_type, _name, _initvalue) \ + DEFINE_PER_CPU_READ_MOSTLY(_type, _name) = _initvalue; \ + __typeof__(_type) _name##_early_map[NR_CPUS] __initdata = \ + { [0 ... NR_CPUS-1] = _initvalue }; \ + __typeof__(_type) *_name##_early_ptr __refdata = _name##_early_map + #define EXPORT_EARLY_PER_CPU_SYMBOL(_name) \ EXPORT_PER_CPU_SYMBOL(_name) @@ -559,6 +565,11 @@ DECLARE_PER_CPU(unsigned long, this_cpu_off); extern __typeof__(_type) *_name##_early_ptr; \ extern __typeof__(_type) _name##_early_map[] +#define DECLARE_EARLY_PER_CPU_READ_MOSTLY(_type, _name) \ + DECLARE_PER_CPU_READ_MOSTLY(_type, _name); \ + extern __typeof__(_type) *_name##_early_ptr; \ + extern __typeof__(_type) _name##_early_map[] + #define early_per_cpu_ptr(_name) (_name##_early_ptr) #define early_per_cpu_map(_name, _idx) (_name##_early_map[_idx]) #define early_per_cpu(_name, _cpu) \ @@ -570,12 +581,18 @@ DECLARE_PER_CPU(unsigned long, this_cpu_off); #define DEFINE_EARLY_PER_CPU(_type, _name, _initvalue) \ DEFINE_PER_CPU(_type, _name) = _initvalue +#define DEFINE_EARLY_PER_CPU_READ_MOSTLY(_type, _name, _initvalue) \ + DEFINE_PER_CPU_READ_MOSTLY(_type, _name) = _initvalue + #define EXPORT_EARLY_PER_CPU_SYMBOL(_name) \ EXPORT_PER_CPU_SYMBOL(_name) #define DECLARE_EARLY_PER_CPU(_type, _name) \ DECLARE_PER_CPU(_type, _name) +#define DECLARE_EARLY_PER_CPU_READ_MOSTLY(_type, _name) \ + DECLARE_PER_CPU_READ_MOSTLY(_type, _name) + #define early_per_cpu(_name, _cpu) per_cpu(_name, _cpu) #define early_per_cpu_ptr(_name) NULL /* no early_per_cpu_map() */ -- cgit v1.2.3 From 0816b0f0365539c8f6280634d2c1778d0108d8f5 Mon Sep 17 00:00:00 2001 From: Vlad Zolotarov Date: Mon, 11 Jun 2012 12:56:52 +0300 Subject: x86: Add read_mostly declaration/definition to variables from smp.h Add "read-mostly" qualifier to the following variables in smp.h: - cpu_sibling_map - cpu_core_map - cpu_llc_shared_map - cpu_llc_id - cpu_number - x86_cpu_to_apicid - x86_bios_cpu_apicid - x86_cpu_to_logical_apicid As long as all the variables above are only written during the initialization, this change is meant to prevent the false sharing. More specifically, on vSMP Foundation platform x86_cpu_to_apicid shared the same internode_cache_line with frequently written lapic_events. From the analysis of the first 33 per_cpu variables out of 219 (memories they describe, to be more specific) the 8 have read_mostly nature (tlb_vector_offset, cpu_loops_per_jiffy, xen_debug_irq, etc.) and 25 are frequently written (irq_stack_union, gdt_page, exception_stacks, idt_desc, etc.). Assuming that the spread of the rest of the per_cpu variables is similar, identifying the read mostly memories will make more sense in terms of long-term code maintenance comparing to identifying frequently written memories. Signed-off-by: Vlad Zolotarov Acked-by: Shai Fultheim Cc: Shai Fultheim (Shai@ScaleMP.com) Cc: ido@wizery.com Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1719258.EYKzE4Zbq5@vlad Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apic.h | 2 +- arch/x86/include/asm/smp.h | 16 ++++++++-------- arch/x86/kernel/apic/apic.c | 6 +++--- arch/x86/kernel/setup_percpu.c | 2 +- arch/x86/kernel/smpboot.c | 8 ++++---- 5 files changed, 17 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index eaff4790ed96..a907d4d251a8 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -537,7 +537,7 @@ static inline const struct cpumask *default_target_cpus(void) #endif } -DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid); +DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_bios_cpu_apicid); static inline unsigned int read_apic_id(void) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index f48394513c37..cc1df2b5cc65 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -31,12 +31,12 @@ static inline bool cpu_has_ht_siblings(void) return has_siblings; } -DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map); -DECLARE_PER_CPU(cpumask_var_t, cpu_core_map); +DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map); +DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map); /* cpus sharing the last level cache: */ -DECLARE_PER_CPU(cpumask_var_t, cpu_llc_shared_map); -DECLARE_PER_CPU(u16, cpu_llc_id); -DECLARE_PER_CPU(int, cpu_number); +DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map); +DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id); +DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number); static inline struct cpumask *cpu_sibling_mask(int cpu) { @@ -53,10 +53,10 @@ static inline struct cpumask *cpu_llc_shared_mask(int cpu) return per_cpu(cpu_llc_shared_map, cpu); } -DECLARE_EARLY_PER_CPU(u16, x86_cpu_to_apicid); -DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid); +DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid); +DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_bios_cpu_apicid); #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32) -DECLARE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid); +DECLARE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid); #endif /* Static state in head.S used to set up a CPU */ diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 39a222e094af..0443b6482214 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -75,8 +75,8 @@ physid_mask_t phys_cpu_present_map; /* * Map cpu index to physical APIC ID */ -DEFINE_EARLY_PER_CPU(u16, x86_cpu_to_apicid, BAD_APICID); -DEFINE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid, BAD_APICID); +DEFINE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid, BAD_APICID); +DEFINE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_bios_cpu_apicid, BAD_APICID); EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid); EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); @@ -88,7 +88,7 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); * used for the mapping. This is where the behaviors of x86_64 and 32 * actually diverge. Let's keep it ugly for now. */ -DEFINE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid, BAD_APICID); +DEFINE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid, BAD_APICID); /* * Knob to control our willingness to enable the local APIC. diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 5a98aa272184..5cdff0357746 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -21,7 +21,7 @@ #include #include -DEFINE_PER_CPU(int, cpu_number); +DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number); EXPORT_PER_CPU_SYMBOL(cpu_number); #ifdef CONFIG_X86_64 diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 3fab55bea29b..e61110e29a8c 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -104,17 +104,17 @@ int smp_num_siblings = 1; EXPORT_SYMBOL(smp_num_siblings); /* Last level cache ID of each logical CPU */ -DEFINE_PER_CPU(u16, cpu_llc_id) = BAD_APICID; +DEFINE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id) = BAD_APICID; /* representing HT siblings of each logical CPU */ -DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map); +DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map); EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); /* representing HT and core siblings of each logical CPU */ -DEFINE_PER_CPU(cpumask_var_t, cpu_core_map); +DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map); EXPORT_PER_CPU_SYMBOL(cpu_core_map); -DEFINE_PER_CPU(cpumask_var_t, cpu_llc_shared_map); +DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map); /* Per CPU bogomips and other parameters */ DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info); -- cgit v1.2.3 From cac4afbc3da58d9e5701b34bd4c1f11ea13328d4 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 14 Jun 2012 12:39:34 +0200 Subject: x86/x2apic/cluster: Vector_allocation_domain() should return a value Since commit 8637e38 ("x86/apic: Avoid useless scanning thru a cpumask in assign_irq_vector()") vector_allocation_domain() operation indicates if a cpumask is dynamic or static. This update fixes the oversight and makes the operation to return a value. Signed-off-by: Alexander Gordeev Cc: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120614103933.GJ3383@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic/x2apic_cluster.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 23a46cf5b6fd..1885a73b7f33 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -228,10 +228,11 @@ static int x2apic_cluster_probe(void) /* * Each x2apic cluster is an allocation domain. */ -static void cluster_vector_allocation_domain(int cpu, struct cpumask *retmask) +static bool cluster_vector_allocation_domain(int cpu, struct cpumask *retmask) { cpumask_clear(retmask); cpumask_copy(retmask, per_cpu(cpus_in_cluster, cpu)); + return true; } static struct apic apic_x2apic_cluster = { -- cgit v1.2.3 From a5a391561bc25898ba1a702a0c4b028aa5b11ce9 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 14 Jun 2012 09:49:35 +0200 Subject: x86/apic: Eliminate cpu_mask_to_apicid() operation Since there are only two locations where cpu_mask_to_apicid() is called from, remove the operation and use only cpu_mask_to_apicid_and() instead. Signed-off-by: Alexander Gordeev Suggested-and-acked-by: Suresh Siddha Acked-by: Yinghai Lu Link: http://lkml.kernel.org/r/20120614074935.GE3383@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apic.h | 33 ++++++++------------------------- arch/x86/kernel/apic/apic.c | 24 ++++++------------------ arch/x86/kernel/apic/apic_flat_64.c | 2 -- arch/x86/kernel/apic/apic_noop.c | 1 - arch/x86/kernel/apic/apic_numachip.c | 1 - arch/x86/kernel/apic/bigsmp_32.c | 1 - arch/x86/kernel/apic/es7000_32.c | 4 +--- arch/x86/kernel/apic/io_apic.c | 3 ++- arch/x86/kernel/apic/numaq_32.c | 8 -------- arch/x86/kernel/apic/probe_32.c | 1 - arch/x86/kernel/apic/summit_32.c | 3 +-- arch/x86/kernel/apic/x2apic_cluster.c | 17 ----------------- arch/x86/kernel/apic/x2apic_phys.c | 1 - arch/x86/kernel/apic/x2apic_uv_x.c | 29 ++++++----------------------- arch/x86/platform/uv/uv_irq.c | 2 +- 15 files changed, 25 insertions(+), 105 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 1ed3eead2039..eec240e12091 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -331,8 +331,6 @@ struct apic { unsigned long (*set_apic_id)(unsigned int id); unsigned long apic_id_mask; - int (*cpu_mask_to_apicid)(const struct cpumask *cpumask, - unsigned int *apicid); int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, const struct cpumask *andmask, unsigned int *apicid); @@ -594,9 +592,15 @@ static inline int default_phys_pkg_id(int cpuid_apic, int index_msb) #endif static inline int -__flat_cpu_mask_to_apicid(unsigned long cpu_mask, unsigned int *apicid) +flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask, + unsigned int *apicid) { - cpu_mask = cpu_mask & APIC_ALL_CPUS & cpumask_bits(cpu_online_mask)[0]; + unsigned long cpu_mask = cpumask_bits(cpumask)[0] & + cpumask_bits(andmask)[0] & + cpumask_bits(cpu_online_mask)[0] & + APIC_ALL_CPUS; + if (likely(cpu_mask)) { *apicid = (unsigned int)cpu_mask; return 0; @@ -605,27 +609,6 @@ __flat_cpu_mask_to_apicid(unsigned long cpu_mask, unsigned int *apicid) } } -static inline int -flat_cpu_mask_to_apicid(const struct cpumask *cpumask, - unsigned int *apicid) -{ - return __flat_cpu_mask_to_apicid(cpumask_bits(cpumask)[0], apicid); -} - -static inline int -flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask, - unsigned int *apicid) -{ - unsigned long mask1 = cpumask_bits(cpumask)[0]; - unsigned long mask2 = cpumask_bits(andmask)[0]; - return __flat_cpu_mask_to_apicid(mask1 & mask2, apicid); -} - -extern int -default_cpu_mask_to_apicid(const struct cpumask *cpumask, - unsigned int *apicid); - extern int default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, const struct cpumask *andmask, diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 7e9bbe73bc5a..048a4f806d46 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -2123,23 +2123,6 @@ void default_init_apic_ldr(void) apic_write(APIC_LDR, val); } -static inline int __default_cpu_to_apicid(int cpu, unsigned int *apicid) -{ - if (likely((unsigned int)cpu < nr_cpu_ids)) { - *apicid = per_cpu(x86_cpu_to_apicid, cpu); - return 0; - } else { - return -EINVAL; - } -} - -int default_cpu_mask_to_apicid(const struct cpumask *cpumask, - unsigned int *apicid) -{ - int cpu = cpumask_first_and(cpumask, cpu_online_mask); - return __default_cpu_to_apicid(cpu, apicid); -} - int default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, const struct cpumask *andmask, unsigned int *apicid) @@ -2151,7 +2134,12 @@ int default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, break; } - return __default_cpu_to_apicid(cpu, apicid); + if (likely((unsigned int)cpu < nr_cpu_ids)) { + *apicid = per_cpu(x86_cpu_to_apicid, cpu); + return 0; + } else { + return -EINVAL; + } } /* diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index bddc92566d0a..00c77cf78e9e 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -191,7 +191,6 @@ static struct apic apic_flat = { .set_apic_id = set_apic_id, .apic_id_mask = 0xFFu << 24, - .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, .send_IPI_mask = flat_send_IPI_mask, @@ -308,7 +307,6 @@ static struct apic apic_physflat = { .set_apic_id = set_apic_id, .apic_id_mask = 0xFFu << 24, - .cpu_mask_to_apicid = default_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, .send_IPI_mask = physflat_send_IPI_mask, diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index ac9edf247b15..65c07fc630a1 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c @@ -159,7 +159,6 @@ struct apic apic_noop = { .set_apic_id = NULL, .apic_id_mask = 0x0F << 24, - .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, .send_IPI_mask = noop_send_IPI_mask, diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index c028132ad358..bc552cff2578 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -234,7 +234,6 @@ static struct apic apic_numachip __refconst = { .set_apic_id = set_apic_id, .apic_id_mask = 0xffU << 24, - .cpu_mask_to_apicid = default_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, .send_IPI_mask = numachip_send_IPI_mask, diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index df342fe4d6aa..d50e3640d5ae 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c @@ -188,7 +188,6 @@ static struct apic apic_bigsmp = { .set_apic_id = NULL, .apic_id_mask = 0xFF << 24, - .cpu_mask_to_apicid = default_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, .send_IPI_mask = bigsmp_send_IPI_mask, diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index b35cfb9b6962..2c5317ea1b83 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -525,7 +525,7 @@ static int es7000_check_phys_apicid_present(int cpu_physical_apicid) return 1; } -static int +static inline int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) { unsigned int round = 0; @@ -643,7 +643,6 @@ static struct apic __refdata apic_es7000_cluster = { .set_apic_id = NULL, .apic_id_mask = 0xFF << 24, - .cpu_mask_to_apicid = es7000_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = es7000_cpu_mask_to_apicid_and, .send_IPI_mask = es7000_send_IPI_mask, @@ -710,7 +709,6 @@ static struct apic __refdata apic_es7000 = { .set_apic_id = NULL, .apic_id_mask = 0xFF << 24, - .cpu_mask_to_apicid = es7000_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = es7000_cpu_mask_to_apicid_and, .send_IPI_mask = es7000_send_IPI_mask, diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 0deb773404e5..0540f083f452 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1492,7 +1492,8 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx, * We use logical delivery to get the timer IRQ * to the first CPU. */ - if (unlikely(apic->cpu_mask_to_apicid(apic->target_cpus(), &dest))) + if (unlikely(apic->cpu_mask_to_apicid_and(apic->target_cpus(), + apic->target_cpus(), &dest))) dest = BAD_APICID; entry.dest_mode = apic->irq_dest_mode; diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index 2b55514c328b..d661ee95cabf 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c @@ -406,13 +406,6 @@ static inline int numaq_check_phys_apicid_present(int phys_apicid) * We use physical apicids here, not logical, so just return the default * physical broadcast to stop people from breaking us */ -static int -numaq_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) -{ - *apicid = 0x0F; - return 0; -} - static int numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask, const struct cpumask *andmask, @@ -499,7 +492,6 @@ static struct apic __refdata apic_numaq = { .set_apic_id = NULL, .apic_id_mask = 0x0F << 24, - .cpu_mask_to_apicid = numaq_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = numaq_cpu_mask_to_apicid_and, .send_IPI_mask = numaq_send_IPI_mask, diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 2c6f003b2e4b..eef6bcd1bf1e 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -108,7 +108,6 @@ static struct apic apic_default = { .set_apic_id = NULL, .apic_id_mask = 0x0F << 24, - .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, .send_IPI_mask = default_send_IPI_mask_logical, diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index 79d360f6729e..bbad180f2890 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c @@ -263,7 +263,7 @@ static int summit_check_phys_apicid_present(int physical_apicid) return 1; } -static int +static inline int summit_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) { unsigned int round = 0; @@ -516,7 +516,6 @@ static struct apic apic_summit = { .set_apic_id = NULL, .apic_id_mask = 0xFF << 24, - .cpu_mask_to_apicid = summit_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = summit_cpu_mask_to_apicid_and, .send_IPI_mask = summit_send_IPI_mask, diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 1885a73b7f33..943d03fc6fc4 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -96,22 +96,6 @@ static void x2apic_send_IPI_all(int vector) __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC); } -static int -x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) -{ - int cpu = cpumask_first_and(cpumask, cpu_online_mask); - int i; - - if (cpu >= nr_cpu_ids) - return -EINVAL; - - *apicid = 0; - for_each_cpu_and(i, cpumask, per_cpu(cpus_in_cluster, cpu)) - *apicid |= per_cpu(x86_cpu_to_logical_apicid, i); - - return 0; -} - static int x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, const struct cpumask *andmask, @@ -270,7 +254,6 @@ static struct apic apic_x2apic_cluster = { .set_apic_id = x2apic_set_apic_id, .apic_id_mask = 0xFFFFFFFFu, - .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = x2apic_cpu_mask_to_apicid_and, .send_IPI_mask = x2apic_send_IPI_mask, diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index f109388a0e80..e03a1e180e81 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -123,7 +123,6 @@ static struct apic apic_x2apic_phys = { .set_apic_id = x2apic_set_apic_id, .apic_id_mask = 0xFFFFFFFFu, - .cpu_mask_to_apicid = default_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, .send_IPI_mask = x2apic_send_IPI_mask, diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 307aa076bd62..026de0114d15 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -269,27 +269,6 @@ static void uv_init_apic_ldr(void) { } -static inline int __uv_cpu_to_apicid(int cpu, unsigned int *apicid) -{ - if (likely((unsigned int)cpu < nr_cpu_ids)) { - *apicid = per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits; - return 0; - } else { - return -EINVAL; - } -} - -static int -uv_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) -{ - /* - * We're using fixed IRQ delivery, can only return one phys APIC ID. - * May as well be the first. - */ - int cpu = cpumask_first_and(cpumask, cpu_online_mask); - return __uv_cpu_to_apicid(cpu, apicid); -} - static int uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, const struct cpumask *andmask, @@ -306,7 +285,12 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, break; } - return __uv_cpu_to_apicid(cpu, apicid); + if (likely((unsigned int)cpu < nr_cpu_ids)) { + *apicid = per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits; + return 0; + } else { + return -EINVAL; + } } static unsigned int x2apic_get_apic_id(unsigned long x) @@ -384,7 +368,6 @@ static struct apic __refdata apic_x2apic_uv_x = { .set_apic_id = set_apic_id, .apic_id_mask = 0xFFFFFFFFu, - .cpu_mask_to_apicid = uv_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = uv_cpu_mask_to_apicid_and, .send_IPI_mask = uv_send_IPI_mask, diff --git a/arch/x86/platform/uv/uv_irq.c b/arch/x86/platform/uv/uv_irq.c index dd1ff39a464c..a67c7a6bac7e 100644 --- a/arch/x86/platform/uv/uv_irq.c +++ b/arch/x86/platform/uv/uv_irq.c @@ -144,7 +144,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, if (err != 0) return err; - err = apic->cpu_mask_to_apicid(eligible_cpu, &dest); + err = apic->cpu_mask_to_apicid_and(eligible_cpu, eligible_cpu, &dest); if (err != 0) return err; -- cgit v1.2.3 From ea3807ea52a53f2cdfd60c89d8491fc9a8208d1c Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 14 Jun 2012 09:49:55 +0200 Subject: x86/apic: Fix ugly casting and branching in cpu_mask_to_apicid_and() Signed-off-by: Alexander Gordeev Cc: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120614074954.GF3383@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic/apic.c | 8 ++++---- arch/x86/kernel/apic/es7000_32.c | 2 +- arch/x86/kernel/apic/summit_32.c | 2 +- arch/x86/kernel/apic/x2apic_uv_x.c | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 048a4f806d46..c421512ca5eb 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -2127,19 +2127,19 @@ int default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, const struct cpumask *andmask, unsigned int *apicid) { - int cpu; + unsigned int cpu; for_each_cpu_and(cpu, cpumask, andmask) { if (cpumask_test_cpu(cpu, cpu_online_mask)) break; } - if (likely((unsigned int)cpu < nr_cpu_ids)) { + if (likely(cpu < nr_cpu_ids)) { *apicid = per_cpu(x86_cpu_to_apicid, cpu); return 0; - } else { - return -EINVAL; } + + return -EINVAL; } /* diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 2c5317ea1b83..effece2ea0db 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -529,7 +529,7 @@ static inline int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) { unsigned int round = 0; - int cpu, uninitialized_var(apicid); + unsigned int cpu, uninitialized_var(apicid); /* * The cpus in the mask must all be on the apic cluster. diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index bbad180f2890..b53fd6c9993a 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c @@ -267,7 +267,7 @@ static inline int summit_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) { unsigned int round = 0; - int cpu, apicid = 0; + unsigned int cpu, apicid = 0; /* * The cpus in the mask must all be on the apic cluster. diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 026de0114d15..8cfade9510a4 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -274,7 +274,7 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, const struct cpumask *andmask, unsigned int *apicid) { - int cpu; + int unsigned cpu; /* * We're using fixed IRQ delivery, can only return one phys APIC ID. @@ -285,12 +285,12 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, break; } - if (likely((unsigned int)cpu < nr_cpu_ids)) { + if (likely(cpu < nr_cpu_ids)) { *apicid = per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits; return 0; - } else { - return -EINVAL; } + + return -EINVAL; } static unsigned int x2apic_get_apic_id(unsigned long x) -- cgit v1.2.3 From 49ad3fd4834182cce9725abb98e080b479fed464 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 14 Jun 2012 09:50:11 +0200 Subject: x86/apic/es7000+summit: Fix compile warning in cpu_mask_to_apicid() Signed-off-by: Alexander Gordeev Cc: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120614075010.GG3383@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic/es7000_32.c | 2 +- arch/x86/kernel/apic/summit_32.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index effece2ea0db..0c1347df3ad0 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -554,8 +554,8 @@ es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask, const struct cpumask *andmask, unsigned int *apicid) { - *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); cpumask_var_t cpumask; + *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) return 0; diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index b53fd6c9993a..e6cc1829f7c8 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c @@ -291,8 +291,8 @@ summit_cpu_mask_to_apicid_and(const struct cpumask *inmask, const struct cpumask *andmask, unsigned int *apicid) { - *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); cpumask_var_t cpumask; + *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) return 0; -- cgit v1.2.3 From 214e270b5f5f6a85400a817d5305c797b2b7467a Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 14 Jun 2012 09:50:27 +0200 Subject: x86/apic/es7000+summit: Always make valid apicid from a cpumask In case of invalid parameters cpu_mask_to_apicid_and() might return apicid value of 0 (on Summit) or a uninitialized value (on ES7000), although it is supposed to return apicid of cpu-0 at least. Fix the operation to always return a valid apicid. Signed-off-by: Alexander Gordeev Cc: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120614075026.GH3383@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic/es7000_32.c | 2 ++ arch/x86/kernel/apic/summit_32.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 0c1347df3ad0..9882093f26e8 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -545,6 +545,8 @@ es7000_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) apicid = new_apicid; round++; } + if (!round) + return -EINVAL; *dest_id = apicid; return 0; } diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index e6cc1829f7c8..b6e61857c29f 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c @@ -282,6 +282,8 @@ summit_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) apicid |= new_apicid; round++; } + if (!round) + return -EINVAL; *dest_id = apicid; return 0; } -- cgit v1.2.3 From 5a0a2a308113086cc800a203d903271c9caa1611 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 14 Jun 2012 09:50:44 +0200 Subject: x86/apic/es7000: Make apicid of a cluster (not CPU) from a cpumask cpu_mask_to_apicid_and() always returns apicid of a single CPU, even in case multiple CPUs were requested. This update fixes a typo and forces apicid of a cluster to be returned. Signed-off-by: Alexander Gordeev Cc: Suresh Siddha Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20120614075043.GI3383@dhcp-26-207.brq.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic/es7000_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 9882093f26e8..0874799a98c6 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -542,7 +542,7 @@ es7000_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) return -EINVAL; } - apicid = new_apicid; + apicid |= new_apicid; round++; } if (!round) -- cgit v1.2.3 From 2307574a50dcb0f9c13e541ca3a196f7554af977 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 12 Jun 2012 12:31:43 +0100 Subject: ARM: 7423/1: kprobes: run t32_simulate_ldr_literal() without insn slot t32_simulate_ldr_literal() can be run without an instruction slot, so it should be using DECODE_SIMULATEX instead of DECODE_EMULATEX. Acked-by: Jon Medhurst Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/kernel/kprobes-thumb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c index 8f96ec778e8d..6123daf397a7 100644 --- a/arch/arm/kernel/kprobes-thumb.c +++ b/arch/arm/kernel/kprobes-thumb.c @@ -660,7 +660,7 @@ static const union decode_item t32_table_1111_100x[] = { /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */ /* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */ /* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal, + DECODE_SIMULATEX(0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal, REGS(PC, NOSPPCX, 0, 0, 0)), /* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */ -- cgit v1.2.3 From 2bea29b774ccb4bf32c7b299c677fccc5a1d8443 Mon Sep 17 00:00:00 2001 From: Mircea Gherzan Date: Mon, 11 Jun 2012 23:52:25 +0100 Subject: ARM: 7421/1: bpf_jit: BPF_S_ANC_ALU_XOR_X support JIT support for the XOR operation introduced by the commit ffe06c17afbb. Signed-off-by: Mircea Gherzan Signed-off-by: Russell King --- arch/arm/net/bpf_jit_32.c | 5 +++++ arch/arm/net/bpf_jit_32.h | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'arch') diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index 62135849f48b..c641fb685017 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -762,6 +762,11 @@ b_epilogue: update_on_xread(ctx); emit(ARM_MOV_R(r_A, r_X), ctx); break; + case BPF_S_ANC_ALU_XOR_X: + /* A ^= X */ + update_on_xread(ctx); + emit(ARM_EOR_R(r_A, r_A, r_X), ctx); + break; case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol) */ ctx->seen |= SEEN_SKB; diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h index 99ae5e3f46d2..7fa2f7d3cb90 100644 --- a/arch/arm/net/bpf_jit_32.h +++ b/arch/arm/net/bpf_jit_32.h @@ -68,6 +68,8 @@ #define ARM_INST_CMP_R 0x01500000 #define ARM_INST_CMP_I 0x03500000 +#define ARM_INST_EOR_R 0x00200000 + #define ARM_INST_LDRB_I 0x05d00000 #define ARM_INST_LDRB_R 0x07d00000 #define ARM_INST_LDRH_I 0x01d000b0 @@ -132,6 +134,8 @@ #define ARM_CMP_R(rn, rm) _AL3_R(ARM_INST_CMP, 0, rn, rm) #define ARM_CMP_I(rn, imm) _AL3_I(ARM_INST_CMP, 0, rn, imm) +#define ARM_EOR_R(rd, rn, rm) _AL3_R(ARM_INST_EOR, rd, rn, rm) + #define ARM_LDR_I(rt, rn, off) (ARM_INST_LDR_I | (rt) << 12 | (rn) << 16 \ | (off)) #define ARM_LDRB_I(rt, rn, off) (ARM_INST_LDRB_I | (rt) << 12 | (rn) << 16 \ -- cgit v1.2.3 From 15ab218318892f60e65c98bba81d725b3c19dab0 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:16 +0200 Subject: ARM: LPC32xx: Add NAND flash timing to PHY3250 board dts This patch adds necessary NAND flash timings to the board specific dts file of the PHY3250 reference board of the LPC32xx SoC. Signed-off-by: Roland Stigge Tested-by: Alexandre Pereira da Silva --- arch/arm/boot/dts/phy3250.dts | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/phy3250.dts b/arch/arm/boot/dts/phy3250.dts index c4ff6d1a018b..d7e985e47831 100644 --- a/arch/arm/boot/dts/phy3250.dts +++ b/arch/arm/boot/dts/phy3250.dts @@ -54,6 +54,17 @@ #address-cells = <1>; #size-cells = <1>; + nxp,wdr-clks = <14>; + nxp,wwidth = <40000000>; + nxp,whold = <100000000>; + nxp,wsetup = <100000000>; + nxp,rdr-clks = <14>; + nxp,rwidth = <40000000>; + nxp,rhold = <66666666>; + nxp,rsetup = <100000000>; + nand-on-flash-bbt; + gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */ + mtd0@00000000 { label = "phy3250-boot"; reg = <0x00000000 0x00064000>; -- cgit v1.2.3 From b27f48227c59754e1c881bd8e2b327ac02fe17b6 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:16 +0200 Subject: ARM: LPC32xx: Clock initialization for NAND controllers This patch adds clock initialization for the MLC NAND controller of the LPC32xx SoC and adjusts it for the SLC controller. Signed-off-by: Roland Stigge --- arch/arm/mach-lpc32xx/clock.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index f6a3ffec1f4b..bf0c3d91af9c 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c @@ -691,10 +691,21 @@ static struct clk clk_nand = { .parent = &clk_hclk, .enable = local_onoff_enable, .enable_reg = LPC32XX_CLKPWR_NAND_CLK_CTRL, - .enable_mask = LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN, + .enable_mask = LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN | + LPC32XX_CLKPWR_NANDCLK_SEL_SLC, .get_rate = local_return_parent_rate, }; +static struct clk clk_nand_mlc = { + .parent = &clk_hclk, + .enable = local_onoff_enable, + .enable_reg = LPC32XX_CLKPWR_NAND_CLK_CTRL, + .enable_mask = LPC32XX_CLKPWR_NANDCLK_MLCCLK_EN | + LPC32XX_CLKPWR_NANDCLK_DMA_INT | + LPC32XX_CLKPWR_NANDCLK_INTSEL_MLC, + .get_rate = local_return_parent_rate, +}; + static struct clk clk_i2s0 = { .parent = &clk_hclk, .enable = local_onoff_enable, @@ -1121,7 +1132,8 @@ static struct clk_lookup lookups[] = { CLKDEV_INIT("dev:ssp0", NULL, &clk_ssp0), CLKDEV_INIT("dev:ssp1", NULL, &clk_ssp1), CLKDEV_INIT("lpc32xx_keys.0", NULL, &clk_kscan), - CLKDEV_INIT("lpc32xx-nand.0", "nand_ck", &clk_nand), + CLKDEV_INIT("20020000.flash", NULL, &clk_nand), + CLKDEV_INIT("200a8000.flash", NULL, &clk_nand_mlc), CLKDEV_INIT("40048000.adc", NULL, &clk_adc), CLKDEV_INIT(NULL, "i2s0_ck", &clk_i2s0), CLKDEV_INIT(NULL, "i2s1_ck", &clk_i2s1), -- cgit v1.2.3 From ba225a0ea225902501487a2c9f620c26dce1cee6 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:16 +0200 Subject: ARM: LPC32xx: Remove SLC controller initialization from platform init Since we now support two MTD NAND controllers (MLC and SLC) for LPC32xx via DT, we don't initialize the SLC controller statically anymore, but do it via the clock setup (see previous patch). Signed-off-by: Roland Stigge Tested-by: Alexandre Pereira da Silva --- arch/arm/mach-lpc32xx/phy3250.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index 540106cdb9ec..42a078eb1665 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -241,10 +241,6 @@ static void __init lpc3250_machine_init(void) { u32 tmp; - /* Setup SLC NAND controller muxing */ - __raw_writel(LPC32XX_CLKPWR_NANDCLK_SEL_SLC, - LPC32XX_CLKPWR_NAND_CLK_CTRL); - /* Setup LCD muxing to RGB565 */ tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) & ~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK | -- cgit v1.2.3 From d807af4793a464f7331f92461a619e5e7ddf9089 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:17 +0200 Subject: ARM: LPC32xx: Add DMA configuration to platform data This patch adds DMA channel configuration to the LPC32xx platform file. The configured DMA signalling is generic for LPC32xx SoC and is not board specific. Signed-off-by: Roland Stigge --- arch/arm/mach-lpc32xx/phy3250.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index 42a078eb1665..eade77fbebdd 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -226,7 +226,38 @@ static int __init phy3250_spi_board_register(void) } arch_initcall(phy3250_spi_board_register); +static struct pl08x_channel_data pl08x_slave_channels[] = { + { + .bus_id = "nand-slc", + .min_signal = 1, /* SLC NAND Flash */ + .max_signal = 1, + .periph_buses = PL08X_AHB1, + }, + { + .bus_id = "nand-mlc", + .min_signal = 12, /* MLC NAND Flash */ + .max_signal = 12, + .periph_buses = PL08X_AHB1, + }, +}; + +/* NOTE: These will change, according to RMK */ +static int pl08x_get_signal(struct pl08x_dma_chan *ch) +{ + return ch->cd->min_signal; +} + +static void pl08x_put_signal(struct pl08x_dma_chan *ch) +{ +} + static struct pl08x_platform_data pl08x_pd = { + .slave_channels = &pl08x_slave_channels[0], + .num_slave_channels = ARRAY_SIZE(pl08x_slave_channels), + .get_signal = pl08x_get_signal, + .put_signal = pl08x_put_signal, + .lli_buses = PL08X_AHB1, + .mem_buses = PL08X_AHB1, }; static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = { -- cgit v1.2.3 From 6d1c3e93e37f35dac67fd88822e4a3100b1bd2c3 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:17 +0200 Subject: ARM: LPC32xx: Adjust dtsi file for MLC controller configuration This patch takes into account that the MTD NAND MLC controller needs more registers, located actually before the previously allocated memory range, already starting at 200a8000 instead of 200b0000. Further, the interrupt for the controller is configured. Signed-off-by: Roland Stigge Tested-by: Alexandre Pereira da Silva --- arch/arm/boot/dts/lpc32xx.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index 3f5dad801a98..254d586d4b1a 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -38,9 +38,10 @@ status = "disable"; }; - mlc: flash@200B0000 { + mlc: flash@200a8000 { compatible = "nxp,lpc3220-mlc"; - reg = <0x200B0000 0x1000>; + reg = <0x200a8000 0x11000>; + interrupts = <11 0>; status = "disable"; }; -- cgit v1.2.3 From d0408713e764c20796a8f79f3179ae41148edf19 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:17 +0200 Subject: ARM: LPC32xx: Add dts for EA3250 reference board There is another reference/development board for the LPC32xx SoC (besides the Phytec 3250): The Embedded Artists LPC3250 board. This patch adds a default dts file for it. Signed-off-by: Roland Stigge Acked-by: Alexandre Pereira da Silva --- arch/arm/boot/dts/ea3250.dts | 157 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 arch/arm/boot/dts/ea3250.dts (limited to 'arch') diff --git a/arch/arm/boot/dts/ea3250.dts b/arch/arm/boot/dts/ea3250.dts new file mode 100644 index 000000000000..c07ba8c2cc0d --- /dev/null +++ b/arch/arm/boot/dts/ea3250.dts @@ -0,0 +1,157 @@ +/* + * Embedded Artists LPC3250 board + * + * Copyright 2012 Roland Stigge + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "lpc32xx.dtsi" + +/ { + model = "Embedded Artists LPC3250 board based on NXP LPC3250"; + compatible = "ea,ea3250", "nxp,lpc3250"; + #address-cells = <1>; + #size-cells = <1>; + + memory { + device_type = "memory"; + reg = <0 0x4000000>; + }; + + ahb { + mac: ethernet@31060000 { + phy-mode = "rmii"; + use-iram; + }; + + /* Here, choose exactly one from: ohci, usbd */ + ohci@31020000 { + transceiver = <&isp1301>; + status = "okay"; + }; + +/* + usbd@31020000 { + transceiver = <&isp1301>; + status = "okay"; + }; +*/ + + /* 128MB Flash via SLC NAND controller */ + slc: flash@20020000 { + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + nxp,wdr-clks = <14>; + nxp,wwidth = <260000000>; + nxp,whold = <104000000>; + nxp,wsetup = <200000000>; + nxp,rdr-clks = <14>; + nxp,rwidth = <34666666>; + nxp,rhold = <104000000>; + nxp,rsetup = <200000000>; + nand-on-flash-bbt; + gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */ + + mtd0@00000000 { + label = "ea3250-boot"; + reg = <0x00000000 0x00080000>; + read-only; + }; + + mtd1@00080000 { + label = "ea3250-uboot"; + reg = <0x00080000 0x000c0000>; + read-only; + }; + + mtd2@00140000 { + label = "ea3250-kernel"; + reg = <0x00140000 0x00400000>; + }; + + mtd3@00540000 { + label = "ea3250-rootfs"; + reg = <0x00540000 0x07ac0000>; + }; + }; + + apb { + uart5: serial@40090000 { + status = "okay"; + }; + + uart3: serial@40080000 { + status = "okay"; + }; + + uart6: serial@40098000 { + status = "okay"; + }; + + i2c1: i2c@400A0000 { + clock-frequency = <100000>; + + eeprom@50 { + compatible = "at,24c256"; + reg = <0x50>; + }; + + eeprom@57 { + compatible = "at,24c64"; + reg = <0x57>; + }; + + uda1380: uda1380@18 { + compatible = "nxp,uda1380"; + reg = <0x18>; + power-gpio = <&gpio 0x59 0>; + reset-gpio = <&gpio 0x51 0>; + dac-clk = "wspll"; + }; + + pca9532: pca9532@60 { + compatible = "nxp,pca9532"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x60>; + }; + }; + + i2c2: i2c@400A8000 { + clock-frequency = <100000>; + }; + + i2cusb: i2c@31020300 { + clock-frequency = <100000>; + + isp1301: usb-transceiver@2d { + compatible = "nxp,isp1301"; + reg = <0x2d>; + }; + }; + + sd@20098000 { + wp-gpios = <&pca9532 5 0>; + cd-gpios = <&pca9532 4 0>; + cd-inverted; + bus-width = <4>; + status = "okay"; + }; + }; + + fab { + uart1: serial@40014000 { + status = "okay"; + }; + }; + }; +}; -- cgit v1.2.3 From a6d1be0e5825246da6df42cdaa21f3ce66698ff2 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:17 +0200 Subject: ARM: LPC32xx: DTS adjustment for key matrix controller This patch connects the lpc32xx-key driver to the LPC32xx platform (via lpc32xx.dtsi), and more specifically to the reference board via its dts file. Signed-off-by: Roland Stigge Acked-by: Rob Herring Acked-by: Alexandre Pereira da Silva --- arch/arm/boot/dts/lpc32xx.dtsi | 2 ++ arch/arm/boot/dts/phy3250.dts | 9 +++++++++ 2 files changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index 254d586d4b1a..e2b50b220a38 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -249,6 +249,8 @@ key@40050000 { compatible = "nxp,lpc3220-key"; reg = <0x40050000 0x1000>; + interrupts = <54 0>; + status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/phy3250.dts b/arch/arm/boot/dts/phy3250.dts index d7e985e47831..1dbfea8b7bdf 100644 --- a/arch/arm/boot/dts/phy3250.dts +++ b/arch/arm/boot/dts/phy3250.dts @@ -135,6 +135,15 @@ tsc@40048000 { status = "okay"; }; + + key@40050000 { + status = "okay"; + keypad,num-rows = <1>; + keypad,num-columns = <1>; + nxp,debounce-delay-ms = <3>; + nxp,scan-delay-ms = <34>; + linux,keymap = <0x00000002>; + }; }; }; -- cgit v1.2.3 From 821e7edd5130a1efd8754bcd7e4c30ccb1fc9c71 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:17 +0200 Subject: ARM: LPC32xx: Clock adjustment for key matrix controller The clock.c file needs to be changed to match the automatic device name to its clock. Signed-off-by: Roland Stigge Acked-by: Rob Herring --- arch/arm/mach-lpc32xx/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index bf0c3d91af9c..963d12a9fc3d 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c @@ -1131,7 +1131,7 @@ static struct clk_lookup lookups[] = { CLKDEV_INIT("31020300.i2c", NULL, &clk_i2c2), CLKDEV_INIT("dev:ssp0", NULL, &clk_ssp0), CLKDEV_INIT("dev:ssp1", NULL, &clk_ssp1), - CLKDEV_INIT("lpc32xx_keys.0", NULL, &clk_kscan), + CLKDEV_INIT("40050000.key", NULL, &clk_kscan), CLKDEV_INIT("20020000.flash", NULL, &clk_nand), CLKDEV_INIT("200a8000.flash", NULL, &clk_nand_mlc), CLKDEV_INIT("40048000.adc", NULL, &clk_adc), -- cgit v1.2.3 From 360c9627cc3b0334514d6cb8260833e768c71b63 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:17 +0200 Subject: ARM: LPC32xx: Defconfig update This defconfig update for the LPC32xx SoC platform adds the new drivers in v3.5 and drivers typically used in systems with the LPC32xx chip. Signed-off-by: Roland Stigge Acked-by: Alexandre Pereira da Silva --- arch/arm/configs/lpc32xx_defconfig | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig index 4fa60547494a..eceed186a3c1 100644 --- a/arch/arm/configs/lpc32xx_defconfig +++ b/arch/arm/configs/lpc32xx_defconfig @@ -1,5 +1,7 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 @@ -16,8 +18,6 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set CONFIG_PARTITION_ADVANCED=y CONFIG_ARCH_LPC32XX=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y CONFIG_PREEMPT=y CONFIG_AEABI=y CONFIG_ZBOOT_ROM_TEXT=0x0 @@ -52,13 +52,17 @@ CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y +CONFIG_MTD_M25P80=y CONFIG_MTD_NAND=y CONFIG_MTD_NAND_MUSEUM_IDS=y +CONFIG_MTD_NAND_SLC_LPC32XX=y +CONFIG_MTD_NAND_MLC_LPC32XX=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=1 CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_EEPROM_AT24=y CONFIG_EEPROM_AT25=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y @@ -79,16 +83,22 @@ CONFIG_LPC_ENET=y # CONFIG_NET_VENDOR_STMICRO is not set CONFIG_SMSC_PHY=y # CONFIG_WLAN is not set +CONFIG_INPUT_MATRIXKMAP=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_MOUSEDEV_SCREEN_X=240 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320 CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_LPC32XX=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_LPC32XX=y +CONFIG_SERIO_LIBPS2=y # CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_HS_LPC32XX=y +CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y CONFIG_I2C_CHARDEV=y @@ -96,7 +106,8 @@ CONFIG_I2C_PNX=y CONFIG_SPI=y CONFIG_SPI_PL022=y CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set +CONFIG_SENSORS_DS620=y +CONFIG_SENSORS_MAX6639=y CONFIG_WATCHDOG=y CONFIG_PNX4008_WATCHDOG=y CONFIG_FB=y @@ -133,6 +144,8 @@ CONFIG_MMC=y CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y +CONFIG_LEDS_PCA9532=y +CONFIG_LEDS_PCA9532_GPIO=y CONFIG_LEDS_GPIO=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y @@ -146,10 +159,10 @@ CONFIG_RTC_DRV_DS1374=y CONFIG_RTC_DRV_PCF8563=y CONFIG_RTC_DRV_LPC32XX=y CONFIG_DMADEVICES=y -CONFIG_AMBA_PL08X=y CONFIG_STAGING=y -CONFIG_IIO=y CONFIG_LPC32XX_ADC=y +CONFIG_MAX517=y +CONFIG_IIO=y CONFIG_EXT2_FS=y CONFIG_AUTOFS4_FS=y CONFIG_MSDOS_FS=y @@ -159,7 +172,6 @@ CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_WBUF_VERIFY=y CONFIG_CRAMFS=y CONFIG_NFS_FS=y -CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ASCII=y -- cgit v1.2.3 From 291dd71fe48c0b696a9391ed1ba476c8878d6fca Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:17 +0200 Subject: ARM: LPC32xx: Add MMC controller support This patch adds support for the MMC controller of the LPC32xx SoC to the platform initialization via the pl08x primecell driver. Lacking more complete DT support, done via DT auxdata. Signed-off-by: Roland Stigge Acked-by: Alexandre Pereira da Silva --- arch/arm/mach-lpc32xx/phy3250.c | 43 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index eade77fbebdd..03ee3491b7cf 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -30,12 +30,13 @@ #include #include #include +#include +#include #include #include #include #include #include -#include #include #include @@ -50,9 +51,12 @@ /* * Mapped GPIOLIB GPIOs */ -#define SPI0_CS_GPIO LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5) -#define LCD_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0) -#define BKL_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4) +#define SPI0_CS_GPIO LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5) +#define LCD_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0) +#define BKL_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4) +#define MMC_PWR_ENABLE_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 5) +#define MMC_CD_GPIO LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 1) +#define MMC_WP_GPIO LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 0) /* * AMBA LCD controller @@ -260,11 +264,32 @@ static struct pl08x_platform_data pl08x_pd = { .mem_buses = PL08X_AHB1, }; +static int mmc_handle_ios(struct device *dev, struct mmc_ios *ios) +{ + /* Only on and off are supported */ + if (ios->power_mode == MMC_POWER_OFF) + gpio_set_value(MMC_PWR_ENABLE_GPIO, 0); + else + gpio_set_value(MMC_PWR_ENABLE_GPIO, 1); + return 0; +} + +static struct mmci_platform_data lpc32xx_mmci_data = { + .ocr_mask = MMC_VDD_30_31 | MMC_VDD_31_32 | + MMC_VDD_32_33 | MMC_VDD_33_34, + .ios_handler = mmc_handle_ios, + .dma_filter = NULL, + /* No DMA for now since AMBA PL080 dmaengine driver only does scatter + * gather, and the MMCI driver doesn't do it this way */ +}; + static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = { OF_DEV_AUXDATA("arm,pl022", 0x20084000, "dev:ssp0", &lpc32xx_ssp0_data), OF_DEV_AUXDATA("arm,pl022", 0x2008C000, "dev:ssp1", &lpc32xx_ssp1_data), OF_DEV_AUXDATA("arm,pl110", 0x31040000, "dev:clcd", &lpc32xx_clcd_data), OF_DEV_AUXDATA("arm,pl080", 0x31000000, "pl08xdmac", &pl08x_pd), + OF_DEV_AUXDATA("arm,pl18x", 0x20098000, "20098000.sd", + &lpc32xx_mmci_data), { } }; @@ -308,6 +333,11 @@ static void __init lpc3250_machine_init(void) * detection or a data fault will occur, so enable the clocks * here. */ + tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL); + tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN | + LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN; + __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL); + tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL); __raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN), LPC32XX_CLKPWR_LCDCLK_CTRL); @@ -335,6 +365,11 @@ static void __init lpc3250_machine_init(void) else if (gpio_direction_output(SPI0_CS_GPIO, 1)) printk(KERN_ERR "Error setting gpio %u to output", SPI0_CS_GPIO); + + if (gpio_request(MMC_PWR_ENABLE_GPIO, "mmc_power_en")) + pr_err("Error requesting gpio %u", MMC_PWR_ENABLE_GPIO); + else if (gpio_direction_output(MMC_PWR_ENABLE_GPIO, 1)) + pr_err("Error setting gpio %u to output", MMC_PWR_ENABLE_GPIO); } static char const *lpc32xx_dt_compat[] __initdata = { -- cgit v1.2.3 From 2c7fa28622d8c00ca41f0362d11c52d9f404f543 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:18 +0200 Subject: ARM: LPC32xx: DTS adjustment for using pl18x primecell This patch adjusts the dts files to reference the pl18x primecell driver correctly. Signed-off-by: Roland Stigge --- arch/arm/boot/dts/lpc32xx.dtsi | 3 ++- arch/arm/boot/dts/phy3250.dts | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index e2b50b220a38..a9b2a6a22024 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -115,9 +115,10 @@ }; sd@20098000 { - compatible = "arm,pl180", "arm,primecell"; + compatible = "arm,pl18x", "arm,primecell"; reg = <0x20098000 0x1000>; interrupts = <0x0f 0>, <0x0d 0>; + status = "disabled"; }; i2s1: i2s@2009C000 { diff --git a/arch/arm/boot/dts/phy3250.dts b/arch/arm/boot/dts/phy3250.dts index 1dbfea8b7bdf..d5432378f234 100644 --- a/arch/arm/boot/dts/phy3250.dts +++ b/arch/arm/boot/dts/phy3250.dts @@ -129,6 +129,14 @@ compatible = "atmel,at25"; }; }; + + sd@20098000 { + wp-gpios = <&gpio 3 0 0>; + cd-gpios = <&gpio 3 1 0>; + cd-inverted; + bus-width = <4>; + status = "okay"; + }; }; fab { -- cgit v1.2.3 From c70426f1534a7d8e52e478ce67fd4634cc588741 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:18 +0200 Subject: ARM: LPC32xx: DT conversion of Standard UARTs This patch switches from static serial driver initialization to devicetree configuration. This way, the Standard UARTs of the LPC32xx SoC can be enabled individually via DT. E.g., instead of Kconfig configuration, the phy3250.dts activates UARTs 3 and 5. Signed-off-by: Roland Stigge Tested-by: Alexandre Pereira da Silva --- arch/arm/Kconfig | 2 - arch/arm/boot/dts/lpc32xx.dtsi | 34 +++++++++++++---- arch/arm/boot/dts/phy3250.dts | 8 ++++ arch/arm/mach-lpc32xx/Kconfig | 32 ---------------- arch/arm/mach-lpc32xx/serial.c | 85 +----------------------------------------- 5 files changed, 35 insertions(+), 126 deletions(-) delete mode 100644 arch/arm/mach-lpc32xx/Kconfig (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 84449dd8f031..973d5380a431 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1019,8 +1019,6 @@ source "arch/arm/mach-kirkwood/Kconfig" source "arch/arm/mach-ks8695/Kconfig" -source "arch/arm/mach-lpc32xx/Kconfig" - source "arch/arm/mach-msm/Kconfig" source "arch/arm/mach-mv78xx0/Kconfig" diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index a9b2a6a22024..acb68171d04d 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -126,24 +126,42 @@ reg = <0x2009C000 0x1000>; }; + /* UART5 first since it is the default console, ttyS0 */ + uart5: serial@40090000 { + /* actually, ns16550a w/ 64 byte fifos! */ + compatible = "nxp,lpc3220-uart"; + reg = <0x40090000 0x1000>; + interrupts = <9 0>; + clock-frequency = <13000000>; + reg-shift = <2>; + status = "disabled"; + }; + uart3: serial@40080000 { - compatible = "nxp,serial"; + compatible = "nxp,lpc3220-uart"; reg = <0x40080000 0x1000>; + interrupts = <7 0>; + clock-frequency = <13000000>; + reg-shift = <2>; + status = "disabled"; }; uart4: serial@40088000 { - compatible = "nxp,serial"; + compatible = "nxp,lpc3220-uart"; reg = <0x40088000 0x1000>; - }; - - uart5: serial@40090000 { - compatible = "nxp,serial"; - reg = <0x40090000 0x1000>; + interrupts = <8 0>; + clock-frequency = <13000000>; + reg-shift = <2>; + status = "disabled"; }; uart6: serial@40098000 { - compatible = "nxp,serial"; + compatible = "nxp,lpc3220-uart"; reg = <0x40098000 0x1000>; + interrupts = <10 0>; + clock-frequency = <13000000>; + reg-shift = <2>; + status = "disabled"; }; i2c1: i2c@400A0000 { diff --git a/arch/arm/boot/dts/phy3250.dts b/arch/arm/boot/dts/phy3250.dts index d5432378f234..57d4961372d4 100644 --- a/arch/arm/boot/dts/phy3250.dts +++ b/arch/arm/boot/dts/phy3250.dts @@ -94,6 +94,14 @@ }; apb { + uart5: serial@40090000 { + status = "okay"; + }; + + uart3: serial@40080000 { + status = "okay"; + }; + i2c1: i2c@400A0000 { clock-frequency = <100000>; diff --git a/arch/arm/mach-lpc32xx/Kconfig b/arch/arm/mach-lpc32xx/Kconfig deleted file mode 100644 index e0b3eee83834..000000000000 --- a/arch/arm/mach-lpc32xx/Kconfig +++ /dev/null @@ -1,32 +0,0 @@ -if ARCH_LPC32XX - -menu "Individual UART enable selections" - -config ARCH_LPC32XX_UART3_SELECT - bool "Add support for standard UART3" - help - Adds support for standard UART 3 when the 8250 serial support - is enabled. - -config ARCH_LPC32XX_UART4_SELECT - bool "Add support for standard UART4" - help - Adds support for standard UART 4 when the 8250 serial support - is enabled. - -config ARCH_LPC32XX_UART5_SELECT - bool "Add support for standard UART5" - default y - help - Adds support for standard UART 5 when the 8250 serial support - is enabled. - -config ARCH_LPC32XX_UART6_SELECT - bool "Add support for standard UART6" - help - Adds support for standard UART 6 when the 8250 serial support - is enabled. - -endmenu - -endif diff --git a/arch/arm/mach-lpc32xx/serial.c b/arch/arm/mach-lpc32xx/serial.c index f2735281616a..b5a3f3423f63 100644 --- a/arch/arm/mach-lpc32xx/serial.c +++ b/arch/arm/mach-lpc32xx/serial.c @@ -31,59 +31,6 @@ #define LPC32XX_SUART_FIFO_SIZE 64 -/* Standard 8250/16550 compatible serial ports */ -static struct plat_serial8250_port serial_std_platform_data[] = { -#ifdef CONFIG_ARCH_LPC32XX_UART5_SELECT - { - .membase = io_p2v(LPC32XX_UART5_BASE), - .mapbase = LPC32XX_UART5_BASE, - .irq = IRQ_LPC32XX_UART_IIR5, - .uartclk = LPC32XX_MAIN_OSC_FREQ, - .regshift = 2, - .iotype = UPIO_MEM32, - .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | - UPF_SKIP_TEST, - }, -#endif -#ifdef CONFIG_ARCH_LPC32XX_UART3_SELECT - { - .membase = io_p2v(LPC32XX_UART3_BASE), - .mapbase = LPC32XX_UART3_BASE, - .irq = IRQ_LPC32XX_UART_IIR3, - .uartclk = LPC32XX_MAIN_OSC_FREQ, - .regshift = 2, - .iotype = UPIO_MEM32, - .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | - UPF_SKIP_TEST, - }, -#endif -#ifdef CONFIG_ARCH_LPC32XX_UART4_SELECT - { - .membase = io_p2v(LPC32XX_UART4_BASE), - .mapbase = LPC32XX_UART4_BASE, - .irq = IRQ_LPC32XX_UART_IIR4, - .uartclk = LPC32XX_MAIN_OSC_FREQ, - .regshift = 2, - .iotype = UPIO_MEM32, - .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | - UPF_SKIP_TEST, - }, -#endif -#ifdef CONFIG_ARCH_LPC32XX_UART6_SELECT - { - .membase = io_p2v(LPC32XX_UART6_BASE), - .mapbase = LPC32XX_UART6_BASE, - .irq = IRQ_LPC32XX_UART_IIR6, - .uartclk = LPC32XX_MAIN_OSC_FREQ, - .regshift = 2, - .iotype = UPIO_MEM32, - .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | - UPF_SKIP_TEST, - }, -#endif - { }, -}; - struct uartinit { char *uart_ck_name; u32 ck_mode_mask; @@ -92,7 +39,6 @@ struct uartinit { }; static struct uartinit uartinit_data[] __initdata = { -#ifdef CONFIG_ARCH_LPC32XX_UART5_SELECT { .uart_ck_name = "uart5_ck", .ck_mode_mask = @@ -100,8 +46,6 @@ static struct uartinit uartinit_data[] __initdata = { .pdiv_clk_reg = LPC32XX_CLKPWR_UART5_CLK_CTRL, .mapbase = LPC32XX_UART5_BASE, }, -#endif -#ifdef CONFIG_ARCH_LPC32XX_UART3_SELECT { .uart_ck_name = "uart3_ck", .ck_mode_mask = @@ -109,8 +53,6 @@ static struct uartinit uartinit_data[] __initdata = { .pdiv_clk_reg = LPC32XX_CLKPWR_UART3_CLK_CTRL, .mapbase = LPC32XX_UART3_BASE, }, -#endif -#ifdef CONFIG_ARCH_LPC32XX_UART4_SELECT { .uart_ck_name = "uart4_ck", .ck_mode_mask = @@ -118,8 +60,6 @@ static struct uartinit uartinit_data[] __initdata = { .pdiv_clk_reg = LPC32XX_CLKPWR_UART4_CLK_CTRL, .mapbase = LPC32XX_UART4_BASE, }, -#endif -#ifdef CONFIG_ARCH_LPC32XX_UART6_SELECT { .uart_ck_name = "uart6_ck", .ck_mode_mask = @@ -127,19 +67,6 @@ static struct uartinit uartinit_data[] __initdata = { .pdiv_clk_reg = LPC32XX_CLKPWR_UART6_CLK_CTRL, .mapbase = LPC32XX_UART6_BASE, }, -#endif -}; - -static struct platform_device serial_std_platform_device = { - .name = "serial8250", - .id = 0, - .dev = { - .platform_data = serial_std_platform_data, - }, -}; - -static struct platform_device *lpc32xx_serial_devs[] __initdata = { - &serial_std_platform_device, }; void __init lpc32xx_serial_init(void) @@ -156,15 +83,8 @@ void __init lpc32xx_serial_init(void) clk = clk_get(NULL, uartinit_data[i].uart_ck_name); if (!IS_ERR(clk)) { clk_enable(clk); - serial_std_platform_data[i].uartclk = - clk_get_rate(clk); } - /* Fall back on main osc rate if clock rate return fails */ - if (serial_std_platform_data[i].uartclk == 0) - serial_std_platform_data[i].uartclk = - LPC32XX_MAIN_OSC_FREQ; - /* Setup UART clock modes for all UARTs, disable autoclock */ clkmodes |= uartinit_data[i].ck_mode_mask; @@ -189,7 +109,7 @@ void __init lpc32xx_serial_init(void) __raw_writel(clkmodes, LPC32XX_UARTCTL_CLKMODE); for (i = 0; i < ARRAY_SIZE(uartinit_data); i++) { /* Force a flush of the RX FIFOs to work around a HW bug */ - puart = serial_std_platform_data[i].mapbase; + puart = uartinit_data[i].mapbase; __raw_writel(0xC1, LPC32XX_UART_IIR_FCR(puart)); __raw_writel(0x00, LPC32XX_UART_DLL_FIFO(puart)); j = LPC32XX_SUART_FIFO_SIZE; @@ -202,7 +122,4 @@ void __init lpc32xx_serial_init(void) tmp = __raw_readl(LPC32XX_UARTCTL_CTRL); tmp &= ~LPC32XX_UART_U5_ROUTE_TO_USB; __raw_writel(tmp, LPC32XX_UARTCTL_CTRL); - - platform_add_devices(lpc32xx_serial_devs, - ARRAY_SIZE(lpc32xx_serial_devs)); } -- cgit v1.2.3 From ac5ced91aa6b5013027d3313824c9c5afb071f23 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:18 +0200 Subject: ARM: LPC32xx: High Speed UART configuration via DT This patch fixes the DTS files for the High Speed UARTs 1, 2 and 7 of the LPC32xx SoC, adjusting the compatible strings, adding interrupts and status configuration. On the PHY3250 reference board, UART2 is enabled. Signed-off-by: Roland Stigge Acked-by: Alexandre Pereira da Silva --- arch/arm/boot/dts/lpc32xx.dtsi | 16 +++++++++++----- arch/arm/boot/dts/phy3250.dts | 4 ++++ 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index acb68171d04d..34a73f34621c 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -212,18 +212,24 @@ }; uart1: serial@40014000 { - compatible = "nxp,serial"; + compatible = "nxp,lpc3220-hsuart"; reg = <0x40014000 0x1000>; + interrupts = <26 0>; + status = "disabled"; }; uart2: serial@40018000 { - compatible = "nxp,serial"; + compatible = "nxp,lpc3220-hsuart"; reg = <0x40018000 0x1000>; + interrupts = <25 0>; + status = "disabled"; }; - uart7: serial@4001C000 { - compatible = "nxp,serial"; - reg = <0x4001C000 0x1000>; + uart7: serial@4001c000 { + compatible = "nxp,lpc3220-hsuart"; + reg = <0x4001c000 0x1000>; + interrupts = <24 0>; + status = "disabled"; }; rtc@40024000 { diff --git a/arch/arm/boot/dts/phy3250.dts b/arch/arm/boot/dts/phy3250.dts index 57d4961372d4..f3bf1493afb0 100644 --- a/arch/arm/boot/dts/phy3250.dts +++ b/arch/arm/boot/dts/phy3250.dts @@ -148,6 +148,10 @@ }; fab { + uart2: serial@40018000 { + status = "okay"; + }; + tsc@40048000 { status = "okay"; }; -- cgit v1.2.3 From 1a6e29c913d25eae0e232926fd9f7ceaf5306dc2 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:18 +0200 Subject: ARM: LPC32xx: Remove mach specific ARCH_NR_GPIOS, use default ARCH_NR_GPIOS was defined statically to include exactly all SoC specific GPIOs. Now if additional GPIOs need to be added dynamically, e.g. via DT, none are available. Removing the mach specific setting, leaving ARCH_NR_GPIOS to the default of 256 (currently in include/asm-generic/gpio.h). Signed-off-by: Roland Stigge Acked-by: Alexandre Pereira da Silva --- arch/arm/mach-lpc32xx/include/mach/gpio.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-lpc32xx/include/mach/gpio.h b/arch/arm/mach-lpc32xx/include/mach/gpio.h index 2ba6ca412bef..0052e7a76179 100644 --- a/arch/arm/mach-lpc32xx/include/mach/gpio.h +++ b/arch/arm/mach-lpc32xx/include/mach/gpio.h @@ -3,6 +3,4 @@ #include "gpio-lpc32xx.h" -#define ARCH_NR_GPIOS (LPC32XX_GPO_P3_GRP + LPC32XX_GPO_P3_MAX) - #endif /* __MACH_GPIO_H */ -- cgit v1.2.3 From cb85a9e50817aec997d3cb7488614dac1f27465d Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 14 Jun 2012 16:16:18 +0200 Subject: ARM: LPC32xx: Fix lpc32xx.dtsi status property: "disable" -> "disabled" This patches fixes some status = "disable" strings to "disabled", the correct way of disabling nodes in the devicetree. Signed-off-by: Roland Stigge --- arch/arm/boot/dts/lpc32xx.dtsi | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index 34a73f34621c..c5f37fbd33e6 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -35,14 +35,14 @@ slc: flash@20020000 { compatible = "nxp,lpc3220-slc"; reg = <0x20020000 0x1000>; - status = "disable"; + status = "disabled"; }; mlc: flash@200a8000 { compatible = "nxp,lpc3220-mlc"; reg = <0x200a8000 0x11000>; interrupts = <11 0>; - status = "disable"; + status = "disabled"; }; dma@31000000 { @@ -58,21 +58,21 @@ compatible = "nxp,ohci-nxp", "usb-ohci"; reg = <0x31020000 0x300>; interrupts = <0x3b 0>; - status = "disable"; + status = "disabled"; }; usbd@31020000 { compatible = "nxp,lpc3220-udc"; reg = <0x31020000 0x300>; interrupts = <0x3d 0>, <0x3e 0>, <0x3c 0>, <0x3a 0>; - status = "disable"; + status = "disabled"; }; clcd@31040000 { compatible = "arm,pl110", "arm,primecell"; reg = <0x31040000 0x1000>; interrupts = <0x0e 0>; - status = "disable"; + status = "disabled"; }; mac: ethernet@31060000 { @@ -261,14 +261,14 @@ compatible = "nxp,lpc3220-adc"; reg = <0x40048000 0x1000>; interrupts = <0x27 0>; - status = "disable"; + status = "disabled"; }; tsc@40048000 { compatible = "nxp,lpc3220-tsc"; reg = <0x40048000 0x1000>; interrupts = <0x27 0>; - status = "disable"; + status = "disabled"; }; key@40050000 { -- cgit v1.2.3 From 1440837440a31672973eedaf632f54c9dfc08c4d Mon Sep 17 00:00:00 2001 From: Alexandre Pereira da Silva Date: Tue, 12 Jun 2012 10:23:27 -0300 Subject: ARM: LPC32xx: Build arch dtbs Add ea3250.dtb and phy3250.dtb to the list of dtbs to be built Signed-off-by: Alexandre Pereira da Silva Signed-off-by: Roland Stigge --- arch/arm/mach-lpc32xx/Makefile.boot | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-lpc32xx/Makefile.boot b/arch/arm/mach-lpc32xx/Makefile.boot index 2cfe0ee635c5..697323b5f92d 100644 --- a/arch/arm/mach-lpc32xx/Makefile.boot +++ b/arch/arm/mach-lpc32xx/Makefile.boot @@ -2,3 +2,4 @@ params_phys-y := 0x80000100 initrd_phys-y := 0x82000000 +dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb -- cgit v1.2.3 From 2e0b5a375288d624feb16b58a3af662338a63641 Mon Sep 17 00:00:00 2001 From: Alexandre Pereira da Silva Date: Tue, 12 Jun 2012 10:34:12 -0300 Subject: ARM: LPC32xx: Add dt settings to the at25 node Add the reg, cs-gpios and max-frequencies that are needed for spi device registry in phy3250. Adds also the pl022 internal transfers details via dt Signed-off-by: Alexandre Pereira da Silva Signed-off-by: Roland Stigge --- arch/arm/boot/dts/phy3250.dts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/phy3250.dts b/arch/arm/boot/dts/phy3250.dts index f3bf1493afb0..802ec5b2fd00 100644 --- a/arch/arm/boot/dts/phy3250.dts +++ b/arch/arm/boot/dts/phy3250.dts @@ -133,8 +133,29 @@ }; ssp0: ssp@20084000 { + #address-cells = <1>; + #size-cells = <0>; + pl022,num-chipselects = <1>; + cs-gpios = <&gpio 3 5 0>; + eeprom: at25@0 { + pl022,hierarchy = <0>; + pl022,interface = <0>; + pl022,slave-tx-disable = <0>; + pl022,com-mode = <0>; + pl022,rx-level-trig = <1>; + pl022,tx-level-trig = <1>; + pl022,ctrl-len = <11>; + pl022,wait-state = <0>; + pl022,duplex = <0>; + + at25,byte-len = <0x8000>; + at25,addr-mode = <2>; + at25,page-size = <64>; + compatible = "atmel,at25"; + reg = <0>; + spi-max-frequency = <5000000>; }; }; -- cgit v1.2.3 From c05a8b145cb84e8101a57b6876f14cdb79fa12b8 Mon Sep 17 00:00:00 2001 From: Alexandre Pereira da Silva Date: Tue, 12 Jun 2012 11:34:28 -0300 Subject: ARM: LPC32xx: Remove spi chipselect request from board init The lpc32xx spi0 chipselect will be requested directly from the pl022 driver Signed-off-by: Alexandre Pereira da Silva Signed-off-by: Roland Stigge --- arch/arm/mach-lpc32xx/phy3250.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index 03ee3491b7cf..4ba238395be9 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -359,13 +359,6 @@ static void __init lpc3250_machine_init(void) lpc32xx_auxdata_lookup, NULL); /* Register GPIOs used on this board */ - if (gpio_request(SPI0_CS_GPIO, "spi0 cs")) - printk(KERN_ERR "Error requesting gpio %u", - SPI0_CS_GPIO); - else if (gpio_direction_output(SPI0_CS_GPIO, 1)) - printk(KERN_ERR "Error setting gpio %u to output", - SPI0_CS_GPIO); - if (gpio_request(MMC_PWR_ENABLE_GPIO, "mmc_power_en")) pr_err("Error requesting gpio %u", MMC_PWR_ENABLE_GPIO); else if (gpio_direction_output(MMC_PWR_ENABLE_GPIO, 1)) -- cgit v1.2.3 From 72b78cf713176f376f369df8ccca865c5d51c42b Mon Sep 17 00:00:00 2001 From: Alexandre Pereira da Silva Date: Mon, 11 Jun 2012 00:25:15 -0300 Subject: ARM: LPC32xx: Remove spi chip definitions Leave chipselect and spi devices binding to the devicetree Signed-off-by: Alexandre Pereira da Silva Signed-off-by: Roland Stigge --- arch/arm/mach-lpc32xx/phy3250.c | 56 ----------------------------------------- 1 file changed, 56 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index 4ba238395be9..93408883eaca 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -162,24 +162,6 @@ static struct clcd_board lpc32xx_clcd_data = { /* * AMBA SSP (SPI) */ -static void phy3250_spi_cs_set(u32 control) -{ - gpio_set_value(SPI0_CS_GPIO, (int) control); -} - -static struct pl022_config_chip spi0_chip_info = { - .com_mode = INTERRUPT_TRANSFER, - .iface = SSP_INTERFACE_MOTOROLA_SPI, - .hierarchy = SSP_MASTER, - .slave_tx_disable = 0, - .rx_lev_trig = SSP_RX_4_OR_MORE_ELEM, - .tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC, - .ctrl_len = SSP_BITS_8, - .wait_state = SSP_MWIRE_WAIT_ZERO, - .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, - .cs_control = phy3250_spi_cs_set, -}; - static struct pl022_ssp_controller lpc32xx_ssp0_data = { .bus_id = 0, .num_chipselect = 1, @@ -192,44 +174,6 @@ static struct pl022_ssp_controller lpc32xx_ssp1_data = { .enable_dma = 0, }; -/* AT25 driver registration */ -static int __init phy3250_spi_board_register(void) -{ -#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE) - static struct spi_board_info info[] = { - { - .modalias = "spidev", - .max_speed_hz = 5000000, - .bus_num = 0, - .chip_select = 0, - .controller_data = &spi0_chip_info, - }, - }; - -#else - static struct spi_eeprom eeprom = { - .name = "at25256a", - .byte_len = 0x8000, - .page_size = 64, - .flags = EE_ADDR2, - }; - - static struct spi_board_info info[] = { - { - .modalias = "at25", - .max_speed_hz = 5000000, - .bus_num = 0, - .chip_select = 0, - .mode = SPI_MODE_0, - .platform_data = &eeprom, - .controller_data = &spi0_chip_info, - }, - }; -#endif - return spi_register_board_info(info, ARRAY_SIZE(info)); -} -arch_initcall(phy3250_spi_board_register); - static struct pl08x_channel_data pl08x_slave_channels[] = { { .bus_id = "nand-slc", -- cgit v1.2.3 From 112e9adda4ddcd56895f20c4c886d2493d7907f3 Mon Sep 17 00:00:00 2001 From: Alexandre Pereira da Silva Date: Wed, 13 Jun 2012 19:28:23 -0300 Subject: ARM: LPC32xx: Cleanup board init, remove duplicate clock init Remove SSP0, CLCD and DMA clocks that are already migrated to the clock framework. Signed-off-by: Alexandre Pereira da Silva Signed-off-by: Roland Stigge --- arch/arm/mach-lpc32xx/phy3250.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index 93408883eaca..d7389598c21a 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -272,28 +272,11 @@ static void __init lpc3250_machine_init(void) lpc32xx_serial_init(); - /* - * AMBA peripheral clocks need to be enabled prior to AMBA device - * detection or a data fault will occur, so enable the clocks - * here. - */ tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL); tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN | LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN; __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL); - tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL); - __raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN), - LPC32XX_CLKPWR_LCDCLK_CTRL); - - tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL); - __raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN), - LPC32XX_CLKPWR_SSP_CLK_CTRL); - - tmp = __raw_readl(LPC32XX_CLKPWR_DMA_CLK_CTRL); - __raw_writel((tmp | LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN), - LPC32XX_CLKPWR_DMA_CLK_CTRL); - /* Test clock needed for UDA1380 initial init */ __raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC | LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN, -- cgit v1.2.3 From 5fe8f11ccb63298bcaab34994c3ca04fd6d30887 Mon Sep 17 00:00:00 2001 From: Alexandre Pereira da Silva Date: Wed, 13 Jun 2012 19:34:25 -0300 Subject: ARM: LPC32xx: Move uart6 irda disable to serial.c Move the irda configuration to serial.c where other special cases are handled Signed-off-by: Alexandre Pereira da Silva Signed-off-by: Roland Stigge --- arch/arm/mach-lpc32xx/phy3250.c | 5 ----- arch/arm/mach-lpc32xx/serial.c | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index d7389598c21a..eb22fbf029ea 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -260,11 +260,6 @@ static void __init lpc3250_machine_init(void) LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE; __raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL); - /* Disable IrDA pulsing support on UART6 */ - tmp = __raw_readl(LPC32XX_UARTCTL_CTRL); - tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS; - __raw_writel(tmp, LPC32XX_UARTCTL_CTRL); - /* Enable DMA for I2S1 channel */ tmp = __raw_readl(LPC32XX_CLKPWR_I2S_CLK_CTRL); tmp = LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA; diff --git a/arch/arm/mach-lpc32xx/serial.c b/arch/arm/mach-lpc32xx/serial.c index b5a3f3423f63..05621a29fba2 100644 --- a/arch/arm/mach-lpc32xx/serial.c +++ b/arch/arm/mach-lpc32xx/serial.c @@ -118,6 +118,11 @@ void __init lpc32xx_serial_init(void) __raw_writel(0, LPC32XX_UART_IIR_FCR(puart)); } + /* Disable IrDA pulsing support on UART6 */ + tmp = __raw_readl(LPC32XX_UARTCTL_CTRL); + tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS; + __raw_writel(tmp, LPC32XX_UARTCTL_CTRL); + /* Disable UART5->USB transparent mode or USB won't work */ tmp = __raw_readl(LPC32XX_UARTCTL_CTRL); tmp &= ~LPC32XX_UART_U5_ROUTE_TO_USB; -- cgit v1.2.3 From df072717eb0050326f0f63eed98200412c395831 Mon Sep 17 00:00:00 2001 From: Alexandre Pereira da Silva Date: Wed, 13 Jun 2012 19:38:48 -0300 Subject: ARM: LPC32xx: Move i2s1 dma enabling to clock.c Move i2s1 dma init to be done when it's clock is enabled. Signed-off-by: Alexandre Pereira da Silva Signed-off-by: Roland Stigge --- arch/arm/mach-lpc32xx/clock.c | 3 ++- arch/arm/mach-lpc32xx/phy3250.c | 5 ----- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index 963d12a9fc3d..e8d315e6db09 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c @@ -718,7 +718,8 @@ static struct clk clk_i2s1 = { .parent = &clk_hclk, .enable = local_onoff_enable, .enable_reg = LPC32XX_CLKPWR_I2S_CLK_CTRL, - .enable_mask = LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN, + .enable_mask = LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN | + LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA, .get_rate = local_return_parent_rate, }; diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index eb22fbf029ea..c1aabfcbde49 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -260,11 +260,6 @@ static void __init lpc3250_machine_init(void) LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE; __raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL); - /* Enable DMA for I2S1 channel */ - tmp = __raw_readl(LPC32XX_CLKPWR_I2S_CLK_CTRL); - tmp = LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA; - __raw_writel(tmp, LPC32XX_CLKPWR_I2S_CLK_CTRL); - lpc32xx_serial_init(); tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL); -- cgit v1.2.3 From f28fa729149c8b39699f7995ce5fff34c5145a9d Mon Sep 17 00:00:00 2001 From: Kautuk Consul Date: Thu, 14 Jun 2012 13:11:37 -0700 Subject: [IA64] Port OOM changes to ia64_do_page_fault Commit d065bd810b6deb67d4897a14bfe21f8eb526ba99 (mm: retry page fault when blocking on disk transfer) and commit 37b23e0525d393d48a7d59f870b3bc061a30ccdb (x86,mm: make pagefault killable) The above commits introduced changes into the x86 pagefault handler for making the page fault handler retryable as well as killable. These changes reduce the mmap_sem hold time, which is crucial during OOM killer invocation. Port these changes to ia64. Signed-off-by: Kautuk Consul Signed-off-by: Tony Luck --- arch/ia64/mm/fault.c | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index 02d29c2a132a..8443daf4f515 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c @@ -72,6 +72,10 @@ mapped_kernel_page_is_present (unsigned long address) return pte_present(pte); } +# define VM_READ_BIT 0 +# define VM_WRITE_BIT 1 +# define VM_EXEC_BIT 2 + void __kprobes ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs) { @@ -81,6 +85,12 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re struct siginfo si; unsigned long mask; int fault; + unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; + + mask = ((((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT) + | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)); + + flags |= ((mask & VM_WRITE) ? FAULT_FLAG_WRITE : 0); /* mmap_sem is performance critical.... */ prefetchw(&mm->mmap_sem); @@ -109,6 +119,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re if (notify_page_fault(regs, TRAP_BRKPT)) return; +retry: down_read(&mm->mmap_sem); vma = find_vma_prev(mm, address, &prev_vma); @@ -130,10 +141,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re /* OK, we've got a good vm_area for this memory area. Check the access permissions: */ -# define VM_READ_BIT 0 -# define VM_WRITE_BIT 1 -# define VM_EXEC_BIT 2 - # if (((1 << VM_READ_BIT) != VM_READ || (1 << VM_WRITE_BIT) != VM_WRITE) \ || (1 << VM_EXEC_BIT) != VM_EXEC) # error File is out of sync with . Please update. @@ -142,9 +149,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re if (((isr >> IA64_ISR_R_BIT) & 1UL) && (!(vma->vm_flags & (VM_READ | VM_WRITE)))) goto bad_area; - mask = ( (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT) - | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)); - if ((vma->vm_flags & mask) != mask) goto bad_area; @@ -153,7 +157,11 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re * sure we exit gracefully rather than endlessly redo the * fault. */ - fault = handle_mm_fault(mm, vma, address, (mask & VM_WRITE) ? FAULT_FLAG_WRITE : 0); + fault = handle_mm_fault(mm, vma, address, flags); + + if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) + return; + if (unlikely(fault & VM_FAULT_ERROR)) { /* * We ran out of memory, or some other thing happened @@ -168,10 +176,24 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re } BUG(); } - if (fault & VM_FAULT_MAJOR) - current->maj_flt++; - else - current->min_flt++; + + if (flags & FAULT_FLAG_ALLOW_RETRY) { + if (fault & VM_FAULT_MAJOR) + current->maj_flt++; + else + current->min_flt++; + if (fault & VM_FAULT_RETRY) { + flags &= ~FAULT_FLAG_ALLOW_RETRY; + + /* No need to up_read(&mm->mmap_sem) as we would + * have already released it in __lock_page_or_retry + * in mm/filemap.c. + */ + + goto retry; + } + } + up_read(&mm->mmap_sem); return; -- cgit v1.2.3 From 0b91f45b23cb73ce11acdc3cf4c6efd4441e3b3e Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 14 Jun 2012 18:07:15 -0700 Subject: x86, compat: Use test_thread_flag(TIF_IA32) in compat signal delivery Signal delivery compat path may not have the 'TS_COMPAT' flag (that flag indicates how we entered the kernel). So use test_thread_flag(TIF_IA32) instead of is_ia32_task(): one of the functions of TIF_IA32 is just what kind of signal frame we want. Signed-off-by: Suresh Siddha Link: http://lkml.kernel.org/r/1339722435.3475.57.camel@sbsiddha-desk.sc.intel.com Cc: stable@kernel.org # v3.4 Signed-off-by: H. Peter Anvin --- arch/x86/ia32/ia32_signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index daeca56211e3..673ac9b63d6b 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -38,7 +38,7 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) { int err = 0; - bool ia32 = is_ia32_task(); + bool ia32 = test_thread_flag(TIF_IA32); if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) return -EFAULT; -- cgit v1.2.3 From 3e386565e14175c57dee50281613c4bd1865f5d3 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 8 Jun 2012 12:04:50 +0200 Subject: ARM: imx27/dt: make dt_compat entry const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/imx27-dt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c index eee0cc8d92a4..52efe4d5149b 100644 --- a/arch/arm/mach-imx/imx27-dt.c +++ b/arch/arm/mach-imx/imx27-dt.c @@ -75,7 +75,7 @@ static struct sys_timer imx27_timer = { .init = imx27_timer_init, }; -static const char *imx27_dt_board_compat[] __initdata = { +static const char * const imx27_dt_board_compat[] __initconst = { "fsl,imx27", NULL }; -- cgit v1.2.3 From d48daf37a3d2e2b28a61e615c0fc538301edb0dd Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Thu, 14 Jun 2012 18:43:08 +0300 Subject: x86/vsmp: Fix linker error when CONFIG_PROC_FS is not set set_vsmp_pv_ops() references no_irq_affinity which is undeclared if CONFIG_PROC_FS isn't set. Fix this by adding an #ifdef around this variable's access. Reported-by: Fengguang Wu Signed-off-by: Ido Yariv Acked-by: Shai Fultheim Link: http://lkml.kernel.org/r/1339688588-12674-1-git-send-email-ido@wizery.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/vsmp_64.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c index 6b96a7374f94..3f0285ac00fa 100644 --- a/arch/x86/kernel/vsmp_64.c +++ b/arch/x86/kernel/vsmp_64.c @@ -101,7 +101,10 @@ static void __init set_vsmp_pv_ops(void) #ifdef CONFIG_SMP if (cap & ctl & BIT(8)) { ctl &= ~BIT(8); +#ifdef CONFIG_PROC_FS + /* Don't let users change irq affinity via procfs */ no_irq_affinity = 1; +#endif } #endif -- cgit v1.2.3 From 7eb9ae0799b1e9f0b77733b432bc5f6f055b020b Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 14 Jun 2012 18:28:49 -0700 Subject: irq/apic: Use config_enabled(CONFIG_SMP) checks to clean up irq_set_affinity() for UP Move the ->irq_set_affinity() routines out of the #ifdef CONFIG_SMP sections and use config_enabled(CONFIG_SMP) checks inside those routines. Thus making those routines simple null stubs for !CONFIG_SMP and retaining those routines with no additional runtime overhead for CONFIG_SMP kernels. Cleans up the ifdef CONFIG_SMP in and around routines related to irq_set_affinity in io_apic and irq_remapping subsystems. Signed-off-by: Suresh Siddha Cc: torvalds@linux-foundation.org Cc: joerg.roedel@amd.com Cc: Sam Ravnborg Cc: Paul Gortmaker Link: http://lkml.kernel.org/r/1339723729.3475.63.camel@sbsiddha-desk.sc.intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic/io_apic.c | 180 ++++++++++++++++-------------------- drivers/iommu/intel_irq_remapping.c | 7 +- drivers/iommu/irq_remapping.c | 5 +- drivers/iommu/irq_remapping.h | 2 - include/linux/irq.h | 2 - 5 files changed, 86 insertions(+), 110 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 7cbd397884f5..a951ef7decb1 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2224,81 +2224,6 @@ void send_cleanup_vector(struct irq_cfg *cfg) cfg->move_in_progress = 0; } -static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg) -{ - int apic, pin; - struct irq_pin_list *entry; - u8 vector = cfg->vector; - - for_each_irq_pin(entry, cfg->irq_2_pin) { - unsigned int reg; - - apic = entry->apic; - pin = entry->pin; - /* - * With interrupt-remapping, destination information comes - * from interrupt-remapping table entry. - */ - if (!irq_remapped(cfg)) - io_apic_write(apic, 0x11 + pin*2, dest); - reg = io_apic_read(apic, 0x10 + pin*2); - reg &= ~IO_APIC_REDIR_VECTOR_MASK; - reg |= vector; - io_apic_modify(apic, 0x10 + pin*2, reg); - } -} - -/* - * Either sets data->affinity to a valid value, and returns - * ->cpu_mask_to_apicid of that in dest_id, or returns -1 and - * leaves data->affinity untouched. - */ -int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, - unsigned int *dest_id) -{ - struct irq_cfg *cfg = data->chip_data; - unsigned int irq = data->irq; - int err; - - if (!cpumask_intersects(mask, cpu_online_mask)) - return -EINVAL; - - err = assign_irq_vector(irq, cfg, mask); - if (err) - return err; - - err = apic->cpu_mask_to_apicid_and(mask, cfg->domain, dest_id); - if (err) { - if (assign_irq_vector(irq, cfg, data->affinity)) - pr_err("Failed to recover vector for irq %d\n", irq); - return err; - } - - cpumask_copy(data->affinity, mask); - - return 0; -} - -static int -ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, - bool force) -{ - unsigned int dest, irq = data->irq; - unsigned long flags; - int ret; - - raw_spin_lock_irqsave(&ioapic_lock, flags); - ret = __ioapic_set_affinity(data, mask, &dest); - if (!ret) { - /* Only the high 8 bits are valid. */ - dest = SET_APIC_LOGICAL_ID(dest); - __target_IO_APIC_irq(irq, dest, data->chip_data); - ret = IRQ_SET_MASK_OK_NOCOPY; - } - raw_spin_unlock_irqrestore(&ioapic_lock, flags); - return ret; -} - asmlinkage void smp_irq_move_cleanup_interrupt(void) { unsigned vector, me; @@ -2386,6 +2311,87 @@ void irq_force_complete_move(int irq) static inline void irq_complete_move(struct irq_cfg *cfg) { } #endif +static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg) +{ + int apic, pin; + struct irq_pin_list *entry; + u8 vector = cfg->vector; + + for_each_irq_pin(entry, cfg->irq_2_pin) { + unsigned int reg; + + apic = entry->apic; + pin = entry->pin; + /* + * With interrupt-remapping, destination information comes + * from interrupt-remapping table entry. + */ + if (!irq_remapped(cfg)) + io_apic_write(apic, 0x11 + pin*2, dest); + reg = io_apic_read(apic, 0x10 + pin*2); + reg &= ~IO_APIC_REDIR_VECTOR_MASK; + reg |= vector; + io_apic_modify(apic, 0x10 + pin*2, reg); + } +} + +/* + * Either sets data->affinity to a valid value, and returns + * ->cpu_mask_to_apicid of that in dest_id, or returns -1 and + * leaves data->affinity untouched. + */ +int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, + unsigned int *dest_id) +{ + struct irq_cfg *cfg = data->chip_data; + unsigned int irq = data->irq; + int err; + + if (!config_enabled(CONFIG_SMP)) + return -1; + + if (!cpumask_intersects(mask, cpu_online_mask)) + return -EINVAL; + + err = assign_irq_vector(irq, cfg, mask); + if (err) + return err; + + err = apic->cpu_mask_to_apicid_and(mask, cfg->domain, dest_id); + if (err) { + if (assign_irq_vector(irq, cfg, data->affinity)) + pr_err("Failed to recover vector for irq %d\n", irq); + return err; + } + + cpumask_copy(data->affinity, mask); + + return 0; +} + +static int +ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, + bool force) +{ + unsigned int dest, irq = data->irq; + unsigned long flags; + int ret; + + if (!config_enabled(CONFIG_SMP)) + return -1; + + raw_spin_lock_irqsave(&ioapic_lock, flags); + ret = __ioapic_set_affinity(data, mask, &dest); + if (!ret) { + /* Only the high 8 bits are valid. */ + dest = SET_APIC_LOGICAL_ID(dest); + __target_IO_APIC_irq(irq, dest, data->chip_data); + ret = IRQ_SET_MASK_OK_NOCOPY; + } + raw_spin_unlock_irqrestore(&ioapic_lock, flags); + return ret; +} + static void ack_apic_edge(struct irq_data *data) { irq_complete_move(data->chip_data); @@ -2565,9 +2571,7 @@ static void irq_remap_modify_chip_defaults(struct irq_chip *chip) chip->irq_ack = ir_ack_apic_edge; chip->irq_eoi = ir_ack_apic_level; -#ifdef CONFIG_SMP chip->irq_set_affinity = set_remapped_irq_affinity; -#endif } #endif /* CONFIG_IRQ_REMAP */ @@ -2578,9 +2582,7 @@ static struct irq_chip ioapic_chip __read_mostly = { .irq_unmask = unmask_ioapic_irq, .irq_ack = ack_apic_edge, .irq_eoi = ack_apic_level, -#ifdef CONFIG_SMP .irq_set_affinity = ioapic_set_affinity, -#endif .irq_retrigger = ioapic_retrigger_irq, }; @@ -3099,7 +3101,6 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, return err; } -#ifdef CONFIG_SMP static int msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) { @@ -3121,7 +3122,6 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) return IRQ_SET_MASK_OK_NOCOPY; } -#endif /* CONFIG_SMP */ /* * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices, @@ -3132,9 +3132,7 @@ static struct irq_chip msi_chip = { .irq_unmask = unmask_msi_irq, .irq_mask = mask_msi_irq, .irq_ack = ack_apic_edge, -#ifdef CONFIG_SMP .irq_set_affinity = msi_set_affinity, -#endif .irq_retrigger = ioapic_retrigger_irq, }; @@ -3219,7 +3217,6 @@ void native_teardown_msi_irq(unsigned int irq) } #ifdef CONFIG_DMAR_TABLE -#ifdef CONFIG_SMP static int dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) @@ -3244,16 +3241,12 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask, return IRQ_SET_MASK_OK_NOCOPY; } -#endif /* CONFIG_SMP */ - static struct irq_chip dmar_msi_type = { .name = "DMAR_MSI", .irq_unmask = dmar_msi_unmask, .irq_mask = dmar_msi_mask, .irq_ack = ack_apic_edge, -#ifdef CONFIG_SMP .irq_set_affinity = dmar_msi_set_affinity, -#endif .irq_retrigger = ioapic_retrigger_irq, }; @@ -3274,7 +3267,6 @@ int arch_setup_dmar_msi(unsigned int irq) #ifdef CONFIG_HPET_TIMER -#ifdef CONFIG_SMP static int hpet_msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) { @@ -3297,16 +3289,12 @@ static int hpet_msi_set_affinity(struct irq_data *data, return IRQ_SET_MASK_OK_NOCOPY; } -#endif /* CONFIG_SMP */ - static struct irq_chip hpet_msi_type = { .name = "HPET_MSI", .irq_unmask = hpet_msi_unmask, .irq_mask = hpet_msi_mask, .irq_ack = ack_apic_edge, -#ifdef CONFIG_SMP .irq_set_affinity = hpet_msi_set_affinity, -#endif .irq_retrigger = ioapic_retrigger_irq, }; @@ -3341,8 +3329,6 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id) */ #ifdef CONFIG_HT_IRQ -#ifdef CONFIG_SMP - static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector) { struct ht_irq_msg msg; @@ -3370,16 +3356,12 @@ ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) return IRQ_SET_MASK_OK_NOCOPY; } -#endif - static struct irq_chip ht_irq_chip = { .name = "PCI-HT", .irq_mask = mask_ht_irq, .irq_unmask = unmask_ht_irq, .irq_ack = ack_apic_edge, -#ifdef CONFIG_SMP .irq_set_affinity = ht_set_affinity, -#endif .irq_retrigger = ioapic_retrigger_irq, }; diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 853902a1b7db..e0b18f3ae9a8 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -902,7 +902,6 @@ static int intel_setup_ioapic_entry(int irq, return 0; } -#ifdef CONFIG_SMP /* * Migrate the IO-APIC irq in the presence of intr-remapping. * @@ -926,6 +925,9 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, struct irte irte; int err; + if (!config_enabled(CONFIG_SMP)) + return -EINVAL; + if (!cpumask_intersects(mask, cpu_online_mask)) return -EINVAL; @@ -963,7 +965,6 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, cpumask_copy(data->affinity, mask); return 0; } -#endif static void intel_compose_msi_msg(struct pci_dev *pdev, unsigned int irq, unsigned int dest, @@ -1065,9 +1066,7 @@ struct irq_remap_ops intel_irq_remap_ops = { .reenable = reenable_irq_remapping, .enable_faulting = enable_drhd_fault_handling, .setup_ioapic_entry = intel_setup_ioapic_entry, -#ifdef CONFIG_SMP .set_affinity = intel_ioapic_set_affinity, -#endif .free_irq = free_irte, .compose_msi_msg = intel_compose_msi_msg, .msi_alloc_irq = intel_msi_alloc_irq, diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 40cda8e98d87..1d29b1c66e72 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -111,16 +111,15 @@ int setup_ioapic_remapped_entry(int irq, vector, attr); } -#ifdef CONFIG_SMP int set_remapped_irq_affinity(struct irq_data *data, const struct cpumask *mask, bool force) { - if (!remap_ops || !remap_ops->set_affinity) + if (!config_enabled(CONFIG_SMP) || !remap_ops || + !remap_ops->set_affinity) return 0; return remap_ops->set_affinity(data, mask, force); } -#endif void free_remapped_irq(int irq) { diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h index be9d72950c51..b12974cc1dfe 100644 --- a/drivers/iommu/irq_remapping.h +++ b/drivers/iommu/irq_remapping.h @@ -59,11 +59,9 @@ struct irq_remap_ops { unsigned int, int, struct io_apic_irq_attr *); -#ifdef CONFIG_SMP /* Set the CPU affinity of a remapped interrupt */ int (*set_affinity)(struct irq_data *data, const struct cpumask *mask, bool force); -#endif /* Free an IRQ */ int (*free_irq)(int); diff --git a/include/linux/irq.h b/include/linux/irq.h index 61f5cec031e0..47a937cd84af 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -150,9 +150,7 @@ struct irq_data { void *handler_data; void *chip_data; struct msi_desc *msi_desc; -#ifdef CONFIG_SMP cpumask_var_t affinity; -#endif }; /* -- cgit v1.2.3 From e2ae715d66bf4becfb85eb84b7150e23cf27df30 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Fri, 15 Jun 2012 14:07:51 +0200 Subject: kmsg - kmsg_dump() use iterator to receive log buffer content Provide an iterator to receive the log buffer content, and convert all kmsg_dump() users to it. The structured data in the kmsg buffer now contains binary data, which should no longer be copied verbatim to the kmsg_dump() users. The iterator should provide reliable access to the buffer data, and also supports proper log line-aware chunking of data while iterating. Signed-off-by: Kay Sievers Tested-by: Tony Luck Reported-by: Anton Vorontsov Tested-by: Anton Vorontsov Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/pseries/nvram.c | 61 +------- arch/x86/platform/mrst/early_printk_mrst.c | 13 +- drivers/mtd/mtdoops.c | 22 +-- fs/pstore/platform.c | 34 ++--- include/linux/kmsg_dump.h | 45 +++++- kernel/printk.c | 220 +++++++++++++++++++++++++---- 6 files changed, 258 insertions(+), 137 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 36f957f31842..8733a86ad52e 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c @@ -68,9 +68,7 @@ static const char *pseries_nvram_os_partitions[] = { }; static void oops_to_nvram(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason, - const char *old_msgs, unsigned long old_len, - const char *new_msgs, unsigned long new_len); + enum kmsg_dump_reason reason); static struct kmsg_dumper nvram_kmsg_dumper = { .dump = oops_to_nvram @@ -503,28 +501,6 @@ int __init pSeries_nvram_init(void) return 0; } -/* - * Try to capture the last capture_len bytes of the printk buffer. Return - * the amount actually captured. - */ -static size_t capture_last_msgs(const char *old_msgs, size_t old_len, - const char *new_msgs, size_t new_len, - char *captured, size_t capture_len) -{ - if (new_len >= capture_len) { - memcpy(captured, new_msgs + (new_len - capture_len), - capture_len); - return capture_len; - } else { - /* Grab the end of old_msgs. */ - size_t old_tail_len = min(old_len, capture_len - new_len); - memcpy(captured, old_msgs + (old_len - old_tail_len), - old_tail_len); - memcpy(captured + old_tail_len, new_msgs, new_len); - return old_tail_len + new_len; - } -} - /* * Are we using the ibm,rtas-log for oops/panic reports? And if so, * would logging this oops/panic overwrite an RTAS event that rtas_errd @@ -541,27 +517,6 @@ static int clobbering_unread_rtas_event(void) NVRAM_RTAS_READ_TIMEOUT); } -/* Squeeze out each line's severity prefix. */ -static size_t elide_severities(char *buf, size_t len) -{ - char *in, *out, *buf_end = buf + len; - /* Assume a at the very beginning marks the start of a line. */ - int newline = 1; - - in = out = buf; - while (in < buf_end) { - if (newline && in+3 <= buf_end && - *in == '<' && isdigit(in[1]) && in[2] == '>') { - in += 3; - newline = 0; - } else { - newline = (*in == '\n'); - *out++ = *in++; - } - } - return out - buf; -} - /* Derived from logfs_compress() */ static int nvram_compress(const void *in, void *out, size_t inlen, size_t outlen) @@ -619,9 +574,7 @@ static int zip_oops(size_t text_len) * partition. If that's too much, go back and capture uncompressed text. */ static void oops_to_nvram(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason, - const char *old_msgs, unsigned long old_len, - const char *new_msgs, unsigned long new_len) + enum kmsg_dump_reason reason) { static unsigned int oops_count = 0; static bool panicking = false; @@ -660,14 +613,14 @@ static void oops_to_nvram(struct kmsg_dumper *dumper, return; if (big_oops_buf) { - text_len = capture_last_msgs(old_msgs, old_len, - new_msgs, new_len, big_oops_buf, big_oops_buf_sz); - text_len = elide_severities(big_oops_buf, text_len); + kmsg_dump_get_buffer(dumper, false, + big_oops_buf, big_oops_buf_sz, &text_len); rc = zip_oops(text_len); } if (rc != 0) { - text_len = capture_last_msgs(old_msgs, old_len, - new_msgs, new_len, oops_data, oops_data_sz); + kmsg_dump_rewind(dumper); + kmsg_dump_get_buffer(dumper, true, + oops_data, oops_data_sz, &text_len); err_type = ERR_TYPE_KERNEL_PANIC; *oops_len = (u16) text_len; } diff --git a/arch/x86/platform/mrst/early_printk_mrst.c b/arch/x86/platform/mrst/early_printk_mrst.c index 3c6e328483c7..028454f0c3a5 100644 --- a/arch/x86/platform/mrst/early_printk_mrst.c +++ b/arch/x86/platform/mrst/early_printk_mrst.c @@ -110,19 +110,16 @@ static struct kmsg_dumper dw_dumper; static int dumper_registered; static void dw_kmsg_dump(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason, - const char *s1, unsigned long l1, - const char *s2, unsigned long l2) + enum kmsg_dump_reason reason) { - int i; + static char line[1024]; + size_t len; /* When run to this, we'd better re-init the HW */ mrst_early_console_init(); - for (i = 0; i < l1; i++) - early_mrst_console.write(&early_mrst_console, s1 + i, 1); - for (i = 0; i < l2; i++) - early_mrst_console.write(&early_mrst_console, s2 + i, 1); + while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len)) + early_mrst_console.write(&early_mrst_console, line, len); } /* Set the ratio rate to 115200, 8n1, IRQ disabled */ diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index ae36d7e1e913..551e316e4454 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c @@ -304,32 +304,17 @@ static void find_next_position(struct mtdoops_context *cxt) } static void mtdoops_do_dump(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason, const char *s1, unsigned long l1, - const char *s2, unsigned long l2) + enum kmsg_dump_reason reason) { struct mtdoops_context *cxt = container_of(dumper, struct mtdoops_context, dump); - unsigned long s1_start, s2_start; - unsigned long l1_cpy, l2_cpy; - char *dst; - - if (reason != KMSG_DUMP_OOPS && - reason != KMSG_DUMP_PANIC) - return; /* Only dump oopses if dump_oops is set */ if (reason == KMSG_DUMP_OOPS && !dump_oops) return; - dst = cxt->oops_buf + MTDOOPS_HEADER_SIZE; /* Skip the header */ - l2_cpy = min(l2, record_size - MTDOOPS_HEADER_SIZE); - l1_cpy = min(l1, record_size - MTDOOPS_HEADER_SIZE - l2_cpy); - - s2_start = l2 - l2_cpy; - s1_start = l1 - l1_cpy; - - memcpy(dst, s1 + s1_start, l1_cpy); - memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy); + kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE, + record_size - MTDOOPS_HEADER_SIZE, NULL); /* Panics must be written immediately */ if (reason != KMSG_DUMP_OOPS) @@ -375,6 +360,7 @@ static void mtdoops_notify_add(struct mtd_info *mtd) return; } + cxt->dump.max_reason = KMSG_DUMP_OOPS; cxt->dump.dump = mtdoops_do_dump; err = kmsg_dump_register(&cxt->dump); if (err) { diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 82c585f715e3..03ce7a9b81cc 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -94,20 +94,15 @@ static const char *get_reason_str(enum kmsg_dump_reason reason) * as we can from the end of the buffer. */ static void pstore_dump(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason, - const char *s1, unsigned long l1, - const char *s2, unsigned long l2) + enum kmsg_dump_reason reason) { - unsigned long s1_start, s2_start; - unsigned long l1_cpy, l2_cpy; - unsigned long size, total = 0; - char *dst; + unsigned long total = 0; const char *why; u64 id; - int hsize, ret; unsigned int part = 1; unsigned long flags = 0; int is_locked = 0; + int ret; why = get_reason_str(reason); @@ -119,30 +114,25 @@ static void pstore_dump(struct kmsg_dumper *dumper, spin_lock_irqsave(&psinfo->buf_lock, flags); oopscount++; while (total < kmsg_bytes) { + char *dst; + unsigned long size; + int hsize; + size_t len; + dst = psinfo->buf; hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part); size = psinfo->bufsize - hsize; dst += hsize; - l2_cpy = min(l2, size); - l1_cpy = min(l1, size - l2_cpy); - - if (l1_cpy + l2_cpy == 0) + if (!kmsg_dump_get_buffer(dumper, true, dst, size, &len)) break; - s2_start = l2 - l2_cpy; - s1_start = l1 - l1_cpy; - - memcpy(dst, s1 + s1_start, l1_cpy); - memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy); - ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part, - hsize + l1_cpy + l2_cpy, psinfo); + hsize + len, psinfo); if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted()) pstore_new_entry = 1; - l1 -= l1_cpy; - l2 -= l2_cpy; - total += l1_cpy + l2_cpy; + + total += hsize + len; part++; } if (in_nmi()) { diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h index 35f7237ec972..af4eb5a39d9a 100644 --- a/include/linux/kmsg_dump.h +++ b/include/linux/kmsg_dump.h @@ -21,6 +21,7 @@ * is passed to the kernel. */ enum kmsg_dump_reason { + KMSG_DUMP_UNDEF, KMSG_DUMP_PANIC, KMSG_DUMP_OOPS, KMSG_DUMP_EMERG, @@ -31,23 +32,37 @@ enum kmsg_dump_reason { /** * struct kmsg_dumper - kernel crash message dumper structure - * @dump: The callback which gets called on crashes. The buffer is passed - * as two sections, where s1 (length l1) contains the older - * messages and s2 (length l2) contains the newer. * @list: Entry in the dumper list (private) + * @dump: Call into dumping code which will retrieve the data with + * through the record iterator + * @max_reason: filter for highest reason number that should be dumped * @registered: Flag that specifies if this is already registered */ struct kmsg_dumper { - void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason, - const char *s1, unsigned long l1, - const char *s2, unsigned long l2); struct list_head list; - int registered; + void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason); + enum kmsg_dump_reason max_reason; + bool active; + bool registered; + + /* private state of the kmsg iterator */ + u32 cur_idx; + u32 next_idx; + u64 cur_seq; + u64 next_seq; }; #ifdef CONFIG_PRINTK void kmsg_dump(enum kmsg_dump_reason reason); +bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, + char *line, size_t size, size_t *len); + +bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, + char *buf, size_t size, size_t *len); + +void kmsg_dump_rewind(struct kmsg_dumper *dumper); + int kmsg_dump_register(struct kmsg_dumper *dumper); int kmsg_dump_unregister(struct kmsg_dumper *dumper); @@ -56,6 +71,22 @@ static inline void kmsg_dump(enum kmsg_dump_reason reason) { } +bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, + const char *line, size_t size, size_t *len) +{ + return false; +} + +bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, + char *buf, size_t size, size_t *len) +{ + return false; +} + +void kmsg_dump_rewind(struct kmsg_dumper *dumper) +{ +} + static inline int kmsg_dump_register(struct kmsg_dumper *dumper) { return -EINVAL; diff --git a/kernel/printk.c b/kernel/printk.c index f205c25c37e2..ceb4a2f775a1 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -909,7 +909,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) /* * Find first record that fits, including all following records, * into the user-provided buffer for this dump. - */ + */ seq = clear_seq; idx = clear_idx; while (seq < log_next_seq) { @@ -919,6 +919,8 @@ static int syslog_print_all(char __user *buf, int size, bool clear) idx = log_next(idx); seq++; } + + /* move first record forward until length fits into the buffer */ seq = clear_seq; idx = clear_idx; while (len > size && seq < log_next_seq) { @@ -929,7 +931,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) seq++; } - /* last message in this dump */ + /* last message fitting into this dump */ next_seq = log_next_seq; len = 0; @@ -2300,48 +2302,210 @@ module_param_named(always_kmsg_dump, always_kmsg_dump, bool, S_IRUGO | S_IWUSR); * kmsg_dump - dump kernel log to kernel message dumpers. * @reason: the reason (oops, panic etc) for dumping * - * Iterate through each of the dump devices and call the oops/panic - * callbacks with the log buffer. + * Call each of the registered dumper's dump() callback, which can + * retrieve the kmsg records with kmsg_dump_get_line() or + * kmsg_dump_get_buffer(). */ void kmsg_dump(enum kmsg_dump_reason reason) { - u64 idx; struct kmsg_dumper *dumper; - const char *s1, *s2; - unsigned long l1, l2; unsigned long flags; if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump) return; - /* Theoretically, the log could move on after we do this, but - there's not a lot we can do about that. The new messages - will overwrite the start of what we dump. */ + rcu_read_lock(); + list_for_each_entry_rcu(dumper, &dump_list, list) { + if (dumper->max_reason && reason > dumper->max_reason) + continue; + + /* initialize iterator with data about the stored records */ + dumper->active = true; + + raw_spin_lock_irqsave(&logbuf_lock, flags); + dumper->cur_seq = clear_seq; + dumper->cur_idx = clear_idx; + dumper->next_seq = log_next_seq; + dumper->next_idx = log_next_idx; + raw_spin_unlock_irqrestore(&logbuf_lock, flags); + + /* invoke dumper which will iterate over records */ + dumper->dump(dumper, reason); + + /* reset iterator */ + dumper->active = false; + } + rcu_read_unlock(); +} + +/** + * kmsg_dump_get_line - retrieve one kmsg log line + * @dumper: registered kmsg dumper + * @syslog: include the "<4>" prefixes + * @line: buffer to copy the line to + * @size: maximum size of the buffer + * @len: length of line placed into buffer + * + * Start at the beginning of the kmsg buffer, with the oldest kmsg + * record, and copy one record into the provided buffer. + * + * Consecutive calls will return the next available record moving + * towards the end of the buffer with the youngest messages. + * + * A return value of FALSE indicates that there are no more records to + * read. + */ +bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, + char *line, size_t size, size_t *len) +{ + unsigned long flags; + struct log *msg; + size_t l = 0; + bool ret = false; + + if (!dumper->active) + goto out; raw_spin_lock_irqsave(&logbuf_lock, flags); - if (syslog_seq < log_first_seq) - idx = syslog_idx; - else - idx = log_first_idx; + if (dumper->cur_seq < log_first_seq) { + /* messages are gone, move to first available one */ + dumper->cur_seq = log_first_seq; + dumper->cur_idx = log_first_idx; + } - if (idx > log_next_idx) { - s1 = log_buf; - l1 = log_next_idx; + /* last entry */ + if (dumper->cur_seq >= log_next_seq) { + raw_spin_unlock_irqrestore(&logbuf_lock, flags); + goto out; + } - s2 = log_buf + idx; - l2 = log_buf_len - idx; - } else { - s1 = ""; - l1 = 0; + msg = log_from_idx(dumper->cur_idx); + l = msg_print_text(msg, syslog, + line, size); + + dumper->cur_idx = log_next(dumper->cur_idx); + dumper->cur_seq++; + ret = true; + raw_spin_unlock_irqrestore(&logbuf_lock, flags); +out: + if (len) + *len = l; + return ret; +} +EXPORT_SYMBOL_GPL(kmsg_dump_get_line); + +/** + * kmsg_dump_get_buffer - copy kmsg log lines + * @dumper: registered kmsg dumper + * @syslog: include the "<4>" prefixes + * @line: buffer to copy the line to + * @size: maximum size of the buffer + * @len: length of line placed into buffer + * + * Start at the end of the kmsg buffer and fill the provided buffer + * with as many of the the *youngest* kmsg records that fit into it. + * If the buffer is large enough, all available kmsg records will be + * copied with a single call. + * + * Consecutive calls will fill the buffer with the next block of + * available older records, not including the earlier retrieved ones. + * + * A return value of FALSE indicates that there are no more records to + * read. + */ +bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, + char *buf, size_t size, size_t *len) +{ + unsigned long flags; + u64 seq; + u32 idx; + u64 next_seq; + u32 next_idx; + size_t l = 0; + bool ret = false; + + if (!dumper->active) + goto out; + + raw_spin_lock_irqsave(&logbuf_lock, flags); + if (dumper->cur_seq < log_first_seq) { + /* messages are gone, move to first available one */ + dumper->cur_seq = log_first_seq; + dumper->cur_idx = log_first_idx; + } + + /* last entry */ + if (dumper->cur_seq >= dumper->next_seq) { + raw_spin_unlock_irqrestore(&logbuf_lock, flags); + goto out; + } + + /* calculate length of entire buffer */ + seq = dumper->cur_seq; + idx = dumper->cur_idx; + while (seq < dumper->next_seq) { + struct log *msg = log_from_idx(idx); + + l += msg_print_text(msg, true, NULL, 0); + idx = log_next(idx); + seq++; + } + + /* move first record forward until length fits into the buffer */ + seq = dumper->cur_seq; + idx = dumper->cur_idx; + while (l > size && seq < dumper->next_seq) { + struct log *msg = log_from_idx(idx); - s2 = log_buf + idx; - l2 = log_next_idx - idx; + l -= msg_print_text(msg, true, NULL, 0); + idx = log_next(idx); + seq++; } + + /* last message in next interation */ + next_seq = seq; + next_idx = idx; + + l = 0; + while (seq < dumper->next_seq) { + struct log *msg = log_from_idx(idx); + + l += msg_print_text(msg, syslog, + buf + l, size - l); + + idx = log_next(idx); + seq++; + } + + dumper->next_seq = next_seq; + dumper->next_idx = next_idx; + ret = true; raw_spin_unlock_irqrestore(&logbuf_lock, flags); +out: + if (len) + *len = l; + return ret; +} +EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); - rcu_read_lock(); - list_for_each_entry_rcu(dumper, &dump_list, list) - dumper->dump(dumper, reason, s1, l1, s2, l2); - rcu_read_unlock(); +/** + * kmsg_dump_rewind - reset the interator + * @dumper: registered kmsg dumper + * + * Reset the dumper's iterator so that kmsg_dump_get_line() and + * kmsg_dump_get_buffer() can be called again and used multiple + * times within the same dumper.dump() callback. + */ +void kmsg_dump_rewind(struct kmsg_dumper *dumper) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&logbuf_lock, flags); + dumper->cur_seq = clear_seq; + dumper->cur_idx = clear_idx; + dumper->next_seq = log_next_seq; + dumper->next_idx = log_next_idx; + raw_spin_unlock_irqrestore(&logbuf_lock, flags); } +EXPORT_SYMBOL_GPL(kmsg_dump_rewind); #endif -- cgit v1.2.3 From 60cd4dba9b75da175c79d0dc6d7beb8701307ff8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 15 Jun 2012 16:38:23 -0600 Subject: sparc/PCI: remove unused pcibios_assign_resource() definition pcibios_assign_resource() isn't used anywhere; remove it. Signed-off-by: Bjorn Helgaas --- arch/sparc/kernel/pcic.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index ded3f6090c3f..46ba84998f16 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -884,11 +884,6 @@ void __init sun4m_pci_init_IRQ(void) sparc_config.load_profile_irq = pcic_load_profile_irq; } -int pcibios_assign_resource(struct pci_dev *pdev, int resource) -{ - return -ENXIO; -} - /* * This probably belongs here rather than ioport.c because * we do not want this crud linked into SBus kernels. -- cgit v1.2.3 From 667d1b48bcb66b89776ebefbaf05b358bc5907ce Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 15 Jun 2012 16:49:58 +0100 Subject: ARM: 7425/1: extable: ensure fixup entries are 4-byte aligned Fixup entries in the kernel exception tables should be 4-byte aligned since we return directly to them when handling a faulting instruction in the kernel. This patch adds the missing align directives to the fixup entries. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/futex.h | 1 + arch/arm/kernel/entry-armv.S | 1 + 2 files changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h index 7be54690aeec..e42cf597f6e6 100644 --- a/arch/arm/include/asm/futex.h +++ b/arch/arm/include/asm/futex.h @@ -19,6 +19,7 @@ " .long 1b, 4f, 2b, 4f\n" \ " .popsection\n" \ " .pushsection .fixup,\"ax\"\n" \ + " .align 2\n" \ "4: mov %0, " err_reg "\n" \ " b 3b\n" \ " .popsection" diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 437f0c426517..0d1851ca6eb9 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -495,6 +495,7 @@ ENDPROC(__und_usr) * The out of line fixup for the ldrt above. */ .pushsection .fixup, "ax" + .align 2 4: mov pc, r9 .popsection .pushsection __ex_table,"a" -- cgit v1.2.3 From 492bf4f25a1c8e87a6abb0e2edaa532b7fd43b29 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:24 +0200 Subject: powerpc/PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Cc: Kumar Gala Cc: Paul Mackerras Acked-by: Benjamin Herrenschmidt Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- arch/powerpc/platforms/85xx/tqm85xx.c | 2 +- arch/powerpc/platforms/86xx/gef_ppc9a.c | 2 +- arch/powerpc/platforms/86xx/gef_sbc310.c | 2 +- arch/powerpc/platforms/86xx/gef_sbc610.c | 2 +- arch/powerpc/sysdev/fsl_pci.c | 2 +- arch/powerpc/sysdev/mv64x60_pci.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c index 4d786c25d3e5..3e70a2035e53 100644 --- a/arch/powerpc/platforms/85xx/tqm85xx.c +++ b/arch/powerpc/platforms/85xx/tqm85xx.c @@ -102,7 +102,7 @@ static void tqm85xx_show_cpuinfo(struct seq_file *m) seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); } -static void __init tqm85xx_ti1520_fixup(struct pci_dev *pdev) +static void __devinit tqm85xx_ti1520_fixup(struct pci_dev *pdev) { unsigned int val; diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c index 1fca663f1b25..563aafa8629c 100644 --- a/arch/powerpc/platforms/86xx/gef_ppc9a.c +++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c @@ -164,7 +164,7 @@ static void gef_ppc9a_show_cpuinfo(struct seq_file *m) gef_ppc9a_get_vme_is_syscon() ? "yes" : "no"); } -static void __init gef_ppc9a_nec_fixup(struct pci_dev *pdev) +static void __devinit gef_ppc9a_nec_fixup(struct pci_dev *pdev) { unsigned int val; diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c index 14e0e576bcbd..cc6a91ae0889 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc310.c +++ b/arch/powerpc/platforms/86xx/gef_sbc310.c @@ -152,7 +152,7 @@ static void gef_sbc310_show_cpuinfo(struct seq_file *m) } -static void __init gef_sbc310_nec_fixup(struct pci_dev *pdev) +static void __devinit gef_sbc310_nec_fixup(struct pci_dev *pdev) { unsigned int val; diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c index 1638f43599f0..aead6b337f4a 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc610.c +++ b/arch/powerpc/platforms/86xx/gef_sbc610.c @@ -141,7 +141,7 @@ static void gef_sbc610_show_cpuinfo(struct seq_file *m) seq_printf(m, "SVR\t\t: 0x%x\n", svid); } -static void __init gef_sbc610_nec_fixup(struct pci_dev *pdev) +static void __devinit gef_sbc610_nec_fixup(struct pci_dev *pdev) { unsigned int val; diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 6073288fed29..edbf79465d50 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -36,7 +36,7 @@ static int fsl_pcie_bus_fixup, is_mpc83xx_pci; -static void __init quirk_fsl_pcie_header(struct pci_dev *dev) +static void __devinit quirk_fsl_pcie_header(struct pci_dev *dev) { u8 progif; diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c index b0037cefaada..364b14d4754b 100644 --- a/arch/powerpc/sysdev/mv64x60_pci.c +++ b/arch/powerpc/sysdev/mv64x60_pci.c @@ -104,7 +104,7 @@ subsys_initcall(mv64x60_sysfs_init); #endif /* CONFIG_SYSFS */ -static void __init mv64x60_pci_fixup_early(struct pci_dev *dev) +static void __devinit mv64x60_pci_fixup_early(struct pci_dev *dev) { /* * Set the host bridge hdr_type to an invalid value so that -- cgit v1.2.3 From 1359bac229637cd9e317f6069e5fb3544d64b7ca Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 3 Jun 2012 20:48:25 +0200 Subject: sh/PCI: move fixup hooks from __init to __devinit The fixups are executed once the pci-device is found which is during boot process so __init seems fine as long as the platform does not support hotplug. However it is possible to remove the PCI bus at run time and have it rediscovered again via "echo 1 > /sys/bus/pci/rescan" and this will call the fixups again. Cc: Paul Mundt Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas --- arch/sh/drivers/pci/fixups-dreamcast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c index edeea8960c30..a5fe1b54c952 100644 --- a/arch/sh/drivers/pci/fixups-dreamcast.c +++ b/arch/sh/drivers/pci/fixups-dreamcast.c @@ -28,7 +28,7 @@ #include #include -static void __init gapspci_fixup_resources(struct pci_dev *dev) +static void __devinit gapspci_fixup_resources(struct pci_dev *dev) { struct pci_channel *p = dev->sysdata; -- cgit v1.2.3 From 9b0f7e399238c61f28539daeb65d72a8d7f91966 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 11 Jun 2012 09:03:58 -0500 Subject: arm: versatile: fix and enable PCI I/O space With commit 4d5fc58dbe34b (ARM: remove bunch of now unused mach/io.h files), the I/O space setup was completely broken on versatile. This patch fixes that and prepares for further I/O space clean-up. I/O space handling on the versatile platform is currently broken in multiple ways. Most importantly, the ports do not get mapped into the virtual address space at all. Also, there is some amount of confusion between PCI I/O space and other statically mapped MMIO registers in the platform code: * The __io_address() macro that is used to access the platform register maps to the same __io macro that gets used for I/O space. * The IO_SPACE_LIMIT is set to a value that is much larger than the total available space. * The I/O resource of the PCI bus is set to the physical address of the mapping, which is way outside of the actual I/O space limit as well as the address range that gets decoded by traditional PCI cards. * No attempt is made to stay outside of the ISA port range that some device drivers try access. * No resource gets requested as a child of ioport_resource, but an IORESOURCE_IO type mapping gets requested as a child of iomem_resource. This patch attempts to correct all of the above. This makes it possible to use virtio-pci based virtual devices as well as actual PCI cards including those with legacy ISA port ranges like VGA. Some of the issues seem to be duplicated on other platforms. Signed-off-by: Arnd Bergmann [rob: update to 3.5-rc2 and io.h cleanup related changes] Signed-off-by: Rob Herring Tested-by: Robert Schwebel Signed-off-by: Olof Johansson --- arch/arm/Kconfig | 1 + arch/arm/mach-versatile/core.c | 19 +++-------------- arch/arm/mach-versatile/include/mach/hardware.h | 3 ++- arch/arm/mach-versatile/include/mach/io.h | 27 +++++++++++++++++++++++++ arch/arm/mach-versatile/pci.c | 18 +++++++++++++++-- 5 files changed, 49 insertions(+), 19 deletions(-) create mode 100644 arch/arm/mach-versatile/include/mach/io.h (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b649c5904a4f..567b4323c9e6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -294,6 +294,7 @@ config ARCH_VERSATILE select ICST select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB + select NEED_MACH_IO_H if PCI select PLAT_VERSATILE select PLAT_VERSATILE_CLCD select PLAT_VERSATILE_FPGA_IRQ diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index cf4687ee2a7b..cd8ea3588f93 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -169,26 +169,13 @@ static struct map_desc versatile_io_desc[] __initdata = { .pfn = __phys_to_pfn(VERSATILE_PCI_CFG_BASE), .length = VERSATILE_PCI_CFG_BASE_SIZE, .type = MT_DEVICE - }, -#if 0 - { - .virtual = VERSATILE_PCI_VIRT_MEM_BASE0, - .pfn = __phys_to_pfn(VERSATILE_PCI_MEM_BASE0), - .length = SZ_16M, - .type = MT_DEVICE }, { - .virtual = VERSATILE_PCI_VIRT_MEM_BASE1, - .pfn = __phys_to_pfn(VERSATILE_PCI_MEM_BASE1), - .length = SZ_16M, - .type = MT_DEVICE - }, { - .virtual = VERSATILE_PCI_VIRT_MEM_BASE2, - .pfn = __phys_to_pfn(VERSATILE_PCI_MEM_BASE2), - .length = SZ_16M, + .virtual = (unsigned long)VERSATILE_PCI_VIRT_MEM_BASE0, + .pfn = __phys_to_pfn(VERSATILE_PCI_MEM_BASE0), + .length = IO_SPACE_LIMIT, .type = MT_DEVICE }, #endif -#endif }; void __init versatile_map_io(void) diff --git a/arch/arm/mach-versatile/include/mach/hardware.h b/arch/arm/mach-versatile/include/mach/hardware.h index 4d4973dd8fba..408e58da46c6 100644 --- a/arch/arm/mach-versatile/include/mach/hardware.h +++ b/arch/arm/mach-versatile/include/mach/hardware.h @@ -29,8 +29,9 @@ */ #define VERSATILE_PCI_VIRT_BASE (void __iomem *)0xe8000000ul #define VERSATILE_PCI_CFG_VIRT_BASE (void __iomem *)0xe9000000ul +#define VERSATILE_PCI_VIRT_MEM_BASE0 (void __iomem *)PCIO_BASE -/* macro to get at IO space when running virtually */ +/* macro to get at MMIO space when running virtually */ #define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) #define __io_address(n) ((void __iomem __force *)IO_ADDRESS(n)) diff --git a/arch/arm/mach-versatile/include/mach/io.h b/arch/arm/mach-versatile/include/mach/io.h new file mode 100644 index 000000000000..0406513be7d8 --- /dev/null +++ b/arch/arm/mach-versatile/include/mach/io.h @@ -0,0 +1,27 @@ +/* + * arch/arm/mach-versatile/include/mach/io.h + * + * Copyright (C) 2003 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define PCIO_BASE 0xeb000000ul + +#define __io(a) ((a) + PCIO_BASE) + +#endif diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c index 15c6a00000ec..bec933b04ef0 100644 --- a/arch/arm/mach-versatile/pci.c +++ b/arch/arm/mach-versatile/pci.c @@ -169,11 +169,18 @@ static struct pci_ops pci_versatile_ops = { .write = versatile_write_config, }; +static struct resource io_port = { + .name = "PCI", + .start = 0, + .end = IO_SPACE_LIMIT, + .flags = IORESOURCE_IO, +}; + static struct resource io_mem = { .name = "PCI I/O space", .start = VERSATILE_PCI_MEM_BASE0, .end = VERSATILE_PCI_MEM_BASE0+VERSATILE_PCI_MEM_BASE0_SIZE-1, - .flags = IORESOURCE_IO, + .flags = IORESOURCE_MEM, }; static struct resource non_mem = { @@ -200,6 +207,12 @@ static int __init pci_versatile_setup_resources(struct pci_sys_data *sys) "memory region (%d)\n", ret); goto out; } + ret = request_resource(&ioport_resource, &io_port); + if (ret) { + printk(KERN_ERR "PCI: unable to allocate I/O " + "port region (%d)\n", ret); + goto out; + } ret = request_resource(&iomem_resource, &non_mem); if (ret) { printk(KERN_ERR "PCI: unable to allocate non-prefetchable " @@ -218,7 +231,7 @@ static int __init pci_versatile_setup_resources(struct pci_sys_data *sys) * the mem resource for this bus * the prefetch mem resource for this bus */ - pci_add_resource_offset(&sys->resources, &io_mem, sys->io_offset); + pci_add_resource_offset(&sys->resources, &io_port, sys->io_offset); pci_add_resource_offset(&sys->resources, &non_mem, sys->mem_offset); pci_add_resource_offset(&sys->resources, &pre_mem, sys->mem_offset); @@ -249,6 +262,7 @@ int __init pci_versatile_setup(int nr, struct pci_sys_data *sys) if (nr == 0) { sys->mem_offset = 0; + sys->io_offset = 0; ret = pci_versatile_setup_resources(sys); if (ret < 0) { printk("pci_versatile_setup: resources... oops?\n"); -- cgit v1.2.3 From 128789a8293653a4f889f2b1601eea07c00ff65e Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 13 Jun 2012 14:52:45 +0200 Subject: ARM: Kirkwood: Fix clk problems modular ethernet driver When the ethernet driver was built as a module, it would lock the machine when loaded. At boot the ethernet clks are unused, so get turned off. Later, when the module is loaded, the probe function would access the hardware before the clock was restarted, and the machine would lock. It has also been determined that when the clk is turned off, the interface forgets its MAC address, which for most systems, is set by the boot loader. When the machine setup file creates a platform device for the interface, prepare and enable the clock for the interface. This will ensure it is not turned off. However, if the setup file only instantiates one platform device, the other will have its clk disabled, thus maybe saving a little power. Report-by: Simon Baatz Signed-off-by: Andrew Lunn Tested-by: Simon Baatz Signed-off-by: Olof Johansson --- arch/arm/mach-kirkwood/common.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index 25fb3fd418ef..e1d2c6def5e6 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -193,9 +193,11 @@ static struct clk __init *kirkwood_register_gate_fn(const char *name, bit_idx, 0, &gating_lock, fn); } +static struct clk *ge0, *ge1; + void __init kirkwood_clk_init(void) { - struct clk *runit, *ge0, *ge1, *sata0, *sata1, *usb0, *sdio; + struct clk *runit, *sata0, *sata1, *usb0, *sdio; struct clk *crypto, *xor0, *xor1, *pex0, *pex1, *audio; tclk = clk_register_fixed_rate(NULL, "tclk", NULL, @@ -257,6 +259,9 @@ void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data) orion_ge00_init(eth_data, GE00_PHYS_BASE, IRQ_KIRKWOOD_GE00_SUM, IRQ_KIRKWOOD_GE00_ERR); + /* The interface forgets the MAC address assigned by u-boot if + the clock is turned off, so claim the clk now. */ + clk_prepare_enable(ge0); } @@ -268,6 +273,7 @@ void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data) orion_ge01_init(eth_data, GE01_PHYS_BASE, IRQ_KIRKWOOD_GE01_SUM, IRQ_KIRKWOOD_GE01_ERR); + clk_prepare_enable(ge1); } -- cgit v1.2.3 From 650513979a437c32d7a0a84f0ed952a55bbb5583 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sat, 16 Jun 2012 21:47:37 -0700 Subject: x86-64, reboot: Allow reboot=bios and reboot-cpu override on x86-64 With the revamped realmode trampoline code, it is trivial to extend support for reboot=bios to x86-64. Furthermore, while we are at it, remove the restriction that only we can only override the reboot CPU on 32 bits. Signed-off-by: H. Peter Anvin Link: http://lkml.kernel.org/n/tip-jopx7y6g6dbcx4tpal8q0jlr@git.kernel.org --- arch/x86/include/asm/emergency-restart.h | 2 - arch/x86/include/asm/realmode.h | 3 +- arch/x86/include/asm/reboot.h | 4 +- arch/x86/kernel/reboot.c | 52 +++++------ arch/x86/realmode/rm/Makefile | 2 +- arch/x86/realmode/rm/header.S | 4 +- arch/x86/realmode/rm/reboot.S | 152 +++++++++++++++++++++++++++++++ arch/x86/realmode/rm/reboot_32.S | 132 --------------------------- 8 files changed, 184 insertions(+), 167 deletions(-) create mode 100644 arch/x86/realmode/rm/reboot.S delete mode 100644 arch/x86/realmode/rm/reboot_32.S (limited to 'arch') diff --git a/arch/x86/include/asm/emergency-restart.h b/arch/x86/include/asm/emergency-restart.h index cc70c1c78ca4..75ce3f47d204 100644 --- a/arch/x86/include/asm/emergency-restart.h +++ b/arch/x86/include/asm/emergency-restart.h @@ -4,9 +4,7 @@ enum reboot_type { BOOT_TRIPLE = 't', BOOT_KBD = 'k', -#ifdef CONFIG_X86_32 BOOT_BIOS = 'b', -#endif BOOT_ACPI = 'a', BOOT_EFI = 'e', BOOT_CF9 = 'p', diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h index fce3f4ae5bd6..fe1ec5bcd846 100644 --- a/arch/x86/include/asm/realmode.h +++ b/arch/x86/include/asm/realmode.h @@ -21,8 +21,9 @@ struct real_mode_header { u32 wakeup_header; #endif /* APM/BIOS reboot */ -#ifdef CONFIG_X86_32 u32 machine_real_restart_asm; +#ifdef CONFIG_X86_64 + u32 machine_real_restart_seg; #endif }; diff --git a/arch/x86/include/asm/reboot.h b/arch/x86/include/asm/reboot.h index 92f297069e87..a82c4f1b4d83 100644 --- a/arch/x86/include/asm/reboot.h +++ b/arch/x86/include/asm/reboot.h @@ -18,8 +18,8 @@ extern struct machine_ops machine_ops; void native_machine_crash_shutdown(struct pt_regs *regs); void native_machine_shutdown(void); -void machine_real_restart(unsigned int type); -/* These must match dispatch_table in reboot_32.S */ +void __noreturn machine_real_restart(unsigned int type); +/* These must match dispatch in arch/x86/realmore/rm/reboot.S */ #define MRR_BIOS 0 #define MRR_APM 1 diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 25b48edb847c..6ddb9cd0ced0 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -20,14 +20,12 @@ #include #include #include +#include -#ifdef CONFIG_X86_32 -# include -# include -# include -#else -# include -#endif +#include +#include +#include +#include /* * Power off function, if any @@ -49,7 +47,7 @@ int reboot_force; */ static int reboot_default = 1; -#if defined(CONFIG_X86_32) && defined(CONFIG_SMP) +#ifdef CONFIG_SMP static int reboot_cpu = -1; #endif @@ -67,8 +65,8 @@ bool port_cf9_safe = false; * reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci] * warm Don't set the cold reboot flag * cold Set the cold reboot flag - * bios Reboot by jumping through the BIOS (only for X86_32) - * smp Reboot by executing reset on BSP or other CPU (only for X86_32) + * bios Reboot by jumping through the BIOS + * smp Reboot by executing reset on BSP or other CPU * triple Force a triple fault (init) * kbd Use the keyboard controller. cold reset (default) * acpi Use the RESET_REG in the FADT @@ -95,7 +93,6 @@ static int __init reboot_setup(char *str) reboot_mode = 0; break; -#ifdef CONFIG_X86_32 #ifdef CONFIG_SMP case 's': if (isdigit(*(str+1))) { @@ -112,7 +109,6 @@ static int __init reboot_setup(char *str) #endif /* CONFIG_SMP */ case 'b': -#endif case 'a': case 'k': case 't': @@ -138,7 +134,6 @@ static int __init reboot_setup(char *str) __setup("reboot=", reboot_setup); -#ifdef CONFIG_X86_32 /* * Reboot options and system auto-detection code provided by * Dell Inc. so their systems "just work". :-) @@ -157,11 +152,8 @@ static int __init set_bios_reboot(const struct dmi_system_id *d) return 0; } -void machine_real_restart(unsigned int type) +void __noreturn machine_real_restart(unsigned int type) { - void (*restart_lowmem)(unsigned int) = (void (*)(unsigned int)) - real_mode_header->machine_real_restart_asm; - local_irq_disable(); /* @@ -181,7 +173,11 @@ void machine_real_restart(unsigned int type) /* * Switch back to the initial page table. */ +#ifdef CONFIG_X86_32 load_cr3(initial_page_table); +#else + write_cr3(real_mode_header->trampoline_pgd); +#endif /* * Write 0x1234 to absolute memory location 0x472. The BIOS reads @@ -192,14 +188,21 @@ void machine_real_restart(unsigned int type) *((unsigned short *)0x472) = reboot_mode; /* Jump to the identity-mapped low memory code */ - restart_lowmem(type); +#ifdef CONFIG_X86_32 + asm volatile("jmpl *%0" : : + "rm" (real_mode_header->machine_real_restart_asm), + "a" (type)); +#else + asm volatile("ljmpl *%0" : : + "m" (real_mode_header->machine_real_restart_asm), + "D" (type)); +#endif + unreachable(); } #ifdef CONFIG_APM_MODULE EXPORT_SYMBOL(machine_real_restart); #endif -#endif /* CONFIG_X86_32 */ - /* * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot */ @@ -223,11 +226,9 @@ static int __init set_kbd_reboot(const struct dmi_system_id *d) } /* - * This is a single dmi_table handling all reboot quirks. Note that - * REBOOT_BIOS is only available for 32bit + * This is a single dmi_table handling all reboot quirks. */ static struct dmi_system_id __initdata reboot_dmi_table[] = { -#ifdef CONFIG_X86_32 { /* Handle problems with rebooting on Dell E520's */ .callback = set_bios_reboot, .ident = "Dell E520", @@ -377,7 +378,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "P4S800"), }, }, -#endif /* CONFIG_X86_32 */ { /* Handle reboot issue on Acer Aspire one */ .callback = set_kbd_reboot, @@ -576,13 +576,11 @@ static void native_machine_emergency_restart(void) reboot_type = BOOT_KBD; break; -#ifdef CONFIG_X86_32 case BOOT_BIOS: machine_real_restart(MRR_BIOS); reboot_type = BOOT_KBD; break; -#endif case BOOT_ACPI: acpi_reboot(); @@ -624,12 +622,10 @@ void native_machine_shutdown(void) /* The boot cpu is always logical cpu 0 */ int reboot_cpu_id = 0; -#ifdef CONFIG_X86_32 /* See if there has been given a command line override */ if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) && cpu_online(reboot_cpu)) reboot_cpu_id = reboot_cpu; -#endif /* Make certain the cpu I'm about to reboot on is online */ if (!cpu_online(reboot_cpu_id)) diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile index 5b84a2d30888..b2d534cab25f 100644 --- a/arch/x86/realmode/rm/Makefile +++ b/arch/x86/realmode/rm/Makefile @@ -22,7 +22,7 @@ wakeup-objs += video-bios.o realmode-y += header.o realmode-y += trampoline_$(BITS).o realmode-y += stack.o -realmode-$(CONFIG_X86_32) += reboot_32.o +realmode-y += reboot.o realmode-$(CONFIG_ACPI_SLEEP) += $(wakeup-objs) targets += $(realmode-y) diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S index fadf48378ada..a28221d94e69 100644 --- a/arch/x86/realmode/rm/header.S +++ b/arch/x86/realmode/rm/header.S @@ -6,6 +6,7 @@ #include #include +#include #include "realmode.h" @@ -28,8 +29,9 @@ GLOBAL(real_mode_header) .long pa_wakeup_header #endif /* APM/BIOS reboot */ -#ifdef CONFIG_X86_32 .long pa_machine_real_restart_asm +#ifdef CONFIG_X86_64 + .long __KERNEL32_CS #endif END(real_mode_header) diff --git a/arch/x86/realmode/rm/reboot.S b/arch/x86/realmode/rm/reboot.S new file mode 100644 index 000000000000..6bf8feac5557 --- /dev/null +++ b/arch/x86/realmode/rm/reboot.S @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include +#include "realmode.h" + +/* + * The following code and data reboots the machine by switching to real + * mode and jumping to the BIOS reset entry point, as if the CPU has + * really been reset. The previous version asked the keyboard + * controller to pulse the CPU reset line, which is more thorough, but + * doesn't work with at least one type of 486 motherboard. It is easy + * to stop this code working; hence the copious comments. + * + * This code is called with the restart type (0 = BIOS, 1 = APM) in + * the primary argument register (%eax for 32 bit, %edi for 64 bit). + */ + .section ".text32", "ax" + .code32 +ENTRY(machine_real_restart_asm) + +#ifdef CONFIG_X86_64 + + /* Disable paging to drop us out of long mode */ + movl %cr0, %eax + andl $~X86_CR0_PG, %eax + movl %eax, %cr0 + jmp 1f /* "A branch" may be needed here, assume near is OK */ + +1: + xorl %eax, %eax + xorl %edx, %edx + movl $MSR_EFER, %ecx + wrmsr + + movl %edi, %eax + +#endif /* CONFIG_X86_64 */ + + /* Set up the IDT for real mode. */ + lidtl pa_machine_real_restart_idt + + /* + * Set up a GDT from which we can load segment descriptors for real + * mode. The GDT is not used in real mode; it is just needed here to + * prepare the descriptors. + */ + lgdtl pa_machine_real_restart_gdt + + /* + * Load the data segment registers with 16-bit compatible values + */ + movl $16, %ecx + movl %ecx, %ds + movl %ecx, %es + movl %ecx, %fs + movl %ecx, %gs + movl %ecx, %ss + ljmpw $8, $1f + +/* + * This is 16-bit protected mode code to disable paging and the cache, + * switch to real mode and jump to the BIOS reset code. + * + * The instruction that switches to real mode by writing to CR0 must be + * followed immediately by a far jump instruction, which set CS to a + * valid value for real mode, and flushes the prefetch queue to avoid + * running instructions that have already been decoded in protected + * mode. + * + * Clears all the flags except ET, especially PG (paging), PE + * (protected-mode enable) and TS (task switch for coprocessor state + * save). Flushes the TLB after paging has been disabled. Sets CD and + * NW, to disable the cache on a 486, and invalidates the cache. This + * is more like the state of a 486 after reset. I don't know if + * something else should be done for other chips. + * + * More could be done here to set up the registers as if a CPU reset had + * occurred; hopefully real BIOSs don't assume much. This is not the + * actual BIOS entry point, anyway (that is at 0xfffffff0). + * + * Most of this work is probably excessive, but it is what is tested. + */ + .text + .code16 + + .balign 16 +machine_real_restart_asm16: +1: + xorl %ecx, %ecx + movl %cr0, %edx + andl $0x00000011, %edx + orl $0x60000000, %edx + movl %edx, %cr0 + movl %ecx, %cr3 + movl %cr0, %edx + testl $0x60000000, %edx /* If no cache bits -> no wbinvd */ + jz 2f + wbinvd +2: + andb $0x10, %dl + movl %edx, %cr0 + LJMPW_RM(3f) +3: + andw %ax, %ax + jz bios + +apm: + movw $0x1000, %ax + movw %ax, %ss + movw $0xf000, %sp + movw $0x5307, %ax + movw $0x0001, %bx + movw $0x0003, %cx + int $0x15 + /* This should never return... */ + +bios: + ljmpw $0xf000, $0xfff0 + + .section ".rodata", "a" + + .balign 16 +GLOBAL(machine_real_restart_idt) + .word 0xffff /* Length - real mode default value */ + .long 0 /* Base - real mode default value */ +END(machine_real_restart_idt) + + .balign 16 +GLOBAL(machine_real_restart_gdt) + /* Self-pointer */ + .word 0xffff /* Length - real mode default value */ + .long pa_machine_real_restart_gdt + .word 0 + + /* + * 16-bit code segment pointing to real_mode_seg + * Selector value 8 + */ + .word 0xffff /* Limit */ + .long 0x9b000000 + pa_real_mode_base + .word 0 + + /* + * 16-bit data segment with the selector value 16 = 0x10 and + * base value 0x100; since this is consistent with real mode + * semantics we don't have to reload the segments once CR0.PE = 0. + */ + .quad GDT_ENTRY(0x0093, 0x100, 0xffff) +END(machine_real_restart_gdt) diff --git a/arch/x86/realmode/rm/reboot_32.S b/arch/x86/realmode/rm/reboot_32.S deleted file mode 100644 index 114044876b3d..000000000000 --- a/arch/x86/realmode/rm/reboot_32.S +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include -#include -#include -#include "realmode.h" - -/* - * The following code and data reboots the machine by switching to real - * mode and jumping to the BIOS reset entry point, as if the CPU has - * really been reset. The previous version asked the keyboard - * controller to pulse the CPU reset line, which is more thorough, but - * doesn't work with at least one type of 486 motherboard. It is easy - * to stop this code working; hence the copious comments. - * - * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax. - */ - .section ".text32", "ax" - .code32 - - .balign 16 -ENTRY(machine_real_restart_asm) - /* Set up the IDT for real mode. */ - lidtl pa_machine_real_restart_idt - - /* - * Set up a GDT from which we can load segment descriptors for real - * mode. The GDT is not used in real mode; it is just needed here to - * prepare the descriptors. - */ - lgdtl pa_machine_real_restart_gdt - - /* - * Load the data segment registers with 16-bit compatible values - */ - movl $16, %ecx - movl %ecx, %ds - movl %ecx, %es - movl %ecx, %fs - movl %ecx, %gs - movl %ecx, %ss - ljmpw $8, $1f - -/* - * This is 16-bit protected mode code to disable paging and the cache, - * switch to real mode and jump to the BIOS reset code. - * - * The instruction that switches to real mode by writing to CR0 must be - * followed immediately by a far jump instruction, which set CS to a - * valid value for real mode, and flushes the prefetch queue to avoid - * running instructions that have already been decoded in protected - * mode. - * - * Clears all the flags except ET, especially PG (paging), PE - * (protected-mode enable) and TS (task switch for coprocessor state - * save). Flushes the TLB after paging has been disabled. Sets CD and - * NW, to disable the cache on a 486, and invalidates the cache. This - * is more like the state of a 486 after reset. I don't know if - * something else should be done for other chips. - * - * More could be done here to set up the registers as if a CPU reset had - * occurred; hopefully real BIOSs don't assume much. This is not the - * actual BIOS entry point, anyway (that is at 0xfffffff0). - * - * Most of this work is probably excessive, but it is what is tested. - */ - .text - .code16 - - .balign 16 -machine_real_restart_asm16: -1: - xorl %ecx, %ecx - movl %cr0, %edx - andl $0x00000011, %edx - orl $0x60000000, %edx - movl %edx, %cr0 - movl %ecx, %cr3 - movl %cr0, %edx - testl $0x60000000, %edx /* If no cache bits -> no wbinvd */ - jz 2f - wbinvd -2: - andb $0x10, %dl - movl %edx, %cr0 - LJMPW_RM(3f) -3: - andw %ax, %ax - jz bios - -apm: - movw $0x1000, %ax - movw %ax, %ss - movw $0xf000, %sp - movw $0x5307, %ax - movw $0x0001, %bx - movw $0x0003, %cx - int $0x15 - /* This should never return... */ - -bios: - ljmpw $0xf000, $0xfff0 - - .section ".rodata", "a" - - .balign 16 -GLOBAL(machine_real_restart_idt) - .word 0xffff /* Length - real mode default value */ - .long 0 /* Base - real mode default value */ -END(machine_real_restart_idt) - - .balign 16 -GLOBAL(machine_real_restart_gdt) - /* Self-pointer */ - .word 0xffff /* Length - real mode default value */ - .long pa_machine_real_restart_gdt - .word 0 - - /* - * 16-bit code segment pointing to real_mode_seg - * Selector value 8 - */ - .word 0xffff /* Limit */ - .long 0x9b000000 + pa_real_mode_base - .word 0 - - /* - * 16-bit data segment with the selector value 16 = 0x10 and - * base value 0x100; since this is consistent with real mode - * semantics we don't have to reload the segments once CR0.PE = 0. - */ - .quad GDT_ENTRY(0x0093, 0x100, 0xffff) -END(machine_real_restart_gdt) -- cgit v1.2.3 From 22cec7ca02f81b57a06d238a4043bc6c9ba6ea03 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 8 Jun 2012 11:36:45 +0200 Subject: ARM: iconnect: Remove include of removed linux/spi/orion_spi.h v3.5-rc1 fails to build when DT and iconnect is enabled because of this now none existant include file. Also remove the other two SPI include files, which are not needed with the move to DT. Signed-off-by: Andrew Lunn Acked-by: Arnaud Patard Signed-off-by: Olof Johansson --- arch/arm/mach-kirkwood/board-iconnect.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-kirkwood/board-iconnect.c b/arch/arm/mach-kirkwood/board-iconnect.c index 2222c5739519..b0d3cc49269d 100644 --- a/arch/arm/mach-kirkwood/board-iconnect.c +++ b/arch/arm/mach-kirkwood/board-iconnect.c @@ -20,9 +20,6 @@ #include #include #include -#include -#include -#include #include #include #include -- cgit v1.2.3 From 6bc07d6afa1679a2f5b272bc36618314686e143a Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Sun, 17 Jun 2012 11:57:50 -0600 Subject: ARM: OMAP: PM: Lock clocks list while generating summary Commit a53025724052b2b1edbc982a4a248784638f563d (OMAP: Add debugfs node to show the summary of all clocks) introduced clock summary, however, we are interested in seeing snapshot of the clock state, not in dynamically changing clock configurations as the data provided by clock summary will then be useless for debugging configuration issues. So, hold the common lock when dumping the clock summary. Cc: Paul Walmsley Cc: Tony Lindgren Signed-off-by: Todd Poynor [nm@ti.com: added commit message] Signed-off-by: Nishanth Menon [paul@pwsan.com: minor edits to commit message] Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/clock.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 62ec5c452792..706b7e29397f 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -461,6 +461,7 @@ static int clk_dbg_show_summary(struct seq_file *s, void *unused) struct clk *c; struct clk *pa; + mutex_lock(&clocks_mutex); seq_printf(s, "%-30s %-30s %-10s %s\n", "clock-name", "parent-name", "rate", "use-count"); @@ -469,6 +470,7 @@ static int clk_dbg_show_summary(struct seq_file *s, void *unused) seq_printf(s, "%-30s %-30s %-10lu %d\n", c->name, pa ? pa->name : "none", c->rate, c->usecount); } + mutex_unlock(&clocks_mutex); return 0; } -- cgit v1.2.3 From 2e113c648dc29c3d8418fe277917b04397375939 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 18 Jun 2012 00:47:25 -0600 Subject: ARM: OMAP2+: control: Add AM33XX control reg & sec clkctrl offset Define AM33XX control register, in order to allow access to control register address space, also add CONTROL_SEC_CLK_CTRL register offset; both are required in clock tree data, for wdt0 and timer0 clock source select configuration. CONTROL.SEC_CLK_CTRL register is provided to select/configure clock input for WDT0 and TIMER0. Signed-off-by: Vaibhav Hiremath Cc: Paul Walmsley Cc: Tony Lindgren [paul@pwsan.com: added include of plat/am33xx.h to fix build break; added AM33XX_CONTROL_STATUS bitfields that will be needed for the clock tree; fixed some control.h whitespace problems while here] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/control.h | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h index a406fd045ce1..c43f03cbefc5 100644 --- a/arch/arm/mach-omap2/control.h +++ b/arch/arm/mach-omap2/control.h @@ -21,6 +21,8 @@ #include #include +#include + #ifndef __ASSEMBLY__ #define OMAP242X_CTRL_REGADDR(reg) \ OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg)) @@ -28,6 +30,8 @@ OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE + (reg)) #define OMAP343X_CTRL_REGADDR(reg) \ OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg)) +#define AM33XX_CTRL_REGADDR(reg) \ + AM33XX_L4_WK_IO_ADDRESS(AM33XX_SCM_BASE + (reg)) #else #define OMAP242X_CTRL_REGADDR(reg) \ OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg)) @@ -35,6 +39,8 @@ OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE + (reg)) #define OMAP343X_CTRL_REGADDR(reg) \ OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg)) +#define AM33XX_CTRL_REGADDR(reg) \ + AM33XX_L4_WK_IO_ADDRESS(AM33XX_SCM_BASE + (reg)) #endif /* __ASSEMBLY__ */ /* @@ -312,15 +318,15 @@ OMAP343X_SCRATCHPAD + reg) /* AM35XX_CONTROL_IPSS_CLK_CTRL bits */ -#define AM35XX_USBOTG_VBUSP_CLK_SHIFT 0 -#define AM35XX_CPGMAC_VBUSP_CLK_SHIFT 1 -#define AM35XX_VPFE_VBUSP_CLK_SHIFT 2 -#define AM35XX_HECC_VBUSP_CLK_SHIFT 3 -#define AM35XX_USBOTG_FCLK_SHIFT 8 -#define AM35XX_CPGMAC_FCLK_SHIFT 9 -#define AM35XX_VPFE_FCLK_SHIFT 10 - -/*AM35XX CONTROL_LVL_INTR_CLEAR bits*/ +#define AM35XX_USBOTG_VBUSP_CLK_SHIFT 0 +#define AM35XX_CPGMAC_VBUSP_CLK_SHIFT 1 +#define AM35XX_VPFE_VBUSP_CLK_SHIFT 2 +#define AM35XX_HECC_VBUSP_CLK_SHIFT 3 +#define AM35XX_USBOTG_FCLK_SHIFT 8 +#define AM35XX_CPGMAC_FCLK_SHIFT 9 +#define AM35XX_VPFE_FCLK_SHIFT 10 + +/* AM35XX CONTROL_LVL_INTR_CLEAR bits */ #define AM35XX_CPGMAC_C0_MISC_PULSE_CLR BIT(0) #define AM35XX_CPGMAC_C0_RX_PULSE_CLR BIT(1) #define AM35XX_CPGMAC_C0_RX_THRESH_CLR BIT(2) @@ -330,21 +336,22 @@ #define AM35XX_VPFE_CCDC_VD1_INT_CLR BIT(6) #define AM35XX_VPFE_CCDC_VD2_INT_CLR BIT(7) -/*AM35XX CONTROL_IP_SW_RESET bits*/ +/* AM35XX CONTROL_IP_SW_RESET bits */ #define AM35XX_USBOTGSS_SW_RST BIT(0) #define AM35XX_CPGMACSS_SW_RST BIT(1) #define AM35XX_VPFE_VBUSP_SW_RST BIT(2) #define AM35XX_HECC_SW_RST BIT(3) #define AM35XX_VPFE_PCLK_SW_RST BIT(4) -/* - * CONTROL AM33XX STATUS register - */ +/* AM33XX CONTROL_STATUS register */ #define AM33XX_CONTROL_STATUS 0x040 +#define AM33XX_CONTROL_SEC_CLK_CTRL 0x1bc -/* - * CONTROL OMAP STATUS register to identify OMAP3 features - */ +/* AM33XX CONTROL_STATUS bitfields (partial) */ +#define AM33XX_CONTROL_STATUS_SYSBOOT1_SHIFT 22 +#define AM33XX_CONTROL_STATUS_SYSBOOT1_MASK (0x3 << 22) + +/* CONTROL OMAP STATUS register to identify OMAP3 features */ #define OMAP3_CONTROL_OMAP_STATUS 0x044c #define OMAP3_SGX_SHIFT 13 -- cgit v1.2.3 From ce3fc89a4e120c1fb012efd71f403116b6bcc1ee Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 18 Jun 2012 00:47:26 -0600 Subject: ARM: OMAP AM33xx: voltagedomain: Add voltage domain data Currently dummy voltage domain data is being created in order to succeed boot process, nothing has been done w.r.t actual hardware (voltage control). Also, hook up the AM33XX voltage domain to OMAP framework. Signed-off-by: Vaibhav Hiremath Signed-off-by: Afzal Mohammed Cc: Benoit Cousson Cc: Tony Lindgren Cc: Kevin Hilman Cc: Paul Walmsley Cc: Rajendra Nayak Acked-by: Kevin Hilman [paul@pwsan.com: updated for 3.5] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/Makefile | 1 + arch/arm/mach-omap2/common.h | 1 + arch/arm/mach-omap2/io.c | 1 + arch/arm/mach-omap2/voltage.h | 1 + arch/arm/mach-omap2/voltagedomains33xx_data.c | 43 +++++++++++++++++++++++++++ 5 files changed, 47 insertions(+) create mode 100644 arch/arm/mach-omap2/voltagedomains33xx_data.c (limited to 'arch') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index fa742f3c2629..6a3aef66f03e 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -99,6 +99,7 @@ obj-$(CONFIG_ARCH_OMAP3) += $(voltagedomain-common) obj-$(CONFIG_ARCH_OMAP3) += voltagedomains3xxx_data.o obj-$(CONFIG_ARCH_OMAP4) += $(voltagedomain-common) obj-$(CONFIG_ARCH_OMAP4) += voltagedomains44xx_data.o +obj-$(CONFIG_SOC_AM33XX) += voltagedomains33xx_data.o # OMAP powerdomain framework powerdomain-common += powerdomain.o powerdomain-common.o diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index 56f687bebd0a..5d99c1b2cb48 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -129,6 +129,7 @@ void omap3430_init_early(void); void omap35xx_init_early(void); void omap3630_init_early(void); void omap3_init_early(void); /* Do not use this one */ +void am33xx_init_early(void); void am35xx_init_early(void); void ti81xx_init_early(void); void am33xx_init_early(void); diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 5d6b2346bf75..d15ecb3782b7 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -484,6 +484,7 @@ void __init am33xx_init_early(void) omap3xxx_check_revision(); ti81xx_check_features(); omap_common_init_early(); + am33xx_voltagedomains_init(); } #endif diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h index 16a1b092cf36..a7c43c1042be 100644 --- a/arch/arm/mach-omap2/voltage.h +++ b/arch/arm/mach-omap2/voltage.h @@ -156,6 +156,7 @@ int omap_voltage_late_init(void); extern void omap2xxx_voltagedomains_init(void); extern void omap3xxx_voltagedomains_init(void); +extern void am33xx_voltagedomains_init(void); extern void omap44xx_voltagedomains_init(void); struct voltagedomain *voltdm_lookup(const char *name); diff --git a/arch/arm/mach-omap2/voltagedomains33xx_data.c b/arch/arm/mach-omap2/voltagedomains33xx_data.c new file mode 100644 index 000000000000..965458dc0cb9 --- /dev/null +++ b/arch/arm/mach-omap2/voltagedomains33xx_data.c @@ -0,0 +1,43 @@ +/* + * AM33XX voltage domain data + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "voltage.h" + +static struct voltagedomain am33xx_voltdm_mpu = { + .name = "mpu", +}; + +static struct voltagedomain am33xx_voltdm_core = { + .name = "core", +}; + +static struct voltagedomain am33xx_voltdm_rtc = { + .name = "rtc", +}; + +static struct voltagedomain *voltagedomains_am33xx[] __initdata = { + &am33xx_voltdm_mpu, + &am33xx_voltdm_core, + &am33xx_voltdm_rtc, + NULL, +}; + +void __init am33xx_voltagedomains_init(void) +{ + voltdm_init(voltagedomains_am33xx); +} -- cgit v1.2.3 From c15acff337ca5c2f101fee99f36c89d47839d387 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Tue, 12 Jun 2012 12:53:21 +0800 Subject: x86: Fix kernel-doc warnings Signed-off-by: Wanpeng Li Cc: Peter Zijlstra Cc: Jason Wessel Cc: Jan Kiszka Cc: Gavin Shan Cc: Wanpeng Li Signed-off-by: Ingo Molnar --- arch/x86/kernel/kgdb.c | 8 ++++---- arch/x86/lib/csum-wrappers_64.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 8bfb6146f753..3f61904365cf 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -444,12 +444,12 @@ void kgdb_roundup_cpus(unsigned long flags) /** * kgdb_arch_handle_exception - Handle architecture specific GDB packets. - * @vector: The error vector of the exception that happened. + * @e_vector: The error vector of the exception that happened. * @signo: The signal number of the exception that happened. * @err_code: The error code of the exception that happened. - * @remcom_in_buffer: The buffer of the packet we have read. - * @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into. - * @regs: The &struct pt_regs of the current process. + * @remcomInBuffer: The buffer of the packet we have read. + * @remcomOutBuffer: The buffer of %BUFMAX bytes to write a packet into. + * @linux_regs: The &struct pt_regs of the current process. * * This function MUST handle the 'c' and 's' command packets, * as well packets to set / remove a hardware breakpoint, if used. diff --git a/arch/x86/lib/csum-wrappers_64.c b/arch/x86/lib/csum-wrappers_64.c index 459b58a8a15c..25b7ae8d058a 100644 --- a/arch/x86/lib/csum-wrappers_64.c +++ b/arch/x86/lib/csum-wrappers_64.c @@ -115,7 +115,7 @@ EXPORT_SYMBOL(csum_partial_copy_to_user); * @src: source address * @dst: destination address * @len: number of bytes to be copied. - * @isum: initial sum that is added into the result (32bit unfolded) + * @sum: initial sum that is added into the result (32bit unfolded) * * Returns an 32bit unfolded checksum of the buffer. */ -- cgit v1.2.3 From abf71f3066740f3b59c3f731b4b68ed335f7b24d Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Fri, 15 Jun 2012 18:10:55 +0300 Subject: x86/vsmp: Fix vector_allocation_domain's return value Commit 8637e38a ("x86/apic: Avoid useless scanning thru a cpumask in assign_irq_vector()") modified vector_allocation_domain() to return a boolean indicating if cpumask is dynamic or static. Adjust vSMP's callback implementation accordingly. Signed-off-by: Ido Yariv Acked-by: Shai Fultheim Cc: Alexander Gordeev Link: http://lkml.kernel.org/r/1339773055-27397-1-git-send-email-ido@wizery.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/vsmp_64.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c index 3f0285ac00fa..fa5adb7c228c 100644 --- a/arch/x86/kernel/vsmp_64.c +++ b/arch/x86/kernel/vsmp_64.c @@ -208,9 +208,10 @@ static int apicid_phys_pkg_id(int initial_apic_id, int index_msb) * In vSMP, all cpus should be capable of handling interrupts, regardless of * the APIC used. */ -static void fill_vector_allocation_domain(int cpu, struct cpumask *retmask) +static bool fill_vector_allocation_domain(int cpu, struct cpumask *retmask) { cpumask_setall(retmask); + return false; } static void vsmp_apic_post_init(void) -- cgit v1.2.3 From 76958a61e42fb6277a8431eb17e4bdb24176f1b7 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Fri, 15 Jun 2012 19:06:44 +0200 Subject: perf/x86/amd: Fix RDPMC index calculation for AMD family 15h The RDPMC index calculation is wrong for AMD family 15h (X86_FEATURE_ PERFCTR_CORE set). This leads to a #GP when accessing the counter: Pid: 2237, comm: syslog-ng Not tainted 3.5.0-rc1-perf-x86_64-standard-g130ff90 #135 AMD Pike/Pike RIP: 0010:[] [] x86_perf_event_update+0x27/0x66 While the msr address offset is (index << 1) we must use index to select the correct rdpmc. Signed-off-by: Robert Richter Acked-by: Peter Zijlstra Cc: Vince Weaver Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 766c76d5ec4c..d1f38c9509d0 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -823,7 +823,7 @@ static inline void x86_assign_hw_event(struct perf_event *event, } else { hwc->config_base = x86_pmu_config_addr(hwc->idx); hwc->event_base = x86_pmu_event_addr(hwc->idx); - hwc->event_base_rdpmc = x86_pmu_addr_offset(hwc->idx); + hwc->event_base_rdpmc = hwc->idx; } } -- cgit v1.2.3 From 4b4969b14490a4f65b572b8f180164181104b5e1 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Fri, 15 Jun 2012 14:31:30 +0800 Subject: perf: Export perf_assign_events() Export perf_assign_events() so the uncore code can use it to schedule events. Signed-off-by: Zheng Yan Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1339741902-8449-2-git-send-email-zheng.z.yan@intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 6 +++--- arch/x86/kernel/cpu/perf_event.h | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index d1f38c9509d0..6d32aefc9dbd 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -626,7 +626,7 @@ static bool __perf_sched_find_counter(struct perf_sched *sched) c = sched->constraints[sched->state.event]; /* Prefer fixed purpose counters */ - if (x86_pmu.num_counters_fixed) { + if (c->idxmsk64 & (~0ULL << X86_PMC_IDX_FIXED)) { idx = X86_PMC_IDX_FIXED; for_each_set_bit_from(idx, c->idxmsk, X86_PMC_IDX_MAX) { if (!__test_and_set_bit(idx, sched->state.used)) @@ -693,8 +693,8 @@ static bool perf_sched_next_event(struct perf_sched *sched) /* * Assign a counter for each event. */ -static int perf_assign_events(struct event_constraint **constraints, int n, - int wmin, int wmax, int *assign) +int perf_assign_events(struct event_constraint **constraints, int n, + int wmin, int wmax, int *assign) { struct perf_sched sched; diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 3df3de9452a9..83238f2a12b2 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -481,6 +481,8 @@ static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, void x86_pmu_enable_all(int added); +int perf_assign_events(struct event_constraint **constraints, int n, + int wmin, int wmax, int *assign); int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign); void x86_pmu_stop(struct perf_event *event, int flags); -- cgit v1.2.3 From 087bfbb032691262f2f7d52b910652450c5554b8 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Fri, 15 Jun 2012 14:31:34 +0800 Subject: perf/x86: Add generic Intel uncore PMU support This patch adds the generic Intel uncore PMU support, including helper functions that add/delete uncore events, a hrtimer that periodically polls the counters to avoid overflow and code that places all events for a particular socket onto a single cpu. The code design is based on the structure of Sandy Bridge-EP's uncore subsystem, which consists of a variety of components, each component contains one or more "boxes". (Tooling support follows in the next patches.) Signed-off-by: Zheng Yan Signed-off-by: Peter Zijlstra Cc: Linus Torvalds Cc: Andrew Morton Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1339741902-8449-6-git-send-email-zheng.z.yan@intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/Makefile | 4 +- arch/x86/kernel/cpu/perf_event_intel_uncore.c | 878 ++++++++++++++++++++++++++ arch/x86/kernel/cpu/perf_event_intel_uncore.h | 204 ++++++ 3 files changed, 1085 insertions(+), 1 deletion(-) create mode 100644 arch/x86/kernel/cpu/perf_event_intel_uncore.c create mode 100644 arch/x86/kernel/cpu/perf_event_intel_uncore.h (limited to 'arch') diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 6ab6aa2fdfdd..bac4c3804cc7 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -32,7 +32,9 @@ obj-$(CONFIG_PERF_EVENTS) += perf_event.o ifdef CONFIG_PERF_EVENTS obj-$(CONFIG_CPU_SUP_AMD) += perf_event_amd.o -obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_p6.o perf_event_p4.o perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o +obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_p6.o perf_event_p4.o +obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o +obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_intel_uncore.o endif obj-$(CONFIG_X86_MCE) += mcheck/ diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c new file mode 100644 index 000000000000..fe76a07dfdbc --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -0,0 +1,878 @@ +#include "perf_event_intel_uncore.h" + +static struct intel_uncore_type *empty_uncore[] = { NULL, }; +static struct intel_uncore_type **msr_uncores = empty_uncore; + +/* mask of cpus that collect uncore events */ +static cpumask_t uncore_cpu_mask; + +/* constraint for the fixed counter */ +static struct event_constraint constraint_fixed = + EVENT_CONSTRAINT(~0ULL, 1 << UNCORE_PMC_IDX_FIXED, ~0ULL); + +static void uncore_assign_hw_event(struct intel_uncore_box *box, + struct perf_event *event, int idx) +{ + struct hw_perf_event *hwc = &event->hw; + + hwc->idx = idx; + hwc->last_tag = ++box->tags[idx]; + + if (hwc->idx == UNCORE_PMC_IDX_FIXED) { + hwc->event_base = uncore_msr_fixed_ctr(box); + hwc->config_base = uncore_msr_fixed_ctl(box); + return; + } + + hwc->config_base = uncore_msr_event_ctl(box, hwc->idx); + hwc->event_base = uncore_msr_perf_ctr(box, hwc->idx); +} + +static void uncore_perf_event_update(struct intel_uncore_box *box, + struct perf_event *event) +{ + u64 prev_count, new_count, delta; + int shift; + + if (event->hw.idx >= UNCORE_PMC_IDX_FIXED) + shift = 64 - uncore_fixed_ctr_bits(box); + else + shift = 64 - uncore_perf_ctr_bits(box); + + /* the hrtimer might modify the previous event value */ +again: + prev_count = local64_read(&event->hw.prev_count); + new_count = uncore_read_counter(box, event); + if (local64_xchg(&event->hw.prev_count, new_count) != prev_count) + goto again; + + delta = (new_count << shift) - (prev_count << shift); + delta >>= shift; + + local64_add(delta, &event->count); +} + +/* + * The overflow interrupt is unavailable for SandyBridge-EP, is broken + * for SandyBridge. So we use hrtimer to periodically poll the counter + * to avoid overflow. + */ +static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer) +{ + struct intel_uncore_box *box; + unsigned long flags; + int bit; + + box = container_of(hrtimer, struct intel_uncore_box, hrtimer); + if (!box->n_active || box->cpu != smp_processor_id()) + return HRTIMER_NORESTART; + /* + * disable local interrupt to prevent uncore_pmu_event_start/stop + * to interrupt the update process + */ + local_irq_save(flags); + + for_each_set_bit(bit, box->active_mask, UNCORE_PMC_IDX_MAX) + uncore_perf_event_update(box, box->events[bit]); + + local_irq_restore(flags); + + hrtimer_forward_now(hrtimer, ns_to_ktime(UNCORE_PMU_HRTIMER_INTERVAL)); + return HRTIMER_RESTART; +} + +static void uncore_pmu_start_hrtimer(struct intel_uncore_box *box) +{ + __hrtimer_start_range_ns(&box->hrtimer, + ns_to_ktime(UNCORE_PMU_HRTIMER_INTERVAL), 0, + HRTIMER_MODE_REL_PINNED, 0); +} + +static void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box) +{ + hrtimer_cancel(&box->hrtimer); +} + +static void uncore_pmu_init_hrtimer(struct intel_uncore_box *box) +{ + hrtimer_init(&box->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + box->hrtimer.function = uncore_pmu_hrtimer; +} + +struct intel_uncore_box *uncore_alloc_box(int cpu) +{ + struct intel_uncore_box *box; + + box = kmalloc_node(sizeof(*box), GFP_KERNEL | __GFP_ZERO, + cpu_to_node(cpu)); + if (!box) + return NULL; + + uncore_pmu_init_hrtimer(box); + atomic_set(&box->refcnt, 1); + box->cpu = -1; + box->phys_id = -1; + + return box; +} + +static struct intel_uncore_box * +uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu) +{ + return *per_cpu_ptr(pmu->box, cpu); +} + +static struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event) +{ + return container_of(event->pmu, struct intel_uncore_pmu, pmu); +} + +static struct intel_uncore_box *uncore_event_to_box(struct perf_event *event) +{ + /* + * perf core schedules event on the basis of cpu, uncore events are + * collected by one of the cpus inside a physical package. + */ + return uncore_pmu_to_box(uncore_event_to_pmu(event), + smp_processor_id()); +} + +static int uncore_collect_events(struct intel_uncore_box *box, + struct perf_event *leader, bool dogrp) +{ + struct perf_event *event; + int n, max_count; + + max_count = box->pmu->type->num_counters; + if (box->pmu->type->fixed_ctl) + max_count++; + + if (box->n_events >= max_count) + return -EINVAL; + + n = box->n_events; + box->event_list[n] = leader; + n++; + if (!dogrp) + return n; + + list_for_each_entry(event, &leader->sibling_list, group_entry) { + if (event->state <= PERF_EVENT_STATE_OFF) + continue; + + if (n >= max_count) + return -EINVAL; + + box->event_list[n] = event; + n++; + } + return n; +} + +static struct event_constraint * +uncore_event_constraint(struct intel_uncore_type *type, + struct perf_event *event) +{ + struct event_constraint *c; + + if (event->hw.config == ~0ULL) + return &constraint_fixed; + + if (type->constraints) { + for_each_event_constraint(c, type->constraints) { + if ((event->hw.config & c->cmask) == c->code) + return c; + } + } + + return &type->unconstrainted; +} + +static int uncore_assign_events(struct intel_uncore_box *box, + int assign[], int n) +{ + unsigned long used_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)]; + struct event_constraint *c, *constraints[UNCORE_PMC_IDX_MAX]; + int i, ret, wmin, wmax; + struct hw_perf_event *hwc; + + bitmap_zero(used_mask, UNCORE_PMC_IDX_MAX); + + for (i = 0, wmin = UNCORE_PMC_IDX_MAX, wmax = 0; i < n; i++) { + c = uncore_event_constraint(box->pmu->type, + box->event_list[i]); + constraints[i] = c; + wmin = min(wmin, c->weight); + wmax = max(wmax, c->weight); + } + + /* fastpath, try to reuse previous register */ + for (i = 0; i < n; i++) { + hwc = &box->event_list[i]->hw; + c = constraints[i]; + + /* never assigned */ + if (hwc->idx == -1) + break; + + /* constraint still honored */ + if (!test_bit(hwc->idx, c->idxmsk)) + break; + + /* not already used */ + if (test_bit(hwc->idx, used_mask)) + break; + + __set_bit(hwc->idx, used_mask); + assign[i] = hwc->idx; + } + if (i == n) + return 0; + + /* slow path */ + ret = perf_assign_events(constraints, n, wmin, wmax, assign); + return ret ? -EINVAL : 0; +} + +static void uncore_pmu_event_start(struct perf_event *event, int flags) +{ + struct intel_uncore_box *box = uncore_event_to_box(event); + int idx = event->hw.idx; + + if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED))) + return; + + if (WARN_ON_ONCE(idx == -1 || idx >= UNCORE_PMC_IDX_MAX)) + return; + + event->hw.state = 0; + box->events[idx] = event; + box->n_active++; + __set_bit(idx, box->active_mask); + + local64_set(&event->hw.prev_count, uncore_read_counter(box, event)); + uncore_enable_event(box, event); + + if (box->n_active == 1) { + uncore_enable_box(box); + uncore_pmu_start_hrtimer(box); + } +} + +static void uncore_pmu_event_stop(struct perf_event *event, int flags) +{ + struct intel_uncore_box *box = uncore_event_to_box(event); + struct hw_perf_event *hwc = &event->hw; + + if (__test_and_clear_bit(hwc->idx, box->active_mask)) { + uncore_disable_event(box, event); + box->n_active--; + box->events[hwc->idx] = NULL; + WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); + hwc->state |= PERF_HES_STOPPED; + + if (box->n_active == 0) { + uncore_disable_box(box); + uncore_pmu_cancel_hrtimer(box); + } + } + + if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) { + /* + * Drain the remaining delta count out of a event + * that we are disabling: + */ + uncore_perf_event_update(box, event); + hwc->state |= PERF_HES_UPTODATE; + } +} + +static int uncore_pmu_event_add(struct perf_event *event, int flags) +{ + struct intel_uncore_box *box = uncore_event_to_box(event); + struct hw_perf_event *hwc = &event->hw; + int assign[UNCORE_PMC_IDX_MAX]; + int i, n, ret; + + if (!box) + return -ENODEV; + + ret = n = uncore_collect_events(box, event, false); + if (ret < 0) + return ret; + + hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED; + if (!(flags & PERF_EF_START)) + hwc->state |= PERF_HES_ARCH; + + ret = uncore_assign_events(box, assign, n); + if (ret) + return ret; + + /* save events moving to new counters */ + for (i = 0; i < box->n_events; i++) { + event = box->event_list[i]; + hwc = &event->hw; + + if (hwc->idx == assign[i] && + hwc->last_tag == box->tags[assign[i]]) + continue; + /* + * Ensure we don't accidentally enable a stopped + * counter simply because we rescheduled. + */ + if (hwc->state & PERF_HES_STOPPED) + hwc->state |= PERF_HES_ARCH; + + uncore_pmu_event_stop(event, PERF_EF_UPDATE); + } + + /* reprogram moved events into new counters */ + for (i = 0; i < n; i++) { + event = box->event_list[i]; + hwc = &event->hw; + + if (hwc->idx != assign[i] || + hwc->last_tag != box->tags[assign[i]]) + uncore_assign_hw_event(box, event, assign[i]); + else if (i < box->n_events) + continue; + + if (hwc->state & PERF_HES_ARCH) + continue; + + uncore_pmu_event_start(event, 0); + } + box->n_events = n; + + return 0; +} + +static void uncore_pmu_event_del(struct perf_event *event, int flags) +{ + struct intel_uncore_box *box = uncore_event_to_box(event); + int i; + + uncore_pmu_event_stop(event, PERF_EF_UPDATE); + + for (i = 0; i < box->n_events; i++) { + if (event == box->event_list[i]) { + while (++i < box->n_events) + box->event_list[i - 1] = box->event_list[i]; + + --box->n_events; + break; + } + } + + event->hw.idx = -1; + event->hw.last_tag = ~0ULL; +} + +static void uncore_pmu_event_read(struct perf_event *event) +{ + struct intel_uncore_box *box = uncore_event_to_box(event); + uncore_perf_event_update(box, event); +} + +/* + * validation ensures the group can be loaded onto the + * PMU if it was the only group available. + */ +static int uncore_validate_group(struct intel_uncore_pmu *pmu, + struct perf_event *event) +{ + struct perf_event *leader = event->group_leader; + struct intel_uncore_box *fake_box; + int assign[UNCORE_PMC_IDX_MAX]; + int ret = -EINVAL, n; + + fake_box = uncore_alloc_box(smp_processor_id()); + if (!fake_box) + return -ENOMEM; + + fake_box->pmu = pmu; + /* + * the event is not yet connected with its + * siblings therefore we must first collect + * existing siblings, then add the new event + * before we can simulate the scheduling + */ + n = uncore_collect_events(fake_box, leader, true); + if (n < 0) + goto out; + + fake_box->n_events = n; + n = uncore_collect_events(fake_box, event, false); + if (n < 0) + goto out; + + fake_box->n_events = n; + + ret = uncore_assign_events(fake_box, assign, n); +out: + kfree(fake_box); + return ret; +} + +int uncore_pmu_event_init(struct perf_event *event) +{ + struct intel_uncore_pmu *pmu; + struct intel_uncore_box *box; + struct hw_perf_event *hwc = &event->hw; + int ret; + + if (event->attr.type != event->pmu->type) + return -ENOENT; + + pmu = uncore_event_to_pmu(event); + /* no device found for this pmu */ + if (pmu->func_id < 0) + return -ENOENT; + + /* + * Uncore PMU does measure at all privilege level all the time. + * So it doesn't make sense to specify any exclude bits. + */ + if (event->attr.exclude_user || event->attr.exclude_kernel || + event->attr.exclude_hv || event->attr.exclude_idle) + return -EINVAL; + + /* Sampling not supported yet */ + if (hwc->sample_period) + return -EINVAL; + + /* + * Place all uncore events for a particular physical package + * onto a single cpu + */ + if (event->cpu < 0) + return -EINVAL; + box = uncore_pmu_to_box(pmu, event->cpu); + if (!box || box->cpu < 0) + return -EINVAL; + event->cpu = box->cpu; + + if (event->attr.config == UNCORE_FIXED_EVENT) { + /* no fixed counter */ + if (!pmu->type->fixed_ctl) + return -EINVAL; + /* + * if there is only one fixed counter, only the first pmu + * can access the fixed counter + */ + if (pmu->type->single_fixed && pmu->pmu_idx > 0) + return -EINVAL; + hwc->config = ~0ULL; + } else { + hwc->config = event->attr.config & pmu->type->event_mask; + } + + event->hw.idx = -1; + event->hw.last_tag = ~0ULL; + + if (event->group_leader != event) + ret = uncore_validate_group(pmu, event); + else + ret = 0; + + return ret; +} + +static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu) +{ + int ret; + + pmu->pmu = (struct pmu) { + .attr_groups = pmu->type->attr_groups, + .task_ctx_nr = perf_invalid_context, + .event_init = uncore_pmu_event_init, + .add = uncore_pmu_event_add, + .del = uncore_pmu_event_del, + .start = uncore_pmu_event_start, + .stop = uncore_pmu_event_stop, + .read = uncore_pmu_event_read, + }; + + if (pmu->type->num_boxes == 1) { + if (strlen(pmu->type->name) > 0) + sprintf(pmu->name, "uncore_%s", pmu->type->name); + else + sprintf(pmu->name, "uncore"); + } else { + sprintf(pmu->name, "uncore_%s_%d", pmu->type->name, + pmu->pmu_idx); + } + + ret = perf_pmu_register(&pmu->pmu, pmu->name, -1); + return ret; +} + +static void __init uncore_type_exit(struct intel_uncore_type *type) +{ + int i; + + for (i = 0; i < type->num_boxes; i++) + free_percpu(type->pmus[i].box); + kfree(type->pmus); + type->pmus = NULL; + kfree(type->attr_groups[1]); + type->attr_groups[1] = NULL; +} + +static int __init uncore_type_init(struct intel_uncore_type *type) +{ + struct intel_uncore_pmu *pmus; + struct attribute_group *events_group; + struct attribute **attrs; + int i, j; + + pmus = kzalloc(sizeof(*pmus) * type->num_boxes, GFP_KERNEL); + if (!pmus) + return -ENOMEM; + + type->unconstrainted = (struct event_constraint) + __EVENT_CONSTRAINT(0, (1ULL << type->num_counters) - 1, + 0, type->num_counters, 0); + + for (i = 0; i < type->num_boxes; i++) { + pmus[i].func_id = -1; + pmus[i].pmu_idx = i; + pmus[i].type = type; + pmus[i].box = alloc_percpu(struct intel_uncore_box *); + if (!pmus[i].box) + goto fail; + } + + if (type->event_descs) { + i = 0; + while (type->event_descs[i].attr.attr.name) + i++; + + events_group = kzalloc(sizeof(struct attribute *) * (i + 1) + + sizeof(*events_group), GFP_KERNEL); + if (!events_group) + goto fail; + + attrs = (struct attribute **)(events_group + 1); + events_group->name = "events"; + events_group->attrs = attrs; + + for (j = 0; j < i; j++) + attrs[j] = &type->event_descs[j].attr.attr; + + type->attr_groups[1] = events_group; + } + + type->pmus = pmus; + return 0; +fail: + uncore_type_exit(type); + return -ENOMEM; +} + +static int __init uncore_types_init(struct intel_uncore_type **types) +{ + int i, ret; + + for (i = 0; types[i]; i++) { + ret = uncore_type_init(types[i]); + if (ret) + goto fail; + } + return 0; +fail: + while (--i >= 0) + uncore_type_exit(types[i]); + return ret; +} + +static void __cpuinit uncore_cpu_dying(int cpu) +{ + struct intel_uncore_type *type; + struct intel_uncore_pmu *pmu; + struct intel_uncore_box *box; + int i, j; + + for (i = 0; msr_uncores[i]; i++) { + type = msr_uncores[i]; + for (j = 0; j < type->num_boxes; j++) { + pmu = &type->pmus[j]; + box = *per_cpu_ptr(pmu->box, cpu); + *per_cpu_ptr(pmu->box, cpu) = NULL; + if (box && atomic_dec_and_test(&box->refcnt)) + kfree(box); + } + } +} + +static int __cpuinit uncore_cpu_starting(int cpu) +{ + struct intel_uncore_type *type; + struct intel_uncore_pmu *pmu; + struct intel_uncore_box *box, *exist; + int i, j, k, phys_id; + + phys_id = topology_physical_package_id(cpu); + + for (i = 0; msr_uncores[i]; i++) { + type = msr_uncores[i]; + for (j = 0; j < type->num_boxes; j++) { + pmu = &type->pmus[j]; + box = *per_cpu_ptr(pmu->box, cpu); + /* called by uncore_cpu_init? */ + if (box && box->phys_id >= 0) { + uncore_box_init(box); + continue; + } + + for_each_online_cpu(k) { + exist = *per_cpu_ptr(pmu->box, k); + if (exist && exist->phys_id == phys_id) { + atomic_inc(&exist->refcnt); + *per_cpu_ptr(pmu->box, cpu) = exist; + kfree(box); + box = NULL; + break; + } + } + + if (box) { + box->phys_id = phys_id; + uncore_box_init(box); + } + } + } + return 0; +} + +static int __cpuinit uncore_cpu_prepare(int cpu, int phys_id) +{ + struct intel_uncore_type *type; + struct intel_uncore_pmu *pmu; + struct intel_uncore_box *box; + int i, j; + + for (i = 0; msr_uncores[i]; i++) { + type = msr_uncores[i]; + for (j = 0; j < type->num_boxes; j++) { + pmu = &type->pmus[j]; + if (pmu->func_id < 0) + pmu->func_id = j; + + box = uncore_alloc_box(cpu); + if (!box) + return -ENOMEM; + + box->pmu = pmu; + box->phys_id = phys_id; + *per_cpu_ptr(pmu->box, cpu) = box; + } + } + return 0; +} + +static void __cpuinit uncore_change_context(struct intel_uncore_type **uncores, + int old_cpu, int new_cpu) +{ + struct intel_uncore_type *type; + struct intel_uncore_pmu *pmu; + struct intel_uncore_box *box; + int i, j; + + for (i = 0; uncores[i]; i++) { + type = uncores[i]; + for (j = 0; j < type->num_boxes; j++) { + pmu = &type->pmus[j]; + if (old_cpu < 0) + box = uncore_pmu_to_box(pmu, new_cpu); + else + box = uncore_pmu_to_box(pmu, old_cpu); + if (!box) + continue; + + if (old_cpu < 0) { + WARN_ON_ONCE(box->cpu != -1); + box->cpu = new_cpu; + continue; + } + + WARN_ON_ONCE(box->cpu != old_cpu); + if (new_cpu >= 0) { + uncore_pmu_cancel_hrtimer(box); + perf_pmu_migrate_context(&pmu->pmu, + old_cpu, new_cpu); + box->cpu = new_cpu; + } else { + box->cpu = -1; + } + } + } +} + +static void __cpuinit uncore_event_exit_cpu(int cpu) +{ + int i, phys_id, target; + + /* if exiting cpu is used for collecting uncore events */ + if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask)) + return; + + /* find a new cpu to collect uncore events */ + phys_id = topology_physical_package_id(cpu); + target = -1; + for_each_online_cpu(i) { + if (i == cpu) + continue; + if (phys_id == topology_physical_package_id(i)) { + target = i; + break; + } + } + + /* migrate uncore events to the new cpu */ + if (target >= 0) + cpumask_set_cpu(target, &uncore_cpu_mask); + + uncore_change_context(msr_uncores, cpu, target); +} + +static void __cpuinit uncore_event_init_cpu(int cpu) +{ + int i, phys_id; + + phys_id = topology_physical_package_id(cpu); + for_each_cpu(i, &uncore_cpu_mask) { + if (phys_id == topology_physical_package_id(i)) + return; + } + + cpumask_set_cpu(cpu, &uncore_cpu_mask); + + uncore_change_context(msr_uncores, -1, cpu); +} + +static int __cpuinit uncore_cpu_notifier(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (long)hcpu; + + /* allocate/free data structure for uncore box */ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_UP_PREPARE: + uncore_cpu_prepare(cpu, -1); + break; + case CPU_STARTING: + uncore_cpu_starting(cpu); + break; + case CPU_UP_CANCELED: + case CPU_DYING: + uncore_cpu_dying(cpu); + break; + default: + break; + } + + /* select the cpu that collects uncore events */ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_DOWN_FAILED: + case CPU_STARTING: + uncore_event_init_cpu(cpu); + break; + case CPU_DOWN_PREPARE: + uncore_event_exit_cpu(cpu); + break; + default: + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block uncore_cpu_nb __cpuinitdata = { + .notifier_call = uncore_cpu_notifier, + /* + * to migrate uncore events, our notifier should be executed + * before perf core's notifier. + */ + .priority = CPU_PRI_PERF + 1, +}; + +static void __init uncore_cpu_setup(void *dummy) +{ + uncore_cpu_starting(smp_processor_id()); +} + +static int __init uncore_cpu_init(void) +{ + int ret, cpu; + + switch (boot_cpu_data.x86_model) { + default: + return 0; + } + + ret = uncore_types_init(msr_uncores); + if (ret) + return ret; + + get_online_cpus(); + + for_each_online_cpu(cpu) { + int i, phys_id = topology_physical_package_id(cpu); + + for_each_cpu(i, &uncore_cpu_mask) { + if (phys_id == topology_physical_package_id(i)) { + phys_id = -1; + break; + } + } + if (phys_id < 0) + continue; + + uncore_cpu_prepare(cpu, phys_id); + uncore_event_init_cpu(cpu); + } + on_each_cpu(uncore_cpu_setup, NULL, 1); + + register_cpu_notifier(&uncore_cpu_nb); + + put_online_cpus(); + + return 0; +} + +static int __init uncore_pmus_register(void) +{ + struct intel_uncore_pmu *pmu; + struct intel_uncore_type *type; + int i, j; + + for (i = 0; msr_uncores[i]; i++) { + type = msr_uncores[i]; + for (j = 0; j < type->num_boxes; j++) { + pmu = &type->pmus[j]; + uncore_pmu_register(pmu); + } + } + + return 0; +} + +static int __init intel_uncore_init(void) +{ + int ret; + + if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) + return -ENODEV; + + ret = uncore_cpu_init(); + if (ret) + goto fail; + + uncore_pmus_register(); + return 0; +fail: + return ret; +} +device_initcall(intel_uncore_init); diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h new file mode 100644 index 000000000000..49a6bfbba0de --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h @@ -0,0 +1,204 @@ +#include +#include +#include +#include "perf_event.h" + +#define UNCORE_PMU_NAME_LEN 32 +#define UNCORE_BOX_HASH_SIZE 8 + +#define UNCORE_PMU_HRTIMER_INTERVAL (60 * NSEC_PER_SEC) + +#define UNCORE_FIXED_EVENT 0xffff +#define UNCORE_PMC_IDX_MAX_GENERIC 8 +#define UNCORE_PMC_IDX_FIXED UNCORE_PMC_IDX_MAX_GENERIC +#define UNCORE_PMC_IDX_MAX (UNCORE_PMC_IDX_FIXED + 1) + +#define UNCORE_EVENT_CONSTRAINT(c, n) EVENT_CONSTRAINT(c, n, 0xff) + +struct intel_uncore_ops; +struct intel_uncore_pmu; +struct intel_uncore_box; +struct uncore_event_desc; + +struct intel_uncore_type { + const char *name; + int num_counters; + int num_boxes; + int perf_ctr_bits; + int fixed_ctr_bits; + int single_fixed; + unsigned perf_ctr; + unsigned event_ctl; + unsigned event_mask; + unsigned fixed_ctr; + unsigned fixed_ctl; + unsigned box_ctl; + unsigned msr_offset; + struct event_constraint unconstrainted; + struct event_constraint *constraints; + struct intel_uncore_pmu *pmus; + struct intel_uncore_ops *ops; + struct uncore_event_desc *event_descs; + const struct attribute_group *attr_groups[3]; +}; + +#define format_group attr_groups[0] + +struct intel_uncore_ops { + void (*init_box)(struct intel_uncore_box *); + void (*disable_box)(struct intel_uncore_box *); + void (*enable_box)(struct intel_uncore_box *); + void (*disable_event)(struct intel_uncore_box *, struct perf_event *); + void (*enable_event)(struct intel_uncore_box *, struct perf_event *); + u64 (*read_counter)(struct intel_uncore_box *, struct perf_event *); +}; + +struct intel_uncore_pmu { + struct pmu pmu; + char name[UNCORE_PMU_NAME_LEN]; + int pmu_idx; + int func_id; + struct intel_uncore_type *type; + struct intel_uncore_box ** __percpu box; +}; + +struct intel_uncore_box { + int phys_id; + int n_active; /* number of active events */ + int n_events; + int cpu; /* cpu to collect events */ + unsigned long flags; + atomic_t refcnt; + struct perf_event *events[UNCORE_PMC_IDX_MAX]; + struct perf_event *event_list[UNCORE_PMC_IDX_MAX]; + unsigned long active_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)]; + u64 tags[UNCORE_PMC_IDX_MAX]; + struct intel_uncore_pmu *pmu; + struct hrtimer hrtimer; + struct list_head list; +}; + +#define UNCORE_BOX_FLAG_INITIATED 0 + +struct uncore_event_desc { + struct kobj_attribute attr; + const char *config; +}; + +#define INTEL_UNCORE_EVENT_DESC(_name, _config) \ +{ \ + .attr = __ATTR(_name, 0444, uncore_event_show, NULL), \ + .config = _config, \ +} + +#define DEFINE_UNCORE_FORMAT_ATTR(_var, _name, _format) \ +static ssize_t __uncore_##_var##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, \ + char *page) \ +{ \ + BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ + return sprintf(page, _format "\n"); \ +} \ +static struct kobj_attribute format_attr_##_var = \ + __ATTR(_name, 0444, __uncore_##_var##_show, NULL) + + +static ssize_t uncore_event_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct uncore_event_desc *event = + container_of(attr, struct uncore_event_desc, attr); + return sprintf(buf, "%s", event->config); +} + +static inline +unsigned uncore_msr_box_ctl(struct intel_uncore_box *box) +{ + if (!box->pmu->type->box_ctl) + return 0; + return box->pmu->type->box_ctl + + box->pmu->type->msr_offset * box->pmu->pmu_idx; +} + +static inline +unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box) +{ + if (!box->pmu->type->fixed_ctl) + return 0; + return box->pmu->type->fixed_ctl + + box->pmu->type->msr_offset * box->pmu->pmu_idx; +} + +static inline +unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box) +{ + return box->pmu->type->fixed_ctr + + box->pmu->type->msr_offset * box->pmu->pmu_idx; +} + +static inline +unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx) +{ + return idx + box->pmu->type->event_ctl + + box->pmu->type->msr_offset * box->pmu->pmu_idx; +} + +static inline +unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx) +{ + return idx + box->pmu->type->perf_ctr + + box->pmu->type->msr_offset * box->pmu->pmu_idx; +} + +static inline int uncore_perf_ctr_bits(struct intel_uncore_box *box) +{ + return box->pmu->type->perf_ctr_bits; +} + +static inline int uncore_fixed_ctr_bits(struct intel_uncore_box *box) +{ + return box->pmu->type->fixed_ctr_bits; +} + +static inline int uncore_num_counters(struct intel_uncore_box *box) +{ + return box->pmu->type->num_counters; +} + +static inline void uncore_disable_box(struct intel_uncore_box *box) +{ + if (box->pmu->type->ops->disable_box) + box->pmu->type->ops->disable_box(box); +} + +static inline void uncore_enable_box(struct intel_uncore_box *box) +{ + if (box->pmu->type->ops->enable_box) + box->pmu->type->ops->enable_box(box); +} + +static inline void uncore_disable_event(struct intel_uncore_box *box, + struct perf_event *event) +{ + box->pmu->type->ops->disable_event(box, event); +} + +static inline void uncore_enable_event(struct intel_uncore_box *box, + struct perf_event *event) +{ + box->pmu->type->ops->enable_event(box, event); +} + +static inline u64 uncore_read_counter(struct intel_uncore_box *box, + struct perf_event *event) +{ + return box->pmu->type->ops->read_counter(box, event); +} + +static inline void uncore_box_init(struct intel_uncore_box *box) +{ + if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) { + if (box->pmu->type->ops->init_box) + box->pmu->type->ops->init_box(box); + } +} -- cgit v1.2.3 From fcde10e916326545e8fec1807357c68ef08dc443 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Fri, 15 Jun 2012 14:31:35 +0800 Subject: perf/x86: Add Intel Nehalem and Sandy Bridge uncore PMU support Signed-off-by: Zheng Yan Signed-off-by: Peter Zijlstra Cc: Linus Torvalds Cc: Andrew Morton Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1339741902-8449-7-git-send-email-zheng.z.yan@intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel_uncore.c | 195 ++++++++++++++++++++++++++ arch/x86/kernel/cpu/perf_event_intel_uncore.h | 50 +++++++ 2 files changed, 245 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index fe76a07dfdbc..3ed941ac3745 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -10,6 +10,192 @@ static cpumask_t uncore_cpu_mask; static struct event_constraint constraint_fixed = EVENT_CONSTRAINT(~0ULL, 1 << UNCORE_PMC_IDX_FIXED, ~0ULL); +DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7"); +DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15"); +DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18"); +DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23"); +DEFINE_UNCORE_FORMAT_ATTR(cmask5, cmask, "config:24-28"); +DEFINE_UNCORE_FORMAT_ATTR(cmask8, cmask, "config:24-31"); + +/* Sandy Bridge uncore support */ +static void snb_uncore_msr_enable_event(struct intel_uncore_box *box, + struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + + if (hwc->idx < UNCORE_PMC_IDX_FIXED) + wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN); + else + wrmsrl(hwc->config_base, SNB_UNC_CTL_EN); +} + +static void snb_uncore_msr_disable_event(struct intel_uncore_box *box, + struct perf_event *event) +{ + wrmsrl(event->hw.config_base, 0); +} + +static u64 snb_uncore_msr_read_counter(struct intel_uncore_box *box, + struct perf_event *event) +{ + u64 count; + rdmsrl(event->hw.event_base, count); + return count; +} + +static void snb_uncore_msr_init_box(struct intel_uncore_box *box) +{ + if (box->pmu->pmu_idx == 0) { + wrmsrl(SNB_UNC_PERF_GLOBAL_CTL, + SNB_UNC_GLOBAL_CTL_EN | SNB_UNC_GLOBAL_CTL_CORE_ALL); + } +} + +static struct attribute *snb_uncore_formats_attr[] = { + &format_attr_event.attr, + &format_attr_umask.attr, + &format_attr_edge.attr, + &format_attr_inv.attr, + &format_attr_cmask5.attr, + NULL, +}; + +static struct attribute_group snb_uncore_format_group = { + .name = "format", + .attrs = snb_uncore_formats_attr, +}; + +static struct intel_uncore_ops snb_uncore_msr_ops = { + .init_box = snb_uncore_msr_init_box, + .disable_event = snb_uncore_msr_disable_event, + .enable_event = snb_uncore_msr_enable_event, + .read_counter = snb_uncore_msr_read_counter, +}; + +static struct event_constraint snb_uncore_cbox_constraints[] = { + UNCORE_EVENT_CONSTRAINT(0x80, 0x1), + UNCORE_EVENT_CONSTRAINT(0x83, 0x1), + EVENT_CONSTRAINT_END +}; + +static struct intel_uncore_type snb_uncore_cbox = { + .name = "cbox", + .num_counters = 2, + .num_boxes = 4, + .perf_ctr_bits = 44, + .fixed_ctr_bits = 48, + .perf_ctr = SNB_UNC_CBO_0_PER_CTR0, + .event_ctl = SNB_UNC_CBO_0_PERFEVTSEL0, + .fixed_ctr = SNB_UNC_FIXED_CTR, + .fixed_ctl = SNB_UNC_FIXED_CTR_CTRL, + .single_fixed = 1, + .event_mask = SNB_UNC_RAW_EVENT_MASK, + .msr_offset = SNB_UNC_CBO_MSR_OFFSET, + .constraints = snb_uncore_cbox_constraints, + .ops = &snb_uncore_msr_ops, + .format_group = &snb_uncore_format_group, +}; + +static struct intel_uncore_type *snb_msr_uncores[] = { + &snb_uncore_cbox, + NULL, +}; +/* end of Sandy Bridge uncore support */ + +/* Nehalem uncore support */ +static void nhm_uncore_msr_disable_box(struct intel_uncore_box *box) +{ + wrmsrl(NHM_UNC_PERF_GLOBAL_CTL, 0); +} + +static void nhm_uncore_msr_enable_box(struct intel_uncore_box *box) +{ + wrmsrl(NHM_UNC_PERF_GLOBAL_CTL, + NHM_UNC_GLOBAL_CTL_EN_PC_ALL | NHM_UNC_GLOBAL_CTL_EN_FC); +} + +static void nhm_uncore_msr_enable_event(struct intel_uncore_box *box, + struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + + if (hwc->idx < UNCORE_PMC_IDX_FIXED) + wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN); + else + wrmsrl(hwc->config_base, NHM_UNC_FIXED_CTR_CTL_EN); +} + +static struct attribute *nhm_uncore_formats_attr[] = { + &format_attr_event.attr, + &format_attr_umask.attr, + &format_attr_edge.attr, + &format_attr_inv.attr, + &format_attr_cmask8.attr, + NULL, +}; + +static struct attribute_group nhm_uncore_format_group = { + .name = "format", + .attrs = nhm_uncore_formats_attr, +}; + +static struct uncore_event_desc nhm_uncore_events[] = { + INTEL_UNCORE_EVENT_DESC(CLOCKTICKS, "config=0xffff"), + /* full cache line writes to DRAM */ + INTEL_UNCORE_EVENT_DESC(QMC_WRITES_FULL_ANY, "event=0x2f,umask=0xf"), + /* Quickpath Memory Controller normal priority read requests */ + INTEL_UNCORE_EVENT_DESC(QMC_NORMAL_READS_ANY, "event=0x2c,umask=0xf"), + /* Quickpath Home Logic read requests from the IOH */ + INTEL_UNCORE_EVENT_DESC(QHL_REQUEST_IOH_READS, + "event=0x20,umask=0x1"), + /* Quickpath Home Logic write requests from the IOH */ + INTEL_UNCORE_EVENT_DESC(QHL_REQUEST_IOH_WRITES, + "event=0x20,umask=0x2"), + /* Quickpath Home Logic read requests from a remote socket */ + INTEL_UNCORE_EVENT_DESC(QHL_REQUEST_REMOTE_READS, + "event=0x20,umask=0x4"), + /* Quickpath Home Logic write requests from a remote socket */ + INTEL_UNCORE_EVENT_DESC(QHL_REQUEST_REMOTE_WRITES, + "event=0x20,umask=0x8"), + /* Quickpath Home Logic read requests from the local socket */ + INTEL_UNCORE_EVENT_DESC(QHL_REQUEST_LOCAL_READS, + "event=0x20,umask=0x10"), + /* Quickpath Home Logic write requests from the local socket */ + INTEL_UNCORE_EVENT_DESC(QHL_REQUEST_LOCAL_WRITES, + "event=0x20,umask=0x20"), + { /* end: all zeroes */ }, +}; + +static struct intel_uncore_ops nhm_uncore_msr_ops = { + .disable_box = nhm_uncore_msr_disable_box, + .enable_box = nhm_uncore_msr_enable_box, + .disable_event = snb_uncore_msr_disable_event, + .enable_event = nhm_uncore_msr_enable_event, + .read_counter = snb_uncore_msr_read_counter, +}; + +static struct intel_uncore_type nhm_uncore = { + .name = "", + .num_counters = 8, + .num_boxes = 1, + .perf_ctr_bits = 48, + .fixed_ctr_bits = 48, + .event_ctl = NHM_UNC_PERFEVTSEL0, + .perf_ctr = NHM_UNC_UNCORE_PMC0, + .fixed_ctr = NHM_UNC_FIXED_CTR, + .fixed_ctl = NHM_UNC_FIXED_CTR_CTRL, + .event_mask = NHM_UNC_RAW_EVENT_MASK, + .event_descs = nhm_uncore_events, + .ops = &nhm_uncore_msr_ops, + .format_group = &nhm_uncore_format_group, +}; + +static struct intel_uncore_type *nhm_msr_uncores[] = { + &nhm_uncore, + NULL, +}; +/* end of Nehalem uncore support */ + static void uncore_assign_hw_event(struct intel_uncore_box *box, struct perf_event *event, int idx) { @@ -808,6 +994,15 @@ static int __init uncore_cpu_init(void) int ret, cpu; switch (boot_cpu_data.x86_model) { + case 26: /* Nehalem */ + case 30: + case 37: /* Westmere */ + case 44: + msr_uncores = nhm_msr_uncores; + break; + case 42: /* Sandy Bridge */ + msr_uncores = snb_msr_uncores; + break; default: return 0; } diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index 49a6bfbba0de..eeb5ca5815a8 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h @@ -15,6 +15,56 @@ #define UNCORE_EVENT_CONSTRAINT(c, n) EVENT_CONSTRAINT(c, n, 0xff) +/* SNB event control */ +#define SNB_UNC_CTL_EV_SEL_MASK 0x000000ff +#define SNB_UNC_CTL_UMASK_MASK 0x0000ff00 +#define SNB_UNC_CTL_EDGE_DET (1 << 18) +#define SNB_UNC_CTL_EN (1 << 22) +#define SNB_UNC_CTL_INVERT (1 << 23) +#define SNB_UNC_CTL_CMASK_MASK 0x1f000000 +#define NHM_UNC_CTL_CMASK_MASK 0xff000000 +#define NHM_UNC_FIXED_CTR_CTL_EN (1 << 0) + +#define SNB_UNC_RAW_EVENT_MASK (SNB_UNC_CTL_EV_SEL_MASK | \ + SNB_UNC_CTL_UMASK_MASK | \ + SNB_UNC_CTL_EDGE_DET | \ + SNB_UNC_CTL_INVERT | \ + SNB_UNC_CTL_CMASK_MASK) + +#define NHM_UNC_RAW_EVENT_MASK (SNB_UNC_CTL_EV_SEL_MASK | \ + SNB_UNC_CTL_UMASK_MASK | \ + SNB_UNC_CTL_EDGE_DET | \ + SNB_UNC_CTL_INVERT | \ + NHM_UNC_CTL_CMASK_MASK) + +/* SNB global control register */ +#define SNB_UNC_PERF_GLOBAL_CTL 0x391 +#define SNB_UNC_FIXED_CTR_CTRL 0x394 +#define SNB_UNC_FIXED_CTR 0x395 + +/* SNB uncore global control */ +#define SNB_UNC_GLOBAL_CTL_CORE_ALL ((1 << 4) - 1) +#define SNB_UNC_GLOBAL_CTL_EN (1 << 29) + +/* SNB Cbo register */ +#define SNB_UNC_CBO_0_PERFEVTSEL0 0x700 +#define SNB_UNC_CBO_0_PER_CTR0 0x706 +#define SNB_UNC_CBO_MSR_OFFSET 0x10 + +/* NHM global control register */ +#define NHM_UNC_PERF_GLOBAL_CTL 0x391 +#define NHM_UNC_FIXED_CTR 0x394 +#define NHM_UNC_FIXED_CTR_CTRL 0x395 + +/* NHM uncore global control */ +#define NHM_UNC_GLOBAL_CTL_EN_PC_ALL ((1ULL << 8) - 1) +#define NHM_UNC_GLOBAL_CTL_EN_FC (1ULL << 32) + +/* NHM uncore register */ +#define NHM_UNC_PERFEVTSEL0 0x3c0 +#define NHM_UNC_UNCORE_PMC0 0x3b0 + + struct intel_uncore_ops; struct intel_uncore_pmu; struct intel_uncore_box; -- cgit v1.2.3 From 14371cce03c2fc393997e17f979e76674b7f392a Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Fri, 15 Jun 2012 14:31:36 +0800 Subject: perf: Add generic PCI uncore PMU device support This patch adds generic support for uncore PMUs presented as PCI devices. (These come in addition to the CPU/MSR based uncores.) Signed-off-by: Zheng Yan Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1339741902-8449-8-git-send-email-zheng.z.yan@intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel_uncore.c | 175 +++++++++++++++++++++++++- arch/x86/kernel/cpu/perf_event_intel_uncore.h | 66 ++++++++++ 2 files changed, 236 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 3ed941ac3745..e20c65a0e108 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -2,6 +2,11 @@ static struct intel_uncore_type *empty_uncore[] = { NULL, }; static struct intel_uncore_type **msr_uncores = empty_uncore; +static struct intel_uncore_type **pci_uncores = empty_uncore; +/* pci bus to socket mapping */ +static int pcibus_to_physid[256] = { [0 ... 255] = -1, }; + +static DEFINE_RAW_SPINLOCK(uncore_box_lock); /* mask of cpus that collect uncore events */ static cpumask_t uncore_cpu_mask; @@ -205,13 +210,13 @@ static void uncore_assign_hw_event(struct intel_uncore_box *box, hwc->last_tag = ++box->tags[idx]; if (hwc->idx == UNCORE_PMC_IDX_FIXED) { - hwc->event_base = uncore_msr_fixed_ctr(box); - hwc->config_base = uncore_msr_fixed_ctl(box); + hwc->event_base = uncore_fixed_ctr(box); + hwc->config_base = uncore_fixed_ctl(box); return; } - hwc->config_base = uncore_msr_event_ctl(box, hwc->idx); - hwc->event_base = uncore_msr_perf_ctr(box, hwc->idx); + hwc->config_base = uncore_event_ctl(box, hwc->idx); + hwc->event_base = uncore_perf_ctr(box, hwc->idx); } static void uncore_perf_event_update(struct intel_uncore_box *box, @@ -305,6 +310,22 @@ struct intel_uncore_box *uncore_alloc_box(int cpu) static struct intel_uncore_box * uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu) { + static struct intel_uncore_box *box; + + box = *per_cpu_ptr(pmu->box, cpu); + if (box) + return box; + + raw_spin_lock(&uncore_box_lock); + list_for_each_entry(box, &pmu->box_list, list) { + if (box->phys_id == topology_physical_package_id(cpu)) { + atomic_inc(&box->refcnt); + *per_cpu_ptr(pmu->box, cpu) = box; + break; + } + } + raw_spin_unlock(&uncore_box_lock); + return *per_cpu_ptr(pmu->box, cpu); } @@ -706,6 +727,13 @@ static void __init uncore_type_exit(struct intel_uncore_type *type) type->attr_groups[1] = NULL; } +static void uncore_types_exit(struct intel_uncore_type **types) +{ + int i; + for (i = 0; types[i]; i++) + uncore_type_exit(types[i]); +} + static int __init uncore_type_init(struct intel_uncore_type *type) { struct intel_uncore_pmu *pmus; @@ -725,6 +753,7 @@ static int __init uncore_type_init(struct intel_uncore_type *type) pmus[i].func_id = -1; pmus[i].pmu_idx = i; pmus[i].type = type; + INIT_LIST_HEAD(&pmus[i].box_list); pmus[i].box = alloc_percpu(struct intel_uncore_box *); if (!pmus[i].box) goto fail; @@ -773,6 +802,127 @@ fail: return ret; } +static struct pci_driver *uncore_pci_driver; +static bool pcidrv_registered; + +/* + * add a pci uncore device + */ +static int __devinit uncore_pci_add(struct intel_uncore_type *type, + struct pci_dev *pdev) +{ + struct intel_uncore_pmu *pmu; + struct intel_uncore_box *box; + int i, phys_id; + + phys_id = pcibus_to_physid[pdev->bus->number]; + if (phys_id < 0) + return -ENODEV; + + box = uncore_alloc_box(0); + if (!box) + return -ENOMEM; + + /* + * for performance monitoring unit with multiple boxes, + * each box has a different function id. + */ + for (i = 0; i < type->num_boxes; i++) { + pmu = &type->pmus[i]; + if (pmu->func_id == pdev->devfn) + break; + if (pmu->func_id < 0) { + pmu->func_id = pdev->devfn; + break; + } + pmu = NULL; + } + + if (!pmu) { + kfree(box); + return -EINVAL; + } + + box->phys_id = phys_id; + box->pci_dev = pdev; + box->pmu = pmu; + uncore_box_init(box); + pci_set_drvdata(pdev, box); + + raw_spin_lock(&uncore_box_lock); + list_add_tail(&box->list, &pmu->box_list); + raw_spin_unlock(&uncore_box_lock); + + return 0; +} + +static void __devexit uncore_pci_remove(struct pci_dev *pdev) +{ + struct intel_uncore_box *box = pci_get_drvdata(pdev); + struct intel_uncore_pmu *pmu = box->pmu; + int cpu, phys_id = pcibus_to_physid[pdev->bus->number]; + + if (WARN_ON_ONCE(phys_id != box->phys_id)) + return; + + raw_spin_lock(&uncore_box_lock); + list_del(&box->list); + raw_spin_unlock(&uncore_box_lock); + + for_each_possible_cpu(cpu) { + if (*per_cpu_ptr(pmu->box, cpu) == box) { + *per_cpu_ptr(pmu->box, cpu) = NULL; + atomic_dec(&box->refcnt); + } + } + + WARN_ON_ONCE(atomic_read(&box->refcnt) != 1); + kfree(box); +} + +static int __devinit uncore_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct intel_uncore_type *type; + + type = (struct intel_uncore_type *)id->driver_data; + return uncore_pci_add(type, pdev); +} + +static int __init uncore_pci_init(void) +{ + int ret; + + switch (boot_cpu_data.x86_model) { + default: + return 0; + } + + ret = uncore_types_init(pci_uncores); + if (ret) + return ret; + + uncore_pci_driver->probe = uncore_pci_probe; + uncore_pci_driver->remove = uncore_pci_remove; + + ret = pci_register_driver(uncore_pci_driver); + if (ret == 0) + pcidrv_registered = true; + else + uncore_types_exit(pci_uncores); + + return ret; +} + +static void __init uncore_pci_exit(void) +{ + if (pcidrv_registered) { + pcidrv_registered = false; + pci_unregister_driver(uncore_pci_driver); + uncore_types_exit(pci_uncores); + } +} + static void __cpuinit uncore_cpu_dying(int cpu) { struct intel_uncore_type *type; @@ -921,6 +1071,7 @@ static void __cpuinit uncore_event_exit_cpu(int cpu) cpumask_set_cpu(target, &uncore_cpu_mask); uncore_change_context(msr_uncores, cpu, target); + uncore_change_context(pci_uncores, cpu, target); } static void __cpuinit uncore_event_init_cpu(int cpu) @@ -936,6 +1087,7 @@ static void __cpuinit uncore_event_init_cpu(int cpu) cpumask_set_cpu(cpu, &uncore_cpu_mask); uncore_change_context(msr_uncores, -1, cpu); + uncore_change_context(pci_uncores, -1, cpu); } static int __cpuinit uncore_cpu_notifier(struct notifier_block *self, @@ -1051,6 +1203,14 @@ static int __init uncore_pmus_register(void) } } + for (i = 0; pci_uncores[i]; i++) { + type = pci_uncores[i]; + for (j = 0; j < type->num_boxes; j++) { + pmu = &type->pmus[j]; + uncore_pmu_register(pmu); + } + } + return 0; } @@ -1061,9 +1221,14 @@ static int __init intel_uncore_init(void) if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) return -ENODEV; - ret = uncore_cpu_init(); + ret = uncore_pci_init(); if (ret) goto fail; + ret = uncore_cpu_init(); + if (ret) { + uncore_pci_exit(); + goto fail; + } uncore_pmus_register(); return 0; diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index eeb5ca5815a8..aa01df87b8de 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h @@ -1,5 +1,6 @@ #include #include +#include #include #include "perf_event.h" @@ -110,6 +111,7 @@ struct intel_uncore_pmu { int func_id; struct intel_uncore_type *type; struct intel_uncore_box ** __percpu box; + struct list_head box_list; }; struct intel_uncore_box { @@ -123,6 +125,7 @@ struct intel_uncore_box { struct perf_event *event_list[UNCORE_PMC_IDX_MAX]; unsigned long active_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)]; u64 tags[UNCORE_PMC_IDX_MAX]; + struct pci_dev *pci_dev; struct intel_uncore_pmu *pmu; struct hrtimer hrtimer; struct list_head list; @@ -161,6 +164,33 @@ static ssize_t uncore_event_show(struct kobject *kobj, return sprintf(buf, "%s", event->config); } +static inline unsigned uncore_pci_box_ctl(struct intel_uncore_box *box) +{ + return box->pmu->type->box_ctl; +} + +static inline unsigned uncore_pci_fixed_ctl(struct intel_uncore_box *box) +{ + return box->pmu->type->fixed_ctl; +} + +static inline unsigned uncore_pci_fixed_ctr(struct intel_uncore_box *box) +{ + return box->pmu->type->fixed_ctr; +} + +static inline +unsigned uncore_pci_event_ctl(struct intel_uncore_box *box, int idx) +{ + return idx * 4 + box->pmu->type->event_ctl; +} + +static inline +unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx) +{ + return idx * 8 + box->pmu->type->perf_ctr; +} + static inline unsigned uncore_msr_box_ctl(struct intel_uncore_box *box) { @@ -200,6 +230,42 @@ unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx) box->pmu->type->msr_offset * box->pmu->pmu_idx; } +static inline +unsigned uncore_fixed_ctl(struct intel_uncore_box *box) +{ + if (box->pci_dev) + return uncore_pci_fixed_ctl(box); + else + return uncore_msr_fixed_ctl(box); +} + +static inline +unsigned uncore_fixed_ctr(struct intel_uncore_box *box) +{ + if (box->pci_dev) + return uncore_pci_fixed_ctr(box); + else + return uncore_msr_fixed_ctr(box); +} + +static inline +unsigned uncore_event_ctl(struct intel_uncore_box *box, int idx) +{ + if (box->pci_dev) + return uncore_pci_event_ctl(box, idx); + else + return uncore_msr_event_ctl(box, idx); +} + +static inline +unsigned uncore_perf_ctr(struct intel_uncore_box *box, int idx) +{ + if (box->pci_dev) + return uncore_pci_perf_ctr(box, idx); + else + return uncore_msr_perf_ctr(box, idx); +} + static inline int uncore_perf_ctr_bits(struct intel_uncore_box *box) { return box->pmu->type->perf_ctr_bits; -- cgit v1.2.3 From 7c94ee2e0917b2ea56498bff939c8aa55da27207 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Fri, 15 Jun 2012 14:31:37 +0800 Subject: perf/x86: Add Intel Nehalem and Sandy Bridge-EP uncore support The uncore subsystem in Sandy Bridge-EP consists of 8 components: Ubox, Cacheing Agent, Home Agent, Memory controller, Power Control, QPI Link Layer, R2PCIe, R3QPI. Signed-off-by: Zheng Yan Signed-off-by: Peter Zijlstra Cc: Linus Torvalds Cc: Andrew Morton Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1339741902-8449-9-git-send-email-zheng.z.yan@intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel_uncore.c | 484 ++++++++++++++++++++++++++ arch/x86/kernel/cpu/perf_event_intel_uncore.h | 86 +++++ include/linux/pci_ids.h | 11 + 3 files changed, 581 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index e20c65a0e108..d34f68bf990b 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -21,6 +21,482 @@ DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18"); DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23"); DEFINE_UNCORE_FORMAT_ATTR(cmask5, cmask, "config:24-28"); DEFINE_UNCORE_FORMAT_ATTR(cmask8, cmask, "config:24-31"); +DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31"); +DEFINE_UNCORE_FORMAT_ATTR(thresh5, thresh, "config:24-28"); +DEFINE_UNCORE_FORMAT_ATTR(occ_sel, occ_sel, "config:14-15"); +DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30"); +DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51"); + +/* Sandy Bridge-EP uncore support */ +static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box) +{ + struct pci_dev *pdev = box->pci_dev; + int box_ctl = uncore_pci_box_ctl(box); + u32 config; + + pci_read_config_dword(pdev, box_ctl, &config); + config |= SNBEP_PMON_BOX_CTL_FRZ; + pci_write_config_dword(pdev, box_ctl, config); +} + +static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box) +{ + struct pci_dev *pdev = box->pci_dev; + int box_ctl = uncore_pci_box_ctl(box); + u32 config; + + pci_read_config_dword(pdev, box_ctl, &config); + config &= ~SNBEP_PMON_BOX_CTL_FRZ; + pci_write_config_dword(pdev, box_ctl, config); +} + +static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, + struct perf_event *event) +{ + struct pci_dev *pdev = box->pci_dev; + struct hw_perf_event *hwc = &event->hw; + + pci_write_config_dword(pdev, hwc->config_base, hwc->config | + SNBEP_PMON_CTL_EN); +} + +static void snbep_uncore_pci_disable_event(struct intel_uncore_box *box, + struct perf_event *event) +{ + struct pci_dev *pdev = box->pci_dev; + struct hw_perf_event *hwc = &event->hw; + + pci_write_config_dword(pdev, hwc->config_base, hwc->config); +} + +static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, + struct perf_event *event) +{ + struct pci_dev *pdev = box->pci_dev; + struct hw_perf_event *hwc = &event->hw; + u64 count; + + pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count); + pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1); + return count; +} + +static void snbep_uncore_pci_init_box(struct intel_uncore_box *box) +{ + struct pci_dev *pdev = box->pci_dev; + pci_write_config_dword(pdev, SNBEP_PCI_PMON_BOX_CTL, + SNBEP_PMON_BOX_CTL_INT); +} + +static void snbep_uncore_msr_disable_box(struct intel_uncore_box *box) +{ + u64 config; + unsigned msr; + + msr = uncore_msr_box_ctl(box); + if (msr) { + rdmsrl(msr, config); + config |= SNBEP_PMON_BOX_CTL_FRZ; + wrmsrl(msr, config); + return; + } +} + +static void snbep_uncore_msr_enable_box(struct intel_uncore_box *box) +{ + u64 config; + unsigned msr; + + msr = uncore_msr_box_ctl(box); + if (msr) { + rdmsrl(msr, config); + config &= ~SNBEP_PMON_BOX_CTL_FRZ; + wrmsrl(msr, config); + return; + } +} + +static void snbep_uncore_msr_enable_event(struct intel_uncore_box *box, + struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + + wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN); +} + +static void snbep_uncore_msr_disable_event(struct intel_uncore_box *box, + struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + + wrmsrl(hwc->config_base, hwc->config); +} + +static u64 snbep_uncore_msr_read_counter(struct intel_uncore_box *box, + struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + u64 count; + + rdmsrl(hwc->event_base, count); + return count; +} + +static void snbep_uncore_msr_init_box(struct intel_uncore_box *box) +{ + unsigned msr = uncore_msr_box_ctl(box); + if (msr) + wrmsrl(msr, SNBEP_PMON_BOX_CTL_INT); +} + +static struct attribute *snbep_uncore_formats_attr[] = { + &format_attr_event.attr, + &format_attr_umask.attr, + &format_attr_edge.attr, + &format_attr_inv.attr, + &format_attr_thresh8.attr, + NULL, +}; + +static struct attribute *snbep_uncore_ubox_formats_attr[] = { + &format_attr_event.attr, + &format_attr_umask.attr, + &format_attr_edge.attr, + &format_attr_inv.attr, + &format_attr_thresh5.attr, + NULL, +}; + +static struct attribute *snbep_uncore_pcu_formats_attr[] = { + &format_attr_event.attr, + &format_attr_occ_sel.attr, + &format_attr_edge.attr, + &format_attr_inv.attr, + &format_attr_thresh5.attr, + &format_attr_occ_invert.attr, + &format_attr_occ_edge.attr, + NULL, +}; + +static struct uncore_event_desc snbep_uncore_imc_events[] = { + INTEL_UNCORE_EVENT_DESC(CLOCKTICKS, "config=0xffff"), + /* read */ + INTEL_UNCORE_EVENT_DESC(CAS_COUNT_RD, "event=0x4,umask=0x3"), + /* write */ + INTEL_UNCORE_EVENT_DESC(CAS_COUNT_WR, "event=0x4,umask=0xc"), + { /* end: all zeroes */ }, +}; + +static struct uncore_event_desc snbep_uncore_qpi_events[] = { + INTEL_UNCORE_EVENT_DESC(CLOCKTICKS, "event=0x14"), + /* outgoing data+nondata flits */ + INTEL_UNCORE_EVENT_DESC(TxL_FLITS_ACTIVE, "event=0x0,umask=0x6"), + /* DRS data received */ + INTEL_UNCORE_EVENT_DESC(DRS_DATA, "event=0x2,umask=0x8"), + /* NCB data received */ + INTEL_UNCORE_EVENT_DESC(NCB_DATA, "event=0x3,umask=0x4"), + { /* end: all zeroes */ }, +}; + +static struct attribute_group snbep_uncore_format_group = { + .name = "format", + .attrs = snbep_uncore_formats_attr, +}; + +static struct attribute_group snbep_uncore_ubox_format_group = { + .name = "format", + .attrs = snbep_uncore_ubox_formats_attr, +}; + +static struct attribute_group snbep_uncore_pcu_format_group = { + .name = "format", + .attrs = snbep_uncore_pcu_formats_attr, +}; + +static struct intel_uncore_ops snbep_uncore_msr_ops = { + .init_box = snbep_uncore_msr_init_box, + .disable_box = snbep_uncore_msr_disable_box, + .enable_box = snbep_uncore_msr_enable_box, + .disable_event = snbep_uncore_msr_disable_event, + .enable_event = snbep_uncore_msr_enable_event, + .read_counter = snbep_uncore_msr_read_counter, +}; + +static struct intel_uncore_ops snbep_uncore_pci_ops = { + .init_box = snbep_uncore_pci_init_box, + .disable_box = snbep_uncore_pci_disable_box, + .enable_box = snbep_uncore_pci_enable_box, + .disable_event = snbep_uncore_pci_disable_event, + .enable_event = snbep_uncore_pci_enable_event, + .read_counter = snbep_uncore_pci_read_counter, +}; + +static struct event_constraint snbep_uncore_cbox_constraints[] = { + UNCORE_EVENT_CONSTRAINT(0x01, 0x1), + UNCORE_EVENT_CONSTRAINT(0x02, 0x3), + UNCORE_EVENT_CONSTRAINT(0x04, 0x3), + UNCORE_EVENT_CONSTRAINT(0x05, 0x3), + UNCORE_EVENT_CONSTRAINT(0x07, 0x3), + UNCORE_EVENT_CONSTRAINT(0x11, 0x1), + UNCORE_EVENT_CONSTRAINT(0x12, 0x3), + UNCORE_EVENT_CONSTRAINT(0x13, 0x3), + UNCORE_EVENT_CONSTRAINT(0x1b, 0xc), + UNCORE_EVENT_CONSTRAINT(0x1c, 0xc), + UNCORE_EVENT_CONSTRAINT(0x1d, 0xc), + UNCORE_EVENT_CONSTRAINT(0x1e, 0xc), + UNCORE_EVENT_CONSTRAINT(0x1f, 0xe), + UNCORE_EVENT_CONSTRAINT(0x21, 0x3), + UNCORE_EVENT_CONSTRAINT(0x23, 0x3), + UNCORE_EVENT_CONSTRAINT(0x31, 0x3), + UNCORE_EVENT_CONSTRAINT(0x32, 0x3), + UNCORE_EVENT_CONSTRAINT(0x33, 0x3), + UNCORE_EVENT_CONSTRAINT(0x34, 0x3), + UNCORE_EVENT_CONSTRAINT(0x35, 0x3), + UNCORE_EVENT_CONSTRAINT(0x36, 0x1), + UNCORE_EVENT_CONSTRAINT(0x37, 0x3), + UNCORE_EVENT_CONSTRAINT(0x38, 0x3), + UNCORE_EVENT_CONSTRAINT(0x39, 0x3), + UNCORE_EVENT_CONSTRAINT(0x3b, 0x1), + EVENT_CONSTRAINT_END +}; + +static struct event_constraint snbep_uncore_r2pcie_constraints[] = { + UNCORE_EVENT_CONSTRAINT(0x10, 0x3), + UNCORE_EVENT_CONSTRAINT(0x11, 0x3), + UNCORE_EVENT_CONSTRAINT(0x12, 0x1), + UNCORE_EVENT_CONSTRAINT(0x23, 0x3), + UNCORE_EVENT_CONSTRAINT(0x24, 0x3), + UNCORE_EVENT_CONSTRAINT(0x25, 0x3), + UNCORE_EVENT_CONSTRAINT(0x26, 0x3), + UNCORE_EVENT_CONSTRAINT(0x32, 0x3), + UNCORE_EVENT_CONSTRAINT(0x33, 0x3), + UNCORE_EVENT_CONSTRAINT(0x34, 0x3), + EVENT_CONSTRAINT_END +}; + +static struct event_constraint snbep_uncore_r3qpi_constraints[] = { + UNCORE_EVENT_CONSTRAINT(0x10, 0x3), + UNCORE_EVENT_CONSTRAINT(0x11, 0x3), + UNCORE_EVENT_CONSTRAINT(0x12, 0x3), + UNCORE_EVENT_CONSTRAINT(0x13, 0x1), + UNCORE_EVENT_CONSTRAINT(0x20, 0x3), + UNCORE_EVENT_CONSTRAINT(0x21, 0x3), + UNCORE_EVENT_CONSTRAINT(0x22, 0x3), + UNCORE_EVENT_CONSTRAINT(0x23, 0x3), + UNCORE_EVENT_CONSTRAINT(0x24, 0x3), + UNCORE_EVENT_CONSTRAINT(0x25, 0x3), + UNCORE_EVENT_CONSTRAINT(0x26, 0x3), + UNCORE_EVENT_CONSTRAINT(0x30, 0x3), + UNCORE_EVENT_CONSTRAINT(0x31, 0x3), + UNCORE_EVENT_CONSTRAINT(0x32, 0x3), + UNCORE_EVENT_CONSTRAINT(0x33, 0x3), + UNCORE_EVENT_CONSTRAINT(0x34, 0x3), + UNCORE_EVENT_CONSTRAINT(0x36, 0x3), + UNCORE_EVENT_CONSTRAINT(0x37, 0x3), + EVENT_CONSTRAINT_END +}; + +static struct intel_uncore_type snbep_uncore_ubox = { + .name = "ubox", + .num_counters = 2, + .num_boxes = 1, + .perf_ctr_bits = 44, + .fixed_ctr_bits = 48, + .perf_ctr = SNBEP_U_MSR_PMON_CTR0, + .event_ctl = SNBEP_U_MSR_PMON_CTL0, + .event_mask = SNBEP_U_MSR_PMON_RAW_EVENT_MASK, + .fixed_ctr = SNBEP_U_MSR_PMON_UCLK_FIXED_CTR, + .fixed_ctl = SNBEP_U_MSR_PMON_UCLK_FIXED_CTL, + .ops = &snbep_uncore_msr_ops, + .format_group = &snbep_uncore_ubox_format_group, +}; + +static struct intel_uncore_type snbep_uncore_cbox = { + .name = "cbox", + .num_counters = 4, + .num_boxes = 8, + .perf_ctr_bits = 44, + .event_ctl = SNBEP_C0_MSR_PMON_CTL0, + .perf_ctr = SNBEP_C0_MSR_PMON_CTR0, + .event_mask = SNBEP_PMON_RAW_EVENT_MASK, + .box_ctl = SNBEP_C0_MSR_PMON_BOX_CTL, + .msr_offset = SNBEP_CBO_MSR_OFFSET, + .constraints = snbep_uncore_cbox_constraints, + .ops = &snbep_uncore_msr_ops, + .format_group = &snbep_uncore_format_group, +}; + +static struct intel_uncore_type snbep_uncore_pcu = { + .name = "pcu", + .num_counters = 4, + .num_boxes = 1, + .perf_ctr_bits = 48, + .perf_ctr = SNBEP_PCU_MSR_PMON_CTR0, + .event_ctl = SNBEP_PCU_MSR_PMON_CTL0, + .event_mask = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK, + .box_ctl = SNBEP_PCU_MSR_PMON_BOX_CTL, + .ops = &snbep_uncore_msr_ops, + .format_group = &snbep_uncore_pcu_format_group, +}; + +static struct intel_uncore_type *snbep_msr_uncores[] = { + &snbep_uncore_ubox, + &snbep_uncore_cbox, + &snbep_uncore_pcu, + NULL, +}; + +#define SNBEP_UNCORE_PCI_COMMON_INIT() \ + .perf_ctr = SNBEP_PCI_PMON_CTR0, \ + .event_ctl = SNBEP_PCI_PMON_CTL0, \ + .event_mask = SNBEP_PMON_RAW_EVENT_MASK, \ + .box_ctl = SNBEP_PCI_PMON_BOX_CTL, \ + .ops = &snbep_uncore_pci_ops, \ + .format_group = &snbep_uncore_format_group + +static struct intel_uncore_type snbep_uncore_ha = { + .name = "ha", + .num_counters = 4, + .num_boxes = 1, + .perf_ctr_bits = 48, + SNBEP_UNCORE_PCI_COMMON_INIT(), +}; + +static struct intel_uncore_type snbep_uncore_imc = { + .name = "imc", + .num_counters = 4, + .num_boxes = 4, + .perf_ctr_bits = 48, + .fixed_ctr_bits = 48, + .fixed_ctr = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR, + .fixed_ctl = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL, + .event_descs = snbep_uncore_imc_events, + SNBEP_UNCORE_PCI_COMMON_INIT(), +}; + +static struct intel_uncore_type snbep_uncore_qpi = { + .name = "qpi", + .num_counters = 4, + .num_boxes = 2, + .perf_ctr_bits = 48, + .event_descs = snbep_uncore_qpi_events, + SNBEP_UNCORE_PCI_COMMON_INIT(), +}; + + +static struct intel_uncore_type snbep_uncore_r2pcie = { + .name = "r2pcie", + .num_counters = 4, + .num_boxes = 1, + .perf_ctr_bits = 44, + .constraints = snbep_uncore_r2pcie_constraints, + SNBEP_UNCORE_PCI_COMMON_INIT(), +}; + +static struct intel_uncore_type snbep_uncore_r3qpi = { + .name = "r3qpi", + .num_counters = 3, + .num_boxes = 2, + .perf_ctr_bits = 44, + .constraints = snbep_uncore_r3qpi_constraints, + SNBEP_UNCORE_PCI_COMMON_INIT(), +}; + +static struct intel_uncore_type *snbep_pci_uncores[] = { + &snbep_uncore_ha, + &snbep_uncore_imc, + &snbep_uncore_qpi, + &snbep_uncore_r2pcie, + &snbep_uncore_r3qpi, + NULL, +}; + +static DEFINE_PCI_DEVICE_TABLE(snbep_uncore_pci_ids) = { + { /* Home Agent */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_HA), + .driver_data = (unsigned long)&snbep_uncore_ha, + }, + { /* MC Channel 0 */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC0), + .driver_data = (unsigned long)&snbep_uncore_imc, + }, + { /* MC Channel 1 */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC1), + .driver_data = (unsigned long)&snbep_uncore_imc, + }, + { /* MC Channel 2 */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC2), + .driver_data = (unsigned long)&snbep_uncore_imc, + }, + { /* MC Channel 3 */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC3), + .driver_data = (unsigned long)&snbep_uncore_imc, + }, + { /* QPI Port 0 */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI0), + .driver_data = (unsigned long)&snbep_uncore_qpi, + }, + { /* QPI Port 1 */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI1), + .driver_data = (unsigned long)&snbep_uncore_qpi, + }, + { /* P2PCIe */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R2PCIE), + .driver_data = (unsigned long)&snbep_uncore_r2pcie, + }, + { /* R3QPI Link 0 */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI0), + .driver_data = (unsigned long)&snbep_uncore_r3qpi, + }, + { /* R3QPI Link 1 */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI1), + .driver_data = (unsigned long)&snbep_uncore_r3qpi, + }, + { /* end: all zeroes */ } +}; + +static struct pci_driver snbep_uncore_pci_driver = { + .name = "snbep_uncore", + .id_table = snbep_uncore_pci_ids, +}; + +/* + * build pci bus to socket mapping + */ +static void snbep_pci2phy_map_init(void) +{ + struct pci_dev *ubox_dev = NULL; + int i, bus, nodeid; + u32 config; + + while (1) { + /* find the UBOX device */ + ubox_dev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_JAKETOWN_UBOX, + ubox_dev); + if (!ubox_dev) + break; + bus = ubox_dev->bus->number; + /* get the Node ID of the local register */ + pci_read_config_dword(ubox_dev, 0x40, &config); + nodeid = config; + /* get the Node ID mapping */ + pci_read_config_dword(ubox_dev, 0x54, &config); + /* + * every three bits in the Node ID mapping register maps + * to a particular node. + */ + for (i = 0; i < 8; i++) { + if (nodeid == ((config >> (3 * i)) & 0x7)) { + pcibus_to_physid[bus] = i; + break; + } + } + }; + return; +} +/* end of Sandy Bridge-EP uncore support */ + /* Sandy Bridge uncore support */ static void snb_uncore_msr_enable_event(struct intel_uncore_box *box, @@ -894,6 +1370,11 @@ static int __init uncore_pci_init(void) int ret; switch (boot_cpu_data.x86_model) { + case 45: /* Sandy Bridge-EP */ + pci_uncores = snbep_pci_uncores; + uncore_pci_driver = &snbep_uncore_pci_driver; + snbep_pci2phy_map_init(); + break; default: return 0; } @@ -1155,6 +1636,9 @@ static int __init uncore_cpu_init(void) case 42: /* Sandy Bridge */ msr_uncores = snb_msr_uncores; break; + case 45: /* Sandy Birdge-EP */ + msr_uncores = snbep_msr_uncores; + break; default: return 0; } diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index aa01df87b8de..4d52db0d1dfe 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h @@ -65,6 +65,92 @@ #define NHM_UNC_PERFEVTSEL0 0x3c0 #define NHM_UNC_UNCORE_PMC0 0x3b0 +/* SNB-EP Box level control */ +#define SNBEP_PMON_BOX_CTL_RST_CTRL (1 << 0) +#define SNBEP_PMON_BOX_CTL_RST_CTRS (1 << 1) +#define SNBEP_PMON_BOX_CTL_FRZ (1 << 8) +#define SNBEP_PMON_BOX_CTL_FRZ_EN (1 << 16) +#define SNBEP_PMON_BOX_CTL_INT (SNBEP_PMON_BOX_CTL_RST_CTRL | \ + SNBEP_PMON_BOX_CTL_RST_CTRS | \ + SNBEP_PMON_BOX_CTL_FRZ_EN) +/* SNB-EP event control */ +#define SNBEP_PMON_CTL_EV_SEL_MASK 0x000000ff +#define SNBEP_PMON_CTL_UMASK_MASK 0x0000ff00 +#define SNBEP_PMON_CTL_RST (1 << 17) +#define SNBEP_PMON_CTL_EDGE_DET (1 << 18) +#define SNBEP_PMON_CTL_EV_SEL_EXT (1 << 21) /* only for QPI */ +#define SNBEP_PMON_CTL_EN (1 << 22) +#define SNBEP_PMON_CTL_INVERT (1 << 23) +#define SNBEP_PMON_CTL_TRESH_MASK 0xff000000 +#define SNBEP_PMON_RAW_EVENT_MASK (SNBEP_PMON_CTL_EV_SEL_MASK | \ + SNBEP_PMON_CTL_UMASK_MASK | \ + SNBEP_PMON_CTL_EDGE_DET | \ + SNBEP_PMON_CTL_INVERT | \ + SNBEP_PMON_CTL_TRESH_MASK) + +/* SNB-EP Ubox event control */ +#define SNBEP_U_MSR_PMON_CTL_TRESH_MASK 0x1f000000 +#define SNBEP_U_MSR_PMON_RAW_EVENT_MASK \ + (SNBEP_PMON_CTL_EV_SEL_MASK | \ + SNBEP_PMON_CTL_UMASK_MASK | \ + SNBEP_PMON_CTL_EDGE_DET | \ + SNBEP_PMON_CTL_INVERT | \ + SNBEP_U_MSR_PMON_CTL_TRESH_MASK) + +/* SNB-EP PCU event control */ +#define SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK 0x0000c000 +#define SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK 0x1f000000 +#define SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT (1 << 30) +#define SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET (1 << 31) +#define SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK \ + (SNBEP_PMON_CTL_EV_SEL_MASK | \ + SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \ + SNBEP_PMON_CTL_EDGE_DET | \ + SNBEP_PMON_CTL_INVERT | \ + SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \ + SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \ + SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET) + +/* SNB-EP pci control register */ +#define SNBEP_PCI_PMON_BOX_CTL 0xf4 +#define SNBEP_PCI_PMON_CTL0 0xd8 +/* SNB-EP pci counter register */ +#define SNBEP_PCI_PMON_CTR0 0xa0 + +/* SNB-EP home agent register */ +#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH0 0x40 +#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH1 0x44 +#define SNBEP_HA_PCI_PMON_BOX_OPCODEMATCH 0x48 +/* SNB-EP memory controller register */ +#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTL 0xf0 +#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTR 0xd0 +/* SNB-EP QPI register */ +#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH0 0x228 +#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH1 0x22c +#define SNBEP_Q_Py_PCI_PMON_PKT_MASK0 0x238 +#define SNBEP_Q_Py_PCI_PMON_PKT_MASK1 0x23c + +/* SNB-EP Ubox register */ +#define SNBEP_U_MSR_PMON_CTR0 0xc16 +#define SNBEP_U_MSR_PMON_CTL0 0xc10 + +#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTL 0xc08 +#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTR 0xc09 + +/* SNB-EP Cbo register */ +#define SNBEP_C0_MSR_PMON_CTR0 0xd16 +#define SNBEP_C0_MSR_PMON_CTL0 0xd10 +#define SNBEP_C0_MSR_PMON_BOX_FILTER 0xd14 +#define SNBEP_C0_MSR_PMON_BOX_CTL 0xd04 +#define SNBEP_CBO_MSR_OFFSET 0x20 + +/* SNB-EP PCU register */ +#define SNBEP_PCU_MSR_PMON_CTR0 0xc36 +#define SNBEP_PCU_MSR_PMON_CTL0 0xc30 +#define SNBEP_PCU_MSR_PMON_BOX_FILTER 0xc34 +#define SNBEP_PCU_MSR_PMON_BOX_CTL 0xc24 +#define SNBEP_PCU_MSR_CORE_C3_CTR 0x3fc +#define SNBEP_PCU_MSR_CORE_C6_CTR 0x3fd struct intel_uncore_ops; struct intel_uncore_pmu; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ab741b0d0074..5f187026b812 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2755,6 +2755,17 @@ #define PCI_DEVICE_ID_INTEL_IOAT_SNB7 0x3c27 #define PCI_DEVICE_ID_INTEL_IOAT_SNB8 0x3c2e #define PCI_DEVICE_ID_INTEL_IOAT_SNB9 0x3c2f +#define PCI_DEVICE_ID_INTEL_UNC_HA 0x3c46 +#define PCI_DEVICE_ID_INTEL_UNC_IMC0 0x3cb0 +#define PCI_DEVICE_ID_INTEL_UNC_IMC1 0x3cb1 +#define PCI_DEVICE_ID_INTEL_UNC_IMC2 0x3cb4 +#define PCI_DEVICE_ID_INTEL_UNC_IMC3 0x3cb5 +#define PCI_DEVICE_ID_INTEL_UNC_QPI0 0x3c41 +#define PCI_DEVICE_ID_INTEL_UNC_QPI1 0x3c42 +#define PCI_DEVICE_ID_INTEL_UNC_R2PCIE 0x3c43 +#define PCI_DEVICE_ID_INTEL_UNC_R3QPI0 0x3c44 +#define PCI_DEVICE_ID_INTEL_UNC_R3QPI1 0x3c45 +#define PCI_DEVICE_ID_INTEL_JAKETOWN_UBOX 0x3ce0 #define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f #define PCI_DEVICE_ID_INTEL_5100_16 0x65f0 #define PCI_DEVICE_ID_INTEL_5100_21 0x65f5 -- cgit v1.2.3 From 70c276a6abdb1a466a9026da631c396fee2984bd Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 25 May 2012 18:06:33 -0300 Subject: [media] Revert "[media] media: mx2_camera: Fix mbus format handling" This reverts commit d509835e32bd761a2b7b446034a273da568e5573. That commit breaks support for the generic pass-through mode in the driver for formats, not natively supported by it. Besides due to a merge conflict it also breaks driver compilation: drivers/media/video/mx2_camera.c: In function 'mx2_camera_set_bus_param': drivers/media/video/mx2_camera.c:937: error: 'pixfmt' undeclared (first use in this function) drivers/media/video/mx2_camera.c:937: error: (Each undeclared identifier is reported only once drivers/media/video/mx2_camera.c:937: error: for each function it appears in.) Signed-off-by: Guennadi Liakhovetski Cc: Javier Martin Signed-off-by: Mauro Carvalho Chehab --- arch/arm/plat-mxc/include/mach/mx2_cam.h | 2 ++ drivers/media/video/mx2_camera.c | 52 +++----------------------------- 2 files changed, 7 insertions(+), 47 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-mxc/include/mach/mx2_cam.h b/arch/arm/plat-mxc/include/mach/mx2_cam.h index 7ded6f1f74bc..3c080a32dbf5 100644 --- a/arch/arm/plat-mxc/include/mach/mx2_cam.h +++ b/arch/arm/plat-mxc/include/mach/mx2_cam.h @@ -23,6 +23,7 @@ #ifndef __MACH_MX2_CAM_H_ #define __MACH_MX2_CAM_H_ +#define MX2_CAMERA_SWAP16 (1 << 0) #define MX2_CAMERA_EXT_VSYNC (1 << 1) #define MX2_CAMERA_CCIR (1 << 2) #define MX2_CAMERA_CCIR_INTERLACE (1 << 3) @@ -30,6 +31,7 @@ #define MX2_CAMERA_GATED_CLOCK (1 << 5) #define MX2_CAMERA_INV_DATA (1 << 6) #define MX2_CAMERA_PCLK_SAMPLE_RISING (1 << 7) +#define MX2_CAMERA_PACK_DIR_MSB (1 << 8) /** * struct mx2_camera_platform_data - optional platform data for mx2_camera diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index ded26b7286fa..41f9a254b245 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c @@ -345,19 +345,6 @@ static struct mx2_fmt_cfg mx27_emma_prp_table[] = { PRP_INTR_CH2OVF, } }, - { - .in_fmt = V4L2_MBUS_FMT_UYVY8_2X8, - .out_fmt = V4L2_PIX_FMT_YUV420, - .cfg = { - .channel = 2, - .in_fmt = PRP_CNTL_DATA_IN_YUV422, - .out_fmt = PRP_CNTL_CH2_OUT_YUV420, - .src_pixel = 0x22000888, /* YUV422 (YUYV) */ - .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR | - PRP_INTR_CH2FC | PRP_INTR_LBOVF | - PRP_INTR_CH2OVF, - } - }, }; static struct mx2_fmt_cfg *mx27_emma_prp_get_format( @@ -984,7 +971,6 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd) struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx2_camera_dev *pcdev = ici->priv; struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; - const struct soc_camera_format_xlate *xlate; unsigned long common_flags; int ret; int bytesperline; @@ -1029,31 +1015,14 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd) return ret; } - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); - if (!xlate) { - dev_warn(icd->parent, "Format %x not found\n", pixfmt); - return -EINVAL; - } - - if (xlate->code == V4L2_MBUS_FMT_YUYV8_2X8) { - csicr1 |= CSICR1_PACK_DIR; - csicr1 &= ~CSICR1_SWAP16_EN; - dev_dbg(icd->parent, "already yuyv format, don't convert\n"); - } else if (xlate->code == V4L2_MBUS_FMT_UYVY8_2X8) { - csicr1 &= ~CSICR1_PACK_DIR; - csicr1 |= CSICR1_SWAP16_EN; - dev_dbg(icd->parent, "convert uyvy mbus format into yuyv\n"); - } else { - dev_warn(icd->parent, "mbus format not supported\n"); - return -EINVAL; - } - if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) csicr1 |= CSICR1_REDGE; if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) csicr1 |= CSICR1_SOF_POL; if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) csicr1 |= CSICR1_HSYNC_POL; + if (pcdev->platform_flags & MX2_CAMERA_SWAP16) + csicr1 |= CSICR1_SWAP16_EN; if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC) csicr1 |= CSICR1_EXT_VSYNC; if (pcdev->platform_flags & MX2_CAMERA_CCIR) @@ -1064,6 +1033,8 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd) csicr1 |= CSICR1_GCLK_MODE; if (pcdev->platform_flags & MX2_CAMERA_INV_DATA) csicr1 |= CSICR1_INV_DATA; + if (pcdev->platform_flags & MX2_CAMERA_PACK_DIR_MSB) + csicr1 |= CSICR1_PACK_DIR; pcdev->csicr1 = csicr1; @@ -1138,8 +1109,7 @@ static int mx2_camera_get_formats(struct soc_camera_device *icd, return 0; } - if (code == V4L2_MBUS_FMT_YUYV8_2X8 || - code == V4L2_MBUS_FMT_UYVY8_2X8) { + if (code == V4L2_MBUS_FMT_YUYV8_2X8) { formats++; if (xlate) { /* @@ -1155,18 +1125,6 @@ static int mx2_camera_get_formats(struct soc_camera_device *icd, } } - if (code == V4L2_MBUS_FMT_UYVY8_2X8) { - formats++; - if (xlate) { - xlate->host_fmt = - soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_2X8); - xlate->code = code; - dev_dbg(dev, "Providing host format %s for sensor code %d\n", - xlate->host_fmt->name, code); - xlate++; - } - } - /* Generic pass-trough */ formats++; if (xlate) { -- cgit v1.2.3 From a1e4ccb990447df0fe83d164d9a7bc2e6c4b7db7 Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Fri, 15 Jun 2012 15:07:13 -0400 Subject: KVM: Introduce __KVM_HAVE_IRQ_LINE This is a preparatory patch for the KVM/ARM implementation. KVM/ARM will use the KVM_IRQ_LINE ioctl, which is currently conditional on __KVM_HAVE_IOAPIC, but ARM obviously doesn't have any IOAPIC support and we need a separate define. Signed-off-by: Christoffer Dall Signed-off-by: Avi Kivity --- arch/ia64/include/asm/kvm.h | 1 + arch/x86/include/asm/kvm.h | 1 + include/trace/events/kvm.h | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/ia64/include/asm/kvm.h b/arch/ia64/include/asm/kvm.h index b9f82c84f093..ec6c6b301238 100644 --- a/arch/ia64/include/asm/kvm.h +++ b/arch/ia64/include/asm/kvm.h @@ -26,6 +26,7 @@ /* Select x86 specific features in */ #define __KVM_HAVE_IOAPIC +#define __KVM_HAVE_IRQ_LINE #define __KVM_HAVE_DEVICE_ASSIGNMENT /* Architectural interrupt line count. */ diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h index e7d1c194d272..246617efd67f 100644 --- a/arch/x86/include/asm/kvm.h +++ b/arch/x86/include/asm/kvm.h @@ -12,6 +12,7 @@ /* Select x86 specific features in */ #define __KVM_HAVE_PIT #define __KVM_HAVE_IOAPIC +#define __KVM_HAVE_IRQ_LINE #define __KVM_HAVE_DEVICE_ASSIGNMENT #define __KVM_HAVE_MSI #define __KVM_HAVE_USER_NMI diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h index 3df5925fe641..7ef9e759f499 100644 --- a/include/trace/events/kvm.h +++ b/include/trace/events/kvm.h @@ -37,7 +37,7 @@ TRACE_EVENT(kvm_userspace_exit, __entry->errno < 0 ? -__entry->errno : __entry->reason) ); -#if defined(__KVM_HAVE_IOAPIC) +#if defined(__KVM_HAVE_IRQ_LINE) TRACE_EVENT(kvm_set_irq, TP_PROTO(unsigned int gsi, int level, int irq_source_id), TP_ARGS(gsi, level, irq_source_id), @@ -57,7 +57,9 @@ TRACE_EVENT(kvm_set_irq, TP_printk("gsi %u level %d source %d", __entry->gsi, __entry->level, __entry->irq_source_id) ); +#endif +#if defined(__KVM_HAVE_IOAPIC) #define kvm_deliver_mode \ {0x0, "Fixed"}, \ {0x1, "LowPrio"}, \ -- cgit v1.2.3 From 2992c542fcd40777ed253f57362c65711fb8acaf Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sat, 16 Jun 2012 14:45:49 +0200 Subject: perf/x86: Lowercase uncore PMU event names Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-ucnds8gkve4x3s4biuukyph3@git.kernel.org [ Trivial build fix ] Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel_uncore.c | 51 +++++++++------------------ 1 file changed, 16 insertions(+), 35 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index d34f68bf990b..28a8413ca199 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -179,22 +179,17 @@ static struct attribute *snbep_uncore_pcu_formats_attr[] = { }; static struct uncore_event_desc snbep_uncore_imc_events[] = { - INTEL_UNCORE_EVENT_DESC(CLOCKTICKS, "config=0xffff"), - /* read */ - INTEL_UNCORE_EVENT_DESC(CAS_COUNT_RD, "event=0x4,umask=0x3"), - /* write */ - INTEL_UNCORE_EVENT_DESC(CAS_COUNT_WR, "event=0x4,umask=0xc"), + INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0xff"), + INTEL_UNCORE_EVENT_DESC(cas_count_read, "event=0x04,umask=0x03"), + INTEL_UNCORE_EVENT_DESC(cas_count_write, "event=0x04,umask=0x0c"), { /* end: all zeroes */ }, }; static struct uncore_event_desc snbep_uncore_qpi_events[] = { - INTEL_UNCORE_EVENT_DESC(CLOCKTICKS, "event=0x14"), - /* outgoing data+nondata flits */ - INTEL_UNCORE_EVENT_DESC(TxL_FLITS_ACTIVE, "event=0x0,umask=0x6"), - /* DRS data received */ - INTEL_UNCORE_EVENT_DESC(DRS_DATA, "event=0x2,umask=0x8"), - /* NCB data received */ - INTEL_UNCORE_EVENT_DESC(NCB_DATA, "event=0x3,umask=0x4"), + INTEL_UNCORE_EVENT_DESC(clockticks, "event=0x14"), + INTEL_UNCORE_EVENT_DESC(txl_flits_active, "event=0x00,umask=0x06"), + INTEL_UNCORE_EVENT_DESC(drs_data, "event=0x02,umask=0x08"), + INTEL_UNCORE_EVENT_DESC(ncb_data, "event=0x03,umask=0x04"), { /* end: all zeroes */ }, }; @@ -621,29 +616,15 @@ static struct attribute_group nhm_uncore_format_group = { }; static struct uncore_event_desc nhm_uncore_events[] = { - INTEL_UNCORE_EVENT_DESC(CLOCKTICKS, "config=0xffff"), - /* full cache line writes to DRAM */ - INTEL_UNCORE_EVENT_DESC(QMC_WRITES_FULL_ANY, "event=0x2f,umask=0xf"), - /* Quickpath Memory Controller normal priority read requests */ - INTEL_UNCORE_EVENT_DESC(QMC_NORMAL_READS_ANY, "event=0x2c,umask=0xf"), - /* Quickpath Home Logic read requests from the IOH */ - INTEL_UNCORE_EVENT_DESC(QHL_REQUEST_IOH_READS, - "event=0x20,umask=0x1"), - /* Quickpath Home Logic write requests from the IOH */ - INTEL_UNCORE_EVENT_DESC(QHL_REQUEST_IOH_WRITES, - "event=0x20,umask=0x2"), - /* Quickpath Home Logic read requests from a remote socket */ - INTEL_UNCORE_EVENT_DESC(QHL_REQUEST_REMOTE_READS, - "event=0x20,umask=0x4"), - /* Quickpath Home Logic write requests from a remote socket */ - INTEL_UNCORE_EVENT_DESC(QHL_REQUEST_REMOTE_WRITES, - "event=0x20,umask=0x8"), - /* Quickpath Home Logic read requests from the local socket */ - INTEL_UNCORE_EVENT_DESC(QHL_REQUEST_LOCAL_READS, - "event=0x20,umask=0x10"), - /* Quickpath Home Logic write requests from the local socket */ - INTEL_UNCORE_EVENT_DESC(QHL_REQUEST_LOCAL_WRITES, - "event=0x20,umask=0x20"), + INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0xff"), + INTEL_UNCORE_EVENT_DESC(qmc_writes_full_any, "event=0x2f,umask=0x0f"), + INTEL_UNCORE_EVENT_DESC(qmc_normal_reads_any, "event=0x2c,umask=0x0f"), + INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_reads, "event=0x20,umask=0x01"), + INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_writes, "event=0x20,umask=0x02"), + INTEL_UNCORE_EVENT_DESC(qhl_request_remote_reads, "event=0x20,umask=0x04"), + INTEL_UNCORE_EVENT_DESC(qhl_request_remote_writes, "event=0x20,umask=0x08"), + INTEL_UNCORE_EVENT_DESC(qhl_request_local_reads, "event=0x20,umask=0x10"), + INTEL_UNCORE_EVENT_DESC(qhl_request_local_writes, "event=0x20,umask=0x20"), { /* end: all zeroes */ }, }; -- cgit v1.2.3 From 13429ced25fdca14b28dbd116333262b0d51d10f Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Wed, 13 Jun 2012 22:14:50 +0200 Subject: ARM: davinci: remove dummy header files These dummy headers are unused. Commit 6ea96e111e6a7f06ef62227bf64e8cd65bd705b3 ("ARM: davinci: add back dummy header files") only added them as a temporary measure. They can be removed now. Signed-off-by: Paul Bolle Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/include/mach/dm365.h | 1 - arch/arm/mach-davinci/include/mach/dm646x.h | 1 - 2 files changed, 2 deletions(-) delete mode 100644 arch/arm/mach-davinci/include/mach/dm365.h delete mode 100644 arch/arm/mach-davinci/include/mach/dm646x.h (limited to 'arch') diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h deleted file mode 100644 index b9bf3d6a4423..000000000000 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ /dev/null @@ -1 +0,0 @@ -/* empty, remove once unused */ diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h deleted file mode 100644 index b9bf3d6a4423..000000000000 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ /dev/null @@ -1 +0,0 @@ -/* empty, remove once unused */ -- cgit v1.2.3 From 9e0304e388ef0e7495b279ce737c24ad56d20b5d Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Mon, 18 Jun 2012 13:11:21 -0400 Subject: arch/tile: big-endian: properly bswap instruction bundles when backtracing Instruction bundles are always little-endian, even when running in big-endian mode. I missed this internal bug fix when cherry-picking the big-endian code to return to the community. Signed-off-by: Chris Metcalf --- arch/tile/kernel/backtrace.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/tile/kernel/backtrace.c b/arch/tile/kernel/backtrace.c index 9092ce8aa6b4..f8b74ca83b92 100644 --- a/arch/tile/kernel/backtrace.c +++ b/arch/tile/kernel/backtrace.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -336,8 +337,12 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, bytes_to_prefetch / sizeof(tile_bundle_bits); } - /* Decode the next bundle. */ - bundle.bits = prefetched_bundles[next_bundle++]; + /* + * Decode the next bundle. + * TILE always stores instruction bundles in little-endian + * mode, even when the chip is running in big-endian mode. + */ + bundle.bits = le64_to_cpu(prefetched_bundles[next_bundle++]); bundle.num_insns = parse_insn_tile(bundle.bits, pc, bundle.insns); num_info_ops = bt_get_info_ops(&bundle, info_operands); -- cgit v1.2.3 From ddd04b989f50157a599de036b670262aa3ec9405 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 18 Jun 2012 00:47:26 -0600 Subject: ARM: OMAP AM33xx: PRM: add PRM support As far as PRM/CM/PRCM modules are concerned, AM33XX device is different than OMAP3 and OMAP4 architectures; so we need to handle it separately. This patch adds support for the PRM APIs required for AM33XX device. Signed-off-by: Vaibhav Hiremath Signed-off-by: Afzal Mohammed Cc: Benoit Cousson Cc: Tony Lindgren Cc: Kevin Hilman Cc: Paul Walmsley Cc: Rajendra Nayak [paul@pwsan.com: separated the PRM parts of "ARM: OMAP3+: am33xx: Add powerdomain & PRM support" into this patch; fixed Makefile prm33xx.o location; cleaned up some checkpatch violations; updated for 3.5] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/Makefile | 1 + arch/arm/mach-omap2/prm-regbits-33xx.h | 357 +++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/prm33xx.c | 135 +++++++++++++ arch/arm/mach-omap2/prm33xx.h | 129 ++++++++++++ 4 files changed, 622 insertions(+) create mode 100644 arch/arm/mach-omap2/prm-regbits-33xx.h create mode 100644 arch/arm/mach-omap2/prm33xx.c create mode 100644 arch/arm/mach-omap2/prm33xx.h (limited to 'arch') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 6a3aef66f03e..76921ebc63d9 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -90,6 +90,7 @@ obj-$(CONFIG_ARCH_OMAP3) += vc3xxx_data.o vp3xxx_data.o obj-$(CONFIG_ARCH_OMAP4) += prcm.o cminst44xx.o cm44xx.o obj-$(CONFIG_ARCH_OMAP4) += prcm_mpu44xx.o prminst44xx.o obj-$(CONFIG_ARCH_OMAP4) += vc44xx_data.o vp44xx_data.o prm44xx.o +obj-$(CONFIG_SOC_AM33XX) += prcm.o prm33xx.o # OMAP voltage domains voltagedomain-common := voltage.o vc.o vp.o diff --git a/arch/arm/mach-omap2/prm-regbits-33xx.h b/arch/arm/mach-omap2/prm-regbits-33xx.h new file mode 100644 index 000000000000..0221b5c20e87 --- /dev/null +++ b/arch/arm/mach-omap2/prm-regbits-33xx.h @@ -0,0 +1,357 @@ +/* + * AM33XX PRM_XXX register bits + * + * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_33XX_H +#define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_33XX_H + +#include "prm.h" + +/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */ +#define AM33XX_ABBOFF_ACT_EXPORT_SHIFT 1 +#define AM33XX_ABBOFF_ACT_EXPORT_MASK (1 << 1) + +/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */ +#define AM33XX_ABBOFF_SLEEP_EXPORT_SHIFT 2 +#define AM33XX_ABBOFF_SLEEP_EXPORT_MASK (1 << 2) + +/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */ +#define AM33XX_AIPOFF_SHIFT 8 +#define AM33XX_AIPOFF_MASK (1 << 8) + +/* Used by PM_WKUP_PWRSTST */ +#define AM33XX_DEBUGSS_MEM_STATEST_SHIFT 17 +#define AM33XX_DEBUGSS_MEM_STATEST_MASK (0x3 << 17) + +/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */ +#define AM33XX_DISABLE_RTA_EXPORT_SHIFT 0 +#define AM33XX_DISABLE_RTA_EXPORT_MASK (1 << 0) + +/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */ +#define AM33XX_DPLL_CORE_RECAL_EN_SHIFT 12 +#define AM33XX_DPLL_CORE_RECAL_EN_MASK (1 << 12) + +/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */ +#define AM33XX_DPLL_CORE_RECAL_ST_SHIFT 12 +#define AM33XX_DPLL_CORE_RECAL_ST_MASK (1 << 12) + +/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */ +#define AM33XX_DPLL_DDR_RECAL_EN_SHIFT 14 +#define AM33XX_DPLL_DDR_RECAL_EN_MASK (1 << 14) + +/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */ +#define AM33XX_DPLL_DDR_RECAL_ST_SHIFT 14 +#define AM33XX_DPLL_DDR_RECAL_ST_MASK (1 << 14) + +/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */ +#define AM33XX_DPLL_DISP_RECAL_EN_SHIFT 15 +#define AM33XX_DPLL_DISP_RECAL_EN_MASK (1 << 15) + +/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */ +#define AM33XX_DPLL_DISP_RECAL_ST_SHIFT 13 +#define AM33XX_DPLL_DISP_RECAL_ST_MASK (1 << 13) + +/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */ +#define AM33XX_DPLL_MPU_RECAL_EN_SHIFT 11 +#define AM33XX_DPLL_MPU_RECAL_EN_MASK (1 << 11) + +/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */ +#define AM33XX_DPLL_MPU_RECAL_ST_SHIFT 11 +#define AM33XX_DPLL_MPU_RECAL_ST_MASK (1 << 11) + +/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */ +#define AM33XX_DPLL_PER_RECAL_EN_SHIFT 13 +#define AM33XX_DPLL_PER_RECAL_EN_MASK (1 << 13) + +/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */ +#define AM33XX_DPLL_PER_RECAL_ST_SHIFT 15 +#define AM33XX_DPLL_PER_RECAL_ST_MASK (1 << 15) + +/* Used by RM_WKUP_RSTST */ +#define AM33XX_EMULATION_M3_RST_SHIFT 6 +#define AM33XX_EMULATION_M3_RST_MASK (1 << 6) + +/* Used by RM_MPU_RSTST */ +#define AM33XX_EMULATION_MPU_RST_SHIFT 5 +#define AM33XX_EMULATION_MPU_RST_MASK (1 << 5) + +/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */ +#define AM33XX_ENFUNC1_EXPORT_SHIFT 3 +#define AM33XX_ENFUNC1_EXPORT_MASK (1 << 3) + +/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */ +#define AM33XX_ENFUNC3_EXPORT_SHIFT 5 +#define AM33XX_ENFUNC3_EXPORT_MASK (1 << 5) + +/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */ +#define AM33XX_ENFUNC4_SHIFT 6 +#define AM33XX_ENFUNC4_MASK (1 << 6) + +/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */ +#define AM33XX_ENFUNC5_SHIFT 7 +#define AM33XX_ENFUNC5_MASK (1 << 7) + +/* Used by PRM_RSTST */ +#define AM33XX_EXTERNAL_WARM_RST_SHIFT 5 +#define AM33XX_EXTERNAL_WARM_RST_MASK (1 << 5) + +/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */ +#define AM33XX_FORCEWKUP_EN_SHIFT 10 +#define AM33XX_FORCEWKUP_EN_MASK (1 << 10) + +/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */ +#define AM33XX_FORCEWKUP_ST_SHIFT 10 +#define AM33XX_FORCEWKUP_ST_MASK (1 << 10) + +/* Used by PM_GFX_PWRSTCTRL */ +#define AM33XX_GFX_MEM_ONSTATE_SHIFT 17 +#define AM33XX_GFX_MEM_ONSTATE_MASK (0x3 << 17) + +/* Used by PM_GFX_PWRSTCTRL */ +#define AM33XX_GFX_MEM_RETSTATE_SHIFT 6 +#define AM33XX_GFX_MEM_RETSTATE_MASK (1 << 6) + +/* Used by PM_GFX_PWRSTST */ +#define AM33XX_GFX_MEM_STATEST_SHIFT 4 +#define AM33XX_GFX_MEM_STATEST_MASK (0x3 << 4) + +/* Used by RM_GFX_RSTCTRL, RM_GFX_RSTST */ +#define AM33XX_GFX_RST_SHIFT 0 +#define AM33XX_GFX_RST_MASK (1 << 0) + +/* Used by PRM_RSTST */ +#define AM33XX_GLOBAL_COLD_RST_SHIFT 0 +#define AM33XX_GLOBAL_COLD_RST_MASK (1 << 0) + +/* Used by PRM_RSTST */ +#define AM33XX_GLOBAL_WARM_SW_RST_SHIFT 1 +#define AM33XX_GLOBAL_WARM_SW_RST_MASK (1 << 1) + +/* Used by RM_WKUP_RSTST */ +#define AM33XX_ICECRUSHER_M3_RST_SHIFT 7 +#define AM33XX_ICECRUSHER_M3_RST_MASK (1 << 7) + +/* Used by RM_MPU_RSTST */ +#define AM33XX_ICECRUSHER_MPU_RST_SHIFT 6 +#define AM33XX_ICECRUSHER_MPU_RST_MASK (1 << 6) + +/* Used by PRM_RSTST */ +#define AM33XX_ICEPICK_RST_SHIFT 9 +#define AM33XX_ICEPICK_RST_MASK (1 << 9) + +/* Used by RM_PER_RSTCTRL */ +#define AM33XX_PRUSS_LRST_SHIFT 1 +#define AM33XX_PRUSS_LRST_MASK (1 << 1) + +/* Used by PM_PER_PWRSTCTRL */ +#define AM33XX_PRUSS_MEM_ONSTATE_SHIFT 5 +#define AM33XX_PRUSS_MEM_ONSTATE_MASK (0x3 << 5) + +/* Used by PM_PER_PWRSTCTRL */ +#define AM33XX_PRUSS_MEM_RETSTATE_SHIFT 7 +#define AM33XX_PRUSS_MEM_RETSTATE_MASK (1 << 7) + +/* Used by PM_PER_PWRSTST */ +#define AM33XX_PRUSS_MEM_STATEST_SHIFT 23 +#define AM33XX_PRUSS_MEM_STATEST_MASK (0x3 << 23) + +/* + * Used by PM_GFX_PWRSTST, PM_CEFUSE_PWRSTST, PM_PER_PWRSTST, PM_MPU_PWRSTST, + * PM_WKUP_PWRSTST, PM_RTC_PWRSTST + */ +#define AM33XX_INTRANSITION_SHIFT 20 +#define AM33XX_INTRANSITION_MASK (1 << 20) + +/* Used by PM_CEFUSE_PWRSTST */ +#define AM33XX_LASTPOWERSTATEENTERED_SHIFT 24 +#define AM33XX_LASTPOWERSTATEENTERED_MASK (0x3 << 24) + +/* Used by PM_GFX_PWRSTCTRL, PM_MPU_PWRSTCTRL, PM_RTC_PWRSTCTRL */ +#define AM33XX_LOGICRETSTATE_SHIFT 2 +#define AM33XX_LOGICRETSTATE_MASK (1 << 2) + +/* Renamed from LOGICRETSTATE Used by PM_PER_PWRSTCTRL, PM_WKUP_PWRSTCTRL */ +#define AM33XX_LOGICRETSTATE_3_3_SHIFT 3 +#define AM33XX_LOGICRETSTATE_3_3_MASK (1 << 3) + +/* + * Used by PM_GFX_PWRSTST, PM_CEFUSE_PWRSTST, PM_PER_PWRSTST, PM_MPU_PWRSTST, + * PM_WKUP_PWRSTST, PM_RTC_PWRSTST + */ +#define AM33XX_LOGICSTATEST_SHIFT 2 +#define AM33XX_LOGICSTATEST_MASK (1 << 2) + +/* + * Used by PM_GFX_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL, PM_PER_PWRSTCTRL, + * PM_MPU_PWRSTCTRL, PM_WKUP_PWRSTCTRL, PM_RTC_PWRSTCTRL + */ +#define AM33XX_LOWPOWERSTATECHANGE_SHIFT 4 +#define AM33XX_LOWPOWERSTATECHANGE_MASK (1 << 4) + +/* Used by PM_MPU_PWRSTCTRL */ +#define AM33XX_MPU_L1_ONSTATE_SHIFT 18 +#define AM33XX_MPU_L1_ONSTATE_MASK (0x3 << 18) + +/* Used by PM_MPU_PWRSTCTRL */ +#define AM33XX_MPU_L1_RETSTATE_SHIFT 22 +#define AM33XX_MPU_L1_RETSTATE_MASK (1 << 22) + +/* Used by PM_MPU_PWRSTST */ +#define AM33XX_MPU_L1_STATEST_SHIFT 6 +#define AM33XX_MPU_L1_STATEST_MASK (0x3 << 6) + +/* Used by PM_MPU_PWRSTCTRL */ +#define AM33XX_MPU_L2_ONSTATE_SHIFT 20 +#define AM33XX_MPU_L2_ONSTATE_MASK (0x3 << 20) + +/* Used by PM_MPU_PWRSTCTRL */ +#define AM33XX_MPU_L2_RETSTATE_SHIFT 23 +#define AM33XX_MPU_L2_RETSTATE_MASK (1 << 23) + +/* Used by PM_MPU_PWRSTST */ +#define AM33XX_MPU_L2_STATEST_SHIFT 8 +#define AM33XX_MPU_L2_STATEST_MASK (0x3 << 8) + +/* Used by PM_MPU_PWRSTCTRL */ +#define AM33XX_MPU_RAM_ONSTATE_SHIFT 16 +#define AM33XX_MPU_RAM_ONSTATE_MASK (0x3 << 16) + +/* Used by PM_MPU_PWRSTCTRL */ +#define AM33XX_MPU_RAM_RETSTATE_SHIFT 24 +#define AM33XX_MPU_RAM_RETSTATE_MASK (1 << 24) + +/* Used by PM_MPU_PWRSTST */ +#define AM33XX_MPU_RAM_STATEST_SHIFT 4 +#define AM33XX_MPU_RAM_STATEST_MASK (0x3 << 4) + +/* Used by PRM_RSTST */ +#define AM33XX_MPU_SECURITY_VIOL_RST_SHIFT 2 +#define AM33XX_MPU_SECURITY_VIOL_RST_MASK (1 << 2) + +/* Used by PRM_SRAM_COUNT */ +#define AM33XX_PCHARGECNT_VALUE_SHIFT 0 +#define AM33XX_PCHARGECNT_VALUE_MASK (0x3f << 0) + +/* Used by RM_PER_RSTCTRL */ +#define AM33XX_PCI_LRST_SHIFT 0 +#define AM33XX_PCI_LRST_MASK (1 << 0) + +/* Renamed from PCI_LRST Used by RM_PER_RSTST */ +#define AM33XX_PCI_LRST_5_5_SHIFT 5 +#define AM33XX_PCI_LRST_5_5_MASK (1 << 5) + +/* Used by PM_PER_PWRSTCTRL */ +#define AM33XX_PER_MEM_ONSTATE_SHIFT 25 +#define AM33XX_PER_MEM_ONSTATE_MASK (0x3 << 25) + +/* Used by PM_PER_PWRSTCTRL */ +#define AM33XX_PER_MEM_RETSTATE_SHIFT 29 +#define AM33XX_PER_MEM_RETSTATE_MASK (1 << 29) + +/* Used by PM_PER_PWRSTST */ +#define AM33XX_PER_MEM_STATEST_SHIFT 17 +#define AM33XX_PER_MEM_STATEST_MASK (0x3 << 17) + +/* + * Used by PM_GFX_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL, PM_PER_PWRSTCTRL, + * PM_MPU_PWRSTCTRL + */ +#define AM33XX_POWERSTATE_SHIFT 0 +#define AM33XX_POWERSTATE_MASK (0x3 << 0) + +/* Used by PM_GFX_PWRSTST, PM_CEFUSE_PWRSTST, PM_PER_PWRSTST, PM_MPU_PWRSTST */ +#define AM33XX_POWERSTATEST_SHIFT 0 +#define AM33XX_POWERSTATEST_MASK (0x3 << 0) + +/* Used by PM_PER_PWRSTCTRL */ +#define AM33XX_RAM_MEM_ONSTATE_SHIFT 30 +#define AM33XX_RAM_MEM_ONSTATE_MASK (0x3 << 30) + +/* Used by PM_PER_PWRSTCTRL */ +#define AM33XX_RAM_MEM_RETSTATE_SHIFT 27 +#define AM33XX_RAM_MEM_RETSTATE_MASK (1 << 27) + +/* Used by PM_PER_PWRSTST */ +#define AM33XX_RAM_MEM_STATEST_SHIFT 21 +#define AM33XX_RAM_MEM_STATEST_MASK (0x3 << 21) + +/* Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_MPU_CTRL */ +#define AM33XX_RETMODE_ENABLE_SHIFT 0 +#define AM33XX_RETMODE_ENABLE_MASK (1 << 0) + +/* Used by REVISION_PRM */ +#define AM33XX_REV_SHIFT 0 +#define AM33XX_REV_MASK (0xff << 0) + +/* Used by PRM_RSTTIME */ +#define AM33XX_RSTTIME1_SHIFT 0 +#define AM33XX_RSTTIME1_MASK (0xff << 0) + +/* Used by PRM_RSTTIME */ +#define AM33XX_RSTTIME2_SHIFT 8 +#define AM33XX_RSTTIME2_MASK (0x1f << 8) + +/* Used by PRM_RSTCTRL */ +#define AM33XX_RST_GLOBAL_COLD_SW_SHIFT 1 +#define AM33XX_RST_GLOBAL_COLD_SW_MASK (1 << 1) + +/* Used by PRM_RSTCTRL */ +#define AM33XX_RST_GLOBAL_WARM_SW_SHIFT 0 +#define AM33XX_RST_GLOBAL_WARM_SW_MASK (1 << 0) + +/* Used by PRM_SRAM_COUNT */ +#define AM33XX_SLPCNT_VALUE_SHIFT 16 +#define AM33XX_SLPCNT_VALUE_MASK (0xff << 16) + +/* Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_MPU_CTRL */ +#define AM33XX_SRAMLDO_STATUS_SHIFT 8 +#define AM33XX_SRAMLDO_STATUS_MASK (1 << 8) + +/* Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_MPU_CTRL */ +#define AM33XX_SRAM_IN_TRANSITION_SHIFT 9 +#define AM33XX_SRAM_IN_TRANSITION_MASK (1 << 9) + +/* Used by PRM_SRAM_COUNT */ +#define AM33XX_STARTUP_COUNT_SHIFT 24 +#define AM33XX_STARTUP_COUNT_MASK (0xff << 24) + +/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */ +#define AM33XX_TRANSITION_EN_SHIFT 8 +#define AM33XX_TRANSITION_EN_MASK (1 << 8) + +/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */ +#define AM33XX_TRANSITION_ST_SHIFT 8 +#define AM33XX_TRANSITION_ST_MASK (1 << 8) + +/* Used by PRM_SRAM_COUNT */ +#define AM33XX_VSETUPCNT_VALUE_SHIFT 8 +#define AM33XX_VSETUPCNT_VALUE_MASK (0xff << 8) + +/* Used by PRM_RSTST */ +#define AM33XX_WDT0_RST_SHIFT 3 +#define AM33XX_WDT0_RST_MASK (1 << 3) + +/* Used by PRM_RSTST */ +#define AM33XX_WDT1_RST_SHIFT 4 +#define AM33XX_WDT1_RST_MASK (1 << 4) + +/* Used by RM_WKUP_RSTCTRL */ +#define AM33XX_WKUP_M3_LRST_SHIFT 3 +#define AM33XX_WKUP_M3_LRST_MASK (1 << 3) + +/* Renamed from WKUP_M3_LRST Used by RM_WKUP_RSTST */ +#define AM33XX_WKUP_M3_LRST_5_5_SHIFT 5 +#define AM33XX_WKUP_M3_LRST_5_5_MASK (1 << 5) + +#endif diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c new file mode 100644 index 000000000000..e7dbb6cf1255 --- /dev/null +++ b/arch/arm/mach-omap2/prm33xx.c @@ -0,0 +1,135 @@ +/* + * AM33XX PRM functions + * + * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "prm33xx.h" +#include "prm-regbits-33xx.h" + +/* Read a register in a PRM instance */ +u32 am33xx_prm_read_reg(s16 inst, u16 idx) +{ + return __raw_readl(prm_base + inst + idx); +} + +/* Write into a register in a PRM instance */ +void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx) +{ + __raw_writel(val, prm_base + inst + idx); +} + +/* Read-modify-write a register in PRM. Caller must lock */ +u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx) +{ + u32 v; + + v = am33xx_prm_read_reg(inst, idx); + v &= ~mask; + v |= bits; + am33xx_prm_write_reg(v, inst, idx); + + return v; +} + +/** + * am33xx_prm_is_hardreset_asserted - read the HW reset line state of + * submodules contained in the hwmod module + * @shift: register bit shift corresponding to the reset line to check + * @inst: CM instance register offset (*_INST macro) + * @rstctrl_offs: RM_RSTCTRL register address offset for this module + * + * Returns 1 if the (sub)module hardreset line is currently asserted, + * 0 if the (sub)module hardreset line is not currently asserted, or + * -EINVAL upon parameter error. + */ +int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst, u16 rstctrl_offs) +{ + u32 v; + + v = am33xx_prm_read_reg(inst, rstctrl_offs); + v &= 1 << shift; + v >>= shift; + + return v; +} + +/** + * am33xx_prm_assert_hardreset - assert the HW reset line of a submodule + * @shift: register bit shift corresponding to the reset line to assert + * @inst: CM instance register offset (*_INST macro) + * @rstctrl_reg: RM_RSTCTRL register address for this module + * + * Some IPs like dsp, ipu or iva contain processors that require an HW + * reset line to be asserted / deasserted in order to fully enable the + * IP. These modules may have multiple hard-reset lines that reset + * different 'submodules' inside the IP block. This function will + * place the submodule into reset. Returns 0 upon success or -EINVAL + * upon an argument error. + */ +int am33xx_prm_assert_hardreset(u8 shift, s16 inst, u16 rstctrl_offs) +{ + u32 mask = 1 << shift; + + am33xx_prm_rmw_reg_bits(mask, mask, inst, rstctrl_offs); + + return 0; +} + +/** + * am33xx_prm_deassert_hardreset - deassert a submodule hardreset line and + * wait + * @shift: register bit shift corresponding to the reset line to deassert + * @inst: CM instance register offset (*_INST macro) + * @rstctrl_reg: RM_RSTCTRL register address for this module + * @rstst_reg: RM_RSTST register address for this module + * + * Some IPs like dsp, ipu or iva contain processors that require an HW + * reset line to be asserted / deasserted in order to fully enable the + * IP. These modules may have multiple hard-reset lines that reset + * different 'submodules' inside the IP block. This function will + * take the submodule out of reset and wait until the PRCM indicates + * that the reset has completed before returning. Returns 0 upon success or + * -EINVAL upon an argument error, -EEXIST if the submodule was already out + * of reset, or -EBUSY if the submodule did not exit reset promptly. + */ +int am33xx_prm_deassert_hardreset(u8 shift, s16 inst, + u16 rstctrl_offs, u16 rstst_offs) +{ + int c; + u32 mask = 1 << shift; + + /* Check the current status to avoid de-asserting the line twice */ + if (am33xx_prm_is_hardreset_asserted(shift, inst, rstctrl_offs) == 0) + return -EEXIST; + + /* Clear the reset status by writing 1 to the status bit */ + am33xx_prm_rmw_reg_bits(0xffffffff, mask, inst, rstst_offs); + /* de-assert the reset control line */ + am33xx_prm_rmw_reg_bits(mask, 0, inst, rstctrl_offs); + /* wait the status to be set */ + + omap_test_timeout(am33xx_prm_is_hardreset_asserted(shift, inst, + rstst_offs), + MAX_MODULE_HARDRESET_WAIT, c); + + return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; +} diff --git a/arch/arm/mach-omap2/prm33xx.h b/arch/arm/mach-omap2/prm33xx.h new file mode 100644 index 000000000000..3f25c563a821 --- /dev/null +++ b/arch/arm/mach-omap2/prm33xx.h @@ -0,0 +1,129 @@ +/* + * AM33XX PRM instance offset macros + * + * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_PRM33XX_H +#define __ARCH_ARM_MACH_OMAP2_PRM33XX_H + +#include "prcm-common.h" +#include "prm.h" + +#define AM33XX_PRM_BASE 0x44E00000 + +#define AM33XX_PRM_REGADDR(inst, reg) \ + AM33XX_L4_WK_IO_ADDRESS(AM33XX_PRM_BASE + (inst) + (reg)) + + +/* PRM instances */ +#define AM33XX_PRM_OCP_SOCKET_MOD 0x0B00 +#define AM33XX_PRM_PER_MOD 0x0C00 +#define AM33XX_PRM_WKUP_MOD 0x0D00 +#define AM33XX_PRM_MPU_MOD 0x0E00 +#define AM33XX_PRM_DEVICE_MOD 0x0F00 +#define AM33XX_PRM_RTC_MOD 0x1000 +#define AM33XX_PRM_GFX_MOD 0x1100 +#define AM33XX_PRM_CEFUSE_MOD 0x1200 + +/* PRM */ + +/* PRM.OCP_SOCKET_PRM register offsets */ +#define AM33XX_REVISION_PRM_OFFSET 0x0000 +#define AM33XX_REVISION_PRM AM33XX_PRM_REGADDR(AM33XX_PRM_OCP_SOCKET_MOD, 0x0000) +#define AM33XX_PRM_IRQSTATUS_MPU_OFFSET 0x0004 +#define AM33XX_PRM_IRQSTATUS_MPU AM33XX_PRM_REGADDR(AM33XX_PRM_OCP_SOCKET_MOD, 0x0004) +#define AM33XX_PRM_IRQENABLE_MPU_OFFSET 0x0008 +#define AM33XX_PRM_IRQENABLE_MPU AM33XX_PRM_REGADDR(AM33XX_PRM_OCP_SOCKET_MOD, 0x0008) +#define AM33XX_PRM_IRQSTATUS_M3_OFFSET 0x000c +#define AM33XX_PRM_IRQSTATUS_M3 AM33XX_PRM_REGADDR(AM33XX_PRM_OCP_SOCKET_MOD, 0x000c) +#define AM33XX_PRM_IRQENABLE_M3_OFFSET 0x0010 +#define AM33XX_PRM_IRQENABLE_M3 AM33XX_PRM_REGADDR(AM33XX_PRM_OCP_SOCKET_MOD, 0x0010) + +/* PRM.PER_PRM register offsets */ +#define AM33XX_RM_PER_RSTCTRL_OFFSET 0x0000 +#define AM33XX_RM_PER_RSTCTRL AM33XX_PRM_REGADDR(AM33XX_PRM_PER_MOD, 0x0000) +#define AM33XX_RM_PER_RSTST_OFFSET 0x0004 +#define AM33XX_RM_PER_RSTST AM33XX_PRM_REGADDR(AM33XX_PRM_PER_MOD, 0x0004) +#define AM33XX_PM_PER_PWRSTST_OFFSET 0x0008 +#define AM33XX_PM_PER_PWRSTST AM33XX_PRM_REGADDR(AM33XX_PRM_PER_MOD, 0x0008) +#define AM33XX_PM_PER_PWRSTCTRL_OFFSET 0x000c +#define AM33XX_PM_PER_PWRSTCTRL AM33XX_PRM_REGADDR(AM33XX_PRM_PER_MOD, 0x000c) + +/* PRM.WKUP_PRM register offsets */ +#define AM33XX_RM_WKUP_RSTCTRL_OFFSET 0x0000 +#define AM33XX_RM_WKUP_RSTCTRL AM33XX_PRM_REGADDR(AM33XX_PRM_WKUP_MOD, 0x0000) +#define AM33XX_PM_WKUP_PWRSTCTRL_OFFSET 0x0004 +#define AM33XX_PM_WKUP_PWRSTCTRL AM33XX_PRM_REGADDR(AM33XX_PRM_WKUP_MOD, 0x0004) +#define AM33XX_PM_WKUP_PWRSTST_OFFSET 0x0008 +#define AM33XX_PM_WKUP_PWRSTST AM33XX_PRM_REGADDR(AM33XX_PRM_WKUP_MOD, 0x0008) +#define AM33XX_RM_WKUP_RSTST_OFFSET 0x000c +#define AM33XX_RM_WKUP_RSTST AM33XX_PRM_REGADDR(AM33XX_PRM_WKUP_MOD, 0x000c) + +/* PRM.MPU_PRM register offsets */ +#define AM33XX_PM_MPU_PWRSTCTRL_OFFSET 0x0000 +#define AM33XX_PM_MPU_PWRSTCTRL AM33XX_PRM_REGADDR(AM33XX_PRM_MPU_MOD, 0x0000) +#define AM33XX_PM_MPU_PWRSTST_OFFSET 0x0004 +#define AM33XX_PM_MPU_PWRSTST AM33XX_PRM_REGADDR(AM33XX_PRM_MPU_MOD, 0x0004) +#define AM33XX_RM_MPU_RSTST_OFFSET 0x0008 +#define AM33XX_RM_MPU_RSTST AM33XX_PRM_REGADDR(AM33XX_PRM_MPU_MOD, 0x0008) + +/* PRM.DEVICE_PRM register offsets */ +#define AM33XX_PRM_RSTCTRL_OFFSET 0x0000 +#define AM33XX_PRM_RSTCTRL AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x0000) +#define AM33XX_PRM_RSTTIME_OFFSET 0x0004 +#define AM33XX_PRM_RSTTIME AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x0004) +#define AM33XX_PRM_RSTST_OFFSET 0x0008 +#define AM33XX_PRM_RSTST AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x0008) +#define AM33XX_PRM_SRAM_COUNT_OFFSET 0x000c +#define AM33XX_PRM_SRAM_COUNT AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x000c) +#define AM33XX_PRM_LDO_SRAM_CORE_SETUP_OFFSET 0x0010 +#define AM33XX_PRM_LDO_SRAM_CORE_SETUP AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x0010) +#define AM33XX_PRM_LDO_SRAM_CORE_CTRL_OFFSET 0x0014 +#define AM33XX_PRM_LDO_SRAM_CORE_CTRL AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x0014) +#define AM33XX_PRM_LDO_SRAM_MPU_SETUP_OFFSET 0x0018 +#define AM33XX_PRM_LDO_SRAM_MPU_SETUP AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x0018) +#define AM33XX_PRM_LDO_SRAM_MPU_CTRL_OFFSET 0x001c +#define AM33XX_PRM_LDO_SRAM_MPU_CTRL AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x001c) + +/* PRM.RTC_PRM register offsets */ +#define AM33XX_PM_RTC_PWRSTCTRL_OFFSET 0x0000 +#define AM33XX_PM_RTC_PWRSTCTRL AM33XX_PRM_REGADDR(AM33XX_PRM_RTC_MOD, 0x0000) +#define AM33XX_PM_RTC_PWRSTST_OFFSET 0x0004 +#define AM33XX_PM_RTC_PWRSTST AM33XX_PRM_REGADDR(AM33XX_PRM_RTC_MOD, 0x0004) + +/* PRM.GFX_PRM register offsets */ +#define AM33XX_PM_GFX_PWRSTCTRL_OFFSET 0x0000 +#define AM33XX_PM_GFX_PWRSTCTRL AM33XX_PRM_REGADDR(AM33XX_PRM_GFX_MOD, 0x0000) +#define AM33XX_RM_GFX_RSTCTRL_OFFSET 0x0004 +#define AM33XX_RM_GFX_RSTCTRL AM33XX_PRM_REGADDR(AM33XX_PRM_GFX_MOD, 0x0004) +#define AM33XX_PM_GFX_PWRSTST_OFFSET 0x0010 +#define AM33XX_PM_GFX_PWRSTST AM33XX_PRM_REGADDR(AM33XX_PRM_GFX_MOD, 0x0010) +#define AM33XX_RM_GFX_RSTST_OFFSET 0x0014 +#define AM33XX_RM_GFX_RSTST AM33XX_PRM_REGADDR(AM33XX_PRM_GFX_MOD, 0x0014) + +/* PRM.CEFUSE_PRM register offsets */ +#define AM33XX_PM_CEFUSE_PWRSTCTRL_OFFSET 0x0000 +#define AM33XX_PM_CEFUSE_PWRSTCTRL AM33XX_PRM_REGADDR(AM33XX_PRM_CEFUSE_MOD, 0x0000) +#define AM33XX_PM_CEFUSE_PWRSTST_OFFSET 0x0004 +#define AM33XX_PM_CEFUSE_PWRSTST AM33XX_PRM_REGADDR(AM33XX_PRM_CEFUSE_MOD, 0x0004) + +extern u32 am33xx_prm_read_reg(s16 inst, u16 idx); +extern void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx); +extern u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx); +extern void am33xx_prm_global_warm_sw_reset(void); +extern int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst, + u16 rstctrl_offs); +extern int am33xx_prm_assert_hardreset(u8 shift, s16 inst, u16 rstctrl_offs); +extern int am33xx_prm_deassert_hardreset(u8 shift, s16 inst, + u16 rstctrl_offs, u16 rstst_offs); +#endif -- cgit v1.2.3 From f969a6dcec75fe997a156b904d4fbbb5b313e54f Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 18 Jun 2012 00:47:26 -0600 Subject: ARM: OMAP AM33xx: CM: Introduce AM33xx CM APIs and register level details As far as PRM/CM/PRCM modules are concerned, AM33XX device is different than OMAP3 and OMAP4 architectures; so similar to PRM implementation, handle AM33XX CM separately. This patch introduces AM33XX CM module low-level api's, used and required by omap clockdomain and hwmod framework. Please note that cm-regbits-33xx.h (register bit field offset) and cm33xx.h (register addr offset) files are mostly auto generated. Signed-off-by: Vaibhav Hiremath Signed-off-by: Afzal Mohammed Signed-off-by: Vaibhav Bedia Cc: Kevin Hilman Cc: Rajendra Nayak CC: Tony Lindgren Cc: Paul Walmsley Cc: Benoit Cousson [paul@pwsan.com: split the hwmod code changes in this patch into a separate patch; updated for 3.5] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/Makefile | 2 +- arch/arm/mach-omap2/cm-regbits-33xx.h | 687 ++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/cm33xx.c | 313 ++++++++++++++++ arch/arm/mach-omap2/cm33xx.h | 420 +++++++++++++++++++++ 4 files changed, 1421 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-omap2/cm-regbits-33xx.h create mode 100644 arch/arm/mach-omap2/cm33xx.c create mode 100644 arch/arm/mach-omap2/cm33xx.h (limited to 'arch') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 76921ebc63d9..cc080946ec61 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -90,7 +90,7 @@ obj-$(CONFIG_ARCH_OMAP3) += vc3xxx_data.o vp3xxx_data.o obj-$(CONFIG_ARCH_OMAP4) += prcm.o cminst44xx.o cm44xx.o obj-$(CONFIG_ARCH_OMAP4) += prcm_mpu44xx.o prminst44xx.o obj-$(CONFIG_ARCH_OMAP4) += vc44xx_data.o vp44xx_data.o prm44xx.o -obj-$(CONFIG_SOC_AM33XX) += prcm.o prm33xx.o +obj-$(CONFIG_SOC_AM33XX) += prcm.o prm33xx.o cm33xx.o # OMAP voltage domains voltagedomain-common := voltage.o vc.o vp.o diff --git a/arch/arm/mach-omap2/cm-regbits-33xx.h b/arch/arm/mach-omap2/cm-regbits-33xx.h new file mode 100644 index 000000000000..532027ee3d8d --- /dev/null +++ b/arch/arm/mach-omap2/cm-regbits-33xx.h @@ -0,0 +1,687 @@ +/* + * AM33XX Power Management register bits + * + * This file is automatically generated from the AM33XX hardware databases. + * Vaibhav Hiremath + * + * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#ifndef __ARCH_ARM_MACH_OMAP2_CM_REGBITS_33XX_H +#define __ARCH_ARM_MACH_OMAP2_CM_REGBITS_33XX_H + +/* + * Used by CM_AUTOIDLE_DPLL_CORE, CM_AUTOIDLE_DPLL_DDR, CM_AUTOIDLE_DPLL_DISP, + * CM_AUTOIDLE_DPLL_MPU, CM_AUTOIDLE_DPLL_PER + */ +#define AM33XX_AUTO_DPLL_MODE_SHIFT 0 +#define AM33XX_AUTO_DPLL_MODE_MASK (0x7 << 0) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_ADC_FCLK_SHIFT 14 +#define AM33XX_CLKACTIVITY_ADC_FCLK_MASK (1 << 16) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_CAN_CLK_SHIFT 11 +#define AM33XX_CLKACTIVITY_CAN_CLK_MASK (1 << 11) + +/* Used by CM_PER_CLK_24MHZ_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_CLK_24MHZ_GCLK_SHIFT 4 +#define AM33XX_CLKACTIVITY_CLK_24MHZ_GCLK_MASK (1 << 4) + +/* Used by CM_PER_CPSW_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_CPSW_125MHZ_GCLK_SHIFT 4 +#define AM33XX_CLKACTIVITY_CPSW_125MHZ_GCLK_MASK (1 << 4) + +/* Used by CM_PER_L4HS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_CPSW_250MHZ_GCLK_SHIFT 4 +#define AM33XX_CLKACTIVITY_CPSW_250MHZ_GCLK_MASK (1 << 4) + +/* Used by CM_PER_L4HS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_CPSW_50MHZ_GCLK_SHIFT 5 +#define AM33XX_CLKACTIVITY_CPSW_50MHZ_GCLK_MASK (1 << 5) + +/* Used by CM_PER_L4HS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_CPSW_5MHZ_GCLK_SHIFT 6 +#define AM33XX_CLKACTIVITY_CPSW_5MHZ_GCLK_MASK (1 << 6) + +/* Used by CM_PER_L3_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_CPTS_RFT_GCLK_SHIFT 6 +#define AM33XX_CLKACTIVITY_CPTS_RFT_GCLK_MASK (1 << 6) + +/* Used by CM_CEFUSE_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT 9 +#define AM33XX_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK (1 << 9) + +/* Used by CM_L3_AON_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_DBGSYSCLK_SHIFT 2 +#define AM33XX_CLKACTIVITY_DBGSYSCLK_MASK (1 << 2) + +/* Used by CM_L3_AON_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_DEBUG_CLKA_SHIFT 4 +#define AM33XX_CLKACTIVITY_DEBUG_CLKA_MASK (1 << 4) + +/* Used by CM_PER_L3_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_EMIF_GCLK_SHIFT 2 +#define AM33XX_CLKACTIVITY_EMIF_GCLK_MASK (1 << 2) + +/* Used by CM_GFX_L3_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_GFX_FCLK_SHIFT 9 +#define AM33XX_CLKACTIVITY_GFX_FCLK_MASK (1 << 9) + +/* Used by CM_GFX_L3_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_GFX_L3_GCLK_SHIFT 8 +#define AM33XX_CLKACTIVITY_GFX_L3_GCLK_MASK (1 << 8) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_GPIO0_GDBCLK_SHIFT 8 +#define AM33XX_CLKACTIVITY_GPIO0_GDBCLK_MASK (1 << 8) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_GPIO_1_GDBCLK_SHIFT 19 +#define AM33XX_CLKACTIVITY_GPIO_1_GDBCLK_MASK (1 << 19) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_GPIO_2_GDBCLK_SHIFT 20 +#define AM33XX_CLKACTIVITY_GPIO_2_GDBCLK_MASK (1 << 20) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_GPIO_3_GDBCLK_SHIFT 21 +#define AM33XX_CLKACTIVITY_GPIO_3_GDBCLK_MASK (1 << 21) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_GPIO_4_GDBCLK_SHIFT 22 +#define AM33XX_CLKACTIVITY_GPIO_4_GDBCLK_MASK (1 << 22) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_GPIO_5_GDBCLK_SHIFT 26 +#define AM33XX_CLKACTIVITY_GPIO_5_GDBCLK_MASK (1 << 26) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_GPIO_6_GDBCLK_SHIFT 18 +#define AM33XX_CLKACTIVITY_GPIO_6_GDBCLK_MASK (1 << 18) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_I2C0_GFCLK_SHIFT 11 +#define AM33XX_CLKACTIVITY_I2C0_GFCLK_MASK (1 << 11) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_I2C_FCLK_SHIFT 24 +#define AM33XX_CLKACTIVITY_I2C_FCLK_MASK (1 << 24) + +/* Used by CM_PER_PRUSS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_PRUSS_IEP_GCLK_SHIFT 5 +#define AM33XX_CLKACTIVITY_PRUSS_IEP_GCLK_MASK (1 << 5) + +/* Used by CM_PER_PRUSS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_PRUSS_OCP_GCLK_SHIFT 4 +#define AM33XX_CLKACTIVITY_PRUSS_OCP_GCLK_MASK (1 << 4) + +/* Used by CM_PER_PRUSS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_PRUSS_UART_GCLK_SHIFT 6 +#define AM33XX_CLKACTIVITY_PRUSS_UART_GCLK_MASK (1 << 6) + +/* Used by CM_PER_L3S_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_L3S_GCLK_SHIFT 3 +#define AM33XX_CLKACTIVITY_L3S_GCLK_MASK (1 << 3) + +/* Used by CM_L3_AON_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_L3_AON_GCLK_SHIFT 3 +#define AM33XX_CLKACTIVITY_L3_AON_GCLK_MASK (1 << 3) + +/* Used by CM_PER_L3_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_L3_GCLK_SHIFT 4 +#define AM33XX_CLKACTIVITY_L3_GCLK_MASK (1 << 4) + +/* Used by CM_PER_L4FW_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_L4FW_GCLK_SHIFT 8 +#define AM33XX_CLKACTIVITY_L4FW_GCLK_MASK (1 << 8) + +/* Used by CM_PER_L4HS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_L4HS_GCLK_SHIFT 3 +#define AM33XX_CLKACTIVITY_L4HS_GCLK_MASK (1 << 3) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_L4LS_GCLK_SHIFT 8 +#define AM33XX_CLKACTIVITY_L4LS_GCLK_MASK (1 << 8) + +/* Used by CM_GFX_L4LS_GFX_CLKSTCTRL__1 */ +#define AM33XX_CLKACTIVITY_L4LS_GFX_GCLK_SHIFT 8 +#define AM33XX_CLKACTIVITY_L4LS_GFX_GCLK_MASK (1 << 8) + +/* Used by CM_CEFUSE_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_L4_CEFUSE_GICLK_SHIFT 8 +#define AM33XX_CLKACTIVITY_L4_CEFUSE_GICLK_MASK (1 << 8) + +/* Used by CM_RTC_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_L4_RTC_GCLK_SHIFT 8 +#define AM33XX_CLKACTIVITY_L4_RTC_GCLK_MASK (1 << 8) + +/* Used by CM_L4_WKUP_AON_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_L4_WKUP_AON_GCLK_SHIFT 2 +#define AM33XX_CLKACTIVITY_L4_WKUP_AON_GCLK_MASK (1 << 2) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_L4_WKUP_GCLK_SHIFT 2 +#define AM33XX_CLKACTIVITY_L4_WKUP_GCLK_MASK (1 << 2) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_LCDC_GCLK_SHIFT 17 +#define AM33XX_CLKACTIVITY_LCDC_GCLK_MASK (1 << 17) + +/* Used by CM_PER_LCDC_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_LCDC_L3_OCP_GCLK_SHIFT 4 +#define AM33XX_CLKACTIVITY_LCDC_L3_OCP_GCLK_MASK (1 << 4) + +/* Used by CM_PER_LCDC_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_LCDC_L4_OCP_GCLK_SHIFT 5 +#define AM33XX_CLKACTIVITY_LCDC_L4_OCP_GCLK_MASK (1 << 5) + +/* Used by CM_PER_L3_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_MCASP_GCLK_SHIFT 7 +#define AM33XX_CLKACTIVITY_MCASP_GCLK_MASK (1 << 7) + +/* Used by CM_PER_L3_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_MMC_FCLK_SHIFT 3 +#define AM33XX_CLKACTIVITY_MMC_FCLK_MASK (1 << 3) + +/* Used by CM_MPU_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_MPU_CLK_SHIFT 2 +#define AM33XX_CLKACTIVITY_MPU_CLK_MASK (1 << 2) + +/* Used by CM_PER_OCPWP_L3_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_OCPWP_L3_GCLK_SHIFT 4 +#define AM33XX_CLKACTIVITY_OCPWP_L3_GCLK_MASK (1 << 4) + +/* Used by CM_PER_OCPWP_L3_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_OCPWP_L4_GCLK_SHIFT 5 +#define AM33XX_CLKACTIVITY_OCPWP_L4_GCLK_MASK (1 << 5) + +/* Used by CM_RTC_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_RTC_32KCLK_SHIFT 9 +#define AM33XX_CLKACTIVITY_RTC_32KCLK_MASK (1 << 9) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_SPI_GCLK_SHIFT 25 +#define AM33XX_CLKACTIVITY_SPI_GCLK_MASK (1 << 25) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_SR_SYSCLK_SHIFT 3 +#define AM33XX_CLKACTIVITY_SR_SYSCLK_MASK (1 << 3) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_TIMER0_GCLK_SHIFT 10 +#define AM33XX_CLKACTIVITY_TIMER0_GCLK_MASK (1 << 10) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_TIMER1_GCLK_SHIFT 13 +#define AM33XX_CLKACTIVITY_TIMER1_GCLK_MASK (1 << 13) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_TIMER2_GCLK_SHIFT 14 +#define AM33XX_CLKACTIVITY_TIMER2_GCLK_MASK (1 << 14) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_TIMER3_GCLK_SHIFT 15 +#define AM33XX_CLKACTIVITY_TIMER3_GCLK_MASK (1 << 15) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_TIMER4_GCLK_SHIFT 16 +#define AM33XX_CLKACTIVITY_TIMER4_GCLK_MASK (1 << 16) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_TIMER5_GCLK_SHIFT 27 +#define AM33XX_CLKACTIVITY_TIMER5_GCLK_MASK (1 << 27) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_TIMER6_GCLK_SHIFT 28 +#define AM33XX_CLKACTIVITY_TIMER6_GCLK_MASK (1 << 28) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_TIMER7_GCLK_SHIFT 13 +#define AM33XX_CLKACTIVITY_TIMER7_GCLK_MASK (1 << 13) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_UART0_GFCLK_SHIFT 12 +#define AM33XX_CLKACTIVITY_UART0_GFCLK_MASK (1 << 12) + +/* Used by CM_PER_L4LS_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_UART_GFCLK_SHIFT 10 +#define AM33XX_CLKACTIVITY_UART_GFCLK_MASK (1 << 10) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_WDT0_GCLK_SHIFT 9 +#define AM33XX_CLKACTIVITY_WDT0_GCLK_MASK (1 << 9) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define AM33XX_CLKACTIVITY_WDT1_GCLK_SHIFT 4 +#define AM33XX_CLKACTIVITY_WDT1_GCLK_MASK (1 << 4) + +/* Used by CLKSEL_GFX_FCLK */ +#define AM33XX_CLKDIV_SEL_GFX_FCLK_SHIFT 0 +#define AM33XX_CLKDIV_SEL_GFX_FCLK_MASK (1 << 0) + +/* Used by CM_CLKOUT_CTRL */ +#define AM33XX_CLKOUT2DIV_SHIFT 3 +#define AM33XX_CLKOUT2DIV_MASK (0x05 << 3) + +/* Used by CM_CLKOUT_CTRL */ +#define AM33XX_CLKOUT2EN_SHIFT 7 +#define AM33XX_CLKOUT2EN_MASK (1 << 7) + +/* Used by CM_CLKOUT_CTRL */ +#define AM33XX_CLKOUT2SOURCE_SHIFT 0 +#define AM33XX_CLKOUT2SOURCE_MASK (0x02 << 0) + +/* + * Used by CLKSEL_GPIO0_DBCLK, CLKSEL_LCDC_PIXEL_CLK, CLKSEL_TIMER2_CLK, + * CLKSEL_TIMER3_CLK, CLKSEL_TIMER4_CLK, CLKSEL_TIMER5_CLK, CLKSEL_TIMER6_CLK, + * CLKSEL_TIMER7_CLK + */ +#define AM33XX_CLKSEL_SHIFT 0 +#define AM33XX_CLKSEL_MASK (0x01 << 0) + +/* + * Renamed from CLKSEL Used by CLKSEL_PRUSS_OCP_CLK, CLKSEL_WDT1_CLK, + * CM_CPTS_RFT_CLKSEL + */ +#define AM33XX_CLKSEL_0_0_SHIFT 0 +#define AM33XX_CLKSEL_0_0_MASK (1 << 0) + +#define AM33XX_CLKSEL_0_1_SHIFT 0 +#define AM33XX_CLKSEL_0_1_MASK (3 << 0) + +/* Renamed from CLKSEL Used by CLKSEL_TIMER1MS_CLK */ +#define AM33XX_CLKSEL_0_2_SHIFT 0 +#define AM33XX_CLKSEL_0_2_MASK (7 << 0) + +/* Used by CLKSEL_GFX_FCLK */ +#define AM33XX_CLKSEL_GFX_FCLK_SHIFT 1 +#define AM33XX_CLKSEL_GFX_FCLK_MASK (1 << 1) + +/* + * Used by CM_MPU_CLKSTCTRL, CM_RTC_CLKSTCTRL, CM_PER_CLK_24MHZ_CLKSTCTRL, + * CM_PER_CPSW_CLKSTCTRL, CM_PER_PRUSS_CLKSTCTRL, CM_PER_L3S_CLKSTCTRL, + * CM_PER_L3_CLKSTCTRL, CM_PER_L4FW_CLKSTCTRL, CM_PER_L4HS_CLKSTCTRL, + * CM_PER_L4LS_CLKSTCTRL, CM_PER_LCDC_CLKSTCTRL, CM_PER_OCPWP_L3_CLKSTCTRL, + * CM_L3_AON_CLKSTCTRL, CM_L4_WKUP_AON_CLKSTCTRL, CM_WKUP_CLKSTCTRL, + * CM_GFX_L3_CLKSTCTRL, CM_GFX_L4LS_GFX_CLKSTCTRL__1, CM_CEFUSE_CLKSTCTRL + */ +#define AM33XX_CLKTRCTRL_SHIFT 0 +#define AM33XX_CLKTRCTRL_MASK (0x3 << 0) + +/* + * Used by CM_SSC_DELTAMSTEP_DPLL_CORE, CM_SSC_DELTAMSTEP_DPLL_DDR, + * CM_SSC_DELTAMSTEP_DPLL_DISP, CM_SSC_DELTAMSTEP_DPLL_MPU, + * CM_SSC_DELTAMSTEP_DPLL_PER + */ +#define AM33XX_DELTAMSTEP_SHIFT 0 +#define AM33XX_DELTAMSTEP_MASK (0x19 << 0) + +/* Used by CM_CLKSEL_DPLL_DDR, CM_CLKSEL_DPLL_DISP, CM_CLKSEL_DPLL_MPU */ +#define AM33XX_DPLL_BYP_CLKSEL_SHIFT 23 +#define AM33XX_DPLL_BYP_CLKSEL_MASK (1 << 23) + +/* Used by CM_CLKDCOLDO_DPLL_PER */ +#define AM33XX_DPLL_CLKDCOLDO_GATE_CTRL_SHIFT 8 +#define AM33XX_DPLL_CLKDCOLDO_GATE_CTRL_MASK (1 << 8) + +/* Used by CM_CLKDCOLDO_DPLL_PER */ +#define AM33XX_DPLL_CLKDCOLDO_PWDN_SHIFT 12 +#define AM33XX_DPLL_CLKDCOLDO_PWDN_MASK (1 << 12) + +/* Used by CM_DIV_M2_DPLL_DDR, CM_DIV_M2_DPLL_DISP, CM_DIV_M2_DPLL_MPU */ +#define AM33XX_DPLL_CLKOUT_DIV_SHIFT 0 +#define AM33XX_DPLL_CLKOUT_DIV_MASK (0x1f << 0) + +/* Renamed from DPLL_CLKOUT_DIV Used by CM_DIV_M2_DPLL_PER */ +#define AM33XX_DPLL_CLKOUT_DIV_0_6_SHIFT 0 +#define AM33XX_DPLL_CLKOUT_DIV_0_6_MASK (0x06 << 0) + +/* Used by CM_DIV_M2_DPLL_DDR, CM_DIV_M2_DPLL_DISP, CM_DIV_M2_DPLL_MPU */ +#define AM33XX_DPLL_CLKOUT_DIVCHACK_SHIFT 5 +#define AM33XX_DPLL_CLKOUT_DIVCHACK_MASK (1 << 5) + +/* Renamed from DPLL_CLKOUT_DIVCHACK Used by CM_DIV_M2_DPLL_PER */ +#define AM33XX_DPLL_CLKOUT_DIVCHACK_M2_PER_SHIFT 7 +#define AM33XX_DPLL_CLKOUT_DIVCHACK_M2_PER_MASK (1 << 7) + +/* + * Used by CM_DIV_M2_DPLL_DDR, CM_DIV_M2_DPLL_DISP, CM_DIV_M2_DPLL_MPU, + * CM_DIV_M2_DPLL_PER + */ +#define AM33XX_DPLL_CLKOUT_GATE_CTRL_SHIFT 8 +#define AM33XX_DPLL_CLKOUT_GATE_CTRL_MASK (1 << 8) + +/* + * Used by CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_DDR, CM_CLKSEL_DPLL_DISP, + * CM_CLKSEL_DPLL_MPU + */ +#define AM33XX_DPLL_DIV_SHIFT 0 +#define AM33XX_DPLL_DIV_MASK (0x7f << 0) + +#define AM33XX_DPLL_PER_DIV_MASK (0xff << 0) + +/* Renamed from DPLL_DIV Used by CM_CLKSEL_DPLL_PERIPH */ +#define AM33XX_DPLL_DIV_0_7_SHIFT 0 +#define AM33XX_DPLL_DIV_0_7_MASK (0x07 << 0) + +/* + * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP, + * CM_CLKMODE_DPLL_MPU + */ +#define AM33XX_DPLL_DRIFTGUARD_EN_SHIFT 8 +#define AM33XX_DPLL_DRIFTGUARD_EN_MASK (1 << 8) + +/* + * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP, + * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER + */ +#define AM33XX_DPLL_EN_SHIFT 0 +#define AM33XX_DPLL_EN_MASK (0x7 << 0) + +/* + * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP, + * CM_CLKMODE_DPLL_MPU + */ +#define AM33XX_DPLL_LPMODE_EN_SHIFT 10 +#define AM33XX_DPLL_LPMODE_EN_MASK (1 << 10) + +/* + * Used by CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_DDR, CM_CLKSEL_DPLL_DISP, + * CM_CLKSEL_DPLL_MPU + */ +#define AM33XX_DPLL_MULT_SHIFT 8 +#define AM33XX_DPLL_MULT_MASK (0x7ff << 8) + +/* Renamed from DPLL_MULT Used by CM_CLKSEL_DPLL_PERIPH */ +#define AM33XX_DPLL_MULT_PERIPH_SHIFT 8 +#define AM33XX_DPLL_MULT_PERIPH_MASK (0xfff << 8) + +/* + * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP, + * CM_CLKMODE_DPLL_MPU + */ +#define AM33XX_DPLL_REGM4XEN_SHIFT 11 +#define AM33XX_DPLL_REGM4XEN_MASK (1 << 11) + +/* Used by CM_CLKSEL_DPLL_PERIPH */ +#define AM33XX_DPLL_SD_DIV_SHIFT 24 +#define AM33XX_DPLL_SD_DIV_MASK (24, 31) + +/* + * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP, + * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER + */ +#define AM33XX_DPLL_SSC_ACK_SHIFT 13 +#define AM33XX_DPLL_SSC_ACK_MASK (1 << 13) + +/* + * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP, + * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER + */ +#define AM33XX_DPLL_SSC_DOWNSPREAD_SHIFT 14 +#define AM33XX_DPLL_SSC_DOWNSPREAD_MASK (1 << 14) + +/* + * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP, + * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER + */ +#define AM33XX_DPLL_SSC_EN_SHIFT 12 +#define AM33XX_DPLL_SSC_EN_MASK (1 << 12) + +/* Used by CM_DIV_M4_DPLL_CORE */ +#define AM33XX_HSDIVIDER_CLKOUT1_DIV_SHIFT 0 +#define AM33XX_HSDIVIDER_CLKOUT1_DIV_MASK (0x1f << 0) + +/* Used by CM_DIV_M4_DPLL_CORE */ +#define AM33XX_HSDIVIDER_CLKOUT1_DIVCHACK_SHIFT 5 +#define AM33XX_HSDIVIDER_CLKOUT1_DIVCHACK_MASK (1 << 5) + +/* Used by CM_DIV_M4_DPLL_CORE */ +#define AM33XX_HSDIVIDER_CLKOUT1_GATE_CTRL_SHIFT 8 +#define AM33XX_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK (1 << 8) + +/* Used by CM_DIV_M4_DPLL_CORE */ +#define AM33XX_HSDIVIDER_CLKOUT1_PWDN_SHIFT 12 +#define AM33XX_HSDIVIDER_CLKOUT1_PWDN_MASK (1 << 12) + +/* Used by CM_DIV_M5_DPLL_CORE */ +#define AM33XX_HSDIVIDER_CLKOUT2_DIV_SHIFT 0 +#define AM33XX_HSDIVIDER_CLKOUT2_DIV_MASK (0x1f << 0) + +/* Used by CM_DIV_M5_DPLL_CORE */ +#define AM33XX_HSDIVIDER_CLKOUT2_DIVCHACK_SHIFT 5 +#define AM33XX_HSDIVIDER_CLKOUT2_DIVCHACK_MASK (1 << 5) + +/* Used by CM_DIV_M5_DPLL_CORE */ +#define AM33XX_HSDIVIDER_CLKOUT2_GATE_CTRL_SHIFT 8 +#define AM33XX_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK (1 << 8) + +/* Used by CM_DIV_M5_DPLL_CORE */ +#define AM33XX_HSDIVIDER_CLKOUT2_PWDN_SHIFT 12 +#define AM33XX_HSDIVIDER_CLKOUT2_PWDN_MASK (1 << 12) + +/* Used by CM_DIV_M6_DPLL_CORE */ +#define AM33XX_HSDIVIDER_CLKOUT3_DIV_SHIFT 0 +#define AM33XX_HSDIVIDER_CLKOUT3_DIV_MASK (0x04 << 0) + +/* Used by CM_DIV_M6_DPLL_CORE */ +#define AM33XX_HSDIVIDER_CLKOUT3_DIVCHACK_SHIFT 5 +#define AM33XX_HSDIVIDER_CLKOUT3_DIVCHACK_MASK (1 << 5) + +/* Used by CM_DIV_M6_DPLL_CORE */ +#define AM33XX_HSDIVIDER_CLKOUT3_GATE_CTRL_SHIFT 8 +#define AM33XX_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK (1 << 8) + +/* Used by CM_DIV_M6_DPLL_CORE */ +#define AM33XX_HSDIVIDER_CLKOUT3_PWDN_SHIFT 12 +#define AM33XX_HSDIVIDER_CLKOUT3_PWDN_MASK (1 << 12) + +/* + * Used by CM_MPU_MPU_CLKCTRL, CM_RTC_RTC_CLKCTRL, CM_PER_AES0_CLKCTRL, + * CM_PER_AES1_CLKCTRL, CM_PER_CLKDIV32K_CLKCTRL, CM_PER_CPGMAC0_CLKCTRL, + * CM_PER_DCAN0_CLKCTRL, CM_PER_DCAN1_CLKCTRL, CM_PER_DES_CLKCTRL, + * CM_PER_ELM_CLKCTRL, CM_PER_EMIF_CLKCTRL, CM_PER_EMIF_FW_CLKCTRL, + * CM_PER_EPWMSS0_CLKCTRL, CM_PER_EPWMSS1_CLKCTRL, CM_PER_EPWMSS2_CLKCTRL, + * CM_PER_GPIO1_CLKCTRL, CM_PER_GPIO2_CLKCTRL, CM_PER_GPIO3_CLKCTRL, + * CM_PER_GPIO4_CLKCTRL, CM_PER_GPIO5_CLKCTRL, CM_PER_GPIO6_CLKCTRL, + * CM_PER_GPMC_CLKCTRL, CM_PER_I2C1_CLKCTRL, CM_PER_I2C2_CLKCTRL, + * CM_PER_PRUSS_CLKCTRL, CM_PER_IEEE5000_CLKCTRL, CM_PER_L3_CLKCTRL, + * CM_PER_L3_INSTR_CLKCTRL, CM_PER_L4FW_CLKCTRL, CM_PER_L4HS_CLKCTRL, + * CM_PER_L4LS_CLKCTRL, CM_PER_LCDC_CLKCTRL, CM_PER_MAILBOX0_CLKCTRL, + * CM_PER_MAILBOX1_CLKCTRL, CM_PER_MCASP0_CLKCTRL, CM_PER_MCASP1_CLKCTRL, + * CM_PER_MCASP2_CLKCTRL, CM_PER_MLB_CLKCTRL, CM_PER_MMC0_CLKCTRL, + * CM_PER_MMC1_CLKCTRL, CM_PER_MMC2_CLKCTRL, CM_PER_MSTR_EXPS_CLKCTRL, + * CM_PER_OCMCRAM_CLKCTRL, CM_PER_OCPWP_CLKCTRL, CM_PER_PCIE_CLKCTRL, + * CM_PER_PKA_CLKCTRL, CM_PER_RNG_CLKCTRL, CM_PER_SHA0_CLKCTRL, + * CM_PER_SLV_EXPS_CLKCTRL, CM_PER_SPARE0_CLKCTRL, CM_PER_SPARE1_CLKCTRL, + * CM_PER_SPARE_CLKCTRL, CM_PER_SPI0_CLKCTRL, CM_PER_SPI1_CLKCTRL, + * CM_PER_SPI2_CLKCTRL, CM_PER_SPI3_CLKCTRL, CM_PER_SPINLOCK_CLKCTRL, + * CM_PER_TIMER2_CLKCTRL, CM_PER_TIMER3_CLKCTRL, CM_PER_TIMER4_CLKCTRL, + * CM_PER_TIMER5_CLKCTRL, CM_PER_TIMER6_CLKCTRL, CM_PER_TIMER7_CLKCTRL, + * CM_PER_TPCC_CLKCTRL, CM_PER_TPTC0_CLKCTRL, CM_PER_TPTC1_CLKCTRL, + * CM_PER_TPTC2_CLKCTRL, CM_PER_UART1_CLKCTRL, CM_PER_UART2_CLKCTRL, + * CM_PER_UART3_CLKCTRL, CM_PER_UART4_CLKCTRL, CM_PER_UART5_CLKCTRL, + * CM_PER_USB0_CLKCTRL, CM_WKUP_ADC_TSC_CLKCTRL, CM_WKUP_CONTROL_CLKCTRL, + * CM_WKUP_DEBUGSS_CLKCTRL, CM_WKUP_GPIO0_CLKCTRL, CM_WKUP_I2C0_CLKCTRL, + * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_SMARTREFLEX0_CLKCTRL, + * CM_WKUP_SMARTREFLEX1_CLKCTRL, CM_WKUP_TIMER0_CLKCTRL, + * CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_UART0_CLKCTRL, CM_WKUP_WDT0_CLKCTRL, + * CM_WKUP_WDT1_CLKCTRL, CM_GFX_BITBLT_CLKCTRL, CM_GFX_GFX_CLKCTRL, + * CM_GFX_MMUCFG_CLKCTRL, CM_GFX_MMUDATA_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL + */ +#define AM33XX_IDLEST_SHIFT 16 +#define AM33XX_IDLEST_MASK (0x3 << 16) +#define AM33XX_IDLEST_VAL 0x3 + +/* Used by CM_MAC_CLKSEL */ +#define AM33XX_MII_CLK_SEL_SHIFT 2 +#define AM33XX_MII_CLK_SEL_MASK (1 << 2) + +/* + * Used by CM_SSC_MODFREQDIV_DPLL_CORE, CM_SSC_MODFREQDIV_DPLL_DDR, + * CM_SSC_MODFREQDIV_DPLL_DISP, CM_SSC_MODFREQDIV_DPLL_MPU, + * CM_SSC_MODFREQDIV_DPLL_PER + */ +#define AM33XX_MODFREQDIV_EXPONENT_SHIFT 8 +#define AM33XX_MODFREQDIV_EXPONENT_MASK (0x10 << 8) + +/* + * Used by CM_SSC_MODFREQDIV_DPLL_CORE, CM_SSC_MODFREQDIV_DPLL_DDR, + * CM_SSC_MODFREQDIV_DPLL_DISP, CM_SSC_MODFREQDIV_DPLL_MPU, + * CM_SSC_MODFREQDIV_DPLL_PER + */ +#define AM33XX_MODFREQDIV_MANTISSA_SHIFT 0 +#define AM33XX_MODFREQDIV_MANTISSA_MASK (0x06 << 0) + +/* + * Used by CM_MPU_MPU_CLKCTRL, CM_RTC_RTC_CLKCTRL, CM_PER_AES0_CLKCTRL, + * CM_PER_AES1_CLKCTRL, CM_PER_CLKDIV32K_CLKCTRL, CM_PER_CPGMAC0_CLKCTRL, + * CM_PER_DCAN0_CLKCTRL, CM_PER_DCAN1_CLKCTRL, CM_PER_DES_CLKCTRL, + * CM_PER_ELM_CLKCTRL, CM_PER_EMIF_CLKCTRL, CM_PER_EMIF_FW_CLKCTRL, + * CM_PER_EPWMSS0_CLKCTRL, CM_PER_EPWMSS1_CLKCTRL, CM_PER_EPWMSS2_CLKCTRL, + * CM_PER_GPIO1_CLKCTRL, CM_PER_GPIO2_CLKCTRL, CM_PER_GPIO3_CLKCTRL, + * CM_PER_GPIO4_CLKCTRL, CM_PER_GPIO5_CLKCTRL, CM_PER_GPIO6_CLKCTRL, + * CM_PER_GPMC_CLKCTRL, CM_PER_I2C1_CLKCTRL, CM_PER_I2C2_CLKCTRL, + * CM_PER_PRUSS_CLKCTRL, CM_PER_IEEE5000_CLKCTRL, CM_PER_L3_CLKCTRL, + * CM_PER_L3_INSTR_CLKCTRL, CM_PER_L4FW_CLKCTRL, CM_PER_L4HS_CLKCTRL, + * CM_PER_L4LS_CLKCTRL, CM_PER_LCDC_CLKCTRL, CM_PER_MAILBOX0_CLKCTRL, + * CM_PER_MAILBOX1_CLKCTRL, CM_PER_MCASP0_CLKCTRL, CM_PER_MCASP1_CLKCTRL, + * CM_PER_MCASP2_CLKCTRL, CM_PER_MLB_CLKCTRL, CM_PER_MMC0_CLKCTRL, + * CM_PER_MMC1_CLKCTRL, CM_PER_MMC2_CLKCTRL, CM_PER_MSTR_EXPS_CLKCTRL, + * CM_PER_OCMCRAM_CLKCTRL, CM_PER_OCPWP_CLKCTRL, CM_PER_PCIE_CLKCTRL, + * CM_PER_PKA_CLKCTRL, CM_PER_RNG_CLKCTRL, CM_PER_SHA0_CLKCTRL, + * CM_PER_SLV_EXPS_CLKCTRL, CM_PER_SPARE0_CLKCTRL, CM_PER_SPARE1_CLKCTRL, + * CM_PER_SPARE_CLKCTRL, CM_PER_SPI0_CLKCTRL, CM_PER_SPI1_CLKCTRL, + * CM_PER_SPI2_CLKCTRL, CM_PER_SPI3_CLKCTRL, CM_PER_SPINLOCK_CLKCTRL, + * CM_PER_TIMER2_CLKCTRL, CM_PER_TIMER3_CLKCTRL, CM_PER_TIMER4_CLKCTRL, + * CM_PER_TIMER5_CLKCTRL, CM_PER_TIMER6_CLKCTRL, CM_PER_TIMER7_CLKCTRL, + * CM_PER_TPCC_CLKCTRL, CM_PER_TPTC0_CLKCTRL, CM_PER_TPTC1_CLKCTRL, + * CM_PER_TPTC2_CLKCTRL, CM_PER_UART1_CLKCTRL, CM_PER_UART2_CLKCTRL, + * CM_PER_UART3_CLKCTRL, CM_PER_UART4_CLKCTRL, CM_PER_UART5_CLKCTRL, + * CM_PER_USB0_CLKCTRL, CM_WKUP_ADC_TSC_CLKCTRL, CM_WKUP_CONTROL_CLKCTRL, + * CM_WKUP_DEBUGSS_CLKCTRL, CM_WKUP_GPIO0_CLKCTRL, CM_WKUP_I2C0_CLKCTRL, + * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_SMARTREFLEX0_CLKCTRL, + * CM_WKUP_SMARTREFLEX1_CLKCTRL, CM_WKUP_TIMER0_CLKCTRL, + * CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_UART0_CLKCTRL, CM_WKUP_WDT0_CLKCTRL, + * CM_WKUP_WDT1_CLKCTRL, CM_WKUP_WKUP_M3_CLKCTRL, CM_GFX_BITBLT_CLKCTRL, + * CM_GFX_GFX_CLKCTRL, CM_GFX_MMUCFG_CLKCTRL, CM_GFX_MMUDATA_CLKCTRL, + * CM_CEFUSE_CEFUSE_CLKCTRL + */ +#define AM33XX_MODULEMODE_SHIFT 0 +#define AM33XX_MODULEMODE_MASK (0x3 << 0) + +/* Used by CM_WKUP_DEBUGSS_CLKCTRL */ +#define AM33XX_OPTCLK_DEBUG_CLKA_SHIFT 30 +#define AM33XX_OPTCLK_DEBUG_CLKA_MASK (1 << 30) + +/* Used by CM_WKUP_DEBUGSS_CLKCTRL */ +#define AM33XX_OPTFCLKEN_DBGSYSCLK_SHIFT 19 +#define AM33XX_OPTFCLKEN_DBGSYSCLK_MASK (1 << 19) + +/* Used by CM_WKUP_GPIO0_CLKCTRL */ +#define AM33XX_OPTFCLKEN_GPIO0_GDBCLK_SHIFT 18 +#define AM33XX_OPTFCLKEN_GPIO0_GDBCLK_MASK (1 << 18) + +/* Used by CM_PER_GPIO1_CLKCTRL */ +#define AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_SHIFT 18 +#define AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_MASK (1 << 18) + +/* Used by CM_PER_GPIO2_CLKCTRL */ +#define AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_SHIFT 18 +#define AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_MASK (1 << 18) + +/* Used by CM_PER_GPIO3_CLKCTRL */ +#define AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_SHIFT 18 +#define AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_MASK (1 << 18) + +/* Used by CM_PER_GPIO4_CLKCTRL */ +#define AM33XX_OPTFCLKEN_GPIO_4_GDBCLK_SHIFT 18 +#define AM33XX_OPTFCLKEN_GPIO_4_GDBCLK_MASK (1 << 18) + +/* Used by CM_PER_GPIO5_CLKCTRL */ +#define AM33XX_OPTFCLKEN_GPIO_5_GDBCLK_SHIFT 18 +#define AM33XX_OPTFCLKEN_GPIO_5_GDBCLK_MASK (1 << 18) + +/* Used by CM_PER_GPIO6_CLKCTRL */ +#define AM33XX_OPTFCLKEN_GPIO_6_GDBCLK_SHIFT 18 +#define AM33XX_OPTFCLKEN_GPIO_6_GDBCLK_MASK (1 << 18) + +/* + * Used by CM_MPU_MPU_CLKCTRL, CM_PER_CPGMAC0_CLKCTRL, CM_PER_PRUSS_CLKCTRL, + * CM_PER_IEEE5000_CLKCTRL, CM_PER_LCDC_CLKCTRL, CM_PER_MLB_CLKCTRL, + * CM_PER_MSTR_EXPS_CLKCTRL, CM_PER_OCPWP_CLKCTRL, CM_PER_PCIE_CLKCTRL, + * CM_PER_SPARE_CLKCTRL, CM_PER_TPTC0_CLKCTRL, CM_PER_TPTC1_CLKCTRL, + * CM_PER_TPTC2_CLKCTRL, CM_PER_USB0_CLKCTRL, CM_WKUP_DEBUGSS_CLKCTRL, + * CM_WKUP_WKUP_M3_CLKCTRL, CM_GFX_BITBLT_CLKCTRL, CM_GFX_GFX_CLKCTRL + */ +#define AM33XX_STBYST_SHIFT 18 +#define AM33XX_STBYST_MASK (1 << 18) + +/* Used by CM_WKUP_DEBUGSS_CLKCTRL */ +#define AM33XX_STM_PMD_CLKDIVSEL_SHIFT 27 +#define AM33XX_STM_PMD_CLKDIVSEL_MASK (0x29 << 27) + +/* Used by CM_WKUP_DEBUGSS_CLKCTRL */ +#define AM33XX_STM_PMD_CLKSEL_SHIFT 22 +#define AM33XX_STM_PMD_CLKSEL_MASK (0x23 << 22) + +/* + * Used by CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDR, CM_IDLEST_DPLL_DISP, + * CM_IDLEST_DPLL_MPU, CM_IDLEST_DPLL_PER + */ +#define AM33XX_ST_DPLL_CLK_SHIFT 0 +#define AM33XX_ST_DPLL_CLK_MASK (1 << 0) + +/* Used by CM_CLKDCOLDO_DPLL_PER */ +#define AM33XX_ST_DPLL_CLKDCOLDO_SHIFT 8 +#define AM33XX_ST_DPLL_CLKDCOLDO_MASK (1 << 8) + +/* + * Used by CM_DIV_M2_DPLL_DDR, CM_DIV_M2_DPLL_DISP, CM_DIV_M2_DPLL_MPU, + * CM_DIV_M2_DPLL_PER + */ +#define AM33XX_ST_DPLL_CLKOUT_SHIFT 9 +#define AM33XX_ST_DPLL_CLKOUT_MASK (1 << 9) + +/* Used by CM_DIV_M4_DPLL_CORE */ +#define AM33XX_ST_HSDIVIDER_CLKOUT1_SHIFT 9 +#define AM33XX_ST_HSDIVIDER_CLKOUT1_MASK (1 << 9) + +/* Used by CM_DIV_M5_DPLL_CORE */ +#define AM33XX_ST_HSDIVIDER_CLKOUT2_SHIFT 9 +#define AM33XX_ST_HSDIVIDER_CLKOUT2_MASK (1 << 9) + +/* Used by CM_DIV_M6_DPLL_CORE */ +#define AM33XX_ST_HSDIVIDER_CLKOUT3_SHIFT 9 +#define AM33XX_ST_HSDIVIDER_CLKOUT3_MASK (1 << 9) + +/* + * Used by CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDR, CM_IDLEST_DPLL_DISP, + * CM_IDLEST_DPLL_MPU, CM_IDLEST_DPLL_PER + */ +#define AM33XX_ST_MN_BYPASS_SHIFT 8 +#define AM33XX_ST_MN_BYPASS_MASK (1 << 8) + +/* Used by CM_WKUP_DEBUGSS_CLKCTRL */ +#define AM33XX_TRC_PMD_CLKDIVSEL_SHIFT 24 +#define AM33XX_TRC_PMD_CLKDIVSEL_MASK (0x26 << 24) + +/* Used by CM_WKUP_DEBUGSS_CLKCTRL */ +#define AM33XX_TRC_PMD_CLKSEL_SHIFT 20 +#define AM33XX_TRC_PMD_CLKSEL_MASK (0x21 << 20) + +/* Used by CONTROL_SEC_CLK_CTRL */ +#define AM33XX_TIMER0_CLKSEL_MASK (0x3 << 4) +#endif diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c new file mode 100644 index 000000000000..13f56eafef03 --- /dev/null +++ b/arch/arm/mach-omap2/cm33xx.c @@ -0,0 +1,313 @@ +/* + * AM33XX CM functions + * + * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ + * Vaibhav Hiremath + * + * Reference taken from from OMAP4 cminst44xx.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include + +#include "cm.h" +#include "cm33xx.h" +#include "cm-regbits-34xx.h" +#include "cm-regbits-33xx.h" +#include "prm33xx.h" + +/* + * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield: + * + * 0x0 func: Module is fully functional, including OCP + * 0x1 trans: Module is performing transition: wakeup, or sleep, or sleep + * abortion + * 0x2 idle: Module is in Idle mode (only OCP part). It is functional if + * using separate functional clock + * 0x3 disabled: Module is disabled and cannot be accessed + * + */ +#define CLKCTRL_IDLEST_FUNCTIONAL 0x0 +#define CLKCTRL_IDLEST_INTRANSITION 0x1 +#define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2 +#define CLKCTRL_IDLEST_DISABLED 0x3 + +/* Private functions */ + +/* Read a register in a CM instance */ +static inline u32 am33xx_cm_read_reg(s16 inst, u16 idx) +{ + return __raw_readl(cm_base + inst + idx); +} + +/* Write into a register in a CM */ +static inline void am33xx_cm_write_reg(u32 val, s16 inst, u16 idx) +{ + __raw_writel(val, cm_base + inst + idx); +} + +/* Read-modify-write a register in CM */ +static inline u32 am33xx_cm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx) +{ + u32 v; + + v = am33xx_cm_read_reg(inst, idx); + v &= ~mask; + v |= bits; + am33xx_cm_write_reg(v, inst, idx); + + return v; +} + +static inline u32 am33xx_cm_set_reg_bits(u32 bits, s16 inst, s16 idx) +{ + return am33xx_cm_rmw_reg_bits(bits, bits, inst, idx); +} + +static inline u32 am33xx_cm_clear_reg_bits(u32 bits, s16 inst, s16 idx) +{ + return am33xx_cm_rmw_reg_bits(bits, 0x0, inst, idx); +} + +static inline u32 am33xx_cm_read_reg_bits(u16 inst, s16 idx, u32 mask) +{ + u32 v; + + v = am33xx_cm_read_reg(inst, idx); + v &= mask; + v >>= __ffs(mask); + + return v; +} + +/** + * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield + * @inst: CM instance register offset (*_INST macro) + * @cdoffs: Clockdomain register offset (*_CDOFFS macro) + * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) + * + * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to + * bit 0. + */ +static u32 _clkctrl_idlest(u16 inst, s16 cdoffs, u16 clkctrl_offs) +{ + u32 v = am33xx_cm_read_reg(inst, clkctrl_offs); + v &= AM33XX_IDLEST_MASK; + v >>= AM33XX_IDLEST_SHIFT; + return v; +} + +/** + * _is_module_ready - can module registers be accessed without causing an abort? + * @inst: CM instance register offset (*_INST macro) + * @cdoffs: Clockdomain register offset (*_CDOFFS macro) + * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) + * + * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either + * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise. + */ +static bool _is_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs) +{ + u32 v; + + v = _clkctrl_idlest(inst, cdoffs, clkctrl_offs); + + return (v == CLKCTRL_IDLEST_FUNCTIONAL || + v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false; +} + +/** + * _clktrctrl_write - write @c to a CM_CLKSTCTRL.CLKTRCTRL register bitfield + * @c: CLKTRCTRL register bitfield (LSB = bit 0, i.e., unshifted) + * @inst: CM instance register offset (*_INST macro) + * @cdoffs: Clockdomain register offset (*_CDOFFS macro) + * + * @c must be the unshifted value for CLKTRCTRL - i.e., this function + * will handle the shift itself. + */ +static void _clktrctrl_write(u8 c, s16 inst, u16 cdoffs) +{ + u32 v; + + v = am33xx_cm_read_reg(inst, cdoffs); + v &= ~AM33XX_CLKTRCTRL_MASK; + v |= c << AM33XX_CLKTRCTRL_SHIFT; + am33xx_cm_write_reg(v, inst, cdoffs); +} + +/* Public functions */ + +/** + * am33xx_cm_is_clkdm_in_hwsup - is a clockdomain in hwsup idle mode? + * @inst: CM instance register offset (*_INST macro) + * @cdoffs: Clockdomain register offset (*_CDOFFS macro) + * + * Returns true if the clockdomain referred to by (@inst, @cdoffs) + * is in hardware-supervised idle mode, or 0 otherwise. + */ +bool am33xx_cm_is_clkdm_in_hwsup(s16 inst, u16 cdoffs) +{ + u32 v; + + v = am33xx_cm_read_reg(inst, cdoffs); + v &= AM33XX_CLKTRCTRL_MASK; + v >>= AM33XX_CLKTRCTRL_SHIFT; + + return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? true : false; +} + +/** + * am33xx_cm_clkdm_enable_hwsup - put a clockdomain in hwsup-idle mode + * @inst: CM instance register offset (*_INST macro) + * @cdoffs: Clockdomain register offset (*_CDOFFS macro) + * + * Put a clockdomain referred to by (@inst, @cdoffs) into + * hardware-supervised idle mode. No return value. + */ +void am33xx_cm_clkdm_enable_hwsup(s16 inst, u16 cdoffs) +{ + _clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, inst, cdoffs); +} + +/** + * am33xx_cm_clkdm_disable_hwsup - put a clockdomain in swsup-idle mode + * @inst: CM instance register offset (*_INST macro) + * @cdoffs: Clockdomain register offset (*_CDOFFS macro) + * + * Put a clockdomain referred to by (@inst, @cdoffs) into + * software-supervised idle mode, i.e., controlled manually by the + * Linux OMAP clockdomain code. No return value. + */ +void am33xx_cm_clkdm_disable_hwsup(s16 inst, u16 cdoffs) +{ + _clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, inst, cdoffs); +} + +/** + * am33xx_cm_clkdm_force_sleep - try to put a clockdomain into idle + * @inst: CM instance register offset (*_INST macro) + * @cdoffs: Clockdomain register offset (*_CDOFFS macro) + * + * Put a clockdomain referred to by (@inst, @cdoffs) into idle + * No return value. + */ +void am33xx_cm_clkdm_force_sleep(s16 inst, u16 cdoffs) +{ + _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, inst, cdoffs); +} + +/** + * am33xx_cm_clkdm_force_wakeup - try to take a clockdomain out of idle + * @inst: CM instance register offset (*_INST macro) + * @cdoffs: Clockdomain register offset (*_CDOFFS macro) + * + * Take a clockdomain referred to by (@inst, @cdoffs) out of idle, + * waking it up. No return value. + */ +void am33xx_cm_clkdm_force_wakeup(s16 inst, u16 cdoffs) +{ + _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, inst, cdoffs); +} + +/* + * + */ + +/** + * am33xx_cm_wait_module_ready - wait for a module to be in 'func' state + * @inst: CM instance register offset (*_INST macro) + * @cdoffs: Clockdomain register offset (*_CDOFFS macro) + * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) + * + * Wait for the module IDLEST to be functional. If the idle state is in any + * the non functional state (trans, idle or disabled), module and thus the + * sysconfig cannot be accessed and will probably lead to an "imprecise + * external abort" + */ +int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs) +{ + int i = 0; + + if (!clkctrl_offs) + return 0; + + omap_test_timeout(_is_module_ready(inst, cdoffs, clkctrl_offs), + MAX_MODULE_READY_TIME, i); + + return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; +} + +/** + * am33xx_cm_wait_module_idle - wait for a module to be in 'disabled' + * state + * @inst: CM instance register offset (*_INST macro) + * @cdoffs: Clockdomain register offset (*_CDOFFS macro) + * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) + * + * Wait for the module IDLEST to be disabled. Some PRCM transition, + * like reset assertion or parent clock de-activation must wait the + * module to be fully disabled. + */ +int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs, u16 clkctrl_offs) +{ + int i = 0; + + if (!clkctrl_offs) + return 0; + + omap_test_timeout((_clkctrl_idlest(inst, cdoffs, clkctrl_offs) == + CLKCTRL_IDLEST_DISABLED), + MAX_MODULE_READY_TIME, i); + + return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; +} + +/** + * am33xx_cm_module_enable - Enable the modulemode inside CLKCTRL + * @mode: Module mode (SW or HW) + * @inst: CM instance register offset (*_INST macro) + * @cdoffs: Clockdomain register offset (*_CDOFFS macro) + * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) + * + * No return value. + */ +void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs, u16 clkctrl_offs) +{ + u32 v; + + v = am33xx_cm_read_reg(inst, clkctrl_offs); + v &= ~AM33XX_MODULEMODE_MASK; + v |= mode << AM33XX_MODULEMODE_SHIFT; + am33xx_cm_write_reg(v, inst, clkctrl_offs); +} + +/** + * am33xx_cm_module_disable - Disable the module inside CLKCTRL + * @inst: CM instance register offset (*_INST macro) + * @cdoffs: Clockdomain register offset (*_CDOFFS macro) + * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) + * + * No return value. + */ +void am33xx_cm_module_disable(u16 inst, s16 cdoffs, u16 clkctrl_offs) +{ + u32 v; + + v = am33xx_cm_read_reg(inst, clkctrl_offs); + v &= ~AM33XX_MODULEMODE_MASK; + am33xx_cm_write_reg(v, inst, clkctrl_offs); +} diff --git a/arch/arm/mach-omap2/cm33xx.h b/arch/arm/mach-omap2/cm33xx.h new file mode 100644 index 000000000000..5fa0b62e1a79 --- /dev/null +++ b/arch/arm/mach-omap2/cm33xx.h @@ -0,0 +1,420 @@ +/* + * AM33XX CM offset macros + * + * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ + * Vaibhav Hiremath + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_CM_33XX_H +#define __ARCH_ARM_MACH_OMAP2_CM_33XX_H + +#include +#include +#include +#include + +#include "common.h" + +#include "cm.h" +#include "cm-regbits-33xx.h" +#include "cm33xx.h" + +/* CM base address */ +#define AM33XX_CM_BASE 0x44e00000 + +#define AM33XX_CM_REGADDR(inst, reg) \ + AM33XX_L4_WK_IO_ADDRESS(AM33XX_CM_BASE + (inst) + (reg)) + +/* CM instances */ +#define AM33XX_CM_PER_MOD 0x0000 +#define AM33XX_CM_WKUP_MOD 0x0400 +#define AM33XX_CM_DPLL_MOD 0x0500 +#define AM33XX_CM_MPU_MOD 0x0600 +#define AM33XX_CM_DEVICE_MOD 0x0700 +#define AM33XX_CM_RTC_MOD 0x0800 +#define AM33XX_CM_GFX_MOD 0x0900 +#define AM33XX_CM_CEFUSE_MOD 0x0A00 + +/* CM */ + +/* CM.PER_CM register offsets */ +#define AM33XX_CM_PER_L4LS_CLKSTCTRL_OFFSET 0x0000 +#define AM33XX_CM_PER_L4LS_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0000) +#define AM33XX_CM_PER_L3S_CLKSTCTRL_OFFSET 0x0004 +#define AM33XX_CM_PER_L3S_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0004) +#define AM33XX_CM_PER_L4FW_CLKSTCTRL_OFFSET 0x0008 +#define AM33XX_CM_PER_L4FW_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0008) +#define AM33XX_CM_PER_L3_CLKSTCTRL_OFFSET 0x000c +#define AM33XX_CM_PER_L3_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x000c) +#define AM33XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET 0x0014 +#define AM33XX_CM_PER_CPGMAC0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0014) +#define AM33XX_CM_PER_LCDC_CLKCTRL_OFFSET 0x0018 +#define AM33XX_CM_PER_LCDC_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0018) +#define AM33XX_CM_PER_USB0_CLKCTRL_OFFSET 0x001c +#define AM33XX_CM_PER_USB0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x001c) +#define AM33XX_CM_PER_MLB_CLKCTRL_OFFSET 0x0020 +#define AM33XX_CM_PER_MLB_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0020) +#define AM33XX_CM_PER_TPTC0_CLKCTRL_OFFSET 0x0024 +#define AM33XX_CM_PER_TPTC0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0024) +#define AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET 0x0028 +#define AM33XX_CM_PER_EMIF_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0028) +#define AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET 0x002c +#define AM33XX_CM_PER_OCMCRAM_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x002c) +#define AM33XX_CM_PER_GPMC_CLKCTRL_OFFSET 0x0030 +#define AM33XX_CM_PER_GPMC_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0030) +#define AM33XX_CM_PER_MCASP0_CLKCTRL_OFFSET 0x0034 +#define AM33XX_CM_PER_MCASP0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0034) +#define AM33XX_CM_PER_UART5_CLKCTRL_OFFSET 0x0038 +#define AM33XX_CM_PER_UART5_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0038) +#define AM33XX_CM_PER_MMC0_CLKCTRL_OFFSET 0x003c +#define AM33XX_CM_PER_MMC0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x003c) +#define AM33XX_CM_PER_ELM_CLKCTRL_OFFSET 0x0040 +#define AM33XX_CM_PER_ELM_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0040) +#define AM33XX_CM_PER_I2C2_CLKCTRL_OFFSET 0x0044 +#define AM33XX_CM_PER_I2C2_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0044) +#define AM33XX_CM_PER_I2C1_CLKCTRL_OFFSET 0x0048 +#define AM33XX_CM_PER_I2C1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0048) +#define AM33XX_CM_PER_SPI0_CLKCTRL_OFFSET 0x004c +#define AM33XX_CM_PER_SPI0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x004c) +#define AM33XX_CM_PER_SPI1_CLKCTRL_OFFSET 0x0050 +#define AM33XX_CM_PER_SPI1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0050) +#define AM33XX_CM_PER_SPI2_CLKCTRL_OFFSET 0x0054 +#define AM33XX_CM_PER_SPI2_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0054) +#define AM33XX_CM_PER_SPI3_CLKCTRL_OFFSET 0x0058 +#define AM33XX_CM_PER_SPI3_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0058) +#define AM33XX_CM_PER_L4LS_CLKCTRL_OFFSET 0x0060 +#define AM33XX_CM_PER_L4LS_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0060) +#define AM33XX_CM_PER_L4FW_CLKCTRL_OFFSET 0x0064 +#define AM33XX_CM_PER_L4FW_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0064) +#define AM33XX_CM_PER_MCASP1_CLKCTRL_OFFSET 0x0068 +#define AM33XX_CM_PER_MCASP1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0068) +#define AM33XX_CM_PER_UART1_CLKCTRL_OFFSET 0x006c +#define AM33XX_CM_PER_UART1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x006c) +#define AM33XX_CM_PER_UART2_CLKCTRL_OFFSET 0x0070 +#define AM33XX_CM_PER_UART2_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0070) +#define AM33XX_CM_PER_UART3_CLKCTRL_OFFSET 0x0074 +#define AM33XX_CM_PER_UART3_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0074) +#define AM33XX_CM_PER_UART4_CLKCTRL_OFFSET 0x0078 +#define AM33XX_CM_PER_UART4_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0078) +#define AM33XX_CM_PER_TIMER7_CLKCTRL_OFFSET 0x007c +#define AM33XX_CM_PER_TIMER7_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x007c) +#define AM33XX_CM_PER_TIMER2_CLKCTRL_OFFSET 0x0080 +#define AM33XX_CM_PER_TIMER2_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0080) +#define AM33XX_CM_PER_TIMER3_CLKCTRL_OFFSET 0x0084 +#define AM33XX_CM_PER_TIMER3_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0084) +#define AM33XX_CM_PER_TIMER4_CLKCTRL_OFFSET 0x0088 +#define AM33XX_CM_PER_TIMER4_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0088) +#define AM33XX_CM_PER_MCASP2_CLKCTRL_OFFSET 0x008c +#define AM33XX_CM_PER_MCASP2_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x008c) +#define AM33XX_CM_PER_RNG_CLKCTRL_OFFSET 0x0090 +#define AM33XX_CM_PER_RNG_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0090) +#define AM33XX_CM_PER_AES0_CLKCTRL_OFFSET 0x0094 +#define AM33XX_CM_PER_AES0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0094) +#define AM33XX_CM_PER_AES1_CLKCTRL_OFFSET 0x0098 +#define AM33XX_CM_PER_AES1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0098) +#define AM33XX_CM_PER_DES_CLKCTRL_OFFSET 0x009c +#define AM33XX_CM_PER_DES_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x009c) +#define AM33XX_CM_PER_SHA0_CLKCTRL_OFFSET 0x00a0 +#define AM33XX_CM_PER_SHA0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00a0) +#define AM33XX_CM_PER_PKA_CLKCTRL_OFFSET 0x00a4 +#define AM33XX_CM_PER_PKA_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00a4) +#define AM33XX_CM_PER_GPIO6_CLKCTRL_OFFSET 0x00a8 +#define AM33XX_CM_PER_GPIO6_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00a8) +#define AM33XX_CM_PER_GPIO1_CLKCTRL_OFFSET 0x00ac +#define AM33XX_CM_PER_GPIO1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00ac) +#define AM33XX_CM_PER_GPIO2_CLKCTRL_OFFSET 0x00b0 +#define AM33XX_CM_PER_GPIO2_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00b0) +#define AM33XX_CM_PER_GPIO3_CLKCTRL_OFFSET 0x00b4 +#define AM33XX_CM_PER_GPIO3_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00b4) +#define AM33XX_CM_PER_GPIO4_CLKCTRL_OFFSET 0x00b8 +#define AM33XX_CM_PER_GPIO4_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00b8) +#define AM33XX_CM_PER_TPCC_CLKCTRL_OFFSET 0x00bc +#define AM33XX_CM_PER_TPCC_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00bc) +#define AM33XX_CM_PER_DCAN0_CLKCTRL_OFFSET 0x00c0 +#define AM33XX_CM_PER_DCAN0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00c0) +#define AM33XX_CM_PER_DCAN1_CLKCTRL_OFFSET 0x00c4 +#define AM33XX_CM_PER_DCAN1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00c4) +#define AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET 0x00cc +#define AM33XX_CM_PER_EPWMSS1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00cc) +#define AM33XX_CM_PER_EMIF_FW_CLKCTRL_OFFSET 0x00d0 +#define AM33XX_CM_PER_EMIF_FW_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00d0) +#define AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET 0x00d4 +#define AM33XX_CM_PER_EPWMSS0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00d4) +#define AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET 0x00d8 +#define AM33XX_CM_PER_EPWMSS2_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00d8) +#define AM33XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET 0x00dc +#define AM33XX_CM_PER_L3_INSTR_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00dc) +#define AM33XX_CM_PER_L3_CLKCTRL_OFFSET 0x00e0 +#define AM33XX_CM_PER_L3_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00e0) +#define AM33XX_CM_PER_IEEE5000_CLKCTRL_OFFSET 0x00e4 +#define AM33XX_CM_PER_IEEE5000_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00e4) +#define AM33XX_CM_PER_PRUSS_CLKCTRL_OFFSET 0x00e8 +#define AM33XX_CM_PER_PRUSS_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00e8) +#define AM33XX_CM_PER_TIMER5_CLKCTRL_OFFSET 0x00ec +#define AM33XX_CM_PER_TIMER5_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00ec) +#define AM33XX_CM_PER_TIMER6_CLKCTRL_OFFSET 0x00f0 +#define AM33XX_CM_PER_TIMER6_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00f0) +#define AM33XX_CM_PER_MMC1_CLKCTRL_OFFSET 0x00f4 +#define AM33XX_CM_PER_MMC1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00f4) +#define AM33XX_CM_PER_MMC2_CLKCTRL_OFFSET 0x00f8 +#define AM33XX_CM_PER_MMC2_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00f8) +#define AM33XX_CM_PER_TPTC1_CLKCTRL_OFFSET 0x00fc +#define AM33XX_CM_PER_TPTC1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00fc) +#define AM33XX_CM_PER_TPTC2_CLKCTRL_OFFSET 0x0100 +#define AM33XX_CM_PER_TPTC2_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0100) +#define AM33XX_CM_PER_GPIO5_CLKCTRL_OFFSET 0x0104 +#define AM33XX_CM_PER_GPIO5_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0104) +#define AM33XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET 0x010c +#define AM33XX_CM_PER_SPINLOCK_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x010c) +#define AM33XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET 0x0110 +#define AM33XX_CM_PER_MAILBOX0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0110) +#define AM33XX_CM_PER_L4HS_CLKSTCTRL_OFFSET 0x011c +#define AM33XX_CM_PER_L4HS_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x011c) +#define AM33XX_CM_PER_L4HS_CLKCTRL_OFFSET 0x0120 +#define AM33XX_CM_PER_L4HS_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0120) +#define AM33XX_CM_PER_MSTR_EXPS_CLKCTRL_OFFSET 0x0124 +#define AM33XX_CM_PER_MSTR_EXPS_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0124) +#define AM33XX_CM_PER_SLV_EXPS_CLKCTRL_OFFSET 0x0128 +#define AM33XX_CM_PER_SLV_EXPS_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0128) +#define AM33XX_CM_PER_OCPWP_L3_CLKSTCTRL_OFFSET 0x012c +#define AM33XX_CM_PER_OCPWP_L3_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x012c) +#define AM33XX_CM_PER_OCPWP_CLKCTRL_OFFSET 0x0130 +#define AM33XX_CM_PER_OCPWP_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0130) +#define AM33XX_CM_PER_MAILBOX1_CLKCTRL_OFFSET 0x0134 +#define AM33XX_CM_PER_MAILBOX1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0134) +#define AM33XX_CM_PER_PRUSS_CLKSTCTRL_OFFSET 0x0140 +#define AM33XX_CM_PER_PRUSS_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0140) +#define AM33XX_CM_PER_CPSW_CLKSTCTRL_OFFSET 0x0144 +#define AM33XX_CM_PER_CPSW_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0144) +#define AM33XX_CM_PER_LCDC_CLKSTCTRL_OFFSET 0x0148 +#define AM33XX_CM_PER_LCDC_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0148) +#define AM33XX_CM_PER_CLKDIV32K_CLKCTRL_OFFSET 0x014c +#define AM33XX_CM_PER_CLKDIV32K_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x014c) +#define AM33XX_CM_PER_CLK_24MHZ_CLKSTCTRL_OFFSET 0x0150 +#define AM33XX_CM_PER_CLK_24MHZ_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0150) + +/* CM.WKUP_CM register offsets */ +#define AM33XX_CM_WKUP_CLKSTCTRL_OFFSET 0x0000 +#define AM33XX_CM_WKUP_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0000) +#define AM33XX_CM_WKUP_CONTROL_CLKCTRL_OFFSET 0x0004 +#define AM33XX_CM_WKUP_CONTROL_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0004) +#define AM33XX_CM_WKUP_GPIO0_CLKCTRL_OFFSET 0x0008 +#define AM33XX_CM_WKUP_GPIO0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0008) +#define AM33XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET 0x000c +#define AM33XX_CM_WKUP_L4WKUP_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x000c) +#define AM33XX_CM_WKUP_TIMER0_CLKCTRL_OFFSET 0x0010 +#define AM33XX_CM_WKUP_TIMER0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0010) +#define AM33XX_CM_WKUP_DEBUGSS_CLKCTRL_OFFSET 0x0014 +#define AM33XX_CM_WKUP_DEBUGSS_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0014) +#define AM33XX_CM_L3_AON_CLKSTCTRL_OFFSET 0x0018 +#define AM33XX_CM_L3_AON_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0018) +#define AM33XX_CM_AUTOIDLE_DPLL_MPU_OFFSET 0x001c +#define AM33XX_CM_AUTOIDLE_DPLL_MPU AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x001c) +#define AM33XX_CM_IDLEST_DPLL_MPU_OFFSET 0x0020 +#define AM33XX_CM_IDLEST_DPLL_MPU AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0020) +#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_MPU_OFFSET 0x0024 +#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_MPU AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0024) +#define AM33XX_CM_SSC_MODFREQDIV_DPLL_MPU_OFFSET 0x0028 +#define AM33XX_CM_SSC_MODFREQDIV_DPLL_MPU AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0028) +#define AM33XX_CM_CLKSEL_DPLL_MPU_OFFSET 0x002c +#define AM33XX_CM_CLKSEL_DPLL_MPU AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x002c) +#define AM33XX_CM_AUTOIDLE_DPLL_DDR_OFFSET 0x0030 +#define AM33XX_CM_AUTOIDLE_DPLL_DDR AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0030) +#define AM33XX_CM_IDLEST_DPLL_DDR_OFFSET 0x0034 +#define AM33XX_CM_IDLEST_DPLL_DDR AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0034) +#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_DDR_OFFSET 0x0038 +#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_DDR AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0038) +#define AM33XX_CM_SSC_MODFREQDIV_DPLL_DDR_OFFSET 0x003c +#define AM33XX_CM_SSC_MODFREQDIV_DPLL_DDR AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x003c) +#define AM33XX_CM_CLKSEL_DPLL_DDR_OFFSET 0x0040 +#define AM33XX_CM_CLKSEL_DPLL_DDR AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0040) +#define AM33XX_CM_AUTOIDLE_DPLL_DISP_OFFSET 0x0044 +#define AM33XX_CM_AUTOIDLE_DPLL_DISP AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0044) +#define AM33XX_CM_IDLEST_DPLL_DISP_OFFSET 0x0048 +#define AM33XX_CM_IDLEST_DPLL_DISP AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0048) +#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_DISP_OFFSET 0x004c +#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_DISP AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x004c) +#define AM33XX_CM_SSC_MODFREQDIV_DPLL_DISP_OFFSET 0x0050 +#define AM33XX_CM_SSC_MODFREQDIV_DPLL_DISP AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0050) +#define AM33XX_CM_CLKSEL_DPLL_DISP_OFFSET 0x0054 +#define AM33XX_CM_CLKSEL_DPLL_DISP AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0054) +#define AM33XX_CM_AUTOIDLE_DPLL_CORE_OFFSET 0x0058 +#define AM33XX_CM_AUTOIDLE_DPLL_CORE AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0058) +#define AM33XX_CM_IDLEST_DPLL_CORE_OFFSET 0x005c +#define AM33XX_CM_IDLEST_DPLL_CORE AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x005c) +#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_CORE_OFFSET 0x0060 +#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_CORE AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0060) +#define AM33XX_CM_SSC_MODFREQDIV_DPLL_CORE_OFFSET 0x0064 +#define AM33XX_CM_SSC_MODFREQDIV_DPLL_CORE AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0064) +#define AM33XX_CM_CLKSEL_DPLL_CORE_OFFSET 0x0068 +#define AM33XX_CM_CLKSEL_DPLL_CORE AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0068) +#define AM33XX_CM_AUTOIDLE_DPLL_PER_OFFSET 0x006c +#define AM33XX_CM_AUTOIDLE_DPLL_PER AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x006c) +#define AM33XX_CM_IDLEST_DPLL_PER_OFFSET 0x0070 +#define AM33XX_CM_IDLEST_DPLL_PER AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0070) +#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_PER_OFFSET 0x0074 +#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_PER AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0074) +#define AM33XX_CM_SSC_MODFREQDIV_DPLL_PER_OFFSET 0x0078 +#define AM33XX_CM_SSC_MODFREQDIV_DPLL_PER AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0078) +#define AM33XX_CM_CLKDCOLDO_DPLL_PER_OFFSET 0x007c +#define AM33XX_CM_CLKDCOLDO_DPLL_PER AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x007c) +#define AM33XX_CM_DIV_M4_DPLL_CORE_OFFSET 0x0080 +#define AM33XX_CM_DIV_M4_DPLL_CORE AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0080) +#define AM33XX_CM_DIV_M5_DPLL_CORE_OFFSET 0x0084 +#define AM33XX_CM_DIV_M5_DPLL_CORE AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0084) +#define AM33XX_CM_CLKMODE_DPLL_MPU_OFFSET 0x0088 +#define AM33XX_CM_CLKMODE_DPLL_MPU AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0088) +#define AM33XX_CM_CLKMODE_DPLL_PER_OFFSET 0x008c +#define AM33XX_CM_CLKMODE_DPLL_PER AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x008c) +#define AM33XX_CM_CLKMODE_DPLL_CORE_OFFSET 0x0090 +#define AM33XX_CM_CLKMODE_DPLL_CORE AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0090) +#define AM33XX_CM_CLKMODE_DPLL_DDR_OFFSET 0x0094 +#define AM33XX_CM_CLKMODE_DPLL_DDR AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0094) +#define AM33XX_CM_CLKMODE_DPLL_DISP_OFFSET 0x0098 +#define AM33XX_CM_CLKMODE_DPLL_DISP AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0098) +#define AM33XX_CM_CLKSEL_DPLL_PERIPH_OFFSET 0x009c +#define AM33XX_CM_CLKSEL_DPLL_PERIPH AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x009c) +#define AM33XX_CM_DIV_M2_DPLL_DDR_OFFSET 0x00a0 +#define AM33XX_CM_DIV_M2_DPLL_DDR AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00a0) +#define AM33XX_CM_DIV_M2_DPLL_DISP_OFFSET 0x00a4 +#define AM33XX_CM_DIV_M2_DPLL_DISP AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00a4) +#define AM33XX_CM_DIV_M2_DPLL_MPU_OFFSET 0x00a8 +#define AM33XX_CM_DIV_M2_DPLL_MPU AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00a8) +#define AM33XX_CM_DIV_M2_DPLL_PER_OFFSET 0x00ac +#define AM33XX_CM_DIV_M2_DPLL_PER AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00ac) +#define AM33XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET 0x00b0 +#define AM33XX_CM_WKUP_WKUP_M3_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00b0) +#define AM33XX_CM_WKUP_UART0_CLKCTRL_OFFSET 0x00b4 +#define AM33XX_CM_WKUP_UART0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00b4) +#define AM33XX_CM_WKUP_I2C0_CLKCTRL_OFFSET 0x00b8 +#define AM33XX_CM_WKUP_I2C0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00b8) +#define AM33XX_CM_WKUP_ADC_TSC_CLKCTRL_OFFSET 0x00bc +#define AM33XX_CM_WKUP_ADC_TSC_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00bc) +#define AM33XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET 0x00c0 +#define AM33XX_CM_WKUP_SMARTREFLEX0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00c0) +#define AM33XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET 0x00c4 +#define AM33XX_CM_WKUP_TIMER1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00c4) +#define AM33XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET 0x00c8 +#define AM33XX_CM_WKUP_SMARTREFLEX1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00c8) +#define AM33XX_CM_L4_WKUP_AON_CLKSTCTRL_OFFSET 0x00cc +#define AM33XX_CM_L4_WKUP_AON_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00cc) +#define AM33XX_CM_WKUP_WDT0_CLKCTRL_OFFSET 0x00d0 +#define AM33XX_CM_WKUP_WDT0_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00d0) +#define AM33XX_CM_WKUP_WDT1_CLKCTRL_OFFSET 0x00d4 +#define AM33XX_CM_WKUP_WDT1_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00d4) +#define AM33XX_CM_DIV_M6_DPLL_CORE_OFFSET 0x00d8 +#define AM33XX_CM_DIV_M6_DPLL_CORE AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00d8) + +/* CM.DPLL_CM register offsets */ +#define AM33XX_CLKSEL_TIMER7_CLK_OFFSET 0x0004 +#define AM33XX_CLKSEL_TIMER7_CLK AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0004) +#define AM33XX_CLKSEL_TIMER2_CLK_OFFSET 0x0008 +#define AM33XX_CLKSEL_TIMER2_CLK AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0008) +#define AM33XX_CLKSEL_TIMER3_CLK_OFFSET 0x000c +#define AM33XX_CLKSEL_TIMER3_CLK AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x000c) +#define AM33XX_CLKSEL_TIMER4_CLK_OFFSET 0x0010 +#define AM33XX_CLKSEL_TIMER4_CLK AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0010) +#define AM33XX_CM_MAC_CLKSEL_OFFSET 0x0014 +#define AM33XX_CM_MAC_CLKSEL AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0014) +#define AM33XX_CLKSEL_TIMER5_CLK_OFFSET 0x0018 +#define AM33XX_CLKSEL_TIMER5_CLK AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0018) +#define AM33XX_CLKSEL_TIMER6_CLK_OFFSET 0x001c +#define AM33XX_CLKSEL_TIMER6_CLK AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x001c) +#define AM33XX_CM_CPTS_RFT_CLKSEL_OFFSET 0x0020 +#define AM33XX_CM_CPTS_RFT_CLKSEL AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0020) +#define AM33XX_CLKSEL_TIMER1MS_CLK_OFFSET 0x0028 +#define AM33XX_CLKSEL_TIMER1MS_CLK AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0028) +#define AM33XX_CLKSEL_GFX_FCLK_OFFSET 0x002c +#define AM33XX_CLKSEL_GFX_FCLK AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x002c) +#define AM33XX_CLKSEL_PRUSS_OCP_CLK_OFFSET 0x0030 +#define AM33XX_CLKSEL_PRUSS_OCP_CLK AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0030) +#define AM33XX_CLKSEL_LCDC_PIXEL_CLK_OFFSET 0x0034 +#define AM33XX_CLKSEL_LCDC_PIXEL_CLK AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0034) +#define AM33XX_CLKSEL_WDT1_CLK_OFFSET 0x0038 +#define AM33XX_CLKSEL_WDT1_CLK AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0038) +#define AM33XX_CLKSEL_GPIO0_DBCLK_OFFSET 0x003c +#define AM33XX_CLKSEL_GPIO0_DBCLK AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x003c) + +/* CM.MPU_CM register offsets */ +#define AM33XX_CM_MPU_CLKSTCTRL_OFFSET 0x0000 +#define AM33XX_CM_MPU_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_MPU_MOD, 0x0000) +#define AM33XX_CM_MPU_MPU_CLKCTRL_OFFSET 0x0004 +#define AM33XX_CM_MPU_MPU_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_MPU_MOD, 0x0004) + +/* CM.DEVICE_CM register offsets */ +#define AM33XX_CM_CLKOUT_CTRL_OFFSET 0x0000 +#define AM33XX_CM_CLKOUT_CTRL AM33XX_CM_REGADDR(AM33XX_CM_DEVICE_MOD, 0x0000) + +/* CM.RTC_CM register offsets */ +#define AM33XX_CM_RTC_RTC_CLKCTRL_OFFSET 0x0000 +#define AM33XX_CM_RTC_RTC_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_RTC_MOD, 0x0000) +#define AM33XX_CM_RTC_CLKSTCTRL_OFFSET 0x0004 +#define AM33XX_CM_RTC_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_RTC_MOD, 0x0004) + +/* CM.GFX_CM register offsets */ +#define AM33XX_CM_GFX_L3_CLKSTCTRL_OFFSET 0x0000 +#define AM33XX_CM_GFX_L3_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_GFX_MOD, 0x0000) +#define AM33XX_CM_GFX_GFX_CLKCTRL_OFFSET 0x0004 +#define AM33XX_CM_GFX_GFX_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_GFX_MOD, 0x0004) +#define AM33XX_CM_GFX_BITBLT_CLKCTRL_OFFSET 0x0008 +#define AM33XX_CM_GFX_BITBLT_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_GFX_MOD, 0x0008) +#define AM33XX_CM_GFX_L4LS_GFX_CLKSTCTRL__1_OFFSET 0x000c +#define AM33XX_CM_GFX_L4LS_GFX_CLKSTCTRL__1 AM33XX_CM_REGADDR(AM33XX_CM_GFX_MOD, 0x000c) +#define AM33XX_CM_GFX_MMUCFG_CLKCTRL_OFFSET 0x0010 +#define AM33XX_CM_GFX_MMUCFG_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_GFX_MOD, 0x0010) +#define AM33XX_CM_GFX_MMUDATA_CLKCTRL_OFFSET 0x0014 +#define AM33XX_CM_GFX_MMUDATA_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_GFX_MOD, 0x0014) + +/* CM.CEFUSE_CM register offsets */ +#define AM33XX_CM_CEFUSE_CLKSTCTRL_OFFSET 0x0000 +#define AM33XX_CM_CEFUSE_CLKSTCTRL AM33XX_CM_REGADDR(AM33XX_CM_CEFUSE_MOD, 0x0000) +#define AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET 0x0020 +#define AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_CEFUSE_MOD, 0x0020) + + +extern bool am33xx_cm_is_clkdm_in_hwsup(s16 inst, u16 cdoffs); +extern void am33xx_cm_clkdm_enable_hwsup(s16 inst, u16 cdoffs); +extern void am33xx_cm_clkdm_disable_hwsup(s16 inst, u16 cdoffs); +extern void am33xx_cm_clkdm_force_sleep(s16 inst, u16 cdoffs); +extern void am33xx_cm_clkdm_force_wakeup(s16 inst, u16 cdoffs); + +#ifdef CONFIG_SOC_AM33XX +extern int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs, + u16 clkctrl_offs); +extern void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs, + u16 clkctrl_offs); +extern void am33xx_cm_module_disable(u16 inst, s16 cdoffs, + u16 clkctrl_offs); +extern int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, + u16 clkctrl_offs); +#else +static inline int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs, + u16 clkctrl_offs) +{ + return 0; +} +static inline void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs, + u16 clkctrl_offs) +{ +} +static inline void am33xx_cm_module_disable(u16 inst, s16 cdoffs, + u16 clkctrl_offs) +{ +} +static inline int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, + u16 clkctrl_offs) +{ + return 0; +} +#endif + +#endif -- cgit v1.2.3 From 3f0ea7645ae6d7111ebc3e83f47fbc0f2c8a8964 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 18 Jun 2012 00:47:27 -0600 Subject: ARM: OMAP AM33xx: powerdomains: add AM335x support Add offset & mask fields to struct powerdomain In case of AM33xx family of devices, there is no consistency between PWRSTCTRL & PWRSTST register offsers in PRM space, for example - PRM_XXX PWRSTCTRL PWRSTST ======================================= PRM_PER_MOD: 0x0C, 0x08 PRM_WKUP_MOD: 0x04, 0x08 PRM_MPU_MOD: 0x00, 0x04 PRM_DEVICE_MOD: NA, NA And also, there is no consistency between bit-offsets inside PWRSTCTRL & PWRSTST register, for example - PRM_XXX LOGICRET MEMON MEMRET ======================================= GFX_PWRCTRL: 2, 17, 6 PER_PWRCTRL: 3, 25, 29 MPU_PWRCTRL: 2, 18, 22 WKUP_PWRCTRL: 3, NA, NA This means, we need to maintain and pass on all this information in powerdomain handle; so adding fields for, - PWRSTCTRL/ST register offset - Logic retention state mask - mem_on/ret/pwrst/retst mask Currently, this fields is only applicable and used for AM33XX devices. Signed-off-by: Vaibhav Hiremath Cc: Benoit Cousson Cc: Tony Lindgren Cc: Kevin Hilman Cc: Paul Walmsley Cc: Rajendra Nayak [paul@pwsan.com: this patch is a combination of "Add offset & mask fields to struct powerdomain" and the powerdomain portions of "ARM: OMAP3+: am33xx: Add powerdomain & PRM support"; updated for 3.5] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/Makefile | 2 + arch/arm/mach-omap2/io.c | 1 + arch/arm/mach-omap2/powerdomain.h | 23 ++- arch/arm/mach-omap2/powerdomain33xx.c | 229 ++++++++++++++++++++++++++++ arch/arm/mach-omap2/powerdomains33xx_data.c | 185 ++++++++++++++++++++++ 5 files changed, 438 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-omap2/powerdomain33xx.c create mode 100644 arch/arm/mach-omap2/powerdomains33xx_data.c (limited to 'arch') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index cc080946ec61..b664dc8722aa 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -115,6 +115,8 @@ obj-$(CONFIG_ARCH_OMAP3) += powerdomains2xxx_3xxx_data.o obj-$(CONFIG_ARCH_OMAP4) += $(powerdomain-common) obj-$(CONFIG_ARCH_OMAP4) += powerdomain44xx.o obj-$(CONFIG_ARCH_OMAP4) += powerdomains44xx_data.o +obj-$(CONFIG_SOC_AM33XX) += powerdomain33xx.o +obj-$(CONFIG_SOC_AM33XX) += powerdomains33xx_data.o # PRCM clockdomain control clockdomain-common += clockdomain.o diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index d15ecb3782b7..3c885248b984 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -485,6 +485,7 @@ void __init am33xx_init_early(void) ti81xx_check_features(); omap_common_init_early(); am33xx_voltagedomains_init(); + am33xx_powerdomains_init(); } #endif diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 8f88d65c46ea..a8a95184243d 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -67,9 +67,9 @@ /* * Maximum number of clockdomains that can be associated with a powerdomain. - * CORE powerdomain on OMAP4 is the worst case + * PER powerdomain on AM33XX is the worst case */ -#define PWRDM_MAX_CLKDMS 9 +#define PWRDM_MAX_CLKDMS 11 /* XXX A completely arbitrary number. What is reasonable here? */ #define PWRDM_TRANSITION_BAILOUT 100000 @@ -92,6 +92,15 @@ struct powerdomain; * @pwrdm_clkdms: Clockdomains in this powerdomain * @node: list_head linking all powerdomains * @voltdm_node: list_head linking all powerdomains in a voltagedomain + * @pwrstctrl_offs: (AM33XX only) XXX_PWRSTCTRL reg offset from prcm_offs + * @pwrstst_offs: (AM33XX only) XXX_PWRSTST reg offset from prcm_offs + * @logicretstate_mask: (AM33XX only) mask for logic retention bitfield + * in @pwrstctrl_offs + * @mem_on_mask: (AM33XX only) mask for mem on bitfield in @pwrstctrl_offs + * @mem_ret_mask: (AM33XX only) mask for mem ret bitfield in @pwrstctrl_offs + * @mem_pwrst_mask: (AM33XX only) mask for mem state bitfield in @pwrstst_offs + * @mem_retst_mask: (AM33XX only) mask for mem retention state bitfield + * in @pwrstctrl_offs * @state: * @state_counter: * @timer: @@ -121,6 +130,14 @@ struct powerdomain { unsigned ret_logic_off_counter; unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS]; + const u8 pwrstctrl_offs; + const u8 pwrstst_offs; + const u32 logicretstate_mask; + const u32 mem_on_mask[PWRDM_MAX_MEM_BANKS]; + const u32 mem_ret_mask[PWRDM_MAX_MEM_BANKS]; + const u32 mem_pwrst_mask[PWRDM_MAX_MEM_BANKS]; + const u32 mem_retst_mask[PWRDM_MAX_MEM_BANKS]; + #ifdef CONFIG_PM_DEBUG s64 timer; s64 state_timer[PWRDM_MAX_PWRSTS]; @@ -222,10 +239,12 @@ bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); extern void omap242x_powerdomains_init(void); extern void omap243x_powerdomains_init(void); extern void omap3xxx_powerdomains_init(void); +extern void am33xx_powerdomains_init(void); extern void omap44xx_powerdomains_init(void); extern struct pwrdm_ops omap2_pwrdm_operations; extern struct pwrdm_ops omap3_pwrdm_operations; +extern struct pwrdm_ops am33xx_pwrdm_operations; extern struct pwrdm_ops omap4_pwrdm_operations; /* Common Internal functions used across OMAP rev's */ diff --git a/arch/arm/mach-omap2/powerdomain33xx.c b/arch/arm/mach-omap2/powerdomain33xx.c new file mode 100644 index 000000000000..67c5663899b6 --- /dev/null +++ b/arch/arm/mach-omap2/powerdomain33xx.c @@ -0,0 +1,229 @@ +/* + * AM33XX Powerdomain control + * + * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * Derived from mach-omap2/powerdomain44xx.c written by Rajendra Nayak + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#include + +#include "powerdomain.h" +#include "prm33xx.h" +#include "prm-regbits-33xx.h" + + +static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) +{ + am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK, + (pwrst << OMAP_POWERSTATE_SHIFT), + pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); + return 0; +} + +static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) +{ + u32 v; + + v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); + v &= OMAP_POWERSTATE_MASK; + v >>= OMAP_POWERSTATE_SHIFT; + + return v; +} + +static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm) +{ + u32 v; + + v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); + v &= OMAP_POWERSTATEST_MASK; + v >>= OMAP_POWERSTATEST_SHIFT; + + return v; +} + +static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) +{ + u32 v; + + v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); + v &= AM33XX_LASTPOWERSTATEENTERED_MASK; + v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT; + + return v; +} + +static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) +{ + am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK, + (1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT), + pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); + return 0; +} + +static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) +{ + am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK, + AM33XX_LASTPOWERSTATEENTERED_MASK, + pwrdm->prcm_offs, pwrdm->pwrstst_offs); + return 0; +} + +static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) +{ + u32 m; + + m = pwrdm->logicretstate_mask; + if (!m) + return -EINVAL; + + am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)), + pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); + + return 0; +} + +static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) +{ + u32 v; + + v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); + v &= AM33XX_LOGICSTATEST_MASK; + v >>= AM33XX_LOGICSTATEST_SHIFT; + + return v; +} + +static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm) +{ + u32 v, m; + + m = pwrdm->logicretstate_mask; + if (!m) + return -EINVAL; + + v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); + v &= m; + v >>= __ffs(m); + + return v; +} + +static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, + u8 pwrst) +{ + u32 m; + + m = pwrdm->mem_on_mask[bank]; + if (!m) + return -EINVAL; + + am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)), + pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); + + return 0; +} + +static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, + u8 pwrst) +{ + u32 m; + + m = pwrdm->mem_ret_mask[bank]; + if (!m) + return -EINVAL; + + am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)), + pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); + + return 0; +} + +static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) +{ + u32 m, v; + + m = pwrdm->mem_pwrst_mask[bank]; + if (!m) + return -EINVAL; + + v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); + v &= m; + v >>= __ffs(m); + + return v; +} + +static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) +{ + u32 m, v; + + m = pwrdm->mem_retst_mask[bank]; + if (!m) + return -EINVAL; + + v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); + v &= m; + v >>= __ffs(m); + + return v; +} + +static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm) +{ + u32 c = 0; + + /* + * REVISIT: pwrdm_wait_transition() may be better implemented + * via a callback and a periodic timer check -- how long do we expect + * powerdomain transitions to take? + */ + + /* XXX Is this udelay() value meaningful? */ + while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs) + & OMAP_INTRANSITION_MASK) && + (c++ < PWRDM_TRANSITION_BAILOUT)) + udelay(1); + + if (c > PWRDM_TRANSITION_BAILOUT) { + pr_err("powerdomain: %s: waited too long to complete transition\n", + pwrdm->name); + return -EAGAIN; + } + + pr_debug("powerdomain: completed transition in %d loops\n", c); + + return 0; +} + +struct pwrdm_ops am33xx_pwrdm_operations = { + .pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst, + .pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst, + .pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst, + .pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst, + .pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst, + .pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst, + .pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst, + .pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst, + .pwrdm_set_lowpwrstchange = am33xx_pwrdm_set_lowpwrstchange, + .pwrdm_read_mem_pwrst = am33xx_pwrdm_read_mem_pwrst, + .pwrdm_read_mem_retst = am33xx_pwrdm_read_mem_retst, + .pwrdm_set_mem_onst = am33xx_pwrdm_set_mem_onst, + .pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst, + .pwrdm_wait_transition = am33xx_pwrdm_wait_transition, +}; diff --git a/arch/arm/mach-omap2/powerdomains33xx_data.c b/arch/arm/mach-omap2/powerdomains33xx_data.c new file mode 100644 index 000000000000..869adb82569e --- /dev/null +++ b/arch/arm/mach-omap2/powerdomains33xx_data.c @@ -0,0 +1,185 @@ +/* + * AM33XX Power domain data + * + * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "powerdomain.h" +#include "prcm-common.h" +#include "prm-regbits-33xx.h" +#include "prm33xx.h" + +static struct powerdomain gfx_33xx_pwrdm = { + .name = "gfx_pwrdm", + .voltdm = { .name = "core" }, + .prcm_offs = AM33XX_PRM_GFX_MOD, + .pwrstctrl_offs = AM33XX_PM_GFX_PWRSTCTRL_OFFSET, + .pwrstst_offs = AM33XX_PM_GFX_PWRSTST_OFFSET, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRSTS_OFF_RET, + .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, + .banks = 1, + .logicretstate_mask = AM33XX_LOGICRETSTATE_MASK, + .mem_on_mask = { + [0] = AM33XX_GFX_MEM_ONSTATE_MASK, /* gfx_mem */ + }, + .mem_ret_mask = { + [0] = AM33XX_GFX_MEM_RETSTATE_MASK, /* gfx_mem */ + }, + .mem_pwrst_mask = { + [0] = AM33XX_GFX_MEM_STATEST_MASK, /* gfx_mem */ + }, + .mem_retst_mask = { + [0] = AM33XX_GFX_MEM_RETSTATE_MASK, /* gfx_mem */ + }, + .pwrsts_mem_ret = { + [0] = PWRSTS_OFF_RET, /* gfx_mem */ + }, + .pwrsts_mem_on = { + [0] = PWRSTS_ON, /* gfx_mem */ + }, +}; + +static struct powerdomain rtc_33xx_pwrdm = { + .name = "rtc_pwrdm", + .voltdm = { .name = "rtc" }, + .prcm_offs = AM33XX_PRM_RTC_MOD, + .pwrstctrl_offs = AM33XX_PM_RTC_PWRSTCTRL_OFFSET, + .pwrstst_offs = AM33XX_PM_RTC_PWRSTST_OFFSET, + .pwrsts = PWRSTS_ON, + .logicretstate_mask = AM33XX_LOGICRETSTATE_MASK, +}; + +static struct powerdomain wkup_33xx_pwrdm = { + .name = "wkup_pwrdm", + .voltdm = { .name = "core" }, + .prcm_offs = AM33XX_PRM_WKUP_MOD, + .pwrstctrl_offs = AM33XX_PM_WKUP_PWRSTCTRL_OFFSET, + .pwrstst_offs = AM33XX_PM_WKUP_PWRSTST_OFFSET, + .pwrsts = PWRSTS_ON, + .logicretstate_mask = AM33XX_LOGICRETSTATE_3_3_MASK, +}; + +static struct powerdomain per_33xx_pwrdm = { + .name = "per_pwrdm", + .voltdm = { .name = "core" }, + .prcm_offs = AM33XX_PRM_PER_MOD, + .pwrstctrl_offs = AM33XX_PM_PER_PWRSTCTRL_OFFSET, + .pwrstst_offs = AM33XX_PM_PER_PWRSTST_OFFSET, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRSTS_OFF_RET, + .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, + .banks = 3, + .logicretstate_mask = AM33XX_LOGICRETSTATE_3_3_MASK, + .mem_on_mask = { + [0] = AM33XX_PRUSS_MEM_ONSTATE_MASK, /* pruss_mem */ + [1] = AM33XX_PER_MEM_ONSTATE_MASK, /* per_mem */ + [2] = AM33XX_RAM_MEM_ONSTATE_MASK, /* ram_mem */ + }, + .mem_ret_mask = { + [0] = AM33XX_PRUSS_MEM_RETSTATE_MASK, /* pruss_mem */ + [1] = AM33XX_PER_MEM_RETSTATE_MASK, /* per_mem */ + [2] = AM33XX_RAM_MEM_RETSTATE_MASK, /* ram_mem */ + }, + .mem_pwrst_mask = { + [0] = AM33XX_PRUSS_MEM_STATEST_MASK, /* pruss_mem */ + [1] = AM33XX_PER_MEM_STATEST_MASK, /* per_mem */ + [2] = AM33XX_RAM_MEM_STATEST_MASK, /* ram_mem */ + }, + .mem_retst_mask = { + [0] = AM33XX_PRUSS_MEM_RETSTATE_MASK, /* pruss_mem */ + [1] = AM33XX_PER_MEM_RETSTATE_MASK, /* per_mem */ + [2] = AM33XX_RAM_MEM_RETSTATE_MASK, /* ram_mem */ + }, + .pwrsts_mem_ret = { + [0] = PWRSTS_OFF_RET, /* pruss_mem */ + [1] = PWRSTS_OFF_RET, /* per_mem */ + [2] = PWRSTS_OFF_RET, /* ram_mem */ + }, + .pwrsts_mem_on = { + [0] = PWRSTS_ON, /* pruss_mem */ + [1] = PWRSTS_ON, /* per_mem */ + [2] = PWRSTS_ON, /* ram_mem */ + }, +}; + +static struct powerdomain mpu_33xx_pwrdm = { + .name = "mpu_pwrdm", + .voltdm = { .name = "mpu" }, + .prcm_offs = AM33XX_PRM_MPU_MOD, + .pwrstctrl_offs = AM33XX_PM_MPU_PWRSTCTRL_OFFSET, + .pwrstst_offs = AM33XX_PM_MPU_PWRSTST_OFFSET, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRSTS_OFF_RET, + .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, + .banks = 3, + .logicretstate_mask = AM33XX_LOGICRETSTATE_MASK, + .mem_on_mask = { + [0] = AM33XX_MPU_L1_ONSTATE_MASK, /* mpu_l1 */ + [1] = AM33XX_MPU_L2_ONSTATE_MASK, /* mpu_l2 */ + [2] = AM33XX_MPU_RAM_ONSTATE_MASK, /* mpu_ram */ + }, + .mem_ret_mask = { + [0] = AM33XX_MPU_L1_RETSTATE_MASK, /* mpu_l1 */ + [1] = AM33XX_MPU_L2_RETSTATE_MASK, /* mpu_l2 */ + [2] = AM33XX_MPU_RAM_RETSTATE_MASK, /* mpu_ram */ + }, + .mem_pwrst_mask = { + [0] = AM33XX_MPU_L1_STATEST_MASK, /* mpu_l1 */ + [1] = AM33XX_MPU_L2_STATEST_MASK, /* mpu_l2 */ + [2] = AM33XX_MPU_RAM_STATEST_MASK, /* mpu_ram */ + }, + .mem_retst_mask = { + [0] = AM33XX_MPU_L1_RETSTATE_MASK, /* mpu_l1 */ + [1] = AM33XX_MPU_L2_RETSTATE_MASK, /* mpu_l2 */ + [2] = AM33XX_MPU_RAM_RETSTATE_MASK, /* mpu_ram */ + }, + .pwrsts_mem_ret = { + [0] = PWRSTS_OFF_RET, /* mpu_l1 */ + [1] = PWRSTS_OFF_RET, /* mpu_l2 */ + [2] = PWRSTS_OFF_RET, /* mpu_ram */ + }, + .pwrsts_mem_on = { + [0] = PWRSTS_ON, /* mpu_l1 */ + [1] = PWRSTS_ON, /* mpu_l2 */ + [2] = PWRSTS_ON, /* mpu_ram */ + }, +}; + +static struct powerdomain cefuse_33xx_pwrdm = { + .name = "cefuse_pwrdm", + .voltdm = { .name = "core" }, + .prcm_offs = AM33XX_PRM_CEFUSE_MOD, + .pwrstctrl_offs = AM33XX_PM_CEFUSE_PWRSTCTRL_OFFSET, + .pwrstst_offs = AM33XX_PM_CEFUSE_PWRSTST_OFFSET, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct powerdomain *powerdomains_am33xx[] __initdata = { + &gfx_33xx_pwrdm, + &rtc_33xx_pwrdm, + &wkup_33xx_pwrdm, + &per_33xx_pwrdm, + &mpu_33xx_pwrdm, + &cefuse_33xx_pwrdm, + NULL, +}; + +void __init am33xx_powerdomains_init(void) +{ + pwrdm_register_platform_funcs(&am33xx_pwrdm_operations); + pwrdm_register_pwrdms(powerdomains_am33xx); + pwrdm_complete_init(); +} -- cgit v1.2.3 From 9c80f3aa8b7828c89c5bae5c769955d1ac58630b Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 18 Jun 2012 00:47:27 -0600 Subject: ARM: OMAP AM33xx: clockdomains: Add clockdomain data and respective operations AM33XX PRCM module consists of various clockdomains, in all total we have 18 clockdomains available, with following controlling options, - SW Sleep: sw forced sleep transition - SW Wakeup: sw forced wakeup transition This patch adds all available clockdomain data, respective clockdomain operations for AM33XX family of device, and also integrates it into existing OMAP framework. Signed-off-by: Vaibhav Hiremath Signed-off-by: Afzal Mohammed Signed-off-by: Vaibhav Bedia Cc: Kevin Hilman Cc: Rajendra Nayak CC: Tony Lindgren Cc: Paul Walmsley Cc: Benoit Cousson [paul@pwsan.com: removed CLKDM_NO_AUTODEPS from clockdomain flags, removed unnecessary .clktrctrl_offs field; updated for 3.5] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/Makefile | 2 + arch/arm/mach-omap2/clockdomain.h | 2 + arch/arm/mach-omap2/clockdomain33xx.c | 74 +++++++++++ arch/arm/mach-omap2/clockdomains33xx_data.c | 196 ++++++++++++++++++++++++++++ arch/arm/mach-omap2/io.c | 1 + 5 files changed, 275 insertions(+) create mode 100644 arch/arm/mach-omap2/clockdomain33xx.c create mode 100644 arch/arm/mach-omap2/clockdomains33xx_data.c (limited to 'arch') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index b664dc8722aa..a4cf93242b0b 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -133,6 +133,8 @@ obj-$(CONFIG_ARCH_OMAP3) += clockdomains3xxx_data.o obj-$(CONFIG_ARCH_OMAP4) += $(clockdomain-common) obj-$(CONFIG_ARCH_OMAP4) += clockdomain44xx.o obj-$(CONFIG_ARCH_OMAP4) += clockdomains44xx_data.o +obj-$(CONFIG_SOC_AM33XX) += clockdomain33xx.o +obj-$(CONFIG_SOC_AM33XX) += clockdomains33xx_data.o # Clock framework obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index f7b58609bad8..72cb12bbb9c3 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -195,6 +195,7 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh); extern void __init omap242x_clockdomains_init(void); extern void __init omap243x_clockdomains_init(void); extern void __init omap3xxx_clockdomains_init(void); +extern void __init am33xx_clockdomains_init(void); extern void __init omap44xx_clockdomains_init(void); extern void _clkdm_add_autodeps(struct clockdomain *clkdm); extern void _clkdm_del_autodeps(struct clockdomain *clkdm); @@ -202,6 +203,7 @@ extern void _clkdm_del_autodeps(struct clockdomain *clkdm); extern struct clkdm_ops omap2_clkdm_operations; extern struct clkdm_ops omap3_clkdm_operations; extern struct clkdm_ops omap4_clkdm_operations; +extern struct clkdm_ops am33xx_clkdm_operations; extern struct clkdm_dep gfx_24xx_wkdeps[]; extern struct clkdm_dep dsp_24xx_wkdeps[]; diff --git a/arch/arm/mach-omap2/clockdomain33xx.c b/arch/arm/mach-omap2/clockdomain33xx.c new file mode 100644 index 000000000000..aca6388fad76 --- /dev/null +++ b/arch/arm/mach-omap2/clockdomain33xx.c @@ -0,0 +1,74 @@ +/* + * AM33XX clockdomain control + * + * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ + * Vaibhav Hiremath + * + * Derived from mach-omap2/clockdomain44xx.c written by Rajendra Nayak + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#include "clockdomain.h" +#include "cm33xx.h" + + +static int am33xx_clkdm_sleep(struct clockdomain *clkdm) +{ + am33xx_cm_clkdm_force_sleep(clkdm->cm_inst, clkdm->clkdm_offs); + return 0; +} + +static int am33xx_clkdm_wakeup(struct clockdomain *clkdm) +{ + am33xx_cm_clkdm_force_wakeup(clkdm->cm_inst, clkdm->clkdm_offs); + return 0; +} + +static void am33xx_clkdm_allow_idle(struct clockdomain *clkdm) +{ + am33xx_cm_clkdm_enable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs); +} + +static void am33xx_clkdm_deny_idle(struct clockdomain *clkdm) +{ + am33xx_cm_clkdm_disable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs); +} + +static int am33xx_clkdm_clk_enable(struct clockdomain *clkdm) +{ + if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) + return am33xx_clkdm_wakeup(clkdm); + + return 0; +} + +static int am33xx_clkdm_clk_disable(struct clockdomain *clkdm) +{ + bool hwsup = false; + + hwsup = am33xx_cm_is_clkdm_in_hwsup(clkdm->cm_inst, clkdm->clkdm_offs); + + if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) + am33xx_clkdm_sleep(clkdm); + + return 0; +} + +struct clkdm_ops am33xx_clkdm_operations = { + .clkdm_sleep = am33xx_clkdm_sleep, + .clkdm_wakeup = am33xx_clkdm_wakeup, + .clkdm_allow_idle = am33xx_clkdm_allow_idle, + .clkdm_deny_idle = am33xx_clkdm_deny_idle, + .clkdm_clk_enable = am33xx_clkdm_clk_enable, + .clkdm_clk_disable = am33xx_clkdm_clk_disable, +}; diff --git a/arch/arm/mach-omap2/clockdomains33xx_data.c b/arch/arm/mach-omap2/clockdomains33xx_data.c new file mode 100644 index 000000000000..32c90fd9eba2 --- /dev/null +++ b/arch/arm/mach-omap2/clockdomains33xx_data.c @@ -0,0 +1,196 @@ +/* + * AM33XX Clock Domain data. + * + * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ + * Vaibhav Hiremath + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clockdomain.h" +#include "cm.h" +#include "cm33xx.h" +#include "cm-regbits-33xx.h" + +static struct clockdomain l4ls_am33xx_clkdm = { + .name = "l4ls_clkdm", + .pwrdm = { .name = "per_pwrdm" }, + .cm_inst = AM33XX_CM_PER_MOD, + .clkdm_offs = AM33XX_CM_PER_L4LS_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain l3s_am33xx_clkdm = { + .name = "l3s_clkdm", + .pwrdm = { .name = "per_pwrdm" }, + .cm_inst = AM33XX_CM_PER_MOD, + .clkdm_offs = AM33XX_CM_PER_L3S_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain l4fw_am33xx_clkdm = { + .name = "l4fw_clkdm", + .pwrdm = { .name = "per_pwrdm" }, + .cm_inst = AM33XX_CM_PER_MOD, + .clkdm_offs = AM33XX_CM_PER_L4FW_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain l3_am33xx_clkdm = { + .name = "l3_clkdm", + .pwrdm = { .name = "per_pwrdm" }, + .cm_inst = AM33XX_CM_PER_MOD, + .clkdm_offs = AM33XX_CM_PER_L3_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain l4hs_am33xx_clkdm = { + .name = "l4hs_clkdm", + .pwrdm = { .name = "per_pwrdm" }, + .cm_inst = AM33XX_CM_PER_MOD, + .clkdm_offs = AM33XX_CM_PER_L4HS_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain ocpwp_l3_am33xx_clkdm = { + .name = "ocpwp_l3_clkdm", + .pwrdm = { .name = "per_pwrdm" }, + .cm_inst = AM33XX_CM_PER_MOD, + .clkdm_offs = AM33XX_CM_PER_OCPWP_L3_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain pruss_ocp_am33xx_clkdm = { + .name = "pruss_ocp_clkdm", + .pwrdm = { .name = "per_pwrdm" }, + .cm_inst = AM33XX_CM_PER_MOD, + .clkdm_offs = AM33XX_CM_PER_PRUSS_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain cpsw_125mhz_am33xx_clkdm = { + .name = "cpsw_125mhz_clkdm", + .pwrdm = { .name = "per_pwrdm" }, + .cm_inst = AM33XX_CM_PER_MOD, + .clkdm_offs = AM33XX_CM_PER_CPSW_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain lcdc_am33xx_clkdm = { + .name = "lcdc_clkdm", + .pwrdm = { .name = "per_pwrdm" }, + .cm_inst = AM33XX_CM_PER_MOD, + .clkdm_offs = AM33XX_CM_PER_LCDC_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain clk_24mhz_am33xx_clkdm = { + .name = "clk_24mhz_clkdm", + .pwrdm = { .name = "per_pwrdm" }, + .cm_inst = AM33XX_CM_PER_MOD, + .clkdm_offs = AM33XX_CM_PER_CLK_24MHZ_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain l4_wkup_am33xx_clkdm = { + .name = "l4_wkup_clkdm", + .pwrdm = { .name = "wkup_pwrdm" }, + .cm_inst = AM33XX_CM_WKUP_MOD, + .clkdm_offs = AM33XX_CM_WKUP_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain l3_aon_am33xx_clkdm = { + .name = "l3_aon_clkdm", + .pwrdm = { .name = "wkup_pwrdm" }, + .cm_inst = AM33XX_CM_WKUP_MOD, + .clkdm_offs = AM33XX_CM_L3_AON_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain l4_wkup_aon_am33xx_clkdm = { + .name = "l4_wkup_aon_clkdm", + .pwrdm = { .name = "wkup_pwrdm" }, + .cm_inst = AM33XX_CM_WKUP_MOD, + .clkdm_offs = AM33XX_CM_L4_WKUP_AON_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain mpu_am33xx_clkdm = { + .name = "mpu_clkdm", + .pwrdm = { .name = "mpu_pwrdm" }, + .cm_inst = AM33XX_CM_MPU_MOD, + .clkdm_offs = AM33XX_CM_MPU_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain l4_rtc_am33xx_clkdm = { + .name = "l4_rtc_clkdm", + .pwrdm = { .name = "rtc_pwrdm" }, + .cm_inst = AM33XX_CM_RTC_MOD, + .clkdm_offs = AM33XX_CM_RTC_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain gfx_l3_am33xx_clkdm = { + .name = "gfx_l3_clkdm", + .pwrdm = { .name = "gfx_pwrdm" }, + .cm_inst = AM33XX_CM_GFX_MOD, + .clkdm_offs = AM33XX_CM_GFX_L3_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain gfx_l4ls_gfx_am33xx_clkdm = { + .name = "gfx_l4ls_gfx_clkdm", + .pwrdm = { .name = "gfx_pwrdm" }, + .cm_inst = AM33XX_CM_GFX_MOD, + .clkdm_offs = AM33XX_CM_GFX_L4LS_GFX_CLKSTCTRL__1_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain l4_cefuse_am33xx_clkdm = { + .name = "l4_cefuse_clkdm", + .pwrdm = { .name = "cefuse_pwrdm" }, + .cm_inst = AM33XX_CM_CEFUSE_MOD, + .clkdm_offs = AM33XX_CM_CEFUSE_CLKSTCTRL_OFFSET, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain *clockdomains_am33xx[] __initdata = { + &l4ls_am33xx_clkdm, + &l3s_am33xx_clkdm, + &l4fw_am33xx_clkdm, + &l3_am33xx_clkdm, + &l4hs_am33xx_clkdm, + &ocpwp_l3_am33xx_clkdm, + &pruss_ocp_am33xx_clkdm, + &cpsw_125mhz_am33xx_clkdm, + &lcdc_am33xx_clkdm, + &clk_24mhz_am33xx_clkdm, + &l4_wkup_am33xx_clkdm, + &l3_aon_am33xx_clkdm, + &l4_wkup_aon_am33xx_clkdm, + &mpu_am33xx_clkdm, + &l4_rtc_am33xx_clkdm, + &gfx_l3_am33xx_clkdm, + &gfx_l4ls_gfx_am33xx_clkdm, + &l4_cefuse_am33xx_clkdm, + NULL, +}; + +void __init am33xx_clockdomains_init(void) +{ + clkdm_register_platform_funcs(&am33xx_clkdm_operations); + clkdm_register_clkdms(clockdomains_am33xx); + clkdm_complete_init(); +} diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 3c885248b984..cb6c11cd8df9 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -486,6 +486,7 @@ void __init am33xx_init_early(void) omap_common_init_early(); am33xx_voltagedomains_init(); am33xx_powerdomains_init(); + am33xx_clockdomains_init(); } #endif -- cgit v1.2.3 From 3d9f032724e72851c6de38d026b2417501a2f240 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 12:12:23 -0600 Subject: ARM: OMAP4: hwmod: rename _enable_module to _omap4_enable_module() _enable_module is specific to SoCs with PRCM interfaces similar to that of the OMAP4, so rename it to be consistent with the corresponding _omap4_disable_module. Signed-off-by: Kevin Hilman [paul@pwsan.com: tweaked commit message] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index bf86f7e8f91f..939032a427fd 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -771,13 +771,13 @@ static void _disable_optional_clocks(struct omap_hwmod *oh) } /** - * _enable_module - enable CLKCTRL modulemode on OMAP4 + * _omap4_enable_module - enable CLKCTRL modulemode on OMAP4 * @oh: struct omap_hwmod * * * Enables the PRCM module mode related to the hwmod @oh. * No return value. */ -static void _enable_module(struct omap_hwmod *oh) +static void _omap4_enable_module(struct omap_hwmod *oh) { /* The module mode does not exist prior OMAP4 */ if (cpu_is_omap24xx() || cpu_is_omap34xx()) @@ -786,8 +786,8 @@ static void _enable_module(struct omap_hwmod *oh) if (!oh->clkdm || !oh->prcm.omap4.modulemode) return; - pr_debug("omap_hwmod: %s: _enable_module: %d\n", - oh->name, oh->prcm.omap4.modulemode); + pr_debug("omap_hwmod: %s: %s: %d\n", + oh->name, __func__, oh->prcm.omap4.modulemode); omap4_cminst_module_enable(oh->prcm.omap4.modulemode, oh->clkdm->prcm_partition, @@ -1814,7 +1814,7 @@ static int _enable(struct omap_hwmod *oh) } _enable_clocks(oh); - _enable_module(oh); + _omap4_enable_module(oh); r = _wait_target_ready(oh); if (!r) { -- cgit v1.2.3 From 9ebfd285371835b1c0243d15aaacd72d5def76f8 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 12:12:23 -0600 Subject: ARM: OMAP2+: hwmod: use init-time function ptrs for enable/disable module The enable/disable module functions are specific to SoCs with OMAP4-class PRCM. Rather than use cpu_is* checks at runtime inside the enable/disable module functions, use cpu_is at init time to initialize function pointers only for SoCs that need them. NOTE: the cpu_is* check for _enable_module was different than the one for _disable_module, and this patch uses cpu_is_omap44xx() for both. Signed-off-by: Kevin Hilman [paul@pwsan.com: moved soc_ops function pointers to be per-kernel rather than per-hwmod since they do not vary by hwmod; added kerneldoc] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 62 ++++++++++++++++++++++------ arch/arm/mach-omap2/omap_hwmod_2420_data.c | 1 + arch/arm/mach-omap2/omap_hwmod_2430_data.c | 1 + arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 2 + arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 1 + arch/arm/plat-omap/include/plat/omap_hwmod.h | 2 + 6 files changed, 57 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 939032a427fd..634a79836c64 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -166,6 +166,23 @@ */ #define LINKS_PER_OCP_IF 2 +/** + * struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations + * @enable_module: function to enable a module (via MODULEMODE) + * @disable_module: function to disable a module (via MODULEMODE) + * + * XXX Eventually this functionality will be hidden inside the PRM/CM + * device drivers. Until then, this should avoid huge blocks of cpu_is_*() + * conditionals in this code. + */ +struct omap_hwmod_soc_ops { + void (*enable_module)(struct omap_hwmod *oh); + int (*disable_module)(struct omap_hwmod *oh); +}; + +/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ +static struct omap_hwmod_soc_ops soc_ops; + /* omap_hwmod_list contains all registered struct omap_hwmods */ static LIST_HEAD(omap_hwmod_list); @@ -186,6 +203,9 @@ static struct omap_hwmod_link *linkspace; */ static unsigned short free_ls, max_ls, ls_supp; +/* inited: set to true once the hwmod code is initialized */ +static bool inited; + /* Private functions */ /** @@ -779,10 +799,6 @@ static void _disable_optional_clocks(struct omap_hwmod *oh) */ static void _omap4_enable_module(struct omap_hwmod *oh) { - /* The module mode does not exist prior OMAP4 */ - if (cpu_is_omap24xx() || cpu_is_omap34xx()) - return; - if (!oh->clkdm || !oh->prcm.omap4.modulemode) return; @@ -1571,10 +1587,6 @@ static int _omap4_disable_module(struct omap_hwmod *oh) { int v; - /* The module mode does not exist prior OMAP4 */ - if (!cpu_is_omap44xx()) - return -EINVAL; - if (!oh->clkdm || !oh->prcm.omap4.modulemode) return -EINVAL; @@ -1814,7 +1826,8 @@ static int _enable(struct omap_hwmod *oh) } _enable_clocks(oh); - _omap4_enable_module(oh); + if (soc_ops.enable_module) + soc_ops.enable_module(oh); r = _wait_target_ready(oh); if (!r) { @@ -1870,7 +1883,8 @@ static int _idle(struct omap_hwmod *oh) _idle_sysc(oh); _del_initiator_dep(oh, mpu_oh); - _omap4_disable_module(oh); + if (soc_ops.disable_module) + soc_ops.disable_module(oh); /* * The module must be in idle mode before disabling any parents @@ -1975,7 +1989,8 @@ static int _shutdown(struct omap_hwmod *oh) if (oh->_state == _HWMOD_STATE_ENABLED) { _del_initiator_dep(oh, mpu_oh); /* XXX what about the other system initiators here? dma, dsp */ - _omap4_disable_module(oh); + if (soc_ops.disable_module) + soc_ops.disable_module(oh); _disable_clocks(oh); if (oh->clkdm) clkdm_hwmod_disable(oh->clkdm, oh); @@ -2563,12 +2578,18 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), * * Intended to be called early in boot before the clock framework is * initialized. If @ois is not null, will register all omap_hwmods - * listed in @ois that are valid for this chip. Returns 0. + * listed in @ois that are valid for this chip. Returns -EINVAL if + * omap_hwmod_init() hasn't been called before calling this function, + * -ENOMEM if the link memory area can't be allocated, or 0 upon + * success. */ int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois) { int r, i; + if (!inited) + return -EINVAL; + if (!ois) return 0; @@ -3401,3 +3422,20 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx) return 0; } + +/** + * omap_hwmod_init - initialize the hwmod code + * + * Sets up some function pointers needed by the hwmod code to operate on the + * currently-booted SoC. Intended to be called once during kernel init + * before any hwmods are registered. No return value. + */ +void __init omap_hwmod_init(void) +{ + if (cpu_is_omap44xx()) { + soc_ops.enable_module = _omap4_enable_module; + soc_ops.disable_module = _omap4_disable_module; + } + + inited = true; +} diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index a7640d1b215e..5b1938b52d09 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -585,5 +585,6 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = { int __init omap2420_hwmod_init(void) { + omap_hwmod_init(); return omap_hwmod_register_links(omap2420_hwmod_ocp_ifs); } diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 4d7264981230..71f199783c63 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -938,5 +938,6 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = { int __init omap2430_hwmod_init(void) { + omap_hwmod_init(); return omap_hwmod_register_links(omap2430_hwmod_ocp_ifs); } diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index b26d3c9bca16..abb1f6b56ee5 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -3283,6 +3283,8 @@ int __init omap3xxx_hwmod_init(void) struct omap_hwmod_ocp_if **h = NULL; unsigned int rev; + omap_hwmod_init(); + /* Register hwmod links common to all OMAP3 */ r = omap_hwmod_register_links(omap3xxx_hwmod_ocp_ifs); if (r < 0) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 950454a3fa31..d3c48dc26af1 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -6144,6 +6144,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { int __init omap44xx_hwmod_init(void) { + omap_hwmod_init(); return omap_hwmod_register_links(omap44xx_hwmod_ocp_ifs); } diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index c835b7194ff5..a8ecc53b3670 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -629,6 +629,8 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh); int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx); +extern void __init omap_hwmod_init(void); + /* * Chip variant-specific hwmod init routines - XXX should be converted * to use initcalls once the initial boot ordering is straightened out -- cgit v1.2.3 From baa2607f56f1589eb21c01fe16aa5f5c3f9dad31 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 12:12:24 -0600 Subject: ARM: OMAP4: hwmod: drop extra cpu_is check from _wait_target_disable() _omap4_wait_target_disable() is called only from inside _omap4_disable_module() which is already protected by SoC specific checks. Remove the cpu_is check here. Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/omap_hwmod.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 634a79836c64..2b845836f7dc 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -823,9 +823,6 @@ static void _omap4_enable_module(struct omap_hwmod *oh) */ static int _omap4_wait_target_disable(struct omap_hwmod *oh) { - if (!cpu_is_omap44xx()) - return 0; - if (!oh) return -EINVAL; -- cgit v1.2.3 From 8f6aa8ee114fb52a425e247e27e271ee35d7d3b3 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 12:12:24 -0600 Subject: ARM: OMAP2+: hwmod: use init-time function pointer for wait_target_ready Rather than using cpu_is* checking at runtime, initialize an SoC specific function pointer for wait_target_ready(). While here, downgrade the BUG() to a WARN_ON() so it gives a noisy warning instead of causing a kernel panic. Signed-off-by: Kevin Hilman [paul@pwsan.com: convert to use soc_ops function pointers; add kerneldoc; move soc_ops functions to their own section in the code; integrated the _wait_target_ready() function with the OMAP2/OMAP4 variants; renamed the wait_module_ready field to wait_target_ready] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 115 ++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 49 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 2b845836f7dc..d1f784cd5f0f 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -178,6 +178,7 @@ struct omap_hwmod_soc_ops { void (*enable_module)(struct omap_hwmod *oh); int (*disable_module)(struct omap_hwmod *oh); + int (*wait_target_ready)(struct omap_hwmod *oh); }; /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ @@ -1361,53 +1362,6 @@ static int _init_clocks(struct omap_hwmod *oh, void *data) return ret; } -/** - * _wait_target_ready - wait for a module to leave slave idle - * @oh: struct omap_hwmod * - * - * Wait for a module @oh to leave slave idle. Returns 0 if the module - * does not have an IDLEST bit or if the module successfully leaves - * slave idle; otherwise, pass along the return value of the - * appropriate *_cm*_wait_module_ready() function. - */ -static int _wait_target_ready(struct omap_hwmod *oh) -{ - struct omap_hwmod_ocp_if *os; - int ret; - - if (!oh) - return -EINVAL; - - if (oh->flags & HWMOD_NO_IDLEST) - return 0; - - os = _find_mpu_rt_port(oh); - if (!os) - return 0; - - /* XXX check module SIDLEMODE */ - - /* XXX check clock enable states */ - - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs, - oh->prcm.omap2.idlest_reg_id, - oh->prcm.omap2.idlest_idle_bit); - } else if (cpu_is_omap44xx()) { - if (!oh->clkdm) - return -EINVAL; - - ret = omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition, - oh->clkdm->cm_inst, - oh->clkdm->clkdm_offs, - oh->prcm.omap4.clkctrl_offs); - } else { - BUG(); - }; - - return ret; -} - /** * _lookup_hardreset - fill register bit info for this hwmod/reset line * @oh: struct omap_hwmod * @@ -1826,7 +1780,8 @@ static int _enable(struct omap_hwmod *oh) if (soc_ops.enable_module) soc_ops.enable_module(oh); - r = _wait_target_ready(oh); + r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) : + -EINVAL; if (!r) { /* * Set the clockdomain to HW_AUTO only if the target is ready, @@ -2443,6 +2398,63 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois) return 0; } +/* Static functions intended only for use in soc_ops field function pointers */ + +/** + * _omap2_wait_target_ready - wait for a module to leave slave idle + * @oh: struct omap_hwmod * + * + * Wait for a module @oh to leave slave idle. Returns 0 if the module + * does not have an IDLEST bit or if the module successfully leaves + * slave idle; otherwise, pass along the return value of the + * appropriate *_cm*_wait_module_ready() function. + */ +static int _omap2_wait_target_ready(struct omap_hwmod *oh) +{ + if (!oh) + return -EINVAL; + + if (oh->flags & HWMOD_NO_IDLEST) + return 0; + + if (!_find_mpu_rt_port(oh)) + return 0; + + /* XXX check module SIDLEMODE, hardreset status, enabled clocks */ + + return omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs, + oh->prcm.omap2.idlest_reg_id, + oh->prcm.omap2.idlest_idle_bit); +} + +/** + * _omap4_wait_target_ready - wait for a module to leave slave idle + * @oh: struct omap_hwmod * + * + * Wait for a module @oh to leave slave idle. Returns 0 if the module + * does not have an IDLEST bit or if the module successfully leaves + * slave idle; otherwise, pass along the return value of the + * appropriate *_cm*_wait_module_ready() function. + */ +static int _omap4_wait_target_ready(struct omap_hwmod *oh) +{ + if (!oh || !oh->clkdm) + return -EINVAL; + + if (oh->flags & HWMOD_NO_IDLEST) + return 0; + + if (!_find_mpu_rt_port(oh)) + return 0; + + /* XXX check module SIDLEMODE, hardreset status */ + + return omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition, + oh->clkdm->cm_inst, + oh->clkdm->clkdm_offs, + oh->prcm.omap4.clkctrl_offs); +} + /* Public functions */ u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs) @@ -3429,9 +3441,14 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx) */ void __init omap_hwmod_init(void) { - if (cpu_is_omap44xx()) { + if (cpu_is_omap24xx() || cpu_is_omap34xx()) { + soc_ops.wait_target_ready = _omap2_wait_target_ready; + } else if (cpu_is_omap44xx()) { soc_ops.enable_module = _omap4_enable_module; soc_ops.disable_module = _omap4_disable_module; + soc_ops.wait_target_ready = _omap4_wait_target_ready; + } else { + WARN(1, "omap_hwmod: unknown SoC type\n"); } inited = true; -- cgit v1.2.3 From b8249cf2d2b16de9582d3cbaa98c16c32c624d8a Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 12:12:24 -0600 Subject: ARM: OMAP2+: hwmod: use init-time function pointer for hardreset Rather than using cpu_is* checking at runtime, initialize SoC specific function pointers for the various hard reset functions at init time. Signed-off-by: Kevin Hilman [paul@pwsan.com: convert to use soc_ops function pointers; add kerneldoc] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 216 ++++++++++++++++++++++++++++++--------- 1 file changed, 169 insertions(+), 47 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index d1f784cd5f0f..93cb96dbb543 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -179,6 +179,12 @@ struct omap_hwmod_soc_ops { void (*enable_module)(struct omap_hwmod *oh); int (*disable_module)(struct omap_hwmod *oh); int (*wait_target_ready)(struct omap_hwmod *oh); + int (*assert_hardreset)(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri); + int (*deassert_hardreset)(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri); + int (*is_hardreset_asserted)(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri); }; /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ @@ -1398,32 +1404,31 @@ static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name, * @oh: struct omap_hwmod * * @name: name of the reset line to lookup and assert * - * Some IP like dsp, ipu or iva contain processor that require - * an HW reset line to be assert / deassert in order to enable fully - * the IP. + * Some IP like dsp, ipu or iva contain processor that require an HW + * reset line to be assert / deassert in order to enable fully the IP. + * Returns -EINVAL if @oh is null, -ENOSYS if we have no way of + * asserting the hardreset line on the currently-booted SoC, or passes + * along the return value from _lookup_hardreset() or the SoC's + * assert_hardreset code. */ static int _assert_hardreset(struct omap_hwmod *oh, const char *name) { struct omap_hwmod_rst_info ohri; - u8 ret; + u8 ret = -EINVAL; if (!oh) return -EINVAL; + if (!soc_ops.assert_hardreset) + return -ENOSYS; + ret = _lookup_hardreset(oh, name, &ohri); if (IS_ERR_VALUE(ret)) return ret; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) - return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs, - ohri.rst_shift); - else if (cpu_is_omap44xx()) - return omap4_prminst_assert_hardreset(ohri.rst_shift, - oh->clkdm->pwrdm.ptr->prcm_partition, - oh->clkdm->pwrdm.ptr->prcm_offs, - oh->prcm.omap4.rstctrl_offs); - else - return -EINVAL; + ret = soc_ops.assert_hardreset(oh, &ohri); + + return ret; } /** @@ -1432,38 +1437,29 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name) * @oh: struct omap_hwmod * * @name: name of the reset line to look up and deassert * - * Some IP like dsp, ipu or iva contain processor that require - * an HW reset line to be assert / deassert in order to enable fully - * the IP. + * Some IP like dsp, ipu or iva contain processor that require an HW + * reset line to be assert / deassert in order to enable fully the IP. + * Returns -EINVAL if @oh is null, -ENOSYS if we have no way of + * deasserting the hardreset line on the currently-booted SoC, or passes + * along the return value from _lookup_hardreset() or the SoC's + * deassert_hardreset code. */ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name) { struct omap_hwmod_rst_info ohri; - int ret; + int ret = -EINVAL; if (!oh) return -EINVAL; + if (!soc_ops.deassert_hardreset) + return -ENOSYS; + ret = _lookup_hardreset(oh, name, &ohri); if (IS_ERR_VALUE(ret)) return ret; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - ret = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs, - ohri.rst_shift, - ohri.st_shift); - } else if (cpu_is_omap44xx()) { - if (ohri.st_shift) - pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n", - oh->name, name); - ret = omap4_prminst_deassert_hardreset(ohri.rst_shift, - oh->clkdm->pwrdm.ptr->prcm_partition, - oh->clkdm->pwrdm.ptr->prcm_offs, - oh->prcm.omap4.rstctrl_offs); - } else { - return -EINVAL; - } - + ret = soc_ops.deassert_hardreset(oh, &ohri); if (ret == -EBUSY) pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name); @@ -1476,31 +1472,28 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name) * @oh: struct omap_hwmod * * @name: name of the reset line to look up and read * - * Return the state of the reset line. + * Return the state of the reset line. Returns -EINVAL if @oh is + * null, -ENOSYS if we have no way of reading the hardreset line + * status on the currently-booted SoC, or passes along the return + * value from _lookup_hardreset() or the SoC's is_hardreset_asserted + * code. */ static int _read_hardreset(struct omap_hwmod *oh, const char *name) { struct omap_hwmod_rst_info ohri; - u8 ret; + u8 ret = -EINVAL; if (!oh) return -EINVAL; + if (!soc_ops.is_hardreset_asserted) + return -ENOSYS; + ret = _lookup_hardreset(oh, name, &ohri); if (IS_ERR_VALUE(ret)) return ret; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs, - ohri.st_shift); - } else if (cpu_is_omap44xx()) { - return omap4_prminst_is_hardreset_asserted(ohri.rst_shift, - oh->clkdm->pwrdm.ptr->prcm_partition, - oh->clkdm->pwrdm.ptr->prcm_offs, - oh->prcm.omap4.rstctrl_offs); - } else { - return -EINVAL; - } + return soc_ops.is_hardreset_asserted(oh, &ohri); } /** @@ -2455,6 +2448,129 @@ static int _omap4_wait_target_ready(struct omap_hwmod *oh) oh->prcm.omap4.clkctrl_offs); } +/** + * _omap2_assert_hardreset - call OMAP2 PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to assert hardreset + * @ohri: hardreset line data + * + * Call omap2_prm_assert_hardreset() with parameters extracted from + * the hwmod @oh and the hardreset line data @ohri. Only intended for + * use as an soc_ops function pointer. Passes along the return value + * from omap2_prm_assert_hardreset(). XXX This function is scheduled + * for removal when the PRM code is moved into drivers/. + */ +static int _omap2_assert_hardreset(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) +{ + return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs, + ohri->rst_shift); +} + +/** + * _omap2_deassert_hardreset - call OMAP2 PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to deassert hardreset + * @ohri: hardreset line data + * + * Call omap2_prm_deassert_hardreset() with parameters extracted from + * the hwmod @oh and the hardreset line data @ohri. Only intended for + * use as an soc_ops function pointer. Passes along the return value + * from omap2_prm_deassert_hardreset(). XXX This function is + * scheduled for removal when the PRM code is moved into drivers/. + */ +static int _omap2_deassert_hardreset(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) +{ + return omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs, + ohri->rst_shift, + ohri->st_shift); +} + +/** + * _omap2_is_hardreset_asserted - call OMAP2 PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to test hardreset + * @ohri: hardreset line data + * + * Call omap2_prm_is_hardreset_asserted() with parameters extracted + * from the hwmod @oh and the hardreset line data @ohri. Only + * intended for use as an soc_ops function pointer. Passes along the + * return value from omap2_prm_is_hardreset_asserted(). XXX This + * function is scheduled for removal when the PRM code is moved into + * drivers/. + */ +static int _omap2_is_hardreset_asserted(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) +{ + return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs, + ohri->st_shift); +} + +/** + * _omap4_assert_hardreset - call OMAP4 PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to assert hardreset + * @ohri: hardreset line data + * + * Call omap4_prminst_assert_hardreset() with parameters extracted + * from the hwmod @oh and the hardreset line data @ohri. Only + * intended for use as an soc_ops function pointer. Passes along the + * return value from omap4_prminst_assert_hardreset(). XXX This + * function is scheduled for removal when the PRM code is moved into + * drivers/. + */ +static int _omap4_assert_hardreset(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) + +{ + return omap4_prminst_assert_hardreset(ohri->rst_shift, + oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.rstctrl_offs); +} + +/** + * _omap4_deassert_hardreset - call OMAP4 PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to deassert hardreset + * @ohri: hardreset line data + * + * Call omap4_prminst_deassert_hardreset() with parameters extracted + * from the hwmod @oh and the hardreset line data @ohri. Only + * intended for use as an soc_ops function pointer. Passes along the + * return value from omap4_prminst_deassert_hardreset(). XXX This + * function is scheduled for removal when the PRM code is moved into + * drivers/. + */ +static int _omap4_deassert_hardreset(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) +{ + if (ohri->st_shift) + pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n", + oh->name, ohri->name); + return omap4_prminst_deassert_hardreset(ohri->rst_shift, + oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.rstctrl_offs); +} + +/** + * _omap4_is_hardreset_asserted - call OMAP4 PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to test hardreset + * @ohri: hardreset line data + * + * Call omap4_prminst_is_hardreset_asserted() with parameters + * extracted from the hwmod @oh and the hardreset line data @ohri. + * Only intended for use as an soc_ops function pointer. Passes along + * the return value from omap4_prminst_is_hardreset_asserted(). XXX + * This function is scheduled for removal when the PRM code is moved + * into drivers/. + */ +static int _omap4_is_hardreset_asserted(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) +{ + return omap4_prminst_is_hardreset_asserted(ohri->rst_shift, + oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.rstctrl_offs); +} + /* Public functions */ u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs) @@ -3443,10 +3559,16 @@ void __init omap_hwmod_init(void) { if (cpu_is_omap24xx() || cpu_is_omap34xx()) { soc_ops.wait_target_ready = _omap2_wait_target_ready; + soc_ops.assert_hardreset = _omap2_assert_hardreset; + soc_ops.deassert_hardreset = _omap2_deassert_hardreset; + soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted; } else if (cpu_is_omap44xx()) { soc_ops.enable_module = _omap4_enable_module; soc_ops.disable_module = _omap4_disable_module; soc_ops.wait_target_ready = _omap4_wait_target_ready; + soc_ops.assert_hardreset = _omap4_assert_hardreset; + soc_ops.deassert_hardreset = _omap4_deassert_hardreset; + soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted; } else { WARN(1, "omap_hwmod: unknown SoC type\n"); } -- cgit v1.2.3 From 0a179eaa436e58ed9fd00e09cdf01f1b3604d9a1 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 12:12:25 -0600 Subject: ARM: OMAP2+: hwmod: use init-time function pointer for _init_clkdm Rather than use runtime cpu_is* checking inside _init_clkdm, initialize SoC specific function pointer at init time. Signed-off-by: Kevin Hilman [paul@pwsan.com: convert to use soc_ops function pointers; remove second para from commit message since soc_ops function pointers are now set during hwmod layer init] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 93cb96dbb543..acc616c02e14 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -185,6 +185,7 @@ struct omap_hwmod_soc_ops { struct omap_hwmod_rst_info *ohri); int (*is_hardreset_asserted)(struct omap_hwmod *oh, struct omap_hwmod_rst_info *ohri); + int (*init_clkdm)(struct omap_hwmod *oh); }; /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ @@ -1315,9 +1316,6 @@ static struct omap_hwmod *_lookup(const char *name) */ static int _init_clkdm(struct omap_hwmod *oh) { - if (cpu_is_omap24xx() || cpu_is_omap34xx()) - return 0; - if (!oh->clkdm_name) { pr_warning("omap_hwmod: %s: no clkdm_name\n", oh->name); return -EINVAL; @@ -1358,7 +1356,8 @@ static int _init_clocks(struct omap_hwmod *oh, void *data) ret |= _init_main_clk(oh); ret |= _init_interface_clks(oh); ret |= _init_opt_clks(oh); - ret |= _init_clkdm(oh); + if (soc_ops.init_clkdm) + ret |= soc_ops.init_clkdm(oh); if (!ret) oh->_state = _HWMOD_STATE_CLKS_INITED; @@ -3569,6 +3568,7 @@ void __init omap_hwmod_init(void) soc_ops.assert_hardreset = _omap4_assert_hardreset; soc_ops.deassert_hardreset = _omap4_deassert_hardreset; soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted; + soc_ops.init_clkdm = _init_clkdm; } else { WARN(1, "omap_hwmod: unknown SoC type\n"); } -- cgit v1.2.3 From d44f42e6af483cbdc239d7f28666e711d2e8ab92 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 16:17:44 -0600 Subject: ARM: OMAP2+: CLEANUP: Remove ARCH_OMAPx ifdef from struct dpll_data There are certain fields inside 'struct dpll_data' which are included under ARCH_OMAP3 and ARCH_OMAP4 option, which makes it difficult to use it for new devices like, am33xx, ti81xx, etc... So remove the ifdef completely, this will add few fields to the struct unused, but it improves readability and maintainability of the code. Signed-off-by: Kevin Hilman [hvaibhav@ti.com: wrote detailed changelog] Signed-off-by: Vaibhav Hiremath Cc: Tony Lindgren Cc: Paul Walmsley Cc: Santosh Shilimkar Cc: R Sricharan Acked-by: Santosh Shilimkar Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/include/plat/clock.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index d0ef57c1d71b..656b9862279e 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h @@ -156,7 +156,6 @@ struct dpll_data { u8 min_divider; u16 max_divider; u8 modes; -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) void __iomem *autoidle_reg; void __iomem *idlest_reg; u32 autoidle_mask; @@ -167,7 +166,6 @@ struct dpll_data { u8 auto_recal_bit; u8 recal_en_bit; u8 recal_st_bit; -# endif u8 flags; }; -- cgit v1.2.3 From 90f1380ef6436a3f5425f942ea0b3f78e1cca142 Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Mon, 18 Jun 2012 16:18:09 -0600 Subject: ARM: OMAP2+: control: new APIs to configure boot address and mode SCM contains boot addr and boot mode registers to control other processors on different OMAP versions. It controls the boot address and mode for DSP based subsystems like: IVA 2.1 (OMAP2430), IVA 2.2 (OMAP3) and DSP (OMAP4). If contained within SCM registers, when a processor is booting it uses BOOTADDR to start running the code at that location. BOOTMOD register specifies a different set of modes for the processor to execute when booting (from direct, idle, self-loop, user and default). Since there was no offset associated with OMAP4, this patch defines it. Signed-off-by: Omar Ramirez Luna Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/control.c | 43 ++++++++++++++++++++++ arch/arm/mach-omap2/control.h | 2 + .../include/mach/ctrl_module_core_44xx.h | 1 + 3 files changed, 46 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index 08e674bb0417..3223b81e7532 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -241,6 +241,49 @@ void omap3_ctrl_write_boot_mode(u8 bootmode) #endif +/** + * omap_ctrl_write_dsp_boot_addr - set boot address for a remote processor + * @bootaddr: physical address of the boot loader + * + * Set boot address for the boot loader of a supported processor + * when a power ON sequence occurs. + */ +void omap_ctrl_write_dsp_boot_addr(u32 bootaddr) +{ + u32 offset = cpu_is_omap243x() ? OMAP243X_CONTROL_IVA2_BOOTADDR : + cpu_is_omap34xx() ? OMAP343X_CONTROL_IVA2_BOOTADDR : + cpu_is_omap44xx() ? OMAP4_CTRL_MODULE_CORE_DSP_BOOTADDR : + 0; + + if (!offset) { + pr_err("%s: unsupported omap type\n", __func__); + return; + } + + omap_ctrl_writel(bootaddr, offset); +} + +/** + * omap_ctrl_write_dsp_boot_mode - set boot mode for a remote processor + * @bootmode: 8-bit value to pass to some boot code + * + * Sets boot mode for the boot loader of a supported processor + * when a power ON sequence occurs. + */ +void omap_ctrl_write_dsp_boot_mode(u8 bootmode) +{ + u32 offset = cpu_is_omap243x() ? OMAP243X_CONTROL_IVA2_BOOTMOD : + cpu_is_omap34xx() ? OMAP343X_CONTROL_IVA2_BOOTMOD : + 0; + + if (!offset) { + pr_err("%s: unsupported omap type\n", __func__); + return; + } + + omap_ctrl_writel(bootmode, offset); +} + #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) /* * Clears the scratchpad contents in case of cold boot- diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h index a406fd045ce1..fcc98f822d9d 100644 --- a/arch/arm/mach-omap2/control.h +++ b/arch/arm/mach-omap2/control.h @@ -397,6 +397,8 @@ extern u32 omap3_arm_context[128]; extern void omap3_control_save_context(void); extern void omap3_control_restore_context(void); extern void omap3_ctrl_write_boot_mode(u8 bootmode); +extern void omap_ctrl_write_dsp_boot_addr(u32 bootaddr); +extern void omap_ctrl_write_dsp_boot_mode(u8 bootmode); extern void omap3630_ctrl_disable_rta(void); extern int omap3_ctrl_save_padconf(void); #else diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h index 2f7ac70a20d8..01970824e0e5 100644 --- a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h +++ b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h @@ -42,6 +42,7 @@ #define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_1 0x0268 #define OMAP4_CTRL_MODULE_CORE_STATUS 0x02c4 #define OMAP4_CTRL_MODULE_CORE_DEV_CONF 0x0300 +#define OMAP4_CTRL_MODULE_CORE_DSP_BOOTADDR 0x0304 #define OMAP4_CTRL_MODULE_CORE_LDOVBB_IVA_VOLTAGE_CTRL 0x0314 #define OMAP4_CTRL_MODULE_CORE_LDOVBB_MPU_VOLTAGE_CTRL 0x0318 #define OMAP4_CTRL_MODULE_CORE_LDOSRAM_IVA_VOLTAGE_CTRL 0x0320 -- cgit v1.2.3 From 3d3635c4d77a97c61a539dff86f9a4b67134b4cb Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Mon, 18 Jun 2012 16:18:10 -0600 Subject: ARM: OMAP: dsp: interface to control module functions Provide an interface for a driver to call SCM functions to set a boot address and boot mode. Signed-off-by: Omar Ramirez Luna Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/dsp.c | 4 ++++ arch/arm/plat-omap/include/plat/dsp.h | 3 +++ 2 files changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/dsp.c b/arch/arm/mach-omap2/dsp.c index 845309f146fe..8b251a995abf 100644 --- a/arch/arm/mach-omap2/dsp.c +++ b/arch/arm/mach-omap2/dsp.c @@ -20,6 +20,7 @@ #include #include +#include "control.h" #include "cm2xxx_3xxx.h" #include "prm2xxx_3xxx.h" #ifdef CONFIG_BRIDGE_DVFS @@ -43,6 +44,9 @@ static struct omap_dsp_platform_data omap_dsp_pdata __initdata = { .dsp_cm_read = omap2_cm_read_mod_reg, .dsp_cm_write = omap2_cm_write_mod_reg, .dsp_cm_rmw_bits = omap2_cm_rmw_mod_reg_bits, + + .set_bootaddr = omap_ctrl_write_dsp_boot_addr, + .set_bootmode = omap_ctrl_write_dsp_boot_mode, }; static phys_addr_t omap_dsp_phys_mempool_base; diff --git a/arch/arm/plat-omap/include/plat/dsp.h b/arch/arm/plat-omap/include/plat/dsp.h index 9c604b390f9f..5927709b1908 100644 --- a/arch/arm/plat-omap/include/plat/dsp.h +++ b/arch/arm/plat-omap/include/plat/dsp.h @@ -18,6 +18,9 @@ struct omap_dsp_platform_data { u32 (*dsp_cm_read)(s16 , u16); u32 (*dsp_cm_rmw_bits)(u32, u32, s16, s16); + void (*set_bootaddr)(u32); + void (*set_bootmode)(u8); + phys_addr_t phys_mempool_base; phys_addr_t phys_mempool_size; }; -- cgit v1.2.3 From b3153100a0b1624dd82d67e956f9229a6a2dbc1b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 18 Jun 2012 16:18:42 -0600 Subject: ARM: OMAP2: Move McBSP fck clock alias to hwmod data for OMAP2420 Remove the existing alias for pad_fck, prcm_fck from the clock data and add them as opt_clks to the hwmod data. Signed-off-by: Peter Ujfalusi Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock2420_data.c | 4 ---- arch/arm/mach-omap2/omap_hwmod_2420_data.c | 9 +++++++++ 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index bace9308a4db..7e39015357b1 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -1774,8 +1774,6 @@ static struct omap_clk omap2420_clks[] = { CLK(NULL, "osc_ck", &osc_ck, CK_242X), CLK(NULL, "sys_ck", &sys_ck, CK_242X), CLK(NULL, "alt_ck", &alt_ck, CK_242X), - CLK("omap-mcbsp.1", "pad_fck", &mcbsp_clks, CK_242X), - CLK("omap-mcbsp.2", "pad_fck", &mcbsp_clks, CK_242X), CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_242X), /* internal analog sources */ CLK(NULL, "dpll_ck", &dpll_ck, CK_242X), @@ -1784,8 +1782,6 @@ static struct omap_clk omap2420_clks[] = { /* internal prcm root sources */ CLK(NULL, "func_54m_ck", &func_54m_ck, CK_242X), CLK(NULL, "core_ck", &core_ck, CK_242X), - CLK("omap-mcbsp.1", "prcm_fck", &func_96m_ck, CK_242X), - CLK("omap-mcbsp.2", "prcm_fck", &func_96m_ck, CK_242X), CLK(NULL, "func_96m_ck", &func_96m_ck, CK_242X), CLK(NULL, "func_48m_ck", &func_48m_ck, CK_242X), CLK(NULL, "func_12m_ck", &func_12m_ck, CK_242X), diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index a7640d1b215e..910d256f3abe 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -192,6 +192,11 @@ static struct omap_hwmod_class omap2420_mcbsp_hwmod_class = { .name = "mcbsp", }; +static struct omap_hwmod_opt_clk mcbsp_opt_clks[] = { + { .role = "pad_fck", .clk = "mcbsp_clks" }, + { .role = "prcm_fck", .clk = "func_96m_ck" }, +}; + /* mcbsp1 */ static struct omap_hwmod_irq_info omap2420_mcbsp1_irqs[] = { { .name = "tx", .irq = 59 }, @@ -214,6 +219,8 @@ static struct omap_hwmod omap2420_mcbsp1_hwmod = { .idlest_idle_bit = OMAP24XX_ST_MCBSP1_SHIFT, }, }, + .opt_clks = mcbsp_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp_opt_clks), }; /* mcbsp2 */ @@ -238,6 +245,8 @@ static struct omap_hwmod omap2420_mcbsp2_hwmod = { .idlest_idle_bit = OMAP24XX_ST_MCBSP2_SHIFT, }, }, + .opt_clks = mcbsp_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp_opt_clks), }; static struct omap_hwmod_class_sysconfig omap2420_msdi_sysc = { -- cgit v1.2.3 From db382a869dfbc6f6ea298c9d8607404016cacbc0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 18 Jun 2012 16:18:43 -0600 Subject: ARM: OMAP2: Move McBSP fck clock alias to hwmod data for OMAP2430 Remove the existing alias for pad_fck, prcm_fck from the clock data and add them as opt_clks to the hwmod data. Signed-off-by: Peter Ujfalusi Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock2430_data.c | 10 ---------- arch/arm/mach-omap2/omap_hwmod_2430_data.c | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 3b4d09a50399..90a08c3b12ac 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -1858,11 +1858,6 @@ static struct omap_clk omap2430_clks[] = { CLK(NULL, "osc_ck", &osc_ck, CK_243X), CLK(NULL, "sys_ck", &sys_ck, CK_243X), CLK(NULL, "alt_ck", &alt_ck, CK_243X), - CLK("omap-mcbsp.1", "pad_fck", &mcbsp_clks, CK_243X), - CLK("omap-mcbsp.2", "pad_fck", &mcbsp_clks, CK_243X), - CLK("omap-mcbsp.3", "pad_fck", &mcbsp_clks, CK_243X), - CLK("omap-mcbsp.4", "pad_fck", &mcbsp_clks, CK_243X), - CLK("omap-mcbsp.5", "pad_fck", &mcbsp_clks, CK_243X), CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_243X), /* internal analog sources */ CLK(NULL, "dpll_ck", &dpll_ck, CK_243X), @@ -1871,11 +1866,6 @@ static struct omap_clk omap2430_clks[] = { /* internal prcm root sources */ CLK(NULL, "func_54m_ck", &func_54m_ck, CK_243X), CLK(NULL, "core_ck", &core_ck, CK_243X), - CLK("omap-mcbsp.1", "prcm_fck", &func_96m_ck, CK_243X), - CLK("omap-mcbsp.2", "prcm_fck", &func_96m_ck, CK_243X), - CLK("omap-mcbsp.3", "prcm_fck", &func_96m_ck, CK_243X), - CLK("omap-mcbsp.4", "prcm_fck", &func_96m_ck, CK_243X), - CLK("omap-mcbsp.5", "prcm_fck", &func_96m_ck, CK_243X), CLK(NULL, "func_96m_ck", &func_96m_ck, CK_243X), CLK(NULL, "func_48m_ck", &func_48m_ck, CK_243X), CLK(NULL, "func_12m_ck", &func_12m_ck, CK_243X), diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 4d7264981230..f105314bdb63 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -296,6 +296,11 @@ static struct omap_hwmod_class omap2430_mcbsp_hwmod_class = { .rev = MCBSP_CONFIG_TYPE2, }; +static struct omap_hwmod_opt_clk mcbsp_opt_clks[] = { + { .role = "pad_fck", .clk = "mcbsp_clks" }, + { .role = "prcm_fck", .clk = "func_96m_ck" }, +}; + /* mcbsp1 */ static struct omap_hwmod_irq_info omap2430_mcbsp1_irqs[] = { { .name = "tx", .irq = 59 }, @@ -320,6 +325,8 @@ static struct omap_hwmod omap2430_mcbsp1_hwmod = { .idlest_idle_bit = OMAP24XX_ST_MCBSP1_SHIFT, }, }, + .opt_clks = mcbsp_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp_opt_clks), }; /* mcbsp2 */ @@ -345,6 +352,8 @@ static struct omap_hwmod omap2430_mcbsp2_hwmod = { .idlest_idle_bit = OMAP24XX_ST_MCBSP2_SHIFT, }, }, + .opt_clks = mcbsp_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp_opt_clks), }; /* mcbsp3 */ @@ -370,6 +379,8 @@ static struct omap_hwmod omap2430_mcbsp3_hwmod = { .idlest_idle_bit = OMAP2430_ST_MCBSP3_SHIFT, }, }, + .opt_clks = mcbsp_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp_opt_clks), }; /* mcbsp4 */ @@ -401,6 +412,8 @@ static struct omap_hwmod omap2430_mcbsp4_hwmod = { .idlest_idle_bit = OMAP2430_ST_MCBSP4_SHIFT, }, }, + .opt_clks = mcbsp_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp_opt_clks), }; /* mcbsp5 */ @@ -432,6 +445,8 @@ static struct omap_hwmod omap2430_mcbsp5_hwmod = { .idlest_idle_bit = OMAP2430_ST_MCBSP5_SHIFT, }, }, + .opt_clks = mcbsp_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp_opt_clks), }; /* MMC/SD/SDIO common */ -- cgit v1.2.3 From 7039154bb218e06cc876a008cdf57f3fbc00c25e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 18 Jun 2012 16:18:43 -0600 Subject: ARM: OMAP3: Move McBSP fck clock alias to hwmod data Remove the existing alias for pad_fck, prcm_fck from the clock data and add them as opt_clks to the hwmod data. Signed-off-by: Peter Ujfalusi Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock3xxx_data.c | 10 ---------- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 4e1a3b0e8cc8..d6889b58dd05 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3236,11 +3236,6 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "osc_sys_ck", &osc_sys_ck, CK_3XXX), CLK(NULL, "sys_ck", &sys_ck, CK_3XXX), CLK(NULL, "sys_altclk", &sys_altclk, CK_3XXX), - CLK("omap-mcbsp.1", "pad_fck", &mcbsp_clks, CK_3XXX), - CLK("omap-mcbsp.2", "pad_fck", &mcbsp_clks, CK_3XXX), - CLK("omap-mcbsp.3", "pad_fck", &mcbsp_clks, CK_3XXX), - CLK("omap-mcbsp.4", "pad_fck", &mcbsp_clks, CK_3XXX), - CLK("omap-mcbsp.5", "pad_fck", &mcbsp_clks, CK_3XXX), CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_3XXX), CLK(NULL, "sys_clkout1", &sys_clkout1, CK_3XXX), CLK(NULL, "dpll1_ck", &dpll1_ck, CK_3XXX), @@ -3307,8 +3302,6 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK("usbhs_omap", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("omap-mcbsp.1", "prcm_fck", &core_96m_fck, CK_3XXX), - CLK("omap-mcbsp.5", "prcm_fck", &core_96m_fck, CK_3XXX), CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX), CLK(NULL, "mmchs3_fck", &mmchs3_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "mmchs2_fck", &mmchs2_fck, CK_3XXX), @@ -3413,9 +3406,6 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "omap_32ksync_ick", &omap_32ksync_ick, CK_3XXX), CLK(NULL, "gpt12_ick", &gpt12_ick, CK_3XXX), CLK(NULL, "gpt1_ick", &gpt1_ick, CK_3XXX), - CLK("omap-mcbsp.2", "prcm_fck", &per_96m_fck, CK_3XXX), - CLK("omap-mcbsp.3", "prcm_fck", &per_96m_fck, CK_3XXX), - CLK("omap-mcbsp.4", "prcm_fck", &per_96m_fck, CK_3XXX), CLK(NULL, "per_96m_fck", &per_96m_fck, CK_3XXX), CLK(NULL, "per_48m_fck", &per_48m_fck, CK_3XXX), CLK(NULL, "uart3_fck", &uart3_fck, CK_3XXX), diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index b26d3c9bca16..7ac051145219 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1074,6 +1074,17 @@ static struct omap_hwmod_class omap3xxx_mcbsp_hwmod_class = { .rev = MCBSP_CONFIG_TYPE3, }; +/* McBSP functional clock mapping */ +static struct omap_hwmod_opt_clk mcbsp15_opt_clks[] = { + { .role = "pad_fck", .clk = "mcbsp_clks" }, + { .role = "prcm_fck", .clk = "core_96m_fck" }, +}; + +static struct omap_hwmod_opt_clk mcbsp234_opt_clks[] = { + { .role = "pad_fck", .clk = "mcbsp_clks" }, + { .role = "prcm_fck", .clk = "per_96m_fck" }, +}; + /* mcbsp1 */ static struct omap_hwmod_irq_info omap3xxx_mcbsp1_irqs[] = { { .name = "common", .irq = 16 }, @@ -1097,6 +1108,8 @@ static struct omap_hwmod omap3xxx_mcbsp1_hwmod = { .idlest_idle_bit = OMAP3430_ST_MCBSP1_SHIFT, }, }, + .opt_clks = mcbsp15_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp15_opt_clks), }; /* mcbsp2 */ @@ -1126,6 +1139,8 @@ static struct omap_hwmod omap3xxx_mcbsp2_hwmod = { .idlest_idle_bit = OMAP3430_ST_MCBSP2_SHIFT, }, }, + .opt_clks = mcbsp234_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp234_opt_clks), .dev_attr = &omap34xx_mcbsp2_dev_attr, }; @@ -1156,6 +1171,8 @@ static struct omap_hwmod omap3xxx_mcbsp3_hwmod = { .idlest_idle_bit = OMAP3430_ST_MCBSP3_SHIFT, }, }, + .opt_clks = mcbsp234_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp234_opt_clks), .dev_attr = &omap34xx_mcbsp3_dev_attr, }; @@ -1188,6 +1205,8 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod = { .idlest_idle_bit = OMAP3430_ST_MCBSP4_SHIFT, }, }, + .opt_clks = mcbsp234_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp234_opt_clks), }; /* mcbsp5 */ @@ -1219,6 +1238,8 @@ static struct omap_hwmod omap3xxx_mcbsp5_hwmod = { .idlest_idle_bit = OMAP3430_ST_MCBSP5_SHIFT, }, }, + .opt_clks = mcbsp15_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp15_opt_clks), }; /* 'mcbsp sidetone' class */ -- cgit v1.2.3 From 6355f25ed965421725d92cf719fc63008690ca1c Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 18 Jun 2012 15:01:50 -0600 Subject: ARM: tegra: make tegra_cpu_reset_handler_enable() __init This solves a section mismatch warning. I hadn't noticed this before, because my compiler was inlining tegra_cpu_reset_handler_enable() inside tegra_cpu_reset_handler_init(), which is already __init, but I switched compilers and it stopped doing that. Cc: # v3.4 Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/reset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c index 4d6a2ee99c3b..5beb7ebe2948 100644 --- a/arch/arm/mach-tegra/reset.c +++ b/arch/arm/mach-tegra/reset.c @@ -33,7 +33,7 @@ static bool is_enabled; -static void tegra_cpu_reset_handler_enable(void) +static void __init tegra_cpu_reset_handler_enable(void) { void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE); void __iomem *evp_cpu_reset = -- cgit v1.2.3 From 081f323bd3cc3a4d5ee6276e53cc52eddfc20a63 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 1 Jun 2012 20:20:24 +1000 Subject: KVM: PPC: Book3S HV: Drop locks around call to kvmppc_pin_guest_page At the moment we call kvmppc_pin_guest_page() in kvmppc_update_vpa() with two spinlocks held: the vcore lock and the vcpu->vpa_update_lock. This is not good, since kvmppc_pin_guest_page() calls down_read() and get_user_pages_fast(), both of which can sleep. This bug was introduced in 2e25aa5f ("KVM: PPC: Book3S HV: Make virtual processor area registration more robust"). This arranges to drop those spinlocks before calling kvmppc_pin_guest_page() and re-take them afterwards. Dropping the vcore lock in kvmppc_run_core() means we have to set the vcore_state field to VCORE_RUNNING before we drop the lock, so that other vcpus won't try to run this vcore. Signed-off-by: Paul Mackerras Acked-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/powerpc/kvm/book3s_hv.c | 96 ++++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 30 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index c6af1d623839..3abe1b86e583 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -268,24 +268,45 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu, return err; } -static void kvmppc_update_vpa(struct kvm *kvm, struct kvmppc_vpa *vpap) +static void kvmppc_update_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *vpap) { + struct kvm *kvm = vcpu->kvm; void *va; unsigned long nb; + unsigned long gpa; - vpap->update_pending = 0; - va = NULL; - if (vpap->next_gpa) { - va = kvmppc_pin_guest_page(kvm, vpap->next_gpa, &nb); - if (nb < vpap->len) { - /* - * If it's now too short, it must be that userspace - * has changed the mappings underlying guest memory, - * so unregister the region. - */ + /* + * We need to pin the page pointed to by vpap->next_gpa, + * but we can't call kvmppc_pin_guest_page under the lock + * as it does get_user_pages() and down_read(). So we + * have to drop the lock, pin the page, then get the lock + * again and check that a new area didn't get registered + * in the meantime. + */ + for (;;) { + gpa = vpap->next_gpa; + spin_unlock(&vcpu->arch.vpa_update_lock); + va = NULL; + nb = 0; + if (gpa) + va = kvmppc_pin_guest_page(kvm, vpap->next_gpa, &nb); + spin_lock(&vcpu->arch.vpa_update_lock); + if (gpa == vpap->next_gpa) + break; + /* sigh... unpin that one and try again */ + if (va) kvmppc_unpin_guest_page(kvm, va); - va = NULL; - } + } + + vpap->update_pending = 0; + if (va && nb < vpap->len) { + /* + * If it's now too short, it must be that userspace + * has changed the mappings underlying guest memory, + * so unregister the region. + */ + kvmppc_unpin_guest_page(kvm, va); + va = NULL; } if (vpap->pinned_addr) kvmppc_unpin_guest_page(kvm, vpap->pinned_addr); @@ -296,20 +317,18 @@ static void kvmppc_update_vpa(struct kvm *kvm, struct kvmppc_vpa *vpap) static void kvmppc_update_vpas(struct kvm_vcpu *vcpu) { - struct kvm *kvm = vcpu->kvm; - spin_lock(&vcpu->arch.vpa_update_lock); if (vcpu->arch.vpa.update_pending) { - kvmppc_update_vpa(kvm, &vcpu->arch.vpa); + kvmppc_update_vpa(vcpu, &vcpu->arch.vpa); init_vpa(vcpu, vcpu->arch.vpa.pinned_addr); } if (vcpu->arch.dtl.update_pending) { - kvmppc_update_vpa(kvm, &vcpu->arch.dtl); + kvmppc_update_vpa(vcpu, &vcpu->arch.dtl); vcpu->arch.dtl_ptr = vcpu->arch.dtl.pinned_addr; vcpu->arch.dtl_index = 0; } if (vcpu->arch.slb_shadow.update_pending) - kvmppc_update_vpa(kvm, &vcpu->arch.slb_shadow); + kvmppc_update_vpa(vcpu, &vcpu->arch.slb_shadow); spin_unlock(&vcpu->arch.vpa_update_lock); } @@ -800,12 +819,39 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc) struct kvm_vcpu *vcpu, *vcpu0, *vnext; long ret; u64 now; - int ptid, i; + int ptid, i, need_vpa_update; /* don't start if any threads have a signal pending */ - list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) + need_vpa_update = 0; + list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) { if (signal_pending(vcpu->arch.run_task)) return 0; + need_vpa_update |= vcpu->arch.vpa.update_pending | + vcpu->arch.slb_shadow.update_pending | + vcpu->arch.dtl.update_pending; + } + + /* + * Initialize *vc, in particular vc->vcore_state, so we can + * drop the vcore lock if necessary. + */ + vc->n_woken = 0; + vc->nap_count = 0; + vc->entry_exit_count = 0; + vc->vcore_state = VCORE_RUNNING; + vc->in_guest = 0; + vc->napping_threads = 0; + + /* + * Updating any of the vpas requires calling kvmppc_pin_guest_page, + * which can't be called with any spinlocks held. + */ + if (need_vpa_update) { + spin_unlock(&vc->lock); + list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) + kvmppc_update_vpas(vcpu); + spin_lock(&vc->lock); + } /* * Make sure we are running on thread 0, and that @@ -838,20 +884,10 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc) if (vcpu->arch.ceded) vcpu->arch.ptid = ptid++; - vc->n_woken = 0; - vc->nap_count = 0; - vc->entry_exit_count = 0; - vc->vcore_state = VCORE_RUNNING; vc->stolen_tb += mftb() - vc->preempt_tb; - vc->in_guest = 0; vc->pcpu = smp_processor_id(); - vc->napping_threads = 0; list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) { kvmppc_start_thread(vcpu); - if (vcpu->arch.vpa.update_pending || - vcpu->arch.slb_shadow.update_pending || - vcpu->arch.dtl.update_pending) - kvmppc_update_vpas(vcpu); kvmppc_create_dtl_entry(vcpu, vc); } /* Grab any remaining hw threads so they can't go into the kernel */ -- cgit v1.2.3 From 9e40b67bf2bfaa40b28354c501a72fd001a1397a Mon Sep 17 00:00:00 2001 From: Takuya Yoshikawa Date: Tue, 19 Jun 2012 22:04:56 +0900 Subject: KVM: Use kvm_kvfree() to free memory allocated by kvm_kvzalloc() The following commit did not care about the error handling path: commit c1a7b32a14138f908df52d7c53b5ce3415ec6b50 KVM: Avoid wasting pages for small lpage_info arrays If memory allocation fails, vfree() will be called with the address returned by kzalloc(). This patch fixes this issue. Signed-off-by: Takuya Yoshikawa Signed-off-by: Avi Kivity --- arch/x86/kvm/x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index a01a4241bc6b..6ed5983f78ff 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6350,7 +6350,7 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages) out_free: for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) { - vfree(slot->arch.lpage_info[i]); + kvm_kvfree(slot->arch.lpage_info[i]); slot->arch.lpage_info[i] = NULL; } return -ENOMEM; -- cgit v1.2.3 From 868c157df9721675c19729eed2c96bac6c3f1d01 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 19 Jun 2012 15:01:02 -0600 Subject: ARM: OMAP2+: hwmod: remove prm_clkdm, cm_clkdm; allow hwmods to have no clockdomain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove prm_clkdm and cm_clkdm and allow hwmods to have no clockdomain. Signed-off-by: Paul Walmsley Cc: Benoît Cousson --- arch/arm/mach-omap2/Makefile | 1 - arch/arm/mach-omap2/clockdomain.h | 2 -- arch/arm/mach-omap2/clockdomains2420_data.c | 2 -- arch/arm/mach-omap2/clockdomains2430_data.c | 2 -- arch/arm/mach-omap2/clockdomains3xxx_data.c | 2 -- arch/arm/mach-omap2/clockdomains44xx_data.c | 2 -- arch/arm/mach-omap2/clockdomains_common_data.c | 24 ---------------------- arch/arm/mach-omap2/omap_hwmod.c | 28 +++++++++++++++++--------- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 3 --- 9 files changed, 19 insertions(+), 47 deletions(-) delete mode 100644 arch/arm/mach-omap2/clockdomains_common_data.c (limited to 'arch') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index fa742f3c2629..bc7d2393161f 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -116,7 +116,6 @@ obj-$(CONFIG_ARCH_OMAP4) += powerdomains44xx_data.o # PRCM clockdomain control clockdomain-common += clockdomain.o -clockdomain-common += clockdomains_common_data.o obj-$(CONFIG_ARCH_OMAP2) += $(clockdomain-common) obj-$(CONFIG_ARCH_OMAP2) += clockdomain2xxx_3xxx.o obj-$(CONFIG_ARCH_OMAP2) += clockdomains2xxx_3xxx_data.o diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index f7b58609bad8..349dcbb6fecb 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -206,7 +206,5 @@ extern struct clkdm_ops omap4_clkdm_operations; extern struct clkdm_dep gfx_24xx_wkdeps[]; extern struct clkdm_dep dsp_24xx_wkdeps[]; extern struct clockdomain wkup_common_clkdm; -extern struct clockdomain prm_common_clkdm; -extern struct clockdomain cm_common_clkdm; #endif diff --git a/arch/arm/mach-omap2/clockdomains2420_data.c b/arch/arm/mach-omap2/clockdomains2420_data.c index 0ab8e46d5b2b..5c741852fac0 100644 --- a/arch/arm/mach-omap2/clockdomains2420_data.c +++ b/arch/arm/mach-omap2/clockdomains2420_data.c @@ -131,8 +131,6 @@ static struct clockdomain dss_2420_clkdm = { static struct clockdomain *clockdomains_omap242x[] __initdata = { &wkup_common_clkdm, - &cm_common_clkdm, - &prm_common_clkdm, &mpu_2420_clkdm, &iva1_2420_clkdm, &dsp_2420_clkdm, diff --git a/arch/arm/mach-omap2/clockdomains2430_data.c b/arch/arm/mach-omap2/clockdomains2430_data.c index 3645ed044890..f09617555e15 100644 --- a/arch/arm/mach-omap2/clockdomains2430_data.c +++ b/arch/arm/mach-omap2/clockdomains2430_data.c @@ -157,8 +157,6 @@ static struct clockdomain dss_2430_clkdm = { static struct clockdomain *clockdomains_omap243x[] __initdata = { &wkup_common_clkdm, - &cm_common_clkdm, - &prm_common_clkdm, &mpu_2430_clkdm, &mdm_clkdm, &dsp_2430_clkdm, diff --git a/arch/arm/mach-omap2/clockdomains3xxx_data.c b/arch/arm/mach-omap2/clockdomains3xxx_data.c index 6038adb97710..2cdc17c9d2fa 100644 --- a/arch/arm/mach-omap2/clockdomains3xxx_data.c +++ b/arch/arm/mach-omap2/clockdomains3xxx_data.c @@ -347,8 +347,6 @@ static struct clkdm_autodep clkdm_autodeps[] = { static struct clockdomain *clockdomains_omap3430_common[] __initdata = { &wkup_common_clkdm, - &cm_common_clkdm, - &prm_common_clkdm, &mpu_3xxx_clkdm, &neon_clkdm, &iva2_clkdm, diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index c53425847493..bd7ed13515cc 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -430,8 +430,6 @@ static struct clockdomain *clockdomains_omap44xx[] __initdata = { &l4_wkup_44xx_clkdm, &emu_sys_44xx_clkdm, &l3_dma_44xx_clkdm, - &prm_common_clkdm, - &cm_common_clkdm, NULL }; diff --git a/arch/arm/mach-omap2/clockdomains_common_data.c b/arch/arm/mach-omap2/clockdomains_common_data.c deleted file mode 100644 index 615b1f04967d..000000000000 --- a/arch/arm/mach-omap2/clockdomains_common_data.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * OMAP2+-common clockdomain data - * - * Copyright (C) 2008-2012 Texas Instruments, Inc. - * Copyright (C) 2008-2010 Nokia Corporation - * - * Paul Walmsley, Jouni Högander - */ - -#include -#include - -#include "clockdomain.h" - -/* These are implicit clockdomains - they are never defined as such in TRM */ -struct clockdomain prm_common_clkdm = { - .name = "prm_clkdm", - .pwrdm = { .name = "wkup_pwrdm" }, -}; - -struct clockdomain cm_common_clkdm = { - .name = "cm_clkdm", - .pwrdm = { .name = "core_pwrdm" }, -}; diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index bf86f7e8f91f..32a5e08ffb9b 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -810,7 +810,7 @@ static int _omap4_wait_target_disable(struct omap_hwmod *oh) if (!cpu_is_omap44xx()) return 0; - if (!oh) + if (!oh || !oh->clkdm) return -EINVAL; if (oh->_int_flags & _HWMOD_NO_MPU_PORT) @@ -1285,23 +1285,22 @@ static struct omap_hwmod *_lookup(const char *name) return oh; } + /** * _init_clkdm - look up a clockdomain name, store pointer in omap_hwmod * @oh: struct omap_hwmod * * * Convert a clockdomain name stored in a struct omap_hwmod into a * clockdomain pointer, and save it into the struct omap_hwmod. - * return -EINVAL if clkdm_name does not exist or if the lookup failed. + * Return -EINVAL if the clkdm_name lookup failed. */ static int _init_clkdm(struct omap_hwmod *oh) { if (cpu_is_omap24xx() || cpu_is_omap34xx()) return 0; - if (!oh->clkdm_name) { - pr_warning("omap_hwmod: %s: no clkdm_name\n", oh->name); - return -EINVAL; - } + if (!oh->clkdm_name) + return 0; oh->clkdm = clkdm_lookup(oh->clkdm_name); if (!oh->clkdm) { @@ -1447,16 +1446,20 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name) if (IS_ERR_VALUE(ret)) return ret; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) + if (cpu_is_omap24xx() || cpu_is_omap34xx()) { return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs, ohri.rst_shift); - else if (cpu_is_omap44xx()) + } else if (cpu_is_omap44xx()) { + if (!oh->clkdm) + return -EINVAL; + return omap4_prminst_assert_hardreset(ohri.rst_shift, oh->clkdm->pwrdm.ptr->prcm_partition, oh->clkdm->pwrdm.ptr->prcm_offs, oh->prcm.omap4.rstctrl_offs); - else + } else { return -EINVAL; + } } /** @@ -1489,6 +1492,10 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name) if (ohri.st_shift) pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n", oh->name, name); + + if (!oh->clkdm) + return -EINVAL; + ret = omap4_prminst_deassert_hardreset(ohri.rst_shift, oh->clkdm->pwrdm.ptr->prcm_partition, oh->clkdm->pwrdm.ptr->prcm_offs, @@ -1527,6 +1534,9 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name) return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs, ohri.st_shift); } else if (cpu_is_omap44xx()) { + if (!oh->clkdm) + return -EINVAL; + return omap4_prminst_is_hardreset_asserted(ohri.rst_shift, oh->clkdm->pwrdm.ptr->prcm_partition, oh->clkdm->pwrdm.ptr->prcm_offs, diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 950454a3fa31..e9e9ec0df64a 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -2540,14 +2540,12 @@ static struct omap_hwmod omap44xx_prcm_mpu_hwmod = { static struct omap_hwmod omap44xx_cm_core_aon_hwmod = { .name = "cm_core_aon", .class = &omap44xx_prcm_hwmod_class, - .clkdm_name = "cm_clkdm", }; /* cm_core */ static struct omap_hwmod omap44xx_cm_core_hwmod = { .name = "cm_core", .class = &omap44xx_prcm_hwmod_class, - .clkdm_name = "cm_clkdm", }; /* prm */ @@ -2564,7 +2562,6 @@ static struct omap_hwmod_rst_info omap44xx_prm_resets[] = { static struct omap_hwmod omap44xx_prm_hwmod = { .name = "prm", .class = &omap44xx_prcm_hwmod_class, - .clkdm_name = "prm_clkdm", .mpu_irqs = omap44xx_prm_irqs, .rst_lines = omap44xx_prm_resets, .rst_lines_cnt = ARRAY_SIZE(omap44xx_prm_resets), -- cgit v1.2.3 From a819c4f16d5a2708c11e708fd59a96565c5384a8 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 19 Apr 2012 11:17:45 -0700 Subject: ARM: OMAP3: PM: Only access IVA if one exists prcm_setup_regs() blindly accesses IVA bits in the PRM and calls omap3_iva_idle() which does more IVA related register accesses. Only do this if the IVA hardware actually exists. Signed-off-by: Mark A. Greer Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/pm34xx.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index a34023d0ca7c..7eb8c5e4183e 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -581,10 +581,13 @@ static void __init prcm_setup_regs(void) OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL); /* Don't attach IVA interrupts */ - omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL); - omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1); - omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3); - omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL); + if (omap3_has_iva()) { + omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL); + omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1); + omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3); + omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD, + OMAP3430_PM_IVAGRPSEL); + } /* Clear any pending 'reset' flags */ omap2_prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST); @@ -598,7 +601,9 @@ static void __init prcm_setup_regs(void) /* Clear any pending PRCM interrupts */ omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); - omap3_iva_idle(); + if (omap3_has_iva()) + omap3_iva_idle(); + omap3_d2d_idle(); } -- cgit v1.2.3 From 164e0cbf608214bddc4d28e2777f49e7b3a0f65c Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 10 May 2012 12:02:57 +0200 Subject: ARM: OMAP3/4: consolidate cpuidle Makefile The current Makefile compiles the cpuidle34xx.c and cpuidle44xx.c files even if the cpuidle option is not set in the kernel. This patch fixes this by creating a section in the Makefile where these files are compiled only if the CONFIG_CPU_IDLE option is set. This modification breaks an implicit dependency between CPU_IDLE and PM as they belong to the same block in the Makefile. This is fixed in the Kconfig by selecting explicitely PM is CPU_IDLE is set. The linux coding style recommend to use no-op functions in the headers when the subsystem is disabled instead of adding big section in C files. This patch fix this also. Signed-off-by: Daniel Lezcano Reviewed-by: Jean Pihet Reviewed-by: Rajendra Nayak Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/Kconfig | 2 ++ arch/arm/mach-omap2/Makefile | 7 +++++-- arch/arm/mach-omap2/cpuidle34xx.c | 8 -------- arch/arm/mach-omap2/cpuidle44xx.c | 8 -------- arch/arm/mach-omap2/pm.h | 17 +++++++++++++++-- 5 files changed, 22 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 4cf5142f22cc..cf84588cd110 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -35,6 +35,7 @@ config ARCH_OMAP3 select CPU_V7 select USB_ARCH_HAS_EHCI if USB_SUPPORT select ARCH_HAS_OPP + select PM if CPU_IDLE select PM_OPP if PM select ARM_CPU_SUSPEND if PM select MULTI_IRQ_HANDLER @@ -52,6 +53,7 @@ config ARCH_OMAP4 select PL310_ERRATA_727915 select ARM_ERRATA_720789 select ARCH_HAS_OPP + select PM if CPU_IDLE select PM_OPP if PM select USB_ARCH_HAS_EHCI if USB_SUPPORT select ARM_CPU_SUSPEND if PM diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index fa742f3c2629..6be43ac5c35c 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -66,9 +66,7 @@ ifeq ($(CONFIG_PM),y) obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o -obj-$(CONFIG_ARCH_OMAP3) += cpuidle34xx.o obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o -obj-$(CONFIG_ARCH_OMAP4) += cpuidle44xx.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o @@ -82,6 +80,11 @@ endif endif +ifeq ($(CONFIG_CPU_IDLE),y) +obj-$(CONFIG_ARCH_OMAP3) += cpuidle34xx.o +obj-$(CONFIG_ARCH_OMAP4) += cpuidle44xx.o +endif + # PRCM obj-y += prm_common.o obj-$(CONFIG_ARCH_OMAP2) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 207bc1c7759f..31344528eb54 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -36,8 +36,6 @@ #include "control.h" #include "common.h" -#ifdef CONFIG_CPU_IDLE - /* Mach specific information to be recorded in the C-state driver_data */ struct omap3_idle_statedata { u32 mpu_state; @@ -379,9 +377,3 @@ int __init omap3_idle_init(void) return 0; } -#else -int __init omap3_idle_init(void) -{ - return 0; -} -#endif /* CONFIG_CPU_IDLE */ diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c index be1617ca84bd..02d15bbd4e35 100644 --- a/arch/arm/mach-omap2/cpuidle44xx.c +++ b/arch/arm/mach-omap2/cpuidle44xx.c @@ -22,8 +22,6 @@ #include "pm.h" #include "prm.h" -#ifdef CONFIG_CPU_IDLE - /* Machine specific information */ struct omap4_idle_statedata { u32 cpu_state; @@ -199,9 +197,3 @@ int __init omap4_idle_init(void) return 0; } -#else -int __init omap4_idle_init(void) -{ - return 0; -} -#endif /* CONFIG_CPU_IDLE */ diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 78564895e914..ab04d3bba2e7 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -15,12 +15,25 @@ #include "powerdomain.h" +#ifdef CONFIG_CPU_IDLE +extern int __init omap3_idle_init(void); +extern int __init omap4_idle_init(void); +#else +static inline int omap3_idle_init(void) +{ + return 0; +} + +static inline int omap4_idle_init(void) +{ + return 0; +} +#endif + extern void *omap3_secure_ram_storage; extern void omap3_pm_off_mode_enable(int); extern void omap_sram_idle(void); extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state); -extern int omap3_idle_init(void); -extern int omap4_idle_init(void); extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused); extern int (*omap_pm_suspend)(void); -- cgit v1.2.3 From b110547e586eb5825bc1d04aa9147bff83b57672 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Fri, 18 May 2012 12:26:19 -0500 Subject: ARM: OMAP2+: OPP: Fix to ensure check of right oppdef after bad one Commit 9fa2df6b90786301b175e264f5fa9846aba81a65 (ARM: OMAP2+: OPP: allow OPP enumeration to continue if device is not present) makes the logic: for (i = 0; i < opp_def_size; i++) { if (!oh || !oh->od) { continue; } opp_def++; } In short, the moment we hit a "Bad OPP", we end up looping the list comparing against the bad opp definition pointer for the rest of the iteration count. Instead, increment opp_def in the for loop itself and allow continue to be used in code without much thought so that we check the next set of OPP definition pointers :) Cc: Steve Sakoman Cc: Tony Lindgren Cc: stable@vger.kernel.org Signed-off-by: Nishanth Menon Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/opp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c index de6d46451746..d8f6dbf45d16 100644 --- a/arch/arm/mach-omap2/opp.c +++ b/arch/arm/mach-omap2/opp.c @@ -53,7 +53,7 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def, omap_table_init = 1; /* Lets now register with OPP library */ - for (i = 0; i < opp_def_size; i++) { + for (i = 0; i < opp_def_size; i++, opp_def++) { struct omap_hwmod *oh; struct device *dev; @@ -86,7 +86,6 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def, __func__, opp_def->freq, opp_def->hwmod_name, i, r); } - opp_def++; } return 0; -- cgit v1.2.3 From a844a197f136ea4cffe050890dd25a35a4d26a42 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Wed, 14 Mar 2012 13:56:01 -0700 Subject: ARM: OMAP2+: TWL: remove usage of pdata->irq_base/_end The TWL driver has been converted to use SPARSE_IRQ and no longer needs to be passed IRQ base/end. Since driver no longer uses these fields, so remove them from the reamaining users. Cc: Benoit Cousson Cc: Samuel Ortiz Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/board-2430sdp.c | 3 --- arch/arm/mach-omap2/board-omap3logic.c | 3 --- arch/arm/mach-omap2/twl-common.c | 9 --------- 3 files changed, 15 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 99ca6bad5c30..0dac4db01139 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -218,9 +218,6 @@ static struct twl4030_gpio_platform_data sdp2430_gpio_data = { }; static struct twl4030_platform_data sdp2430_twldata = { - .irq_base = TWL4030_IRQ_BASE, - .irq_end = TWL4030_IRQ_END, - /* platform_data for children goes here */ .gpio = &sdp2430_gpio_data, .vmmc1 = &sdp2430_vmmc1, diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c index 932e1778aff9..fca93d1afd43 100644 --- a/arch/arm/mach-omap2/board-omap3logic.c +++ b/arch/arm/mach-omap2/board-omap3logic.c @@ -93,9 +93,6 @@ static struct twl4030_usb_data omap3logic_usb_data = { static struct twl4030_platform_data omap3logic_twldata = { - .irq_base = TWL4030_IRQ_BASE, - .irq_end = TWL4030_IRQ_END, - /* platform_data for children goes here */ .gpio = &omap3logic_gpio_data, .vmmc1 = &omap3logic_vmmc1, diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index 119d5a910f3a..ce7cccf5a772 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -211,10 +211,6 @@ static struct twl_regulator_driver_data omap3_vdd2_drvdata = { void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data, u32 pdata_flags, u32 regulators_flags) { - if (!pmic_data->irq_base) - pmic_data->irq_base = TWL4030_IRQ_BASE; - if (!pmic_data->irq_end) - pmic_data->irq_end = TWL4030_IRQ_END; if (!pmic_data->vdd1) { omap3_vdd1.driver_data = &omap3_vdd1_drvdata; omap3_vdd1_drvdata.data = voltdm_lookup("mpu_iva"); @@ -479,11 +475,6 @@ static struct regulator_init_data omap4_v2v1_idata = { void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data, u32 pdata_flags, u32 regulators_flags) { - if (!pmic_data->irq_base) - pmic_data->irq_base = TWL6030_IRQ_BASE; - if (!pmic_data->irq_end) - pmic_data->irq_end = TWL6030_IRQ_END; - if (!pmic_data->vdd1) { omap4_vdd1.driver_data = &omap4_vdd1_drvdata; omap4_vdd1_drvdata.data = voltdm_lookup("mpu"); -- cgit v1.2.3 From fbb20e81bd26e41667d8d0929fd08ed60b24d9ec Mon Sep 17 00:00:00 2001 From: Boojin Kim Date: Tue, 19 Jun 2012 13:26:53 +0900 Subject: ARM: SAMSUNG: Add config() function in DMA common operations This patch adds config() that configures DMA transmit option. This function was originally included in request(). But, Some DMA client driver requires to change the configuration after request(). So, This patch picks up it from request(). Signed-off-by: Boojin Kim Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/dma-ops.c | 77 ++++++++++++++++------------ arch/arm/plat-samsung/include/plat/dma-ops.h | 20 +++++--- arch/arm/plat-samsung/s3c-dma-ops.c | 39 ++++++++------ 3 files changed, 77 insertions(+), 59 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c index eb9f4f534006..f9eb353d768c 100644 --- a/arch/arm/plat-samsung/dma-ops.c +++ b/arch/arm/plat-samsung/dma-ops.c @@ -19,72 +19,80 @@ #include static unsigned samsung_dmadev_request(enum dma_ch dma_ch, - struct samsung_dma_info *info) + struct samsung_dma_req *param) { - struct dma_chan *chan; dma_cap_mask_t mask; - struct dma_slave_config slave_config; void *filter_param; dma_cap_zero(mask); - dma_cap_set(info->cap, mask); + dma_cap_set(param->cap, mask); /* * If a dma channel property of a device node from device tree is * specified, use that as the fliter parameter. */ - filter_param = (dma_ch == DMACH_DT_PROP) ? (void *)info->dt_dmach_prop : - (void *)dma_ch; - chan = dma_request_channel(mask, pl330_filter, filter_param); + filter_param = (dma_ch == DMACH_DT_PROP) ? + (void *)param->dt_dmach_prop : (void *)dma_ch; + return (unsigned)dma_request_channel(mask, pl330_filter, filter_param); +} - if (info->direction == DMA_DEV_TO_MEM) { +static int samsung_dmadev_release(unsigned ch, + struct s3c2410_dma_client *client) +{ + dma_release_channel((struct dma_chan *)ch); + + return 0; +} + +static int samsung_dmadev_config(unsigned ch, + struct samsung_dma_config *param) +{ + struct dma_chan *chan = (struct dma_chan *)ch; + struct dma_slave_config slave_config; + + if (param->direction == DMA_DEV_TO_MEM) { memset(&slave_config, 0, sizeof(struct dma_slave_config)); - slave_config.direction = info->direction; - slave_config.src_addr = info->fifo; - slave_config.src_addr_width = info->width; + slave_config.direction = param->direction; + slave_config.src_addr = param->fifo; + slave_config.src_addr_width = param->width; slave_config.src_maxburst = 1; dmaengine_slave_config(chan, &slave_config); - } else if (info->direction == DMA_MEM_TO_DEV) { + } else if (param->direction == DMA_MEM_TO_DEV) { memset(&slave_config, 0, sizeof(struct dma_slave_config)); - slave_config.direction = info->direction; - slave_config.dst_addr = info->fifo; - slave_config.dst_addr_width = info->width; + slave_config.direction = param->direction; + slave_config.dst_addr = param->fifo; + slave_config.dst_addr_width = param->width; slave_config.dst_maxburst = 1; dmaengine_slave_config(chan, &slave_config); + } else { + pr_warn("unsupported direction\n"); + return -EINVAL; } - return (unsigned)chan; -} - -static int samsung_dmadev_release(unsigned ch, - struct s3c2410_dma_client *client) -{ - dma_release_channel((struct dma_chan *)ch); - return 0; } static int samsung_dmadev_prepare(unsigned ch, - struct samsung_dma_prep_info *info) + struct samsung_dma_prep *param) { struct scatterlist sg; struct dma_chan *chan = (struct dma_chan *)ch; struct dma_async_tx_descriptor *desc; - switch (info->cap) { + switch (param->cap) { case DMA_SLAVE: sg_init_table(&sg, 1); - sg_dma_len(&sg) = info->len; - sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)), - info->len, offset_in_page(info->buf)); - sg_dma_address(&sg) = info->buf; + sg_dma_len(&sg) = param->len; + sg_set_page(&sg, pfn_to_page(PFN_DOWN(param->buf)), + param->len, offset_in_page(param->buf)); + sg_dma_address(&sg) = param->buf; desc = dmaengine_prep_slave_sg(chan, - &sg, 1, info->direction, DMA_PREP_INTERRUPT); + &sg, 1, param->direction, DMA_PREP_INTERRUPT); break; case DMA_CYCLIC: - desc = dmaengine_prep_dma_cyclic(chan, - info->buf, info->len, info->period, info->direction); + desc = dmaengine_prep_dma_cyclic(chan, param->buf, + param->len, param->period, param->direction); break; default: dev_err(&chan->dev->device, "unsupported format\n"); @@ -96,8 +104,8 @@ static int samsung_dmadev_prepare(unsigned ch, return -EFAULT; } - desc->callback = info->fp; - desc->callback_param = info->fp_param; + desc->callback = param->fp; + desc->callback_param = param->fp_param; dmaengine_submit((struct dma_async_tx_descriptor *)desc); @@ -119,6 +127,7 @@ static inline int samsung_dmadev_flush(unsigned ch) static struct samsung_dma_ops dmadev_ops = { .request = samsung_dmadev_request, .release = samsung_dmadev_release, + .config = samsung_dmadev_config, .prepare = samsung_dmadev_prepare, .trigger = samsung_dmadev_trigger, .started = NULL, diff --git a/arch/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h index 71a6827c7706..f5144cdd3001 100644 --- a/arch/arm/plat-samsung/include/plat/dma-ops.h +++ b/arch/arm/plat-samsung/include/plat/dma-ops.h @@ -16,7 +16,13 @@ #include #include -struct samsung_dma_prep_info { +struct samsung_dma_req { + enum dma_transaction_type cap; + struct property *dt_dmach_prop; + struct s3c2410_dma_client *client; +}; + +struct samsung_dma_prep { enum dma_transaction_type cap; enum dma_transfer_direction direction; dma_addr_t buf; @@ -26,19 +32,17 @@ struct samsung_dma_prep_info { void *fp_param; }; -struct samsung_dma_info { - enum dma_transaction_type cap; +struct samsung_dma_config { enum dma_transfer_direction direction; enum dma_slave_buswidth width; dma_addr_t fifo; - struct s3c2410_dma_client *client; - struct property *dt_dmach_prop; }; struct samsung_dma_ops { - unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info); - int (*release)(unsigned ch, struct s3c2410_dma_client *client); - int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info); + unsigned (*request)(enum dma_ch ch, struct samsung_dma_req *param); + int (*release)(unsigned ch, void *param); + int (*config)(unsigned ch, struct samsung_dma_config *param); + int (*prepare)(unsigned ch, struct samsung_dma_prep *param); int (*trigger)(unsigned ch); int (*started)(unsigned ch); int (*flush)(unsigned ch); diff --git a/arch/arm/plat-samsung/s3c-dma-ops.c b/arch/arm/plat-samsung/s3c-dma-ops.c index 781494912827..f99448c48d30 100644 --- a/arch/arm/plat-samsung/s3c-dma-ops.c +++ b/arch/arm/plat-samsung/s3c-dma-ops.c @@ -36,30 +36,26 @@ static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param, } static unsigned s3c_dma_request(enum dma_ch dma_ch, - struct samsung_dma_info *info) + struct samsung_dma_req *param) { struct cb_data *data; - if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) { - s3c2410_dma_free(dma_ch, info->client); + if (s3c2410_dma_request(dma_ch, param->client, NULL) < 0) { + s3c2410_dma_free(dma_ch, param->client); return 0; } + if (param->cap == DMA_CYCLIC) + s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR); + data = kzalloc(sizeof(struct cb_data), GFP_KERNEL); data->ch = dma_ch; list_add_tail(&data->node, &dma_list); - s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo); - - if (info->cap == DMA_CYCLIC) - s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR); - - s3c2410_dma_config(dma_ch, info->width); - return (unsigned)dma_ch; } -static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client) +static int s3c_dma_release(unsigned ch, void *param) { struct cb_data *data; @@ -68,16 +64,24 @@ static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client) break; list_del(&data->node); - s3c2410_dma_free(ch, client); + s3c2410_dma_free(ch, param); kfree(data); return 0; } -static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info) +static int s3c_dma_config(unsigned ch, struct samsung_dma_config *param) +{ + s3c2410_dma_devconfig(ch, param->direction, param->fifo); + s3c2410_dma_config(ch, param->width); + + return 0; +} + +static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep *param) { struct cb_data *data; - int len = (info->cap == DMA_CYCLIC) ? info->period : info->len; + int len = (param->cap == DMA_CYCLIC) ? param->period : param->len; list_for_each_entry(data, &dma_list, node) if (data->ch == ch) @@ -85,11 +89,11 @@ static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info) if (!data->fp) { s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb); - data->fp = info->fp; - data->fp_param = info->fp_param; + data->fp = param->fp; + data->fp_param = param->fp_param; } - s3c2410_dma_enqueue(ch, (void *)data, info->buf, len); + s3c2410_dma_enqueue(ch, (void *)data, param->buf, len); return 0; } @@ -117,6 +121,7 @@ static inline int s3c_dma_stop(unsigned ch) static struct samsung_dma_ops s3c_dma_ops = { .request = s3c_dma_request, .release = s3c_dma_release, + .config = s3c_dma_config, .prepare = s3c_dma_prepare, .trigger = s3c_dma_trigger, .started = s3c_dma_started, -- cgit v1.2.3 From 4efdc8a5731d6617f99486d9024041f712628a0c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 20 Jun 2012 09:13:40 +0900 Subject: ARM: S5P64X0: Remove unused variable in dma.c file Fixes the following warning: arch/arm/mach-s5p64x0/dma.c:39:12: warning: 'dma_dmamask' defined but not used [-Wunused-variable] Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim --- arch/arm/mach-s5p64x0/dma.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c index 2ee5dc069b37..9c4ce085f585 100644 --- a/arch/arm/mach-s5p64x0/dma.c +++ b/arch/arm/mach-s5p64x0/dma.c @@ -36,8 +36,6 @@ #include #include -static u64 dma_dmamask = DMA_BIT_MASK(32); - static u8 s5p6440_pdma_peri[] = { DMACH_UART0_RX, DMACH_UART0_TX, -- cgit v1.2.3 From f876c22a5cf4003b000718c2497fc6142fdff621 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 20 Jun 2012 09:14:08 +0900 Subject: ARM: S5PC100: Remove unused variable in dma.c file Fixes the following warning: arch/arm/mach-s5pc100/dma.c:36:12: warning: 'dma_dmamask' defined but not used [-Wunused-variable] Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim --- arch/arm/mach-s5pc100/dma.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-s5pc100/dma.c b/arch/arm/mach-s5pc100/dma.c index afd8db2d5991..b1418409709e 100644 --- a/arch/arm/mach-s5pc100/dma.c +++ b/arch/arm/mach-s5pc100/dma.c @@ -33,8 +33,6 @@ #include #include -static u64 dma_dmamask = DMA_BIT_MASK(32); - static u8 pdma0_peri[] = { DMACH_UART0_RX, DMACH_UART0_TX, -- cgit v1.2.3 From 9d530786c4ed88720671ba83b669b7e7da5cdc91 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 20 Jun 2012 09:18:39 +0900 Subject: ARM: SAMSUNG: Remove description corresponding to a deleted element Commit 3c582647a9f8 ("video: s3c-fb: remove 'default_win' element from platform data") removed the default_win element from the structure, but the description was not removed. Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/include/plat/fb.h | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h index 536002ff2ab8..b885322717a1 100644 --- a/arch/arm/plat-samsung/include/plat/fb.h +++ b/arch/arm/plat-samsung/include/plat/fb.h @@ -43,7 +43,6 @@ struct s3c_fb_pd_win { * @setup_gpio: Setup the external GPIO pins to the right state to transfer * the data from the display system to the connected display * device. - * @default_win: default window layer number to be used for UI layer. * @vidcon0: The base vidcon0 values to control the panel data format. * @vidcon1: The base vidcon1 values to control the panel data output. * @vtiming: Video timing when connected to a RGB type panel. -- cgit v1.2.3 From 334a511a811133182f8dbdc7b63f141bb1185fbb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 20 Jun 2012 09:19:17 +0900 Subject: ARM: S3C24XX: Remove duplicate header file inclusion regs-clock.h header file was included twice. Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/common.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 56cdd34cce41..0c9e9a785ef6 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -41,7 +41,6 @@ #include #include -#include #include #include -- cgit v1.2.3 From 3817575b4e0a58199ebe8f05faed4fc6469fda74 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Wed, 20 Jun 2012 09:25:07 +0900 Subject: ARM: S3C24XX: remove unused header Since (at least) v2.6.12-rc2 there has been a bast-pmu.h header in the tree. Currently it can be found at arch/arm/mach-s3c24xx/include/mach/bast-pmu.h. It seems that during that entire period nothing included that header and that none of the named constants it provided were ever used. That header can safely be removed. Signed-off-by: Paul Bolle Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/include/mach/bast-pmu.h | 40 --------------------------- 1 file changed, 40 deletions(-) delete mode 100644 arch/arm/mach-s3c24xx/include/mach/bast-pmu.h (limited to 'arch') diff --git a/arch/arm/mach-s3c24xx/include/mach/bast-pmu.h b/arch/arm/mach-s3c24xx/include/mach/bast-pmu.h deleted file mode 100644 index 4c38b39b741d..000000000000 --- a/arch/arm/mach-s3c24xx/include/mach/bast-pmu.h +++ /dev/null @@ -1,40 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/bast-pmu.h - * - * Copyright (c) 2003-2004 Simtec Electronics - * Ben Dooks - * Vincent Sanders - * - * Machine BAST - Power Management chip - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __ASM_ARCH_BASTPMU_H -#define __ASM_ARCH_BASTPMU_H "08_OCT_2004" - -#define BASTPMU_REG_IDENT (0x00) -#define BASTPMU_REG_VERSION (0x01) -#define BASTPMU_REG_DDCCTRL (0x02) -#define BASTPMU_REG_POWER (0x03) -#define BASTPMU_REG_RESET (0x04) -#define BASTPMU_REG_GWO (0x05) -#define BASTPMU_REG_WOL (0x06) -#define BASTPMU_REG_WOR (0x07) -#define BASTPMU_REG_UID (0x09) - -#define BASTPMU_EEPROM (0xC0) - -#define BASTPMU_EEP_UID (BASTPMU_EEPROM + 0) -#define BASTPMU_EEP_WOL (BASTPMU_EEPROM + 8) -#define BASTPMU_EEP_WOR (BASTPMU_EEPROM + 9) - -#define BASTPMU_IDENT_0 0x53 -#define BASTPMU_IDENT_1 0x42 -#define BASTPMU_IDENT_2 0x50 -#define BASTPMU_IDENT_3 0x4d - -#define BASTPMU_RESET_GUARD (0x55) - -#endif /* __ASM_ARCH_BASTPMU_H */ -- cgit v1.2.3 From 4f6939f898c408e6ba9754a42405494f821f22cb Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Wed, 20 Jun 2012 13:11:38 +0900 Subject: ARM: SAMSUNG: remove unused SPI clock headers Commit 875a59374cd10200ac24f03877ccd8f73af590cc ("ARM: SAMSUNG: Consolidation of SPI platform devices to plat-samsung") deleted all (four) files that included one of the "spi-clocks.h" headers. It seems it was just an oversight to not remove those headers too. They can safely be removed now. Signed-off-by: Paul Bolle Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/include/mach/spi-clocks.h | 16 ---------------- arch/arm/mach-s3c64xx/include/mach/spi-clocks.h | 18 ------------------ arch/arm/mach-s5p64x0/include/mach/spi-clocks.h | 20 -------------------- arch/arm/mach-s5pc100/include/mach/spi-clocks.h | 18 ------------------ arch/arm/mach-s5pv210/include/mach/spi-clocks.h | 17 ----------------- 5 files changed, 89 deletions(-) delete mode 100644 arch/arm/mach-exynos/include/mach/spi-clocks.h delete mode 100644 arch/arm/mach-s3c64xx/include/mach/spi-clocks.h delete mode 100644 arch/arm/mach-s5p64x0/include/mach/spi-clocks.h delete mode 100644 arch/arm/mach-s5pc100/include/mach/spi-clocks.h delete mode 100644 arch/arm/mach-s5pv210/include/mach/spi-clocks.h (limited to 'arch') diff --git a/arch/arm/mach-exynos/include/mach/spi-clocks.h b/arch/arm/mach-exynos/include/mach/spi-clocks.h deleted file mode 100644 index c71a5fba6a84..000000000000 --- a/arch/arm/mach-exynos/include/mach/spi-clocks.h +++ /dev/null @@ -1,16 +0,0 @@ -/* linux/arch/arm/mach-exynos4/include/mach/spi-clocks.h - * - * Copyright (C) 2011 Samsung Electronics Co. Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __ASM_ARCH_SPI_CLKS_H -#define __ASM_ARCH_SPI_CLKS_H __FILE__ - -/* Must source from SCLK_SPI */ -#define EXYNOS_SPI_SRCCLK_SCLK 0 - -#endif /* __ASM_ARCH_SPI_CLKS_H */ diff --git a/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h b/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h deleted file mode 100644 index 9d0c43b4b687..000000000000 --- a/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h +++ /dev/null @@ -1,18 +0,0 @@ -/* linux/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h - * - * Copyright (C) 2009 Samsung Electronics Ltd. - * Jaswinder Singh - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __S3C64XX_PLAT_SPI_CLKS_H -#define __S3C64XX_PLAT_SPI_CLKS_H __FILE__ - -#define S3C64XX_SPI_SRCCLK_PCLK 0 -#define S3C64XX_SPI_SRCCLK_SPIBUS 1 -#define S3C64XX_SPI_SRCCLK_48M 2 - -#endif /* __S3C64XX_PLAT_SPI_CLKS_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h b/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h deleted file mode 100644 index 170a20a9643a..000000000000 --- a/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h +++ /dev/null @@ -1,20 +0,0 @@ -/* linux/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h - * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Copyright (C) 2010 Samsung Electronics Co. Ltd. - * Jaswinder Singh - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __ASM_ARCH_SPI_CLKS_H -#define __ASM_ARCH_SPI_CLKS_H __FILE__ - -#define S5P64X0_SPI_SRCCLK_PCLK 0 -#define S5P64X0_SPI_SRCCLK_SCLK 1 - -#endif /* __ASM_ARCH_SPI_CLKS_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/spi-clocks.h b/arch/arm/mach-s5pc100/include/mach/spi-clocks.h deleted file mode 100644 index 65e426370bb2..000000000000 --- a/arch/arm/mach-s5pc100/include/mach/spi-clocks.h +++ /dev/null @@ -1,18 +0,0 @@ -/* linux/arch/arm/mach-s5pc100/include/mach/spi-clocks.h - * - * Copyright (C) 2010 Samsung Electronics Co. Ltd. - * Jaswinder Singh - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __S5PC100_PLAT_SPI_CLKS_H -#define __S5PC100_PLAT_SPI_CLKS_H __FILE__ - -#define S5PC100_SPI_SRCCLK_PCLK 0 -#define S5PC100_SPI_SRCCLK_48M 1 -#define S5PC100_SPI_SRCCLK_SPIBUS 2 - -#endif /* __S5PC100_PLAT_SPI_CLKS_H */ diff --git a/arch/arm/mach-s5pv210/include/mach/spi-clocks.h b/arch/arm/mach-s5pv210/include/mach/spi-clocks.h deleted file mode 100644 index 02acded5f73d..000000000000 --- a/arch/arm/mach-s5pv210/include/mach/spi-clocks.h +++ /dev/null @@ -1,17 +0,0 @@ -/* linux/arch/arm/mach-s5pv210/include/mach/spi-clocks.h - * - * Copyright (C) 2010 Samsung Electronics Co. Ltd. - * Jaswinder Singh - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __S5PV210_PLAT_SPI_CLKS_H -#define __S5PV210_PLAT_SPI_CLKS_H __FILE__ - -#define S5PV210_SPI_SRCCLK_PCLK 0 -#define S5PV210_SPI_SRCCLK_SCLK 1 - -#endif /* __S5PV210_PLAT_SPI_CLKS_H */ -- cgit v1.2.3 From 58f8c0543a9b0d84bca43526aec3774110201bc8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 20 Jun 2012 08:16:19 +0900 Subject: ARM: S3C64XX: Add module identification for Balblair Cragganmore module Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/mach-crag6410-module.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c index 7a27f5603c74..f51cc70064a4 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c @@ -209,6 +209,7 @@ static __devinitdata const struct { .spi_devs = wm1253_devs, .num_spi_devs = ARRAY_SIZE(wm1253_devs) }, { .id = 0x32, .name = "XXXX-EV1 Caol Illa" }, { .id = 0x33, .name = "XXXX-EV1 Oban" }, + { .id = 0x34, .name = "WM0010-6320-CS42 Balblair" }, { .id = 0x39, .name = "1254-EV1 Dallas Dhu", .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) }, { .id = 0x3a, .name = "1259-EV1 Tobermory", -- cgit v1.2.3 From 9b6e1b0e882a00d654a8313e22c189f13c321a20 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 20 Jun 2012 08:16:25 +0900 Subject: ARM: S3C64XX: Add WM5102 EVM to Cragganmore modules No platform data yet as driver is not yet merged. Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/mach-crag6410-module.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c index f51cc70064a4..497937222a29 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c @@ -182,6 +182,11 @@ static const struct i2c_board_info wm1277_devs[] = { }, }; +static const struct i2c_board_info wm5102_devs[] = { + { I2C_BOARD_INFO("wm5102", 0x1a), + .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2, }, +}; + static const struct i2c_board_info wm6230_i2c_devs[] = { { I2C_BOARD_INFO("wm9081", 0x6c), .platform_data = &wm9081_pdata, }, @@ -219,6 +224,8 @@ static __devinitdata const struct { { .id = 0x3c, .name = "1273-EV1 Longmorn" }, { .id = 0x3d, .name = "1277-EV1 Littlemill", .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs) }, + { .id = 0x3e, .name = "WM5102-6271-EV1-CS127", + .i2c_devs = wm5102_devs, .num_i2c_devs = ARRAY_SIZE(wm5102_devs) }, }; static __devinit int wlf_gf_module_probe(struct i2c_client *i2c, -- cgit v1.2.3 From 7d1d8ce5b50f4593f6d4b9d8149f978c122f617b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 20 Jun 2012 08:18:04 +0900 Subject: ARM: S3C64XX: Dynamically allocate the IRQ range for WM8994 on Cragganmore Use the new irqdomain support in the WM8994 driver to dynamically allocate the interrupt range for the WM8994 rather than doing it explicitly. This is more idiomatic for modern interrupt usage. Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/include/mach/crag6410.h | 1 - arch/arm/mach-s3c64xx/mach-crag6410-module.c | 1 - 2 files changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-s3c64xx/include/mach/crag6410.h b/arch/arm/mach-s3c64xx/include/mach/crag6410.h index 4cb2f951f1e9..ec97c15b109e 100644 --- a/arch/arm/mach-s3c64xx/include/mach/crag6410.h +++ b/arch/arm/mach-s3c64xx/include/mach/crag6410.h @@ -15,7 +15,6 @@ #define BANFF_PMIC_IRQ_BASE IRQ_BOARD_START #define GLENFARCLAS_PMIC_IRQ_BASE (IRQ_BOARD_START + 64) -#define CODEC_IRQ_BASE (IRQ_BOARD_START + 128) #define PCA935X_GPIO_BASE GPIO_BOARD_START #define CODEC_GPIO_BASE (GPIO_BOARD_START + 8) diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c index 497937222a29..4a83b4e7ab32 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c @@ -168,7 +168,6 @@ static struct wm8994_pdata wm8994_pdata = { .gpio_defaults = { 0x3, /* IRQ out, active high, CMOS */ }, - .irq_base = CODEC_IRQ_BASE, .ldo = { { .init_data = &wm8994_ldo1, }, { .init_data = &wm8994_ldo2, }, -- cgit v1.2.3 From 4f057aa0dcb2660bb09ead75d829a19ec71319f1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 20 Jun 2012 08:18:07 +0900 Subject: ARM: S3C64XX: Dynamically assign interrupts for CPU PMIC on Cragganmore Now that the WM831x driver uses irq_domain we can happily allow it to assign its own IRQs. Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/include/mach/crag6410.h | 3 +-- arch/arm/mach-s3c64xx/mach-crag6410.c | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-s3c64xx/include/mach/crag6410.h b/arch/arm/mach-s3c64xx/include/mach/crag6410.h index ec97c15b109e..4c3c9994fc2c 100644 --- a/arch/arm/mach-s3c64xx/include/mach/crag6410.h +++ b/arch/arm/mach-s3c64xx/include/mach/crag6410.h @@ -13,8 +13,7 @@ #include -#define BANFF_PMIC_IRQ_BASE IRQ_BOARD_START -#define GLENFARCLAS_PMIC_IRQ_BASE (IRQ_BOARD_START + 64) +#define GLENFARCLAS_PMIC_IRQ_BASE IRQ_BOARD_START #define PCA935X_GPIO_BASE GPIO_BOARD_START #define CODEC_GPIO_BASE (GPIO_BOARD_START + 8) diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index d0c352d861f8..161c3b6218a2 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -525,7 +525,6 @@ static struct wm831x_touch_pdata touch_pdata __initdata = { static struct wm831x_pdata crag_pmic_pdata __initdata = { .wm831x_num = 1, - .irq_base = BANFF_PMIC_IRQ_BASE, .gpio_base = BANFF_PMIC_GPIO_BASE, .soft_shutdown = true, -- cgit v1.2.3 From 33fe1a49ad23a63a60a816c99bdf6640f2314aea Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 20 Jun 2012 09:12:33 +0900 Subject: ARM: EXYNOS: Update keypad entries for SMDK4X12 Keypad entries are updated as per the latest revision of the board. Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/mach-smdk4x12.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c index fb09c70e195a..e134c9562f15 100644 --- a/arch/arm/mach-exynos/mach-smdk4x12.c +++ b/arch/arm/mach-exynos/mach-smdk4x12.c @@ -219,8 +219,10 @@ static struct platform_pwm_backlight_data smdk4x12_bl_data = { static uint32_t smdk4x12_keymap[] __initdata = { /* KEY(row, col, keycode) */ - KEY(1, 0, KEY_D), KEY(1, 1, KEY_A), KEY(1, 2, KEY_B), - KEY(1, 3, KEY_E), KEY(1, 4, KEY_C) + KEY(1, 3, KEY_1), KEY(1, 4, KEY_2), KEY(1, 5, KEY_3), + KEY(1, 6, KEY_4), KEY(1, 7, KEY_5), + KEY(2, 5, KEY_D), KEY(2, 6, KEY_A), KEY(2, 7, KEY_B), + KEY(0, 7, KEY_E), KEY(0, 5, KEY_C) }; static struct matrix_keymap_data smdk4x12_keymap_data __initdata = { @@ -230,8 +232,8 @@ static struct matrix_keymap_data smdk4x12_keymap_data __initdata = { static struct samsung_keypad_platdata smdk4x12_keypad_data __initdata = { .keymap_data = &smdk4x12_keymap_data, - .rows = 2, - .cols = 5, + .rows = 3, + .cols = 8, }; static struct platform_device *smdk4x12_devices[] __initdata = { -- cgit v1.2.3 From 25bcde9fa805c2f723aa3a0ed559f5e5472a7afc Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 20 Jun 2012 16:29:52 +0900 Subject: ARM: S5PV210: Add HSOTG support to SMDKV210 Adds S3C-HSOTG support to SMDKV210 board. Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim --- arch/arm/mach-s5pv210/Kconfig | 2 ++ arch/arm/mach-s5pv210/mach-smdkv210.c | 9 +++++++++ 2 files changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig index 88e983b0c82e..77185c38188b 100644 --- a/arch/arm/mach-s5pv210/Kconfig +++ b/arch/arm/mach-s5pv210/Kconfig @@ -152,6 +152,7 @@ config MACH_SMDKV210 select S3C_DEV_I2C1 select S3C_DEV_I2C2 select S3C_DEV_RTC + select S3C_DEV_USB_HSOTG select S3C_DEV_WDT select S5P_DEV_FIMC0 select S5P_DEV_FIMC1 @@ -170,6 +171,7 @@ config MACH_SMDKV210 select S5PV210_SETUP_IDE select S5PV210_SETUP_KEYPAD select S5PV210_SETUP_SDHCI + select S5PV210_SETUP_USB_PHY help Machine support for Samsung SMDKV210 diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index 0d7ddec88eb7..c8997bce642d 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,7 @@ #include #include #include +#include #include "common.h" @@ -203,6 +205,9 @@ static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = { .setup_gpio = s5pv210_fb_gpio_setup_24bpp, }; +/* USB OTG */ +static struct s3c_hsotg_plat smdkv210_hsotg_pdata; + static struct platform_device *smdkv210_devices[] __initdata = { &s3c_device_adc, &s3c_device_cfcon, @@ -216,6 +221,7 @@ static struct platform_device *smdkv210_devices[] __initdata = { &s3c_device_i2c2, &s3c_device_rtc, &s3c_device_ts, + &s3c_device_usb_hsotg, &s3c_device_wdt, &s5p_device_fimc0, &s5p_device_fimc1, @@ -314,6 +320,9 @@ static void __init smdkv210_machine_init(void) samsung_bl_set(&smdkv210_bl_gpio_info, &smdkv210_bl_data); + s3c_hsotg_set_platdata(&smdkv210_hsotg_pdata); + clk_xusbxti.rate = 24000000; + platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices)); } -- cgit v1.2.3 From a5d8f4765f0e92ef027492a8cb979c5b8d45f2c3 Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Wed, 20 Jun 2012 17:05:37 +0900 Subject: ARM: SAMSUNG: Should check for IS_ERR(clk) instead of NULL On the error condition clk_get() returns ERR_PTR(). Signed-off-by: Jonghwan Choi Cc: Stable Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/include/plat/watchdog-reset.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/plat-samsung/include/plat/watchdog-reset.h b/arch/arm/plat-samsung/include/plat/watchdog-reset.h index f19aff19205c..bc4db9b04e36 100644 --- a/arch/arm/plat-samsung/include/plat/watchdog-reset.h +++ b/arch/arm/plat-samsung/include/plat/watchdog-reset.h @@ -25,7 +25,7 @@ static inline void arch_wdt_reset(void) __raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */ - if (s3c2410_wdtclk) + if (!IS_ERR(s3c2410_wdtclk)) clk_enable(s3c2410_wdtclk); /* put initial values into count and data */ -- cgit v1.2.3 From 32103c7ba7d274bcb3ace48bc3366e1df37ebb56 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 20 Jun 2012 11:30:25 +0200 Subject: ARM: shmobile: sh73a0: bugfix: SY-DMAC number 681e1b3eeb3606e06a7c4984e8058df84296f8bb (ARM: mach-shmobile: sh73a0 DMA Engine support for SY-DMAC) adds SY-DMAC, but it is 218, not 318 This patch is based on v2.0 manual Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/clock-sh73a0.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 472d1f5361e5..3946c4ba2aa8 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -475,9 +475,9 @@ static struct clk *late_main_clks[] = { enum { MSTP001, MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100, - MSTP219, + MSTP219, MSTP218, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, - MSTP331, MSTP329, MSTP325, MSTP323, MSTP318, + MSTP331, MSTP329, MSTP325, MSTP323, MSTP314, MSTP313, MSTP312, MSTP311, MSTP303, MSTP302, MSTP301, MSTP300, MSTP411, MSTP410, MSTP403, @@ -497,6 +497,7 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP116] = MSTP(&div4_clks[DIV4_HP], SMSTPCR1, 16, 0), /* IIC0 */ [MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */ [MSTP219] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 19, 0), /* SCIFA7 */ + [MSTP218] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* SY-DMAC */ [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */ [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */ [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */ @@ -508,7 +509,6 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */ [MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */ - [MSTP318] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 18, 0), /* SY-DMAC */ [MSTP314] = MSTP(&div6_clks[DIV6_SDHI0], SMSTPCR3, 14, 0), /* SDHI0 */ [MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */ [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */ @@ -552,6 +552,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */ CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */ + CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* SY-DMAC */ CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */ CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), /* SCIFB */ CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */ @@ -563,7 +564,6 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */ CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */ - CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP318]), /* SY-DMAC */ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */ -- cgit v1.2.3 From 4d6344f3c943a5ff1fd8dcbd7be61ebdef1d0285 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 20 Jun 2012 11:30:32 +0200 Subject: ARM: shmobile: sh7372: bugfix: chclr_offset base chclr_write() will use (chan_reg + chclr_offset). In sh7372 case, DMA1CHCLR is started from 0xfe008220, and chan_reg is started from 0xfe008020 (= sh7372_dmae0_resources). Thus, chclr_offset should be (0x220 - 0x20) instead of 0x220. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/setup-sh7372.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 6a4bd582c028..fafce9ce8218 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -484,7 +484,7 @@ static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = { }, }; -#define SH7372_CHCLR 0x220 +#define SH7372_CHCLR (0x220 - 0x20) static const struct sh_dmae_channel sh7372_dmae_channels[] = { { -- cgit v1.2.3 From 6ae42bb22b40254e6488bbfe47f970620ab6d433 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Wed, 20 Jun 2012 11:30:41 +0200 Subject: ARM: mach-shmobile: Fix build when SMP is enabled and EMEV2 is not enabled Build failed, when SMP is enabled and EMEV2 is not enabled. arch/arm/mach-shmobile/built-in.o: In function `shmobile_platform_cpu_kill': /home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:62: undefined reference to `emev2_platform_cpu_kill' arch/arm/mach-shmobile/built-in.o: In function `shmobile_smp_get_core_count': /home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:39: undefined reference to `emev2_get_core_count' arch/arm/mach-shmobile/built-in.o: In function `shmobile_smp_prepare_cpus': /home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:53: undefined reference to `emev2_smp_prepare_cpus' arch/arm/mach-shmobile/built-in.o: In function `platform_secondary_init': /home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:78: undefined reference to `emev2_secondary_init' arch/arm/mach-shmobile/built-in.o: In function `boot_secondary': /home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:90: undefined reference to `emev2_boot_secondary This is the cause by when EMEV2 is disabled, that the check by OF of EMEV2 is performed in platsmp.c. This patch revise what the function about EMEV2 may not be used in this file, when EMEV2 is not enabled. Signed-off-by: Nobuhiro Iwamatsu Acked-by: Simon Horman Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/platsmp.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index bacdd667e3b1..e859fcdb3d58 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -25,7 +25,12 @@ #define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \ of_machine_is_compatible("renesas,sh73a0")) #define is_r8a7779() machine_is_marzen() + +#ifdef CONFIG_ARCH_EMEV2 #define is_emev2() of_machine_is_compatible("renesas,emev2") +#else +#define is_emev2() (0) +#endif static unsigned int __init shmobile_smp_get_core_count(void) { -- cgit v1.2.3 From 56fb523f12665974bd249a39524b75b4f5e57388 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 20 Jun 2012 12:15:59 +0200 Subject: ARM: mach-shmobile: add missing GPIO IRQ configuration on mackerel SDHI0 card-detect GPIO IRQ on mackarel currently works, because it is the default configuration of IRQ26. However, we should not rely on this and should configure the function explicitly. Signed-off-by: Guennadi Liakhovetski Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/board-mackerel.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index b577f7c44678..150122a44630 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -1512,6 +1512,9 @@ static void __init mackerel_init(void) gpio_request(GPIO_FN_SDHID0_1, NULL); gpio_request(GPIO_FN_SDHID0_0, NULL); + /* SDHI0 PORT172 card-detect IRQ26 */ + gpio_request(GPIO_FN_IRQ26_172, NULL); + #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) /* enable SDHI1 */ gpio_request(GPIO_FN_SDHICMD1, NULL); -- cgit v1.2.3 From 0718467c859f5571dc48d294596f841096f6a47a Mon Sep 17 00:00:00 2001 From: Li Zhong Date: Mon, 18 Jun 2012 15:56:33 -0400 Subject: x86/nmi: Clean up register_nmi_handler() usage Implement a cleaner and easier to maintain version for the section warning fixes implemented in commit eeaaa96a3a21 ("x86/nmi: Fix section mismatch warnings on 32-bit"). Signed-off-by: Li Zhong Signed-off-by: Don Zickus Cc: Jan Beulich Link: http://lkml.kernel.org/r/1340049393-17771-1-git-send-email-dzickus@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/nmi.h | 20 +++----------------- arch/x86/kernel/nmi_selftest.c | 7 ++++--- 2 files changed, 7 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h index dc580c42851c..c0fa356e90de 100644 --- a/arch/x86/include/asm/nmi.h +++ b/arch/x86/include/asm/nmi.h @@ -44,28 +44,14 @@ struct nmiaction { const char *name; }; -#define register_nmi_handler(t, fn, fg, n) \ +#define register_nmi_handler(t, fn, fg, n, init...) \ ({ \ - static struct nmiaction fn##_na = { \ + static struct nmiaction init fn##_na = { \ .handler = (fn), \ .name = (n), \ .flags = (fg), \ }; \ - __register_nmi_handler((t), &fn##_na); \ -}) - -/* - * For special handlers that register/unregister in the - * init section only. This should be considered rare. - */ -#define register_nmi_handler_initonly(t, fn, fg, n) \ -({ \ - static struct nmiaction fn##_na __initdata = { \ - .handler = (fn), \ - .name = (n), \ - .flags = (fg), \ - }; \ - __register_nmi_handler((t), &fn##_na); \ + __register_nmi_handler((t), &fn##_na); \ }) int __register_nmi_handler(unsigned int, struct nmiaction *); diff --git a/arch/x86/kernel/nmi_selftest.c b/arch/x86/kernel/nmi_selftest.c index 149b8d9c6ad4..6d9582ec0324 100644 --- a/arch/x86/kernel/nmi_selftest.c +++ b/arch/x86/kernel/nmi_selftest.c @@ -42,7 +42,8 @@ static int __init nmi_unk_cb(unsigned int val, struct pt_regs *regs) static void __init init_nmi_testsuite(void) { /* trap all the unknown NMIs we may generate */ - register_nmi_handler_initonly(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk"); + register_nmi_handler(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk", + __initdata); } static void __init cleanup_nmi_testsuite(void) @@ -64,8 +65,8 @@ static void __init test_nmi_ipi(struct cpumask *mask) { unsigned long timeout; - if (register_nmi_handler_initonly(NMI_LOCAL, test_nmi_ipi_callback, - NMI_FLAG_FIRST, "nmi_selftest")) { + if (register_nmi_handler(NMI_LOCAL, test_nmi_ipi_callback, + NMI_FLAG_FIRST, "nmi_selftest", __initdata)) { nmi_fail = FAILURE; return; } -- cgit v1.2.3 From e1b6fc55da40bc17e20795901cb786e3619f9be9 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 18 Jun 2012 11:28:45 +0100 Subject: x86/microcode: Mark microcode_id[] as __initconst It's not being used for other than creating module aliases (i.e. no loadable section has any reference to it). Signed-off-by: Jan Beulich Link: http://lkml.kernel.org/r/4FDF1EFD020000780008A65D@nat28.tlf.novell.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index fbdfc6917180..c383b3f8f397 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -504,7 +504,7 @@ static struct notifier_block __refdata mc_cpu_notifier = { #ifdef MODULE /* Autoload on Intel and AMD systems */ -static const struct x86_cpu_id microcode_id[] = { +static const struct x86_cpu_id __initconst microcode_id[] = { #ifdef CONFIG_MICROCODE_INTEL { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, }, #endif -- cgit v1.2.3 From 0d26d1d873a302828e064737746c53a2689e6c0f Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 18 Jun 2012 11:30:20 +0100 Subject: x86/mm: Mark free_initrd_mem() as __init ... matching various other architectures. Signed-off-by: Jan Beulich Link: http://lkml.kernel.org/r/4FDF1F5C020000780008A661@nat28.tlf.novell.com Signed-off-by: Ingo Molnar --- arch/x86/mm/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index bc4e9d84157f..e0e6990723e9 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -385,7 +385,7 @@ void free_initmem(void) } #ifdef CONFIG_BLK_DEV_INITRD -void free_initrd_mem(unsigned long start, unsigned long end) +void __init free_initrd_mem(unsigned long start, unsigned long end) { /* * end could be not aligned, and We can not align that, -- cgit v1.2.3 From 0fa0e2f02e8edfbdb5f86d1cab0fa6dc0517489f Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 18 Jun 2012 11:40:04 +0100 Subject: x86: Move call to print_modules() out of show_regs() Printing the list of loaded modules is really unrelated to what this function is about, and is particularly unnecessary in the context of the SysRQ key handling (gets printed so far over and over). It should really be the caller of the function to decide whether this piece of information is useful (and to avoid redundantly printing it). Signed-off-by: Jan Beulich Link: http://lkml.kernel.org/r/4FDF21A4020000780008A67F@nat28.tlf.novell.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/dumpstack.c | 1 + arch/x86/kernel/dumpstack_32.c | 1 - arch/x86/kernel/dumpstack_64.c | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 87d3b5d663cd..ae42418bc50f 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -271,6 +271,7 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err) current->thread.trap_nr, SIGSEGV) == NOTIFY_STOP) return 1; + print_modules(); show_regs(regs); #ifdef CONFIG_X86_32 if (user_mode_vm(regs)) { diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index 3a8aced11ae9..1038a417ea53 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c @@ -86,7 +86,6 @@ void show_regs(struct pt_regs *regs) { int i; - print_modules(); __show_regs(regs, !user_mode_vm(regs)); pr_emerg("Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)\n", diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index c582e9c5bd1a..b653675d5288 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -254,7 +254,6 @@ void show_regs(struct pt_regs *regs) sp = regs->sp; printk("CPU %d ", cpu); - print_modules(); __show_regs(regs, 1); printk(KERN_DEFAULT "Process %s (pid: %d, threadinfo %p, task %p)\n", cur->comm, cur->pid, task_thread_info(cur), cur); -- cgit v1.2.3 From 310018d52ec06c19dc946c2807c07c8b70e2d1a6 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 20 Jun 2012 07:18:15 -0700 Subject: ARM: OMAP2+: Fix MUSB ifdefs for platform init code Commit 62285963 (usb: musb: drop a gigantic amount of ifdeferry) got rid of a bunch of ifdefs in the MUSB code. Looks like the platform init code is still using these dropped defines though, which in many cases results the board defaulting always to host mode. Currently the situation is that USB_MUSB_HDRC is the main Kconfig option with additional USB_GADGET_MUSB_HDRC so only these two should be used to select between host and OTG mode. Fix the situation for omaps. The following users should fix the platform init code in a similar way: Dropped Kconfig option Current users USB_MUSB_OTG blackfin, davinci, not in Kconfigs USB_MUSB_PERIPHERAL davinci, not in Kconfigs USB_MUSB_HOST davinci, not in Kconfigs USB_MUSB_HDRC_HCD blackfin, not in Kconfigs USB_MUSB_OTG blackfin, not in Kconfigs Cc: Mike Frysinger Cc: Sekhar Nori Cc: linux-usb@vger.kernel.org Cc: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-n8x0.c | 6 ++---- arch/arm/mach-omap2/omap_phy_internal.c | 6 ------ arch/arm/mach-omap2/usb-musb.c | 6 ++---- 3 files changed, 4 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 8ca14e88a31a..2c5d0ed75285 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -83,11 +83,9 @@ static struct musb_hdrc_config musb_config = { }; static struct musb_hdrc_platform_data tusb_data = { -#if defined(CONFIG_USB_MUSB_OTG) +#ifdef CONFIG_USB_GADGET_MUSB_HDRC .mode = MUSB_OTG, -#elif defined(CONFIG_USB_MUSB_PERIPHERAL) - .mode = MUSB_PERIPHERAL, -#else /* defined(CONFIG_USB_MUSB_HOST) */ +#else .mode = MUSB_HOST, #endif .set_power = tusb_set_power, diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c index 4c90477e6f82..d52651a05daa 100644 --- a/arch/arm/mach-omap2/omap_phy_internal.c +++ b/arch/arm/mach-omap2/omap_phy_internal.c @@ -239,21 +239,15 @@ void am35x_set_mode(u8 musb_mode) devconf2 &= ~CONF2_OTGMODE; switch (musb_mode) { -#ifdef CONFIG_USB_MUSB_HDRC_HCD case MUSB_HOST: /* Force VBUS valid, ID = 0 */ devconf2 |= CONF2_FORCE_HOST; break; -#endif -#ifdef CONFIG_USB_GADGET_MUSB_HDRC case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */ devconf2 |= CONF2_FORCE_DEVICE; break; -#endif -#ifdef CONFIG_USB_MUSB_OTG case MUSB_OTG: /* Don't override the VBUS/ID comparators */ devconf2 |= CONF2_NO_OVERRIDE; break; -#endif default: pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode); } diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index b19d1b43c12e..c4a576856661 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c @@ -41,12 +41,10 @@ static struct musb_hdrc_config musb_config = { }; static struct musb_hdrc_platform_data musb_plat = { -#ifdef CONFIG_USB_MUSB_OTG +#ifdef CONFIG_USB_GADGET_MUSB_HDRC .mode = MUSB_OTG, -#elif defined(CONFIG_USB_MUSB_HDRC_HCD) +#else .mode = MUSB_HOST, -#elif defined(CONFIG_USB_GADGET_MUSB_HDRC) - .mode = MUSB_PERIPHERAL, #endif /* .clock is set dynamically */ .config = &musb_config, -- cgit v1.2.3 From 3d09b33fecf204561e5c7126648ec05c756c631c Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 20 Jun 2012 07:18:15 -0700 Subject: ARM: OMAP2: Fix tusb6010 GPIO interrupt for n8x0 Here's one more gpio_to_irq conversion that we missed earlier. Tested with n800 in gadget mode using USB_ETH. Cc: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/usb-tusb6010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index db84a46ce7fd..805bea6edf17 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c @@ -300,7 +300,7 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data, printk(error, 3, status); return status; } - tusb_resources[2].start = irq + IH_GPIO_BASE; + tusb_resources[2].start = gpio_to_irq(irq); /* set up memory timings ... can speed them up later */ if (!ps_refclk) { -- cgit v1.2.3 From 95dca12d6bf2dd5e7720506b8f9786318899b8d6 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 12 Jun 2012 19:40:46 -0500 Subject: arm/dts: OMAP2: Fix interrupt controller binding When booting with device-tree on an OMAP2420H4, the kernel is hanging when initialising the interrupts and following kernel dumps is seen ... [ 0.000000] ------------[ cut here ]------------ [ 0.000000] WARNING: at arch/arm/mach-omap2/irq.c:271 omap_intc_of_init+0x50/0xb4() [ 0.000000] unable to get intc registers [ 0.000000] Modules linked in: [ 0.000000] [] (unwind_backtrace+0x0/0xf4) from [] (warn_slowpath_common+0x4c/0x64) [ 0.000000] [] (warn_slowpath_common+0x4c/0x64) from [] (warn_slowpath_fmt+0x30/0x40) [ 0.000000] [] (warn_slowpath_fmt+0x30/0x40) from [] (omap_intc_of_init+0x50/0xb4) [ 0.000000] [] (omap_intc_of_init+0x50/0xb4) from [] (of_irq_init+0x144/0x288) [ 0.000000] [] (of_irq_init+0x144/0x288) from [] (init_IRQ+0x14/0x1c) [ 0.000000] [] (init_IRQ+0x14/0x1c) from [] (start_kernel+0x198/0x304) [ 0.000000] [] (start_kernel+0x198/0x304) from [<80008044>] (0x80008044) [ 0.000000] ---[ end trace 1b75b31a2719ed1c ]--- [ 0.000000] of_irq_init: children remain, but no parents The OMAP2 interrupt controller binding is missing the number of interrupts and interrupt controller register address. Adding these fixes the problem. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap2.dtsi | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/omap2.dtsi b/arch/arm/boot/dts/omap2.dtsi index f2ab4ea7cc0e..581cb081cb0f 100644 --- a/arch/arm/boot/dts/omap2.dtsi +++ b/arch/arm/boot/dts/omap2.dtsi @@ -44,6 +44,8 @@ compatible = "ti,omap2-intc"; interrupt-controller; #interrupt-cells = <1>; + ti,intc-size = <96>; + reg = <0x480FE000 0x1000>; }; uart1: serial@4806a000 { -- cgit v1.2.3 From aef2b89662b8a7506846d0dc0df672d196ddf8d0 Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Wed, 9 May 2012 15:15:03 -0700 Subject: ARM: OMAP: Fix Beagleboard DVI reset gpio Commit e813a55eb9c9bc6c8039fb16332cf43402125b30 ("OMAP: board-files: remove custom PD GPIO handling for DVI output") moved TFP410 chip's powerdown-gpio handling from the board files to the tfp410 driver. One gpio_request_one(powerdown-gpio, ...) was mistakenly left unremoved in the Beagle board file. This causes the tfp410 driver to fail to request the gpio on Beagle, causing the driver to fail and thus the DVI output doesn't work. This patch removes several boot errors from board-omap3beagle.c: - gpio_request: gpio--22 (DVI reset) status -22 - Unable to get DVI reset GPIO There is a combination of leftover code and revision confusion. Additionally, xM support is currently a hack. For original Beagleboard this removes the double initialization of GPIO 170, properly configures it as an output, and wraps the initialization in an if block so that xM does not attempt to request it. For Beagleboard xM it removes reference to GPIO 129 which was part of rev A1 and A2 designs, but never functioned. It then properly assigns beagle_dvi_device.reset_gpio in beagle_twl_gpio_setup and removes the hack of initializing it high. Additionally, it uses gpio_set_value_cansleep since this GPIO is connected through i2c. Unfortunately, there is no way to tell the difference between xM A2 and A3. However, GPIO 129 does not function on rev A1 and A2, and the TWL GPIO used on A3 and beyond is not used on rev A1 and A2, there are no problems created by this fix. Tested on Beagleboard-xM Rev C1 and Beagleboard Rev B4. Signed-off-by: Russ Dill Acked-by: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-omap3beagle.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 79c6909eeb78..580fd17208da 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -81,13 +81,13 @@ static u8 omap3_beagle_version; static struct { int mmc1_gpio_wp; int usb_pwr_level; - int reset_gpio; + int dvi_pd_gpio; int usr_button_gpio; int mmc_caps; } beagle_config = { .mmc1_gpio_wp = -EINVAL, .usb_pwr_level = GPIOF_OUT_INIT_LOW, - .reset_gpio = 129, + .dvi_pd_gpio = -EINVAL, .usr_button_gpio = 4, .mmc_caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, }; @@ -126,21 +126,21 @@ static void __init omap3_beagle_init_rev(void) printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n"); omap3_beagle_version = OMAP3BEAGLE_BOARD_AXBX; beagle_config.mmc1_gpio_wp = 29; - beagle_config.reset_gpio = 170; + beagle_config.dvi_pd_gpio = 170; beagle_config.usr_button_gpio = 7; break; case 6: printk(KERN_INFO "OMAP3 Beagle Rev: C1/C2/C3\n"); omap3_beagle_version = OMAP3BEAGLE_BOARD_C1_3; beagle_config.mmc1_gpio_wp = 23; - beagle_config.reset_gpio = 170; + beagle_config.dvi_pd_gpio = 170; beagle_config.usr_button_gpio = 7; break; case 5: printk(KERN_INFO "OMAP3 Beagle Rev: C4\n"); omap3_beagle_version = OMAP3BEAGLE_BOARD_C4; beagle_config.mmc1_gpio_wp = 23; - beagle_config.reset_gpio = 170; + beagle_config.dvi_pd_gpio = 170; beagle_config.usr_button_gpio = 7; break; case 0: @@ -274,11 +274,9 @@ static int beagle_twl_gpio_setup(struct device *dev, if (r) pr_err("%s: unable to configure nDVI_PWR_EN\n", __func__); - r = gpio_request_one(gpio + 2, GPIOF_OUT_INIT_HIGH, - "DVI_LDO_EN"); - if (r) - pr_err("%s: unable to configure DVI_LDO_EN\n", - __func__); + + beagle_config.dvi_pd_gpio = gpio + 2; + } else { /* * REVISIT: need ehci-omap hooks for external VBUS @@ -287,7 +285,7 @@ static int beagle_twl_gpio_setup(struct device *dev, if (gpio_request_one(gpio + 1, GPIOF_IN, "EHCI_nOC")) pr_err("%s: unable to configure EHCI_nOC\n", __func__); } - dvi_panel.power_down_gpio = beagle_config.reset_gpio; + dvi_panel.power_down_gpio = beagle_config.dvi_pd_gpio; gpio_request_one(gpio + TWL4030_GPIO_MAX, beagle_config.usb_pwr_level, "nEN_USB_PWR"); @@ -499,7 +497,7 @@ static void __init omap3_beagle_init(void) omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap3_beagle_init_rev(); - if (beagle_config.mmc1_gpio_wp != -EINVAL) + if (gpio_is_valid(beagle_config.mmc1_gpio_wp)) omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT); mmc[0].caps = beagle_config.mmc_caps; omap_hsmmc_init(mmc); @@ -510,15 +508,13 @@ static void __init omap3_beagle_init(void) platform_add_devices(omap3_beagle_devices, ARRAY_SIZE(omap3_beagle_devices)); + if (gpio_is_valid(beagle_config.dvi_pd_gpio)) + omap_mux_init_gpio(beagle_config.dvi_pd_gpio, OMAP_PIN_OUTPUT); omap_display_init(&beagle_dss_data); omap_serial_init(); omap_sdrc_init(mt46h32m32lf6_sdrc_params, mt46h32m32lf6_sdrc_params); - omap_mux_init_gpio(170, OMAP_PIN_INPUT); - /* REVISIT leave DVI powered down until it's needed ... */ - gpio_request_one(170, GPIOF_OUT_INIT_HIGH, "DVI_nPD"); - usb_musb_init(NULL); usbhs_init(&usbhs_bdata); omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions, -- cgit v1.2.3 From 702b0e4f2f2782962aab7d9a0a40ad68770bb1f6 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 11 Jun 2012 16:25:07 -0600 Subject: ARM: dt: tegra: rename board files to match SoC Most ARM ${board}.dts files are already named ${soc}-${board}.dts. This change modifies the Tegra board files to be named the same way for consistency. Once a related change is made in U-Boot, this will cause both U-Boot and the kernel to use the same names for the .dts files and SoC identifiers, thus allowing U-Boot's recently added "soc" and "board" environment variables to be used to construct the name of Tegra .dtb files, and hence allow board-generic U-Boot bootcmd scripts to be written. Signed-off-by: Stephen Warren --- arch/arm/boot/dts/tegra-cardhu.dts | 171 ------------ arch/arm/boot/dts/tegra-harmony.dts | 336 ------------------------ arch/arm/boot/dts/tegra-paz00.dts | 347 ------------------------- arch/arm/boot/dts/tegra-seaboard.dts | 444 -------------------------------- arch/arm/boot/dts/tegra-trimslice.dts | 306 ---------------------- arch/arm/boot/dts/tegra-ventana.dts | 343 ------------------------ arch/arm/boot/dts/tegra20-harmony.dts | 336 ++++++++++++++++++++++++ arch/arm/boot/dts/tegra20-paz00.dts | 347 +++++++++++++++++++++++++ arch/arm/boot/dts/tegra20-seaboard.dts | 444 ++++++++++++++++++++++++++++++++ arch/arm/boot/dts/tegra20-trimslice.dts | 306 ++++++++++++++++++++++ arch/arm/boot/dts/tegra20-ventana.dts | 343 ++++++++++++++++++++++++ arch/arm/boot/dts/tegra30-cardhu.dts | 171 ++++++++++++ arch/arm/mach-tegra/Makefile.boot | 12 +- 13 files changed, 1953 insertions(+), 1953 deletions(-) delete mode 100644 arch/arm/boot/dts/tegra-cardhu.dts delete mode 100644 arch/arm/boot/dts/tegra-harmony.dts delete mode 100644 arch/arm/boot/dts/tegra-paz00.dts delete mode 100644 arch/arm/boot/dts/tegra-seaboard.dts delete mode 100644 arch/arm/boot/dts/tegra-trimslice.dts delete mode 100644 arch/arm/boot/dts/tegra-ventana.dts create mode 100644 arch/arm/boot/dts/tegra20-harmony.dts create mode 100644 arch/arm/boot/dts/tegra20-paz00.dts create mode 100644 arch/arm/boot/dts/tegra20-seaboard.dts create mode 100644 arch/arm/boot/dts/tegra20-trimslice.dts create mode 100644 arch/arm/boot/dts/tegra20-ventana.dts create mode 100644 arch/arm/boot/dts/tegra30-cardhu.dts (limited to 'arch') diff --git a/arch/arm/boot/dts/tegra-cardhu.dts b/arch/arm/boot/dts/tegra-cardhu.dts deleted file mode 100644 index c169bced131e..000000000000 --- a/arch/arm/boot/dts/tegra-cardhu.dts +++ /dev/null @@ -1,171 +0,0 @@ -/dts-v1/; - -/include/ "tegra30.dtsi" - -/ { - model = "NVIDIA Tegra30 Cardhu evaluation board"; - compatible = "nvidia,cardhu", "nvidia,tegra30"; - - memory { - reg = <0x80000000 0x40000000>; - }; - - pinmux { - pinctrl-names = "default"; - pinctrl-0 = <&state_default>; - - state_default: pinmux { - sdmmc1_clk_pz0 { - nvidia,pins = "sdmmc1_clk_pz0"; - nvidia,function = "sdmmc1"; - nvidia,pull = <0>; - nvidia,tristate = <0>; - }; - sdmmc1_cmd_pz1 { - nvidia,pins = "sdmmc1_cmd_pz1", - "sdmmc1_dat0_py7", - "sdmmc1_dat1_py6", - "sdmmc1_dat2_py5", - "sdmmc1_dat3_py4"; - nvidia,function = "sdmmc1"; - nvidia,pull = <2>; - nvidia,tristate = <0>; - }; - sdmmc4_clk_pcc4 { - nvidia,pins = "sdmmc4_clk_pcc4", - "sdmmc4_rst_n_pcc3"; - nvidia,function = "sdmmc4"; - nvidia,pull = <0>; - nvidia,tristate = <0>; - }; - sdmmc4_dat0_paa0 { - nvidia,pins = "sdmmc4_dat0_paa0", - "sdmmc4_dat1_paa1", - "sdmmc4_dat2_paa2", - "sdmmc4_dat3_paa3", - "sdmmc4_dat4_paa4", - "sdmmc4_dat5_paa5", - "sdmmc4_dat6_paa6", - "sdmmc4_dat7_paa7"; - nvidia,function = "sdmmc4"; - nvidia,pull = <2>; - nvidia,tristate = <0>; - }; - dap2_fs_pa2 { - nvidia,pins = "dap2_fs_pa2", - "dap2_sclk_pa3", - "dap2_din_pa4", - "dap2_dout_pa5"; - nvidia,function = "i2s1"; - nvidia,pull = <0>; - nvidia,tristate = <0>; - }; - }; - }; - - serial@70006000 { - status = "okay"; - clock-frequency = <408000000>; - }; - - i2c@7000c000 { - status = "okay"; - clock-frequency = <100000>; - }; - - i2c@7000c400 { - status = "okay"; - clock-frequency = <100000>; - }; - - i2c@7000c500 { - status = "okay"; - clock-frequency = <100000>; - - /* ALS and Proximity sensor */ - isl29028@44 { - compatible = "isil,isl29028"; - reg = <0x44>; - interrupt-parent = <&gpio>; - interrupts = <88 0x04>; /*gpio PL0 */ - }; - }; - - i2c@7000c700 { - status = "okay"; - clock-frequency = <100000>; - }; - - i2c@7000d000 { - status = "okay"; - clock-frequency = <100000>; - - wm8903: wm8903@1a { - compatible = "wlf,wm8903"; - reg = <0x1a>; - interrupt-parent = <&gpio>; - interrupts = <179 0x04>; /* gpio PW3 */ - - gpio-controller; - #gpio-cells = <2>; - - micdet-cfg = <0>; - micdet-delay = <100>; - gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>; - }; - - tps62361 { - compatible = "ti,tps62361"; - reg = <0x60>; - - regulator-name = "tps62361-vout"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1500000>; - regulator-boot-on; - regulator-always-on; - ti,vsel0-state-high; - ti,vsel1-state-high; - }; - }; - - ahub { - i2s@70080400 { - status = "okay"; - }; - }; - - sdhci@78000000 { - status = "okay"; - cd-gpios = <&gpio 69 0>; /* gpio PI5 */ - wp-gpios = <&gpio 155 0>; /* gpio PT3 */ - power-gpios = <&gpio 31 0>; /* gpio PD7 */ - bus-width = <4>; - }; - - sdhci@78000600 { - status = "okay"; - bus-width = <8>; - }; - - sound { - compatible = "nvidia,tegra-audio-wm8903-cardhu", - "nvidia,tegra-audio-wm8903"; - nvidia,model = "NVIDIA Tegra Cardhu"; - - nvidia,audio-routing = - "Headphone Jack", "HPOUTR", - "Headphone Jack", "HPOUTL", - "Int Spk", "ROP", - "Int Spk", "RON", - "Int Spk", "LOP", - "Int Spk", "LON", - "Mic Jack", "MICBIAS", - "IN1L", "Mic Jack"; - - nvidia,i2s-controller = <&tegra_i2s1>; - nvidia,audio-codec = <&wm8903>; - - nvidia,spkr-en-gpios = <&wm8903 2 0>; - nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ - }; -}; diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts deleted file mode 100644 index f146dbf6f7f8..000000000000 --- a/arch/arm/boot/dts/tegra-harmony.dts +++ /dev/null @@ -1,336 +0,0 @@ -/dts-v1/; - -/include/ "tegra20.dtsi" - -/ { - model = "NVIDIA Tegra2 Harmony evaluation board"; - compatible = "nvidia,harmony", "nvidia,tegra20"; - - memory { - reg = <0x00000000 0x40000000>; - }; - - pinmux { - pinctrl-names = "default"; - pinctrl-0 = <&state_default>; - - state_default: pinmux { - ata { - nvidia,pins = "ata"; - nvidia,function = "ide"; - }; - atb { - nvidia,pins = "atb", "gma", "gme"; - nvidia,function = "sdio4"; - }; - atc { - nvidia,pins = "atc"; - nvidia,function = "nand"; - }; - atd { - nvidia,pins = "atd", "ate", "gmb", "gmd", "gpu", - "spia", "spib", "spic"; - nvidia,function = "gmi"; - }; - cdev1 { - nvidia,pins = "cdev1"; - nvidia,function = "plla_out"; - }; - cdev2 { - nvidia,pins = "cdev2"; - nvidia,function = "pllp_out4"; - }; - crtp { - nvidia,pins = "crtp"; - nvidia,function = "crt"; - }; - csus { - nvidia,pins = "csus"; - nvidia,function = "vi_sensor_clk"; - }; - dap1 { - nvidia,pins = "dap1"; - nvidia,function = "dap1"; - }; - dap2 { - nvidia,pins = "dap2"; - nvidia,function = "dap2"; - }; - dap3 { - nvidia,pins = "dap3"; - nvidia,function = "dap3"; - }; - dap4 { - nvidia,pins = "dap4"; - nvidia,function = "dap4"; - }; - ddc { - nvidia,pins = "ddc"; - nvidia,function = "i2c2"; - }; - dta { - nvidia,pins = "dta", "dtd"; - nvidia,function = "sdio2"; - }; - dtb { - nvidia,pins = "dtb", "dtc", "dte"; - nvidia,function = "rsvd1"; - }; - dtf { - nvidia,pins = "dtf"; - nvidia,function = "i2c3"; - }; - gmc { - nvidia,pins = "gmc"; - nvidia,function = "uartd"; - }; - gpu7 { - nvidia,pins = "gpu7"; - nvidia,function = "rtck"; - }; - gpv { - nvidia,pins = "gpv", "slxa", "slxk"; - nvidia,function = "pcie"; - }; - hdint { - nvidia,pins = "hdint", "pta"; - nvidia,function = "hdmi"; - }; - i2cp { - nvidia,pins = "i2cp"; - nvidia,function = "i2cp"; - }; - irrx { - nvidia,pins = "irrx", "irtx"; - nvidia,function = "uarta"; - }; - kbca { - nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", - "kbce", "kbcf"; - nvidia,function = "kbc"; - }; - lcsn { - nvidia,pins = "lcsn", "ld0", "ld1", "ld2", - "ld3", "ld4", "ld5", "ld6", "ld7", - "ld8", "ld9", "ld10", "ld11", "ld12", - "ld13", "ld14", "ld15", "ld16", "ld17", - "ldc", "ldi", "lhp0", "lhp1", "lhp2", - "lhs", "lm0", "lm1", "lpp", "lpw0", - "lpw1", "lpw2", "lsc0", "lsc1", "lsck", - "lsda", "lsdi", "lspi", "lvp0", "lvp1", - "lvs"; - nvidia,function = "displaya"; - }; - owc { - nvidia,pins = "owc", "spdi", "spdo", "uac"; - nvidia,function = "rsvd2"; - }; - pmc { - nvidia,pins = "pmc"; - nvidia,function = "pwr_on"; - }; - rm { - nvidia,pins = "rm"; - nvidia,function = "i2c1"; - }; - sdb { - nvidia,pins = "sdb", "sdc", "sdd"; - nvidia,function = "pwm"; - }; - sdio1 { - nvidia,pins = "sdio1"; - nvidia,function = "sdio1"; - }; - slxc { - nvidia,pins = "slxc", "slxd"; - nvidia,function = "spdif"; - }; - spid { - nvidia,pins = "spid", "spie", "spif"; - nvidia,function = "spi1"; - }; - spig { - nvidia,pins = "spig", "spih"; - nvidia,function = "spi2_alt"; - }; - uaa { - nvidia,pins = "uaa", "uab", "uda"; - nvidia,function = "ulpi"; - }; - uad { - nvidia,pins = "uad"; - nvidia,function = "irda"; - }; - uca { - nvidia,pins = "uca", "ucb"; - nvidia,function = "uartc"; - }; - conf_ata { - nvidia,pins = "ata", "atb", "atc", "atd", "ate", - "cdev1", "cdev2", "dap1", "dtb", "gma", - "gmb", "gmc", "gmd", "gme", "gpu7", - "gpv", "i2cp", "pta", "rm", "slxa", - "slxk", "spia", "spib", "uac"; - nvidia,pull = <0>; - nvidia,tristate = <0>; - }; - conf_ck32 { - nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", - "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; - nvidia,pull = <0>; - }; - conf_csus { - nvidia,pins = "csus", "spid", "spif"; - nvidia,pull = <1>; - nvidia,tristate = <1>; - }; - conf_crtp { - nvidia,pins = "crtp", "dap2", "dap3", "dap4", - "dtc", "dte", "dtf", "gpu", "sdio1", - "slxc", "slxd", "spdi", "spdo", "spig", - "uda"; - nvidia,pull = <0>; - nvidia,tristate = <1>; - }; - conf_ddc { - nvidia,pins = "ddc", "dta", "dtd", "kbca", - "kbcb", "kbcc", "kbcd", "kbce", "kbcf", - "sdc"; - nvidia,pull = <2>; - nvidia,tristate = <0>; - }; - conf_hdint { - nvidia,pins = "hdint", "lcsn", "ldc", "lm1", - "lpw1", "lsc1", "lsck", "lsda", "lsdi", - "lvp0", "owc", "sdb"; - nvidia,tristate = <1>; - }; - conf_irrx { - nvidia,pins = "irrx", "irtx", "sdd", "spic", - "spie", "spih", "uaa", "uab", "uad", - "uca", "ucb"; - nvidia,pull = <2>; - nvidia,tristate = <1>; - }; - conf_lc { - nvidia,pins = "lc", "ls"; - nvidia,pull = <2>; - }; - conf_ld0 { - nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", - "ld5", "ld6", "ld7", "ld8", "ld9", - "ld10", "ld11", "ld12", "ld13", "ld14", - "ld15", "ld16", "ld17", "ldi", "lhp0", - "lhp1", "lhp2", "lhs", "lm0", "lpp", - "lpw0", "lpw2", "lsc0", "lspi", "lvp1", - "lvs", "pmc"; - nvidia,tristate = <0>; - }; - conf_ld17_0 { - nvidia,pins = "ld17_0", "ld19_18", "ld21_20", - "ld23_22"; - nvidia,pull = <1>; - }; - }; - }; - - i2s@70002800 { - status = "okay"; - }; - - serial@70006300 { - status = "okay"; - clock-frequency = <216000000>; - }; - - i2c@7000c000 { - status = "okay"; - clock-frequency = <400000>; - - wm8903: wm8903@1a { - compatible = "wlf,wm8903"; - reg = <0x1a>; - interrupt-parent = <&gpio>; - interrupts = <187 0x04>; - - gpio-controller; - #gpio-cells = <2>; - - micdet-cfg = <0>; - micdet-delay = <100>; - gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>; - }; - }; - - i2c@7000c400 { - status = "okay"; - clock-frequency = <400000>; - }; - - i2c@7000c500 { - status = "okay"; - clock-frequency = <400000>; - }; - - i2c@7000d000 { - status = "okay"; - clock-frequency = <400000>; - }; - - pmc { - nvidia,invert-interrupt; - }; - - usb@c5000000 { - status = "okay"; - }; - - usb@c5004000 { - status = "okay"; - nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ - }; - - usb@c5008000 { - status = "okay"; - }; - - sdhci@c8000200 { - status = "okay"; - cd-gpios = <&gpio 69 0>; /* gpio PI5 */ - wp-gpios = <&gpio 57 0>; /* gpio PH1 */ - power-gpios = <&gpio 155 0>; /* gpio PT3 */ - bus-width = <4>; - }; - - sdhci@c8000600 { - status = "okay"; - cd-gpios = <&gpio 58 0>; /* gpio PH2 */ - wp-gpios = <&gpio 59 0>; /* gpio PH3 */ - power-gpios = <&gpio 70 0>; /* gpio PI6 */ - bus-width = <8>; - }; - - sound { - compatible = "nvidia,tegra-audio-wm8903-harmony", - "nvidia,tegra-audio-wm8903"; - nvidia,model = "NVIDIA Tegra Harmony"; - - nvidia,audio-routing = - "Headphone Jack", "HPOUTR", - "Headphone Jack", "HPOUTL", - "Int Spk", "ROP", - "Int Spk", "RON", - "Int Spk", "LOP", - "Int Spk", "LON", - "Mic Jack", "MICBIAS", - "IN1L", "Mic Jack"; - - nvidia,i2s-controller = <&tegra_i2s1>; - nvidia,audio-codec = <&wm8903>; - - nvidia,spkr-en-gpios = <&wm8903 2 0>; - nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ - nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */ - nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */ - }; -}; diff --git a/arch/arm/boot/dts/tegra-paz00.dts b/arch/arm/boot/dts/tegra-paz00.dts deleted file mode 100644 index 684a9e1ff7e9..000000000000 --- a/arch/arm/boot/dts/tegra-paz00.dts +++ /dev/null @@ -1,347 +0,0 @@ -/dts-v1/; - -/include/ "tegra20.dtsi" - -/ { - model = "Toshiba AC100 / Dynabook AZ"; - compatible = "compal,paz00", "nvidia,tegra20"; - - memory { - reg = <0x00000000 0x20000000>; - }; - - pinmux { - pinctrl-names = "default"; - pinctrl-0 = <&state_default>; - - state_default: pinmux { - ata { - nvidia,pins = "ata", "atc", "atd", "ate", - "dap2", "gmb", "gmc", "gmd", "spia", - "spib", "spic", "spid", "spie"; - nvidia,function = "gmi"; - }; - atb { - nvidia,pins = "atb", "gma", "gme"; - nvidia,function = "sdio4"; - }; - cdev1 { - nvidia,pins = "cdev1"; - nvidia,function = "plla_out"; - }; - cdev2 { - nvidia,pins = "cdev2"; - nvidia,function = "pllp_out4"; - }; - crtp { - nvidia,pins = "crtp"; - nvidia,function = "crt"; - }; - csus { - nvidia,pins = "csus"; - nvidia,function = "pllc_out1"; - }; - dap1 { - nvidia,pins = "dap1"; - nvidia,function = "dap1"; - }; - dap3 { - nvidia,pins = "dap3"; - nvidia,function = "dap3"; - }; - dap4 { - nvidia,pins = "dap4"; - nvidia,function = "dap4"; - }; - ddc { - nvidia,pins = "ddc"; - nvidia,function = "i2c2"; - }; - dta { - nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte"; - nvidia,function = "rsvd1"; - }; - dtf { - nvidia,pins = "dtf"; - nvidia,function = "i2c3"; - }; - gpu { - nvidia,pins = "gpu", "sdb", "sdd"; - nvidia,function = "pwm"; - }; - gpu7 { - nvidia,pins = "gpu7"; - nvidia,function = "rtck"; - }; - gpv { - nvidia,pins = "gpv", "slxa", "slxk"; - nvidia,function = "pcie"; - }; - hdint { - nvidia,pins = "hdint", "pta"; - nvidia,function = "hdmi"; - }; - i2cp { - nvidia,pins = "i2cp"; - nvidia,function = "i2cp"; - }; - irrx { - nvidia,pins = "irrx", "irtx"; - nvidia,function = "uarta"; - }; - kbca { - nvidia,pins = "kbca", "kbcc", "kbce", "kbcf"; - nvidia,function = "kbc"; - }; - kbcb { - nvidia,pins = "kbcb", "kbcd"; - nvidia,function = "sdio2"; - }; - lcsn { - nvidia,pins = "lcsn", "ld0", "ld1", "ld2", - "ld3", "ld4", "ld5", "ld6", "ld7", - "ld8", "ld9", "ld10", "ld11", "ld12", - "ld13", "ld14", "ld15", "ld16", "ld17", - "ldc", "ldi", "lhp0", "lhp1", "lhp2", - "lhs", "lm0", "lm1", "lpp", "lpw0", - "lpw1", "lpw2", "lsc0", "lsc1", "lsck", - "lsda", "lsdi", "lspi", "lvp0", "lvp1", - "lvs"; - nvidia,function = "displaya"; - }; - owc { - nvidia,pins = "owc"; - nvidia,function = "owr"; - }; - pmc { - nvidia,pins = "pmc"; - nvidia,function = "pwr_on"; - }; - rm { - nvidia,pins = "rm"; - nvidia,function = "i2c1"; - }; - sdc { - nvidia,pins = "sdc"; - nvidia,function = "twc"; - }; - sdio1 { - nvidia,pins = "sdio1"; - nvidia,function = "sdio1"; - }; - slxc { - nvidia,pins = "slxc", "slxd"; - nvidia,function = "spi4"; - }; - spdi { - nvidia,pins = "spdi", "spdo"; - nvidia,function = "rsvd2"; - }; - spif { - nvidia,pins = "spif", "uac"; - nvidia,function = "rsvd4"; - }; - spig { - nvidia,pins = "spig", "spih"; - nvidia,function = "spi2_alt"; - }; - uaa { - nvidia,pins = "uaa", "uab", "uda"; - nvidia,function = "ulpi"; - }; - uad { - nvidia,pins = "uad"; - nvidia,function = "spdif"; - }; - uca { - nvidia,pins = "uca", "ucb"; - nvidia,function = "uartc"; - }; - conf_ata { - nvidia,pins = "ata", "atb", "atc", "atd", "ate", - "cdev1", "cdev2", "dap1", "dap2", "dtf", - "gma", "gmb", "gmc", "gmd", "gme", - "gpu", "gpu7", "gpv", "i2cp", "pta", - "rm", "sdio1", "slxk", "spdo", "uac", - "uda"; - nvidia,pull = <0>; - nvidia,tristate = <0>; - }; - conf_ck32 { - nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", - "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; - nvidia,pull = <0>; - }; - conf_crtp { - nvidia,pins = "crtp", "dap3", "dap4", "dtb", - "dtc", "dte", "slxa", "slxc", "slxd", - "spdi"; - nvidia,pull = <0>; - nvidia,tristate = <1>; - }; - conf_csus { - nvidia,pins = "csus", "spia", "spib", "spid", - "spif"; - nvidia,pull = <1>; - nvidia,tristate = <1>; - }; - conf_ddc { - nvidia,pins = "ddc", "irrx", "irtx", "kbca", - "kbcb", "kbcc", "kbcd", "kbce", "kbcf", - "spic", "spig", "uaa", "uab"; - nvidia,pull = <2>; - nvidia,tristate = <0>; - }; - conf_dta { - nvidia,pins = "dta", "dtd", "owc", "sdc", "sdd", - "spie", "spih", "uad", "uca", "ucb"; - nvidia,pull = <2>; - nvidia,tristate = <1>; - }; - conf_hdint { - nvidia,pins = "hdint", "ld0", "ld1", "ld2", - "ld3", "ld4", "ld5", "ld6", "ld7", - "ld8", "ld9", "ld10", "ld11", "ld12", - "ld13", "ld14", "ld15", "ld16", "ld17", - "ldc", "ldi", "lhs", "lsc0", "lspi", - "lvs", "pmc"; - nvidia,tristate = <0>; - }; - conf_lc { - nvidia,pins = "lc", "ls"; - nvidia,pull = <2>; - }; - conf_lcsn { - nvidia,pins = "lcsn", "lhp0", "lhp1", "lhp2", - "lm0", "lm1", "lpp", "lpw0", "lpw1", - "lpw2", "lsc1", "lsck", "lsda", "lsdi", - "lvp0", "lvp1", "sdb"; - nvidia,tristate = <1>; - }; - conf_ld17_0 { - nvidia,pins = "ld17_0", "ld19_18", "ld21_20", - "ld23_22"; - nvidia,pull = <1>; - }; - }; - }; - - i2s@70002800 { - status = "okay"; - }; - - serial@70006000 { - status = "okay"; - clock-frequency = <216000000>; - }; - - serial@70006200 { - status = "okay"; - clock-frequency = <216000000>; - }; - - i2c@7000c000 { - status = "okay"; - clock-frequency = <400000>; - - alc5632: alc5632@1e { - compatible = "realtek,alc5632"; - reg = <0x1e>; - gpio-controller; - #gpio-cells = <2>; - }; - }; - - i2c@7000c400 { - status = "okay"; - clock-frequency = <400000>; - }; - - nvec { - compatible = "nvidia,nvec"; - reg = <0x7000c500 0x100>; - interrupts = <0 92 0x04>; - #address-cells = <1>; - #size-cells = <0>; - clock-frequency = <80000>; - request-gpios = <&gpio 170 0>; /* gpio PV2 */ - slave-addr = <138>; - }; - - i2c@7000d000 { - status = "okay"; - clock-frequency = <400000>; - - adt7461@4c { - compatible = "adi,adt7461"; - reg = <0x4c>; - }; - }; - - usb@c5000000 { - status = "okay"; - }; - - usb@c5004000 { - status = "okay"; - nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ - }; - - usb@c5008000 { - status = "okay"; - }; - - sdhci@c8000000 { - status = "okay"; - cd-gpios = <&gpio 173 0>; /* gpio PV5 */ - wp-gpios = <&gpio 57 0>; /* gpio PH1 */ - power-gpios = <&gpio 169 0>; /* gpio PV1 */ - bus-width = <4>; - }; - - sdhci@c8000600 { - status = "okay"; - bus-width = <8>; - }; - - gpio-keys { - compatible = "gpio-keys"; - - power { - label = "Power"; - gpios = <&gpio 79 1>; /* gpio PJ7, active low */ - linux,code = <116>; /* KEY_POWER */ - gpio-key,wakeup; - }; - }; - - gpio-leds { - compatible = "gpio-leds"; - - wifi { - label = "wifi-led"; - gpios = <&gpio 24 0>; /* gpio PD0 */ - linux,default-trigger = "rfkill0"; - }; - }; - - sound { - compatible = "nvidia,tegra-audio-alc5632-paz00", - "nvidia,tegra-audio-alc5632"; - - nvidia,model = "Compal PAZ00"; - - nvidia,audio-routing = - "Int Spk", "SPKOUT", - "Int Spk", "SPKOUTN", - "Headset Mic", "MICBIAS1", - "MIC1", "Headset Mic", - "Headset Stereophone", "HPR", - "Headset Stereophone", "HPL", - "DMICDAT", "Digital Mic"; - - nvidia,audio-codec = <&alc5632>; - nvidia,i2s-controller = <&tegra_i2s1>; - nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ - }; -}; diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts deleted file mode 100644 index b797901d040d..000000000000 --- a/arch/arm/boot/dts/tegra-seaboard.dts +++ /dev/null @@ -1,444 +0,0 @@ -/dts-v1/; - -/include/ "tegra20.dtsi" - -/ { - model = "NVIDIA Seaboard"; - compatible = "nvidia,seaboard", "nvidia,tegra20"; - - memory { - reg = <0x00000000 0x40000000>; - }; - - pinmux { - pinctrl-names = "default"; - pinctrl-0 = <&state_default>; - - state_default: pinmux { - ata { - nvidia,pins = "ata"; - nvidia,function = "ide"; - }; - atb { - nvidia,pins = "atb", "gma", "gme"; - nvidia,function = "sdio4"; - }; - atc { - nvidia,pins = "atc"; - nvidia,function = "nand"; - }; - atd { - nvidia,pins = "atd", "ate", "gmb", "spia", - "spib", "spic"; - nvidia,function = "gmi"; - }; - cdev1 { - nvidia,pins = "cdev1"; - nvidia,function = "plla_out"; - }; - cdev2 { - nvidia,pins = "cdev2"; - nvidia,function = "pllp_out4"; - }; - crtp { - nvidia,pins = "crtp", "lm1"; - nvidia,function = "crt"; - }; - csus { - nvidia,pins = "csus"; - nvidia,function = "vi_sensor_clk"; - }; - dap1 { - nvidia,pins = "dap1"; - nvidia,function = "dap1"; - }; - dap2 { - nvidia,pins = "dap2"; - nvidia,function = "dap2"; - }; - dap3 { - nvidia,pins = "dap3"; - nvidia,function = "dap3"; - }; - dap4 { - nvidia,pins = "dap4"; - nvidia,function = "dap4"; - }; - ddc { - nvidia,pins = "ddc", "owc", "spdi", "spdo", - "uac"; - nvidia,function = "rsvd2"; - }; - dta { - nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte"; - nvidia,function = "vi"; - }; - dtf { - nvidia,pins = "dtf"; - nvidia,function = "i2c3"; - }; - gmc { - nvidia,pins = "gmc"; - nvidia,function = "uartd"; - }; - gmd { - nvidia,pins = "gmd"; - nvidia,function = "sflash"; - }; - gpu { - nvidia,pins = "gpu"; - nvidia,function = "pwm"; - }; - gpu7 { - nvidia,pins = "gpu7"; - nvidia,function = "rtck"; - }; - gpv { - nvidia,pins = "gpv", "slxa", "slxk"; - nvidia,function = "pcie"; - }; - hdint { - nvidia,pins = "hdint", "lpw0", "lpw2", "lsc1", - "lsck", "lsda"; - nvidia,function = "hdmi"; - }; - i2cp { - nvidia,pins = "i2cp"; - nvidia,function = "i2cp"; - }; - irrx { - nvidia,pins = "irrx", "irtx"; - nvidia,function = "uartb"; - }; - kbca { - nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", - "kbce", "kbcf"; - nvidia,function = "kbc"; - }; - lcsn { - nvidia,pins = "lcsn", "ldc", "lm0", "lpw1", - "lsdi", "lvp0"; - nvidia,function = "rsvd4"; - }; - ld0 { - nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", - "ld5", "ld6", "ld7", "ld8", "ld9", - "ld10", "ld11", "ld12", "ld13", "ld14", - "ld15", "ld16", "ld17", "ldi", "lhp0", - "lhp1", "lhp2", "lhs", "lpp", "lsc0", - "lspi", "lvp1", "lvs"; - nvidia,function = "displaya"; - }; - pmc { - nvidia,pins = "pmc"; - nvidia,function = "pwr_on"; - }; - pta { - nvidia,pins = "pta"; - nvidia,function = "i2c2"; - }; - rm { - nvidia,pins = "rm"; - nvidia,function = "i2c1"; - }; - sdb { - nvidia,pins = "sdb", "sdc", "sdd"; - nvidia,function = "sdio3"; - }; - sdio1 { - nvidia,pins = "sdio1"; - nvidia,function = "sdio1"; - }; - slxc { - nvidia,pins = "slxc", "slxd"; - nvidia,function = "spdif"; - }; - spid { - nvidia,pins = "spid", "spie", "spif"; - nvidia,function = "spi1"; - }; - spig { - nvidia,pins = "spig", "spih"; - nvidia,function = "spi2_alt"; - }; - uaa { - nvidia,pins = "uaa", "uab", "uda"; - nvidia,function = "ulpi"; - }; - uad { - nvidia,pins = "uad"; - nvidia,function = "irda"; - }; - uca { - nvidia,pins = "uca", "ucb"; - nvidia,function = "uartc"; - }; - conf_ata { - nvidia,pins = "ata", "atb", "atc", "atd", - "cdev1", "cdev2", "dap1", "dap2", - "dap4", "dtf", "gma", "gmc", "gmd", - "gme", "gpu", "gpu7", "i2cp", "irrx", - "irtx", "pta", "rm", "sdc", "sdd", - "slxd", "slxk", "spdi", "spdo", "uac", - "uad", "uca", "ucb", "uda"; - nvidia,pull = <0>; - nvidia,tristate = <0>; - }; - conf_ate { - nvidia,pins = "ate", "csus", "dap3", "ddc", - "gpv", "owc", "slxc", "spib", "spid", - "spie"; - nvidia,pull = <0>; - nvidia,tristate = <1>; - }; - conf_ck32 { - nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", - "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; - nvidia,pull = <0>; - }; - conf_crtp { - nvidia,pins = "crtp", "gmb", "slxa", "spia", - "spig", "spih"; - nvidia,pull = <2>; - nvidia,tristate = <1>; - }; - conf_dta { - nvidia,pins = "dta", "dtb", "dtc", "dtd"; - nvidia,pull = <1>; - nvidia,tristate = <0>; - }; - conf_dte { - nvidia,pins = "dte", "spif"; - nvidia,pull = <1>; - nvidia,tristate = <1>; - }; - conf_hdint { - nvidia,pins = "hdint", "lcsn", "ldc", "lm1", - "lpw1", "lsc1", "lsck", "lsda", "lsdi", - "lvp0"; - nvidia,tristate = <1>; - }; - conf_kbca { - nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", - "kbce", "kbcf", "sdio1", "spic", "uaa", - "uab"; - nvidia,pull = <2>; - nvidia,tristate = <0>; - }; - conf_lc { - nvidia,pins = "lc", "ls"; - nvidia,pull = <2>; - }; - conf_ld0 { - nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", - "ld5", "ld6", "ld7", "ld8", "ld9", - "ld10", "ld11", "ld12", "ld13", "ld14", - "ld15", "ld16", "ld17", "ldi", "lhp0", - "lhp1", "lhp2", "lhs", "lm0", "lpp", - "lpw0", "lpw2", "lsc0", "lspi", "lvp1", - "lvs", "pmc", "sdb"; - nvidia,tristate = <0>; - }; - conf_ld17_0 { - nvidia,pins = "ld17_0", "ld19_18", "ld21_20", - "ld23_22"; - nvidia,pull = <1>; - }; - drive_sdio1 { - nvidia,pins = "drive_sdio1"; - nvidia,high-speed-mode = <0>; - nvidia,schmitt = <0>; - nvidia,low-power-mode = <3>; - nvidia,pull-down-strength = <31>; - nvidia,pull-up-strength = <31>; - nvidia,slew-rate-rising = <3>; - nvidia,slew-rate-falling = <3>; - }; - }; - }; - - i2s@70002800 { - status = "okay"; - }; - - serial@70006300 { - status = "okay"; - clock-frequency = <216000000>; - }; - - i2c@7000c000 { - status = "okay"; - clock-frequency = <400000>; - - wm8903: wm8903@1a { - compatible = "wlf,wm8903"; - reg = <0x1a>; - interrupt-parent = <&gpio>; - interrupts = <187 0x04>; - - gpio-controller; - #gpio-cells = <2>; - - micdet-cfg = <0>; - micdet-delay = <100>; - gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>; - }; - - /* ALS and proximity sensor */ - isl29018@44 { - compatible = "isil,isl29018"; - reg = <0x44>; - interrupt-parent = <&gpio>; - interrupts = <202 0x04>; /* GPIO PZ2 */ - }; - - gyrometer@68 { - compatible = "invn,mpu3050"; - reg = <0x68>; - interrupt-parent = <&gpio>; - interrupts = <204 0x04>; /* gpio PZ4 */ - }; - }; - - i2c@7000c400 { - status = "okay"; - clock-frequency = <100000>; - - smart-battery@b { - compatible = "ti,bq20z75", "smart-battery-1.1"; - reg = <0xb>; - ti,i2c-retry-count = <2>; - ti,poll-retry-count = <10>; - }; - }; - - i2c@7000c500 { - status = "okay"; - clock-frequency = <400000>; - }; - - i2c@7000d000 { - status = "okay"; - clock-frequency = <400000>; - - temperature-sensor@4c { - compatible = "nct1008"; - reg = <0x4c>; - }; - - magnetometer@c { - compatible = "ak8975"; - reg = <0xc>; - interrupt-parent = <&gpio>; - interrupts = <109 0x04>; /* gpio PN5 */ - }; - }; - - memory-controller@0x7000f400 { - emc-table@190000 { - reg = <190000>; - compatible = "nvidia,tegra20-emc-table"; - clock-frequency = <190000>; - nvidia,emc-registers = <0x0000000c 0x00000026 - 0x00000009 0x00000003 0x00000004 0x00000004 - 0x00000002 0x0000000c 0x00000003 0x00000003 - 0x00000002 0x00000001 0x00000004 0x00000005 - 0x00000004 0x00000009 0x0000000d 0x0000059f - 0x00000000 0x00000003 0x00000003 0x00000003 - 0x00000003 0x00000001 0x0000000b 0x000000c8 - 0x00000003 0x00000007 0x00000004 0x0000000f - 0x00000002 0x00000000 0x00000000 0x00000002 - 0x00000000 0x00000000 0x00000083 0xa06204ae - 0x007dc010 0x00000000 0x00000000 0x00000000 - 0x00000000 0x00000000 0x00000000 0x00000000>; - }; - - emc-table@380000 { - reg = <380000>; - compatible = "nvidia,tegra20-emc-table"; - clock-frequency = <380000>; - nvidia,emc-registers = <0x00000017 0x0000004b - 0x00000012 0x00000006 0x00000004 0x00000005 - 0x00000003 0x0000000c 0x00000006 0x00000006 - 0x00000003 0x00000001 0x00000004 0x00000005 - 0x00000004 0x00000009 0x0000000d 0x00000b5f - 0x00000000 0x00000003 0x00000003 0x00000006 - 0x00000006 0x00000001 0x00000011 0x000000c8 - 0x00000003 0x0000000e 0x00000007 0x0000000f - 0x00000002 0x00000000 0x00000000 0x00000002 - 0x00000000 0x00000000 0x00000083 0xe044048b - 0x007d8010 0x00000000 0x00000000 0x00000000 - 0x00000000 0x00000000 0x00000000 0x00000000>; - }; - }; - - usb@c5000000 { - status = "okay"; - nvidia,vbus-gpio = <&gpio 24 0>; /* PD0 */ - dr_mode = "otg"; - }; - - usb@c5004000 { - status = "okay"; - nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ - }; - - usb@c5008000 { - status = "okay"; - }; - - sdhci@c8000400 { - status = "okay"; - cd-gpios = <&gpio 69 0>; /* gpio PI5 */ - wp-gpios = <&gpio 57 0>; /* gpio PH1 */ - power-gpios = <&gpio 70 0>; /* gpio PI6 */ - bus-width = <4>; - }; - - sdhci@c8000600 { - status = "okay"; - bus-width = <8>; - }; - - gpio-keys { - compatible = "gpio-keys"; - - power { - label = "Power"; - gpios = <&gpio 170 1>; /* gpio PV2, active low */ - linux,code = <116>; /* KEY_POWER */ - gpio-key,wakeup; - }; - - lid { - label = "Lid"; - gpios = <&gpio 23 0>; /* gpio PC7 */ - linux,input-type = <5>; /* EV_SW */ - linux,code = <0>; /* SW_LID */ - debounce-interval = <1>; - gpio-key,wakeup; - }; - }; - - sound { - compatible = "nvidia,tegra-audio-wm8903-seaboard", - "nvidia,tegra-audio-wm8903"; - nvidia,model = "NVIDIA Tegra Seaboard"; - - nvidia,audio-routing = - "Headphone Jack", "HPOUTR", - "Headphone Jack", "HPOUTL", - "Int Spk", "ROP", - "Int Spk", "RON", - "Int Spk", "LOP", - "Int Spk", "LON", - "Mic Jack", "MICBIAS", - "IN1R", "Mic Jack"; - - nvidia,i2s-controller = <&tegra_i2s1>; - nvidia,audio-codec = <&wm8903>; - - nvidia,spkr-en-gpios = <&wm8903 2 0>; - nvidia,hp-det-gpios = <&gpio 185 0>; /* gpio PX1 */ - }; -}; diff --git a/arch/arm/boot/dts/tegra-trimslice.dts b/arch/arm/boot/dts/tegra-trimslice.dts deleted file mode 100644 index 9de5636023f6..000000000000 --- a/arch/arm/boot/dts/tegra-trimslice.dts +++ /dev/null @@ -1,306 +0,0 @@ -/dts-v1/; - -/include/ "tegra20.dtsi" - -/ { - model = "Compulab TrimSlice board"; - compatible = "compulab,trimslice", "nvidia,tegra20"; - - memory { - reg = <0x00000000 0x40000000>; - }; - - pinmux { - pinctrl-names = "default"; - pinctrl-0 = <&state_default>; - - state_default: pinmux { - ata { - nvidia,pins = "ata"; - nvidia,function = "ide"; - }; - atb { - nvidia,pins = "atb", "gma"; - nvidia,function = "sdio4"; - }; - atc { - nvidia,pins = "atc", "gmb"; - nvidia,function = "nand"; - }; - atd { - nvidia,pins = "atd", "ate", "gme", "pta"; - nvidia,function = "gmi"; - }; - cdev1 { - nvidia,pins = "cdev1"; - nvidia,function = "plla_out"; - }; - cdev2 { - nvidia,pins = "cdev2"; - nvidia,function = "pllp_out4"; - }; - crtp { - nvidia,pins = "crtp"; - nvidia,function = "crt"; - }; - csus { - nvidia,pins = "csus"; - nvidia,function = "vi_sensor_clk"; - }; - dap1 { - nvidia,pins = "dap1"; - nvidia,function = "dap1"; - }; - dap2 { - nvidia,pins = "dap2"; - nvidia,function = "dap2"; - }; - dap3 { - nvidia,pins = "dap3"; - nvidia,function = "dap3"; - }; - dap4 { - nvidia,pins = "dap4"; - nvidia,function = "dap4"; - }; - ddc { - nvidia,pins = "ddc"; - nvidia,function = "i2c2"; - }; - dta { - nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte"; - nvidia,function = "vi"; - }; - dtf { - nvidia,pins = "dtf"; - nvidia,function = "i2c3"; - }; - gmc { - nvidia,pins = "gmc", "gmd"; - nvidia,function = "sflash"; - }; - gpu { - nvidia,pins = "gpu"; - nvidia,function = "uarta"; - }; - gpu7 { - nvidia,pins = "gpu7"; - nvidia,function = "rtck"; - }; - gpv { - nvidia,pins = "gpv", "slxa", "slxk"; - nvidia,function = "pcie"; - }; - hdint { - nvidia,pins = "hdint"; - nvidia,function = "hdmi"; - }; - i2cp { - nvidia,pins = "i2cp"; - nvidia,function = "i2cp"; - }; - irrx { - nvidia,pins = "irrx", "irtx"; - nvidia,function = "uartb"; - }; - kbca { - nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", - "kbce", "kbcf"; - nvidia,function = "kbc"; - }; - lcsn { - nvidia,pins = "lcsn", "ld0", "ld1", "ld2", - "ld3", "ld4", "ld5", "ld6", "ld7", - "ld8", "ld9", "ld10", "ld11", "ld12", - "ld13", "ld14", "ld15", "ld16", "ld17", - "ldc", "ldi", "lhp0", "lhp1", "lhp2", - "lhs", "lm0", "lm1", "lpp", "lpw0", - "lpw1", "lpw2", "lsc0", "lsc1", "lsck", - "lsda", "lsdi", "lspi", "lvp0", "lvp1", - "lvs"; - nvidia,function = "displaya"; - }; - owc { - nvidia,pins = "owc", "uac"; - nvidia,function = "rsvd2"; - }; - pmc { - nvidia,pins = "pmc"; - nvidia,function = "pwr_on"; - }; - rm { - nvidia,pins = "rm"; - nvidia,function = "i2c1"; - }; - sdb { - nvidia,pins = "sdb", "sdc", "sdd"; - nvidia,function = "pwm"; - }; - sdio1 { - nvidia,pins = "sdio1"; - nvidia,function = "sdio1"; - }; - slxc { - nvidia,pins = "slxc", "slxd"; - nvidia,function = "sdio3"; - }; - spdi { - nvidia,pins = "spdi", "spdo"; - nvidia,function = "spdif"; - }; - spia { - nvidia,pins = "spia", "spib", "spic"; - nvidia,function = "spi2"; - }; - spid { - nvidia,pins = "spid", "spie", "spif"; - nvidia,function = "spi1"; - }; - spig { - nvidia,pins = "spig", "spih"; - nvidia,function = "spi2_alt"; - }; - uaa { - nvidia,pins = "uaa", "uab", "uda"; - nvidia,function = "ulpi"; - }; - uad { - nvidia,pins = "uad"; - nvidia,function = "irda"; - }; - uca { - nvidia,pins = "uca", "ucb"; - nvidia,function = "uartc"; - }; - conf_ata { - nvidia,pins = "ata", "atc", "atd", "ate", - "crtp", "dap2", "dap3", "dap4", "dta", - "dtb", "dtc", "dtd", "dte", "gmb", - "gme", "i2cp", "pta", "slxc", "slxd", - "spdi", "spdo", "uda"; - nvidia,pull = <0>; - nvidia,tristate = <1>; - }; - conf_atb { - nvidia,pins = "atb", "cdev1", "cdev2", "dap1", - "gma", "gmc", "gmd", "gpu", "gpu7", - "gpv", "sdio1", "slxa", "slxk", "uac"; - nvidia,pull = <0>; - nvidia,tristate = <0>; - }; - conf_ck32 { - nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", - "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; - nvidia,pull = <0>; - }; - conf_csus { - nvidia,pins = "csus", "spia", "spib", - "spid", "spif"; - nvidia,pull = <1>; - nvidia,tristate = <1>; - }; - conf_ddc { - nvidia,pins = "ddc", "dtf", "rm", "sdc", "sdd"; - nvidia,pull = <2>; - nvidia,tristate = <0>; - }; - conf_hdint { - nvidia,pins = "hdint", "lcsn", "ldc", "lm1", - "lpw1", "lsc1", "lsck", "lsda", "lsdi", - "lvp0", "pmc"; - nvidia,tristate = <1>; - }; - conf_irrx { - nvidia,pins = "irrx", "irtx", "kbca", "kbcb", - "kbcc", "kbcd", "kbce", "kbcf", "owc", - "spic", "spie", "spig", "spih", "uaa", - "uab", "uad", "uca", "ucb"; - nvidia,pull = <2>; - nvidia,tristate = <1>; - }; - conf_lc { - nvidia,pins = "lc", "ls"; - nvidia,pull = <2>; - }; - conf_ld0 { - nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", - "ld5", "ld6", "ld7", "ld8", "ld9", - "ld10", "ld11", "ld12", "ld13", "ld14", - "ld15", "ld16", "ld17", "ldi", "lhp0", - "lhp1", "lhp2", "lhs", "lm0", "lpp", - "lpw0", "lpw2", "lsc0", "lspi", "lvp1", - "lvs", "sdb"; - nvidia,tristate = <0>; - }; - conf_ld17_0 { - nvidia,pins = "ld17_0", "ld19_18", "ld21_20", - "ld23_22"; - nvidia,pull = <1>; - }; - }; - }; - - i2s@70002800 { - status = "okay"; - }; - - serial@70006000 { - status = "okay"; - clock-frequency = <216000000>; - }; - - i2c@7000c000 { - status = "okay"; - clock-frequency = <400000>; - }; - - i2c@7000c400 { - status = "okay"; - clock-frequency = <400000>; - }; - - i2c@7000c500 { - status = "okay"; - clock-frequency = <400000>; - - codec: codec@1a { - compatible = "ti,tlv320aic23"; - reg = <0x1a>; - }; - - rtc@56 { - compatible = "emmicro,em3027"; - reg = <0x56>; - }; - }; - - usb@c5000000 { - status = "okay"; - }; - - usb@c5004000 { - nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ - }; - - usb@c5008000 { - status = "okay"; - }; - - sdhci@c8000000 { - status = "okay"; - bus-width = <4>; - }; - - sdhci@c8000600 { - status = "okay"; - cd-gpios = <&gpio 121 0>; /* gpio PP1 */ - wp-gpios = <&gpio 122 0>; /* gpio PP2 */ - bus-width = <4>; - }; - - sound { - compatible = "nvidia,tegra-audio-trimslice"; - nvidia,i2s-controller = <&tegra_i2s1>; - nvidia,audio-codec = <&codec>; - }; -}; diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts deleted file mode 100644 index be90544e6b59..000000000000 --- a/arch/arm/boot/dts/tegra-ventana.dts +++ /dev/null @@ -1,343 +0,0 @@ -/dts-v1/; - -/include/ "tegra20.dtsi" - -/ { - model = "NVIDIA Tegra2 Ventana evaluation board"; - compatible = "nvidia,ventana", "nvidia,tegra20"; - - memory { - reg = <0x00000000 0x40000000>; - }; - - pinmux { - pinctrl-names = "default"; - pinctrl-0 = <&state_default>; - - state_default: pinmux { - ata { - nvidia,pins = "ata"; - nvidia,function = "ide"; - }; - atb { - nvidia,pins = "atb", "gma", "gme"; - nvidia,function = "sdio4"; - }; - atc { - nvidia,pins = "atc"; - nvidia,function = "nand"; - }; - atd { - nvidia,pins = "atd", "ate", "gmb", "spia", - "spib", "spic"; - nvidia,function = "gmi"; - }; - cdev1 { - nvidia,pins = "cdev1"; - nvidia,function = "plla_out"; - }; - cdev2 { - nvidia,pins = "cdev2"; - nvidia,function = "pllp_out4"; - }; - crtp { - nvidia,pins = "crtp", "lm1"; - nvidia,function = "crt"; - }; - csus { - nvidia,pins = "csus"; - nvidia,function = "vi_sensor_clk"; - }; - dap1 { - nvidia,pins = "dap1"; - nvidia,function = "dap1"; - }; - dap2 { - nvidia,pins = "dap2"; - nvidia,function = "dap2"; - }; - dap3 { - nvidia,pins = "dap3"; - nvidia,function = "dap3"; - }; - dap4 { - nvidia,pins = "dap4"; - nvidia,function = "dap4"; - }; - ddc { - nvidia,pins = "ddc", "owc", "spdi", "spdo", - "uac"; - nvidia,function = "rsvd2"; - }; - dta { - nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte"; - nvidia,function = "vi"; - }; - dtf { - nvidia,pins = "dtf"; - nvidia,function = "i2c3"; - }; - gmc { - nvidia,pins = "gmc"; - nvidia,function = "uartd"; - }; - gmd { - nvidia,pins = "gmd"; - nvidia,function = "sflash"; - }; - gpu { - nvidia,pins = "gpu"; - nvidia,function = "pwm"; - }; - gpu7 { - nvidia,pins = "gpu7"; - nvidia,function = "rtck"; - }; - gpv { - nvidia,pins = "gpv", "slxa", "slxk"; - nvidia,function = "pcie"; - }; - hdint { - nvidia,pins = "hdint", "pta"; - nvidia,function = "hdmi"; - }; - i2cp { - nvidia,pins = "i2cp"; - nvidia,function = "i2cp"; - }; - irrx { - nvidia,pins = "irrx", "irtx"; - nvidia,function = "uartb"; - }; - kbca { - nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", - "kbce", "kbcf"; - nvidia,function = "kbc"; - }; - lcsn { - nvidia,pins = "lcsn", "ldc", "lm0", "lpw1", - "lsdi", "lvp0"; - nvidia,function = "rsvd4"; - }; - ld0 { - nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", - "ld5", "ld6", "ld7", "ld8", "ld9", - "ld10", "ld11", "ld12", "ld13", "ld14", - "ld15", "ld16", "ld17", "ldi", "lhp0", - "lhp1", "lhp2", "lhs", "lpp", "lpw0", - "lpw2", "lsc0", "lsc1", "lsck", "lsda", - "lspi", "lvp1", "lvs"; - nvidia,function = "displaya"; - }; - pmc { - nvidia,pins = "pmc"; - nvidia,function = "pwr_on"; - }; - rm { - nvidia,pins = "rm"; - nvidia,function = "i2c1"; - }; - sdb { - nvidia,pins = "sdb", "sdc", "sdd", "slxc"; - nvidia,function = "sdio3"; - }; - sdio1 { - nvidia,pins = "sdio1"; - nvidia,function = "sdio1"; - }; - slxd { - nvidia,pins = "slxd"; - nvidia,function = "spdif"; - }; - spid { - nvidia,pins = "spid", "spie", "spif"; - nvidia,function = "spi1"; - }; - spig { - nvidia,pins = "spig", "spih"; - nvidia,function = "spi2_alt"; - }; - uaa { - nvidia,pins = "uaa", "uab", "uda"; - nvidia,function = "ulpi"; - }; - uad { - nvidia,pins = "uad"; - nvidia,function = "irda"; - }; - uca { - nvidia,pins = "uca", "ucb"; - nvidia,function = "uartc"; - }; - conf_ata { - nvidia,pins = "ata", "atb", "atc", "atd", - "cdev1", "cdev2", "dap1", "dap2", - "dap4", "ddc", "dtf", "gma", "gmc", - "gme", "gpu", "gpu7", "i2cp", "irrx", - "irtx", "pta", "rm", "sdc", "sdd", - "slxc", "slxd", "slxk", "spdi", "spdo", - "uac", "uad", "uca", "ucb", "uda"; - nvidia,pull = <0>; - nvidia,tristate = <0>; - }; - conf_ate { - nvidia,pins = "ate", "csus", "dap3", "gmd", - "gpv", "owc", "spia", "spib", "spic", - "spid", "spie", "spig"; - nvidia,pull = <0>; - nvidia,tristate = <1>; - }; - conf_ck32 { - nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", - "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; - nvidia,pull = <0>; - }; - conf_crtp { - nvidia,pins = "crtp", "gmb", "slxa", "spih"; - nvidia,pull = <2>; - nvidia,tristate = <1>; - }; - conf_dta { - nvidia,pins = "dta", "dtb", "dtc", "dtd"; - nvidia,pull = <1>; - nvidia,tristate = <0>; - }; - conf_dte { - nvidia,pins = "dte", "spif"; - nvidia,pull = <1>; - nvidia,tristate = <1>; - }; - conf_hdint { - nvidia,pins = "hdint", "lcsn", "ldc", "lm1", - "lpw1", "lsck", "lsda", "lsdi", "lvp0"; - nvidia,tristate = <1>; - }; - conf_kbca { - nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", - "kbce", "kbcf", "sdio1", "uaa", "uab"; - nvidia,pull = <2>; - nvidia,tristate = <0>; - }; - conf_lc { - nvidia,pins = "lc", "ls"; - nvidia,pull = <2>; - }; - conf_ld0 { - nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", - "ld5", "ld6", "ld7", "ld8", "ld9", - "ld10", "ld11", "ld12", "ld13", "ld14", - "ld15", "ld16", "ld17", "ldi", "lhp0", - "lhp1", "lhp2", "lhs", "lm0", "lpp", - "lpw0", "lpw2", "lsc0", "lsc1", "lspi", - "lvp1", "lvs", "pmc", "sdb"; - nvidia,tristate = <0>; - }; - conf_ld17_0 { - nvidia,pins = "ld17_0", "ld19_18", "ld21_20", - "ld23_22"; - nvidia,pull = <1>; - }; - }; - }; - - i2s@70002800 { - status = "okay"; - }; - - serial@70006300 { - status = "okay"; - clock-frequency = <216000000>; - }; - - i2c@7000c000 { - status = "okay"; - clock-frequency = <400000>; - - wm8903: wm8903@1a { - compatible = "wlf,wm8903"; - reg = <0x1a>; - interrupt-parent = <&gpio>; - interrupts = <187 0x04>; - - gpio-controller; - #gpio-cells = <2>; - - micdet-cfg = <0>; - micdet-delay = <100>; - gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>; - }; - - /* ALS and proximity sensor */ - isl29018@44 { - compatible = "isil,isl29018"; - reg = <0x44>; - interrupt-parent = <&gpio>; - interrupts = <202 0x04>; /*gpio PZ2 */ - }; - }; - - i2c@7000c400 { - status = "okay"; - clock-frequency = <400000>; - }; - - i2c@7000c500 { - status = "okay"; - clock-frequency = <400000>; - }; - - i2c@7000d000 { - status = "okay"; - clock-frequency = <400000>; - }; - - usb@c5000000 { - status = "okay"; - }; - - usb@c5004000 { - status = "okay"; - nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ - }; - - usb@c5008000 { - status = "okay"; - }; - - sdhci@c8000400 { - status = "okay"; - cd-gpios = <&gpio 69 0>; /* gpio PI5 */ - wp-gpios = <&gpio 57 0>; /* gpio PH1 */ - power-gpios = <&gpio 70 0>; /* gpio PI6 */ - bus-width = <4>; - }; - - sdhci@c8000600 { - status = "okay"; - bus-width = <8>; - }; - - sound { - compatible = "nvidia,tegra-audio-wm8903-ventana", - "nvidia,tegra-audio-wm8903"; - nvidia,model = "NVIDIA Tegra Ventana"; - - nvidia,audio-routing = - "Headphone Jack", "HPOUTR", - "Headphone Jack", "HPOUTL", - "Int Spk", "ROP", - "Int Spk", "RON", - "Int Spk", "LOP", - "Int Spk", "LON", - "Mic Jack", "MICBIAS", - "IN1L", "Mic Jack"; - - nvidia,i2s-controller = <&tegra_i2s1>; - nvidia,audio-codec = <&wm8903>; - - nvidia,spkr-en-gpios = <&wm8903 2 0>; - nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ - nvidia,int-mic-en-gpios = <&gpio 184 0>; /* gpio PX0 */ - nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */ - }; -}; diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts new file mode 100644 index 000000000000..f146dbf6f7f8 --- /dev/null +++ b/arch/arm/boot/dts/tegra20-harmony.dts @@ -0,0 +1,336 @@ +/dts-v1/; + +/include/ "tegra20.dtsi" + +/ { + model = "NVIDIA Tegra2 Harmony evaluation board"; + compatible = "nvidia,harmony", "nvidia,tegra20"; + + memory { + reg = <0x00000000 0x40000000>; + }; + + pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + ata { + nvidia,pins = "ata"; + nvidia,function = "ide"; + }; + atb { + nvidia,pins = "atb", "gma", "gme"; + nvidia,function = "sdio4"; + }; + atc { + nvidia,pins = "atc"; + nvidia,function = "nand"; + }; + atd { + nvidia,pins = "atd", "ate", "gmb", "gmd", "gpu", + "spia", "spib", "spic"; + nvidia,function = "gmi"; + }; + cdev1 { + nvidia,pins = "cdev1"; + nvidia,function = "plla_out"; + }; + cdev2 { + nvidia,pins = "cdev2"; + nvidia,function = "pllp_out4"; + }; + crtp { + nvidia,pins = "crtp"; + nvidia,function = "crt"; + }; + csus { + nvidia,pins = "csus"; + nvidia,function = "vi_sensor_clk"; + }; + dap1 { + nvidia,pins = "dap1"; + nvidia,function = "dap1"; + }; + dap2 { + nvidia,pins = "dap2"; + nvidia,function = "dap2"; + }; + dap3 { + nvidia,pins = "dap3"; + nvidia,function = "dap3"; + }; + dap4 { + nvidia,pins = "dap4"; + nvidia,function = "dap4"; + }; + ddc { + nvidia,pins = "ddc"; + nvidia,function = "i2c2"; + }; + dta { + nvidia,pins = "dta", "dtd"; + nvidia,function = "sdio2"; + }; + dtb { + nvidia,pins = "dtb", "dtc", "dte"; + nvidia,function = "rsvd1"; + }; + dtf { + nvidia,pins = "dtf"; + nvidia,function = "i2c3"; + }; + gmc { + nvidia,pins = "gmc"; + nvidia,function = "uartd"; + }; + gpu7 { + nvidia,pins = "gpu7"; + nvidia,function = "rtck"; + }; + gpv { + nvidia,pins = "gpv", "slxa", "slxk"; + nvidia,function = "pcie"; + }; + hdint { + nvidia,pins = "hdint", "pta"; + nvidia,function = "hdmi"; + }; + i2cp { + nvidia,pins = "i2cp"; + nvidia,function = "i2cp"; + }; + irrx { + nvidia,pins = "irrx", "irtx"; + nvidia,function = "uarta"; + }; + kbca { + nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", + "kbce", "kbcf"; + nvidia,function = "kbc"; + }; + lcsn { + nvidia,pins = "lcsn", "ld0", "ld1", "ld2", + "ld3", "ld4", "ld5", "ld6", "ld7", + "ld8", "ld9", "ld10", "ld11", "ld12", + "ld13", "ld14", "ld15", "ld16", "ld17", + "ldc", "ldi", "lhp0", "lhp1", "lhp2", + "lhs", "lm0", "lm1", "lpp", "lpw0", + "lpw1", "lpw2", "lsc0", "lsc1", "lsck", + "lsda", "lsdi", "lspi", "lvp0", "lvp1", + "lvs"; + nvidia,function = "displaya"; + }; + owc { + nvidia,pins = "owc", "spdi", "spdo", "uac"; + nvidia,function = "rsvd2"; + }; + pmc { + nvidia,pins = "pmc"; + nvidia,function = "pwr_on"; + }; + rm { + nvidia,pins = "rm"; + nvidia,function = "i2c1"; + }; + sdb { + nvidia,pins = "sdb", "sdc", "sdd"; + nvidia,function = "pwm"; + }; + sdio1 { + nvidia,pins = "sdio1"; + nvidia,function = "sdio1"; + }; + slxc { + nvidia,pins = "slxc", "slxd"; + nvidia,function = "spdif"; + }; + spid { + nvidia,pins = "spid", "spie", "spif"; + nvidia,function = "spi1"; + }; + spig { + nvidia,pins = "spig", "spih"; + nvidia,function = "spi2_alt"; + }; + uaa { + nvidia,pins = "uaa", "uab", "uda"; + nvidia,function = "ulpi"; + }; + uad { + nvidia,pins = "uad"; + nvidia,function = "irda"; + }; + uca { + nvidia,pins = "uca", "ucb"; + nvidia,function = "uartc"; + }; + conf_ata { + nvidia,pins = "ata", "atb", "atc", "atd", "ate", + "cdev1", "cdev2", "dap1", "dtb", "gma", + "gmb", "gmc", "gmd", "gme", "gpu7", + "gpv", "i2cp", "pta", "rm", "slxa", + "slxk", "spia", "spib", "uac"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + conf_ck32 { + nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", + "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; + nvidia,pull = <0>; + }; + conf_csus { + nvidia,pins = "csus", "spid", "spif"; + nvidia,pull = <1>; + nvidia,tristate = <1>; + }; + conf_crtp { + nvidia,pins = "crtp", "dap2", "dap3", "dap4", + "dtc", "dte", "dtf", "gpu", "sdio1", + "slxc", "slxd", "spdi", "spdo", "spig", + "uda"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + conf_ddc { + nvidia,pins = "ddc", "dta", "dtd", "kbca", + "kbcb", "kbcc", "kbcd", "kbce", "kbcf", + "sdc"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + }; + conf_hdint { + nvidia,pins = "hdint", "lcsn", "ldc", "lm1", + "lpw1", "lsc1", "lsck", "lsda", "lsdi", + "lvp0", "owc", "sdb"; + nvidia,tristate = <1>; + }; + conf_irrx { + nvidia,pins = "irrx", "irtx", "sdd", "spic", + "spie", "spih", "uaa", "uab", "uad", + "uca", "ucb"; + nvidia,pull = <2>; + nvidia,tristate = <1>; + }; + conf_lc { + nvidia,pins = "lc", "ls"; + nvidia,pull = <2>; + }; + conf_ld0 { + nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", + "ld5", "ld6", "ld7", "ld8", "ld9", + "ld10", "ld11", "ld12", "ld13", "ld14", + "ld15", "ld16", "ld17", "ldi", "lhp0", + "lhp1", "lhp2", "lhs", "lm0", "lpp", + "lpw0", "lpw2", "lsc0", "lspi", "lvp1", + "lvs", "pmc"; + nvidia,tristate = <0>; + }; + conf_ld17_0 { + nvidia,pins = "ld17_0", "ld19_18", "ld21_20", + "ld23_22"; + nvidia,pull = <1>; + }; + }; + }; + + i2s@70002800 { + status = "okay"; + }; + + serial@70006300 { + status = "okay"; + clock-frequency = <216000000>; + }; + + i2c@7000c000 { + status = "okay"; + clock-frequency = <400000>; + + wm8903: wm8903@1a { + compatible = "wlf,wm8903"; + reg = <0x1a>; + interrupt-parent = <&gpio>; + interrupts = <187 0x04>; + + gpio-controller; + #gpio-cells = <2>; + + micdet-cfg = <0>; + micdet-delay = <100>; + gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>; + }; + }; + + i2c@7000c400 { + status = "okay"; + clock-frequency = <400000>; + }; + + i2c@7000c500 { + status = "okay"; + clock-frequency = <400000>; + }; + + i2c@7000d000 { + status = "okay"; + clock-frequency = <400000>; + }; + + pmc { + nvidia,invert-interrupt; + }; + + usb@c5000000 { + status = "okay"; + }; + + usb@c5004000 { + status = "okay"; + nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + }; + + usb@c5008000 { + status = "okay"; + }; + + sdhci@c8000200 { + status = "okay"; + cd-gpios = <&gpio 69 0>; /* gpio PI5 */ + wp-gpios = <&gpio 57 0>; /* gpio PH1 */ + power-gpios = <&gpio 155 0>; /* gpio PT3 */ + bus-width = <4>; + }; + + sdhci@c8000600 { + status = "okay"; + cd-gpios = <&gpio 58 0>; /* gpio PH2 */ + wp-gpios = <&gpio 59 0>; /* gpio PH3 */ + power-gpios = <&gpio 70 0>; /* gpio PI6 */ + bus-width = <8>; + }; + + sound { + compatible = "nvidia,tegra-audio-wm8903-harmony", + "nvidia,tegra-audio-wm8903"; + nvidia,model = "NVIDIA Tegra Harmony"; + + nvidia,audio-routing = + "Headphone Jack", "HPOUTR", + "Headphone Jack", "HPOUTL", + "Int Spk", "ROP", + "Int Spk", "RON", + "Int Spk", "LOP", + "Int Spk", "LON", + "Mic Jack", "MICBIAS", + "IN1L", "Mic Jack"; + + nvidia,i2s-controller = <&tegra_i2s1>; + nvidia,audio-codec = <&wm8903>; + + nvidia,spkr-en-gpios = <&wm8903 2 0>; + nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ + nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */ + nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */ + }; +}; diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts new file mode 100644 index 000000000000..684a9e1ff7e9 --- /dev/null +++ b/arch/arm/boot/dts/tegra20-paz00.dts @@ -0,0 +1,347 @@ +/dts-v1/; + +/include/ "tegra20.dtsi" + +/ { + model = "Toshiba AC100 / Dynabook AZ"; + compatible = "compal,paz00", "nvidia,tegra20"; + + memory { + reg = <0x00000000 0x20000000>; + }; + + pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + ata { + nvidia,pins = "ata", "atc", "atd", "ate", + "dap2", "gmb", "gmc", "gmd", "spia", + "spib", "spic", "spid", "spie"; + nvidia,function = "gmi"; + }; + atb { + nvidia,pins = "atb", "gma", "gme"; + nvidia,function = "sdio4"; + }; + cdev1 { + nvidia,pins = "cdev1"; + nvidia,function = "plla_out"; + }; + cdev2 { + nvidia,pins = "cdev2"; + nvidia,function = "pllp_out4"; + }; + crtp { + nvidia,pins = "crtp"; + nvidia,function = "crt"; + }; + csus { + nvidia,pins = "csus"; + nvidia,function = "pllc_out1"; + }; + dap1 { + nvidia,pins = "dap1"; + nvidia,function = "dap1"; + }; + dap3 { + nvidia,pins = "dap3"; + nvidia,function = "dap3"; + }; + dap4 { + nvidia,pins = "dap4"; + nvidia,function = "dap4"; + }; + ddc { + nvidia,pins = "ddc"; + nvidia,function = "i2c2"; + }; + dta { + nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte"; + nvidia,function = "rsvd1"; + }; + dtf { + nvidia,pins = "dtf"; + nvidia,function = "i2c3"; + }; + gpu { + nvidia,pins = "gpu", "sdb", "sdd"; + nvidia,function = "pwm"; + }; + gpu7 { + nvidia,pins = "gpu7"; + nvidia,function = "rtck"; + }; + gpv { + nvidia,pins = "gpv", "slxa", "slxk"; + nvidia,function = "pcie"; + }; + hdint { + nvidia,pins = "hdint", "pta"; + nvidia,function = "hdmi"; + }; + i2cp { + nvidia,pins = "i2cp"; + nvidia,function = "i2cp"; + }; + irrx { + nvidia,pins = "irrx", "irtx"; + nvidia,function = "uarta"; + }; + kbca { + nvidia,pins = "kbca", "kbcc", "kbce", "kbcf"; + nvidia,function = "kbc"; + }; + kbcb { + nvidia,pins = "kbcb", "kbcd"; + nvidia,function = "sdio2"; + }; + lcsn { + nvidia,pins = "lcsn", "ld0", "ld1", "ld2", + "ld3", "ld4", "ld5", "ld6", "ld7", + "ld8", "ld9", "ld10", "ld11", "ld12", + "ld13", "ld14", "ld15", "ld16", "ld17", + "ldc", "ldi", "lhp0", "lhp1", "lhp2", + "lhs", "lm0", "lm1", "lpp", "lpw0", + "lpw1", "lpw2", "lsc0", "lsc1", "lsck", + "lsda", "lsdi", "lspi", "lvp0", "lvp1", + "lvs"; + nvidia,function = "displaya"; + }; + owc { + nvidia,pins = "owc"; + nvidia,function = "owr"; + }; + pmc { + nvidia,pins = "pmc"; + nvidia,function = "pwr_on"; + }; + rm { + nvidia,pins = "rm"; + nvidia,function = "i2c1"; + }; + sdc { + nvidia,pins = "sdc"; + nvidia,function = "twc"; + }; + sdio1 { + nvidia,pins = "sdio1"; + nvidia,function = "sdio1"; + }; + slxc { + nvidia,pins = "slxc", "slxd"; + nvidia,function = "spi4"; + }; + spdi { + nvidia,pins = "spdi", "spdo"; + nvidia,function = "rsvd2"; + }; + spif { + nvidia,pins = "spif", "uac"; + nvidia,function = "rsvd4"; + }; + spig { + nvidia,pins = "spig", "spih"; + nvidia,function = "spi2_alt"; + }; + uaa { + nvidia,pins = "uaa", "uab", "uda"; + nvidia,function = "ulpi"; + }; + uad { + nvidia,pins = "uad"; + nvidia,function = "spdif"; + }; + uca { + nvidia,pins = "uca", "ucb"; + nvidia,function = "uartc"; + }; + conf_ata { + nvidia,pins = "ata", "atb", "atc", "atd", "ate", + "cdev1", "cdev2", "dap1", "dap2", "dtf", + "gma", "gmb", "gmc", "gmd", "gme", + "gpu", "gpu7", "gpv", "i2cp", "pta", + "rm", "sdio1", "slxk", "spdo", "uac", + "uda"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + conf_ck32 { + nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", + "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; + nvidia,pull = <0>; + }; + conf_crtp { + nvidia,pins = "crtp", "dap3", "dap4", "dtb", + "dtc", "dte", "slxa", "slxc", "slxd", + "spdi"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + conf_csus { + nvidia,pins = "csus", "spia", "spib", "spid", + "spif"; + nvidia,pull = <1>; + nvidia,tristate = <1>; + }; + conf_ddc { + nvidia,pins = "ddc", "irrx", "irtx", "kbca", + "kbcb", "kbcc", "kbcd", "kbce", "kbcf", + "spic", "spig", "uaa", "uab"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + }; + conf_dta { + nvidia,pins = "dta", "dtd", "owc", "sdc", "sdd", + "spie", "spih", "uad", "uca", "ucb"; + nvidia,pull = <2>; + nvidia,tristate = <1>; + }; + conf_hdint { + nvidia,pins = "hdint", "ld0", "ld1", "ld2", + "ld3", "ld4", "ld5", "ld6", "ld7", + "ld8", "ld9", "ld10", "ld11", "ld12", + "ld13", "ld14", "ld15", "ld16", "ld17", + "ldc", "ldi", "lhs", "lsc0", "lspi", + "lvs", "pmc"; + nvidia,tristate = <0>; + }; + conf_lc { + nvidia,pins = "lc", "ls"; + nvidia,pull = <2>; + }; + conf_lcsn { + nvidia,pins = "lcsn", "lhp0", "lhp1", "lhp2", + "lm0", "lm1", "lpp", "lpw0", "lpw1", + "lpw2", "lsc1", "lsck", "lsda", "lsdi", + "lvp0", "lvp1", "sdb"; + nvidia,tristate = <1>; + }; + conf_ld17_0 { + nvidia,pins = "ld17_0", "ld19_18", "ld21_20", + "ld23_22"; + nvidia,pull = <1>; + }; + }; + }; + + i2s@70002800 { + status = "okay"; + }; + + serial@70006000 { + status = "okay"; + clock-frequency = <216000000>; + }; + + serial@70006200 { + status = "okay"; + clock-frequency = <216000000>; + }; + + i2c@7000c000 { + status = "okay"; + clock-frequency = <400000>; + + alc5632: alc5632@1e { + compatible = "realtek,alc5632"; + reg = <0x1e>; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + i2c@7000c400 { + status = "okay"; + clock-frequency = <400000>; + }; + + nvec { + compatible = "nvidia,nvec"; + reg = <0x7000c500 0x100>; + interrupts = <0 92 0x04>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <80000>; + request-gpios = <&gpio 170 0>; /* gpio PV2 */ + slave-addr = <138>; + }; + + i2c@7000d000 { + status = "okay"; + clock-frequency = <400000>; + + adt7461@4c { + compatible = "adi,adt7461"; + reg = <0x4c>; + }; + }; + + usb@c5000000 { + status = "okay"; + }; + + usb@c5004000 { + status = "okay"; + nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ + }; + + usb@c5008000 { + status = "okay"; + }; + + sdhci@c8000000 { + status = "okay"; + cd-gpios = <&gpio 173 0>; /* gpio PV5 */ + wp-gpios = <&gpio 57 0>; /* gpio PH1 */ + power-gpios = <&gpio 169 0>; /* gpio PV1 */ + bus-width = <4>; + }; + + sdhci@c8000600 { + status = "okay"; + bus-width = <8>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + power { + label = "Power"; + gpios = <&gpio 79 1>; /* gpio PJ7, active low */ + linux,code = <116>; /* KEY_POWER */ + gpio-key,wakeup; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wifi { + label = "wifi-led"; + gpios = <&gpio 24 0>; /* gpio PD0 */ + linux,default-trigger = "rfkill0"; + }; + }; + + sound { + compatible = "nvidia,tegra-audio-alc5632-paz00", + "nvidia,tegra-audio-alc5632"; + + nvidia,model = "Compal PAZ00"; + + nvidia,audio-routing = + "Int Spk", "SPKOUT", + "Int Spk", "SPKOUTN", + "Headset Mic", "MICBIAS1", + "MIC1", "Headset Mic", + "Headset Stereophone", "HPR", + "Headset Stereophone", "HPL", + "DMICDAT", "Digital Mic"; + + nvidia,audio-codec = <&alc5632>; + nvidia,i2s-controller = <&tegra_i2s1>; + nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ + }; +}; diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts new file mode 100644 index 000000000000..b797901d040d --- /dev/null +++ b/arch/arm/boot/dts/tegra20-seaboard.dts @@ -0,0 +1,444 @@ +/dts-v1/; + +/include/ "tegra20.dtsi" + +/ { + model = "NVIDIA Seaboard"; + compatible = "nvidia,seaboard", "nvidia,tegra20"; + + memory { + reg = <0x00000000 0x40000000>; + }; + + pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + ata { + nvidia,pins = "ata"; + nvidia,function = "ide"; + }; + atb { + nvidia,pins = "atb", "gma", "gme"; + nvidia,function = "sdio4"; + }; + atc { + nvidia,pins = "atc"; + nvidia,function = "nand"; + }; + atd { + nvidia,pins = "atd", "ate", "gmb", "spia", + "spib", "spic"; + nvidia,function = "gmi"; + }; + cdev1 { + nvidia,pins = "cdev1"; + nvidia,function = "plla_out"; + }; + cdev2 { + nvidia,pins = "cdev2"; + nvidia,function = "pllp_out4"; + }; + crtp { + nvidia,pins = "crtp", "lm1"; + nvidia,function = "crt"; + }; + csus { + nvidia,pins = "csus"; + nvidia,function = "vi_sensor_clk"; + }; + dap1 { + nvidia,pins = "dap1"; + nvidia,function = "dap1"; + }; + dap2 { + nvidia,pins = "dap2"; + nvidia,function = "dap2"; + }; + dap3 { + nvidia,pins = "dap3"; + nvidia,function = "dap3"; + }; + dap4 { + nvidia,pins = "dap4"; + nvidia,function = "dap4"; + }; + ddc { + nvidia,pins = "ddc", "owc", "spdi", "spdo", + "uac"; + nvidia,function = "rsvd2"; + }; + dta { + nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte"; + nvidia,function = "vi"; + }; + dtf { + nvidia,pins = "dtf"; + nvidia,function = "i2c3"; + }; + gmc { + nvidia,pins = "gmc"; + nvidia,function = "uartd"; + }; + gmd { + nvidia,pins = "gmd"; + nvidia,function = "sflash"; + }; + gpu { + nvidia,pins = "gpu"; + nvidia,function = "pwm"; + }; + gpu7 { + nvidia,pins = "gpu7"; + nvidia,function = "rtck"; + }; + gpv { + nvidia,pins = "gpv", "slxa", "slxk"; + nvidia,function = "pcie"; + }; + hdint { + nvidia,pins = "hdint", "lpw0", "lpw2", "lsc1", + "lsck", "lsda"; + nvidia,function = "hdmi"; + }; + i2cp { + nvidia,pins = "i2cp"; + nvidia,function = "i2cp"; + }; + irrx { + nvidia,pins = "irrx", "irtx"; + nvidia,function = "uartb"; + }; + kbca { + nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", + "kbce", "kbcf"; + nvidia,function = "kbc"; + }; + lcsn { + nvidia,pins = "lcsn", "ldc", "lm0", "lpw1", + "lsdi", "lvp0"; + nvidia,function = "rsvd4"; + }; + ld0 { + nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", + "ld5", "ld6", "ld7", "ld8", "ld9", + "ld10", "ld11", "ld12", "ld13", "ld14", + "ld15", "ld16", "ld17", "ldi", "lhp0", + "lhp1", "lhp2", "lhs", "lpp", "lsc0", + "lspi", "lvp1", "lvs"; + nvidia,function = "displaya"; + }; + pmc { + nvidia,pins = "pmc"; + nvidia,function = "pwr_on"; + }; + pta { + nvidia,pins = "pta"; + nvidia,function = "i2c2"; + }; + rm { + nvidia,pins = "rm"; + nvidia,function = "i2c1"; + }; + sdb { + nvidia,pins = "sdb", "sdc", "sdd"; + nvidia,function = "sdio3"; + }; + sdio1 { + nvidia,pins = "sdio1"; + nvidia,function = "sdio1"; + }; + slxc { + nvidia,pins = "slxc", "slxd"; + nvidia,function = "spdif"; + }; + spid { + nvidia,pins = "spid", "spie", "spif"; + nvidia,function = "spi1"; + }; + spig { + nvidia,pins = "spig", "spih"; + nvidia,function = "spi2_alt"; + }; + uaa { + nvidia,pins = "uaa", "uab", "uda"; + nvidia,function = "ulpi"; + }; + uad { + nvidia,pins = "uad"; + nvidia,function = "irda"; + }; + uca { + nvidia,pins = "uca", "ucb"; + nvidia,function = "uartc"; + }; + conf_ata { + nvidia,pins = "ata", "atb", "atc", "atd", + "cdev1", "cdev2", "dap1", "dap2", + "dap4", "dtf", "gma", "gmc", "gmd", + "gme", "gpu", "gpu7", "i2cp", "irrx", + "irtx", "pta", "rm", "sdc", "sdd", + "slxd", "slxk", "spdi", "spdo", "uac", + "uad", "uca", "ucb", "uda"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + conf_ate { + nvidia,pins = "ate", "csus", "dap3", "ddc", + "gpv", "owc", "slxc", "spib", "spid", + "spie"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + conf_ck32 { + nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", + "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; + nvidia,pull = <0>; + }; + conf_crtp { + nvidia,pins = "crtp", "gmb", "slxa", "spia", + "spig", "spih"; + nvidia,pull = <2>; + nvidia,tristate = <1>; + }; + conf_dta { + nvidia,pins = "dta", "dtb", "dtc", "dtd"; + nvidia,pull = <1>; + nvidia,tristate = <0>; + }; + conf_dte { + nvidia,pins = "dte", "spif"; + nvidia,pull = <1>; + nvidia,tristate = <1>; + }; + conf_hdint { + nvidia,pins = "hdint", "lcsn", "ldc", "lm1", + "lpw1", "lsc1", "lsck", "lsda", "lsdi", + "lvp0"; + nvidia,tristate = <1>; + }; + conf_kbca { + nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", + "kbce", "kbcf", "sdio1", "spic", "uaa", + "uab"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + }; + conf_lc { + nvidia,pins = "lc", "ls"; + nvidia,pull = <2>; + }; + conf_ld0 { + nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", + "ld5", "ld6", "ld7", "ld8", "ld9", + "ld10", "ld11", "ld12", "ld13", "ld14", + "ld15", "ld16", "ld17", "ldi", "lhp0", + "lhp1", "lhp2", "lhs", "lm0", "lpp", + "lpw0", "lpw2", "lsc0", "lspi", "lvp1", + "lvs", "pmc", "sdb"; + nvidia,tristate = <0>; + }; + conf_ld17_0 { + nvidia,pins = "ld17_0", "ld19_18", "ld21_20", + "ld23_22"; + nvidia,pull = <1>; + }; + drive_sdio1 { + nvidia,pins = "drive_sdio1"; + nvidia,high-speed-mode = <0>; + nvidia,schmitt = <0>; + nvidia,low-power-mode = <3>; + nvidia,pull-down-strength = <31>; + nvidia,pull-up-strength = <31>; + nvidia,slew-rate-rising = <3>; + nvidia,slew-rate-falling = <3>; + }; + }; + }; + + i2s@70002800 { + status = "okay"; + }; + + serial@70006300 { + status = "okay"; + clock-frequency = <216000000>; + }; + + i2c@7000c000 { + status = "okay"; + clock-frequency = <400000>; + + wm8903: wm8903@1a { + compatible = "wlf,wm8903"; + reg = <0x1a>; + interrupt-parent = <&gpio>; + interrupts = <187 0x04>; + + gpio-controller; + #gpio-cells = <2>; + + micdet-cfg = <0>; + micdet-delay = <100>; + gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>; + }; + + /* ALS and proximity sensor */ + isl29018@44 { + compatible = "isil,isl29018"; + reg = <0x44>; + interrupt-parent = <&gpio>; + interrupts = <202 0x04>; /* GPIO PZ2 */ + }; + + gyrometer@68 { + compatible = "invn,mpu3050"; + reg = <0x68>; + interrupt-parent = <&gpio>; + interrupts = <204 0x04>; /* gpio PZ4 */ + }; + }; + + i2c@7000c400 { + status = "okay"; + clock-frequency = <100000>; + + smart-battery@b { + compatible = "ti,bq20z75", "smart-battery-1.1"; + reg = <0xb>; + ti,i2c-retry-count = <2>; + ti,poll-retry-count = <10>; + }; + }; + + i2c@7000c500 { + status = "okay"; + clock-frequency = <400000>; + }; + + i2c@7000d000 { + status = "okay"; + clock-frequency = <400000>; + + temperature-sensor@4c { + compatible = "nct1008"; + reg = <0x4c>; + }; + + magnetometer@c { + compatible = "ak8975"; + reg = <0xc>; + interrupt-parent = <&gpio>; + interrupts = <109 0x04>; /* gpio PN5 */ + }; + }; + + memory-controller@0x7000f400 { + emc-table@190000 { + reg = <190000>; + compatible = "nvidia,tegra20-emc-table"; + clock-frequency = <190000>; + nvidia,emc-registers = <0x0000000c 0x00000026 + 0x00000009 0x00000003 0x00000004 0x00000004 + 0x00000002 0x0000000c 0x00000003 0x00000003 + 0x00000002 0x00000001 0x00000004 0x00000005 + 0x00000004 0x00000009 0x0000000d 0x0000059f + 0x00000000 0x00000003 0x00000003 0x00000003 + 0x00000003 0x00000001 0x0000000b 0x000000c8 + 0x00000003 0x00000007 0x00000004 0x0000000f + 0x00000002 0x00000000 0x00000000 0x00000002 + 0x00000000 0x00000000 0x00000083 0xa06204ae + 0x007dc010 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000>; + }; + + emc-table@380000 { + reg = <380000>; + compatible = "nvidia,tegra20-emc-table"; + clock-frequency = <380000>; + nvidia,emc-registers = <0x00000017 0x0000004b + 0x00000012 0x00000006 0x00000004 0x00000005 + 0x00000003 0x0000000c 0x00000006 0x00000006 + 0x00000003 0x00000001 0x00000004 0x00000005 + 0x00000004 0x00000009 0x0000000d 0x00000b5f + 0x00000000 0x00000003 0x00000003 0x00000006 + 0x00000006 0x00000001 0x00000011 0x000000c8 + 0x00000003 0x0000000e 0x00000007 0x0000000f + 0x00000002 0x00000000 0x00000000 0x00000002 + 0x00000000 0x00000000 0x00000083 0xe044048b + 0x007d8010 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000>; + }; + }; + + usb@c5000000 { + status = "okay"; + nvidia,vbus-gpio = <&gpio 24 0>; /* PD0 */ + dr_mode = "otg"; + }; + + usb@c5004000 { + status = "okay"; + nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + }; + + usb@c5008000 { + status = "okay"; + }; + + sdhci@c8000400 { + status = "okay"; + cd-gpios = <&gpio 69 0>; /* gpio PI5 */ + wp-gpios = <&gpio 57 0>; /* gpio PH1 */ + power-gpios = <&gpio 70 0>; /* gpio PI6 */ + bus-width = <4>; + }; + + sdhci@c8000600 { + status = "okay"; + bus-width = <8>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + power { + label = "Power"; + gpios = <&gpio 170 1>; /* gpio PV2, active low */ + linux,code = <116>; /* KEY_POWER */ + gpio-key,wakeup; + }; + + lid { + label = "Lid"; + gpios = <&gpio 23 0>; /* gpio PC7 */ + linux,input-type = <5>; /* EV_SW */ + linux,code = <0>; /* SW_LID */ + debounce-interval = <1>; + gpio-key,wakeup; + }; + }; + + sound { + compatible = "nvidia,tegra-audio-wm8903-seaboard", + "nvidia,tegra-audio-wm8903"; + nvidia,model = "NVIDIA Tegra Seaboard"; + + nvidia,audio-routing = + "Headphone Jack", "HPOUTR", + "Headphone Jack", "HPOUTL", + "Int Spk", "ROP", + "Int Spk", "RON", + "Int Spk", "LOP", + "Int Spk", "LON", + "Mic Jack", "MICBIAS", + "IN1R", "Mic Jack"; + + nvidia,i2s-controller = <&tegra_i2s1>; + nvidia,audio-codec = <&wm8903>; + + nvidia,spkr-en-gpios = <&wm8903 2 0>; + nvidia,hp-det-gpios = <&gpio 185 0>; /* gpio PX1 */ + }; +}; diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts new file mode 100644 index 000000000000..9de5636023f6 --- /dev/null +++ b/arch/arm/boot/dts/tegra20-trimslice.dts @@ -0,0 +1,306 @@ +/dts-v1/; + +/include/ "tegra20.dtsi" + +/ { + model = "Compulab TrimSlice board"; + compatible = "compulab,trimslice", "nvidia,tegra20"; + + memory { + reg = <0x00000000 0x40000000>; + }; + + pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + ata { + nvidia,pins = "ata"; + nvidia,function = "ide"; + }; + atb { + nvidia,pins = "atb", "gma"; + nvidia,function = "sdio4"; + }; + atc { + nvidia,pins = "atc", "gmb"; + nvidia,function = "nand"; + }; + atd { + nvidia,pins = "atd", "ate", "gme", "pta"; + nvidia,function = "gmi"; + }; + cdev1 { + nvidia,pins = "cdev1"; + nvidia,function = "plla_out"; + }; + cdev2 { + nvidia,pins = "cdev2"; + nvidia,function = "pllp_out4"; + }; + crtp { + nvidia,pins = "crtp"; + nvidia,function = "crt"; + }; + csus { + nvidia,pins = "csus"; + nvidia,function = "vi_sensor_clk"; + }; + dap1 { + nvidia,pins = "dap1"; + nvidia,function = "dap1"; + }; + dap2 { + nvidia,pins = "dap2"; + nvidia,function = "dap2"; + }; + dap3 { + nvidia,pins = "dap3"; + nvidia,function = "dap3"; + }; + dap4 { + nvidia,pins = "dap4"; + nvidia,function = "dap4"; + }; + ddc { + nvidia,pins = "ddc"; + nvidia,function = "i2c2"; + }; + dta { + nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte"; + nvidia,function = "vi"; + }; + dtf { + nvidia,pins = "dtf"; + nvidia,function = "i2c3"; + }; + gmc { + nvidia,pins = "gmc", "gmd"; + nvidia,function = "sflash"; + }; + gpu { + nvidia,pins = "gpu"; + nvidia,function = "uarta"; + }; + gpu7 { + nvidia,pins = "gpu7"; + nvidia,function = "rtck"; + }; + gpv { + nvidia,pins = "gpv", "slxa", "slxk"; + nvidia,function = "pcie"; + }; + hdint { + nvidia,pins = "hdint"; + nvidia,function = "hdmi"; + }; + i2cp { + nvidia,pins = "i2cp"; + nvidia,function = "i2cp"; + }; + irrx { + nvidia,pins = "irrx", "irtx"; + nvidia,function = "uartb"; + }; + kbca { + nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", + "kbce", "kbcf"; + nvidia,function = "kbc"; + }; + lcsn { + nvidia,pins = "lcsn", "ld0", "ld1", "ld2", + "ld3", "ld4", "ld5", "ld6", "ld7", + "ld8", "ld9", "ld10", "ld11", "ld12", + "ld13", "ld14", "ld15", "ld16", "ld17", + "ldc", "ldi", "lhp0", "lhp1", "lhp2", + "lhs", "lm0", "lm1", "lpp", "lpw0", + "lpw1", "lpw2", "lsc0", "lsc1", "lsck", + "lsda", "lsdi", "lspi", "lvp0", "lvp1", + "lvs"; + nvidia,function = "displaya"; + }; + owc { + nvidia,pins = "owc", "uac"; + nvidia,function = "rsvd2"; + }; + pmc { + nvidia,pins = "pmc"; + nvidia,function = "pwr_on"; + }; + rm { + nvidia,pins = "rm"; + nvidia,function = "i2c1"; + }; + sdb { + nvidia,pins = "sdb", "sdc", "sdd"; + nvidia,function = "pwm"; + }; + sdio1 { + nvidia,pins = "sdio1"; + nvidia,function = "sdio1"; + }; + slxc { + nvidia,pins = "slxc", "slxd"; + nvidia,function = "sdio3"; + }; + spdi { + nvidia,pins = "spdi", "spdo"; + nvidia,function = "spdif"; + }; + spia { + nvidia,pins = "spia", "spib", "spic"; + nvidia,function = "spi2"; + }; + spid { + nvidia,pins = "spid", "spie", "spif"; + nvidia,function = "spi1"; + }; + spig { + nvidia,pins = "spig", "spih"; + nvidia,function = "spi2_alt"; + }; + uaa { + nvidia,pins = "uaa", "uab", "uda"; + nvidia,function = "ulpi"; + }; + uad { + nvidia,pins = "uad"; + nvidia,function = "irda"; + }; + uca { + nvidia,pins = "uca", "ucb"; + nvidia,function = "uartc"; + }; + conf_ata { + nvidia,pins = "ata", "atc", "atd", "ate", + "crtp", "dap2", "dap3", "dap4", "dta", + "dtb", "dtc", "dtd", "dte", "gmb", + "gme", "i2cp", "pta", "slxc", "slxd", + "spdi", "spdo", "uda"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + conf_atb { + nvidia,pins = "atb", "cdev1", "cdev2", "dap1", + "gma", "gmc", "gmd", "gpu", "gpu7", + "gpv", "sdio1", "slxa", "slxk", "uac"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + conf_ck32 { + nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", + "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; + nvidia,pull = <0>; + }; + conf_csus { + nvidia,pins = "csus", "spia", "spib", + "spid", "spif"; + nvidia,pull = <1>; + nvidia,tristate = <1>; + }; + conf_ddc { + nvidia,pins = "ddc", "dtf", "rm", "sdc", "sdd"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + }; + conf_hdint { + nvidia,pins = "hdint", "lcsn", "ldc", "lm1", + "lpw1", "lsc1", "lsck", "lsda", "lsdi", + "lvp0", "pmc"; + nvidia,tristate = <1>; + }; + conf_irrx { + nvidia,pins = "irrx", "irtx", "kbca", "kbcb", + "kbcc", "kbcd", "kbce", "kbcf", "owc", + "spic", "spie", "spig", "spih", "uaa", + "uab", "uad", "uca", "ucb"; + nvidia,pull = <2>; + nvidia,tristate = <1>; + }; + conf_lc { + nvidia,pins = "lc", "ls"; + nvidia,pull = <2>; + }; + conf_ld0 { + nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", + "ld5", "ld6", "ld7", "ld8", "ld9", + "ld10", "ld11", "ld12", "ld13", "ld14", + "ld15", "ld16", "ld17", "ldi", "lhp0", + "lhp1", "lhp2", "lhs", "lm0", "lpp", + "lpw0", "lpw2", "lsc0", "lspi", "lvp1", + "lvs", "sdb"; + nvidia,tristate = <0>; + }; + conf_ld17_0 { + nvidia,pins = "ld17_0", "ld19_18", "ld21_20", + "ld23_22"; + nvidia,pull = <1>; + }; + }; + }; + + i2s@70002800 { + status = "okay"; + }; + + serial@70006000 { + status = "okay"; + clock-frequency = <216000000>; + }; + + i2c@7000c000 { + status = "okay"; + clock-frequency = <400000>; + }; + + i2c@7000c400 { + status = "okay"; + clock-frequency = <400000>; + }; + + i2c@7000c500 { + status = "okay"; + clock-frequency = <400000>; + + codec: codec@1a { + compatible = "ti,tlv320aic23"; + reg = <0x1a>; + }; + + rtc@56 { + compatible = "emmicro,em3027"; + reg = <0x56>; + }; + }; + + usb@c5000000 { + status = "okay"; + }; + + usb@c5004000 { + nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ + }; + + usb@c5008000 { + status = "okay"; + }; + + sdhci@c8000000 { + status = "okay"; + bus-width = <4>; + }; + + sdhci@c8000600 { + status = "okay"; + cd-gpios = <&gpio 121 0>; /* gpio PP1 */ + wp-gpios = <&gpio 122 0>; /* gpio PP2 */ + bus-width = <4>; + }; + + sound { + compatible = "nvidia,tegra-audio-trimslice"; + nvidia,i2s-controller = <&tegra_i2s1>; + nvidia,audio-codec = <&codec>; + }; +}; diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts new file mode 100644 index 000000000000..be90544e6b59 --- /dev/null +++ b/arch/arm/boot/dts/tegra20-ventana.dts @@ -0,0 +1,343 @@ +/dts-v1/; + +/include/ "tegra20.dtsi" + +/ { + model = "NVIDIA Tegra2 Ventana evaluation board"; + compatible = "nvidia,ventana", "nvidia,tegra20"; + + memory { + reg = <0x00000000 0x40000000>; + }; + + pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + ata { + nvidia,pins = "ata"; + nvidia,function = "ide"; + }; + atb { + nvidia,pins = "atb", "gma", "gme"; + nvidia,function = "sdio4"; + }; + atc { + nvidia,pins = "atc"; + nvidia,function = "nand"; + }; + atd { + nvidia,pins = "atd", "ate", "gmb", "spia", + "spib", "spic"; + nvidia,function = "gmi"; + }; + cdev1 { + nvidia,pins = "cdev1"; + nvidia,function = "plla_out"; + }; + cdev2 { + nvidia,pins = "cdev2"; + nvidia,function = "pllp_out4"; + }; + crtp { + nvidia,pins = "crtp", "lm1"; + nvidia,function = "crt"; + }; + csus { + nvidia,pins = "csus"; + nvidia,function = "vi_sensor_clk"; + }; + dap1 { + nvidia,pins = "dap1"; + nvidia,function = "dap1"; + }; + dap2 { + nvidia,pins = "dap2"; + nvidia,function = "dap2"; + }; + dap3 { + nvidia,pins = "dap3"; + nvidia,function = "dap3"; + }; + dap4 { + nvidia,pins = "dap4"; + nvidia,function = "dap4"; + }; + ddc { + nvidia,pins = "ddc", "owc", "spdi", "spdo", + "uac"; + nvidia,function = "rsvd2"; + }; + dta { + nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte"; + nvidia,function = "vi"; + }; + dtf { + nvidia,pins = "dtf"; + nvidia,function = "i2c3"; + }; + gmc { + nvidia,pins = "gmc"; + nvidia,function = "uartd"; + }; + gmd { + nvidia,pins = "gmd"; + nvidia,function = "sflash"; + }; + gpu { + nvidia,pins = "gpu"; + nvidia,function = "pwm"; + }; + gpu7 { + nvidia,pins = "gpu7"; + nvidia,function = "rtck"; + }; + gpv { + nvidia,pins = "gpv", "slxa", "slxk"; + nvidia,function = "pcie"; + }; + hdint { + nvidia,pins = "hdint", "pta"; + nvidia,function = "hdmi"; + }; + i2cp { + nvidia,pins = "i2cp"; + nvidia,function = "i2cp"; + }; + irrx { + nvidia,pins = "irrx", "irtx"; + nvidia,function = "uartb"; + }; + kbca { + nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", + "kbce", "kbcf"; + nvidia,function = "kbc"; + }; + lcsn { + nvidia,pins = "lcsn", "ldc", "lm0", "lpw1", + "lsdi", "lvp0"; + nvidia,function = "rsvd4"; + }; + ld0 { + nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", + "ld5", "ld6", "ld7", "ld8", "ld9", + "ld10", "ld11", "ld12", "ld13", "ld14", + "ld15", "ld16", "ld17", "ldi", "lhp0", + "lhp1", "lhp2", "lhs", "lpp", "lpw0", + "lpw2", "lsc0", "lsc1", "lsck", "lsda", + "lspi", "lvp1", "lvs"; + nvidia,function = "displaya"; + }; + pmc { + nvidia,pins = "pmc"; + nvidia,function = "pwr_on"; + }; + rm { + nvidia,pins = "rm"; + nvidia,function = "i2c1"; + }; + sdb { + nvidia,pins = "sdb", "sdc", "sdd", "slxc"; + nvidia,function = "sdio3"; + }; + sdio1 { + nvidia,pins = "sdio1"; + nvidia,function = "sdio1"; + }; + slxd { + nvidia,pins = "slxd"; + nvidia,function = "spdif"; + }; + spid { + nvidia,pins = "spid", "spie", "spif"; + nvidia,function = "spi1"; + }; + spig { + nvidia,pins = "spig", "spih"; + nvidia,function = "spi2_alt"; + }; + uaa { + nvidia,pins = "uaa", "uab", "uda"; + nvidia,function = "ulpi"; + }; + uad { + nvidia,pins = "uad"; + nvidia,function = "irda"; + }; + uca { + nvidia,pins = "uca", "ucb"; + nvidia,function = "uartc"; + }; + conf_ata { + nvidia,pins = "ata", "atb", "atc", "atd", + "cdev1", "cdev2", "dap1", "dap2", + "dap4", "ddc", "dtf", "gma", "gmc", + "gme", "gpu", "gpu7", "i2cp", "irrx", + "irtx", "pta", "rm", "sdc", "sdd", + "slxc", "slxd", "slxk", "spdi", "spdo", + "uac", "uad", "uca", "ucb", "uda"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + conf_ate { + nvidia,pins = "ate", "csus", "dap3", "gmd", + "gpv", "owc", "spia", "spib", "spic", + "spid", "spie", "spig"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + conf_ck32 { + nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", + "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; + nvidia,pull = <0>; + }; + conf_crtp { + nvidia,pins = "crtp", "gmb", "slxa", "spih"; + nvidia,pull = <2>; + nvidia,tristate = <1>; + }; + conf_dta { + nvidia,pins = "dta", "dtb", "dtc", "dtd"; + nvidia,pull = <1>; + nvidia,tristate = <0>; + }; + conf_dte { + nvidia,pins = "dte", "spif"; + nvidia,pull = <1>; + nvidia,tristate = <1>; + }; + conf_hdint { + nvidia,pins = "hdint", "lcsn", "ldc", "lm1", + "lpw1", "lsck", "lsda", "lsdi", "lvp0"; + nvidia,tristate = <1>; + }; + conf_kbca { + nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", + "kbce", "kbcf", "sdio1", "uaa", "uab"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + }; + conf_lc { + nvidia,pins = "lc", "ls"; + nvidia,pull = <2>; + }; + conf_ld0 { + nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", + "ld5", "ld6", "ld7", "ld8", "ld9", + "ld10", "ld11", "ld12", "ld13", "ld14", + "ld15", "ld16", "ld17", "ldi", "lhp0", + "lhp1", "lhp2", "lhs", "lm0", "lpp", + "lpw0", "lpw2", "lsc0", "lsc1", "lspi", + "lvp1", "lvs", "pmc", "sdb"; + nvidia,tristate = <0>; + }; + conf_ld17_0 { + nvidia,pins = "ld17_0", "ld19_18", "ld21_20", + "ld23_22"; + nvidia,pull = <1>; + }; + }; + }; + + i2s@70002800 { + status = "okay"; + }; + + serial@70006300 { + status = "okay"; + clock-frequency = <216000000>; + }; + + i2c@7000c000 { + status = "okay"; + clock-frequency = <400000>; + + wm8903: wm8903@1a { + compatible = "wlf,wm8903"; + reg = <0x1a>; + interrupt-parent = <&gpio>; + interrupts = <187 0x04>; + + gpio-controller; + #gpio-cells = <2>; + + micdet-cfg = <0>; + micdet-delay = <100>; + gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>; + }; + + /* ALS and proximity sensor */ + isl29018@44 { + compatible = "isil,isl29018"; + reg = <0x44>; + interrupt-parent = <&gpio>; + interrupts = <202 0x04>; /*gpio PZ2 */ + }; + }; + + i2c@7000c400 { + status = "okay"; + clock-frequency = <400000>; + }; + + i2c@7000c500 { + status = "okay"; + clock-frequency = <400000>; + }; + + i2c@7000d000 { + status = "okay"; + clock-frequency = <400000>; + }; + + usb@c5000000 { + status = "okay"; + }; + + usb@c5004000 { + status = "okay"; + nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + }; + + usb@c5008000 { + status = "okay"; + }; + + sdhci@c8000400 { + status = "okay"; + cd-gpios = <&gpio 69 0>; /* gpio PI5 */ + wp-gpios = <&gpio 57 0>; /* gpio PH1 */ + power-gpios = <&gpio 70 0>; /* gpio PI6 */ + bus-width = <4>; + }; + + sdhci@c8000600 { + status = "okay"; + bus-width = <8>; + }; + + sound { + compatible = "nvidia,tegra-audio-wm8903-ventana", + "nvidia,tegra-audio-wm8903"; + nvidia,model = "NVIDIA Tegra Ventana"; + + nvidia,audio-routing = + "Headphone Jack", "HPOUTR", + "Headphone Jack", "HPOUTL", + "Int Spk", "ROP", + "Int Spk", "RON", + "Int Spk", "LOP", + "Int Spk", "LON", + "Mic Jack", "MICBIAS", + "IN1L", "Mic Jack"; + + nvidia,i2s-controller = <&tegra_i2s1>; + nvidia,audio-codec = <&wm8903>; + + nvidia,spkr-en-gpios = <&wm8903 2 0>; + nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ + nvidia,int-mic-en-gpios = <&gpio 184 0>; /* gpio PX0 */ + nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */ + }; +}; diff --git a/arch/arm/boot/dts/tegra30-cardhu.dts b/arch/arm/boot/dts/tegra30-cardhu.dts new file mode 100644 index 000000000000..c169bced131e --- /dev/null +++ b/arch/arm/boot/dts/tegra30-cardhu.dts @@ -0,0 +1,171 @@ +/dts-v1/; + +/include/ "tegra30.dtsi" + +/ { + model = "NVIDIA Tegra30 Cardhu evaluation board"; + compatible = "nvidia,cardhu", "nvidia,tegra30"; + + memory { + reg = <0x80000000 0x40000000>; + }; + + pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + sdmmc1_clk_pz0 { + nvidia,pins = "sdmmc1_clk_pz0"; + nvidia,function = "sdmmc1"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + sdmmc1_cmd_pz1 { + nvidia,pins = "sdmmc1_cmd_pz1", + "sdmmc1_dat0_py7", + "sdmmc1_dat1_py6", + "sdmmc1_dat2_py5", + "sdmmc1_dat3_py4"; + nvidia,function = "sdmmc1"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + }; + sdmmc4_clk_pcc4 { + nvidia,pins = "sdmmc4_clk_pcc4", + "sdmmc4_rst_n_pcc3"; + nvidia,function = "sdmmc4"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + sdmmc4_dat0_paa0 { + nvidia,pins = "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat5_paa5", + "sdmmc4_dat6_paa6", + "sdmmc4_dat7_paa7"; + nvidia,function = "sdmmc4"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + }; + dap2_fs_pa2 { + nvidia,pins = "dap2_fs_pa2", + "dap2_sclk_pa3", + "dap2_din_pa4", + "dap2_dout_pa5"; + nvidia,function = "i2s1"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + }; + }; + + serial@70006000 { + status = "okay"; + clock-frequency = <408000000>; + }; + + i2c@7000c000 { + status = "okay"; + clock-frequency = <100000>; + }; + + i2c@7000c400 { + status = "okay"; + clock-frequency = <100000>; + }; + + i2c@7000c500 { + status = "okay"; + clock-frequency = <100000>; + + /* ALS and Proximity sensor */ + isl29028@44 { + compatible = "isil,isl29028"; + reg = <0x44>; + interrupt-parent = <&gpio>; + interrupts = <88 0x04>; /*gpio PL0 */ + }; + }; + + i2c@7000c700 { + status = "okay"; + clock-frequency = <100000>; + }; + + i2c@7000d000 { + status = "okay"; + clock-frequency = <100000>; + + wm8903: wm8903@1a { + compatible = "wlf,wm8903"; + reg = <0x1a>; + interrupt-parent = <&gpio>; + interrupts = <179 0x04>; /* gpio PW3 */ + + gpio-controller; + #gpio-cells = <2>; + + micdet-cfg = <0>; + micdet-delay = <100>; + gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>; + }; + + tps62361 { + compatible = "ti,tps62361"; + reg = <0x60>; + + regulator-name = "tps62361-vout"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + regulator-always-on; + ti,vsel0-state-high; + ti,vsel1-state-high; + }; + }; + + ahub { + i2s@70080400 { + status = "okay"; + }; + }; + + sdhci@78000000 { + status = "okay"; + cd-gpios = <&gpio 69 0>; /* gpio PI5 */ + wp-gpios = <&gpio 155 0>; /* gpio PT3 */ + power-gpios = <&gpio 31 0>; /* gpio PD7 */ + bus-width = <4>; + }; + + sdhci@78000600 { + status = "okay"; + bus-width = <8>; + }; + + sound { + compatible = "nvidia,tegra-audio-wm8903-cardhu", + "nvidia,tegra-audio-wm8903"; + nvidia,model = "NVIDIA Tegra Cardhu"; + + nvidia,audio-routing = + "Headphone Jack", "HPOUTR", + "Headphone Jack", "HPOUTL", + "Int Spk", "ROP", + "Int Spk", "RON", + "Int Spk", "LOP", + "Int Spk", "LON", + "Mic Jack", "MICBIAS", + "IN1L", "Mic Jack"; + + nvidia,i2s-controller = <&tegra_i2s1>; + nvidia,audio-codec = <&wm8903>; + + nvidia,spkr-en-gpios = <&wm8903 2 0>; + nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ + }; +}; diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot index 9a82094092d7..8040345bd971 100644 --- a/arch/arm/mach-tegra/Makefile.boot +++ b/arch/arm/mach-tegra/Makefile.boot @@ -2,9 +2,9 @@ zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC) += 0x00008000 params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00000100 initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00800000 -dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb -dtb-$(CONFIG_MACH_PAZ00) += tegra-paz00.dtb -dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb -dtb-$(CONFIG_MACH_TRIMSLICE) += tegra-trimslice.dtb -dtb-$(CONFIG_MACH_VENTANA) += tegra-ventana.dtb -dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra-cardhu.dtb +dtb-$(CONFIG_MACH_HARMONY) += tegra20-harmony.dtb +dtb-$(CONFIG_MACH_PAZ00) += tegra20-paz00.dtb +dtb-$(CONFIG_MACH_SEABOARD) += tegra20-seaboard.dtb +dtb-$(CONFIG_MACH_TRIMSLICE) += tegra20-trimslice.dtb +dtb-$(CONFIG_MACH_VENTANA) += tegra20-ventana.dtb +dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30-cardhu.dtb -- cgit v1.2.3 From 223ef78d04e1eea5490ee7c3dafdf6e259634fd1 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Mon, 11 Jun 2012 21:09:45 +0200 Subject: ARM: tegra: Fix dts files w/ status property: "disable" -> "disabled" This patches fixes some status = "disable" strings to "disabled", the correct way of disabling nodes in the devicetree. Just the tegra part here. Everything else goes via other patches and trees. Signed-off-by: Roland Stigge Acked-by: Rob Herring Signed-off-by: Stephen Warren --- arch/arm/boot/dts/tegra20.dtsi | 36 ++++++++++++++++++------------------ arch/arm/boot/dts/tegra30.dtsi | 38 +++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 37 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 59116b852434..9f1921634eb7 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -72,7 +72,7 @@ reg = <0x70002800 0x200>; interrupts = <0 13 0x04>; nvidia,dma-request-selector = <&apbdma 2>; - status = "disable"; + status = "disabled"; }; tegra_i2s2: i2s@70002a00 { @@ -80,7 +80,7 @@ reg = <0x70002a00 0x200>; interrupts = <0 3 0x04>; nvidia,dma-request-selector = <&apbdma 1>; - status = "disable"; + status = "disabled"; }; serial@70006000 { @@ -88,7 +88,7 @@ reg = <0x70006000 0x40>; reg-shift = <2>; interrupts = <0 36 0x04>; - status = "disable"; + status = "disabled"; }; serial@70006040 { @@ -96,7 +96,7 @@ reg = <0x70006040 0x40>; reg-shift = <2>; interrupts = <0 37 0x04>; - status = "disable"; + status = "disabled"; }; serial@70006200 { @@ -104,7 +104,7 @@ reg = <0x70006200 0x100>; reg-shift = <2>; interrupts = <0 46 0x04>; - status = "disable"; + status = "disabled"; }; serial@70006300 { @@ -112,7 +112,7 @@ reg = <0x70006300 0x100>; reg-shift = <2>; interrupts = <0 90 0x04>; - status = "disable"; + status = "disabled"; }; serial@70006400 { @@ -120,7 +120,7 @@ reg = <0x70006400 0x100>; reg-shift = <2>; interrupts = <0 91 0x04>; - status = "disable"; + status = "disabled"; }; i2c@7000c000 { @@ -129,7 +129,7 @@ interrupts = <0 38 0x04>; #address-cells = <1>; #size-cells = <0>; - status = "disable"; + status = "disabled"; }; i2c@7000c400 { @@ -138,7 +138,7 @@ interrupts = <0 84 0x04>; #address-cells = <1>; #size-cells = <0>; - status = "disable"; + status = "disabled"; }; i2c@7000c500 { @@ -147,7 +147,7 @@ interrupts = <0 92 0x04>; #address-cells = <1>; #size-cells = <0>; - status = "disable"; + status = "disabled"; }; i2c@7000d000 { @@ -156,7 +156,7 @@ interrupts = <0 53 0x04>; #address-cells = <1>; #size-cells = <0>; - status = "disable"; + status = "disabled"; }; pmc { @@ -190,7 +190,7 @@ interrupts = <0 20 0x04>; phy_type = "utmi"; nvidia,has-legacy-mode; - status = "disable"; + status = "disabled"; }; usb@c5004000 { @@ -198,7 +198,7 @@ reg = <0xc5004000 0x4000>; interrupts = <0 21 0x04>; phy_type = "ulpi"; - status = "disable"; + status = "disabled"; }; usb@c5008000 { @@ -206,35 +206,35 @@ reg = <0xc5008000 0x4000>; interrupts = <0 97 0x04>; phy_type = "utmi"; - status = "disable"; + status = "disabled"; }; sdhci@c8000000 { compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000000 0x200>; interrupts = <0 14 0x04>; - status = "disable"; + status = "disabled"; }; sdhci@c8000200 { compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000200 0x200>; interrupts = <0 15 0x04>; - status = "disable"; + status = "disabled"; }; sdhci@c8000400 { compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000400 0x200>; interrupts = <0 19 0x04>; - status = "disable"; + status = "disabled"; }; sdhci@c8000600 { compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000600 0x200>; interrupts = <0 31 0x04>; - status = "disable"; + status = "disabled"; }; pmu { diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index 19479393842e..da740191771f 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -82,7 +82,7 @@ reg = <0x70006000 0x40>; reg-shift = <2>; interrupts = <0 36 0x04>; - status = "disable"; + status = "disabled"; }; serial@70006040 { @@ -90,7 +90,7 @@ reg = <0x70006040 0x40>; reg-shift = <2>; interrupts = <0 37 0x04>; - status = "disable"; + status = "disabled"; }; serial@70006200 { @@ -98,7 +98,7 @@ reg = <0x70006200 0x100>; reg-shift = <2>; interrupts = <0 46 0x04>; - status = "disable"; + status = "disabled"; }; serial@70006300 { @@ -106,7 +106,7 @@ reg = <0x70006300 0x100>; reg-shift = <2>; interrupts = <0 90 0x04>; - status = "disable"; + status = "disabled"; }; serial@70006400 { @@ -114,7 +114,7 @@ reg = <0x70006400 0x100>; reg-shift = <2>; interrupts = <0 91 0x04>; - status = "disable"; + status = "disabled"; }; i2c@7000c000 { @@ -123,7 +123,7 @@ interrupts = <0 38 0x04>; #address-cells = <1>; #size-cells = <0>; - status = "disable"; + status = "disabled"; }; i2c@7000c400 { @@ -132,7 +132,7 @@ interrupts = <0 84 0x04>; #address-cells = <1>; #size-cells = <0>; - status = "disable"; + status = "disabled"; }; i2c@7000c500 { @@ -141,7 +141,7 @@ interrupts = <0 92 0x04>; #address-cells = <1>; #size-cells = <0>; - status = "disable"; + status = "disabled"; }; i2c@7000c700 { @@ -150,7 +150,7 @@ interrupts = <0 120 0x04>; #address-cells = <1>; #size-cells = <0>; - status = "disable"; + status = "disabled"; }; i2c@7000d000 { @@ -159,7 +159,7 @@ interrupts = <0 53 0x04>; #address-cells = <1>; #size-cells = <0>; - status = "disable"; + status = "disabled"; }; pmc { @@ -201,35 +201,35 @@ compatible = "nvidia,tegra30-i2s"; reg = <0x70080300 0x100>; nvidia,ahub-cif-ids = <4 4>; - status = "disable"; + status = "disabled"; }; tegra_i2s1: i2s@70080400 { compatible = "nvidia,tegra30-i2s"; reg = <0x70080400 0x100>; nvidia,ahub-cif-ids = <5 5>; - status = "disable"; + status = "disabled"; }; tegra_i2s2: i2s@70080500 { compatible = "nvidia,tegra30-i2s"; reg = <0x70080500 0x100>; nvidia,ahub-cif-ids = <6 6>; - status = "disable"; + status = "disabled"; }; tegra_i2s3: i2s@70080600 { compatible = "nvidia,tegra30-i2s"; reg = <0x70080600 0x100>; nvidia,ahub-cif-ids = <7 7>; - status = "disable"; + status = "disabled"; }; tegra_i2s4: i2s@70080700 { compatible = "nvidia,tegra30-i2s"; reg = <0x70080700 0x100>; nvidia,ahub-cif-ids = <8 8>; - status = "disable"; + status = "disabled"; }; }; @@ -237,28 +237,28 @@ compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci"; reg = <0x78000000 0x200>; interrupts = <0 14 0x04>; - status = "disable"; + status = "disabled"; }; sdhci@78000200 { compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci"; reg = <0x78000200 0x200>; interrupts = <0 15 0x04>; - status = "disable"; + status = "disabled"; }; sdhci@78000400 { compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci"; reg = <0x78000400 0x200>; interrupts = <0 19 0x04>; - status = "disable"; + status = "disabled"; }; sdhci@78000600 { compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci"; reg = <0x78000600 0x200>; interrupts = <0 31 0x04>; - status = "disable"; + status = "disabled"; }; pmu { -- cgit v1.2.3 From 95ef9958849381931a79ecec53e677e52c406c5a Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 13 Jun 2012 15:55:47 +0200 Subject: ARM: tegra: build powergate unconditionally powergate functions are needed for tegra30 as well (see common.c), so build it always. Fixes: arch/arm/mach-tegra/built-in.o: In function `tegra30_init_early': apbio.c:(.init.text+0x78): undefined reference to `tegra_powergate_init' (using "allnoconfig" with tegra30 enabled) Signed-off-by: Wolfram Sang Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 2eb4445ddb14..35253fdd1ba7 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -8,9 +8,9 @@ obj-y += timer.o obj-y += fuse.o obj-y += pmc.o obj-y += flowctrl.o +obj-y += powergate.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_CPU_IDLE) += sleep.o -obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += powergate.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o -- cgit v1.2.3 From 9132b0ed57320996b16eafbf651a04e02ad29092 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 21 May 2012 14:44:26 -0600 Subject: ARM: tegra: make .dts compilation depend on Tegra2 support Update Makefile.boot to compile *.dts when the appropriate Tegra SoC support is enabled, rather than requiring Kconfig to list each board individually. Remove CONFIG_MACH_VENTANA now that it has no use. Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/Kconfig | 7 ------- arch/arm/mach-tegra/Makefile.boot | 10 +++++----- 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 7c407393cd07..5b9b1166003f 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -108,13 +108,6 @@ config MACH_WARIO help Support for the Wario version of Seaboard -config MACH_VENTANA - bool "Ventana board" - depends on ARCH_TEGRA_2x_SOC - select MACH_TEGRA_DT - help - Support for the nVidia Ventana development platform - choice prompt "Default low-level debug console UART" default TEGRA_DEBUG_UART_NONE diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot index 8040345bd971..a369f96bd05e 100644 --- a/arch/arm/mach-tegra/Makefile.boot +++ b/arch/arm/mach-tegra/Makefile.boot @@ -2,9 +2,9 @@ zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC) += 0x00008000 params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00000100 initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00800000 -dtb-$(CONFIG_MACH_HARMONY) += tegra20-harmony.dtb -dtb-$(CONFIG_MACH_PAZ00) += tegra20-paz00.dtb -dtb-$(CONFIG_MACH_SEABOARD) += tegra20-seaboard.dtb -dtb-$(CONFIG_MACH_TRIMSLICE) += tegra20-trimslice.dtb -dtb-$(CONFIG_MACH_VENTANA) += tegra20-ventana.dtb +dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-harmony.dtb +dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-paz00.dtb +dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-seaboard.dtb +dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-trimslice.dtb +dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-ventana.dtb dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30-cardhu.dtb -- cgit v1.2.3 From 2c95b7e06f63b264500fbcd5b4718c1a7258aa76 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 21 May 2012 15:07:19 -0600 Subject: ARM: tegra: remove CONFIG_MACH_TEGRA_DT * Make ARCH_TEGRA select USE_OF; DT is the way forward. * Build board-dt-tegra*.c when the relevant Tegra SoC support is enabled, rather than requiring a specific config option for this. * The board-specific config options already build board-*-pinmux.o, and when booting from device tree these files are no longer needed, so we can remove some Makefile commands related to those files. Signed-off-by: Stephen Warren --- arch/arm/Kconfig | 1 + arch/arm/mach-tegra/Kconfig | 7 ------- arch/arm/mach-tegra/Makefile | 10 +++------- 3 files changed, 4 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 84449dd8f031..3b24b41458ae 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -645,6 +645,7 @@ config ARCH_TEGRA select MIGHT_HAVE_CACHE_L2X0 select NEED_MACH_IO_H if PCI select ARCH_HAS_CPUFREQ + select USE_OF help This enables support for NVIDIA Tegra based systems (Tegra APX, Tegra 6xx and Tegra 2 series). diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 5b9b1166003f..621466a717d1 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -87,13 +87,6 @@ config MACH_SEABOARD also be included for some of the derivative boards that have large similarities with the seaboard design. -config MACH_TEGRA_DT - bool "Generic Tegra20 board (FDT support)" - depends on ARCH_TEGRA_2x_SOC - select USE_OF - help - Support for generic NVIDIA Tegra20 boards using Flattened Device Tree - config MACH_TRIMSLICE bool "TrimSlice board" depends on ARCH_TEGRA_2x_SOC diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 2eb4445ddb14..60a02132d2da 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_CPU_IDLE) += sleep.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += powergate.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o -obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_SMP) += reset.o @@ -23,6 +22,9 @@ obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o obj-$(CONFIG_TEGRA_PCI) += pcie.o obj-$(CONFIG_USB_SUPPORT) += usb_phy.o +obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-dt-tegra20.o +obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o + obj-$(CONFIG_MACH_HARMONY) += board-harmony.o obj-$(CONFIG_MACH_HARMONY) += board-harmony-pinmux.o obj-$(CONFIG_MACH_HARMONY) += board-harmony-pcie.o @@ -34,11 +36,5 @@ obj-$(CONFIG_MACH_PAZ00) += board-paz00-pinmux.o obj-$(CONFIG_MACH_SEABOARD) += board-seaboard.o obj-$(CONFIG_MACH_SEABOARD) += board-seaboard-pinmux.o -obj-$(CONFIG_MACH_TEGRA_DT) += board-dt-tegra20.o -obj-$(CONFIG_MACH_TEGRA_DT) += board-harmony-pinmux.o -obj-$(CONFIG_MACH_TEGRA_DT) += board-seaboard-pinmux.o -obj-$(CONFIG_MACH_TEGRA_DT) += board-paz00-pinmux.o -obj-$(CONFIG_MACH_TEGRA_DT) += board-trimslice-pinmux.o - obj-$(CONFIG_MACH_TRIMSLICE) += board-trimslice.o obj-$(CONFIG_MACH_TRIMSLICE) += board-trimslice-pinmux.o -- cgit v1.2.3 From 98a1405e20ecf261abbc091eabb229d8adfbf62c Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 21 May 2012 14:40:14 -0600 Subject: ARM: tegra: remove Seaboard board files The Seaboard device tree supports all the features that the Seaboard board files support. Hence, there's no need to keep the board files around any more; all users should convert to device tree. MACH_KAEN and MACH_WARIO are also removed. While tegra-seaboard.dts doesn't support those explicitly, it would be trivial to create device trees for those boards if anyone cares. The Seaboard device tree is now compiled if Tegra2 support is enabled, rather than when Seaboard support is enabled. Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/Kconfig | 22 -- arch/arm/mach-tegra/Makefile | 3 - arch/arm/mach-tegra/board-seaboard-pinmux.c | 197 ------------------ arch/arm/mach-tegra/board-seaboard.c | 306 ---------------------------- arch/arm/mach-tegra/board-seaboard.h | 47 ----- 5 files changed, 575 deletions(-) delete mode 100644 arch/arm/mach-tegra/board-seaboard-pinmux.c delete mode 100644 arch/arm/mach-tegra/board-seaboard.c delete mode 100644 arch/arm/mach-tegra/board-seaboard.h (limited to 'arch') diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 621466a717d1..9077aaa398d9 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -66,27 +66,12 @@ config MACH_HARMONY help Support for nVidia Harmony development platform -config MACH_KAEN - bool "Kaen board" - depends on ARCH_TEGRA_2x_SOC - select MACH_SEABOARD - help - Support for the Kaen version of Seaboard - config MACH_PAZ00 bool "Paz00 board" depends on ARCH_TEGRA_2x_SOC help Support for the Toshiba AC100/Dynabook AZ netbook -config MACH_SEABOARD - bool "Seaboard board" - depends on ARCH_TEGRA_2x_SOC - help - Support for nVidia Seaboard development platform. It will - also be included for some of the derivative boards that - have large similarities with the seaboard design. - config MACH_TRIMSLICE bool "TrimSlice board" depends on ARCH_TEGRA_2x_SOC @@ -94,13 +79,6 @@ config MACH_TRIMSLICE help Support for CompuLab TrimSlice platform -config MACH_WARIO - bool "Wario board" - depends on ARCH_TEGRA_2x_SOC - select MACH_SEABOARD - help - Support for the Wario version of Seaboard - choice prompt "Default low-level debug console UART" default TEGRA_DEBUG_UART_NONE diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 60a02132d2da..1f6f237586e4 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -33,8 +33,5 @@ obj-$(CONFIG_MACH_HARMONY) += board-harmony-power.o obj-$(CONFIG_MACH_PAZ00) += board-paz00.o obj-$(CONFIG_MACH_PAZ00) += board-paz00-pinmux.o -obj-$(CONFIG_MACH_SEABOARD) += board-seaboard.o -obj-$(CONFIG_MACH_SEABOARD) += board-seaboard-pinmux.o - obj-$(CONFIG_MACH_TRIMSLICE) += board-trimslice.o obj-$(CONFIG_MACH_TRIMSLICE) += board-trimslice-pinmux.o diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c deleted file mode 100644 index 11fc8a568c64..000000000000 --- a/arch/arm/mach-tegra/board-seaboard-pinmux.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2010-2012 NVIDIA Corporation - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include - -#include "board-seaboard.h" -#include "board-pinmux.h" - -static unsigned long seaboard_pincfg_drive_sdio1[] = { - TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE, 0), - TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_SCHMITT, 0), - TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_LOW_POWER_MODE, 3), - TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH, 31), - TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH, 31), - TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING, 3), - TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_SLEW_RATE_RISING, 3), -}; - -static struct pinctrl_map common_map[] = { - TEGRA_MAP_MUXCONF("ata", "ide", none, driven), - TEGRA_MAP_MUXCONF("atb", "sdio4", none, driven), - TEGRA_MAP_MUXCONF("atc", "nand", none, driven), - TEGRA_MAP_MUXCONF("atd", "gmi", none, driven), - TEGRA_MAP_MUXCONF("ate", "gmi", none, tristate), - TEGRA_MAP_MUXCONF("cdev1", "plla_out", none, driven), - TEGRA_MAP_MUXCONF("cdev2", "pllp_out4", none, driven), - TEGRA_MAP_MUXCONF("crtp", "crt", up, tristate), - TEGRA_MAP_MUXCONF("csus", "vi_sensor_clk", none, tristate), - TEGRA_MAP_MUXCONF("dap1", "dap1", none, driven), - TEGRA_MAP_MUXCONF("dap2", "dap2", none, driven), - TEGRA_MAP_MUXCONF("dap3", "dap3", none, tristate), - TEGRA_MAP_MUXCONF("dap4", "dap4", none, driven), - TEGRA_MAP_MUXCONF("dta", "vi", down, driven), - TEGRA_MAP_MUXCONF("dtb", "vi", down, driven), - TEGRA_MAP_MUXCONF("dtc", "vi", down, driven), - TEGRA_MAP_MUXCONF("dtd", "vi", down, driven), - TEGRA_MAP_MUXCONF("dte", "vi", down, tristate), - TEGRA_MAP_MUXCONF("dtf", "i2c3", none, driven), - TEGRA_MAP_MUXCONF("gma", "sdio4", none, driven), - TEGRA_MAP_MUXCONF("gmb", "gmi", up, tristate), - TEGRA_MAP_MUXCONF("gmc", "uartd", none, driven), - TEGRA_MAP_MUXCONF("gme", "sdio4", none, driven), - TEGRA_MAP_MUXCONF("gpu", "pwm", none, driven), - TEGRA_MAP_MUXCONF("gpu7", "rtck", none, driven), - TEGRA_MAP_MUXCONF("gpv", "pcie", none, tristate), - TEGRA_MAP_MUXCONF("hdint", "hdmi", na, tristate), - TEGRA_MAP_MUXCONF("i2cp", "i2cp", none, driven), - TEGRA_MAP_MUXCONF("irrx", "uartb", none, driven), - TEGRA_MAP_MUXCONF("irtx", "uartb", none, driven), - TEGRA_MAP_MUXCONF("kbca", "kbc", up, driven), - TEGRA_MAP_MUXCONF("kbcb", "kbc", up, driven), - TEGRA_MAP_MUXCONF("kbcc", "kbc", up, driven), - TEGRA_MAP_MUXCONF("kbcd", "kbc", up, driven), - TEGRA_MAP_MUXCONF("kbce", "kbc", up, driven), - TEGRA_MAP_MUXCONF("kbcf", "kbc", up, driven), - TEGRA_MAP_MUXCONF("lcsn", "rsvd4", na, tristate), - TEGRA_MAP_MUXCONF("ld0", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld1", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld10", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld11", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld12", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld13", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld14", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld15", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld16", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld17", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld2", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld3", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld4", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld5", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld6", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld7", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld8", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ld9", "displaya", na, driven), - TEGRA_MAP_MUXCONF("ldc", "rsvd4", na, tristate), - TEGRA_MAP_MUXCONF("ldi", "displaya", na, driven), - TEGRA_MAP_MUXCONF("lhp0", "displaya", na, driven), - TEGRA_MAP_MUXCONF("lhp1", "displaya", na, driven), - TEGRA_MAP_MUXCONF("lhp2", "displaya", na, driven), - TEGRA_MAP_MUXCONF("lhs", "displaya", na, driven), - TEGRA_MAP_MUXCONF("lm0", "rsvd4", na, driven), - TEGRA_MAP_MUXCONF("lm1", "crt", na, tristate), - TEGRA_MAP_MUXCONF("lpp", "displaya", na, driven), - TEGRA_MAP_MUXCONF("lpw1", "rsvd4", na, tristate), - TEGRA_MAP_MUXCONF("lsc0", "displaya", na, driven), - TEGRA_MAP_MUXCONF("lsdi", "rsvd4", na, tristate), - TEGRA_MAP_MUXCONF("lspi", "displaya", na, driven), - TEGRA_MAP_MUXCONF("lvp0", "rsvd4", na, tristate), - TEGRA_MAP_MUXCONF("lvp1", "displaya", na, driven), - TEGRA_MAP_MUXCONF("lvs", "displaya", na, driven), - TEGRA_MAP_MUXCONF("owc", "rsvd2", none, tristate), - TEGRA_MAP_MUXCONF("pmc", "pwr_on", na, driven), - TEGRA_MAP_MUXCONF("pta", "hdmi", none, driven), - TEGRA_MAP_MUXCONF("rm", "i2c1", none, driven), - TEGRA_MAP_MUXCONF("sdb", "sdio3", na, driven), - TEGRA_MAP_MUXCONF("sdc", "sdio3", none, driven), - TEGRA_MAP_MUXCONF("sdd", "sdio3", none, driven), - TEGRA_MAP_MUXCONF("sdio1", "sdio1", up, driven), - TEGRA_MAP_MUXCONF("slxa", "pcie", up, tristate), - TEGRA_MAP_MUXCONF("slxd", "spdif", none, driven), - TEGRA_MAP_MUXCONF("slxk", "pcie", none, driven), - TEGRA_MAP_MUXCONF("spdi", "rsvd2", none, driven), - TEGRA_MAP_MUXCONF("spdo", "rsvd2", none, driven), - TEGRA_MAP_MUXCONF("spib", "gmi", none, tristate), - TEGRA_MAP_MUXCONF("spid", "spi1", none, tristate), - TEGRA_MAP_MUXCONF("spie", "spi1", none, tristate), - TEGRA_MAP_MUXCONF("spif", "spi1", down, tristate), - TEGRA_MAP_MUXCONF("spih", "spi2_alt", up, tristate), - TEGRA_MAP_MUXCONF("uaa", "ulpi", up, driven), - TEGRA_MAP_MUXCONF("uab", "ulpi", up, driven), - TEGRA_MAP_MUXCONF("uac", "rsvd2", none, driven), - TEGRA_MAP_MUXCONF("uad", "irda", none, driven), - TEGRA_MAP_MUXCONF("uca", "uartc", none, driven), - TEGRA_MAP_MUXCONF("ucb", "uartc", none, driven), - TEGRA_MAP_MUXCONF("uda", "ulpi", none, driven), - TEGRA_MAP_CONF("ck32", none, na), - TEGRA_MAP_CONF("ddrc", none, na), - TEGRA_MAP_CONF("pmca", none, na), - TEGRA_MAP_CONF("pmcb", none, na), - TEGRA_MAP_CONF("pmcc", none, na), - TEGRA_MAP_CONF("pmcd", none, na), - TEGRA_MAP_CONF("pmce", none, na), - TEGRA_MAP_CONF("xm2c", none, na), - TEGRA_MAP_CONF("xm2d", none, na), - TEGRA_MAP_CONF("ls", up, na), - TEGRA_MAP_CONF("lc", up, na), - TEGRA_MAP_CONF("ld17_0", down, na), - TEGRA_MAP_CONF("ld19_18", down, na), - TEGRA_MAP_CONF("ld21_20", down, na), - TEGRA_MAP_CONF("ld23_22", down, na), -}; - -static struct pinctrl_map seaboard_map[] = { - TEGRA_MAP_MUXCONF("ddc", "rsvd2", none, tristate), - TEGRA_MAP_MUXCONF("gmd", "sflash", none, driven), - TEGRA_MAP_MUXCONF("lpw0", "hdmi", na, driven), - TEGRA_MAP_MUXCONF("lpw2", "hdmi", na, driven), - TEGRA_MAP_MUXCONF("lsc1", "hdmi", na, tristate), - TEGRA_MAP_MUXCONF("lsck", "hdmi", na, tristate), - TEGRA_MAP_MUXCONF("lsda", "hdmi", na, tristate), - TEGRA_MAP_MUXCONF("slxc", "spdif", none, tristate), - TEGRA_MAP_MUXCONF("spia", "gmi", up, tristate), - TEGRA_MAP_MUXCONF("spic", "gmi", up, driven), - TEGRA_MAP_MUXCONF("spig", "spi2_alt", up, tristate), - PIN_MAP_CONFIGS_GROUP_HOG_DEFAULT(PINMUX_DEV, "drive_sdio1", seaboard_pincfg_drive_sdio1), -}; - -static struct pinctrl_map ventana_map[] = { - TEGRA_MAP_MUXCONF("ddc", "rsvd2", none, driven), - TEGRA_MAP_MUXCONF("gmd", "sflash", none, tristate), - TEGRA_MAP_MUXCONF("lpw0", "displaya", na, driven), - TEGRA_MAP_MUXCONF("lpw2", "displaya", na, driven), - TEGRA_MAP_MUXCONF("lsc1", "displaya", na, driven), - TEGRA_MAP_MUXCONF("lsck", "displaya", na, tristate), - TEGRA_MAP_MUXCONF("lsda", "displaya", na, tristate), - TEGRA_MAP_MUXCONF("slxc", "sdio3", none, driven), - TEGRA_MAP_MUXCONF("spia", "gmi", none, tristate), - TEGRA_MAP_MUXCONF("spic", "gmi", none, tristate), - TEGRA_MAP_MUXCONF("spig", "spi2_alt", none, tristate), -}; - -static struct tegra_board_pinmux_conf common_conf = { - .maps = common_map, - .map_count = ARRAY_SIZE(common_map), -}; - -static struct tegra_board_pinmux_conf seaboard_conf = { - .maps = seaboard_map, - .map_count = ARRAY_SIZE(seaboard_map), -}; - -static struct tegra_board_pinmux_conf ventana_conf = { - .maps = ventana_map, - .map_count = ARRAY_SIZE(ventana_map), -}; - -void seaboard_pinmux_init(void) -{ - tegra_board_pinmux_init(&common_conf, &seaboard_conf); -} - -void ventana_pinmux_init(void) -{ - tegra_board_pinmux_init(&common_conf, &ventana_conf); -} diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c deleted file mode 100644 index 71e9f3fc7fba..000000000000 --- a/arch/arm/mach-tegra/board-seaboard.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (c) 2010, 2011 NVIDIA Corporation. - * Copyright (C) 2010, 2011 Google, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "board.h" -#include "board-seaboard.h" -#include "clock.h" -#include "devices.h" -#include "gpio-names.h" - -static struct plat_serial8250_port debug_uart_platform_data[] = { - { - /* Memory and IRQ filled in before registration */ - .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, - .type = PORT_TEGRA, - .handle_break = tegra_serial_handle_break, - .iotype = UPIO_MEM, - .regshift = 2, - .uartclk = 216000000, - }, { - .flags = 0, - } -}; - -static struct platform_device debug_uart = { - .name = "serial8250", - .id = PLAT8250_DEV_PLATFORM, - .dev = { - .platform_data = debug_uart_platform_data, - }, -}; - -static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = { - /* name parent rate enabled */ - { "uartb", "pll_p", 216000000, true}, - { "uartd", "pll_p", 216000000, true}, - { "pll_a", "pll_p_out1", 56448000, true }, - { "pll_a_out0", "pll_a", 11289600, true }, - { "cdev1", NULL, 0, true }, - { "i2s1", "pll_a_out0", 11289600, false}, - { "usbd", "clk_m", 12000000, true}, - { "usb3", "clk_m", 12000000, true}, - { NULL, NULL, 0, 0}, -}; - -static struct gpio_keys_button seaboard_gpio_keys_buttons[] = { - { - .code = SW_LID, - .gpio = TEGRA_GPIO_LIDSWITCH, - .active_low = 0, - .desc = "Lid", - .type = EV_SW, - .wakeup = 1, - .debounce_interval = 1, - }, - { - .code = KEY_POWER, - .gpio = TEGRA_GPIO_POWERKEY, - .active_low = 1, - .desc = "Power", - .type = EV_KEY, - .wakeup = 1, - }, -}; - -static struct gpio_keys_platform_data seaboard_gpio_keys = { - .buttons = seaboard_gpio_keys_buttons, - .nbuttons = ARRAY_SIZE(seaboard_gpio_keys_buttons), -}; - -static struct platform_device seaboard_gpio_keys_device = { - .name = "gpio-keys", - .id = -1, - .dev = { - .platform_data = &seaboard_gpio_keys, - } -}; - -static struct tegra_sdhci_platform_data sdhci_pdata1 = { - .cd_gpio = -1, - .wp_gpio = -1, - .power_gpio = -1, -}; - -static struct tegra_sdhci_platform_data sdhci_pdata3 = { - .cd_gpio = TEGRA_GPIO_SD2_CD, - .wp_gpio = TEGRA_GPIO_SD2_WP, - .power_gpio = TEGRA_GPIO_SD2_POWER, -}; - -static struct tegra_sdhci_platform_data sdhci_pdata4 = { - .cd_gpio = -1, - .wp_gpio = -1, - .power_gpio = -1, - .is_8bit = 1, -}; - -static struct tegra_wm8903_platform_data seaboard_audio_pdata = { - .gpio_spkr_en = TEGRA_GPIO_SPKR_EN, - .gpio_hp_det = TEGRA_GPIO_HP_DET, - .gpio_hp_mute = -1, - .gpio_int_mic_en = -1, - .gpio_ext_mic_en = -1, -}; - -static struct platform_device seaboard_audio_device = { - .name = "tegra-snd-wm8903", - .id = 0, - .dev = { - .platform_data = &seaboard_audio_pdata, - }, -}; - -static struct platform_device *seaboard_devices[] __initdata = { - &debug_uart, - &tegra_pmu_device, - &tegra_sdhci_device4, - &tegra_sdhci_device3, - &tegra_sdhci_device1, - &seaboard_gpio_keys_device, - &tegra_i2s_device1, - &tegra_das_device, - &seaboard_audio_device, -}; - -static struct i2c_board_info __initdata isl29018_device = { - I2C_BOARD_INFO("isl29018", 0x44), -}; - -static struct i2c_board_info __initdata adt7461_device = { - I2C_BOARD_INFO("adt7461", 0x4c), -}; - -static struct wm8903_platform_data wm8903_pdata = { - .irq_active_low = 0, - .micdet_cfg = 0, - .micdet_delay = 100, - .gpio_base = SEABOARD_GPIO_WM8903(0), - .gpio_cfg = { - 0, - 0, - WM8903_GPIO_CONFIG_ZERO, - 0, - 0, - }, -}; - -static struct i2c_board_info __initdata wm8903_device = { - I2C_BOARD_INFO("wm8903", 0x1a), - .platform_data = &wm8903_pdata, -}; - -static int seaboard_ehci_init(void) -{ - struct tegra_ehci_platform_data *pdata; - - pdata = tegra_ehci1_device.dev.platform_data; - pdata->vbus_gpio = TEGRA_GPIO_USB1; - - platform_device_register(&tegra_ehci1_device); - platform_device_register(&tegra_ehci3_device); - - return 0; -} - -static void __init seaboard_i2c_init(void) -{ - isl29018_device.irq = gpio_to_irq(TEGRA_GPIO_ISL29018_IRQ); - i2c_register_board_info(0, &isl29018_device, 1); - - wm8903_device.irq = gpio_to_irq(TEGRA_GPIO_CDC_IRQ); - i2c_register_board_info(0, &wm8903_device, 1); - - i2c_register_board_info(3, &adt7461_device, 1); - - platform_device_register(&tegra_i2c_device1); - platform_device_register(&tegra_i2c_device2); - platform_device_register(&tegra_i2c_device3); - platform_device_register(&tegra_i2c_device4); -} - -static void __init seaboard_common_init(void) -{ - seaboard_pinmux_init(); - - tegra_clk_init_from_table(seaboard_clk_init_table); - - tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1; - tegra_sdhci_device3.dev.platform_data = &sdhci_pdata3; - tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4; - - platform_add_devices(seaboard_devices, ARRAY_SIZE(seaboard_devices)); - - seaboard_ehci_init(); -} - -static void __init tegra_seaboard_init(void) -{ - /* Seaboard uses UARTD for the debug port. */ - debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTD_BASE); - debug_uart_platform_data[0].mapbase = TEGRA_UARTD_BASE; - debug_uart_platform_data[0].irq = INT_UARTD; - - seaboard_common_init(); - - seaboard_i2c_init(); -} - -static void __init tegra_kaen_init(void) -{ - /* Kaen uses UARTB for the debug port. */ - debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE); - debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE; - debug_uart_platform_data[0].irq = INT_UARTB; - - seaboard_audio_pdata.gpio_hp_mute = TEGRA_GPIO_KAEN_HP_MUTE; - - seaboard_common_init(); - - seaboard_i2c_init(); -} - -static void __init tegra_wario_init(void) -{ - /* Wario uses UARTB for the debug port. */ - debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE); - debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE; - debug_uart_platform_data[0].irq = INT_UARTB; - - seaboard_common_init(); - - seaboard_i2c_init(); -} - - -MACHINE_START(SEABOARD, "seaboard") - .atag_offset = 0x100, - .map_io = tegra_map_common_io, - .init_early = tegra20_init_early, - .init_irq = tegra_init_irq, - .handle_irq = gic_handle_irq, - .timer = &tegra_timer, - .init_machine = tegra_seaboard_init, - .init_late = tegra_init_late, - .restart = tegra_assert_system_reset, -MACHINE_END - -MACHINE_START(KAEN, "kaen") - .atag_offset = 0x100, - .map_io = tegra_map_common_io, - .init_early = tegra20_init_early, - .init_irq = tegra_init_irq, - .handle_irq = gic_handle_irq, - .timer = &tegra_timer, - .init_machine = tegra_kaen_init, - .init_late = tegra_init_late, - .restart = tegra_assert_system_reset, -MACHINE_END - -MACHINE_START(WARIO, "wario") - .atag_offset = 0x100, - .map_io = tegra_map_common_io, - .init_early = tegra20_init_early, - .init_irq = tegra_init_irq, - .handle_irq = gic_handle_irq, - .timer = &tegra_timer, - .init_machine = tegra_wario_init, - .init_late = tegra_init_late, - .restart = tegra_assert_system_reset, -MACHINE_END diff --git a/arch/arm/mach-tegra/board-seaboard.h b/arch/arm/mach-tegra/board-seaboard.h deleted file mode 100644 index 4c45d4ca3c49..000000000000 --- a/arch/arm/mach-tegra/board-seaboard.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * arch/arm/mach-tegra/board-seaboard.h - * - * Copyright (C) 2010 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _MACH_TEGRA_BOARD_SEABOARD_H -#define _MACH_TEGRA_BOARD_SEABOARD_H - -#include - -#define SEABOARD_GPIO_TPS6586X(_x_) (TEGRA_NR_GPIOS + (_x_)) -#define SEABOARD_GPIO_WM8903(_x_) (SEABOARD_GPIO_TPS6586X(4) + (_x_)) - -#define TEGRA_GPIO_SD2_CD TEGRA_GPIO_PI5 -#define TEGRA_GPIO_SD2_WP TEGRA_GPIO_PH1 -#define TEGRA_GPIO_SD2_POWER TEGRA_GPIO_PI6 -#define TEGRA_GPIO_LIDSWITCH TEGRA_GPIO_PC7 -#define TEGRA_GPIO_USB1 TEGRA_GPIO_PD0 -#define TEGRA_GPIO_POWERKEY TEGRA_GPIO_PV2 -#define TEGRA_GPIO_BACKLIGHT TEGRA_GPIO_PD4 -#define TEGRA_GPIO_LVDS_SHUTDOWN TEGRA_GPIO_PB2 -#define TEGRA_GPIO_BACKLIGHT_PWM TEGRA_GPIO_PU5 -#define TEGRA_GPIO_BACKLIGHT_VDD TEGRA_GPIO_PW0 -#define TEGRA_GPIO_EN_VDD_PNL TEGRA_GPIO_PC6 -#define TEGRA_GPIO_MAGNETOMETER TEGRA_GPIO_PN5 -#define TEGRA_GPIO_ISL29018_IRQ TEGRA_GPIO_PZ2 -#define TEGRA_GPIO_AC_ONLINE TEGRA_GPIO_PV3 -#define TEGRA_GPIO_WWAN_PWR SEABOARD_GPIO_TPS6586X(2) -#define TEGRA_GPIO_CDC_IRQ TEGRA_GPIO_PX3 -#define TEGRA_GPIO_SPKR_EN SEABOARD_GPIO_WM8903(2) -#define TEGRA_GPIO_HP_DET TEGRA_GPIO_PX1 -#define TEGRA_GPIO_KAEN_HP_MUTE TEGRA_GPIO_PA5 - -void seaboard_pinmux_init(void); - -#endif -- cgit v1.2.3 From c554dee35c3e6b0c19db5fb75193d4cd99736c6b Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 2 May 2012 13:43:26 -0600 Subject: ARM: tegra: trimslice: enable PCIe when booting from device tree There currently aren't bindings for the Tegra PCIe controller. Work on this is in progress, but not yet complete. Manually initialize PCIe when booting from device tree, in order to bring DT support to the same feature level as board files, which will in turn allow board files to be deprecated. PCIe hosts the wired Ethernet controller on TrimSlice. To support this, add infra-structure to board-dt-tegra20.c for board- specific initialization code. Once device tree support for the relevant features is in place, this code will be removed. Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/board-dt-tegra20.c | 36 +++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c index eb7249db50a5..9537f20384fc 100644 --- a/arch/arm/mach-tegra/board-dt-tegra20.c +++ b/arch/arm/mach-tegra/board-dt-tegra20.c @@ -98,6 +98,40 @@ static void __init tegra_dt_init(void) tegra20_auxdata_lookup, NULL); } +#ifdef CONFIG_MACH_TRIMSLICE +static void __init trimslice_init(void) +{ + int ret; + + ret = tegra_pcie_init(true, true); + if (ret) + pr_err("tegra_pci_init() failed: %d\n", ret); +} +#endif + +static struct { + char *machine; + void (*init)(void); +} board_init_funcs[] = { +#ifdef CONFIG_MACH_TRIMSLICE + { "compulab,trimslice", trimslice_init }, +#endif +}; + +static void __init tegra_dt_init_late(void) +{ + int i; + + tegra_init_late(); + + for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) { + if (of_machine_is_compatible(board_init_funcs[i].machine)) { + board_init_funcs[i].init(); + break; + } + } +} + static const char *tegra20_dt_board_compat[] = { "nvidia,tegra20", NULL @@ -110,7 +144,7 @@ DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)") .handle_irq = gic_handle_irq, .timer = &tegra_timer, .init_machine = tegra_dt_init, - .init_late = tegra_init_late, + .init_late = tegra_dt_init_late, .restart = tegra_assert_system_reset, .dt_compat = tegra20_dt_board_compat, MACHINE_END -- cgit v1.2.3 From a12c0efc7a3f433377add0fa1fd0ed4836cc595e Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 2 May 2012 15:47:12 -0600 Subject: ARM: tegra: harmony: init regulators, PCIe when booting from DT There currently aren't bindings for the Tegra PCIe controller. Work on this is in progress, but not yet complete. Manually initialize PCIe when booting from device tree, in order to bring DT support to the same feature level as board files, which will in turn allow board files to be deprecated. PCIe on Harmony requires various regulators to be registered and enabled before initializing the PCIe controller. Note that since the I2C controllers are instantiated from DT, we must use i2c_new_device() to register the PMU rather than i2c_register_board_info(). Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/board-dt-tegra20.c | 20 ++++++++++++++++++++ arch/arm/mach-tegra/board-harmony-pcie.c | 15 ++++++++++----- arch/arm/mach-tegra/board-harmony-power.c | 25 ++++++++++++++++++++++++- arch/arm/mach-tegra/board.h | 7 +++++++ 4 files changed, 61 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c index 9537f20384fc..777138611c77 100644 --- a/arch/arm/mach-tegra/board-dt-tegra20.c +++ b/arch/arm/mach-tegra/board-dt-tegra20.c @@ -109,6 +109,23 @@ static void __init trimslice_init(void) } #endif +#ifdef CONFIG_MACH_HARMONY +static void __init harmony_init(void) +{ + int ret; + + ret = harmony_regulator_init(); + if (ret) { + pr_err("harmony_regulator_init() failed: %d\n", ret); + return; + } + + ret = harmony_pcie_init(); + if (ret) + pr_err("harmony_pcie_init() failed: %d\n", ret); +} +#endif + static struct { char *machine; void (*init)(void); @@ -116,6 +133,9 @@ static struct { #ifdef CONFIG_MACH_TRIMSLICE { "compulab,trimslice", trimslice_init }, #endif +#ifdef CONFIG_MACH_HARMONY + { "nvidia,harmony", harmony_init }, +#endif }; static void __init tegra_dt_init_late(void) diff --git a/arch/arm/mach-tegra/board-harmony-pcie.c b/arch/arm/mach-tegra/board-harmony-pcie.c index 33c4fedab840..e8c3fda9bec2 100644 --- a/arch/arm/mach-tegra/board-harmony-pcie.c +++ b/arch/arm/mach-tegra/board-harmony-pcie.c @@ -27,14 +27,11 @@ #ifdef CONFIG_TEGRA_PCI -static int __init harmony_pcie_init(void) +int __init harmony_pcie_init(void) { struct regulator *regulator = NULL; int err; - if (!machine_is_harmony()) - return 0; - err = gpio_request(TEGRA_GPIO_EN_VDD_1V05_GPIO, "EN_VDD_1V05"); if (err) return err; @@ -62,7 +59,15 @@ err_reg: return err; } +static int __init harmony_pcie_initcall(void) +{ + if (!machine_is_harmony()) + return 0; + + return harmony_pcie_init(); +} + /* PCI should be initialized after I2C, mfd and regulators */ -subsys_initcall_sync(harmony_pcie_init); +subsys_initcall_sync(harmony_pcie_initcall); #endif diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c index 82f32300796c..44dcb2e869b5 100644 --- a/arch/arm/mach-tegra/board-harmony-power.c +++ b/arch/arm/mach-tegra/board-harmony-power.c @@ -20,6 +20,10 @@ #include #include #include +#include +#include + +#include #include @@ -110,7 +114,26 @@ static struct i2c_board_info __initdata harmony_regulators[] = { int __init harmony_regulator_init(void) { - i2c_register_board_info(3, harmony_regulators, 1); + if (machine_is_harmony()) { + i2c_register_board_info(3, harmony_regulators, 1); + } else { /* Harmony, booted using device tree */ + struct device_node *np; + struct i2c_adapter *adapter; + + np = of_find_node_by_path("/i2c@7000d000"); + if (np == NULL) { + pr_err("Could not find device_node for DVC I2C\n"); + return -ENODEV; + } + + adapter = of_find_i2c_adapter_by_node(np); + if (!adapter) { + pr_err("Could not find i2c_adapter for DVC I2C\n"); + return -ENODEV; + } + + i2c_new_device(adapter, harmony_regulators); + } return 0; } diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h index 65014968fc6c..097e0e16eacd 100644 --- a/arch/arm/mach-tegra/board.h +++ b/arch/arm/mach-tegra/board.h @@ -46,5 +46,12 @@ int __init tegra_powergate_debugfs_init(void); static inline int tegra_powergate_debugfs_init(void) { return 0; } #endif +int __init harmony_regulator_init(void); +#ifdef CONFIG_TEGRA_PCI +int __init harmony_pcie_init(void); +#else +static inline int harmony_pcie_init(void) { return 0; } +#endif + extern struct sys_timer tegra_timer; #endif -- cgit v1.2.3 From b64a02c6fa184405ac2de0ea048be2f342144a08 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 2 May 2012 16:05:44 -0600 Subject: ARM: tegra: paz00: enable WiFi rfkill when booting from device tree There currently aren't bindings for a WiFi rfkill button, and defining a good binding is non-trivial. Manually register this "device" when booting from device tree, in order to bring DT support to the same feature level as board files, which will in turn allow board files to be deprecated. Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/board-dt-tegra20.c | 10 ++++++++++ arch/arm/mach-tegra/board-paz00.c | 7 ++++++- arch/arm/mach-tegra/board.h | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c index 777138611c77..8b4e6e1f0f7b 100644 --- a/arch/arm/mach-tegra/board-dt-tegra20.c +++ b/arch/arm/mach-tegra/board-dt-tegra20.c @@ -126,6 +126,13 @@ static void __init harmony_init(void) } #endif +#ifdef CONFIG_MACH_PAZ00 +static void __init paz00_init(void) +{ + tegra_paz00_wifikill_init(); +} +#endif + static struct { char *machine; void (*init)(void); @@ -136,6 +143,9 @@ static struct { #ifdef CONFIG_MACH_HARMONY { "nvidia,harmony", harmony_init }, #endif +#ifdef CONFIG_MACH_PAZ00 + { "compal,paz00", paz00_init }, +#endif }; static void __init tegra_dt_init_late(void) diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c index bbc1907e98a6..4b64af5cab27 100644 --- a/arch/arm/mach-tegra/board-paz00.c +++ b/arch/arm/mach-tegra/board-paz00.c @@ -148,7 +148,6 @@ static struct platform_device *paz00_devices[] __initdata = { &debug_uart, &tegra_sdhci_device4, &tegra_sdhci_device1, - &wifi_rfkill_device, &leds_gpio, &gpio_keys_device, }; @@ -201,6 +200,11 @@ static struct tegra_sdhci_platform_data sdhci_pdata4 = { .is_8bit = 1, }; +void __init tegra_paz00_wifikill_init(void) +{ + platform_device_register(&wifi_rfkill_device); +} + static void __init tegra_paz00_init(void) { tegra_clk_init_from_table(paz00_clk_init_table); @@ -211,6 +215,7 @@ static void __init tegra_paz00_init(void) tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4; platform_add_devices(paz00_devices, ARRAY_SIZE(paz00_devices)); + tegra_paz00_wifikill_init(); paz00_i2c_init(); paz00_usb_init(); diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h index 097e0e16eacd..f88e5143c767 100644 --- a/arch/arm/mach-tegra/board.h +++ b/arch/arm/mach-tegra/board.h @@ -53,5 +53,7 @@ int __init harmony_pcie_init(void); static inline int harmony_pcie_init(void) { return 0; } #endif +void __init tegra_paz00_wifikill_init(void); + extern struct sys_timer tegra_timer; #endif -- cgit v1.2.3 From 1521109318466c2e064dcbd732aa64f99a62852f Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Thu, 21 Jun 2012 03:43:57 +0900 Subject: ARM: S3C64XX: Add IRQ mapping for wm0010 on Cragganmore Signed-off-by: Dimitris Papastamos Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/mach-crag6410-module.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c index 4a83b4e7ab32..4645aa15c82a 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c @@ -39,6 +39,7 @@ static struct spi_board_info wm1253_devs[] = { .bus_num = 0, .chip_select = 0, .mode = SPI_MODE_0, + .irq = S3C_EINT(5), .controller_data = &wm0010_spi_csinfo, }, }; -- cgit v1.2.3 From 3dca938656c7b0ff6b0717a5dde0f5f45e592be5 Mon Sep 17 00:00:00 2001 From: Jose Miguel Goncalves Date: Sat, 12 May 2012 06:11:49 +0900 Subject: ARM: SAMSUNG: Fix for S3C2412 EBI memory mapping While upgrading the kernel on a S3C2412 based board I've noted that it was impossible to boot the board with a 2.6.32 or upper kernel. I've tracked down the problem to the EBI virtual memory mapping that is in conflict with the IO mapping definition in arch/arm/mach-s3c24xx/s3c2412.c. Signed-off-by: Jose Miguel Goncalves Cc: Stable Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/include/plat/map-s3c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/plat-samsung/include/plat/map-s3c.h b/arch/arm/plat-samsung/include/plat/map-s3c.h index 7d048759b772..c0c70a895ca8 100644 --- a/arch/arm/plat-samsung/include/plat/map-s3c.h +++ b/arch/arm/plat-samsung/include/plat/map-s3c.h @@ -22,7 +22,7 @@ #define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG #define S3C2412_VA_SSMC S3C_ADDR_CPU(0x00000000) -#define S3C2412_VA_EBI S3C_ADDR_CPU(0x00010000) +#define S3C2412_VA_EBI S3C_ADDR_CPU(0x00100000) #define S3C2410_PA_UART (0x50000000) #define S3C24XX_PA_UART S3C2410_PA_UART -- cgit v1.2.3 From e4eed03fd06578571c01d4f1478c874bb432c815 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Wed, 20 Jun 2012 12:52:57 -0700 Subject: thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE In the x86 32bit PAE CONFIG_TRANSPARENT_HUGEPAGE=y case while holding the mmap_sem for reading, cmpxchg8b cannot be used to read pmd contents under Xen. So instead of dealing only with "consistent" pmdvals in pmd_none_or_trans_huge_or_clear_bad() (which would be conceptually simpler) we let pmd_none_or_trans_huge_or_clear_bad() deal with pmdvals where the low 32bit and high 32bit could be inconsistent (to avoid having to use cmpxchg8b). The only guarantee we get from pmd_read_atomic is that if the low part of the pmd was found null, the high part will be null too (so the pmd will be considered unstable). And if the low part of the pmd is found "stable" later, then it means the whole pmd was read atomically (because after a pmd is stable, neither MADV_DONTNEED nor page faults can alter it anymore, and we read the high part after the low part). In the 32bit PAE x86 case, it is enough to read the low part of the pmdval atomically to declare the pmd as "stable" and that's true for THP and no THP, furthermore in the THP case we also have a barrier() that will prevent any inconsistent pmdvals to be cached by a later re-read of the *pmd. Signed-off-by: Andrea Arcangeli Cc: Jonathan Nieder Cc: Ulrich Obergfell Cc: Mel Gorman Cc: Hugh Dickins Cc: Larry Woodman Cc: Petr Matousek Cc: Rik van Riel Cc: Jan Beulich Cc: KOSAKI Motohiro Tested-by: Andrew Jones Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86/include/asm/pgtable-3level.h | 30 +++++++++++++++++------------- include/asm-generic/pgtable.h | 10 ++++++++++ 2 files changed, 27 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 43876f16caf1..cb00ccc7d571 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -47,16 +47,26 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte) * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd * operations. * - * Without THP if the mmap_sem is hold for reading, the - * pmd can only transition from null to not null while pmd_read_atomic runs. - * So there's no need of literally reading it atomically. + * Without THP if the mmap_sem is hold for reading, the pmd can only + * transition from null to not null while pmd_read_atomic runs. So + * we can always return atomic pmd values with this function. * * With THP if the mmap_sem is hold for reading, the pmd can become - * THP or null or point to a pte (and in turn become "stable") at any - * time under pmd_read_atomic, so it's mandatory to read it atomically - * with cmpxchg8b. + * trans_huge or none or point to a pte (and in turn become "stable") + * at any time under pmd_read_atomic. We could read it really + * atomically here with a atomic64_read for the THP enabled case (and + * it would be a whole lot simpler), but to avoid using cmpxchg8b we + * only return an atomic pmdval if the low part of the pmdval is later + * found stable (i.e. pointing to a pte). And we're returning a none + * pmdval if the low part of the pmd is none. In some cases the high + * and low part of the pmdval returned may not be consistent if THP is + * enabled (the low part may point to previously mapped hugepage, + * while the high part may point to a more recently mapped hugepage), + * but pmd_none_or_trans_huge_or_clear_bad() only needs the low part + * of the pmd to be read atomically to decide if the pmd is unstable + * or not, with the only exception of when the low part of the pmd is + * zero in which case we return a none pmd. */ -#ifndef CONFIG_TRANSPARENT_HUGEPAGE static inline pmd_t pmd_read_atomic(pmd_t *pmdp) { pmdval_t ret; @@ -74,12 +84,6 @@ static inline pmd_t pmd_read_atomic(pmd_t *pmdp) return (pmd_t) { ret }; } -#else /* CONFIG_TRANSPARENT_HUGEPAGE */ -static inline pmd_t pmd_read_atomic(pmd_t *pmdp) -{ - return (pmd_t) { atomic64_read((atomic64_t *)pmdp) }; -} -#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) { diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 6f2b45a9b6bc..ff4947b7a976 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -484,6 +484,16 @@ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) /* * The barrier will stabilize the pmdval in a register or on * the stack so that it will stop changing under the code. + * + * When CONFIG_TRANSPARENT_HUGEPAGE=y on x86 32bit PAE, + * pmd_read_atomic is allowed to return a not atomic pmdval + * (for example pointing to an hugepage that has never been + * mapped in the pmd). The below checks will only care about + * the low part of the pmd with 32bit PAE x86 anyway, with the + * exception of pmd_none(). So the important thing is that if + * the low part of the pmd is found null, the high part will + * be also null or the pmd_none() check below would be + * confused. */ #ifdef CONFIG_TRANSPARENT_HUGEPAGE barrier(); -- cgit v1.2.3 From 5e7b6ed8e9bf3c8e3bb579fd0aec64f6526f8c81 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Jun 2012 12:52:58 -0700 Subject: xtensa: replace xtensa-specific _f{data,text} by _s{data,text} commit a2d063ac216c161 ("extable, core_kernel_data(): Make sure all archs define _sdata") missed xtensa. Xtensa does have a start of data marker, but calls it _fdata, causing kernel/built-in.o:(.text+0x964): undefined reference to `_sdata' _stext was already defined, but it was duplicated by _fdata. Signed-off-by: Geert Uytterhoeven Cc: Steven Rostedt Cc: Chris Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/xtensa/kernel/vmlinux.lds.S | 3 +-- arch/xtensa/mm/init.c | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index 88ecea3facb4..ee2e2089483d 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S @@ -83,7 +83,6 @@ SECTIONS _text = .; _stext = .; - _ftext = .; .text : { @@ -112,7 +111,7 @@ SECTIONS EXCEPTION_TABLE(16) /* Data section */ - _fdata = .; + _sdata = .; RW_DATA_SECTION(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE) _edata = .; diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index ba150e5de2eb..c82af58f60bc 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c @@ -29,7 +29,7 @@ /* References to section boundaries */ -extern char _ftext, _etext, _fdata, _edata, _rodata_end; +extern char _stext, _etext, _sdata, _edata, _rodata_end; extern char __init_begin, __init_end; /* @@ -197,8 +197,8 @@ void __init mem_init(void) reservedpages++; } - codesize = (unsigned long) &_etext - (unsigned long) &_ftext; - datasize = (unsigned long) &_edata - (unsigned long) &_fdata; + codesize = (unsigned long) &_etext - (unsigned long) &_stext; + datasize = (unsigned long) &_edata - (unsigned long) &_sdata; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, " -- cgit v1.2.3 From 0eff08b5d1bf4b30f1a549a58c85806748256b18 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Jun 2012 12:52:59 -0700 Subject: xtensa: use "test -e" instead of bashism "test -a" On Ubuntu, /bin/sh is a symlink to dash, which does not support "test -a". This causes messages like test: 1: -a: unexpected operator test: 1: -a: unexpected operator and link failures like (.init.text+0x132): undefined reference to `platform_init' due to the appropriate platform code not being compiled. Signed-off-by: Geert Uytterhoeven Cc: Chris Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/xtensa/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile index 7608559de93a..f973754ddf90 100644 --- a/arch/xtensa/Makefile +++ b/arch/xtensa/Makefile @@ -68,8 +68,8 @@ endif # Only build variant and/or platform if it includes a Makefile -buildvar := $(shell test -a $(srctree)/arch/xtensa/variants/$(VARIANT)/Makefile && echo arch/xtensa/variants/$(VARIANT)/) -buildplf := $(shell test -a $(srctree)/arch/xtensa/platforms/$(PLATFORM)/Makefile && echo arch/xtensa/platforms/$(PLATFORM)/) +buildvar := $(shell test -e $(srctree)/arch/xtensa/variants/$(VARIANT)/Makefile && echo arch/xtensa/variants/$(VARIANT)/) +buildplf := $(shell test -e $(srctree)/arch/xtensa/platforms/$(PLATFORM)/Makefile && echo arch/xtensa/platforms/$(PLATFORM)/) # Find libgcc.a -- cgit v1.2.3 From f022d0fa183c4def30ddd74f2baebd72c4254fcf Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Jun 2012 12:52:59 -0700 Subject: xtensa: use the declarations provided by Cleanups: - Include , - Remove the (different) extern declarations, - Remove the no longer needed address-of ('&') operators, - Use %p to format pointer differences. Signed-off-by: Geert Uytterhoeven Cc: Chris Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/xtensa/mm/init.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index c82af58f60bc..db955179da2d 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c @@ -26,11 +26,7 @@ #include #include - -/* References to section boundaries */ - -extern char _stext, _etext, _sdata, _edata, _rodata_end; -extern char __init_begin, __init_end; +#include /* * mem_reserve(start, end, must_exist) @@ -197,9 +193,9 @@ void __init mem_init(void) reservedpages++; } - codesize = (unsigned long) &_etext - (unsigned long) &_stext; - datasize = (unsigned long) &_edata - (unsigned long) &_sdata; - initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; + codesize = (unsigned long) _etext - (unsigned long) _stext; + datasize = (unsigned long) _edata - (unsigned long) _sdata; + initsize = (unsigned long) __init_end - (unsigned long) __init_begin; printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, " "%ldk data, %ldk init %ldk highmem)\n", @@ -237,7 +233,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) void free_initmem(void) { - free_reserved_mem(&__init_begin, &__init_end); - printk("Freeing unused kernel memory: %dk freed\n", - (&__init_end - &__init_begin) >> 10); + free_reserved_mem(__init_begin, __init_end); + printk("Freeing unused kernel memory: %zuk freed\n", + (__init_end - __init_begin) >> 10); } -- cgit v1.2.3 From ffb20313c01addc04212577af5f9b1399156a5bd Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Jun 2012 12:53:00 -0700 Subject: h8300: fix use of extinct _sbss and _ebss Nowadays it should use __bss_start and __bss_stop Signed-off-by: Geert Uytterhoeven Cc: Yoshinori Sato Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/h8300/kernel/setup.c | 6 +++--- arch/h8300/mm/init.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c index 68d651081bd3..050f13665b8e 100644 --- a/arch/h8300/kernel/setup.c +++ b/arch/h8300/kernel/setup.c @@ -54,7 +54,7 @@ unsigned long memory_end; char __initdata command_line[COMMAND_LINE_SIZE]; -extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end; +extern int _stext, _etext, _sdata, _edata, __bss_start, __bss_stop, _end; extern int _ramstart, _ramend; extern char _target_name[]; extern void h8300_gpio_init(void); @@ -137,10 +137,10 @@ void __init setup_arch(char **cmdline_p) printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x " "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext, (int) &_sdata, (int) &_edata, - (int) &_sbss, (int) &_ebss); + (int) &__bss_start, (int) &__bss_stop); printk(KERN_DEBUG "KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x " "STACK=0x%06x-0x%06x\n", - (int) &_ebss, (int) memory_start, + (int) &__bss_stop, (int) memory_start, (int) memory_start, (int) memory_end, (int) memory_end, (int) &_ramend); #endif diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c index 973369c32a95..ee4c9dbf58cc 100644 --- a/arch/h8300/mm/init.c +++ b/arch/h8300/mm/init.c @@ -123,7 +123,7 @@ void __init mem_init(void) int codek = 0, datak = 0, initk = 0; /* DAVIDM look at setup memory map generically with reserved area */ unsigned long tmp; - extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end; + extern char _etext, _stext, _sdata, __bss_stop, __init_begin, __init_end; extern unsigned long _ramend, _ramstart; unsigned long len = &_ramend - &_ramstart; unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */ @@ -143,7 +143,7 @@ void __init mem_init(void) totalram_pages = free_all_bootmem(); codek = (&_etext - &_stext) >> 10; - datak = (&_ebss - &_sdata) >> 10; + datak = (&__bss_stop - &_sdata) >> 10; initk = (&__init_begin - &__init_end) >> 10; tmp = nr_free_pages() << PAGE_SHIFT; -- cgit v1.2.3 From 436814e61f5c526ed123853a9bf63fb2ff4ff94b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Jun 2012 12:53:00 -0700 Subject: h8300: use the declarations provided by Cleanups: - Include , - Remove the (different) extern declarations, - Remove the no longer needed address-of ('&') operators, - Remove the superfluous casts, use proper printk formatting instead. Signed-off-by: Geert Uytterhoeven Cc: Yoshinori Sato Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/h8300/kernel/setup.c | 23 ++++++++++------------- arch/h8300/mm/init.c | 17 ++++++++--------- 2 files changed, 18 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c index 050f13665b8e..d0b1607f2711 100644 --- a/arch/h8300/kernel/setup.c +++ b/arch/h8300/kernel/setup.c @@ -35,6 +35,7 @@ #include #include #include +#include #if defined(__H8300H__) #define CPU "H8/300H" @@ -54,7 +55,6 @@ unsigned long memory_end; char __initdata command_line[COMMAND_LINE_SIZE]; -extern int _stext, _etext, _sdata, _edata, __bss_start, __bss_stop, _end; extern int _ramstart, _ramend; extern char _target_name[]; extern void h8300_gpio_init(void); @@ -119,9 +119,9 @@ void __init setup_arch(char **cmdline_p) memory_end = CONFIG_BLKDEV_RESERVE_ADDRESS; #endif - init_mm.start_code = (unsigned long) &_stext; - init_mm.end_code = (unsigned long) &_etext; - init_mm.end_data = (unsigned long) &_edata; + init_mm.start_code = (unsigned long) _stext; + init_mm.end_code = (unsigned long) _etext; + init_mm.end_data = (unsigned long) _edata; init_mm.brk = (unsigned long) 0; #if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) && defined(CONFIG_GDB_MAGICPRINT) @@ -134,15 +134,12 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "H8/300 series support by Yoshinori Sato \n"); #ifdef DEBUG - printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x " - "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext, - (int) &_sdata, (int) &_edata, - (int) &__bss_start, (int) &__bss_stop); - printk(KERN_DEBUG "KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x " - "STACK=0x%06x-0x%06x\n", - (int) &__bss_stop, (int) memory_start, - (int) memory_start, (int) memory_end, - (int) memory_end, (int) &_ramend); + printk(KERN_DEBUG "KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p " + "BSS=0x%p-0x%p\n", _stext, _etext, _sdata, _edata, __bss_start, + __bss_stop); + printk(KERN_DEBUG "KERNEL -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx " + "STACK=0x%06lx-0x%p\n", __bss_stop, memory_start, memory_start, + memory_end, memory_end, &_ramend); #endif #ifdef CONFIG_DEFAULT_CMDLINE diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c index ee4c9dbf58cc..981e25094b1a 100644 --- a/arch/h8300/mm/init.c +++ b/arch/h8300/mm/init.c @@ -36,6 +36,7 @@ #include #include #include +#include #undef DEBUG @@ -123,7 +124,6 @@ void __init mem_init(void) int codek = 0, datak = 0, initk = 0; /* DAVIDM look at setup memory map generically with reserved area */ unsigned long tmp; - extern char _etext, _stext, _sdata, __bss_stop, __init_begin, __init_end; extern unsigned long _ramend, _ramstart; unsigned long len = &_ramend - &_ramstart; unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */ @@ -142,9 +142,9 @@ void __init mem_init(void) /* this will put all memory onto the freelists */ totalram_pages = free_all_bootmem(); - codek = (&_etext - &_stext) >> 10; - datak = (&__bss_stop - &_sdata) >> 10; - initk = (&__init_begin - &__init_end) >> 10; + codek = (_etext - _stext) >> 10; + datak = (__bss_stop - _sdata) >> 10; + initk = (__init_begin - __init_end) >> 10; tmp = nr_free_pages() << PAGE_SHIFT; printk(KERN_INFO "Memory available: %luk/%luk RAM, %luk/%luk ROM (%dk kernel code, %dk data)\n", @@ -178,22 +178,21 @@ free_initmem(void) { #ifdef CONFIG_RAMKERNEL unsigned long addr; - extern char __init_begin, __init_end; /* * the following code should be cool even if these sections * are not page aligned. */ - addr = PAGE_ALIGN((unsigned long)(&__init_begin)); + addr = PAGE_ALIGN((unsigned long)(__init_begin)); /* next to check that the page we free is not a partial page */ - for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) { + for (; addr + PAGE_SIZE < (unsigned long)__init_end; addr +=PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } printk(KERN_INFO "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n", - (addr - PAGE_ALIGN((long) &__init_begin)) >> 10, - (int)(PAGE_ALIGN((unsigned long)(&__init_begin))), + (addr - PAGE_ALIGN((long) __init_begin)) >> 10, + (int)(PAGE_ALIGN((unsigned long)__init_begin)), (int)(addr - PAGE_SIZE)); #endif } -- cgit v1.2.3 From 10d8935f46e5028847b179757ecbf9238b13d129 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 Jun 2012 12:53:02 -0700 Subject: Viresh has moved viresh.kumar@st.com email-id doesn't exist anymore as I have left the company. Replace ST's id with viresh.linux@gmail.com. It also updates .mailmap file to fix address for 'git shortlog' Signed-off-by: Viresh Kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- .mailmap | 1 + Documentation/arm/SPEAr/overview.txt | 2 +- MAINTAINERS | 18 +++++++++--------- arch/arm/boot/dts/spear1310-evb.dts | 2 +- arch/arm/boot/dts/spear1310.dtsi | 2 +- arch/arm/boot/dts/spear1340-evb.dts | 2 +- arch/arm/boot/dts/spear1340.dtsi | 2 +- arch/arm/boot/dts/spear13xx.dtsi | 2 +- arch/arm/boot/dts/spear300-evb.dts | 2 +- arch/arm/boot/dts/spear300.dtsi | 2 +- arch/arm/boot/dts/spear310-evb.dts | 2 +- arch/arm/boot/dts/spear310.dtsi | 2 +- arch/arm/boot/dts/spear320-evb.dts | 2 +- arch/arm/boot/dts/spear320.dtsi | 2 +- arch/arm/boot/dts/spear3xx.dtsi | 2 +- arch/arm/include/asm/hardware/sp810.h | 2 +- arch/arm/mach-spear13xx/include/mach/debug-macro.S | 2 +- arch/arm/mach-spear13xx/include/mach/dma.h | 2 +- arch/arm/mach-spear13xx/include/mach/generic.h | 2 +- arch/arm/mach-spear13xx/include/mach/gpio.h | 2 +- arch/arm/mach-spear13xx/include/mach/irqs.h | 2 +- arch/arm/mach-spear13xx/include/mach/spear.h | 2 +- arch/arm/mach-spear13xx/include/mach/timex.h | 2 +- arch/arm/mach-spear13xx/include/mach/uncompress.h | 2 +- arch/arm/mach-spear13xx/spear1310.c | 2 +- arch/arm/mach-spear13xx/spear1340.c | 2 +- arch/arm/mach-spear13xx/spear13xx.c | 2 +- arch/arm/mach-spear3xx/include/mach/debug-macro.S | 2 +- arch/arm/mach-spear3xx/include/mach/generic.h | 2 +- arch/arm/mach-spear3xx/include/mach/gpio.h | 2 +- arch/arm/mach-spear3xx/include/mach/irqs.h | 2 +- arch/arm/mach-spear3xx/include/mach/misc_regs.h | 2 +- arch/arm/mach-spear3xx/include/mach/spear.h | 2 +- arch/arm/mach-spear3xx/include/mach/timex.h | 2 +- arch/arm/mach-spear3xx/include/mach/uncompress.h | 2 +- arch/arm/mach-spear3xx/spear300.c | 2 +- arch/arm/mach-spear3xx/spear310.c | 2 +- arch/arm/mach-spear3xx/spear320.c | 2 +- arch/arm/mach-spear3xx/spear3xx.c | 2 +- arch/arm/mach-spear6xx/include/mach/gpio.h | 2 +- arch/arm/mach-spear6xx/include/mach/misc_regs.h | 2 +- arch/arm/plat-spear/include/plat/debug-macro.S | 2 +- arch/arm/plat-spear/include/plat/pl080.h | 2 +- arch/arm/plat-spear/include/plat/shirq.h | 2 +- arch/arm/plat-spear/include/plat/timex.h | 2 +- arch/arm/plat-spear/include/plat/uncompress.h | 2 +- arch/arm/plat-spear/pl080.c | 2 +- arch/arm/plat-spear/restart.c | 2 +- arch/arm/plat-spear/shirq.c | 2 +- drivers/ata/pata_arasan_cf.c | 4 ++-- drivers/clk/spear/clk-aux-synth.c | 2 +- drivers/clk/spear/clk-frac-synth.c | 2 +- drivers/clk/spear/clk-gpt-synth.c | 2 +- drivers/clk/spear/clk-vco-pll.c | 2 +- drivers/clk/spear/clk.c | 2 +- drivers/clk/spear/clk.h | 2 +- drivers/clk/spear/spear1310_clock.c | 2 +- drivers/clk/spear/spear1340_clock.c | 2 +- drivers/clk/spear/spear3xx_clock.c | 2 +- drivers/clk/spear/spear6xx_clock.c | 2 +- drivers/dma/dw_dmac.c | 2 +- drivers/mfd/stmpe-i2c.c | 2 +- drivers/mfd/stmpe-spi.c | 4 ++-- drivers/mmc/host/sdhci-spear.c | 4 ++-- drivers/pinctrl/spear/pinctrl-spear.c | 2 +- drivers/pinctrl/spear/pinctrl-spear.h | 2 +- drivers/pinctrl/spear/pinctrl-spear1310.c | 4 ++-- drivers/pinctrl/spear/pinctrl-spear1340.c | 4 ++-- drivers/pinctrl/spear/pinctrl-spear300.c | 4 ++-- drivers/pinctrl/spear/pinctrl-spear310.c | 4 ++-- drivers/pinctrl/spear/pinctrl-spear320.c | 4 ++-- drivers/pinctrl/spear/pinctrl-spear3xx.c | 2 +- drivers/pinctrl/spear/pinctrl-spear3xx.h | 2 +- drivers/watchdog/sp805_wdt.c | 4 ++-- include/linux/mmc/sdhci-spear.h | 2 +- include/linux/pata_arasan_cf_data.h | 2 +- 76 files changed, 93 insertions(+), 92 deletions(-) (limited to 'arch') diff --git a/.mailmap b/.mailmap index 2909c33bc54e..658003aa9446 100644 --- a/.mailmap +++ b/.mailmap @@ -111,6 +111,7 @@ Uwe Kleine-König Uwe Kleine-König Uwe Kleine-König Valdis Kletnieks +Viresh Kumar Takashi YOSHII Yusuke Goda Gustavo Padovan diff --git a/Documentation/arm/SPEAr/overview.txt b/Documentation/arm/SPEAr/overview.txt index 57aae7765c74..65610bf52ebf 100644 --- a/Documentation/arm/SPEAr/overview.txt +++ b/Documentation/arm/SPEAr/overview.txt @@ -60,4 +60,4 @@ Introduction Document Author --------------- - Viresh Kumar , (c) 2010-2012 ST Microelectronics + Viresh Kumar , (c) 2010-2012 ST Microelectronics diff --git a/MAINTAINERS b/MAINTAINERS index 3e30a3afe2a4..a81b298d9c75 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -579,7 +579,7 @@ F: drivers/net/appletalk/ F: net/appletalk/ ARASAN COMPACT FLASH PATA CONTROLLER -M: Viresh Kumar +M: Viresh Kumar L: linux-ide@vger.kernel.org S: Maintained F: include/linux/pata_arasan_cf_data.h @@ -5296,7 +5296,7 @@ S: Maintained F: drivers/pinctrl/ PIN CONTROLLER - ST SPEAR -M: Viresh Kumar +M: Viresh Kumar L: spear-devel@list.st.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.st.com/spear @@ -5873,7 +5873,7 @@ S: Maintained F: drivers/tty/serial SYNOPSYS DESIGNWARE DMAC DRIVER -M: Viresh Kumar +M: Viresh Kumar S: Maintained F: include/linux/dw_dmac.h F: drivers/dma/dw_dmac_regs.h @@ -6021,7 +6021,7 @@ S: Maintained F: drivers/mmc/host/sdhci-s3c.c SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) ST SPEAR DRIVER -M: Viresh Kumar +M: Viresh Kumar L: spear-devel@list.st.com L: linux-mmc@vger.kernel.org S: Maintained @@ -6377,7 +6377,7 @@ S: Maintained F: include/linux/compiler.h SPEAR PLATFORM SUPPORT -M: Viresh Kumar +M: Viresh Kumar M: Shiraz Hashim L: spear-devel@list.st.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -6386,7 +6386,7 @@ S: Maintained F: arch/arm/plat-spear/ SPEAR13XX MACHINE SUPPORT -M: Viresh Kumar +M: Viresh Kumar M: Shiraz Hashim L: spear-devel@list.st.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -6395,7 +6395,7 @@ S: Maintained F: arch/arm/mach-spear13xx/ SPEAR3XX MACHINE SUPPORT -M: Viresh Kumar +M: Viresh Kumar M: Shiraz Hashim L: spear-devel@list.st.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -6406,7 +6406,7 @@ F: arch/arm/mach-spear3xx/ SPEAR6XX MACHINE SUPPORT M: Rajeev Kumar M: Shiraz Hashim -M: Viresh Kumar +M: Viresh Kumar L: spear-devel@list.st.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.st.com/spear @@ -6414,7 +6414,7 @@ S: Maintained F: arch/arm/mach-spear6xx/ SPEAR CLOCK FRAMEWORK SUPPORT -M: Viresh Kumar +M: Viresh Kumar L: spear-devel@list.st.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.st.com/spear diff --git a/arch/arm/boot/dts/spear1310-evb.dts b/arch/arm/boot/dts/spear1310-evb.dts index 8314e4171884..dd4358bc26e2 100644 --- a/arch/arm/boot/dts/spear1310-evb.dts +++ b/arch/arm/boot/dts/spear1310-evb.dts @@ -1,7 +1,7 @@ /* * DTS file for SPEAr1310 Evaluation Baord * - * Copyright 2012 Viresh Kumar + * Copyright 2012 Viresh Kumar * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/boot/dts/spear1310.dtsi b/arch/arm/boot/dts/spear1310.dtsi index 9e61da404d57..419ea7413d23 100644 --- a/arch/arm/boot/dts/spear1310.dtsi +++ b/arch/arm/boot/dts/spear1310.dtsi @@ -1,7 +1,7 @@ /* * DTS file for all SPEAr1310 SoCs * - * Copyright 2012 Viresh Kumar + * Copyright 2012 Viresh Kumar * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/boot/dts/spear1340-evb.dts b/arch/arm/boot/dts/spear1340-evb.dts index 0d8472e5ab9f..c9a54e06fb68 100644 --- a/arch/arm/boot/dts/spear1340-evb.dts +++ b/arch/arm/boot/dts/spear1340-evb.dts @@ -1,7 +1,7 @@ /* * DTS file for SPEAr1340 Evaluation Baord * - * Copyright 2012 Viresh Kumar + * Copyright 2012 Viresh Kumar * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi index a26fc47a55e8..d71fe2a68f09 100644 --- a/arch/arm/boot/dts/spear1340.dtsi +++ b/arch/arm/boot/dts/spear1340.dtsi @@ -1,7 +1,7 @@ /* * DTS file for all SPEAr1340 SoCs * - * Copyright 2012 Viresh Kumar + * Copyright 2012 Viresh Kumar * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi index 1f8e1e1481df..10dcec7e7321 100644 --- a/arch/arm/boot/dts/spear13xx.dtsi +++ b/arch/arm/boot/dts/spear13xx.dtsi @@ -1,7 +1,7 @@ /* * DTS file for all SPEAr13xx SoCs * - * Copyright 2012 Viresh Kumar + * Copyright 2012 Viresh Kumar * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/boot/dts/spear300-evb.dts b/arch/arm/boot/dts/spear300-evb.dts index fc82b1a26458..d71b8d581e3d 100644 --- a/arch/arm/boot/dts/spear300-evb.dts +++ b/arch/arm/boot/dts/spear300-evb.dts @@ -1,7 +1,7 @@ /* * DTS file for SPEAr300 Evaluation Baord * - * Copyright 2012 Viresh Kumar + * Copyright 2012 Viresh Kumar * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/boot/dts/spear300.dtsi b/arch/arm/boot/dts/spear300.dtsi index 01c5e358fdb2..ed3627c116cc 100644 --- a/arch/arm/boot/dts/spear300.dtsi +++ b/arch/arm/boot/dts/spear300.dtsi @@ -1,7 +1,7 @@ /* * DTS file for SPEAr300 SoC * - * Copyright 2012 Viresh Kumar + * Copyright 2012 Viresh Kumar * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/boot/dts/spear310-evb.dts b/arch/arm/boot/dts/spear310-evb.dts index dc5e2d445a93..b00544e0cd5d 100644 --- a/arch/arm/boot/dts/spear310-evb.dts +++ b/arch/arm/boot/dts/spear310-evb.dts @@ -1,7 +1,7 @@ /* * DTS file for SPEAr310 Evaluation Baord * - * Copyright 2012 Viresh Kumar + * Copyright 2012 Viresh Kumar * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi index e47081c494d9..62fc4fb3e5f9 100644 --- a/arch/arm/boot/dts/spear310.dtsi +++ b/arch/arm/boot/dts/spear310.dtsi @@ -1,7 +1,7 @@ /* * DTS file for SPEAr310 SoC * - * Copyright 2012 Viresh Kumar + * Copyright 2012 Viresh Kumar * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/boot/dts/spear320-evb.dts b/arch/arm/boot/dts/spear320-evb.dts index 6308fa3bec1e..c13fd1f3b09f 100644 --- a/arch/arm/boot/dts/spear320-evb.dts +++ b/arch/arm/boot/dts/spear320-evb.dts @@ -1,7 +1,7 @@ /* * DTS file for SPEAr320 Evaluation Baord * - * Copyright 2012 Viresh Kumar + * Copyright 2012 Viresh Kumar * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi index 5372ca399b1f..1f49d69595a0 100644 --- a/arch/arm/boot/dts/spear320.dtsi +++ b/arch/arm/boot/dts/spear320.dtsi @@ -1,7 +1,7 @@ /* * DTS file for SPEAr320 SoC * - * Copyright 2012 Viresh Kumar + * Copyright 2012 Viresh Kumar * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/boot/dts/spear3xx.dtsi b/arch/arm/boot/dts/spear3xx.dtsi index 91072553963f..3a8bb5736928 100644 --- a/arch/arm/boot/dts/spear3xx.dtsi +++ b/arch/arm/boot/dts/spear3xx.dtsi @@ -1,7 +1,7 @@ /* * DTS file for all SPEAr3xx SoCs * - * Copyright 2012 Viresh Kumar + * Copyright 2012 Viresh Kumar * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/include/asm/hardware/sp810.h b/arch/arm/include/asm/hardware/sp810.h index e0d1c0cfa548..6b9b077d86b3 100644 --- a/arch/arm/include/asm/hardware/sp810.h +++ b/arch/arm/include/asm/hardware/sp810.h @@ -4,7 +4,7 @@ * ARM PrimeXsys System Controller SP810 header file * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear13xx/include/mach/debug-macro.S b/arch/arm/mach-spear13xx/include/mach/debug-macro.S index ea1564609bd4..9e3ae6bfe50d 100644 --- a/arch/arm/mach-spear13xx/include/mach/debug-macro.S +++ b/arch/arm/mach-spear13xx/include/mach/debug-macro.S @@ -4,7 +4,7 @@ * Debugging macro include header spear13xx machine family * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear13xx/include/mach/dma.h b/arch/arm/mach-spear13xx/include/mach/dma.h index 383ab04dc6c9..d50bdb605925 100644 --- a/arch/arm/mach-spear13xx/include/mach/dma.h +++ b/arch/arm/mach-spear13xx/include/mach/dma.h @@ -4,7 +4,7 @@ * DMA information for SPEAr13xx machine family * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h index 6d8c45b9f298..dac57fd0cdfd 100644 --- a/arch/arm/mach-spear13xx/include/mach/generic.h +++ b/arch/arm/mach-spear13xx/include/mach/generic.h @@ -4,7 +4,7 @@ * spear13xx machine family generic header file * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear13xx/include/mach/gpio.h b/arch/arm/mach-spear13xx/include/mach/gpio.h index cd6f4f86a56b..85f176311f63 100644 --- a/arch/arm/mach-spear13xx/include/mach/gpio.h +++ b/arch/arm/mach-spear13xx/include/mach/gpio.h @@ -4,7 +4,7 @@ * GPIO macros for SPEAr13xx machine family * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear13xx/include/mach/irqs.h b/arch/arm/mach-spear13xx/include/mach/irqs.h index f542a24aa5f2..271a62b4cd31 100644 --- a/arch/arm/mach-spear13xx/include/mach/irqs.h +++ b/arch/arm/mach-spear13xx/include/mach/irqs.h @@ -4,7 +4,7 @@ * IRQ helper macros for spear13xx machine family * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear13xx/include/mach/spear.h b/arch/arm/mach-spear13xx/include/mach/spear.h index 30c57ef72686..65f27def239b 100644 --- a/arch/arm/mach-spear13xx/include/mach/spear.h +++ b/arch/arm/mach-spear13xx/include/mach/spear.h @@ -4,7 +4,7 @@ * spear13xx Machine family specific definition * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear13xx/include/mach/timex.h b/arch/arm/mach-spear13xx/include/mach/timex.h index 31af3e8d976e..3a58b8284a6a 100644 --- a/arch/arm/mach-spear13xx/include/mach/timex.h +++ b/arch/arm/mach-spear13xx/include/mach/timex.h @@ -4,7 +4,7 @@ * SPEAr3XX machine family specific timex definitions * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear13xx/include/mach/uncompress.h b/arch/arm/mach-spear13xx/include/mach/uncompress.h index c7840896ae6e..70fe72f05dea 100644 --- a/arch/arm/mach-spear13xx/include/mach/uncompress.h +++ b/arch/arm/mach-spear13xx/include/mach/uncompress.h @@ -4,7 +4,7 @@ * Serial port stubs for kernel decompress status messages * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c index fefd15b2f380..732d29bc7330 100644 --- a/arch/arm/mach-spear13xx/spear1310.c +++ b/arch/arm/mach-spear13xx/spear1310.c @@ -4,7 +4,7 @@ * SPEAr1310 machine source file * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear13xx/spear1340.c b/arch/arm/mach-spear13xx/spear1340.c index ee38cbc56869..81e4ed76ad06 100644 --- a/arch/arm/mach-spear13xx/spear1340.c +++ b/arch/arm/mach-spear13xx/spear1340.c @@ -4,7 +4,7 @@ * SPEAr1340 machine source file * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c index 50b349ae863d..cf936b106e27 100644 --- a/arch/arm/mach-spear13xx/spear13xx.c +++ b/arch/arm/mach-spear13xx/spear13xx.c @@ -4,7 +4,7 @@ * SPEAr13XX machines common source file * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear3xx/include/mach/debug-macro.S b/arch/arm/mach-spear3xx/include/mach/debug-macro.S index 590519f10d6e..0a6381fad5d9 100644 --- a/arch/arm/mach-spear3xx/include/mach/debug-macro.S +++ b/arch/arm/mach-spear3xx/include/mach/debug-macro.S @@ -4,7 +4,7 @@ * Debugging macro include header spear3xx machine family * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h index 4a95b9453c2a..ce19113ca791 100644 --- a/arch/arm/mach-spear3xx/include/mach/generic.h +++ b/arch/arm/mach-spear3xx/include/mach/generic.h @@ -4,7 +4,7 @@ * SPEAr3XX machine family generic header file * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear3xx/include/mach/gpio.h b/arch/arm/mach-spear3xx/include/mach/gpio.h index 451b2081bfc9..2ac74c6db7f1 100644 --- a/arch/arm/mach-spear3xx/include/mach/gpio.h +++ b/arch/arm/mach-spear3xx/include/mach/gpio.h @@ -4,7 +4,7 @@ * GPIO macros for SPEAr3xx machine family * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear3xx/include/mach/irqs.h b/arch/arm/mach-spear3xx/include/mach/irqs.h index 51bd62a0254c..803de76f5f36 100644 --- a/arch/arm/mach-spear3xx/include/mach/irqs.h +++ b/arch/arm/mach-spear3xx/include/mach/irqs.h @@ -4,7 +4,7 @@ * IRQ helper macros for SPEAr3xx machine family * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear3xx/include/mach/misc_regs.h b/arch/arm/mach-spear3xx/include/mach/misc_regs.h index 18e2ac576f25..6309bf68d6f8 100644 --- a/arch/arm/mach-spear3xx/include/mach/misc_regs.h +++ b/arch/arm/mach-spear3xx/include/mach/misc_regs.h @@ -4,7 +4,7 @@ * Miscellaneous registers definitions for SPEAr3xx machine family * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear3xx/include/mach/spear.h b/arch/arm/mach-spear3xx/include/mach/spear.h index 51eb953148a9..8cca95193d4d 100644 --- a/arch/arm/mach-spear3xx/include/mach/spear.h +++ b/arch/arm/mach-spear3xx/include/mach/spear.h @@ -4,7 +4,7 @@ * SPEAr3xx Machine family specific definition * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear3xx/include/mach/timex.h b/arch/arm/mach-spear3xx/include/mach/timex.h index a38cc9de876f..9f5d08bd0c44 100644 --- a/arch/arm/mach-spear3xx/include/mach/timex.h +++ b/arch/arm/mach-spear3xx/include/mach/timex.h @@ -4,7 +4,7 @@ * SPEAr3XX machine family specific timex definitions * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear3xx/include/mach/uncompress.h b/arch/arm/mach-spear3xx/include/mach/uncompress.h index 53ba8bbc0dfa..b909b011f7c8 100644 --- a/arch/arm/mach-spear3xx/include/mach/uncompress.h +++ b/arch/arm/mach-spear3xx/include/mach/uncompress.h @@ -4,7 +4,7 @@ * Serial port stubs for kernel decompress status messages * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c index f74a05bdb829..0f882ecb7d81 100644 --- a/arch/arm/mach-spear3xx/spear300.c +++ b/arch/arm/mach-spear3xx/spear300.c @@ -4,7 +4,7 @@ * SPEAr300 machine source file * * Copyright (C) 2009-2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c index 84dfb0900747..bbcf4571d361 100644 --- a/arch/arm/mach-spear3xx/spear310.c +++ b/arch/arm/mach-spear3xx/spear310.c @@ -4,7 +4,7 @@ * SPEAr310 machine source file * * Copyright (C) 2009-2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c index a88fa841d29d..88d483bcd66a 100644 --- a/arch/arm/mach-spear3xx/spear320.c +++ b/arch/arm/mach-spear3xx/spear320.c @@ -4,7 +4,7 @@ * SPEAr320 machine source file * * Copyright (C) 2009-2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c index f22419ed74a8..0f41bd1c47c3 100644 --- a/arch/arm/mach-spear3xx/spear3xx.c +++ b/arch/arm/mach-spear3xx/spear3xx.c @@ -4,7 +4,7 @@ * SPEAr3XX machines common source file * * Copyright (C) 2009-2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear6xx/include/mach/gpio.h b/arch/arm/mach-spear6xx/include/mach/gpio.h index 3a789dbb69f7..d42cefc0356d 100644 --- a/arch/arm/mach-spear6xx/include/mach/gpio.h +++ b/arch/arm/mach-spear6xx/include/mach/gpio.h @@ -4,7 +4,7 @@ * GPIO macros for SPEAr6xx machine family * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/mach-spear6xx/include/mach/misc_regs.h b/arch/arm/mach-spear6xx/include/mach/misc_regs.h index 179e45774b3a..c34acc201d34 100644 --- a/arch/arm/mach-spear6xx/include/mach/misc_regs.h +++ b/arch/arm/mach-spear6xx/include/mach/misc_regs.h @@ -4,7 +4,7 @@ * Miscellaneous registers definitions for SPEAr6xx machine family * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/plat-spear/include/plat/debug-macro.S b/arch/arm/plat-spear/include/plat/debug-macro.S index ab3de721c5db..75b05ad0fbad 100644 --- a/arch/arm/plat-spear/include/plat/debug-macro.S +++ b/arch/arm/plat-spear/include/plat/debug-macro.S @@ -4,7 +4,7 @@ * Debugging macro include header for spear platform * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/plat-spear/include/plat/pl080.h b/arch/arm/plat-spear/include/plat/pl080.h index e14a3e4932f9..2bc6b54460a8 100644 --- a/arch/arm/plat-spear/include/plat/pl080.h +++ b/arch/arm/plat-spear/include/plat/pl080.h @@ -4,7 +4,7 @@ * DMAC pl080 definitions for SPEAr platform * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/plat-spear/include/plat/shirq.h b/arch/arm/plat-spear/include/plat/shirq.h index 03ed8b585dcf..88a7fbd24793 100644 --- a/arch/arm/plat-spear/include/plat/shirq.h +++ b/arch/arm/plat-spear/include/plat/shirq.h @@ -4,7 +4,7 @@ * SPEAr platform shared irq layer header file * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/plat-spear/include/plat/timex.h b/arch/arm/plat-spear/include/plat/timex.h index 914d09dd50fd..ef95e5b780bd 100644 --- a/arch/arm/plat-spear/include/plat/timex.h +++ b/arch/arm/plat-spear/include/plat/timex.h @@ -4,7 +4,7 @@ * SPEAr platform specific timex definitions * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/plat-spear/include/plat/uncompress.h b/arch/arm/plat-spear/include/plat/uncompress.h index 6dd455bafdfd..2ce6cb17a98b 100644 --- a/arch/arm/plat-spear/include/plat/uncompress.h +++ b/arch/arm/plat-spear/include/plat/uncompress.h @@ -4,7 +4,7 @@ * Serial port stubs for kernel decompress status messages * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/plat-spear/pl080.c b/arch/arm/plat-spear/pl080.c index a56a067717c1..12cf27f935f9 100644 --- a/arch/arm/plat-spear/pl080.c +++ b/arch/arm/plat-spear/pl080.c @@ -4,7 +4,7 @@ * DMAC pl080 definitions for SPEAr platform * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/plat-spear/restart.c b/arch/arm/plat-spear/restart.c index ea0a61302b7e..4f990115b1bd 100644 --- a/arch/arm/plat-spear/restart.c +++ b/arch/arm/plat-spear/restart.c @@ -4,7 +4,7 @@ * SPEAr platform specific restart functions * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/arch/arm/plat-spear/shirq.c b/arch/arm/plat-spear/shirq.c index 961fb7261243..853e891e1184 100644 --- a/arch/arm/plat-spear/shirq.c +++ b/arch/arm/plat-spear/shirq.c @@ -4,7 +4,7 @@ * SPEAr platform shared irq layer source file * * Copyright (C) 2009 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index 3239517f4d90..ac6a5beb28f3 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -4,7 +4,7 @@ * Arasan Compact Flash host controller source file * * Copyright (C) 2011 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -959,7 +959,7 @@ static struct platform_driver arasan_cf_driver = { module_platform_driver(arasan_cf_driver); -MODULE_AUTHOR("Viresh Kumar "); +MODULE_AUTHOR("Viresh Kumar "); MODULE_DESCRIPTION("Arasan ATA Compact Flash driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c index af34074e702b..6756e7c3bc07 100644 --- a/drivers/clk/spear/clk-aux-synth.c +++ b/drivers/clk/spear/clk-aux-synth.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/clk-frac-synth.c b/drivers/clk/spear/clk-frac-synth.c index 4dbdb3fe18e0..958aa3ad1d60 100644 --- a/drivers/clk/spear/clk-frac-synth.c +++ b/drivers/clk/spear/clk-frac-synth.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/clk-gpt-synth.c b/drivers/clk/spear/clk-gpt-synth.c index b471c9762a97..1afc18c4effc 100644 --- a/drivers/clk/spear/clk-gpt-synth.c +++ b/drivers/clk/spear/clk-gpt-synth.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c index dcd4bdf4b0d9..5f1b6badeb15 100644 --- a/drivers/clk/spear/clk-vco-pll.c +++ b/drivers/clk/spear/clk-vco-pll.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/clk.c b/drivers/clk/spear/clk.c index 376d4e5ff326..7cd63788d546 100644 --- a/drivers/clk/spear/clk.c +++ b/drivers/clk/spear/clk.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h index 3321c46a071c..931737677dfa 100644 --- a/drivers/clk/spear/clk.h +++ b/drivers/clk/spear/clk.h @@ -2,7 +2,7 @@ * Clock framework definitions for SPEAr platform * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c index 42b68df9aeef..8f05652d53e6 100644 --- a/drivers/clk/spear/spear1310_clock.c +++ b/drivers/clk/spear/spear1310_clock.c @@ -4,7 +4,7 @@ * SPEAr1310 machine clock framework source file * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c index f130919d5bf8..e3ea72162236 100644 --- a/drivers/clk/spear/spear1340_clock.c +++ b/drivers/clk/spear/spear1340_clock.c @@ -4,7 +4,7 @@ * SPEAr1340 machine clock framework source file * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/spear3xx_clock.c b/drivers/clk/spear/spear3xx_clock.c index 440bb3e4c971..01dd6daff2a1 100644 --- a/drivers/clk/spear/spear3xx_clock.c +++ b/drivers/clk/spear/spear3xx_clock.c @@ -2,7 +2,7 @@ * SPEAr3xx machines clock framework source file * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/spear6xx_clock.c b/drivers/clk/spear/spear6xx_clock.c index f9a20b382304..554d64b062a1 100644 --- a/drivers/clk/spear/spear6xx_clock.c +++ b/drivers/clk/spear/spear6xx_clock.c @@ -2,7 +2,7 @@ * SPEAr6xx machines clock framework source file * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index e23dc82d43ac..721296157577 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1626,4 +1626,4 @@ module_exit(dw_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller driver"); MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); -MODULE_AUTHOR("Viresh Kumar "); +MODULE_AUTHOR("Viresh Kumar "); diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index 373f423b1181..947a06a1845f 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -6,7 +6,7 @@ * * License Terms: GNU General Public License, version 2 * Author: Rabin Vincent for ST-Ericsson - * Author: Viresh Kumar for ST Microelectronics + * Author: Viresh Kumar for ST Microelectronics */ #include diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c index afd459013ecb..9edfe864cc05 100644 --- a/drivers/mfd/stmpe-spi.c +++ b/drivers/mfd/stmpe-spi.c @@ -4,7 +4,7 @@ * Copyright (C) ST Microelectronics SA 2011 * * License Terms: GNU General Public License, version 2 - * Author: Viresh Kumar for ST Microelectronics + * Author: Viresh Kumar for ST Microelectronics */ #include @@ -146,4 +146,4 @@ module_exit(stmpe_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("STMPE MFD SPI Interface Driver"); -MODULE_AUTHOR("Viresh Kumar "); +MODULE_AUTHOR("Viresh Kumar "); diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index 1fe32dfa7cd4..423da8194cd8 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c @@ -4,7 +4,7 @@ * Support of SDHCI platform devices for spear soc family * * Copyright (C) 2010 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * Inspired by sdhci-pltfm.c * @@ -289,5 +289,5 @@ static struct platform_driver sdhci_driver = { module_platform_driver(sdhci_driver); MODULE_DESCRIPTION("SPEAr Secure Digital Host Controller Interface driver"); -MODULE_AUTHOR("Viresh Kumar "); +MODULE_AUTHOR("Viresh Kumar "); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c index 5ae50aadf885..b3f6b2873fdd 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.c +++ b/drivers/pinctrl/spear/pinctrl-spear.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * Inspired from: * - U300 Pinctl drivers diff --git a/drivers/pinctrl/spear/pinctrl-spear.h b/drivers/pinctrl/spear/pinctrl-spear.h index 9155783bb47f..d950eb78d939 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.h +++ b/drivers/pinctrl/spear/pinctrl-spear.h @@ -2,7 +2,7 @@ * Driver header file for the ST Microelectronics SPEAr pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c index fff168be7f00..d6cca8c81b92 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1310.c +++ b/drivers/pinctrl/spear/pinctrl-spear1310.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr1310 pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -2192,7 +2192,7 @@ static void __exit spear1310_pinctrl_exit(void) } module_exit(spear1310_pinctrl_exit); -MODULE_AUTHOR("Viresh Kumar "); +MODULE_AUTHOR("Viresh Kumar "); MODULE_DESCRIPTION("ST Microelectronics SPEAr1310 pinctrl driver"); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, spear1310_pinctrl_of_match); diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c index a8ab2a6f51bf..a0eb057e55bd 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1340.c +++ b/drivers/pinctrl/spear/pinctrl-spear1340.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr1340 pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -1983,7 +1983,7 @@ static void __exit spear1340_pinctrl_exit(void) } module_exit(spear1340_pinctrl_exit); -MODULE_AUTHOR("Viresh Kumar "); +MODULE_AUTHOR("Viresh Kumar "); MODULE_DESCRIPTION("ST Microelectronics SPEAr1340 pinctrl driver"); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, spear1340_pinctrl_of_match); diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c index 9c82a35e4e78..4dfc2849b172 100644 --- a/drivers/pinctrl/spear/pinctrl-spear300.c +++ b/drivers/pinctrl/spear/pinctrl-spear300.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr300 pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -702,7 +702,7 @@ static void __exit spear300_pinctrl_exit(void) } module_exit(spear300_pinctrl_exit); -MODULE_AUTHOR("Viresh Kumar "); +MODULE_AUTHOR("Viresh Kumar "); MODULE_DESCRIPTION("ST Microelectronics SPEAr300 pinctrl driver"); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, spear300_pinctrl_of_match); diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c index 1a9707605125..96883693fb7e 100644 --- a/drivers/pinctrl/spear/pinctrl-spear310.c +++ b/drivers/pinctrl/spear/pinctrl-spear310.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr310 pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -425,7 +425,7 @@ static void __exit spear310_pinctrl_exit(void) } module_exit(spear310_pinctrl_exit); -MODULE_AUTHOR("Viresh Kumar "); +MODULE_AUTHOR("Viresh Kumar "); MODULE_DESCRIPTION("ST Microelectronics SPEAr310 pinctrl driver"); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, SPEAr310_pinctrl_of_match); diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c index de726e6c283a..020b1e0bdb3e 100644 --- a/drivers/pinctrl/spear/pinctrl-spear320.c +++ b/drivers/pinctrl/spear/pinctrl-spear320.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr320 pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -3462,7 +3462,7 @@ static void __exit spear320_pinctrl_exit(void) } module_exit(spear320_pinctrl_exit); -MODULE_AUTHOR("Viresh Kumar "); +MODULE_AUTHOR("Viresh Kumar "); MODULE_DESCRIPTION("ST Microelectronics SPEAr320 pinctrl driver"); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, spear320_pinctrl_of_match); diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.c b/drivers/pinctrl/spear/pinctrl-spear3xx.c index 91c883bc46a6..0242378f7cb8 100644 --- a/drivers/pinctrl/spear/pinctrl-spear3xx.c +++ b/drivers/pinctrl/spear/pinctrl-spear3xx.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr3xx pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.h b/drivers/pinctrl/spear/pinctrl-spear3xx.h index 5d5fdd8df7b8..31f44347f17c 100644 --- a/drivers/pinctrl/spear/pinctrl-spear3xx.h +++ b/drivers/pinctrl/spear/pinctrl-spear3xx.h @@ -2,7 +2,7 @@ * Header file for the ST Microelectronics SPEAr3xx pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index afcd13676542..e4841c36798b 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -4,7 +4,7 @@ * Watchdog driver for ARM SP805 watchdog module * * Copyright (C) 2010 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2 or later. This program is licensed "as is" without any @@ -331,6 +331,6 @@ static struct amba_driver sp805_wdt_driver = { module_amba_driver(sp805_wdt_driver); -MODULE_AUTHOR("Viresh Kumar "); +MODULE_AUTHOR("Viresh Kumar "); MODULE_DESCRIPTION("ARM SP805 Watchdog Driver"); MODULE_LICENSE("GPL"); diff --git a/include/linux/mmc/sdhci-spear.h b/include/linux/mmc/sdhci-spear.h index 5cdc96da9dd5..e78c0e236e9d 100644 --- a/include/linux/mmc/sdhci-spear.h +++ b/include/linux/mmc/sdhci-spear.h @@ -4,7 +4,7 @@ * SDHCI declarations specific to ST SPEAr platform * * Copyright (C) 2010 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/include/linux/pata_arasan_cf_data.h b/include/linux/pata_arasan_cf_data.h index a6ee9aa898bb..a7b4fc386e63 100644 --- a/include/linux/pata_arasan_cf_data.h +++ b/include/linux/pata_arasan_cf_data.h @@ -4,7 +4,7 @@ * Arasan Compact Flash host controller platform data header file * * Copyright (C) 2011 ST Microelectronics - * Viresh Kumar + * Viresh Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any -- cgit v1.2.3 From 8f748e20b8060317bf56f7a8afa6e24047a38cdb Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Wed, 20 Jun 2012 17:02:30 +0900 Subject: ARM: SAMSUNG: Remove unused variable 'running' on PWM This variable is indeed no longer in use. Signed-off-by: Jonghwan Choi Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/pwm.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-samsung/pwm.c b/arch/arm/plat-samsung/pwm.c index c559d8438c70..d3583050fb05 100644 --- a/arch/arm/plat-samsung/pwm.c +++ b/arch/arm/plat-samsung/pwm.c @@ -36,7 +36,6 @@ struct pwm_device { unsigned int duty_ns; unsigned char tcon_base; - unsigned char running; unsigned char use_count; unsigned char pwm_id; }; @@ -116,7 +115,6 @@ int pwm_enable(struct pwm_device *pwm) local_irq_restore(flags); - pwm->running = 1; return 0; } @@ -134,8 +132,6 @@ void pwm_disable(struct pwm_device *pwm) __raw_writel(tcon, S3C2410_TCON); local_irq_restore(flags); - - pwm->running = 0; } EXPORT_SYMBOL(pwm_disable); -- cgit v1.2.3 From e5a7286b5f1b0b5beb97275f2152bf10c4aa4204 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 21 Jun 2012 00:16:29 +0200 Subject: x86, boot: Remove ancient, unconditionally #ifdef'd out dead code Release v1.3.82 wrapped a few lines of code in an "#ifdef SAFE_RESET_DISK_CONTROLLER" and "#endif" pair. Since SAFE_RESET_DISK_CONTROLLER was never defined anywhere that was basically a verbose "#ifdef 0" and "#endif" pair. These dead lines have been in the tree for sixteen years but now the time has come to remove them. I guess the main lesson here is that if you want your dead code in the tree for a very long time you'd better be creative. A plain old "#ifdef 0" and "#endif" pair just doesn't cut it! See: http://lkml.kernel.org/r/199603301718.LAA00178@craie.inetnebr.com Signed-off-by: Paul Bolle Link: http://lkml.kernel.org/r/1340230589.1773.7.camel@x61.thuisdomein Acked-by: Jeff Epler Acked-by: Jesper Juhl Signed-off-by: H. Peter Anvin --- arch/x86/boot/header.S | 7 ------- 1 file changed, 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 8bbea6aa40d9..fde5bde3b605 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -386,13 +386,6 @@ init_size: .long INIT_SIZE # kernel initialization size .section ".entrytext", "ax" start_of_setup: -#ifdef SAFE_RESET_DISK_CONTROLLER -# Reset the disk controller. - movw $0x0000, %ax # Reset disk controller - movb $0x80, %dl # All disks - int $0x13 -#endif - # Force %es = %ds movw %ds, %ax movw %ax, %es -- cgit v1.2.3 From 2b1b712f050eaf0ac576591281446dc960c0afc5 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 20 Jun 2012 21:18:14 -0700 Subject: x86, reboot: Drop redundant write of reboot_mode We write reboot_mode to BIOS location 0x472 in native_machine_emergency_restart() (reboot.c:542) already, there is no need to then write it again in machine_real_restart(). This means nothing gets written there for MRR_APM, but the APM call is a poweroff call and doesn't use this memory location. Link: http://lkml.kernel.org/n/tip-3i0pfh44c1e3jv5lab0cf7sc@git.kernel.org Signed-off-by: H. Peter Anvin --- arch/x86/kernel/reboot.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 6ddb9cd0ced0..6ef559f09acd 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -179,14 +179,6 @@ void __noreturn machine_real_restart(unsigned int type) write_cr3(real_mode_header->trampoline_pgd); #endif - /* - * Write 0x1234 to absolute memory location 0x472. The BIOS reads - * this on booting to tell it to "Bypass memory test (also warm - * boot)". This seems like a fairly standard thing that gets set by - * REBOOT.COM programs, and the previous reset routine did this - * too. */ - *((unsigned short *)0x472) = reboot_mode; - /* Jump to the identity-mapped low memory code */ #ifdef CONFIG_X86_32 asm volatile("jmpl *%0" : : -- cgit v1.2.3 From 97ee9f01d6f26a69847d7a0ea07be756fe9f8eb6 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Thu, 21 Jun 2012 01:36:02 -0700 Subject: ARM: OMAP: fix the ads7846 init code In case a board provides the gpio_pendown and not board_pdata, the GPIO debounce is not taken care of. Fix this by taking care of GPIO debounce in any case. Signed-off-by: Igor Grinberg Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/common-board-devices.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c index 1706ebcec08d..c1875862679f 100644 --- a/arch/arm/mach-omap2/common-board-devices.c +++ b/arch/arm/mach-omap2/common-board-devices.c @@ -63,28 +63,30 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce, struct spi_board_info *spi_bi = &ads7846_spi_board_info; int err; - if (board_pdata && board_pdata->get_pendown_state) { - err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown"); - if (err) { - pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err); - return; - } - gpio_export(gpio_pendown, 0); - - if (gpio_debounce) - gpio_set_debounce(gpio_pendown, gpio_debounce); + err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown"); + if (err) { + pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err); + return; } + if (gpio_debounce) + gpio_set_debounce(gpio_pendown, gpio_debounce); + spi_bi->bus_num = bus_num; spi_bi->irq = gpio_to_irq(gpio_pendown); if (board_pdata) { board_pdata->gpio_pendown = gpio_pendown; spi_bi->platform_data = board_pdata; + if (board_pdata->get_pendown_state) + gpio_export(gpio_pendown, 0); } else { ads7846_config.gpio_pendown = gpio_pendown; } + if (!board_pdata || (board_pdata && !board_pdata->get_pendown_state)) + gpio_free(gpio_pendown); + spi_register_board_info(&ads7846_spi_board_info, 1); } #else -- cgit v1.2.3 From da0085ff9b2ca9ad21fd9fb380247e6639cccacd Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 21 Jun 2012 01:36:02 -0700 Subject: ARM: OMAP2: twl-common: Fix compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the kernel is built only for OMAP2 the following warning will show up: arch/arm/mach-omap2/twl-common.c:52: warning: ‘twl_set_voltage’ defined but not used arch/arm/mach-omap2/twl-common.c:58: warning: ‘twl_get_voltage’ defined but not used The twl_set/get_voltage callbacks only used when OMAP3/4 is selected. Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/twl-common.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index 119d5a910f3a..5447c135633f 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -48,6 +48,7 @@ static struct i2c_board_info __initdata omap4_i2c1_board_info[] = { }, }; +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) static int twl_set_voltage(void *data, int target_uV) { struct voltagedomain *voltdm = (struct voltagedomain *)data; @@ -59,6 +60,7 @@ static int twl_get_voltage(void *data) struct voltagedomain *voltdm = (struct voltagedomain *)data; return voltdm_get_voltage(voltdm); } +#endif void __init omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq, -- cgit v1.2.3 From f6f6c9a5be996f266ff6fbe7850d76c3b0bdab95 Mon Sep 17 00:00:00 2001 From: Brian Austin Date: Thu, 21 Jun 2012 01:36:02 -0700 Subject: ARM: OMAP: beagle: Set USB Host Port 1 to OMAP_USBHS_PORT_MODE_UNUSED The beagleboard USB Host Port that is used is Port 2. The platform driver sets MODE_PHY for port 1 causing pin muxing to override the pins on the expansion connector P17 when using board_mux[]. Since USBHS Port 1 is not connected remove the case for muxing the USB Port1 pins by default. Tested with BeagleBoard xM revC and checked the userguides for Beagle xM and revC to be sure USB Port2 is what is used. Signed-off-by: Brian Austin Acked-by: Russ Dill Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-omap3beagle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 79c6909eeb78..75eb88a738c4 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -435,7 +435,7 @@ static struct platform_device *omap3_beagle_devices[] __initdata = { static const struct usbhs_omap_board_data usbhs_bdata __initconst = { - .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, + .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED, .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY, .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED, -- cgit v1.2.3 From fd5c3fd7c4d06414453d7b72ab6d59ab1a0d2356 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 21 Jun 2012 01:36:03 -0700 Subject: ARM: OMAP: Fix dts files w/ status property: "disable" -> "disabled" This patches fixes some status = "disable" strings to "disabled", the correct way of disabling nodes in the devicetree. Just the OMAP part here, the rest goes via other patches and trees. Signed-off-by: Roland Stigge Acked-by: Rob Herring Acked-by: Benoit Cousson Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-beagle.dts | 4 ++-- arch/arm/boot/dts/omap4-panda.dts | 6 +++--- arch/arm/boot/dts/omap4-sdp.dts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts index 5b4506c0a8c4..cdcb98c7e075 100644 --- a/arch/arm/boot/dts/omap3-beagle.dts +++ b/arch/arm/boot/dts/omap3-beagle.dts @@ -61,9 +61,9 @@ }; &mmc2 { - status = "disable"; + status = "disabled"; }; &mmc3 { - status = "disable"; + status = "disabled"; }; diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts index 1efe0c587985..9d8abf0938e0 100644 --- a/arch/arm/boot/dts/omap4-panda.dts +++ b/arch/arm/boot/dts/omap4-panda.dts @@ -74,15 +74,15 @@ }; &mmc2 { - status = "disable"; + status = "disabled"; }; &mmc3 { - status = "disable"; + status = "disabled"; }; &mmc4 { - status = "disable"; + status = "disabled"; }; &mmc5 { diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index d08c4d137280..9b1c13a16c2c 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts @@ -147,11 +147,11 @@ }; &mmc3 { - status = "disable"; + status = "disabled"; }; &mmc4 { - status = "disable"; + status = "disabled"; }; &mmc5 { -- cgit v1.2.3 From 37f971b68009b8fadd322130787d693137302925 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 20 Jun 2012 12:53:25 +0200 Subject: ARM: mach-shmobile: armadillo800eva: Use late init machine hook Since commit 21cc1b7ede3cf456cf1d51f8a906093261f7c111 ("ARM: shmobile: use machine specific hook for late init") suspend and CPU idle are not initialized automatically anymore. Set shmobile_init_late() as the machine late init hook to initialize them. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/board-armadillo800eva.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 9e37026ef9dd..9bd135531d76 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -779,6 +779,7 @@ DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva") .init_irq = r8a7740_init_irq, .handle_irq = shmobile_handle_irq_intc, .init_machine = eva_init, + .init_late = shmobile_init_late, .timer = &shmobile_timer, .dt_compat = eva_boards_compat_dt, MACHINE_END -- cgit v1.2.3 From 14dd52f4389e206537488aeb2b85d6b21fc27196 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 20 Jun 2012 22:40:08 -0700 Subject: ARM: shmobile: kzm9g: use late init machine hook Since commit 21cc1b7ede3cf456cf1d51f8a906093261f7c111 ("ARM: shmobile: use machine specific hook for late init") suspend and CPU idle are not initialized automatically anymore. Set shmobile_init_late() as the machine late init hook to initialize them. Signed-off-by: Kuninori Morimoto Acked-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/board-kzm9g.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index d8e33b682832..c0ae815e7beb 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c @@ -455,6 +455,7 @@ DT_MACHINE_START(KZM9G_DT, "kzm9g") .init_irq = sh73a0_init_irq, .handle_irq = gic_handle_irq, .init_machine = kzm_init, + .init_late = shmobile_init_late, .timer = &shmobile_timer, .dt_compat = kzm9g_boards_compat_dt, MACHINE_END -- cgit v1.2.3 From c207d2df1c1b2a160b7d52229e5a43feea6a7d26 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 20 Jun 2012 22:41:34 -0700 Subject: ARM: shmobile: kzm9d: use late init machine hook Since commit 21cc1b7ede3cf456cf1d51f8a906093261f7c111 ("ARM: shmobile: use machine specific hook for late init") suspend and CPU idle are not initialized automatically anymore. Set shmobile_init_late() as the machine late init hook to initialize them. Signed-off-by: Kuninori Morimoto Acked-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/board-kzm9d.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c index 7bc5e7d39f9b..6a33cf393428 100644 --- a/arch/arm/mach-shmobile/board-kzm9d.c +++ b/arch/arm/mach-shmobile/board-kzm9d.c @@ -80,6 +80,7 @@ DT_MACHINE_START(KZM9D_DT, "kzm9d") .init_irq = emev2_init_irq, .handle_irq = gic_handle_irq, .init_machine = kzm9d_add_standard_devices, + .init_late = shmobile_init_late, .timer = &shmobile_timer, .dt_compat = kzm9d_boards_compat_dt, MACHINE_END -- cgit v1.2.3 From 9751d7627582fc1cc64625d63bde9528c14f1544 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 21 Jun 2012 10:25:03 -0700 Subject: x86-64, reboot: Be more paranoid in 64-bit reboot=bios Be a bit more paranoid in the transition back to 16-bit mode. In particular, in case the kernel is residing above the 4 GiB mark, switch to the trampoline GDT, and make the jump after turning off paging a far jump. In theory, none of this should matter, but it is exactly the kind of things that broken SMM or virtualization software could trip up on. Signed-off-by: H. Peter Anvin Link: http://lkml.kernel.org/r/tip-jopx7y6g6dbcx4tpal8q0jlr@git.kernel.org --- arch/x86/realmode/rm/reboot.S | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/realmode/rm/reboot.S b/arch/x86/realmode/rm/reboot.S index 6bf8feac5557..f932ea61d1c8 100644 --- a/arch/x86/realmode/rm/reboot.S +++ b/arch/x86/realmode/rm/reboot.S @@ -22,14 +22,18 @@ ENTRY(machine_real_restart_asm) #ifdef CONFIG_X86_64 + /* Switch to trampoline GDT as it is guaranteed < 4 GiB */ + movl $__KERNEL_DS, %eax + movl %eax, %ds + lgdtl pa_tr_gdt /* Disable paging to drop us out of long mode */ movl %cr0, %eax andl $~X86_CR0_PG, %eax movl %eax, %cr0 - jmp 1f /* "A branch" may be needed here, assume near is OK */ + ljmpl $__KERNEL32_CS, $pa_machine_real_restart_paging_off -1: +GLOBAL(machine_real_restart_paging_off) xorl %eax, %eax xorl %edx, %edx movl $MSR_EFER, %ecx -- cgit v1.2.3 From 561038f0a8aa1de272a2ac5dad24cc8246d9f496 Mon Sep 17 00:00:00 2001 From: Djamil Elaidi Date: Sun, 17 Jun 2012 11:57:51 -0600 Subject: ARM: OMAP4+: hwmod: fix issue causing IPs not going back to Smart-Standby If an IP is configured in Smart-Standby-Wakeup, when disabling wakeup feature the IP will not go back to Smart-Standby, but will remain in Smart-Standby-Wakeup. Signed-off-by: Djamil Elaidi Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index bf86f7e8f91f..773193670ea2 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -530,7 +530,7 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v) if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) _set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART, v); if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP) - _set_master_standbymode(oh, HWMOD_IDLEMODE_SMART_WKUP, v); + _set_master_standbymode(oh, HWMOD_IDLEMODE_SMART, v); /* XXX test pwrdm_get_wken for this hwmod's subsystem */ -- cgit v1.2.3 From 252a4c5443ec4d0bd310ae5b0d1b7f9c5b1e7f46 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Sun, 17 Jun 2012 11:57:51 -0600 Subject: ARM: OMAP4: hwmod data: fix 32k sync timer idle modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 32k sync timer IP block target idle modes in the hwmod data are incorrect. The IP block does not support any smart-idle modes. Update the data to reflect the correct modes. This problem was initially identified and a diff fragment posted to the lists by Benoît Cousson . A patch description bug in the first version was also identified by Benoît. Signed-off-by: Paul Walmsley Cc: Benoît Cousson Cc: Tero Kristo --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 950454a3fa31..c4c9cdd4c0cf 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -393,8 +393,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_counter_sysc = { .rev_offs = 0x0000, .sysc_offs = 0x0004, .sysc_flags = SYSC_HAS_SIDLEMODE, - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | - SIDLE_SMART_WKUP), + .idlemodes = (SIDLE_FORCE | SIDLE_NO), .sysc_fields = &omap_hwmod_sysc_type1, }; -- cgit v1.2.3 From 9a47d32d5c4b91a4ce4c459f3b7b0290185e7578 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Sun, 17 Jun 2012 11:57:52 -0600 Subject: ARM: OMAP4: clock data: add clockdomains for clocks used as main clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until the OMAP4 code is converted to disable the use of the clock framework-based clockdomain enable/disable sequence, any clock used as a hwmod main_clk must have a clockdomain associated with it. This patch populates some clock structure clockdomain names to resolve the following warnings during kernel init: omap_hwmod: dpll_mpu_m2_ck: missing clockdomain for dpll_mpu_m2_ck. omap_hwmod: trace_clk_div_ck: missing clockdomain for trace_clk_div_ck. omap_hwmod: l3_div_ck: missing clockdomain for l3_div_ck. omap_hwmod: ddrphy_ck: missing clockdomain for ddrphy_ck. Signed-off-by: Paul Walmsley Cc: Rajendra Nayak Cc: Benoît Cousson --- arch/arm/mach-omap2/clock44xx_data.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 2172f6603848..e2b701e164f6 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -84,6 +84,7 @@ static struct clk slimbus_clk = { static struct clk sys_32k_ck = { .name = "sys_32k_ck", + .clkdm_name = "prm_clkdm", .rate = 32768, .ops = &clkops_null, }; @@ -512,6 +513,7 @@ static struct clk ddrphy_ck = { .name = "ddrphy_ck", .parent = &dpll_core_m2_ck, .ops = &clkops_null, + .clkdm_name = "l3_emif_clkdm", .fixed_div = 2, .recalc = &omap_fixed_divisor_recalc, }; @@ -769,6 +771,7 @@ static const struct clksel dpll_mpu_m2_div[] = { static struct clk dpll_mpu_m2_ck = { .name = "dpll_mpu_m2_ck", .parent = &dpll_mpu_ck, + .clkdm_name = "cm_clkdm", .clksel = dpll_mpu_m2_div, .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_MPU, .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, @@ -1149,6 +1152,7 @@ static const struct clksel l3_div_div[] = { static struct clk l3_div_ck = { .name = "l3_div_ck", .parent = &div_core_ck, + .clkdm_name = "cm_clkdm", .clksel = l3_div_div, .clksel_reg = OMAP4430_CM_CLKSEL_CORE, .clksel_mask = OMAP4430_CLKSEL_L3_MASK, @@ -2824,6 +2828,7 @@ static const struct clksel trace_clk_div_div[] = { static struct clk trace_clk_div_ck = { .name = "trace_clk_div_ck", .parent = &pmd_trace_clk_mux_ck, + .clkdm_name = "emu_sys_clkdm", .clksel = trace_clk_div_div, .clksel_reg = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK, -- cgit v1.2.3 From b8f15b7e1dd3638d35cfff85571df1d7ea96e35e Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Sun, 17 Jun 2012 11:57:53 -0600 Subject: ARM: OMAP2+: CM: increase the module disable timeout Increase the timeout for disabling an IP block to five milliseconds. This is to handle the usb_host_fs idle latency, which takes almost four milliseconds after a host controller reset. This is the second of two patches needed to resolve the following boot warning: omap_hwmod: usb_host_fs: _wait_target_disable failed Thanks to Sergei Shtylyov for finding an unrelated hunk in a previous version of this patch. Signed-off-by: Paul Walmsley Cc: Sergei Shtylyov Cc: Tero Kristo --- arch/arm/mach-omap2/cm.h | 11 +++++++++++ arch/arm/mach-omap2/cminst44xx.c | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h index a7bc096bd407..f24e3f7a2bbc 100644 --- a/arch/arm/mach-omap2/cm.h +++ b/arch/arm/mach-omap2/cm.h @@ -22,4 +22,15 @@ */ #define MAX_MODULE_READY_TIME 2000 +/* + * MAX_MODULE_DISABLE_TIME: max duration in microseconds to wait for + * the PRCM to request that a module enter the inactive state in the + * case of OMAP2 & 3. In the case of OMAP4 this is the max duration + * in microseconds for the module to reach the inactive state from + * a functional state. + * XXX FSUSB on OMAP4430 takes ~4ms to idle after reset during + * kernel init. + */ +#define MAX_MODULE_DISABLE_TIME 5000 + #endif diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index 8c86d294b1a3..1a39945d9ff8 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c @@ -313,9 +313,9 @@ int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_off omap_test_timeout((_clkctrl_idlest(part, inst, cdoffs, clkctrl_offs) == CLKCTRL_IDLEST_DISABLED), - MAX_MODULE_READY_TIME, i); + MAX_MODULE_DISABLE_TIME, i); - return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; + return (i < MAX_MODULE_DISABLE_TIME) ? 0 : -EBUSY; } /** -- cgit v1.2.3 From 65e25976b75c4996c5650afadc4180db09ec7475 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Sun, 17 Jun 2012 12:00:58 -0600 Subject: ARM: OMAP2+: mux: fix sparse warning Commit bbd707acee279a61177a604822db92e8164d00db ("ARM: omap2: use machine specific hook for late init") resulted in the addition of this sparse warning: arch/arm/mach-omap2/mux.c:791:12: warning: symbol 'omap_mux_late_init' was not declared. Should it be static? Fix by including the header file containing the prototype. Signed-off-by: Paul Walmsley Cc: Shawn Guo Cc: Tony Lindgren --- arch/arm/mach-omap2/mux.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 80e55c5c9998..d3ef99c5cad8 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -41,6 +41,7 @@ #include "control.h" #include "mux.h" #include "prm.h" +#include "common.h" #define OMAP_MUX_BASE_OFFSET 0x30 /* Offset from CTRL_BASE */ #define OMAP_MUX_BASE_SZ 0x5ca -- cgit v1.2.3 From dc57aef503859dbf724f6126c58b2e1672e215f3 Mon Sep 17 00:00:00 2001 From: Ricardo Neri Date: Thu, 21 Jun 2012 10:08:53 +0200 Subject: ARM: OMAP4: hwmod data: Force HDMI in no-idle while enabled As per the OMAP4 documentation, audio over HDMI must be transmitted in no-idle mode. This patch adds the HWMOD_SWSUP_SIDLE so that omap_hwmod uses no-idle/force-idle settings instead of smart-idle mode. This is required as the DSS interface clock is used as functional clock for the HDMI wrapper audio FIFO. If no-idle mode is not used, audio could be choppy, have bad quality or not be audible at all. Signed-off-by: Ricardo Neri [b-cousson@ti.com: Update the subject and align the .flags location with the script template] Signed-off-by: Benoit Cousson Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index c4c9cdd4c0cf..f30e861ce6d9 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -853,6 +853,11 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = { .name = "dss_hdmi", .class = &omap44xx_hdmi_hwmod_class, .clkdm_name = "l3_dss_clkdm", + /* + * HDMI audio requires to use no-idle mode. Hence, + * set idle mode by software. + */ + .flags = HWMOD_SWSUP_SIDLE, .mpu_irqs = omap44xx_dss_hdmi_irqs, .sdma_reqs = omap44xx_dss_hdmi_sdma_reqs, .main_clk = "dss_48mhz_clk", -- cgit v1.2.3 From 96b1b29d37b0ca3ecd424a1fe301406cf525fc04 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Thu, 21 Jun 2012 21:40:38 -0600 Subject: ARM: OMAP2+: HDQ1W: use omap_device Convert the old-style device registration code for HDQ1W to use omap_device. This will allow the driver to be converted to use PM runtime and to take advantage of the OMAP IP block management infrastructure (hwmod, PM, etc.). A side benefit of this conversion is that it also makes the HDQ device available on OMAP2420. The previous code only enabled it on 2430 and 3430. Signed-off-by: Paul Walmsley Cc: NeilBrown Tested-by: NeilBrown --- arch/arm/mach-omap2/devices.c | 38 -------------------------------------- arch/arm/mach-omap2/hdq1w.c | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 38 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 7b4b9327e543..8cab358603ac 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -672,43 +672,6 @@ void __init omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data) #endif -/*-------------------------------------------------------------------------*/ - -#if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE) -#define OMAP_HDQ_BASE 0x480B2000 -static struct resource omap_hdq_resources[] = { - { - .start = OMAP_HDQ_BASE, - .end = OMAP_HDQ_BASE + 0x1C, - .flags = IORESOURCE_MEM, - }, - { - .start = INT_24XX_HDQ_IRQ, - .flags = IORESOURCE_IRQ, - }, -}; -static struct platform_device omap_hdq_dev = { - .name = "omap_hdq", - .id = 0, - .dev = { - .platform_data = NULL, - }, - .num_resources = ARRAY_SIZE(omap_hdq_resources), - .resource = omap_hdq_resources, -}; -static inline void omap_hdq_init(void) -{ - if (cpu_is_omap2420()) - return; - - platform_device_register(&omap_hdq_dev); -} -#else -static inline void omap_hdq_init(void) {} -#endif - -/*---------------------------------------------------------------------------*/ - #if defined(CONFIG_VIDEO_OMAP2_VOUT) || \ defined(CONFIG_VIDEO_OMAP2_VOUT_MODULE) #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) @@ -753,7 +716,6 @@ static int __init omap2_init_devices(void) omap_init_mcspi(); } omap_init_pmu(); - omap_hdq_init(); omap_init_sti(); omap_init_sham(); omap_init_aes(); diff --git a/arch/arm/mach-omap2/hdq1w.c b/arch/arm/mach-omap2/hdq1w.c index 297ebe03f09c..cdd6dda03828 100644 --- a/arch/arm/mach-omap2/hdq1w.c +++ b/arch/arm/mach-omap2/hdq1w.c @@ -22,7 +22,13 @@ * 02110-1301 USA */ +#include +#include +#include +#include + #include +#include #include #include "common.h" @@ -70,3 +76,23 @@ int omap_hdq1w_reset(struct omap_hwmod *oh) return 0; } + +static int __init omap_init_hdq(void) +{ + int id = -1; + struct platform_device *pdev; + struct omap_hwmod *oh; + char *oh_name = "hdq1w"; + char *devname = "omap_hdq"; + + oh = omap_hwmod_lookup(oh_name); + if (!oh) + return 0; + + pdev = omap_device_build(devname, id, oh, NULL, 0, NULL, 0, 0); + WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n", + devname, oh->name); + + return 0; +} +arch_initcall(omap_init_hdq); -- cgit v1.2.3 From 75a4433e409b2d22cbe443b623d92047b59cbb9a Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 22 Jun 2012 08:40:02 -0600 Subject: ARM: OMAP2+: PRM: fix compile for OMAP4-only build For OMAP4 only builds, the omap2_prm_* functions have dummy wrappers to detect incorrect usage. However, several unrelated omap3 PRM functions have made it inside the #else clause of the #ifdef wrapping the omap2_prm stubs, causing them to disappear on OMAP4-only builds. This was unnoticed until the IO chain support was added and introduced a new function in this section which is referenced by omap_hwmod.c: arch/arm/mach-omap2/omap_hwmod.c: In function '_reconfigure_io_chain': arch/arm/mach-omap2/omap_hwmod.c:1665:3: error: implicit declaration of function 'omap3xxx_prm_reconfigure_io_chain' [-Werror=implicit-function-declaration] Fix by using the #ifdef to only wrap the omap2_prm functions that need stubs on OMAP4-only builds. Cc: Paul Walmsley Signed-off-by: Kevin Hilman [paul@pwsan.com: fixed checkpatch warnings for patch description] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/prm2xxx_3xxx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h index 70ac2a19dc5f..491c72dd20a0 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h @@ -303,6 +303,8 @@ extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift); extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift); extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift); +#endif /* CONFIG_ARCH_OMAP4 */ + /* OMAP3-specific VP functions */ u32 omap3_prm_vp_check_txdone(u8 vp_id); void omap3_prm_vp_clear_txdone(u8 vp_id); @@ -321,8 +323,6 @@ extern void omap3xxx_prm_ocp_barrier(void); extern void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask); extern void omap3xxx_prm_restore_irqen(u32 *saved_mask); -#endif /* CONFIG_ARCH_OMAP4 */ - #endif /* -- cgit v1.2.3 From fe7ea0062f2f846bb68447c7b813b9230285dbeb Mon Sep 17 00:00:00 2001 From: Mohan V Date: Fri, 22 Jun 2012 08:40:02 -0600 Subject: ARM: OMAP3: PM: correct enable/disable of daisy io chain Currently the enabling and disabling of IO Daisy chain is not according to the TRM. The below steps are followed to enable/ disable the IO chain, based loosely on the "Sec 3.5.7.2.2 I/O Wake-Up Mechanism" section in OMAP3630 Public TRM[1]. Steps to enable IO chain: [a] Set PM_WKEN_WKUP.EN_IO bit [b] Set the PM_WKEN_WKUP.EN_IO_CHAIN bit [c] Poll for PM_WKST_WKUP.ST_IO_CHAIN. [d] When ST_IO_CHAIN bit set to 1, clear PM_WKEN_WKUP.EN_IO_CHAIN [e] Clear ST_IO_CHAIN bit. Steps to disable IO chain: [a] Clear PM_WKEN_WKUP.EN_IO_CHAIN bit [b] Clear PM_WKEN_WKUP.EN_IO bit [c] Clear PM_WKST_WKUP.ST_IO bit by writing 1 to it. Step [e] & [c] in each case can be skipped, as these are handled by the PRCM interrupt handler later. [1] http://focus.ti.com/pdfs/wtbu/OMAP36xx_ES1.x_PUBLIC_TRM_vV.zip Signed-off-by: Mohan V Signed-off-by: Vishwanath BS [paul@pwsan.com: modified commit message to clarify that these steps are based loosely on the TRM section, rather than documented exactly] Reviewed-by: Rajendra Nayak [paul@pwsan.com: resolved new warnings from checkpatch] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/pm34xx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index a34023d0ca7c..6d7f0d8a3103 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -81,16 +81,17 @@ static void omap3_enable_io_chain(void) /* Do a readback to assure write has been done */ omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN); - while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) & + while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) & OMAP3430_ST_IO_CHAIN_MASK)) { timeout++; if (timeout > 1000) { pr_err("Wake up daisy chain activation failed.\n"); return; } - omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, - WKUP_MOD, PM_WKEN); } + omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, + PM_WKEN); + } static void omap3_disable_io_chain(void) -- cgit v1.2.3 From 09659fa72bf638ae986b8b80cf99309768dd0b32 Mon Sep 17 00:00:00 2001 From: Vishwanath BS Date: Fri, 22 Jun 2012 08:40:02 -0600 Subject: ARM: OMAP3: PM: Move IO Daisychain function to omap3 prm file Since IO Daisychain modifies only PRM registers, it makes sense to move it to PRM File. Also changed the timeout value for IO chain enable to 100us and added a wait for status disable at the end. Thanks to Nishanth Menon for contributing a fix to the timeout code waiting for WUCLKOUT to go high. Signed-off-by: Vishwanath BS Signed-off-by: Tero Kristo Cc: Nishanth Menon Reviewed-by: Rajendra Nayak [paul@pwsan.com: renamed omap3_trigger_io_chain() to better describe the end result and to match other PRM functions; removed omap3_disable_io_chain(); moved MAX_IOPAD_LATCH_TIME to prcm-common as it will also be used by the OMAP4 code; removed unnecessary barrier; added kerneldoc; added credit for fix from Nishanth] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/pm34xx.c | 35 ++--------------------------------- arch/arm/mach-omap2/prcm-common.h | 8 ++++++++ arch/arm/mach-omap2/prm2xxx_3xxx.c | 31 +++++++++++++++++++++++++++++++ arch/arm/mach-omap2/prm2xxx_3xxx.h | 2 ++ 4 files changed, 43 insertions(+), 33 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 6d7f0d8a3103..9d6cb7cc94ab 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -72,34 +72,6 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm; static struct powerdomain *core_pwrdm, *per_pwrdm; static struct powerdomain *cam_pwrdm; -static void omap3_enable_io_chain(void) -{ - int timeout = 0; - - omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, - PM_WKEN); - /* Do a readback to assure write has been done */ - omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN); - - while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) & - OMAP3430_ST_IO_CHAIN_MASK)) { - timeout++; - if (timeout > 1000) { - pr_err("Wake up daisy chain activation failed.\n"); - return; - } - } - omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, - PM_WKEN); - -} - -static void omap3_disable_io_chain(void) -{ - omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, - PM_WKEN); -} - static void omap3_core_save_context(void) { omap3_ctrl_save_padconf(); @@ -305,7 +277,7 @@ void omap_sram_idle(void) core_next_state < PWRDM_POWER_ON)) { omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN); if (omap3_has_io_chain_ctrl()) - omap3_enable_io_chain(); + omap3xxx_prm_reconfigure_io_chain(); } pwrdm_pre_transition(); @@ -382,12 +354,9 @@ void omap_sram_idle(void) /* Disable IO-PAD and IO-CHAIN wakeup */ if (omap3_has_io_wakeup() && (per_next_state < PWRDM_POWER_ON || - core_next_state < PWRDM_POWER_ON)) { + core_next_state < PWRDM_POWER_ON)) omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN); - if (omap3_has_io_chain_ctrl()) - omap3_disable_io_chain(); - } clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]); } diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index 6da3ba483ad1..fca23cbea708 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -410,6 +410,14 @@ */ #define MAX_MODULE_HARDRESET_WAIT 10000 +/* + * Maximum time(us) it takes to output the signal WUCLKOUT of the last + * pad of the I/O ring after asserting WUCLKIN high. Tero measured + * the actual time at 7 to 8 microseconds on OMAP3 and 2 to 4 + * microseconds on OMAP4, so this timeout may be too high. + */ +#define MAX_IOPAD_LATCH_TIME 100 + # ifndef __ASSEMBLER__ extern void __iomem *prm_base; extern void __iomem *cm_base; diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index 9ce765407ad5..7d62bd654dbe 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c @@ -301,6 +301,37 @@ void omap3xxx_prm_restore_irqen(u32 *saved_mask) OMAP3_PRM_IRQENABLE_MPU_OFFSET); } +/** + * omap3xxx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain + * + * Clear any previously-latched I/O wakeup events and ensure that the + * I/O wakeup gates are aligned with the current mux settings. Works + * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then + * deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit. No + * return value. + */ +void omap3xxx_prm_reconfigure_io_chain(void) +{ + int i = 0; + + omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, + PM_WKEN); + + omap_test_timeout(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) & + OMAP3430_ST_IO_CHAIN_MASK, + MAX_IOPAD_LATCH_TIME, i); + if (i == MAX_IOPAD_LATCH_TIME) + pr_warn("PRM: I/O chain clock line assertion timed out\n"); + + omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, + PM_WKEN); + + omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, WKUP_MOD, + PM_WKST); + + omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST); +} + static int __init omap3xxx_prcm_init(void) { if (cpu_is_omap34xx()) diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h index 491c72dd20a0..a8c946f318ab 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h @@ -317,6 +317,8 @@ extern u32 omap3_prm_vcvp_read(u8 offset); extern void omap3_prm_vcvp_write(u32 val, u8 offset); extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset); +extern void omap3xxx_prm_reconfigure_io_chain(void); + /* PRM interrupt-related functions */ extern void omap3xxx_prm_read_pending_irqs(unsigned long *events); extern void omap3xxx_prm_ocp_barrier(void); -- cgit v1.2.3 From dea6200ba0a43afb90a277802c3edf0124848eed Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 22 Jun 2012 08:40:03 -0600 Subject: ARM: OMAP4: PRM: Add IO Daisychain support IO daisychain is a mechanism that allows individual IO pads to generate wakeup events on their own based on a switch of an input signal level. This allows the hardware module behind the pad to be powered down, but still have device level capability to detect IO events, and once this happens the module can be powered back up to resume IO. See section 3.9.4 in OMAP4430 Public TRM for details. Signed-off-by: Rajendra Nayak Signed-off-by: Vishwanath BS Signed-off-by: Tero Kristo [paul@pwsan.com: use the shared MAX_IOPAD_LATCH_TIME declaration; renamed omap4_trigger_io_chain() to conform to other PRM function names; added kerneldoc; resolved checkpatch warnings] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/prm44xx.c | 54 +++++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/prm44xx.h | 2 ++ 2 files changed, 56 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index f106d21ff581..28ffbc55f8d6 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -233,6 +233,60 @@ void omap44xx_prm_restore_irqen(u32 *saved_mask) OMAP4_PRM_IRQENABLE_MPU_2_OFFSET); } +/** + * omap44xx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain + * + * Clear any previously-latched I/O wakeup events and ensure that the + * I/O wakeup gates are aligned with the current mux settings. Works + * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then + * deasserting WUCLKIN and waiting for WUCLKOUT to be deasserted. + * No return value. XXX Are the final two steps necessary? + */ +void omap44xx_prm_reconfigure_io_chain(void) +{ + int i = 0; + u32 v; + + v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, + OMAP4_PRM_IO_PMCTRL_OFFSET); + + /* Enable GLOBAL_WUEN */ + if (!(v & OMAP4430_GLOBAL_WUEN_MASK)) + omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK, + OMAP4430_GLOBAL_WUEN_MASK, + OMAP4430_PRM_DEVICE_INST, + OMAP4_PRM_IO_PMCTRL_OFFSET); + + /* Trigger WUCLKIN enable */ + omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, + OMAP4430_WUCLK_CTRL_MASK, + OMAP4430_PRM_DEVICE_INST, + OMAP4_PRM_IO_PMCTRL_OFFSET); + omap_test_timeout( + (((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, + OMAP4_PRM_IO_PMCTRL_OFFSET) & + OMAP4430_WUCLK_STATUS_MASK) >> + OMAP4430_WUCLK_STATUS_SHIFT) == 1), + MAX_IOPAD_LATCH_TIME, i); + if (i == MAX_IOPAD_LATCH_TIME) + pr_warn("PRM: I/O chain clock line assertion timed out\n"); + + /* Trigger WUCLKIN disable */ + omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0, + OMAP4430_PRM_DEVICE_INST, + OMAP4_PRM_IO_PMCTRL_OFFSET); + omap_test_timeout( + (((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, + OMAP4_PRM_IO_PMCTRL_OFFSET) & + OMAP4430_WUCLK_STATUS_MASK) >> + OMAP4430_WUCLK_STATUS_SHIFT) == 0), + MAX_IOPAD_LATCH_TIME, i); + if (i == MAX_IOPAD_LATCH_TIME) + pr_warn("PRM: I/O chain clock line deassertion timed out\n"); + + return; +} + static int __init omap4xxx_prcm_init(void) { if (cpu_is_omap44xx()) diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h index 7978092946db..ee72ae6bd8c9 100644 --- a/arch/arm/mach-omap2/prm44xx.h +++ b/arch/arm/mach-omap2/prm44xx.h @@ -763,6 +763,8 @@ extern u32 omap4_prm_vcvp_read(u8 offset); extern void omap4_prm_vcvp_write(u32 val, u8 offset); extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset); +extern void omap44xx_prm_reconfigure_io_chain(void); + /* PRM interrupt-related functions */ extern void omap44xx_prm_read_pending_irqs(unsigned long *events); extern void omap44xx_prm_ocp_barrier(void); -- cgit v1.2.3 From 8a680ea2eb2e9ad602e290396add29e9eaed0911 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 22 Jun 2012 08:40:03 -0600 Subject: ARM: OMAP3+: PRM: Enable IO wake up Enable IO Wake up for OMAP3/4 as part of PRM Init. Currently this has been managed in cpuidle path which is not the right place. Subsequent patch will remove IO Daisy chain handling in cpuidle path once daisy chain is handled as part of hwmod mux. This patch also moves the OMAP4 IO wakeup enable code from the trigger function to init time setup. Signed-off-by: Tero Kristo Reviewed-by: Rajendra Nayak [paul@pwsan.com: harmonize function names with other PRM functions; add kerneldoc; resolve checkpatch warnings] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/prm2xxx_3xxx.c | 20 +++++++++++++++++++- arch/arm/mach-omap2/prm44xx.c | 31 +++++++++++++++++++------------ 2 files changed, 38 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index 7d62bd654dbe..1471a33738f3 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c @@ -332,10 +332,28 @@ void omap3xxx_prm_reconfigure_io_chain(void) omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST); } +/** + * omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches + * + * Activates the I/O wakeup event latches and allows events logged by + * those latches to signal a wakeup event to the PRCM. For I/O + * wakeups to occur, WAKEUPENABLE bits must be set in the pad mux + * registers, and omap3xxx_prm_reconfigure_io_chain() must be called. + * No return value. + */ +static void __init omap3xxx_prm_enable_io_wakeup(void) +{ + if (omap3_has_io_wakeup()) + omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, + PM_WKEN); +} + static int __init omap3xxx_prcm_init(void) { - if (cpu_is_omap34xx()) + if (cpu_is_omap34xx()) { + omap3xxx_prm_enable_io_wakeup(); return omap_prcm_register_chain_handler(&omap3_prcm_irq_setup); + } return 0; } subsys_initcall(omap3xxx_prcm_init); diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index 28ffbc55f8d6..bb727c2d9337 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -245,17 +245,6 @@ void omap44xx_prm_restore_irqen(u32 *saved_mask) void omap44xx_prm_reconfigure_io_chain(void) { int i = 0; - u32 v; - - v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, - OMAP4_PRM_IO_PMCTRL_OFFSET); - - /* Enable GLOBAL_WUEN */ - if (!(v & OMAP4430_GLOBAL_WUEN_MASK)) - omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK, - OMAP4430_GLOBAL_WUEN_MASK, - OMAP4430_PRM_DEVICE_INST, - OMAP4_PRM_IO_PMCTRL_OFFSET); /* Trigger WUCLKIN enable */ omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, @@ -287,10 +276,28 @@ void omap44xx_prm_reconfigure_io_chain(void) return; } +/** + * omap44xx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches + * + * Activates the I/O wakeup event latches and allows events logged by + * those latches to signal a wakeup event to the PRCM. For I/O wakeups + * to occur, WAKEUPENABLE bits must be set in the pad mux registers, and + * omap44xx_prm_reconfigure_io_chain() must be called. No return value. + */ +static void __init omap44xx_prm_enable_io_wakeup(void) +{ + omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK, + OMAP4430_GLOBAL_WUEN_MASK, + OMAP4430_PRM_DEVICE_INST, + OMAP4_PRM_IO_PMCTRL_OFFSET); +} + static int __init omap4xxx_prcm_init(void) { - if (cpu_is_omap44xx()) + if (cpu_is_omap44xx()) { + omap44xx_prm_enable_io_wakeup(); return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup); + } return 0; } subsys_initcall(omap4xxx_prcm_init); -- cgit v1.2.3 From 5165882a387325ac0df2f30c62ea710cfa328b54 Mon Sep 17 00:00:00 2001 From: Vishwanath BS Date: Fri, 22 Jun 2012 08:40:04 -0600 Subject: ARM: OMAP3PLUS: hwmod: reconfigure IO Daisychain during hwmod mux IO Daisychain feature has to be triggered whenever there is a change in device's mux configuration (See section 3.9.4 in OMAP4 Public TRM vP). Now devices can idle independent of the powerdomain, there can be a window where device is idled and corresponding powerdomain can be ON/INACTIVE state. In such situations, since both module wake up is enabled at padlevel as well as io daisychain sequence is triggered, there will be 2 PRCM interrupts (Module async wake up via swakeup and IO Pad interrupt). But as PRCM Interrupt handler clears the Module Padlevel WKST bit in the first interrupt, module specific interrupt handler will not triggered for the second time Also look at detailed explanation given by Rajendra at http://www.spinics.net/lists/linux-serial/msg04480.html Signed-off-by: Vishwanath BS Signed-off-by: Tero Kristo Reviewed-by: Rajendra Nayak [paul@pwsan.com: remove dependency on pm.c & pm.h; add kerneldoc] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index bf86f7e8f91f..6d6c31a10a1b 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -153,6 +153,7 @@ #include "prm44xx.h" #include "prminst44xx.h" #include "mux.h" +#include "pm.h" /* Maximum microseconds to wait for OMAP module to softreset */ #define MAX_MODULE_SOFTRESET_WAIT 10000 @@ -172,6 +173,9 @@ static LIST_HEAD(omap_hwmod_list); /* mpu_oh: used to add/remove MPU initiator from sleepdep list */ static struct omap_hwmod *mpu_oh; +/* io_chain_lock: used to serialize reconfigurations of the I/O chain */ +static DEFINE_SPINLOCK(io_chain_lock); + /* * linkspace: ptr to a buffer that struct omap_hwmod_link records are * allocated from - used to reduce the number of small memory @@ -1737,6 +1741,32 @@ static int _reset(struct omap_hwmod *oh) return r; } +/** + * _reconfigure_io_chain - clear any I/O chain wakeups and reconfigure chain + * + * Call the appropriate PRM function to clear any logged I/O chain + * wakeups and to reconfigure the chain. This apparently needs to be + * done upon every mux change. Since hwmods can be concurrently + * enabled and idled, hold a spinlock around the I/O chain + * reconfiguration sequence. No return value. + * + * XXX When the PRM code is moved to drivers, this function can be removed, + * as the PRM infrastructure should abstract this. + */ +static void _reconfigure_io_chain(void) +{ + unsigned long flags; + + spin_lock_irqsave(&io_chain_lock, flags); + + if (cpu_is_omap34xx() && omap3_has_io_chain_ctrl()) + omap3xxx_prm_reconfigure_io_chain(); + else if (cpu_is_omap44xx()) + omap44xx_prm_reconfigure_io_chain(); + + spin_unlock_irqrestore(&io_chain_lock, flags); +} + /** * _enable - enable an omap_hwmod * @oh: struct omap_hwmod * @@ -1793,8 +1823,10 @@ static int _enable(struct omap_hwmod *oh) /* Mux pins for device runtime if populated */ if (oh->mux && (!oh->mux->enabled || ((oh->_state == _HWMOD_STATE_IDLE) && - oh->mux->pads_dynamic))) + oh->mux->pads_dynamic))) { omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); + _reconfigure_io_chain(); + } _add_initiator_dep(oh, mpu_oh); @@ -1883,8 +1915,10 @@ static int _idle(struct omap_hwmod *oh) clkdm_hwmod_disable(oh->clkdm, oh); /* Mux pins for device idle if populated */ - if (oh->mux && oh->mux->pads_dynamic) + if (oh->mux && oh->mux->pads_dynamic) { omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE); + _reconfigure_io_chain(); + } oh->_state = _HWMOD_STATE_IDLE; -- cgit v1.2.3 From fafcdd53220f44d7ae2f06a9ce20c8d550df2d9b Mon Sep 17 00:00:00 2001 From: Vishwanath BS Date: Wed, 2 May 2012 02:44:40 -0600 Subject: ARM: OMAP3: PM: Remove IO Daisychain control from cpuidle As IO Daisy chain sequence is triggered via hwmod mux, there is no need to control it from cpuidle path for OMAP3. Also as omap3_disable_io_chain is no longer being used, just remove the function. Signed-off-by: Vishwanath BS Signed-off-by: Tero Kristo Reviewed-by: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/pm34xx.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 9d6cb7cc94ab..9d8258f16666 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -272,13 +272,6 @@ void omap_sram_idle(void) /* Enable IO-PAD and IO-CHAIN wakeups */ per_next_state = pwrdm_read_next_pwrst(per_pwrdm); core_next_state = pwrdm_read_next_pwrst(core_pwrdm); - if (omap3_has_io_wakeup() && - (per_next_state < PWRDM_POWER_ON || - core_next_state < PWRDM_POWER_ON)) { - omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN); - if (omap3_has_io_chain_ctrl()) - omap3xxx_prm_reconfigure_io_chain(); - } pwrdm_pre_transition(); @@ -351,13 +344,6 @@ void omap_sram_idle(void) if (per_next_state < PWRDM_POWER_ON) omap2_gpio_resume_after_idle(); - /* Disable IO-PAD and IO-CHAIN wakeup */ - if (omap3_has_io_wakeup() && - (per_next_state < PWRDM_POWER_ON || - core_next_state < PWRDM_POWER_ON)) - omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, - PM_WKEN); - clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]); } -- cgit v1.2.3 From 2a76c450bd0377f715caf313ded530290d7dc7d7 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 22 Jun 2012 14:55:10 +0800 Subject: x86/PCI: split out pci_mmcfg_check_reserved() for code reuse Split out pci_mmcfg_check_reserved() for code reuse, which will be used when supporting PCI host bridge hotplug. Reviewed-by: Yinghai Lu Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/mmconfig-shared.c | 51 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 301e325992f6..f799949a08a5 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -474,39 +474,38 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved, return valid; } +static int __devinit pci_mmcfg_check_reserved(struct pci_mmcfg_region *cfg, + int early) +{ + if (!early && !acpi_disabled) { + if (is_mmconf_reserved(is_acpi_reserved, cfg, 0)) + return 1; + else + printk(KERN_ERR FW_BUG PREFIX + "MMCONFIG at %pR not reserved in " + "ACPI motherboard resources\n", + &cfg->res); + } + + /* Don't try to do this check unless configuration + type 1 is available. how about type 2 ?*/ + if (raw_pci_ops) + return is_mmconf_reserved(e820_all_mapped, cfg, 1); + + return 0; +} + static void __init pci_mmcfg_reject_broken(int early) { struct pci_mmcfg_region *cfg; list_for_each_entry(cfg, &pci_mmcfg_list, list) { - int valid = 0; - - if (!early && !acpi_disabled) { - valid = is_mmconf_reserved(is_acpi_reserved, cfg, 0); - - if (valid) - continue; - else - printk(KERN_ERR FW_BUG PREFIX - "MMCONFIG at %pR not reserved in " - "ACPI motherboard resources\n", - &cfg->res); + if (pci_mmcfg_check_reserved(cfg, early) == 0) { + printk(KERN_INFO PREFIX "not using MMCONFIG\n"); + free_all_mmcfg(); + return; } - - /* Don't try to do this check unless configuration - type 1 is available. how about type 2 ?*/ - if (raw_pci_ops) - valid = is_mmconf_reserved(e820_all_mapped, cfg, 1); - - if (!valid) - goto reject; } - - return; - -reject: - printk(KERN_INFO PREFIX "not using MMCONFIG\n"); - free_all_mmcfg(); } static int __initdata known_bridge; -- cgit v1.2.3 From 846e402300ffa2131239dcf82265b5366cd755f4 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 22 Jun 2012 14:55:11 +0800 Subject: x86/PCI: split out pci_mmconfig_alloc() for code reuse Split out pci_mmconfig_alloc() for code reuse, which will be used when supporting PCI root bridge hotplug. Reviewed-by: Yinghai Lu Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/mmconfig-shared.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index f799949a08a5..5e2cd2aa2889 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -61,8 +61,9 @@ static __init void list_add_sorted(struct pci_mmcfg_region *new) list_add_tail(&new->list, &pci_mmcfg_list); } -static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start, - int end, u64 addr) +static __devinit struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, + int start, + int end, u64 addr) { struct pci_mmcfg_region *new; struct resource *res; @@ -79,8 +80,6 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start, new->start_bus = start; new->end_bus = end; - list_add_sorted(new); - res = &new->res; res->start = addr + PCI_MMCFG_BUS_OFFSET(start); res->end = addr + PCI_MMCFG_BUS_OFFSET(end + 1) - 1; @@ -96,6 +95,18 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start, return new; } +static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start, + int end, u64 addr) +{ + struct pci_mmcfg_region *new; + + new = pci_mmconfig_alloc(segment, start, end, addr); + if (new) + list_add_sorted(new); + + return new; +} + struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus) { struct pci_mmcfg_region *cfg; -- cgit v1.2.3 From 376f70acfe4bd97493299cdfc00a8d235279d267 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 22 Jun 2012 14:55:12 +0800 Subject: x86/PCI: use RCU list to protect mmconfig list Use RCU list to protect mmconfig list from dynamic change when supporting PCI host bridge hotplug. Reviewed-by: Yinghai Lu Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/mmconfig-shared.c | 18 ++++++++++++------ arch/x86/pci/mmconfig_32.c | 13 +++++++++++-- arch/x86/pci/mmconfig_64.c | 13 +++++++++++-- 3 files changed, 34 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 5e2cd2aa2889..0ac97d54bcac 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include #include @@ -25,6 +27,7 @@ /* Indicate if the mmcfg resources have been placed into the resource table. */ static int __initdata pci_mmcfg_resources_inserted; +static DEFINE_MUTEX(pci_mmcfg_lock); LIST_HEAD(pci_mmcfg_list); @@ -45,20 +48,20 @@ static __init void free_all_mmcfg(void) pci_mmconfig_remove(cfg); } -static __init void list_add_sorted(struct pci_mmcfg_region *new) +static __devinit void list_add_sorted(struct pci_mmcfg_region *new) { struct pci_mmcfg_region *cfg; /* keep list sorted by segment and starting bus number */ - list_for_each_entry(cfg, &pci_mmcfg_list, list) { + list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list) { if (cfg->segment > new->segment || (cfg->segment == new->segment && cfg->start_bus >= new->start_bus)) { - list_add_tail(&new->list, &cfg->list); + list_add_tail_rcu(&new->list, &cfg->list); return; } } - list_add_tail(&new->list, &pci_mmcfg_list); + list_add_tail_rcu(&new->list, &pci_mmcfg_list); } static __devinit struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, @@ -101,8 +104,11 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start, struct pci_mmcfg_region *new; new = pci_mmconfig_alloc(segment, start, end, addr); - if (new) + if (new) { + mutex_lock(&pci_mmcfg_lock); list_add_sorted(new); + mutex_unlock(&pci_mmcfg_lock); + } return new; } @@ -111,7 +117,7 @@ struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus) { struct pci_mmcfg_region *cfg; - list_for_each_entry(cfg, &pci_mmcfg_list, list) + list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list) if (cfg->segment == segment && cfg->start_bus <= bus && bus <= cfg->end_bus) return cfg; diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c index 5372e86834c0..5dad04aa6b37 100644 --- a/arch/x86/pci/mmconfig_32.c +++ b/arch/x86/pci/mmconfig_32.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -60,9 +61,12 @@ err: *value = -1; return -EINVAL; } + rcu_read_lock(); base = get_base_addr(seg, bus, devfn); - if (!base) + if (!base) { + rcu_read_unlock(); goto err; + } raw_spin_lock_irqsave(&pci_config_lock, flags); @@ -80,6 +84,7 @@ err: *value = -1; break; } raw_spin_unlock_irqrestore(&pci_config_lock, flags); + rcu_read_unlock(); return 0; } @@ -93,9 +98,12 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, if ((bus > 255) || (devfn > 255) || (reg > 4095)) return -EINVAL; + rcu_read_lock(); base = get_base_addr(seg, bus, devfn); - if (!base) + if (!base) { + rcu_read_unlock(); return -EINVAL; + } raw_spin_lock_irqsave(&pci_config_lock, flags); @@ -113,6 +121,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, break; } raw_spin_unlock_irqrestore(&pci_config_lock, flags); + rcu_read_unlock(); return 0; } diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c index 915a493502cb..acc48c5b6863 100644 --- a/arch/x86/pci/mmconfig_64.c +++ b/arch/x86/pci/mmconfig_64.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -34,9 +35,12 @@ err: *value = -1; return -EINVAL; } + rcu_read_lock(); addr = pci_dev_base(seg, bus, devfn); - if (!addr) + if (!addr) { + rcu_read_unlock(); goto err; + } switch (len) { case 1: @@ -49,6 +53,7 @@ err: *value = -1; *value = mmio_config_readl(addr + reg); break; } + rcu_read_unlock(); return 0; } @@ -62,9 +67,12 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) return -EINVAL; + rcu_read_lock(); addr = pci_dev_base(seg, bus, devfn); - if (!addr) + if (!addr) { + rcu_read_unlock(); return -EINVAL; + } switch (len) { case 1: @@ -77,6 +85,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, mmio_config_writel(addr + reg, value); break; } + rcu_read_unlock(); return 0; } -- cgit v1.2.3 From 9cf0105da5a315677d8f91043fb87fdade0d8b39 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 22 Jun 2012 14:55:13 +0800 Subject: x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap() Introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap(), which will be used when supporting PCI root bridge hotplug. Reviewed-by: Yinghai Lu Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/x86/include/asm/pci_x86.h | 2 ++ arch/x86/pci/mmconfig_32.c | 15 +++++++++++++++ arch/x86/pci/mmconfig_64.c | 38 ++++++++++++++++++++++++++------------ 3 files changed, 43 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index b3a531746026..df898ceab4d4 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h @@ -135,6 +135,8 @@ struct pci_mmcfg_region { extern int __init pci_mmcfg_arch_init(void); extern void __init pci_mmcfg_arch_free(void); +extern int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg); +extern void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg); extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus); extern struct list_head pci_mmcfg_list; diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c index 5dad04aa6b37..a22785deb50e 100644 --- a/arch/x86/pci/mmconfig_32.c +++ b/arch/x86/pci/mmconfig_32.c @@ -141,3 +141,18 @@ int __init pci_mmcfg_arch_init(void) void __init pci_mmcfg_arch_free(void) { } + +int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg) +{ + return 0; +} + +void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg) +{ + unsigned long flags; + + /* Invalidate the cached mmcfg map entry. */ + raw_spin_lock_irqsave(&pci_config_lock, flags); + mmcfg_last_accessed_device = 0; + raw_spin_unlock_irqrestore(&pci_config_lock, flags); +} diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c index acc48c5b6863..ebefea5107a7 100644 --- a/arch/x86/pci/mmconfig_64.c +++ b/arch/x86/pci/mmconfig_64.c @@ -95,7 +95,7 @@ static const struct pci_raw_ops pci_mmcfg = { .write = pci_mmcfg_write, }; -static void __iomem * __init mcfg_ioremap(struct pci_mmcfg_region *cfg) +static void __iomem * __devinit mcfg_ioremap(struct pci_mmcfg_region *cfg) { void __iomem *addr; u64 start, size; @@ -114,16 +114,14 @@ int __init pci_mmcfg_arch_init(void) { struct pci_mmcfg_region *cfg; - list_for_each_entry(cfg, &pci_mmcfg_list, list) { - cfg->virt = mcfg_ioremap(cfg); - if (!cfg->virt) { - printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n", - &cfg->res); + list_for_each_entry(cfg, &pci_mmcfg_list, list) + if (pci_mmcfg_arch_map(cfg)) { pci_mmcfg_arch_free(); return 0; } - } + raw_pci_ext_ops = &pci_mmcfg; + return 1; } @@ -131,10 +129,26 @@ void __init pci_mmcfg_arch_free(void) { struct pci_mmcfg_region *cfg; - list_for_each_entry(cfg, &pci_mmcfg_list, list) { - if (cfg->virt) { - iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus)); - cfg->virt = NULL; - } + list_for_each_entry(cfg, &pci_mmcfg_list, list) + pci_mmcfg_arch_unmap(cfg); +} + +int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg) +{ + cfg->virt = mcfg_ioremap(cfg); + if (!cfg->virt) { + printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n", + &cfg->res); + return -ENOMEM; + } + + return 0; +} + +void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg) +{ + if (cfg && cfg->virt) { + iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus)); + cfg->virt = NULL; } } -- cgit v1.2.3 From 95c5e92f4f691bbaba40bbf3decfc8e13b6ea897 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 22 Jun 2012 14:55:14 +0800 Subject: x86/PCI: prepare pci_mmcfg_check_reserved() to be called at runtime Prepare function pci_mmcfg_check_reserved() to be called at runtime for PCI host bridge hot-plugging Reviewed-by: Yinghai Lu Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/mmconfig-shared.c | 104 +++++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 36 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 0ac97d54bcac..15a7abf5139c 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -27,6 +27,7 @@ /* Indicate if the mmcfg resources have been placed into the resource table. */ static int __initdata pci_mmcfg_resources_inserted; +static bool pci_mmcfg_running_state; static DEFINE_MUTEX(pci_mmcfg_lock); LIST_HEAD(pci_mmcfg_list); @@ -375,14 +376,15 @@ static void __init pci_mmcfg_insert_resources(void) struct pci_mmcfg_region *cfg; list_for_each_entry(cfg, &pci_mmcfg_list, list) - insert_resource(&iomem_resource, &cfg->res); + if (!cfg->res.parent) + insert_resource(&iomem_resource, &cfg->res); /* Mark that the resources have been inserted. */ pci_mmcfg_resources_inserted = 1; } -static acpi_status __init check_mcfg_resource(struct acpi_resource *res, - void *data) +static acpi_status __devinit check_mcfg_resource(struct acpi_resource *res, + void *data) { struct resource *mcfg_res = data; struct acpi_resource_address64 address; @@ -418,8 +420,8 @@ static acpi_status __init check_mcfg_resource(struct acpi_resource *res, return AE_OK; } -static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl, - void *context, void **rv) +static acpi_status __devinit find_mboard_resource(acpi_handle handle, u32 lvl, + void *context, void **rv) { struct resource *mcfg_res = context; @@ -432,7 +434,7 @@ static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl, return AE_OK; } -static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used) +static int __devinit is_acpi_reserved(u64 start, u64 end, unsigned not_used) { struct resource mcfg_res; @@ -451,13 +453,15 @@ static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used) typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type); -static int __init is_mmconf_reserved(check_reserved_t is_reserved, - struct pci_mmcfg_region *cfg, int with_e820) +static int __ref is_mmconf_reserved(check_reserved_t is_reserved, + struct pci_mmcfg_region *cfg, + struct device *dev, int with_e820) { u64 addr = cfg->res.start; u64 size = resource_size(&cfg->res); u64 old_size = size; - int valid = 0, num_buses; + int num_buses; + char *method = with_e820 ? "E820" : "ACPI motherboard resources"; while (!is_reserved(addr, addr + size, E820_RESERVED)) { size >>= 1; @@ -465,49 +469,75 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved, break; } - if (size >= (16UL<<20) || size == old_size) { - printk(KERN_INFO PREFIX "MMCONFIG at %pR reserved in %s\n", - &cfg->res, - with_e820 ? "E820" : "ACPI motherboard resources"); - valid = 1; - - if (old_size != size) { - /* update end_bus */ - cfg->end_bus = cfg->start_bus + ((size>>20) - 1); - num_buses = cfg->end_bus - cfg->start_bus + 1; - cfg->res.end = cfg->res.start + - PCI_MMCFG_BUS_OFFSET(num_buses) - 1; - snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN, - "PCI MMCONFIG %04x [bus %02x-%02x]", - cfg->segment, cfg->start_bus, cfg->end_bus); + if (size < (16UL<<20) && size != old_size) + return 0; + + if (dev) + dev_info(dev, "MMCONFIG at %pR reserved in %s\n", + &cfg->res, method); + else + printk(KERN_INFO PREFIX + "MMCONFIG at %pR reserved in %s\n", + &cfg->res, method); + + if (old_size != size) { + /* update end_bus */ + cfg->end_bus = cfg->start_bus + ((size>>20) - 1); + num_buses = cfg->end_bus - cfg->start_bus + 1; + cfg->res.end = cfg->res.start + + PCI_MMCFG_BUS_OFFSET(num_buses) - 1; + snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN, + "PCI MMCONFIG %04x [bus %02x-%02x]", + cfg->segment, cfg->start_bus, cfg->end_bus); + + if (dev) + dev_info(dev, + "MMCONFIG " + "at %pR (base %#lx) (size reduced!)\n", + &cfg->res, (unsigned long) cfg->address); + else printk(KERN_INFO PREFIX - "MMCONFIG for %04x [bus%02x-%02x] " - "at %pR (base %#lx) (size reduced!)\n", - cfg->segment, cfg->start_bus, cfg->end_bus, - &cfg->res, (unsigned long) cfg->address); - } + "MMCONFIG for %04x [bus%02x-%02x] " + "at %pR (base %#lx) (size reduced!)\n", + cfg->segment, cfg->start_bus, cfg->end_bus, + &cfg->res, (unsigned long) cfg->address); } - return valid; + return 1; } -static int __devinit pci_mmcfg_check_reserved(struct pci_mmcfg_region *cfg, - int early) +static int __ref pci_mmcfg_check_reserved(struct device *dev, + struct pci_mmcfg_region *cfg, int early) { if (!early && !acpi_disabled) { - if (is_mmconf_reserved(is_acpi_reserved, cfg, 0)) + if (is_mmconf_reserved(is_acpi_reserved, cfg, dev, 0)) return 1; + + if (dev) + dev_info(dev, FW_INFO + "MMCONFIG at %pR not reserved in " + "ACPI motherboard resources\n", + &cfg->res); else - printk(KERN_ERR FW_BUG PREFIX + printk(KERN_INFO FW_INFO PREFIX "MMCONFIG at %pR not reserved in " "ACPI motherboard resources\n", &cfg->res); } + /* + * e820_all_mapped() is marked as __init. + * All entries from ACPI MCFG table have been checked at boot time. + * For MCFG information constructed from hotpluggable host bridge's + * _CBA method, just assume it's reserved. + */ + if (pci_mmcfg_running_state) + return 1; + /* Don't try to do this check unless configuration type 1 is available. how about type 2 ?*/ if (raw_pci_ops) - return is_mmconf_reserved(e820_all_mapped, cfg, 1); + return is_mmconf_reserved(e820_all_mapped, cfg, dev, 1); return 0; } @@ -517,7 +547,7 @@ static void __init pci_mmcfg_reject_broken(int early) struct pci_mmcfg_region *cfg; list_for_each_entry(cfg, &pci_mmcfg_list, list) { - if (pci_mmcfg_check_reserved(cfg, early) == 0) { + if (pci_mmcfg_check_reserved(NULL, cfg, early) == 0) { printk(KERN_INFO PREFIX "not using MMCONFIG\n"); free_all_mmcfg(); return; @@ -656,6 +686,8 @@ void __init pci_mmcfg_late_init(void) static int __init pci_mmcfg_late_insert_resources(void) { + pci_mmcfg_running_state = true; + /* * If resources are already inserted or we are not using MMCONFIG, * don't insert the resources. -- cgit v1.2.3 From 9c95111b330d2ddf851444528a7608f267cbb50c Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 22 Jun 2012 14:55:15 +0800 Subject: x86/PCI: add pci_mmconfig_insert()/delete() for PCI root bridge hotplug Introduce pci_mmconfig_insert()/pci_mmconfig_delete(), which will be used to update MMCONFIG information when supporting PCI root bridge hotplug. Reviewed-by: Yinghai Lu Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/x86/include/asm/pci_x86.h | 4 ++ arch/x86/pci/mmconfig-shared.c | 109 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 109 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index df898ceab4d4..af5018f3d7c3 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h @@ -137,6 +137,10 @@ extern int __init pci_mmcfg_arch_init(void); extern void __init pci_mmcfg_arch_free(void); extern int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg); extern void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg); +extern int __devinit pci_mmconfig_insert(struct device *dev, + u16 seg, u8 start, + u8 end, phys_addr_t addr); +extern int pci_mmconfig_delete(u16 seg, u8 start, u8 end); extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus); extern struct list_head pci_mmcfg_list; diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 15a7abf5139c..19fc42b9f823 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -28,6 +28,7 @@ /* Indicate if the mmcfg resources have been placed into the resource table. */ static int __initdata pci_mmcfg_resources_inserted; static bool pci_mmcfg_running_state; +static bool pci_mmcfg_arch_init_failed; static DEFINE_MUTEX(pci_mmcfg_lock); LIST_HEAD(pci_mmcfg_list); @@ -92,10 +93,6 @@ static __devinit struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, "PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end); res->name = new->name; - printk(KERN_INFO PREFIX "MMCONFIG for domain %04x [bus %02x-%02x] at " - "%pR (base %#lx)\n", segment, start, end, &new->res, - (unsigned long) addr); - return new; } @@ -109,6 +106,11 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start, mutex_lock(&pci_mmcfg_lock); list_add_sorted(new); mutex_unlock(&pci_mmcfg_lock); + + printk(KERN_INFO PREFIX + "MMCONFIG for domain %04x [bus %02x-%02x] at %pR " + "(base %#lx)\n", + segment, start, end, &new->res, (unsigned long)addr); } return new; @@ -671,6 +673,7 @@ static void __init __pci_mmcfg_init(int early) * the architecture mmcfg setup could not initialize. */ pci_mmcfg_resources_inserted = 1; + pci_mmcfg_arch_init_failed = true; } } @@ -713,3 +716,101 @@ static int __init pci_mmcfg_late_insert_resources(void) * with other system resources. */ late_initcall(pci_mmcfg_late_insert_resources); + +/* Add MMCFG information for host bridges */ +int __devinit pci_mmconfig_insert(struct device *dev, + u16 seg, u8 start, u8 end, + phys_addr_t addr) +{ + int rc; + struct resource *tmp = NULL; + struct pci_mmcfg_region *cfg; + + if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed) + return -ENODEV; + + if (start > end) + return -EINVAL; + + mutex_lock(&pci_mmcfg_lock); + cfg = pci_mmconfig_lookup(seg, start); + if (cfg) { + if (cfg->end_bus < end) + dev_info(dev, FW_INFO + "MMCONFIG for " + "domain %04x [bus %02x-%02x] " + "only partially covers this bridge\n", + cfg->segment, cfg->start_bus, cfg->end_bus); + mutex_unlock(&pci_mmcfg_lock); + return -EEXIST; + } + + if (!addr) { + mutex_unlock(&pci_mmcfg_lock); + return -EINVAL; + } + + rc = -EBUSY; + cfg = pci_mmconfig_alloc(seg, start, end, addr); + if (cfg == NULL) { + dev_warn(dev, "fail to add MMCONFIG (out of memory)\n"); + rc = -ENOMEM; + } else if (!pci_mmcfg_check_reserved(dev, cfg, 0)) { + dev_warn(dev, FW_BUG "MMCONFIG %pR isn't reserved\n", + &cfg->res); + } else { + /* Insert resource if it's not in boot stage */ + if (pci_mmcfg_running_state) + tmp = insert_resource_conflict(&iomem_resource, + &cfg->res); + + if (tmp) { + dev_warn(dev, + "MMCONFIG %pR conflicts with " + "%s %pR\n", + &cfg->res, tmp->name, tmp); + } else if (pci_mmcfg_arch_map(cfg)) { + dev_warn(dev, "fail to map MMCONFIG %pR.\n", + &cfg->res); + } else { + list_add_sorted(cfg); + dev_info(dev, "MMCONFIG at %pR (base %#lx)\n", + &cfg->res, (unsigned long)addr); + cfg = NULL; + rc = 0; + } + } + + if (cfg) { + if (cfg->res.parent) + release_resource(&cfg->res); + kfree(cfg); + } + + mutex_unlock(&pci_mmcfg_lock); + + return rc; +} + +/* Delete MMCFG information for host bridges */ +int pci_mmconfig_delete(u16 seg, u8 start, u8 end) +{ + struct pci_mmcfg_region *cfg; + + mutex_lock(&pci_mmcfg_lock); + list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list) + if (cfg->segment == seg && cfg->start_bus == start && + cfg->end_bus == end) { + list_del_rcu(&cfg->list); + synchronize_rcu(); + pci_mmcfg_arch_unmap(cfg); + if (cfg->res.parent) + release_resource(&cfg->res); + mutex_unlock(&pci_mmcfg_lock); + kfree(cfg); + return 0; + } + mutex_unlock(&pci_mmcfg_lock); + + return -ENOENT; +} -- cgit v1.2.3 From c0fa40784cce9cc66b54499a3762cfe07e35353f Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 22 Jun 2012 14:55:17 +0800 Subject: x86/PCI: update MMCONFIG information when hot-plugging PCI host bridges This patch enhances x86 arch-specific code to update MMCONFIG information when PCI host bridge hotplug event happens. Reviewed-by: Yinghai Lu Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/x86/include/asm/pci_x86.h | 1 + arch/x86/pci/acpi.c | 93 ++++++++++++++++++++++++++++++++++++++++-- arch/x86/pci/mmconfig_32.c | 2 +- arch/x86/pci/mmconfig_64.c | 2 +- 4 files changed, 93 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index af5018f3d7c3..b2652e95b3d7 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h @@ -100,6 +100,7 @@ struct pci_raw_ops { extern const struct pci_raw_ops *raw_pci_ops; extern const struct pci_raw_ops *raw_pci_ext_ops; +extern const struct pci_raw_ops pci_mmcfg; extern const struct pci_raw_ops pci_direct_conf1; extern bool port_cf9_safe; diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 2bb885afe103..912b54b26d6a 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -13,6 +13,12 @@ struct pci_root_info { unsigned int res_num; struct resource *res; struct pci_sysdata sd; +#ifdef CONFIG_PCI_MMCONFIG + bool mcfg_added; + u16 segment; + u8 start_bus; + u8 end_bus; +#endif }; static bool pci_use_crs = true; @@ -119,6 +125,81 @@ void __init pci_acpi_crs_quirks(void) pci_use_crs ? "nocrs" : "use_crs"); } +#ifdef CONFIG_PCI_MMCONFIG +static int __devinit check_segment(u16 seg, struct device *dev, char *estr) +{ + if (seg) { + dev_err(dev, + "%s can't access PCI configuration " + "space under this host bridge.\n", + estr); + return -EIO; + } + + /* + * Failure in adding MMCFG information is not fatal, + * just can't access extended configuration space of + * devices under this host bridge. + */ + dev_warn(dev, + "%s can't access extended PCI configuration " + "space under this bridge.\n", + estr); + + return 0; +} + +static int __devinit setup_mcfg_map(struct pci_root_info *info, + u16 seg, u8 start, u8 end, + phys_addr_t addr) +{ + int result; + struct device *dev = &info->bridge->dev; + + info->start_bus = start; + info->end_bus = end; + info->mcfg_added = false; + + /* return success if MMCFG is not in use */ + if (raw_pci_ext_ops && raw_pci_ext_ops != &pci_mmcfg) + return 0; + + if (!(pci_probe & PCI_PROBE_MMCONF)) + return check_segment(seg, dev, "MMCONFIG is disabled,"); + + result = pci_mmconfig_insert(dev, seg, start, end, addr); + if (result == 0) { + /* enable MMCFG if it hasn't been enabled yet */ + if (raw_pci_ext_ops == NULL) + raw_pci_ext_ops = &pci_mmcfg; + info->mcfg_added = true; + } else if (result != -EEXIST) + return check_segment(seg, dev, + "fail to add MMCONFIG information,"); + + return 0; +} + +static void teardown_mcfg_map(struct pci_root_info *info) +{ + if (info->mcfg_added) { + pci_mmconfig_delete(info->segment, info->start_bus, + info->end_bus); + info->mcfg_added = false; + } +} +#else +static int __devinit setup_mcfg_map(struct pci_root_info *info, + u16 seg, u8 start, u8 end, + phys_addr_t addr) +{ + return 0; +} +static void teardown_mcfg_map(struct pci_root_info *info) +{ +} +#endif + static acpi_status resource_to_addr(struct acpi_resource *resource, struct acpi_resource_address64 *addr) @@ -331,8 +412,11 @@ static void __release_pci_root_info(struct pci_root_info *info) free_pci_root_info_res(info); + teardown_mcfg_map(info); + kfree(info); } + static void release_pci_root_info(struct pci_host_bridge *bridge) { struct pci_root_info *info = bridge->release_data; @@ -372,7 +456,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) int domain = root->segment; int busnum = root->secondary.start; LIST_HEAD(resources); - struct pci_bus *bus; + struct pci_bus *bus = NULL; struct pci_sysdata *sd; int node; #ifdef CONFIG_ACPI_NUMA @@ -438,8 +522,11 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) x86_pci_root_bus_resources(busnum, &resources); } - bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd, - &resources); + if (!setup_mcfg_map(info, domain, (u8)root->secondary.start, + (u8)root->secondary.end, root->mcfg_addr)) + bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, + sd, &resources); + if (bus) { pci_scan_child_bus(bus); pci_set_host_bridge_release( diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c index a22785deb50e..db63ac23e3d9 100644 --- a/arch/x86/pci/mmconfig_32.c +++ b/arch/x86/pci/mmconfig_32.c @@ -126,7 +126,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, return 0; } -static const struct pci_raw_ops pci_mmcfg = { +const struct pci_raw_ops pci_mmcfg = { .read = pci_mmcfg_read, .write = pci_mmcfg_write, }; diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c index ebefea5107a7..c206521fe98e 100644 --- a/arch/x86/pci/mmconfig_64.c +++ b/arch/x86/pci/mmconfig_64.c @@ -90,7 +90,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, return 0; } -static const struct pci_raw_ops pci_mmcfg = { +const struct pci_raw_ops pci_mmcfg = { .read = pci_mmcfg_read, .write = pci_mmcfg_write, }; -- cgit v1.2.3 From 66e8850a2a34e6c52105d92a0f0054b304cb7140 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 22 Jun 2012 14:55:18 +0800 Subject: x86/PCI: simplify pci_mmcfg_late_insert_resources() Reduce redundant code to simplify pci_mmcfg_late_insert_resources(). Reviewed-by: Yinghai Lu Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/mmconfig-shared.c | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 19fc42b9f823..332fabdeff43 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -26,7 +26,6 @@ #define PREFIX "PCI: " /* Indicate if the mmcfg resources have been placed into the resource table. */ -static int __initdata pci_mmcfg_resources_inserted; static bool pci_mmcfg_running_state; static bool pci_mmcfg_arch_init_failed; static DEFINE_MUTEX(pci_mmcfg_lock); @@ -373,18 +372,6 @@ static int __init pci_mmcfg_check_hostbridge(void) return !list_empty(&pci_mmcfg_list); } -static void __init pci_mmcfg_insert_resources(void) -{ - struct pci_mmcfg_region *cfg; - - list_for_each_entry(cfg, &pci_mmcfg_list, list) - if (!cfg->res.parent) - insert_resource(&iomem_resource, &cfg->res); - - /* Mark that the resources have been inserted. */ - pci_mmcfg_resources_inserted = 1; -} - static acpi_status __devinit check_mcfg_resource(struct acpi_resource *res, void *data) { @@ -668,11 +655,7 @@ static void __init __pci_mmcfg_init(int early) if (pci_mmcfg_arch_init()) pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; else { - /* - * Signal not to attempt to insert mmcfg resources because - * the architecture mmcfg setup could not initialize. - */ - pci_mmcfg_resources_inserted = 1; + free_all_mmcfg(); pci_mmcfg_arch_init_failed = true; } } @@ -689,15 +672,12 @@ void __init pci_mmcfg_late_init(void) static int __init pci_mmcfg_late_insert_resources(void) { + struct pci_mmcfg_region *cfg; + pci_mmcfg_running_state = true; - /* - * If resources are already inserted or we are not using MMCONFIG, - * don't insert the resources. - */ - if ((pci_mmcfg_resources_inserted == 1) || - (pci_probe & PCI_PROBE_MMCONF) == 0 || - list_empty(&pci_mmcfg_list)) + /* If we are not using MMCONFIG, don't insert the resources. */ + if ((pci_probe & PCI_PROBE_MMCONF) == 0) return 1; /* @@ -705,7 +685,9 @@ static int __init pci_mmcfg_late_insert_resources(void) * marked so it won't cause request errors when __request_region is * called. */ - pci_mmcfg_insert_resources(); + list_for_each_entry(cfg, &pci_mmcfg_list, list) + if (!cfg->res.parent) + insert_resource(&iomem_resource, &cfg->res); return 0; } -- cgit v1.2.3 From 8503562fd4e8e261bd7ca442705c6e8f0fd88228 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 22 Jun 2012 14:55:19 +0800 Subject: x86/PCI: get rid of redundant log messages For each resource of a PCI host bridge, the arch code and PCI code log following messages. We don't need both, so drop the arch-specific printing. pci_root PNP0A08:00: host bridge window [io 0x0000-0x03af] pci_bus 0000:00: root bus resource [io 0x0000-0x03af] Reviewed-by: Yinghai Lu Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/acpi.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 912b54b26d6a..505acdd6d600 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -314,13 +314,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data) } info->res_num++; - if (addr.translation_offset) - dev_info(&info->bridge->dev, "host bridge window %pR " - "(PCI address [%#llx-%#llx])\n", - res, res->start - addr.translation_offset, - res->end - addr.translation_offset); - else - dev_info(&info->bridge->dev, "host bridge window %pR\n", res); return AE_OK; } -- cgit v1.2.3 From 574a59414083df3911e5a1514742959b412b6947 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 22 Jun 2012 14:55:20 +0800 Subject: x86/PCI: refine __pci_mmcfg_init() for better code readability Refine __pci_mmcfg_init() for better code readability. Reviewed-by: Yinghai Lu Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/mmconfig-shared.c | 46 +++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 332fabdeff43..ffe72b9d6869 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -544,8 +544,6 @@ static void __init pci_mmcfg_reject_broken(int early) } } -static int __initdata known_bridge; - static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg, struct acpi_mcfg_allocation *cfg) { @@ -617,28 +615,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header) static void __init __pci_mmcfg_init(int early) { - /* MMCONFIG disabled */ - if ((pci_probe & PCI_PROBE_MMCONF) == 0) - return; - - /* MMCONFIG already enabled */ - if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF)) - return; - - /* for late to exit */ - if (known_bridge) - return; - - if (early) { - if (pci_mmcfg_check_hostbridge()) - known_bridge = 1; - } - - if (!known_bridge) - acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); - pci_mmcfg_reject_broken(early); - if (list_empty(&pci_mmcfg_list)) return; @@ -660,14 +637,33 @@ static void __init __pci_mmcfg_init(int early) } } +static int __initdata known_bridge; + void __init pci_mmcfg_early_init(void) { - __pci_mmcfg_init(1); + if (pci_probe & PCI_PROBE_MMCONF) { + if (pci_mmcfg_check_hostbridge()) + known_bridge = 1; + else + acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); + __pci_mmcfg_init(1); + } } void __init pci_mmcfg_late_init(void) { - __pci_mmcfg_init(0); + /* MMCONFIG disabled */ + if ((pci_probe & PCI_PROBE_MMCONF) == 0) + return; + + if (known_bridge) + return; + + /* MMCONFIG hasn't been enabled yet, try again */ + if (pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF) { + acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); + __pci_mmcfg_init(0); + } } static int __init pci_mmcfg_late_insert_resources(void) -- cgit v1.2.3 From 24c97f04c4570e02c5cf4b97c73ab9dc27bacdbe Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 22 Jun 2012 14:55:22 +0800 Subject: x86/PCI: use pr_level() to replace printk(KERN_LEVEL) Script checkpatch.pl recommends to replace printk(KERN_LVL) with pr_lvl(), so do it. Reviewed-by: Yinghai Lu Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/mmconfig-shared.c | 21 +++++++++------------ arch/x86/pci/mmconfig_64.c | 3 +-- 2 files changed, 10 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index ffe72b9d6869..937bcece7006 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -106,7 +106,7 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start, list_add_sorted(new); mutex_unlock(&pci_mmcfg_lock); - printk(KERN_INFO PREFIX + pr_info(PREFIX "MMCONFIG for domain %04x [bus %02x-%02x] at %pR " "(base %#lx)\n", segment, start, end, &new->res, (unsigned long)addr); @@ -362,8 +362,7 @@ static int __init pci_mmcfg_check_hostbridge(void) name = pci_mmcfg_probes[i].probe(); if (name) - printk(KERN_INFO PREFIX "%s with MMCONFIG support\n", - name); + pr_info(PREFIX "%s with MMCONFIG support\n", name); } /* some end_bus_number is crazy, fix it */ @@ -465,8 +464,7 @@ static int __ref is_mmconf_reserved(check_reserved_t is_reserved, dev_info(dev, "MMCONFIG at %pR reserved in %s\n", &cfg->res, method); else - printk(KERN_INFO PREFIX - "MMCONFIG at %pR reserved in %s\n", + pr_info(PREFIX "MMCONFIG at %pR reserved in %s\n", &cfg->res, method); if (old_size != size) { @@ -485,7 +483,7 @@ static int __ref is_mmconf_reserved(check_reserved_t is_reserved, "at %pR (base %#lx) (size reduced!)\n", &cfg->res, (unsigned long) cfg->address); else - printk(KERN_INFO PREFIX + pr_info(PREFIX "MMCONFIG for %04x [bus%02x-%02x] " "at %pR (base %#lx) (size reduced!)\n", cfg->segment, cfg->start_bus, cfg->end_bus, @@ -508,7 +506,7 @@ static int __ref pci_mmcfg_check_reserved(struct device *dev, "ACPI motherboard resources\n", &cfg->res); else - printk(KERN_INFO FW_INFO PREFIX + pr_info(FW_INFO PREFIX "MMCONFIG at %pR not reserved in " "ACPI motherboard resources\n", &cfg->res); @@ -537,7 +535,7 @@ static void __init pci_mmcfg_reject_broken(int early) list_for_each_entry(cfg, &pci_mmcfg_list, list) { if (pci_mmcfg_check_reserved(NULL, cfg, early) == 0) { - printk(KERN_INFO PREFIX "not using MMCONFIG\n"); + pr_info(PREFIX "not using MMCONFIG\n"); free_all_mmcfg(); return; } @@ -562,7 +560,7 @@ static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg, return 0; } - printk(KERN_ERR PREFIX "MCFG region for %04x [bus %02x-%02x] at %#llx " + pr_err(PREFIX "MCFG region for %04x [bus %02x-%02x] at %#llx " "is above 4GB, ignored\n", cfg->pci_segment, cfg->start_bus_number, cfg->end_bus_number, cfg->address); return -EINVAL; @@ -589,7 +587,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header) i -= sizeof(struct acpi_mcfg_allocation); }; if (entries == 0) { - printk(KERN_ERR PREFIX "MMCONFIG has no entries\n"); + pr_err(PREFIX "MMCONFIG has no entries\n"); return -ENODEV; } @@ -603,8 +601,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header) if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number, cfg->end_bus_number, cfg->address) == NULL) { - printk(KERN_WARNING PREFIX - "no memory for MCFG entries\n"); + pr_warn(PREFIX "no memory for MCFG entries\n"); free_all_mmcfg(); return -ENOMEM; } diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c index c206521fe98e..d4ebd07c306d 100644 --- a/arch/x86/pci/mmconfig_64.c +++ b/arch/x86/pci/mmconfig_64.c @@ -137,8 +137,7 @@ int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg) { cfg->virt = mcfg_ioremap(cfg); if (!cfg->virt) { - printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n", - &cfg->res); + pr_err(PREFIX "can't map MMCONFIG at %pR\n", &cfg->res); return -ENOMEM; } -- cgit v1.2.3 From 9973290ce20ace7cac8ad06f753468c0b826fd0f Mon Sep 17 00:00:00 2001 From: David Brown Date: Wed, 20 Jun 2012 22:52:24 +0100 Subject: ARM: 7428/1: Prevent KALLSYM size mismatch on ARM. ARM builds seem to be plagued by an occasional build error: Inconsistent kallsyms data This is a bug - please report about it Try "make KALLSYMS_EXTRA_PASS=1" as a workaround The problem has to do with alignment of some sections by the linker. The kallsyms data is built in two passes by first linking the kernel without it, and then linking the kernel again with the symbols included. Normally, this just shifts the symbols, without changing their order, and the compression used by the kallsyms gives the same result. On non SMP, the per CPU data is empty. Depending on the where the alignment ends up, it can come out as either: +-------------------+ | last text segment | +-------------------+ /* padding */ +-------------------+ <- L1_CACHE_BYTES alignemnt | per cpu (empty) | +-------------------+ __per_cpu_end: /* padding */ __data_loc: +-------------------+ <- THREAD_SIZE alignment | data | +-------------------+ or +-------------------+ | last text segment | +-------------------+ /* padding */ +-------------------+ <- L1_CACHE_BYTES alignemnt | per cpu (empty) | +-------------------+ __per_cpu_end: /* no padding */ __data_loc: +-------------------+ <- THREAD_SIZE alignment | data | +-------------------+ if the alignment satisfies both. Because symbols that have the same address are sorted by 'nm -n', the second case will be in a different order than the first case. This changes the compression, changing the size of the kallsym data, causing the build failure. The KALLSYMS_EXTRA_PASS=1 workaround usually works, but it is still possible to have the alignment change between the second and third pass. It's probably even possible for it to never reach a fixedpoint. The problem only occurs on non-SMP, when the per-cpu data is empty, and when the data segment has alignment (and immediately follows the text segments). Fix this by only including the per_cpu section on SMP, when it is not empty. Signed-off-by: David Brown Signed-off-by: Russell King --- arch/arm/kernel/vmlinux.lds.S | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 43a31fb06318..36ff15bbfdd4 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -183,7 +183,9 @@ SECTIONS } #endif +#ifdef CONFIG_SMP PERCPU_SECTION(L1_CACHE_BYTES) +#endif #ifdef CONFIG_XIP_KERNEL __data_loc = ALIGN(4); /* location in binary */ -- cgit v1.2.3 From 86f887c105b909a2cea7b06f2136d66b3438b038 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Sat, 23 Jun 2012 01:12:09 +0200 Subject: ARM: shmobile: r8a7779: Route all interrupts to ARM Without this, the interrupts for I2C, VIN, GPIO, SDHC, HSCIF and HPB-DMAC are sent to the SH processor. Signed-off-by: Phil Edworthy Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/intc-r8a7779.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c index 550b23df4fd4..f04fad4ec4fb 100644 --- a/arch/arm/mach-shmobile/intc-r8a7779.c +++ b/arch/arm/mach-shmobile/intc-r8a7779.c @@ -35,6 +35,9 @@ #define INT2SMSKCR3 0xfe7822ac #define INT2SMSKCR4 0xfe7822b0 +#define INT2NTSR0 0xfe700060 +#define INT2NTSR1 0xfe700064 + static int r8a7779_set_wake(struct irq_data *data, unsigned int on) { return 0; /* always allow wakeup */ @@ -49,6 +52,10 @@ void __init r8a7779_init_irq(void) gic_init(0, 29, gic_dist_base, gic_cpu_base); gic_arch_extn.irq_set_wake = r8a7779_set_wake; + /* route all interrupts to ARM */ + __raw_writel(0xffffffff, INT2NTSR0); + __raw_writel(0x3fffffff, INT2NTSR1); + /* unmask all known interrupts in INTCS2 */ __raw_writel(0xfffffff0, INT2SMSKCR0); __raw_writel(0xfff7ffff, INT2SMSKCR1); -- cgit v1.2.3 From 8497f696686ae1ab3f01e5956046d59844b9f500 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Sat, 23 Jun 2012 10:23:50 +0800 Subject: PCI: do not call pci_set_power_state with PCI_D3cold PCI subsystem has not been ready for D3cold support yet. So PCI_D3cold should not be used as parameter for pci_set_power_state. This patch is needed for upcoming PCI_D3cold support. This patch has no functionality change, because pci_set_power_state will bound the parameter to PCI_D3hot too. CC: Michal Miroslaw CC: Jesse Barnes Reviewed-by: Rafael J. Wysocki Signed-off-by: Huang Ying Signed-off-by: Bjorn Helgaas --- arch/x86/pci/mrst.c | 2 +- drivers/misc/cb710/core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c index 140942f66b31..e14a2ff708b5 100644 --- a/arch/x86/pci/mrst.c +++ b/arch/x86/pci/mrst.c @@ -264,7 +264,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_d3delay_fixup); static void __devinit mrst_power_off_unused_dev(struct pci_dev *dev) { - pci_set_power_state(dev, PCI_D3cold); + pci_set_power_state(dev, PCI_D3hot); } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0801, mrst_power_off_unused_dev); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0809, mrst_power_off_unused_dev); diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c index 85cc7710193c..9d5eed754666 100644 --- a/drivers/misc/cb710/core.c +++ b/drivers/misc/cb710/core.c @@ -180,7 +180,7 @@ static int cb710_suspend(struct pci_dev *pdev, pm_message_t state) pci_save_state(pdev); pci_disable_device(pdev); if (state.event & PM_EVENT_SLEEP) - pci_set_power_state(pdev, PCI_D3cold); + pci_set_power_state(pdev, PCI_D3hot); return 0; } -- cgit v1.2.3 From b5e12229a4850ae9b19ee5252508749da8844b3c Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 22 Jun 2012 20:57:57 +0200 Subject: ARM: Orion5x - Restore parts of io.h, with rework Commit 4d5fc58dbe34b78157c05b319669bb3e064ba8bd (ARM: remove bunch of now unused mach/io.h files) removed the orion5x io.h. Unfortunately, this is still needed for the definition of IO_SPACE_LIMIT which overrides the default 64K. All Orion based systems have 1Mbyte of IO space per PCI[e] bus, and try to request_resource() this size. Orion5x has two such PCI buses. It is likely that the original, removed version, was broken. This version might be less broken. However, it has not been tested on hardware with a PCI card, let alone hardware with a PCI card with IO capabilities. Signed-off-by: Andrew Lunn Acked-by: Rob Herring Signed-off-by: Olof Johansson --- arch/arm/Kconfig | 1 + arch/arm/mach-orion5x/include/mach/io.h | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 arch/arm/mach-orion5x/include/mach/io.h (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b1b27525b24d..a91009c61870 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -589,6 +589,7 @@ config ARCH_ORION5X select PCI select ARCH_REQUIRE_GPIOLIB select GENERIC_CLOCKEVENTS + select NEED_MACH_IO_H select PLAT_ORION help Support for the following Marvell Orion 5x series SoCs: diff --git a/arch/arm/mach-orion5x/include/mach/io.h b/arch/arm/mach-orion5x/include/mach/io.h new file mode 100644 index 000000000000..1aa5d0a50a0b --- /dev/null +++ b/arch/arm/mach-orion5x/include/mach/io.h @@ -0,0 +1,22 @@ +/* + * arch/arm/mach-orion5x/include/mach/io.h + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ASM_ARCH_IO_H +#define __ASM_ARCH_IO_H + +#include +#include + +#define IO_SPACE_LIMIT SZ_2M +static inline void __iomem *__io(unsigned long addr) +{ + return (void __iomem *)(addr + ORION5X_PCIE_IO_VIRT_BASE); +} + +#define __io(a) __io(a) +#endif -- cgit v1.2.3 From 5fb2ce119c113e5c987fa81ed89e73b2653e28e4 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 22 Jun 2012 08:54:01 +0200 Subject: ARM: Kirkwood: clk_register_gate_fn: add fn assignment In commit: 98d9986 ARM: Kirkwood: Replace clock gating the kirkwood clock gating has been reworked. A custom variant of clock gating, that calls a custom function before gating the clock off, has been introduced. However in clk_register_gate_fn() this custom function "fn" is never assigned. This patch adds the missing fn assignment. Cc: stable Signed-off-by: Marc Kleine-Budde Tested-by: Andrew Lunn Acked-by: Andrew Lunn Signed-off-by: Olof Johansson --- arch/arm/mach-kirkwood/common.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index e1d2c6def5e6..f261cd242643 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -159,6 +159,7 @@ static struct clk __init *clk_register_gate_fn(struct device *dev, gate_fn->gate.flags = clk_gate_flags; gate_fn->gate.lock = lock; gate_fn->gate.hw.init = &init; + gate_fn->fn = fn; /* ops is the gate ops, but with our disable function */ if (clk_gate_fn_ops.disable != clk_gate_fn_disable) { -- cgit v1.2.3 From 0fa1f0609a0c1fe8b2be3c0089a2cb48f7fda521 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 22 Jun 2012 08:54:02 +0200 Subject: ARM: Orion: Fix Virtual/Physical mixup with watchdog The orion watchdog is expecting to be passed the physcial address of the hardware, and will ioremap() it to give a virtual address it will use as the base address for the hardware. However, when creating the platform resource record, a virtual address was being used. Add the necassary #define's so we can pass the physical address as expected. Tested on Kirkwood and Orion5x. Cc: stable Signed-off-by: Andrew Lunn Signed-off-by: Olof Johansson --- arch/arm/mach-kirkwood/include/mach/bridge-regs.h | 1 + arch/arm/mach-kirkwood/include/mach/kirkwood.h | 1 + arch/arm/mach-orion5x/include/mach/bridge-regs.h | 2 +- arch/arm/mach-orion5x/include/mach/orion5x.h | 1 + arch/arm/plat-orion/common.c | 2 +- 5 files changed, 5 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h index 3eee37a3b501..a115142f8690 100644 --- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h +++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h @@ -38,6 +38,7 @@ #define IRQ_MASK_HIGH_OFF 0x0014 #define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300) +#define TIMER_PHYS_BASE (BRIDGE_PHYS_BASE | 0x0300) #define L2_CONFIG_REG (BRIDGE_VIRT_BASE | 0x0128) #define L2_WRITETHROUGH 0x00000010 diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h index fede3d503efa..c5b68510776b 100644 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h @@ -80,6 +80,7 @@ #define UART1_VIRT_BASE (DEV_BUS_VIRT_BASE | 0x2100) #define BRIDGE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x20000) +#define BRIDGE_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x20000) #define CRYPTO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x30000) diff --git a/arch/arm/mach-orion5x/include/mach/bridge-regs.h b/arch/arm/mach-orion5x/include/mach/bridge-regs.h index 96484bcd34ca..11a3c1e9801f 100644 --- a/arch/arm/mach-orion5x/include/mach/bridge-regs.h +++ b/arch/arm/mach-orion5x/include/mach/bridge-regs.h @@ -35,5 +35,5 @@ #define MAIN_IRQ_MASK (ORION5X_BRIDGE_VIRT_BASE | 0x204) #define TIMER_VIRT_BASE (ORION5X_BRIDGE_VIRT_BASE | 0x300) - +#define TIMER_PHYS_BASE (ORION5X_BRIDGE_PHYS_BASE | 0x300) #endif diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h index 2745f5d95b3f..683e085ce162 100644 --- a/arch/arm/mach-orion5x/include/mach/orion5x.h +++ b/arch/arm/mach-orion5x/include/mach/orion5x.h @@ -82,6 +82,7 @@ #define UART1_VIRT_BASE (ORION5X_DEV_BUS_VIRT_BASE | 0x2100) #define ORION5X_BRIDGE_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x20000) +#define ORION5X_BRIDGE_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x20000) #define ORION5X_PCI_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x30000) diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c index 61fd837624a8..c1793786aea9 100644 --- a/arch/arm/plat-orion/common.c +++ b/arch/arm/plat-orion/common.c @@ -582,7 +582,7 @@ void __init orion_spi_1_init(unsigned long mapbase) * Watchdog ****************************************************************************/ static struct resource orion_wdt_resource = - DEFINE_RES_MEM(TIMER_VIRT_BASE, 0x28); + DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x28); static struct platform_device orion_wdt_device = { .name = "orion_wdt", -- cgit v1.2.3 From d9b0cde91c60da0ed5f92cdc3ac878142e6b5f27 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 29 May 2012 14:31:23 -0700 Subject: x86-64, gcc: Use -mpreferred-stack-boundary=3 if supported On x86-64, the standard ABI requires alignment to 16 bytes. However, this is not actually necessary in the kernel (we don't do SSE except in very controlled ways); and furthermore, the standard kernel entry on x86-64 actually leaves the stack on an odd 8-byte boundary, which means that gcc will generate extra instructions to keep the stack *mis*aligned! gcc 4.8 adds an -mpreferred-stack-boundary=3 option to override this and lets us save some stack space and a handful of instructions. Note that this causes us to pass -mno-sse twice; this is redundant, but necessary since the cc-option test will fail unless -mno-sse is passed on the same command line. [ hpa: rewrote the patch description ] Signed-off-by: H.J. Lu Link: http://lkml.kernel.org/r/CAMe9rOqPfy3JcZRLaUeCjBe9BVY-P6e0uaSbMi5hvS-6WwQueg@mail.gmail.com Signed-off-by: H. Peter Anvin --- arch/x86/Makefile | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 1f2521434554..b0c5276861ec 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -49,6 +49,9 @@ else KBUILD_AFLAGS += -m64 KBUILD_CFLAGS += -m64 + # Use -mpreferred-stack-boundary=3 if supported. + KBUILD_CFLAGS += $(call cc-option,-mno-sse -mpreferred-stack-boundary=3) + # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu) cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8) cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona) -- cgit v1.2.3 From 02b7d83436ae4b1d86a5df03e72c1c69af7e239d Mon Sep 17 00:00:00 2001 From: Anatol Pomozov Date: Sat, 23 Jun 2012 15:54:34 -0700 Subject: Fix typo in printed messages Coult -> Could Signed-off-by: Linus Torvalds --- arch/sparc/kernel/vio.c | 2 +- drivers/net/wireless/b43/main.c | 2 +- drivers/net/wireless/b43legacy/main.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index 5cffdc55f075..3e244f31e56b 100644 --- a/arch/sparc/kernel/vio.c +++ b/arch/sparc/kernel/vio.c @@ -443,7 +443,7 @@ static int __init vio_init(void) root_vdev = vio_create_one(hp, root, NULL); err = -ENODEV; if (!root_vdev) { - printk(KERN_ERR "VIO: Coult not create root device.\n"); + printk(KERN_ERR "VIO: Could not create root device.\n"); goto out_release; } diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index acd03a4f9730..1b988f26bdf1 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3767,7 +3767,7 @@ static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan) if (prev_status >= B43_STAT_STARTED) { err = b43_wireless_core_start(up_dev); if (err) { - b43err(wl, "Fatal: Coult not start device for " + b43err(wl, "Fatal: Could not start device for " "selected %s-GHz band\n", band_to_string(chan->band)); b43_wireless_core_exit(up_dev); diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index cd9c9bc186d9..eae691e2f7dd 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2633,7 +2633,7 @@ static int b43legacy_switch_phymode(struct b43legacy_wl *wl, if (prev_status >= B43legacy_STAT_STARTED) { err = b43legacy_wireless_core_start(up_dev); if (err) { - b43legacyerr(wl, "Fatal: Coult not start device for " + b43legacyerr(wl, "Fatal: Could not start device for " "newly selected %s-PHY mode\n", phymode_to_string(new_mode)); b43legacy_wireless_core_exit(up_dev); -- cgit v1.2.3 From 19a1d332cc8ca599578111b9ff8cd6963f75c387 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Tue, 12 Jun 2012 13:27:31 +1000 Subject: m68knommu: define a local devm_clk_get() function Commit f4d40de39a23f0c39cca55ac63e1175c69c3d2f7 ("net fec: do not depend on grouped clocks") breaks compilation of the FEC driver for non iMX platforms in linux-3.5-rc1. For example when compiling for ColdFire I get: LD vmlinux drivers/built-in.o: In function `fec_probe': fec.c:(.devinit.text+0x1e0): undefined reference to `devm_clk_get' Define a simple devm_clk_get() function for the m68knommu architecture. Signed-off-by: Greg Ungerer --- arch/m68k/platform/coldfire/clk.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/m68k/platform/coldfire/clk.c b/arch/m68k/platform/coldfire/clk.c index 9f1260c5e2ad..44da406897e5 100644 --- a/arch/m68k/platform/coldfire/clk.c +++ b/arch/m68k/platform/coldfire/clk.c @@ -42,4 +42,11 @@ unsigned long clk_get_rate(struct clk *clk) return MCF_CLK; } EXPORT_SYMBOL(clk_get_rate); + +struct clk *devm_clk_get(struct device *dev, const char *id) +{ + return NULL; +} +EXPORT_SYMBOL(devm_clk_get); + /***************************************************************************/ -- cgit v1.2.3 From 593f47355467b9ef44293698817e2bdb347e2d11 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 21 Jun 2012 11:48:11 +0200 Subject: ARM: dma-mapping: fix buffer chunk allocation order IOMMU-aware dma_alloc_attrs() implementation allocates buffers in power-of-two chunks to improve performance and take advantage of large page mappings provided by some IOMMU hardware. However current code, due to a subtle bug, allocated those chunks in the smallest-to-largest order, what completely killed all the advantages of using larger than page chunks. If a 4KiB chunk has been mapped as a first chunk, the consecutive chunks are not aligned correctly to the power-of-two which match their size and IOMMU drivers were not able to use internal mappings of size other than the 4KiB (largest common denominator of alignment and chunk size). This patch fixes this issue by changing to the correct largest-to-smallest chunk size allocation sequence. Signed-off-by: Marek Szyprowski --- arch/arm/mm/dma-mapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index d766e4256b74..4044abcf6f9d 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1067,7 +1067,7 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t return NULL; while (count) { - int j, order = __ffs(count); + int j, order = __fls(count); pages[i] = alloc_pages(gfp | __GFP_NOWARN, order); while (!pages[i] && order) -- cgit v1.2.3 From 357398e96d8c883b010379a7669df43ed0e2e32b Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 20 Jun 2012 18:39:27 +0200 Subject: perf/x86: Fix section mismatch in uncore_pci_init() Fix section mismatch in uncore_pci_init(): WARNING: vmlinux.o(.init.text+0x9246): Section mismatch in reference from the function uncore_pci_init() to the function .devexit.text:uncore_pci_remove() The function __init uncore_pci_init() references a function __devexit uncore_pci_remove(). [...] Signed-off-by: Robert Richter Cc: Cc: Link: http://lkml.kernel.org/r/20120620163927.GI5046@erda.amd.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel_uncore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 28a8413ca199..6f43f9584e3d 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -1313,7 +1313,7 @@ static int __devinit uncore_pci_add(struct intel_uncore_type *type, return 0; } -static void __devexit uncore_pci_remove(struct pci_dev *pdev) +static void uncore_pci_remove(struct pci_dev *pdev) { struct intel_uncore_box *box = pci_get_drvdata(pdev); struct intel_uncore_pmu *pmu = box->pmu; -- cgit v1.2.3 From 5eadf916dfa04c3c51397dbcb803ce8735bf191a Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 24 Jun 2012 19:24:19 +0300 Subject: KVM: document lapic regs field Signed-off-by: Michael S. Tsirkin Signed-off-by: Avi Kivity --- arch/x86/kvm/lapic.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 6f4ce2575d09..d29da25ea525 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -13,6 +13,11 @@ struct kvm_lapic { u32 divide_count; struct kvm_vcpu *vcpu; bool irr_pending; + /** + * APIC register page. The layout matches the register layout seen by + * the guest 1:1, because it is accessed by the vmx microcode. + * Note: Only one register, the TPR, is used by the microcode. + */ void *regs; gpa_t vapic_addr; struct page *vapic_page; -- cgit v1.2.3 From 8680b94b0e6046af2644c17313287ec0cb5843dc Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 24 Jun 2012 19:24:26 +0300 Subject: KVM: optimize ISR lookups We perform ISR lookups twice: during interrupt injection and on EOI. Typical workloads only have a single bit set there. So we can avoid ISR scans by 1. counting bits as we set/clear them in ISR 2. on set, caching the injected vector number 3. on clear, invalidating the cache The real purpose of this is enabling PV EOI which needs to quickly validate the vector. But non PV guests also benefit: with this patch, and without interrupt nesting, apic_find_highest_isr will always return immediately without scanning ISR. Signed-off-by: Michael S. Tsirkin Signed-off-by: Avi Kivity --- arch/x86/kvm/lapic.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++-- arch/x86/kvm/lapic.h | 4 ++++ 2 files changed, 55 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 93c15743f1ee..805d887784f6 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -107,6 +107,16 @@ static inline void apic_clear_vector(int vec, void *bitmap) clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); } +static inline int __apic_test_and_set_vector(int vec, void *bitmap) +{ + return __test_and_set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); +} + +static inline int __apic_test_and_clear_vector(int vec, void *bitmap) +{ + return __test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); +} + static inline int apic_hw_enabled(struct kvm_lapic *apic) { return (apic)->vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE; @@ -210,6 +220,16 @@ static int find_highest_vector(void *bitmap) return fls(word[word_offset << 2]) - 1 + (word_offset << 5); } +static u8 count_vectors(void *bitmap) +{ + u32 *word = bitmap; + int word_offset; + u8 count = 0; + for (word_offset = 0; word_offset < MAX_APIC_VECTOR >> 5; ++word_offset) + count += hweight32(word[word_offset << 2]); + return count; +} + static inline int apic_test_and_set_irr(int vec, struct kvm_lapic *apic) { apic->irr_pending = true; @@ -242,6 +262,27 @@ static inline void apic_clear_irr(int vec, struct kvm_lapic *apic) apic->irr_pending = true; } +static inline void apic_set_isr(int vec, struct kvm_lapic *apic) +{ + if (!__apic_test_and_set_vector(vec, apic->regs + APIC_ISR)) + ++apic->isr_count; + BUG_ON(apic->isr_count > MAX_APIC_VECTOR); + /* + * ISR (in service register) bit is set when injecting an interrupt. + * The highest vector is injected. Thus the latest bit set matches + * the highest bit in ISR. + */ + apic->highest_isr_cache = vec; +} + +static inline void apic_clear_isr(int vec, struct kvm_lapic *apic) +{ + if (__apic_test_and_clear_vector(vec, apic->regs + APIC_ISR)) + --apic->isr_count; + BUG_ON(apic->isr_count < 0); + apic->highest_isr_cache = -1; +} + int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu) { struct kvm_lapic *apic = vcpu->arch.apic; @@ -273,6 +314,10 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq) static inline int apic_find_highest_isr(struct kvm_lapic *apic) { int result; + if (!apic->isr_count) + return -1; + if (likely(apic->highest_isr_cache != -1)) + return apic->highest_isr_cache; result = find_highest_vector(apic->regs + APIC_ISR); ASSERT(result == -1 || result >= 16); @@ -492,7 +537,7 @@ static void apic_set_eoi(struct kvm_lapic *apic) if (vector == -1) return; - apic_clear_vector(vector, apic->regs + APIC_ISR); + apic_clear_isr(vector, apic); apic_update_ppr(apic); if (!(apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI) && @@ -1081,6 +1126,8 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu) apic_set_reg(apic, APIC_TMR + 0x10 * i, 0); } apic->irr_pending = false; + apic->isr_count = 0; + apic->highest_isr_cache = -1; update_divide_count(apic); atomic_set(&apic->lapic_timer.pending, 0); if (kvm_vcpu_is_bsp(vcpu)) @@ -1248,7 +1295,7 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu) if (vector == -1) return -1; - apic_set_vector(vector, apic->regs + APIC_ISR); + apic_set_isr(vector, apic); apic_update_ppr(apic); apic_clear_irr(vector, apic); return vector; @@ -1267,6 +1314,8 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu) update_divide_count(apic); start_apic_timer(apic); apic->irr_pending = true; + apic->isr_count = count_vectors(apic->regs + APIC_ISR); + apic->highest_isr_cache = -1; kvm_make_request(KVM_REQ_EVENT, vcpu); } diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index d29da25ea525..5ac9e5e2fedd 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -13,6 +13,10 @@ struct kvm_lapic { u32 divide_count; struct kvm_vcpu *vcpu; bool irr_pending; + /* Number of bits set in ISR. */ + s16 isr_count; + /* The highest vector set in ISR; if -1 - invalid, must scan ISR. */ + int highest_isr_cache; /** * APIC register page. The layout matches the register layout seen by * the guest 1:1, because it is accessed by the vmx microcode. -- cgit v1.2.3 From ab9cf4996bb989983e73da894b8dd0239aa2c3c2 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 24 Jun 2012 19:24:34 +0300 Subject: KVM guest: guest side for eoi avoidance The idea is simple: there's a bit, per APIC, in guest memory, that tells the guest that it does not need EOI. Guest tests it using a single est and clear operation - this is necessary so that host can detect interrupt nesting - and if set, it can skip the EOI MSR. I run a simple microbenchmark to show exit reduction (note: for testing, need to apply follow-up patch 'kvm: host side for eoi optimization' + a qemu patch I posted separately, on host): Before: Performance counter stats for 'sleep 1s': 47,357 kvm:kvm_entry [99.98%] 0 kvm:kvm_hypercall [99.98%] 0 kvm:kvm_hv_hypercall [99.98%] 5,001 kvm:kvm_pio [99.98%] 0 kvm:kvm_cpuid [99.98%] 22,124 kvm:kvm_apic [99.98%] 49,849 kvm:kvm_exit [99.98%] 21,115 kvm:kvm_inj_virq [99.98%] 0 kvm:kvm_inj_exception [99.98%] 0 kvm:kvm_page_fault [99.98%] 22,937 kvm:kvm_msr [99.98%] 0 kvm:kvm_cr [99.98%] 0 kvm:kvm_pic_set_irq [99.98%] 0 kvm:kvm_apic_ipi [99.98%] 22,207 kvm:kvm_apic_accept_irq [99.98%] 22,421 kvm:kvm_eoi [99.98%] 0 kvm:kvm_pv_eoi [99.99%] 0 kvm:kvm_nested_vmrun [99.99%] 0 kvm:kvm_nested_intercepts [99.99%] 0 kvm:kvm_nested_vmexit [99.99%] 0 kvm:kvm_nested_vmexit_inject [99.99%] 0 kvm:kvm_nested_intr_vmexit [99.99%] 0 kvm:kvm_invlpga [99.99%] 0 kvm:kvm_skinit [99.99%] 57 kvm:kvm_emulate_insn [99.99%] 0 kvm:vcpu_match_mmio [99.99%] 0 kvm:kvm_userspace_exit [99.99%] 2 kvm:kvm_set_irq [99.99%] 2 kvm:kvm_ioapic_set_irq [99.99%] 23,609 kvm:kvm_msi_set_irq [99.99%] 1 kvm:kvm_ack_irq [99.99%] 131 kvm:kvm_mmio [99.99%] 226 kvm:kvm_fpu [100.00%] 0 kvm:kvm_age_page [100.00%] 0 kvm:kvm_try_async_get_page [100.00%] 0 kvm:kvm_async_pf_doublefault [100.00%] 0 kvm:kvm_async_pf_not_present [100.00%] 0 kvm:kvm_async_pf_ready [100.00%] 0 kvm:kvm_async_pf_completed 1.002100578 seconds time elapsed After: Performance counter stats for 'sleep 1s': 28,354 kvm:kvm_entry [99.98%] 0 kvm:kvm_hypercall [99.98%] 0 kvm:kvm_hv_hypercall [99.98%] 1,347 kvm:kvm_pio [99.98%] 0 kvm:kvm_cpuid [99.98%] 1,931 kvm:kvm_apic [99.98%] 29,595 kvm:kvm_exit [99.98%] 24,884 kvm:kvm_inj_virq [99.98%] 0 kvm:kvm_inj_exception [99.98%] 0 kvm:kvm_page_fault [99.98%] 1,986 kvm:kvm_msr [99.98%] 0 kvm:kvm_cr [99.98%] 0 kvm:kvm_pic_set_irq [99.98%] 0 kvm:kvm_apic_ipi [99.99%] 25,953 kvm:kvm_apic_accept_irq [99.99%] 26,132 kvm:kvm_eoi [99.99%] 26,593 kvm:kvm_pv_eoi [99.99%] 0 kvm:kvm_nested_vmrun [99.99%] 0 kvm:kvm_nested_intercepts [99.99%] 0 kvm:kvm_nested_vmexit [99.99%] 0 kvm:kvm_nested_vmexit_inject [99.99%] 0 kvm:kvm_nested_intr_vmexit [99.99%] 0 kvm:kvm_invlpga [99.99%] 0 kvm:kvm_skinit [99.99%] 284 kvm:kvm_emulate_insn [99.99%] 68 kvm:vcpu_match_mmio [99.99%] 68 kvm:kvm_userspace_exit [99.99%] 2 kvm:kvm_set_irq [99.99%] 2 kvm:kvm_ioapic_set_irq [99.99%] 28,288 kvm:kvm_msi_set_irq [99.99%] 1 kvm:kvm_ack_irq [99.99%] 131 kvm:kvm_mmio [100.00%] 588 kvm:kvm_fpu [100.00%] 0 kvm:kvm_age_page [100.00%] 0 kvm:kvm_try_async_get_page [100.00%] 0 kvm:kvm_async_pf_doublefault [100.00%] 0 kvm:kvm_async_pf_not_present [100.00%] 0 kvm:kvm_async_pf_ready [100.00%] 0 kvm:kvm_async_pf_completed 1.002039622 seconds time elapsed We see that # of exits is almost halved. Signed-off-by: Michael S. Tsirkin Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_para.h | 7 +++++ arch/x86/kernel/kvm.c | 57 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h index 63ab1661d00e..2f7712e08b1e 100644 --- a/arch/x86/include/asm/kvm_para.h +++ b/arch/x86/include/asm/kvm_para.h @@ -22,6 +22,7 @@ #define KVM_FEATURE_CLOCKSOURCE2 3 #define KVM_FEATURE_ASYNC_PF 4 #define KVM_FEATURE_STEAL_TIME 5 +#define KVM_FEATURE_PV_EOI 6 /* The last 8 bits are used to indicate how to interpret the flags field * in pvclock structure. If no bits are set, all flags are ignored. @@ -37,6 +38,7 @@ #define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01 #define MSR_KVM_ASYNC_PF_EN 0x4b564d02 #define MSR_KVM_STEAL_TIME 0x4b564d03 +#define MSR_KVM_PV_EOI_EN 0x4b564d04 struct kvm_steal_time { __u64 steal; @@ -89,6 +91,11 @@ struct kvm_vcpu_pv_apf_data { __u32 enabled; }; +#define KVM_PV_EOI_BIT 0 +#define KVM_PV_EOI_MASK (0x1 << KVM_PV_EOI_BIT) +#define KVM_PV_EOI_ENABLED KVM_PV_EOI_MASK +#define KVM_PV_EOI_DISABLED 0x0 + #ifdef __KERNEL__ #include diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index e554e5ad2fe8..75ab94c75c7a 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -39,6 +39,8 @@ #include #include #include +#include +#include static int kvmapf = 1; @@ -283,6 +285,22 @@ static void kvm_register_steal_time(void) cpu, __pa(st)); } +static DEFINE_PER_CPU(unsigned long, kvm_apic_eoi) = KVM_PV_EOI_DISABLED; + +static void kvm_guest_apic_eoi_write(u32 reg, u32 val) +{ + /** + * This relies on __test_and_clear_bit to modify the memory + * in a way that is atomic with respect to the local CPU. + * The hypervisor only accesses this memory from the local CPU so + * there's no need for lock or memory barriers. + * An optimization barrier is implied in apic write. + */ + if (__test_and_clear_bit(KVM_PV_EOI_BIT, &__get_cpu_var(kvm_apic_eoi))) + return; + apic->write(APIC_EOI, APIC_EOI_ACK); +} + void __cpuinit kvm_guest_cpu_init(void) { if (!kvm_para_available()) @@ -300,11 +318,20 @@ void __cpuinit kvm_guest_cpu_init(void) smp_processor_id()); } + if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) { + unsigned long pa; + /* Size alignment is implied but just to make it explicit. */ + BUILD_BUG_ON(__alignof__(kvm_apic_eoi) < 4); + __get_cpu_var(kvm_apic_eoi) = 0; + pa = __pa(&__get_cpu_var(kvm_apic_eoi)) | KVM_MSR_ENABLED; + wrmsrl(MSR_KVM_PV_EOI_EN, pa); + } + if (has_steal_clock) kvm_register_steal_time(); } -static void kvm_pv_disable_apf(void *unused) +static void kvm_pv_disable_apf(void) { if (!__get_cpu_var(apf_reason).enabled) return; @@ -316,11 +343,23 @@ static void kvm_pv_disable_apf(void *unused) smp_processor_id()); } +static void kvm_pv_guest_cpu_reboot(void *unused) +{ + /* + * We disable PV EOI before we load a new kernel by kexec, + * since MSR_KVM_PV_EOI_EN stores a pointer into old kernel's memory. + * New kernel can re-enable when it boots. + */ + if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) + wrmsrl(MSR_KVM_PV_EOI_EN, 0); + kvm_pv_disable_apf(); +} + static int kvm_pv_reboot_notify(struct notifier_block *nb, unsigned long code, void *unused) { if (code == SYS_RESTART) - on_each_cpu(kvm_pv_disable_apf, NULL, 1); + on_each_cpu(kvm_pv_guest_cpu_reboot, NULL, 1); return NOTIFY_DONE; } @@ -371,7 +410,9 @@ static void __cpuinit kvm_guest_cpu_online(void *dummy) static void kvm_guest_cpu_offline(void *dummy) { kvm_disable_steal_time(); - kvm_pv_disable_apf(NULL); + if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) + wrmsrl(MSR_KVM_PV_EOI_EN, 0); + kvm_pv_disable_apf(); apf_task_wake_all(); } @@ -424,6 +465,16 @@ void __init kvm_guest_init(void) pv_time_ops.steal_clock = kvm_steal_clock; } + if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) { + struct apic **drv; + + for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) { + /* Should happen once for each apic */ + WARN_ON((*drv)->eoi_write == kvm_guest_apic_eoi_write); + (*drv)->eoi_write = kvm_guest_apic_eoi_write; + } + } + #ifdef CONFIG_SMP smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu; register_cpu_notifier(&kvm_cpu_notifier); -- cgit v1.2.3 From d0a69d6321ca759bb8d47803d06ba8571ab42d07 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 24 Jun 2012 19:24:42 +0300 Subject: x86, bitops: note on __test_and_clear_bit atomicity __test_and_clear_bit is actually atomic with respect to the local CPU. Add a note saying that KVM on x86 relies on this behaviour so people don't accidentaly break it. Also warn not to rely on this in portable code. Signed-off-by: Michael S. Tsirkin Signed-off-by: Avi Kivity --- arch/x86/include/asm/bitops.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h index a6983b277220..72f5009deb5a 100644 --- a/arch/x86/include/asm/bitops.h +++ b/arch/x86/include/asm/bitops.h @@ -264,6 +264,13 @@ static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) * This operation is non-atomic and can be reordered. * If two examples of this operation race, one can appear to succeed * but actually fail. You must protect multiple accesses with a lock. + * + * Note: the operation is performed atomically with respect to + * the local CPU, but not other CPUs. Portable code should not + * rely on this behaviour. + * KVM relies on this behaviour on x86 for modifying memory that is also + * accessed from a hypervisor on the same CPU if running in a VM: don't change + * this without also updating arch/x86/kernel/kvm.c */ static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) { -- cgit v1.2.3 From 5cfb1d5a65dd96d2d3a0751a1e4e81dc84c1f08f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 24 Jun 2012 19:24:54 +0300 Subject: KVM: only sync when attention bits set Commit eb0dc6d0368072236dcd086d7fdc17fd3c4574d4 introduced apic attention bitmask but kvm still syncs lapic unconditionally. As that commit suggested and in anticipation of adding more attention bits, only sync lapic if(apic_attention). Signed-off-by: Michael S. Tsirkin Signed-off-by: Avi Kivity --- arch/x86/kvm/x86.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 6ed5983f78ff..c1f870690a64 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5388,7 +5388,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) if (unlikely(vcpu->arch.tsc_always_catchup)) kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu); - kvm_lapic_sync_from_vapic(vcpu); + if (vcpu->arch.apic_attention) + kvm_lapic_sync_from_vapic(vcpu); r = kvm_x86_ops->handle_exit(vcpu); out: -- cgit v1.2.3 From d905c0693514e6f713b207377b67c9972c5d7d49 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 24 Jun 2012 19:25:00 +0300 Subject: KVM: rearrange injection cancelling code Each time we need to cancel injection we invoke same code (cancel_injection callback). Move it towards the end of function using the familiar goto on error pattern. Will make it easier to do more cleanups for PV EOI. Signed-off-by: Michael S. Tsirkin Signed-off-by: Avi Kivity --- arch/x86/kvm/x86.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c1f870690a64..7ea0f611bc89 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5296,8 +5296,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) r = kvm_mmu_reload(vcpu); if (unlikely(r)) { - kvm_x86_ops->cancel_injection(vcpu); - goto out; + goto cancel_injection; } preempt_disable(); @@ -5322,9 +5321,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) smp_wmb(); local_irq_enable(); preempt_enable(); - kvm_x86_ops->cancel_injection(vcpu); r = 1; - goto out; + goto cancel_injection; } srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); @@ -5392,6 +5390,10 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) kvm_lapic_sync_from_vapic(vcpu); r = kvm_x86_ops->handle_exit(vcpu); + return r; + +cancel_injection: + kvm_x86_ops->cancel_injection(vcpu); out: return r; } -- cgit v1.2.3 From ae7a2a3fb6f8b784c2752863f4f1f20c656f76fb Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 24 Jun 2012 19:25:07 +0300 Subject: KVM: host side for eoi optimization Implementation of PV EOI using shared memory. This reduces the number of exits an interrupt causes as much as by half. The idea is simple: there's a bit, per APIC, in guest memory, that tells the guest that it does not need EOI. We set it before injecting an interrupt and clear before injecting a nested one. Guest tests it using a test and clear operation - this is necessary so that host can detect interrupt nesting - and if set, it can skip the EOI MSR. There's a new MSR to set the address of said register in guest memory. Otherwise not much changed: - Guest EOI is not required - Register is tested & ISR is automatically cleared on exit For testing results see description of previous patch 'kvm_para: guest side for eoi avoidance'. Signed-off-by: Michael S. Tsirkin Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_host.h | 12 ++++ arch/x86/kvm/cpuid.c | 1 + arch/x86/kvm/lapic.c | 141 ++++++++++++++++++++++++++++++++++++++-- arch/x86/kvm/lapic.h | 2 + arch/x86/kvm/trace.h | 34 ++++++++++ arch/x86/kvm/x86.c | 7 ++ 6 files changed, 193 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index db7c1f2709a2..24b76474d9de 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -175,6 +175,13 @@ enum { /* apic attention bits */ #define KVM_APIC_CHECK_VAPIC 0 +/* + * The following bit is set with PV-EOI, unset on EOI. + * We detect PV-EOI changes by guest by comparing + * this bit with PV-EOI in guest memory. + * See the implementation in apic_update_pv_eoi. + */ +#define KVM_APIC_PV_EOI_PENDING 1 /* * We don't want allocation failures within the mmu code, so we preallocate @@ -484,6 +491,11 @@ struct kvm_vcpu_arch { u64 length; u64 status; } osvw; + + struct { + u64 msr_val; + struct gfn_to_hva_cache data; + } pv_eoi; }; struct kvm_lpage_info { diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 7df1c6d839fb..61ccbdf3d0ac 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -409,6 +409,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, (1 << KVM_FEATURE_NOP_IO_DELAY) | (1 << KVM_FEATURE_CLOCKSOURCE2) | (1 << KVM_FEATURE_ASYNC_PF) | + (1 << KVM_FEATURE_PV_EOI) | (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT); if (sched_info_on()) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 805d887784f6..ce878788a39f 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -311,6 +311,54 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq) irq->level, irq->trig_mode); } +static int pv_eoi_put_user(struct kvm_vcpu *vcpu, u8 val) +{ + + return kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.pv_eoi.data, &val, + sizeof(val)); +} + +static int pv_eoi_get_user(struct kvm_vcpu *vcpu, u8 *val) +{ + + return kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.pv_eoi.data, val, + sizeof(*val)); +} + +static inline bool pv_eoi_enabled(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.pv_eoi.msr_val & KVM_MSR_ENABLED; +} + +static bool pv_eoi_get_pending(struct kvm_vcpu *vcpu) +{ + u8 val; + if (pv_eoi_get_user(vcpu, &val) < 0) + apic_debug("Can't read EOI MSR value: 0x%llx\n", + (unsigned long long)vcpi->arch.pv_eoi.msr_val); + return val & 0x1; +} + +static void pv_eoi_set_pending(struct kvm_vcpu *vcpu) +{ + if (pv_eoi_put_user(vcpu, KVM_PV_EOI_ENABLED) < 0) { + apic_debug("Can't set EOI MSR value: 0x%llx\n", + (unsigned long long)vcpi->arch.pv_eoi.msr_val); + return; + } + __set_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention); +} + +static void pv_eoi_clr_pending(struct kvm_vcpu *vcpu) +{ + if (pv_eoi_put_user(vcpu, KVM_PV_EOI_DISABLED) < 0) { + apic_debug("Can't clear EOI MSR value: 0x%llx\n", + (unsigned long long)vcpi->arch.pv_eoi.msr_val); + return; + } + __clear_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention); +} + static inline int apic_find_highest_isr(struct kvm_lapic *apic) { int result; @@ -527,15 +575,18 @@ int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2) return vcpu1->arch.apic_arb_prio - vcpu2->arch.apic_arb_prio; } -static void apic_set_eoi(struct kvm_lapic *apic) +static int apic_set_eoi(struct kvm_lapic *apic) { int vector = apic_find_highest_isr(apic); + + trace_kvm_eoi(apic, vector); + /* * Not every write EOI will has corresponding ISR, * one example is when Kernel check timer on setup_IO_APIC */ if (vector == -1) - return; + return vector; apic_clear_isr(vector, apic); apic_update_ppr(apic); @@ -550,6 +601,7 @@ static void apic_set_eoi(struct kvm_lapic *apic) kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode); } kvm_make_request(KVM_REQ_EVENT, apic->vcpu); + return vector; } static void apic_send_ipi(struct kvm_lapic *apic) @@ -1132,6 +1184,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu) atomic_set(&apic->lapic_timer.pending, 0); if (kvm_vcpu_is_bsp(vcpu)) vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP; + vcpu->arch.pv_eoi.msr_val = 0; apic_update_ppr(apic); vcpu->arch.apic_arb_prio = 0; @@ -1332,11 +1385,51 @@ void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) hrtimer_start_expires(timer, HRTIMER_MODE_ABS); } +/* + * apic_sync_pv_eoi_from_guest - called on vmexit or cancel interrupt + * + * Detect whether guest triggered PV EOI since the + * last entry. If yes, set EOI on guests's behalf. + * Clear PV EOI in guest memory in any case. + */ +static void apic_sync_pv_eoi_from_guest(struct kvm_vcpu *vcpu, + struct kvm_lapic *apic) +{ + bool pending; + int vector; + /* + * PV EOI state is derived from KVM_APIC_PV_EOI_PENDING in host + * and KVM_PV_EOI_ENABLED in guest memory as follows: + * + * KVM_APIC_PV_EOI_PENDING is unset: + * -> host disabled PV EOI. + * KVM_APIC_PV_EOI_PENDING is set, KVM_PV_EOI_ENABLED is set: + * -> host enabled PV EOI, guest did not execute EOI yet. + * KVM_APIC_PV_EOI_PENDING is set, KVM_PV_EOI_ENABLED is unset: + * -> host enabled PV EOI, guest executed EOI. + */ + BUG_ON(!pv_eoi_enabled(vcpu)); + pending = pv_eoi_get_pending(vcpu); + /* + * Clear pending bit in any case: it will be set again on vmentry. + * While this might not be ideal from performance point of view, + * this makes sure pv eoi is only enabled when we know it's safe. + */ + pv_eoi_clr_pending(vcpu); + if (pending) + return; + vector = apic_set_eoi(apic); + trace_kvm_pv_eoi(apic, vector); +} + void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu) { u32 data; void *vapic; + if (test_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention)) + apic_sync_pv_eoi_from_guest(vcpu, vcpu->arch.apic); + if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention)) return; @@ -1347,17 +1440,44 @@ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu) apic_set_tpr(vcpu->arch.apic, data & 0xff); } +/* + * apic_sync_pv_eoi_to_guest - called before vmentry + * + * Detect whether it's safe to enable PV EOI and + * if yes do so. + */ +static void apic_sync_pv_eoi_to_guest(struct kvm_vcpu *vcpu, + struct kvm_lapic *apic) +{ + if (!pv_eoi_enabled(vcpu) || + /* IRR set or many bits in ISR: could be nested. */ + apic->irr_pending || + /* Cache not set: could be safe but we don't bother. */ + apic->highest_isr_cache == -1 || + /* Need EOI to update ioapic. */ + kvm_ioapic_handles_vector(vcpu->kvm, apic->highest_isr_cache)) { + /* + * PV EOI was disabled by apic_sync_pv_eoi_from_guest + * so we need not do anything here. + */ + return; + } + + pv_eoi_set_pending(apic->vcpu); +} + void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu) { u32 data, tpr; int max_irr, max_isr; - struct kvm_lapic *apic; + struct kvm_lapic *apic = vcpu->arch.apic; void *vapic; + apic_sync_pv_eoi_to_guest(vcpu, apic); + if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention)) return; - apic = vcpu->arch.apic; tpr = apic_get_reg(apic, APIC_TASKPRI) & 0xff; max_irr = apic_find_highest_irr(apic); if (max_irr < 0) @@ -1443,3 +1563,16 @@ int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data) return 0; } + +int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data) +{ + u64 addr = data & ~KVM_MSR_ENABLED; + if (!IS_ALIGNED(addr, 4)) + return 1; + + vcpu->arch.pv_eoi.msr_val = data; + if (!pv_eoi_enabled(vcpu)) + return 0; + return kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.pv_eoi.data, + addr); +} diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 5ac9e5e2fedd..4af5405ae1e2 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -69,4 +69,6 @@ static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu) { return vcpu->arch.hv_vapic & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE; } + +int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data); #endif diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index 911d2641f14c..851914e207fc 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h @@ -517,6 +517,40 @@ TRACE_EVENT(kvm_apic_accept_irq, __entry->coalesced ? " (coalesced)" : "") ); +TRACE_EVENT(kvm_eoi, + TP_PROTO(struct kvm_lapic *apic, int vector), + TP_ARGS(apic, vector), + + TP_STRUCT__entry( + __field( __u32, apicid ) + __field( int, vector ) + ), + + TP_fast_assign( + __entry->apicid = apic->vcpu->vcpu_id; + __entry->vector = vector; + ), + + TP_printk("apicid %x vector %d", __entry->apicid, __entry->vector) +); + +TRACE_EVENT(kvm_pv_eoi, + TP_PROTO(struct kvm_lapic *apic, int vector), + TP_ARGS(apic, vector), + + TP_STRUCT__entry( + __field( __u32, apicid ) + __field( int, vector ) + ), + + TP_fast_assign( + __entry->apicid = apic->vcpu->vcpu_id; + __entry->vector = vector; + ), + + TP_printk("apicid %x vector %d", __entry->apicid, __entry->vector) +); + /* * Tracepoint for nested VMRUN */ diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 7ea0f611bc89..8eacb2e64560 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -795,6 +795,7 @@ static u32 msrs_to_save[] = { MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW, HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL, HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN, MSR_KVM_STEAL_TIME, + MSR_KVM_PV_EOI_EN, MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, MSR_STAR, #ifdef CONFIG_X86_64 @@ -1653,6 +1654,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu); break; + case MSR_KVM_PV_EOI_EN: + if (kvm_lapic_enable_pv_eoi(vcpu, data)) + return 1; + break; case MSR_IA32_MCG_CTL: case MSR_IA32_MCG_STATUS: @@ -5394,6 +5399,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) cancel_injection: kvm_x86_ops->cancel_injection(vcpu); + if (unlikely(vcpu->arch.apic_attention)) + kvm_lapic_sync_from_vapic(vcpu); out: return r; } -- cgit v1.2.3 From 7d43c2e42cb1e436f97c1763150e4e1122ae0d57 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 30 May 2012 14:19:55 -0600 Subject: iommu: Remove group_mf The iommu=group_mf is really no longer needed with the addition of ACS support in IOMMU drivers creating groups. Most multifunction devices will now be grouped already. If a device has gone to the trouble of exposing ACS, trust that it works. We can use the device specific ACS function for fixing devices we trust individually. This largely reverts bcb71abe. Signed-off-by: Alex Williamson Signed-off-by: Joerg Roedel --- Documentation/kernel-parameters.txt | 1 - arch/ia64/include/asm/iommu.h | 2 -- arch/ia64/kernel/pci-dma.c | 1 - arch/x86/include/asm/iommu.h | 1 - arch/x86/kernel/pci-dma.c | 11 ----------- 5 files changed, 16 deletions(-) (limited to 'arch') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index a92c5ebf373e..d2f4f7acc435 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1134,7 +1134,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. forcesac soft pt [x86, IA-64] - group_mf [x86, IA-64] io7= [HW] IO7 for Marvel based alpha systems diff --git a/arch/ia64/include/asm/iommu.h b/arch/ia64/include/asm/iommu.h index b6a809fa2995..105c93b00b1b 100644 --- a/arch/ia64/include/asm/iommu.h +++ b/arch/ia64/include/asm/iommu.h @@ -11,12 +11,10 @@ extern void no_iommu_init(void); extern int force_iommu, no_iommu; extern int iommu_pass_through; extern int iommu_detected; -extern int iommu_group_mf; #else #define iommu_pass_through (0) #define no_iommu (1) #define iommu_detected (0) -#define iommu_group_mf (0) #endif extern void iommu_dma_init(void); extern void machvec_init(const char *name); diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c index 7cdc89b2483c..1ddcfe5ef353 100644 --- a/arch/ia64/kernel/pci-dma.c +++ b/arch/ia64/kernel/pci-dma.c @@ -32,7 +32,6 @@ int force_iommu __read_mostly; #endif int iommu_pass_through; -int iommu_group_mf; /* Dummy device used for NULL arguments (normally ISA). Better would be probably a smaller DMA mask, but this is bug-to-bug compatible diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h index dffc38ee6255..345c99cef152 100644 --- a/arch/x86/include/asm/iommu.h +++ b/arch/x86/include/asm/iommu.h @@ -5,7 +5,6 @@ extern struct dma_map_ops nommu_dma_ops; extern int force_iommu, no_iommu; extern int iommu_detected; extern int iommu_pass_through; -extern int iommu_group_mf; /* 10 seconds */ #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index c0f420f76cd3..de2b7ad70273 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -45,15 +45,6 @@ int iommu_detected __read_mostly = 0; */ int iommu_pass_through __read_mostly; -/* - * Group multi-function PCI devices into a single device-group for the - * iommu_device_group interface. This tells the iommu driver to pretend - * it cannot distinguish between functions of a device, exposing only one - * group for the device. Useful for disallowing use of individual PCI - * functions from userspace drivers. - */ -int iommu_group_mf __read_mostly; - extern struct iommu_table_entry __iommu_table[], __iommu_table_end[]; /* Dummy device used for NULL arguments (normally ISA). */ @@ -194,8 +185,6 @@ static __init int iommu_setup(char *p) #endif if (!strncmp(p, "pt", 2)) iommu_pass_through = 1; - if (!strncmp(p, "group_mf", 8)) - iommu_group_mf = 1; gart_parse_options(p); -- cgit v1.2.3 From 11cab711f686893f2696a061dfca30454a624784 Mon Sep 17 00:00:00 2001 From: Cliff Wickman Date: Fri, 22 Jun 2012 08:12:12 -0500 Subject: x86/uv: Fix the UV BAU destination timeout period Correct the calculation of a destination timeout period, which is used to distinguish between a destination timeout and the situation where all the target software ack resources are full and a request is returned immediately. The problem is that integer arithmetic was overflowing, yielding a very large result. Without this fix destination timeouts are identified as resource 'plugged' events and an ipi method of resource releasing is unnecessarily employed. Signed-off-by: Cliff Wickman Link: http://lkml.kernel.org/r/20120622131212.GA31884@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/platform/uv/tlb_uv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 59880afa851f..0c48d438cbba 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -1811,8 +1811,8 @@ static int calculate_destination_timeout(void) index = (mmr_image >> BAU_URGENCY_7_SHIFT) & BAU_URGENCY_7_MASK; mmr_image = uv_read_local_mmr(UVH_TRANSACTION_TIMEOUT); mult2 = (mmr_image >> BAU_TRANS_SHIFT) & BAU_TRANS_MASK; - base = timeout_base_ns[index]; - ts_ns = base * mult1 * mult2; + ts_ns = timeout_base_ns[index]; + ts_ns *= (mult1 * mult2); ret = ts_ns / 1000; } else { /* 4 bits 0/1 for 10/80us base, 3 bits of multiplier */ -- cgit v1.2.3 From 26ef85770c765bb8b6b6922f8a413872dd8e3979 Mon Sep 17 00:00:00 2001 From: Cliff Wickman Date: Fri, 22 Jun 2012 08:13:30 -0500 Subject: x86/uv: Implement UV BAU runtime enable and disable control via /proc/sgi_uv/ This patch enables the BAU to be turned on or off dynamically. echo "on" > /proc/sgi_uv/ptc_statistics echo "off" > /proc/sgi_uv/ptc_statistics The system may be booted with or without the nobau option. Whether the system currently has the BAU off can be seen in the /proc file -- normally with the baustats script. Each cpu will have a 1 in the bauoff field if the BAU was turned off, so baustats will give a count of cpus that have it off. Signed-off-by: Cliff Wickman Link: http://lkml.kernel.org/r/20120622131330.GB31884@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/uv/uv_bau.h | 2 ++ arch/x86/platform/uv/tlb_uv.c | 76 ++++++++++++++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index 6149b476d9df..847c00b721b2 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h @@ -520,6 +520,7 @@ struct ptc_stats { unsigned long s_uv2_wars; /* uv2 workaround, perm. busy */ unsigned long s_uv2_wars_hw; /* uv2 workaround, hiwater */ unsigned long s_uv2_war_waits; /* uv2 workaround, long waits */ + unsigned long s_enters; /* entries to the driver */ /* destination statistics */ unsigned long d_alltlb; /* times all tlb's on this cpu were flushed */ @@ -586,6 +587,7 @@ struct bau_control { int timeout_tries; int ipi_attempts; int conseccompletes; + short nobau; int baudisabled; int set_bau_off; short cpu; diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 0c48d438cbba..1492170cbb5a 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -38,6 +38,7 @@ static int timeout_base_ns[] = { static int timeout_us; static int nobau; +static int nobau_perm; static int baudisabled; static spinlock_t disable_lock; static cycles_t congested_cycles; @@ -120,6 +121,40 @@ static DEFINE_PER_CPU(struct ptc_stats, ptcstats); static DEFINE_PER_CPU(struct bau_control, bau_control); static DEFINE_PER_CPU(cpumask_var_t, uv_flush_tlb_mask); +static void +set_bau_on(void) +{ + int cpu; + struct bau_control *bcp; + + if (nobau_perm) { + pr_info("BAU not initialized; cannot be turned on\n"); + return; + } + nobau = 0; + for_each_present_cpu(cpu) { + bcp = &per_cpu(bau_control, cpu); + bcp->nobau = 0; + } + pr_info("BAU turned on\n"); + return; +} + +static void +set_bau_off(void) +{ + int cpu; + struct bau_control *bcp; + + nobau = 1; + for_each_present_cpu(cpu) { + bcp = &per_cpu(bau_control, cpu); + bcp->nobau = 1; + } + pr_info("BAU turned off\n"); + return; +} + /* * Determine the first node on a uvhub. 'Nodes' are used for kernel * memory allocation. @@ -1079,12 +1114,12 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, struct ptc_stats *stat; struct bau_control *bcp; - /* kernel was booted 'nobau' */ - if (nobau) - return cpumask; - bcp = &per_cpu(bau_control, cpu); stat = bcp->statp; + stat->s_enters++; + + if (bcp->nobau) + return cpumask; /* bau was disabled due to slow response */ if (bcp->baudisabled) { @@ -1338,29 +1373,32 @@ static inline unsigned long long usec_2_cycles(unsigned long microsec) static int ptc_seq_show(struct seq_file *file, void *data) { struct ptc_stats *stat; + struct bau_control *bcp; int cpu; cpu = *(loff_t *)data; if (!cpu) { seq_printf(file, - "# cpu sent stime self locals remotes ncpus localhub "); + "# cpu bauoff sent stime self locals remotes ncpus localhub "); seq_printf(file, "remotehub numuvhubs numuvhubs16 numuvhubs8 "); seq_printf(file, "numuvhubs4 numuvhubs2 numuvhubs1 dto snacks retries rok "); seq_printf(file, - "resetp resett giveup sto bz throt swack recv rtime "); + "resetp resett giveup sto bz throt enters swack recv rtime "); seq_printf(file, "all one mult none retry canc nocan reset rcan "); seq_printf(file, "disable enable wars warshw warwaits\n"); } if (cpu < num_possible_cpus() && cpu_online(cpu)) { - stat = &per_cpu(ptcstats, cpu); + bcp = &per_cpu(bau_control, cpu); + stat = bcp->statp; /* source side statistics */ seq_printf(file, - "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ", - cpu, stat->s_requestor, cycles_2_us(stat->s_time), + "cpu %d %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ", + cpu, bcp->nobau, stat->s_requestor, + cycles_2_us(stat->s_time), stat->s_ntargself, stat->s_ntarglocals, stat->s_ntargremotes, stat->s_ntargcpu, stat->s_ntarglocaluvhub, stat->s_ntargremoteuvhub, @@ -1369,11 +1407,11 @@ static int ptc_seq_show(struct seq_file *file, void *data) stat->s_ntarguvhub8, stat->s_ntarguvhub4, stat->s_ntarguvhub2, stat->s_ntarguvhub1, stat->s_dtimeout, stat->s_strongnacks); - seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld ", + seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld %ld ", stat->s_retry_messages, stat->s_retriesok, stat->s_resets_plug, stat->s_resets_timeout, stat->s_giveup, stat->s_stimeout, - stat->s_busy, stat->s_throttles); + stat->s_busy, stat->s_throttles, stat->s_enters); /* destination side statistics */ seq_printf(file, @@ -1438,6 +1476,14 @@ static ssize_t ptc_proc_write(struct file *file, const char __user *user, return -EFAULT; optstr[count - 1] = '\0'; + if (!strcmp(optstr, "on")) { + set_bau_on(); + return count; + } else if (!strcmp(optstr, "off")) { + set_bau_off(); + return count; + } + if (strict_strtol(optstr, 10, &input_arg) < 0) { printk(KERN_DEBUG "%s is invalid\n", optstr); return -EINVAL; @@ -1836,6 +1882,8 @@ static void __init init_per_cpu_tunables(void) for_each_present_cpu(cpu) { bcp = &per_cpu(bau_control, cpu); bcp->baudisabled = 0; + if (nobau) + bcp->nobau = 1; bcp->statp = &per_cpu(ptcstats, cpu); /* time interval to catch a hardware stay-busy bug */ bcp->timeout_interval = usec_2_cycles(2*timeout_us); @@ -2069,9 +2117,6 @@ static int __init uv_bau_init(void) if (!is_uv_system()) return 0; - if (nobau) - return 0; - for_each_possible_cpu(cur_cpu) { mask = &per_cpu(uv_flush_tlb_mask, cur_cpu); zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu)); @@ -2091,7 +2136,8 @@ static int __init uv_bau_init(void) enable_timeouts(); if (init_per_cpu(nuvhubs, uv_base_pnode)) { - nobau = 1; + set_bau_off(); + nobau_perm = 1; return 0; } -- cgit v1.2.3 From 8b6e511e51f7e540c8e71022318ee4cc9a4567a7 Mon Sep 17 00:00:00 2001 From: Cliff Wickman Date: Fri, 22 Jun 2012 08:14:59 -0500 Subject: x86/uv: Work around UV2 BAU hangs On SGI's UV2 the BAU (Broadcast Assist Unit) driver can hang under a heavy load. To cure this: - Disable the UV2 extended status mode (see UV2_EXT_SHFT), as this mode changes BAU behavior in more ways then just delivering an extra bit of status. Revert status to just two meaningful bits, like UV1. - Use no IPI-style resets on UV2. Just give up the request for whatever the reason it failed and let it be accomplished with the legacy IPI method. - Use no alternate sending descriptor (the former UV2 workaround bcp->using_desc and handle_uv2_busy() stuff). Just disable the use of the BAU for a period of time in favor of the legacy IPI method when the h/w bug leaves a descriptor busy. -- new tunable: giveup_limit determines the threshold at which a hub is so plugged that it should do all requests with the legacy IPI method for a period of time -- generalize disable_for_congestion() (renamed disable_for_period()) for use whenever a hub should avoid using the BAU for a period of time Also: - Fix find_another_by_swack(), which is part of the UV2 bug workaround - Correct and clarify the statistics (new stats s_overipilimit, s_giveuplimit, s_enters, s_ipifordisabled, s_plugged, s_congested) Signed-off-by: Cliff Wickman Link: http://lkml.kernel.org/r/20120622131459.GC31884@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/uv/uv_bau.h | 28 ++- arch/x86/platform/uv/tlb_uv.c | 387 ++++++++++++++++++--------------------- 2 files changed, 200 insertions(+), 215 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index 847c00b721b2..a06983cdc125 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h @@ -140,6 +140,9 @@ #define IPI_RESET_LIMIT 1 /* after this # consecutive successes, bump up the throttle if it was lowered */ #define COMPLETE_THRESHOLD 5 +/* after this # of giveups (fall back to kernel IPI's) disable the use of + the BAU for a period of time */ +#define GIVEUP_LIMIT 100 #define UV_LB_SUBNODEID 0x10 @@ -166,7 +169,6 @@ #define FLUSH_RETRY_TIMEOUT 2 #define FLUSH_GIVEUP 3 #define FLUSH_COMPLETE 4 -#define FLUSH_RETRY_BUSYBUG 5 /* * tuning the action when the numalink network is extremely delayed @@ -175,7 +177,7 @@ microseconds */ #define CONGESTED_REPS 10 /* long delays averaged over this many broadcasts */ -#define CONGESTED_PERIOD 30 /* time for the bau to be +#define DISABLED_PERIOD 10 /* time for the bau to be disabled, in seconds */ /* see msg_type: */ #define MSG_NOOP 0 @@ -520,7 +522,12 @@ struct ptc_stats { unsigned long s_uv2_wars; /* uv2 workaround, perm. busy */ unsigned long s_uv2_wars_hw; /* uv2 workaround, hiwater */ unsigned long s_uv2_war_waits; /* uv2 workaround, long waits */ - unsigned long s_enters; /* entries to the driver */ + unsigned long s_overipilimit; /* over the ipi reset limit */ + unsigned long s_giveuplimit; /* disables, over giveup limit*/ + unsigned long s_enters; /* entries to the driver */ + unsigned long s_ipifordisabled; /* fall back to IPI; disabled */ + unsigned long s_plugged; /* plugged by h/w bug*/ + unsigned long s_congested; /* giveup on long wait */ /* destination statistics */ unsigned long d_alltlb; /* times all tlb's on this cpu were flushed */ @@ -588,8 +595,7 @@ struct bau_control { int ipi_attempts; int conseccompletes; short nobau; - int baudisabled; - int set_bau_off; + short baudisabled; short cpu; short osnode; short uvhub_cpu; @@ -598,14 +604,16 @@ struct bau_control { short cpus_in_socket; short cpus_in_uvhub; short partition_base_pnode; - short using_desc; /* an index, like uvhub_cpu */ - unsigned int inuse_map; + short busy; /* all were busy (war) */ unsigned short message_number; unsigned short uvhub_quiesce; short socket_acknowledge_count[DEST_Q_SIZE]; cycles_t send_message; + cycles_t period_end; + cycles_t period_time; spinlock_t uvhub_lock; spinlock_t queue_lock; + spinlock_t disable_lock; /* tunables */ int max_concurr; int max_concurr_const; @@ -616,9 +624,9 @@ struct bau_control { int complete_threshold; int cong_response_us; int cong_reps; - int cong_period; - unsigned long clocks_per_100_usec; - cycles_t period_time; + cycles_t disabled_period; + int period_giveups; + int giveup_limit; long period_requests; struct hub_and_pnode *thp; }; diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 1492170cbb5a..71b5d5a07d7b 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -1,7 +1,7 @@ /* * SGI UltraViolet TLB flush routines. * - * (c) 2008-2011 Cliff Wickman , SGI. + * (c) 2008-2012 Cliff Wickman , SGI. * * This code is released under the GNU General Public License version 2 or * later. @@ -39,8 +39,6 @@ static int timeout_base_ns[] = { static int timeout_us; static int nobau; static int nobau_perm; -static int baudisabled; -static spinlock_t disable_lock; static cycles_t congested_cycles; /* tunables: */ @@ -48,12 +46,13 @@ static int max_concurr = MAX_BAU_CONCURRENT; static int max_concurr_const = MAX_BAU_CONCURRENT; static int plugged_delay = PLUGGED_DELAY; static int plugsb4reset = PLUGSB4RESET; +static int giveup_limit = GIVEUP_LIMIT; static int timeoutsb4reset = TIMEOUTSB4RESET; static int ipi_reset_limit = IPI_RESET_LIMIT; static int complete_threshold = COMPLETE_THRESHOLD; static int congested_respns_us = CONGESTED_RESPONSE_US; static int congested_reps = CONGESTED_REPS; -static int congested_period = CONGESTED_PERIOD; +static int disabled_period = DISABLED_PERIOD; static struct tunables tunables[] = { {&max_concurr, MAX_BAU_CONCURRENT}, /* must be [0] */ @@ -64,7 +63,8 @@ static struct tunables tunables[] = { {&complete_threshold, COMPLETE_THRESHOLD}, {&congested_respns_us, CONGESTED_RESPONSE_US}, {&congested_reps, CONGESTED_REPS}, - {&congested_period, CONGESTED_PERIOD} + {&disabled_period, DISABLED_PERIOD}, + {&giveup_limit, GIVEUP_LIMIT} }; static struct dentry *tunables_dir; @@ -313,7 +313,7 @@ static void bau_process_message(struct msg_desc *mdp, struct bau_control *bcp, * Both sockets dump their completed count total into * the message's count. */ - smaster->socket_acknowledge_count[mdp->msg_slot] = 0; + *sp = 0; asp = (struct atomic_short *)&msg->acknowledge_count; msg_ack_count = atom_asr(socket_ack_count, asp); @@ -526,16 +526,15 @@ static int uv1_wait_completion(struct bau_desc *bau_desc, } /* - * UV2 has an extra bit of status in the ACTIVATION_STATUS_2 register. + * UV2 could have an extra bit of status in the ACTIVATION_STATUS_2 register. + * But not currently used. */ static unsigned long uv2_read_status(unsigned long offset, int rshft, int desc) { unsigned long descriptor_status; - unsigned long descriptor_status2; - descriptor_status = ((read_lmmr(offset) >> rshft) & UV_ACT_STATUS_MASK); - descriptor_status2 = (read_mmr_uv2_status() >> desc) & 0x1UL; - descriptor_status = (descriptor_status << 1) | descriptor_status2; + descriptor_status = + ((read_lmmr(offset) >> rshft) & UV_ACT_STATUS_MASK) << 1; return descriptor_status; } @@ -566,87 +565,11 @@ int normal_busy(struct bau_control *bcp) */ int handle_uv2_busy(struct bau_control *bcp) { - int busy_one = bcp->using_desc; - int normal = bcp->uvhub_cpu; - int selected = -1; - int i; - unsigned long descriptor_status; - unsigned long status; - int mmr_offset; - struct bau_desc *bau_desc_old; - struct bau_desc *bau_desc_new; - struct bau_control *hmaster = bcp->uvhub_master; struct ptc_stats *stat = bcp->statp; - cycles_t ttm; stat->s_uv2_wars++; - spin_lock(&hmaster->uvhub_lock); - /* try for the original first */ - if (busy_one != normal) { - if (!normal_busy(bcp)) - selected = normal; - } - if (selected < 0) { - /* can't use the normal, select an alternate */ - mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_1; - descriptor_status = read_lmmr(mmr_offset); - - /* scan available descriptors 32-63 */ - for (i = 0; i < UV_CPUS_PER_AS; i++) { - if ((hmaster->inuse_map & (1 << i)) == 0) { - status = ((descriptor_status >> - (i * UV_ACT_STATUS_SIZE)) & - UV_ACT_STATUS_MASK) << 1; - if (status != UV2H_DESC_BUSY) { - selected = i + UV_CPUS_PER_AS; - break; - } - } - } - } - - if (busy_one != normal) - /* mark the busy alternate as not in-use */ - hmaster->inuse_map &= ~(1 << (busy_one - UV_CPUS_PER_AS)); - - if (selected >= 0) { - /* switch to the selected descriptor */ - if (selected != normal) { - /* set the selected alternate as in-use */ - hmaster->inuse_map |= - (1 << (selected - UV_CPUS_PER_AS)); - if (selected > stat->s_uv2_wars_hw) - stat->s_uv2_wars_hw = selected; - } - bau_desc_old = bcp->descriptor_base; - bau_desc_old += (ITEMS_PER_DESC * busy_one); - bcp->using_desc = selected; - bau_desc_new = bcp->descriptor_base; - bau_desc_new += (ITEMS_PER_DESC * selected); - *bau_desc_new = *bau_desc_old; - } else { - /* - * All are busy. Wait for the normal one for this cpu to - * free up. - */ - stat->s_uv2_war_waits++; - spin_unlock(&hmaster->uvhub_lock); - ttm = get_cycles(); - do { - cpu_relax(); - } while (normal_busy(bcp)); - spin_lock(&hmaster->uvhub_lock); - /* switch to the original descriptor */ - bcp->using_desc = normal; - bau_desc_old = bcp->descriptor_base; - bau_desc_old += (ITEMS_PER_DESC * bcp->using_desc); - bcp->using_desc = (ITEMS_PER_DESC * normal); - bau_desc_new = bcp->descriptor_base; - bau_desc_new += (ITEMS_PER_DESC * normal); - *bau_desc_new = *bau_desc_old; /* copy the entire descriptor */ - } - spin_unlock(&hmaster->uvhub_lock); - return FLUSH_RETRY_BUSYBUG; + bcp->busy = 1; + return FLUSH_GIVEUP; } static int uv2_wait_completion(struct bau_desc *bau_desc, @@ -655,7 +578,7 @@ static int uv2_wait_completion(struct bau_desc *bau_desc, { unsigned long descriptor_stat; cycles_t ttm; - int desc = bcp->using_desc; + int desc = bcp->uvhub_cpu; long busy_reps = 0; struct ptc_stats *stat = bcp->statp; @@ -663,24 +586,38 @@ static int uv2_wait_completion(struct bau_desc *bau_desc, /* spin on the status MMR, waiting for it to go idle */ while (descriptor_stat != UV2H_DESC_IDLE) { - /* - * Our software ack messages may be blocked because - * there are no swack resources available. As long - * as none of them has timed out hardware will NACK - * our message and its state will stay IDLE. - */ - if ((descriptor_stat == UV2H_DESC_SOURCE_TIMEOUT) || - (descriptor_stat == UV2H_DESC_DEST_PUT_ERR)) { + if ((descriptor_stat == UV2H_DESC_SOURCE_TIMEOUT)) { + /* + * A h/w bug on the destination side may + * have prevented the message being marked + * pending, thus it doesn't get replied to + * and gets continually nacked until it times + * out with a SOURCE_TIMEOUT. + */ stat->s_stimeout++; return FLUSH_GIVEUP; - } else if (descriptor_stat == UV2H_DESC_DEST_STRONG_NACK) { - stat->s_strongnacks++; - bcp->conseccompletes = 0; - return FLUSH_GIVEUP; } else if (descriptor_stat == UV2H_DESC_DEST_TIMEOUT) { + ttm = get_cycles(); + + /* + * Our retries may be blocked by all destination + * swack resources being consumed, and a timeout + * pending. In that case hardware returns the + * ERROR that looks like a destination timeout. + * Without using the extended status we have to + * deduce from the short time that this was a + * strong nack. + */ + if (cycles_2_us(ttm - bcp->send_message) < timeout_us) { + bcp->conseccompletes = 0; + stat->s_plugged++; + /* FLUSH_RETRY_PLUGGED causes hang on boot */ + return FLUSH_GIVEUP; + } stat->s_dtimeout++; bcp->conseccompletes = 0; - return FLUSH_RETRY_TIMEOUT; + /* FLUSH_RETRY_TIMEOUT causes hang on boot */ + return FLUSH_GIVEUP; } else { busy_reps++; if (busy_reps > 1000000) { @@ -688,9 +625,8 @@ static int uv2_wait_completion(struct bau_desc *bau_desc, busy_reps = 0; ttm = get_cycles(); if ((ttm - bcp->send_message) > - (bcp->clocks_per_100_usec)) { + bcp->timeout_interval) return handle_uv2_busy(bcp); - } } /* * descriptor_stat is still BUSY @@ -714,7 +650,7 @@ static int wait_completion(struct bau_desc *bau_desc, { int right_shift; unsigned long mmr_offset; - int desc = bcp->using_desc; + int desc = bcp->uvhub_cpu; if (desc < UV_CPUS_PER_AS) { mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_0; @@ -793,33 +729,31 @@ static void destination_timeout(struct bau_desc *bau_desc, } /* - * Completions are taking a very long time due to a congested numalink - * network. + * Stop all cpus on a uvhub from using the BAU for a period of time. + * This is reversed by check_enable. */ -static void disable_for_congestion(struct bau_control *bcp, - struct ptc_stats *stat) +static void disable_for_period(struct bau_control *bcp, struct ptc_stats *stat) { - /* let only one cpu do this disabling */ - spin_lock(&disable_lock); - - if (!baudisabled && bcp->period_requests && - ((bcp->period_time / bcp->period_requests) > congested_cycles)) { - int tcpu; - struct bau_control *tbcp; - /* it becomes this cpu's job to turn on the use of the - BAU again */ - baudisabled = 1; - bcp->set_bau_off = 1; - bcp->set_bau_on_time = get_cycles(); - bcp->set_bau_on_time += sec_2_cycles(bcp->cong_period); + int tcpu; + struct bau_control *tbcp; + struct bau_control *hmaster; + cycles_t tm1; + + hmaster = bcp->uvhub_master; + spin_lock(&hmaster->disable_lock); + if (!bcp->baudisabled) { stat->s_bau_disabled++; + tm1 = get_cycles(); for_each_present_cpu(tcpu) { tbcp = &per_cpu(bau_control, tcpu); - tbcp->baudisabled = 1; + if (tbcp->uvhub_master == hmaster) { + tbcp->baudisabled = 1; + tbcp->set_bau_on_time = + tm1 + bcp->disabled_period; + } } } - - spin_unlock(&disable_lock); + spin_unlock(&hmaster->disable_lock); } static void count_max_concurr(int stat, struct bau_control *bcp, @@ -850,16 +784,30 @@ static void record_send_stats(cycles_t time1, cycles_t time2, bcp->period_requests++; bcp->period_time += elapsed; if ((elapsed > congested_cycles) && - (bcp->period_requests > bcp->cong_reps)) - disable_for_congestion(bcp, stat); + (bcp->period_requests > bcp->cong_reps) && + ((bcp->period_time / bcp->period_requests) > + congested_cycles)) { + stat->s_congested++; + disable_for_period(bcp, stat); + } } } else stat->s_requestor--; if (completion_status == FLUSH_COMPLETE && try > 1) stat->s_retriesok++; - else if (completion_status == FLUSH_GIVEUP) + else if (completion_status == FLUSH_GIVEUP) { stat->s_giveup++; + if (get_cycles() > bcp->period_end) + bcp->period_giveups = 0; + bcp->period_giveups++; + if (bcp->period_giveups == 1) + bcp->period_end = get_cycles() + bcp->disabled_period; + if (bcp->period_giveups > bcp->giveup_limit) { + disable_for_period(bcp, stat); + stat->s_giveuplimit++; + } + } } /* @@ -903,7 +851,8 @@ static void handle_cmplt(int completion_status, struct bau_desc *bau_desc, * Returns 1 if it gives up entirely and the original cpu mask is to be * returned to the kernel. */ -int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp) +int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp, + struct bau_desc *bau_desc) { int seq_number = 0; int completion_stat = 0; @@ -916,24 +865,23 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp) struct bau_control *hmaster = bcp->uvhub_master; struct uv1_bau_msg_header *uv1_hdr = NULL; struct uv2_bau_msg_header *uv2_hdr = NULL; - struct bau_desc *bau_desc; - if (bcp->uvhub_version == 1) + if (bcp->uvhub_version == 1) { + uv1 = 1; uv1_throttle(hmaster, stat); + } while (hmaster->uvhub_quiesce) cpu_relax(); time1 = get_cycles(); + if (uv1) + uv1_hdr = &bau_desc->header.uv1_hdr; + else + uv2_hdr = &bau_desc->header.uv2_hdr; + do { - bau_desc = bcp->descriptor_base; - bau_desc += (ITEMS_PER_DESC * bcp->using_desc); - if (bcp->uvhub_version == 1) { - uv1 = 1; - uv1_hdr = &bau_desc->header.uv1_hdr; - } else - uv2_hdr = &bau_desc->header.uv2_hdr; - if ((try == 0) || (completion_stat == FLUSH_RETRY_BUSYBUG)) { + if (try == 0) { if (uv1) uv1_hdr->msg_type = MSG_REGULAR; else @@ -951,25 +899,24 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp) uv1_hdr->sequence = seq_number; else uv2_hdr->sequence = seq_number; - index = (1UL << AS_PUSH_SHIFT) | bcp->using_desc; + index = (1UL << AS_PUSH_SHIFT) | bcp->uvhub_cpu; bcp->send_message = get_cycles(); write_mmr_activation(index); try++; completion_stat = wait_completion(bau_desc, bcp, try); - /* UV2: wait_completion() may change the bcp->using_desc */ handle_cmplt(completion_stat, bau_desc, bcp, hmaster, stat); if (bcp->ipi_attempts >= bcp->ipi_reset_limit) { bcp->ipi_attempts = 0; + stat->s_overipilimit++; completion_stat = FLUSH_GIVEUP; break; } cpu_relax(); } while ((completion_stat == FLUSH_RETRY_PLUGGED) || - (completion_stat == FLUSH_RETRY_BUSYBUG) || (completion_stat == FLUSH_RETRY_TIMEOUT)); time2 = get_cycles(); @@ -990,28 +937,33 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp) } /* - * The BAU is disabled. When the disabled time period has expired, the cpu - * that disabled it must re-enable it. - * Return 0 if it is re-enabled for all cpus. + * The BAU is disabled for this uvhub. When the disabled time period has + * expired re-enable it. + * Return 0 if it is re-enabled for all cpus on this uvhub. */ static int check_enable(struct bau_control *bcp, struct ptc_stats *stat) { int tcpu; struct bau_control *tbcp; + struct bau_control *hmaster; - if (bcp->set_bau_off) { - if (get_cycles() >= bcp->set_bau_on_time) { - stat->s_bau_reenabled++; - baudisabled = 0; - for_each_present_cpu(tcpu) { - tbcp = &per_cpu(bau_control, tcpu); + hmaster = bcp->uvhub_master; + spin_lock(&hmaster->disable_lock); + if (bcp->baudisabled && (get_cycles() >= bcp->set_bau_on_time)) { + stat->s_bau_reenabled++; + for_each_present_cpu(tcpu) { + tbcp = &per_cpu(bau_control, tcpu); + if (tbcp->uvhub_master == hmaster) { tbcp->baudisabled = 0; tbcp->period_requests = 0; tbcp->period_time = 0; + tbcp->period_giveups = 0; } - return 0; } + spin_unlock(&hmaster->disable_lock); + return 0; } + spin_unlock(&hmaster->disable_lock); return -1; } @@ -1113,6 +1065,8 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, struct cpumask *flush_mask; struct ptc_stats *stat; struct bau_control *bcp; + unsigned long descriptor_status; + unsigned long status; bcp = &per_cpu(bau_control, cpu); stat = bcp->statp; @@ -1121,10 +1075,22 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, if (bcp->nobau) return cpumask; + if (bcp->busy) { + descriptor_status = + read_lmmr(UVH_LB_BAU_SB_ACTIVATION_STATUS_0); + status = ((descriptor_status >> (bcp->uvhub_cpu * + UV_ACT_STATUS_SIZE)) & UV_ACT_STATUS_MASK) << 1; + if (status == UV2H_DESC_BUSY) + return cpumask; + bcp->busy = 0; + } + /* bau was disabled due to slow response */ if (bcp->baudisabled) { - if (check_enable(bcp, stat)) + if (check_enable(bcp, stat)) { + stat->s_ipifordisabled++; return cpumask; + } } /* @@ -1140,7 +1106,7 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, stat->s_ntargself++; bau_desc = bcp->descriptor_base; - bau_desc += (ITEMS_PER_DESC * bcp->using_desc); + bau_desc += (ITEMS_PER_DESC * bcp->uvhub_cpu); bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE); if (set_distrib_bits(flush_mask, bcp, bau_desc, &locals, &remotes)) return NULL; @@ -1153,25 +1119,27 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, * uv_flush_send_and_wait returns 0 if all cpu's were messaged, * or 1 if it gave up and the original cpumask should be returned. */ - if (!uv_flush_send_and_wait(flush_mask, bcp)) + if (!uv_flush_send_and_wait(flush_mask, bcp, bau_desc)) return NULL; else return cpumask; } /* - * Search the message queue for any 'other' message with the same software - * acknowledge resource bit vector. + * Search the message queue for any 'other' unprocessed message with the + * same software acknowledge resource bit vector as the 'msg' message. */ struct bau_pq_entry *find_another_by_swack(struct bau_pq_entry *msg, - struct bau_control *bcp, unsigned char swack_vec) + struct bau_control *bcp) { struct bau_pq_entry *msg_next = msg + 1; + unsigned char swack_vec = msg->swack_vec; if (msg_next > bcp->queue_last) msg_next = bcp->queue_first; - while ((msg_next->swack_vec != 0) && (msg_next != msg)) { - if (msg_next->swack_vec == swack_vec) + while (msg_next != msg) { + if ((msg_next->canceled == 0) && (msg_next->replied_to == 0) && + (msg_next->swack_vec == swack_vec)) return msg_next; msg_next++; if (msg_next > bcp->queue_last) @@ -1200,32 +1168,30 @@ void process_uv2_message(struct msg_desc *mdp, struct bau_control *bcp) * This message was assigned a swack resource, but no * reserved acknowlegment is pending. * The bug has prevented this message from setting the MMR. - * And no other message has used the same sw_ack resource. - * Do the requested shootdown but do not reply to the msg. - * (the 0 means make no acknowledge) */ - bau_process_message(mdp, bcp, 0); - return; - } - - /* - * Some message has set the MMR 'pending' bit; it might have been - * another message. Look for that message. - */ - other_msg = find_another_by_swack(msg, bcp, msg->swack_vec); - if (other_msg) { - /* There is another. Do not ack the current one. */ - bau_process_message(mdp, bcp, 0); /* - * Let the natural processing of that message acknowledge - * it. Don't get the processing of sw_ack's out of order. + * Some message has set the MMR 'pending' bit; it might have + * been another message. Look for that message. */ - return; + other_msg = find_another_by_swack(msg, bcp); + if (other_msg) { + /* + * There is another. Process this one but do not + * ack it. + */ + bau_process_message(mdp, bcp, 0); + /* + * Let the natural processing of that other message + * acknowledge it. Don't get the processing of sw_ack's + * out of order. + */ + return; + } } /* - * There is no other message using this sw_ack, so it is safe to - * acknowledge it. + * Either the MMR shows this one pending a reply or there is no + * other message using this sw_ack, so it is safe to acknowledge it. */ bau_process_message(mdp, bcp, 1); @@ -1330,7 +1296,8 @@ static void __init enable_timeouts(void) */ mmr_image |= (1L << SOFTACK_MSHIFT); if (is_uv2_hub()) { - mmr_image |= (1L << UV2_EXT_SHFT); + /* hw bug workaround; do not use extended status */ + mmr_image &= ~(1L << UV2_EXT_SHFT); } write_mmr_misc_control(pnode, mmr_image); } @@ -1379,24 +1346,26 @@ static int ptc_seq_show(struct seq_file *file, void *data) cpu = *(loff_t *)data; if (!cpu) { seq_printf(file, - "# cpu bauoff sent stime self locals remotes ncpus localhub "); + "# cpu bauoff sent stime self locals remotes ncpus localhub "); seq_printf(file, "remotehub numuvhubs numuvhubs16 numuvhubs8 "); seq_printf(file, - "numuvhubs4 numuvhubs2 numuvhubs1 dto snacks retries rok "); + "numuvhubs4 numuvhubs2 numuvhubs1 dto snacks retries "); + seq_printf(file, + "rok resetp resett giveup sto bz throt disable "); seq_printf(file, - "resetp resett giveup sto bz throt enters swack recv rtime "); + "enable wars warshw warwaits enters ipidis plugged "); seq_printf(file, - "all one mult none retry canc nocan reset rcan "); + "ipiover glim cong swack recv rtime all one mult "); seq_printf(file, - "disable enable wars warshw warwaits\n"); + "none retry canc nocan reset rcan\n"); } if (cpu < num_possible_cpus() && cpu_online(cpu)) { bcp = &per_cpu(bau_control, cpu); stat = bcp->statp; /* source side statistics */ seq_printf(file, - "cpu %d %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ", + "cpu %d %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ", cpu, bcp->nobau, stat->s_requestor, cycles_2_us(stat->s_time), stat->s_ntargself, stat->s_ntarglocals, @@ -1407,25 +1376,28 @@ static int ptc_seq_show(struct seq_file *file, void *data) stat->s_ntarguvhub8, stat->s_ntarguvhub4, stat->s_ntarguvhub2, stat->s_ntarguvhub1, stat->s_dtimeout, stat->s_strongnacks); - seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld %ld ", + seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld ", stat->s_retry_messages, stat->s_retriesok, stat->s_resets_plug, stat->s_resets_timeout, stat->s_giveup, stat->s_stimeout, - stat->s_busy, stat->s_throttles, stat->s_enters); + stat->s_busy, stat->s_throttles); + seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ", + stat->s_bau_disabled, stat->s_bau_reenabled, + stat->s_uv2_wars, stat->s_uv2_wars_hw, + stat->s_uv2_war_waits, stat->s_enters, + stat->s_ipifordisabled, stat->s_plugged, + stat->s_overipilimit, stat->s_giveuplimit, + stat->s_congested); /* destination side statistics */ seq_printf(file, - "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ", + "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", read_gmmr_sw_ack(uv_cpu_to_pnode(cpu)), stat->d_requestee, cycles_2_us(stat->d_time), stat->d_alltlb, stat->d_onetlb, stat->d_multmsg, stat->d_nomsg, stat->d_retries, stat->d_canceled, stat->d_nocanceled, stat->d_resets, stat->d_rcanceled); - seq_printf(file, "%ld %ld %ld %ld %ld\n", - stat->s_bau_disabled, stat->s_bau_reenabled, - stat->s_uv2_wars, stat->s_uv2_wars_hw, - stat->s_uv2_war_waits); } return 0; } @@ -1439,13 +1411,14 @@ static ssize_t tunables_read(struct file *file, char __user *userbuf, char *buf; int ret; - buf = kasprintf(GFP_KERNEL, "%s %s %s\n%d %d %d %d %d %d %d %d %d\n", - "max_concur plugged_delay plugsb4reset", - "timeoutsb4reset ipi_reset_limit complete_threshold", - "congested_response_us congested_reps congested_period", + buf = kasprintf(GFP_KERNEL, "%s %s %s\n%d %d %d %d %d %d %d %d %d %d\n", + "max_concur plugged_delay plugsb4reset timeoutsb4reset", + "ipi_reset_limit complete_threshold congested_response_us", + "congested_reps disabled_period giveup_limit", max_concurr, plugged_delay, plugsb4reset, timeoutsb4reset, ipi_reset_limit, complete_threshold, - congested_respns_us, congested_reps, congested_period); + congested_respns_us, congested_reps, disabled_period, + giveup_limit); if (!buf) return -ENOMEM; @@ -1616,7 +1589,8 @@ static ssize_t tunables_write(struct file *file, const char __user *user, bcp->complete_threshold = complete_threshold; bcp->cong_response_us = congested_respns_us; bcp->cong_reps = congested_reps; - bcp->cong_period = congested_period; + bcp->disabled_period = sec_2_cycles(disabled_period); + bcp->giveup_limit = giveup_limit; } return count; } @@ -1745,6 +1719,10 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode) * fairness chaining multilevel count replied_to */ } else { + /* + * BIOS uses legacy mode, but UV2 hardware always + * uses native mode for selective broadcasts. + */ uv2_hdr = &bd2->header.uv2_hdr; uv2_hdr->swack_flag = 1; uv2_hdr->base_dest_nasid = @@ -1896,10 +1874,11 @@ static void __init init_per_cpu_tunables(void) bcp->complete_threshold = complete_threshold; bcp->cong_response_us = congested_respns_us; bcp->cong_reps = congested_reps; - bcp->cong_period = congested_period; - bcp->clocks_per_100_usec = usec_2_cycles(100); + bcp->disabled_period = sec_2_cycles(disabled_period); + bcp->giveup_limit = giveup_limit; spin_lock_init(&bcp->queue_lock); spin_lock_init(&bcp->uvhub_lock); + spin_lock_init(&bcp->disable_lock); } } @@ -2020,7 +1999,6 @@ static int scan_sock(struct socket_desc *sdp, struct uvhub_desc *bdp, } bcp->uvhub_master = *hmasterp; bcp->uvhub_cpu = uv_cpu_hub_info(cpu)->blade_processor_id; - bcp->using_desc = bcp->uvhub_cpu; if (bcp->uvhub_cpu >= MAX_CPUS_PER_UVHUB) { printk(KERN_EMERG "%d cpus per uvhub invalid\n", bcp->uvhub_cpu); @@ -2123,7 +2101,6 @@ static int __init uv_bau_init(void) } nuvhubs = uv_num_possible_blades(); - spin_lock_init(&disable_lock); congested_cycles = usec_2_cycles(congested_respns_us); uv_base_pnode = 0x7fffffff; -- cgit v1.2.3 From 4ad33411308596f2f918603509729922a1ec4411 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 22 Jun 2012 10:58:06 -0700 Subject: x86, cpufeature: Rename X86_FEATURE_DTS to X86_FEATURE_DTHERM It makes sense to label "Digital Thermal Sensor" as "DTS", but unfortunately the string "dts" was already used for "Debug Store", and /proc/cpuinfo is a user space ABI. Therefore, rename this to "dtherm". This conflict went into mainline via the hwmon tree without any x86 maintainer ack, and without any kind of hint in the subject. a4659053 x86/hwmon: fix initialization of coretemp Reported-by: Jean Delvare Link: http://lkml.kernel.org/r/4FE34BCB.5050305@linux.intel.com Cc: Jan Beulich Cc: v2.6.36..v3.4 Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/cpufeature.h | 2 +- arch/x86/kernel/cpu/scattered.c | 2 +- drivers/hwmon/coretemp.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 340ee49961a6..f91e80f4f180 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -176,7 +176,7 @@ #define X86_FEATURE_XSAVEOPT (7*32+ 4) /* Optimized Xsave */ #define X86_FEATURE_PLN (7*32+ 5) /* Intel Power Limit Notification */ #define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */ -#define X86_FEATURE_DTS (7*32+ 7) /* Digital Thermal Sensor */ +#define X86_FEATURE_DTHERM (7*32+ 7) /* Digital Thermal Sensor */ #define X86_FEATURE_HW_PSTATE (7*32+ 8) /* AMD HW-PState */ /* Virtualization flags: Linux defined, word 8 */ diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index addf9e82a7f2..ee8e9abc859f 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -31,7 +31,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) const struct cpuid_bit *cb; static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { - { X86_FEATURE_DTS, CR_EAX, 0, 0x00000006, 0 }, + { X86_FEATURE_DTHERM, CR_EAX, 0, 0x00000006, 0 }, { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006, 0 }, { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006, 0 }, { X86_FEATURE_PLN, CR_EAX, 4, 0x00000006, 0 }, diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index b9d512331ed4..0f52799973d4 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -664,7 +664,7 @@ static void __cpuinit get_core_online(unsigned int cpu) * sensors. We check this bit only, all the early CPUs * without thermal sensors will be filtered out. */ - if (!cpu_has(c, X86_FEATURE_DTS)) + if (!cpu_has(c, X86_FEATURE_DTHERM)) return; if (!pdev) { @@ -765,7 +765,7 @@ static struct notifier_block coretemp_cpu_notifier __refdata = { }; static const struct x86_cpu_id coretemp_ids[] = { - { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTS }, + { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM }, {} }; MODULE_DEVICE_TABLE(x86cpu, coretemp_ids); -- cgit v1.2.3 From 55f6cb9d0b364e7e8cb65b51193f5e4743c44fde Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 22 Jun 2012 11:47:15 -0700 Subject: x86, cpufeature: Catch duplicate CPU feature strings We had a case of duplicate CPU feature strings, a user space ABI violation, for almost two years. Make it a build error so that doesn't happen again. Link: http://lkml.kernel.org/r/4FE34BCB.5050305@linux.intel.com Cc: Jan Beulich Cc: Jean Delvare --- arch/x86/kernel/cpu/mkcapflags.pl | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mkcapflags.pl b/arch/x86/kernel/cpu/mkcapflags.pl index dfea390e1608..0c5b54919c7b 100644 --- a/arch/x86/kernel/cpu/mkcapflags.pl +++ b/arch/x86/kernel/cpu/mkcapflags.pl @@ -11,22 +11,35 @@ open(OUT, "> $out\0") or die "$0: cannot create: $out: $!\n"; print OUT "#include \n\n"; print OUT "const char * const x86_cap_flags[NCAPINTS*32] = {\n"; +%features = (); +$err = 0; + while (defined($line = )) { if ($line =~ /^\s*\#\s*define\s+(X86_FEATURE_(\S+))\s+(.*)$/) { $macro = $1; - $feature = $2; + $feature = "\L$2"; $tail = $3; if ($tail =~ /\/\*\s*\"([^"]*)\".*\*\//) { - $feature = $1; + $feature = "\L$1"; } - if ($feature ne '') { - printf OUT "\t%-32s = \"%s\",\n", - "[$macro]", "\L$feature"; + next if ($feature eq ''); + + if ($features{$feature}++) { + print STDERR "$in: duplicate feature name: $feature\n"; + $err++; } + printf OUT "\t%-32s = \"%s\",%s\n", "[$macro]", $feature; } } print OUT "};\n"; close(IN); close(OUT); + +if ($err) { + unlink($out); + exit(1); +} + +exit(0); -- cgit v1.2.3 From 07caba966dee241cd6599618a243be721195de38 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Wed, 30 May 2012 12:18:57 +0200 Subject: ARM: davinci: cp_intc: Add irq domain support Add irq domain support for DaVinci cp_intc. Boot tested on AM18x EVM. Also tested with GPIO IRQ support on AM18x EVM. Signed-off-by: Heiko Schocher Cc: davinci-linux-open-source@linux.davincidsp.com Cc: linux-arm-kernel@lists.infradead.org Cc: devicetree-discuss@lists.ozlabs.org Cc: Grant Likely Cc: Sekhar Nori Cc: Wolfgang Denk Cc: Sergei Shtylyov [nsekhar@ti.com: add commit description, select IRQ_DOMAIN for CP_INTC in Kconfig] Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/Kconfig | 1 + arch/arm/mach-davinci/cp_intc.c | 63 ++++++++++++++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 32d837d8eab9..2ce1ef07c13d 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -4,6 +4,7 @@ config AINTC bool config CP_INTC + select IRQ_DOMAIN bool config ARCH_DAVINCI_DMx diff --git a/arch/arm/mach-davinci/cp_intc.c b/arch/arm/mach-davinci/cp_intc.c index f83152d643c5..45d52567ced7 100644 --- a/arch/arm/mach-davinci/cp_intc.c +++ b/arch/arm/mach-davinci/cp_intc.c @@ -9,8 +9,10 @@ * kind, whether express or implied. */ +#include #include #include +#include #include #include @@ -28,7 +30,7 @@ static inline void cp_intc_write(unsigned long value, unsigned offset) static void cp_intc_ack_irq(struct irq_data *d) { - cp_intc_write(d->irq, CP_INTC_SYS_STAT_IDX_CLR); + cp_intc_write(d->hwirq, CP_INTC_SYS_STAT_IDX_CLR); } /* Disable interrupt */ @@ -36,20 +38,20 @@ static void cp_intc_mask_irq(struct irq_data *d) { /* XXX don't know why we need to disable nIRQ here... */ cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_CLR); - cp_intc_write(d->irq, CP_INTC_SYS_ENABLE_IDX_CLR); + cp_intc_write(d->hwirq, CP_INTC_SYS_ENABLE_IDX_CLR); cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_SET); } /* Enable interrupt */ static void cp_intc_unmask_irq(struct irq_data *d) { - cp_intc_write(d->irq, CP_INTC_SYS_ENABLE_IDX_SET); + cp_intc_write(d->hwirq, CP_INTC_SYS_ENABLE_IDX_SET); } static int cp_intc_set_irq_type(struct irq_data *d, unsigned int flow_type) { - unsigned reg = BIT_WORD(d->irq); - unsigned mask = BIT_MASK(d->irq); + unsigned reg = BIT_WORD(d->hwirq); + unsigned mask = BIT_MASK(d->hwirq); unsigned polarity = cp_intc_read(CP_INTC_SYS_POLARITY(reg)); unsigned type = cp_intc_read(CP_INTC_SYS_TYPE(reg)); @@ -99,18 +101,36 @@ static struct irq_chip cp_intc_irq_chip = { .irq_set_wake = cp_intc_set_wake, }; -void __init cp_intc_init(void) +static struct irq_domain *cp_intc_domain; + +static int cp_intc_host_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + pr_debug("cp_intc_host_map(%d, 0x%lx)\n", virq, hw); + + irq_set_chip(virq, &cp_intc_irq_chip); + set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); + irq_set_handler(virq, handle_edge_irq); + return 0; +} + +static const struct irq_domain_ops cp_intc_host_ops = { + .map = cp_intc_host_map, + .xlate = irq_domain_xlate_onetwocell, +}; + +int __init __cp_intc_init(struct device_node *node) { - unsigned long num_irq = davinci_soc_info.intc_irq_num; + u32 num_irq = davinci_soc_info.intc_irq_num; u8 *irq_prio = davinci_soc_info.intc_irq_prios; u32 *host_map = davinci_soc_info.intc_host_map; unsigned num_reg = BITS_TO_LONGS(num_irq); - int i; + int i, irq_base; davinci_intc_type = DAVINCI_INTC_TYPE_CP_INTC; davinci_intc_base = ioremap(davinci_soc_info.intc_base, SZ_8K); if (WARN_ON(!davinci_intc_base)) - return; + return -EINVAL; cp_intc_write(0, CP_INTC_GLOBAL_ENABLE); @@ -165,13 +185,28 @@ void __init cp_intc_init(void) for (i = 0; host_map[i] != -1; i++) cp_intc_write(host_map[i], CP_INTC_HOST_MAP(i)); - /* Set up genirq dispatching for cp_intc */ - for (i = 0; i < num_irq; i++) { - irq_set_chip(i, &cp_intc_irq_chip); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); - irq_set_handler(i, handle_edge_irq); + irq_base = irq_alloc_descs(-1, 0, num_irq, 0); + if (irq_base < 0) { + pr_warn("Couldn't allocate IRQ numbers\n"); + irq_base = 0; + } + + /* create a legacy host */ + cp_intc_domain = irq_domain_add_legacy(node, num_irq, + irq_base, 0, &cp_intc_host_ops, NULL); + + if (!cp_intc_domain) { + pr_err("cp_intc: failed to allocate irq host!\n"); + return -EINVAL; } /* Enable global interrupt */ cp_intc_write(1, CP_INTC_GLOBAL_ENABLE); + + return 0; +} + +void __init cp_intc_init(void) +{ + __cp_intc_init(NULL); } -- cgit v1.2.3 From 0b5168f92d587c328a4ac060a9f3d1a029ddc3b4 Mon Sep 17 00:00:00 2001 From: Prashant Gaikwad Date: Mon, 25 Jun 2012 13:25:08 +0530 Subject: ARM: tegra: Remove second instance of uart clk In Tegra30 clock file two clk objects were created for same UART clock. Remove the duplicates and add clock aliases instead. Update the Tegra20 clock file to make the names consistent. Signed-off-by: Prashant Gaikwad Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/tegra2_clocks.c | 20 ++++++++++---------- arch/arm/mach-tegra/tegra30_clocks.c | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index b59315ce3691..034d9529b51e 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c @@ -2189,11 +2189,11 @@ static struct clk tegra_list_clks[] = { PERIPH_CLK("i2c2_i2c", "tegra-i2c.1", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), PERIPH_CLK("i2c3_i2c", "tegra-i2c.2", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), PERIPH_CLK("dvc_i2c", "tegra-i2c.3", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), - PERIPH_CLK("uarta", "uart.0", NULL, 6, 0x178, 600000000, mux_pllp_pllc_pllm_clkm, MUX), - PERIPH_CLK("uartb", "uart.1", NULL, 7, 0x17c, 600000000, mux_pllp_pllc_pllm_clkm, MUX), - PERIPH_CLK("uartc", "uart.2", NULL, 55, 0x1a0, 600000000, mux_pllp_pllc_pllm_clkm, MUX), - PERIPH_CLK("uartd", "uart.3", NULL, 65, 0x1c0, 600000000, mux_pllp_pllc_pllm_clkm, MUX), - PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, 600000000, mux_pllp_pllc_pllm_clkm, MUX), + PERIPH_CLK("uarta", "tegra-uart.0", NULL, 6, 0x178, 600000000, mux_pllp_pllc_pllm_clkm, MUX), + PERIPH_CLK("uartb", "tegra-uart.1", NULL, 7, 0x17c, 600000000, mux_pllp_pllc_pllm_clkm, MUX), + PERIPH_CLK("uartc", "tegra-uart.2", NULL, 55, 0x1a0, 600000000, mux_pllp_pllc_pllm_clkm, MUX), + PERIPH_CLK("uartd", "tegra-uart.3", NULL, 65, 0x1c0, 600000000, mux_pllp_pllc_pllm_clkm, MUX), + PERIPH_CLK("uarte", "tegra-uart.4", NULL, 66, 0x1c4, 600000000, mux_pllp_pllc_pllm_clkm, MUX), PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */ PERIPH_CLK("2d", "2d", NULL, 21, 0x15c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ PERIPH_CLK("vi", "tegra_camera", "vi", 20, 0x148, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ @@ -2245,11 +2245,11 @@ static struct clk tegra_list_clks[] = { * table under two names. */ static struct clk_duplicate tegra_clk_duplicates[] = { - CLK_DUPLICATE("uarta", "tegra_uart.0", NULL), - CLK_DUPLICATE("uartb", "tegra_uart.1", NULL), - CLK_DUPLICATE("uartc", "tegra_uart.2", NULL), - CLK_DUPLICATE("uartd", "tegra_uart.3", NULL), - CLK_DUPLICATE("uarte", "tegra_uart.4", NULL), + CLK_DUPLICATE("uarta", "serial8250.0", NULL), + CLK_DUPLICATE("uartb", "serial8250.1", NULL), + CLK_DUPLICATE("uartc", "serial8250.2", NULL), + CLK_DUPLICATE("uartd", "serial8250.3", NULL), + CLK_DUPLICATE("uarte", "serial8250.4", NULL), CLK_DUPLICATE("usbd", "utmip-pad", NULL), CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL), CLK_DUPLICATE("usbd", "tegra-otg", NULL), diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c index e33fe4b14a2a..e1a74895dc3a 100644 --- a/arch/arm/mach-tegra/tegra30_clocks.c +++ b/arch/arm/mach-tegra/tegra30_clocks.c @@ -2924,16 +2924,11 @@ struct clk tegra_list_clks[] = { PERIPH_CLK("i2c3", "tegra-i2c.2", NULL, 67, 0x1b8, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), PERIPH_CLK("i2c4", "tegra-i2c.3", NULL, 103, 0x3c4, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), PERIPH_CLK("i2c5", "tegra-i2c.4", NULL, 47, 0x128, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), - PERIPH_CLK("uarta", "tegra_uart.0", NULL, 6, 0x178, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), - PERIPH_CLK("uartb", "tegra_uart.1", NULL, 7, 0x17c, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), - PERIPH_CLK("uartc", "tegra_uart.2", NULL, 55, 0x1a0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), - PERIPH_CLK("uartd", "tegra_uart.3", NULL, 65, 0x1c0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), - PERIPH_CLK("uarte", "tegra_uart.4", NULL, 66, 0x1c4, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), - PERIPH_CLK("uarta_dbg", "serial8250.0", "uarta", 6, 0x178, 800000000, mux_pllp_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), - PERIPH_CLK("uartb_dbg", "serial8250.0", "uartb", 7, 0x17c, 800000000, mux_pllp_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), - PERIPH_CLK("uartc_dbg", "serial8250.0", "uartc", 55, 0x1a0, 800000000, mux_pllp_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), - PERIPH_CLK("uartd_dbg", "serial8250.0", "uartd", 65, 0x1c0, 800000000, mux_pllp_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), - PERIPH_CLK("uarte_dbg", "serial8250.0", "uarte", 66, 0x1c4, 800000000, mux_pllp_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), + PERIPH_CLK("uarta", "tegra-uart.0", NULL, 6, 0x178, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), + PERIPH_CLK("uartb", "tegra-uart.1", NULL, 7, 0x17c, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), + PERIPH_CLK("uartc", "tegra-uart.2", NULL, 55, 0x1a0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), + PERIPH_CLK("uartd", "tegra-uart.3", NULL, 65, 0x1c0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), + PERIPH_CLK("uarte", "tegra-uart.4", NULL, 66, 0x1c4, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB), PERIPH_CLK_EX("vi", "tegra_camera", "vi", 20, 0x148, 425000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT, &tegra_vi_clk_ops), PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 520000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET), PERIPH_CLK("3d2", "3d2", NULL, 98, 0x3b0, 520000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET), @@ -2983,6 +2978,11 @@ struct clk tegra_list_clks[] = { * table under two names. */ struct clk_duplicate tegra_clk_duplicates[] = { + CLK_DUPLICATE("uarta", "serial8250.0", NULL), + CLK_DUPLICATE("uartb", "serial8250.1", NULL), + CLK_DUPLICATE("uartc", "serial8250.2", NULL), + CLK_DUPLICATE("uartd", "serial8250.3", NULL), + CLK_DUPLICATE("uarte", "serial8250.4", NULL), CLK_DUPLICATE("usbd", "utmip-pad", NULL), CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL), CLK_DUPLICATE("usbd", "tegra-otg", NULL), -- cgit v1.2.3 From e055548953355b6e69c56f9e54388845b29b4e97 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 11 May 2012 16:00:24 -0700 Subject: ARM: OMAP2+: powerdomain: allow pre/post transtion to be per pwrdm Iteration over all power domains in the idle path is unnecessary since only power domains that are transitioning need to be accounted for. Also PRCM register accesses are known to be expensive, so the additional latency added to the idle path is signficiant. In order allow the pre/post transitions to be isolated and called per-pwrdm, change the API so passing in a specific power domain will trigger the pre/post transtion accounting for only that specific power domain. Passing NULL means iterating over all power domains as is current behavior. Reviewed-by: Santosh Shilimkar Tested-by: Santosh Shilimkar Tested-by: Grazvydas Ignotas Acked-by: Paul Walmsley Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 4 ++-- arch/arm/mach-omap2/pm34xx.c | 4 ++-- arch/arm/mach-omap2/powerdomain.c | 16 ++++++++++++---- arch/arm/mach-omap2/powerdomain.h | 4 ++-- 4 files changed, 18 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 13670aa84e58..e35a86bf4e1d 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -255,7 +255,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) return -ENXIO; } - pwrdm_pre_transition(); + pwrdm_pre_transition(NULL); /* * Check MPUSS next state and save interrupt controller if needed. @@ -287,7 +287,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) wakeup_cpu = smp_processor_id(); set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON); - pwrdm_post_transition(); + pwrdm_post_transition(NULL); return 0; } diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index e67d898433fb..0bbbc8c82fd8 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -273,7 +273,7 @@ void omap_sram_idle(void) per_next_state = pwrdm_read_next_pwrst(per_pwrdm); core_next_state = pwrdm_read_next_pwrst(core_pwrdm); - pwrdm_pre_transition(); + pwrdm_pre_transition(NULL); /* PER */ if (per_next_state < PWRDM_POWER_ON) { @@ -338,7 +338,7 @@ void omap_sram_idle(void) } omap3_intc_resume_idle(); - pwrdm_post_transition(); + pwrdm_post_transition(NULL); /* PER */ if (per_next_state < PWRDM_POWER_ON) diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 96114901b932..eefe179045e6 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -981,15 +981,23 @@ int pwrdm_state_switch(struct powerdomain *pwrdm) return ret; } -int pwrdm_pre_transition(void) +int pwrdm_pre_transition(struct powerdomain *pwrdm) { - pwrdm_for_each(_pwrdm_pre_transition_cb, NULL); + if (pwrdm) + _pwrdm_pre_transition_cb(pwrdm, NULL); + else + pwrdm_for_each(_pwrdm_pre_transition_cb, NULL); + return 0; } -int pwrdm_post_transition(void) +int pwrdm_post_transition(struct powerdomain *pwrdm) { - pwrdm_for_each(_pwrdm_post_transition_cb, NULL); + if (pwrdm) + _pwrdm_post_transition_cb(pwrdm, NULL); + else + pwrdm_for_each(_pwrdm_post_transition_cb, NULL); + return 0; } diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 8f88d65c46ea..a6a4604801ad 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -213,8 +213,8 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm); int pwrdm_wait_transition(struct powerdomain *pwrdm); int pwrdm_state_switch(struct powerdomain *pwrdm); -int pwrdm_pre_transition(void); -int pwrdm_post_transition(void); +int pwrdm_pre_transition(struct powerdomain *pwrdm); +int pwrdm_post_transition(struct powerdomain *pwrdm); int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); -- cgit v1.2.3 From 58f0829b7186150318c79515f0e0850c5e7a9c89 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 11 May 2012 15:47:17 -0700 Subject: ARM: OMAP3: PM: call pre/post transition per powerdomain We only need to call the pre/post transtion methods when we know the power state is changing. First, split up the pre/post transition calls to be per-powerdomain, and then make them conditional on whether the power domain is actually changing states. Reviewed-by: Santosh Shilimkar Tested-by: Santosh Shilimkar Tested-by: Grazvydas Ignotas Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/pm34xx.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 0bbbc8c82fd8..dec2d55d7182 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -273,16 +273,21 @@ void omap_sram_idle(void) per_next_state = pwrdm_read_next_pwrst(per_pwrdm); core_next_state = pwrdm_read_next_pwrst(core_pwrdm); - pwrdm_pre_transition(NULL); + if (mpu_next_state < PWRDM_POWER_ON) { + pwrdm_pre_transition(mpu_pwrdm); + pwrdm_pre_transition(neon_pwrdm); + } /* PER */ if (per_next_state < PWRDM_POWER_ON) { + pwrdm_pre_transition(per_pwrdm); per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0; omap2_gpio_prepare_for_idle(per_going_off); } /* CORE */ if (core_next_state < PWRDM_POWER_ON) { + pwrdm_pre_transition(core_pwrdm); if (core_next_state == PWRDM_POWER_OFF) { omap3_core_save_context(); omap3_cm_save_context(); @@ -335,14 +340,20 @@ void omap_sram_idle(void) omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK, OMAP3430_GR_MOD, OMAP3_PRM_VOLTCTRL_OFFSET); + pwrdm_post_transition(core_pwrdm); } omap3_intc_resume_idle(); - pwrdm_post_transition(NULL); - /* PER */ - if (per_next_state < PWRDM_POWER_ON) + if (per_next_state < PWRDM_POWER_ON) { omap2_gpio_resume_after_idle(); + pwrdm_post_transition(per_pwrdm); + } + + if (mpu_next_state < PWRDM_POWER_ON) { + pwrdm_post_transition(mpu_pwrdm); + pwrdm_post_transition(neon_pwrdm); + } clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]); } -- cgit v1.2.3 From 34059a878f5cb20652cbc937f35c925f2b378831 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 19 Jun 2012 09:54:38 -0700 Subject: ARM: OMAP3: PM: cleanup cam_pwrdm leftovers commit e7410cf7 (OMAP3: PM: move device-specific special cases from PM core into CPUidle) moved mangement of cam_pwrdm to CPUidle but left some remnants behind, namely the call to clkcm_allo_idle() for the clockdomains in the MPU pwrdm. Remove these since they are not necessary and cause unwanted latency in the idle path. Acked-by: Tero Kristo Reviewed-by: Santosh Shilimkar Tested-by: Santosh Shilimkar Tested-by: Grazvydas Ignotas Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/pm34xx.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index dec2d55d7182..e63fdd02c6f5 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -70,7 +70,6 @@ void (*omap3_do_wfi_sram)(void); static struct powerdomain *mpu_pwrdm, *neon_pwrdm; static struct powerdomain *core_pwrdm, *per_pwrdm; -static struct powerdomain *cam_pwrdm; static void omap3_core_save_context(void) { @@ -354,8 +353,6 @@ void omap_sram_idle(void) pwrdm_post_transition(mpu_pwrdm); pwrdm_post_transition(neon_pwrdm); } - - clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]); } static void omap3_pm_idle(void) @@ -716,7 +713,6 @@ int __init omap3_pm_init(void) neon_pwrdm = pwrdm_lookup("neon_pwrdm"); per_pwrdm = pwrdm_lookup("per_pwrdm"); core_pwrdm = pwrdm_lookup("core_pwrdm"); - cam_pwrdm = pwrdm_lookup("cam_pwrdm"); neon_clkdm = clkdm_lookup("neon_clkdm"); mpu_clkdm = clkdm_lookup("mpu_clkdm"); -- cgit v1.2.3 From 063a5d011698950c86a01044394105605556e92c Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Fri, 1 Jun 2012 17:11:06 +0200 Subject: ARM: OMAP3: PM: cpuidle: default to C1 in next_valid_state If the next state is no found in the next_valid_state function, fallback to the default value of C1 (which is state 0). This prevents the use of a bogus state -1 in the rest of the cpuidle code. Signed-off-by: Jean Pihet Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/cpuidle34xx.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 207bc1c7759f..f619a928f01e 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -178,7 +178,7 @@ static int next_valid_state(struct cpuidle_device *dev, u32 mpu_deepest_state = PWRDM_POWER_RET; u32 core_deepest_state = PWRDM_POWER_RET; int idx; - int next_index = -1; + int next_index = 0; /* C1 is the default value */ if (enable_off_mode) { mpu_deepest_state = PWRDM_POWER_OFF; @@ -209,12 +209,6 @@ static int next_valid_state(struct cpuidle_device *dev, } } - /* - * C1 is always valid. - * So, no need to check for 'next_index == -1' outside - * this loop. - */ - return next_index; } -- cgit v1.2.3 From 13d65c897e93dfeaed6fe28233559239f9676164 Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Fri, 1 Jun 2012 17:11:07 +0200 Subject: ARM: OMAP3: PM: cpuidle: optimize the PER latency in C1 state One of the main contributors of the low power code latency is the PER power domain. To optimize the high-performance and low-latency C1 state, prevent any PER state which is lower than the CORE state in C1. Reported and suggested by Kevin Hilman. Reported-by: Kevin Hilman Signed-off-by: Jean Pihet Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/cpuidle34xx.c | 41 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index f619a928f01e..2e2f1c6f0f0b 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -222,23 +222,22 @@ static int next_valid_state(struct cpuidle_device *dev, * the device to the specified or a safer state. */ static int omap3_enter_idle_bm(struct cpuidle_device *dev, - struct cpuidle_driver *drv, + struct cpuidle_driver *drv, int index) { int new_state_idx; - u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; + u32 core_next_state, per_next_state = 0, per_saved_state = 0; struct omap3_idle_statedata *cx; int ret; /* - * Prevent idle completely if CAM is active. + * Use only C1 if CAM is active. * CAM does not have wakeup capability in OMAP3. */ - cam_state = pwrdm_read_pwrst(cam_pd); - if (cam_state == PWRDM_POWER_ON) { + if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON) new_state_idx = drv->safe_state_index; - goto select_state; - } + else + new_state_idx = next_valid_state(dev, drv, index); /* * FIXME: we currently manage device-specific idle states @@ -248,24 +247,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, * its own code. */ - /* - * Prevent PER off if CORE is not in retention or off as this - * would disable PER wakeups completely. - */ - cx = &omap3_idle_data[index]; + /* Program PER state */ + cx = &omap3_idle_data[new_state_idx]; core_next_state = cx->core_state; per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); - if ((per_next_state == PWRDM_POWER_OFF) && - (core_next_state > PWRDM_POWER_RET)) - per_next_state = PWRDM_POWER_RET; + if (new_state_idx == 0) { + /* In C1 do not allow PER state lower than CORE state */ + if (per_next_state < core_next_state) + per_next_state = core_next_state; + } else { + /* + * Prevent PER OFF if CORE is not in RETention or OFF as this + * would disable PER wakeups completely. + */ + if ((per_next_state == PWRDM_POWER_OFF) && + (core_next_state > PWRDM_POWER_RET)) + per_next_state = PWRDM_POWER_RET; + } /* Are we changing PER target state? */ if (per_next_state != per_saved_state) pwrdm_set_next_pwrst(per_pd, per_next_state); - new_state_idx = next_valid_state(dev, drv, index); - -select_state: ret = omap3_enter_idle(dev, drv, new_state_idx); /* Restore original PER state if it was modified */ @@ -282,7 +285,7 @@ struct cpuidle_driver omap3_idle_driver = { .owner = THIS_MODULE, .states = { { - .enter = omap3_enter_idle, + .enter = omap3_enter_idle_bm, .exit_latency = 2 + 2, .target_residency = 5, .flags = CPUIDLE_FLAG_TIME_VALID, -- cgit v1.2.3 From 05011f711fc751456972d126bbb8081723629408 Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Fri, 1 Jun 2012 17:11:08 +0200 Subject: ARM: OMAP3: PM: cpuidle: optimize the clkdm idle latency in C1 state For a power domain to idle all the clock domains in it must idle. This patch implements an optimization of the cpuidle code by denying and later allowing only the first registered clock domain of a power domain, and so optimizes the latency of the low power code. The functions _cpuidle_allow_idle and _cpuidle_deny_idle are not used anymore and so are removed. Signed-off-by: Jean Pihet Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/cpuidle34xx.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 2e2f1c6f0f0b..e6ae3fe5cdc6 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -77,20 +77,6 @@ static struct omap3_idle_statedata omap3_idle_data[] = { static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; -static int _cpuidle_allow_idle(struct powerdomain *pwrdm, - struct clockdomain *clkdm) -{ - clkdm_allow_idle(clkdm); - return 0; -} - -static int _cpuidle_deny_idle(struct powerdomain *pwrdm, - struct clockdomain *clkdm) -{ - clkdm_deny_idle(clkdm); - return 0; -} - static int __omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) @@ -108,8 +94,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, /* Deny idle for C1 */ if (index == 0) { - pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); - pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); + clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]); + clkdm_deny_idle(core_pd->pwrdm_clkdms[0]); } /* @@ -131,8 +117,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, /* Re-allow idle for C1 */ if (index == 0) { - pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); - pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); + clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]); + clkdm_allow_idle(core_pd->pwrdm_clkdms[0]); } return_sleep_time: -- cgit v1.2.3 From b955eefc46a6923424cbede2f8ab76c8f5acf056 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 26 Jun 2012 03:14:20 -0700 Subject: ARM: OMAP2: Use hwmod to initialize mmc for 2420 This allows us to pass dma request lines in platform data to MMC driver the same way as we already do for omap2430 and later. Also note that we need to only build this code if MMC_OMAP is selected, so change Makefile accordingly and place it near the MMC_OMAP_HS in the Makefile. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/devices.c | 70 ----------------------------------------- arch/arm/mach-omap2/msdi.c | 73 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 70 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 8cab358603ac..91ef6699df5e 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -27,7 +27,6 @@ #include "iomap.h" #include -#include #include #include #include @@ -603,75 +602,6 @@ static inline void omap_init_aes(void) { } /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) - -static inline void omap242x_mmc_mux(struct omap_mmc_platform_data - *mmc_controller) -{ - if ((mmc_controller->slots[0].switch_pin > 0) && \ - (mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES)) - omap_mux_init_gpio(mmc_controller->slots[0].switch_pin, - OMAP_PIN_INPUT_PULLUP); - if ((mmc_controller->slots[0].gpio_wp > 0) && \ - (mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES)) - omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp, - OMAP_PIN_INPUT_PULLUP); - - omap_mux_init_signal("sdmmc_cmd", 0); - omap_mux_init_signal("sdmmc_clki", 0); - omap_mux_init_signal("sdmmc_clko", 0); - omap_mux_init_signal("sdmmc_dat0", 0); - omap_mux_init_signal("sdmmc_dat_dir0", 0); - omap_mux_init_signal("sdmmc_cmd_dir", 0); - if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) { - omap_mux_init_signal("sdmmc_dat1", 0); - omap_mux_init_signal("sdmmc_dat2", 0); - omap_mux_init_signal("sdmmc_dat3", 0); - omap_mux_init_signal("sdmmc_dat_dir1", 0); - omap_mux_init_signal("sdmmc_dat_dir2", 0); - omap_mux_init_signal("sdmmc_dat_dir3", 0); - } - - /* - * Use internal loop-back in MMC/SDIO Module Input Clock - * selection - */ - if (mmc_controller->slots[0].internal_clock) { - u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - v |= (1 << 24); - omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); - } -} - -void __init omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data) -{ - struct platform_device *pdev; - struct omap_hwmod *oh; - int id = 0; - char *oh_name = "msdi1"; - char *dev_name = "mmci-omap"; - - if (!mmc_data[0]) { - pr_err("%s fails: Incomplete platform data\n", __func__); - return; - } - - omap242x_mmc_mux(mmc_data[0]); - - oh = omap_hwmod_lookup(oh_name); - if (!oh) { - pr_err("Could not look up %s\n", oh_name); - return; - } - pdev = omap_device_build(dev_name, id, oh, mmc_data[0], - sizeof(struct omap_mmc_platform_data), NULL, 0, 0); - if (IS_ERR(pdev)) - WARN(1, "Can'd build omap_device for %s:%s.\n", - dev_name, oh->name); -} - -#endif - #if defined(CONFIG_VIDEO_OMAP2_VOUT) || \ defined(CONFIG_VIDEO_OMAP2_VOUT_MODULE) #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) diff --git a/arch/arm/mach-omap2/msdi.c b/arch/arm/mach-omap2/msdi.c index ef2a6924731a..fb5bc6cf3773 100644 --- a/arch/arm/mach-omap2/msdi.c +++ b/arch/arm/mach-omap2/msdi.c @@ -22,11 +22,15 @@ */ #include +#include #include +#include #include #include "common.h" +#include "control.h" +#include "mux.h" /* * MSDI_CON_OFFSET: offset in bytes of the MSDI IP block's CON register @@ -86,3 +90,72 @@ int omap_msdi_reset(struct omap_hwmod *oh) return 0; } + +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) + +static inline void omap242x_mmc_mux(struct omap_mmc_platform_data + *mmc_controller) +{ + if ((mmc_controller->slots[0].switch_pin > 0) && \ + (mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES)) + omap_mux_init_gpio(mmc_controller->slots[0].switch_pin, + OMAP_PIN_INPUT_PULLUP); + if ((mmc_controller->slots[0].gpio_wp > 0) && \ + (mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES)) + omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp, + OMAP_PIN_INPUT_PULLUP); + + omap_mux_init_signal("sdmmc_cmd", 0); + omap_mux_init_signal("sdmmc_clki", 0); + omap_mux_init_signal("sdmmc_clko", 0); + omap_mux_init_signal("sdmmc_dat0", 0); + omap_mux_init_signal("sdmmc_dat_dir0", 0); + omap_mux_init_signal("sdmmc_cmd_dir", 0); + if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) { + omap_mux_init_signal("sdmmc_dat1", 0); + omap_mux_init_signal("sdmmc_dat2", 0); + omap_mux_init_signal("sdmmc_dat3", 0); + omap_mux_init_signal("sdmmc_dat_dir1", 0); + omap_mux_init_signal("sdmmc_dat_dir2", 0); + omap_mux_init_signal("sdmmc_dat_dir3", 0); + } + + /* + * Use internal loop-back in MMC/SDIO Module Input Clock + * selection + */ + if (mmc_controller->slots[0].internal_clock) { + u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); + v |= (1 << 24); + omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); + } +} + +void __init omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data) +{ + struct platform_device *pdev; + struct omap_hwmod *oh; + int id = 0; + char *oh_name = "msdi1"; + char *dev_name = "mmci-omap"; + + if (!mmc_data[0]) { + pr_err("%s fails: Incomplete platform data\n", __func__); + return; + } + + omap242x_mmc_mux(mmc_data[0]); + + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err("Could not look up %s\n", oh_name); + return; + } + pdev = omap_device_build(dev_name, id, oh, mmc_data[0], + sizeof(struct omap_mmc_platform_data), NULL, 0, 0); + if (IS_ERR(pdev)) + WARN(1, "Can'd build omap_device for %s:%s.\n", + dev_name, oh->name); +} + +#endif -- cgit v1.2.3 From bb44c30e53053c653302b53c8671c3c5ca62e881 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 26 Jun 2012 03:29:57 -0700 Subject: ARM: OMAP2+: nand: fix build error when CONFIG_MTD_ONENAND_OMAP2=n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 8259573b (ARM: OMAP2+: nand: Make board_onenand_init() visible to board code) broke the build for configs with OneNAND disabled. By removing the static in the header file, it created a duplicate definition in the .c and the .h files, resuling in a build error: /work/kernel/omap/dev/arch/arm/mach-omap2/board-flash.c:102:111: error: redefinition of 'board_onenand_init' /work/kernel/omap/dev/arch/arm/mach-omap2/board-flash.h:56:51: note: previous definition of 'board_onenand_init' was here make[2]: *** [arch/arm/mach-omap2/board-flash.o] Error 1 make[2]: *** Waiting for unfinished jobs.... make[1]: *** [arch/arm/mach-omap2] Error 2 make: *** [sub-make] Error 2 Fix this by removing the duplicate dummy entry from the C file. Cc: Enric Balletbò i Serra Cc: Javier Martinez Canillas Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-flash.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 70a81f900bb5..53c39d239d6e 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -97,11 +97,6 @@ __init board_onenand_init(struct mtd_partition *onenand_parts, gpmc_onenand_init(&board_onenand_data); } -#else -void -__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) -{ -} #endif /* CONFIG_MTD_ONENAND_OMAP2 || CONFIG_MTD_ONENAND_OMAP2_MODULE */ #if defined(CONFIG_MTD_NAND_OMAP2) || \ -- cgit v1.2.3 From 9d74c5c0a3194f7a4351c47db09449a2e1d97ec1 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 25 Jun 2012 21:31:10 -0600 Subject: alpha/PCI: factor out pcibios_setup() The PCI core provides a generic pcibios_setup() routine. Drop this architecture-specific version in favor of that. Acked-by: Richard Henderson Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- arch/alpha/kernel/pci.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 1a629636cc16..133d2d445a36 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -198,12 +198,6 @@ pcibios_init(void) subsys_initcall(pcibios_init); -char * __devinit -pcibios_setup(char *str) -{ - return str; -} - #ifdef ALPHA_RESTORE_SRM_SETUP static struct pdev_srm_saved_conf *srm_saved_configs; -- cgit v1.2.3 From 1b6b7c9ff3514772958c075f8c89e42dddf6a4d8 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 26 Jun 2012 07:58:23 -0700 Subject: x86, cpufeature: Remove stray %s, add -w to mkcapflags.pl There was a stray %s left from testing, remove it. Add -w to the #! line (which is parsed by Perl even if the Perl interpreter is invoked explicitly on the command line) to catch these kinds of errors in the future. Reported-by: Jean Delvare Link: http://lkml.kernel.org/r/20120626143246.0c9bf301@endymion.delvare Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/mkcapflags.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mkcapflags.pl b/arch/x86/kernel/cpu/mkcapflags.pl index 0c5b54919c7b..c7b3fe2d72e0 100644 --- a/arch/x86/kernel/cpu/mkcapflags.pl +++ b/arch/x86/kernel/cpu/mkcapflags.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/perl -w # # Generate the x86_cap_flags[] array from include/asm-x86/cpufeature.h # @@ -29,7 +29,7 @@ while (defined($line = )) { print STDERR "$in: duplicate feature name: $feature\n"; $err++; } - printf OUT "\t%-32s = \"%s\",%s\n", "[$macro]", $feature; + printf OUT "\t%-32s = \"%s\",\n", "[$macro]", $feature; } } print OUT "};\n"; -- cgit v1.2.3 From 72d967eda2fd69a6cac01498585bc019ade4f8ff Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 26 Jun 2012 12:48:32 +0530 Subject: ARM: tegra: dma: rename driver name for clock to "tegra-apbdma" Rename the driver name of the clock entry of Tegra APBDMA to tegra-apbdma from of tegra-dma. This name is more aligned towards the movement of dmaengine based new DMA driver. Signed-off-by: Laxman Dewangan Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/dma.c | 2 +- arch/arm/mach-tegra/tegra2_clocks.c | 2 +- arch/arm/mach-tegra/tegra30_clocks.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c index 2698d7d5c9ca..29c5114d607c 100644 --- a/arch/arm/mach-tegra/dma.c +++ b/arch/arm/mach-tegra/dma.c @@ -714,7 +714,7 @@ int __init tegra_dma_init(void) bitmap_fill(channel_usage, NV_DMA_MAX_CHANNELS); - c = clk_get_sys("tegra-dma", NULL); + c = clk_get_sys("tegra-apbdma", NULL); if (IS_ERR(c)) { pr_err("Unable to get clock for APB DMA\n"); ret = PTR_ERR(c); diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index 034d9529b51e..b79cb93ffd54 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c @@ -2149,7 +2149,7 @@ static struct clk tegra_clk_emc = { } static struct clk tegra_list_clks[] = { - PERIPH_CLK("apbdma", "tegra-dma", NULL, 34, 0, 108000000, mux_pclk, 0), + PERIPH_CLK("apbdma", "tegra-apbdma", NULL, 34, 0, 108000000, mux_pclk, 0), PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET), PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0), PERIPH_CLK("i2s1", "tegra20-i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c index e1a74895dc3a..2ba948ea21ff 100644 --- a/arch/arm/mach-tegra/tegra30_clocks.c +++ b/arch/arm/mach-tegra/tegra30_clocks.c @@ -2871,7 +2871,7 @@ static struct clk tegra30_clk_twd = { }, \ } struct clk tegra_list_clks[] = { - PERIPH_CLK("apbdma", "tegra-dma", NULL, 34, 0, 26000000, mux_clk_m, 0), + PERIPH_CLK("apbdma", "tegra-apbdma", NULL, 34, 0, 26000000, mux_clk_m, 0), PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET | PERIPH_ON_APB), PERIPH_CLK("kbc", "tegra-kbc", NULL, 36, 0, 32768, mux_clk_32k, PERIPH_NO_RESET | PERIPH_ON_APB), PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0), -- cgit v1.2.3 From bd976e0307fbb3c715df944ded6b70a9fa8d6bb1 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 26 Jun 2012 12:48:31 +0530 Subject: ARM: tegra: add device tree AUXDATA for APBDMA Add DT AUXDATA for Tegra's APBDMA controller driver. Signed-off-by: Laxman Dewangan Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/board-dt-tegra20.c | 1 + arch/arm/mach-tegra/board-dt-tegra30.c | 1 + 2 files changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c index 8b4e6e1f0f7b..1b43c3350e3c 100644 --- a/arch/arm/mach-tegra/board-dt-tegra20.c +++ b/arch/arm/mach-tegra/board-dt-tegra20.c @@ -64,6 +64,7 @@ struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = { &tegra_ehci2_pdata), OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB3_BASE, "tegra-ehci.2", &tegra_ehci3_pdata), + OF_DEV_AUXDATA("nvidia,tegra20-apbdma", 0x6000a000, "tegra-apbdma", NULL), {} }; diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c index 4f76fa7a5da3..4a409862015f 100644 --- a/arch/arm/mach-tegra/board-dt-tegra30.c +++ b/arch/arm/mach-tegra/board-dt-tegra30.c @@ -52,6 +52,7 @@ struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C700, "tegra-i2c.3", NULL), OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000D000, "tegra-i2c.4", NULL), OF_DEV_AUXDATA("nvidia,tegra30-ahub", 0x70080000, "tegra30-ahub", NULL), + OF_DEV_AUXDATA("nvidia,tegra30-apbdma", 0x6000a000, "tegra-apbdma", NULL), {} }; -- cgit v1.2.3 From 65ab16fd385f72baf556fcebe5118d8b6f256ace Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 22 Jun 2012 10:20:04 +0200 Subject: ARM: EXYNOS: Remove leftovers of the Samsung specific power domain control Nowadays we use generic power domain support instead of Samsung specific power domain control driver. Cc: Thomas Abraham Cc: Rob Herring Cc: Grant Likely Cc: Rafael J. Wysocki Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/mach-nuri.c | 1 - arch/arm/mach-exynos/mach-origen.c | 1 - arch/arm/mach-exynos/mach-smdkv310.c | 1 - arch/arm/mach-exynos/mach-universal_c210.c | 1 - arch/arm/plat-samsung/Kconfig | 8 --- arch/arm/plat-samsung/Makefile | 4 -- arch/arm/plat-samsung/include/plat/devs.h | 1 - arch/arm/plat-samsung/include/plat/pd.h | 30 ---------- arch/arm/plat-samsung/pd.c | 95 ------------------------------ 9 files changed, 142 deletions(-) delete mode 100644 arch/arm/plat-samsung/include/plat/pd.h delete mode 100644 arch/arm/plat-samsung/pd.c (limited to 'arch') diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index 656f8fc9addd..f3b328d0aff6 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index f5572be9d7bf..873c708fd340 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c index 262e9e446a96..5fb209c4a594 100644 --- a/arch/arm/mach-exynos/mach-smdkv310.c +++ b/arch/arm/mach-exynos/mach-smdkv310.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c index cd92fa86ba41..68719f57dcea 100644 --- a/arch/arm/mach-exynos/mach-universal_c210.c +++ b/arch/arm/mach-exynos/mach-universal_c210.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index a2fae4ea0936..ffc84acb7e97 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -491,14 +491,6 @@ config S5P_SLEEP Internal config node to apply common S5P sleep management code. Can be selected by S5P and newer SoCs with similar sleep procedure. -comment "Power Domain" - -config SAMSUNG_PD - bool "Samsung Power Domain" - depends on PM_RUNTIME - help - Say Y here if you want to control Power Domain by Runtime PM. - config DEBUG_S3C_UART depends on PLAT_SAMSUNG int diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 860b2db4db15..4bb58c2dc704 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -60,10 +60,6 @@ obj-$(CONFIG_SAMSUNG_WAKEMASK) += wakeup-mask.o obj-$(CONFIG_S5P_PM) += s5p-pm.o s5p-irq-pm.o obj-$(CONFIG_S5P_SLEEP) += s5p-sleep.o -# PD support - -obj-$(CONFIG_SAMSUNG_PD) += pd.o - # PWM support obj-$(CONFIG_HAVE_PWM) += pwm.o diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 61ca2f356c52..5da4b4f38f40 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -131,7 +131,6 @@ extern struct platform_device exynos4_device_ohci; extern struct platform_device exynos4_device_pcm0; extern struct platform_device exynos4_device_pcm1; extern struct platform_device exynos4_device_pcm2; -extern struct platform_device exynos4_device_pd[]; extern struct platform_device exynos4_device_spdif; extern struct platform_device exynos_device_drm; diff --git a/arch/arm/plat-samsung/include/plat/pd.h b/arch/arm/plat-samsung/include/plat/pd.h deleted file mode 100644 index abb4bc32716a..000000000000 --- a/arch/arm/plat-samsung/include/plat/pd.h +++ /dev/null @@ -1,30 +0,0 @@ -/* linux/arch/arm/plat-samsung/include/plat/pd.h - * - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __ASM_PLAT_SAMSUNG_PD_H -#define __ASM_PLAT_SAMSUNG_PD_H __FILE__ - -struct samsung_pd_info { - int (*enable)(struct device *dev); - int (*disable)(struct device *dev); - void __iomem *base; -}; - -enum exynos4_pd_block { - PD_MFC, - PD_G3D, - PD_LCD0, - PD_LCD1, - PD_TV, - PD_CAM, - PD_GPS -}; - -#endif /* __ASM_PLAT_SAMSUNG_PD_H */ diff --git a/arch/arm/plat-samsung/pd.c b/arch/arm/plat-samsung/pd.c deleted file mode 100644 index 312b510d86b7..000000000000 --- a/arch/arm/plat-samsung/pd.c +++ /dev/null @@ -1,95 +0,0 @@ -/* linux/arch/arm/plat-samsung/pd.c - * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Samsung Power domain support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include - -#include - -static int samsung_pd_probe(struct platform_device *pdev) -{ - struct samsung_pd_info *pdata = pdev->dev.platform_data; - struct device *dev = &pdev->dev; - - if (!pdata) { - dev_err(dev, "no device data specified\n"); - return -ENOENT; - } - - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - dev_info(dev, "power domain registered\n"); - return 0; -} - -static int __devexit samsung_pd_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - - pm_runtime_disable(dev); - return 0; -} - -static int samsung_pd_runtime_suspend(struct device *dev) -{ - struct samsung_pd_info *pdata = dev->platform_data; - int ret = 0; - - if (pdata->disable) - ret = pdata->disable(dev); - - dev_dbg(dev, "suspended\n"); - return ret; -} - -static int samsung_pd_runtime_resume(struct device *dev) -{ - struct samsung_pd_info *pdata = dev->platform_data; - int ret = 0; - - if (pdata->enable) - ret = pdata->enable(dev); - - dev_dbg(dev, "resumed\n"); - return ret; -} - -static const struct dev_pm_ops samsung_pd_pm_ops = { - .runtime_suspend = samsung_pd_runtime_suspend, - .runtime_resume = samsung_pd_runtime_resume, -}; - -static struct platform_driver samsung_pd_driver = { - .driver = { - .name = "samsung-pd", - .owner = THIS_MODULE, - .pm = &samsung_pd_pm_ops, - }, - .probe = samsung_pd_probe, - .remove = __devexit_p(samsung_pd_remove), -}; - -static int __init samsung_pd_init(void) -{ - int ret; - - ret = platform_driver_register(&samsung_pd_driver); - if (ret) - printk(KERN_ERR "%s: failed to add PD driver\n", __func__); - - return ret; -} -arch_initcall(samsung_pd_init); -- cgit v1.2.3 From c8dd5110dead436b178bb2d8976290fd5f77a2ee Mon Sep 17 00:00:00 2001 From: Boojin Kim Date: Wed, 27 Jun 2012 09:45:42 +0900 Subject: ARM: EXYNOS: Remove the L2 cache latency setting for EXYNOS5 Since SYSRAM set the L2 cache latency on EXYNOS5 SoCs, no longer need that in the kernel. It helps to reduce booting time (no need cache disable and cache enable). Signed-off-by: Boojin Kim Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.c | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 742edd3bbec3..0ec1a91388c7 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -712,31 +712,6 @@ static int __init exynos4_l2x0_cache_init(void) early_initcall(exynos4_l2x0_cache_init); #endif -static int __init exynos5_l2_cache_init(void) -{ - unsigned int val; - - if (!soc_is_exynos5250()) - return 0; - - asm volatile("mrc p15, 0, %0, c1, c0, 0\n" - "bic %0, %0, #(1 << 2)\n" /* cache disable */ - "mcr p15, 0, %0, c1, c0, 0\n" - "mrc p15, 1, %0, c9, c0, 2\n" - : "=r"(val)); - - val |= (1 << 9) | (1 << 5) | (2 << 6) | (2 << 0); - - asm volatile("mcr p15, 1, %0, c9, c0, 2\n" : : "r"(val)); - asm volatile("mrc p15, 0, %0, c1, c0, 0\n" - "orr %0, %0, #(1 << 2)\n" /* cache enable */ - "mcr p15, 0, %0, c1, c0, 0\n" - : : "r"(val)); - - return 0; -} -early_initcall(exynos5_l2_cache_init); - static int __init exynos_init(void) { printk(KERN_INFO "EXYNOS: Initializing architecture\n"); -- cgit v1.2.3 From 58c553d4d4637e1955a571350888530cd0073276 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 27 Jun 2012 10:03:00 +0900 Subject: ARM: EXYNOS: Fix EXYNOS_DEV_DMA Kconfig entry Commit 20ef9e08 ("ARM: EXYNOS: Support DMA for EXYNOS5250 SoC") renamed EXYNOS4_DEV_DMA to EXYNOS_DEV_DMA. But some machine entries still had EXYNOS4_DEV_DMA. Changed them to EXYNOS_DEV_DMA. Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 573be57d3d28..6f6d13f91e4c 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -212,7 +212,7 @@ config MACH_SMDKV310 select EXYNOS_DEV_SYSMMU select EXYNOS4_DEV_AHCI select SAMSUNG_DEV_KEYPAD - select EXYNOS4_DEV_DMA + select EXYNOS_DEV_DMA select SAMSUNG_DEV_PWM select EXYNOS4_DEV_USB_OHCI select EXYNOS4_SETUP_FIMD0 @@ -264,7 +264,7 @@ config MACH_UNIVERSAL_C210 select S5P_DEV_ONENAND select S5P_DEV_TV select EXYNOS_DEV_SYSMMU - select EXYNOS4_DEV_DMA + select EXYNOS_DEV_DMA select EXYNOS_DEV_DRM select EXYNOS4_SETUP_FIMD0 select EXYNOS4_SETUP_I2C1 @@ -303,7 +303,7 @@ config MACH_NURI select S5P_DEV_MFC select S5P_DEV_USB_EHCI select S5P_SETUP_MIPIPHY - select EXYNOS4_DEV_DMA + select EXYNOS_DEV_DMA select EXYNOS_DEV_DRM select EXYNOS4_SETUP_FIMC select EXYNOS4_SETUP_FIMD0 @@ -341,7 +341,7 @@ config MACH_ORIGEN select SAMSUNG_DEV_PWM select EXYNOS_DEV_DRM select EXYNOS_DEV_SYSMMU - select EXYNOS4_DEV_DMA + select EXYNOS_DEV_DMA select EXYNOS4_DEV_USB_OHCI select EXYNOS4_SETUP_FIMD0 select EXYNOS4_SETUP_SDHCI -- cgit v1.2.3 From 3688be49e901551756f4c570a8eb3b98b1e2bbe5 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 27 Jun 2012 11:29:54 +0900 Subject: ARM: SAMSUNG: Fix compiler warning in dma-ops.c file Fixes the following build warning: arch/arm/plat-samsung/dma-ops.c:129:2: warning: initialization from incompatible pointer type [enabled by default] arch/arm/plat-samsung/dma-ops.c:129:2: warning: (near initialization for 'dmadev_ops.release') [enabled by default] Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/dma-ops.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c index f9eb353d768c..c38d75489240 100644 --- a/arch/arm/plat-samsung/dma-ops.c +++ b/arch/arm/plat-samsung/dma-ops.c @@ -36,8 +36,7 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch, return (unsigned)dma_request_channel(mask, pl330_filter, filter_param); } -static int samsung_dmadev_release(unsigned ch, - struct s3c2410_dma_client *client) +static int samsung_dmadev_release(unsigned ch, void *param) { dma_release_channel((struct dma_chan *)ch); -- cgit v1.2.3 From afd6bb387323154ff6554b52d333ec6efb8efe61 Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Thu, 21 Jun 2012 03:44:32 -0700 Subject: Fix OMAP EHCI suspend/resume failure (i693) '354ab856' causes an oops on boot for all omap3xxx platforms that use usbhs_omap for EHCI. The actual oops comes from faulty ehci-omap cleanup, but the failure caused by the change is evidenced here: [ 3.655059] ehci-omap ehci-omap.0: utmi_p1_gfclk failed error:-2 [ 3.661376] ehci-omap: probe of ehci-omap.0 failed with error -2 utmi_p1_gfclk is a clock that exists on OMAP4, but not OMAP3. In the OMAP3 case, it is configured as a dummy clock. However, OMAP4 lists the dev_id as NULL, but OMAP3 lists it as "usbhs_omap". Attempting to get that clock from ehci-omap then fails. The solution is to just change the clock3xxx_data.c for dummy clocks used in the errata fix to match the dev_id, NULL, used in clock44xx_data.c. Tested on BB-xM. Signed-off-by: Russ Dill Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/clock3xxx_data.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 1efdec236ae8..d5c0cba6a340 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3391,15 +3391,15 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs_omap", "utmi_p1_gfclk", &dummy_ck, CK_3XXX), - CLK("usbhs_omap", "utmi_p2_gfclk", &dummy_ck, CK_3XXX), - CLK("usbhs_omap", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX), - CLK("usbhs_omap", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX), - CLK("usbhs_omap", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX), - CLK("usbhs_omap", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX), + CLK(NULL, "utmi_p1_gfclk", &dummy_ck, CK_3XXX), + CLK(NULL, "utmi_p2_gfclk", &dummy_ck, CK_3XXX), + CLK(NULL, "xclk60mhsp1_ck", &dummy_ck, CK_3XXX), + CLK(NULL, "xclk60mhsp2_ck", &dummy_ck, CK_3XXX), + CLK(NULL, "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX), + CLK(NULL, "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX), CLK("usbhs_omap", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX), CLK("usbhs_omap", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX), - CLK("usbhs_omap", "init_60m_fclk", &dummy_ck, CK_3XXX), + CLK(NULL, "init_60m_fclk", &dummy_ck, CK_3XXX), CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2PLUS | CK_36XX), CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX), CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX), -- cgit v1.2.3 From 571efa0d3ba8ef6ad857259bfa194e9b2ee403ad Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 29 May 2012 15:26:40 +0530 Subject: ARM: OMAP3+: clock: Move common clksel_rate & clock data to common file OMAP3, OMAP4 and AM33xx share some common data like, clksel_rate oscillator clock input (Virtual clock nodes), required for clock tree; so move common data to common data file so that it can be reused. [hvaibhav@ti.com: Created separate commit from Paul's developement branch] Signed-off-by: Vaibhav Hiremath Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock.h | 12 +++++ arch/arm/mach-omap2/clock3xxx_data.c | 20 ++------- arch/arm/mach-omap2/clock44xx_data.c | 72 ------------------------------ arch/arm/mach-omap2/clock_common_data.c | 77 +++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 88 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index a1bb23a23351..980b0a436c29 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -155,4 +155,16 @@ extern const struct clkops clkops_omap3_noncore_dpll_ops; extern const struct clkops clkops_omap3_core_dpll_ops; extern const struct clkops clkops_omap4_dpllmx_ops; +/* clksel_rate blocks shared between OMAP44xx and AM33xx */ +extern const struct clksel_rate div_1_0_rates[]; +extern const struct clksel_rate div_1_1_rates[]; +extern const struct clksel_rate div_1_2_rates[]; +extern const struct clksel_rate div_1_3_rates[]; +extern const struct clksel_rate div_1_4_rates[]; +extern const struct clksel_rate div31_1to31_rates[]; + +/* clocks shared between various OMAP SoCs */ +extern struct clk virt_19200000_ck; +extern struct clk virt_26000000_ck; + #endif diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 4e1a3b0e8cc8..9d7ef6c13745 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -93,18 +93,6 @@ static struct clk virt_16_8m_ck = { .rate = 16800000, }; -static struct clk virt_19_2m_ck = { - .name = "virt_19_2m_ck", - .ops = &clkops_null, - .rate = 19200000, -}; - -static struct clk virt_26m_ck = { - .name = "virt_26m_ck", - .ops = &clkops_null, - .rate = 26000000, -}; - static struct clk virt_38_4m_ck = { .name = "virt_38_4m_ck", .ops = &clkops_null, @@ -145,8 +133,8 @@ static const struct clksel osc_sys_clksel[] = { { .parent = &virt_12m_ck, .rates = osc_sys_12m_rates }, { .parent = &virt_13m_ck, .rates = osc_sys_13m_rates }, { .parent = &virt_16_8m_ck, .rates = osc_sys_16_8m_rates }, - { .parent = &virt_19_2m_ck, .rates = osc_sys_19_2m_rates }, - { .parent = &virt_26m_ck, .rates = osc_sys_26m_rates }, + { .parent = &virt_19200000_ck, .rates = osc_sys_19_2m_rates }, + { .parent = &virt_26000000_ck, .rates = osc_sys_26m_rates }, { .parent = &virt_38_4m_ck, .rates = osc_sys_38_4m_rates }, { .parent = NULL }, }; @@ -3230,8 +3218,8 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "virt_12m_ck", &virt_12m_ck, CK_3XXX), CLK(NULL, "virt_13m_ck", &virt_13m_ck, CK_3XXX), CLK(NULL, "virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK(NULL, "virt_19_2m_ck", &virt_19_2m_ck, CK_3XXX), - CLK(NULL, "virt_26m_ck", &virt_26m_ck, CK_3XXX), + CLK(NULL, "virt_19200000_ck", &virt_19200000_ck, CK_3XXX), + CLK(NULL, "virt_26000000_ck", &virt_26000000_ck, CK_3XXX), CLK(NULL, "virt_38_4m_ck", &virt_38_4m_ck, CK_3XXX), CLK(NULL, "osc_sys_ck", &osc_sys_ck, CK_3XXX), CLK(NULL, "sys_ck", &sys_ck, CK_3XXX), diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 2172f6603848..66c2e2701f0c 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -106,18 +106,6 @@ static struct clk virt_16800000_ck = { .rate = 16800000, }; -static struct clk virt_19200000_ck = { - .name = "virt_19200000_ck", - .ops = &clkops_null, - .rate = 19200000, -}; - -static struct clk virt_26000000_ck = { - .name = "virt_26000000_ck", - .ops = &clkops_null, - .rate = 26000000, -}; - static struct clk virt_27000000_ck = { .name = "virt_27000000_ck", .ops = &clkops_null, @@ -130,31 +118,6 @@ static struct clk virt_38400000_ck = { .rate = 38400000, }; -static const struct clksel_rate div_1_0_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_4430 }, - { .div = 0 }, -}; - -static const struct clksel_rate div_1_1_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_4430 }, - { .div = 0 }, -}; - -static const struct clksel_rate div_1_2_rates[] = { - { .div = 1, .val = 2, .flags = RATE_IN_4430 }, - { .div = 0 }, -}; - -static const struct clksel_rate div_1_3_rates[] = { - { .div = 1, .val = 3, .flags = RATE_IN_4430 }, - { .div = 0 }, -}; - -static const struct clksel_rate div_1_4_rates[] = { - { .div = 1, .val = 4, .flags = RATE_IN_4430 }, - { .div = 0 }, -}; - static const struct clksel_rate div_1_5_rates[] = { { .div = 1, .val = 5, .flags = RATE_IN_4430 }, { .div = 0 }, @@ -288,41 +251,6 @@ static struct clk dpll_abe_x2_ck = { .recalc = &omap3_clkoutx2_recalc, }; -static const struct clksel_rate div31_1to31_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_4430 }, - { .div = 2, .val = 2, .flags = RATE_IN_4430 }, - { .div = 3, .val = 3, .flags = RATE_IN_4430 }, - { .div = 4, .val = 4, .flags = RATE_IN_4430 }, - { .div = 5, .val = 5, .flags = RATE_IN_4430 }, - { .div = 6, .val = 6, .flags = RATE_IN_4430 }, - { .div = 7, .val = 7, .flags = RATE_IN_4430 }, - { .div = 8, .val = 8, .flags = RATE_IN_4430 }, - { .div = 9, .val = 9, .flags = RATE_IN_4430 }, - { .div = 10, .val = 10, .flags = RATE_IN_4430 }, - { .div = 11, .val = 11, .flags = RATE_IN_4430 }, - { .div = 12, .val = 12, .flags = RATE_IN_4430 }, - { .div = 13, .val = 13, .flags = RATE_IN_4430 }, - { .div = 14, .val = 14, .flags = RATE_IN_4430 }, - { .div = 15, .val = 15, .flags = RATE_IN_4430 }, - { .div = 16, .val = 16, .flags = RATE_IN_4430 }, - { .div = 17, .val = 17, .flags = RATE_IN_4430 }, - { .div = 18, .val = 18, .flags = RATE_IN_4430 }, - { .div = 19, .val = 19, .flags = RATE_IN_4430 }, - { .div = 20, .val = 20, .flags = RATE_IN_4430 }, - { .div = 21, .val = 21, .flags = RATE_IN_4430 }, - { .div = 22, .val = 22, .flags = RATE_IN_4430 }, - { .div = 23, .val = 23, .flags = RATE_IN_4430 }, - { .div = 24, .val = 24, .flags = RATE_IN_4430 }, - { .div = 25, .val = 25, .flags = RATE_IN_4430 }, - { .div = 26, .val = 26, .flags = RATE_IN_4430 }, - { .div = 27, .val = 27, .flags = RATE_IN_4430 }, - { .div = 28, .val = 28, .flags = RATE_IN_4430 }, - { .div = 29, .val = 29, .flags = RATE_IN_4430 }, - { .div = 30, .val = 30, .flags = RATE_IN_4430 }, - { .div = 31, .val = 31, .flags = RATE_IN_4430 }, - { .div = 0 }, -}; - static const struct clksel dpll_abe_m2x2_div[] = { { .parent = &dpll_abe_x2_ck, .rates = div31_1to31_rates }, { .parent = NULL }, diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c index 6424d46be14a..b9f3ba68148c 100644 --- a/arch/arm/mach-omap2/clock_common_data.c +++ b/arch/arm/mach-omap2/clock_common_data.c @@ -43,3 +43,80 @@ const struct clksel_rate dsp_ick_rates[] = { { .div = 3, .val = 3, .flags = RATE_IN_243X }, { .div = 0 }, }; + + +/* clksel_rate blocks shared between OMAP44xx and AM33xx */ + +const struct clksel_rate div_1_0_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 0 }, +}; + +const struct clksel_rate div_1_1_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 0 }, +}; + +const struct clksel_rate div_1_2_rates[] = { + { .div = 1, .val = 2, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 0 }, +}; + +const struct clksel_rate div_1_3_rates[] = { + { .div = 1, .val = 3, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 0 }, +}; + +const struct clksel_rate div_1_4_rates[] = { + { .div = 1, .val = 4, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 0 }, +}; + +const struct clksel_rate div31_1to31_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 2, .val = 2, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 3, .val = 3, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 4, .val = 4, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 5, .val = 5, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 6, .val = 6, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 7, .val = 7, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 8, .val = 8, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 9, .val = 9, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 10, .val = 10, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 11, .val = 11, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 12, .val = 12, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 13, .val = 13, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 14, .val = 14, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 15, .val = 15, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 16, .val = 16, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 17, .val = 17, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 18, .val = 18, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 19, .val = 19, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 20, .val = 20, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 21, .val = 21, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 22, .val = 22, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 23, .val = 23, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 24, .val = 24, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 25, .val = 25, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 26, .val = 26, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 27, .val = 27, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 28, .val = 28, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 29, .val = 29, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 30, .val = 30, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 31, .val = 31, .flags = RATE_IN_4430 | RATE_IN_AM33XX }, + { .div = 0 }, +}; + +/* Clocks shared between various OMAP SoCs */ + +struct clk virt_19200000_ck = { + .name = "virt_19200000_ck", + .ops = &clkops_null, + .rate = 19200000, +}; + +struct clk virt_26000000_ck = { + .name = "virt_26000000_ck", + .ops = &clkops_null, + .rate = 26000000, +}; -- cgit v1.2.3 From 95ead5d7ff824a01cb07921c9211a7e29437a929 Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Wed, 13 Jun 2012 13:22:42 -0500 Subject: crypto: nx - move nx build to driver/crypto Makefile When the nx driver was pulled, the Makefile that actually builds it is arch/powerpc/Makefile. This is unnatural. This patch moves the line that builds the nx driver from arch/powerpc/Makefile to drivers/crypto/Makefile where it belongs. Signed-off-by: Seth Jennings Acked-by: Kent Yoder Signed-off-by: Herbert Xu --- arch/powerpc/Makefile | 1 - drivers/crypto/Makefile | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 950d1f7a5a39..159e94f4b22a 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -149,7 +149,6 @@ core-$(CONFIG_KVM) += arch/powerpc/kvm/ core-$(CONFIG_PERF_EVENTS) += arch/powerpc/perf/ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ -drivers-$(CONFIG_CRYPTO_DEV_NX) += drivers/crypto/nx/ # Default to zImage, override when needed all: zImage diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index d5062bb7a1f2..1c5a145cc268 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ obj-$(CONFIG_CRYPTO_DEV_BFIN_CRC) += bfin_crc.o +obj-$(CONFIG_CRYPTO_DEV_NX) += nx/ -- cgit v1.2.3 From ffaf9156320a077ebf9c5b9a5cf987689dc1a6b3 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 18 Jun 2012 14:06:58 +0300 Subject: crypto: ablk_helper - move ablk_* functions from serpent-sse2/avx glue code to shared module Move ablk-* functions to separate module to share common code between cipher implementations. Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/Makefile | 2 + arch/x86/crypto/ablk_helper.c | 150 ++++++++++++++++++++++++++++++ arch/x86/crypto/serpent_avx_glue.c | 115 ++--------------------- arch/x86/crypto/serpent_sse2_glue.c | 115 ++--------------------- arch/x86/include/asm/crypto/ablk_helper.h | 29 ++++++ crypto/Kconfig | 8 ++ 6 files changed, 201 insertions(+), 218 deletions(-) create mode 100644 arch/x86/crypto/ablk_helper.c create mode 100644 arch/x86/include/asm/crypto/ablk_helper.h (limited to 'arch') diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 83caa4b948c8..ad746916f912 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -2,6 +2,8 @@ # Arch-specific CryptoAPI modules. # +obj-$(CONFIG_CRYPTO_ABLK_HELPER_X86) += ablk_helper.o + obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o diff --git a/arch/x86/crypto/ablk_helper.c b/arch/x86/crypto/ablk_helper.c new file mode 100644 index 000000000000..284ca3bc2383 --- /dev/null +++ b/arch/x86/crypto/ablk_helper.c @@ -0,0 +1,150 @@ +/* + * Shared async block cipher helpers + * + * Copyright (c) 2012 Jussi Kivilinna + * + * Based on aesni-intel_glue.c by: + * Copyright (C) 2008, Intel Corp. + * Author: Huang Ying + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int key_len) +{ + struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm); + struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base; + int err; + + crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); + crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm) + & CRYPTO_TFM_REQ_MASK); + err = crypto_ablkcipher_setkey(child, key, key_len); + crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child) + & CRYPTO_TFM_RES_MASK); + return err; +} +EXPORT_SYMBOL_GPL(ablk_set_key); + +int __ablk_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm); + struct blkcipher_desc desc; + + desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); + desc.info = req->info; + desc.flags = 0; + + return crypto_blkcipher_crt(desc.tfm)->encrypt( + &desc, req->dst, req->src, req->nbytes); +} +EXPORT_SYMBOL_GPL(__ablk_encrypt); + +int ablk_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm); + + if (!irq_fpu_usable()) { + struct ablkcipher_request *cryptd_req = + ablkcipher_request_ctx(req); + + memcpy(cryptd_req, req, sizeof(*req)); + ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); + + return crypto_ablkcipher_encrypt(cryptd_req); + } else { + return __ablk_encrypt(req); + } +} +EXPORT_SYMBOL_GPL(ablk_encrypt); + +int ablk_decrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm); + + if (!irq_fpu_usable()) { + struct ablkcipher_request *cryptd_req = + ablkcipher_request_ctx(req); + + memcpy(cryptd_req, req, sizeof(*req)); + ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); + + return crypto_ablkcipher_decrypt(cryptd_req); + } else { + struct blkcipher_desc desc; + + desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); + desc.info = req->info; + desc.flags = 0; + + return crypto_blkcipher_crt(desc.tfm)->decrypt( + &desc, req->dst, req->src, req->nbytes); + } +} +EXPORT_SYMBOL_GPL(ablk_decrypt); + +void ablk_exit(struct crypto_tfm *tfm) +{ + struct async_helper_ctx *ctx = crypto_tfm_ctx(tfm); + + cryptd_free_ablkcipher(ctx->cryptd_tfm); +} +EXPORT_SYMBOL_GPL(ablk_exit); + +void ablk_init_common(struct crypto_tfm *tfm, + struct cryptd_ablkcipher *cryptd_tfm) +{ + struct async_helper_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->cryptd_tfm = cryptd_tfm; + tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + + crypto_ablkcipher_reqsize(&cryptd_tfm->base); +} +EXPORT_SYMBOL_GPL(ablk_init_common); + +int ablk_init(struct crypto_tfm *tfm) +{ + struct cryptd_ablkcipher *cryptd_tfm; + char drv_name[CRYPTO_MAX_ALG_NAME]; + + snprintf(drv_name, sizeof(drv_name), "__driver-%s", + crypto_tfm_alg_driver_name(tfm)); + + cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); + if (IS_ERR(cryptd_tfm)) + return PTR_ERR(cryptd_tfm); + + ablk_init_common(tfm, cryptd_tfm); + + return 0; +} +EXPORT_SYMBOL_GPL(ablk_init); + +MODULE_LICENSE("GPL"); diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c index dd81bab4f11a..31eb567cc893 100644 --- a/arch/x86/crypto/serpent_avx_glue.c +++ b/arch/x86/crypto/serpent_avx_glue.c @@ -40,14 +40,11 @@ #include #include #include +#include #include #include #include -struct async_serpent_ctx { - struct cryptd_ablkcipher *cryptd_tfm; -}; - static inline bool serpent_fpu_begin(bool fpu_enabled, unsigned int nbytes) { if (fpu_enabled) @@ -593,106 +590,6 @@ static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, return ret; } -static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, - unsigned int key_len) -{ - struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); - struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base; - int err; - - crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); - crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm) - & CRYPTO_TFM_REQ_MASK); - err = crypto_ablkcipher_setkey(child, key, key_len); - crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child) - & CRYPTO_TFM_RES_MASK); - return err; -} - -static int __ablk_encrypt(struct ablkcipher_request *req) -{ - struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); - struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); - struct blkcipher_desc desc; - - desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); - desc.info = req->info; - desc.flags = 0; - - return crypto_blkcipher_crt(desc.tfm)->encrypt( - &desc, req->dst, req->src, req->nbytes); -} - -static int ablk_encrypt(struct ablkcipher_request *req) -{ - struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); - struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); - - if (!irq_fpu_usable()) { - struct ablkcipher_request *cryptd_req = - ablkcipher_request_ctx(req); - - memcpy(cryptd_req, req, sizeof(*req)); - ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); - - return crypto_ablkcipher_encrypt(cryptd_req); - } else { - return __ablk_encrypt(req); - } -} - -static int ablk_decrypt(struct ablkcipher_request *req) -{ - struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); - struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); - - if (!irq_fpu_usable()) { - struct ablkcipher_request *cryptd_req = - ablkcipher_request_ctx(req); - - memcpy(cryptd_req, req, sizeof(*req)); - ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); - - return crypto_ablkcipher_decrypt(cryptd_req); - } else { - struct blkcipher_desc desc; - - desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); - desc.info = req->info; - desc.flags = 0; - - return crypto_blkcipher_crt(desc.tfm)->decrypt( - &desc, req->dst, req->src, req->nbytes); - } -} - -static void ablk_exit(struct crypto_tfm *tfm) -{ - struct async_serpent_ctx *ctx = crypto_tfm_ctx(tfm); - - cryptd_free_ablkcipher(ctx->cryptd_tfm); -} - -static int ablk_init(struct crypto_tfm *tfm) -{ - struct async_serpent_ctx *ctx = crypto_tfm_ctx(tfm); - struct cryptd_ablkcipher *cryptd_tfm; - char drv_name[CRYPTO_MAX_ALG_NAME]; - - snprintf(drv_name, sizeof(drv_name), "__driver-%s", - crypto_tfm_alg_driver_name(tfm)); - - cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); - if (IS_ERR(cryptd_tfm)) - return PTR_ERR(cryptd_tfm); - - ctx->cryptd_tfm = cryptd_tfm; - tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + - crypto_ablkcipher_reqsize(&cryptd_tfm->base); - - return 0; -} - static struct crypto_alg serpent_algs[10] = { { .cra_name = "__ecb-serpent-avx", .cra_driver_name = "__driver-ecb-serpent-avx", @@ -805,7 +702,7 @@ static struct crypto_alg serpent_algs[10] = { { .cra_priority = 500, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = SERPENT_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -827,7 +724,7 @@ static struct crypto_alg serpent_algs[10] = { { .cra_priority = 500, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = SERPENT_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -850,7 +747,7 @@ static struct crypto_alg serpent_algs[10] = { { .cra_priority = 500, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -874,7 +771,7 @@ static struct crypto_alg serpent_algs[10] = { { .cra_priority = 500, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = SERPENT_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -899,7 +796,7 @@ static struct crypto_alg serpent_algs[10] = { { .cra_priority = 500, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = SERPENT_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c index deecd25c1299..805c91fda7a2 100644 --- a/arch/x86/crypto/serpent_sse2_glue.c +++ b/arch/x86/crypto/serpent_sse2_glue.c @@ -43,14 +43,11 @@ #include #include #include +#include #include #include #include -struct async_serpent_ctx { - struct cryptd_ablkcipher *cryptd_tfm; -}; - static inline bool serpent_fpu_begin(bool fpu_enabled, unsigned int nbytes) { if (fpu_enabled) @@ -596,106 +593,6 @@ static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, return ret; } -static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, - unsigned int key_len) -{ - struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); - struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base; - int err; - - crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); - crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm) - & CRYPTO_TFM_REQ_MASK); - err = crypto_ablkcipher_setkey(child, key, key_len); - crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child) - & CRYPTO_TFM_RES_MASK); - return err; -} - -static int __ablk_encrypt(struct ablkcipher_request *req) -{ - struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); - struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); - struct blkcipher_desc desc; - - desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); - desc.info = req->info; - desc.flags = 0; - - return crypto_blkcipher_crt(desc.tfm)->encrypt( - &desc, req->dst, req->src, req->nbytes); -} - -static int ablk_encrypt(struct ablkcipher_request *req) -{ - struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); - struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); - - if (!irq_fpu_usable()) { - struct ablkcipher_request *cryptd_req = - ablkcipher_request_ctx(req); - - memcpy(cryptd_req, req, sizeof(*req)); - ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); - - return crypto_ablkcipher_encrypt(cryptd_req); - } else { - return __ablk_encrypt(req); - } -} - -static int ablk_decrypt(struct ablkcipher_request *req) -{ - struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); - struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm); - - if (!irq_fpu_usable()) { - struct ablkcipher_request *cryptd_req = - ablkcipher_request_ctx(req); - - memcpy(cryptd_req, req, sizeof(*req)); - ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); - - return crypto_ablkcipher_decrypt(cryptd_req); - } else { - struct blkcipher_desc desc; - - desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); - desc.info = req->info; - desc.flags = 0; - - return crypto_blkcipher_crt(desc.tfm)->decrypt( - &desc, req->dst, req->src, req->nbytes); - } -} - -static void ablk_exit(struct crypto_tfm *tfm) -{ - struct async_serpent_ctx *ctx = crypto_tfm_ctx(tfm); - - cryptd_free_ablkcipher(ctx->cryptd_tfm); -} - -static int ablk_init(struct crypto_tfm *tfm) -{ - struct async_serpent_ctx *ctx = crypto_tfm_ctx(tfm); - struct cryptd_ablkcipher *cryptd_tfm; - char drv_name[CRYPTO_MAX_ALG_NAME]; - - snprintf(drv_name, sizeof(drv_name), "__driver-%s", - crypto_tfm_alg_driver_name(tfm)); - - cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); - if (IS_ERR(cryptd_tfm)) - return PTR_ERR(cryptd_tfm); - - ctx->cryptd_tfm = cryptd_tfm; - tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + - crypto_ablkcipher_reqsize(&cryptd_tfm->base); - - return 0; -} - static struct crypto_alg serpent_algs[10] = { { .cra_name = "__ecb-serpent-sse2", .cra_driver_name = "__driver-ecb-serpent-sse2", @@ -808,7 +705,7 @@ static struct crypto_alg serpent_algs[10] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = SERPENT_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -830,7 +727,7 @@ static struct crypto_alg serpent_algs[10] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = SERPENT_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -853,7 +750,7 @@ static struct crypto_alg serpent_algs[10] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -877,7 +774,7 @@ static struct crypto_alg serpent_algs[10] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = SERPENT_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -902,7 +799,7 @@ static struct crypto_alg serpent_algs[10] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = SERPENT_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_serpent_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, diff --git a/arch/x86/include/asm/crypto/ablk_helper.h b/arch/x86/include/asm/crypto/ablk_helper.h new file mode 100644 index 000000000000..6d6b37c6f5d3 --- /dev/null +++ b/arch/x86/include/asm/crypto/ablk_helper.h @@ -0,0 +1,29 @@ +/* + * Shared async block cipher helpers + */ + +#ifndef _CRYPTO_ABLK_HELPER_H +#define _CRYPTO_ABLK_HELPER_H + +#include +#include +#include + +struct async_helper_ctx { + struct cryptd_ablkcipher *cryptd_tfm; +}; + +extern int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int key_len); + +extern int __ablk_encrypt(struct ablkcipher_request *req); + +extern int ablk_encrypt(struct ablkcipher_request *req); + +extern int ablk_decrypt(struct ablkcipher_request *req); + +extern void ablk_exit(struct crypto_tfm *tfm); + +extern int ablk_init(struct crypto_tfm *tfm); + +#endif /* _CRYPTO_ABLK_HELPER_H */ diff --git a/crypto/Kconfig b/crypto/Kconfig index 2c1c2dfcc02a..8e9145c07d87 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -174,6 +174,11 @@ config CRYPTO_TEST help Quick & dirty crypto test module. +config CRYPTO_ABLK_HELPER_X86 + tristate + depends on X86 + select CRYPTO_CRYPTD + comment "Authenticated Encryption with Associated Data" config CRYPTO_CCM @@ -786,6 +791,7 @@ config CRYPTO_SERPENT_SSE2_X86_64 depends on X86 && 64BIT select CRYPTO_ALGAPI select CRYPTO_CRYPTD + select CRYPTO_ABLK_HELPER_X86 select CRYPTO_SERPENT select CRYPTO_LRW select CRYPTO_XTS @@ -806,6 +812,7 @@ config CRYPTO_SERPENT_SSE2_586 depends on X86 && !64BIT select CRYPTO_ALGAPI select CRYPTO_CRYPTD + select CRYPTO_ABLK_HELPER_X86 select CRYPTO_SERPENT select CRYPTO_LRW select CRYPTO_XTS @@ -826,6 +833,7 @@ config CRYPTO_SERPENT_AVX_X86_64 depends on X86 && 64BIT select CRYPTO_ALGAPI select CRYPTO_CRYPTD + select CRYPTO_ABLK_HELPER_X86 select CRYPTO_SERPENT select CRYPTO_LRW select CRYPTO_XTS -- cgit v1.2.3 From 30a04008827b58c4aafbd1d6a27d6b6ed239e993 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 18 Jun 2012 14:07:03 +0300 Subject: crypto: twofish-avx - change to use shared ablk_* functions Remove duplicate ablk_* functions and make use of ablk_helper module instead. Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/twofish_avx_glue.c | 116 ++----------------------------------- crypto/Kconfig | 1 + 2 files changed, 7 insertions(+), 110 deletions(-) (limited to 'arch') diff --git a/arch/x86/crypto/twofish_avx_glue.c b/arch/x86/crypto/twofish_avx_glue.c index 599f19e4bef6..cabe058eba14 100644 --- a/arch/x86/crypto/twofish_avx_glue.c +++ b/arch/x86/crypto/twofish_avx_glue.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -95,11 +96,6 @@ static inline void twofish_dec_blk_xway(struct twofish_ctx *ctx, u8 *dst, } - -struct async_twofish_ctx { - struct cryptd_ablkcipher *cryptd_tfm; -}; - static inline bool twofish_fpu_begin(bool fpu_enabled, unsigned int nbytes) { if (fpu_enabled) @@ -730,106 +726,6 @@ static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, return ret; } -static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, - unsigned int key_len) -{ - struct async_twofish_ctx *ctx = crypto_ablkcipher_ctx(tfm); - struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base; - int err; - - crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); - crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm) - & CRYPTO_TFM_REQ_MASK); - err = crypto_ablkcipher_setkey(child, key, key_len); - crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child) - & CRYPTO_TFM_RES_MASK); - return err; -} - -static int __ablk_encrypt(struct ablkcipher_request *req) -{ - struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); - struct async_twofish_ctx *ctx = crypto_ablkcipher_ctx(tfm); - struct blkcipher_desc desc; - - desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); - desc.info = req->info; - desc.flags = 0; - - return crypto_blkcipher_crt(desc.tfm)->encrypt( - &desc, req->dst, req->src, req->nbytes); -} - -static int ablk_encrypt(struct ablkcipher_request *req) -{ - struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); - struct async_twofish_ctx *ctx = crypto_ablkcipher_ctx(tfm); - - if (!irq_fpu_usable()) { - struct ablkcipher_request *cryptd_req = - ablkcipher_request_ctx(req); - - memcpy(cryptd_req, req, sizeof(*req)); - ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); - - return crypto_ablkcipher_encrypt(cryptd_req); - } else { - return __ablk_encrypt(req); - } -} - -static int ablk_decrypt(struct ablkcipher_request *req) -{ - struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); - struct async_twofish_ctx *ctx = crypto_ablkcipher_ctx(tfm); - - if (!irq_fpu_usable()) { - struct ablkcipher_request *cryptd_req = - ablkcipher_request_ctx(req); - - memcpy(cryptd_req, req, sizeof(*req)); - ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); - - return crypto_ablkcipher_decrypt(cryptd_req); - } else { - struct blkcipher_desc desc; - - desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); - desc.info = req->info; - desc.flags = 0; - - return crypto_blkcipher_crt(desc.tfm)->decrypt( - &desc, req->dst, req->src, req->nbytes); - } -} - -static void ablk_exit(struct crypto_tfm *tfm) -{ - struct async_twofish_ctx *ctx = crypto_tfm_ctx(tfm); - - cryptd_free_ablkcipher(ctx->cryptd_tfm); -} - -static int ablk_init(struct crypto_tfm *tfm) -{ - struct async_twofish_ctx *ctx = crypto_tfm_ctx(tfm); - struct cryptd_ablkcipher *cryptd_tfm; - char drv_name[CRYPTO_MAX_ALG_NAME]; - - snprintf(drv_name, sizeof(drv_name), "__driver-%s", - crypto_tfm_alg_driver_name(tfm)); - - cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); - if (IS_ERR(cryptd_tfm)) - return PTR_ERR(cryptd_tfm); - - ctx->cryptd_tfm = cryptd_tfm; - tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + - crypto_ablkcipher_reqsize(&cryptd_tfm->base); - - return 0; -} - static struct crypto_alg twofish_algs[10] = { { .cra_name = "__ecb-twofish-avx", .cra_driver_name = "__driver-ecb-twofish-avx", @@ -942,7 +838,7 @@ static struct crypto_alg twofish_algs[10] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = TF_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -964,7 +860,7 @@ static struct crypto_alg twofish_algs[10] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = TF_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -987,7 +883,7 @@ static struct crypto_alg twofish_algs[10] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -1011,7 +907,7 @@ static struct crypto_alg twofish_algs[10] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = TF_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -1036,7 +932,7 @@ static struct crypto_alg twofish_algs[10] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = TF_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_twofish_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, diff --git a/crypto/Kconfig b/crypto/Kconfig index 8e9145c07d87..24b929e30bf3 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -946,6 +946,7 @@ config CRYPTO_TWOFISH_AVX_X86_64 depends on X86 && 64BIT select CRYPTO_ALGAPI select CRYPTO_CRYPTD + select CRYPTO_ABLK_HELPER_X86 select CRYPTO_TWOFISH_COMMON select CRYPTO_TWOFISH_X86_64 select CRYPTO_TWOFISH_X86_64_3WAY -- cgit v1.2.3 From a9629d7142ea22567eaa999232d8a31a7493665a Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 18 Jun 2012 14:07:08 +0300 Subject: crypto: aes_ni - change to use shared ablk_* functions Remove duplicate ablk_* functions and make use of ablk_helper module instead. Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/ablk_helper.c | 19 +++--- arch/x86/crypto/aesni-intel_glue.c | 100 +++--------------------------- arch/x86/include/asm/crypto/ablk_helper.h | 2 + crypto/Kconfig | 1 + 4 files changed, 20 insertions(+), 102 deletions(-) (limited to 'arch') diff --git a/arch/x86/crypto/ablk_helper.c b/arch/x86/crypto/ablk_helper.c index 284ca3bc2383..43282fe04a8b 100644 --- a/arch/x86/crypto/ablk_helper.c +++ b/arch/x86/crypto/ablk_helper.c @@ -118,32 +118,31 @@ void ablk_exit(struct crypto_tfm *tfm) } EXPORT_SYMBOL_GPL(ablk_exit); -void ablk_init_common(struct crypto_tfm *tfm, - struct cryptd_ablkcipher *cryptd_tfm) +int ablk_init_common(struct crypto_tfm *tfm, const char *drv_name) { struct async_helper_ctx *ctx = crypto_tfm_ctx(tfm); + struct cryptd_ablkcipher *cryptd_tfm; + + cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); + if (IS_ERR(cryptd_tfm)) + return PTR_ERR(cryptd_tfm); ctx->cryptd_tfm = cryptd_tfm; tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + crypto_ablkcipher_reqsize(&cryptd_tfm->base); + + return 0; } EXPORT_SYMBOL_GPL(ablk_init_common); int ablk_init(struct crypto_tfm *tfm) { - struct cryptd_ablkcipher *cryptd_tfm; char drv_name[CRYPTO_MAX_ALG_NAME]; snprintf(drv_name, sizeof(drv_name), "__driver-%s", crypto_tfm_alg_driver_name(tfm)); - cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); - if (IS_ERR(cryptd_tfm)) - return PTR_ERR(cryptd_tfm); - - ablk_init_common(tfm, cryptd_tfm); - - return 0; + return ablk_init_common(tfm, drv_name); } EXPORT_SYMBOL_GPL(ablk_init); diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index ac7f5cd019e8..7c9d54d8dc4d 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -52,10 +53,6 @@ #define HAS_XTS #endif -struct async_aes_ctx { - struct cryptd_ablkcipher *cryptd_tfm; -}; - /* This data is stored at the end of the crypto_tfm struct. * It's a type of per "session" data storage location. * This needs to be 16 byte aligned. @@ -377,87 +374,6 @@ static int ctr_crypt(struct blkcipher_desc *desc, } #endif -static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, - unsigned int key_len) -{ - struct async_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); - struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base; - int err; - - crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); - crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm) - & CRYPTO_TFM_REQ_MASK); - err = crypto_ablkcipher_setkey(child, key, key_len); - crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child) - & CRYPTO_TFM_RES_MASK); - return err; -} - -static int ablk_encrypt(struct ablkcipher_request *req) -{ - struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); - struct async_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); - - if (!irq_fpu_usable()) { - struct ablkcipher_request *cryptd_req = - ablkcipher_request_ctx(req); - memcpy(cryptd_req, req, sizeof(*req)); - ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); - return crypto_ablkcipher_encrypt(cryptd_req); - } else { - struct blkcipher_desc desc; - desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); - desc.info = req->info; - desc.flags = 0; - return crypto_blkcipher_crt(desc.tfm)->encrypt( - &desc, req->dst, req->src, req->nbytes); - } -} - -static int ablk_decrypt(struct ablkcipher_request *req) -{ - struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); - struct async_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); - - if (!irq_fpu_usable()) { - struct ablkcipher_request *cryptd_req = - ablkcipher_request_ctx(req); - memcpy(cryptd_req, req, sizeof(*req)); - ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); - return crypto_ablkcipher_decrypt(cryptd_req); - } else { - struct blkcipher_desc desc; - desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm); - desc.info = req->info; - desc.flags = 0; - return crypto_blkcipher_crt(desc.tfm)->decrypt( - &desc, req->dst, req->src, req->nbytes); - } -} - -static void ablk_exit(struct crypto_tfm *tfm) -{ - struct async_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - cryptd_free_ablkcipher(ctx->cryptd_tfm); -} - -static int ablk_init_common(struct crypto_tfm *tfm, const char *drv_name) -{ - struct async_aes_ctx *ctx = crypto_tfm_ctx(tfm); - struct cryptd_ablkcipher *cryptd_tfm; - - cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); - if (IS_ERR(cryptd_tfm)) - return PTR_ERR(cryptd_tfm); - - ctx->cryptd_tfm = cryptd_tfm; - tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + - crypto_ablkcipher_reqsize(&cryptd_tfm->base); - - return 0; -} - static int ablk_ecb_init(struct crypto_tfm *tfm) { return ablk_init_common(tfm, "__driver-ecb-aes-aesni"); @@ -968,7 +884,7 @@ static struct crypto_alg aesni_algs[] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_aes_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -989,7 +905,7 @@ static struct crypto_alg aesni_algs[] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_aes_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -1033,7 +949,7 @@ static struct crypto_alg aesni_algs[] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct async_aes_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -1098,7 +1014,7 @@ static struct crypto_alg aesni_algs[] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct async_aes_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -1126,7 +1042,7 @@ static struct crypto_alg aesni_algs[] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_aes_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -1150,7 +1066,7 @@ static struct crypto_alg aesni_algs[] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_aes_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, @@ -1174,7 +1090,7 @@ static struct crypto_alg aesni_algs[] = { { .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_aes_ctx), + .cra_ctxsize = sizeof(struct async_helper_ctx), .cra_alignmask = 0, .cra_type = &crypto_ablkcipher_type, .cra_module = THIS_MODULE, diff --git a/arch/x86/include/asm/crypto/ablk_helper.h b/arch/x86/include/asm/crypto/ablk_helper.h index 6d6b37c6f5d3..4f93df50c23e 100644 --- a/arch/x86/include/asm/crypto/ablk_helper.h +++ b/arch/x86/include/asm/crypto/ablk_helper.h @@ -24,6 +24,8 @@ extern int ablk_decrypt(struct ablkcipher_request *req); extern void ablk_exit(struct crypto_tfm *tfm); +extern int ablk_init_common(struct crypto_tfm *tfm, const char *drv_name); + extern int ablk_init(struct crypto_tfm *tfm); #endif /* _CRYPTO_ABLK_HELPER_H */ diff --git a/crypto/Kconfig b/crypto/Kconfig index 24b929e30bf3..471cc468e18f 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -557,6 +557,7 @@ config CRYPTO_AES_NI_INTEL select CRYPTO_AES_X86_64 if 64BIT select CRYPTO_AES_586 if !64BIT select CRYPTO_CRYPTD + select CRYPTO_ABLK_HELPER_X86 select CRYPTO_ALGAPI help Use Intel AES-NI instructions for AES algorithm. -- cgit v1.2.3 From e81792fbc2a6fa4969f724b959829667fb2d4f01 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 18 Jun 2012 14:07:14 +0300 Subject: crypto: serpent-sse2 - prepare serpent-sse2 glue code into generic x86 glue code for 128bit block ciphers Block cipher implementations in arch/x86/crypto/ contain common glue code that is currently duplicated in each module (camellia-x86_64, twofish-x86_64-3way, twofish-avx, serpent-sse2 and serpent-avx). This patch prepares serpent-sse2 glue into generic glue code for all 128bit block ciphers to use in arch/x86/crypto. Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/serpent_sse2_glue.c | 466 +++++++++++++++++++++++------------- 1 file changed, 303 insertions(+), 163 deletions(-) (limited to 'arch') diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c index 805c91fda7a2..8c86239010ae 100644 --- a/arch/x86/crypto/serpent_sse2_glue.c +++ b/arch/x86/crypto/serpent_sse2_glue.c @@ -48,105 +48,129 @@ #include #include -static inline bool serpent_fpu_begin(bool fpu_enabled, unsigned int nbytes) +typedef void (*common_glue_func_t)(void *ctx, u8 *dst, const u8 *src); +typedef void (*common_glue_cbc_func_t)(void *ctx, u128 *dst, const u128 *src); +typedef void (*common_glue_ctr_func_t)(void *ctx, u128 *dst, const u128 *src, + u128 *iv); + +#define GLUE_FUNC_CAST(fn) ((common_glue_func_t)(fn)) +#define GLUE_CBC_FUNC_CAST(fn) ((common_glue_cbc_func_t)(fn)) +#define GLUE_CTR_FUNC_CAST(fn) ((common_glue_ctr_func_t)(fn)) + +struct common_glue_func_entry { + unsigned int num_blocks; /* number of blocks that @fn will process */ + union { + common_glue_func_t ecb; + common_glue_cbc_func_t cbc; + common_glue_ctr_func_t ctr; + } fn_u; +}; + +struct common_glue_ctx { + unsigned int num_funcs; + int fpu_blocks_limit; /* -1 means fpu not needed at all */ + + /* + * First funcs entry must have largest num_blocks and last funcs entry + * must have num_blocks == 1! + */ + struct common_glue_func_entry funcs[]; +}; + +static inline bool glue_fpu_begin(unsigned int bsize, int fpu_blocks_limit, + struct blkcipher_desc *desc, + bool fpu_enabled, unsigned int nbytes) { + if (likely(fpu_blocks_limit < 0)) + return false; + if (fpu_enabled) return true; - /* SSE2 is only used when chunk to be processed is large enough, so - * do not enable FPU until it is necessary. + /* + * Vector-registers are only used when chunk to be processed is large + * enough, so do not enable FPU until it is necessary. */ - if (nbytes < SERPENT_BLOCK_SIZE * SERPENT_PARALLEL_BLOCKS) + if (nbytes < bsize * (unsigned int)fpu_blocks_limit) return false; + if (desc) { + /* prevent sleeping if FPU is in use */ + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + } + kernel_fpu_begin(); return true; } -static inline void serpent_fpu_end(bool fpu_enabled) +static inline void glue_fpu_end(bool fpu_enabled) { if (fpu_enabled) kernel_fpu_end(); } -static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk, - bool enc) +static int __glue_ecb_crypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, + struct blkcipher_walk *walk) { + void *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = 128 / 8; + unsigned int nbytes, i, func_bytes; bool fpu_enabled = false; - struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = SERPENT_BLOCK_SIZE; - unsigned int nbytes; int err; err = blkcipher_walk_virt(desc, walk); - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; while ((nbytes = walk->nbytes)) { u8 *wsrc = walk->src.virt.addr; u8 *wdst = walk->dst.virt.addr; - fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes); + fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, + desc, fpu_enabled, nbytes); - /* Process multi-block batch */ - if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) { - do { - if (enc) - serpent_enc_blk_xway(ctx, wdst, wsrc); - else - serpent_dec_blk_xway(ctx, wdst, wsrc); + for (i = 0; i < gctx->num_funcs; i++) { + func_bytes = bsize * gctx->funcs[i].num_blocks; - wsrc += bsize * SERPENT_PARALLEL_BLOCKS; - wdst += bsize * SERPENT_PARALLEL_BLOCKS; - nbytes -= bsize * SERPENT_PARALLEL_BLOCKS; - } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS); + /* Process multi-block batch */ + if (nbytes >= func_bytes) { + do { + gctx->funcs[i].fn_u.ecb(ctx, wdst, + wsrc); - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - do { - if (enc) - __serpent_encrypt(ctx, wdst, wsrc); - else - __serpent_decrypt(ctx, wdst, wsrc); + wsrc += func_bytes; + wdst += func_bytes; + nbytes -= func_bytes; + } while (nbytes >= func_bytes); - wsrc += bsize; - wdst += bsize; - nbytes -= bsize; - } while (nbytes >= bsize); + if (nbytes < bsize) + goto done; + } + } done: err = blkcipher_walk_done(desc, walk, nbytes); } - serpent_fpu_end(fpu_enabled); + glue_fpu_end(fpu_enabled); return err; } -static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +int glue_ecb_crypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_crypt(desc, &walk, true); + return __glue_ecb_crypt_128bit(gctx, desc, &walk); } -static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static unsigned int __glue_cbc_encrypt_128bit(const common_glue_func_t fn, + struct blkcipher_desc *desc, + struct blkcipher_walk *walk) { - struct blkcipher_walk walk; - - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_crypt(desc, &walk, false); -} - -static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = SERPENT_BLOCK_SIZE; + void *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = 128 / 8; unsigned int nbytes = walk->nbytes; u128 *src = (u128 *)walk->src.virt.addr; u128 *dst = (u128 *)walk->dst.virt.addr; @@ -154,7 +178,7 @@ static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, do { u128_xor(dst, src, iv); - __serpent_encrypt(ctx, (u8 *)dst, (u8 *)dst); + fn(ctx, (u8 *)dst, (u8 *)dst); iv = dst; src += 1; @@ -166,8 +190,10 @@ static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, return nbytes; } -static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +int glue_cbc_encrypt_128bit(const common_glue_func_t fn, + struct blkcipher_desc *desc, + struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { struct blkcipher_walk walk; int err; @@ -176,24 +202,26 @@ static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, err = blkcipher_walk_virt(desc, &walk); while ((nbytes = walk.nbytes)) { - nbytes = __cbc_encrypt(desc, &walk); + nbytes = __glue_cbc_encrypt_128bit(fn, desc, &walk); err = blkcipher_walk_done(desc, &walk, nbytes); } return err; } -static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static unsigned int +__glue_cbc_decrypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, + struct blkcipher_walk *walk) { - struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = SERPENT_BLOCK_SIZE; + void *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = 128 / 8; unsigned int nbytes = walk->nbytes; u128 *src = (u128 *)walk->src.virt.addr; u128 *dst = (u128 *)walk->dst.virt.addr; - u128 ivs[SERPENT_PARALLEL_BLOCKS - 1]; u128 last_iv; - int i; + unsigned int num_blocks, func_bytes; + unsigned int i; /* Start of the last block. */ src += nbytes / bsize - 1; @@ -201,45 +229,31 @@ static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, last_iv = *src; - /* Process multi-block batch */ - if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) { - do { - nbytes -= bsize * (SERPENT_PARALLEL_BLOCKS - 1); - src -= SERPENT_PARALLEL_BLOCKS - 1; - dst -= SERPENT_PARALLEL_BLOCKS - 1; + for (i = 0; i < gctx->num_funcs; i++) { + num_blocks = gctx->funcs[i].num_blocks; + func_bytes = bsize * num_blocks; - for (i = 0; i < SERPENT_PARALLEL_BLOCKS - 1; i++) - ivs[i] = src[i]; + /* Process multi-block batch */ + if (nbytes >= func_bytes) { + do { + nbytes -= func_bytes - bsize; + src -= num_blocks - 1; + dst -= num_blocks - 1; + + gctx->funcs[i].fn_u.cbc(ctx, dst, src); - serpent_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src); + nbytes -= bsize; + if (nbytes < bsize) + goto done; - for (i = 0; i < SERPENT_PARALLEL_BLOCKS - 1; i++) - u128_xor(dst + (i + 1), dst + (i + 1), ivs + i); + u128_xor(dst, dst, src - 1); + src -= 1; + dst -= 1; + } while (nbytes >= func_bytes); - nbytes -= bsize; if (nbytes < bsize) goto done; - - u128_xor(dst, dst, src - 1); - src -= 1; - dst -= 1; - } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS); - - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - for (;;) { - __serpent_decrypt(ctx, (u8 *)dst, (u8 *)src); - - nbytes -= bsize; - if (nbytes < bsize) - break; - - u128_xor(dst, dst, src - 1); - src -= 1; - dst -= 1; + } } done: @@ -249,24 +263,27 @@ done: return nbytes; } -static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +int glue_cbc_decrypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, + struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { + const unsigned int bsize = 128 / 8; bool fpu_enabled = false; struct blkcipher_walk walk; int err; blkcipher_walk_init(&walk, dst, src, nbytes); err = blkcipher_walk_virt(desc, &walk); - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; while ((nbytes = walk.nbytes)) { - fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes); - nbytes = __cbc_decrypt(desc, &walk); + fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, + desc, fpu_enabled, nbytes); + nbytes = __glue_cbc_decrypt_128bit(gctx, desc, &walk); err = blkcipher_walk_done(desc, &walk, nbytes); } - serpent_fpu_end(fpu_enabled); + glue_fpu_end(fpu_enabled); return err; } @@ -289,109 +306,232 @@ static inline void u128_inc(u128 *i) i->a++; } -static void ctr_crypt_final(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static void glue_ctr_crypt_final_128bit(const common_glue_ctr_func_t fn_ctr, + struct blkcipher_desc *desc, + struct blkcipher_walk *walk) { - struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - u8 *ctrblk = walk->iv; - u8 keystream[SERPENT_BLOCK_SIZE]; - u8 *src = walk->src.virt.addr; - u8 *dst = walk->dst.virt.addr; + void *ctx = crypto_blkcipher_ctx(desc->tfm); + u8 *src = (u8 *)walk->src.virt.addr; + u8 *dst = (u8 *)walk->dst.virt.addr; unsigned int nbytes = walk->nbytes; + u128 ctrblk; + u128 tmp; - __serpent_encrypt(ctx, keystream, ctrblk); - crypto_xor(keystream, src, nbytes); - memcpy(dst, keystream, nbytes); + be128_to_u128(&ctrblk, (be128 *)walk->iv); - crypto_inc(ctrblk, SERPENT_BLOCK_SIZE); + memcpy(&tmp, src, nbytes); + fn_ctr(ctx, &tmp, &tmp, &ctrblk); + memcpy(dst, &tmp, nbytes); + + u128_to_be128((be128 *)walk->iv, &ctrblk); } -static unsigned int __ctr_crypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static unsigned int __glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, + struct blkcipher_walk *walk) { - struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = SERPENT_BLOCK_SIZE; + const unsigned int bsize = 128 / 8; + void *ctx = crypto_blkcipher_ctx(desc->tfm); unsigned int nbytes = walk->nbytes; u128 *src = (u128 *)walk->src.virt.addr; u128 *dst = (u128 *)walk->dst.virt.addr; u128 ctrblk; - be128 ctrblocks[SERPENT_PARALLEL_BLOCKS]; - int i; + unsigned int num_blocks, func_bytes; + unsigned int i; be128_to_u128(&ctrblk, (be128 *)walk->iv); /* Process multi-block batch */ - if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) { - do { - /* create ctrblks for parallel encrypt */ - for (i = 0; i < SERPENT_PARALLEL_BLOCKS; i++) { - if (dst != src) - dst[i] = src[i]; - - u128_to_be128(&ctrblocks[i], &ctrblk); - u128_inc(&ctrblk); - } + for (i = 0; i < gctx->num_funcs; i++) { + num_blocks = gctx->funcs[i].num_blocks; + func_bytes = bsize * num_blocks; - serpent_enc_blk_xway_xor(ctx, (u8 *)dst, - (u8 *)ctrblocks); + if (nbytes >= func_bytes) { + do { + gctx->funcs[i].fn_u.ctr(ctx, dst, src, &ctrblk); - src += SERPENT_PARALLEL_BLOCKS; - dst += SERPENT_PARALLEL_BLOCKS; - nbytes -= bsize * SERPENT_PARALLEL_BLOCKS; - } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS); + src += num_blocks; + dst += num_blocks; + nbytes -= func_bytes; + } while (nbytes >= func_bytes); - if (nbytes < bsize) - goto done; + if (nbytes < bsize) + goto done; + } } - /* Handle leftovers */ - do { - if (dst != src) - *dst = *src; - - u128_to_be128(&ctrblocks[0], &ctrblk); - u128_inc(&ctrblk); - - __serpent_encrypt(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks); - u128_xor(dst, dst, (u128 *)ctrblocks); - - src += 1; - dst += 1; - nbytes -= bsize; - } while (nbytes >= bsize); - done: u128_to_be128((be128 *)walk->iv, &ctrblk); return nbytes; } -static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +int glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { + const unsigned int bsize = 128 / 8; bool fpu_enabled = false; struct blkcipher_walk walk; int err; blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt_block(desc, &walk, SERPENT_BLOCK_SIZE); - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + err = blkcipher_walk_virt_block(desc, &walk, bsize); - while ((nbytes = walk.nbytes) >= SERPENT_BLOCK_SIZE) { - fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes); - nbytes = __ctr_crypt(desc, &walk); + while ((nbytes = walk.nbytes) >= bsize) { + fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, + desc, fpu_enabled, nbytes); + nbytes = __glue_ctr_crypt_128bit(gctx, desc, &walk); err = blkcipher_walk_done(desc, &walk, nbytes); } - serpent_fpu_end(fpu_enabled); + glue_fpu_end(fpu_enabled); if (walk.nbytes) { - ctr_crypt_final(desc, &walk); + glue_ctr_crypt_final_128bit( + gctx->funcs[gctx->num_funcs - 1].fn_u.ctr, desc, &walk); err = blkcipher_walk_done(desc, &walk, 0); } return err; } +static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src) +{ + u128 ivs[SERPENT_PARALLEL_BLOCKS - 1]; + unsigned int j; + + for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++) + ivs[j] = src[j]; + + serpent_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src); + + for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++) + u128_xor(dst + (j + 1), dst + (j + 1), ivs + j); +} + +static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv) +{ + be128 ctrblk; + + u128_to_be128(&ctrblk, iv); + u128_inc(iv); + + __serpent_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk); + u128_xor(dst, src, (u128 *)&ctrblk); +} + +static void serpent_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src, + u128 *iv) +{ + be128 ctrblks[SERPENT_PARALLEL_BLOCKS]; + unsigned int i; + + for (i = 0; i < SERPENT_PARALLEL_BLOCKS; i++) { + if (dst != src) + dst[i] = src[i]; + + u128_to_be128(&ctrblks[i], iv); + u128_inc(iv); + } + + serpent_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks); +} + +static const struct common_glue_ctx serpent_enc = { + .num_funcs = 2, + .fpu_blocks_limit = SERPENT_PARALLEL_BLOCKS, + + .funcs = { { + .num_blocks = SERPENT_PARALLEL_BLOCKS, + .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_enc_blk_xway) } + }, { + .num_blocks = 1, + .fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_encrypt) } + } } +}; + +static const struct common_glue_ctx serpent_ctr = { + .num_funcs = 2, + .fpu_blocks_limit = SERPENT_PARALLEL_BLOCKS, + + .funcs = { { + .num_blocks = SERPENT_PARALLEL_BLOCKS, + .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_crypt_ctr_xway) } + }, { + .num_blocks = 1, + .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_crypt_ctr) } + } } +}; + +static const struct common_glue_ctx serpent_dec = { + .num_funcs = 2, + .fpu_blocks_limit = SERPENT_PARALLEL_BLOCKS, + + .funcs = { { + .num_blocks = SERPENT_PARALLEL_BLOCKS, + .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_dec_blk_xway) } + }, { + .num_blocks = 1, + .fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_decrypt) } + } } +}; + +static const struct common_glue_ctx serpent_dec_cbc = { + .num_funcs = 2, + .fpu_blocks_limit = SERPENT_PARALLEL_BLOCKS, + + .funcs = { { + .num_blocks = SERPENT_PARALLEL_BLOCKS, + .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_decrypt_cbc_xway) } + }, { + .num_blocks = 1, + .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__serpent_decrypt) } + } } +}; + +static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + return glue_ecb_crypt_128bit(&serpent_enc, desc, dst, src, nbytes); +} + +static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + return glue_ecb_crypt_128bit(&serpent_dec, desc, dst, src, nbytes); +} + +static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + return glue_cbc_encrypt_128bit(GLUE_FUNC_CAST(__serpent_encrypt), desc, + dst, src, nbytes); +} + +static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + return glue_cbc_decrypt_128bit(&serpent_dec_cbc, desc, dst, src, + nbytes); +} + +static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + return glue_ctr_crypt_128bit(&serpent_ctr, desc, dst, src, nbytes); +} + +static inline bool serpent_fpu_begin(bool fpu_enabled, unsigned int nbytes) +{ + return glue_fpu_begin(SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS, + NULL, fpu_enabled, nbytes); +} + +static inline void serpent_fpu_end(bool fpu_enabled) +{ + glue_fpu_end(fpu_enabled); +} + struct crypt_priv { struct serpent_ctx *ctx; bool fpu_enabled; -- cgit v1.2.3 From 596d875052dac6bf084f0c3a3e946fb4709b727b Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 18 Jun 2012 14:07:19 +0300 Subject: crypto: serpent-sse2 - split generic glue code to new helper module Now that serpent-sse2 glue code has been made generic, it can be split to separate module. Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/Makefile | 1 + arch/x86/crypto/glue_helper.c | 307 ++++++++++++++++++++++++++ arch/x86/crypto/serpent_sse2_glue.c | 352 +----------------------------- arch/x86/include/asm/crypto/glue_helper.h | 115 ++++++++++ crypto/Kconfig | 7 + 5 files changed, 431 insertions(+), 351 deletions(-) create mode 100644 arch/x86/crypto/glue_helper.c create mode 100644 arch/x86/include/asm/crypto/glue_helper.h (limited to 'arch') diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index ad746916f912..e908e5de82d3 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_CRYPTO_ABLK_HELPER_X86) += ablk_helper.o +obj-$(CONFIG_CRYPTO_GLUE_HELPER_X86) += glue_helper.o obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o diff --git a/arch/x86/crypto/glue_helper.c b/arch/x86/crypto/glue_helper.c new file mode 100644 index 000000000000..4854f0f31e4f --- /dev/null +++ b/arch/x86/crypto/glue_helper.c @@ -0,0 +1,307 @@ +/* + * Shared glue code for 128bit block ciphers + * + * Copyright (c) 2012 Jussi Kivilinna + * + * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by: + * Copyright (c) 2006 Herbert Xu + * CTR part based on code (crypto/ctr.c) by: + * (C) Copyright IBM Corp. 2007 - Joy Latten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + */ + +#include +#include +#include +#include +#include +#include + +static int __glue_ecb_crypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + void *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = 128 / 8; + unsigned int nbytes, i, func_bytes; + bool fpu_enabled = false; + int err; + + err = blkcipher_walk_virt(desc, walk); + + while ((nbytes = walk->nbytes)) { + u8 *wsrc = walk->src.virt.addr; + u8 *wdst = walk->dst.virt.addr; + + fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, + desc, fpu_enabled, nbytes); + + for (i = 0; i < gctx->num_funcs; i++) { + func_bytes = bsize * gctx->funcs[i].num_blocks; + + /* Process multi-block batch */ + if (nbytes >= func_bytes) { + do { + gctx->funcs[i].fn_u.ecb(ctx, wdst, + wsrc); + + wsrc += func_bytes; + wdst += func_bytes; + nbytes -= func_bytes; + } while (nbytes >= func_bytes); + + if (nbytes < bsize) + goto done; + } + } + +done: + err = blkcipher_walk_done(desc, walk, nbytes); + } + + glue_fpu_end(fpu_enabled); + return err; +} + +int glue_ecb_crypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + + blkcipher_walk_init(&walk, dst, src, nbytes); + return __glue_ecb_crypt_128bit(gctx, desc, &walk); +} +EXPORT_SYMBOL_GPL(glue_ecb_crypt_128bit); + +static unsigned int __glue_cbc_encrypt_128bit(const common_glue_func_t fn, + struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + void *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = 128 / 8; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 *iv = (u128 *)walk->iv; + + do { + u128_xor(dst, src, iv); + fn(ctx, (u8 *)dst, (u8 *)dst); + iv = dst; + + src += 1; + dst += 1; + nbytes -= bsize; + } while (nbytes >= bsize); + + u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv); + return nbytes; +} + +int glue_cbc_encrypt_128bit(const common_glue_func_t fn, + struct blkcipher_desc *desc, + struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + + while ((nbytes = walk.nbytes)) { + nbytes = __glue_cbc_encrypt_128bit(fn, desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + return err; +} +EXPORT_SYMBOL_GPL(glue_cbc_encrypt_128bit); + +static unsigned int +__glue_cbc_decrypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + void *ctx = crypto_blkcipher_ctx(desc->tfm); + const unsigned int bsize = 128 / 8; + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 last_iv; + unsigned int num_blocks, func_bytes; + unsigned int i; + + /* Start of the last block. */ + src += nbytes / bsize - 1; + dst += nbytes / bsize - 1; + + last_iv = *src; + + for (i = 0; i < gctx->num_funcs; i++) { + num_blocks = gctx->funcs[i].num_blocks; + func_bytes = bsize * num_blocks; + + /* Process multi-block batch */ + if (nbytes >= func_bytes) { + do { + nbytes -= func_bytes - bsize; + src -= num_blocks - 1; + dst -= num_blocks - 1; + + gctx->funcs[i].fn_u.cbc(ctx, dst, src); + + nbytes -= bsize; + if (nbytes < bsize) + goto done; + + u128_xor(dst, dst, src - 1); + src -= 1; + dst -= 1; + } while (nbytes >= func_bytes); + + if (nbytes < bsize) + goto done; + } + } + +done: + u128_xor(dst, dst, (u128 *)walk->iv); + *(u128 *)walk->iv = last_iv; + + return nbytes; +} + +int glue_cbc_decrypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, + struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + const unsigned int bsize = 128 / 8; + bool fpu_enabled = false; + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + + while ((nbytes = walk.nbytes)) { + fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, + desc, fpu_enabled, nbytes); + nbytes = __glue_cbc_decrypt_128bit(gctx, desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + glue_fpu_end(fpu_enabled); + return err; +} +EXPORT_SYMBOL_GPL(glue_cbc_decrypt_128bit); + +static void glue_ctr_crypt_final_128bit(const common_glue_ctr_func_t fn_ctr, + struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + void *ctx = crypto_blkcipher_ctx(desc->tfm); + u8 *src = (u8 *)walk->src.virt.addr; + u8 *dst = (u8 *)walk->dst.virt.addr; + unsigned int nbytes = walk->nbytes; + u128 ctrblk; + u128 tmp; + + be128_to_u128(&ctrblk, (be128 *)walk->iv); + + memcpy(&tmp, src, nbytes); + fn_ctr(ctx, &tmp, &tmp, &ctrblk); + memcpy(dst, &tmp, nbytes); + + u128_to_be128((be128 *)walk->iv, &ctrblk); +} +EXPORT_SYMBOL_GPL(glue_ctr_crypt_final_128bit); + +static unsigned int __glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, + struct blkcipher_walk *walk) +{ + const unsigned int bsize = 128 / 8; + void *ctx = crypto_blkcipher_ctx(desc->tfm); + unsigned int nbytes = walk->nbytes; + u128 *src = (u128 *)walk->src.virt.addr; + u128 *dst = (u128 *)walk->dst.virt.addr; + u128 ctrblk; + unsigned int num_blocks, func_bytes; + unsigned int i; + + be128_to_u128(&ctrblk, (be128 *)walk->iv); + + /* Process multi-block batch */ + for (i = 0; i < gctx->num_funcs; i++) { + num_blocks = gctx->funcs[i].num_blocks; + func_bytes = bsize * num_blocks; + + if (nbytes >= func_bytes) { + do { + gctx->funcs[i].fn_u.ctr(ctx, dst, src, &ctrblk); + + src += num_blocks; + dst += num_blocks; + nbytes -= func_bytes; + } while (nbytes >= func_bytes); + + if (nbytes < bsize) + goto done; + } + } + +done: + u128_to_be128((be128 *)walk->iv, &ctrblk); + return nbytes; +} + +int glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + const unsigned int bsize = 128 / 8; + bool fpu_enabled = false; + struct blkcipher_walk walk; + int err; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt_block(desc, &walk, bsize); + + while ((nbytes = walk.nbytes) >= bsize) { + fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, + desc, fpu_enabled, nbytes); + nbytes = __glue_ctr_crypt_128bit(gctx, desc, &walk); + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + glue_fpu_end(fpu_enabled); + + if (walk.nbytes) { + glue_ctr_crypt_final_128bit( + gctx->funcs[gctx->num_funcs - 1].fn_u.ctr, desc, &walk); + err = blkcipher_walk_done(desc, &walk, 0); + } + + return err; +} +EXPORT_SYMBOL_GPL(glue_ctr_crypt_128bit); + +MODULE_LICENSE("GPL"); diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c index 8c86239010ae..49a32eedf0c8 100644 --- a/arch/x86/crypto/serpent_sse2_glue.c +++ b/arch/x86/crypto/serpent_sse2_glue.c @@ -41,359 +41,9 @@ #include #include #include -#include #include #include -#include -#include -#include - -typedef void (*common_glue_func_t)(void *ctx, u8 *dst, const u8 *src); -typedef void (*common_glue_cbc_func_t)(void *ctx, u128 *dst, const u128 *src); -typedef void (*common_glue_ctr_func_t)(void *ctx, u128 *dst, const u128 *src, - u128 *iv); - -#define GLUE_FUNC_CAST(fn) ((common_glue_func_t)(fn)) -#define GLUE_CBC_FUNC_CAST(fn) ((common_glue_cbc_func_t)(fn)) -#define GLUE_CTR_FUNC_CAST(fn) ((common_glue_ctr_func_t)(fn)) - -struct common_glue_func_entry { - unsigned int num_blocks; /* number of blocks that @fn will process */ - union { - common_glue_func_t ecb; - common_glue_cbc_func_t cbc; - common_glue_ctr_func_t ctr; - } fn_u; -}; - -struct common_glue_ctx { - unsigned int num_funcs; - int fpu_blocks_limit; /* -1 means fpu not needed at all */ - - /* - * First funcs entry must have largest num_blocks and last funcs entry - * must have num_blocks == 1! - */ - struct common_glue_func_entry funcs[]; -}; - -static inline bool glue_fpu_begin(unsigned int bsize, int fpu_blocks_limit, - struct blkcipher_desc *desc, - bool fpu_enabled, unsigned int nbytes) -{ - if (likely(fpu_blocks_limit < 0)) - return false; - - if (fpu_enabled) - return true; - - /* - * Vector-registers are only used when chunk to be processed is large - * enough, so do not enable FPU until it is necessary. - */ - if (nbytes < bsize * (unsigned int)fpu_blocks_limit) - return false; - - if (desc) { - /* prevent sleeping if FPU is in use */ - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; - } - - kernel_fpu_begin(); - return true; -} - -static inline void glue_fpu_end(bool fpu_enabled) -{ - if (fpu_enabled) - kernel_fpu_end(); -} - -static int __glue_ecb_crypt_128bit(const struct common_glue_ctx *gctx, - struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - void *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = 128 / 8; - unsigned int nbytes, i, func_bytes; - bool fpu_enabled = false; - int err; - - err = blkcipher_walk_virt(desc, walk); - - while ((nbytes = walk->nbytes)) { - u8 *wsrc = walk->src.virt.addr; - u8 *wdst = walk->dst.virt.addr; - - fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, - desc, fpu_enabled, nbytes); - - for (i = 0; i < gctx->num_funcs; i++) { - func_bytes = bsize * gctx->funcs[i].num_blocks; - - /* Process multi-block batch */ - if (nbytes >= func_bytes) { - do { - gctx->funcs[i].fn_u.ecb(ctx, wdst, - wsrc); - - wsrc += func_bytes; - wdst += func_bytes; - nbytes -= func_bytes; - } while (nbytes >= func_bytes); - - if (nbytes < bsize) - goto done; - } - } - -done: - err = blkcipher_walk_done(desc, walk, nbytes); - } - - glue_fpu_end(fpu_enabled); - return err; -} - -int glue_ecb_crypt_128bit(const struct common_glue_ctx *gctx, - struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) -{ - struct blkcipher_walk walk; - - blkcipher_walk_init(&walk, dst, src, nbytes); - return __glue_ecb_crypt_128bit(gctx, desc, &walk); -} - -static unsigned int __glue_cbc_encrypt_128bit(const common_glue_func_t fn, - struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - void *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = 128 / 8; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 *iv = (u128 *)walk->iv; - - do { - u128_xor(dst, src, iv); - fn(ctx, (u8 *)dst, (u8 *)dst); - iv = dst; - - src += 1; - dst += 1; - nbytes -= bsize; - } while (nbytes >= bsize); - - u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv); - return nbytes; -} - -int glue_cbc_encrypt_128bit(const common_glue_func_t fn, - struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) -{ - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); - - while ((nbytes = walk.nbytes)) { - nbytes = __glue_cbc_encrypt_128bit(fn, desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - return err; -} - -static unsigned int -__glue_cbc_decrypt_128bit(const struct common_glue_ctx *gctx, - struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - void *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = 128 / 8; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 last_iv; - unsigned int num_blocks, func_bytes; - unsigned int i; - - /* Start of the last block. */ - src += nbytes / bsize - 1; - dst += nbytes / bsize - 1; - - last_iv = *src; - - for (i = 0; i < gctx->num_funcs; i++) { - num_blocks = gctx->funcs[i].num_blocks; - func_bytes = bsize * num_blocks; - - /* Process multi-block batch */ - if (nbytes >= func_bytes) { - do { - nbytes -= func_bytes - bsize; - src -= num_blocks - 1; - dst -= num_blocks - 1; - - gctx->funcs[i].fn_u.cbc(ctx, dst, src); - - nbytes -= bsize; - if (nbytes < bsize) - goto done; - - u128_xor(dst, dst, src - 1); - src -= 1; - dst -= 1; - } while (nbytes >= func_bytes); - - if (nbytes < bsize) - goto done; - } - } - -done: - u128_xor(dst, dst, (u128 *)walk->iv); - *(u128 *)walk->iv = last_iv; - - return nbytes; -} - -int glue_cbc_decrypt_128bit(const struct common_glue_ctx *gctx, - struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) -{ - const unsigned int bsize = 128 / 8; - bool fpu_enabled = false; - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); - - while ((nbytes = walk.nbytes)) { - fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, - desc, fpu_enabled, nbytes); - nbytes = __glue_cbc_decrypt_128bit(gctx, desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - glue_fpu_end(fpu_enabled); - return err; -} - -static inline void u128_to_be128(be128 *dst, const u128 *src) -{ - dst->a = cpu_to_be64(src->a); - dst->b = cpu_to_be64(src->b); -} - -static inline void be128_to_u128(u128 *dst, const be128 *src) -{ - dst->a = be64_to_cpu(src->a); - dst->b = be64_to_cpu(src->b); -} - -static inline void u128_inc(u128 *i) -{ - i->b++; - if (!i->b) - i->a++; -} - -static void glue_ctr_crypt_final_128bit(const common_glue_ctr_func_t fn_ctr, - struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - void *ctx = crypto_blkcipher_ctx(desc->tfm); - u8 *src = (u8 *)walk->src.virt.addr; - u8 *dst = (u8 *)walk->dst.virt.addr; - unsigned int nbytes = walk->nbytes; - u128 ctrblk; - u128 tmp; - - be128_to_u128(&ctrblk, (be128 *)walk->iv); - - memcpy(&tmp, src, nbytes); - fn_ctr(ctx, &tmp, &tmp, &ctrblk); - memcpy(dst, &tmp, nbytes); - - u128_to_be128((be128 *)walk->iv, &ctrblk); -} - -static unsigned int __glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx, - struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - const unsigned int bsize = 128 / 8; - void *ctx = crypto_blkcipher_ctx(desc->tfm); - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 ctrblk; - unsigned int num_blocks, func_bytes; - unsigned int i; - - be128_to_u128(&ctrblk, (be128 *)walk->iv); - - /* Process multi-block batch */ - for (i = 0; i < gctx->num_funcs; i++) { - num_blocks = gctx->funcs[i].num_blocks; - func_bytes = bsize * num_blocks; - - if (nbytes >= func_bytes) { - do { - gctx->funcs[i].fn_u.ctr(ctx, dst, src, &ctrblk); - - src += num_blocks; - dst += num_blocks; - nbytes -= func_bytes; - } while (nbytes >= func_bytes); - - if (nbytes < bsize) - goto done; - } - } - -done: - u128_to_be128((be128 *)walk->iv, &ctrblk); - return nbytes; -} - -int glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx, - struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) -{ - const unsigned int bsize = 128 / 8; - bool fpu_enabled = false; - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt_block(desc, &walk, bsize); - - while ((nbytes = walk.nbytes) >= bsize) { - fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, - desc, fpu_enabled, nbytes); - nbytes = __glue_ctr_crypt_128bit(gctx, desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - glue_fpu_end(fpu_enabled); - - if (walk.nbytes) { - glue_ctr_crypt_final_128bit( - gctx->funcs[gctx->num_funcs - 1].fn_u.ctr, desc, &walk); - err = blkcipher_walk_done(desc, &walk, 0); - } - - return err; -} +#include static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src) { diff --git a/arch/x86/include/asm/crypto/glue_helper.h b/arch/x86/include/asm/crypto/glue_helper.h new file mode 100644 index 000000000000..3e408bddc96f --- /dev/null +++ b/arch/x86/include/asm/crypto/glue_helper.h @@ -0,0 +1,115 @@ +/* + * Shared glue code for 128bit block ciphers + */ + +#ifndef _CRYPTO_GLUE_HELPER_H +#define _CRYPTO_GLUE_HELPER_H + +#include +#include +#include +#include + +typedef void (*common_glue_func_t)(void *ctx, u8 *dst, const u8 *src); +typedef void (*common_glue_cbc_func_t)(void *ctx, u128 *dst, const u128 *src); +typedef void (*common_glue_ctr_func_t)(void *ctx, u128 *dst, const u128 *src, + u128 *iv); + +#define GLUE_FUNC_CAST(fn) ((common_glue_func_t)(fn)) +#define GLUE_CBC_FUNC_CAST(fn) ((common_glue_cbc_func_t)(fn)) +#define GLUE_CTR_FUNC_CAST(fn) ((common_glue_ctr_func_t)(fn)) + +struct common_glue_func_entry { + unsigned int num_blocks; /* number of blocks that @fn will process */ + union { + common_glue_func_t ecb; + common_glue_cbc_func_t cbc; + common_glue_ctr_func_t ctr; + } fn_u; +}; + +struct common_glue_ctx { + unsigned int num_funcs; + int fpu_blocks_limit; /* -1 means fpu not needed at all */ + + /* + * First funcs entry must have largest num_blocks and last funcs entry + * must have num_blocks == 1! + */ + struct common_glue_func_entry funcs[]; +}; + +static inline bool glue_fpu_begin(unsigned int bsize, int fpu_blocks_limit, + struct blkcipher_desc *desc, + bool fpu_enabled, unsigned int nbytes) +{ + if (likely(fpu_blocks_limit < 0)) + return false; + + if (fpu_enabled) + return true; + + /* + * Vector-registers are only used when chunk to be processed is large + * enough, so do not enable FPU until it is necessary. + */ + if (nbytes < bsize * (unsigned int)fpu_blocks_limit) + return false; + + if (desc) { + /* prevent sleeping if FPU is in use */ + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + } + + kernel_fpu_begin(); + return true; +} + +static inline void glue_fpu_end(bool fpu_enabled) +{ + if (fpu_enabled) + kernel_fpu_end(); +} + +static inline void u128_to_be128(be128 *dst, const u128 *src) +{ + dst->a = cpu_to_be64(src->a); + dst->b = cpu_to_be64(src->b); +} + +static inline void be128_to_u128(u128 *dst, const be128 *src) +{ + dst->a = be64_to_cpu(src->a); + dst->b = be64_to_cpu(src->b); +} + +static inline void u128_inc(u128 *i) +{ + i->b++; + if (!i->b) + i->a++; +} + +extern int glue_ecb_crypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, + struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes); + +extern int glue_cbc_encrypt_128bit(const common_glue_func_t fn, + struct blkcipher_desc *desc, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes); + +extern int glue_cbc_decrypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes); + +extern int glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx, + struct blkcipher_desc *desc, + struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes); + +#endif /* _CRYPTO_GLUE_HELPER_H */ diff --git a/crypto/Kconfig b/crypto/Kconfig index 471cc468e18f..92b46970c856 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -179,6 +179,11 @@ config CRYPTO_ABLK_HELPER_X86 depends on X86 select CRYPTO_CRYPTD +config CRYPTO_GLUE_HELPER_X86 + tristate + depends on X86 + select CRYPTO_ALGAPI + comment "Authenticated Encryption with Associated Data" config CRYPTO_CCM @@ -793,6 +798,7 @@ config CRYPTO_SERPENT_SSE2_X86_64 select CRYPTO_ALGAPI select CRYPTO_CRYPTD select CRYPTO_ABLK_HELPER_X86 + select CRYPTO_GLUE_HELPER_X86 select CRYPTO_SERPENT select CRYPTO_LRW select CRYPTO_XTS @@ -814,6 +820,7 @@ config CRYPTO_SERPENT_SSE2_586 select CRYPTO_ALGAPI select CRYPTO_CRYPTD select CRYPTO_ABLK_HELPER_X86 + select CRYPTO_GLUE_HELPER_X86 select CRYPTO_SERPENT select CRYPTO_LRW select CRYPTO_XTS -- cgit v1.2.3 From 1d0debbd4671a8d302a11837a126d5f87db16bdc Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 18 Jun 2012 14:07:24 +0300 Subject: crypto: serpent-avx: remove duplicated glue code and use shared glue code from glue_helper Now that shared glue code is available, convert serpent-avx to use it. Cc: Johannes Goetzfried Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/serpent_avx_glue.c | 398 +++++++++---------------------------- crypto/Kconfig | 1 + 2 files changed, 95 insertions(+), 304 deletions(-) (limited to 'arch') diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c index 31eb567cc893..c61b91aa42a8 100644 --- a/arch/x86/crypto/serpent_avx_glue.c +++ b/arch/x86/crypto/serpent_avx_glue.c @@ -36,357 +36,147 @@ #include #include #include -#include #include #include #include #include -#include -#include -#include +#include -static inline bool serpent_fpu_begin(bool fpu_enabled, unsigned int nbytes) +static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src) { - if (fpu_enabled) - return true; - - /* AVX is only used when chunk to be processed is large enough, so - * do not enable FPU until it is necessary. - */ - if (nbytes < SERPENT_BLOCK_SIZE * SERPENT_PARALLEL_BLOCKS) - return false; - - kernel_fpu_begin(); - return true; -} - -static inline void serpent_fpu_end(bool fpu_enabled) -{ - if (fpu_enabled) - kernel_fpu_end(); -} - -static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk, - bool enc) -{ - bool fpu_enabled = false; - struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = SERPENT_BLOCK_SIZE; - unsigned int nbytes; - int err; + u128 ivs[SERPENT_PARALLEL_BLOCKS - 1]; + unsigned int j; - err = blkcipher_walk_virt(desc, walk); - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++) + ivs[j] = src[j]; - while ((nbytes = walk->nbytes)) { - u8 *wsrc = walk->src.virt.addr; - u8 *wdst = walk->dst.virt.addr; - - fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes); - - /* Process multi-block batch */ - if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) { - do { - if (enc) - serpent_enc_blk_xway(ctx, wdst, wsrc); - else - serpent_dec_blk_xway(ctx, wdst, wsrc); - - wsrc += bsize * SERPENT_PARALLEL_BLOCKS; - wdst += bsize * SERPENT_PARALLEL_BLOCKS; - nbytes -= bsize * SERPENT_PARALLEL_BLOCKS; - } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS); - - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - do { - if (enc) - __serpent_encrypt(ctx, wdst, wsrc); - else - __serpent_decrypt(ctx, wdst, wsrc); - - wsrc += bsize; - wdst += bsize; - nbytes -= bsize; - } while (nbytes >= bsize); - -done: - err = blkcipher_walk_done(desc, walk, nbytes); - } + serpent_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src); - serpent_fpu_end(fpu_enabled); - return err; + for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++) + u128_xor(dst + (j + 1), dst + (j + 1), ivs + j); } -static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv) { - struct blkcipher_walk walk; - - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_crypt(desc, &walk, true); -} + be128 ctrblk; -static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) -{ - struct blkcipher_walk walk; + u128_to_be128(&ctrblk, iv); + u128_inc(iv); - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_crypt(desc, &walk, false); + __serpent_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk); + u128_xor(dst, src, (u128 *)&ctrblk); } -static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static void serpent_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src, + u128 *iv) { - struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = SERPENT_BLOCK_SIZE; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 *iv = (u128 *)walk->iv; - - do { - u128_xor(dst, src, iv); - __serpent_encrypt(ctx, (u8 *)dst, (u8 *)dst); - iv = dst; - - src += 1; - dst += 1; - nbytes -= bsize; - } while (nbytes >= bsize); - - u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv); - return nbytes; -} + be128 ctrblks[SERPENT_PARALLEL_BLOCKS]; + unsigned int i; -static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) -{ - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); + for (i = 0; i < SERPENT_PARALLEL_BLOCKS; i++) { + if (dst != src) + dst[i] = src[i]; - while ((nbytes = walk.nbytes)) { - nbytes = __cbc_encrypt(desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); + u128_to_be128(&ctrblks[i], iv); + u128_inc(iv); } - return err; + serpent_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks); } -static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = SERPENT_BLOCK_SIZE; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 ivs[SERPENT_PARALLEL_BLOCKS - 1]; - u128 last_iv; - int i; - - /* Start of the last block. */ - src += nbytes / bsize - 1; - dst += nbytes / bsize - 1; - - last_iv = *src; - - /* Process multi-block batch */ - if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) { - do { - nbytes -= bsize * (SERPENT_PARALLEL_BLOCKS - 1); - src -= SERPENT_PARALLEL_BLOCKS - 1; - dst -= SERPENT_PARALLEL_BLOCKS - 1; - - for (i = 0; i < SERPENT_PARALLEL_BLOCKS - 1; i++) - ivs[i] = src[i]; - - serpent_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src); - - for (i = 0; i < SERPENT_PARALLEL_BLOCKS - 1; i++) - u128_xor(dst + (i + 1), dst + (i + 1), ivs + i); - - nbytes -= bsize; - if (nbytes < bsize) - goto done; - - u128_xor(dst, dst, src - 1); - src -= 1; - dst -= 1; - } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS); - - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - for (;;) { - __serpent_decrypt(ctx, (u8 *)dst, (u8 *)src); - - nbytes -= bsize; - if (nbytes < bsize) - break; +static const struct common_glue_ctx serpent_enc = { + .num_funcs = 2, + .fpu_blocks_limit = SERPENT_PARALLEL_BLOCKS, + + .funcs = { { + .num_blocks = SERPENT_PARALLEL_BLOCKS, + .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_enc_blk_xway) } + }, { + .num_blocks = 1, + .fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_encrypt) } + } } +}; - u128_xor(dst, dst, src - 1); - src -= 1; - dst -= 1; - } +static const struct common_glue_ctx serpent_ctr = { + .num_funcs = 2, + .fpu_blocks_limit = SERPENT_PARALLEL_BLOCKS, + + .funcs = { { + .num_blocks = SERPENT_PARALLEL_BLOCKS, + .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_crypt_ctr_xway) } + }, { + .num_blocks = 1, + .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_crypt_ctr) } + } } +}; -done: - u128_xor(dst, dst, (u128 *)walk->iv); - *(u128 *)walk->iv = last_iv; +static const struct common_glue_ctx serpent_dec = { + .num_funcs = 2, + .fpu_blocks_limit = SERPENT_PARALLEL_BLOCKS, + + .funcs = { { + .num_blocks = SERPENT_PARALLEL_BLOCKS, + .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_dec_blk_xway) } + }, { + .num_blocks = 1, + .fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_decrypt) } + } } +}; - return nbytes; -} +static const struct common_glue_ctx serpent_dec_cbc = { + .num_funcs = 2, + .fpu_blocks_limit = SERPENT_PARALLEL_BLOCKS, + + .funcs = { { + .num_blocks = SERPENT_PARALLEL_BLOCKS, + .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_decrypt_cbc_xway) } + }, { + .num_blocks = 1, + .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__serpent_decrypt) } + } } +}; -static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, +static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { - bool fpu_enabled = false; - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; - - while ((nbytes = walk.nbytes)) { - fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes); - nbytes = __cbc_decrypt(desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - serpent_fpu_end(fpu_enabled); - return err; + return glue_ecb_crypt_128bit(&serpent_enc, desc, dst, src, nbytes); } -static inline void u128_to_be128(be128 *dst, const u128 *src) +static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - dst->a = cpu_to_be64(src->a); - dst->b = cpu_to_be64(src->b); + return glue_ecb_crypt_128bit(&serpent_dec, desc, dst, src, nbytes); } -static inline void be128_to_u128(u128 *dst, const be128 *src) +static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - dst->a = be64_to_cpu(src->a); - dst->b = be64_to_cpu(src->b); + return glue_cbc_encrypt_128bit(GLUE_FUNC_CAST(__serpent_encrypt), desc, + dst, src, nbytes); } -static inline void u128_inc(u128 *i) +static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - i->b++; - if (!i->b) - i->a++; + return glue_cbc_decrypt_128bit(&serpent_dec_cbc, desc, dst, src, + nbytes); } -static void ctr_crypt_final(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - u8 *ctrblk = walk->iv; - u8 keystream[SERPENT_BLOCK_SIZE]; - u8 *src = walk->src.virt.addr; - u8 *dst = walk->dst.virt.addr; - unsigned int nbytes = walk->nbytes; - - __serpent_encrypt(ctx, keystream, ctrblk); - crypto_xor(keystream, src, nbytes); - memcpy(dst, keystream, nbytes); - - crypto_inc(ctrblk, SERPENT_BLOCK_SIZE); + return glue_ctr_crypt_128bit(&serpent_ctr, desc, dst, src, nbytes); } -static unsigned int __ctr_crypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static inline bool serpent_fpu_begin(bool fpu_enabled, unsigned int nbytes) { - struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = SERPENT_BLOCK_SIZE; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 ctrblk; - be128 ctrblocks[SERPENT_PARALLEL_BLOCKS]; - int i; - - be128_to_u128(&ctrblk, (be128 *)walk->iv); - - /* Process multi-block batch */ - if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) { - do { - /* create ctrblks for parallel encrypt */ - for (i = 0; i < SERPENT_PARALLEL_BLOCKS; i++) { - if (dst != src) - dst[i] = src[i]; - - u128_to_be128(&ctrblocks[i], &ctrblk); - u128_inc(&ctrblk); - } - - serpent_enc_blk_xway_xor(ctx, (u8 *)dst, - (u8 *)ctrblocks); - - src += SERPENT_PARALLEL_BLOCKS; - dst += SERPENT_PARALLEL_BLOCKS; - nbytes -= bsize * SERPENT_PARALLEL_BLOCKS; - } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS); - - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - do { - if (dst != src) - *dst = *src; - - u128_to_be128(&ctrblocks[0], &ctrblk); - u128_inc(&ctrblk); - - __serpent_encrypt(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks); - u128_xor(dst, dst, (u128 *)ctrblocks); - - src += 1; - dst += 1; - nbytes -= bsize; - } while (nbytes >= bsize); - -done: - u128_to_be128((be128 *)walk->iv, &ctrblk); - return nbytes; + return glue_fpu_begin(SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS, + NULL, fpu_enabled, nbytes); } -static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static inline void serpent_fpu_end(bool fpu_enabled) { - bool fpu_enabled = false; - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt_block(desc, &walk, SERPENT_BLOCK_SIZE); - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; - - while ((nbytes = walk.nbytes) >= SERPENT_BLOCK_SIZE) { - fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes); - nbytes = __ctr_crypt(desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - serpent_fpu_end(fpu_enabled); - - if (walk.nbytes) { - ctr_crypt_final(desc, &walk); - err = blkcipher_walk_done(desc, &walk, 0); - } - - return err; + glue_fpu_end(fpu_enabled); } struct crypt_priv { diff --git a/crypto/Kconfig b/crypto/Kconfig index 92b46970c856..a86c2fb92ea9 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -842,6 +842,7 @@ config CRYPTO_SERPENT_AVX_X86_64 select CRYPTO_ALGAPI select CRYPTO_CRYPTD select CRYPTO_ABLK_HELPER_X86 + select CRYPTO_GLUE_HELPER_X86 select CRYPTO_SERPENT select CRYPTO_LRW select CRYPTO_XTS -- cgit v1.2.3 From 964263afdcbf9d1e85c021acfff0cc68dd168475 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 18 Jun 2012 14:07:29 +0300 Subject: crypto: camellia-x86_64 - remove duplicated glue code and use shared glue code from glue_helper Now that shared glue code is available, convert camellia-x86_64 to use it. Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/camellia_glue.c | 355 ++++++++++------------------------------ crypto/Kconfig | 1 + 2 files changed, 87 insertions(+), 269 deletions(-) (limited to 'arch') diff --git a/arch/x86/crypto/camellia_glue.c b/arch/x86/crypto/camellia_glue.c index 3306dc0b139e..eeb2b3b743e9 100644 --- a/arch/x86/crypto/camellia_glue.c +++ b/arch/x86/crypto/camellia_glue.c @@ -5,10 +5,6 @@ * * Camellia parts based on code by: * Copyright (C) 2006 NTT (Nippon Telegraph and Telephone Corporation) - * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by: - * Copyright (c) 2006 Herbert Xu - * CTR part based on code (crypto/ctr.c) by: - * (C) Copyright IBM Corp. 2007 - Joy Latten * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,9 +30,9 @@ #include #include #include -#include #include #include +#include #define CAMELLIA_MIN_KEY_SIZE 16 #define CAMELLIA_MAX_KEY_SIZE 32 @@ -1312,307 +1308,128 @@ static int camellia_setkey(struct crypto_tfm *tfm, const u8 *in_key, &tfm->crt_flags); } -static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk, - void (*fn)(struct camellia_ctx *, u8 *, const u8 *), - void (*fn_2way)(struct camellia_ctx *, u8 *, const u8 *)) +static void camellia_decrypt_cbc_2way(void *ctx, u128 *dst, const u128 *src) { - struct camellia_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - unsigned int bsize = CAMELLIA_BLOCK_SIZE; - unsigned int nbytes; - int err; - - err = blkcipher_walk_virt(desc, walk); - - while ((nbytes = walk->nbytes)) { - u8 *wsrc = walk->src.virt.addr; - u8 *wdst = walk->dst.virt.addr; - - /* Process two block batch */ - if (nbytes >= bsize * 2) { - do { - fn_2way(ctx, wdst, wsrc); - - wsrc += bsize * 2; - wdst += bsize * 2; - nbytes -= bsize * 2; - } while (nbytes >= bsize * 2); - - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - do { - fn(ctx, wdst, wsrc); - - wsrc += bsize; - wdst += bsize; - nbytes -= bsize; - } while (nbytes >= bsize); - -done: - err = blkcipher_walk_done(desc, walk, nbytes); - } - - return err; -} - -static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) -{ - struct blkcipher_walk walk; - - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_crypt(desc, &walk, camellia_enc_blk, camellia_enc_blk_2way); -} + u128 iv = *src; -static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) -{ - struct blkcipher_walk walk; - - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_crypt(desc, &walk, camellia_dec_blk, camellia_dec_blk_2way); -} + camellia_dec_blk_2way(ctx, (u8 *)dst, (u8 *)src); -static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - struct camellia_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - unsigned int bsize = CAMELLIA_BLOCK_SIZE; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 *iv = (u128 *)walk->iv; - - do { - u128_xor(dst, src, iv); - camellia_enc_blk(ctx, (u8 *)dst, (u8 *)dst); - iv = dst; - - src += 1; - dst += 1; - nbytes -= bsize; - } while (nbytes >= bsize); - - u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv); - return nbytes; + u128_xor(&dst[1], &dst[1], &iv); } -static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static void camellia_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv) { - struct blkcipher_walk walk; - int err; + be128 ctrblk; - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); + if (dst != src) + *dst = *src; - while ((nbytes = walk.nbytes)) { - nbytes = __cbc_encrypt(desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } + u128_to_be128(&ctrblk, iv); + u128_inc(iv); - return err; + camellia_enc_blk_xor(ctx, (u8 *)dst, (u8 *)&ctrblk); } -static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src, + u128 *iv) { - struct camellia_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - unsigned int bsize = CAMELLIA_BLOCK_SIZE; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 ivs[2 - 1]; - u128 last_iv; + be128 ctrblks[2]; - /* Start of the last block. */ - src += nbytes / bsize - 1; - dst += nbytes / bsize - 1; - - last_iv = *src; - - /* Process two block batch */ - if (nbytes >= bsize * 2) { - do { - nbytes -= bsize * (2 - 1); - src -= 2 - 1; - dst -= 2 - 1; - - ivs[0] = src[0]; - - camellia_dec_blk_2way(ctx, (u8 *)dst, (u8 *)src); - - u128_xor(dst + 1, dst + 1, ivs + 0); - - nbytes -= bsize; - if (nbytes < bsize) - goto done; - - u128_xor(dst, dst, src - 1); - src -= 1; - dst -= 1; - } while (nbytes >= bsize * 2); - - if (nbytes < bsize) - goto done; + if (dst != src) { + dst[0] = src[0]; + dst[1] = src[1]; } - /* Handle leftovers */ - for (;;) { - camellia_dec_blk(ctx, (u8 *)dst, (u8 *)src); - - nbytes -= bsize; - if (nbytes < bsize) - break; + u128_to_be128(&ctrblks[0], iv); + u128_inc(iv); + u128_to_be128(&ctrblks[1], iv); + u128_inc(iv); - u128_xor(dst, dst, src - 1); - src -= 1; - dst -= 1; - } - -done: - u128_xor(dst, dst, (u128 *)walk->iv); - *(u128 *)walk->iv = last_iv; - - return nbytes; + camellia_enc_blk_xor_2way(ctx, (u8 *)dst, (u8 *)ctrblks); } -static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) -{ - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); +static const struct common_glue_ctx camellia_enc = { + .num_funcs = 2, + .fpu_blocks_limit = -1, + + .funcs = { { + .num_blocks = 2, + .fn_u = { .ecb = GLUE_FUNC_CAST(camellia_enc_blk_2way) } + }, { + .num_blocks = 1, + .fn_u = { .ecb = GLUE_FUNC_CAST(camellia_enc_blk) } + } } +}; - while ((nbytes = walk.nbytes)) { - nbytes = __cbc_decrypt(desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } +static const struct common_glue_ctx camellia_ctr = { + .num_funcs = 2, + .fpu_blocks_limit = -1, + + .funcs = { { + .num_blocks = 2, + .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_crypt_ctr_2way) } + }, { + .num_blocks = 1, + .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_crypt_ctr) } + } } +}; - return err; -} +static const struct common_glue_ctx camellia_dec = { + .num_funcs = 2, + .fpu_blocks_limit = -1, + + .funcs = { { + .num_blocks = 2, + .fn_u = { .ecb = GLUE_FUNC_CAST(camellia_dec_blk_2way) } + }, { + .num_blocks = 1, + .fn_u = { .ecb = GLUE_FUNC_CAST(camellia_dec_blk) } + } } +}; -static inline void u128_to_be128(be128 *dst, const u128 *src) -{ - dst->a = cpu_to_be64(src->a); - dst->b = cpu_to_be64(src->b); -} +static const struct common_glue_ctx camellia_dec_cbc = { + .num_funcs = 2, + .fpu_blocks_limit = -1, + + .funcs = { { + .num_blocks = 2, + .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_decrypt_cbc_2way) } + }, { + .num_blocks = 1, + .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_dec_blk) } + } } +}; -static inline void be128_to_u128(u128 *dst, const be128 *src) +static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - dst->a = be64_to_cpu(src->a); - dst->b = be64_to_cpu(src->b); + return glue_ecb_crypt_128bit(&camellia_enc, desc, dst, src, nbytes); } -static inline void u128_inc(u128 *i) +static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - i->b++; - if (!i->b) - i->a++; + return glue_ecb_crypt_128bit(&camellia_dec, desc, dst, src, nbytes); } -static void ctr_crypt_final(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - struct camellia_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - u8 keystream[CAMELLIA_BLOCK_SIZE]; - u8 *src = walk->src.virt.addr; - u8 *dst = walk->dst.virt.addr; - unsigned int nbytes = walk->nbytes; - u128 ctrblk; - - memcpy(keystream, src, nbytes); - camellia_enc_blk_xor(ctx, keystream, walk->iv); - memcpy(dst, keystream, nbytes); - - be128_to_u128(&ctrblk, (be128 *)walk->iv); - u128_inc(&ctrblk); - u128_to_be128((be128 *)walk->iv, &ctrblk); + return glue_cbc_encrypt_128bit(GLUE_FUNC_CAST(camellia_enc_blk), desc, + dst, src, nbytes); } -static unsigned int __ctr_crypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - struct camellia_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - unsigned int bsize = CAMELLIA_BLOCK_SIZE; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 ctrblk; - be128 ctrblocks[2]; - - be128_to_u128(&ctrblk, (be128 *)walk->iv); - - /* Process two block batch */ - if (nbytes >= bsize * 2) { - do { - if (dst != src) { - dst[0] = src[0]; - dst[1] = src[1]; - } - - /* create ctrblks for parallel encrypt */ - u128_to_be128(&ctrblocks[0], &ctrblk); - u128_inc(&ctrblk); - u128_to_be128(&ctrblocks[1], &ctrblk); - u128_inc(&ctrblk); - - camellia_enc_blk_xor_2way(ctx, (u8 *)dst, - (u8 *)ctrblocks); - - src += 2; - dst += 2; - nbytes -= bsize * 2; - } while (nbytes >= bsize * 2); - - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - do { - if (dst != src) - *dst = *src; - - u128_to_be128(&ctrblocks[0], &ctrblk); - u128_inc(&ctrblk); - - camellia_enc_blk_xor(ctx, (u8 *)dst, (u8 *)ctrblocks); - - src += 1; - dst += 1; - nbytes -= bsize; - } while (nbytes >= bsize); - -done: - u128_to_be128((be128 *)walk->iv, &ctrblk); - return nbytes; + return glue_cbc_decrypt_128bit(&camellia_dec_cbc, desc, dst, src, + nbytes); } static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt_block(desc, &walk, CAMELLIA_BLOCK_SIZE); - - while ((nbytes = walk.nbytes) >= CAMELLIA_BLOCK_SIZE) { - nbytes = __ctr_crypt(desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - if (walk.nbytes) { - ctr_crypt_final(desc, &walk); - err = blkcipher_walk_done(desc, &walk, 0); - } - - return err; + return glue_ctr_crypt_128bit(&camellia_ctr, desc, dst, src, nbytes); } static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) diff --git a/crypto/Kconfig b/crypto/Kconfig index a86c2fb92ea9..72828fafe09f 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -671,6 +671,7 @@ config CRYPTO_CAMELLIA_X86_64 depends on X86 && 64BIT depends on CRYPTO select CRYPTO_ALGAPI + select CRYPTO_GLUE_HELPER_X86 select CRYPTO_LRW select CRYPTO_XTS help -- cgit v1.2.3 From 414cb5e7cc6e258fe36e2c3cc3ef1ff2e246c0e3 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 18 Jun 2012 14:07:34 +0300 Subject: crypto: twofish-x86_64-3way - remove duplicated glue code and use shared glue code from glue_helper Now that shared glue code is available, convert twofish-x86_64-3way to use it. Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/twofish_glue_3way.c | 365 +++++++++--------------------------- crypto/Kconfig | 1 + 2 files changed, 94 insertions(+), 272 deletions(-) (limited to 'arch') diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c index 77e4e55a2660..25bf5e9b0067 100644 --- a/arch/x86/crypto/twofish_glue_3way.c +++ b/arch/x86/crypto/twofish_glue_3way.c @@ -3,11 +3,6 @@ * * Copyright (c) 2011 Jussi Kivilinna * - * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by: - * Copyright (c) 2006 Herbert Xu - * CTR part based on code (crypto/ctr.c) by: - * (C) Copyright IBM Corp. 2007 - Joy Latten - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -33,6 +28,7 @@ #include #include #include +#include #include #include @@ -62,311 +58,136 @@ static inline void twofish_enc_blk_xor_3way(struct twofish_ctx *ctx, u8 *dst, __twofish_enc_blk_3way(ctx, dst, src, true); } -static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk, - void (*fn)(struct twofish_ctx *, u8 *, const u8 *), - void (*fn_3way)(struct twofish_ctx *, u8 *, const u8 *)) +static void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src) { - struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - unsigned int bsize = TF_BLOCK_SIZE; - unsigned int nbytes; - int err; - - err = blkcipher_walk_virt(desc, walk); - - while ((nbytes = walk->nbytes)) { - u8 *wsrc = walk->src.virt.addr; - u8 *wdst = walk->dst.virt.addr; - - /* Process three block batch */ - if (nbytes >= bsize * 3) { - do { - fn_3way(ctx, wdst, wsrc); + u128 ivs[2]; - wsrc += bsize * 3; - wdst += bsize * 3; - nbytes -= bsize * 3; - } while (nbytes >= bsize * 3); + ivs[0] = src[0]; + ivs[1] = src[1]; - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - do { - fn(ctx, wdst, wsrc); - - wsrc += bsize; - wdst += bsize; - nbytes -= bsize; - } while (nbytes >= bsize); - -done: - err = blkcipher_walk_done(desc, walk, nbytes); - } + twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src); - return err; + u128_xor(&dst[1], &dst[1], &ivs[0]); + u128_xor(&dst[2], &dst[2], &ivs[1]); } -static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv) { - struct blkcipher_walk walk; + be128 ctrblk; - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_crypt(desc, &walk, twofish_enc_blk, twofish_enc_blk_3way); -} + if (dst != src) + *dst = *src; -static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) -{ - struct blkcipher_walk walk; + u128_to_be128(&ctrblk, iv); + u128_inc(iv); - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_crypt(desc, &walk, twofish_dec_blk, twofish_dec_blk_3way); + twofish_enc_blk(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk); + u128_xor(dst, dst, (u128 *)&ctrblk); } -static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src, + u128 *iv) { - struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - unsigned int bsize = TF_BLOCK_SIZE; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 *iv = (u128 *)walk->iv; - - do { - u128_xor(dst, src, iv); - twofish_enc_blk(ctx, (u8 *)dst, (u8 *)dst); - iv = dst; - - src += 1; - dst += 1; - nbytes -= bsize; - } while (nbytes >= bsize); - - u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv); - return nbytes; -} + be128 ctrblks[3]; -static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) -{ - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); - - while ((nbytes = walk.nbytes)) { - nbytes = __cbc_encrypt(desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - return err; -} - -static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - unsigned int bsize = TF_BLOCK_SIZE; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 ivs[3 - 1]; - u128 last_iv; - - /* Start of the last block. */ - src += nbytes / bsize - 1; - dst += nbytes / bsize - 1; - - last_iv = *src; - - /* Process three block batch */ - if (nbytes >= bsize * 3) { - do { - nbytes -= bsize * (3 - 1); - src -= 3 - 1; - dst -= 3 - 1; - - ivs[0] = src[0]; - ivs[1] = src[1]; - - twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src); - - u128_xor(dst + 1, dst + 1, ivs + 0); - u128_xor(dst + 2, dst + 2, ivs + 1); - - nbytes -= bsize; - if (nbytes < bsize) - goto done; - - u128_xor(dst, dst, src - 1); - src -= 1; - dst -= 1; - } while (nbytes >= bsize * 3); - - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - for (;;) { - twofish_dec_blk(ctx, (u8 *)dst, (u8 *)src); - - nbytes -= bsize; - if (nbytes < bsize) - break; - - u128_xor(dst, dst, src - 1); - src -= 1; - dst -= 1; + if (dst != src) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; } -done: - u128_xor(dst, dst, (u128 *)walk->iv); - *(u128 *)walk->iv = last_iv; + u128_to_be128(&ctrblks[0], iv); + u128_inc(iv); + u128_to_be128(&ctrblks[1], iv); + u128_inc(iv); + u128_to_be128(&ctrblks[2], iv); + u128_inc(iv); - return nbytes; + twofish_enc_blk_xor_3way(ctx, (u8 *)dst, (u8 *)ctrblks); } -static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) -{ - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); +static const struct common_glue_ctx twofish_enc = { + .num_funcs = 2, + .fpu_blocks_limit = -1, + + .funcs = { { + .num_blocks = 3, + .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_3way) } + }, { + .num_blocks = 1, + .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk) } + } } +}; - while ((nbytes = walk.nbytes)) { - nbytes = __cbc_decrypt(desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } +static const struct common_glue_ctx twofish_ctr = { + .num_funcs = 2, + .fpu_blocks_limit = -1, + + .funcs = { { + .num_blocks = 3, + .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_ctr_3way) } + }, { + .num_blocks = 1, + .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_ctr) } + } } +}; - return err; -} +static const struct common_glue_ctx twofish_dec = { + .num_funcs = 2, + .fpu_blocks_limit = -1, + + .funcs = { { + .num_blocks = 3, + .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_3way) } + }, { + .num_blocks = 1, + .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk) } + } } +}; -static inline void u128_to_be128(be128 *dst, const u128 *src) -{ - dst->a = cpu_to_be64(src->a); - dst->b = cpu_to_be64(src->b); -} +static const struct common_glue_ctx twofish_dec_cbc = { + .num_funcs = 2, + .fpu_blocks_limit = -1, + + .funcs = { { + .num_blocks = 3, + .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_3way) } + }, { + .num_blocks = 1, + .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk) } + } } +}; -static inline void be128_to_u128(u128 *dst, const be128 *src) +static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - dst->a = be64_to_cpu(src->a); - dst->b = be64_to_cpu(src->b); + return glue_ecb_crypt_128bit(&twofish_enc, desc, dst, src, nbytes); } -static inline void u128_inc(u128 *i) +static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - i->b++; - if (!i->b) - i->a++; + return glue_ecb_crypt_128bit(&twofish_dec, desc, dst, src, nbytes); } -static void ctr_crypt_final(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - u8 *ctrblk = walk->iv; - u8 keystream[TF_BLOCK_SIZE]; - u8 *src = walk->src.virt.addr; - u8 *dst = walk->dst.virt.addr; - unsigned int nbytes = walk->nbytes; - - twofish_enc_blk(ctx, keystream, ctrblk); - crypto_xor(keystream, src, nbytes); - memcpy(dst, keystream, nbytes); - - crypto_inc(ctrblk, TF_BLOCK_SIZE); + return glue_cbc_encrypt_128bit(GLUE_FUNC_CAST(twofish_enc_blk), desc, + dst, src, nbytes); } -static unsigned int __ctr_crypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - unsigned int bsize = TF_BLOCK_SIZE; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 ctrblk; - be128 ctrblocks[3]; - - be128_to_u128(&ctrblk, (be128 *)walk->iv); - - /* Process three block batch */ - if (nbytes >= bsize * 3) { - do { - if (dst != src) { - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; - } - - /* create ctrblks for parallel encrypt */ - u128_to_be128(&ctrblocks[0], &ctrblk); - u128_inc(&ctrblk); - u128_to_be128(&ctrblocks[1], &ctrblk); - u128_inc(&ctrblk); - u128_to_be128(&ctrblocks[2], &ctrblk); - u128_inc(&ctrblk); - - twofish_enc_blk_xor_3way(ctx, (u8 *)dst, - (u8 *)ctrblocks); - - src += 3; - dst += 3; - nbytes -= bsize * 3; - } while (nbytes >= bsize * 3); - - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - do { - if (dst != src) - *dst = *src; - - u128_to_be128(&ctrblocks[0], &ctrblk); - u128_inc(&ctrblk); - - twofish_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks); - u128_xor(dst, dst, (u128 *)ctrblocks); - - src += 1; - dst += 1; - nbytes -= bsize; - } while (nbytes >= bsize); - -done: - u128_to_be128((be128 *)walk->iv, &ctrblk); - return nbytes; + return glue_cbc_decrypt_128bit(&twofish_dec_cbc, desc, dst, src, + nbytes); } static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt_block(desc, &walk, TF_BLOCK_SIZE); - - while ((nbytes = walk.nbytes) >= TF_BLOCK_SIZE) { - nbytes = __ctr_crypt(desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - if (walk.nbytes) { - ctr_crypt_final(desc, &walk); - err = blkcipher_walk_done(desc, &walk, 0); - } - - return err; + return glue_ctr_crypt_128bit(&twofish_ctr, desc, dst, src, nbytes); } static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) diff --git a/crypto/Kconfig b/crypto/Kconfig index 72828fafe09f..fc559caaa9ad 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -935,6 +935,7 @@ config CRYPTO_TWOFISH_X86_64_3WAY select CRYPTO_ALGAPI select CRYPTO_TWOFISH_COMMON select CRYPTO_TWOFISH_X86_64 + select CRYPTO_GLUE_HELPER_X86 select CRYPTO_LRW select CRYPTO_XTS help -- cgit v1.2.3 From a7378d4e552ac139ae1cbbdfebfeaa9b18c948d0 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 18 Jun 2012 14:07:39 +0300 Subject: crypto: twofish-avx - remove duplicated glue code and use shared glue code from glue_helper Now that shared glue code is available, convert twofish-avx to use it. Cc: Johannes Goetzfried Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/twofish_avx_glue.c | 556 ++++++---------------------------- arch/x86/crypto/twofish_glue_3way.c | 46 +-- arch/x86/include/asm/crypto/twofish.h | 46 +++ crypto/Kconfig | 1 + 4 files changed, 162 insertions(+), 487 deletions(-) create mode 100644 arch/x86/include/asm/crypto/twofish.h (limited to 'arch') diff --git a/arch/x86/crypto/twofish_avx_glue.c b/arch/x86/crypto/twofish_avx_glue.c index cabe058eba14..782b67ddaf6a 100644 --- a/arch/x86/crypto/twofish_avx_glue.c +++ b/arch/x86/crypto/twofish_avx_glue.c @@ -4,9 +4,6 @@ * Copyright (C) 2012 Johannes Goetzfried * * - * Glue code based on serpent_sse2_glue.c by: - * Copyright (C) 2011 Jussi Kivilinna - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -39,38 +36,21 @@ #include #include #include +#include #include +#include #include #include #include - #define TWOFISH_PARALLEL_BLOCKS 8 -/* regular block cipher functions from twofish_x86_64 module */ -asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst, - const u8 *src); -asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst, - const u8 *src); - -/* 3-way parallel cipher functions from twofish_x86_64-3way module */ -asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, - const u8 *src, bool xor); -asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst, - const u8 *src); - static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, const u8 *src) { __twofish_enc_blk_3way(ctx, dst, src, false); } -static inline void twofish_enc_blk_3way_xor(struct twofish_ctx *ctx, u8 *dst, - const u8 *src) -{ - __twofish_enc_blk_3way(ctx, dst, src, true); -} - /* 8-way parallel cipher functions */ asmlinkage void __twofish_enc_blk_8way(struct twofish_ctx *ctx, u8 *dst, const u8 *src, bool xor); @@ -95,423 +75,142 @@ static inline void twofish_dec_blk_xway(struct twofish_ctx *ctx, u8 *dst, twofish_dec_blk_8way(ctx, dst, src); } - -static inline bool twofish_fpu_begin(bool fpu_enabled, unsigned int nbytes) +static void twofish_dec_blk_cbc_xway(void *ctx, u128 *dst, const u128 *src) { - if (fpu_enabled) - return true; + u128 ivs[TWOFISH_PARALLEL_BLOCKS - 1]; + unsigned int j; - /* AVX is only used when chunk to be processed is large enough, so - * do not enable FPU until it is necessary. - */ - if (nbytes < TF_BLOCK_SIZE * TWOFISH_PARALLEL_BLOCKS) - return false; + for (j = 0; j < TWOFISH_PARALLEL_BLOCKS - 1; j++) + ivs[j] = src[j]; - kernel_fpu_begin(); - return true; -} + twofish_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src); -static inline void twofish_fpu_end(bool fpu_enabled) -{ - if (fpu_enabled) - kernel_fpu_end(); + for (j = 0; j < TWOFISH_PARALLEL_BLOCKS - 1; j++) + u128_xor(dst + (j + 1), dst + (j + 1), ivs + j); } -static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk, - bool enc) +static void twofish_enc_blk_ctr_xway(void *ctx, u128 *dst, const u128 *src, + u128 *iv) { - bool fpu_enabled = false; - struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = TF_BLOCK_SIZE; - unsigned int nbytes; - int err; + be128 ctrblks[TWOFISH_PARALLEL_BLOCKS]; + unsigned int i; - err = blkcipher_walk_virt(desc, walk); - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + for (i = 0; i < TWOFISH_PARALLEL_BLOCKS; i++) { + if (dst != src) + dst[i] = src[i]; - while ((nbytes = walk->nbytes)) { - u8 *wsrc = walk->src.virt.addr; - u8 *wdst = walk->dst.virt.addr; - - fpu_enabled = twofish_fpu_begin(fpu_enabled, nbytes); - - /* Process multi-block batch */ - if (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS) { - do { - if (enc) - twofish_enc_blk_xway(ctx, wdst, wsrc); - else - twofish_dec_blk_xway(ctx, wdst, wsrc); - - wsrc += bsize * TWOFISH_PARALLEL_BLOCKS; - wdst += bsize * TWOFISH_PARALLEL_BLOCKS; - nbytes -= bsize * TWOFISH_PARALLEL_BLOCKS; - } while (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS); - - if (nbytes < bsize) - goto done; - } - - /* Process three block batch */ - if (nbytes >= bsize * 3) { - do { - if (enc) - twofish_enc_blk_3way(ctx, wdst, wsrc); - else - twofish_dec_blk_3way(ctx, wdst, wsrc); - - wsrc += bsize * 3; - wdst += bsize * 3; - nbytes -= bsize * 3; - } while (nbytes >= bsize * 3); - - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - do { - if (enc) - twofish_enc_blk(ctx, wdst, wsrc); - else - twofish_dec_blk(ctx, wdst, wsrc); - - wsrc += bsize; - wdst += bsize; - nbytes -= bsize; - } while (nbytes >= bsize); - -done: - err = blkcipher_walk_done(desc, walk, nbytes); + u128_to_be128(&ctrblks[i], iv); + u128_inc(iv); } - twofish_fpu_end(fpu_enabled); - return err; + twofish_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks); } +static const struct common_glue_ctx twofish_enc = { + .num_funcs = 3, + .fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS, + + .funcs = { { + .num_blocks = TWOFISH_PARALLEL_BLOCKS, + .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_xway) } + }, { + .num_blocks = 3, + .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_3way) } + }, { + .num_blocks = 1, + .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk) } + } } +}; + +static const struct common_glue_ctx twofish_ctr = { + .num_funcs = 3, + .fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS, + + .funcs = { { + .num_blocks = TWOFISH_PARALLEL_BLOCKS, + .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr_xway) } + }, { + .num_blocks = 3, + .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr_3way) } + }, { + .num_blocks = 1, + .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr) } + } } +}; + +static const struct common_glue_ctx twofish_dec = { + .num_funcs = 3, + .fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS, + + .funcs = { { + .num_blocks = TWOFISH_PARALLEL_BLOCKS, + .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_xway) } + }, { + .num_blocks = 3, + .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_3way) } + }, { + .num_blocks = 1, + .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk) } + } } +}; + +static const struct common_glue_ctx twofish_dec_cbc = { + .num_funcs = 3, + .fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS, + + .funcs = { { + .num_blocks = TWOFISH_PARALLEL_BLOCKS, + .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_xway) } + }, { + .num_blocks = 3, + .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_3way) } + }, { + .num_blocks = 1, + .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk) } + } } +}; + static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { - struct blkcipher_walk walk; - - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_crypt(desc, &walk, true); + return glue_ecb_crypt_128bit(&twofish_enc, desc, dst, src, nbytes); } static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { - struct blkcipher_walk walk; - - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_crypt(desc, &walk, false); -} - -static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = TF_BLOCK_SIZE; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 *iv = (u128 *)walk->iv; - - do { - u128_xor(dst, src, iv); - twofish_enc_blk(ctx, (u8 *)dst, (u8 *)dst); - iv = dst; - - src += 1; - dst += 1; - nbytes -= bsize; - } while (nbytes >= bsize); - - u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv); - return nbytes; + return glue_ecb_crypt_128bit(&twofish_dec, desc, dst, src, nbytes); } static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); - - while ((nbytes = walk.nbytes)) { - nbytes = __cbc_encrypt(desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - return err; -} - -static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = TF_BLOCK_SIZE; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 ivs[TWOFISH_PARALLEL_BLOCKS - 1]; - u128 last_iv; - int i; - - /* Start of the last block. */ - src += nbytes / bsize - 1; - dst += nbytes / bsize - 1; - - last_iv = *src; - - /* Process multi-block batch */ - if (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS) { - do { - nbytes -= bsize * (TWOFISH_PARALLEL_BLOCKS - 1); - src -= TWOFISH_PARALLEL_BLOCKS - 1; - dst -= TWOFISH_PARALLEL_BLOCKS - 1; - - for (i = 0; i < TWOFISH_PARALLEL_BLOCKS - 1; i++) - ivs[i] = src[i]; - - twofish_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src); - - for (i = 0; i < TWOFISH_PARALLEL_BLOCKS - 1; i++) - u128_xor(dst + (i + 1), dst + (i + 1), ivs + i); - - nbytes -= bsize; - if (nbytes < bsize) - goto done; - - u128_xor(dst, dst, src - 1); - src -= 1; - dst -= 1; - } while (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS); - - if (nbytes < bsize) - goto done; - } - - /* Process three block batch */ - if (nbytes >= bsize * 3) { - do { - nbytes -= bsize * (3 - 1); - src -= 3 - 1; - dst -= 3 - 1; - - ivs[0] = src[0]; - ivs[1] = src[1]; - - twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src); - - u128_xor(dst + 1, dst + 1, ivs + 0); - u128_xor(dst + 2, dst + 2, ivs + 1); - - nbytes -= bsize; - if (nbytes < bsize) - goto done; - - u128_xor(dst, dst, src - 1); - src -= 1; - dst -= 1; - } while (nbytes >= bsize * 3); - - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - for (;;) { - twofish_dec_blk(ctx, (u8 *)dst, (u8 *)src); - - nbytes -= bsize; - if (nbytes < bsize) - break; - - u128_xor(dst, dst, src - 1); - src -= 1; - dst -= 1; - } - -done: - u128_xor(dst, dst, (u128 *)walk->iv); - *(u128 *)walk->iv = last_iv; - - return nbytes; + return glue_cbc_encrypt_128bit(GLUE_FUNC_CAST(twofish_enc_blk), desc, + dst, src, nbytes); } static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { - bool fpu_enabled = false; - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; - - while ((nbytes = walk.nbytes)) { - fpu_enabled = twofish_fpu_begin(fpu_enabled, nbytes); - nbytes = __cbc_decrypt(desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - twofish_fpu_end(fpu_enabled); - return err; -} - -static inline void u128_to_be128(be128 *dst, const u128 *src) -{ - dst->a = cpu_to_be64(src->a); - dst->b = cpu_to_be64(src->b); + return glue_cbc_decrypt_128bit(&twofish_dec_cbc, desc, dst, src, + nbytes); } -static inline void be128_to_u128(u128 *dst, const be128 *src) -{ - dst->a = be64_to_cpu(src->a); - dst->b = be64_to_cpu(src->b); -} - -static inline void u128_inc(u128 *i) +static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - i->b++; - if (!i->b) - i->a++; + return glue_ctr_crypt_128bit(&twofish_ctr, desc, dst, src, nbytes); } -static void ctr_crypt_final(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) +static inline bool twofish_fpu_begin(bool fpu_enabled, unsigned int nbytes) { - struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - u8 *ctrblk = walk->iv; - u8 keystream[TF_BLOCK_SIZE]; - u8 *src = walk->src.virt.addr; - u8 *dst = walk->dst.virt.addr; - unsigned int nbytes = walk->nbytes; - - twofish_enc_blk(ctx, keystream, ctrblk); - crypto_xor(keystream, src, nbytes); - memcpy(dst, keystream, nbytes); - - crypto_inc(ctrblk, TF_BLOCK_SIZE); + return glue_fpu_begin(TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS, NULL, + fpu_enabled, nbytes); } -static unsigned int __ctr_crypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); - const unsigned int bsize = TF_BLOCK_SIZE; - unsigned int nbytes = walk->nbytes; - u128 *src = (u128 *)walk->src.virt.addr; - u128 *dst = (u128 *)walk->dst.virt.addr; - u128 ctrblk; - be128 ctrblocks[TWOFISH_PARALLEL_BLOCKS]; - int i; - - be128_to_u128(&ctrblk, (be128 *)walk->iv); - - /* Process multi-block batch */ - if (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS) { - do { - /* create ctrblks for parallel encrypt */ - for (i = 0; i < TWOFISH_PARALLEL_BLOCKS; i++) { - if (dst != src) - dst[i] = src[i]; - - u128_to_be128(&ctrblocks[i], &ctrblk); - u128_inc(&ctrblk); - } - - twofish_enc_blk_xway_xor(ctx, (u8 *)dst, - (u8 *)ctrblocks); - - src += TWOFISH_PARALLEL_BLOCKS; - dst += TWOFISH_PARALLEL_BLOCKS; - nbytes -= bsize * TWOFISH_PARALLEL_BLOCKS; - } while (nbytes >= bsize * TWOFISH_PARALLEL_BLOCKS); - - if (nbytes < bsize) - goto done; - } - - /* Process three block batch */ - if (nbytes >= bsize * 3) { - do { - if (dst != src) { - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; - } - - /* create ctrblks for parallel encrypt */ - u128_to_be128(&ctrblocks[0], &ctrblk); - u128_inc(&ctrblk); - u128_to_be128(&ctrblocks[1], &ctrblk); - u128_inc(&ctrblk); - u128_to_be128(&ctrblocks[2], &ctrblk); - u128_inc(&ctrblk); - - twofish_enc_blk_3way_xor(ctx, (u8 *)dst, - (u8 *)ctrblocks); - - src += 3; - dst += 3; - nbytes -= bsize * 3; - } while (nbytes >= bsize * 3); - - if (nbytes < bsize) - goto done; - } - - /* Handle leftovers */ - do { - if (dst != src) - *dst = *src; - - u128_to_be128(&ctrblocks[0], &ctrblk); - u128_inc(&ctrblk); - - twofish_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks); - u128_xor(dst, dst, (u128 *)ctrblocks); - - src += 1; - dst += 1; - nbytes -= bsize; - } while (nbytes >= bsize); - -done: - u128_to_be128((be128 *)walk->iv, &ctrblk); - return nbytes; -} - -static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static inline void twofish_fpu_end(bool fpu_enabled) { - bool fpu_enabled = false; - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt_block(desc, &walk, TF_BLOCK_SIZE); - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; - - while ((nbytes = walk.nbytes) >= TF_BLOCK_SIZE) { - fpu_enabled = twofish_fpu_begin(fpu_enabled, nbytes); - nbytes = __ctr_crypt(desc, &walk); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - twofish_fpu_end(fpu_enabled); - - if (walk.nbytes) { - ctr_crypt_final(desc, &walk); - err = blkcipher_walk_done(desc, &walk, 0); - } - - return err; + glue_fpu_end(fpu_enabled); } struct crypt_priv { @@ -563,26 +262,6 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) twofish_dec_blk(ctx->ctx, srcdst, srcdst); } -struct twofish_lrw_ctx { - struct lrw_table_ctx lrw_table; - struct twofish_ctx twofish_ctx; -}; - -static int lrw_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) -{ - struct twofish_lrw_ctx *ctx = crypto_tfm_ctx(tfm); - int err; - - err = __twofish_setkey(&ctx->twofish_ctx, key, - keylen - TF_BLOCK_SIZE, &tfm->crt_flags); - if (err) - return err; - - return lrw_init_table(&ctx->lrw_table, key + keylen - - TF_BLOCK_SIZE); -} - static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { @@ -635,43 +314,6 @@ static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, return ret; } -static void lrw_exit_tfm(struct crypto_tfm *tfm) -{ - struct twofish_lrw_ctx *ctx = crypto_tfm_ctx(tfm); - - lrw_free_table(&ctx->lrw_table); -} - -struct twofish_xts_ctx { - struct twofish_ctx tweak_ctx; - struct twofish_ctx crypt_ctx; -}; - -static int xts_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) -{ - struct twofish_xts_ctx *ctx = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; - int err; - - /* key consists of keys of equal size concatenated, therefore - * the length must be even - */ - if (keylen % 2) { - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; - return -EINVAL; - } - - /* first half of xts-key is for crypt */ - err = __twofish_setkey(&ctx->crypt_ctx, key, keylen / 2, flags); - if (err) - return err; - - /* second half of xts-key is for tweak */ - return __twofish_setkey(&ctx->tweak_ctx, - key + keylen / 2, keylen / 2, flags); -} - static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { @@ -798,7 +440,7 @@ static struct crypto_alg twofish_algs[10] = { { .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(twofish_algs[3].cra_list), - .cra_exit = lrw_exit_tfm, + .cra_exit = lrw_twofish_exit_tfm, .cra_u = { .blkcipher = { .min_keysize = TF_MIN_KEY_SIZE + diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c index 25bf5e9b0067..15f9347316c8 100644 --- a/arch/x86/crypto/twofish_glue_3way.c +++ b/arch/x86/crypto/twofish_glue_3way.c @@ -28,22 +28,12 @@ #include #include #include +#include #include #include #include -/* regular block cipher functions from twofish_x86_64 module */ -asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst, - const u8 *src); -asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst, - const u8 *src); - -/* 3-way parallel cipher functions */ -asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, - const u8 *src, bool xor); EXPORT_SYMBOL_GPL(__twofish_enc_blk_3way); -asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst, - const u8 *src); EXPORT_SYMBOL_GPL(twofish_dec_blk_3way); static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, @@ -58,7 +48,7 @@ static inline void twofish_enc_blk_xor_3way(struct twofish_ctx *ctx, u8 *dst, __twofish_enc_blk_3way(ctx, dst, src, true); } -static void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src) +void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src) { u128 ivs[2]; @@ -70,8 +60,9 @@ static void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src) u128_xor(&dst[1], &dst[1], &ivs[0]); u128_xor(&dst[2], &dst[2], &ivs[1]); } +EXPORT_SYMBOL_GPL(twofish_dec_blk_cbc_3way); -static void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv) +void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv) { be128 ctrblk; @@ -84,8 +75,9 @@ static void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv) twofish_enc_blk(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk); u128_xor(dst, dst, (u128 *)&ctrblk); } +EXPORT_SYMBOL_GPL(twofish_enc_blk_ctr); -static void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src, +void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src, u128 *iv) { be128 ctrblks[3]; @@ -105,6 +97,7 @@ static void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src, twofish_enc_blk_xor_3way(ctx, (u8 *)dst, (u8 *)ctrblks); } +EXPORT_SYMBOL_GPL(twofish_enc_blk_ctr_3way); static const struct common_glue_ctx twofish_enc = { .num_funcs = 2, @@ -220,13 +213,8 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) twofish_dec_blk(ctx, srcdst, srcdst); } -struct twofish_lrw_ctx { - struct lrw_table_ctx lrw_table; - struct twofish_ctx twofish_ctx; -}; - -static int lrw_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) +int lrw_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen) { struct twofish_lrw_ctx *ctx = crypto_tfm_ctx(tfm); int err; @@ -238,6 +226,7 @@ static int lrw_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, return lrw_init_table(&ctx->lrw_table, key + keylen - TF_BLOCK_SIZE); } +EXPORT_SYMBOL_GPL(lrw_twofish_setkey); static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) @@ -273,20 +262,16 @@ static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, return lrw_crypt(desc, dst, src, nbytes, &req); } -static void lrw_exit_tfm(struct crypto_tfm *tfm) +void lrw_twofish_exit_tfm(struct crypto_tfm *tfm) { struct twofish_lrw_ctx *ctx = crypto_tfm_ctx(tfm); lrw_free_table(&ctx->lrw_table); } +EXPORT_SYMBOL_GPL(lrw_twofish_exit_tfm); -struct twofish_xts_ctx { - struct twofish_ctx tweak_ctx; - struct twofish_ctx crypt_ctx; -}; - -static int xts_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) +int xts_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen) { struct twofish_xts_ctx *ctx = crypto_tfm_ctx(tfm); u32 *flags = &tfm->crt_flags; @@ -309,6 +294,7 @@ static int xts_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, return __twofish_setkey(&ctx->tweak_ctx, key + keylen / 2, keylen / 2, flags); } +EXPORT_SYMBOL_GPL(xts_twofish_setkey); static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) @@ -419,7 +405,7 @@ static struct crypto_alg tf_algs[5] = { { .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(tf_algs[3].cra_list), - .cra_exit = lrw_exit_tfm, + .cra_exit = lrw_twofish_exit_tfm, .cra_u = { .blkcipher = { .min_keysize = TF_MIN_KEY_SIZE + TF_BLOCK_SIZE, diff --git a/arch/x86/include/asm/crypto/twofish.h b/arch/x86/include/asm/crypto/twofish.h new file mode 100644 index 000000000000..9d2c514bd5f9 --- /dev/null +++ b/arch/x86/include/asm/crypto/twofish.h @@ -0,0 +1,46 @@ +#ifndef ASM_X86_TWOFISH_H +#define ASM_X86_TWOFISH_H + +#include +#include +#include +#include + +struct twofish_lrw_ctx { + struct lrw_table_ctx lrw_table; + struct twofish_ctx twofish_ctx; +}; + +struct twofish_xts_ctx { + struct twofish_ctx tweak_ctx; + struct twofish_ctx crypt_ctx; +}; + +/* regular block cipher functions from twofish_x86_64 module */ +asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst, + const u8 *src); +asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst, + const u8 *src); + +/* 3-way parallel cipher functions */ +asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, + const u8 *src, bool xor); +asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst, + const u8 *src); + +/* helpers from twofish_x86_64-3way module */ +extern void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src); +extern void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, + u128 *iv); +extern void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src, + u128 *iv); + +extern int lrw_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen); + +extern void lrw_twofish_exit_tfm(struct crypto_tfm *tfm); + +extern int xts_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen); + +#endif /* ASM_X86_TWOFISH_H */ diff --git a/crypto/Kconfig b/crypto/Kconfig index fc559caaa9ad..02e303774691 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -958,6 +958,7 @@ config CRYPTO_TWOFISH_AVX_X86_64 select CRYPTO_ALGAPI select CRYPTO_CRYPTD select CRYPTO_ABLK_HELPER_X86 + select CRYPTO_GLUE_HELPER_X86 select CRYPTO_TWOFISH_COMMON select CRYPTO_TWOFISH_X86_64 select CRYPTO_TWOFISH_X86_64_3WAY -- cgit v1.2.3 From d4af0e9d6eef6ce53c1935ca6ee3c01889e3212d Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 18 Jun 2012 14:07:45 +0300 Subject: crypto: move arch/x86/include/asm/serpent-{sse2|avx}.h to arch/x86/include/asm/crypto/ Move serpent crypto headers to the new asm/crypto/ directory. Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/serpent_avx_glue.c | 2 +- arch/x86/crypto/serpent_sse2_glue.c | 2 +- arch/x86/include/asm/crypto/serpent-avx.h | 32 +++++++++++++++ arch/x86/include/asm/crypto/serpent-sse2.h | 63 ++++++++++++++++++++++++++++++ arch/x86/include/asm/serpent-avx.h | 32 --------------- arch/x86/include/asm/serpent-sse2.h | 63 ------------------------------ 6 files changed, 97 insertions(+), 97 deletions(-) create mode 100644 arch/x86/include/asm/crypto/serpent-avx.h create mode 100644 arch/x86/include/asm/crypto/serpent-sse2.h delete mode 100644 arch/x86/include/asm/serpent-avx.h delete mode 100644 arch/x86/include/asm/serpent-sse2.h (limited to 'arch') diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c index c61b91aa42a8..b36bdac237eb 100644 --- a/arch/x86/crypto/serpent_avx_glue.c +++ b/arch/x86/crypto/serpent_avx_glue.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c index 49a32eedf0c8..d679c8675f4a 100644 --- a/arch/x86/crypto/serpent_sse2_glue.c +++ b/arch/x86/crypto/serpent_sse2_glue.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/x86/include/asm/crypto/serpent-avx.h b/arch/x86/include/asm/crypto/serpent-avx.h new file mode 100644 index 000000000000..432deedd2945 --- /dev/null +++ b/arch/x86/include/asm/crypto/serpent-avx.h @@ -0,0 +1,32 @@ +#ifndef ASM_X86_SERPENT_AVX_H +#define ASM_X86_SERPENT_AVX_H + +#include +#include + +#define SERPENT_PARALLEL_BLOCKS 8 + +asmlinkage void __serpent_enc_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst, + const u8 *src, bool xor); +asmlinkage void serpent_dec_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst, + const u8 *src); + +static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_8way_avx(ctx, dst, src, false); +} + +static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_8way_avx(ctx, dst, src, true); +} + +static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + serpent_dec_blk_8way_avx(ctx, dst, src); +} + +#endif diff --git a/arch/x86/include/asm/crypto/serpent-sse2.h b/arch/x86/include/asm/crypto/serpent-sse2.h new file mode 100644 index 000000000000..e6e77dffbdab --- /dev/null +++ b/arch/x86/include/asm/crypto/serpent-sse2.h @@ -0,0 +1,63 @@ +#ifndef ASM_X86_SERPENT_SSE2_H +#define ASM_X86_SERPENT_SSE2_H + +#include +#include + +#ifdef CONFIG_X86_32 + +#define SERPENT_PARALLEL_BLOCKS 4 + +asmlinkage void __serpent_enc_blk_4way(struct serpent_ctx *ctx, u8 *dst, + const u8 *src, bool xor); +asmlinkage void serpent_dec_blk_4way(struct serpent_ctx *ctx, u8 *dst, + const u8 *src); + +static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_4way(ctx, dst, src, false); +} + +static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_4way(ctx, dst, src, true); +} + +static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + serpent_dec_blk_4way(ctx, dst, src); +} + +#else + +#define SERPENT_PARALLEL_BLOCKS 8 + +asmlinkage void __serpent_enc_blk_8way(struct serpent_ctx *ctx, u8 *dst, + const u8 *src, bool xor); +asmlinkage void serpent_dec_blk_8way(struct serpent_ctx *ctx, u8 *dst, + const u8 *src); + +static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_8way(ctx, dst, src, false); +} + +static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + __serpent_enc_blk_8way(ctx, dst, src, true); +} + +static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst, + const u8 *src) +{ + serpent_dec_blk_8way(ctx, dst, src); +} + +#endif + +#endif diff --git a/arch/x86/include/asm/serpent-avx.h b/arch/x86/include/asm/serpent-avx.h deleted file mode 100644 index 432deedd2945..000000000000 --- a/arch/x86/include/asm/serpent-avx.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef ASM_X86_SERPENT_AVX_H -#define ASM_X86_SERPENT_AVX_H - -#include -#include - -#define SERPENT_PARALLEL_BLOCKS 8 - -asmlinkage void __serpent_enc_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst, - const u8 *src, bool xor); -asmlinkage void serpent_dec_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst, - const u8 *src); - -static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - __serpent_enc_blk_8way_avx(ctx, dst, src, false); -} - -static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - __serpent_enc_blk_8way_avx(ctx, dst, src, true); -} - -static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - serpent_dec_blk_8way_avx(ctx, dst, src); -} - -#endif diff --git a/arch/x86/include/asm/serpent-sse2.h b/arch/x86/include/asm/serpent-sse2.h deleted file mode 100644 index e6e77dffbdab..000000000000 --- a/arch/x86/include/asm/serpent-sse2.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef ASM_X86_SERPENT_SSE2_H -#define ASM_X86_SERPENT_SSE2_H - -#include -#include - -#ifdef CONFIG_X86_32 - -#define SERPENT_PARALLEL_BLOCKS 4 - -asmlinkage void __serpent_enc_blk_4way(struct serpent_ctx *ctx, u8 *dst, - const u8 *src, bool xor); -asmlinkage void serpent_dec_blk_4way(struct serpent_ctx *ctx, u8 *dst, - const u8 *src); - -static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - __serpent_enc_blk_4way(ctx, dst, src, false); -} - -static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - __serpent_enc_blk_4way(ctx, dst, src, true); -} - -static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - serpent_dec_blk_4way(ctx, dst, src); -} - -#else - -#define SERPENT_PARALLEL_BLOCKS 8 - -asmlinkage void __serpent_enc_blk_8way(struct serpent_ctx *ctx, u8 *dst, - const u8 *src, bool xor); -asmlinkage void serpent_dec_blk_8way(struct serpent_ctx *ctx, u8 *dst, - const u8 *src); - -static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - __serpent_enc_blk_8way(ctx, dst, src, false); -} - -static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - __serpent_enc_blk_8way(ctx, dst, src, true); -} - -static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst, - const u8 *src) -{ - serpent_dec_blk_8way(ctx, dst, src); -} - -#endif - -#endif -- cgit v1.2.3 From 70ef2601feb09d40f4086d055700b7923b3c2d6f Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 18 Jun 2012 14:07:50 +0300 Subject: crypto: move arch/x86/include/asm/aes.h to arch/x86/include/asm/crypto/ Move AES header to the new asm/crypto directory. Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/aes_glue.c | 2 +- arch/x86/crypto/aesni-intel_glue.c | 2 +- arch/x86/include/asm/aes.h | 11 ----------- arch/x86/include/asm/crypto/aes.h | 11 +++++++++++ 4 files changed, 13 insertions(+), 13 deletions(-) delete mode 100644 arch/x86/include/asm/aes.h create mode 100644 arch/x86/include/asm/crypto/aes.h (limited to 'arch') diff --git a/arch/x86/crypto/aes_glue.c b/arch/x86/crypto/aes_glue.c index 8efcf42a9d7e..59b37deb8c8d 100644 --- a/arch/x86/crypto/aes_glue.c +++ b/arch/x86/crypto/aes_glue.c @@ -5,7 +5,7 @@ #include #include -#include +#include asmlinkage void aes_enc_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); asmlinkage void aes_dec_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 7c9d54d8dc4d..d6626152067d 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/include/asm/aes.h b/arch/x86/include/asm/aes.h deleted file mode 100644 index 80545a1cbe39..000000000000 --- a/arch/x86/include/asm/aes.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef ASM_X86_AES_H -#define ASM_X86_AES_H - -#include -#include - -void crypto_aes_encrypt_x86(struct crypto_aes_ctx *ctx, u8 *dst, - const u8 *src); -void crypto_aes_decrypt_x86(struct crypto_aes_ctx *ctx, u8 *dst, - const u8 *src); -#endif diff --git a/arch/x86/include/asm/crypto/aes.h b/arch/x86/include/asm/crypto/aes.h new file mode 100644 index 000000000000..80545a1cbe39 --- /dev/null +++ b/arch/x86/include/asm/crypto/aes.h @@ -0,0 +1,11 @@ +#ifndef ASM_X86_AES_H +#define ASM_X86_AES_H + +#include +#include + +void crypto_aes_encrypt_x86(struct crypto_aes_ctx *ctx, u8 *dst, + const u8 *src); +void crypto_aes_decrypt_x86(struct crypto_aes_ctx *ctx, u8 *dst, + const u8 *src); +#endif -- cgit v1.2.3 From 8138136ec26277c59df47a7f5756e5308cc634b2 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 21 May 2012 00:20:13 -0300 Subject: ARM: mxs: Let GPMI driver be built by default Let GPMI driver be built by default. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/configs/mxs_defconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig index 5406c23a02e3..6b86df7bb243 100644 --- a/arch/arm/configs/mxs_defconfig +++ b/arch/arm/configs/mxs_defconfig @@ -58,6 +58,9 @@ CONFIG_CAN_FLEXCAN=m CONFIG_DEVTMPFS=y # CONFIG_FIRMWARE_IN_KERNEL is not set # CONFIG_BLK_DEV is not set +CONFIG_MTD=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_GPMI_NAND=y CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y CONFIG_ENC28J60=y -- cgit v1.2.3 From 79a6664c29603bae044f8ec2f53720519d0db8f0 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 1 Jun 2012 00:26:13 -0300 Subject: ARM: mxs: Enable MACH_APX4DEVKIT Enable MACH_APX4DEVKIT to be built by default. Signed-off-by: Fabio Estevam Acked-by: Lauri Hintsala Signed-off-by: Shawn Guo --- arch/arm/configs/mxs_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig index 6b86df7bb243..ae411ddcc7c0 100644 --- a/arch/arm/configs/mxs_defconfig +++ b/arch/arm/configs/mxs_defconfig @@ -28,6 +28,7 @@ CONFIG_MACH_MX28EVK=y CONFIG_MACH_STMP378X_DEVB=y CONFIG_MACH_TX28=y CONFIG_MACH_M28EVK=y +CONFIG_MACH_APX4DEVKIT=y # CONFIG_ARM_THUMB is not set CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y -- cgit v1.2.3 From 783f061371536b1c2f8326e24f4ff287348ea59c Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 15 Jun 2012 08:32:30 -0300 Subject: ARM: mxs_defconfig: Let AUART driver be built by default Let AUART driver be built by default. Signed-off-by: Fabio Estevam Reviewed-by: Marek Vasut Signed-off-by: Shawn Guo --- arch/arm/configs/mxs_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig index ae411ddcc7c0..94198c52fe2c 100644 --- a/arch/arm/configs/mxs_defconfig +++ b/arch/arm/configs/mxs_defconfig @@ -81,6 +81,7 @@ CONFIG_DEVPTS_MULTIPLE_INSTANCES=y # CONFIG_DEVKMEM is not set CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_MXS_AUART=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y # CONFIG_I2C_COMPAT is not set -- cgit v1.2.3 From e90b833ee1aae64b6fca2455001323ffe29e1698 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Mon, 25 Jun 2012 12:38:23 -0500 Subject: ARM: OMAP4470: Fix OMAP4470 boot failure OMAP4470 currently fails to boot, printing various messages such as ... omap_hwmod: mpu: cannot clk_get main_clk dpll_mpu_m2_ck omap_hwmod: mpu: cannot _init_clocks ------------[ cut here ]------------ WARNING: at arch/arm/mach-omap2/omap_hwmod.c:2062 _init+0x2a0/0x2e4() omap_hwmod: mpu: couldn't init clocks Modules linked in: [] (unwind_backtrace+0x0/0xf4) from [] (warn_slowpath_common+0x4c/0x64) [] (warn_slowpath_common+0x4c/0x64) from [] (warn_slowpath_fmt+0x30/0x40) [] (warn_slowpath_fmt+0x30/0x40) from [] (_init+0x2a0/0x2e4) [] (_init+0x2a0/0x2e4) from [] (omap_hwmod_setup_one+0x40/0x60) [] (omap_hwmod_setup_one+0x40/0x60) from [] (omap_hwmod_setup_one+0x34/0x60) [] (omap_hwmod_setup_one+0x34/0x60) from [] (omap_dm_timer_init_one+0x30/0x250) [] (omap_dm_timer_init_one+0x30/0x250) from [] (omap2_gp_clockevent_init+0x1c/0x108) [] (omap2_gp_clockevent_init+0x1c/0x108) from [] (omap4_timer_init+0x10/0x5c) [] (omap4_timer_init+0x10/0x5c) from [] (time_init+0x20/0x30) [] (time_init+0x20/0x30) from [] (start_kernel+0x1b0/0x304) [] (start_kernel+0x1b0/0x304) from [<80008044>] (0x80008044) ---[ end trace 1b75b31a2719ed1c ]--- The problem is that currently none of the clocks are being registered for OMAP4470 devices and so on boot-up no clocks can be found and the kernel panics. This fix allows the kernel to boot without failure using a simple RAMDISK file system on OMAP4470 blaze board. Per feedback from Paul and Benoit the 4470 clock data is incomplete for new modules such as the 2D graphics block that has been added to the 4470. Therefore add a warning to indicate that the clock data is incomplete. Cc: Paul Walmsley Cc: Benoit Cousson Signed-off-by: Jon Hunter [tony@atomide.com: updated comments] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clock44xx_data.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index e2b701e164f6..ba6f9a0a43e9 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -3417,9 +3417,12 @@ int __init omap4xxx_clk_init(void) if (cpu_is_omap443x()) { cpu_mask = RATE_IN_4430; cpu_clkflg = CK_443X; - } else if (cpu_is_omap446x()) { + } else if (cpu_is_omap446x() || cpu_is_omap447x()) { cpu_mask = RATE_IN_4460 | RATE_IN_4430; cpu_clkflg = CK_446X | CK_443X; + + if (cpu_is_omap447x()) + pr_warn("WARNING: OMAP4470 clock data incomplete!\n"); } else { return 0; } -- cgit v1.2.3 From a7df7a9494ac8eb5fa4d902d3e90b083705dc80f Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Wed, 27 Jun 2012 14:43:31 +0200 Subject: s390/ipl: Fix ipib handling for "dumpreipl" shutdown action Fix problem that was introduced with patch "s390/smp: make absolute lowcore / cpu restart parameter". After that patch the "dumpreipl" shutdown action does not work any more. To fix the problem we have to assign "reipl_block_actual" instead of "&reipl_block_actual" Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/ipl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 25241cd8ddd8..c903aa14df2a 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -1528,7 +1528,7 @@ static struct shutdown_action __refdata dump_action = { static void dump_reipl_run(struct shutdown_trigger *trigger) { - unsigned long ipib = (unsigned long) &reipl_block_actual; + unsigned long ipib = (unsigned long) reipl_block_actual; unsigned int csum; csum = csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0); -- cgit v1.2.3 From 89ea25835a5565a0a7abf4e2b423c30408d74a80 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 27 Jun 2012 14:53:46 -0600 Subject: ARM: OMAP AM35xx: clock and hwmod data: fix AM35xx HSOTGUSB hwmod Partially fix the hwmod data for the AM35xx USB OTG hwmod. This should resolve the following boot warning on AM35xx platforms: omap_hwmod: am35x_otg_hs: cannot be enabled for reset (3) While here, also fix the clkdev records, to avoid warnings about duplicate clock aliases. The hwmod is also connected to the wrong interconnect. It should be connected to the IPSS, not the L4 CORE. But that is left for a future fix, since it probably has a dependency on some hwmod core changes. Cc: Felipe Balbi Cc: Hema HK Cc: Mark A. Greer Signed-off-by: Paul Walmsley Tested-by: Mark A. Greer --- arch/arm/mach-omap2/clock3xxx_data.c | 4 ++-- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 14 +++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 1efdec236ae8..15e65046471d 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3478,8 +3478,8 @@ static struct omap_clk omap3xxx_clks[] = { CLK("davinci_mdio.0", NULL, &emac_fck, CK_AM35XX), CLK("vpfe-capture", "master", &vpfe_ick, CK_AM35XX), CLK("vpfe-capture", "slave", &vpfe_fck, CK_AM35XX), - CLK("musb-am35x", "ick", &hsotgusb_ick_am35xx, CK_AM35XX), - CLK("musb-am35x", "fck", &hsotgusb_fck_am35xx, CK_AM35XX), + CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_am35xx, CK_AM35XX), + CLK(NULL, "hsotgusb_fck", &hsotgusb_fck_am35xx, CK_AM35XX), CLK(NULL, "hecc_ck", &hecc_ck, CK_AM35XX), CLK(NULL, "uart4_ick", &uart4_ick_am35xx, CK_AM35XX), CLK("omap_timer.1", "32k_ck", &omap_32k_fck, CK_3XXX), diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index b26d3c9bca16..21428fe6ffa4 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1638,25 +1638,20 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = { /* usb_otg_hs */ static struct omap_hwmod_irq_info am35xx_usbhsotg_mpu_irqs[] = { - { .name = "mc", .irq = 71 }, { .irq = -1 } }; static struct omap_hwmod_class am35xx_usbotg_class = { .name = "am35xx_usbotg", - .sysc = NULL, }; static struct omap_hwmod am35xx_usbhsotg_hwmod = { .name = "am35x_otg_hs", .mpu_irqs = am35xx_usbhsotg_mpu_irqs, - .main_clk = NULL, - .prcm = { - .omap2 = { - }, - }, + .main_clk = "hsotgusb_fck", .class = &am35xx_usbotg_class, + .flags = HWMOD_NO_IDLEST, }; /* MMC/SD/SDIO common */ @@ -2097,9 +2092,10 @@ static struct omap_hwmod_ocp_if omap3xxx_usbhsotg__l3 = { static struct omap_hwmod_ocp_if am35xx_usbhsotg__l3 = { .master = &am35xx_usbhsotg_hwmod, .slave = &omap3xxx_l3_main_hwmod, - .clk = "core_l3_ick", + .clk = "hsotgusb_ick", .user = OCP_USER_MPU, }; + /* L4_CORE -> L4_WKUP interface */ static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = { .master = &omap3xxx_l4_core_hwmod, @@ -2393,7 +2389,7 @@ static struct omap_hwmod_addr_space am35xx_usbhsotg_addrs[] = { static struct omap_hwmod_ocp_if am35xx_l4_core__usbhsotg = { .master = &omap3xxx_l4_core_hwmod, .slave = &am35xx_usbhsotg_hwmod, - .clk = "l4_ick", + .clk = "hsotgusb_ick", .addr = am35xx_usbhsotg_addrs, .user = OCP_USER_MPU, }; -- cgit v1.2.3 From bf7652372777c3a6003a05a3e9e462c3dcd0c90d Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 27 Jun 2012 14:53:46 -0600 Subject: ARM: OMAP AM35xx: clock and hwmod data: fix UART4 data Add missing terminators to the arrays of IRQ, DMA, and address space structure records in the AM35xx UART4 hwmod data. Without these terminators, the following warnings appear on boot: omap_uart.3: failed to claim resource 58 omap_device: omap_uart: build failed (-16) WARNING: at /home/paul/linux/arch/arm/mach-omap2/serial.c:375 omap_serial_init_port+0x198/0x284() Could not build omap_device for omap_uart: uart4. Also, AM35xx uart4_fck has an incorrect parent clock pointer. Fix it and clean up a whitespace issue. Fix some incorrectly-named macros related to AM35xx UART4. Cc: Kyle Manna Cc: Mark A. Greer Cc: Ranjith Lohithakshan Signed-off-by: Paul Walmsley Tested-by: Mark A. Greer --- arch/arm/mach-omap2/clock3xxx_data.c | 14 +++++++------- arch/arm/mach-omap2/cm-regbits-34xx.h | 4 ++-- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 7 +++++-- arch/arm/mach-omap2/prcm-common.h | 4 ++-- 4 files changed, 16 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 15e65046471d..58c6e477a4f1 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -2490,13 +2490,13 @@ static struct clk uart4_fck = { }; static struct clk uart4_fck_am35xx = { - .name = "uart4_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_48m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_UART4_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, + .name = "uart4_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_48m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = AM35XX_EN_UART4_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, }; static struct clk gpt2_fck = { diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h index 8083a8cdc55f..766338fe4d34 100644 --- a/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h @@ -169,8 +169,6 @@ /* AM35XX specific CM_ICLKEN1_CORE bits */ #define AM35XX_EN_IPSS_MASK (1 << 4) #define AM35XX_EN_IPSS_SHIFT 4 -#define AM35XX_EN_UART4_MASK (1 << 23) -#define AM35XX_EN_UART4_SHIFT 23 /* CM_ICLKEN2_CORE */ #define OMAP3430_EN_PKA_MASK (1 << 4) @@ -207,6 +205,8 @@ #define OMAP3430_ST_DES2_MASK (1 << 26) #define OMAP3430_ST_MSPRO_SHIFT 23 #define OMAP3430_ST_MSPRO_MASK (1 << 23) +#define AM35XX_ST_UART4_SHIFT 23 +#define AM35XX_ST_UART4_MASK (1 << 23) #define OMAP3430_ST_HDQ_SHIFT 22 #define OMAP3430_ST_HDQ_MASK (1 << 22) #define OMAP3430ES1_ST_FAC_SHIFT 8 diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 21428fe6ffa4..2f4889e514e5 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -527,11 +527,13 @@ static struct omap_hwmod omap36xx_uart4_hwmod = { static struct omap_hwmod_irq_info am35xx_uart4_mpu_irqs[] = { { .irq = INT_35XX_UART4_IRQ, }, + { .irq = -1 } }; static struct omap_hwmod_dma_info am35xx_uart4_sdma_reqs[] = { { .name = "rx", .dma_req = AM35XX_DMA_UART4_RX, }, { .name = "tx", .dma_req = AM35XX_DMA_UART4_TX, }, + { .dma_req = -1 } }; static struct omap_hwmod am35xx_uart4_hwmod = { @@ -543,9 +545,9 @@ static struct omap_hwmod am35xx_uart4_hwmod = { .omap2 = { .module_offs = CORE_MOD, .prcm_reg_id = 1, - .module_bit = OMAP3430_EN_UART4_SHIFT, + .module_bit = AM35XX_EN_UART4_SHIFT, .idlest_reg_id = 1, - .idlest_idle_bit = OMAP3430_EN_UART4_SHIFT, + .idlest_idle_bit = AM35XX_ST_UART4_SHIFT, }, }, .class = &omap2_uart_class, @@ -2239,6 +2241,7 @@ static struct omap_hwmod_addr_space am35xx_uart4_addr_space[] = { .pa_end = OMAP3_UART4_AM35XX_BASE + SZ_1K - 1, .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, }, + { } }; static struct omap_hwmod_ocp_if am35xx_l4_core__uart4 = { diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index 6da3ba483ad1..cc1398e8b469 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -203,8 +203,8 @@ #define OMAP3430_EN_MMC2_SHIFT 25 #define OMAP3430_EN_MMC1_MASK (1 << 24) #define OMAP3430_EN_MMC1_SHIFT 24 -#define OMAP3430_EN_UART4_MASK (1 << 23) -#define OMAP3430_EN_UART4_SHIFT 23 +#define AM35XX_EN_UART4_MASK (1 << 23) +#define AM35XX_EN_UART4_SHIFT 23 #define OMAP3430_EN_MCSPI4_MASK (1 << 21) #define OMAP3430_EN_MCSPI4_SHIFT 21 #define OMAP3430_EN_MCSPI3_MASK (1 << 20) -- cgit v1.2.3 From 82ee620dc6e1906fe064e93047489f0aea72b75b Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 27 Jun 2012 14:53:46 -0600 Subject: ARM: OMAP: AM35xx: fix UART4 softreset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During kernel init, the AM3505/AM3517 UART4 cannot complete its softreset: omap_hwmod: uart4: softreset failed (waited 10000 usec) This also results in another warning later in the boot process: omap_hwmod: uart4: enabled state can only be entered from initialized, idle, or disabled state From empirical observation, the AM35xx UART4 IP block requires either uart1_fck or uart2_fck to be enabled while UART4 resets. Otherwise the reset will never complete. So this patch adds uart1_fck as an optional clock for UART4 and adds the appropriate hwmod flag to cause uart1_fck to be enabled during the reset process. (The choice of uart1_fck over uart2_fck was arbitrary.) Unfortunately this observation raises many questions. Is it necessary for uart1_fck or uart2_fck to be controlled with uart4_fck for the UART4 to work correctly? What exactly do the AM35xx UART4 clock tree and the related PRCM idle management FSMs look like? If anyone has the ability to answer these questions through empirical functional testing, or hardware information from the AM35xx designers, it would be greatly appreciated. Cc: Benoît Cousson Cc: Kyle Manna Cc: Mark A. Greer Cc: Ranjith Lohithakshan Signed-off-by: Paul Walmsley Tested-by: Mark A. Greer --- arch/arm/mach-omap2/clock3xxx_data.c | 8 ++++++-- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 58c6e477a4f1..4a3c1c819adc 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3201,8 +3201,12 @@ static struct clk vpfe_fck = { }; /* - * The UART1/2 functional clock acts as the functional - * clock for UART4. No separate fclk control available. + * The UART1/2 functional clock acts as the functional clock for + * UART4. No separate fclk control available. XXX Well now we have a + * uart4_fck that is apparently used as the UART4 functional clock, + * but it also seems that uart1_fck or uart2_fck are still needed, at + * least for UART4 softresets to complete. This really needs + * clarification. */ static struct clk uart4_ick_am35xx = { .name = "uart4_ick", diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 2f4889e514e5..1120d388eca3 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -536,6 +536,20 @@ static struct omap_hwmod_dma_info am35xx_uart4_sdma_reqs[] = { { .dma_req = -1 } }; +/* + * XXX AM35xx UART4 cannot complete its softreset without uart1_fck or + * uart2_fck being enabled. So we add uart1_fck as an optional clock, + * below, and set the HWMOD_CONTROL_OPT_CLKS_IN_RESET. This really + * should not be needed. The functional clock structure of the AM35xx + * UART4 is extremely unclear and opaque; it is unclear what the role + * of uart1/2_fck is for the UART4. Any clarification from either + * empirical testing or the AM3505/3517 hardware designers would be + * most welcome. + */ +static struct omap_hwmod_opt_clk am35xx_uart4_opt_clks[] = { + { .role = "softreset_uart1_fck", .clk = "uart1_fck" }, +}; + static struct omap_hwmod am35xx_uart4_hwmod = { .name = "uart4", .mpu_irqs = am35xx_uart4_mpu_irqs, @@ -550,6 +564,9 @@ static struct omap_hwmod am35xx_uart4_hwmod = { .idlest_idle_bit = AM35XX_ST_UART4_SHIFT, }, }, + .opt_clks = am35xx_uart4_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(am35xx_uart4_opt_clks), + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, .class = &omap2_uart_class, }; -- cgit v1.2.3 From 31ba88083fec3b141fc1863a2dc0822c474a89a2 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Wed, 27 Jun 2012 14:59:57 -0600 Subject: ARM: OMAP AM35x: EMAC/MDIO integration: Add Davinci EMAC/MDIO hwmod support Add hwmod support for the EMAC (and MDIO) ethernet controller that's on the am35x family of SoC's. Signed-off-by: Mark A. Greer [paul@pwsan.com: updated subject line; updated to apply on v3.5-rc4; added comments to hwmod data regarding IPSS] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/am35xx-emac.c | 90 +++++++++++++------------ arch/arm/mach-omap2/clock3xxx_data.c | 2 +- arch/arm/mach-omap2/include/mach/am35xx.h | 2 + arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 105 +++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 45 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 447682c4e11c..2c90ac686686 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -15,27 +15,13 @@ * General Public License for more details. */ -#include +#include #include -#include -#include +#include +#include #include - #include "control.h" - -static struct mdio_platform_data am35xx_emac_mdio_pdata; - -static struct resource am35xx_emac_mdio_resources[] = { - DEFINE_RES_MEM(AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET, SZ_4K), -}; - -static struct platform_device am35xx_emac_mdio_device = { - .name = "davinci_mdio", - .id = 0, - .num_resources = ARRAY_SIZE(am35xx_emac_mdio_resources), - .resource = am35xx_emac_mdio_resources, - .dev.platform_data = &am35xx_emac_mdio_pdata, -}; +#include "am35xx-emac.h" static void am35xx_enable_emac_int(void) { @@ -69,41 +55,57 @@ static struct emac_platform_data am35xx_emac_pdata = { .interrupt_disable = am35xx_disable_emac_int, }; -static struct resource am35xx_emac_resources[] = { - DEFINE_RES_MEM(AM35XX_IPSS_EMAC_BASE, 0x30000), - DEFINE_RES_IRQ(INT_35XX_EMAC_C0_RXTHRESH_IRQ), - DEFINE_RES_IRQ(INT_35XX_EMAC_C0_RX_PULSE_IRQ), - DEFINE_RES_IRQ(INT_35XX_EMAC_C0_TX_PULSE_IRQ), - DEFINE_RES_IRQ(INT_35XX_EMAC_C0_MISC_PULSE_IRQ), -}; +static struct mdio_platform_data am35xx_mdio_pdata; -static struct platform_device am35xx_emac_device = { - .name = "davinci_emac", - .id = -1, - .num_resources = ARRAY_SIZE(am35xx_emac_resources), - .resource = am35xx_emac_resources, - .dev = { - .platform_data = &am35xx_emac_pdata, - }, -}; +static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, + void *pdata, int pdata_len) +{ + struct platform_device *pdev; + + pdev = omap_device_build(oh->class->name, 0, oh, pdata, pdata_len, + NULL, 0, false); + if (IS_ERR(pdev)) { + WARN(1, "Can't build omap_device for %s:%s.\n", + oh->class->name, oh->name); + return PTR_ERR(pdev); + } + + return 0; +} void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) { + struct omap_hwmod *oh; u32 v; - int err; + int ret; - am35xx_emac_pdata.rmii_en = rmii_en; - am35xx_emac_mdio_pdata.bus_freq = mdio_bus_freq; - err = platform_device_register(&am35xx_emac_device); - if (err) { - pr_err("AM35x: failed registering EMAC device: %d\n", err); + oh = omap_hwmod_lookup("davinci_mdio"); + if (!oh) { + pr_err("Could not find davinci_mdio hwmod\n"); + return; + } + + am35xx_mdio_pdata.bus_freq = mdio_bus_freq; + + ret = omap_davinci_emac_dev_init(oh, &am35xx_mdio_pdata, + sizeof(am35xx_mdio_pdata)); + if (ret) { + pr_err("Could not build davinci_mdio hwmod device\n"); return; } - err = platform_device_register(&am35xx_emac_mdio_device); - if (err) { - pr_err("AM35x: failed registering EMAC MDIO device: %d\n", err); - platform_device_unregister(&am35xx_emac_device); + oh = omap_hwmod_lookup("davinci_emac"); + if (!oh) { + pr_err("Could not find davinci_emac hwmod\n"); + return; + } + + am35xx_emac_pdata.rmii_en = rmii_en; + + ret = omap_davinci_emac_dev_init(oh, &am35xx_emac_pdata, + sizeof(am35xx_emac_pdata)); + if (ret) { + pr_err("Could not build davinci_emac hwmod device\n"); return; } diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 1efdec236ae8..10c139580ff1 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3474,7 +3474,7 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "ipss_ick", &ipss_ick, CK_AM35XX), CLK(NULL, "rmii_ck", &rmii_ck, CK_AM35XX), CLK(NULL, "pclk_ck", &pclk_ck, CK_AM35XX), - CLK("davinci_emac", NULL, &emac_ick, CK_AM35XX), + CLK("davinci_emac.0", NULL, &emac_ick, CK_AM35XX), CLK("davinci_mdio.0", NULL, &emac_fck, CK_AM35XX), CLK("vpfe-capture", "master", &vpfe_ick, CK_AM35XX), CLK("vpfe-capture", "slave", &vpfe_fck, CK_AM35XX), diff --git a/arch/arm/mach-omap2/include/mach/am35xx.h b/arch/arm/mach-omap2/include/mach/am35xx.h index f1e13d1ca5e7..95594495fcf6 100644 --- a/arch/arm/mach-omap2/include/mach/am35xx.h +++ b/arch/arm/mach-omap2/include/mach/am35xx.h @@ -36,6 +36,8 @@ #define AM35XX_EMAC_CNTRL_MOD_OFFSET (0x0) #define AM35XX_EMAC_CNTRL_RAM_OFFSET (0x20000) #define AM35XX_EMAC_MDIO_OFFSET (0x30000) +#define AM35XX_IPSS_MDIO_BASE (AM35XX_IPSS_EMAC_BASE + \ + AM35XX_EMAC_MDIO_OFFSET) #define AM35XX_EMAC_CNTRL_RAM_SIZE (0x2000) #define AM35XX_EMAC_RAM_ADDR (AM3517_EMAC_BASE + \ AM3517_EMAC_CNTRL_RAM_OFFSET) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index b26d3c9bca16..a16b832f1d9c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -3138,6 +3138,107 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__counter_32k = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* am35xx has Davinci MDIO & EMAC */ +static struct omap_hwmod_class am35xx_mdio_class = { + .name = "davinci_mdio", +}; + +static struct omap_hwmod am35xx_mdio_hwmod = { + .name = "davinci_mdio", + .class = &am35xx_mdio_class, + .flags = HWMOD_NO_IDLEST, +}; + +/* + * XXX Should be connected to an IPSS hwmod, not the L3 directly; + * but this will probably require some additional hwmod core support, + * so is left as a future to-do item. + */ +static struct omap_hwmod_ocp_if am35xx_mdio__l3 = { + .master = &am35xx_mdio_hwmod, + .slave = &omap3xxx_l3_main_hwmod, + .clk = "emac_fck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space am35xx_mdio_addrs[] = { + { + .pa_start = AM35XX_IPSS_MDIO_BASE, + .pa_end = AM35XX_IPSS_MDIO_BASE + SZ_4K - 1, + .flags = ADDR_TYPE_RT, + }, + { } +}; + +/* l4_core -> davinci mdio */ +/* + * XXX Should be connected to an IPSS hwmod, not the L4_CORE directly; + * but this will probably require some additional hwmod core support, + * so is left as a future to-do item. + */ +static struct omap_hwmod_ocp_if am35xx_l4_core__mdio = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &am35xx_mdio_hwmod, + .clk = "emac_fck", + .addr = am35xx_mdio_addrs, + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_irq_info am35xx_emac_mpu_irqs[] = { + { .name = "rxthresh", .irq = INT_35XX_EMAC_C0_RXTHRESH_IRQ }, + { .name = "rx_pulse", .irq = INT_35XX_EMAC_C0_RX_PULSE_IRQ }, + { .name = "tx_pulse", .irq = INT_35XX_EMAC_C0_TX_PULSE_IRQ }, + { .name = "misc_pulse", .irq = INT_35XX_EMAC_C0_MISC_PULSE_IRQ }, + { .irq = -1 } +}; + +static struct omap_hwmod_class am35xx_emac_class = { + .name = "davinci_emac", +}; + +static struct omap_hwmod am35xx_emac_hwmod = { + .name = "davinci_emac", + .mpu_irqs = am35xx_emac_mpu_irqs, + .class = &am35xx_emac_class, + .flags = HWMOD_NO_IDLEST, +}; + +/* l3_core -> davinci emac interface */ +/* + * XXX Should be connected to an IPSS hwmod, not the L3 directly; + * but this will probably require some additional hwmod core support, + * so is left as a future to-do item. + */ +static struct omap_hwmod_ocp_if am35xx_emac__l3 = { + .master = &am35xx_emac_hwmod, + .slave = &omap3xxx_l3_main_hwmod, + .clk = "emac_ick", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space am35xx_emac_addrs[] = { + { + .pa_start = AM35XX_IPSS_EMAC_BASE, + .pa_end = AM35XX_IPSS_EMAC_BASE + 0x30000 - 1, + .flags = ADDR_TYPE_RT, + }, + { } +}; + +/* l4_core -> davinci emac */ +/* + * XXX Should be connected to an IPSS hwmod, not the L4_CORE directly; + * but this will probably require some additional hwmod core support, + * so is left as a future to-do item. + */ +static struct omap_hwmod_ocp_if am35xx_l4_core__emac = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &am35xx_emac_hwmod, + .clk = "emac_ick", + .addr = am35xx_emac_addrs, + .user = OCP_USER_MPU, +}; + static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = { &omap3xxx_l3_main__l4_core, &omap3xxx_l3_main__l4_per, @@ -3266,6 +3367,10 @@ static struct omap_hwmod_ocp_if *am35xx_hwmod_ocp_ifs[] __initdata = { &omap3xxx_l4_core__usb_tll_hs, &omap3xxx_l4_core__es3plus_mmc1, &omap3xxx_l4_core__es3plus_mmc2, + &am35xx_mdio__l3, + &am35xx_l4_core__mdio, + &am35xx_emac__l3, + &am35xx_l4_core__emac, NULL }; -- cgit v1.2.3 From e0ba94f14f747c2661c4d21f8c44e5b0b8cd8e48 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Thu, 28 Jun 2012 09:02:16 +0800 Subject: x86/tlb_info: get last level TLB entry number of CPU For 4KB pages, x86 CPU has 2 or 1 level TLB, first level is data TLB and instruction TLB, second level is shared TLB for both data and instructions. For hupe page TLB, usually there is just one level and seperated by 2MB/4MB and 1GB. Although each levels TLB size is important for performance tuning, but for genernal and rude optimizing, last level TLB entry number is suitable. And in fact, last level TLB always has the biggest entry number. This patch will get the biggest TLB entry number and use it in furture TLB optimizing. Accroding Borislav's suggestion, except tlb_ll[i/d]_* array, other function and data will be released after system boot up. For all kinds of x86 vendor friendly, vendor specific code was moved to its specific files. Signed-off-by: Alex Shi Link: http://lkml.kernel.org/r/1340845344-27557-2-git-send-email-alex.shi@intel.com Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/processor.h | 11 +++ arch/x86/kernel/cpu/common.c | 21 ++++++ arch/x86/kernel/cpu/cpu.h | 9 +++ arch/x86/kernel/cpu/intel.c | 142 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 39bc5777211a..39b2bd48dfbc 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -61,6 +61,17 @@ static inline void *current_text_addr(void) # define ARCH_MIN_MMSTRUCT_ALIGN 0 #endif +enum tlb_infos { + ENTRIES, + NR_INFO +}; + +extern u16 __read_mostly tlb_lli_4k[NR_INFO]; +extern u16 __read_mostly tlb_lli_2m[NR_INFO]; +extern u16 __read_mostly tlb_lli_4m[NR_INFO]; +extern u16 __read_mostly tlb_lld_4k[NR_INFO]; +extern u16 __read_mostly tlb_lld_2m[NR_INFO]; +extern u16 __read_mostly tlb_lld_4m[NR_INFO]; /* * CPU type and hardware bug flags. Kept separately for each CPU. * Members of this structure are referenced in head.S, so think twice diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 6b9333b429ba..b2016df00813 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -452,6 +452,25 @@ void __cpuinit cpu_detect_cache_sizes(struct cpuinfo_x86 *c) c->x86_cache_size = l2size; } +u16 __read_mostly tlb_lli_4k[NR_INFO]; +u16 __read_mostly tlb_lli_2m[NR_INFO]; +u16 __read_mostly tlb_lli_4m[NR_INFO]; +u16 __read_mostly tlb_lld_4k[NR_INFO]; +u16 __read_mostly tlb_lld_2m[NR_INFO]; +u16 __read_mostly tlb_lld_4m[NR_INFO]; + +void __cpuinit cpu_detect_tlb(struct cpuinfo_x86 *c) +{ + if (this_cpu->c_detect_tlb) + this_cpu->c_detect_tlb(c); + + printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \ + "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d\n", + tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES], + tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES], + tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES]); +} + void __cpuinit detect_ht(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_HT @@ -911,6 +930,8 @@ void __init identify_boot_cpu(void) #else vgetcpu_set_mode(); #endif + if (boot_cpu_data.cpuid_level >= 2) + cpu_detect_tlb(&boot_cpu_data); } void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h index 8bacc7826fb3..4041c24ae7db 100644 --- a/arch/x86/kernel/cpu/cpu.h +++ b/arch/x86/kernel/cpu/cpu.h @@ -20,10 +20,19 @@ struct cpu_dev { void (*c_bsp_init)(struct cpuinfo_x86 *); void (*c_init)(struct cpuinfo_x86 *); void (*c_identify)(struct cpuinfo_x86 *); + void (*c_detect_tlb)(struct cpuinfo_x86 *); unsigned int (*c_size_cache)(struct cpuinfo_x86 *, unsigned int); int c_x86_vendor; }; +struct _tlb_table { + unsigned char descriptor; + char tlb_type; + unsigned int entries; + /* unsigned int ways; */ + char info[128]; +}; + #define cpu_dev_register(cpu_devX) \ static const struct cpu_dev *const __cpu_dev_##cpu_devX __used \ __attribute__((__section__(".x86_cpu_dev.init"))) = \ diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 3e6ff6cbf42a..ed0d512cf51b 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -491,6 +491,147 @@ static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned i } #endif +#define TLB_INST_4K 0x01 +#define TLB_INST_4M 0x02 +#define TLB_INST_2M_4M 0x03 + +#define TLB_INST_ALL 0x05 +#define TLB_INST_1G 0x06 + +#define TLB_DATA_4K 0x11 +#define TLB_DATA_4M 0x12 +#define TLB_DATA_2M_4M 0x13 +#define TLB_DATA_4K_4M 0x14 + +#define TLB_DATA_1G 0x16 + +#define TLB_DATA0_4K 0x21 +#define TLB_DATA0_4M 0x22 +#define TLB_DATA0_2M_4M 0x23 + +#define STLB_4K 0x41 + +static const struct _tlb_table intel_tlb_table[] __cpuinitconst = { + { 0x01, TLB_INST_4K, 32, " TLB_INST 4 KByte pages, 4-way set associative" }, + { 0x02, TLB_INST_4M, 2, " TLB_INST 4 MByte pages, full associative" }, + { 0x03, TLB_DATA_4K, 64, " TLB_DATA 4 KByte pages, 4-way set associative" }, + { 0x04, TLB_DATA_4M, 8, " TLB_DATA 4 MByte pages, 4-way set associative" }, + { 0x05, TLB_DATA_4M, 32, " TLB_DATA 4 MByte pages, 4-way set associative" }, + { 0x0b, TLB_INST_4M, 4, " TLB_INST 4 MByte pages, 4-way set associative" }, + { 0x4f, TLB_INST_4K, 32, " TLB_INST 4 KByte pages */" }, + { 0x50, TLB_INST_ALL, 64, " TLB_INST 4 KByte and 2-MByte or 4-MByte pages" }, + { 0x51, TLB_INST_ALL, 128, " TLB_INST 4 KByte and 2-MByte or 4-MByte pages" }, + { 0x52, TLB_INST_ALL, 256, " TLB_INST 4 KByte and 2-MByte or 4-MByte pages" }, + { 0x55, TLB_INST_2M_4M, 7, " TLB_INST 2-MByte or 4-MByte pages, fully associative" }, + { 0x56, TLB_DATA0_4M, 16, " TLB_DATA0 4 MByte pages, 4-way set associative" }, + { 0x57, TLB_DATA0_4K, 16, " TLB_DATA0 4 KByte pages, 4-way associative" }, + { 0x59, TLB_DATA0_4K, 16, " TLB_DATA0 4 KByte pages, fully associative" }, + { 0x5a, TLB_DATA0_2M_4M, 32, " TLB_DATA0 2-MByte or 4 MByte pages, 4-way set associative" }, + { 0x5b, TLB_DATA_4K_4M, 64, " TLB_DATA 4 KByte and 4 MByte pages" }, + { 0x5c, TLB_DATA_4K_4M, 128, " TLB_DATA 4 KByte and 4 MByte pages" }, + { 0x5d, TLB_DATA_4K_4M, 256, " TLB_DATA 4 KByte and 4 MByte pages" }, + { 0xb0, TLB_INST_4K, 128, " TLB_INST 4 KByte pages, 4-way set associative" }, + { 0xb1, TLB_INST_2M_4M, 4, " TLB_INST 2M pages, 4-way, 8 entries or 4M pages, 4-way entries" }, + { 0xb2, TLB_INST_4K, 64, " TLB_INST 4KByte pages, 4-way set associative" }, + { 0xb3, TLB_DATA_4K, 128, " TLB_DATA 4 KByte pages, 4-way set associative" }, + { 0xb4, TLB_DATA_4K, 256, " TLB_DATA 4 KByte pages, 4-way associative" }, + { 0xba, TLB_DATA_4K, 64, " TLB_DATA 4 KByte pages, 4-way associative" }, + { 0xc0, TLB_DATA_4K_4M, 8, " TLB_DATA 4 KByte and 4 MByte pages, 4-way associative" }, + { 0xca, STLB_4K, 512, " STLB 4 KByte pages, 4-way associative" }, + { 0x00, 0, 0 } +}; + +static void __cpuinit intel_tlb_lookup(const unsigned char desc) +{ + unsigned char k; + if (desc == 0) + return; + + /* look up this descriptor in the table */ + for (k = 0; intel_tlb_table[k].descriptor != desc && \ + intel_tlb_table[k].descriptor != 0; k++) + ; + + if (intel_tlb_table[k].tlb_type == 0) + return; + + switch (intel_tlb_table[k].tlb_type) { + case STLB_4K: + if (tlb_lli_4k[ENTRIES] < intel_tlb_table[k].entries) + tlb_lli_4k[ENTRIES] = intel_tlb_table[k].entries; + if (tlb_lld_4k[ENTRIES] < intel_tlb_table[k].entries) + tlb_lld_4k[ENTRIES] = intel_tlb_table[k].entries; + break; + case TLB_INST_ALL: + if (tlb_lli_4k[ENTRIES] < intel_tlb_table[k].entries) + tlb_lli_4k[ENTRIES] = intel_tlb_table[k].entries; + if (tlb_lli_2m[ENTRIES] < intel_tlb_table[k].entries) + tlb_lli_2m[ENTRIES] = intel_tlb_table[k].entries; + if (tlb_lli_4m[ENTRIES] < intel_tlb_table[k].entries) + tlb_lli_4m[ENTRIES] = intel_tlb_table[k].entries; + break; + case TLB_INST_4K: + if (tlb_lli_4k[ENTRIES] < intel_tlb_table[k].entries) + tlb_lli_4k[ENTRIES] = intel_tlb_table[k].entries; + break; + case TLB_INST_4M: + if (tlb_lli_4m[ENTRIES] < intel_tlb_table[k].entries) + tlb_lli_4m[ENTRIES] = intel_tlb_table[k].entries; + break; + case TLB_INST_2M_4M: + if (tlb_lli_2m[ENTRIES] < intel_tlb_table[k].entries) + tlb_lli_2m[ENTRIES] = intel_tlb_table[k].entries; + if (tlb_lli_4m[ENTRIES] < intel_tlb_table[k].entries) + tlb_lli_4m[ENTRIES] = intel_tlb_table[k].entries; + break; + case TLB_DATA_4K: + case TLB_DATA0_4K: + if (tlb_lld_4k[ENTRIES] < intel_tlb_table[k].entries) + tlb_lld_4k[ENTRIES] = intel_tlb_table[k].entries; + break; + case TLB_DATA_4M: + case TLB_DATA0_4M: + if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries) + tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries; + break; + case TLB_DATA_2M_4M: + case TLB_DATA0_2M_4M: + if (tlb_lld_2m[ENTRIES] < intel_tlb_table[k].entries) + tlb_lld_2m[ENTRIES] = intel_tlb_table[k].entries; + if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries) + tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries; + break; + case TLB_DATA_4K_4M: + if (tlb_lld_4k[ENTRIES] < intel_tlb_table[k].entries) + tlb_lld_4k[ENTRIES] = intel_tlb_table[k].entries; + if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries) + tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries; + break; + } +} + +static void __cpuinit intel_detect_tlb(struct cpuinfo_x86 *c) +{ + int i, j, n; + unsigned int regs[4]; + unsigned char *desc = (unsigned char *)regs; + /* Number of times to iterate */ + n = cpuid_eax(2) & 0xFF; + + for (i = 0 ; i < n ; i++) { + cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]); + + /* If bit 31 is set, this is an unknown format */ + for (j = 0 ; j < 3 ; j++) + if (regs[j] & (1 << 31)) + regs[j] = 0; + + /* Byte 0 is level count, not a descriptor */ + for (j = 1 ; j < 16 ; j++) + intel_tlb_lookup(desc[j]); + } +} + static const struct cpu_dev __cpuinitconst intel_cpu_dev = { .c_vendor = "Intel", .c_ident = { "GenuineIntel" }, @@ -546,6 +687,7 @@ static const struct cpu_dev __cpuinitconst intel_cpu_dev = { }, .c_size_cache = intel_size_cache, #endif + .c_detect_tlb = intel_detect_tlb, .c_early_init = early_init_intel, .c_init = init_intel, .c_x86_vendor = X86_VENDOR_INTEL, -- cgit v1.2.3 From e7b52ffd45a6d834473f43b349e7d86593d763c7 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Thu, 28 Jun 2012 09:02:17 +0800 Subject: x86/flush_tlb: try flush_tlb_single one by one in flush_tlb_range x86 has no flush_tlb_range support in instruction level. Currently the flush_tlb_range just implemented by flushing all page table. That is not the best solution for all scenarios. In fact, if we just use 'invlpg' to flush few lines from TLB, we can get the performance gain from later remain TLB lines accessing. But the 'invlpg' instruction costs much of time. Its execution time can compete with cr3 rewriting, and even a bit more on SNB CPU. So, on a 512 4KB TLB entries CPU, the balance points is at: (512 - X) * 100ns(assumed TLB refill cost) = X(TLB flush entries) * 100ns(assumed invlpg cost) Here, X is 256, that is 1/2 of 512 entries. But with the mysterious CPU pre-fetcher and page miss handler Unit, the assumed TLB refill cost is far lower then 100ns in sequential access. And 2 HT siblings in one core makes the memory access more faster if they are accessing the same memory. So, in the patch, I just do the change when the target entries is less than 1/16 of whole active tlb entries. Actually, I have no data support for the percentage '1/16', so any suggestions are welcomed. As to hugetlb, guess due to smaller page table, and smaller active TLB entries, I didn't see benefit via my benchmark, so no optimizing now. My micro benchmark show in ideal scenarios, the performance improves 70 percent in reading. And in worst scenario, the reading/writing performance is similar with unpatched 3.4-rc4 kernel. Here is the reading data on my 2P * 4cores *HT NHM EP machine, with THP 'always': multi thread testing, '-t' paramter is thread number: with patch unpatched 3.4-rc4 ./mprotect -t 1 14ns 24ns ./mprotect -t 2 13ns 22ns ./mprotect -t 4 12ns 19ns ./mprotect -t 8 14ns 16ns ./mprotect -t 16 28ns 26ns ./mprotect -t 32 54ns 51ns ./mprotect -t 128 200ns 199ns Single process with sequencial flushing and memory accessing: with patch unpatched 3.4-rc4 ./mprotect 7ns 11ns ./mprotect -p 4096 -l 8 -n 10240 21ns 21ns [ hpa: http://lkml.kernel.org/r/1B4B44D9196EFF41AE41FDA404FC0A100BFF94@SHSMSX101.ccr.corp.intel.com has additional performance numbers. ] Signed-off-by: Alex Shi Link: http://lkml.kernel.org/r/1340845344-27557-3-git-send-email-alex.shi@intel.com Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/paravirt.h | 5 +- arch/x86/include/asm/paravirt_types.h | 3 +- arch/x86/include/asm/tlbflush.h | 23 ++++----- arch/x86/include/asm/uv/uv.h | 5 +- arch/x86/mm/tlb.c | 97 +++++++++++++++++++++++++++++------ arch/x86/platform/uv/tlb_uv.c | 6 +-- arch/x86/xen/mmu.c | 12 ++--- include/trace/events/xen.h | 12 +++-- 8 files changed, 114 insertions(+), 49 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 6cbbabf52707..7e2c2a635737 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -397,9 +397,10 @@ static inline void __flush_tlb_single(unsigned long addr) static inline void flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, - unsigned long va) + unsigned long start, + unsigned long end) { - PVOP_VCALL3(pv_mmu_ops.flush_tlb_others, cpumask, mm, va); + PVOP_VCALL4(pv_mmu_ops.flush_tlb_others, cpumask, mm, start, end); } static inline int paravirt_pgd_alloc(struct mm_struct *mm) diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index 8e8b9a4987ee..600a5fcac9cd 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -250,7 +250,8 @@ struct pv_mmu_ops { void (*flush_tlb_single)(unsigned long addr); void (*flush_tlb_others)(const struct cpumask *cpus, struct mm_struct *mm, - unsigned long va); + unsigned long start, + unsigned long end); /* Hooks for allocating and freeing a pagetable top-level */ int (*pgd_alloc)(struct mm_struct *mm); diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 36a1a2ab87d2..33608d96d68b 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -73,14 +73,10 @@ static inline void __flush_tlb_one(unsigned long addr) * - flush_tlb_page(vma, vmaddr) flushes one page * - flush_tlb_range(vma, start, end) flushes a range of pages * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages - * - flush_tlb_others(cpumask, mm, va) flushes TLBs on other cpus + * - flush_tlb_others(cpumask, mm, start, end) flushes TLBs on other cpus * * ..but the i386 has somewhat limited tlb flushing capabilities, * and page-granular flushes are available only on i486 and up. - * - * x86-64 can only flush individual pages or full VMs. For a range flush - * we always do the full VM. Might be worth trying if for a small - * range a few INVLPGs in a row are a win. */ #ifndef CONFIG_SMP @@ -111,7 +107,8 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, static inline void native_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, - unsigned long va) + unsigned long start, + unsigned long end) { } @@ -129,17 +126,14 @@ extern void flush_tlb_all(void); extern void flush_tlb_current_task(void); extern void flush_tlb_mm(struct mm_struct *); extern void flush_tlb_page(struct vm_area_struct *, unsigned long); +extern void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end); #define flush_tlb() flush_tlb_current_task() -static inline void flush_tlb_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) -{ - flush_tlb_mm(vma->vm_mm); -} - void native_flush_tlb_others(const struct cpumask *cpumask, - struct mm_struct *mm, unsigned long va); + struct mm_struct *mm, + unsigned long start, unsigned long end); #define TLBSTATE_OK 1 #define TLBSTATE_LAZY 2 @@ -159,7 +153,8 @@ static inline void reset_lazy_tlbstate(void) #endif /* SMP */ #ifndef CONFIG_PARAVIRT -#define flush_tlb_others(mask, mm, va) native_flush_tlb_others(mask, mm, va) +#define flush_tlb_others(mask, mm, start, end) \ + native_flush_tlb_others(mask, mm, start, end) #endif static inline void flush_tlb_kernel_range(unsigned long start, diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h index 3bb9491b7659..b47c2a82ff15 100644 --- a/arch/x86/include/asm/uv/uv.h +++ b/arch/x86/include/asm/uv/uv.h @@ -15,7 +15,8 @@ extern void uv_nmi_init(void); extern void uv_system_init(void); extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, - unsigned long va, + unsigned long start, + unsigned end, unsigned int cpu); #else /* X86_UV */ @@ -26,7 +27,7 @@ static inline void uv_cpu_init(void) { } static inline void uv_system_init(void) { } static inline const struct cpumask * uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, - unsigned long va, unsigned int cpu) + unsigned long start, unsigned long end, unsigned int cpu) { return cpumask; } #endif /* X86_UV */ diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 5e57e113b72c..3b91c981a27f 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -41,7 +41,8 @@ DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) union smp_flush_state { struct { struct mm_struct *flush_mm; - unsigned long flush_va; + unsigned long flush_start; + unsigned long flush_end; raw_spinlock_t tlbstate_lock; DECLARE_BITMAP(flush_cpumask, NR_CPUS); }; @@ -156,10 +157,19 @@ void smp_invalidate_interrupt(struct pt_regs *regs) if (f->flush_mm == this_cpu_read(cpu_tlbstate.active_mm)) { if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) { - if (f->flush_va == TLB_FLUSH_ALL) + if (f->flush_end == TLB_FLUSH_ALL + || !cpu_has_invlpg) local_flush_tlb(); - else - __flush_tlb_one(f->flush_va); + else if (!f->flush_end) + __flush_tlb_single(f->flush_start); + else { + unsigned long addr; + addr = f->flush_start; + while (addr < f->flush_end) { + __flush_tlb_single(addr); + addr += PAGE_SIZE; + } + } } else leave_mm(cpu); } @@ -172,7 +182,8 @@ out: } static void flush_tlb_others_ipi(const struct cpumask *cpumask, - struct mm_struct *mm, unsigned long va) + struct mm_struct *mm, unsigned long start, + unsigned long end) { unsigned int sender; union smp_flush_state *f; @@ -185,7 +196,8 @@ static void flush_tlb_others_ipi(const struct cpumask *cpumask, raw_spin_lock(&f->tlbstate_lock); f->flush_mm = mm; - f->flush_va = va; + f->flush_start = start; + f->flush_end = end; if (cpumask_andnot(to_cpumask(f->flush_cpumask), cpumask, cpumask_of(smp_processor_id()))) { /* * We have to send the IPI only to @@ -199,24 +211,26 @@ static void flush_tlb_others_ipi(const struct cpumask *cpumask, } f->flush_mm = NULL; - f->flush_va = 0; + f->flush_start = 0; + f->flush_end = 0; if (nr_cpu_ids > NUM_INVALIDATE_TLB_VECTORS) raw_spin_unlock(&f->tlbstate_lock); } void native_flush_tlb_others(const struct cpumask *cpumask, - struct mm_struct *mm, unsigned long va) + struct mm_struct *mm, unsigned long start, + unsigned long end) { if (is_uv_system()) { unsigned int cpu; cpu = smp_processor_id(); - cpumask = uv_flush_tlb_others(cpumask, mm, va, cpu); + cpumask = uv_flush_tlb_others(cpumask, mm, start, end, cpu); if (cpumask) - flush_tlb_others_ipi(cpumask, mm, va); + flush_tlb_others_ipi(cpumask, mm, start, end); return; } - flush_tlb_others_ipi(cpumask, mm, va); + flush_tlb_others_ipi(cpumask, mm, start, end); } static void __cpuinit calculate_tlb_offset(void) @@ -282,7 +296,7 @@ void flush_tlb_current_task(void) local_flush_tlb(); if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) - flush_tlb_others(mm_cpumask(mm), mm, TLB_FLUSH_ALL); + flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL); preempt_enable(); } @@ -297,12 +311,63 @@ void flush_tlb_mm(struct mm_struct *mm) leave_mm(smp_processor_id()); } if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) - flush_tlb_others(mm_cpumask(mm), mm, TLB_FLUSH_ALL); + flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL); + + preempt_enable(); +} + +#define FLUSHALL_BAR 16 + +void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + struct mm_struct *mm; + + if (!cpu_has_invlpg || vma->vm_flags & VM_HUGETLB) { + flush_tlb_mm(vma->vm_mm); + return; + } + + preempt_disable(); + mm = vma->vm_mm; + if (current->active_mm == mm) { + if (current->mm) { + unsigned long addr, vmflag = vma->vm_flags; + unsigned act_entries, tlb_entries = 0; + + if (vmflag & VM_EXEC) + tlb_entries = tlb_lli_4k[ENTRIES]; + else + tlb_entries = tlb_lld_4k[ENTRIES]; + + act_entries = tlb_entries > mm->total_vm ? + mm->total_vm : tlb_entries; + if ((end - start)/PAGE_SIZE > act_entries/FLUSHALL_BAR) + local_flush_tlb(); + else { + for (addr = start; addr < end; + addr += PAGE_SIZE) + __flush_tlb_single(addr); + + if (cpumask_any_but(mm_cpumask(mm), + smp_processor_id()) < nr_cpu_ids) + flush_tlb_others(mm_cpumask(mm), mm, + start, end); + preempt_enable(); + return; + } + } else { + leave_mm(smp_processor_id()); + } + } + if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) + flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL); preempt_enable(); } -void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) + +void flush_tlb_page(struct vm_area_struct *vma, unsigned long start) { struct mm_struct *mm = vma->vm_mm; @@ -310,13 +375,13 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) if (current->active_mm == mm) { if (current->mm) - __flush_tlb_one(va); + __flush_tlb_one(start); else leave_mm(smp_processor_id()); } if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) - flush_tlb_others(mm_cpumask(mm), mm, va); + flush_tlb_others(mm_cpumask(mm), mm, start, 0UL); preempt_enable(); } diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 59880afa851f..f1bef8e1d633 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -1068,8 +1068,8 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp, * done. The returned pointer is valid till preemption is re-enabled. */ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, - struct mm_struct *mm, unsigned long va, - unsigned int cpu) + struct mm_struct *mm, unsigned long start, + unsigned end, unsigned int cpu) { int locals = 0; int remotes = 0; @@ -1112,7 +1112,7 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, record_send_statistics(stat, locals, hubs, remotes, bau_desc); - bau_desc->payload.address = va; + bau_desc->payload.address = start; bau_desc->payload.sending_cpu = cpu; /* * uv_flush_send_and_wait returns 0 if all cpu's were messaged, diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 3a73785631ce..39ed56789f68 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1244,7 +1244,8 @@ static void xen_flush_tlb_single(unsigned long addr) } static void xen_flush_tlb_others(const struct cpumask *cpus, - struct mm_struct *mm, unsigned long va) + struct mm_struct *mm, unsigned long start, + unsigned long end) { struct { struct mmuext_op op; @@ -1256,7 +1257,7 @@ static void xen_flush_tlb_others(const struct cpumask *cpus, } *args; struct multicall_space mcs; - trace_xen_mmu_flush_tlb_others(cpus, mm, va); + trace_xen_mmu_flush_tlb_others(cpus, mm, start, end); if (cpumask_empty(cpus)) return; /* nothing to do */ @@ -1269,11 +1270,10 @@ static void xen_flush_tlb_others(const struct cpumask *cpus, cpumask_and(to_cpumask(args->mask), cpus, cpu_online_mask); cpumask_clear_cpu(smp_processor_id(), to_cpumask(args->mask)); - if (va == TLB_FLUSH_ALL) { - args->op.cmd = MMUEXT_TLB_FLUSH_MULTI; - } else { + args->op.cmd = MMUEXT_TLB_FLUSH_MULTI; + if (start != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) { args->op.cmd = MMUEXT_INVLPG_MULTI; - args->op.arg1.linear_addr = va; + args->op.arg1.linear_addr = start; } MULTI_mmuext_op(mcs.mc, &args->op, 1, NULL, DOMID_SELF); diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h index 92f1a796829e..15ba03bdd7c6 100644 --- a/include/trace/events/xen.h +++ b/include/trace/events/xen.h @@ -397,18 +397,20 @@ TRACE_EVENT(xen_mmu_flush_tlb_single, TRACE_EVENT(xen_mmu_flush_tlb_others, TP_PROTO(const struct cpumask *cpus, struct mm_struct *mm, - unsigned long addr), - TP_ARGS(cpus, mm, addr), + unsigned long addr, unsigned long end), + TP_ARGS(cpus, mm, addr, end), TP_STRUCT__entry( __field(unsigned, ncpus) __field(struct mm_struct *, mm) __field(unsigned long, addr) + __field(unsigned long, end) ), TP_fast_assign(__entry->ncpus = cpumask_weight(cpus); __entry->mm = mm; - __entry->addr = addr), - TP_printk("ncpus %d mm %p addr %lx", - __entry->ncpus, __entry->mm, __entry->addr) + __entry->addr = addr, + __entry->end = end), + TP_printk("ncpus %d mm %p addr %lx, end %lx", + __entry->ncpus, __entry->mm, __entry->addr, __entry->end) ); TRACE_EVENT(xen_mmu_write_cr3, -- cgit v1.2.3 From d8dfe60d6dcad5989c4558b753b98d657e2813c0 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Thu, 28 Jun 2012 09:02:18 +0800 Subject: x86/tlb: fall back to flush all when meet a THP large page We don't need to flush large pages by PAGE_SIZE step, that just waste time. and actually, large page don't need 'invlpg' optimizing according to our micro benchmark. So, just flush whole TLB is enough for them. The following result is tested on a 2CPU * 4cores * 2HT NHM EP machine, with THP 'always' setting. Multi-thread testing, '-t' paramter is thread number: without this patch with this patch ./mprotect -t 1 14ns 13ns ./mprotect -t 2 13ns 13ns ./mprotect -t 4 12ns 11ns ./mprotect -t 8 14ns 10ns ./mprotect -t 16 28ns 28ns ./mprotect -t 32 54ns 52ns ./mprotect -t 128 200ns 200ns Signed-off-by: Alex Shi Link: http://lkml.kernel.org/r/1340845344-27557-4-git-send-email-alex.shi@intel.com Signed-off-by: H. Peter Anvin --- arch/x86/mm/tlb.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'arch') diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 3b91c981a27f..184a02a4d871 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -318,12 +318,42 @@ void flush_tlb_mm(struct mm_struct *mm) #define FLUSHALL_BAR 16 +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +static inline unsigned long has_large_page(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + unsigned long addr = ALIGN(start, HPAGE_SIZE); + for (; addr < end; addr += HPAGE_SIZE) { + pgd = pgd_offset(mm, addr); + if (likely(!pgd_none(*pgd))) { + pud = pud_offset(pgd, addr); + if (likely(!pud_none(*pud))) { + pmd = pmd_offset(pud, addr); + if (likely(!pmd_none(*pmd))) + if (pmd_large(*pmd)) + return addr; + } + } + } + return 0; +} +#else +static inline unsigned long has_large_page(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ + return 0; +} +#endif void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { struct mm_struct *mm; if (!cpu_has_invlpg || vma->vm_flags & VM_HUGETLB) { +flush_all: flush_tlb_mm(vma->vm_mm); return; } @@ -346,6 +376,10 @@ void flush_tlb_range(struct vm_area_struct *vma, if ((end - start)/PAGE_SIZE > act_entries/FLUSHALL_BAR) local_flush_tlb(); else { + if (has_large_page(mm, start, end)) { + preempt_enable(); + goto flush_all; + } for (addr = start; addr < end; addr += PAGE_SIZE) __flush_tlb_single(addr); -- cgit v1.2.3 From c4211f42d3e66875298a5e26a75109878c80f15b Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Thu, 28 Jun 2012 09:02:19 +0800 Subject: x86/tlb: add tlb_flushall_shift for specific CPU Testing show different CPU type(micro architectures and NUMA mode) has different balance points between the TLB flush all and multiple invlpg. And there also has cases the tlb flush change has no any help. This patch give a interface to let x86 vendor developers have a chance to set different shift for different CPU type. like some machine in my hands, balance points is 16 entries on Romely-EP; while it is at 8 entries on Bloomfield NHM-EP; and is 256 on IVB mobile CPU. but on model 15 core2 Xeon using invlpg has nothing help. For untested machine, do a conservative optimization, same as NHM CPU. Signed-off-by: Alex Shi Link: http://lkml.kernel.org/r/1340845344-27557-5-git-send-email-alex.shi@intel.com Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/processor.h | 2 ++ arch/x86/kernel/cpu/common.c | 14 ++++++++++++-- arch/x86/kernel/cpu/intel.c | 34 ++++++++++++++++++++++++++++++++++ arch/x86/mm/tlb.c | 7 +++---- include/asm-generic/tlb.h | 3 ++- 5 files changed, 53 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 39b2bd48dfbc..d048cad9bcad 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -72,6 +72,8 @@ extern u16 __read_mostly tlb_lli_4m[NR_INFO]; extern u16 __read_mostly tlb_lld_4k[NR_INFO]; extern u16 __read_mostly tlb_lld_2m[NR_INFO]; extern u16 __read_mostly tlb_lld_4m[NR_INFO]; +extern s8 __read_mostly tlb_flushall_shift; + /* * CPU type and hardware bug flags. Kept separately for each CPU. * Members of this structure are referenced in head.S, so think twice diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index b2016df00813..7595552600b8 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -459,16 +459,26 @@ u16 __read_mostly tlb_lld_4k[NR_INFO]; u16 __read_mostly tlb_lld_2m[NR_INFO]; u16 __read_mostly tlb_lld_4m[NR_INFO]; +/* + * tlb_flushall_shift shows the balance point in replacing cr3 write + * with multiple 'invlpg'. It will do this replacement when + * flush_tlb_lines <= active_lines/2^tlb_flushall_shift. + * If tlb_flushall_shift is -1, means the replacement will be disabled. + */ +s8 __read_mostly tlb_flushall_shift = -1; + void __cpuinit cpu_detect_tlb(struct cpuinfo_x86 *c) { if (this_cpu->c_detect_tlb) this_cpu->c_detect_tlb(c); printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \ - "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d\n", + "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \ + "tlb_flushall_shift is 0x%x\n", tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES], tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES], - tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES]); + tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES], + tlb_flushall_shift); } void __cpuinit detect_ht(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index ed0d512cf51b..0a4ce2980a5a 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -610,6 +610,39 @@ static void __cpuinit intel_tlb_lookup(const unsigned char desc) } } +static void __cpuinit intel_tlb_flushall_shift_set(struct cpuinfo_x86 *c) +{ + if (!cpu_has_invlpg) { + tlb_flushall_shift = -1; + return; + } + switch ((c->x86 << 8) + c->x86_model) { + case 0x60f: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */ + case 0x616: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */ + case 0x617: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */ + case 0x61d: /* six-core 45 nm xeon "Dunnington" */ + tlb_flushall_shift = -1; + break; + case 0x61a: /* 45 nm nehalem, "Bloomfield" */ + case 0x61e: /* 45 nm nehalem, "Lynnfield" */ + case 0x625: /* 32 nm nehalem, "Clarkdale" */ + case 0x62c: /* 32 nm nehalem, "Gulftown" */ + case 0x62e: /* 45 nm nehalem-ex, "Beckton" */ + case 0x62f: /* 32 nm Xeon E7 */ + tlb_flushall_shift = 6; + break; + case 0x62a: /* SandyBridge */ + case 0x62d: /* SandyBridge, "Romely-EP" */ + tlb_flushall_shift = 5; + break; + case 0x63a: /* Ivybridge */ + tlb_flushall_shift = 1; + break; + default: + tlb_flushall_shift = 6; + } +} + static void __cpuinit intel_detect_tlb(struct cpuinfo_x86 *c) { int i, j, n; @@ -630,6 +663,7 @@ static void __cpuinit intel_detect_tlb(struct cpuinfo_x86 *c) for (j = 1 ; j < 16 ; j++) intel_tlb_lookup(desc[j]); } + intel_tlb_flushall_shift_set(c); } static const struct cpu_dev __cpuinitconst intel_cpu_dev = { diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 184a02a4d871..2939f2f9edbb 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -316,8 +316,6 @@ void flush_tlb_mm(struct mm_struct *mm) preempt_enable(); } -#define FLUSHALL_BAR 16 - #ifdef CONFIG_TRANSPARENT_HUGEPAGE static inline unsigned long has_large_page(struct mm_struct *mm, unsigned long start, unsigned long end) @@ -352,7 +350,7 @@ void flush_tlb_range(struct vm_area_struct *vma, { struct mm_struct *mm; - if (!cpu_has_invlpg || vma->vm_flags & VM_HUGETLB) { + if (vma->vm_flags & VM_HUGETLB || tlb_flushall_shift == -1) { flush_all: flush_tlb_mm(vma->vm_mm); return; @@ -373,7 +371,8 @@ flush_all: act_entries = tlb_entries > mm->total_vm ? mm->total_vm : tlb_entries; - if ((end - start)/PAGE_SIZE > act_entries/FLUSHALL_BAR) + if ((end - start) >> PAGE_SHIFT > + act_entries >> tlb_flushall_shift) local_flush_tlb(); else { if (has_large_page(mm, start, end)) { diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h index f96a5b58a975..75e888b3cfd2 100644 --- a/include/asm-generic/tlb.h +++ b/include/asm-generic/tlb.h @@ -113,7 +113,8 @@ static inline int tlb_fast_mode(struct mmu_gather *tlb) void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm); void tlb_flush_mmu(struct mmu_gather *tlb); -void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end); +void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, + unsigned long end); int __tlb_remove_page(struct mmu_gather *tlb, struct page *page); /* tlb_remove_page -- cgit v1.2.3 From 3df3212f9722c7e45c723b9ea231a04ba4dbc47c Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Thu, 28 Jun 2012 09:02:20 +0800 Subject: x86/tlb: add tlb_flushall_shift knob into debugfs kernel will replace cr3 rewrite with invlpg when tlb_flush_entries <= active_tlb_entries / 2^tlb_flushall_factor if tlb_flushall_factor is -1, kernel won't do this replacement. User can modify its value according to specific CPU/applications. Thanks for Borislav providing the help message of CONFIG_DEBUG_TLBFLUSH. Signed-off-by: Alex Shi Link: http://lkml.kernel.org/r/1340845344-27557-6-git-send-email-alex.shi@intel.com Signed-off-by: H. Peter Anvin --- arch/x86/Kconfig.debug | 19 +++++++++++++++++++ arch/x86/mm/tlb.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) (limited to 'arch') diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index e46c2147397f..b322f124ee3c 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -129,6 +129,25 @@ config DOUBLEFAULT option saves about 4k and might cause you much additional grey hair. +config DEBUG_TLBFLUSH + bool "Set upper limit of TLB entries to flush one-by-one" + depends on DEBUG_KERNEL && (X86_64 || X86_INVLPG) + ---help--- + + X86-only for now. + + This option allows the user to tune the amount of TLB entries the + kernel flushes one-by-one instead of doing a full TLB flush. In + certain situations, the former is cheaper. This is controlled by the + tlb_flushall_shift knob under /sys/kernel/debug/x86. If you set it + to -1, the code flushes the whole TLB unconditionally. Otherwise, + for positive values of it, the kernel will use single TLB entry + invalidating instructions according to the following formula: + + flush_entries <= active_tlb_entries / 2^tlb_flushall_shift + + If in doubt, say "N". + config IOMMU_DEBUG bool "Enable IOMMU debugging" depends on GART_IOMMU && DEBUG_KERNEL diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 2939f2f9edbb..5911f61e300e 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -12,6 +12,7 @@ #include #include #include +#include DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = { &init_mm, 0, }; @@ -430,3 +431,53 @@ void flush_tlb_all(void) { on_each_cpu(do_flush_tlb_all, NULL, 1); } + +#ifdef CONFIG_DEBUG_TLBFLUSH +static ssize_t tlbflush_read_file(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + char buf[32]; + unsigned int len; + + len = sprintf(buf, "%hd\n", tlb_flushall_shift); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t tlbflush_write_file(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + char buf[32]; + ssize_t len; + s8 shift; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + if (kstrtos8(buf, 0, &shift)) + return -EINVAL; + + if (shift > 64) + return -EINVAL; + + tlb_flushall_shift = shift; + return count; +} + +static const struct file_operations fops_tlbflush = { + .read = tlbflush_read_file, + .write = tlbflush_write_file, + .llseek = default_llseek, +}; + +static int __cpuinit create_tlb_flushall_shift(void) +{ + if (cpu_has_invlpg) { + debugfs_create_file("tlb_flushall_shift", S_IRUSR | S_IWUSR, + arch_debugfs_dir, NULL, &fops_tlbflush); + } + return 0; +} +late_initcall(create_tlb_flushall_shift); +#endif -- cgit v1.2.3 From 611ae8e3f5204f7480b3b405993b3352cfa16662 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Thu, 28 Jun 2012 09:02:22 +0800 Subject: x86/tlb: enable tlb flush range support for x86 Not every tlb_flush execution moment is really need to evacuate all TLB entries, like in munmap, just few 'invlpg' is better for whole process performance, since it leaves most of TLB entries for later accessing. This patch also rewrite flush_tlb_range for 2 purposes: 1, split it out to get flush_blt_mm_range function. 2, clean up to reduce line breaking, thanks for Borislav's input. My micro benchmark 'mummap' http://lkml.org/lkml/2012/5/17/59 show that the random memory access on other CPU has 0~50% speed up on a 2P * 4cores * HT NHM EP while do 'munmap'. Thanks Yongjie's testing on this patch: ------------- I used Linux 3.4-RC6 w/ and w/o his patches as Xen dom0 and guest kernel. After running two benchmarks in Xen HVM guest, I found his patches brought about 1%~3% performance gain in 'kernel build' and 'netperf' testing, though the performance gain was not very stable in 'kernel build' testing. Some detailed testing results are below. Testing Environment: Hardware: Romley-EP platform Xen version: latest upstream Linux kernel: 3.4-RC6 Guest vCPU number: 8 NIC: Intel 82599 (10GB bandwidth) In 'kernel build' testing in guest: Command line | performance gain make -j 4 | 3.81% make -j 8 | 0.37% make -j 16 | -0.52% In 'netperf' testing, we tested TCP_STREAM with default socket size 16384 byte as large packet and 64 byte as small packet. I used several clients to add networking pressure, then 'netperf' server automatically generated several threads to response them. I also used large-size packet and small-size packet in the testing. Packet size | Thread number | performance gain 16384 bytes | 4 | 0.02% 16384 bytes | 8 | 2.21% 16384 bytes | 16 | 2.04% 64 bytes | 4 | 1.07% 64 bytes | 8 | 3.31% 64 bytes | 16 | 0.71% Signed-off-by: Alex Shi Link: http://lkml.kernel.org/r/1340845344-27557-8-git-send-email-alex.shi@intel.com Tested-by: Ren, Yongjie Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/tlb.h | 9 +++- arch/x86/include/asm/tlbflush.h | 17 ++++-- arch/x86/mm/tlb.c | 112 +++++++++++++++++----------------------- 3 files changed, 68 insertions(+), 70 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/tlb.h b/arch/x86/include/asm/tlb.h index 829215fef9ee..4fef20773b8f 100644 --- a/arch/x86/include/asm/tlb.h +++ b/arch/x86/include/asm/tlb.h @@ -4,7 +4,14 @@ #define tlb_start_vma(tlb, vma) do { } while (0) #define tlb_end_vma(tlb, vma) do { } while (0) #define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0) -#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) + +#define tlb_flush(tlb) \ +{ \ + if (tlb->fullmm == 0) \ + flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end, 0UL); \ + else \ + flush_tlb_mm_range(tlb->mm, 0UL, TLB_FLUSH_ALL, 0UL); \ +} #include diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 33608d96d68b..621b959e1dbf 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -105,6 +105,13 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, __flush_tlb(); } +static inline void flush_tlb_mm_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end, unsigned long vmflag) +{ + if (vma->vm_mm == current->active_mm) + __flush_tlb(); +} + static inline void native_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long start, @@ -122,12 +129,16 @@ static inline void reset_lazy_tlbstate(void) #define local_flush_tlb() __flush_tlb() +#define flush_tlb_mm(mm) flush_tlb_mm_range(mm, 0UL, TLB_FLUSH_ALL, 0UL) + +#define flush_tlb_range(vma, start, end) \ + flush_tlb_mm_range(vma->vm_mm, start, end, vma->vm_flags) + extern void flush_tlb_all(void); extern void flush_tlb_current_task(void); -extern void flush_tlb_mm(struct mm_struct *); extern void flush_tlb_page(struct vm_area_struct *, unsigned long); -extern void flush_tlb_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end); +extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, + unsigned long end, unsigned long vmflag); #define flush_tlb() flush_tlb_current_task() diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 5911f61e300e..481737def84a 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -301,23 +301,10 @@ void flush_tlb_current_task(void) preempt_enable(); } -void flush_tlb_mm(struct mm_struct *mm) -{ - preempt_disable(); - - if (current->active_mm == mm) { - if (current->mm) - local_flush_tlb(); - else - leave_mm(smp_processor_id()); - } - if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) - flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL); - - preempt_enable(); -} - -#ifdef CONFIG_TRANSPARENT_HUGEPAGE +/* + * It can find out the THP large page, or + * HUGETLB page in tlb_flush when THP disabled + */ static inline unsigned long has_large_page(struct mm_struct *mm, unsigned long start, unsigned long end) { @@ -339,68 +326,61 @@ static inline unsigned long has_large_page(struct mm_struct *mm, } return 0; } -#else -static inline unsigned long has_large_page(struct mm_struct *mm, - unsigned long start, unsigned long end) -{ - return 0; -} -#endif -void flush_tlb_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) -{ - struct mm_struct *mm; - if (vma->vm_flags & VM_HUGETLB || tlb_flushall_shift == -1) { -flush_all: - flush_tlb_mm(vma->vm_mm); - return; - } +void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, + unsigned long end, unsigned long vmflag) +{ + unsigned long addr; + unsigned act_entries, tlb_entries = 0; preempt_disable(); - mm = vma->vm_mm; - if (current->active_mm == mm) { - if (current->mm) { - unsigned long addr, vmflag = vma->vm_flags; - unsigned act_entries, tlb_entries = 0; + if (current->active_mm != mm) + goto flush_all; - if (vmflag & VM_EXEC) - tlb_entries = tlb_lli_4k[ENTRIES]; - else - tlb_entries = tlb_lld_4k[ENTRIES]; - - act_entries = tlb_entries > mm->total_vm ? - mm->total_vm : tlb_entries; + if (!current->mm) { + leave_mm(smp_processor_id()); + goto flush_all; + } - if ((end - start) >> PAGE_SHIFT > - act_entries >> tlb_flushall_shift) - local_flush_tlb(); - else { - if (has_large_page(mm, start, end)) { - preempt_enable(); - goto flush_all; - } - for (addr = start; addr < end; - addr += PAGE_SIZE) - __flush_tlb_single(addr); + if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1 + || vmflag == VM_HUGETLB) { + local_flush_tlb(); + goto flush_all; + } - if (cpumask_any_but(mm_cpumask(mm), - smp_processor_id()) < nr_cpu_ids) - flush_tlb_others(mm_cpumask(mm), mm, - start, end); - preempt_enable(); - return; - } - } else { - leave_mm(smp_processor_id()); + /* In modern CPU, last level tlb used for both data/ins */ + if (vmflag & VM_EXEC) + tlb_entries = tlb_lli_4k[ENTRIES]; + else + tlb_entries = tlb_lld_4k[ENTRIES]; + /* Assume all of TLB entries was occupied by this task */ + act_entries = mm->total_vm > tlb_entries ? tlb_entries : mm->total_vm; + + /* tlb_flushall_shift is on balance point, details in commit log */ + if ((end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift) + local_flush_tlb(); + else { + if (has_large_page(mm, start, end)) { + local_flush_tlb(); + goto flush_all; } + /* flush range by one by one 'invlpg' */ + for (addr = start; addr < end; addr += PAGE_SIZE) + __flush_tlb_single(addr); + + if (cpumask_any_but(mm_cpumask(mm), + smp_processor_id()) < nr_cpu_ids) + flush_tlb_others(mm_cpumask(mm), mm, start, end); + preempt_enable(); + return; } + +flush_all: if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL); preempt_enable(); } - void flush_tlb_page(struct vm_area_struct *vma, unsigned long start) { struct mm_struct *mm = vma->vm_mm; -- cgit v1.2.3 From 52aec3308db85f4e9f5c8b9f5dc4fbd0138c6fa4 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Thu, 28 Jun 2012 09:02:23 +0800 Subject: x86/tlb: replace INVALIDATE_TLB_VECTOR by CALL_FUNCTION_VECTOR There are 32 INVALIDATE_TLB_VECTOR now in kernel. That is quite big amount of vector in IDT. But it is still not enough, since modern x86 sever has more cpu number. That still causes heavy lock contention in TLB flushing. The patch using generic smp call function to replace it. That saved 32 vector number in IDT, and resolved the lock contention in TLB flushing on large system. In the NHM EX machine 4P * 8cores * HT = 64 CPUs, hackbench pthread has 3% performance increase. Signed-off-by: Alex Shi Link: http://lkml.kernel.org/r/1340845344-27557-9-git-send-email-alex.shi@intel.com Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/entry_arch.h | 9 -- arch/x86/include/asm/irq_vectors.h | 11 -- arch/x86/kernel/entry_64.S | 18 --- arch/x86/kernel/irqinit.c | 73 ----------- arch/x86/mm/tlb.c | 242 +++++++------------------------------ 5 files changed, 47 insertions(+), 306 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h index 0baa628e330c..40afa0005c69 100644 --- a/arch/x86/include/asm/entry_arch.h +++ b/arch/x86/include/asm/entry_arch.h @@ -15,15 +15,6 @@ BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR) BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR) BUILD_INTERRUPT(reboot_interrupt,REBOOT_VECTOR) - -.irp idx,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \ - 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 -.if NUM_INVALIDATE_TLB_VECTORS > \idx -BUILD_INTERRUPT3(invalidate_interrupt\idx, - (INVALIDATE_TLB_VECTOR_START)+\idx, - smp_invalidate_interrupt) -.endif -.endr #endif BUILD_INTERRUPT(x86_platform_ipi, X86_PLATFORM_IPI_VECTOR) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 4b4448761e88..1508e518c7e3 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -119,17 +119,6 @@ */ #define LOCAL_TIMER_VECTOR 0xef -/* up to 32 vectors used for spreading out TLB flushes: */ -#if NR_CPUS <= 32 -# define NUM_INVALIDATE_TLB_VECTORS (NR_CPUS) -#else -# define NUM_INVALIDATE_TLB_VECTORS (32) -#endif - -#define INVALIDATE_TLB_VECTOR_END (0xee) -#define INVALIDATE_TLB_VECTOR_START \ - (INVALIDATE_TLB_VECTOR_END-NUM_INVALIDATE_TLB_VECTORS+1) - #define NR_VECTORS 256 #define FPU_IRQ 13 diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 7d65133b51be..bcf28e1ce1a7 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1048,24 +1048,6 @@ apicinterrupt LOCAL_TIMER_VECTOR \ apicinterrupt X86_PLATFORM_IPI_VECTOR \ x86_platform_ipi smp_x86_platform_ipi -#ifdef CONFIG_SMP - ALIGN - INTR_FRAME -.irp idx,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \ - 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 -.if NUM_INVALIDATE_TLB_VECTORS > \idx -ENTRY(invalidate_interrupt\idx) - pushq_cfi $~(INVALIDATE_TLB_VECTOR_START+\idx) - jmp .Lcommon_invalidate_interrupt0 - CFI_ADJUST_CFA_OFFSET -8 -END(invalidate_interrupt\idx) -.endif -.endr - CFI_ENDPROC -apicinterrupt INVALIDATE_TLB_VECTOR_START, \ - invalidate_interrupt0, smp_invalidate_interrupt -#endif - apicinterrupt THRESHOLD_APIC_VECTOR \ threshold_interrupt smp_threshold_interrupt apicinterrupt THERMAL_APIC_VECTOR \ diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 252981afd6c4..6e03b0d69138 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c @@ -171,79 +171,6 @@ static void __init smp_intr_init(void) */ alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); - /* IPIs for invalidation */ -#define ALLOC_INVTLB_VEC(NR) \ - alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+NR, \ - invalidate_interrupt##NR) - - switch (NUM_INVALIDATE_TLB_VECTORS) { - default: - ALLOC_INVTLB_VEC(31); - case 31: - ALLOC_INVTLB_VEC(30); - case 30: - ALLOC_INVTLB_VEC(29); - case 29: - ALLOC_INVTLB_VEC(28); - case 28: - ALLOC_INVTLB_VEC(27); - case 27: - ALLOC_INVTLB_VEC(26); - case 26: - ALLOC_INVTLB_VEC(25); - case 25: - ALLOC_INVTLB_VEC(24); - case 24: - ALLOC_INVTLB_VEC(23); - case 23: - ALLOC_INVTLB_VEC(22); - case 22: - ALLOC_INVTLB_VEC(21); - case 21: - ALLOC_INVTLB_VEC(20); - case 20: - ALLOC_INVTLB_VEC(19); - case 19: - ALLOC_INVTLB_VEC(18); - case 18: - ALLOC_INVTLB_VEC(17); - case 17: - ALLOC_INVTLB_VEC(16); - case 16: - ALLOC_INVTLB_VEC(15); - case 15: - ALLOC_INVTLB_VEC(14); - case 14: - ALLOC_INVTLB_VEC(13); - case 13: - ALLOC_INVTLB_VEC(12); - case 12: - ALLOC_INVTLB_VEC(11); - case 11: - ALLOC_INVTLB_VEC(10); - case 10: - ALLOC_INVTLB_VEC(9); - case 9: - ALLOC_INVTLB_VEC(8); - case 8: - ALLOC_INVTLB_VEC(7); - case 7: - ALLOC_INVTLB_VEC(6); - case 6: - ALLOC_INVTLB_VEC(5); - case 5: - ALLOC_INVTLB_VEC(4); - case 4: - ALLOC_INVTLB_VEC(3); - case 3: - ALLOC_INVTLB_VEC(2); - case 2: - ALLOC_INVTLB_VEC(1); - case 1: - ALLOC_INVTLB_VEC(0); - break; - } - /* IPI for generic function call */ alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 481737def84a..2b5f506a7655 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -28,34 +28,14 @@ DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) * * More scalable flush, from Andi Kleen * - * To avoid global state use 8 different call vectors. - * Each CPU uses a specific vector to trigger flushes on other - * CPUs. Depending on the received vector the target CPUs look into - * the right array slot for the flush data. - * - * With more than 8 CPUs they are hashed to the 8 available - * vectors. The limited global vector space forces us to this right now. - * In future when interrupts are split into per CPU domains this could be - * fixed, at the cost of triggering multiple IPIs in some cases. + * Implement flush IPI by CALL_FUNCTION_VECTOR, Alex Shi */ -union smp_flush_state { - struct { - struct mm_struct *flush_mm; - unsigned long flush_start; - unsigned long flush_end; - raw_spinlock_t tlbstate_lock; - DECLARE_BITMAP(flush_cpumask, NR_CPUS); - }; - char pad[INTERNODE_CACHE_BYTES]; -} ____cacheline_internodealigned_in_smp; - -/* State is put into the per CPU data section, but padded - to a full cache line because other CPUs can access it and we don't - want false sharing in the per cpu data segment. */ -static union smp_flush_state flush_state[NUM_INVALIDATE_TLB_VECTORS]; - -static DEFINE_PER_CPU_READ_MOSTLY(int, tlb_vector_offset); +struct flush_tlb_info { + struct mm_struct *flush_mm; + unsigned long flush_start; + unsigned long flush_end; +}; /* * We cannot call mmdrop() because we are in interrupt context, @@ -74,28 +54,25 @@ void leave_mm(int cpu) EXPORT_SYMBOL_GPL(leave_mm); /* - * * The flush IPI assumes that a thread switch happens in this order: * [cpu0: the cpu that switches] * 1) switch_mm() either 1a) or 1b) * 1a) thread switch to a different mm - * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask); - * Stop ipi delivery for the old mm. This is not synchronized with - * the other cpus, but smp_invalidate_interrupt ignore flush ipis - * for the wrong mm, and in the worst case we perform a superfluous - * tlb flush. - * 1a2) set cpu mmu_state to TLBSTATE_OK - * Now the smp_invalidate_interrupt won't call leave_mm if cpu0 - * was in lazy tlb mode. - * 1a3) update cpu active_mm + * 1a1) set cpu_tlbstate to TLBSTATE_OK + * Now the tlb flush NMI handler flush_tlb_func won't call leave_mm + * if cpu0 was in lazy tlb mode. + * 1a2) update cpu active_mm * Now cpu0 accepts tlb flushes for the new mm. - * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask); + * 1a3) cpu_set(cpu, new_mm->cpu_vm_mask); * Now the other cpus will send tlb flush ipis. * 1a4) change cr3. + * 1a5) cpu_clear(cpu, old_mm->cpu_vm_mask); + * Stop ipi delivery for the old mm. This is not synchronized with + * the other cpus, but flush_tlb_func ignore flush ipis for the wrong + * mm, and in the worst case we perform a superfluous tlb flush. * 1b) thread switch without mm change - * cpu active_mm is correct, cpu0 already handles - * flush ipis. - * 1b1) set cpu mmu_state to TLBSTATE_OK + * cpu active_mm is correct, cpu0 already handles flush ipis. + * 1b1) set cpu_tlbstate to TLBSTATE_OK * 1b2) test_and_set the cpu bit in cpu_vm_mask. * Atomically set the bit [other cpus will start sending flush ipis], * and test the bit. @@ -108,186 +85,61 @@ EXPORT_SYMBOL_GPL(leave_mm); * runs in kernel space, the cpu could load tlb entries for user space * pages. * - * The good news is that cpu mmu_state is local to each cpu, no + * The good news is that cpu_tlbstate is local to each cpu, no * write/read ordering problems. */ /* - * TLB flush IPI: - * + * TLB flush funcation: * 1) Flush the tlb entries if the cpu uses the mm that's being flushed. * 2) Leave the mm if we are in the lazy tlb mode. - * - * Interrupts are disabled. - */ - -/* - * FIXME: use of asmlinkage is not consistent. On x86_64 it's noop - * but still used for documentation purpose but the usage is slightly - * inconsistent. On x86_32, asmlinkage is regparm(0) but interrupt - * entry calls in with the first parameter in %eax. Maybe define - * intrlinkage? */ -#ifdef CONFIG_X86_64 -asmlinkage -#endif -void smp_invalidate_interrupt(struct pt_regs *regs) +static void flush_tlb_func(void *info) { - unsigned int cpu; - unsigned int sender; - union smp_flush_state *f; - - cpu = smp_processor_id(); - /* - * orig_rax contains the negated interrupt vector. - * Use that to determine where the sender put the data. - */ - sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START; - f = &flush_state[sender]; - - if (!cpumask_test_cpu(cpu, to_cpumask(f->flush_cpumask))) - goto out; - /* - * This was a BUG() but until someone can quote me the - * line from the intel manual that guarantees an IPI to - * multiple CPUs is retried _only_ on the erroring CPUs - * its staying as a return - * - * BUG(); - */ - - if (f->flush_mm == this_cpu_read(cpu_tlbstate.active_mm)) { - if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) { - if (f->flush_end == TLB_FLUSH_ALL - || !cpu_has_invlpg) - local_flush_tlb(); - else if (!f->flush_end) - __flush_tlb_single(f->flush_start); - else { - unsigned long addr; - addr = f->flush_start; - while (addr < f->flush_end) { - __flush_tlb_single(addr); - addr += PAGE_SIZE; - } - } - } else - leave_mm(cpu); - } -out: - ack_APIC_irq(); - smp_mb__before_clear_bit(); - cpumask_clear_cpu(cpu, to_cpumask(f->flush_cpumask)); - smp_mb__after_clear_bit(); - inc_irq_stat(irq_tlb_count); -} + struct flush_tlb_info *f = info; -static void flush_tlb_others_ipi(const struct cpumask *cpumask, - struct mm_struct *mm, unsigned long start, - unsigned long end) -{ - unsigned int sender; - union smp_flush_state *f; - - /* Caller has disabled preemption */ - sender = this_cpu_read(tlb_vector_offset); - f = &flush_state[sender]; - - if (nr_cpu_ids > NUM_INVALIDATE_TLB_VECTORS) - raw_spin_lock(&f->tlbstate_lock); - - f->flush_mm = mm; - f->flush_start = start; - f->flush_end = end; - if (cpumask_andnot(to_cpumask(f->flush_cpumask), cpumask, cpumask_of(smp_processor_id()))) { - /* - * We have to send the IPI only to - * CPUs affected. - */ - apic->send_IPI_mask(to_cpumask(f->flush_cpumask), - INVALIDATE_TLB_VECTOR_START + sender); - - while (!cpumask_empty(to_cpumask(f->flush_cpumask))) - cpu_relax(); - } + if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm)) + return; + + if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) { + if (f->flush_end == TLB_FLUSH_ALL || !cpu_has_invlpg) + local_flush_tlb(); + else if (!f->flush_end) + __flush_tlb_single(f->flush_start); + else { + unsigned long addr; + addr = f->flush_start; + while (addr < f->flush_end) { + __flush_tlb_single(addr); + addr += PAGE_SIZE; + } + } + } else + leave_mm(smp_processor_id()); - f->flush_mm = NULL; - f->flush_start = 0; - f->flush_end = 0; - if (nr_cpu_ids > NUM_INVALIDATE_TLB_VECTORS) - raw_spin_unlock(&f->tlbstate_lock); } void native_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long start, unsigned long end) { + struct flush_tlb_info info; + info.flush_mm = mm; + info.flush_start = start; + info.flush_end = end; + if (is_uv_system()) { unsigned int cpu; cpu = smp_processor_id(); cpumask = uv_flush_tlb_others(cpumask, mm, start, end, cpu); if (cpumask) - flush_tlb_others_ipi(cpumask, mm, start, end); + smp_call_function_many(cpumask, flush_tlb_func, + &info, 1); return; } - flush_tlb_others_ipi(cpumask, mm, start, end); -} - -static void __cpuinit calculate_tlb_offset(void) -{ - int cpu, node, nr_node_vecs, idx = 0; - /* - * we are changing tlb_vector_offset for each CPU in runtime, but this - * will not cause inconsistency, as the write is atomic under X86. we - * might see more lock contentions in a short time, but after all CPU's - * tlb_vector_offset are changed, everything should go normal - * - * Note: if NUM_INVALIDATE_TLB_VECTORS % nr_online_nodes !=0, we might - * waste some vectors. - **/ - if (nr_online_nodes > NUM_INVALIDATE_TLB_VECTORS) - nr_node_vecs = 1; - else - nr_node_vecs = NUM_INVALIDATE_TLB_VECTORS/nr_online_nodes; - - for_each_online_node(node) { - int node_offset = (idx % NUM_INVALIDATE_TLB_VECTORS) * - nr_node_vecs; - int cpu_offset = 0; - for_each_cpu(cpu, cpumask_of_node(node)) { - per_cpu(tlb_vector_offset, cpu) = node_offset + - cpu_offset; - cpu_offset++; - cpu_offset = cpu_offset % nr_node_vecs; - } - idx++; - } -} - -static int __cpuinit tlb_cpuhp_notify(struct notifier_block *n, - unsigned long action, void *hcpu) -{ - switch (action & 0xf) { - case CPU_ONLINE: - case CPU_DEAD: - calculate_tlb_offset(); - } - return NOTIFY_OK; -} - -static int __cpuinit init_smp_flush(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(flush_state); i++) - raw_spin_lock_init(&flush_state[i].tlbstate_lock); - - calculate_tlb_offset(); - hotcpu_notifier(tlb_cpuhp_notify, 0); - return 0; + smp_call_function_many(cpumask, flush_tlb_func, &info, 1); } -core_initcall(init_smp_flush); void flush_tlb_current_task(void) { -- cgit v1.2.3 From effee4b9b3b0aa5770bcd98de5f672b05b27703c Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Thu, 28 Jun 2012 09:02:24 +0800 Subject: x86/tlb: do flush_tlb_kernel_range by 'invlpg' This patch do flush_tlb_kernel_range by 'invlpg'. The performance pay and gain was analyzed in previous patch (x86/flush_tlb: try flush_tlb_single one by one in flush_tlb_range). In the testing: http://lkml.org/lkml/2012/6/21/10 The pay is mostly covered by long kernel path, but the gain is still quite clear, memory access in user APP can increase 30+% when kernel execute this funtion. Signed-off-by: Alex Shi Link: http://lkml.kernel.org/r/1340845344-27557-10-git-send-email-alex.shi@intel.com Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/tlbflush.h | 13 +++++++------ arch/x86/mm/tlb.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 621b959e1dbf..b5a27bd77669 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -123,6 +123,12 @@ static inline void reset_lazy_tlbstate(void) { } +static inline void flush_tlb_kernel_range(unsigned long start, + unsigned long end) +{ + flush_tlb_all(); +} + #else /* SMP */ #include @@ -139,6 +145,7 @@ extern void flush_tlb_current_task(void); extern void flush_tlb_page(struct vm_area_struct *, unsigned long); extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long vmflag); +extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); #define flush_tlb() flush_tlb_current_task() @@ -168,10 +175,4 @@ static inline void reset_lazy_tlbstate(void) native_flush_tlb_others(mask, mm, start, end) #endif -static inline void flush_tlb_kernel_range(unsigned long start, - unsigned long end) -{ - flush_tlb_all(); -} - #endif /* _ASM_X86_TLBFLUSH_H */ diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 2b5f506a7655..613cd83e8c0c 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -264,6 +264,36 @@ void flush_tlb_all(void) on_each_cpu(do_flush_tlb_all, NULL, 1); } +static void do_kernel_range_flush(void *info) +{ + struct flush_tlb_info *f = info; + unsigned long addr; + + /* flush range by one by one 'invlpg' */ + for (addr = f->flush_start; addr < f->flush_end; addr += PAGE_SIZE) + __flush_tlb_single(addr); +} + +void flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + unsigned act_entries; + struct flush_tlb_info info; + + /* In modern CPU, last level tlb used for both data/ins */ + act_entries = tlb_lld_4k[ENTRIES]; + + /* Balance as user space task's flush, a bit conservative */ + if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1 || + (end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift) + + on_each_cpu(do_flush_tlb_all, NULL, 1); + else { + info.flush_start = start; + info.flush_end = end; + on_each_cpu(do_kernel_range_flush, &info, 1); + } +} + #ifdef CONFIG_DEBUG_TLBFLUSH static ssize_t tlbflush_read_file(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -- cgit v1.2.3 From 16e5e2c471ab889f838bfe1c44032d0481c115e1 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 19 Apr 2012 13:16:46 -0700 Subject: ARM: OMAP AM35x: clockdomain data: Fix clockdomain dependencies The am35x family of SoCs do not have an IVA so a parallel set of clockdomain dependencies are required that are simililar to OMAP3 but without any IVA dependencies. Signed-off-by: Mark A. Greer Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomains3xxx_data.c | 157 +++++++++++++++++++++++++--- 1 file changed, 144 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clockdomains3xxx_data.c b/arch/arm/mach-omap2/clockdomains3xxx_data.c index 6038adb97710..8e35080026d3 100644 --- a/arch/arm/mach-omap2/clockdomains3xxx_data.c +++ b/arch/arm/mach-omap2/clockdomains3xxx_data.c @@ -59,6 +59,12 @@ static struct clkdm_dep gfx_sgx_3xxx_wkdeps[] = { { NULL }, }; +static struct clkdm_dep gfx_sgx_am35x_wkdeps[] = { + { .clkdm_name = "mpu_clkdm" }, + { .clkdm_name = "wkup_clkdm" }, + { NULL }, +}; + /* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */ static struct clkdm_dep per_wkdeps[] = { { .clkdm_name = "core_l3_clkdm" }, @@ -69,6 +75,14 @@ static struct clkdm_dep per_wkdeps[] = { { NULL }, }; +static struct clkdm_dep per_am35x_wkdeps[] = { + { .clkdm_name = "core_l3_clkdm" }, + { .clkdm_name = "core_l4_clkdm" }, + { .clkdm_name = "mpu_clkdm" }, + { .clkdm_name = "wkup_clkdm" }, + { NULL }, +}; + /* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */ static struct clkdm_dep usbhost_wkdeps[] = { { .clkdm_name = "core_l3_clkdm" }, @@ -79,6 +93,14 @@ static struct clkdm_dep usbhost_wkdeps[] = { { NULL }, }; +static struct clkdm_dep usbhost_am35x_wkdeps[] = { + { .clkdm_name = "core_l3_clkdm" }, + { .clkdm_name = "core_l4_clkdm" }, + { .clkdm_name = "mpu_clkdm" }, + { .clkdm_name = "wkup_clkdm" }, + { NULL }, +}; + /* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */ static struct clkdm_dep mpu_3xxx_wkdeps[] = { { .clkdm_name = "core_l3_clkdm" }, @@ -89,6 +111,14 @@ static struct clkdm_dep mpu_3xxx_wkdeps[] = { { NULL }, }; +static struct clkdm_dep mpu_am35x_wkdeps[] = { + { .clkdm_name = "core_l3_clkdm" }, + { .clkdm_name = "core_l4_clkdm" }, + { .clkdm_name = "dss_clkdm" }, + { .clkdm_name = "per_clkdm" }, + { NULL }, +}; + /* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */ static struct clkdm_dep iva2_wkdeps[] = { { .clkdm_name = "core_l3_clkdm" }, @@ -116,6 +146,12 @@ static struct clkdm_dep dss_wkdeps[] = { { NULL }, }; +static struct clkdm_dep dss_am35x_wkdeps[] = { + { .clkdm_name = "mpu_clkdm" }, + { .clkdm_name = "wkup_clkdm" }, + { NULL }, +}; + /* 3430: PM_WKDEP_NEON: MPU */ static struct clkdm_dep neon_wkdeps[] = { { .clkdm_name = "mpu_clkdm" }, @@ -131,6 +167,11 @@ static struct clkdm_dep dss_sleepdeps[] = { { NULL }, }; +static struct clkdm_dep dss_am35x_sleepdeps[] = { + { .clkdm_name = "mpu_clkdm" }, + { NULL }, +}; + /* 3430: CM_SLEEPDEP_PER: MPU, IVA */ static struct clkdm_dep per_sleepdeps[] = { { .clkdm_name = "mpu_clkdm" }, @@ -138,6 +179,11 @@ static struct clkdm_dep per_sleepdeps[] = { { NULL }, }; +static struct clkdm_dep per_am35x_sleepdeps[] = { + { .clkdm_name = "mpu_clkdm" }, + { NULL }, +}; + /* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */ static struct clkdm_dep usbhost_sleepdeps[] = { { .clkdm_name = "mpu_clkdm" }, @@ -145,6 +191,11 @@ static struct clkdm_dep usbhost_sleepdeps[] = { { NULL }, }; +static struct clkdm_dep usbhost_am35x_sleepdeps[] = { + { .clkdm_name = "mpu_clkdm" }, + { NULL }, +}; + /* 3430: CM_SLEEPDEP_CAM: MPU */ static struct clkdm_dep cam_sleepdeps[] = { { .clkdm_name = "mpu_clkdm" }, @@ -175,6 +226,15 @@ static struct clockdomain mpu_3xxx_clkdm = { .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK, }; +static struct clockdomain mpu_am35x_clkdm = { + .name = "mpu_clkdm", + .pwrdm = { .name = "mpu_pwrdm" }, + .flags = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP, + .dep_bit = OMAP3430_EN_MPU_SHIFT, + .wkdep_srcs = mpu_am35x_wkdeps, + .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK, +}; + static struct clockdomain neon_clkdm = { .name = "neon_clkdm", .pwrdm = { .name = "neon_pwrdm" }, @@ -210,6 +270,15 @@ static struct clockdomain sgx_clkdm = { .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK, }; +static struct clockdomain sgx_am35x_clkdm = { + .name = "sgx_clkdm", + .pwrdm = { .name = "sgx_pwrdm" }, + .flags = CLKDM_CAN_HWSUP_SWSUP, + .wkdep_srcs = gfx_sgx_am35x_wkdeps, + .sleepdep_srcs = gfx_sgx_sleepdeps, + .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK, +}; + /* * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but * then that information was removed from the 34xx ES2+ TRM. It is @@ -261,6 +330,16 @@ static struct clockdomain dss_3xxx_clkdm = { .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK, }; +static struct clockdomain dss_am35x_clkdm = { + .name = "dss_clkdm", + .pwrdm = { .name = "dss_pwrdm" }, + .flags = CLKDM_CAN_HWSUP_SWSUP, + .dep_bit = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT, + .wkdep_srcs = dss_am35x_wkdeps, + .sleepdep_srcs = dss_am35x_sleepdeps, + .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK, +}; + static struct clockdomain cam_clkdm = { .name = "cam_clkdm", .pwrdm = { .name = "cam_pwrdm" }, @@ -279,6 +358,15 @@ static struct clockdomain usbhost_clkdm = { .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK, }; +static struct clockdomain usbhost_am35x_clkdm = { + .name = "usbhost_clkdm", + .pwrdm = { .name = "core_pwrdm" }, + .flags = CLKDM_CAN_HWSUP_SWSUP, + .wkdep_srcs = usbhost_am35x_wkdeps, + .sleepdep_srcs = usbhost_am35x_sleepdeps, + .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK, +}; + static struct clockdomain per_clkdm = { .name = "per_clkdm", .pwrdm = { .name = "per_pwrdm" }, @@ -289,6 +377,16 @@ static struct clockdomain per_clkdm = { .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK, }; +static struct clockdomain per_am35x_clkdm = { + .name = "per_clkdm", + .pwrdm = { .name = "per_pwrdm" }, + .flags = CLKDM_CAN_HWSUP_SWSUP, + .dep_bit = OMAP3430_EN_PER_SHIFT, + .wkdep_srcs = per_am35x_wkdeps, + .sleepdep_srcs = per_am35x_sleepdeps, + .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK, +}; + /* * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is * switched of even if sdti is in use @@ -341,31 +439,44 @@ static struct clkdm_autodep clkdm_autodeps[] = { } }; +static struct clkdm_autodep clkdm_am35x_autodeps[] = { + { + .clkdm = { .name = "mpu_clkdm" }, + }, + { + .clkdm = { .name = NULL }, + } +}; + /* * */ -static struct clockdomain *clockdomains_omap3430_common[] __initdata = { +static struct clockdomain *clockdomains_common[] __initdata = { &wkup_common_clkdm, &cm_common_clkdm, &prm_common_clkdm, - &mpu_3xxx_clkdm, &neon_clkdm, - &iva2_clkdm, - &d2d_clkdm, &core_l3_3xxx_clkdm, &core_l4_3xxx_clkdm, - &dss_3xxx_clkdm, - &cam_clkdm, - &per_clkdm, &emu_clkdm, &dpll1_clkdm, - &dpll2_clkdm, &dpll3_clkdm, &dpll4_clkdm, NULL }; +static struct clockdomain *clockdomains_omap3430[] __initdata = { + &mpu_3xxx_clkdm, + &iva2_clkdm, + &d2d_clkdm, + &dss_3xxx_clkdm, + &cam_clkdm, + &per_clkdm, + &dpll2_clkdm, + NULL +}; + static struct clockdomain *clockdomains_omap3430es1[] __initdata = { &gfx_3430es1_clkdm, NULL, @@ -378,21 +489,41 @@ static struct clockdomain *clockdomains_omap3430es2plus[] __initdata = { NULL, }; +static struct clockdomain *clockdomains_am35x[] __initdata = { + &mpu_am35x_clkdm, + &sgx_am35x_clkdm, + &dss_am35x_clkdm, + &per_am35x_clkdm, + &usbhost_am35x_clkdm, + &dpll5_clkdm, + NULL +}; + void __init omap3xxx_clockdomains_init(void) { struct clockdomain **sc; + unsigned int rev; if (!cpu_is_omap34xx()) return; clkdm_register_platform_funcs(&omap3_clkdm_operations); - clkdm_register_clkdms(clockdomains_omap3430_common); + clkdm_register_clkdms(clockdomains_common); - sc = (omap_rev() == OMAP3430_REV_ES1_0) ? clockdomains_omap3430es1 : - clockdomains_omap3430es2plus; + rev = omap_rev(); - clkdm_register_clkdms(sc); + if (rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1) { + clkdm_register_clkdms(clockdomains_am35x); + clkdm_register_autodeps(clkdm_am35x_autodeps); + } else { + clkdm_register_clkdms(clockdomains_omap3430); + + sc = (rev == OMAP3430_REV_ES1_0) ? + clockdomains_omap3430es1 : clockdomains_omap3430es2plus; + + clkdm_register_clkdms(sc); + clkdm_register_autodeps(clkdm_autodeps); + } - clkdm_register_autodeps(clkdm_autodeps); clkdm_complete_init(); } -- cgit v1.2.3 From ff7ad7e492b13d4063313f4aace18ced0de8edb4 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Wed, 27 Jun 2012 18:43:59 -0600 Subject: arm: omap3: am35x: Set proper powerdomain states The am35x family of SoCs only support the PWRSTS_ON state so create a new set of powerdomain structures that ensure that only the ON state is entered. Signed-off-by: Mark A. Greer --- arch/arm/mach-omap2/powerdomains3xxx_data.c | 139 +++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c index fb0a0a6869d1..bb883e463078 100644 --- a/arch/arm/mach-omap2/powerdomains3xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c @@ -71,6 +71,22 @@ static struct powerdomain mpu_3xxx_pwrdm = { .voltdm = { .name = "mpu_iva" }, }; +static struct powerdomain mpu_am35x_pwrdm = { + .name = "mpu_pwrdm", + .prcm_offs = MPU_MOD, + .pwrsts = PWRSTS_ON, + .pwrsts_logic_ret = PWRSTS_ON, + .flags = PWRDM_HAS_MPU_QUIRK, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRSTS_ON, + }, + .pwrsts_mem_on = { + [0] = PWRSTS_ON, + }, + .voltdm = { .name = "mpu_iva" }, +}; + /* * The USBTLL Save-and-Restore mechanism is broken on * 3430s up to ES3.0 and 3630ES1.0. Hence this feature @@ -120,6 +136,23 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = { .voltdm = { .name = "core" }, }; +static struct powerdomain core_am35x_pwrdm = { + .name = "core_pwrdm", + .prcm_offs = CORE_MOD, + .pwrsts = PWRSTS_ON, + .pwrsts_logic_ret = PWRSTS_ON, + .banks = 2, + .pwrsts_mem_ret = { + [0] = PWRSTS_ON, /* MEM1RETSTATE */ + [1] = PWRSTS_ON, /* MEM2RETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRSTS_ON, /* MEM1ONSTATE */ + [1] = PWRSTS_ON, /* MEM2ONSTATE */ + }, + .voltdm = { .name = "core" }, +}; + static struct powerdomain dss_pwrdm = { .name = "dss_pwrdm", .prcm_offs = OMAP3430_DSS_MOD, @@ -135,6 +168,21 @@ static struct powerdomain dss_pwrdm = { .voltdm = { .name = "core" }, }; +static struct powerdomain dss_am35x_pwrdm = { + .name = "dss_pwrdm", + .prcm_offs = OMAP3430_DSS_MOD, + .pwrsts = PWRSTS_ON, + .pwrsts_logic_ret = PWRSTS_ON, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRSTS_ON, /* MEMRETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRSTS_ON, /* MEMONSTATE */ + }, + .voltdm = { .name = "core" }, +}; + /* * Although the 34XX TRM Rev K Table 4-371 notes that retention is a * possible SGX powerstate, the SGX device itself does not support @@ -156,6 +204,21 @@ static struct powerdomain sgx_pwrdm = { .voltdm = { .name = "core" }, }; +static struct powerdomain sgx_am35x_pwrdm = { + .name = "sgx_pwrdm", + .prcm_offs = OMAP3430ES2_SGX_MOD, + .pwrsts = PWRSTS_ON, + .pwrsts_logic_ret = PWRSTS_ON, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRSTS_ON, /* MEMRETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRSTS_ON, /* MEMONSTATE */ + }, + .voltdm = { .name = "core" }, +}; + static struct powerdomain cam_pwrdm = { .name = "cam_pwrdm", .prcm_offs = OMAP3430_CAM_MOD, @@ -186,6 +249,21 @@ static struct powerdomain per_pwrdm = { .voltdm = { .name = "core" }, }; +static struct powerdomain per_am35x_pwrdm = { + .name = "per_pwrdm", + .prcm_offs = OMAP3430_PER_MOD, + .pwrsts = PWRSTS_ON, + .pwrsts_logic_ret = PWRSTS_ON, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRSTS_ON, /* MEMRETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRSTS_ON, /* MEMONSTATE */ + }, + .voltdm = { .name = "core" }, +}; + static struct powerdomain emu_pwrdm = { .name = "emu_pwrdm", .prcm_offs = OMAP3430_EMU_MOD, @@ -200,6 +278,14 @@ static struct powerdomain neon_pwrdm = { .voltdm = { .name = "mpu_iva" }, }; +static struct powerdomain neon_am35x_pwrdm = { + .name = "neon_pwrdm", + .prcm_offs = OMAP3430_NEON_MOD, + .pwrsts = PWRSTS_ON, + .pwrsts_logic_ret = PWRSTS_ON, + .voltdm = { .name = "mpu_iva" }, +}; + static struct powerdomain usbhost_pwrdm = { .name = "usbhost_pwrdm", .prcm_offs = OMAP3430ES2_USBHOST_MOD, @@ -293,6 +379,22 @@ static struct powerdomain *powerdomains_omap3430es3_1plus[] __initdata = { NULL }; +static struct powerdomain *powerdomains_am35x[] __initdata = { + &wkup_omap2_pwrdm, + &mpu_am35x_pwrdm, + &neon_am35x_pwrdm, + &core_am35x_pwrdm, + &sgx_am35x_pwrdm, + &dss_am35x_pwrdm, + &per_am35x_pwrdm, + &emu_pwrdm, + &dpll1_pwrdm, + &dpll3_pwrdm, + &dpll4_pwrdm, + &dpll5_pwrdm, + NULL +}; + void __init omap3xxx_powerdomains_init(void) { unsigned int rev; @@ -301,21 +403,34 @@ void __init omap3xxx_powerdomains_init(void) return; pwrdm_register_platform_funcs(&omap3_pwrdm_operations); - pwrdm_register_pwrdms(powerdomains_omap3430_common); rev = omap_rev(); - if (rev == OMAP3430_REV_ES1_0) - pwrdm_register_pwrdms(powerdomains_omap3430es1); - else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 || - rev == OMAP3430_REV_ES3_0 || rev == OMAP3630_REV_ES1_0) - pwrdm_register_pwrdms(powerdomains_omap3430es2_es3_0); - else if (rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2 || - rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1 || - rev == OMAP3630_REV_ES1_1 || rev == OMAP3630_REV_ES1_2) - pwrdm_register_pwrdms(powerdomains_omap3430es3_1plus); - else - WARN(1, "OMAP3 powerdomain init: unknown chip type\n"); + if (rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1) { + pwrdm_register_pwrdms(powerdomains_am35x); + } else { + pwrdm_register_pwrdms(powerdomains_omap3430_common); + + switch (rev) { + case OMAP3430_REV_ES1_0: + pwrdm_register_pwrdms(powerdomains_omap3430es1); + break; + case OMAP3430_REV_ES2_0: + case OMAP3430_REV_ES2_1: + case OMAP3430_REV_ES3_0: + case OMAP3630_REV_ES1_0: + pwrdm_register_pwrdms(powerdomains_omap3430es2_es3_0); + break; + case OMAP3430_REV_ES3_1: + case OMAP3430_REV_ES3_1_2: + case OMAP3630_REV_ES1_1: + case OMAP3630_REV_ES1_2: + pwrdm_register_pwrdms(powerdomains_omap3430es3_1plus); + break; + default: + WARN(1, "OMAP3 powerdomain init: unknown chip type\n"); + } + } pwrdm_complete_init(); } -- cgit v1.2.3 From 00a3669838a02de2ae139bdb13c1019aa427a442 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 7 Jun 2012 18:50:51 -0600 Subject: ARM: OMAP depends on MMU There is no way to build OMAP kernels without an MMU at this point because of dependencies on MMU-only functions. As long as nobody is interested in fixing this, let's just disable this platforms for nommu kernels. Signed-off-by: Arnd Bergmann Signed-off-by: Mathieu Poirier Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 84449dd8f031..4b1fc0d612b6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -934,6 +934,7 @@ config ARCH_DAVINCI config ARCH_OMAP bool "TI OMAP" + depends on MMU select HAVE_CLK select ARCH_REQUIRE_GPIOLIB select ARCH_HAS_CPUFREQ -- cgit v1.2.3 From d3ada72ee3a479acbfb718302ca8b87d9d6e5e60 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Sun, 24 Jun 2012 00:18:59 +0200 Subject: ARM: OMAP: omap2plus_defconfig: Enable EXT4 support On OMAP boards that includes an SD card slot, an EXT4 partition could be used to store the root file system. So, the kernel should have built-in support for EXT4 to be able to mount the VFS root on boot. Signed-off-by: Javier Martinez Canillas Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 9854ff4279e0..f3087cb0ab08 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -197,6 +197,7 @@ CONFIG_RTC_DRV_TWL4030=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set +CONFIG_EXT4_FS=y CONFIG_QUOTA=y CONFIG_QFMT_V2=y CONFIG_MSDOS_FS=y -- cgit v1.2.3 From b56f2cb71a73618c97721762feb0a1be81302e22 Mon Sep 17 00:00:00 2001 From: Venkatraman S Date: Mon, 25 Jun 2012 15:56:39 +0530 Subject: ARM: OMAP2+: fix naming collision of variable nr_irqs Using nr_irqs as local variable name triggers the sparse warning.. ./arch/arm/mach-omap2/irq.c:265:6: warning: symbol 'nr_irqs' shadows an earlier one ./linux/include/linux/irqnr.h:26:12: originally declared here Signed-off-by: Venkatraman S Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/irq.c | 8 ++++---- arch/arm/mach-omap2/prm_common.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index fdc4303be563..74d77e008025 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -261,7 +261,7 @@ int __init omap_intc_of_init(struct device_node *node, struct device_node *parent) { struct resource res; - u32 nr_irqs = 96; + u32 nr_irq = 96; if (WARN_ON(!node)) return -ENODEV; @@ -271,10 +271,10 @@ int __init omap_intc_of_init(struct device_node *node, return -EINVAL; } - if (of_property_read_u32(node, "ti,intc-size", &nr_irqs)) - pr_warn("unable to get intc-size, default to %d\n", nr_irqs); + if (of_property_read_u32(node, "ti,intc-size", &nr_irq)) + pr_warn("unable to get intc-size, default to %d\n", nr_irq); - omap_init_irq(res.start, nr_irqs, of_node_get(node)); + omap_init_irq(res.start, nr_irq, of_node_get(node)); return 0; } diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c index dfe00ddb5c60..534d732caa1e 100644 --- a/arch/arm/mach-omap2/prm_common.c +++ b/arch/arm/mach-omap2/prm_common.c @@ -85,7 +85,7 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc) unsigned long priority_pending[OMAP_PRCM_MAX_NR_PENDING_REG]; struct irq_chip *chip = irq_desc_get_chip(desc); unsigned int virtirq; - int nr_irqs = prcm_irq_setup->nr_regs * 32; + int nr_irq = prcm_irq_setup->nr_regs * 32; /* * If we are suspended, mask all interrupts from PRCM level, @@ -110,7 +110,7 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc) prcm_irq_setup->read_pending_irqs(pending); /* No bit set, then all IRQs are handled */ - if (find_first_bit(pending, nr_irqs) >= nr_irqs) + if (find_first_bit(pending, nr_irq) >= nr_irq) break; omap_prcm_events_filter_priority(pending, priority_pending); @@ -121,11 +121,11 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc) */ /* Serve priority events first */ - for_each_set_bit(virtirq, priority_pending, nr_irqs) + for_each_set_bit(virtirq, priority_pending, nr_irq) generic_handle_irq(prcm_irq_setup->base_irq + virtirq); /* Serve normal events next */ - for_each_set_bit(virtirq, pending, nr_irqs) + for_each_set_bit(virtirq, pending, nr_irq) generic_handle_irq(prcm_irq_setup->base_irq + virtirq); } if (chip->irq_ack) -- cgit v1.2.3 From 59757c750fb3a89f172537a9e0ea2c6977771eee Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 28 Jun 2012 00:08:10 -0700 Subject: ARM: OMAP7XX: Remove omap730.h and omap850.h No file includes omap730.h or omap850.h. That's not surprising, as commit e6684f7132c6e6333e96407b06910bebaa4c1935 ("OMAP7XX: Create omap7xx.h") created a header that was "intended to replace omap730.h and omap850.h", while all "values defined [in omap7xx.h] are identical to those in both the old files". So it seems it was just an oversight to keep both the old files after commit 7a8f48f8c611ac8c07023260258e2fec312b9242 ("OMAP7XX: omap_uwire.c: Convert to omap7xx.h") converted the last file still including one of those two old files. Convert the last reference to omap730.h to a reference to omap7xx.h too. Signed-off-by: Paul Bolle Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/mux.h | 2 +- arch/arm/plat-omap/include/plat/omap730.h | 102 ------------------------------ arch/arm/plat-omap/include/plat/omap850.h | 102 ------------------------------ 3 files changed, 1 insertion(+), 205 deletions(-) delete mode 100644 arch/arm/plat-omap/include/plat/omap730.h delete mode 100644 arch/arm/plat-omap/include/plat/omap850.h (limited to 'arch') diff --git a/arch/arm/plat-omap/include/plat/mux.h b/arch/arm/plat-omap/include/plat/mux.h index aeba71796ad9..323948959200 100644 --- a/arch/arm/plat-omap/include/plat/mux.h +++ b/arch/arm/plat-omap/include/plat/mux.h @@ -99,7 +99,7 @@ /* * OMAP730/850 has a slightly different config for the pin mux. - * - config regs are the OMAP7XX_IO_CONF_x regs (see omap730.h) regs and + * - config regs are the OMAP7XX_IO_CONF_x regs (see omap7xx.h) regs and * not the FUNC_MUX_CTRL_x regs from hardware.h * - for pull-up/down, only has one enable bit which is is in the same register * as mux config diff --git a/arch/arm/plat-omap/include/plat/omap730.h b/arch/arm/plat-omap/include/plat/omap730.h deleted file mode 100644 index 14272bc1a6fd..000000000000 --- a/arch/arm/plat-omap/include/plat/omap730.h +++ /dev/null @@ -1,102 +0,0 @@ -/* arch/arm/plat-omap/include/mach/omap730.h - * - * Hardware definitions for TI OMAP730 processor. - * - * Cleanup for Linux-2.6 by Dirk Behme - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ASM_ARCH_OMAP730_H -#define __ASM_ARCH_OMAP730_H - -/* - * ---------------------------------------------------------------------------- - * Base addresses - * ---------------------------------------------------------------------------- - */ - -/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */ - -#define OMAP730_DSP_BASE 0xE0000000 -#define OMAP730_DSP_SIZE 0x50000 -#define OMAP730_DSP_START 0xE0000000 - -#define OMAP730_DSPREG_BASE 0xE1000000 -#define OMAP730_DSPREG_SIZE SZ_128K -#define OMAP730_DSPREG_START 0xE1000000 - -/* - * ---------------------------------------------------------------------------- - * OMAP730 specific configuration registers - * ---------------------------------------------------------------------------- - */ -#define OMAP730_CONFIG_BASE 0xfffe1000 -#define OMAP730_IO_CONF_0 0xfffe1070 -#define OMAP730_IO_CONF_1 0xfffe1074 -#define OMAP730_IO_CONF_2 0xfffe1078 -#define OMAP730_IO_CONF_3 0xfffe107c -#define OMAP730_IO_CONF_4 0xfffe1080 -#define OMAP730_IO_CONF_5 0xfffe1084 -#define OMAP730_IO_CONF_6 0xfffe1088 -#define OMAP730_IO_CONF_7 0xfffe108c -#define OMAP730_IO_CONF_8 0xfffe1090 -#define OMAP730_IO_CONF_9 0xfffe1094 -#define OMAP730_IO_CONF_10 0xfffe1098 -#define OMAP730_IO_CONF_11 0xfffe109c -#define OMAP730_IO_CONF_12 0xfffe10a0 -#define OMAP730_IO_CONF_13 0xfffe10a4 - -#define OMAP730_MODE_1 0xfffe1010 -#define OMAP730_MODE_2 0xfffe1014 - -/* CSMI specials: in terms of base + offset */ -#define OMAP730_MODE2_OFFSET 0x14 - -/* - * ---------------------------------------------------------------------------- - * OMAP730 traffic controller configuration registers - * ---------------------------------------------------------------------------- - */ -#define OMAP730_FLASH_CFG_0 0xfffecc10 -#define OMAP730_FLASH_ACFG_0 0xfffecc50 -#define OMAP730_FLASH_CFG_1 0xfffecc14 -#define OMAP730_FLASH_ACFG_1 0xfffecc54 - -/* - * ---------------------------------------------------------------------------- - * OMAP730 DSP control registers - * ---------------------------------------------------------------------------- - */ -#define OMAP730_ICR_BASE 0xfffbb800 -#define OMAP730_DSP_M_CTL 0xfffbb804 -#define OMAP730_DSP_MMU_BASE 0xfffed200 - -/* - * ---------------------------------------------------------------------------- - * OMAP730 PCC_UPLD configuration registers - * ---------------------------------------------------------------------------- - */ -#define OMAP730_PCC_UPLD_CTRL_BASE (0xfffe0900) -#define OMAP730_PCC_UPLD_CTRL (OMAP730_PCC_UPLD_CTRL_BASE + 0x00) - -#endif /* __ASM_ARCH_OMAP730_H */ - diff --git a/arch/arm/plat-omap/include/plat/omap850.h b/arch/arm/plat-omap/include/plat/omap850.h deleted file mode 100644 index c33f67981712..000000000000 --- a/arch/arm/plat-omap/include/plat/omap850.h +++ /dev/null @@ -1,102 +0,0 @@ -/* arch/arm/plat-omap/include/mach/omap850.h - * - * Hardware definitions for TI OMAP850 processor. - * - * Derived from omap730.h by Zebediah C. McClure - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ASM_ARCH_OMAP850_H -#define __ASM_ARCH_OMAP850_H - -/* - * ---------------------------------------------------------------------------- - * Base addresses - * ---------------------------------------------------------------------------- - */ - -/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */ - -#define OMAP850_DSP_BASE 0xE0000000 -#define OMAP850_DSP_SIZE 0x50000 -#define OMAP850_DSP_START 0xE0000000 - -#define OMAP850_DSPREG_BASE 0xE1000000 -#define OMAP850_DSPREG_SIZE SZ_128K -#define OMAP850_DSPREG_START 0xE1000000 - -/* - * ---------------------------------------------------------------------------- - * OMAP850 specific configuration registers - * ---------------------------------------------------------------------------- - */ -#define OMAP850_CONFIG_BASE 0xfffe1000 -#define OMAP850_IO_CONF_0 0xfffe1070 -#define OMAP850_IO_CONF_1 0xfffe1074 -#define OMAP850_IO_CONF_2 0xfffe1078 -#define OMAP850_IO_CONF_3 0xfffe107c -#define OMAP850_IO_CONF_4 0xfffe1080 -#define OMAP850_IO_CONF_5 0xfffe1084 -#define OMAP850_IO_CONF_6 0xfffe1088 -#define OMAP850_IO_CONF_7 0xfffe108c -#define OMAP850_IO_CONF_8 0xfffe1090 -#define OMAP850_IO_CONF_9 0xfffe1094 -#define OMAP850_IO_CONF_10 0xfffe1098 -#define OMAP850_IO_CONF_11 0xfffe109c -#define OMAP850_IO_CONF_12 0xfffe10a0 -#define OMAP850_IO_CONF_13 0xfffe10a4 - -#define OMAP850_MODE_1 0xfffe1010 -#define OMAP850_MODE_2 0xfffe1014 - -/* CSMI specials: in terms of base + offset */ -#define OMAP850_MODE2_OFFSET 0x14 - -/* - * ---------------------------------------------------------------------------- - * OMAP850 traffic controller configuration registers - * ---------------------------------------------------------------------------- - */ -#define OMAP850_FLASH_CFG_0 0xfffecc10 -#define OMAP850_FLASH_ACFG_0 0xfffecc50 -#define OMAP850_FLASH_CFG_1 0xfffecc14 -#define OMAP850_FLASH_ACFG_1 0xfffecc54 - -/* - * ---------------------------------------------------------------------------- - * OMAP850 DSP control registers - * ---------------------------------------------------------------------------- - */ -#define OMAP850_ICR_BASE 0xfffbb800 -#define OMAP850_DSP_M_CTL 0xfffbb804 -#define OMAP850_DSP_MMU_BASE 0xfffed200 - -/* - * ---------------------------------------------------------------------------- - * OMAP850 PCC_UPLD configuration registers - * ---------------------------------------------------------------------------- - */ -#define OMAP850_PCC_UPLD_CTRL_BASE (0xfffe0900) -#define OMAP850_PCC_UPLD_CTRL (OMAP850_PCC_UPLD_CTRL_BASE + 0x00) - -#endif /* __ASM_ARCH_OMAP850_H */ - -- cgit v1.2.3 From d2ba779afc84b2e05dcb64cb801a4af52f1c4be7 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 26 Jun 2012 23:12:47 +0200 Subject: ARM: OMAP: fix typos related to OMAP330 Signed-off-by: Paul Bolle Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/cpu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h index 297245dba66e..f2bdf15bdcef 100644 --- a/arch/arm/plat-omap/include/plat/cpu.h +++ b/arch/arm/plat-omap/include/plat/cpu.h @@ -238,7 +238,7 @@ IS_AM_SUBCLASS(335x, 0x335) /* * Macros to detect individual cpu types. * These are only rarely needed. - * cpu_is_omap330(): True for OMAP330 + * cpu_is_omap310(): True for OMAP310 * cpu_is_omap730(): True for OMAP730 * cpu_is_omap850(): True for OMAP850 * cpu_is_omap1510(): True for OMAP1510 @@ -304,7 +304,7 @@ IS_OMAP_TYPE(3517, 0x3517) /* * Whether we have MULTI_OMAP1 or not, we still need to distinguish - * between 730 vs 850, 330 vs. 1510 and 1611B/5912 vs. 1710. + * between 730 vs 850, 310 vs. 1510 and 1611B/5912 vs. 1710. */ #if defined(CONFIG_ARCH_OMAP730) -- cgit v1.2.3 From 0fb37842e47dd7f96725b86cb89a03dcecc72a46 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 26 Jun 2012 23:13:29 +0200 Subject: ARM: OMAP: remove unused cpu detection macros Now that OMAP730 and OMAP850 support is mostly unified, there's no need for separate cpu detection macros for these architectures. At least, currently there isn't, because both macros are unused. cpu_is_7xx() seems to cover all possible uses. Signed-off-by: Paul Bolle [tony@atomide.com: updated to also to remove related IS_OMAP_TYPE] Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/cpu.h | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h index f2bdf15bdcef..e79e913d95de 100644 --- a/arch/arm/plat-omap/include/plat/cpu.h +++ b/arch/arm/plat-omap/include/plat/cpu.h @@ -239,8 +239,6 @@ IS_AM_SUBCLASS(335x, 0x335) * Macros to detect individual cpu types. * These are only rarely needed. * cpu_is_omap310(): True for OMAP310 - * cpu_is_omap730(): True for OMAP730 - * cpu_is_omap850(): True for OMAP850 * cpu_is_omap1510(): True for OMAP1510 * cpu_is_omap1610(): True for OMAP1610 * cpu_is_omap1611(): True for OMAP1611 @@ -264,8 +262,6 @@ static inline int is_omap ##type (void) \ } IS_OMAP_TYPE(310, 0x0310) -IS_OMAP_TYPE(730, 0x0730) -IS_OMAP_TYPE(850, 0x0850) IS_OMAP_TYPE(1510, 0x1510) IS_OMAP_TYPE(1610, 0x1610) IS_OMAP_TYPE(1611, 0x1611) @@ -281,8 +277,6 @@ IS_OMAP_TYPE(3505, 0x3517) IS_OMAP_TYPE(3517, 0x3517) #define cpu_is_omap310() 0 -#define cpu_is_omap730() 0 -#define cpu_is_omap850() 0 #define cpu_is_omap1510() 0 #define cpu_is_omap1610() 0 #define cpu_is_omap5912() 0 @@ -304,19 +298,9 @@ IS_OMAP_TYPE(3517, 0x3517) /* * Whether we have MULTI_OMAP1 or not, we still need to distinguish - * between 730 vs 850, 310 vs. 1510 and 1611B/5912 vs. 1710. + * between 310 vs. 1510 and 1611B/5912 vs. 1710. */ -#if defined(CONFIG_ARCH_OMAP730) -# undef cpu_is_omap730 -# define cpu_is_omap730() is_omap730() -#endif - -#if defined(CONFIG_ARCH_OMAP850) -# undef cpu_is_omap850 -# define cpu_is_omap850() is_omap850() -#endif - #if defined(CONFIG_ARCH_OMAP15XX) # undef cpu_is_omap310 # undef cpu_is_omap1510 -- cgit v1.2.3 From bc404e9128dd69654f5fda6320fc6af4ee94474c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 27 Jun 2012 11:26:34 +0200 Subject: sh: kfr2r09: fix compile breakage Fix compile breakage caused by commit aa82f9fcd0062782dcbe29a2c820ba7c04dbe572 Author: Paul Mundt sh: kfr2r09 evt2irq migration. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- arch/sh/boards/mach-kfr2r09/setup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index 158c9176e42a..43a179ce9afc 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -201,8 +201,8 @@ static struct resource kfr2r09_usb0_gadget_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = evtirq(0xa20), - .end = evtirq(0xa20), + .start = evt2irq(0xa20), + .end = evt2irq(0xa20), .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW, }, }; -- cgit v1.2.3 From ad3337cb38bf1f4c677ce2d05f9c049b35f7147e Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Wed, 27 Jun 2012 09:59:40 +0900 Subject: sh: Convert sh_clk_mstp32_register to sh_clk_mstp_register sh_clk_mstp32_register is deprecated. This convert to sh_clk_mstp_register. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pcie-sh7786.c | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7343.c | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7366.c | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7723.c | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7724.c | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7734.c | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7757.c | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7785.c | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7786.c | 2 +- arch/sh/kernel/cpu/sh4a/clock-shx3.c | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index c045142f7338..9e702f2f8045 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -239,7 +239,7 @@ static int __init pcie_clk_init(struct sh7786_pcie_port *port) clk->enable_reg = (void __iomem *)(chan->reg_base + SH4A_PCIEPHYCTLR); clk->enable_bit = BITS_CKE; - ret = sh_clk_mstp32_register(clk, 1); + ret = sh_clk_mstp_register(clk, 1); if (unlikely(ret < 0)) goto err_phy; diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index ea01a72f1b94..53638e231cd0 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -283,7 +283,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index 7ac07b4f75de..22e485d1990b 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c @@ -276,7 +276,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 8e1f97010c0d..c4cb740e4d10 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -261,7 +261,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, HWBLK_NR); + ret = sh_clk_mstp_register(mstp_clks, HWBLK_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index 35f75cf0c7e5..37c41c7747a3 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -311,7 +311,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, HWBLK_NR); + ret = sh_clk_mstp_register(mstp_clks, HWBLK_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index 2a87901673fe..c87e78f73234 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -375,7 +375,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, HWBLK_NR); + ret = sh_clk_mstp_register(mstp_clks, HWBLK_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7734.c b/arch/sh/kernel/cpu/sh4a/clock-sh7734.c index 1697642c1f73..deb683abacf0 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7734.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7734.c @@ -260,7 +260,7 @@ int __init arch_clk_init(void) &div4_table); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c index 04ab5aeaf920..e84a43229b9c 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c @@ -148,7 +148,7 @@ int __init arch_clk_init(void) ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), &div4_table); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index ab1c58f2d101..1c83788db76a 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c @@ -175,7 +175,7 @@ int __init arch_clk_init(void) ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), &div4_table); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index 491709483e10..8bba6f159023 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c @@ -194,7 +194,7 @@ int __init arch_clk_init(void) ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), &div4_table); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c index 0f11b392bf46..a9422dab0ce7 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c @@ -149,7 +149,7 @@ int __init arch_clk_init(void) ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), &div4_table); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); return ret; } -- cgit v1.2.3 From 6ac7d11527a31d01b566a5c45369180e326ff4f1 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Wed, 6 Jun 2012 14:17:46 +0200 Subject: treewide: Put a space between #include and FILE Signed-off-by: Paul Bolle Signed-off-by: Jiri Kosina --- arch/arm/plat-samsung/include/plat/gpio-cfg.h | 2 +- arch/ia64/kernel/ia64_ksyms.c | 2 +- arch/ia64/kvm/vmm.c | 6 +++--- arch/parisc/include/asm/compat_rt_sigframe.h | 6 +++--- drivers/media/video/zoran/zr36016.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-io.c | 2 +- drivers/scsi/aha1542.c | 2 +- drivers/staging/comedi/drivers/s626.h | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h index df8155b9d4d1..08740eed050c 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h @@ -24,7 +24,7 @@ #ifndef __PLAT_GPIO_CFG_H #define __PLAT_GPIO_CFG_H __FILE__ -#include +#include typedef unsigned int __bitwise__ samsung_gpio_pull_t; typedef unsigned int __bitwise__ s5p_gpio_drvstr_t; diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c index 7f4a0ed24152..5b7791dd3965 100644 --- a/arch/ia64/kernel/ia64_ksyms.c +++ b/arch/ia64/kernel/ia64_ksyms.c @@ -12,7 +12,7 @@ EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(strlen); -#include +#include EXPORT_SYMBOL_GPL(empty_zero_page); #include diff --git a/arch/ia64/kvm/vmm.c b/arch/ia64/kvm/vmm.c index f0b9cac82414..176a12cd56de 100644 --- a/arch/ia64/kvm/vmm.c +++ b/arch/ia64/kvm/vmm.c @@ -20,9 +20,9 @@ */ -#include -#include -#include +#include +#include +#include #include "vcpu.h" diff --git a/arch/parisc/include/asm/compat_rt_sigframe.h b/arch/parisc/include/asm/compat_rt_sigframe.h index 81bec28bdc48..b3f95a7f18b4 100644 --- a/arch/parisc/include/asm/compat_rt_sigframe.h +++ b/arch/parisc/include/asm/compat_rt_sigframe.h @@ -1,6 +1,6 @@ -#include -#include -#include +#include +#include +#include #ifndef _ASM_PARISC_COMPAT_RT_SIGFRAME_H #define _ASM_PARISC_COMPAT_RT_SIGFRAME_H diff --git a/drivers/media/video/zoran/zr36016.c b/drivers/media/video/zoran/zr36016.c index 21c088ea9046..b87ddba8608f 100644 --- a/drivers/media/video/zoran/zr36016.c +++ b/drivers/media/video/zoran/zr36016.c @@ -40,10 +40,10 @@ /* v4l API */ /* headerfile of this module */ -#include"zr36016.h" +#include "zr36016.h" /* codec io API */ -#include"videocodec.h" +#include "videocodec.h" /* it doesn't make sense to have more than 20 or so, just to prevent some unwanted loops */ diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 081dd34d2387..0f8b8aa9e8d7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -29,7 +29,7 @@ #include #include "iwl-io.h" -#include"iwl-csr.h" +#include "iwl-csr.h" #include "iwl-debug.h" #define IWL_POLL_INTERVAL 10 /* microseconds */ diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index f79c8f9e33a4..770c48ddbe5e 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -49,7 +49,7 @@ #define SCSI_BUF_PA(address) isa_virt_to_bus(address) #define SCSI_SG_PA(sgent) (isa_page_to_bus(sg_page((sgent))) + (sgent)->offset) -#include +#include #ifdef DEBUG #define DEB(x) x diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index 2d1afecbbb60..92d3ea5eb44d 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -80,7 +80,7 @@ #define INLINE static __inline #endif -#include +#include #define S626_SIZE 0x0200 #define SIZEOF_ADDRESS_SPACE 0x0200 -- cgit v1.2.3 From b102f1d0f1cd0bb5ec82e5aeb1e33502d6ad6710 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 27 Jun 2012 09:41:39 +0900 Subject: tracing/kvm: Use __print_hex() for kvm_emulate_insn tracepoint The kvm_emulate_insn tracepoint used __print_insn() for printing its instructions. However it makes the format of the event hard to parse as it reveals TP internals. Fortunately, kernel provides __print_hex for almost same purpose, we can use it instead of open coding it. The user-space can be changed to parse it later. That means raw kernel tracing will not be affected by this change: # cd /sys/kernel/debug/tracing/ # cat events/kvm/kvm_emulate_insn/format name: kvm_emulate_insn ID: 29 format: ... print fmt: "%x:%llx:%s (%s)%s", REC->csbase, REC->rip, __print_hex(REC->insn, REC->len), \ __print_symbolic(REC->flags, { 0, "real" }, { (1 << 0) | (1 << 1), "vm16" }, \ { (1 << 0), "prot16" }, { (1 << 0) | (1 << 2), "prot32" }, { (1 << 0) | (1 << 3), "prot64" }), \ REC->failed ? " failed" : "" # echo 1 > events/kvm/kvm_emulate_insn/enable # cat trace # tracer: nop # # entries-in-buffer/entries-written: 2183/2183 #P:12 # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | qemu-kvm-1782 [002] ...1 140.931636: kvm_emulate_insn: 0:c102fa25:89 10 (prot32) qemu-kvm-1781 [004] ...1 140.931637: kvm_emulate_insn: 0:c102fa25:89 10 (prot32) Link: http://lkml.kernel.org/n/tip-wfw6y3b9ugtey8snaow9nmg5@git.kernel.org Link: http://lkml.kernel.org/r/1340757701-10711-2-git-send-email-namhyung@kernel.org Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Namhyung Kim Cc: kvm@vger.kernel.org Acked-by: Avi Kivity Signed-off-by: Namhyung Kim Signed-off-by: Steven Rostedt --- arch/x86/kvm/trace.h | 12 +----------- include/trace/ftrace.h | 1 + 2 files changed, 2 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index 911d2641f14c..62d02e3c3ed6 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h @@ -710,16 +710,6 @@ TRACE_EVENT(kvm_skinit, __entry->rip, __entry->slb) ); -#define __print_insn(insn, ilen) ({ \ - int i; \ - const char *ret = p->buffer + p->len; \ - \ - for (i = 0; i < ilen; ++i) \ - trace_seq_printf(p, " %02x", insn[i]); \ - trace_seq_printf(p, "%c", 0); \ - ret; \ - }) - #define KVM_EMUL_INSN_F_CR0_PE (1 << 0) #define KVM_EMUL_INSN_F_EFL_VM (1 << 1) #define KVM_EMUL_INSN_F_CS_D (1 << 2) @@ -786,7 +776,7 @@ TRACE_EVENT(kvm_emulate_insn, TP_printk("%x:%llx:%s (%s)%s", __entry->csbase, __entry->rip, - __print_insn(__entry->insn, __entry->len), + __print_hex(__entry->insn, __entry->len), __print_symbolic(__entry->flags, kvm_trace_symbol_emul_flags), __entry->failed ? " failed" : "" diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index 769724944fc6..c6bc2faaf261 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h @@ -571,6 +571,7 @@ static inline void ftrace_test_probe_##call(void) \ #undef __print_flags #undef __print_symbolic +#undef __print_hex #undef __get_dynamic_array #undef __get_str -- cgit v1.2.3 From f1cefa855f6e7d10dd49724ede771b8f0c2a90e7 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 28 Jun 2012 12:39:05 +0200 Subject: ARM: mxs/tx28: fix odd include arch/arm/mach-mxs/module-tx28.c includes "../devices-mx28.h". That's a bit odd, because that header can be found in the same directory. This only works because arch/arm/mach-mxs/include should be in the header search path for this file. Nevertheless, this file can simply include "device-mx28.h" (just as the four other files including that header do). Signed-off-by: Paul Bolle Signed-off-by: Shawn Guo --- arch/arm/mach-mxs/module-tx28.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-mxs/module-tx28.c b/arch/arm/mach-mxs/module-tx28.c index 9a7b08b2a925..0f71f82101cc 100644 --- a/arch/arm/mach-mxs/module-tx28.c +++ b/arch/arm/mach-mxs/module-tx28.c @@ -11,7 +11,7 @@ #include #include -#include "../devices-mx28.h" +#include "devices-mx28.h" #include "module-tx28.h" -- cgit v1.2.3 From 7784655acc5a946aac49af423cc1099c5d593d73 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 21 Jun 2012 17:50:27 +0000 Subject: powerpc: Fix BPF_JIT code to link with multiple TOCs If the kernel is big enough (eg. allyesconfig), the linker may need to switch TOCs when calling from the BPF JIT code out to the external helpers (skb_copy_bits() & bpf_internal_load_pointer_neg_helper()). In order to do that we need to leave space after the bl for the linker to insert a reload of our TOC pointer. Signed-off-by: Michael Ellerman Acked-by: Matt Evans Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/net/bpf_jit_64.S | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/powerpc/net/bpf_jit_64.S b/arch/powerpc/net/bpf_jit_64.S index 55ba3855a97f..7d3a3b5619a2 100644 --- a/arch/powerpc/net/bpf_jit_64.S +++ b/arch/powerpc/net/bpf_jit_64.S @@ -105,6 +105,7 @@ sk_load_byte_msh_positive_offset: mr r4, r_addr; \ li r6, SIZE; \ bl skb_copy_bits; \ + nop; \ /* R3 = 0 on success */ \ addi r1, r1, BPF_PPC_SLOWPATH_FRAME; \ ld r0, 16(r1); \ @@ -156,6 +157,7 @@ bpf_slow_path_byte_msh: mr r4, r_addr; \ li r5, SIZE; \ bl bpf_internal_load_pointer_neg_helper; \ + nop; \ /* R3 != 0 on success */ \ addi r1, r1, BPF_PPC_SLOWPATH_FRAME; \ ld r0, 16(r1); \ -- cgit v1.2.3 From 82b2521d257b5c0efd51821cf5fa306e53bbb6ba Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Tue, 19 Jun 2012 20:01:45 +0000 Subject: powerpc: Fix uninitialised error in numa.c chroma_defconfig currently gives me this with gcc 4.6: arch/powerpc/mm/numa.c:638:13: error: 'dm' may be used uninitialized in this function [-Werror=uninitialized] It's a bogus warning/error since of_get_drconf_memory() only writes it anyway. Signed-off-by: Michael Neuling cc: [v3.3+] Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/mm/numa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index b6edbb3b4a54..6e8f677f5646 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -635,7 +635,7 @@ static inline int __init read_usm_ranges(const u32 **usm) */ static void __init parse_drconf_memory(struct device_node *memory) { - const u32 *dm, *usm; + const u32 *uninitialized_var(dm), *usm; unsigned int n, rc, ranges, is_kexec_kdump = 0; unsigned long lmb_size, base, size, sz; int nid; -- cgit v1.2.3 From c58ce2b1e3c75c55e7ebf751afce9f5a30f60b42 Mon Sep 17 00:00:00 2001 From: Tiejun Chen Date: Wed, 6 Jun 2012 20:56:43 +0000 Subject: ppc64: fix missing to check all bits of _TIF_USER_WORK_MASK in preempt In entry_64.S version of ret_from_except_lite, you'll notice that in the !preempt case, after we've checked MSR_PR we test for any TIF flag in _TIF_USER_WORK_MASK to decide whether to go to do_work or not. However, in the preempt case, we do a convoluted trick to test SIGPENDING only if PR was set and always test NEED_RESCHED ... but we forget to test any other bit of _TIF_USER_WORK_MASK !!! So that means that with preempt, we completely fail to test for things like single step, syscall tracing, etc... This should be fixed as the following path: - Test PR. If not set, go to resume_kernel, else continue. - If go resume_kernel, to do that original do_work. - If else, then always test for _TIF_USER_WORK_MASK to decide to do that original user_work, else restore directly. Signed-off-by: Tiejun Chen Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/entry_64.S | 97 +++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 57 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index ed1718feb9d9..5971c85df136 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -558,27 +558,54 @@ _GLOBAL(ret_from_except_lite) mtmsrd r10,1 /* Update machine state */ #endif /* CONFIG_PPC_BOOK3E */ -#ifdef CONFIG_PREEMPT clrrdi r9,r1,THREAD_SHIFT /* current_thread_info() */ - li r0,_TIF_NEED_RESCHED /* bits to check */ ld r3,_MSR(r1) ld r4,TI_FLAGS(r9) - /* Move MSR_PR bit in r3 to _TIF_SIGPENDING position in r0 */ - rlwimi r0,r3,32+TIF_SIGPENDING-MSR_PR_LG,_TIF_SIGPENDING - and. r0,r4,r0 /* check NEED_RESCHED and maybe SIGPENDING */ - bne do_work - -#else /* !CONFIG_PREEMPT */ - ld r3,_MSR(r1) /* Returning to user mode? */ andi. r3,r3,MSR_PR - beq restore /* if not, just restore regs and return */ + beq resume_kernel /* Check current_thread_info()->flags */ + andi. r0,r4,_TIF_USER_WORK_MASK + beq restore + + andi. r0,r4,_TIF_NEED_RESCHED + beq 1f + bl .restore_interrupts + bl .schedule + b .ret_from_except_lite + +1: bl .save_nvgprs + bl .restore_interrupts + addi r3,r1,STACK_FRAME_OVERHEAD + bl .do_notify_resume + b .ret_from_except + +resume_kernel: +#ifdef CONFIG_PREEMPT + /* Check if we need to preempt */ + andi. r0,r4,_TIF_NEED_RESCHED + beq+ restore + /* Check that preempt_count() == 0 and interrupts are enabled */ + lwz r8,TI_PREEMPT(r9) + cmpwi cr1,r8,0 + ld r0,SOFTE(r1) + cmpdi r0,0 + crandc eq,cr1*4+eq,eq + bne restore + + /* + * Here we are preempting the current task. We want to make + * sure we are soft-disabled first + */ + SOFT_DISABLE_INTS(r3,r4) +1: bl .preempt_schedule_irq + + /* Re-test flags and eventually loop */ clrrdi r9,r1,THREAD_SHIFT ld r4,TI_FLAGS(r9) - andi. r0,r4,_TIF_USER_WORK_MASK - bne do_work -#endif /* !CONFIG_PREEMPT */ + andi. r0,r4,_TIF_NEED_RESCHED + bne 1b +#endif /* CONFIG_PREEMPT */ .globl fast_exc_return_irq fast_exc_return_irq: @@ -759,50 +786,6 @@ restore_check_irq_replay: #endif /* CONFIG_PPC_BOOK3E */ 1: b .ret_from_except /* What else to do here ? */ - - -3: -do_work: -#ifdef CONFIG_PREEMPT - andi. r0,r3,MSR_PR /* Returning to user mode? */ - bne user_work - /* Check that preempt_count() == 0 and interrupts are enabled */ - lwz r8,TI_PREEMPT(r9) - cmpwi cr1,r8,0 - ld r0,SOFTE(r1) - cmpdi r0,0 - crandc eq,cr1*4+eq,eq - bne restore - - /* - * Here we are preempting the current task. We want to make - * sure we are soft-disabled first - */ - SOFT_DISABLE_INTS(r3,r4) -1: bl .preempt_schedule_irq - - /* Re-test flags and eventually loop */ - clrrdi r9,r1,THREAD_SHIFT - ld r4,TI_FLAGS(r9) - andi. r0,r4,_TIF_NEED_RESCHED - bne 1b - b restore - -user_work: -#endif /* CONFIG_PREEMPT */ - - andi. r0,r4,_TIF_NEED_RESCHED - beq 1f - bl .restore_interrupts - bl .schedule - b .ret_from_except_lite - -1: bl .save_nvgprs - bl .restore_interrupts - addi r3,r1,STACK_FRAME_OVERHEAD - bl .do_notify_resume - b .ret_from_except - unrecov_restore: addi r3,r1,STACK_FRAME_OVERHEAD bl .unrecoverable_exception -- cgit v1.2.3 From 2cb387ae758d97ee7396a82528c824b8dc510b8a Mon Sep 17 00:00:00 2001 From: Li Zhong Date: Thu, 7 Jun 2012 17:44:23 +0000 Subject: powerpc: Fix Section mismatch warnings in prom_init.c This patches tries to fix a couple of Section mismatch warnings like following one: WARNING: arch/powerpc/kernel/built-in.o(.text+0x2923c): Section mismatch in reference from the function .prom_query_opal() to the function .init.text:.call_prom() The function .prom_query_opal() references the function __init .call_prom(). This is often because .prom_query_opal lacks a __init annotation or the annotation of .call_prom is wrong. Signed-off-by: Li Zhong Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/prom_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 1b488e5305c5..0794a3017b1b 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -1312,7 +1312,7 @@ static struct opal_secondary_data { extern char opal_secondary_entry; -static void prom_query_opal(void) +static void __init prom_query_opal(void) { long rc; @@ -1436,7 +1436,7 @@ static void __init prom_opal_hold_cpus(void) prom_debug("prom_opal_hold_cpus: end...\n"); } -static void prom_opal_takeover(void) +static void __init prom_opal_takeover(void) { struct opal_secondary_data *data = &RELOC(opal_secondary_data); struct opal_takeover_args *args = &data->args; -- cgit v1.2.3 From 2d773aa4810d4a612d1c879faacc38594cc3f841 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 4 Jun 2012 16:27:54 +0000 Subject: powerpc/ftrace: Do not trace restore_interrupts() As I was adding code that affects all archs, I started testing function tracer against PPC64 and found that it currently locks up with 3.4 kernel. I figured it was due to tracing a function that shouldn't be, so I went through the following process to bisect to find the culprit: cat /debug/tracing/available_filter_functions > t num=`wc -l t` sed -ne "1,${num}p" t > t1 let num=num+1 sed -ne "${num},$p" t > t2 cat t1 > /debug/tracing/set_ftrace_filter echo function /debug/tracing/current_tracer It finally came down to this function: restore_interrupts() I'm not sure why this locks up the system. It just seems to prevent scheduling from occurring. Interrupts seem to still work, as I can ping the box. But all user processes freeze. When restore_interrupts() is not traced, function tracing works fine. Cc: stable@kernel.org Signed-off-by: Steven Rostedt Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 7835a5e1ea5f..1b415027ec0e 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -277,7 +277,7 @@ EXPORT_SYMBOL(arch_local_irq_restore); * NOTE: This is called with interrupts hard disabled but not marked * as such in paca->irq_happened, so we need to resync this. */ -void restore_interrupts(void) +void notrace restore_interrupts(void) { if (irqs_disabled()) { local_paca->irq_happened |= PACA_IRQ_HARD_DIS; -- cgit v1.2.3 From 0b17ba7258db83cd02da560884e053b85de371f2 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 27 Jun 2012 13:13:52 +0000 Subject: powerpc: check_and_cede_processor() never cedes Commit f948501b36c6 ("Make hard_irq_disable() actually hard-disable interrupts") caused check_and_cede_processor to stop working. ->irq_happened will never be zero right after a hard_irq_disable so the compiler removes the call to cede_processor completely. The bug was introduced back in the lazy interrupt handling rework of 3.4 but was hidden until recently because hard_irq_disable did nothing. This issue will eventually appear in 3.4 stable since the hard_irq_disable fix is marked stable, so mark this one for stable too. Signed-off-by: Anton Blanchard Cc: stable@vger.kernel.org Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/hw_irq.h | 5 +++++ arch/powerpc/platforms/pseries/processor_idle.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index 32b394f3b854..6eb75b80488c 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h @@ -103,6 +103,11 @@ static inline void hard_irq_disable(void) /* include/linux/interrupt.h needs hard_irq_disable to be a macro */ #define hard_irq_disable hard_irq_disable +static inline bool lazy_irq_pending(void) +{ + return !!(get_paca()->irq_happened & ~PACA_IRQ_HARD_DIS); +} + /* * This is called by asynchronous interrupts to conditionally * re-enable hard interrupts when soft-disabled after having diff --git a/arch/powerpc/platforms/pseries/processor_idle.c b/arch/powerpc/platforms/pseries/processor_idle.c index 41a34bc4a9a2..e61483e8e960 100644 --- a/arch/powerpc/platforms/pseries/processor_idle.c +++ b/arch/powerpc/platforms/pseries/processor_idle.c @@ -106,7 +106,7 @@ static void check_and_cede_processor(void) * we first hard disable then check. */ hard_irq_disable(); - if (get_paca()->irq_happened == 0) + if (!lazy_irq_pending()) cede_processor(); } -- cgit v1.2.3 From bc6dc752f35488160ffac07ae91bed1bddaea32a Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Tue, 26 Jun 2012 21:26:37 +0000 Subject: powerpc/pseries: Fix software invalidate TCE The following added support for powernv but broke pseries/BML: 1f1616e powerpc/powernv: Add TCE SW invalidation support TCE_PCI_SW_INVAL was split into FREE and CREATE flags but the tests in the pseries code were not updated to reflect this. Signed-off-by: Michael Neuling cc: stable@kernel.org [v3.3+] Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 0915b1ad66ce..2d311c0caf8e 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -106,7 +106,7 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index, tcep++; } - if (tbl->it_type == TCE_PCI_SWINV_CREATE) + if (tbl->it_type & TCE_PCI_SWINV_CREATE) tce_invalidate_pSeries_sw(tbl, tces, tcep - 1); return 0; } @@ -121,7 +121,7 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) while (npages--) *(tcep++) = 0; - if (tbl->it_type == TCE_PCI_SWINV_FREE) + if (tbl->it_type & TCE_PCI_SWINV_FREE) tce_invalidate_pSeries_sw(tbl, tces, tcep - 1); } -- cgit v1.2.3 From e0246e8ecad10b9437381b89756292ac031d4cfa Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 28 Jun 2012 09:45:14 -0700 Subject: ARM: OMAP2+: fix CONFIG_CPU_IDLE dependency on CONFIG_PM commit 164e0cbf60 (ARM: OMAP3/4: consolidate cpuidle Makefile) added an OMAP-specific dependency from CPU_IDLE to CONFIG_PM. This causes some randconfig warnings when CONFIG_PM has unmet dependencies: warning: (ARCH_OMAP3 && ARCH_OMAP4) selects PM which has unmet direct dependencies (PM_SLEEP || PM_RUNTIME) warning: (ARCH_OMAP3 && ARCH_OMAP4) selects PM which has unmet direct dependencies (PM_SLEEP || PM_RUNTIME) warning: (ARCH_OMAP3 && ARCH_OMAP4) selects PM which has unmet direct dependencies (PM_SLEEP || PM_RUNTIME) Fix this by making the dependency on CONFIG_PM_RUNTIME (which in turn will enable CONFIG_PM.) Reported-by: Tony Lindgren Cc: Daniel Lezcano Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index cf84588cd110..2f4ace6f91d1 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -35,7 +35,7 @@ config ARCH_OMAP3 select CPU_V7 select USB_ARCH_HAS_EHCI if USB_SUPPORT select ARCH_HAS_OPP - select PM if CPU_IDLE + select PM_RUNTIME if CPU_IDLE select PM_OPP if PM select ARM_CPU_SUSPEND if PM select MULTI_IRQ_HANDLER @@ -53,7 +53,7 @@ config ARCH_OMAP4 select PL310_ERRATA_727915 select ARM_ERRATA_720789 select ARCH_HAS_OPP - select PM if CPU_IDLE + select PM_RUNTIME if CPU_IDLE select PM_OPP if PM select USB_ARCH_HAS_EHCI if USB_SUPPORT select ARM_CPU_SUSPEND if PM -- cgit v1.2.3 From d660e9b92b44f113c3fc345a8ce66ffa56a3506f Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 29 Jun 2012 07:03:34 -0700 Subject: ARM: OMAP2+: PM: fix IRQ_NOAUTOEN removal by mis-merge commit 99b59df0 (ARM: OMAP3: PM: fix shared PRCM interrupt leave disabled at boot) added IRQ_NOAUTOEN to the PRCM interrupt so it could be enabled later if needed. However, this commit was partially undone when merging the IO daisy chain rework in 9a17d88e (Merge tag 'omap-devel-c-for-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending into devel-pm This patch adds back the IRQ_NOAUTOEN fix that was removed by the merge resolution. This also fixes the following boot-time warning that showed up after merging the IO daisy chain rework: [ 3.849334] WARNING: at kernel/irq/manage.c:436 enable_irq+0x3c/0x78() [ 3.856231] Unbalanced enable for IRQ 297 [ 3.860473] Modules linked in: [ 3.863739] [] (unwind_backtrace+0x0/0xf0) from [] (warn_slowpath_common+0x4c/0x64) [ 3.873687] [] (warn_slowpath_common+0x4c/0x64) from [] (warn_slowpath_fmt+0x30/0x40) [ 3.883819] [] (warn_slowpath_fmt+0x30/0x40) from [] (enable_irq+0x3c/0x78) [ 3.893035] [] (enable_irq+0x3c/0x78) from [] (omap3_pm_init+0x328/0x5f4) [ 3.902099] [] (omap3_pm_init+0x328/0x5f4) from [] (init_machine_late+0x1c/0x28) [ 3.911773] [] (init_machine_late+0x1c/0x28) from [] (do_one_initcall+0x34/0x178) [ 3.921539] [] (do_one_initcall+0x34/0x178) from [] (kernel_init+0xfc/0x1c0) [ 3.930847] [] (kernel_init+0xfc/0x1c0) from [] (kernel_thread_exit+0x0/0x8) [ 3.940246] ---[ end trace 55a0ad32ca2ca682 ]--- Reported-by: Javier Martinez Canillas Cc: Paul Walmsley Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/prm2xxx_3xxx.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index e10fd1e9446b..a0309dea6794 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c @@ -351,11 +351,16 @@ static void __init omap3xxx_prm_enable_io_wakeup(void) static int __init omap3xxx_prcm_init(void) { + int ret = 0; + if (cpu_is_omap34xx()) { omap3xxx_prm_enable_io_wakeup(); - return omap_prcm_register_chain_handler(&omap3_prcm_irq_setup); + ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup); + if (!ret) + irq_set_status_flags(omap_prcm_event_to_irq("io"), + IRQ_NOAUTOEN); } - return 0; + return ret; } subsys_initcall(omap3xxx_prcm_init); -- cgit v1.2.3 From e30384abd63dfa11508a38243e1d78f1d70486b1 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Tue, 29 May 2012 15:26:41 +0530 Subject: ARM: OMAP3+: clock33xx: Add AM33XX clock tree data AM33XX clock implementation is different than any existing OMAP family of devices. Although DPLL module is similar to OMAP4 device, but the usage is very much different than OMAP4. AM33XX has different peripheral set and each module gets integrated to the clock framework differently than OMAP family of devices. This patch adds full Clock tree data for AM33XX family of devices and also integrates it into existing OMAP framework. Signed-off-by: Vaibhav Hiremath Signed-off-by: Afzal Mohammed Signed-off-by: Vaibhav Bedia Cc: Kevin Hilman Cc: Rajendra Nayak CC: Tony Lindgren Cc: Paul Walmsley Cc: Benoit Cousson [paul@pwsan.com: updated to apply; changed 'soc_is_am33xx' to 'cpu_is_am33xx' to match usage in Tony's current am33xx branch] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/Makefile | 2 + arch/arm/mach-omap2/clock.h | 2 + arch/arm/mach-omap2/clock33xx_data.c | 1105 +++++++++++++++++++++++++ arch/arm/mach-omap2/io.c | 2 + arch/arm/plat-omap/include/plat/clkdev_omap.h | 1 + 5 files changed, 1112 insertions(+) create mode 100644 arch/arm/mach-omap2/clock33xx_data.c (limited to 'arch') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index a4cf93242b0b..b167152ca69f 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -152,6 +152,8 @@ obj-$(CONFIG_ARCH_OMAP3) += dpll3xxx.o clock3xxx_data.o obj-$(CONFIG_ARCH_OMAP3) += clkt_iclk.o obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) clock44xx_data.o obj-$(CONFIG_ARCH_OMAP4) += dpll3xxx.o dpll44xx.o +obj-$(CONFIG_SOC_AM33XX) += $(clock-common) dpll3xxx.o +obj-$(CONFIG_SOC_AM33XX) += clock33xx_data.o # OMAP2 clock rate set data (old "OPP" data) obj-$(CONFIG_SOC_OMAP2420) += opp2420_data.o diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 980b0a436c29..35ec5f3d9a73 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -167,4 +167,6 @@ extern const struct clksel_rate div31_1to31_rates[]; extern struct clk virt_19200000_ck; extern struct clk virt_26000000_ck; +extern int am33xx_clk_init(void); + #endif diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c new file mode 100644 index 000000000000..9c8ac7dc9f3c --- /dev/null +++ b/arch/arm/mach-omap2/clock33xx_data.c @@ -0,0 +1,1105 @@ +/* + * AM33XX Clock data + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * Vaibhav Hiremath + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "iomap.h" +#include "control.h" +#include "clock.h" +#include "cm.h" +#include "cm33xx.h" +#include "cm-regbits-33xx.h" +#include "prm.h" + +/* Maximum DPLL multiplier, divider values for AM33XX */ +#define AM33XX_MAX_DPLL_MULT 2047 +#define AM33XX_MAX_DPLL_DIV 128 + +/* Modulemode control */ +#define AM33XX_MODULEMODE_HWCTRL 0 +#define AM33XX_MODULEMODE_SWCTRL 1 + +/* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always + * physically present, in such a case HWMOD enabling of + * clock would be failure with default parent. And timer + * probe thinks clock is already enabled, this leads to + * crash upon accessing timer 3 & 6 registers in probe. + * Fix by setting parent of both these timers to master + * oscillator clock. + */ +static inline void am33xx_init_timer_parent(struct clk *clk) +{ + omap2_clksel_set_parent(clk, clk->parent); +} + +/* Root clocks */ + +/* RTC 32k */ +static struct clk clk_32768_ck = { + .name = "clk_32768_ck", + .clkdm_name = "l4_rtc_clkdm", + .rate = 32768, + .ops = &clkops_null, +}; + +/* On-Chip 32KHz RC OSC */ +static struct clk clk_rc32k_ck = { + .name = "clk_rc32k_ck", + .rate = 32000, + .ops = &clkops_null, +}; + +/* Crystal input clks */ +static struct clk virt_24000000_ck = { + .name = "virt_24000000_ck", + .rate = 24000000, + .ops = &clkops_null, +}; + +static struct clk virt_25000000_ck = { + .name = "virt_25000000_ck", + .rate = 25000000, + .ops = &clkops_null, +}; + +/* Oscillator clock */ +/* 19.2, 24, 25 or 26 MHz */ +static const struct clksel sys_clkin_sel[] = { + { .parent = &virt_19200000_ck, .rates = div_1_0_rates }, + { .parent = &virt_24000000_ck, .rates = div_1_1_rates }, + { .parent = &virt_25000000_ck, .rates = div_1_2_rates }, + { .parent = &virt_26000000_ck, .rates = div_1_3_rates }, + { .parent = NULL }, +}; + +/* External clock - 12 MHz */ +static struct clk tclkin_ck = { + .name = "tclkin_ck", + .rate = 12000000, + .ops = &clkops_null, +}; + +/* + * sys_clk in: input to the dpll and also used as funtional clock for, + * adc_tsc, smartreflex0-1, timer1-7, mcasp0-1, dcan0-1, cefuse + * + */ +static struct clk sys_clkin_ck = { + .name = "sys_clkin_ck", + .parent = &virt_24000000_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = AM33XX_CTRL_REGADDR(AM33XX_CONTROL_STATUS), + .clksel_mask = AM33XX_CONTROL_STATUS_SYSBOOT1_MASK, + .clksel = sys_clkin_sel, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, +}; + +/* DPLL_CORE */ +static struct dpll_data dpll_core_dd = { + .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_CORE, + .clk_bypass = &sys_clkin_ck, + .clk_ref = &sys_clkin_ck, + .control_reg = AM33XX_CM_CLKMODE_DPLL_CORE, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .idlest_reg = AM33XX_CM_IDLEST_DPLL_CORE, + .mult_mask = AM33XX_DPLL_MULT_MASK, + .div1_mask = AM33XX_DPLL_DIV_MASK, + .enable_mask = AM33XX_DPLL_EN_MASK, + .idlest_mask = AM33XX_ST_DPLL_CLK_MASK, + .max_multiplier = AM33XX_MAX_DPLL_MULT, + .max_divider = AM33XX_MAX_DPLL_DIV, + .min_divider = 1, +}; + +/* CLKDCOLDO output */ +static struct clk dpll_core_ck = { + .name = "dpll_core_ck", + .parent = &sys_clkin_ck, + .dpll_data = &dpll_core_dd, + .init = &omap2_init_dpll_parent, + .ops = &clkops_omap3_core_dpll_ops, + .recalc = &omap3_dpll_recalc, +}; + +static struct clk dpll_core_x2_ck = { + .name = "dpll_core_x2_ck", + .parent = &dpll_core_ck, + .flags = CLOCK_CLKOUTX2, + .ops = &clkops_null, + .recalc = &omap3_clkoutx2_recalc, +}; + + +static const struct clksel dpll_core_m4_div[] = { + { .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_core_m4_ck = { + .name = "dpll_core_m4_ck", + .parent = &dpll_core_x2_ck, + .init = &omap2_init_clksel_parent, + .clksel = dpll_core_m4_div, + .clksel_reg = AM33XX_CM_DIV_M4_DPLL_CORE, + .clksel_mask = AM33XX_HSDIVIDER_CLKOUT1_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +static const struct clksel dpll_core_m5_div[] = { + { .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_core_m5_ck = { + .name = "dpll_core_m5_ck", + .parent = &dpll_core_x2_ck, + .init = &omap2_init_clksel_parent, + .clksel = dpll_core_m5_div, + .clksel_reg = AM33XX_CM_DIV_M5_DPLL_CORE, + .clksel_mask = AM33XX_HSDIVIDER_CLKOUT2_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +static const struct clksel dpll_core_m6_div[] = { + { .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_core_m6_ck = { + .name = "dpll_core_m6_ck", + .parent = &dpll_core_x2_ck, + .init = &omap2_init_clksel_parent, + .clksel = dpll_core_m6_div, + .clksel_reg = AM33XX_CM_DIV_M6_DPLL_CORE, + .clksel_mask = AM33XX_HSDIVIDER_CLKOUT3_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +/* DPLL_MPU */ +static struct dpll_data dpll_mpu_dd = { + .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_MPU, + .clk_bypass = &sys_clkin_ck, + .clk_ref = &sys_clkin_ck, + .control_reg = AM33XX_CM_CLKMODE_DPLL_MPU, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .idlest_reg = AM33XX_CM_IDLEST_DPLL_MPU, + .mult_mask = AM33XX_DPLL_MULT_MASK, + .div1_mask = AM33XX_DPLL_DIV_MASK, + .enable_mask = AM33XX_DPLL_EN_MASK, + .idlest_mask = AM33XX_ST_DPLL_CLK_MASK, + .max_multiplier = AM33XX_MAX_DPLL_MULT, + .max_divider = AM33XX_MAX_DPLL_DIV, + .min_divider = 1, +}; + +/* CLKOUT: fdpll/M2 */ +static struct clk dpll_mpu_ck = { + .name = "dpll_mpu_ck", + .parent = &sys_clkin_ck, + .dpll_data = &dpll_mpu_dd, + .init = &omap2_init_dpll_parent, + .ops = &clkops_omap3_noncore_dpll_ops, + .recalc = &omap3_dpll_recalc, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, +}; + +/* + * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2 + * and ALT_CLK1/2) + */ +static const struct clksel dpll_mpu_m2_div[] = { + { .parent = &dpll_mpu_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_mpu_m2_ck = { + .name = "dpll_mpu_m2_ck", + .clkdm_name = "mpu_clkdm", + .parent = &dpll_mpu_ck, + .clksel = dpll_mpu_m2_div, + .clksel_reg = AM33XX_CM_DIV_M2_DPLL_MPU, + .clksel_mask = AM33XX_DPLL_CLKOUT_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +/* DPLL_DDR */ +static struct dpll_data dpll_ddr_dd = { + .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_DDR, + .clk_bypass = &sys_clkin_ck, + .clk_ref = &sys_clkin_ck, + .control_reg = AM33XX_CM_CLKMODE_DPLL_DDR, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .idlest_reg = AM33XX_CM_IDLEST_DPLL_DDR, + .mult_mask = AM33XX_DPLL_MULT_MASK, + .div1_mask = AM33XX_DPLL_DIV_MASK, + .enable_mask = AM33XX_DPLL_EN_MASK, + .idlest_mask = AM33XX_ST_DPLL_CLK_MASK, + .max_multiplier = AM33XX_MAX_DPLL_MULT, + .max_divider = AM33XX_MAX_DPLL_DIV, + .min_divider = 1, +}; + +/* CLKOUT: fdpll/M2 */ +static struct clk dpll_ddr_ck = { + .name = "dpll_ddr_ck", + .parent = &sys_clkin_ck, + .dpll_data = &dpll_ddr_dd, + .init = &omap2_init_dpll_parent, + .ops = &clkops_null, + .recalc = &omap3_dpll_recalc, +}; + +/* + * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2 + * and ALT_CLK1/2) + */ +static const struct clksel dpll_ddr_m2_div[] = { + { .parent = &dpll_ddr_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_ddr_m2_ck = { + .name = "dpll_ddr_m2_ck", + .parent = &dpll_ddr_ck, + .clksel = dpll_ddr_m2_div, + .clksel_reg = AM33XX_CM_DIV_M2_DPLL_DDR, + .clksel_mask = AM33XX_DPLL_CLKOUT_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +/* emif_fck functional clock */ +static struct clk dpll_ddr_m2_div2_ck = { + .name = "dpll_ddr_m2_div2_ck", + .clkdm_name = "l3_clkdm", + .parent = &dpll_ddr_m2_ck, + .ops = &clkops_null, + .fixed_div = 2, + .recalc = &omap_fixed_divisor_recalc, +}; + +/* DPLL_DISP */ +static struct dpll_data dpll_disp_dd = { + .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_DISP, + .clk_bypass = &sys_clkin_ck, + .clk_ref = &sys_clkin_ck, + .control_reg = AM33XX_CM_CLKMODE_DPLL_DISP, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .idlest_reg = AM33XX_CM_IDLEST_DPLL_DISP, + .mult_mask = AM33XX_DPLL_MULT_MASK, + .div1_mask = AM33XX_DPLL_DIV_MASK, + .enable_mask = AM33XX_DPLL_EN_MASK, + .idlest_mask = AM33XX_ST_DPLL_CLK_MASK, + .max_multiplier = AM33XX_MAX_DPLL_MULT, + .max_divider = AM33XX_MAX_DPLL_DIV, + .min_divider = 1, +}; + +/* CLKOUT: fdpll/M2 */ +static struct clk dpll_disp_ck = { + .name = "dpll_disp_ck", + .parent = &sys_clkin_ck, + .dpll_data = &dpll_disp_dd, + .init = &omap2_init_dpll_parent, + .ops = &clkops_null, + .recalc = &omap3_dpll_recalc, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, +}; + +/* + * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2 + * and ALT_CLK1/2) + */ +static const struct clksel dpll_disp_m2_div[] = { + { .parent = &dpll_disp_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_disp_m2_ck = { + .name = "dpll_disp_m2_ck", + .parent = &dpll_disp_ck, + .clksel = dpll_disp_m2_div, + .clksel_reg = AM33XX_CM_DIV_M2_DPLL_DISP, + .clksel_mask = AM33XX_DPLL_CLKOUT_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +/* DPLL_PER */ +static struct dpll_data dpll_per_dd = { + .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_PERIPH, + .clk_bypass = &sys_clkin_ck, + .clk_ref = &sys_clkin_ck, + .control_reg = AM33XX_CM_CLKMODE_DPLL_PER, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .idlest_reg = AM33XX_CM_IDLEST_DPLL_PER, + .mult_mask = AM33XX_DPLL_MULT_PERIPH_MASK, + .div1_mask = AM33XX_DPLL_PER_DIV_MASK, + .enable_mask = AM33XX_DPLL_EN_MASK, + .idlest_mask = AM33XX_ST_DPLL_CLK_MASK, + .max_multiplier = AM33XX_MAX_DPLL_MULT, + .max_divider = AM33XX_MAX_DPLL_DIV, + .min_divider = 1, + .flags = DPLL_J_TYPE, +}; + +/* CLKDCOLDO */ +static struct clk dpll_per_ck = { + .name = "dpll_per_ck", + .parent = &sys_clkin_ck, + .dpll_data = &dpll_per_dd, + .init = &omap2_init_dpll_parent, + .ops = &clkops_null, + .recalc = &omap3_dpll_recalc, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, +}; + +/* CLKOUT: fdpll/M2 */ +static const struct clksel dpll_per_m2_div[] = { + { .parent = &dpll_per_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_per_m2_ck = { + .name = "dpll_per_m2_ck", + .parent = &dpll_per_ck, + .clksel = dpll_per_m2_div, + .clksel_reg = AM33XX_CM_DIV_M2_DPLL_PER, + .clksel_mask = AM33XX_DPLL_CLKOUT_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +static struct clk dpll_per_m2_div4_wkupdm_ck = { + .name = "dpll_per_m2_div4_wkupdm_ck", + .clkdm_name = "l4_wkup_clkdm", + .parent = &dpll_per_m2_ck, + .fixed_div = 4, + .ops = &clkops_null, + .recalc = &omap_fixed_divisor_recalc, +}; + +static struct clk dpll_per_m2_div4_ck = { + .name = "dpll_per_m2_div4_ck", + .clkdm_name = "l4ls_clkdm", + .parent = &dpll_per_m2_ck, + .fixed_div = 4, + .ops = &clkops_null, + .recalc = &omap_fixed_divisor_recalc, +}; + +static struct clk l3_gclk = { + .name = "l3_gclk", + .clkdm_name = "l3_clkdm", + .parent = &dpll_core_m4_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static struct clk dpll_core_m4_div2_ck = { + .name = "dpll_core_m4_div2_ck", + .clkdm_name = "l4_wkup_clkdm", + .parent = &dpll_core_m4_ck, + .ops = &clkops_null, + .fixed_div = 2, + .recalc = &omap_fixed_divisor_recalc, +}; + +static struct clk l4_rtc_gclk = { + .name = "l4_rtc_gclk", + .parent = &dpll_core_m4_ck, + .ops = &clkops_null, + .fixed_div = 2, + .recalc = &omap_fixed_divisor_recalc, +}; + +static struct clk clk_24mhz = { + .name = "clk_24mhz", + .parent = &dpll_per_m2_ck, + .fixed_div = 8, + .ops = &clkops_null, + .recalc = &omap_fixed_divisor_recalc, +}; + +/* + * Below clock nodes describes clockdomains derived out + * of core clock. + */ +static struct clk l4hs_gclk = { + .name = "l4hs_gclk", + .clkdm_name = "l4hs_clkdm", + .parent = &dpll_core_m4_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static struct clk l3s_gclk = { + .name = "l3s_gclk", + .clkdm_name = "l3s_clkdm", + .parent = &dpll_core_m4_div2_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static struct clk l4fw_gclk = { + .name = "l4fw_gclk", + .clkdm_name = "l4fw_clkdm", + .parent = &dpll_core_m4_div2_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static struct clk l4ls_gclk = { + .name = "l4ls_gclk", + .clkdm_name = "l4ls_clkdm", + .parent = &dpll_core_m4_div2_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static struct clk sysclk_div_ck = { + .name = "sysclk_div_ck", + .parent = &dpll_core_m4_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +/* + * In order to match the clock domain with hwmod clockdomain entry, + * separate clock nodes is required for the modules which are + * directly getting their funtioncal clock from sys_clkin. + */ +static struct clk adc_tsc_fck = { + .name = "adc_tsc_fck", + .clkdm_name = "l4_wkup_clkdm", + .parent = &sys_clkin_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static struct clk dcan0_fck = { + .name = "dcan0_fck", + .clkdm_name = "l4ls_clkdm", + .parent = &sys_clkin_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static struct clk dcan1_fck = { + .name = "dcan1_fck", + .clkdm_name = "l4ls_clkdm", + .parent = &sys_clkin_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static struct clk mcasp0_fck = { + .name = "mcasp0_fck", + .clkdm_name = "l3s_clkdm", + .parent = &sys_clkin_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static struct clk mcasp1_fck = { + .name = "mcasp1_fck", + .clkdm_name = "l3s_clkdm", + .parent = &sys_clkin_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static struct clk smartreflex0_fck = { + .name = "smartreflex0_fck", + .clkdm_name = "l4_wkup_clkdm", + .parent = &sys_clkin_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static struct clk smartreflex1_fck = { + .name = "smartreflex1_fck", + .clkdm_name = "l4_wkup_clkdm", + .parent = &sys_clkin_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +/* + * Modules clock nodes + * + * The following clock leaf nodes are added for the moment because: + * + * - hwmod data is not present for these modules, either hwmod + * control is not required or its not populated. + * - Driver code is not yet migrated to use hwmod/runtime pm + * - Modules outside kernel access (to disable them by default) + * + * - debugss + * - mmu (gfx domain) + * - cefuse + * - usbotg_fck (its additional clock and not really a modulemode) + * - ieee5000 + */ +static struct clk debugss_ick = { + .name = "debugss_ick", + .clkdm_name = "l3_aon_clkdm", + .parent = &dpll_core_m4_ck, + .ops = &clkops_omap2_dflt, + .enable_reg = AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, + .enable_bit = AM33XX_MODULEMODE_SWCTRL, + .recalc = &followparent_recalc, +}; + +static struct clk mmu_fck = { + .name = "mmu_fck", + .clkdm_name = "gfx_l3_clkdm", + .parent = &dpll_core_m4_ck, + .ops = &clkops_omap2_dflt, + .enable_reg = AM33XX_CM_GFX_MMUDATA_CLKCTRL, + .enable_bit = AM33XX_MODULEMODE_SWCTRL, + .recalc = &followparent_recalc, +}; + +static struct clk cefuse_fck = { + .name = "cefuse_fck", + .clkdm_name = "l4_cefuse_clkdm", + .parent = &sys_clkin_ck, + .enable_reg = AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL, + .enable_bit = AM33XX_MODULEMODE_SWCTRL, + .ops = &clkops_omap2_dflt, + .recalc = &followparent_recalc, +}; + +/* + * clkdiv32 is generated from fixed division of 732.4219 + */ +static struct clk clkdiv32k_ick = { + .name = "clkdiv32k_ick", + .clkdm_name = "clk_24mhz_clkdm", + .rate = 32768, + .parent = &clk_24mhz, + .enable_reg = AM33XX_CM_PER_CLKDIV32K_CLKCTRL, + .enable_bit = AM33XX_MODULEMODE_SWCTRL, + .ops = &clkops_omap2_dflt, +}; + +static struct clk usbotg_fck = { + .name = "usbotg_fck", + .clkdm_name = "l3s_clkdm", + .parent = &dpll_per_ck, + .enable_reg = AM33XX_CM_CLKDCOLDO_DPLL_PER, + .enable_bit = AM33XX_ST_DPLL_CLKDCOLDO_SHIFT, + .ops = &clkops_omap2_dflt, + .recalc = &followparent_recalc, +}; + +static struct clk ieee5000_fck = { + .name = "ieee5000_fck", + .clkdm_name = "l3s_clkdm", + .parent = &dpll_core_m4_div2_ck, + .enable_reg = AM33XX_CM_PER_IEEE5000_CLKCTRL, + .enable_bit = AM33XX_MODULEMODE_SWCTRL, + .ops = &clkops_omap2_dflt, + .recalc = &followparent_recalc, +}; + +/* Timers */ +static const struct clksel timer1_clkmux_sel[] = { + { .parent = &sys_clkin_ck, .rates = div_1_0_rates }, + { .parent = &clkdiv32k_ick, .rates = div_1_1_rates }, + { .parent = &tclkin_ck, .rates = div_1_2_rates }, + { .parent = &clk_rc32k_ck, .rates = div_1_3_rates }, + { .parent = &clk_32768_ck, .rates = div_1_4_rates }, + { .parent = NULL }, +}; + +static struct clk timer1_fck = { + .name = "timer1_fck", + .clkdm_name = "l4ls_clkdm", + .parent = &sys_clkin_ck, + .init = &omap2_init_clksel_parent, + .clksel = timer1_clkmux_sel, + .clksel_reg = AM33XX_CLKSEL_TIMER1MS_CLK, + .clksel_mask = AM33XX_CLKSEL_0_2_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, +}; + +static const struct clksel timer2_to_7_clk_sel[] = { + { .parent = &tclkin_ck, .rates = div_1_0_rates }, + { .parent = &sys_clkin_ck, .rates = div_1_1_rates }, + { .parent = &clkdiv32k_ick, .rates = div_1_2_rates }, + { .parent = NULL }, +}; + +static struct clk timer2_fck = { + .name = "timer2_fck", + .clkdm_name = "l4ls_clkdm", + .parent = &sys_clkin_ck, + .init = &omap2_init_clksel_parent, + .clksel = timer2_to_7_clk_sel, + .clksel_reg = AM33XX_CLKSEL_TIMER2_CLK, + .clksel_mask = AM33XX_CLKSEL_0_1_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, +}; + +static struct clk timer3_fck = { + .name = "timer3_fck", + .clkdm_name = "l4ls_clkdm", + .parent = &sys_clkin_ck, + .init = &am33xx_init_timer_parent, + .clksel = timer2_to_7_clk_sel, + .clksel_reg = AM33XX_CLKSEL_TIMER3_CLK, + .clksel_mask = AM33XX_CLKSEL_0_1_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, +}; + +static struct clk timer4_fck = { + .name = "timer4_fck", + .clkdm_name = "l4ls_clkdm", + .parent = &sys_clkin_ck, + .init = &omap2_init_clksel_parent, + .clksel = timer2_to_7_clk_sel, + .clksel_reg = AM33XX_CLKSEL_TIMER4_CLK, + .clksel_mask = AM33XX_CLKSEL_0_1_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, +}; + +static struct clk timer5_fck = { + .name = "timer5_fck", + .clkdm_name = "l4ls_clkdm", + .parent = &sys_clkin_ck, + .init = &omap2_init_clksel_parent, + .clksel = timer2_to_7_clk_sel, + .clksel_reg = AM33XX_CLKSEL_TIMER5_CLK, + .clksel_mask = AM33XX_CLKSEL_0_1_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, +}; + +static struct clk timer6_fck = { + .name = "timer6_fck", + .clkdm_name = "l4ls_clkdm", + .parent = &sys_clkin_ck, + .init = &am33xx_init_timer_parent, + .clksel = timer2_to_7_clk_sel, + .clksel_reg = AM33XX_CLKSEL_TIMER6_CLK, + .clksel_mask = AM33XX_CLKSEL_0_1_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, +}; + +static struct clk timer7_fck = { + .name = "timer7_fck", + .clkdm_name = "l4ls_clkdm", + .parent = &sys_clkin_ck, + .init = &omap2_init_clksel_parent, + .clksel = timer2_to_7_clk_sel, + .clksel_reg = AM33XX_CLKSEL_TIMER7_CLK, + .clksel_mask = AM33XX_CLKSEL_0_1_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, +}; + +static struct clk cpsw_125mhz_gclk = { + .name = "cpsw_125mhz_gclk", + .clkdm_name = "cpsw_125mhz_clkdm", + .parent = &dpll_core_m5_ck, + .ops = &clkops_null, + .fixed_div = 2, + .recalc = &omap_fixed_divisor_recalc, +}; + +static const struct clksel cpsw_cpts_rft_clkmux_sel[] = { + { .parent = &dpll_core_m5_ck, .rates = div_1_0_rates }, + { .parent = &dpll_core_m4_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk cpsw_cpts_rft_clk = { + .name = "cpsw_cpts_rft_clk", + .clkdm_name = "cpsw_125mhz_clkdm", + .parent = &dpll_core_m5_ck, + .clksel = cpsw_cpts_rft_clkmux_sel, + .clksel_reg = AM33XX_CM_CPTS_RFT_CLKSEL, + .clksel_mask = AM33XX_CLKSEL_0_0_MASK, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +/* gpio */ +static const struct clksel gpio0_dbclk_mux_sel[] = { + { .parent = &clk_rc32k_ck, .rates = div_1_0_rates }, + { .parent = &clk_32768_ck, .rates = div_1_1_rates }, + { .parent = &clkdiv32k_ick, .rates = div_1_2_rates }, + { .parent = NULL }, +}; + +static struct clk gpio0_dbclk_mux_ck = { + .name = "gpio0_dbclk_mux_ck", + .clkdm_name = "l4_wkup_clkdm", + .parent = &clk_rc32k_ck, + .init = &omap2_init_clksel_parent, + .clksel = gpio0_dbclk_mux_sel, + .clksel_reg = AM33XX_CLKSEL_GPIO0_DBCLK, + .clksel_mask = AM33XX_CLKSEL_0_1_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, +}; + +static struct clk gpio0_dbclk = { + .name = "gpio0_dbclk", + .clkdm_name = "l4_wkup_clkdm", + .parent = &gpio0_dbclk_mux_ck, + .enable_reg = AM33XX_CM_WKUP_GPIO0_CLKCTRL, + .enable_bit = AM33XX_OPTFCLKEN_GPIO0_GDBCLK_SHIFT, + .ops = &clkops_omap2_dflt, + .recalc = &followparent_recalc, +}; + +static struct clk gpio1_dbclk = { + .name = "gpio1_dbclk", + .clkdm_name = "l4ls_clkdm", + .parent = &clkdiv32k_ick, + .enable_reg = AM33XX_CM_PER_GPIO1_CLKCTRL, + .enable_bit = AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_SHIFT, + .ops = &clkops_omap2_dflt, + .recalc = &followparent_recalc, +}; + +static struct clk gpio2_dbclk = { + .name = "gpio2_dbclk", + .clkdm_name = "l4ls_clkdm", + .parent = &clkdiv32k_ick, + .enable_reg = AM33XX_CM_PER_GPIO2_CLKCTRL, + .enable_bit = AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_SHIFT, + .ops = &clkops_omap2_dflt, + .recalc = &followparent_recalc, +}; + +static struct clk gpio3_dbclk = { + .name = "gpio3_dbclk", + .clkdm_name = "l4ls_clkdm", + .parent = &clkdiv32k_ick, + .enable_reg = AM33XX_CM_PER_GPIO3_CLKCTRL, + .enable_bit = AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_SHIFT, + .ops = &clkops_omap2_dflt, + .recalc = &followparent_recalc, +}; + +static const struct clksel pruss_ocp_clk_mux_sel[] = { + { .parent = &l3_gclk, .rates = div_1_0_rates }, + { .parent = &dpll_disp_m2_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk pruss_ocp_gclk = { + .name = "pruss_ocp_gclk", + .clkdm_name = "pruss_ocp_clkdm", + .parent = &l3_gclk, + .init = &omap2_init_clksel_parent, + .clksel = pruss_ocp_clk_mux_sel, + .clksel_reg = AM33XX_CLKSEL_PRUSS_OCP_CLK, + .clksel_mask = AM33XX_CLKSEL_0_0_MASK, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static const struct clksel lcd_clk_mux_sel[] = { + { .parent = &dpll_disp_m2_ck, .rates = div_1_0_rates }, + { .parent = &dpll_core_m5_ck, .rates = div_1_1_rates }, + { .parent = &dpll_per_m2_ck, .rates = div_1_2_rates }, + { .parent = NULL }, +}; + +static struct clk lcd_gclk = { + .name = "lcd_gclk", + .clkdm_name = "lcdc_clkdm", + .parent = &dpll_disp_m2_ck, + .init = &omap2_init_clksel_parent, + .clksel = lcd_clk_mux_sel, + .clksel_reg = AM33XX_CLKSEL_LCDC_PIXEL_CLK, + .clksel_mask = AM33XX_CLKSEL_0_1_MASK, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static struct clk mmc_clk = { + .name = "mmc_clk", + .clkdm_name = "l4ls_clkdm", + .parent = &dpll_per_m2_ck, + .ops = &clkops_null, + .fixed_div = 2, + .recalc = &omap_fixed_divisor_recalc, +}; + +static struct clk mmc2_fck = { + .name = "mmc2_fck", + .clkdm_name = "l3s_clkdm", + .parent = &mmc_clk, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + +static const struct clksel gfx_clksel_sel[] = { + { .parent = &dpll_core_m4_ck, .rates = div_1_0_rates }, + { .parent = &dpll_per_m2_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk gfx_fclk_clksel_ck = { + .name = "gfx_fclk_clksel_ck", + .parent = &dpll_core_m4_ck, + .clksel = gfx_clksel_sel, + .ops = &clkops_null, + .clksel_reg = AM33XX_CLKSEL_GFX_FCLK, + .clksel_mask = AM33XX_CLKSEL_GFX_FCLK_MASK, + .recalc = &omap2_clksel_recalc, +}; + +static const struct clksel_rate div_1_0_2_1_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_AM33XX }, + { .div = 2, .val = 1, .flags = RATE_IN_AM33XX }, + { .div = 0 }, +}; + +static const struct clksel gfx_div_sel[] = { + { .parent = &gfx_fclk_clksel_ck, .rates = div_1_0_2_1_rates }, + { .parent = NULL }, +}; + +static struct clk gfx_fck_div_ck = { + .name = "gfx_fck_div_ck", + .clkdm_name = "gfx_l3_clkdm", + .parent = &gfx_fclk_clksel_ck, + .init = &omap2_init_clksel_parent, + .clksel = gfx_div_sel, + .clksel_reg = AM33XX_CLKSEL_GFX_FCLK, + .clksel_mask = AM33XX_CLKSEL_0_0_MASK, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .ops = &clkops_null, +}; + +static const struct clksel sysclkout_pre_sel[] = { + { .parent = &clk_32768_ck, .rates = div_1_0_rates }, + { .parent = &l3_gclk, .rates = div_1_1_rates }, + { .parent = &dpll_ddr_m2_ck, .rates = div_1_2_rates }, + { .parent = &dpll_per_m2_ck, .rates = div_1_3_rates }, + { .parent = &lcd_gclk, .rates = div_1_4_rates }, + { .parent = NULL }, +}; + +static struct clk sysclkout_pre_ck = { + .name = "sysclkout_pre_ck", + .parent = &clk_32768_ck, + .init = &omap2_init_clksel_parent, + .clksel = sysclkout_pre_sel, + .clksel_reg = AM33XX_CM_CLKOUT_CTRL, + .clksel_mask = AM33XX_CLKOUT2SOURCE_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, +}; + +/* Divide by 8 clock rates with default clock is 1/1*/ +static const struct clksel_rate div8_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_AM33XX }, + { .div = 2, .val = 1, .flags = RATE_IN_AM33XX }, + { .div = 3, .val = 2, .flags = RATE_IN_AM33XX }, + { .div = 4, .val = 3, .flags = RATE_IN_AM33XX }, + { .div = 5, .val = 4, .flags = RATE_IN_AM33XX }, + { .div = 6, .val = 5, .flags = RATE_IN_AM33XX }, + { .div = 7, .val = 6, .flags = RATE_IN_AM33XX }, + { .div = 8, .val = 7, .flags = RATE_IN_AM33XX }, + { .div = 0 }, +}; + +static const struct clksel clkout2_div[] = { + { .parent = &sysclkout_pre_ck, .rates = div8_rates }, + { .parent = NULL }, +}; + +static struct clk clkout2_ck = { + .name = "clkout2_ck", + .parent = &sysclkout_pre_ck, + .ops = &clkops_omap2_dflt, + .clksel = clkout2_div, + .clksel_reg = AM33XX_CM_CLKOUT_CTRL, + .clksel_mask = AM33XX_CLKOUT2DIV_MASK, + .enable_reg = AM33XX_CM_CLKOUT_CTRL, + .enable_bit = AM33XX_CLKOUT2EN_SHIFT, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +static const struct clksel wdt_clkmux_sel[] = { + { .parent = &clk_rc32k_ck, .rates = div_1_0_rates }, + { .parent = &clkdiv32k_ick, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk wdt1_fck = { + .name = "wdt1_fck", + .clkdm_name = "l4_wkup_clkdm", + .parent = &clk_rc32k_ck, + .init = &omap2_init_clksel_parent, + .clksel = wdt_clkmux_sel, + .clksel_reg = AM33XX_CLKSEL_WDT1_CLK, + .clksel_mask = AM33XX_CLKSEL_0_1_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, +}; + +/* + * clkdev + */ +static struct omap_clk am33xx_clks[] = { + CLK(NULL, "clk_32768_ck", &clk_32768_ck, CK_AM33XX), + CLK(NULL, "clk_rc32k_ck", &clk_rc32k_ck, CK_AM33XX), + CLK(NULL, "virt_19200000_ck", &virt_19200000_ck, CK_AM33XX), + CLK(NULL, "virt_24000000_ck", &virt_24000000_ck, CK_AM33XX), + CLK(NULL, "virt_25000000_ck", &virt_25000000_ck, CK_AM33XX), + CLK(NULL, "virt_26000000_ck", &virt_26000000_ck, CK_AM33XX), + CLK(NULL, "sys_clkin_ck", &sys_clkin_ck, CK_AM33XX), + CLK(NULL, "tclkin_ck", &tclkin_ck, CK_AM33XX), + CLK(NULL, "dpll_core_ck", &dpll_core_ck, CK_AM33XX), + CLK(NULL, "dpll_core_x2_ck", &dpll_core_x2_ck, CK_AM33XX), + CLK(NULL, "dpll_core_m4_ck", &dpll_core_m4_ck, CK_AM33XX), + CLK(NULL, "dpll_core_m5_ck", &dpll_core_m5_ck, CK_AM33XX), + CLK(NULL, "dpll_core_m6_ck", &dpll_core_m6_ck, CK_AM33XX), + CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck, CK_AM33XX), + CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck, CK_AM33XX), + CLK(NULL, "dpll_ddr_ck", &dpll_ddr_ck, CK_AM33XX), + CLK(NULL, "dpll_ddr_m2_ck", &dpll_ddr_m2_ck, CK_AM33XX), + CLK(NULL, "dpll_ddr_m2_div2_ck", &dpll_ddr_m2_div2_ck, CK_AM33XX), + CLK(NULL, "dpll_disp_ck", &dpll_disp_ck, CK_AM33XX), + CLK(NULL, "dpll_disp_m2_ck", &dpll_disp_m2_ck, CK_AM33XX), + CLK(NULL, "dpll_per_ck", &dpll_per_ck, CK_AM33XX), + CLK(NULL, "dpll_per_m2_ck", &dpll_per_m2_ck, CK_AM33XX), + CLK(NULL, "dpll_per_m2_div4_wkupdm_ck", &dpll_per_m2_div4_wkupdm_ck, CK_AM33XX), + CLK(NULL, "dpll_per_m2_div4_ck", &dpll_per_m2_div4_ck, CK_AM33XX), + CLK(NULL, "adc_tsc_fck", &adc_tsc_fck, CK_AM33XX), + CLK(NULL, "cefuse_fck", &cefuse_fck, CK_AM33XX), + CLK(NULL, "clkdiv32k_ick", &clkdiv32k_ick, CK_AM33XX), + CLK(NULL, "dcan0_fck", &dcan0_fck, CK_AM33XX), + CLK(NULL, "dcan1_fck", &dcan1_fck, CK_AM33XX), + CLK(NULL, "debugss_ick", &debugss_ick, CK_AM33XX), + CLK(NULL, "pruss_ocp_gclk", &pruss_ocp_gclk, CK_AM33XX), + CLK("davinci-mcasp.0", NULL, &mcasp0_fck, CK_AM33XX), + CLK("davinci-mcasp.1", NULL, &mcasp1_fck, CK_AM33XX), + CLK("NULL", "mmc2_fck", &mmc2_fck, CK_AM33XX), + CLK(NULL, "mmu_fck", &mmu_fck, CK_AM33XX), + CLK(NULL, "smartreflex0_fck", &smartreflex0_fck, CK_AM33XX), + CLK(NULL, "smartreflex1_fck", &smartreflex1_fck, CK_AM33XX), + CLK(NULL, "gpt1_fck", &timer1_fck, CK_AM33XX), + CLK(NULL, "gpt2_fck", &timer2_fck, CK_AM33XX), + CLK(NULL, "gpt3_fck", &timer3_fck, CK_AM33XX), + CLK(NULL, "gpt4_fck", &timer4_fck, CK_AM33XX), + CLK(NULL, "gpt5_fck", &timer5_fck, CK_AM33XX), + CLK(NULL, "gpt6_fck", &timer6_fck, CK_AM33XX), + CLK(NULL, "gpt7_fck", &timer7_fck, CK_AM33XX), + CLK(NULL, "usbotg_fck", &usbotg_fck, CK_AM33XX), + CLK(NULL, "ieee5000_fck", &ieee5000_fck, CK_AM33XX), + CLK(NULL, "wdt1_fck", &wdt1_fck, CK_AM33XX), + CLK(NULL, "l4_rtc_gclk", &l4_rtc_gclk, CK_AM33XX), + CLK(NULL, "l3_gclk", &l3_gclk, CK_AM33XX), + CLK(NULL, "dpll_core_m4_div2_ck", &dpll_core_m4_div2_ck, CK_AM33XX), + CLK(NULL, "l4hs_gclk", &l4hs_gclk, CK_AM33XX), + CLK(NULL, "l3s_gclk", &l3s_gclk, CK_AM33XX), + CLK(NULL, "l4fw_gclk", &l4fw_gclk, CK_AM33XX), + CLK(NULL, "l4ls_gclk", &l4ls_gclk, CK_AM33XX), + CLK(NULL, "clk_24mhz", &clk_24mhz, CK_AM33XX), + CLK(NULL, "sysclk_div_ck", &sysclk_div_ck, CK_AM33XX), + CLK(NULL, "cpsw_125mhz_gclk", &cpsw_125mhz_gclk, CK_AM33XX), + CLK(NULL, "cpsw_cpts_rft_clk", &cpsw_cpts_rft_clk, CK_AM33XX), + CLK(NULL, "gpio0_dbclk_mux_ck", &gpio0_dbclk_mux_ck, CK_AM33XX), + CLK(NULL, "gpio0_dbclk", &gpio0_dbclk, CK_AM33XX), + CLK(NULL, "gpio1_dbclk", &gpio1_dbclk, CK_AM33XX), + CLK(NULL, "gpio2_dbclk", &gpio2_dbclk, CK_AM33XX), + CLK(NULL, "gpio3_dbclk", &gpio3_dbclk, CK_AM33XX), + CLK(NULL, "lcd_gclk", &lcd_gclk, CK_AM33XX), + CLK(NULL, "mmc_clk", &mmc_clk, CK_AM33XX), + CLK(NULL, "gfx_fclk_clksel_ck", &gfx_fclk_clksel_ck, CK_AM33XX), + CLK(NULL, "gfx_fck_div_ck", &gfx_fck_div_ck, CK_AM33XX), + CLK(NULL, "sysclkout_pre_ck", &sysclkout_pre_ck, CK_AM33XX), + CLK(NULL, "clkout2_ck", &clkout2_ck, CK_AM33XX), +}; + +int __init am33xx_clk_init(void) +{ + struct omap_clk *c; + u32 cpu_clkflg; + + if (cpu_is_am33xx()) { + cpu_mask = RATE_IN_AM33XX; + cpu_clkflg = CK_AM33XX; + } + + clk_init(&omap2_clk_functions); + + for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++) + clk_preinit(c->lk.clk); + + for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++) { + if (c->cpu & cpu_clkflg) { + clkdev_add(&c->lk); + clk_register(c->lk.clk); + omap2_init_clk_clkdm(c->lk.clk); + } + } + + recalculate_root_clocks(); + + /* + * Only enable those clocks we will need, let the drivers + * enable other clocks as necessary + */ + clk_enable_init_clocks(); + + return 0; +} diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index cb6c11cd8df9..eb007d03ec98 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -38,6 +38,7 @@ #include "powerdomain.h" #include "clockdomain.h" #include "common.h" +#include "clock.h" #include "clock2xxx.h" #include "clock3xxx.h" #include "clock44xx.h" @@ -487,6 +488,7 @@ void __init am33xx_init_early(void) am33xx_voltagedomains_init(); am33xx_powerdomains_init(); am33xx_clockdomains_init(); + am33xx_clk_init(); } #endif diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h index d0ed8c443a63..025d85a3ee86 100644 --- a/arch/arm/plat-omap/include/plat/clkdev_omap.h +++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h @@ -39,6 +39,7 @@ struct omap_clk { #define CK_443X (1 << 11) #define CK_TI816X (1 << 12) #define CK_446X (1 << 13) +#define CK_AM33XX (1 << 14) /* AM33xx specific clocks */ #define CK_1710 (1 << 15) /* 1710 extra for rate selection */ -- cgit v1.2.3 From 954e482bde20b0e208fd4d34ef26e10afd194600 Mon Sep 17 00:00:00 2001 From: Fenghua Yu Date: Thu, 24 May 2012 18:19:45 -0700 Subject: x86/copy_user_generic: Optimize copy_user_generic with CPU erms feature According to Intel 64 and IA-32 SDM and Optimization Reference Manual, beginning with Ivybridge, REG string operation using MOVSB and STOSB can provide both flexible and high-performance REG string operations in cases like memory copy. Enhancement availability is indicated by CPUID.7.0.EBX[9] (Enhanced REP MOVSB/ STOSB). If CPU erms feature is detected, patch copy_user_generic with enhanced fast string version of copy_user_generic. A few new macros are defined to reduce duplicate code in ALTERNATIVE and ALTERNATIVE_2. Signed-off-by: Fenghua Yu Link: http://lkml.kernel.org/r/1337908785-14015-1-git-send-email-fenghua.yu@intel.com Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/alternative.h | 74 ++++++++++++++++++++++++++++++-------- arch/x86/include/asm/uaccess_64.h | 11 +++++- arch/x86/kernel/x8664_ksyms_64.c | 1 + 3 files changed, 70 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 49331bedc158..70780689599a 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -75,23 +75,54 @@ static inline int alternatives_text_reserved(void *start, void *end) } #endif /* CONFIG_SMP */ +#define OLDINSTR(oldinstr) "661:\n\t" oldinstr "\n662:\n" + +#define b_replacement(number) "663"#number +#define e_replacement(number) "664"#number + +#define alt_slen "662b-661b" +#define alt_rlen(number) e_replacement(number)"f-"b_replacement(number)"f" + +#define ALTINSTR_ENTRY(feature, number) \ + " .long 661b - .\n" /* label */ \ + " .long " b_replacement(number)"f - .\n" /* new instruction */ \ + " .word " __stringify(feature) "\n" /* feature bit */ \ + " .byte " alt_slen "\n" /* source len */ \ + " .byte " alt_rlen(number) "\n" /* replacement len */ + +#define DISCARD_ENTRY(number) /* rlen <= slen */ \ + " .byte 0xff + (" alt_rlen(number) ") - (" alt_slen ")\n" + +#define ALTINSTR_REPLACEMENT(newinstr, feature, number) /* replacement */ \ + b_replacement(number)":\n\t" newinstr "\n" e_replacement(number) ":\n\t" + /* alternative assembly primitive: */ #define ALTERNATIVE(oldinstr, newinstr, feature) \ - \ - "661:\n\t" oldinstr "\n662:\n" \ - ".section .altinstructions,\"a\"\n" \ - " .long 661b - .\n" /* label */ \ - " .long 663f - .\n" /* new instruction */ \ - " .word " __stringify(feature) "\n" /* feature bit */ \ - " .byte 662b-661b\n" /* sourcelen */ \ - " .byte 664f-663f\n" /* replacementlen */ \ - ".previous\n" \ - ".section .discard,\"aw\",@progbits\n" \ - " .byte 0xff + (664f-663f) - (662b-661b)\n" /* rlen <= slen */ \ - ".previous\n" \ - ".section .altinstr_replacement, \"ax\"\n" \ - "663:\n\t" newinstr "\n664:\n" /* replacement */ \ - ".previous" + OLDINSTR(oldinstr) \ + ".section .altinstructions,\"a\"\n" \ + ALTINSTR_ENTRY(feature, 1) \ + ".previous\n" \ + ".section .discard,\"aw\",@progbits\n" \ + DISCARD_ENTRY(1) \ + ".previous\n" \ + ".section .altinstr_replacement, \"ax\"\n" \ + ALTINSTR_REPLACEMENT(newinstr, feature, 1) \ + ".previous" + +#define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2)\ + OLDINSTR(oldinstr) \ + ".section .altinstructions,\"a\"\n" \ + ALTINSTR_ENTRY(feature1, 1) \ + ALTINSTR_ENTRY(feature2, 2) \ + ".previous\n" \ + ".section .discard,\"aw\",@progbits\n" \ + DISCARD_ENTRY(1) \ + DISCARD_ENTRY(2) \ + ".previous\n" \ + ".section .altinstr_replacement, \"ax\"\n" \ + ALTINSTR_REPLACEMENT(newinstr1, feature1, 1) \ + ALTINSTR_REPLACEMENT(newinstr2, feature2, 2) \ + ".previous" /* * This must be included *after* the definition of ALTERNATIVE due to @@ -139,6 +170,19 @@ static inline int alternatives_text_reserved(void *start, void *end) asm volatile (ALTERNATIVE("call %P[old]", "call %P[new]", feature) \ : output : [old] "i" (oldfunc), [new] "i" (newfunc), ## input) +/* + * Like alternative_call, but there are two features and respective functions. + * If CPU has feature2, function2 is used. + * Otherwise, if CPU has feature1, function1 is used. + * Otherwise, old function is used. + */ +#define alternative_call_2(oldfunc, newfunc1, feature1, newfunc2, feature2, \ + output, input...) \ + asm volatile (ALTERNATIVE_2("call %P[old]", "call %P[new1]", feature1,\ + "call %P[new2]", feature2) \ + : output : [old] "i" (oldfunc), [new1] "i" (newfunc1), \ + [new2] "i" (newfunc2), ## input) + /* * use this macro(s) if you need more than one output parameter * in alternative_io diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index 8e796fbbf9c6..d8def8b3dba0 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -17,6 +17,8 @@ /* Handles exceptions in both to and from, but doesn't do access_ok */ __must_check unsigned long +copy_user_enhanced_fast_string(void *to, const void *from, unsigned len); +__must_check unsigned long copy_user_generic_string(void *to, const void *from, unsigned len); __must_check unsigned long copy_user_generic_unrolled(void *to, const void *from, unsigned len); @@ -26,9 +28,16 @@ copy_user_generic(void *to, const void *from, unsigned len) { unsigned ret; - alternative_call(copy_user_generic_unrolled, + /* + * If CPU has ERMS feature, use copy_user_enhanced_fast_string. + * Otherwise, if CPU has rep_good feature, use copy_user_generic_string. + * Otherwise, use copy_user_generic_unrolled. + */ + alternative_call_2(copy_user_generic_unrolled, copy_user_generic_string, X86_FEATURE_REP_GOOD, + copy_user_enhanced_fast_string, + X86_FEATURE_ERMS, ASM_OUTPUT2("=a" (ret), "=D" (to), "=S" (from), "=d" (len)), "1" (to), "2" (from), "3" (len) diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c index 9796c2f3d074..6020f6f5927c 100644 --- a/arch/x86/kernel/x8664_ksyms_64.c +++ b/arch/x86/kernel/x8664_ksyms_64.c @@ -28,6 +28,7 @@ EXPORT_SYMBOL(__put_user_8); EXPORT_SYMBOL(copy_user_generic_string); EXPORT_SYMBOL(copy_user_generic_unrolled); +EXPORT_SYMBOL(copy_user_enhanced_fast_string); EXPORT_SYMBOL(__copy_user_nocache); EXPORT_SYMBOL(_copy_from_user); EXPORT_SYMBOL(_copy_to_user); -- cgit v1.2.3 From 2553dcc6e603e3833990bd3a29bee98d1dbdf251 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 28 Jun 2012 16:29:19 -0600 Subject: ARM: tegra: use of_default_bus_match_table of_default_bus_match_table is a table of default bus types supported by of_platform_populate(). Since Tegra has no need to support any specific custom list of bus types, modify the DT board files to use this default list. Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/board-dt-tegra20.c | 7 +------ arch/arm/mach-tegra/board-dt-tegra30.c | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c index 1b43c3350e3c..d0de9c1192f7 100644 --- a/arch/arm/mach-tegra/board-dt-tegra20.c +++ b/arch/arm/mach-tegra/board-dt-tegra20.c @@ -82,11 +82,6 @@ static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = { { NULL, NULL, 0, 0}, }; -static struct of_device_id tegra_dt_match_table[] __initdata = { - { .compatible = "simple-bus", }, - {} -}; - static void __init tegra_dt_init(void) { tegra_clk_init_from_table(tegra_dt_clk_init_table); @@ -95,7 +90,7 @@ static void __init tegra_dt_init(void) * Finished with the static registrations now; fill in the missing * devices */ - of_platform_populate(NULL, tegra_dt_match_table, + of_platform_populate(NULL, of_default_bus_match_table, tegra20_auxdata_lookup, NULL); } diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c index 4a409862015f..ee48214bfd89 100644 --- a/arch/arm/mach-tegra/board-dt-tegra30.c +++ b/arch/arm/mach-tegra/board-dt-tegra30.c @@ -36,11 +36,6 @@ #include "board.h" #include "clock.h" -static struct of_device_id tegra_dt_match_table[] __initdata = { - { .compatible = "simple-bus", }, - {} -}; - struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL), OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000200, "sdhci-tegra.1", NULL), @@ -75,7 +70,7 @@ static void __init tegra30_dt_init(void) { tegra_clk_init_from_table(tegra_dt_clk_init_table); - of_platform_populate(NULL, tegra_dt_match_table, + of_platform_populate(NULL, of_default_bus_match_table, tegra30_auxdata_lookup, NULL); } -- cgit v1.2.3 From 5ae95aefb73b32ec4e7c46554304042ba82230ca Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 5 Jun 2012 15:16:43 +0800 Subject: ARM: imx6q: fix suspend regression caused by common clk migration When moving to common clk framework, the imx6q clks rom and mmdc_ch1_axi get different on/off states than old clk driver, which breaks suspend function. There might be a better way to manage these clocks, but let's takes the old clk driver approach to fix the regression first. Signed-off-by: Shawn Guo Signed-off-by: Olof Johansson --- arch/arm/mach-imx/clk-imx6q.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 17dc66a085a5..e1a17ac7b3b4 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -152,13 +152,14 @@ enum mx6q_clks { ssi2, ssi3, uart_ipg, uart_serial, usboh3, usdhc1, usdhc2, usdhc3, usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg, pll4_audio, pll5_video, pll6_mlb, pll7_usb_host, pll8_enet, ssi1_ipg, - ssi2_ipg, ssi3_ipg, clk_max + ssi2_ipg, ssi3_ipg, rom, + clk_max }; static struct clk *clk[clk_max]; static enum mx6q_clks const clks_init_on[] __initconst = { - mmdc_ch0_axi, mmdc_ch1_axi, + mmdc_ch0_axi, rom, }; int __init mx6q_clocks_init(void) @@ -364,6 +365,7 @@ int __init mx6q_clocks_init(void) clk[gpmi_bch] = imx_clk_gate2("gpmi_bch", "usdhc4", base + 0x78, 26); clk[gpmi_io] = imx_clk_gate2("gpmi_io", "enfc", base + 0x78, 28); clk[gpmi_apb] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30); + clk[rom] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0); clk[sata] = imx_clk_gate2("sata", "ipg", base + 0x7c, 4); clk[sdma] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6); clk[spba] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); -- cgit v1.2.3 From 6416c0409dda00aa66b2a4615044fb59d80f6bb2 Mon Sep 17 00:00:00 2001 From: Paul Parsons Date: Mon, 11 Jun 2012 15:31:14 +0100 Subject: ARM: pxa: hx4700: Fix basic suspend/resume Basic suspend/resume is fixed by ensuring that the PGSR registers are set correctly before sleep mode is entered. In particular four of the active low resets need to be driven high while in sleep mode, otherwise the unit resets itself instead of suspending. Another problem was that the PCFR_GPROD bit is set by the HTC bootloader; this caused GPIO reset (i.e. the reset button) to fail immediately after returning from sleep mode. Signed-off-by: Paul Parsons Cc: Philipp Zabel Signed-off-by: Haojian Zhuang --- arch/arm/mach-pxa/hx4700.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index d09da6a746b8..d3de84b0dcbe 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -127,7 +127,11 @@ static unsigned long hx4700_pin_config[] __initdata = { GPIO19_SSP2_SCLK, GPIO86_SSP2_RXD, GPIO87_SSP2_TXD, - GPIO88_GPIO, + GPIO88_GPIO | MFP_LPM_DRIVE_HIGH, /* TSC2046_CS */ + + /* BQ24022 Regulator */ + GPIO72_GPIO | MFP_LPM_KEEP_OUTPUT, /* BQ24022_nCHARGE_EN */ + GPIO96_GPIO | MFP_LPM_KEEP_OUTPUT, /* BQ24022_ISET2 */ /* HX4700 specific input GPIOs */ GPIO12_GPIO | WAKEUP_ON_EDGE_RISE, /* ASIC3_IRQ */ @@ -135,6 +139,10 @@ static unsigned long hx4700_pin_config[] __initdata = { GPIO14_GPIO, /* nWLAN_IRQ */ /* HX4700 specific output GPIOs */ + GPIO61_GPIO | MFP_LPM_DRIVE_HIGH, /* W3220_nRESET */ + GPIO71_GPIO | MFP_LPM_DRIVE_HIGH, /* ASIC3_nRESET */ + GPIO81_GPIO | MFP_LPM_DRIVE_HIGH, /* CPU_GP_nRESET */ + GPIO116_GPIO | MFP_LPM_DRIVE_HIGH, /* CPU_HW_nRESET */ GPIO102_GPIO | MFP_LPM_DRIVE_LOW, /* SYNAPTICS_POWER_ON */ GPIO10_GPIO, /* GSM_IRQ */ @@ -872,14 +880,19 @@ static struct gpio global_gpios[] = { { GPIO110_HX4700_LCD_LVDD_3V3_ON, GPIOF_OUT_INIT_HIGH, "LCD_LVDD" }, { GPIO111_HX4700_LCD_AVDD_3V3_ON, GPIOF_OUT_INIT_HIGH, "LCD_AVDD" }, { GPIO32_HX4700_RS232_ON, GPIOF_OUT_INIT_HIGH, "RS232_ON" }, + { GPIO61_HX4700_W3220_nRESET, GPIOF_OUT_INIT_HIGH, "W3220_nRESET" }, { GPIO71_HX4700_ASIC3_nRESET, GPIOF_OUT_INIT_HIGH, "ASIC3_nRESET" }, + { GPIO81_HX4700_CPU_GP_nRESET, GPIOF_OUT_INIT_HIGH, "CPU_GP_nRESET" }, { GPIO82_HX4700_EUART_RESET, GPIOF_OUT_INIT_HIGH, "EUART_RESET" }, + { GPIO116_HX4700_CPU_HW_nRESET, GPIOF_OUT_INIT_HIGH, "CPU_HW_nRESET" }, }; static void __init hx4700_init(void) { int ret; + PCFR = PCFR_GPR_EN | PCFR_OPDE; + pxa2xx_mfp_config(ARRAY_AND_SIZE(hx4700_pin_config)); gpio_set_wake(GPIO12_HX4700_ASIC3_IRQ, 1); ret = gpio_request_array(ARRAY_AND_SIZE(global_gpios)); -- cgit v1.2.3 From ce9dcb8784611c50974d1c6b600c71f5c0a29308 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 31 May 2012 09:59:53 -0700 Subject: ARM: davinci: add runtime PM support for clock management Add runtime PM core support to davinci by using the pm_clk infrastructure of the PM core. When runtime PM is enabled, the davinci runtime PM implementation will use the pm_clk layer to enable/disable clocks on demand. When runtime PM is disabled, the pm_clk core will automatically enable clocks when the driver is bound and disable clocks when the driver is unbound. Cc: Mark A. Greer Cc: Sekhar Nori Signed-off-by: Kevin Hilman [nsekhar@ti.com: pruned list of header file includes and removed some debug code] Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/pm_domain.c | 64 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 arch/arm/mach-davinci/pm_domain.c (limited to 'arch') diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 2db78bd5c835..2227effcb0e9 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -39,3 +39,4 @@ obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_SUSPEND) += pm.o sleep.o +obj-$(CONFIG_HAVE_CLK) += pm_domain.o diff --git a/arch/arm/mach-davinci/pm_domain.c b/arch/arm/mach-davinci/pm_domain.c new file mode 100644 index 000000000000..00946e23c1ee --- /dev/null +++ b/arch/arm/mach-davinci/pm_domain.c @@ -0,0 +1,64 @@ +/* + * Runtime PM support code for DaVinci + * + * Author: Kevin Hilman + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ +#include +#include +#include +#include + +#ifdef CONFIG_PM_RUNTIME +static int davinci_pm_runtime_suspend(struct device *dev) +{ + int ret; + + dev_dbg(dev, "%s\n", __func__); + + ret = pm_generic_runtime_suspend(dev); + if (ret) + return ret; + + ret = pm_clk_suspend(dev); + if (ret) { + pm_generic_runtime_resume(dev); + return ret; + } + + return 0; +} + +static int davinci_pm_runtime_resume(struct device *dev) +{ + dev_dbg(dev, "%s\n", __func__); + + pm_clk_resume(dev); + return pm_generic_runtime_resume(dev); +} +#endif + +static struct dev_pm_domain davinci_pm_domain = { + .ops = { + SET_RUNTIME_PM_OPS(davinci_pm_runtime_suspend, + davinci_pm_runtime_resume, NULL) + USE_PLATFORM_PM_SLEEP_OPS + }, +}; + +static struct pm_clk_notifier_block platform_bus_notifier = { + .pm_domain = &davinci_pm_domain, +}; + +static int __init davinci_pm_runtime_init(void) +{ + pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier); + + return 0; +} +core_initcall(davinci_pm_runtime_init); -- cgit v1.2.3 From 19b52abe3c5d759661500a1dc810924369b2ad46 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 27 Jun 2012 17:28:57 +0100 Subject: ARM: 7438/1: fill possible PMD empty section gaps On ARM with the 2-level page table format, a PMD entry is represented by two consecutive section entries covering 2MB of virtual space. However, static mappings always were allowed to use separate 1MB section entries. This means in practice that a static mapping may create half populated PMDs via create_mapping(). Since commit 0536bdf33f (ARM: move iotable mappings within the vmalloc region) those static mappings are located in the vmalloc area. We must ensure no such half populated PMDs are accessible once vmalloc() or ioremap() start looking at the vmalloc area for nearby free virtual address ranges, or various things leading to a kernel crash will happen. Signed-off-by: Nicolas Pitre Reported-by: Santosh Shilimkar Tested-by: "R, Sricharan" Reviewed-by: Catalin Marinas Cc: stable@vger.kernel.org Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'arch') diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index e5dad60b558b..cf4528d51774 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -791,6 +791,79 @@ void __init iotable_init(struct map_desc *io_desc, int nr) } } +#ifndef CONFIG_ARM_LPAE + +/* + * The Linux PMD is made of two consecutive section entries covering 2MB + * (see definition in include/asm/pgtable-2level.h). However a call to + * create_mapping() may optimize static mappings by using individual + * 1MB section mappings. This leaves the actual PMD potentially half + * initialized if the top or bottom section entry isn't used, leaving it + * open to problems if a subsequent ioremap() or vmalloc() tries to use + * the virtual space left free by that unused section entry. + * + * Let's avoid the issue by inserting dummy vm entries covering the unused + * PMD halves once the static mappings are in place. + */ + +static void __init pmd_empty_section_gap(unsigned long addr) +{ + struct vm_struct *vm; + + vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm)); + vm->addr = (void *)addr; + vm->size = SECTION_SIZE; + vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING; + vm->caller = pmd_empty_section_gap; + vm_area_add_early(vm); +} + +static void __init fill_pmd_gaps(void) +{ + struct vm_struct *vm; + unsigned long addr, next = 0; + pmd_t *pmd; + + /* we're still single threaded hence no lock needed here */ + for (vm = vmlist; vm; vm = vm->next) { + if (!(vm->flags & VM_ARM_STATIC_MAPPING)) + continue; + addr = (unsigned long)vm->addr; + if (addr < next) + continue; + + /* + * Check if this vm starts on an odd section boundary. + * If so and the first section entry for this PMD is free + * then we block the corresponding virtual address. + */ + if ((addr & ~PMD_MASK) == SECTION_SIZE) { + pmd = pmd_off_k(addr); + if (pmd_none(*pmd)) + pmd_empty_section_gap(addr & PMD_MASK); + } + + /* + * Then check if this vm ends on an odd section boundary. + * If so and the second section entry for this PMD is empty + * then we block the corresponding virtual address. + */ + addr += vm->size; + if ((addr & ~PMD_MASK) == SECTION_SIZE) { + pmd = pmd_off_k(addr) + 1; + if (pmd_none(*pmd)) + pmd_empty_section_gap(addr); + } + + /* no need to look at any vm entry until we hit the next PMD */ + next = (addr + PMD_SIZE - 1) & PMD_MASK; + } +} + +#else +#define fill_pmd_gaps() do { } while (0) +#endif + static void * __initdata vmalloc_min = (void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET); @@ -1072,6 +1145,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) */ if (mdesc->map_io) mdesc->map_io(); + fill_pmd_gaps(); /* * Finally flush the caches and tlb to ensure that we're in a -- cgit v1.2.3 From 84715dd6c19e058557ab173d327ea65eac0ccb02 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 2 Dec 2011 15:31:11 +0800 Subject: ARM: imx: eliminate macro IMX_GPIO_TO_IRQ() This patch changes all the static gpio irq number assigning with IMX_GPIO_TO_IRQ() to run-time assigning with gpio_to_irq call, and in turn eliminates the macro IMX_GPIO_TO_IRQ(). Signed-off-by: Shawn Guo Acked-by: Sascha Hauer --- arch/arm/mach-imx/mach-cpuimx35.c | 3 ++- arch/arm/mach-imx/mach-cpuimx51sd.c | 3 ++- arch/arm/mach-imx/mach-mx27_3ds.c | 3 ++- arch/arm/mach-imx/mach-mx35_3ds.c | 3 ++- arch/arm/mach-imx/mach-mx53_ard.c | 5 +++-- arch/arm/mach-imx/mach-vpr200.c | 3 ++- arch/arm/mach-imx/mx51_efika.c | 3 ++- arch/arm/plat-mxc/include/mach/hardware.h | 2 -- 8 files changed, 15 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c index c515f8ede1a1..73c4b65ebbe4 100644 --- a/arch/arm/mach-imx/mach-cpuimx35.c +++ b/arch/arm/mach-imx/mach-cpuimx35.c @@ -72,7 +72,7 @@ static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = { I2C_BOARD_INFO("tsc2007", 0x48), .type = "tsc2007", .platform_data = &tsc2007_info, - .irq = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO), + /* irq number is run-time assigned */ }, }; @@ -173,6 +173,7 @@ static void __init eukrea_cpuimx35_init(void) imx35_add_imx_uart0(&uart_pdata); imx35_add_mxc_nand(&eukrea_cpuimx35_nand_board_info); + eukrea_cpuimx35_i2c_devices[1].irq = gpio_to_irq(TSC2007_IRQGPIO); i2c_register_board_info(0, eukrea_cpuimx35_i2c_devices, ARRAY_SIZE(eukrea_cpuimx35_i2c_devices)); imx35_add_imx_i2c0(&eukrea_cpuimx35_i2c0_data); diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c index ac50f1671e38..e42c6f8bed70 100644 --- a/arch/arm/mach-imx/mach-cpuimx51sd.c +++ b/arch/arm/mach-imx/mach-cpuimx51sd.c @@ -259,7 +259,7 @@ static struct spi_board_info cpuimx51sd_spi_device[] = { .mode = SPI_MODE_0, .chip_select = 0, .platform_data = &mcp251x_info, - .irq = IMX_GPIO_TO_IRQ(CAN_IRQGPIO) + /* irq number is run-time assigned */ }, }; @@ -310,6 +310,7 @@ static void __init eukrea_cpuimx51sd_init(void) msleep(20); gpio_set_value(CAN_RST, 1); imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata); + cpuimx51sd_spi_device[0].irq = gpio_to_irq(CAN_IRQGPIO); spi_register_board_info(cpuimx51sd_spi_device, ARRAY_SIZE(cpuimx51sd_spi_device)); diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c index c6d385c52257..18b9bcaa40e3 100644 --- a/arch/arm/mach-imx/mach-mx27_3ds.c +++ b/arch/arm/mach-imx/mach-mx27_3ds.c @@ -445,7 +445,7 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = { .bus_num = 1, .chip_select = 0, /* SS0 */ .platform_data = &mc13783_pdata, - .irq = IMX_GPIO_TO_IRQ(PMIC_INT), + /* irq number is run-time assigned */ .mode = SPI_CS_HIGH, }, { .modalias = "l4f00242t03", @@ -496,6 +496,7 @@ static void __init mx27pdk_init(void) imx27_add_spi_imx1(&spi2_pdata); imx27_add_spi_imx0(&spi1_pdata); + mx27_3ds_spi_devs[0].irq = gpio_to_irq(PMIC_INT); spi_register_board_info(mx27_3ds_spi_devs, ARRAY_SIZE(mx27_3ds_spi_devs)); diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c index 28aa19476de7..fa1ea74dfdd3 100644 --- a/arch/arm/mach-imx/mach-mx35_3ds.c +++ b/arch/arm/mach-imx/mach-mx35_3ds.c @@ -492,7 +492,7 @@ static struct i2c_board_info mx35_3ds_i2c_mc13892 = { I2C_BOARD_INFO("mc13892", 0x08), .platform_data = &mx35_3ds_mc13892_data, - .irq = IMX_GPIO_TO_IRQ(GPIO_PMIC_INT), + /* irq number is run-time assigned */ }; static void __init imx35_3ds_init_mc13892(void) @@ -504,6 +504,7 @@ static void __init imx35_3ds_init_mc13892(void) return; } + mx35_3ds_i2c_mc13892.irq = gpio_to_irq(GPIO_PMIC_INT); i2c_register_board_info(0, &mx35_3ds_i2c_mc13892, 1); } diff --git a/arch/arm/mach-imx/mach-mx53_ard.c b/arch/arm/mach-imx/mach-mx53_ard.c index 05641980dc5e..fe3f3969cf1d 100644 --- a/arch/arm/mach-imx/mach-mx53_ard.c +++ b/arch/arm/mach-imx/mach-mx53_ard.c @@ -135,8 +135,7 @@ static struct resource ard_smsc911x_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B), - .end = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B), + /* irq number is run-time assigned */ .flags = IORESOURCE_IRQ, }, }; @@ -240,6 +239,8 @@ static void __init mx53_ard_board_init(void) imx53_ard_common_init(); mx53_ard_io_init(); regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + ard_smsc911x_resources[1].start = gpio_to_irq(ARD_ETHERNET_INT_B); + ard_smsc911x_resources[1].end = gpio_to_irq(ARD_ETHERNET_INT_B); platform_add_devices(devices, ARRAY_SIZE(devices)); imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data); diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c index add8c69c6c1a..e36eb2c40f41 100644 --- a/arch/arm/mach-imx/mach-vpr200.c +++ b/arch/arm/mach-imx/mach-vpr200.c @@ -162,7 +162,7 @@ static struct i2c_board_info vpr200_i2c_devices[] = { }, { I2C_BOARD_INFO("mc13892", 0x08), .platform_data = &vpr200_pmic, - .irq = IMX_GPIO_TO_IRQ(GPIO_PMIC_INT), + /* irq number is run-time assigned */ } }; @@ -299,6 +299,7 @@ static void __init vpr200_board_init(void) imx35_add_mxc_nand(&vpr200_nand_board_info); imx35_add_sdhci_esdhc_imx(0, NULL); + vpr200_i2c_devices[1].irq = gpio_to_irq(GPIO_PMIC_INT); i2c_register_board_info(0, vpr200_i2c_devices, ARRAY_SIZE(vpr200_i2c_devices)); diff --git a/arch/arm/mach-imx/mx51_efika.c b/arch/arm/mach-imx/mx51_efika.c index ec6ca91b299b..ee870c49bc63 100644 --- a/arch/arm/mach-imx/mx51_efika.c +++ b/arch/arm/mach-imx/mx51_efika.c @@ -587,7 +587,7 @@ static struct spi_board_info mx51_efika_spi_board_info[] __initdata = { .bus_num = 0, .chip_select = 0, .platform_data = &mx51_efika_mc13892_data, - .irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC), + /* irq number is run-time assigned */ }, }; @@ -620,6 +620,7 @@ void __init efika_board_common_init(void) gpio_request(EFIKAMX_PMIC, "pmic irq"); gpio_direction_input(EFIKAMX_PMIC); + mx51_efika_spi_board_info[1].irq = gpio_to_irq(EFIKAMX_PMIC); spi_register_board_info(mx51_efika_spi_board_info, ARRAY_SIZE(mx51_efika_spi_board_info)); imx51_add_ecspi(0, &mx51_efika_spi_pdata); diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h index 0630513554de..1d432a75e409 100644 --- a/arch/arm/plat-mxc/include/mach/hardware.h +++ b/arch/arm/plat-mxc/include/mach/hardware.h @@ -128,6 +128,4 @@ /* range e.g. GPIO_1_5 is gpio 5 under linux */ #define IMX_GPIO_NR(bank, nr) (((bank) - 1) * 32 + (nr)) -#define IMX_GPIO_TO_IRQ(gpio) (MXC_GPIO_IRQ_START + (gpio)) - #endif /* __ASM_ARCH_MXC_HARDWARE_H__ */ -- cgit v1.2.3 From ed175343b4b53d686e30b1e37fb94e142f56fa2f Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 2 Dec 2011 20:00:33 +0800 Subject: ARM: imx: eliminate macro IOMUX_TO_IRQ() This patch changes all the static gpio irq number assigning with IOMUX_TO_IRQ() to run-time assigning with gpio_to_irq call, and in turn eliminates the macro IOMUX_TO_IRQ(). Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Acked-by: Dong Aisheng --- arch/arm/mach-imx/mach-armadillo5x0.c | 12 ++++++++---- arch/arm/mach-imx/mach-kzm_arm11_01.c | 20 +++++++++++++++----- arch/arm/mach-imx/mach-mx31_3ds.c | 13 ++++++------- arch/arm/mach-imx/mach-mx31ads.c | 14 +++++++++----- arch/arm/mach-imx/mach-mx31lilly.c | 10 +++++++--- arch/arm/mach-imx/mach-mx31lite.c | 10 +++++++--- arch/arm/mach-imx/mach-mx31moboard.c | 4 +++- arch/arm/mach-imx/mach-pcm037.c | 18 ++++++++++++------ arch/arm/mach-imx/mach-qong.c | 9 +++++---- arch/arm/mach-imx/mx31lilly-db.c | 5 +++-- arch/arm/mach-imx/mx31lite-db.c | 5 +++-- arch/arm/plat-mxc/include/mach/iomux-mx3.h | 3 --- 12 files changed, 78 insertions(+), 45 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c index c650145d1646..f83c5c683575 100644 --- a/arch/arm/mach-imx/mach-armadillo5x0.c +++ b/arch/arm/mach-imx/mach-armadillo5x0.c @@ -408,7 +408,8 @@ static int armadillo5x0_sdhc1_init(struct device *dev, gpio_direction_input(gpio_wp); /* When supported the trigger type have to be BOTH */ - ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_ATA_DMACK), detect_irq, + ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK)), + detect_irq, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "sdhc-detect", data); @@ -429,7 +430,7 @@ err_gpio_free: static void armadillo5x0_sdhc1_exit(struct device *dev, void *data) { - free_irq(IOMUX_TO_IRQ(MX31_PIN_ATA_DMACK), data); + free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK)), data); gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK)); gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B)); } @@ -450,8 +451,7 @@ static struct resource armadillo5x0_smc911x_resources[] = { .end = MX31_CS3_BASE_ADDR + SZ_32M - 1, .flags = IORESOURCE_MEM, }, { - .start = IOMUX_TO_IRQ(MX31_PIN_GPIO1_0), - .end = IOMUX_TO_IRQ(MX31_PIN_GPIO1_0), + /* irq number is run-time assigned */ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, }, }; @@ -498,6 +498,10 @@ static void __init armadillo5x0_init(void) regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + armadillo5x0_smc911x_resources[1].start = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_0)); + armadillo5x0_smc911x_resources[1].end = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_0)); platform_add_devices(devices, ARRAY_SIZE(devices)); imx_add_gpio_keys(&armadillo5x0_button_data); imx31_add_imx_i2c1(NULL); diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c index 15a26e908260..5d08533ab2c7 100644 --- a/arch/arm/mach-imx/mach-kzm_arm11_01.c +++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c @@ -73,7 +73,7 @@ static struct plat_serial8250_port serial_platform_data[] = { { .membase = KZM_ARM11_IO_ADDRESS(KZM_ARM11_16550), .mapbase = KZM_ARM11_16550, - .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), + /* irq number is run-time assigned */ .irqflags = IRQ_TYPE_EDGE_RISING, .uartclk = 14745600, .regshift = 0, @@ -91,8 +91,7 @@ static struct resource serial8250_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), - .end = IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), + /* irq number is run-time assigned */ .flags = IORESOURCE_IRQ, }, }; @@ -125,6 +124,13 @@ static int __init kzm_init_ext_uart(void) tmp |= 0x2; __raw_writeb(tmp, KZM_ARM11_IO_ADDRESS(KZM_ARM11_CTL1)); + serial_platform_data[0].irq = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)); + serial8250_resources[1].start = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)); + serial8250_resources[1].end = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)); + return platform_device_register(&serial_device); } #else @@ -152,8 +158,7 @@ static struct resource kzm_smsc9118_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = IOMUX_TO_IRQ(MX31_PIN_GPIO1_2), - .end = IOMUX_TO_IRQ(MX31_PIN_GPIO1_2), + /* irq number is run-time assigned */ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, }, }; @@ -184,6 +189,11 @@ static int __init kzm_init_smsc9118(void) regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + kzm_smsc9118_resources[1].start = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2)); + kzm_smsc9118_resources[1].end = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2)); + return platform_device_register(&kzm_smsc9118_device); } #else diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c index 4eafdf275ea2..ecdba0497e7e 100644 --- a/arch/arm/mach-imx/mach-mx31_3ds.c +++ b/arch/arm/mach-imx/mach-mx31_3ds.c @@ -44,9 +44,6 @@ #include "devices-imx31.h" -/* CPLD IRQ line for external uart, external ethernet etc */ -#define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX31_PIN_GPIO1_1) - static int mx31_3ds_pins[] = { /* UART1 */ MX31_PIN_CTS1__CTS1, @@ -317,7 +314,7 @@ static int mx31_3ds_sdhc1_init(struct device *dev, return ret; } - ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), + ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)), detect_irq, IRQF_DISABLED | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "sdhc1-detect", data); @@ -336,7 +333,7 @@ gpio_free: static void mx31_3ds_sdhc1_exit(struct device *dev, void *data) { - free_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), data); + free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)), data); gpio_free_array(mx31_3ds_sdhc1_gpios, ARRAY_SIZE(mx31_3ds_sdhc1_gpios)); } @@ -539,7 +536,7 @@ static struct spi_board_info mx31_3ds_spi_devs[] __initdata = { .bus_num = 1, .chip_select = 1, /* SS2 */ .platform_data = &mc13783_pdata, - .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3), + /* irq number is run-time assigned */ .mode = SPI_CS_HIGH, }, { .modalias = "l4f00242t03", @@ -714,6 +711,7 @@ static void __init mx31_3ds_init(void) imx31_add_mxc_nand(&mx31_3ds_nand_board_info); imx31_add_spi_imx1(&spi1_pdata); + mx31_3ds_spi_devs[0].irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3)); spi_register_board_info(mx31_3ds_spi_devs, ARRAY_SIZE(mx31_3ds_spi_devs)); @@ -736,7 +734,8 @@ static void __init mx31_3ds_init(void) if (!otg_mode_host) imx31_add_fsl_usb2_udc(&usbotg_pdata); - if (mxc_expio_init(MX31_CS5_BASE_ADDR, EXPIO_PARENT_INT)) + if (mxc_expio_init(MX31_CS5_BASE_ADDR, + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)))) printk(KERN_WARNING "Init of the debug board failed, all " "devices on the debug board are unusable.\n"); imx31_add_imx2_wdt(NULL); diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c index 4518e5448227..6f19f98ddbe9 100644 --- a/arch/arm/mach-imx/mach-mx31ads.c +++ b/arch/arm/mach-imx/mach-mx31ads.c @@ -62,7 +62,6 @@ #define PBC_INTSTATUS_REG (PBC_INTSTATUS + PBC_BASE_ADDRESS) #define PBC_INTMASK_SET_REG (PBC_INTMASK_SET + PBC_BASE_ADDRESS) #define PBC_INTMASK_CLEAR_REG (PBC_INTMASK_CLEAR + PBC_BASE_ADDRESS) -#define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX31_PIN_GPIO1_4) #define MXC_EXP_IO_BASE MXC_BOARD_IRQ_START #define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_EXP_IO_BASE) @@ -209,7 +208,7 @@ static struct irq_chip expio_irq_chip = { static void __init mx31ads_init_expio(void) { - int i; + int i, irq; printk(KERN_INFO "MX31ADS EXPIO(CPLD) hardware\n"); @@ -226,8 +225,9 @@ static void __init mx31ads_init_expio(void) irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq); set_irq_flags(i, IRQF_VALID); } - irq_set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_HIGH); - irq_set_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler); + irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_4)); + irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH); + irq_set_chained_handler(irq, mx31ads_expio_irq_handler); } #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1 @@ -488,13 +488,17 @@ static struct i2c_board_info __initdata mx31ads_i2c1_devices[] = { { I2C_BOARD_INFO("wm8350", 0x1a), .platform_data = &mx31_wm8350_pdata, - .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3), + /* irq number is run-time assigned */ }, #endif }; static void __init mxc_init_i2c(void) { +#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1 + mx31ads_i2c1_devices[0].irq = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3)); +#endif i2c_register_board_info(1, mx31ads_i2c1_devices, ARRAY_SIZE(mx31ads_i2c1_devices)); diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c index 83714b0cc290..34b9bf075daf 100644 --- a/arch/arm/mach-imx/mach-mx31lilly.c +++ b/arch/arm/mach-imx/mach-mx31lilly.c @@ -65,8 +65,7 @@ static struct resource smsc91x_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = IOMUX_TO_IRQ(MX31_PIN_GPIO1_0), - .end = IOMUX_TO_IRQ(MX31_PIN_GPIO1_0), + /* irq number is run-time assigned */ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING, } }; @@ -233,7 +232,7 @@ static struct spi_board_info mc13783_dev __initdata = { .bus_num = 1, .chip_select = 0, .platform_data = &mc13783_pdata, - .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3), + /* irq number is run-time assigned */ }; static struct platform_device *devices[] __initdata = { @@ -285,10 +284,15 @@ static void __init mx31lilly_board_init(void) imx31_add_spi_imx0(&spi0_pdata); imx31_add_spi_imx1(&spi1_pdata); + mc13783_dev.irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3)); spi_register_board_info(&mc13783_dev, 1); regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + smsc91x_resources[1].start = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_0)); + smsc91x_resources[1].end = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_0)); platform_add_devices(devices, ARRAY_SIZE(devices)); /* USB */ diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c index 686c60587980..4977378d2f60 100644 --- a/arch/arm/mach-imx/mach-mx31lite.c +++ b/arch/arm/mach-imx/mach-mx31lite.c @@ -83,8 +83,7 @@ static struct resource smsc911x_resources[] = { .end = MX31_CS4_BASE_ADDR + 0x100, .flags = IORESOURCE_MEM, }, { - .start = IOMUX_TO_IRQ(MX31_PIN_SFS6), - .end = IOMUX_TO_IRQ(MX31_PIN_SFS6), + /* irq number is run-time assigned */ .flags = IORESOURCE_IRQ, }, }; @@ -124,7 +123,7 @@ static struct spi_board_info mc13783_spi_dev __initdata = { .bus_num = 1, .chip_select = 0, .platform_data = &mc13783_pdata, - .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3), + /* irq number is run-time assigned */ }; /* @@ -258,6 +257,7 @@ static void __init mx31lite_init(void) imx31_add_mxc_nand(&mx31lite_nand_board_info); imx31_add_spi_imx1(&spi1_pdata); + mc13783_spi_dev.irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3)); spi_register_board_info(&mc13783_spi_dev, 1); /* USB */ @@ -274,6 +274,10 @@ static void __init mx31lite_init(void) pr_warning("could not get LAN irq gpio\n"); else { gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_SFS6)); + smsc911x_resources[1].start = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SFS6)); + smsc911x_resources[1].end = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SFS6)); platform_device_register(&smsc911x_device); } } diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c index 016791f038b0..f0d26db7719e 100644 --- a/arch/arm/mach-imx/mach-mx31moboard.c +++ b/arch/arm/mach-imx/mach-mx31moboard.c @@ -303,7 +303,7 @@ static struct imx_ssi_platform_data moboard_ssi_pdata = { static struct spi_board_info moboard_spi_board_info[] __initdata = { { .modalias = "mc13783", - .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3), + /* irq number is run-time assigned */ .max_speed_hz = 300000, .bus_num = 1, .chip_select = 0, @@ -557,6 +557,8 @@ static void __init mx31moboard_init(void) gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3), "pmic-irq"); gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3)); + moboard_spi_board_info[0].irq = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3)); spi_register_board_info(moboard_spi_board_info, ARRAY_SIZE(moboard_spi_board_info)); diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c index 0a40004154f2..551a035f0c2d 100644 --- a/arch/arm/mach-imx/mach-pcm037.c +++ b/arch/arm/mach-imx/mach-pcm037.c @@ -225,8 +225,7 @@ static struct resource smsc911x_resources[] = { .end = MX31_CS1_BASE_ADDR + 0x300 + SZ_64K - 1, .flags = IORESOURCE_MEM, }, { - .start = IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), - .end = IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), + /* irq number is run-time assigned */ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, }, }; @@ -371,7 +370,7 @@ static int pcm970_sdhc1_init(struct device *dev, irq_handler_t detect_irq, gpio_direction_input(SDHC1_GPIO_WP); #endif - ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_SCK6), detect_irq, + ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SCK6)), detect_irq, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "sdhc-detect", data); if (ret) @@ -391,7 +390,7 @@ err_gpio_free: static void pcm970_sdhc1_exit(struct device *dev, void *data) { - free_irq(IOMUX_TO_IRQ(MX31_PIN_SCK6), data); + free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SCK6)), data); gpio_free(SDHC1_GPIO_DET); gpio_free(SDHC1_GPIO_WP); } @@ -511,8 +510,7 @@ static struct resource pcm970_sja1000_resources[] = { .end = MX31_CS5_BASE_ADDR + 0x100 - 1, .flags = IORESOURCE_MEM, }, { - .start = IOMUX_TO_IRQ(IOMUX_PIN(48, 105)), - .end = IOMUX_TO_IRQ(IOMUX_PIN(48, 105)), + /* irq number is run-time assigned */ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, }, }; @@ -633,6 +631,10 @@ static void __init pcm037_init(void) pr_warning("could not get LAN irq gpio\n"); else { gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)); + smsc911x_resources[1].start = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)); + smsc911x_resources[1].end = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)); platform_device_register(&pcm037_eth); } @@ -659,6 +661,10 @@ static void __init pcm037_init(void) pcm037_init_camera(); + pcm970_sja1000_resources[1].start = + gpio_to_irq(IOMUX_TO_GPIO(IOMUX_PIN(48, 105))); + pcm970_sja1000_resources[1].end = + gpio_to_irq(IOMUX_TO_GPIO(IOMUX_PIN(48, 105))); platform_device_register(&pcm970_sja1000); if (otg_mode_host) { diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c index 260621055b6b..b6f11d25f25a 100644 --- a/arch/arm/mach-imx/mach-qong.c +++ b/arch/arm/mach-imx/mach-qong.c @@ -51,8 +51,6 @@ (QONG_FPGA_BASEADDR + QONG_DNET_ID * QONG_FPGA_PERIPH_SIZE) #define QONG_DNET_SIZE 0x00001000 -#define QONG_FPGA_IRQ IOMUX_TO_IRQ(MX31_PIN_DTR_DCE1) - static const struct imxuart_platform_data uart_pdata __initconst = { .flags = IMXUART_HAVE_RTSCTS, }; @@ -78,8 +76,7 @@ static struct resource dnet_resources[] = { .end = QONG_DNET_BASEADDR + QONG_DNET_SIZE - 1, .flags = IORESOURCE_MEM, }, { - .start = QONG_FPGA_IRQ, - .end = QONG_FPGA_IRQ, + /* irq number is run-time assigned */ .flags = IORESOURCE_IRQ, }, }; @@ -95,6 +92,10 @@ static int __init qong_init_dnet(void) { int ret; + dnet_resources[1].start = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1)); + dnet_resources[1].end = + gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1)); ret = platform_device_register(&dnet_device); return ret; } diff --git a/arch/arm/mach-imx/mx31lilly-db.c b/arch/arm/mach-imx/mx31lilly-db.c index 7d26f766a4ee..2df625bdc71e 100644 --- a/arch/arm/mach-imx/mx31lilly-db.c +++ b/arch/arm/mach-imx/mx31lilly-db.c @@ -130,7 +130,8 @@ static int mxc_mmc1_init(struct device *dev, gpio_direction_input(gpio_det); gpio_direction_input(gpio_wp); - ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), detect_irq, + ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)), + detect_irq, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "MMC detect", data); if (ret) @@ -151,7 +152,7 @@ static void mxc_mmc1_exit(struct device *dev, void *data) { gpio_free(gpio_det); gpio_free(gpio_wp); - free_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), data); + free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)), data); } static const struct imxmmc_platform_data mmc_pdata __initconst = { diff --git a/arch/arm/mach-imx/mx31lite-db.c b/arch/arm/mach-imx/mx31lite-db.c index bf0fb87946ba..d639391a5841 100644 --- a/arch/arm/mach-imx/mx31lite-db.c +++ b/arch/arm/mach-imx/mx31lite-db.c @@ -116,7 +116,8 @@ static int mxc_mmc1_init(struct device *dev, gpio_direction_input(gpio_det); gpio_direction_input(gpio_wp); - ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_DCD_DCE1), detect_irq, + ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1)), + detect_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "MMC detect", data); if (ret) @@ -137,7 +138,7 @@ static void mxc_mmc1_exit(struct device *dev, void *data) { gpio_free(gpio_det); gpio_free(gpio_wp); - free_irq(IOMUX_TO_IRQ(MX31_PIN_DCD_DCE1), data); + free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1)), data); } static const struct imxmmc_platform_data mmc_pdata __initconst = { diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h index 63f22a009a65..d8b65b51f2a9 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h @@ -160,9 +160,6 @@ int mxc_iomux_mode(unsigned int pin_mode); #define IOMUX_TO_GPIO(iomux_pin) \ ((iomux_pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT) -#define IOMUX_TO_IRQ(iomux_pin) \ - (((iomux_pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT) + \ - MXC_GPIO_IRQ_START) /* * This enumeration is constructed based on the Section -- cgit v1.2.3 From 438196c371cb32f0eacaf2a44166d9a0cf37c4a8 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 5 Dec 2011 10:12:28 +0800 Subject: ARM: imx: eliminate macro IRQ_GPIOx() This patch changes all the static gpio irq number assigning with IRQ_GPIOA() ... IRQ_GPIOF() to run-time assigning with gpio_to_irq call, and in turn eliminates these macros. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Acked-by: Dong Aisheng --- arch/arm/mach-imx/eukrea_mbimx27-baseboard.c | 3 ++- arch/arm/mach-imx/mach-apf9328.c | 6 ++++-- arch/arm/mach-imx/mach-cpuimx27.c | 12 ++++++++---- arch/arm/mach-imx/mach-imx27_visstrim_m10.c | 9 +++++---- arch/arm/mach-imx/mach-mx21ads.c | 16 +++++++++++----- arch/arm/mach-imx/mach-mx27ads.c | 12 ++++++------ arch/arm/mach-imx/mach-mxt_td60.c | 6 +++--- arch/arm/mach-imx/mach-pca100.c | 4 ++-- arch/arm/mach-imx/mach-pcm038.c | 4 +++- arch/arm/mach-imx/mach-scb9328.c | 6 ++++-- arch/arm/mach-imx/pcm970-baseboard.c | 13 +++++++------ arch/arm/plat-mxc/include/mach/iomux-v1.h | 7 ------- 12 files changed, 55 insertions(+), 43 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c index b46cab0ced53..fd3177f9e79a 100644 --- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c @@ -266,7 +266,7 @@ static struct spi_board_info __maybe_unused .bus_num = 0, .chip_select = 0, .max_speed_hz = 1500000, - .irq = IRQ_GPIOD(25), + /* irq number is run-time assigned */ .platform_data = &ads7846_config, .mode = SPI_MODE_2, }, @@ -329,6 +329,7 @@ void __init eukrea_mbimx27_baseboard_init(void) /* SPI_CS0 init */ mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT); imx27_add_spi_imx0(&eukrea_mbimx27_spi0_data); + eukrea_mbimx27_spi_board_info[0].irq = gpio_to_irq(IMX_GPIO_NR(4, 25)); spi_register_board_info(eukrea_mbimx27_spi_board_info, ARRAY_SIZE(eukrea_mbimx27_spi_board_info)); diff --git a/arch/arm/mach-imx/mach-apf9328.c b/arch/arm/mach-imx/mach-apf9328.c index f4a63ee9e217..5062fcb88498 100644 --- a/arch/arm/mach-imx/mach-apf9328.c +++ b/arch/arm/mach-imx/mach-apf9328.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -87,8 +88,7 @@ static struct resource dm9000_resources[] = { .end = MX1_CS4_PHYS + 0x00C00003, .flags = IORESOURCE_MEM, }, { - .start = IRQ_GPIOB(14), - .end = IRQ_GPIOB(14), + /* irq number is run-time assigned */ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, }, }; @@ -129,6 +129,8 @@ static void __init apf9328_init(void) imx1_add_imx_i2c(&apf9328_i2c_data); + dm9000_resources[2].start = gpio_to_irq(IMX_GPIO_NR(2, 14)); + dm9000_resources[2].end = gpio_to_irq(IMX_GPIO_NR(2, 14)); platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c index d085aea08709..fe74c84a1f4e 100644 --- a/arch/arm/mach-imx/mach-cpuimx27.c +++ b/arch/arm/mach-imx/mach-cpuimx27.c @@ -169,28 +169,28 @@ static struct i2c_board_info eukrea_cpuimx27_i2c_devices[] = { static struct plat_serial8250_port serial_platform_data[] = { { .mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x200000), - .irq = IRQ_GPIOB(23), + /* irq number is run-time assigned */ .uartclk = 14745600, .regshift = 1, .iotype = UPIO_MEM, .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, }, { .mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x400000), - .irq = IRQ_GPIOB(22), + /* irq number is run-time assigned */ .uartclk = 14745600, .regshift = 1, .iotype = UPIO_MEM, .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, }, { .mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x800000), - .irq = IRQ_GPIOB(27), + /* irq number is run-time assigned */ .uartclk = 14745600, .regshift = 1, .iotype = UPIO_MEM, .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, }, { .mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x1000000), - .irq = IRQ_GPIOB(30), + /* irq number is run-time assigned */ .uartclk = 14745600, .regshift = 1, .iotype = UPIO_MEM, @@ -279,6 +279,10 @@ static void __init eukrea_cpuimx27_init(void) #endif #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE) + serial_platform_data[0].irq = IMX_GPIO_NR(2, 23); + serial_platform_data[1].irq = IMX_GPIO_NR(2, 22); + serial_platform_data[2].irq = IMX_GPIO_NR(2, 27); + serial_platform_data[3].irq = IMX_GPIO_NR(2, 30); platform_device_register(&serial_device); #endif diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c index dff82eb57cd9..54c34a6f92c7 100644 --- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c +++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include "devices-imx27.h" @@ -47,7 +48,7 @@ #define TVP5150_RSTN (GPIO_PORTC + 18) #define TVP5150_PWDN (GPIO_PORTC + 19) #define OTG_PHY_CS_GPIO (GPIO_PORTF + 17) -#define SDHC1_IRQ IRQ_GPIOB(25) +#define SDHC1_IRQ_GPIO IMX_GPIO_NR(2, 25) #define MOTHERBOARD_BIT2 (GPIO_PORTD + 31) #define MOTHERBOARD_BIT1 (GPIO_PORTD + 30) @@ -294,14 +295,14 @@ static int visstrim_m10_sdhc1_init(struct device *dev, { int ret; - ret = request_irq(SDHC1_IRQ, detect_irq, IRQF_TRIGGER_FALLING, - "mmc-detect", data); + ret = request_irq(gpio_to_irq(SDHC1_IRQ_GPIO), detect_irq, + IRQF_TRIGGER_FALLING, "mmc-detect", data); return ret; } static void visstrim_m10_sdhc1_exit(struct device *dev, void *data) { - free_irq(SDHC1_IRQ, data); + free_irq(gpio_to_irq(SDHC1_IRQ_GPIO), data); } static const struct imxmmc_platform_data visstrim_m10_sdhc_pdata __initconst = { diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c index d14bbe949a4f..ab3bdf738f53 100644 --- a/arch/arm/mach-imx/mach-mx21ads.c +++ b/arch/arm/mach-imx/mach-mx21ads.c @@ -38,7 +38,7 @@ (MX21ADS_MMIO_BASE_ADDR + (offset)) #define MX21ADS_CS8900A_MMIO_SIZE 0x200000 -#define MX21ADS_CS8900A_IRQ IRQ_GPIOE(11) +#define MX21ADS_CS8900A_IRQ_GPIO IMX_GPIO_NR(5, 11) #define MX21ADS_ST16C255_IOBASE_REG MX21ADS_REG_ADDR(0x200000) #define MX21ADS_VERSION_REG MX21ADS_REG_ADDR(0x400000) #define MX21ADS_IO_REG MX21ADS_REG_ADDR(0x800000) @@ -159,9 +159,10 @@ static struct platform_device mx21ads_nor_mtd_device = { .resource = &mx21ads_flash_resource, }; -static const struct resource mx21ads_cs8900_resources[] __initconst = { +static struct resource mx21ads_cs8900_resources[] __initdata = { DEFINE_RES_MEM(MX21_CS1_BASE_ADDR, MX21ADS_CS8900A_MMIO_SIZE), - DEFINE_RES_IRQ(MX21ADS_CS8900A_IRQ), + /* irq number is run-time assigned */ + DEFINE_RES_IRQ(-1), }; static const struct platform_device_info mx21ads_cs8900_devinfo __initconst = { @@ -241,13 +242,13 @@ static int mx21ads_sdhc_get_ro(struct device *dev) static int mx21ads_sdhc_init(struct device *dev, irq_handler_t detect_irq, void *data) { - return request_irq(IRQ_GPIOD(25), detect_irq, + return request_irq(gpio_to_irq(IMX_GPIO_NR(4, 25)), detect_irq, IRQF_TRIGGER_FALLING, "mmc-detect", data); } static void mx21ads_sdhc_exit(struct device *dev, void *data) { - free_irq(IRQ_GPIOD(25), data); + free_irq(gpio_to_irq(IMX_GPIO_NR(4, 25)), data); } static const struct imxmmc_platform_data mx21ads_sdhc_pdata __initconst = { @@ -304,6 +305,11 @@ static void __init mx21ads_board_init(void) imx21_add_mxc_nand(&mx21ads_nand_board_info); platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); + + mx21ads_cs8900_resources[1].start = + gpio_to_irq(MX21ADS_CS8900A_IRQ_GPIO); + mx21ads_cs8900_resources[1].end = + gpio_to_irq(MX21ADS_CS8900A_IRQ_GPIO); platform_device_register_full(&mx21ads_cs8900_devinfo); } diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c index 0228d2e07fe0..78b6bb5fcc6a 100644 --- a/arch/arm/mach-imx/mach-mx27ads.c +++ b/arch/arm/mach-imx/mach-mx27ads.c @@ -246,25 +246,25 @@ static const struct imx_fb_platform_data mx27ads_fb_data __initconst = { static int mx27ads_sdhc1_init(struct device *dev, irq_handler_t detect_irq, void *data) { - return request_irq(IRQ_GPIOE(21), detect_irq, IRQF_TRIGGER_RISING, - "sdhc1-card-detect", data); + return request_irq(gpio_to_irq(IMX_GPIO_NR(5, 21)), detect_irq, + IRQF_TRIGGER_RISING, "sdhc1-card-detect", data); } static int mx27ads_sdhc2_init(struct device *dev, irq_handler_t detect_irq, void *data) { - return request_irq(IRQ_GPIOB(7), detect_irq, IRQF_TRIGGER_RISING, - "sdhc2-card-detect", data); + return request_irq(gpio_to_irq(IMX_GPIO_NR(2, 7)), detect_irq, + IRQF_TRIGGER_RISING, "sdhc2-card-detect", data); } static void mx27ads_sdhc1_exit(struct device *dev, void *data) { - free_irq(IRQ_GPIOE(21), data); + free_irq(gpio_to_irq(IMX_GPIO_NR(5, 21)), data); } static void mx27ads_sdhc2_exit(struct device *dev, void *data) { - free_irq(IRQ_GPIOB(7), data); + free_irq(gpio_to_irq(IMX_GPIO_NR(2, 7)), data); } static const struct imxmmc_platform_data sdhc1_pdata __initconst = { diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c index 8b3d3f07d894..0bf6d30aa32d 100644 --- a/arch/arm/mach-imx/mach-mxt_td60.c +++ b/arch/arm/mach-imx/mach-mxt_td60.c @@ -213,13 +213,13 @@ static const struct imx_fb_platform_data mxt_td60_fb_data __initconst = { static int mxt_td60_sdhc1_init(struct device *dev, irq_handler_t detect_irq, void *data) { - return request_irq(IRQ_GPIOF(8), detect_irq, IRQF_TRIGGER_FALLING, - "sdhc1-card-detect", data); + return request_irq(gpio_to_irq(IMX_GPIO_NR(6, 8)), detect_irq, + IRQF_TRIGGER_FALLING, "sdhc1-card-detect", data); } static void mxt_td60_sdhc1_exit(struct device *dev, void *data) { - free_irq(IRQ_GPIOF(8), data); + free_irq(gpio_to_irq(IMX_GPIO_NR(6, 8)), data); } static const struct imxmmc_platform_data sdhc1_pdata __initconst = { diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c index 541152e450c4..8b1dfa277fd5 100644 --- a/arch/arm/mach-imx/mach-pca100.c +++ b/arch/arm/mach-imx/mach-pca100.c @@ -245,7 +245,7 @@ static int pca100_sdhc2_init(struct device *dev, irq_handler_t detect_irq, { int ret; - ret = request_irq(IRQ_GPIOC(29), detect_irq, + ret = request_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), detect_irq, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "imx-mmc-detect", data); if (ret) @@ -257,7 +257,7 @@ static int pca100_sdhc2_init(struct device *dev, irq_handler_t detect_irq, static void pca100_sdhc2_exit(struct device *dev, void *data) { - free_irq(IRQ_GPIOC(29), data); + free_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), data); } static const struct imxmmc_platform_data sdhc_pdata __initconst = { diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c index 2f3debe2a113..cfb39037b203 100644 --- a/arch/arm/mach-imx/mach-pcm038.c +++ b/arch/arm/mach-imx/mach-pcm038.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -274,7 +275,7 @@ static struct mc13xxx_platform_data pcm038_pmic = { static struct spi_board_info pcm038_spi_board_info[] __initdata = { { .modalias = "mc13783", - .irq = IRQ_GPIOB(23), + /* irq number is run-time assigned */ .max_speed_hz = 300000, .bus_num = 0, .chip_select = 0, @@ -325,6 +326,7 @@ static void __init pcm038_init(void) mxc_gpio_mode(GPIO_PORTB | 23 | GPIO_GPIO | GPIO_IN); imx27_add_spi_imx0(&pcm038_spi0_data); + pcm038_spi_board_info[0].irq = gpio_to_irq(IMX_GPIO_NR(2, 23)); spi_register_board_info(pcm038_spi_board_info, ARRAY_SIZE(pcm038_spi_board_info)); diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c index cb9ceae2f648..500116498698 100644 --- a/arch/arm/mach-imx/mach-scb9328.c +++ b/arch/arm/mach-imx/mach-scb9328.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -78,8 +79,7 @@ static struct resource dm9000x_resources[] = { .end = MX1_CS5_PHYS + 5, .flags = IORESOURCE_MEM, /* data access */ }, { - .start = IRQ_GPIOC(3), - .end = IRQ_GPIOC(3), + /* irq number is run-time assigned */ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, }, }; @@ -123,6 +123,8 @@ static void __init scb9328_init(void) imx1_add_imx_uart0(&uart_pdata); printk(KERN_INFO"Scb9328: Adding devices\n"); + dm9000x_resources[2].start = gpio_to_irq(IMX_GPIO_NR(3, 3)); + dm9000x_resources[2].end = gpio_to_irq(IMX_GPIO_NR(3, 3)); platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/arch/arm/mach-imx/pcm970-baseboard.c b/arch/arm/mach-imx/pcm970-baseboard.c index 99afbc3f43a3..9917e2ff51da 100644 --- a/arch/arm/mach-imx/pcm970-baseboard.c +++ b/arch/arm/mach-imx/pcm970-baseboard.c @@ -95,14 +95,14 @@ static int pcm970_sdhc2_init(struct device *dev, irq_handler_t detect_irq, void { int ret; - ret = request_irq(IRQ_GPIOC(29), detect_irq, IRQF_TRIGGER_FALLING, - "imx-mmc-detect", data); + ret = request_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), detect_irq, + IRQF_TRIGGER_FALLING, "imx-mmc-detect", data); if (ret) return ret; ret = gpio_request(GPIO_PORTC + 28, "imx-mmc-ro"); if (ret) { - free_irq(IRQ_GPIOC(29), data); + free_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), data); return ret; } @@ -113,7 +113,7 @@ static int pcm970_sdhc2_init(struct device *dev, irq_handler_t detect_irq, void static void pcm970_sdhc2_exit(struct device *dev, void *data) { - free_irq(IRQ_GPIOC(29), data); + free_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), data); gpio_free(GPIO_PORTC + 28); } @@ -192,8 +192,7 @@ static struct resource pcm970_sja1000_resources[] = { .end = MX27_CS4_BASE_ADDR + 0x100 - 1, .flags = IORESOURCE_MEM, }, { - .start = IRQ_GPIOE(19), - .end = IRQ_GPIOE(19), + /* irq number is run-time assigned */ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, }, }; @@ -227,5 +226,7 @@ void __init pcm970_baseboard_init(void) imx27_add_imx_fb(&pcm038_fb_data); mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN); imx27_add_mxc_mmc(1, &sdhc_pdata); + pcm970_sja1000_resources[1].start = gpio_to_irq(IMX_GPIO_NR(5, 19)); + pcm970_sja1000_resources[1].end = gpio_to_irq(IMX_GPIO_NR(5, 19)); platform_device_register(&pcm970_sja1000); } diff --git a/arch/arm/plat-mxc/include/mach/iomux-v1.h b/arch/arm/plat-mxc/include/mach/iomux-v1.h index f7d18046c04f..02651a40fe23 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-v1.h +++ b/arch/arm/plat-mxc/include/mach/iomux-v1.h @@ -85,13 +85,6 @@ #define GPIO_BOUT_0 (2 << GPIO_BOUT_SHIFT) #define GPIO_BOUT_1 (3 << GPIO_BOUT_SHIFT) -#define IRQ_GPIOA(x) (MXC_GPIO_IRQ_START + x) -#define IRQ_GPIOB(x) (IRQ_GPIOA(32) + x) -#define IRQ_GPIOC(x) (IRQ_GPIOB(32) + x) -#define IRQ_GPIOD(x) (IRQ_GPIOC(32) + x) -#define IRQ_GPIOE(x) (IRQ_GPIOD(32) + x) -#define IRQ_GPIOF(x) (IRQ_GPIOE(32) + x) - extern int mxc_gpio_mode(int gpio_mode); extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, const char *label); -- cgit v1.2.3 From 1ab7ef158dfbaf6314b6660a3e3fb037cba2a1ca Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 13 Jun 2012 09:04:03 +0800 Subject: gpio/mxc: move irq_domain_add_legacy call into gpio driver Move irq_domain_add_legacy call from imx*-dt.c into gpio driver and have the gpio driver adopt irqdomain support for both DT and non-DT boot. With all imx platform code converted from static gpio irq number computation to use run-time gpio_to_irq call, we can now use irq_alloc_descs and irqdomain support to dynamically get irq_base and have the mapping between gpio and irq number available without using virtual_irq_start and MXC_GPIO_IRQ_START. Signed-off-by: Shawn Guo Cc: Grant Likely Acked-by: Sascha Hauer Acked-by: Dong Aisheng --- arch/arm/mach-imx/imx27-dt.c | 13 ---------- arch/arm/mach-imx/imx51-dt.c | 12 --------- arch/arm/mach-imx/imx53-dt.c | 12 --------- arch/arm/mach-imx/mach-imx6q.c | 14 ----------- drivers/gpio/gpio-mxc.c | 56 ++++++++++++++++++++++++------------------ 5 files changed, 32 insertions(+), 75 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c index eee0cc8d92a4..c734e564f204 100644 --- a/arch/arm/mach-imx/imx27-dt.c +++ b/arch/arm/mach-imx/imx27-dt.c @@ -40,21 +40,8 @@ static int __init imx27_avic_add_irq_domain(struct device_node *np, return 0; } -static int __init imx27_gpio_add_irq_domain(struct device_node *np, - struct device_node *interrupt_parent) -{ - static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS; - - gpio_irq_base -= 32; - irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, - NULL); - - return 0; -} - static const struct of_device_id imx27_irq_match[] __initconst = { { .compatible = "fsl,imx27-avic", .data = imx27_avic_add_irq_domain, }, - { .compatible = "fsl,imx27-gpio", .data = imx27_gpio_add_irq_domain, }, { /* sentinel */ } }; diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c index 18e78dba4298..3bdabbc64f43 100644 --- a/arch/arm/mach-imx/imx51-dt.c +++ b/arch/arm/mach-imx/imx51-dt.c @@ -52,20 +52,8 @@ static int __init imx51_tzic_add_irq_domain(struct device_node *np, return 0; } -static int __init imx51_gpio_add_irq_domain(struct device_node *np, - struct device_node *interrupt_parent) -{ - static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS; - - gpio_irq_base -= 32; - irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL); - - return 0; -} - static const struct of_device_id imx51_irq_match[] __initconst = { { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, }, - { .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, }, { /* sentinel */ } }; diff --git a/arch/arm/mach-imx/imx53-dt.c b/arch/arm/mach-imx/imx53-dt.c index eb04b6248e48..17fca3cac268 100644 --- a/arch/arm/mach-imx/imx53-dt.c +++ b/arch/arm/mach-imx/imx53-dt.c @@ -59,20 +59,8 @@ static int __init imx53_tzic_add_irq_domain(struct device_node *np, return 0; } -static int __init imx53_gpio_add_irq_domain(struct device_node *np, - struct device_node *interrupt_parent) -{ - static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS; - - gpio_irq_base -= 32; - irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL); - - return 0; -} - static const struct of_device_id imx53_irq_match[] __initconst = { { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, }, - { .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, }, { /* sentinel */ } }; diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index b47e98b7d539..8c2a649192ca 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -136,21 +135,8 @@ static void __init imx6q_map_io(void) imx6q_clock_map_io(); } -static int __init imx6q_gpio_add_irq_domain(struct device_node *np, - struct device_node *interrupt_parent) -{ - static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS; - - gpio_irq_base -= 32; - irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, - NULL); - - return 0; -} - static const struct of_device_id imx6q_irq_match[] __initconst = { { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - { .compatible = "fsl,imx6q-gpio", .data = imx6q_gpio_add_irq_domain, }, { /* sentinel */ } }; diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index c337143b18f8..e5db670d0002 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -33,8 +34,6 @@ #include #include -#define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START) - enum mxc_gpio_hwtype { IMX1_GPIO, /* runs on i.mx1 */ IMX21_GPIO, /* runs on i.mx21 and i.mx27 */ @@ -61,7 +60,7 @@ struct mxc_gpio_port { void __iomem *base; int irq; int irq_high; - int virtual_irq_start; + struct irq_domain *domain; struct bgpio_chip bgc; u32 both_edges; }; @@ -144,14 +143,15 @@ static LIST_HEAD(mxc_gpio_ports); static int gpio_set_irq_type(struct irq_data *d, u32 type) { - u32 gpio = irq_to_gpio(d->irq); struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct mxc_gpio_port *port = gc->private; u32 bit, val; + u32 gpio_idx = d->hwirq; + u32 gpio = port->bgc.gc.base + gpio_idx; int edge; void __iomem *reg = port->base; - port->both_edges &= ~(1 << (gpio & 31)); + port->both_edges &= ~(1 << gpio_idx); switch (type) { case IRQ_TYPE_EDGE_RISING: edge = GPIO_INT_RISE_EDGE; @@ -168,7 +168,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) edge = GPIO_INT_HIGH_LEV; pr_debug("mxc: set GPIO %d to high trigger\n", gpio); } - port->both_edges |= 1 << (gpio & 31); + port->both_edges |= 1 << gpio_idx; break; case IRQ_TYPE_LEVEL_LOW: edge = GPIO_INT_LOW_LEV; @@ -180,11 +180,11 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) return -EINVAL; } - reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */ - bit = gpio & 0xf; + reg += GPIO_ICR1 + ((gpio_idx & 0x10) >> 2); /* ICR1 or ICR2 */ + bit = gpio_idx & 0xf; val = readl(reg) & ~(0x3 << (bit << 1)); writel(val | (edge << (bit << 1)), reg); - writel(1 << (gpio & 0x1f), port->base + GPIO_ISR); + writel(1 << gpio_idx, port->base + GPIO_ISR); return 0; } @@ -217,15 +217,13 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio) /* handle 32 interrupts in one status register */ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat) { - u32 gpio_irq_no_base = port->virtual_irq_start; - while (irq_stat != 0) { int irqoffset = fls(irq_stat) - 1; if (port->both_edges & (1 << irqoffset)) mxc_flip_edge(port, irqoffset); - generic_handle_irq(gpio_irq_no_base + irqoffset); + generic_handle_irq(irq_find_mapping(port->domain, irqoffset)); irq_stat &= ~(1 << irqoffset); } @@ -276,10 +274,9 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc) */ static int gpio_set_wake_irq(struct irq_data *d, u32 enable) { - u32 gpio = irq_to_gpio(d->irq); - u32 gpio_idx = gpio & 0x1F; struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct mxc_gpio_port *port = gc->private; + u32 gpio_idx = d->hwirq; if (enable) { if (port->irq_high && (gpio_idx >= 16)) @@ -296,12 +293,12 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable) return 0; } -static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port) +static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base) { struct irq_chip_generic *gc; struct irq_chip_type *ct; - gc = irq_alloc_generic_chip("gpio-mxc", 1, port->virtual_irq_start, + gc = irq_alloc_generic_chip("gpio-mxc", 1, irq_base, port->base, handle_level_irq); gc->private = port; @@ -352,7 +349,7 @@ static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset) struct mxc_gpio_port *port = container_of(bgc, struct mxc_gpio_port, bgc); - return port->virtual_irq_start + offset; + return irq_find_mapping(port->domain, offset); } static int __devinit mxc_gpio_probe(struct platform_device *pdev) @@ -360,6 +357,7 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct mxc_gpio_port *port; struct resource *iores; + int irq_base; int err; mxc_gpio_get_hw(pdev); @@ -430,20 +428,30 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) if (err) goto out_bgpio_remove; - /* - * In dt case, we use gpio number range dynamically - * allocated by gpio core. - */ - port->virtual_irq_start = MXC_GPIO_IRQ_START + (np ? port->bgc.gc.base : - pdev->id * 32); + irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id()); + if (irq_base < 0) { + err = irq_base; + goto out_gpiochip_remove; + } + + port->domain = irq_domain_add_legacy(np, 32, irq_base, 0, + &irq_domain_simple_ops, NULL); + if (!port->domain) { + err = -ENODEV; + goto out_irqdesc_free; + } /* gpio-mxc can be a generic irq chip */ - mxc_gpio_init_gc(port); + mxc_gpio_init_gc(port, irq_base); list_add_tail(&port->node, &mxc_gpio_ports); return 0; +out_irqdesc_free: + irq_free_descs(irq_base, 32); +out_gpiochip_remove: + WARN_ON(gpiochip_remove(&port->bgc.gc) < 0); out_bgpio_remove: bgpio_remove(&port->bgc); out_iounmap: -- cgit v1.2.3 From f3eac29da1f6a477722b56ff00228e8a13f8f6c6 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 13 Jun 2012 10:20:58 +0800 Subject: ARM: imx: move irq_domain_add_legacy call into tzic driver Move irq_domain_add_legacy call from imx5*-dt.c into tzic init function and have the tzic driver adopt irqdomain support for both DT and non-DT boot. Now tzic init function calls irq_alloc_descs to get irq_base and adds a lenacy irqdomain with the irq_base, so that the mapping between tzic irq and Linux irq number can be handled by irqdomain. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Acked-by: Dong Aisheng --- arch/arm/mach-imx/imx51-dt.c | 15 --------------- arch/arm/mach-imx/imx53-dt.c | 15 --------------- arch/arm/plat-mxc/tzic.c | 28 ++++++++++++++++++++-------- 3 files changed, 20 insertions(+), 38 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c index 3bdabbc64f43..d4067fe36357 100644 --- a/arch/arm/mach-imx/imx51-dt.c +++ b/arch/arm/mach-imx/imx51-dt.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include @@ -45,18 +44,6 @@ static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = { { /* sentinel */ } }; -static int __init imx51_tzic_add_irq_domain(struct device_node *np, - struct device_node *interrupt_parent) -{ - irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL); - return 0; -} - -static const struct of_device_id imx51_irq_match[] __initconst = { - { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, }, - { /* sentinel */ } -}; - static const struct of_device_id imx51_iomuxc_of_match[] __initconst = { { .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, }, { /* sentinel */ } @@ -68,8 +55,6 @@ static void __init imx51_dt_init(void) const struct of_device_id *of_id; void (*func)(void); - of_irq_init(imx51_irq_match); - pinctrl_provide_dummies(); node = of_find_matching_node(NULL, imx51_iomuxc_of_match); diff --git a/arch/arm/mach-imx/imx53-dt.c b/arch/arm/mach-imx/imx53-dt.c index 17fca3cac268..fdd90805d98e 100644 --- a/arch/arm/mach-imx/imx53-dt.c +++ b/arch/arm/mach-imx/imx53-dt.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -52,18 +51,6 @@ static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = { { /* sentinel */ } }; -static int __init imx53_tzic_add_irq_domain(struct device_node *np, - struct device_node *interrupt_parent) -{ - irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL); - return 0; -} - -static const struct of_device_id imx53_irq_match[] __initconst = { - { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, }, - { /* sentinel */ } -}; - static const struct of_device_id imx53_iomuxc_of_match[] __initconst = { { .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, }, { .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, }, @@ -91,8 +78,6 @@ static void __init imx53_dt_init(void) const struct of_device_id *of_id; void (*func)(void); - of_irq_init(imx53_irq_match); - pinctrl_provide_dummies(); node = of_find_matching_node(NULL, imx53_iomuxc_of_match); diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c index 98308ec1f321..abc90e4116f5 100644 --- a/arch/arm/plat-mxc/tzic.c +++ b/arch/arm/plat-mxc/tzic.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -49,6 +51,7 @@ #define TZIC_ID0 0x0FD0 /* Indentification Register 0 */ void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */ +static struct irq_domain *domain; #define TZIC_NUM_IRQS 128 @@ -77,15 +80,14 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type) static void tzic_irq_suspend(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - int idx = gc->irq_base >> 5; + int idx = d->hwirq >> 5; __raw_writel(gc->wake_active, tzic_base + TZIC_WAKEUP0(idx)); } static void tzic_irq_resume(struct irq_data *d) { - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - int idx = gc->irq_base >> 5; + int idx = d->hwirq >> 5; __raw_writel(__raw_readl(tzic_base + TZIC_ENSET0(idx)), tzic_base + TZIC_WAKEUP0(idx)); @@ -102,11 +104,10 @@ static struct mxc_extra_irq tzic_extra_irq = { #endif }; -static __init void tzic_init_gc(unsigned int irq_start) +static __init void tzic_init_gc(int idx, unsigned int irq_start) { struct irq_chip_generic *gc; struct irq_chip_type *ct; - int idx = irq_start >> 5; gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base, handle_level_irq); @@ -140,7 +141,8 @@ asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs) while (stat) { handled = 1; irqofs = fls(stat) - 1; - handle_IRQ(irqofs + i * 32, regs); + handle_IRQ(irq_find_mapping(domain, + irqofs + i * 32), regs); stat &= ~(1 << irqofs); } } @@ -154,6 +156,8 @@ asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs) */ void __init tzic_init_irq(void __iomem *irqbase) { + struct device_node *np; + int irq_base; int i; tzic_base = irqbase; @@ -175,8 +179,16 @@ void __init tzic_init_irq(void __iomem *irqbase) /* all IRQ no FIQ Warning :: No selection */ - for (i = 0; i < TZIC_NUM_IRQS; i += 32) - tzic_init_gc(i); + irq_base = irq_alloc_descs(-1, 0, TZIC_NUM_IRQS, numa_node_id()); + WARN_ON(irq_base < 0); + + np = of_find_compatible_node(NULL, NULL, "fsl,tzic"); + domain = irq_domain_add_legacy(np, TZIC_NUM_IRQS, irq_base, 0, + &irq_domain_simple_ops, NULL); + WARN_ON(!domain); + + for (i = 0; i < 4; i++, irq_base += 32) + tzic_init_gc(i, irq_base); #ifdef CONFIG_FIQ /* Initialize FIQ */ -- cgit v1.2.3 From 544496ab5cbdae312351da4c742ae70cab08dbf2 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 13 Jun 2012 10:55:46 +0800 Subject: ARM: imx: move irq_domain_add_legacy call into avic driver Move irq_domain_add_legacy call from imx27-dt.c into avic init function and have the avic driver adopt irqdomain support for both DT and non-DT boot. Now avic init function calls irq_alloc_descs to get irq_base and adds a lenacy irqdomain with the irq_base, so that the mapping between avic irq and Linux irq number can be handled by irqdomain. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Acked-by: Dong Aisheng --- arch/arm/mach-imx/imx27-dt.c | 15 --------------- arch/arm/plat-mxc/avic.c | 32 +++++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c index c734e564f204..5142ef048a60 100644 --- a/arch/arm/mach-imx/imx27-dt.c +++ b/arch/arm/mach-imx/imx27-dt.c @@ -10,7 +10,6 @@ */ #include -#include #include #include #include @@ -33,22 +32,8 @@ static const struct of_dev_auxdata imx27_auxdata_lookup[] __initconst = { { /* sentinel */ } }; -static int __init imx27_avic_add_irq_domain(struct device_node *np, - struct device_node *interrupt_parent) -{ - irq_domain_add_legacy(np, 64, 0, 0, &irq_domain_simple_ops, NULL); - return 0; -} - -static const struct of_device_id imx27_irq_match[] __initconst = { - { .compatible = "fsl,imx27-avic", .data = imx27_avic_add_irq_domain, }, - { /* sentinel */ } -}; - static void __init imx27_dt_init(void) { - of_irq_init(imx27_irq_match); - of_platform_populate(NULL, of_default_bus_match_table, imx27_auxdata_lookup, NULL); } diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c index 689f81f9593b..e612cc1edede 100644 --- a/arch/arm/plat-mxc/avic.c +++ b/arch/arm/plat-mxc/avic.c @@ -19,7 +19,9 @@ #include #include +#include #include +#include #include #include #include @@ -50,15 +52,19 @@ #define AVIC_NUM_IRQS 64 void __iomem *avic_base; +static struct irq_domain *domain; static u32 avic_saved_mask_reg[2]; #ifdef CONFIG_MXC_IRQ_PRIOR static int avic_irq_set_priority(unsigned char irq, unsigned char prio) { + struct irq_data *d = irq_get_irq_data(irq); unsigned int temp; unsigned int mask = 0x0F << irq % 8 * 4; + irq = d->hwirq; + if (irq >= AVIC_NUM_IRQS) return -EINVAL; @@ -75,8 +81,11 @@ static int avic_irq_set_priority(unsigned char irq, unsigned char prio) #ifdef CONFIG_FIQ static int avic_set_irq_fiq(unsigned int irq, unsigned int type) { + struct irq_data *d = irq_get_irq_data(irq); unsigned int irqt; + irq = d->hwirq; + if (irq >= AVIC_NUM_IRQS) return -EINVAL; @@ -108,7 +117,7 @@ static void avic_irq_suspend(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct irq_chip_type *ct = gc->chip_types; - int idx = gc->irq_base >> 5; + int idx = d->hwirq >> 5; avic_saved_mask_reg[idx] = __raw_readl(avic_base + ct->regs.mask); __raw_writel(gc->wake_active, avic_base + ct->regs.mask); @@ -118,7 +127,7 @@ static void avic_irq_resume(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct irq_chip_type *ct = gc->chip_types; - int idx = gc->irq_base >> 5; + int idx = d->hwirq >> 5; __raw_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask); } @@ -128,11 +137,10 @@ static void avic_irq_resume(struct irq_data *d) #define avic_irq_resume NULL #endif -static __init void avic_init_gc(unsigned int irq_start) +static __init void avic_init_gc(int idx, unsigned int irq_start) { struct irq_chip_generic *gc; struct irq_chip_type *ct; - int idx = irq_start >> 5; gc = irq_alloc_generic_chip("mxc-avic", 1, irq_start, avic_base, handle_level_irq); @@ -161,7 +169,7 @@ asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs) if (nivector == 0xffff) break; - handle_IRQ(nivector, regs); + handle_IRQ(irq_find_mapping(domain, nivector), regs); } while (1); } @@ -172,6 +180,8 @@ asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs) */ void __init mxc_init_irq(void __iomem *irqbase) { + struct device_node *np; + int irq_base; int i; avic_base = irqbase; @@ -190,8 +200,16 @@ void __init mxc_init_irq(void __iomem *irqbase) __raw_writel(0, avic_base + AVIC_INTTYPEH); __raw_writel(0, avic_base + AVIC_INTTYPEL); - for (i = 0; i < AVIC_NUM_IRQS; i += 32) - avic_init_gc(i); + irq_base = irq_alloc_descs(-1, 0, AVIC_NUM_IRQS, numa_node_id()); + WARN_ON(irq_base < 0); + + np = of_find_compatible_node(NULL, NULL, "fsl,avic"); + domain = irq_domain_add_legacy(np, AVIC_NUM_IRQS, irq_base, 0, + &irq_domain_simple_ops, NULL); + WARN_ON(!domain); + + for (i = 0; i < AVIC_NUM_IRQS / 32; i++, irq_base += 32) + avic_init_gc(i, irq_base); /* Set default priority value (0) for all IRQ's */ for (i = 0; i < 8; i++) -- cgit v1.2.3 From 88289c80d419897c03f7f43b35e3730d8fb6825b Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 13 Jun 2012 14:07:31 +0800 Subject: dma: ipu: remove the use of ipu_platform_data The struct ipu_platform_data is used by platform code to pass MXC_IPU_IRQ_START to ipu-core driver. We can save it by having ipu-core driver call irq_alloc_descs to get the irq_base. Signed-off-by: Shawn Guo Acked-by: Vinod Koul Acked-by: Sascha Hauer Acked-by: Dong Aisheng --- arch/arm/mach-imx/devices-imx31.h | 4 ++-- arch/arm/mach-imx/devices-imx35.h | 4 ++-- arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c | 6 +----- arch/arm/mach-imx/mach-armadillo5x0.c | 6 +----- arch/arm/mach-imx/mach-mx31_3ds.c | 6 +----- arch/arm/mach-imx/mach-mx31moboard.c | 6 +----- arch/arm/mach-imx/mach-mx35_3ds.c | 10 +--------- arch/arm/mach-imx/mach-pcm037.c | 6 +----- arch/arm/mach-imx/mach-pcm043.c | 6 +----- arch/arm/mach-imx/mach-vpr200.c | 6 +----- arch/arm/mach-imx/mx31lilly-db.c | 6 +----- arch/arm/plat-mxc/devices/platform-ipu-core.c | 5 ++--- arch/arm/plat-mxc/include/mach/devices-common.h | 4 +--- arch/arm/plat-mxc/include/mach/ipu.h | 4 ---- drivers/dma/ipu/ipu_idmac.c | 8 +++----- drivers/dma/ipu/ipu_irq.c | 14 +++++++++----- 16 files changed, 28 insertions(+), 73 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/devices-imx31.h b/arch/arm/mach-imx/devices-imx31.h index 488e241a6db6..911c2dac2452 100644 --- a/arch/arm/mach-imx/devices-imx31.h +++ b/arch/arm/mach-imx/devices-imx31.h @@ -42,8 +42,8 @@ extern const struct imx_imx_uart_1irq_data imx31_imx_uart_data[]; #define imx31_add_imx_uart4(pdata) imx31_add_imx_uart(4, pdata) extern const struct imx_ipu_core_data imx31_ipu_core_data; -#define imx31_add_ipu_core(pdata) \ - imx_add_ipu_core(&imx31_ipu_core_data, pdata) +#define imx31_add_ipu_core() \ + imx_add_ipu_core(&imx31_ipu_core_data) #define imx31_alloc_mx3_camera(pdata) \ imx_alloc_mx3_camera(&imx31_ipu_core_data, pdata) #define imx31_add_mx3_sdc_fb(pdata) \ diff --git a/arch/arm/mach-imx/devices-imx35.h b/arch/arm/mach-imx/devices-imx35.h index 7b99ef0bb501..6fb907290f47 100644 --- a/arch/arm/mach-imx/devices-imx35.h +++ b/arch/arm/mach-imx/devices-imx35.h @@ -50,8 +50,8 @@ extern const struct imx_imx_uart_1irq_data imx35_imx_uart_data[]; #define imx35_add_imx_uart2(pdata) imx35_add_imx_uart(2, pdata) extern const struct imx_ipu_core_data imx35_ipu_core_data; -#define imx35_add_ipu_core(pdata) \ - imx_add_ipu_core(&imx35_ipu_core_data, pdata) +#define imx35_add_ipu_core() \ + imx_add_ipu_core(&imx35_ipu_core_data) #define imx35_alloc_mx3_camera(pdata) \ imx_alloc_mx3_camera(&imx35_ipu_core_data, pdata) #define imx35_add_mx3_sdc_fb(pdata) \ diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c index 557f6c486053..6e9dd12a6961 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c @@ -95,10 +95,6 @@ static const struct fb_videomode fb_modedb[] = { }, }; -static const struct ipu_platform_data mx3_ipu_data __initconst = { - .irq_base = MXC_IPU_IRQ_START, -}; - static struct mx3fb_platform_data mx3fb_pdata __initdata = { .name = "CMO-QVGA", .mode = fb_modedb, @@ -287,7 +283,7 @@ void __init eukrea_mbimxsd35_baseboard_init(void) printk(KERN_ERR "error setting mbimxsd pads !\n"); imx35_add_imx_uart1(&uart_pdata); - imx35_add_ipu_core(&mx3_ipu_data); + imx35_add_ipu_core(); imx35_add_mx3_sdc_fb(&mx3fb_pdata); imx35_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata); diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c index f83c5c683575..2c6ab3273f9e 100644 --- a/arch/arm/mach-imx/mach-armadillo5x0.c +++ b/arch/arm/mach-imx/mach-armadillo5x0.c @@ -367,10 +367,6 @@ static const struct fb_videomode fb_modedb[] = { }, }; -static const struct ipu_platform_data mx3_ipu_data __initconst = { - .irq_base = MXC_IPU_IRQ_START, -}; - static struct mx3fb_platform_data mx3fb_pdata __initdata = { .name = "CRT-VGA", .mode = fb_modedb, @@ -517,7 +513,7 @@ static void __init armadillo5x0_init(void) imx31_add_mxc_mmc(0, &sdhc_pdata); /* Register FB */ - imx31_add_ipu_core(&mx3_ipu_data); + imx31_add_ipu_core(); imx31_add_mx3_sdc_fb(&mx3fb_pdata); /* Register NOR Flash */ diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c index ecdba0497e7e..618935e1e325 100644 --- a/arch/arm/mach-imx/mach-mx31_3ds.c +++ b/arch/arm/mach-imx/mach-mx31_3ds.c @@ -274,10 +274,6 @@ static const struct fb_videomode fb_modedb[] = { }, }; -static struct ipu_platform_data mx3_ipu_data = { - .irq_base = MXC_IPU_IRQ_START, -}; - static struct mx3fb_platform_data mx3fb_pdata __initdata = { .name = "Epson-VGA", .mode = fb_modedb, @@ -743,7 +739,7 @@ static void __init mx31_3ds_init(void) imx31_add_mxc_mmc(0, &sdhc1_pdata); imx31_add_spi_imx0(&spi0_pdata); - imx31_add_ipu_core(&mx3_ipu_data); + imx31_add_ipu_core(); imx31_add_mx3_sdc_fb(&mx3fb_pdata); /* CSI */ diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c index f0d26db7719e..54d9e5d9fcec 100644 --- a/arch/arm/mach-imx/mach-mx31moboard.c +++ b/arch/arm/mach-imx/mach-mx31moboard.c @@ -473,10 +473,6 @@ static const struct gpio_led_platform_data mx31moboard_led_pdata __initconst = { .leds = mx31moboard_leds, }; -static const struct ipu_platform_data mx3_ipu_data __initconst = { - .irq_base = MXC_IPU_IRQ_START, -}; - static struct platform_device *devices[] __initdata = { &mx31moboard_flash, }; @@ -494,7 +490,7 @@ static int __init mx31moboard_init_cam(void) int dma, ret = -ENOMEM; struct platform_device *pdev; - imx31_add_ipu_core(&mx3_ipu_data); + imx31_add_ipu_core(); pdev = imx31_alloc_mx3_camera(&camera_pdata); if (IS_ERR(pdev)) diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c index fa1ea74dfdd3..ad63e6ebee6d 100644 --- a/arch/arm/mach-imx/mach-mx35_3ds.c +++ b/arch/arm/mach-imx/mach-mx35_3ds.c @@ -80,10 +80,6 @@ static const struct fb_videomode fb_modedb[] = { }, }; -static const struct ipu_platform_data mx3_ipu_data __initconst = { - .irq_base = MXC_IPU_IRQ_START, -}; - static struct mx3fb_platform_data mx3fb_pdata __initdata = { .name = "Ceramate-CLAA070VC01", .mode = fb_modedb, @@ -297,10 +293,6 @@ err: return ret; } -static const struct ipu_platform_data mx35_3ds_ipu_data __initconst = { - .irq_base = MXC_IPU_IRQ_START, -}; - static struct i2c_board_info mx35_3ds_i2c_camera = { I2C_BOARD_INFO("ov2640", 0x30), }; @@ -596,7 +588,7 @@ static void __init mx35_3ds_init(void) i2c_register_board_info( 0, i2c_devices_3ds, ARRAY_SIZE(i2c_devices_3ds)); - imx35_add_ipu_core(&mx35_3ds_ipu_data); + imx35_add_ipu_core(); platform_device_register(&mx35_3ds_ov2640); imx35_3ds_init_camera(); diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c index 551a035f0c2d..ded4ed9def9e 100644 --- a/arch/arm/mach-imx/mach-pcm037.c +++ b/arch/arm/mach-imx/mach-pcm037.c @@ -441,10 +441,6 @@ static struct platform_device *devices[] __initdata = { &pcm037_mt9v022, }; -static const struct ipu_platform_data mx3_ipu_data __initconst = { - .irq_base = MXC_IPU_IRQ_START, -}; - static const struct fb_videomode fb_modedb[] = { { /* 240x320 @ 60 Hz Sharp */ @@ -648,7 +644,7 @@ static void __init pcm037_init(void) imx31_add_mxc_nand(&pcm037_nand_board_info); imx31_add_mxc_mmc(0, &sdhc_pdata); - imx31_add_ipu_core(&mx3_ipu_data); + imx31_add_ipu_core(); imx31_add_mx3_sdc_fb(&mx3fb_pdata); /* CSI */ diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c index 73585f55cca0..133908f94f7e 100644 --- a/arch/arm/mach-imx/mach-pcm043.c +++ b/arch/arm/mach-imx/mach-pcm043.c @@ -76,10 +76,6 @@ static const struct fb_videomode fb_modedb[] = { }, }; -static const struct ipu_platform_data mx3_ipu_data __initconst = { - .irq_base = MXC_IPU_IRQ_START, -}; - static struct mx3fb_platform_data mx3fb_pdata __initdata = { .name = "Sharp-LQ035Q7", .mode = fb_modedb, @@ -376,7 +372,7 @@ static void __init pcm043_init(void) imx35_add_imx_i2c0(&pcm043_i2c0_data); - imx35_add_ipu_core(&mx3_ipu_data); + imx35_add_ipu_core(); imx35_add_mx3_sdc_fb(&mx3fb_pdata); if (otg_mode_host) { diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c index e36eb2c40f41..1aa562285960 100644 --- a/arch/arm/mach-imx/mach-vpr200.c +++ b/arch/arm/mach-imx/mach-vpr200.c @@ -87,10 +87,6 @@ static const struct fb_videomode fb_modedb[] = { } }; -static const struct ipu_platform_data mx3_ipu_data __initconst = { - .irq_base = MXC_IPU_IRQ_START, -}; - static struct mx3fb_platform_data mx3fb_pdata __initdata = { .name = "PT0708048", .mode = fb_modedb, @@ -290,7 +286,7 @@ static void __init vpr200_board_init(void) imx35_add_imx_uart0(NULL); imx35_add_imx_uart2(NULL); - imx35_add_ipu_core(&mx3_ipu_data); + imx35_add_ipu_core(); imx35_add_mx3_sdc_fb(&mx3fb_pdata); imx35_add_fsl_usb2_udc(&otg_device_pdata); diff --git a/arch/arm/mach-imx/mx31lilly-db.c b/arch/arm/mach-imx/mx31lilly-db.c index 2df625bdc71e..29e890f92055 100644 --- a/arch/arm/mach-imx/mx31lilly-db.c +++ b/arch/arm/mach-imx/mx31lilly-db.c @@ -162,10 +162,6 @@ static const struct imxmmc_platform_data mmc_pdata __initconst = { }; /* Framebuffer support */ -static const struct ipu_platform_data ipu_data __initconst = { - .irq_base = MXC_IPU_IRQ_START, -}; - static const struct fb_videomode fb_modedb = { /* 640x480 TFT panel (IPS-056T) */ .name = "CRT-VGA", @@ -199,7 +195,7 @@ static void __init mx31lilly_init_fb(void) return; } - imx31_add_ipu_core(&ipu_data); + imx31_add_ipu_core(); imx31_add_mx3_sdc_fb(&fb_pdata); gpio_direction_output(LCD_VCC_EN_GPIO, 1); } diff --git a/arch/arm/plat-mxc/devices/platform-ipu-core.c b/arch/arm/plat-mxc/devices/platform-ipu-core.c index 79d340ae0af1..d1e33cc6f12e 100644 --- a/arch/arm/plat-mxc/devices/platform-ipu-core.c +++ b/arch/arm/plat-mxc/devices/platform-ipu-core.c @@ -30,8 +30,7 @@ const struct imx_ipu_core_data imx35_ipu_core_data __initconst = static struct platform_device *imx_ipu_coredev __initdata; struct platform_device *__init imx_add_ipu_core( - const struct imx_ipu_core_data *data, - const struct ipu_platform_data *pdata) + const struct imx_ipu_core_data *data) { /* The resource order is important! */ struct resource res[] = { @@ -55,7 +54,7 @@ struct platform_device *__init imx_add_ipu_core( }; return imx_ipu_coredev = imx_add_platform_device("ipu-core", -1, - res, ARRAY_SIZE(res), pdata, sizeof(*pdata)); + res, ARRAY_SIZE(res), NULL, 0); } struct platform_device *__init imx_alloc_mx3_camera( diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h index 1b2258daa05b..a7f5bb1084d7 100644 --- a/arch/arm/plat-mxc/include/mach/devices-common.h +++ b/arch/arm/plat-mxc/include/mach/devices-common.h @@ -183,7 +183,6 @@ struct platform_device *__init imx_add_imx_udc( const struct imx_imx_udc_data *data, const struct imxusb_platform_data *pdata); -#include #include #include struct imx_ipu_core_data { @@ -192,8 +191,7 @@ struct imx_ipu_core_data { resource_size_t errirq; }; struct platform_device *__init imx_add_ipu_core( - const struct imx_ipu_core_data *data, - const struct ipu_platform_data *pdata); + const struct imx_ipu_core_data *data); struct platform_device *__init imx_alloc_mx3_camera( const struct imx_ipu_core_data *data, const struct mx3_camera_pdata *pdata); diff --git a/arch/arm/plat-mxc/include/mach/ipu.h b/arch/arm/plat-mxc/include/mach/ipu.h index a9221f1cc1a0..539e559d18b2 100644 --- a/arch/arm/plat-mxc/include/mach/ipu.h +++ b/arch/arm/plat-mxc/include/mach/ipu.h @@ -110,10 +110,6 @@ enum ipu_rotate_mode { IPU_ROTATE_90_LEFT = 7, }; -struct ipu_platform_data { - unsigned int irq_base; -}; - /* * Enumeration of DI ports for ADC. */ diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index 5ec72044ea4c..c7573e50aa14 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -1663,7 +1663,6 @@ static void __exit ipu_idmac_exit(struct ipu *ipu) static int __init ipu_probe(struct platform_device *pdev) { - struct ipu_platform_data *pdata = pdev->dev.platform_data; struct resource *mem_ipu, *mem_ic; int ret; @@ -1671,7 +1670,7 @@ static int __init ipu_probe(struct platform_device *pdev) mem_ipu = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem_ic = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!pdata || !mem_ipu || !mem_ic) + if (!mem_ipu || !mem_ic) return -EINVAL; ipu_data.dev = &pdev->dev; @@ -1688,10 +1687,9 @@ static int __init ipu_probe(struct platform_device *pdev) goto err_noirq; ipu_data.irq_err = ret; - ipu_data.irq_base = pdata->irq_base; - dev_dbg(&pdev->dev, "fn irq %u, err irq %u, irq-base %u\n", - ipu_data.irq_fn, ipu_data.irq_err, ipu_data.irq_base); + dev_dbg(&pdev->dev, "fn irq %u, err irq %u\n", + ipu_data.irq_fn, ipu_data.irq_err); /* Remap IPU common registers */ ipu_data.reg_ipu = ioremap(mem_ipu->start, resource_size(mem_ipu)); diff --git a/drivers/dma/ipu/ipu_irq.c b/drivers/dma/ipu/ipu_irq.c index a71f55e72be9..fa95bcc3de1f 100644 --- a/drivers/dma/ipu/ipu_irq.c +++ b/drivers/dma/ipu/ipu_irq.c @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -354,10 +355,12 @@ static struct irq_chip ipu_irq_chip = { /* Install the IRQ handler */ int __init ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev) { - struct ipu_platform_data *pdata = dev->dev.platform_data; - unsigned int irq, irq_base, i; + unsigned int irq, i; + int irq_base = irq_alloc_descs(-1, 0, CONFIG_MX3_IPU_IRQS, + numa_node_id()); - irq_base = pdata->irq_base; + if (irq_base < 0) + return irq_base; for (i = 0; i < IPU_IRQ_NR_BANKS; i++) irq_bank[i].ipu = ipu; @@ -387,15 +390,16 @@ int __init ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev) irq_set_handler_data(ipu->irq_err, ipu); irq_set_chained_handler(ipu->irq_err, ipu_irq_err); + ipu->irq_base = irq_base; + return 0; } void ipu_irq_detach_irq(struct ipu *ipu, struct platform_device *dev) { - struct ipu_platform_data *pdata = dev->dev.platform_data; unsigned int irq, irq_base; - irq_base = pdata->irq_base; + irq_base = ipu->irq_base; irq_set_chained_handler(ipu->irq_fn, NULL); irq_set_handler_data(ipu->irq_fn, NULL); -- cgit v1.2.3 From 1595f16c5e537cb33e118e7ae18dff139f22bdb1 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 13 Jun 2012 15:12:24 +0800 Subject: ARM: imx: leave irq_base of wm8350_platform_data uninitialized With commit d1738ae (mfd: Allocate wm835x irq descs dynamically) being in the tree, there is no need to initialize irq_base field of struct wm8350_platform_data. Remove it to save one reference to macro MXC_BOARD_IRQ_START. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Acked-by: Dong Aisheng --- arch/arm/mach-imx/mach-mx31ads.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c index 6f19f98ddbe9..a27a8543b9b5 100644 --- a/arch/arm/mach-imx/mach-mx31ads.c +++ b/arch/arm/mach-imx/mach-mx31ads.c @@ -479,7 +479,6 @@ static int mx31_wm8350_init(struct wm8350 *wm8350) static struct wm8350_platform_data __initdata mx31_wm8350_pdata = { .init = mx31_wm8350_init, - .irq_base = MXC_BOARD_IRQ_START + MXC_MAX_EXP_IO_LINES, }; #endif -- cgit v1.2.3 From ed4a7fb01a467f5d264fe12f17eb981f21c7bbcd Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 13 Jun 2012 15:58:08 +0800 Subject: ARM: imx: pass gpio than irq number into mxc_expio_init Change mxc_expio_init interface a little bit to have gpio than irq number passed in. With the change, gpio_to_irq can be called inside mxc_expio_init to get irq number, so that MXC_IRQ_TO_GPIO can be removed. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Acked-by: Dong Aisheng --- arch/arm/mach-imx/mach-mx27_3ds.c | 3 +-- arch/arm/mach-imx/mach-mx31_3ds.c | 3 +-- arch/arm/mach-imx/mach-mx35_3ds.c | 4 +--- arch/arm/mach-imx/mach-mx51_3ds.c | 3 +-- arch/arm/plat-mxc/3ds_debugboard.c | 8 ++++---- arch/arm/plat-mxc/include/mach/3ds_debugboard.h | 2 +- 6 files changed, 9 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c index 18b9bcaa40e3..eeff0b6aaba3 100644 --- a/arch/arm/mach-imx/mach-mx27_3ds.c +++ b/arch/arm/mach-imx/mach-mx27_3ds.c @@ -48,7 +48,6 @@ #define SD1_EN_GPIO IMX_GPIO_NR(2, 25) #define OTG_PHY_RESET_GPIO IMX_GPIO_NR(2, 23) #define SPI2_SS0 IMX_GPIO_NR(4, 21) -#define EXPIO_PARENT_INT gpio_to_irq(IMX_GPIO_NR(3, 28)) #define PMIC_INT IMX_GPIO_NR(3, 14) #define SPI1_SS0 IMX_GPIO_NR(4, 28) #define SD1_CD IMX_GPIO_NR(2, 26) @@ -500,7 +499,7 @@ static void __init mx27pdk_init(void) spi_register_board_info(mx27_3ds_spi_devs, ARRAY_SIZE(mx27_3ds_spi_devs)); - if (mxc_expio_init(MX27_CS5_BASE_ADDR, EXPIO_PARENT_INT)) + if (mxc_expio_init(MX27_CS5_BASE_ADDR, IMX_GPIO_NR(3, 28))) pr_warn("Init of the debugboard failed, all devices on the debugboard are unusable.\n"); imx27_add_imx_i2c(0, &mx27_3ds_i2c0_data); platform_add_devices(devices, ARRAY_SIZE(devices)); diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c index 618935e1e325..f37d9b5774ab 100644 --- a/arch/arm/mach-imx/mach-mx31_3ds.c +++ b/arch/arm/mach-imx/mach-mx31_3ds.c @@ -730,8 +730,7 @@ static void __init mx31_3ds_init(void) if (!otg_mode_host) imx31_add_fsl_usb2_udc(&usbotg_pdata); - if (mxc_expio_init(MX31_CS5_BASE_ADDR, - gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)))) + if (mxc_expio_init(MX31_CS5_BASE_ADDR, IOMUX_TO_GPIO(MX31_PIN_GPIO1_1))) printk(KERN_WARNING "Init of the debug board failed, all " "devices on the debug board are unusable.\n"); imx31_add_imx2_wdt(NULL); diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c index ad63e6ebee6d..596f237c0d0e 100644 --- a/arch/arm/mach-imx/mach-mx35_3ds.c +++ b/arch/arm/mach-imx/mach-mx35_3ds.c @@ -132,8 +132,6 @@ static struct platform_device mx35_3ds_lcd = { .dev.platform_data = &mx35_3ds_lcd_data, }; -#define EXPIO_PARENT_INT gpio_to_irq(IMX_GPIO_NR(1, 1)) - static const struct imxuart_platform_data uart_pdata __initconst = { .flags = IMXUART_HAVE_RTSCTS, }; @@ -580,7 +578,7 @@ static void __init mx35_3ds_init(void) imx35_add_mxc_nand(&mx35pdk_nand_board_info); imx35_add_sdhci_esdhc_imx(0, NULL); - if (mxc_expio_init(MX35_CS5_BASE_ADDR, EXPIO_PARENT_INT)) + if (mxc_expio_init(MX35_CS5_BASE_ADDR, IMX_GPIO_NR(1, 1))) pr_warn("Init of the debugboard failed, all " "devices on the debugboard are unusable.\n"); imx35_add_imx_i2c0(&mx35_3ds_i2c0_data); diff --git a/arch/arm/mach-imx/mach-mx51_3ds.c b/arch/arm/mach-imx/mach-mx51_3ds.c index 3c5b163923f6..ebb91882ae63 100644 --- a/arch/arm/mach-imx/mach-mx51_3ds.c +++ b/arch/arm/mach-imx/mach-mx51_3ds.c @@ -26,7 +26,6 @@ #include "devices-imx51.h" -#define EXPIO_PARENT_INT gpio_to_irq(IMX_GPIO_NR(1, 6)) #define MX51_3DS_ECSPI2_CS (GPIO_PORTC + 28) static iomux_v3_cfg_t mx51_3ds_pads[] = { @@ -148,7 +147,7 @@ static void __init mx51_3ds_init(void) spi_register_board_info(mx51_3ds_spi_nor_device, ARRAY_SIZE(mx51_3ds_spi_nor_device)); - if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT)) + if (mxc_expio_init(MX51_CS5_BASE_ADDR, IMX_GPIO_NR(1, 6))) printk(KERN_WARNING "Init of the debugboard failed, all " "devices on the board are unusable.\n"); diff --git a/arch/arm/plat-mxc/3ds_debugboard.c b/arch/arm/plat-mxc/3ds_debugboard.c index 5cac2c540f4f..3b48a08c165a 100644 --- a/arch/arm/plat-mxc/3ds_debugboard.c +++ b/arch/arm/plat-mxc/3ds_debugboard.c @@ -49,7 +49,6 @@ #define MCU_BOARD_ID_REG 0x68 #define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_BOARD_IRQ_START) -#define MXC_IRQ_TO_GPIO(irq) ((irq) - MXC_INTERNAL_IRQS) #define MXC_EXP_IO_BASE (MXC_BOARD_IRQ_START) #define MXC_MAX_EXP_IO_LINES 16 @@ -155,8 +154,9 @@ static struct regulator_consumer_supply dummy_supplies[] = { REGULATOR_SUPPLY("vddvario", "smsc911x"), }; -int __init mxc_expio_init(u32 base, u32 p_irq) +int __init mxc_expio_init(u32 base, u32 intr_gpio) { + u32 p_irq = gpio_to_irq(intr_gpio); int i; brd_io = ioremap(BOARD_IO_ADDR(base), SZ_4K); @@ -178,8 +178,8 @@ int __init mxc_expio_init(u32 base, u32 p_irq) /* * Configure INT line as GPIO input */ - gpio_request(MXC_IRQ_TO_GPIO(p_irq), "expio_pirq"); - gpio_direction_input(MXC_IRQ_TO_GPIO(p_irq)); + gpio_request(intr_gpio, "expio_pirq"); + gpio_direction_input(intr_gpio); /* disable the interrupt and clear the status */ __raw_writew(0, brd_io + INTR_MASK_REG); diff --git a/arch/arm/plat-mxc/include/mach/3ds_debugboard.h b/arch/arm/plat-mxc/include/mach/3ds_debugboard.h index a384fdd49c62..9fd6cb3f8fad 100644 --- a/arch/arm/plat-mxc/include/mach/3ds_debugboard.h +++ b/arch/arm/plat-mxc/include/mach/3ds_debugboard.h @@ -13,6 +13,6 @@ #ifndef __ASM_ARCH_MXC_3DS_DB_H__ #define __ASM_ARCH_MXC_3DS_DB_H__ -extern int __init mxc_expio_init(u32 base, u32 p_irq); +extern int __init mxc_expio_init(u32 base, u32 intr_gpio); #endif /* __ASM_ARCH_MXC_3DS_DB_H__ */ -- cgit v1.2.3 From ec7828807b14aab647a43c5b4ee2084de273c172 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 13 Jun 2012 16:37:04 +0800 Subject: ARM: imx: add a legacy irqdomain for 3ds_debugboard Call irq_alloc_descs to get the irq_base for 3ds_debugboard, and add a legacy irqdomain using the irq_base, so that the mapping between 3ds_debugboard hardware irq and Linux irq number can be dynamically handled by irqdomain. As the result, the use of MXC_BOARD_IRQ_START can be completely removed from 3ds_debugboard.c. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Acked-by: Dong Aisheng --- arch/arm/plat-mxc/3ds_debugboard.c | 42 +++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-mxc/3ds_debugboard.c b/arch/arm/plat-mxc/3ds_debugboard.c index 3b48a08c165a..5c10ad05df74 100644 --- a/arch/arm/plat-mxc/3ds_debugboard.c +++ b/arch/arm/plat-mxc/3ds_debugboard.c @@ -12,9 +12,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -48,26 +50,22 @@ /* CPU ID and Personality ID */ #define MCU_BOARD_ID_REG 0x68 -#define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_BOARD_IRQ_START) - -#define MXC_EXP_IO_BASE (MXC_BOARD_IRQ_START) #define MXC_MAX_EXP_IO_LINES 16 /* interrupts like external uart , external ethernet etc*/ -#define EXPIO_INT_ENET (MXC_BOARD_IRQ_START + 0) -#define EXPIO_INT_XUART_A (MXC_BOARD_IRQ_START + 1) -#define EXPIO_INT_XUART_B (MXC_BOARD_IRQ_START + 2) -#define EXPIO_INT_BUTTON_A (MXC_BOARD_IRQ_START + 3) -#define EXPIO_INT_BUTTON_B (MXC_BOARD_IRQ_START + 4) +#define EXPIO_INT_ENET 0 +#define EXPIO_INT_XUART_A 1 +#define EXPIO_INT_XUART_B 2 +#define EXPIO_INT_BUTTON_A 3 +#define EXPIO_INT_BUTTON_B 4 static void __iomem *brd_io; +static struct irq_domain *domain; static struct resource smsc911x_resources[] = { { .flags = IORESOURCE_MEM, } , { - .start = EXPIO_INT_ENET, - .end = EXPIO_INT_ENET, .flags = IORESOURCE_IRQ, }, }; @@ -99,11 +97,11 @@ static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc) imr_val = __raw_readw(brd_io + INTR_MASK_REG); int_valid = __raw_readw(brd_io + INTR_STATUS_REG) & ~imr_val; - expio_irq = MXC_BOARD_IRQ_START; + expio_irq = 0; for (; int_valid != 0; int_valid >>= 1, expio_irq++) { if ((int_valid & 1) == 0) continue; - generic_handle_irq(expio_irq); + generic_handle_irq(irq_find_mapping(domain, expio_irq)); } desc->irq_data.chip->irq_ack(&desc->irq_data); @@ -117,7 +115,7 @@ static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc) static void expio_mask_irq(struct irq_data *d) { u16 reg; - u32 expio = MXC_IRQ_TO_EXPIO(d->irq); + u32 expio = d->hwirq; reg = __raw_readw(brd_io + INTR_MASK_REG); reg |= (1 << expio); @@ -126,7 +124,7 @@ static void expio_mask_irq(struct irq_data *d) static void expio_ack_irq(struct irq_data *d) { - u32 expio = MXC_IRQ_TO_EXPIO(d->irq); + u32 expio = d->hwirq; __raw_writew(1 << expio, brd_io + INTR_RESET_REG); __raw_writew(0, brd_io + INTR_RESET_REG); @@ -136,7 +134,7 @@ static void expio_ack_irq(struct irq_data *d) static void expio_unmask_irq(struct irq_data *d) { u16 reg; - u32 expio = MXC_IRQ_TO_EXPIO(d->irq); + u32 expio = d->hwirq; reg = __raw_readw(brd_io + INTR_MASK_REG); reg &= ~(1 << expio); @@ -157,6 +155,7 @@ static struct regulator_consumer_supply dummy_supplies[] = { int __init mxc_expio_init(u32 base, u32 intr_gpio) { u32 p_irq = gpio_to_irq(intr_gpio); + int irq_base; int i; brd_io = ioremap(BOARD_IO_ADDR(base), SZ_4K); @@ -186,8 +185,15 @@ int __init mxc_expio_init(u32 base, u32 intr_gpio) __raw_writew(0xFFFF, brd_io + INTR_RESET_REG); __raw_writew(0, brd_io + INTR_RESET_REG); __raw_writew(0x1F, brd_io + INTR_MASK_REG); - for (i = MXC_EXP_IO_BASE; - i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES); i++) { + + irq_base = irq_alloc_descs(-1, 0, MXC_MAX_EXP_IO_LINES, numa_node_id()); + WARN_ON(irq_base < 0); + + domain = irq_domain_add_legacy(NULL, MXC_MAX_EXP_IO_LINES, irq_base, 0, + &irq_domain_simple_ops, NULL); + WARN_ON(!domain); + + for (i = irq_base; i < irq_base + MXC_MAX_EXP_IO_LINES; i++) { irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq); set_irq_flags(i, IRQF_VALID); } @@ -199,6 +205,8 @@ int __init mxc_expio_init(u32 base, u32 intr_gpio) smsc911x_resources[0].start = LAN9217_BASE_ADDR(base); smsc911x_resources[0].end = LAN9217_BASE_ADDR(base) + 0x100 - 1; + smsc911x_resources[1].start = irq_find_mapping(domain, EXPIO_INT_ENET); + smsc911x_resources[1].end = irq_find_mapping(domain, EXPIO_INT_ENET); platform_device_register(&smsc_lan9217_device); return 0; -- cgit v1.2.3 From 130d8bd7b67ddfcac52437821cf84a1087b19d4e Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 13 Jun 2012 17:07:25 +0800 Subject: ARM: imx: add a legacy irqdomain for mx31ads Call irq_alloc_descs to get the irq_base for mx31ads, and add a legacy irqdomain using the irq_base, so that the mapping between mx31ads hardware irq and Linux irq number can be dynamically handled by irqdomain. As the result, the use of MXC_BOARD_IRQ_START can be completely removed from mach-mx31ads.c. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Acked-by: Dong Aisheng --- arch/arm/mach-imx/mach-mx31ads.c | 48 ++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c index a27a8543b9b5..d37f4809c556 100644 --- a/arch/arm/mach-imx/mach-mx31ads.c +++ b/arch/arm/mach-imx/mach-mx31ads.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -63,18 +64,17 @@ #define PBC_INTMASK_SET_REG (PBC_INTMASK_SET + PBC_BASE_ADDRESS) #define PBC_INTMASK_CLEAR_REG (PBC_INTMASK_CLEAR + PBC_BASE_ADDRESS) -#define MXC_EXP_IO_BASE MXC_BOARD_IRQ_START -#define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_EXP_IO_BASE) - -#define EXPIO_INT_XUART_INTA (MXC_EXP_IO_BASE + 10) -#define EXPIO_INT_XUART_INTB (MXC_EXP_IO_BASE + 11) +#define EXPIO_INT_XUART_INTA 10 +#define EXPIO_INT_XUART_INTB 11 #define MXC_MAX_EXP_IO_LINES 16 /* CS8900 */ -#define EXPIO_INT_ENET_INT (MXC_EXP_IO_BASE + 8) +#define EXPIO_INT_ENET_INT 8 #define CS4_CS8900_MMIO_START 0x20000 +static struct irq_domain *domain; + /* * The serial port definition structure. */ @@ -82,7 +82,6 @@ static struct plat_serial8250_port serial_platform_data[] = { { .membase = (void *)(PBC_BASE_ADDRESS + PBC_SC16C652_UARTA), .mapbase = (unsigned long)(MX31_CS4_BASE_ADDR + PBC_SC16C652_UARTA), - .irq = EXPIO_INT_XUART_INTA, .uartclk = 14745600, .regshift = 0, .iotype = UPIO_MEM, @@ -90,7 +89,6 @@ static struct plat_serial8250_port serial_platform_data[] = { }, { .membase = (void *)(PBC_BASE_ADDRESS + PBC_SC16C652_UARTB), .mapbase = (unsigned long)(MX31_CS4_BASE_ADDR + PBC_SC16C652_UARTB), - .irq = EXPIO_INT_XUART_INTB, .uartclk = 14745600, .regshift = 0, .iotype = UPIO_MEM, @@ -107,9 +105,9 @@ static struct platform_device serial_device = { }, }; -static const struct resource mx31ads_cs8900_resources[] __initconst = { +static struct resource mx31ads_cs8900_resources[] __initdata = { DEFINE_RES_MEM(MX31_CS4_BASE_ADDR + CS4_CS8900_MMIO_START, SZ_64K), - DEFINE_RES_IRQ(EXPIO_INT_ENET_INT), + DEFINE_RES_IRQ(-1), }; static const struct platform_device_info mx31ads_cs8900_devinfo __initconst = { @@ -121,11 +119,19 @@ static const struct platform_device_info mx31ads_cs8900_devinfo __initconst = { static int __init mxc_init_extuart(void) { + serial_platform_data[0].irq = irq_find_mapping(domain, + EXPIO_INT_XUART_INTA); + serial_platform_data[1].irq = irq_find_mapping(domain, + EXPIO_INT_XUART_INTB); return platform_device_register(&serial_device); } static void __init mxc_init_ext_ethernet(void) { + mx31ads_cs8900_resources[1].start = + irq_find_mapping(domain, EXPIO_INT_ENET_INT); + mx31ads_cs8900_resources[1].end = + irq_find_mapping(domain, EXPIO_INT_ENET_INT); platform_device_register_full( (struct platform_device_info *)&mx31ads_cs8900_devinfo); } @@ -156,12 +162,12 @@ static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc) imr_val = __raw_readw(PBC_INTMASK_SET_REG); int_valid = __raw_readw(PBC_INTSTATUS_REG) & imr_val; - expio_irq = MXC_EXP_IO_BASE; + expio_irq = 0; for (; int_valid != 0; int_valid >>= 1, expio_irq++) { if ((int_valid & 1) == 0) continue; - generic_handle_irq(expio_irq); + generic_handle_irq(irq_find_mapping(domain, expio_irq)); } } @@ -171,7 +177,7 @@ static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc) */ static void expio_mask_irq(struct irq_data *d) { - u32 expio = MXC_IRQ_TO_EXPIO(d->irq); + u32 expio = d->hwirq; /* mask the interrupt */ __raw_writew(1 << expio, PBC_INTMASK_CLEAR_REG); __raw_readw(PBC_INTMASK_CLEAR_REG); @@ -183,7 +189,7 @@ static void expio_mask_irq(struct irq_data *d) */ static void expio_ack_irq(struct irq_data *d) { - u32 expio = MXC_IRQ_TO_EXPIO(d->irq); + u32 expio = d->hwirq; /* clear the interrupt status */ __raw_writew(1 << expio, PBC_INTSTATUS_REG); } @@ -194,7 +200,7 @@ static void expio_ack_irq(struct irq_data *d) */ static void expio_unmask_irq(struct irq_data *d) { - u32 expio = MXC_IRQ_TO_EXPIO(d->irq); + u32 expio = d->hwirq; /* unmask the interrupt */ __raw_writew(1 << expio, PBC_INTMASK_SET_REG); } @@ -208,6 +214,7 @@ static struct irq_chip expio_irq_chip = { static void __init mx31ads_init_expio(void) { + int irq_base; int i, irq; printk(KERN_INFO "MX31ADS EXPIO(CPLD) hardware\n"); @@ -220,8 +227,15 @@ static void __init mx31ads_init_expio(void) /* disable the interrupt and clear the status */ __raw_writew(0xFFFF, PBC_INTMASK_CLEAR_REG); __raw_writew(0xFFFF, PBC_INTSTATUS_REG); - for (i = MXC_EXP_IO_BASE; i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES); - i++) { + + irq_base = irq_alloc_descs(-1, 0, MXC_MAX_EXP_IO_LINES, numa_node_id()); + WARN_ON(irq_base < 0); + + domain = irq_domain_add_legacy(NULL, MXC_MAX_EXP_IO_LINES, irq_base, 0, + &irq_domain_simple_ops, NULL); + WARN_ON(!domain); + + for (i = irq_base; i < irq_base + MXC_MAX_EXP_IO_LINES; i++) { irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq); set_irq_flags(i, IRQF_VALID); } -- cgit v1.2.3 From 69fcbc74bb7a8b3c86e15f27b74ee512633ffcc6 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 14 Jun 2012 11:26:46 +0800 Subject: ARM: imx: remove unneeded mach/irq.h inclusion Remove unneeded mach/irq.h inclusion from imx platform code. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Acked-by: Dong Aisheng --- arch/arm/mach-imx/mach-apf9328.c | 1 - arch/arm/mach-imx/mach-mx1ads.c | 1 - arch/arm/mach-imx/mach-mx27_3ds.c | 1 - arch/arm/mach-imx/mach-mx31lite.c | 1 - arch/arm/mach-imx/mach-mx35_3ds.c | 1 - arch/arm/mach-imx/mach-pca100.c | 1 - arch/arm/mach-imx/mach-qong.c | 1 - arch/arm/mach-imx/mach-scb9328.c | 1 - arch/arm/mach-imx/mach-vpr200.c | 1 - arch/arm/mach-imx/mm-imx1.c | 1 - arch/arm/mach-imx/mm-imx21.c | 1 - arch/arm/mach-imx/mm-imx25.c | 1 - arch/arm/mach-imx/mm-imx27.c | 1 - arch/arm/mach-imx/mm-imx3.c | 1 - 14 files changed, 14 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-apf9328.c b/arch/arm/mach-imx/mach-apf9328.c index 5062fcb88498..7b99a79722b6 100644 --- a/arch/arm/mach-imx/mach-apf9328.c +++ b/arch/arm/mach-imx/mach-apf9328.c @@ -27,7 +27,6 @@ #include #include -#include #include #include "devices-imx1.h" diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c index 7274e7928136..667f359a2e8b 100644 --- a/arch/arm/mach-imx/mach-mx1ads.c +++ b/arch/arm/mach-imx/mach-mx1ads.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "devices-imx1.h" diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c index eeff0b6aaba3..71f7c58ee4b6 100644 --- a/arch/arm/mach-imx/mach-mx27_3ds.c +++ b/arch/arm/mach-imx/mach-mx27_3ds.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include "devices-imx27.h" diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c index 4977378d2f60..c8785b39eaed 100644 --- a/arch/arm/mach-imx/mach-mx31lite.c +++ b/arch/arm/mach-imx/mach-mx31lite.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include "devices-imx31.h" diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c index 596f237c0d0e..e78525405c98 100644 --- a/arch/arm/mach-imx/mach-mx35_3ds.c +++ b/arch/arm/mach-imx/mach-mx35_3ds.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include