From a71558d0eca1bbb23737f832297926666f9b36db Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 27 Jan 2009 22:32:29 +0000 Subject: [PATCH 01/16] [ARM] etherh: continue fixing build failure Further to 483a2b3a3182abcb7fcea986d7ea13e793bb00b1, also fix: drivers/net/arm/etherh.c:649: error: 'eth_set_mac_addr' undeclared here (not in a function) Signed-off-by: Russell King --- drivers/net/arm/etherh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index d15d8b79d8e53..54b52e5b1821b 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -646,7 +646,7 @@ static const struct net_device_ops etherh_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_set_mac_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, From 9ce8bb55e32d11bb82e19e76bdd2cf1c2ed32fd1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 27 Jan 2009 22:44:12 +0000 Subject: [PATCH 02/16] [ARM] msm: fix build errors arch/arm/mach-msm/board-halibut.c:45: error: implicit declaration of function 'MSM_GPIO_TO_INT' arch/arm/mach-msm/board-halibut.c:45: error: initializer element is not constant arch/arm/mach-msm/board-halibut.c:45: error: (near initialization for 'smc91x_resources[1].start') arch/arm/mach-msm/board-halibut.c:46: error: initializer element is not constant arch/arm/mach-msm/board-halibut.c:46: error: (near initialization for 'smc91x_resources[1].end') Signed-off-by: Russell King --- arch/arm/mach-msm/board-halibut.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c index c2a96e3965a6c..e61967dde9a1f 100644 --- a/arch/arm/mach-msm/board-halibut.c +++ b/arch/arm/mach-msm/board-halibut.c @@ -27,6 +27,7 @@ #include #include +#include #include #include From ecbab71c521819716e204659dfe72fc39d00630a Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 27 Jan 2009 23:20:00 +0000 Subject: [PATCH 03/16] [ARM] call undefined instruction exception handler with irqs enabled Aaro says: > With spinlock debugs enabled I get might_sleep() warnings when using > ptrace. tracked down to a missing enable_irq before calling do_undefinstr(). Reported-by: Aaro Koskinen Tested-by: Aaro Koskinen Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 77b047475539b..85040cfeb5e51 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -650,6 +650,7 @@ ENTRY(fp_enter) no_fp: mov pc, lr __und_usr_unknown: + enable_irq mov r0, sp adr lr, ret_from_exception b do_undefinstr From 08e445bd6a98fa09befe0cf6d67705324f913fc6 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 16 Jan 2009 23:02:54 +0100 Subject: [PATCH 04/16] [ARM] 5366/1: fix shared memory coherency with VIVT L1 + L2 caches When there are multiple L1-aliasing userland mappings of the same physical page, we currently remap each of them uncached, to prevent VIVT cache aliasing issues. (E.g. writes to one of the mappings not being immediately visible via another mapping.) However, when we do this remapping, there could still be stale data in the L2 cache, and an uncached mapping might bypass L2 and go straight to RAM. This would cause reads from such mappings to see old data (until the dirty L2 line is eventually evicted.) This issue is solved by forcing a L2 cache flush whenever the shared page is made L1 uncacheable. Ideally, we would make L1 uncacheable and L2 cacheable as L2 is PIPT. But Feroceon does not support that combination, and the TEX=5 C=0 B=0 encoding for XSc3 doesn't appear to work in practice. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mm/fault-armv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 81d0b8772de33..bc0099d5ae85c 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -66,7 +66,10 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address) * fault (ie, is old), we can safely ignore any issues. */ if (ret && (pte_val(entry) & L_PTE_MT_MASK) != shared_pte_mask) { - flush_cache_page(vma, address, pte_pfn(entry)); + unsigned long pfn = pte_pfn(entry); + flush_cache_page(vma, address, pfn); + outer_flush_range((pfn << PAGE_SHIFT), + (pfn << PAGE_SHIFT) + PAGE_SIZE); pte_val(entry) &= ~L_PTE_MT_MASK; pte_val(entry) |= shared_pte_mask; set_pte_at(vma->vm_mm, address, pte, entry); From 06151158f2da4764479b4ec01688dc4bade6ce9d Mon Sep 17 00:00:00 2001 From: "Stanley.Miao" Date: Thu, 29 Jan 2009 08:57:12 -0800 Subject: [PATCH 05/16] ARM: OMAP: Fix McBSP spin_lock deadlock A spin_lock deadlock will occur when omap_mcbsp_request() is invoked. omap_mcbsp_request() \- clk_enable(mcbsp->clk) [takes and holds clockfw_lock] \- omap2_clk_enable() \- _omap2_clk_enable() \- omap_mcbsp_clk_enable() \- clk_enable(child clock) [tries for clockfw_lock again] mcbsp_clk is a virtual clock and it comprises several child clocks. when enable mcbsp_clk in omap_mcbsp_request(), the enable function of mcbsp_clk will enable its child clocks, then the deadlock occurs. The solution is to remove the virtual clock and enable these child clocks in omap_mcbsp_request() directly. Signed-off-by: Stanley.Miao Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/mcbsp.c | 98 ++-------------- arch/arm/mach-omap2/mcbsp.c | 145 ++++-------------------- arch/arm/plat-omap/include/mach/mcbsp.h | 6 +- arch/arm/plat-omap/mcbsp.c | 52 ++++++--- 4 files changed, 78 insertions(+), 223 deletions(-) diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c index ca7a0cc1707c2..575ba31295cf1 100644 --- a/arch/arm/mach-omap1/mcbsp.c +++ b/arch/arm/mach-omap1/mcbsp.c @@ -28,81 +28,8 @@ #define DPS_RSTCT2_PER_EN (1 << 0) #define DSP_RSTCT2_WD_PER_EN (1 << 1) -struct mcbsp_internal_clk { - struct clk clk; - struct clk **childs; - int n_childs; -}; - #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) -static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk) -{ - const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" }; - int i; - - mclk->n_childs = ARRAY_SIZE(clk_names); - mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *), - GFP_KERNEL); - - for (i = 0; i < mclk->n_childs; i++) { - /* We fake a platform device to get correct device id */ - struct platform_device pdev; - - pdev.dev.bus = &platform_bus_type; - pdev.id = mclk->clk.id; - mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]); - if (IS_ERR(mclk->childs[i])) - printk(KERN_ERR "Could not get clock %s (%d).\n", - clk_names[i], mclk->clk.id); - } -} - -static int omap_mcbsp_clk_enable(struct clk *clk) -{ - struct mcbsp_internal_clk *mclk = container_of(clk, - struct mcbsp_internal_clk, clk); - int i; - - for (i = 0; i < mclk->n_childs; i++) - clk_enable(mclk->childs[i]); - return 0; -} - -static void omap_mcbsp_clk_disable(struct clk *clk) -{ - struct mcbsp_internal_clk *mclk = container_of(clk, - struct mcbsp_internal_clk, clk); - int i; - - for (i = 0; i < mclk->n_childs; i++) - clk_disable(mclk->childs[i]); -} - -static struct mcbsp_internal_clk omap_mcbsp_clks[] = { - { - .clk = { - .name = "mcbsp_clk", - .id = 1, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 3, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, -}; - -#define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks) -#else -#define omap_mcbsp_clks_size 0 -static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks; -static inline void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk) -{ } +const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" }; #endif static void omap1_mcbsp_request(unsigned int id) @@ -167,8 +94,9 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP1RX, .tx_irq = INT_McBSP1TX, .ops = &omap1_mcbsp_ops, - .clk_name = "mcbsp_clk", - }, + .clk_names = clk_names, + .num_clks = 3, + }, { .phys_base = OMAP1510_MCBSP2_BASE, .dma_rx_sync = OMAP_DMA_MCBSP2_RX, @@ -184,7 +112,8 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP3RX, .tx_irq = INT_McBSP3TX, .ops = &omap1_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 3, }, }; #define OMAP15XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap15xx_mcbsp_pdata) @@ -202,7 +131,8 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP1RX, .tx_irq = INT_McBSP1TX, .ops = &omap1_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 3, }, { .phys_base = OMAP1610_MCBSP2_BASE, @@ -219,7 +149,8 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP3RX, .tx_irq = INT_McBSP3TX, .ops = &omap1_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 3, }, }; #define OMAP16XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap16xx_mcbsp_pdata) @@ -230,15 +161,6 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { int __init omap1_mcbsp_init(void) { - int i; - - for (i = 0; i < omap_mcbsp_clks_size; i++) { - if (cpu_is_omap15xx() || cpu_is_omap16xx()) { - omap_mcbsp_clk_init(&omap_mcbsp_clks[i]); - clk_register(&omap_mcbsp_clks[i].clk); - } - } - if (cpu_is_omap730()) omap_mcbsp_count = OMAP730_MCBSP_PDATA_SZ; if (cpu_is_omap15xx()) diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index e20023c9d15de..a9e631fc11341 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -24,106 +24,7 @@ #include #include -struct mcbsp_internal_clk { - struct clk clk; - struct clk **childs; - int n_childs; -}; - -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) -static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk) -{ - const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" }; - int i; - - mclk->n_childs = ARRAY_SIZE(clk_names); - mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *), - GFP_KERNEL); - - for (i = 0; i < mclk->n_childs; i++) { - /* We fake a platform device to get correct device id */ - struct platform_device pdev; - - pdev.dev.bus = &platform_bus_type; - pdev.id = mclk->clk.id; - mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]); - if (IS_ERR(mclk->childs[i])) - printk(KERN_ERR "Could not get clock %s (%d).\n", - clk_names[i], mclk->clk.id); - } -} - -static int omap_mcbsp_clk_enable(struct clk *clk) -{ - struct mcbsp_internal_clk *mclk = container_of(clk, - struct mcbsp_internal_clk, clk); - int i; - - for (i = 0; i < mclk->n_childs; i++) - clk_enable(mclk->childs[i]); - return 0; -} - -static void omap_mcbsp_clk_disable(struct clk *clk) -{ - struct mcbsp_internal_clk *mclk = container_of(clk, - struct mcbsp_internal_clk, clk); - int i; - - for (i = 0; i < mclk->n_childs; i++) - clk_disable(mclk->childs[i]); -} - -static struct mcbsp_internal_clk omap_mcbsp_clks[] = { - { - .clk = { - .name = "mcbsp_clk", - .id = 1, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 2, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 3, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 4, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 5, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, -}; - -#define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks) -#else -#define omap_mcbsp_clks_size 0 -static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks; -static inline void omap_mcbsp_clk_init(struct clk *clk) -{ } -#endif +const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" }; static void omap2_mcbsp2_mux_setup(void) { @@ -156,7 +57,8 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP24XX_MCBSP2_BASE, @@ -165,7 +67,8 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, }; #define OMAP2420_MCBSP_PDATA_SZ ARRAY_SIZE(omap2420_mcbsp_pdata) @@ -183,7 +86,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP24XX_MCBSP2_BASE, @@ -192,7 +96,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP2430_MCBSP3_BASE, @@ -201,7 +106,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP3_IRQ_RX, .tx_irq = INT_24XX_MCBSP3_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP2430_MCBSP4_BASE, @@ -210,7 +116,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP4_IRQ_RX, .tx_irq = INT_24XX_MCBSP4_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP2430_MCBSP5_BASE, @@ -219,7 +126,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP5_IRQ_RX, .tx_irq = INT_24XX_MCBSP5_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, }; #define OMAP2430_MCBSP_PDATA_SZ ARRAY_SIZE(omap2430_mcbsp_pdata) @@ -237,7 +145,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP2_BASE, @@ -246,7 +155,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP3_BASE, @@ -255,7 +165,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP3_IRQ_RX, .tx_irq = INT_24XX_MCBSP3_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP4_BASE, @@ -264,7 +175,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP4_IRQ_RX, .tx_irq = INT_24XX_MCBSP4_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP5_BASE, @@ -273,7 +185,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP5_IRQ_RX, .tx_irq = INT_24XX_MCBSP5_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, }; #define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata) @@ -284,14 +197,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { static int __init omap2_mcbsp_init(void) { - int i; - - for (i = 0; i < omap_mcbsp_clks_size; i++) { - /* Once we call clk_get inside init, we do not register it */ - omap_mcbsp_clk_init(&omap_mcbsp_clks[i]); - clk_register(&omap_mcbsp_clks[i].clk); - } - if (cpu_is_omap2420()) omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ; if (cpu_is_omap2430()) diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index eef873db3d48f..113c2466c86a7 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -344,7 +344,8 @@ struct omap_mcbsp_platform_data { u8 dma_rx_sync, dma_tx_sync; u16 rx_irq, tx_irq; struct omap_mcbsp_ops *ops; - char const *clk_name; + char const **clk_names; + int num_clks; }; struct omap_mcbsp { @@ -376,7 +377,8 @@ struct omap_mcbsp { /* Protect the field .free, while checking if the mcbsp is in use */ spinlock_t lock; struct omap_mcbsp_platform_data *pdata; - struct clk *clk; + struct clk **clks; + int num_clks; }; extern struct omap_mcbsp **mcbsp_ptr; extern int omap_mcbsp_count; diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index f2401a831f991..e5842e30e5344 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -214,6 +214,7 @@ EXPORT_SYMBOL(omap_mcbsp_set_io_type); int omap_mcbsp_request(unsigned int id) { struct omap_mcbsp *mcbsp; + int i; int err; if (!omap_mcbsp_check_valid_id(id)) { @@ -225,7 +226,8 @@ int omap_mcbsp_request(unsigned int id) if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request) mcbsp->pdata->ops->request(id); - clk_enable(mcbsp->clk); + for (i = 0; i < mcbsp->num_clks; i++) + clk_enable(mcbsp->clks[i]); spin_lock(&mcbsp->lock); if (!mcbsp->free) { @@ -276,6 +278,7 @@ EXPORT_SYMBOL(omap_mcbsp_request); void omap_mcbsp_free(unsigned int id) { struct omap_mcbsp *mcbsp; + int i; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); @@ -286,7 +289,8 @@ void omap_mcbsp_free(unsigned int id) if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(id); - clk_disable(mcbsp->clk); + for (i = mcbsp->num_clks - 1; i >= 0; i--) + clk_disable(mcbsp->clks[i]); spin_lock(&mcbsp->lock); if (mcbsp->free) { @@ -872,6 +876,7 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data; struct omap_mcbsp *mcbsp; int id = pdev->id - 1; + int i; int ret = 0; if (!pdata) { @@ -916,14 +921,25 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) mcbsp->dma_rx_sync = pdata->dma_rx_sync; mcbsp->dma_tx_sync = pdata->dma_tx_sync; - if (pdata->clk_name) - mcbsp->clk = clk_get(&pdev->dev, pdata->clk_name); - if (IS_ERR(mcbsp->clk)) { - dev_err(&pdev->dev, - "Invalid clock configuration for McBSP%d.\n", - mcbsp->id); - ret = PTR_ERR(mcbsp->clk); - goto err_clk; + if (pdata->num_clks) { + mcbsp->num_clks = pdata->num_clks; + mcbsp->clks = kzalloc(mcbsp->num_clks * sizeof(struct clk *), + GFP_KERNEL); + if (!mcbsp->clks) { + ret = -ENOMEM; + goto exit; + } + for (i = 0; i < mcbsp->num_clks; i++) { + mcbsp->clks[i] = clk_get(&pdev->dev, pdata->clk_names[i]); + if (IS_ERR(mcbsp->clks[i])) { + dev_err(&pdev->dev, + "Invalid %s configuration for McBSP%d.\n", + pdata->clk_names[i], mcbsp->id); + ret = PTR_ERR(mcbsp->clks[i]); + goto err_clk; + } + } + } mcbsp->pdata = pdata; @@ -932,6 +948,9 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) return 0; err_clk: + while (i--) + clk_put(mcbsp->clks[i]); + kfree(mcbsp->clks); iounmap(mcbsp->io_base); err_ioremap: mcbsp->free = 0; @@ -942,6 +961,7 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) static int __devexit omap_mcbsp_remove(struct platform_device *pdev) { struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); + int i; platform_set_drvdata(pdev, NULL); if (mcbsp) { @@ -950,12 +970,18 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev) mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(mcbsp->id); - clk_disable(mcbsp->clk); - clk_put(mcbsp->clk); + for (i = mcbsp->num_clks - 1; i >= 0; i--) { + clk_disable(mcbsp->clks[i]); + clk_put(mcbsp->clks[i]); + } iounmap(mcbsp->io_base); - mcbsp->clk = NULL; + if (mcbsp->num_clks) { + kfree(mcbsp->clks); + mcbsp->clks = NULL; + mcbsp->num_clks = 0; + } mcbsp->free = 0; mcbsp->dev = NULL; } From 320ce6f6fb3d95e02a183709e51d8a16a8b00e0a Mon Sep 17 00:00:00 2001 From: Juha Yrjola Date: Thu, 29 Jan 2009 08:57:12 -0800 Subject: [PATCH 06/16] ARM: OMAP: Fix race in OMAP2/3 DMA IRQ handling CSR must be cleared before invoking the callback. If the callback function starts a new, fast DMA transfer on the same channel, the completion status might lost if CSR is cleared after the callback invocation. Signed-off-by: Juha Yrjola Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index e77373c39f8c8..bec8e363d545f 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -1888,11 +1888,11 @@ static int omap2_dma_handle_ch(int ch) status = dma_read(CSR(ch)); } + dma_write(status, CSR(ch)); + if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, status, dma_chan[ch].data); - dma_write(status, CSR(ch)); - return 0; } From a92fda194d31d26c1fecd191a03d2dbc5b6ac230 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 29 Jan 2009 08:57:12 -0800 Subject: [PATCH 07/16] ARM: OMAP: DMA: Fix uninitialized channel flags This has similar symptoms than 66c23551b1b774e2be3c7bdf91c0ebf2c7a3519e where just omap_request_dma, omap_dma_link_lch and omap_dma_unlink_lch can cause incorrect dump_stack(). Here it can happen if channel has been used before and the channel flags variable holds old status. Signed-off-by: Jarkko Nikula Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index bec8e363d545f..47ec77af4ccbe 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -709,6 +709,7 @@ int omap_request_dma(int dev_id, const char *dev_name, chan->dev_name = dev_name; chan->callback = callback; chan->data = data; + chan->flags = 0; #ifndef CONFIG_ARCH_OMAP1 if (cpu_class_is_omap2()) { From 187e688d237a6df11a2d32e8ac480b6d1fbd40b9 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 29 Jan 2009 08:57:16 -0800 Subject: [PATCH 08/16] ARM: OMAP: Fix omap34xx revision detection for ES3.1 Fix omap34xx revision detection for ES3.1 Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/id.c | 6 +++++- arch/arm/plat-omap/include/mach/cpu.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index b0f8e7d627987..b52a02fc7cd63 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -172,9 +172,13 @@ void __init omap34xx_check_revision(void) omap_revision = OMAP3430_REV_ES3_0; rev_name = "ES3.0"; break; + case 4: + omap_revision = OMAP3430_REV_ES3_1; + rev_name = "ES3.1"; + break; default: /* Use the latest known revision as default */ - omap_revision = OMAP3430_REV_ES3_0; + omap_revision = OMAP3430_REV_ES3_1; rev_name = "Unknown revision\n"; } } diff --git a/arch/arm/plat-omap/include/mach/cpu.h b/arch/arm/plat-omap/include/mach/cpu.h index b2062f1175de0..a8e1178a94687 100644 --- a/arch/arm/plat-omap/include/mach/cpu.h +++ b/arch/arm/plat-omap/include/mach/cpu.h @@ -339,6 +339,7 @@ IS_OMAP_TYPE(3430, 0x3430) #define OMAP3430_REV_ES2_0 0x34301034 #define OMAP3430_REV_ES2_1 0x34302034 #define OMAP3430_REV_ES3_0 0x34303034 +#define OMAP3430_REV_ES3_1 0x34304034 /* * omap_chip bits From 0dffb5c57a1d76532e2f2c7398579bfce81c3e5c Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 29 Jan 2009 08:57:16 -0800 Subject: [PATCH 09/16] ARM: OMAP: Fix hsmmc init, v2 The naming accidentally broke while changing the name for the driver to not to conflict with the other mmc driver. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/devices.c | 2 +- arch/arm/mach-omap2/devices.c | 11 +++++++---- arch/arm/plat-omap/devices.c | 7 ++++--- arch/arm/plat-omap/include/mach/mmc.h | 10 ++++++---- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 77382d8b6b2f6..ba5d7c08dc17f 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -181,7 +181,7 @@ void __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, } size = OMAP1_MMC_SIZE; - omap_mmc_add(i, base, size, irq, mmc_data[i]); + omap_mmc_add("mmci-omap", i, base, size, irq, mmc_data[i]); }; } diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 9d7216ff6c9f5..ce03fa750775d 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -421,6 +421,7 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers) { int i; + char *name; for (i = 0; i < nr_controllers; i++) { unsigned long base, size; @@ -450,12 +451,14 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, continue; } - if (cpu_is_omap2420()) + if (cpu_is_omap2420()) { size = OMAP2420_MMC_SIZE; - else + name = "mmci-omap"; + } else { size = HSMMC_SIZE; - - omap_mmc_add(i, base, size, irq, mmc_data[i]); + name = "mmci-omap-hs"; + } + omap_mmc_add(name, i, base, size, irq, mmc_data[i]); }; } diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index ac15c23fd5da8..208dbb121f477 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -200,14 +200,15 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, /* * Register MMC devices. Called from mach-omap1 and mach-omap2 device init. */ -int __init omap_mmc_add(int id, unsigned long base, unsigned long size, - unsigned int irq, struct omap_mmc_platform_data *data) +int __init omap_mmc_add(const char *name, int id, unsigned long base, + unsigned long size, unsigned int irq, + struct omap_mmc_platform_data *data) { struct platform_device *pdev; struct resource res[OMAP_MMC_NR_RES]; int ret; - pdev = platform_device_alloc("mmci-omap", id); + pdev = platform_device_alloc(name, id); if (!pdev) return -ENOMEM; diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 031250f028050..73a9e15031b18 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -115,8 +115,9 @@ void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers); void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers); -int omap_mmc_add(int id, unsigned long base, unsigned long size, - unsigned int irq, struct omap_mmc_platform_data *data); +int omap_mmc_add(const char *name, int id, unsigned long base, + unsigned long size, unsigned int irq, + struct omap_mmc_platform_data *data); #else static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers) @@ -126,8 +127,9 @@ static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers) { } -static inline int omap_mmc_add(int id, unsigned long base, unsigned long size, - unsigned int irq, struct omap_mmc_platform_data *data) +static inline int omap_mmc_add(const char *name, int id, unsigned long base, + unsigned long size, unsigned int irq, + struct omap_mmc_platform_data *data) { return 0; } From df88acbbdc48d0bfe2a46bf2561d984b6d87a9ac Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 29 Jan 2009 08:57:17 -0800 Subject: [PATCH 10/16] ARM: OMAP: gptimer min_delta_ns corrected When 32 kHz timer is used the min_delta_ns should be initialized so that it reflects the timer programming cost. A write to the timer device will be usually posted, but it takes roughly 3 cycles before it is effective. If the timer is reprogrammed before that, the CPU will stall until the previous write completes. This was pointed out by Richard Woodruff. Since the lower bound for min_delta_ns is 1000, the change is visible only with tick rates less than 3 MHz. Also note that the old value is incorrect for 32 kHz also due to a rounding error, and it can cause the timer queue to hang (due to clockevent code trying to program the timer with zero ticks). Signed-off-by: Aaro Koskinen Reviewed-by: Richard Woodruff Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/timer-gp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index ae6036300f603..9fc13a2cc3f4e 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c @@ -118,7 +118,8 @@ static void __init omap2_gp_clockevent_init(void) clockevent_gpt.max_delta_ns = clockevent_delta2ns(0xffffffff, &clockevent_gpt); clockevent_gpt.min_delta_ns = - clockevent_delta2ns(1, &clockevent_gpt); + clockevent_delta2ns(3, &clockevent_gpt); + /* Timer internal resynch latency. */ clockevent_gpt.cpumask = cpumask_of(0); clockevents_register_device(&clockevent_gpt); From 5461af5af5c6a7fee78978aafe720541bf3a2f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EA=B7=9C=EC=9B=90?= Date: Thu, 29 Jan 2009 08:57:17 -0800 Subject: [PATCH 11/16] ARM: OMAP: Mask interrupts when disabling interrupts, v2 By Ingo Molnar, interrupts are not masked by default. (refer to 76d2160147f43f982dfe881404cfde9fd0a9da21) But if interrupts are not masked, the processor can wake up while in Suspend-to-RAM state by an external interrupt. For example, if an OMAP3 board is connected to Host PC by USB and entered to Suspend-to-RAM state, it wake up automatically by M_IRQ_92. The disable_irq() function can't disable the interrupt in H/W level, So I modified arch/arm/mach-omap2/irq.c Signed-off-by: Kim Kyuwon Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/irq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 636e2821af7da..9ba20d985dda2 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -134,6 +134,7 @@ static struct irq_chip omap_irq_chip = { .ack = omap_mask_ack_irq, .mask = omap_mask_irq, .unmask = omap_unmask_irq, + .disable = omap_mask_irq, }; static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank) From 0dc23d704874e892c3fb5f2c0e4dfbef3c9c6edf Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 29 Jan 2009 08:57:18 -0800 Subject: [PATCH 12/16] ARM: OMAP: fix fault in enter_full_retention() In omap24xx_cpu_suspend assembly routine, the r2 register which holds the address of the SDRC_POWER reg is set to zero before the value is written back triggering a fault due to writing to address zero. It's hard to tell where this change was introduced since this file has been moved and merged. While this fix prevents a crash, suspend on my n810 is broken with current kernels. I never come out of suspend. Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/sleep24xx.S | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S index 43336b93b21c0..bf9e96105e111 100644 --- a/arch/arm/mach-omap2/sleep24xx.S +++ b/arch/arm/mach-omap2/sleep24xx.S @@ -93,9 +93,8 @@ ENTRY(omap24xx_cpu_suspend) orr r4, r4, #0x40 @ enable self refresh on idle req mov r5, #0x2000 @ set delay (DPLL relock + DLL relock) str r4, [r2] @ make it so - mov r2, #0 nop - mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt + mcr p15, 0, r3, c7, c0, 4 @ wait for interrupt nop loop: subs r5, r5, #0x1 @ awake, wait just a bit From 6fd7ad96d6c51ba15479cb74dcb189b666422394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 31 Jan 2009 01:21:55 +0100 Subject: [PATCH 13/16] Use __SPIN_LOCK_UNLOCKED to initialize bad_irq_desc.lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SPIN_LOCK_UNLOCKED is deprecated as lockdep cannot properly work with locks initialized with it. This fix is necessary to compile the linux-rt tree for ARM. Signed-off-by: Uwe Kleine-König Cc: Steven Rostedt --- arch/arm/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 7141cee1fab71..363db186cb933 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -101,7 +101,7 @@ int show_interrupts(struct seq_file *p, void *v) /* Handle bad interrupts */ static struct irq_desc bad_irq_desc = { .handle_irq = handle_bad_irq, - .lock = SPIN_LOCK_UNLOCKED + .lock = __SPIN_LOCK_UNLOCKED(bad_irq_desc.lock), }; /* From b3c960b277c440c8a7788d338c9f494ad62e46ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 31 Jan 2009 01:21:56 +0100 Subject: [PATCH 14/16] annotate that [fp, #-4] is the saved lr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König --- arch/arm/kernel/entry-common.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 06269ea375c52..49a6ba926c2bc 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -136,7 +136,7 @@ ENTRY(mcount) ldmia sp!, {r0-r3, pc} trace: - ldr r1, [fp, #-4] + ldr r1, [fp, #-4] @ lr of instrumented routine mov r0, lr sub r0, r0, #MCOUNT_INSN_SIZE mov lr, pc From bcc8f3e01facc51b9d4f6351cd866f19eac0b5ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 31 Jan 2009 01:21:58 +0100 Subject: [PATCH 15/16] rename platform_driver name "flash" to "sa1100-mtd" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "flash" is a very generic name for a platform_driver that is only available on SA11x0. Signed-off-by: Uwe Kleine-König Cc: Nicolas Pitre --- arch/arm/mach-sa1100/generic.c | 2 +- drivers/mtd/maps/sa1100-flash.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index c1fbd5b5f9c45..23cfdd5939541 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -289,7 +289,7 @@ static struct platform_device sa11x0pcmcia_device = { }; static struct platform_device sa11x0mtd_device = { - .name = "flash", + .name = "sa1100-mtd", .id = -1, }; diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index 7df6bbf0e4d93..6f6a0f6dafd61 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -453,7 +453,7 @@ static struct platform_driver sa1100_mtd_driver = { .resume = sa1100_mtd_resume, .shutdown = sa1100_mtd_shutdown, .driver = { - .name = "flash", + .name = "sa1100-mtd", .owner = THIS_MODULE, }, }; @@ -474,4 +474,4 @@ module_exit(sa1100_mtd_exit); MODULE_AUTHOR("Nicolas Pitre"); MODULE_DESCRIPTION("SA1100 CFI map driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:flash"); +MODULE_ALIAS("platform:sa1100-mtd"); From 807a96cd0e5f5311e7f7a1030b43aab624cd7d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 31 Jan 2009 01:21:59 +0100 Subject: [PATCH 16/16] NVRAM depends on RTC_DRV_CMOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/char/nvram.c uses rtc_lock, that (on ARM) is only defined if RTC_DRV_CMOS is enabled. Signed-off-by: Uwe Kleine-König --- drivers/char/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index f5be8081cd818..735bbe2be51aa 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -761,7 +761,7 @@ source "drivers/char/hw_random/Kconfig" config NVRAM tristate "/dev/nvram support" - depends on ATARI || X86 || ARM || GENERIC_NVRAM + depends on ATARI || X86 || (ARM && RTC_DRV_CMOS) || GENERIC_NVRAM ---help--- If you say Y here and create a character special file /dev/nvram with major number 10 and minor number 144 using mknod ("man mknod"),