From 8d69abb08343706f88380edb83927ffc0fc83098 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 18 Jan 2009 11:55:19 +0200 Subject: [ARM] pxa: fix NAND and MMC clock initialization for pxa3xx After commit 8c3abc7d903df492a7394b0adae4349d9a381aaf ("[ARM] pxa: convert to clkdev and match clocks by struct device where possible") get_clk in pxa3xx_nand fails with -ENOENT. Apparently, clk_get in pxamci will also fail for MCI2 on PXA310. The 'clk_find' and therefore 'clk_get' require driver to supply both 'dev_id' and 'con_id' if they are not NULL in the 'strcut clk_lookup', but neither pxa3xx_nand nor pxamci supply 'con_id'. This patch sets 'con_id' to NULL in NAND clock and MCI2 clock registration. Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao --- arch/arm/mach-pxa/pxa300.c | 4 ++-- arch/arm/mach-pxa/pxa320.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c index f735e58e666..83fb609b6eb 100644 --- a/arch/arm/mach-pxa/pxa300.c +++ b/arch/arm/mach-pxa/pxa300.c @@ -88,13 +88,13 @@ static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = { static DEFINE_PXA3_CKEN(common_nand, NAND, 156000000, 0); static struct clk_lookup common_clkregs[] = { - INIT_CLKREG(&clk_common_nand, "pxa3xx-nand", "NANDCLK"), + INIT_CLKREG(&clk_common_nand, "pxa3xx-nand", NULL), }; static DEFINE_PXA3_CKEN(pxa310_mmc3, MMC3, 19500000, 0); static struct clk_lookup pxa310_clkregs[] = { - INIT_CLKREG(&clk_pxa310_mmc3, "pxa2xx-mci.2", "MMCCLK"), + INIT_CLKREG(&clk_pxa310_mmc3, "pxa2xx-mci.2", NULL), }; static int __init pxa300_init(void) diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c index effe408c186..36f066196fa 100644 --- a/arch/arm/mach-pxa/pxa320.c +++ b/arch/arm/mach-pxa/pxa320.c @@ -83,7 +83,7 @@ static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = { static DEFINE_PXA3_CKEN(pxa320_nand, NAND, 104000000, 0); static struct clk_lookup pxa320_clkregs[] = { - INIT_CLKREG(&clk_pxa320_nand, "pxa3xx-nand", "NANDCLK"), + INIT_CLKREG(&clk_pxa320_nand, "pxa3xx-nand", NULL), }; static int __init pxa320_init(void) -- cgit v1.2.3-70-g09d2 From ec971c91c55b8e2e2609f8d61eb34da13aedb37d Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Mon, 19 Jan 2009 11:39:36 +0800 Subject: [ARM] pxa: fix missing of __REG() definition for ac97 registers access This currently happens for 'drivers/input/touch/mainstone-wm97xx.c'. Signed-off-by: Eric Miao --- arch/arm/mach-pxa/include/mach/regs-ac97.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-pxa/include/mach/regs-ac97.h b/arch/arm/mach-pxa/include/mach/regs-ac97.h index e41b9d202b8..b8d14bd9ae5 100644 --- a/arch/arm/mach-pxa/include/mach/regs-ac97.h +++ b/arch/arm/mach-pxa/include/mach/regs-ac97.h @@ -1,6 +1,8 @@ #ifndef __ASM_ARCH_REGS_AC97_H #define __ASM_ARCH_REGS_AC97_H +#include + /* * AC97 Controller registers */ -- cgit v1.2.3-70-g09d2 From b6729deb26a131083add5b7238c7b7478ef6b502 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Mon, 19 Jan 2009 11:42:32 +0800 Subject: [ARM] pxa: make more SSCR0 bit definitions visible on multiple processors The only exclusive definitions are SSCR0_SCR and SSCR0_SerClkDiv(), loosen that exclusive #ifdef .. #else .. #endif to allow other definitions to be visible when slected multiple processors. This helps to pass the building of pxa-ssp.c. Signed-off-by: Eric Miao --- arch/arm/mach-pxa/include/mach/regs-ssp.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-pxa/include/mach/regs-ssp.h b/arch/arm/mach-pxa/include/mach/regs-ssp.h index 3c04cde2cf1..cf31986f6f0 100644 --- a/arch/arm/mach-pxa/include/mach/regs-ssp.h +++ b/arch/arm/mach-pxa/include/mach/regs-ssp.h @@ -41,6 +41,9 @@ #elif defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) #define SSCR0_SCR (0x000fff00) /* Serial Clock Rate (mask) */ #define SSCR0_SerClkDiv(x) (((x) - 1) << 8) /* Divisor [1..4096] */ +#endif + +#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) #define SSCR0_EDSS (1 << 20) /* Extended data size select */ #define SSCR0_NCS (1 << 21) /* Network clock select */ #define SSCR0_RIM (1 << 22) /* Receive FIFO overrrun interrupt mask */ -- cgit v1.2.3-70-g09d2 From 26a552264bc92d2ec4747b1babb7cb1264908018 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 21 Jan 2009 11:29:19 +0800 Subject: [ARM] pxa: stop and disable IRQ for each DMA channels at startup Some broken bootloaders will leave the DMA channel state unclean, which we should really initialize correctly here. Signed-off-by: Eric Miao --- arch/arm/mach-pxa/dma.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c index b1514fb20d3..7de17fc5d54 100644 --- a/arch/arm/mach-pxa/dma.c +++ b/arch/arm/mach-pxa/dma.c @@ -121,20 +121,22 @@ int __init pxa_init_dma(int num_ch) if (dma_channels == NULL) return -ENOMEM; - ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL); - if (ret) { - printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n"); - kfree(dma_channels); - return ret; - } - /* dma channel priorities on pxa2xx processors: * ch 0 - 3, 16 - 19 <--> (0) DMA_PRIO_HIGH * ch 4 - 7, 20 - 23 <--> (1) DMA_PRIO_MEDIUM * ch 8 - 15, 24 - 31 <--> (2) DMA_PRIO_LOW */ - for (i = 0; i < num_ch; i++) + for (i = 0; i < num_ch; i++) { + DCSR(i) = 0; dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW); + } + + ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL); + if (ret) { + printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n"); + kfree(dma_channels); + return ret; + } num_dma_channels = num_ch; return 0; -- cgit v1.2.3-70-g09d2 From 9ce8bb55e32d11bb82e19e76bdd2cf1c2ed32fd1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 27 Jan 2009 22:44:12 +0000 Subject: [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(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c index c2a96e3965a..e61967dde9a 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 -- cgit v1.2.3-70-g09d2 From ecbab71c521819716e204659dfe72fc39d00630a Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 27 Jan 2009 23:20:00 +0000 Subject: [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(+) (limited to 'arch/arm') diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 77b04747553..85040cfeb5e 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 -- cgit v1.2.3-70-g09d2 From 08e445bd6a98fa09befe0cf6d67705324f913fc6 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 16 Jan 2009 23:02:54 +0100 Subject: [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(-) (limited to 'arch/arm') diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 81d0b8772de..bc0099d5ae8 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); -- cgit v1.2.3-70-g09d2 From 06151158f2da4764479b4ec01688dc4bade6ce9d Mon Sep 17 00:00:00 2001 From: "Stanley.Miao" Date: Thu, 29 Jan 2009 08:57:12 -0800 Subject: 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(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c index ca7a0cc1707..575ba31295c 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 e20023c9d15..a9e631fc113 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 eef873db3d4..113c2466c86 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 f2401a831f9..e5842e30e53 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 @@ exit: 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; } -- cgit v1.2.3-70-g09d2 From 320ce6f6fb3d95e02a183709e51d8a16a8b00e0a Mon Sep 17 00:00:00 2001 From: Juha Yrjola Date: Thu, 29 Jan 2009 08:57:12 -0800 Subject: 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(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index e77373c39f8..bec8e363d54 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; } -- cgit v1.2.3-70-g09d2 From a92fda194d31d26c1fecd191a03d2dbc5b6ac230 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 29 Jan 2009 08:57:12 -0800 Subject: 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(+) (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index bec8e363d54..47ec77af4cc 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()) { -- cgit v1.2.3-70-g09d2 From 187e688d237a6df11a2d32e8ac480b6d1fbd40b9 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 29 Jan 2009 08:57:16 -0800 Subject: 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(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index b0f8e7d6279..b52a02fc7cd 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 b2062f1175d..a8e1178a946 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 -- cgit v1.2.3-70-g09d2 From 0dffb5c57a1d76532e2f2c7398579bfce81c3e5c Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 29 Jan 2009 08:57:16 -0800 Subject: 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(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 77382d8b6b2..ba5d7c08dc1 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 9d7216ff6c9..ce03fa75077 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 ac15c23fd5d..208dbb121f4 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 031250f0280..73a9e15031b 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; } -- cgit v1.2.3-70-g09d2 From df88acbbdc48d0bfe2a46bf2561d984b6d87a9ac Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 29 Jan 2009 08:57:17 -0800 Subject: 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(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index ae6036300f6..9fc13a2cc3f 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); -- cgit v1.2.3-70-g09d2 From 5461af5af5c6a7fee78978aafe720541bf3a2f55 Mon Sep 17 00:00:00 2001 From: 김규원 Date: Thu, 29 Jan 2009 08:57:17 -0800 Subject: 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(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 636e2821af7..9ba20d985dd 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) -- cgit v1.2.3-70-g09d2 From 0dc23d704874e892c3fb5f2c0e4dfbef3c9c6edf Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 29 Jan 2009 08:57:18 -0800 Subject: 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(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S index 43336b93b21..bf9e96105e1 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 -- cgit v1.2.3-70-g09d2 From 6fd7ad96d6c51ba15479cb74dcb189b666422394 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 31 Jan 2009 01:21:55 +0100 Subject: 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(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 7141cee1fab..363db186cb9 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -101,7 +101,7 @@ unlock: /* 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), }; /* -- cgit v1.2.3-70-g09d2 From b3c960b277c440c8a7788d338c9f494ad62e46ab Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 31 Jan 2009 01:21:56 +0100 Subject: 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(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 06269ea375c..49a6ba926c2 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 -- cgit v1.2.3-70-g09d2 From bcc8f3e01facc51b9d4f6351cd866f19eac0b5ae Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 31 Jan 2009 01:21:58 +0100 Subject: 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(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index c1fbd5b5f9c..23cfdd59395 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 7df6bbf0e4d..6f6a0f6dafd 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"); -- cgit v1.2.3-70-g09d2 From d96be879ff469759af6d7fcebdb66237c18da6f8 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 6 Jan 2009 17:04:14 +0100 Subject: mmc: Add a MX2/MX3 specific SDHC driver This patch adds a MX2/MX3 specific SDHC driver. The hardware is basically the same as in the MX1, but unlike the MX1 controller the MX2 controller just works as expected. Since the MX1 driver has more workarounds for bugs than anything else I had no success with supporting MX1 and MX2 in a sane way in one driver. Signed-off-by: Sascha Hauer Signed-off-by: Pierre Ossman --- arch/arm/plat-mxc/include/mach/mmc.h | 36 ++ drivers/mmc/host/Kconfig | 10 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/mxcmmc.c | 880 +++++++++++++++++++++++++++++++++++ 4 files changed, 927 insertions(+) create mode 100644 arch/arm/plat-mxc/include/mach/mmc.h create mode 100644 drivers/mmc/host/mxcmmc.c (limited to 'arch/arm') diff --git a/arch/arm/plat-mxc/include/mach/mmc.h b/arch/arm/plat-mxc/include/mach/mmc.h new file mode 100644 index 00000000000..de2128dada5 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/mmc.h @@ -0,0 +1,36 @@ +#ifndef ASMARM_ARCH_MMC_H +#define ASMARM_ARCH_MMC_H + +#include + +struct device; + +/* board specific SDHC data, optional. + * If not present, a writable card with 3,3V is assumed. + */ +struct imxmmc_platform_data { + /* Return values for the get_ro callback should be: + * 0 for a read/write card + * 1 for a read-only card + * -ENOSYS when not supported (equal to NULL callback) + * or a negative errno value when something bad happened + */ + int (*get_ro)(struct device *); + + /* board specific hook to (de)initialize the SD slot. + * The board code can call 'handler' on a card detection + * change giving data as argument. + */ + int (*init)(struct device *dev, irq_handler_t handler, void *data); + void (*exit)(struct device *dev, void *data); + + /* available voltages. If not given, assume + * MMC_VDD_32_33 | MMC_VDD_33_34 + */ + unsigned int ocr_avail; + + /* adjust slot voltage */ + void (*setpower)(struct device *, unsigned int vdd); +}; + +#endif diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 0efa390978b..99d4b28d52e 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -145,6 +145,16 @@ config MMC_IMX If unsure, say N. +config MMC_MXC + tristate "Freescale i.MX2/3 Multimedia Card Interface support" + depends on ARCH_MXC + help + This selects the Freescale i.MX2/3 Multimedia card Interface. + If you have a i.MX platform with a Multimedia Card slot, + say Y or M here. + + If unsure, say N. + config MMC_TIFM_SD tristate "TI Flash Media MMC/SD Interface support (EXPERIMENTAL)" depends on EXPERIMENTAL && PCI diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 98cab84829b..dedec55861d 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -9,6 +9,7 @@ endif obj-$(CONFIG_MMC_ARMMMCI) += mmci.o obj-$(CONFIG_MMC_PXA) += pxamci.o obj-$(CONFIG_MMC_IMX) += imxmmc.o +obj-$(CONFIG_MMC_MXC) += mxcmmc.o obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c new file mode 100644 index 00000000000..dda0be4e25d --- /dev/null +++ b/drivers/mmc/host/mxcmmc.c @@ -0,0 +1,880 @@ +/* + * linux/drivers/mmc/host/mxcmmc.c - Freescale i.MX MMCI driver + * + * This is a driver for the SDHC controller found in Freescale MX2/MX3 + * SoCs. It is basically the same hardware as found on MX1 (imxmmc.c). + * Unlike the hardware found on MX1, this hardware just works and does + * not need all the quirks found in imxmmc.c, hence the seperate driver. + * + * Copyright (C) 2008 Sascha Hauer, Pengutronix + * Copyright (C) 2006 Pavel Pisa, PiKRON + * + * derived from pxamci.c by Russell King + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_ARCH_MX2 +#include +#define HAS_DMA +#endif + +#define DRIVER_NAME "imx-mmc" + +#define MMC_REG_STR_STP_CLK 0x00 +#define MMC_REG_STATUS 0x04 +#define MMC_REG_CLK_RATE 0x08 +#define MMC_REG_CMD_DAT_CONT 0x0C +#define MMC_REG_RES_TO 0x10 +#define MMC_REG_READ_TO 0x14 +#define MMC_REG_BLK_LEN 0x18 +#define MMC_REG_NOB 0x1C +#define MMC_REG_REV_NO 0x20 +#define MMC_REG_INT_CNTR 0x24 +#define MMC_REG_CMD 0x28 +#define MMC_REG_ARG 0x2C +#define MMC_REG_RES_FIFO 0x34 +#define MMC_REG_BUFFER_ACCESS 0x38 + +#define STR_STP_CLK_RESET (1 << 3) +#define STR_STP_CLK_START_CLK (1 << 1) +#define STR_STP_CLK_STOP_CLK (1 << 0) + +#define STATUS_CARD_INSERTION (1 << 31) +#define STATUS_CARD_REMOVAL (1 << 30) +#define STATUS_YBUF_EMPTY (1 << 29) +#define STATUS_XBUF_EMPTY (1 << 28) +#define STATUS_YBUF_FULL (1 << 27) +#define STATUS_XBUF_FULL (1 << 26) +#define STATUS_BUF_UND_RUN (1 << 25) +#define STATUS_BUF_OVFL (1 << 24) +#define STATUS_SDIO_INT_ACTIVE (1 << 14) +#define STATUS_END_CMD_RESP (1 << 13) +#define STATUS_WRITE_OP_DONE (1 << 12) +#define STATUS_DATA_TRANS_DONE (1 << 11) +#define STATUS_READ_OP_DONE (1 << 11) +#define STATUS_WR_CRC_ERROR_CODE_MASK (3 << 10) +#define STATUS_CARD_BUS_CLK_RUN (1 << 8) +#define STATUS_BUF_READ_RDY (1 << 7) +#define STATUS_BUF_WRITE_RDY (1 << 6) +#define STATUS_RESP_CRC_ERR (1 << 5) +#define STATUS_CRC_READ_ERR (1 << 3) +#define STATUS_CRC_WRITE_ERR (1 << 2) +#define STATUS_TIME_OUT_RESP (1 << 1) +#define STATUS_TIME_OUT_READ (1 << 0) +#define STATUS_ERR_MASK 0x2f + +#define CMD_DAT_CONT_CMD_RESP_LONG_OFF (1 << 12) +#define CMD_DAT_CONT_STOP_READWAIT (1 << 11) +#define CMD_DAT_CONT_START_READWAIT (1 << 10) +#define CMD_DAT_CONT_BUS_WIDTH_4 (2 << 8) +#define CMD_DAT_CONT_INIT (1 << 7) +#define CMD_DAT_CONT_WRITE (1 << 4) +#define CMD_DAT_CONT_DATA_ENABLE (1 << 3) +#define CMD_DAT_CONT_RESPONSE_48BIT_CRC (1 << 0) +#define CMD_DAT_CONT_RESPONSE_136BIT (2 << 0) +#define CMD_DAT_CONT_RESPONSE_48BIT (3 << 0) + +#define INT_SDIO_INT_WKP_EN (1 << 18) +#define INT_CARD_INSERTION_WKP_EN (1 << 17) +#define INT_CARD_REMOVAL_WKP_EN (1 << 16) +#define INT_CARD_INSERTION_EN (1 << 15) +#define INT_CARD_REMOVAL_EN (1 << 14) +#define INT_SDIO_IRQ_EN (1 << 13) +#define INT_DAT0_EN (1 << 12) +#define INT_BUF_READ_EN (1 << 4) +#define INT_BUF_WRITE_EN (1 << 3) +#define INT_END_CMD_RES_EN (1 << 2) +#define INT_WRITE_OP_DONE_EN (1 << 1) +#define INT_READ_OP_EN (1 << 0) + +struct mxcmci_host { + struct mmc_host *mmc; + struct resource *res; + void __iomem *base; + int irq; + int detect_irq; + int dma; + int do_dma; + unsigned int power_mode; + struct imxmmc_platform_data *pdata; + + struct mmc_request *req; + struct mmc_command *cmd; + struct mmc_data *data; + + unsigned int dma_nents; + unsigned int datasize; + unsigned int dma_dir; + + u16 rev_no; + unsigned int cmdat; + + struct clk *clk; + + int clock; + + struct work_struct datawork; +}; + +static inline int mxcmci_use_dma(struct mxcmci_host *host) +{ + return host->do_dma; +} + +static void mxcmci_softreset(struct mxcmci_host *host) +{ + int i; + + /* reset sequence */ + writew(STR_STP_CLK_RESET, host->base + MMC_REG_STR_STP_CLK); + writew(STR_STP_CLK_RESET | STR_STP_CLK_START_CLK, + host->base + MMC_REG_STR_STP_CLK); + + for (i = 0; i < 8; i++) + writew(STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK); + + writew(0xff, host->base + MMC_REG_RES_TO); +} + +static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) +{ + unsigned int nob = data->blocks; + unsigned int blksz = data->blksz; + unsigned int datasize = nob * blksz; +#ifdef HAS_DMA + struct scatterlist *sg; + int i; +#endif + if (data->flags & MMC_DATA_STREAM) + nob = 0xffff; + + host->data = data; + data->bytes_xfered = 0; + + writew(nob, host->base + MMC_REG_NOB); + writew(blksz, host->base + MMC_REG_BLK_LEN); + host->datasize = datasize; + +#ifdef HAS_DMA + for_each_sg(data->sg, sg, data->sg_len, i) { + if (sg->offset & 3 || sg->length & 3) { + host->do_dma = 0; + return; + } + } + + if (data->flags & MMC_DATA_READ) { + host->dma_dir = DMA_FROM_DEVICE; + host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, host->dma_dir); + + imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize, + host->res->start + MMC_REG_BUFFER_ACCESS, + DMA_MODE_READ); + } else { + host->dma_dir = DMA_TO_DEVICE; + host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, host->dma_dir); + + imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize, + host->res->start + MMC_REG_BUFFER_ACCESS, + DMA_MODE_WRITE); + } + + wmb(); + + imx_dma_enable(host->dma); +#endif /* HAS_DMA */ +} + +static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, + unsigned int cmdat) +{ + WARN_ON(host->cmd != NULL); + host->cmd = cmd; + + switch (mmc_resp_type(cmd)) { + case MMC_RSP_R1: /* short CRC, OPCODE */ + case MMC_RSP_R1B:/* short CRC, OPCODE, BUSY */ + cmdat |= CMD_DAT_CONT_RESPONSE_48BIT_CRC; + break; + case MMC_RSP_R2: /* long 136 bit + CRC */ + cmdat |= CMD_DAT_CONT_RESPONSE_136BIT; + break; + case MMC_RSP_R3: /* short */ + cmdat |= CMD_DAT_CONT_RESPONSE_48BIT; + break; + case MMC_RSP_NONE: + break; + default: + dev_err(mmc_dev(host->mmc), "unhandled response type 0x%x\n", + mmc_resp_type(cmd)); + cmd->error = -EINVAL; + return -EINVAL; + } + + if (mxcmci_use_dma(host)) + writel(INT_READ_OP_EN | INT_WRITE_OP_DONE_EN | + INT_END_CMD_RES_EN, + host->base + MMC_REG_INT_CNTR); + else + writel(INT_END_CMD_RES_EN, host->base + MMC_REG_INT_CNTR); + + writew(cmd->opcode, host->base + MMC_REG_CMD); + writel(cmd->arg, host->base + MMC_REG_ARG); + writew(cmdat, host->base + MMC_REG_CMD_DAT_CONT); + + return 0; +} + +static void mxcmci_finish_request(struct mxcmci_host *host, + struct mmc_request *req) +{ + writel(0, host->base + MMC_REG_INT_CNTR); + + host->req = NULL; + host->cmd = NULL; + host->data = NULL; + + mmc_request_done(host->mmc, req); +} + +static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat) +{ + struct mmc_data *data = host->data; + int data_error; + +#ifdef HAS_DMA + if (mxcmci_use_dma(host)) { + imx_dma_disable(host->dma); + dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents, + host->dma_dir); + } +#endif + + if (stat & STATUS_ERR_MASK) { + dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", + stat); + if (stat & STATUS_CRC_READ_ERR) { + data->error = -EILSEQ; + } else if (stat & STATUS_CRC_WRITE_ERR) { + u32 err_code = (stat >> 9) & 0x3; + if (err_code == 2) /* No CRC response */ + data->error = -ETIMEDOUT; + else + data->error = -EILSEQ; + } else if (stat & STATUS_TIME_OUT_READ) { + data->error = -ETIMEDOUT; + } else { + data->error = -EIO; + } + } else { + data->bytes_xfered = host->datasize; + } + + data_error = data->error; + + host->data = NULL; + + return data_error; +} + +static void mxcmci_read_response(struct mxcmci_host *host, unsigned int stat) +{ + struct mmc_command *cmd = host->cmd; + int i; + u32 a, b, c; + + if (!cmd) + return; + + if (stat & STATUS_TIME_OUT_RESP) { + dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n"); + cmd->error = -ETIMEDOUT; + } else if (stat & STATUS_RESP_CRC_ERR && cmd->flags & MMC_RSP_CRC) { + dev_dbg(mmc_dev(host->mmc), "cmd crc error\n"); + cmd->error = -EILSEQ; + } + + if (cmd->flags & MMC_RSP_PRESENT) { + if (cmd->flags & MMC_RSP_136) { + for (i = 0; i < 4; i++) { + a = readw(host->base + MMC_REG_RES_FIFO); + b = readw(host->base + MMC_REG_RES_FIFO); + cmd->resp[i] = a << 16 | b; + } + } else { + a = readw(host->base + MMC_REG_RES_FIFO); + b = readw(host->base + MMC_REG_RES_FIFO); + c = readw(host->base + MMC_REG_RES_FIFO); + cmd->resp[0] = a << 24 | b << 8 | c >> 8; + } + } +} + +static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask) +{ + u32 stat; + unsigned long timeout = jiffies + HZ; + + do { + stat = readl(host->base + MMC_REG_STATUS); + if (stat & STATUS_ERR_MASK) + return stat; + if (time_after(jiffies, timeout)) + return STATUS_TIME_OUT_READ; + if (stat & mask) + return 0; + cpu_relax(); + } while (1); +} + +static int mxcmci_pull(struct mxcmci_host *host, void *_buf, int bytes) +{ + unsigned int stat; + u32 *buf = _buf; + + while (bytes > 3) { + stat = mxcmci_poll_status(host, + STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE); + if (stat) + return stat; + *buf++ = readl(host->base + MMC_REG_BUFFER_ACCESS); + bytes -= 4; + } + + if (bytes) { + u8 *b = (u8 *)buf; + u32 tmp; + + stat = mxcmci_poll_status(host, + STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE); + if (stat) + return stat; + tmp = readl(host->base + MMC_REG_BUFFER_ACCESS); + memcpy(b, &tmp, bytes); + } + + return 0; +} + +static int mxcmci_push(struct mxcmci_host *host, void *_buf, int bytes) +{ + unsigned int stat; + u32 *buf = _buf; + + while (bytes > 3) { + stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); + if (stat) + return stat; + writel(*buf++, host->base + MMC_REG_BUFFER_ACCESS); + bytes -= 4; + } + + if (bytes) { + u8 *b = (u8 *)buf; + u32 tmp; + + stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); + if (stat) + return stat; + + memcpy(&tmp, b, bytes); + writel(tmp, host->base + MMC_REG_BUFFER_ACCESS); + } + + stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); + if (stat) + return stat; + + return 0; +} + +static int mxcmci_transfer_data(struct mxcmci_host *host) +{ + struct mmc_data *data = host->req->data; + struct scatterlist *sg; + int stat, i; + + host->datasize = 0; + + host->data = data; + host->datasize = 0; + + if (data->flags & MMC_DATA_READ) { + for_each_sg(data->sg, sg, data->sg_len, i) { + stat = mxcmci_pull(host, sg_virt(sg), sg->length); + if (stat) + return stat; + host->datasize += sg->length; + } + } else { + for_each_sg(data->sg, sg, data->sg_len, i) { + stat = mxcmci_push(host, sg_virt(sg), sg->length); + if (stat) + return stat; + host->datasize += sg->length; + } + stat = mxcmci_poll_status(host, STATUS_WRITE_OP_DONE); + if (stat) + return stat; + } + return 0; +} + +static void mxcmci_datawork(struct work_struct *work) +{ + struct mxcmci_host *host = container_of(work, struct mxcmci_host, + datawork); + int datastat = mxcmci_transfer_data(host); + mxcmci_finish_data(host, datastat); + + if (host->req->stop) { + if (mxcmci_start_cmd(host, host->req->stop, 0)) { + mxcmci_finish_request(host, host->req); + return; + } + } else { + mxcmci_finish_request(host, host->req); + } +} + +#ifdef HAS_DMA +static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat) +{ + struct mmc_data *data = host->data; + int data_error; + + if (!data) + return; + + data_error = mxcmci_finish_data(host, stat); + + mxcmci_read_response(host, stat); + host->cmd = NULL; + + if (host->req->stop) { + if (mxcmci_start_cmd(host, host->req->stop, 0)) { + mxcmci_finish_request(host, host->req); + return; + } + } else { + mxcmci_finish_request(host, host->req); + } +} +#endif /* HAS_DMA */ + +static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat) +{ + mxcmci_read_response(host, stat); + host->cmd = NULL; + + if (!host->data && host->req) { + mxcmci_finish_request(host, host->req); + return; + } + + /* For the DMA case the DMA engine handles the data transfer + * automatically. For non DMA we have to to it ourselves. + * Don't do it in interrupt context though. + */ + if (!mxcmci_use_dma(host) && host->data) + schedule_work(&host->datawork); + +} + +static irqreturn_t mxcmci_irq(int irq, void *devid) +{ + struct mxcmci_host *host = devid; + u32 stat; + + stat = readl(host->base + MMC_REG_STATUS); + writel(stat, host->base + MMC_REG_STATUS); + + dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); + + if (stat & STATUS_END_CMD_RESP) + mxcmci_cmd_done(host, stat); +#ifdef HAS_DMA + if (mxcmci_use_dma(host) && + (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) + mxcmci_data_done(host, stat); +#endif + return IRQ_HANDLED; +} + +static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req) +{ + struct mxcmci_host *host = mmc_priv(mmc); + unsigned int cmdat = host->cmdat; + + WARN_ON(host->req != NULL); + + host->req = req; + host->cmdat &= ~CMD_DAT_CONT_INIT; +#ifdef HAS_DMA + host->do_dma = 1; +#endif + if (req->data) { + mxcmci_setup_data(host, req->data); + + cmdat |= CMD_DAT_CONT_DATA_ENABLE; + + if (req->data->flags & MMC_DATA_WRITE) + cmdat |= CMD_DAT_CONT_WRITE; + } + + if (mxcmci_start_cmd(host, req->cmd, cmdat)) + mxcmci_finish_request(host, req); +} + +static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios) +{ + unsigned int divider; + int prescaler = 0; + unsigned int clk_in = clk_get_rate(host->clk); + + while (prescaler <= 0x800) { + for (divider = 1; divider <= 0xF; divider++) { + int x; + + x = (clk_in / (divider + 1)); + + if (prescaler) + x /= (prescaler * 2); + + if (x <= clk_ios) + break; + } + if (divider < 0x10) + break; + + if (prescaler == 0) + prescaler = 1; + else + prescaler <<= 1; + } + + writew((prescaler << 4) | divider, host->base + MMC_REG_CLK_RATE); + + dev_dbg(mmc_dev(host->mmc), "scaler: %d divider: %d in: %d out: %d\n", + prescaler, divider, clk_in, clk_ios); +} + +static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct mxcmci_host *host = mmc_priv(mmc); +#ifdef HAS_DMA + unsigned int blen; + /* + * use burstlen of 64 in 4 bit mode (--> reg value 0) + * use burstlen of 16 in 1 bit mode (--> reg value 16) + */ + if (ios->bus_width == MMC_BUS_WIDTH_4) + blen = 0; + else + blen = 16; + + imx_dma_config_burstlen(host->dma, blen); +#endif + if (ios->bus_width == MMC_BUS_WIDTH_4) + host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4; + else + host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4; + + if (host->power_mode != ios->power_mode) { + if (host->pdata && host->pdata->setpower) + host->pdata->setpower(mmc_dev(mmc), ios->vdd); + host->power_mode = ios->power_mode; + if (ios->power_mode == MMC_POWER_ON) + host->cmdat |= CMD_DAT_CONT_INIT; + } + + if (ios->clock) { + mxcmci_set_clk_rate(host, ios->clock); + writew(STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK); + } else { + writew(STR_STP_CLK_STOP_CLK, host->base + MMC_REG_STR_STP_CLK); + } + + host->clock = ios->clock; +} + +static irqreturn_t mxcmci_detect_irq(int irq, void *data) +{ + struct mmc_host *mmc = data; + + dev_dbg(mmc_dev(mmc), "%s\n", __func__); + + mmc_detect_change(mmc, msecs_to_jiffies(250)); + return IRQ_HANDLED; +} + +static int mxcmci_get_ro(struct mmc_host *mmc) +{ + struct mxcmci_host *host = mmc_priv(mmc); + + if (host->pdata && host->pdata->get_ro) + return !!host->pdata->get_ro(mmc_dev(mmc)); + /* + * Board doesn't support read only detection; let the mmc core + * decide what to do. + */ + return -ENOSYS; +} + + +static const struct mmc_host_ops mxcmci_ops = { + .request = mxcmci_request, + .set_ios = mxcmci_set_ios, + .get_ro = mxcmci_get_ro, +}; + +static int mxcmci_probe(struct platform_device *pdev) +{ + struct mmc_host *mmc; + struct mxcmci_host *host = NULL; + struct resource *r; + int ret = 0, irq; + + printk(KERN_INFO "i.MX SDHC driver\n"); + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!r || irq < 0) + return -EINVAL; + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) + return -EBUSY; + + mmc = mmc_alloc_host(sizeof(struct mxcmci_host), &pdev->dev); + if (!mmc) { + ret = -ENOMEM; + goto out_release_mem; + } + + mmc->ops = &mxcmci_ops; + mmc->caps = MMC_CAP_4_BIT_DATA; + + /* MMC core transfer sizes tunable parameters */ + mmc->max_hw_segs = 64; + mmc->max_phys_segs = 64; + mmc->max_blk_size = 2048; + mmc->max_blk_count = 65535; + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + mmc->max_seg_size = mmc->max_seg_size; + + host = mmc_priv(mmc); + host->base = ioremap(r->start, resource_size(r)); + if (!host->base) { + ret = -ENOMEM; + goto out_free; + } + + host->mmc = mmc; + host->pdata = pdev->dev.platform_data; + + if (host->pdata && host->pdata->ocr_avail) + mmc->ocr_avail = host->pdata->ocr_avail; + else + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + + host->res = r; + host->irq = irq; + + host->clk = clk_get(&pdev->dev, "sdhc_clk"); + if (IS_ERR(host->clk)) { + ret = PTR_ERR(host->clk); + goto out_iounmap; + } + clk_enable(host->clk); + + mxcmci_softreset(host); + + host->rev_no = readw(host->base + MMC_REG_REV_NO); + if (host->rev_no != 0x400) { + ret = -ENODEV; + dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n", + host->rev_no); + goto out_clk_put; + } + + mmc->f_min = clk_get_rate(host->clk) >> 7; + mmc->f_max = clk_get_rate(host->clk) >> 1; + + /* recommended in data sheet */ + writew(0x2db4, host->base + MMC_REG_READ_TO); + + writel(0, host->base + MMC_REG_INT_CNTR); + +#ifdef HAS_DMA + host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW); + if (host->dma < 0) { + dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n"); + ret = -EBUSY; + goto out_clk_put; + } + + r = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (!r) { + ret = -EINVAL; + goto out_free_dma; + } + + ret = imx_dma_config_channel(host->dma, + IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO, + IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, + r->start, 0); + if (ret) { + dev_err(mmc_dev(host->mmc), "failed to config DMA channel\n"); + goto out_free_dma; + } +#endif + INIT_WORK(&host->datawork, mxcmci_datawork); + + ret = request_irq(host->irq, mxcmci_irq, 0, DRIVER_NAME, host); + if (ret) + goto out_free_dma; + + platform_set_drvdata(pdev, mmc); + + if (host->pdata && host->pdata->init) { + ret = host->pdata->init(&pdev->dev, mxcmci_detect_irq, + host->mmc); + if (ret) + goto out_free_irq; + } + + mmc_add_host(mmc); + + return 0; + +out_free_irq: + free_irq(host->irq, host); +out_free_dma: +#ifdef HAS_DMA + imx_dma_free(host->dma); +#endif +out_clk_put: + clk_disable(host->clk); + clk_put(host->clk); +out_iounmap: + iounmap(host->base); +out_free: + mmc_free_host(mmc); +out_release_mem: + release_mem_region(host->res->start, resource_size(host->res)); + return ret; +} + +static int mxcmci_remove(struct platform_device *pdev) +{ + struct mmc_host *mmc = platform_get_drvdata(pdev); + struct mxcmci_host *host = mmc_priv(mmc); + + platform_set_drvdata(pdev, NULL); + + mmc_remove_host(mmc); + + if (host->pdata && host->pdata->exit) + host->pdata->exit(&pdev->dev, mmc); + + free_irq(host->irq, host); + iounmap(host->base); +#ifdef HAS_DMA + imx_dma_free(host->dma); +#endif + clk_disable(host->clk); + clk_put(host->clk); + + release_mem_region(host->res->start, resource_size(host->res)); + release_resource(host->res); + + mmc_free_host(mmc); + + return 0; +} + +#ifdef CONFIG_PM +static int mxcmci_suspend(struct platform_device *dev, pm_message_t state) +{ + struct mmc_host *mmc = platform_get_drvdata(dev); + int ret = 0; + + if (mmc) + ret = mmc_suspend_host(mmc, state); + + return ret; +} + +static int mxcmci_resume(struct platform_device *dev) +{ + struct mmc_host *mmc = platform_get_drvdata(dev); + struct mxcmci_host *host; + int ret = 0; + + if (mmc) { + host = mmc_priv(mmc); + ret = mmc_resume_host(mmc); + } + + return ret; +} +#else +#define mxcmci_suspend NULL +#define mxcmci_resume NULL +#endif /* CONFIG_PM */ + +static struct platform_driver mxcmci_driver = { + .probe = mxcmci_probe, + .remove = mxcmci_remove, + .suspend = mxcmci_suspend, + .resume = mxcmci_resume, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + } +}; + +static int __init mxcmci_init(void) +{ + return platform_driver_register(&mxcmci_driver); +} + +static void __exit mxcmci_exit(void) +{ + platform_driver_unregister(&mxcmci_driver); +} + +module_init(mxcmci_init); +module_exit(mxcmci_exit); + +MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver"); +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:imx-mmc"); -- cgit v1.2.3-70-g09d2 From e0fc4f97ab6b11594d0b0658ef6cf02bd68f3b4e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 9 Feb 2009 21:35:39 +0100 Subject: [ARM] Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Signed-off-by: Russell King --- arch/arm/kernel/machine_kexec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 440dc62cdc3..598ca61e7bc 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -13,8 +13,8 @@ #include #include -const extern unsigned char relocate_new_kernel[]; -const extern unsigned int relocate_new_kernel_size; +extern const unsigned char relocate_new_kernel[]; +extern const unsigned int relocate_new_kernel_size; extern void setup_mm_for_reboot(char mode); -- cgit v1.2.3-70-g09d2 From 9132f1b453924e7595ce2dc1853704b2a31f42de Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 14 Feb 2009 13:24:10 +0000 Subject: [ARM] omap: fix omap2_divisor_to_clksel() error return value The error checks for omap2_divisor_to_clksel() and comment disagree with the actual value returned on error. Fix this to return the correct error value. Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index ad721e0cbf7..2899cba2aaa 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -565,7 +565,7 @@ u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val) * * Given a struct clk of a rate-selectable clksel clock, and a clock divisor, * find the corresponding register field value. The return register value is - * the value before left-shifting. Returns 0xffffffff on error + * the value before left-shifting. Returns ~0 on error */ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div) { @@ -577,7 +577,7 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div) clks = omap2_get_clksel_by_parent(clk, clk->parent); if (clks == NULL) - return 0; + return ~0; for (clkr = clks->rates; clkr->div; clkr++) { if ((clkr->flags & cpu_mask) && (clkr->div == div)) @@ -588,7 +588,7 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div) printk(KERN_ERR "clock: Could not find divisor %d for " "clock %s parent %s\n", div, clk->name, clk->parent->name); - return 0; + return ~0; } return clkr->val; -- cgit v1.2.3-70-g09d2 From abf239657b88fa7e75d5b44a65a4177e7bb8acce Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 14 Feb 2009 13:25:38 +0000 Subject: [ARM] omap: fix _omap2_clksel_get_src_field() _omap2_clksel_get_src_field() was returning the first entry which was either the default _or_ applicable to the SoC. This is wrong - we should be returning the first default which is applicable to the SoC. Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 2899cba2aaa..e64549e4e32 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -708,7 +708,7 @@ static u32 omap2_clksel_get_src_field(void __iomem **src_addr, return 0; for (clkr = clks->rates; clkr->div; clkr++) { - if (clkr->flags & (cpu_mask | DEFAULT_RATE)) + if (clkr->flags & cpu_mask && clkr->flags & DEFAULT_RATE) break; /* Found the default rate for this platform */ } -- cgit v1.2.3-70-g09d2 From 2af29b78618ac8b3a8746337002f108f8fdf56ad Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Wed, 11 Feb 2009 21:23:10 +0100 Subject: [ARM] 5390/1: AT91: Watchdog fixes The recently merged AT91SAM9 watchdog driver uses the AT91SAM9X_WATCHDOG config variable, whereas the original version of the driver (and the platform support code) used AT91SAM9_WATCHDOG. This causes the watchdog platform_device to never be registered, and therefore the driver not to be initialized. This patch: - updates the platform support code to use AT91SAM9X_WATCHDOG. - includes to fix compile error (same fix as was applied to at91rm9200_wdt.c) - fixes comment regarding watchdog clock-rates in at91rm9200. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/configs/at91sam9260ek_defconfig | 2 +- arch/arm/configs/at91sam9261ek_defconfig | 2 +- arch/arm/configs/at91sam9263ek_defconfig | 2 +- arch/arm/configs/at91sam9rlek_defconfig | 2 +- arch/arm/configs/qil-a9260_defconfig | 2 +- arch/arm/mach-at91/at91cap9_devices.c | 2 +- arch/arm/mach-at91/at91sam9260_devices.c | 2 +- arch/arm/mach-at91/at91sam9261_devices.c | 2 +- arch/arm/mach-at91/at91sam9263_devices.c | 2 +- arch/arm/mach-at91/at91sam9rl_devices.c | 2 +- drivers/watchdog/at91rm9200_wdt.c | 4 ++-- drivers/watchdog/at91sam9_wdt.c | 1 + 12 files changed, 13 insertions(+), 12 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig index e0ee7060f9a..98e2f3de4bc 100644 --- a/arch/arm/configs/at91sam9260ek_defconfig +++ b/arch/arm/configs/at91sam9260ek_defconfig @@ -608,7 +608,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91SAM9_WATCHDOG=y +CONFIG_AT91SAM9X_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/arch/arm/configs/at91sam9261ek_defconfig b/arch/arm/configs/at91sam9261ek_defconfig index 01d1ef97d8b..14945614239 100644 --- a/arch/arm/configs/at91sam9261ek_defconfig +++ b/arch/arm/configs/at91sam9261ek_defconfig @@ -700,7 +700,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91SAM9_WATCHDOG=y +CONFIG_AT91SAM9X_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/arch/arm/configs/at91sam9263ek_defconfig b/arch/arm/configs/at91sam9263ek_defconfig index 036a126725c..21599f3c627 100644 --- a/arch/arm/configs/at91sam9263ek_defconfig +++ b/arch/arm/configs/at91sam9263ek_defconfig @@ -710,7 +710,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91SAM9_WATCHDOG=y +CONFIG_AT91SAM9X_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/arch/arm/configs/at91sam9rlek_defconfig b/arch/arm/configs/at91sam9rlek_defconfig index 237a2a6a851..e2df81a3e80 100644 --- a/arch/arm/configs/at91sam9rlek_defconfig +++ b/arch/arm/configs/at91sam9rlek_defconfig @@ -606,7 +606,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91SAM9_WATCHDOG=y +CONFIG_AT91SAM9X_WATCHDOG=y # # Sonics Silicon Backplane diff --git a/arch/arm/configs/qil-a9260_defconfig b/arch/arm/configs/qil-a9260_defconfig index cd1d717903a..9b32d0eb89b 100644 --- a/arch/arm/configs/qil-a9260_defconfig +++ b/arch/arm/configs/qil-a9260_defconfig @@ -727,7 +727,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -# CONFIG_AT91SAM9_WATCHDOG is not set +# CONFIG_AT91SAM9X_WATCHDOG is not set # # USB-based Watchdog Cards diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c index 9eca2209cde..412aa49ad2f 100644 --- a/arch/arm/mach-at91/at91cap9_devices.c +++ b/arch/arm/mach-at91/at91cap9_devices.c @@ -697,7 +697,7 @@ static void __init at91_add_device_rtt(void) * Watchdog * -------------------------------------------------------------------- */ -#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE) +#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE) static struct platform_device at91cap9_wdt_device = { .name = "at91_wdt", .id = -1, diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index fdde1ea21b0..d74c9ac007e 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -643,7 +643,7 @@ static void __init at91_add_device_rtt(void) * Watchdog * -------------------------------------------------------------------- */ -#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE) +#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE) static struct platform_device at91sam9260_wdt_device = { .name = "at91_wdt", .id = -1, diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 17289756f80..59fc48311fb 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -621,7 +621,7 @@ static void __init at91_add_device_rtt(void) * Watchdog * -------------------------------------------------------------------- */ -#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE) +#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE) static struct platform_device at91sam9261_wdt_device = { .name = "at91_wdt", .id = -1, diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index b753cb879d8..134af97ff34 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -854,7 +854,7 @@ static void __init at91_add_device_rtt(void) * Watchdog * -------------------------------------------------------------------- */ -#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE) +#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE) static struct platform_device at91sam9263_wdt_device = { .name = "at91_wdt", .id = -1, diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index 145324f4ec5..728186515cd 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -609,7 +609,7 @@ static void __init at91_add_device_rtt(void) * Watchdog * -------------------------------------------------------------------- */ -#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE) +#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE) static struct platform_device at91sam9rl_wdt_device = { .name = "at91_wdt", .id = -1, diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c index 5531691f46e..e35d5458923 100644 --- a/drivers/watchdog/at91rm9200_wdt.c +++ b/drivers/watchdog/at91rm9200_wdt.c @@ -107,10 +107,10 @@ static int at91_wdt_close(struct inode *inode, struct file *file) static int at91_wdt_settimeout(int new_time) { /* - * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz + * All counting occurs at SLOW_CLOCK / 128 = 256 Hz * * Since WDV is a 16-bit counter, the maximum period is - * 65536 / 0.256 = 256 seconds. + * 65536 / 256 = 256 seconds. */ if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) return -EINVAL; diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index b1da287f90e..a56ac84381b 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3-70-g09d2 From 2b768b6cdbcf7fa0761e6c35c6ea288297582c43 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Wed, 11 Feb 2009 21:39:05 +0100 Subject: [ARM] 5391/1: AT91: Enable GPIO clocks earlier Enable the GPIO clocks earlier in the initialization sequence. This allow the board-setup code to read and set GPIO pins. Signed-off-by: Marc Pignat Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91/gpio.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c index 9b0447c3d59..2f7d4977dce 100644 --- a/arch/arm/mach-at91/gpio.c +++ b/arch/arm/mach-at91/gpio.c @@ -490,7 +490,8 @@ postcore_initcall(at91_gpio_debugfs_init); /*--------------------------------------------------------------------------*/ -/* This lock class tells lockdep that GPIO irqs are in a different +/* + * This lock class tells lockdep that GPIO irqs are in a different * category than their parents, so it won't report false recursion. */ static struct lock_class_key gpio_lock_class; @@ -509,9 +510,6 @@ void __init at91_gpio_irq_setup(void) unsigned id = this->id; unsigned i; - /* enable PIO controller's clock */ - clk_enable(this->clock); - __raw_writel(~0, this->regbase + PIO_IDR); for (i = 0, pin = this->chipbase; i < 32; i++, pin++) { @@ -556,7 +554,14 @@ void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks) data->chipbase = PIN_BASE + i * 32; data->regbase = data->offset + (void __iomem *)AT91_VA_BASE_SYS; - /* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */ + /* enable PIO controller's clock */ + clk_enable(data->clock); + + /* + * Some processors share peripheral ID between multiple GPIO banks. + * SAM9263 (PIOC, PIOD, PIOE) + * CAP9 (PIOA, PIOB, PIOC, PIOD) + */ if (last && last->id == data->id) last->next = data; } -- cgit v1.2.3-70-g09d2 From 744f6592727a7ab9e3ca4266bedaa786825a31bb Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 16 Feb 2009 21:21:47 +0100 Subject: [ARM] 5400/1: Add support for inverted rdy_busy pin for Atmel nand device controller Add support for inverted rdy_busy pin for Atmel nand device controller It will fix building error on NeoCore926 board. Acked-by: Andrew Victor Acked-by: David Woodhouse Signed-off-by: Gregory CLEMENT Signed-off-by: Russell King --- arch/arm/mach-at91/include/mach/board.h | 1 + arch/avr32/mach-at32ap/include/mach/board.h | 1 + drivers/mtd/nand/atmel_nand.c | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index fb51f0e0a83..0b3ae21b456 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -93,6 +93,7 @@ struct atmel_nand_data { u8 enable_pin; /* chip enable */ u8 det_pin; /* card detect */ u8 rdy_pin; /* ready/busy */ + u8 rdy_pin_active_low; /* rdy_pin value is inverted */ u8 ale; /* address line number connected to ALE */ u8 cle; /* address line number connected to CLE */ u8 bus_width_16; /* buswidth is 16 bit */ diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h index aafaf7a7888..cff8e84f78f 100644 --- a/arch/avr32/mach-at32ap/include/mach/board.h +++ b/arch/avr32/mach-at32ap/include/mach/board.h @@ -116,6 +116,7 @@ struct atmel_nand_data { int enable_pin; /* chip enable */ int det_pin; /* card detect */ int rdy_pin; /* ready/busy */ + u8 rdy_pin_active_low; /* rdy_pin value is inverted */ u8 ale; /* address line number connected to ALE */ u8 cle; /* address line number connected to CLE */ u8 bus_width_16; /* buswidth is 16 bit */ diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index c98c1570a40..47a33cec379 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -139,7 +139,8 @@ static int atmel_nand_device_ready(struct mtd_info *mtd) struct nand_chip *nand_chip = mtd->priv; struct atmel_nand_host *host = nand_chip->priv; - return gpio_get_value(host->board->rdy_pin); + return gpio_get_value(host->board->rdy_pin) ^ + !!host->board->rdy_pin_active_low; } /* -- cgit v1.2.3-70-g09d2 From fd4b9b3650076ffadbdd6e360eb198f5d61747c0 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 17 Feb 2009 20:45:50 +0100 Subject: [ARM] 5401/1: Orion: fix edge triggered GPIO interrupt support The GPIO interrupts can be configured as either level triggered or edge triggered, with a default of level triggered. When an edge triggered interrupt is requested, the gpio_irq_set_type method is called which currently switches the given IRQ descriptor between two struct irq_chip instances: orion_gpio_irq_level_chip and orion_gpio_irq_edge_chip. This happens via __setup_irq() which also calls irq_chip_set_defaults() to assign default methods to uninitialized ones. The problem is that irq_chip_set_defaults() is called before the irq_chip reference is switched, leaving the new irq_chip (orion_gpio_irq_edge_chip in this case) with uninitialized methods such as chip->startup() causing a kernel oops. Many solutions are possible, such as making irq_chip_set_defaults() global and calling it from gpio_irq_set_type(), or calling __irq_set_trigger() before irq_chip_set_defaults() in __setup_irq(). But those require modifications to the generic IRQ code which might have adverse effect on other architectures, and that would still be a fragile arrangement. Manually copying the missing methods from within gpio_irq_set_type() would be really ugly and it would break again the day new methods with automatic defaults are added. A better solution is to have a single irq_chip instance which can deal with both edge and level triggered interrupts. It is also a good idea to switch the IRQ handler instead, as the edge IRQ handler allows for one edge IRQ event to be queued as the IRQ is actually masked only when that second IRQ is received, at which point the hardware can queue an additional IRQ event, making edge triggered interrupts a bit more reliable. Tested-by: Martin Michlmayr Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mach-kirkwood/irq.c | 2 +- arch/arm/mach-mv78xx0/irq.c | 2 +- arch/arm/mach-orion5x/irq.c | 2 +- arch/arm/plat-orion/gpio.c | 73 +++++++++++---------------------- arch/arm/plat-orion/include/plat/gpio.h | 3 +- 5 files changed, 29 insertions(+), 53 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-kirkwood/irq.c b/arch/arm/mach-kirkwood/irq.c index efb86b70027..06083b23bb4 100644 --- a/arch/arm/mach-kirkwood/irq.c +++ b/arch/arm/mach-kirkwood/irq.c @@ -42,7 +42,7 @@ void __init kirkwood_init_irq(void) writel(0, GPIO_EDGE_CAUSE(32)); for (i = IRQ_KIRKWOOD_GPIO_START; i < NR_IRQS; i++) { - set_irq_chip(i, &orion_gpio_irq_level_chip); + set_irq_chip(i, &orion_gpio_irq_chip); set_irq_handler(i, handle_level_irq); irq_desc[i].status |= IRQ_LEVEL; set_irq_flags(i, IRQF_VALID); diff --git a/arch/arm/mach-mv78xx0/irq.c b/arch/arm/mach-mv78xx0/irq.c index e273418797b..30b7e4bcdbc 100644 --- a/arch/arm/mach-mv78xx0/irq.c +++ b/arch/arm/mach-mv78xx0/irq.c @@ -40,7 +40,7 @@ void __init mv78xx0_init_irq(void) writel(0, GPIO_EDGE_CAUSE(0)); for (i = IRQ_MV78XX0_GPIO_START; i < NR_IRQS; i++) { - set_irq_chip(i, &orion_gpio_irq_level_chip); + set_irq_chip(i, &orion_gpio_irq_chip); set_irq_handler(i, handle_level_irq); irq_desc[i].status |= IRQ_LEVEL; set_irq_flags(i, IRQF_VALID); diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c index 0caae43301e..e03f7b45cb0 100644 --- a/arch/arm/mach-orion5x/irq.c +++ b/arch/arm/mach-orion5x/irq.c @@ -44,7 +44,7 @@ void __init orion5x_init_irq(void) * User can use set_type() if he wants to use edge types handlers. */ for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) { - set_irq_chip(i, &orion_gpio_irq_level_chip); + set_irq_chip(i, &orion_gpio_irq_chip); set_irq_handler(i, handle_level_irq); irq_desc[i].status |= IRQ_LEVEL; set_irq_flags(i, IRQF_VALID); diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c index 967186425ca..0d12c216476 100644 --- a/arch/arm/plat-orion/gpio.c +++ b/arch/arm/plat-orion/gpio.c @@ -265,51 +265,36 @@ EXPORT_SYMBOL(orion_gpio_set_blink); * polarity LEVEL mask * ****************************************************************************/ -static void gpio_irq_edge_ack(u32 irq) -{ - int pin = irq_to_gpio(irq); - - writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin)); -} - -static void gpio_irq_edge_mask(u32 irq) -{ - int pin = irq_to_gpio(irq); - u32 u; - - u = readl(GPIO_EDGE_MASK(pin)); - u &= ~(1 << (pin & 31)); - writel(u, GPIO_EDGE_MASK(pin)); -} -static void gpio_irq_edge_unmask(u32 irq) +static void gpio_irq_ack(u32 irq) { - int pin = irq_to_gpio(irq); - u32 u; - - u = readl(GPIO_EDGE_MASK(pin)); - u |= 1 << (pin & 31); - writel(u, GPIO_EDGE_MASK(pin)); + int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK; + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { + int pin = irq_to_gpio(irq); + writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin)); + } } -static void gpio_irq_level_mask(u32 irq) +static void gpio_irq_mask(u32 irq) { int pin = irq_to_gpio(irq); - u32 u; - - u = readl(GPIO_LEVEL_MASK(pin)); + int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK; + u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ? + GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin); + u32 u = readl(reg); u &= ~(1 << (pin & 31)); - writel(u, GPIO_LEVEL_MASK(pin)); + writel(u, reg); } -static void gpio_irq_level_unmask(u32 irq) +static void gpio_irq_unmask(u32 irq) { int pin = irq_to_gpio(irq); - u32 u; - - u = readl(GPIO_LEVEL_MASK(pin)); + int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK; + u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ? + GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin); + u32 u = readl(reg); u |= 1 << (pin & 31); - writel(u, GPIO_LEVEL_MASK(pin)); + writel(u, reg); } static int gpio_irq_set_type(u32 irq, u32 type) @@ -331,9 +316,9 @@ static int gpio_irq_set_type(u32 irq, u32 type) * Set edge/level type. */ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - desc->chip = &orion_gpio_irq_edge_chip; + desc->handle_irq = handle_edge_irq; } else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { - desc->chip = &orion_gpio_irq_level_chip; + desc->handle_irq = handle_level_irq; } else { printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type); return -EINVAL; @@ -371,19 +356,11 @@ static int gpio_irq_set_type(u32 irq, u32 type) return 0; } -struct irq_chip orion_gpio_irq_edge_chip = { - .name = "orion_gpio_irq_edge", - .ack = gpio_irq_edge_ack, - .mask = gpio_irq_edge_mask, - .unmask = gpio_irq_edge_unmask, - .set_type = gpio_irq_set_type, -}; - -struct irq_chip orion_gpio_irq_level_chip = { - .name = "orion_gpio_irq_level", - .mask = gpio_irq_level_mask, - .mask_ack = gpio_irq_level_mask, - .unmask = gpio_irq_level_unmask, +struct irq_chip orion_gpio_irq_chip = { + .name = "orion_gpio", + .ack = gpio_irq_ack, + .mask = gpio_irq_mask, + .unmask = gpio_irq_unmask, .set_type = gpio_irq_set_type, }; diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h index 54deaf274b5..ec743e82c87 100644 --- a/arch/arm/plat-orion/include/plat/gpio.h +++ b/arch/arm/plat-orion/include/plat/gpio.h @@ -31,8 +31,7 @@ void orion_gpio_set_blink(unsigned pin, int blink); /* * GPIO interrupt handling. */ -extern struct irq_chip orion_gpio_irq_edge_chip; -extern struct irq_chip orion_gpio_irq_level_chip; +extern struct irq_chip orion_gpio_irq_chip; void orion_gpio_irq_handler(int irqoff); -- cgit v1.2.3-70-g09d2 From 3fd9825c42c784a59b3b90bdf073f49d4bb42a8d Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 18 Feb 2009 22:29:22 +0100 Subject: [ARM] 5402/1: fix a case of wrap-around in sanity_check_meminfo() In the non highmem case, if two memory banks of 1GB each are provided, the second bank would evade suppression since its virtual base would be 0. Fix this by disallowing any memory bank which virtual base address is found to be lower than PAGE_OFFSET. Reported-by: Lennert Buytenhek Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 9b36c5cb5e9..d4d082c5c2d 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -693,7 +693,8 @@ static void __init sanity_check_meminfo(void) * Check whether this memory bank would entirely overlap * the vmalloc area. */ - if (__va(bank->start) >= VMALLOC_MIN) { + if (__va(bank->start) >= VMALLOC_MIN || + __va(bank->start) < PAGE_OFFSET) { printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx " "(vmalloc region overlap).\n", bank->start, bank->start + bank->size - 1); -- cgit v1.2.3-70-g09d2 From 41f3103fcfffff096c34f5267d7c9a26b44d89d3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 19 Feb 2009 13:25:16 +0000 Subject: [ARM] omap: fix clock reparenting in omap2_clk_set_parent() When changing the parent of a clock, it is necessary to keep the clock use counts balanced otherwise things the parent state will get corrupted. Since we already disable and re-enable the clock, we might as well use the recursive versions instead. Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index e64549e4e32..ce4d46a4a83 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -746,7 +746,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) return -EINVAL; if (clk->usecount > 0) - _omap2_clk_disable(clk); + omap2_clk_disable(clk); /* Set new source value (previous dividers if any in effect) */ reg_val = __raw_readl(src_addr) & ~field_mask; @@ -759,11 +759,11 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) wmb(); } - if (clk->usecount > 0) - _omap2_clk_enable(clk); - clk->parent = new_parent; + if (clk->usecount > 0) + omap2_clk_enable(clk); + /* CLKSEL clocks follow their parents' rates, divided by a divisor */ clk->rate = new_parent->rate; -- cgit v1.2.3-70-g09d2 From 9da616fb9946c8d65387052e5a538b8f54ddb292 Mon Sep 17 00:00:00 2001 From: Makito SHIOKAWA Date: Thu, 19 Feb 2009 15:34:59 +0100 Subject: [ARM] 5404/1: Fix condition in arm_elf_read_implies_exec() to set READ_IMPLIES_EXEC READ_IMPLIES_EXEC must be set when: o binary _is_ an executable stack (i.e. not EXSTACK_DISABLE_X) o processor architecture is _under_ ARMv6 (XN bit is supported from ARMv6) Signed-off-by: Makito SHIOKAWA Signed-off-by: Russell King --- arch/arm/kernel/elf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c index 84849098c8e..d4a0da1e48f 100644 --- a/arch/arm/kernel/elf.c +++ b/arch/arm/kernel/elf.c @@ -74,9 +74,9 @@ EXPORT_SYMBOL(elf_set_personality); */ int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack) { - if (executable_stack != EXSTACK_ENABLE_X) + if (executable_stack != EXSTACK_DISABLE_X) return 1; - if (cpu_architecture() <= CPU_ARCH_ARMv6) + if (cpu_architecture() < CPU_ARCH_ARMv6) return 1; return 0; } -- cgit v1.2.3-70-g09d2 From 9dd446f657ebebb209274878be5d01103fcfe988 Mon Sep 17 00:00:00 2001 From: Hartley Sweeten Date: Thu, 19 Feb 2009 17:09:04 +0100 Subject: [ARM] 5405/1: ep93xx: remove unused gesbc9312.h header Remove the gesbc9312.h header since it is unused. Signed-off-by: H Hartley Sweeten Signed-off-by: Russell King --- arch/arm/mach-ep93xx/include/mach/gesbc9312.h | 3 --- arch/arm/mach-ep93xx/include/mach/hardware.h | 1 - 2 files changed, 4 deletions(-) delete mode 100644 arch/arm/mach-ep93xx/include/mach/gesbc9312.h (limited to 'arch/arm') diff --git a/arch/arm/mach-ep93xx/include/mach/gesbc9312.h b/arch/arm/mach-ep93xx/include/mach/gesbc9312.h deleted file mode 100644 index 21fe2b922aa..00000000000 --- a/arch/arm/mach-ep93xx/include/mach/gesbc9312.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * arch/arm/mach-ep93xx/include/mach/gesbc9312.h - */ diff --git a/arch/arm/mach-ep93xx/include/mach/hardware.h b/arch/arm/mach-ep93xx/include/mach/hardware.h index 529807d182b..2866297310b 100644 --- a/arch/arm/mach-ep93xx/include/mach/hardware.h +++ b/arch/arm/mach-ep93xx/include/mach/hardware.h @@ -10,7 +10,6 @@ #include "platform.h" -#include "gesbc9312.h" #include "ts72xx.h" #endif -- cgit v1.2.3-70-g09d2 From d82ad6d6833ee8248e6c34e1b9fc3c4e61e3f035 Mon Sep 17 00:00:00 2001 From: Andrei Birjukov Date: Sun, 22 Feb 2009 22:37:21 +0000 Subject: [ARM] at91: fix for Atmel AT91 powersaving We've discovered that our AT91SAM9260 board consumed too much power when returning from a slowclock low-power mode. RAM self-refresh is enabled in a bootloader in our case, this is how we saw a difference. Estimated ca. 30mA more on 4V battery than the same state before powersaving. After a small research we found that there seems to be a bogus sdram_selfrefresh_disable() call at the end of at91_pm_enter() call, which overwrites the LPR register with uninitialized value. Please find the suggested patch attached. This patch fixes correct restoring of LPR register of the Atmel AT91 SDRAM controller when returning from a power saving mode. Signed-off-by: Andrei Birjukov Acked-by: Andrew Victor Signed-off-by: Andrew Morton Signed-off-by: Russell King --- arch/arm/mach-at91/pm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 9bb4f043aa2..7ac812dc055 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -332,7 +332,6 @@ static int at91_pm_enter(suspend_state_t state) at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR)); error: - sdram_selfrefresh_disable(); target_state = PM_SUSPEND_ON; at91_irq_resume(); at91_gpio_resume(); -- cgit v1.2.3-70-g09d2 From 531660ef5604c75de6fdead9da1304051af17c09 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 24 Feb 2009 19:19:50 +0100 Subject: Add i2c_board_info for RiscPC PCF8583 Add the necessary i2c_board_info structure to fix the lack of PCF8583 RTC on RiscPC. Signed-off-by: Russell King Signed-off-by: Jean Delvare Cc: Alessandro Zummo --- arch/arm/mach-rpc/riscpc.c | 6 ++++++ drivers/i2c/busses/i2c-acorn.c | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c index e88d417736a..c7fc01e9d1f 100644 --- a/arch/arm/mach-rpc/riscpc.c +++ b/arch/arm/mach-rpc/riscpc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -201,8 +202,13 @@ static struct platform_device *devs[] __initdata = { &pata_device, }; +static struct i2c_board_info i2c_rtc = { + I2C_BOARD_INFO("pcf8583", 0x50) +}; + static int __init rpc_init(void) { + i2c_register_board_info(0, &i2c_rtc, 1); return platform_add_devices(devs, ARRAY_SIZE(devs)); } diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c index dddccdd91f9..9aefb5e5864 100644 --- a/drivers/i2c/busses/i2c-acorn.c +++ b/drivers/i2c/busses/i2c-acorn.c @@ -83,6 +83,7 @@ static struct i2c_algo_bit_data ioc_data = { }; static struct i2c_adapter ioc_ops = { + .nr = 0, .algo_data = &ioc_data, }; @@ -90,7 +91,7 @@ static int __init i2c_ioc_init(void) { force_ones = FORCE_ONES | SCL | SDA; - return i2c_bit_add_bus(&ioc_ops); + return i2c_bit_add_numbered_bus(&ioc_ops); } module_init(i2c_ioc_init); -- cgit v1.2.3-70-g09d2 From c8532db7f2661b63f658b9a08cf4053a3e6abb78 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 24 Feb 2009 15:55:48 +0100 Subject: [ARM] 5411/1: S3C64XX: Fix EINT unmask Currently the unmask function for EINT interrupts was setting the mask bit rather than clearing it. This was also previously reported and fixed by Kyungmin Park and others. Acked-By: Ben Dooks Signed-off-by: Mark Brown Signed-off-by: Russell King --- arch/arm/plat-s3c64xx/irq-eint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c index 1f7cc0067f5..ebb305ce768 100644 --- a/arch/arm/plat-s3c64xx/irq-eint.c +++ b/arch/arm/plat-s3c64xx/irq-eint.c @@ -55,7 +55,7 @@ static void s3c_irq_eint_unmask(unsigned int irq) u32 mask; mask = __raw_readl(S3C64XX_EINT0MASK); - mask |= eint_irq_to_bit(irq); + mask &= ~eint_irq_to_bit(irq); __raw_writel(mask, S3C64XX_EINT0MASK); } -- cgit v1.2.3-70-g09d2 From 28fd2d397bab5c7fb0eed0c20b6766c99ae34a8f Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 12 Dec 2008 00:24:33 +0000 Subject: [ARM] S3C64XX: Set GPIO pin when select IRQ_EINT type Set the GPIO pin mode to external interrupt when configuring an IRQ_EINT's IRQ type. Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/irq-eint.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c index 1f7cc0067f5..5d62f2799ea 100644 --- a/arch/arm/plat-s3c64xx/irq-eint.c +++ b/arch/arm/plat-s3c64xx/irq-eint.c @@ -14,12 +14,15 @@ #include #include +#include #include #include #include #include +#include +#include #include #include @@ -74,6 +77,7 @@ static void s3c_irq_eint_maskack(unsigned int irq) static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type) { int offs = eint_offset(irq); + int pin; int shift; u32 ctrl, mask; u32 newvalue = 0; @@ -125,6 +129,15 @@ static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type) ctrl |= newvalue << shift; __raw_writel(ctrl, reg); + /* set the GPIO pin appropriately */ + + if (offs < 23) + pin = S3C64XX_GPN(offs); + else + pin = S3C64XX_GPM(offs - 23); + + s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(2)); + return 0; } -- cgit v1.2.3-70-g09d2 From 789b4ad36c7037758309df98f1efa65d0c26527d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 26 Jan 2009 19:12:01 +0000 Subject: [ARM] S3C64XX: Fix section mismatch for s3c64xx_register_clocks() Signed-off-by: Mark Brown Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c index 136c982c68e..ad1b9682c9c 100644 --- a/arch/arm/plat-s3c64xx/clock.c +++ b/arch/arm/plat-s3c64xx/clock.c @@ -248,7 +248,7 @@ static struct clk *clks[] __initdata = { &clk_48m, }; -void s3c64xx_register_clocks(void) +void __init s3c64xx_register_clocks(void) { struct clk *clkp; int ret; -- cgit v1.2.3-70-g09d2 From 778974797793e7dcd42e3701e09c686b6419cb35 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 16:29:41 +0000 Subject: [ARM] SMDK6410: Correct I2C device name for WM8580 The WM8580 driver registers itself as "wm8580" rather than "WM8580". Signed-off-by: Mark Brown Signed-off-by: Ben Dooks --- arch/arm/mach-s3c6410/mach-smdk6410.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c index 3c4d47145c8..0436783c87d 100644 --- a/arch/arm/mach-s3c6410/mach-smdk6410.c +++ b/arch/arm/mach-s3c6410/mach-smdk6410.c @@ -146,7 +146,7 @@ static struct platform_device *smdk6410_devices[] __initdata = { static struct i2c_board_info i2c_devs0[] __initdata = { { I2C_BOARD_INFO("24c08", 0x50), }, - { I2C_BOARD_INFO("WM8580", 0X1b), }, + { I2C_BOARD_INFO("wm8580", 0x1b), }, }; static struct i2c_board_info i2c_devs1[] __initdata = { -- cgit v1.2.3-70-g09d2 From 027191a8c6602d3fb6dde3820517339e1daf191d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 16:29:43 +0000 Subject: [ARM] SMDK6410: Declare iodesc table static Shuts up a warning. Signed-off-by: Mark Brown Signed-off-by: Ben Dooks --- arch/arm/mach-s3c6410/mach-smdk6410.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c index 0436783c87d..25f7935576f 100644 --- a/arch/arm/mach-s3c6410/mach-smdk6410.c +++ b/arch/arm/mach-s3c6410/mach-smdk6410.c @@ -129,7 +129,7 @@ static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = { .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, }; -struct map_desc smdk6410_iodesc[] = {}; +static struct map_desc smdk6410_iodesc[] = {}; static struct platform_device *smdk6410_devices[] __initdata = { #ifdef CONFIG_SMDK6410_SD_CH0 -- cgit v1.2.3-70-g09d2 From 8bd8dbdf3725ce569467bd704840249869f626d6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 16:29:44 +0000 Subject: [ARM] S3C64XX: Staticise s3c64xx_init_irq_eint() It's an initcall and does not need to be exported. Signed-off-by: Mark Brown Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/irq-eint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c index 5d62f2799ea..8d1b7290aa1 100644 --- a/arch/arm/plat-s3c64xx/irq-eint.c +++ b/arch/arm/plat-s3c64xx/irq-eint.c @@ -194,7 +194,7 @@ static void s3c_irq_demux_eint20_27(unsigned int irq, struct irq_desc *desc) s3c_irq_demux_eint(20, 27); } -int __init s3c64xx_init_irq_eint(void) +static int __init s3c64xx_init_irq_eint(void) { int irq; -- cgit v1.2.3-70-g09d2 From 24d4076734b4ecf083a6be611040fe0743e59989 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 17:06:23 +0000 Subject: [ARM] S3C64XX: Do gpiolib configuration earlier arch_initcall() runs after the machine init function which means that any configuration of GPIO pins must currently be done later on, for example in callbacks from drivers. Move the initialisation earlier in order to allow machines to configure GPIOs directly in their init functions rather than having to have a callback invoked later on. Some other ARM platforms use this method. Other solutions for this include providing a special interface for setting up GPIOs en masse, adding callbacks to do the GPIO configuration from devices and doing the GPIO configuration implicitly. Signed-off-by: Mark Brown Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-s3c64xx/gpiolib.c b/arch/arm/plat-s3c64xx/gpiolib.c index cc62941d7b5..ee9188add8f 100644 --- a/arch/arm/plat-s3c64xx/gpiolib.c +++ b/arch/arm/plat-s3c64xx/gpiolib.c @@ -417,4 +417,4 @@ static __init int s3c64xx_gpiolib_init(void) return 0; } -arch_initcall(s3c64xx_gpiolib_init); +core_initcall(s3c64xx_gpiolib_init); -- cgit v1.2.3-70-g09d2 From 4271c3bd46a0f0448118cf618c7210237a98e6bf Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 26 Feb 2009 23:00:27 +0000 Subject: [ARM] S3C64XX: Rename IRQ_UHOST to IRQ_USBH The USB OHCI host device expects the IRQ definition to be named IRQ_USBH, so rename the S3C64XX IRQ header to match. Signed-off-by: Ben Dooks Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/include/plat/irqs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-s3c64xx/include/plat/irqs.h b/arch/arm/plat-s3c64xx/include/plat/irqs.h index 2846f550b72..f865bf4d709 100644 --- a/arch/arm/plat-s3c64xx/include/plat/irqs.h +++ b/arch/arm/plat-s3c64xx/include/plat/irqs.h @@ -117,7 +117,7 @@ #define IRQ_ONENAND1 S3C64XX_IRQ_VIC1(12) #define IRQ_NFC S3C64XX_IRQ_VIC1(13) #define IRQ_CFCON S3C64XX_IRQ_VIC1(14) -#define IRQ_UHOST S3C64XX_IRQ_VIC1(15) +#define IRQ_USBH S3C64XX_IRQ_VIC1(15) #define IRQ_SPI0 S3C64XX_IRQ_VIC1(16) #define IRQ_SPI1 S3C64XX_IRQ_VIC1(17) #define IRQ_IIC S3C64XX_IRQ_VIC1(18) -- cgit v1.2.3-70-g09d2 From 19c5957081a6ffbf014e6c944e6aafee3c1632c3 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 26 Feb 2009 23:00:33 +0000 Subject: [ARM] S3C64XX: Fix name of USB host clock. The usb-host-bus clock should be named usb-bus-host. Signed-off-by: Ben Dooks Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/s3c6400-clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-s3c64xx/s3c6400-clock.c b/arch/arm/plat-s3c64xx/s3c6400-clock.c index 8d9a0cada66..a2f526bcb38 100644 --- a/arch/arm/plat-s3c64xx/s3c6400-clock.c +++ b/arch/arm/plat-s3c64xx/s3c6400-clock.c @@ -351,7 +351,7 @@ static struct clksrc_clk clk_mmc2 = { static struct clksrc_clk clk_usbhost = { .clk = { - .name = "usb-host-bus", + .name = "usb-bus-host", .id = -1, .ctrlbit = S3C_CLKCON_SCLK_UHOST, .enable = s3c64xx_sclk_ctrl, -- cgit v1.2.3-70-g09d2 From 41ba41d7c7e1d2a3c9cdfe16c1ee9f7af4693ae2 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 26 Feb 2009 23:00:34 +0000 Subject: [ARM] S3C64XX: Fix USB host clock mux list The clock list for the USB host bus clock was in the wrong order, move clk_48m to position 0. Signed-off-by: Ben Dooks Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/s3c6400-clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-s3c64xx/s3c6400-clock.c b/arch/arm/plat-s3c64xx/s3c6400-clock.c index a2f526bcb38..2984270b40a 100644 --- a/arch/arm/plat-s3c64xx/s3c6400-clock.c +++ b/arch/arm/plat-s3c64xx/s3c6400-clock.c @@ -189,10 +189,10 @@ static struct clk_sources clkset_uart = { }; static struct clk *clkset_uhost_list[] = { + &clk_48m, &clk_mout_epll.clk, &clk_dout_mpll, &clk_fin_epll, - &clk_48m, }; static struct clk_sources clkset_uhost = { -- cgit v1.2.3-70-g09d2 From 3782d3605522b836f53c6d11f76abf5404425c1b Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 27 Feb 2009 11:25:37 +0000 Subject: [ARM] S3C64XX: sparse warnings in arch/arm/plat-s3c64xx/s3c6400-clock.c Fix the following sparse warnings in s3c6400-clock.c: 39:12: warning: symbol 'clk_ext_xtal_mux' was not declared. Should it be static? 66:12: warning: symbol 'clk_fout_apll' was not declared. Should it be static? 81:19: warning: symbol 'clk_mout_apll' was not declared. Should it be static? 91:12: warning: symbol 'clk_fout_epll' was not declared. Should it be static? 106:19: warning: symbol 'clk_mout_epll' was not declared. Should it be static? 126:19: warning: symbol 'clk_mout_mpll' was not declared. Should it be static? 148:12: warning: symbol 'clk_dout_mpll' was not declared. Should it be static? Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/s3c6400-clock.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-s3c64xx/s3c6400-clock.c b/arch/arm/plat-s3c64xx/s3c6400-clock.c index 2984270b40a..6edbeef6aa9 100644 --- a/arch/arm/plat-s3c64xx/s3c6400-clock.c +++ b/arch/arm/plat-s3c64xx/s3c6400-clock.c @@ -36,7 +36,7 @@ * ext_xtal_mux for want of an actual name from the manual. */ -struct clk clk_ext_xtal_mux = { +static struct clk clk_ext_xtal_mux = { .name = "ext_xtal", .id = -1, }; @@ -63,7 +63,7 @@ struct clksrc_clk { void __iomem *reg_divider; }; -struct clk clk_fout_apll = { +static struct clk clk_fout_apll = { .name = "fout_apll", .id = -1, }; @@ -78,7 +78,7 @@ static struct clk_sources clk_src_apll = { .nr_sources = ARRAY_SIZE(clk_src_apll_list), }; -struct clksrc_clk clk_mout_apll = { +static struct clksrc_clk clk_mout_apll = { .clk = { .name = "mout_apll", .id = -1, @@ -88,7 +88,7 @@ struct clksrc_clk clk_mout_apll = { .sources = &clk_src_apll, }; -struct clk clk_fout_epll = { +static struct clk clk_fout_epll = { .name = "fout_epll", .id = -1, }; @@ -103,7 +103,7 @@ static struct clk_sources clk_src_epll = { .nr_sources = ARRAY_SIZE(clk_src_epll_list), }; -struct clksrc_clk clk_mout_epll = { +static struct clksrc_clk clk_mout_epll = { .clk = { .name = "mout_epll", .id = -1, @@ -123,7 +123,7 @@ static struct clk_sources clk_src_mpll = { .nr_sources = ARRAY_SIZE(clk_src_mpll_list), }; -struct clksrc_clk clk_mout_mpll = { +static struct clksrc_clk clk_mout_mpll = { .clk = { .name = "mout_mpll", .id = -1, @@ -145,7 +145,7 @@ static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk) return rate; } -struct clk clk_dout_mpll = { +static struct clk clk_dout_mpll = { .name = "dout_mpll", .id = -1, .parent = &clk_mout_mpll.clk, -- cgit v1.2.3-70-g09d2 From fdca9bf2dae14218704ddd7dc60ad1b198c1d787 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 27 Feb 2009 11:29:23 +0000 Subject: [ARM] S3C64XX: sparse warnings in arch/arm/plat-s3c64xx/irq.c Fix the following sparse warnings in arch/arm/plat-s3c64xx/irq.c arch/arm/plat-s3c64xx/irq.c:210:23: warning: incorrect type in initializer (different address spaces) arch/arm/plat-s3c64xx/irq.c:210:23: expected void *reg_base arch/arm/plat-s3c64xx/irq.c:210:23: got void [noderef] *regs arch/arm/plat-s3c64xx/irq.c:215:2: warning: incorrect type in argument 1 (different address spaces) arch/arm/plat-s3c64xx/irq.c:215:2: expected void const volatile [noderef] * arch/arm/plat-s3c64xx/irq.c:215:2: got void * Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-s3c64xx/irq.c b/arch/arm/plat-s3c64xx/irq.c index a94f1d5e819..f22edf7c2d2 100644 --- a/arch/arm/plat-s3c64xx/irq.c +++ b/arch/arm/plat-s3c64xx/irq.c @@ -207,7 +207,7 @@ static struct irq_chip s3c_irq_uart = { static void __init s3c64xx_uart_irq(struct uart_irq *uirq) { - void *reg_base = uirq->regs; + void __iomem *reg_base = uirq->regs; unsigned int irq; int offs; -- cgit v1.2.3-70-g09d2 From efeff568677aa325f84d3ce37c219019887a79eb Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Fri, 27 Feb 2009 08:03:07 -0300 Subject: [ARM] S3C64XX: Fix s3c64xx_setrate_clksrc Some of the rate selection logic in s3c64xx_setrate_clksrc uses what appears to be parent clock selection logic. This patch corrects it. I also added a check for overly large dividers to prevent them from changing unrelated clocks. Signed-off-by: Werner Almesberger Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/s3c6400-clock.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-s3c64xx/s3c6400-clock.c b/arch/arm/plat-s3c64xx/s3c6400-clock.c index 6edbeef6aa9..05b17528041 100644 --- a/arch/arm/plat-s3c64xx/s3c6400-clock.c +++ b/arch/arm/plat-s3c64xx/s3c6400-clock.c @@ -239,10 +239,12 @@ static int s3c64xx_setrate_clksrc(struct clk *clk, unsigned long rate) rate = clk_round_rate(clk, rate); div = clk_get_rate(clk->parent) / rate; + if (div > 16) + return -EINVAL; val = __raw_readl(reg); - val &= ~sclk->mask; - val |= (rate - 1) << sclk->shift; + val &= ~(0xf << sclk->shift); + val |= (div - 1) << sclk->shift; __raw_writel(val, reg); return 0; -- cgit v1.2.3-70-g09d2 From 34f32c9701013ac5af89b82a6ae285e790b643e7 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 20 Feb 2009 13:45:17 -0800 Subject: usb: musb: make Davinci *work* in mainline Now that the musb build fixes for DaVinci got merged (RC3?), kick in the other bits needed to get it finally *working* in mainline: - Use clk_enable()/clk_disable() ... the "always enable USB clocks" code this originally relied on has since been removed. - Initialize the USB device only after the relevant I2C GPIOs are available, so the host side can properly enable VBUS. - Tweak init sequencing to cope with mainline's relatively late init of the I2C system bus for power switches, transceivers, and so on. Sanity tested on DM6664 EVM for host and peripheral modes; that system won't boot with CONFIG_PM enabled, so OTG can't yet be tested. Also verified on OMAP3. (Unrelated: correct the MODULE_PARM_DESC spelling of musb_debug.) Signed-off-by: David Brownell Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-davinci/board-evm.c | 6 +++--- arch/arm/mach-davinci/clock.c | 5 +++++ arch/arm/mach-davinci/usb.c | 1 + drivers/usb/musb/davinci.c | 15 ++++----------- drivers/usb/musb/musb_core.c | 8 ++++---- 5 files changed, 17 insertions(+), 18 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c index a957d239a68..38b6a9ce2a9 100644 --- a/arch/arm/mach-davinci/board-evm.c +++ b/arch/arm/mach-davinci/board-evm.c @@ -311,6 +311,9 @@ evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) gpio_request(gpio + 7, "nCF_SEL"); gpio_direction_output(gpio + 7, 1); + /* irlml6401 sustains over 3A, switches 5V in under 8 msec */ + setup_usb(500, 8); + return 0; } @@ -417,9 +420,6 @@ static __init void davinci_evm_init(void) platform_add_devices(davinci_evm_devices, ARRAY_SIZE(davinci_evm_devices)); evm_init_i2c(); - - /* irlml6401 sustains over 3A, switches 5V in under 8 msec */ - setup_usb(500, 8); } static __init void davinci_evm_irq_init(void) diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 28f6dbc95bd..abb92b7eca0 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -230,6 +230,11 @@ static struct clk davinci_clks[] = { .rate = &commonrate, .lpsc = DAVINCI_LPSC_GPIO, }, + { + .name = "usb", + .rate = &commonrate, + .lpsc = DAVINCI_LPSC_USB, + }, { .name = "AEMIFCLK", .rate = &commonrate, diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c index 867ead2559a..69680784448 100644 --- a/arch/arm/mach-davinci/usb.c +++ b/arch/arm/mach-davinci/usb.c @@ -47,6 +47,7 @@ static struct musb_hdrc_platform_data usb_data = { #elif defined(CONFIG_USB_MUSB_HOST) .mode = MUSB_HOST, #endif + .clock = "usb", .config = &musb_config, }; diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 5a8fd5d57a1..2dc7606f319 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -377,18 +377,8 @@ int __init musb_platform_init(struct musb *musb) u32 revision; musb->mregs += DAVINCI_BASE_OFFSET; -#if 0 - /* REVISIT there's something odd about clocking, this - * didn't appear do the job ... - */ - musb->clock = clk_get(pDevice, "usb"); - if (IS_ERR(musb->clock)) - return PTR_ERR(musb->clock); - status = clk_enable(musb->clock); - if (status < 0) - return -ENODEV; -#endif + clk_enable(musb->clock); /* returns zero if e.g. not clocked */ revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); @@ -453,5 +443,8 @@ int musb_platform_exit(struct musb *musb) } phy_off(); + + clk_disable(musb->clock); + return 0; } diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 2cc34fa05b7..b120fdcd889 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -115,7 +115,7 @@ unsigned musb_debug; -module_param(musb_debug, uint, S_IRUGO | S_IWUSR); +module_param_named(debug, musb_debug, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" @@ -2243,10 +2243,10 @@ static int __init musb_init(void) return platform_driver_probe(&musb_driver, musb_probe); } -/* make us init after usbcore and before usb - * gadget and host-side drivers start to register +/* make us init after usbcore and i2c (transceivers, regulators, etc) + * and before usb gadget and host-side drivers start to register */ -subsys_initcall(musb_init); +fs_initcall(musb_init); static void __exit musb_cleanup(void) { -- cgit v1.2.3-70-g09d2 From 07555c9880da3e2e96e5eae00a03b44cc076deaf Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 2 Mar 2009 22:29:37 -0800 Subject: OMAP: enable smc911x support for LDP platform The following patch enables SMC911x support to work on the OMAP LDP board. Although the SMC911x driver will eventually be obsoleted, the smsc911x patches are rather invasive for the -rc kernels. Rather than risk destablising smsc911x, this simpler patch is preferred to allow the network interface to work. Signed-off-by: Russell King Acked-by: Tony Lindgren Signed-off-by: David S. Miller --- arch/arm/mach-omap2/board-ldp.c | 2 +- drivers/net/smc911x.h | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index f6a13451d1f..6031e179926 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -81,7 +81,7 @@ static inline void __init ldp_init_smc911x(void) } ldp_smc911x_resources[0].start = cs_mem_base + 0x0; - ldp_smc911x_resources[0].end = cs_mem_base + 0xf; + ldp_smc911x_resources[0].end = cs_mem_base + 0xff; udelay(100); eth_gpio = LDP_SMC911X_GPIO; diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h index 870b4c33f10..a45952e7201 100644 --- a/drivers/net/smc911x.h +++ b/drivers/net/smc911x.h @@ -42,6 +42,16 @@ #define SMC_USE_16BIT 0 #define SMC_USE_32BIT 1 #define SMC_IRQ_SENSE IRQF_TRIGGER_LOW +#elif defined(CONFIG_ARCH_OMAP34XX) + #define SMC_USE_16BIT 0 + #define SMC_USE_32BIT 1 + #define SMC_IRQ_SENSE IRQF_TRIGGER_LOW + #define SMC_MEM_RESERVED 1 +#elif defined(CONFIG_ARCH_OMAP24XX) + #define SMC_USE_16BIT 0 + #define SMC_USE_32BIT 1 + #define SMC_IRQ_SENSE IRQF_TRIGGER_LOW + #define SMC_MEM_RESERVED 1 #else /* * Default configuration @@ -675,6 +685,7 @@ smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr, #define CHIP_9116 0x0116 #define CHIP_9117 0x0117 #define CHIP_9118 0x0118 +#define CHIP_9211 0x9211 #define CHIP_9215 0x115A #define CHIP_9217 0x117A #define CHIP_9218 0x118A @@ -689,6 +700,7 @@ static const struct chip_id chip_ids[] = { { CHIP_9116, "LAN9116" }, { CHIP_9117, "LAN9117" }, { CHIP_9118, "LAN9118" }, + { CHIP_9211, "LAN9211" }, { CHIP_9215, "LAN9215" }, { CHIP_9217, "LAN9217" }, { CHIP_9218, "LAN9218" }, -- cgit v1.2.3-70-g09d2 From 25ef4a67e78e1322d55f0a38783537ed89addc02 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 2 Mar 2009 22:39:36 +0100 Subject: [ARM] 5416/1: Use unused address in v6_early_abort The target of the strex instruction to clear the exlusive monitor is currently the top of the stack. If the store succeeeds this corrupts r0 in pt_regs. Use the next stack location instead of the current one to prevent any chance of corrupting an in-use address. Signed-off-by: Seth Forshee Signed-off-by: Russell King --- arch/arm/mm/abort-ev6.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S index 8a7f65ba14b..94077fbd96b 100644 --- a/arch/arm/mm/abort-ev6.S +++ b/arch/arm/mm/abort-ev6.S @@ -23,7 +23,8 @@ ENTRY(v6_early_abort) #ifdef CONFIG_CPU_32v6K clrex #else - strex r0, r1, [sp] @ Clear the exclusive monitor + sub r1, sp, #4 @ Get unused stack location + strex r0, r1, [r1] @ Clear the exclusive monitor #endif mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR -- cgit v1.2.3-70-g09d2 From b57ee99fab25dbc12150fe66fe54dc52bc6de784 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 3 Mar 2009 11:44:12 +0100 Subject: [ARM] 5417/1: Set the correct cacheid for ARMv6 CPUs with ARMv7 style MMU The cacheid_init() function assumes that if cpu_architecture() returns 7, the caches are VIPT_NONALIASING. The cpu_architecture() function returns the version of the supported MMU features (e.g. TEX remapping) but it doesn't make any assumptions about the cache type. The patch adds the checking of the Cache Type Register for the ARMv7 format. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 7049815d66d..68d6494c038 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -233,12 +233,13 @@ static void __init cacheid_init(void) unsigned int cachetype = read_cpuid_cachetype(); unsigned int arch = cpu_architecture(); - if (arch >= CPU_ARCH_ARMv7) { - cacheid = CACHEID_VIPT_NONALIASING; - if ((cachetype & (3 << 14)) == 1 << 14) - cacheid |= CACHEID_ASID_TAGGED; - } else if (arch >= CPU_ARCH_ARMv6) { - if (cachetype & (1 << 23)) + if (arch >= CPU_ARCH_ARMv6) { + if ((cachetype & (7 << 29)) == 4 << 29) { + /* ARMv7 register format */ + cacheid = CACHEID_VIPT_NONALIASING; + if ((cachetype & (3 << 14)) == 1 << 14) + cacheid |= CACHEID_ASID_TAGGED; + } else if (cachetype & (1 << 23)) cacheid = CACHEID_VIPT_ALIASING; else cacheid = CACHEID_VIPT_NONALIASING; -- cgit v1.2.3-70-g09d2 From f45964ed6971db2e7ae6cb9b164def1d23b46612 Mon Sep 17 00:00:00 2001 From: Saeed Bishara Date: Mon, 2 Mar 2009 17:30:36 +0200 Subject: [ARM] orion5x: pass dram mbus data to xor driver This data should be passed to the xor driver in order to initialize the address decoding windows of the xor unit. without this patch, the self tests of the xor will fail unless the address decoding windows were initialized by the boot loader. Signed-off-by: Saeed Bishara Signed-off-by: Nicolas Pitre --- arch/arm/mach-orion5x/common.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 0a623379789..8a0e49d8425 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -431,6 +431,10 @@ void __init orion5x_uart1_init(void) /***************************************************************************** * XOR engine ****************************************************************************/ +struct mv_xor_platform_shared_data orion5x_xor_shared_data = { + .dram = &orion5x_mbus_dram_info, +}; + static struct resource orion5x_xor_shared_resources[] = { { .name = "xor low", @@ -448,6 +452,9 @@ static struct resource orion5x_xor_shared_resources[] = { static struct platform_device orion5x_xor_shared = { .name = MV_XOR_SHARED_NAME, .id = 0, + .dev = { + .platform_data = &orion5x_xor_shared_data, + }, .num_resources = ARRAY_SIZE(orion5x_xor_shared_resources), .resource = orion5x_xor_shared_resources, }; -- cgit v1.2.3-70-g09d2 From 87d99d6f7ee3ec73b2b0212427b173502ec9d6cb Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 4 Mar 2009 10:07:40 -0800 Subject: ARM: OMAP: Fix compile error if pm.h is included Change the error to a warning. Signed-off-by: David Brownell Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/mach/pm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/include/mach/pm.h b/arch/arm/plat-omap/include/mach/pm.h index 2a9c27ad4c3..37e2f0f38b4 100644 --- a/arch/arm/plat-omap/include/mach/pm.h +++ b/arch/arm/plat-omap/include/mach/pm.h @@ -108,7 +108,7 @@ !defined(CONFIG_ARCH_OMAP15XX) && \ !defined(CONFIG_ARCH_OMAP16XX) && \ !defined(CONFIG_ARCH_OMAP24XX) -#error "Power management for this processor not implemented yet" +#warning "Power management for this processor not implemented yet" #endif #ifndef __ASSEMBLER__ -- cgit v1.2.3-70-g09d2 From 80ea3bac3a47bc73efa334d0dd57099d0ff14216 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 4 Mar 2009 10:07:41 -0800 Subject: ARM: OMAP: sched_clock() corrected After my OMAP3 board has been running for a while, I'm seeing weird latency traces like this: sh-1574 0d.h2 153us : do_timer (tick_do_update_jiffies64) sh-1574 0d.h2 153us : update_wall_time (do_timer) sh-1574 0d.h2 153us!: omap_32k_read (update_wall_time) sh-1574 0d.h2 1883us : update_xtime_cache (update_wall_time) sh-1574 0d.h2 1883us : clocksource_get_next (update_wall_time) sh-1574 0d.h2 1883us+: _spin_lock_irqsave (clocksource_get_next) and after a while: sh-17818 0d.h3 153us : do_timer (tick_do_update_jiffies64) sh-17818 0d.h3 153us : update_wall_time (do_timer) sh-17818 0d.h3 153us!: omap_32k_read (update_wall_time) sh-17818 0d.h3 1915us : update_xtime_cache (update_wall_time) sh-17818 0d.h3 1915us+: clocksource_get_next (update_wall_time) sh-17818 0d.h3 1945us : _spin_lock_irqsave (clocksource_get_next) Turns out that sched_clock() is using cyc2ns(), which returns NTP adjusted time. The sched_clock() frequency should not be adjusted. The patch deletes omap_32k_ticks_to_nsecs() and rewrites sched_clock() to do the conversion using the constant multiplier. Signed-off-by: Aaro Koskinen Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/common.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index 0843b8882f9..6825fbb5a05 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -199,21 +199,17 @@ static struct clocksource clocksource_32k = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -/* - * Rounds down to nearest nsec. - */ -unsigned long long omap_32k_ticks_to_nsecs(unsigned long ticks_32k) -{ - return cyc2ns(&clocksource_32k, ticks_32k); -} - /* * Returns current time from boot in nsecs. It's OK for this to wrap * around for now, as it's just a relative time stamp. */ unsigned long long sched_clock(void) { - return omap_32k_ticks_to_nsecs(omap_32k_read()); + unsigned long long ret; + + ret = (unsigned long long)omap_32k_read(); + ret = (ret * clocksource_32k.mult_orig) >> clocksource_32k.shift; + return ret; } static int __init omap_init_clocksource_32k(void) -- cgit v1.2.3-70-g09d2 From e951651657610305c9af0045fd64c6a5b0bc4b80 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 4 Mar 2009 10:07:41 -0800 Subject: ARM: OMAP: Allow I2C bus driver to be compiled as a module Fixes a linker error when OMAP I2C bus driver is compiled as a module: ERROR: "i2c_register_board_info" [arch/arm/plat-omap/i2c.ko] undefined! The I2C utility functions used for board initialization should be always built-in. Signed-off-by: Aaro Koskinen Acked-by: Jarkko Nikula Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/Makefile | 3 ++- arch/arm/plat-omap/include/mach/common.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index deaff58878a..04a100cfb8e 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -18,7 +18,8 @@ obj-$(CONFIG_CPU_FREQ) += cpu-omap.o obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o -obj-$(CONFIG_I2C_OMAP) += i2c.o +i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o +obj-y += $(i2c-omap-m) $(i2c-omap-y) # OMAP mailbox framework obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o diff --git a/arch/arm/plat-omap/include/mach/common.h b/arch/arm/plat-omap/include/mach/common.h index ef70e2b0f05..e746ec7e785 100644 --- a/arch/arm/plat-omap/include/mach/common.h +++ b/arch/arm/plat-omap/include/mach/common.h @@ -35,7 +35,7 @@ extern void omap_map_common_io(void); extern struct sys_timer omap_timer; extern void omap_serial_init(void); extern void omap_serial_enable_clocks(int enable); -#ifdef CONFIG_I2C_OMAP +#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) extern int omap_register_i2c_bus(int bus_id, u32 clkrate, struct i2c_board_info const *info, unsigned len); -- cgit v1.2.3-70-g09d2 From 8ca7fe267f58462825729443f3e3b44ef4901cf0 Mon Sep 17 00:00:00 2001 From: Koen Kooi Date: Wed, 4 Mar 2009 10:07:42 -0800 Subject: ARM: OMAP: board-omap3beagle: set i2c-3 to 100kHz Changing it do 100kHz is needed to make more devices works properly. Controlling the TI DLP Pico projector[1] doesn't work properly at 400kHz, 100kHz and lower work fine. EDID readout is unaffected by this change. [1] http://focus.ti.com/dlpdmd/docs/dlpdiscovery.tsp?sectionId=60&tabId=2234 Signed-off-by: Koen Kooi Acked-by: David Brownell Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-omap3beagle.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 38c88fbe658..e39cd2c46cf 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -178,7 +178,9 @@ static int __init omap3_beagle_i2c_init(void) #ifdef CONFIG_I2C2_OMAP_BEAGLE omap_register_i2c_bus(2, 400, NULL, 0); #endif - omap_register_i2c_bus(3, 400, NULL, 0); + /* Bus 3 is attached to the DVI port where devices like the pico DLP + * projector don't work reliably with 400kHz */ + omap_register_i2c_bus(3, 100, NULL, 0); return 0; } -- cgit v1.2.3-70-g09d2 From d4cc510c61b050ef38e842a12feef71c56d7cf81 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 4 Mar 2009 11:48:46 +0100 Subject: [ARM] 5418/1: restore lr before leaving mcount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc seems to expect that lr isn't clobbered by mcount, because for a function starting with: static int func(void) { void *ra = __builtin_return_address(0); printk(KERN_EMERG "__builtin_return_address(0) = %pS\n", ra) ... the following assembler is generated by gcc 4.3.2: 0: e1a0c00d mov ip, sp 4: e92dd810 push {r4, fp, ip, lr, pc} 8: e24cb004 sub fp, ip, #4 ; 0x4 c: ebfffffe bl 0 10: e59f0034 ldr r0, [pc, #52] 14: e1a0100e mov r1, lr 18: ebfffffe bl 0 Without this patch obviously __builtin_return_address(0) yields func+0x10 instead of the return address of the caller. Note this patch fixes a similar issue for the routines used with dynamic ftrace even though this isn't currently selectable for ARM. Cc: Abhishek Sagar Cc: Steven Rostedt Cc: Ingo Molnar Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 49a6ba926c2..159d0416f27 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -111,6 +111,7 @@ ENTRY(mcount) .globl mcount_call mcount_call: bl ftrace_stub + ldr lr, [fp, #-4] @ restore lr ldmia sp!, {r0-r3, pc} ENTRY(ftrace_caller) @@ -122,6 +123,7 @@ ENTRY(ftrace_caller) .globl ftrace_call ftrace_call: bl ftrace_stub + ldr lr, [fp, #-4] @ restore lr ldmia sp!, {r0-r3, pc} #else @@ -133,6 +135,7 @@ ENTRY(mcount) adr r0, ftrace_stub cmp r0, r2 bne trace + ldr lr, [fp, #-4] @ restore lr ldmia sp!, {r0-r3, pc} trace: @@ -141,6 +144,7 @@ trace: sub r0, r0, #MCOUNT_INSN_SIZE mov lr, pc mov pc, r2 + mov lr, r1 @ restore lr ldmia sp!, {r0-r3, pc} #endif /* CONFIG_DYNAMIC_FTRACE */ -- cgit v1.2.3-70-g09d2 From 6e5f1e1115bb041993f9f247036996364b4c84d5 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 5 Mar 2009 16:10:58 +0100 Subject: ide: add at91_ide driver This is IDE host driver for AT91 (SAM9, CAP9, AT572D940HF) Static Memory Controller with Compact Flash True IDE Mode logic. Driver have to switch 8/16 bit bus width when accessing Task Tile or Data Register. Moreover some extra things need to be done when setting PIO mode. Only PIO mode is used, hardware have no DMA support. If interrupt line is connected through GPIO extra quirk is needed to cope with fake interrupts. Signed-off-by: Stanislaw Gruszka Cc: Andrew Victor Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- arch/arm/mach-at91/include/mach/board.h | 3 + drivers/ide/Kconfig | 5 + drivers/ide/Makefile | 1 + drivers/ide/at91_ide.c | 467 ++++++++++++++++++++++++++++++++ 4 files changed, 476 insertions(+) create mode 100644 drivers/ide/at91_ide.c (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index 0b3ae21b456..793fe7b25f3 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -56,6 +56,9 @@ struct at91_cf_data { u8 vcc_pin; /* power switching */ u8 rst_pin; /* card reset */ u8 chipselect; /* EBI Chip Select number */ + u8 flags; +#define AT91_CF_TRUE_IDE 0x01 +#define AT91_IDE_SWAP_A0_A2 0x02 }; extern void __init at91_add_device_cf(struct at91_cf_data *data); diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index e072903b12f..5ea3bfad172 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -721,6 +721,11 @@ config BLK_DEV_IDE_TX4939 depends on SOC_TX4939 select BLK_DEV_IDEDMA_SFF +config BLK_DEV_IDE_AT91 + tristate "Atmel AT91 (SAM9, CAP9, AT572D940HF) IDE support" + depends on ARM && ARCH_AT91 && !ARCH_AT91RM9200 && !ARCH_AT91X40 + select IDE_TIMINGS + config IDE_ARM tristate "ARM IDE support" depends on ARM && (ARCH_RPC || ARCH_SHARK) diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index d0e3d7d5b46..1c326d94aa6 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -116,3 +116,4 @@ obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o obj-$(CONFIG_BLK_DEV_IDE_TX4938) += tx4938ide.o obj-$(CONFIG_BLK_DEV_IDE_TX4939) += tx4939ide.o +obj-$(CONFIG_BLK_DEV_IDE_AT91) += at91_ide.o diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c new file mode 100644 index 00000000000..1bb50f46388 --- /dev/null +++ b/drivers/ide/at91_ide.c @@ -0,0 +1,467 @@ +/* + * IDE host driver for AT91 (SAM9, CAP9, AT572D940HF) Static Memory Controller + * with Compact Flash True IDE logic + * + * Copyright (c) 2008, 2009 Kelvatek Ltd. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define DRV_NAME "at91_ide" + +#define perr(fmt, args...) pr_err(DRV_NAME ": " fmt, ##args) +#define pdbg(fmt, args...) pr_debug("%s " fmt, __func__, ##args) + +/* + * Access to IDE device is possible through EBI Static Memory Controller + * with Compact Flash logic. For details see EBI and SMC datasheet sections + * of any microcontroller from AT91SAM9 family. + * + * Within SMC chip select address space, lines A[23:21] distinguish Compact + * Flash modes (I/O, common memory, attribute memory, True IDE). IDE modes are: + * 0x00c0000 - True IDE + * 0x00e0000 - Alternate True IDE (Alt Status Register) + * + * On True IDE mode Task File and Data Register are mapped at the same address. + * To distinguish access between these two different bus data width is used: + * 8Bit for Task File, 16Bit for Data I/O. + * + * After initialization we do 8/16 bit flipping (changes in SMC MODE register) + * only inside IDE callback routines which are serialized by IDE layer, + * so no additional locking needed. + */ + +#define TASK_FILE 0x00c00000 +#define ALT_MODE 0x00e00000 +#define REGS_SIZE 8 + +#define enter_16bit(cs, mode) do { \ + mode = at91_sys_read(AT91_SMC_MODE(cs)); \ + at91_sys_write(AT91_SMC_MODE(cs), mode | AT91_SMC_DBW_16); \ +} while (0) + +#define leave_16bit(cs, mode) at91_sys_write(AT91_SMC_MODE(cs), mode); + +static void set_smc_timings(const u8 chipselect, const u16 cycle, + const u16 setup, const u16 pulse, + const u16 data_float, int use_iordy) +{ + unsigned long mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | + AT91_SMC_BAT_SELECT; + + /* disable or enable waiting for IORDY signal */ + if (use_iordy) + mode |= AT91_SMC_EXNWMODE_READY; + + /* add data float cycles if needed */ + if (data_float) + mode |= AT91_SMC_TDF_(data_float); + + at91_sys_write(AT91_SMC_MODE(chipselect), mode); + + /* setup timings in SMC */ + at91_sys_write(AT91_SMC_SETUP(chipselect), AT91_SMC_NWESETUP_(setup) | + AT91_SMC_NCS_WRSETUP_(0) | + AT91_SMC_NRDSETUP_(setup) | + AT91_SMC_NCS_RDSETUP_(0)); + at91_sys_write(AT91_SMC_PULSE(chipselect), AT91_SMC_NWEPULSE_(pulse) | + AT91_SMC_NCS_WRPULSE_(cycle) | + AT91_SMC_NRDPULSE_(pulse) | + AT91_SMC_NCS_RDPULSE_(cycle)); + at91_sys_write(AT91_SMC_CYCLE(chipselect), AT91_SMC_NWECYCLE_(cycle) | + AT91_SMC_NRDCYCLE_(cycle)); +} + +static unsigned int calc_mck_cycles(unsigned int ns, unsigned int mck_hz) +{ + u64 tmp = ns; + + tmp *= mck_hz; + tmp += 1000*1000*1000 - 1; /* round up */ + do_div(tmp, 1000*1000*1000); + return (unsigned int) tmp; +} + +static void apply_timings(const u8 chipselect, const u8 pio, + const struct ide_timing *timing, int use_iordy) +{ + unsigned int t0, t1, t2, t6z; + unsigned int cycle, setup, pulse, data_float; + unsigned int mck_hz; + struct clk *mck; + + /* see table 22 of Compact Flash standard 4.1 for the meaning, + * we do not stretch active (t2) time, so setup (t1) + hold time (th) + * assure at least minimal recovery (t2i) time */ + t0 = timing->cyc8b; + t1 = timing->setup; + t2 = timing->act8b; + t6z = (pio < 5) ? 30 : 20; + + pdbg("t0=%u t1=%u t2=%u t6z=%u\n", t0, t1, t2, t6z); + + mck = clk_get(NULL, "mck"); + BUG_ON(IS_ERR(mck)); + mck_hz = clk_get_rate(mck); + pdbg("mck_hz=%u\n", mck_hz); + + cycle = calc_mck_cycles(t0, mck_hz); + setup = calc_mck_cycles(t1, mck_hz); + pulse = calc_mck_cycles(t2, mck_hz); + data_float = calc_mck_cycles(t6z, mck_hz); + + pdbg("cycle=%u setup=%u pulse=%u data_float=%u\n", + cycle, setup, pulse, data_float); + + set_smc_timings(chipselect, cycle, setup, pulse, data_float, use_iordy); +} + +static void at91_ide_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + u8 chipselect = hwif->select_data; + unsigned long mode; + + pdbg("cs %u buf %p len %d\n", chipselect, buf, len); + + len++; + + enter_16bit(chipselect, mode); + __ide_mm_insw((void __iomem *) io_ports->data_addr, buf, len / 2); + leave_16bit(chipselect, mode); +} + +static void at91_ide_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + u8 chipselect = hwif->select_data; + unsigned long mode; + + pdbg("cs %u buf %p len %d\n", chipselect, buf, len); + + enter_16bit(chipselect, mode); + __ide_mm_outsw((void __iomem *) io_ports->data_addr, buf, len / 2); + leave_16bit(chipselect, mode); +} + +static u8 ide_mm_inb(unsigned long port) +{ + return readb((void __iomem *) port); +} + +static void ide_mm_outb(u8 value, unsigned long port) +{ + writeb(value, (void __iomem *) port); +} + +static void at91_ide_tf_load(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + HIHI = 0xFF; + + if (task->tf_flags & IDE_TFLAG_OUT_DATA) { + u16 data = (tf->hob_data << 8) | tf->data; + + at91_ide_output_data(drive, NULL, &data, 2); + } + + if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) + ide_mm_outb(tf->hob_feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) + ide_mm_outb(tf->hob_nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) + ide_mm_outb(tf->hob_lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) + ide_mm_outb(tf->hob_lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) + ide_mm_outb(tf->hob_lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) + ide_mm_outb(tf->feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_NSECT) + ide_mm_outb(tf->nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAL) + ide_mm_outb(tf->lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAM) + ide_mm_outb(tf->lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAH) + ide_mm_outb(tf->lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) + ide_mm_outb((tf->device & HIHI) | drive->select, io_ports->device_addr); +} + +static void at91_ide_tf_read(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data; + + at91_ide_input_data(drive, NULL, &data, 2); + tf->data = data & 0xff; + tf->hob_data = (data >> 8) & 0xff; + } + + /* be sure we're looking at the low order bits */ + ide_mm_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_FEATURE) + tf->feature = ide_mm_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = ide_mm_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = ide_mm_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = ide_mm_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = ide_mm_inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = ide_mm_inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + ide_mm_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = ide_mm_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = ide_mm_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = ide_mm_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = ide_mm_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = ide_mm_inb(io_ports->lbah_addr); + } +} + +static void at91_ide_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + struct ide_timing *timing; + u8 chipselect = drive->hwif->select_data; + int use_iordy = 0; + + pdbg("chipselect %u pio %u\n", chipselect, pio); + + timing = ide_timing_find_mode(XFER_PIO_0 + pio); + BUG_ON(!timing); + + if ((pio > 2 || ata_id_has_iordy(drive->id)) && + !(ata_id_is_cfa(drive->id) && pio > 4)) + use_iordy = 1; + + apply_timings(chipselect, pio, timing, use_iordy); +} + +static const struct ide_tp_ops at91_ide_tp_ops = { + .exec_command = ide_exec_command, + .read_status = ide_read_status, + .read_altstatus = ide_read_altstatus, + .set_irq = ide_set_irq, + + .tf_load = at91_ide_tf_load, + .tf_read = at91_ide_tf_read, + + .input_data = at91_ide_input_data, + .output_data = at91_ide_output_data, +}; + +static const struct ide_port_ops at91_ide_port_ops = { + .set_pio_mode = at91_ide_set_pio_mode, +}; + +static const struct ide_port_info at91_ide_port_info __initdata = { + .port_ops = &at91_ide_port_ops, + .tp_ops = &at91_ide_tp_ops, + .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE | + IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS, + .pio_mask = ATA_PIO5, +}; + +/* + * If interrupt is delivered through GPIO, IRQ are triggered on falling + * and rising edge of signal. Whereas IDE device request interrupt on high + * level (rising edge in our case). This mean we have fake interrupts, so + * we need to check interrupt pin and exit instantly from ISR when line + * is on low level. + */ + +irqreturn_t at91_irq_handler(int irq, void *dev_id) +{ + int ntries = 8; + int pin_val1, pin_val2; + + /* additional deglitch, line can be noisy in badly designed PCB */ + do { + pin_val1 = at91_get_gpio_value(irq); + pin_val2 = at91_get_gpio_value(irq); + } while (pin_val1 != pin_val2 && --ntries > 0); + + if (pin_val1 == 0 || ntries <= 0) + return IRQ_HANDLED; + + return ide_intr(irq, dev_id); +} + +static int __init at91_ide_probe(struct platform_device *pdev) +{ + int ret; + hw_regs_t hw; + hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; + struct ide_host *host; + struct resource *res; + unsigned long tf_base = 0, ctl_base = 0; + struct at91_cf_data *board = pdev->dev.platform_data; + + if (!board) + return -ENODEV; + + if (board->det_pin && at91_get_gpio_value(board->det_pin) != 0) { + perr("no device detected\n"); + return -ENODEV; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + perr("can't get memory resource\n"); + return -ENODEV; + } + + if (!devm_request_mem_region(&pdev->dev, res->start + TASK_FILE, + REGS_SIZE, "ide") || + !devm_request_mem_region(&pdev->dev, res->start + ALT_MODE, + REGS_SIZE, "alt")) { + perr("memory resources in use\n"); + return -EBUSY; + } + + pdbg("chipselect %u irq %u res %08lx\n", board->chipselect, + board->irq_pin, (unsigned long) res->start); + + tf_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + TASK_FILE, + REGS_SIZE); + ctl_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + ALT_MODE, + REGS_SIZE); + if (!tf_base || !ctl_base) { + perr("can't map memory regions\n"); + return -EBUSY; + } + + memset(&hw, 0, sizeof(hw)); + + if (board->flags & AT91_IDE_SWAP_A0_A2) { + /* workaround for stupid hardware bug */ + hw.io_ports.data_addr = tf_base + 0; + hw.io_ports.error_addr = tf_base + 4; + hw.io_ports.nsect_addr = tf_base + 2; + hw.io_ports.lbal_addr = tf_base + 6; + hw.io_ports.lbam_addr = tf_base + 1; + hw.io_ports.lbah_addr = tf_base + 5; + hw.io_ports.device_addr = tf_base + 3; + hw.io_ports.command_addr = tf_base + 7; + hw.io_ports.ctl_addr = ctl_base + 3; + } else + ide_std_init_ports(&hw, tf_base, ctl_base + 6); + + hw.irq = board->irq_pin; + hw.chipset = ide_generic; + hw.dev = &pdev->dev; + + host = ide_host_alloc(&at91_ide_port_info, hws); + if (!host) { + perr("failed to allocate ide host\n"); + return -ENOMEM; + } + + /* setup Static Memory Controller - PIO 0 as default */ + apply_timings(board->chipselect, 0, ide_timing_find_mode(XFER_PIO_0), 0); + + /* with GPIO interrupt we have to do quirks in handler */ + if (board->irq_pin >= PIN_BASE) + host->irq_handler = at91_irq_handler; + + host->ports[0]->select_data = board->chipselect; + + ret = ide_host_register(host, &at91_ide_port_info, hws); + if (ret) { + perr("failed to register ide host\n"); + goto err_free_host; + } + platform_set_drvdata(pdev, host); + return 0; + +err_free_host: + ide_host_free(host); + return ret; +} + +static int __exit at91_ide_remove(struct platform_device *pdev) +{ + struct ide_host *host = platform_get_drvdata(pdev); + + ide_host_remove(host); + return 0; +} + +static struct platform_driver at91_ide_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .remove = __exit_p(at91_ide_remove), +}; + +static int __init at91_ide_init(void) +{ + return platform_driver_probe(&at91_ide_driver, at91_ide_probe); +} + +static void __exit at91_ide_exit(void) +{ + platform_driver_unregister(&at91_ide_driver); +} + +module_init(at91_ide_init); +module_exit(at91_ide_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Stanislaw Gruszka "); + -- cgit v1.2.3-70-g09d2 From e565f206082a725108a75bcf00bbe3db21a56474 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 5 Mar 2009 16:10:58 +0100 Subject: AT91: initialize Compact Flash on AT91SAM9263 cpu Signed-off-by: Stanislaw Gruszka Cc: Andrew Victor Acked-by: Sergei Shtylyov Acked-by: Andrew Victor Signed-off-by: Bartlomiej Zolnierkiewicz --- arch/arm/mach-at91/at91sam9263_devices.c | 105 +++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 134af97ff34..b7f23324231 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -347,6 +347,111 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} #endif +/* -------------------------------------------------------------------- + * Compact Flash (PCMCIA or IDE) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) || \ + defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE) + +static struct at91_cf_data cf0_data; + +static struct resource cf0_resources[] = { + [0] = { + .start = AT91_CHIPSELECT_4, + .end = AT91_CHIPSELECT_4 + SZ_256M - 1, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, + } +}; + +static struct platform_device cf0_device = { + .id = 0, + .dev = { + .platform_data = &cf0_data, + }, + .resource = cf0_resources, + .num_resources = ARRAY_SIZE(cf0_resources), +}; + +static struct at91_cf_data cf1_data; + +static struct resource cf1_resources[] = { + [0] = { + .start = AT91_CHIPSELECT_5, + .end = AT91_CHIPSELECT_5 + SZ_256M - 1, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, + } +}; + +static struct platform_device cf1_device = { + .id = 1, + .dev = { + .platform_data = &cf1_data, + }, + .resource = cf1_resources, + .num_resources = ARRAY_SIZE(cf1_resources), +}; + +void __init at91_add_device_cf(struct at91_cf_data *data) +{ + unsigned long ebi0_csa; + struct platform_device *pdev; + + if (!data) + return; + + /* + * assign CS4 or CS5 to SMC with Compact Flash logic support, + * we assume SMC timings are configured by board code, + * except True IDE where timings are controlled by driver + */ + ebi0_csa = at91_sys_read(AT91_MATRIX_EBI0CSA); + switch (data->chipselect) { + case 4: + at91_set_A_periph(AT91_PIN_PD6, 0); /* EBI0_NCS4/CFCS0 */ + ebi0_csa |= AT91_MATRIX_EBI0_CS4A_SMC_CF1; + cf0_data = *data; + pdev = &cf0_device; + break; + case 5: + at91_set_A_periph(AT91_PIN_PD7, 0); /* EBI0_NCS5/CFCS1 */ + ebi0_csa |= AT91_MATRIX_EBI0_CS5A_SMC_CF2; + cf1_data = *data; + pdev = &cf1_device; + break; + default: + printk(KERN_ERR "AT91 CF: bad chip-select requested (%u)\n", + data->chipselect); + return; + } + at91_sys_write(AT91_MATRIX_EBI0CSA, ebi0_csa); + + if (data->det_pin) { + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + } + + if (data->irq_pin) { + at91_set_gpio_input(data->irq_pin, 1); + at91_set_deglitch(data->irq_pin, 1); + } + + if (data->vcc_pin) + /* initially off */ + at91_set_gpio_output(data->vcc_pin, 0); + + /* enable EBI controlled pins */ + at91_set_A_periph(AT91_PIN_PD5, 1); /* NWAIT */ + at91_set_A_periph(AT91_PIN_PD8, 0); /* CFCE1 */ + at91_set_A_periph(AT91_PIN_PD9, 0); /* CFCE2 */ + at91_set_A_periph(AT91_PIN_PD14, 0); /* CFNRW */ + + pdev->name = (data->flags & AT91_CF_TRUE_IDE) ? "at91_ide" : "at91_cf"; + platform_device_register(pdev); +} +#else +void __init at91_add_device_cf(struct at91_cf_data *data) {} +#endif /* -------------------------------------------------------------------- * NAND / SmartMedia -- cgit v1.2.3-70-g09d2 From ef449e6d21b6e560c7ec36ed285ec3a34e0b12ed Mon Sep 17 00:00:00 2001 From: Hartley Sweeten Date: Thu, 5 Mar 2009 17:33:50 +0100 Subject: [ARM] 5419/1: ep93xx: fix build warnings about struct i2c_board_info Fix build warnings due to struct i2c_board_info in Patch "5311/1: add core support for built in i2c bus" is causing 11 of 39 the build warnings with Kautobuild for ep93xx_defconfig on kernel 2.6.29-rc5-git4. This patch fixes it. Signed-off-by: H Hartley Sweeten Signed-off-by: Russell King --- arch/arm/mach-ep93xx/include/mach/platform.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index 88f7e88f152..05f0f4f2f3c 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -4,6 +4,8 @@ #ifndef __ASSEMBLY__ +struct i2c_board_info; + struct ep93xx_eth_data { unsigned char dev_addr[6]; -- cgit v1.2.3-70-g09d2 From 20214fcd74bddc16d65d466212f5dd32aafe8868 Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Mon, 12 Jan 2009 16:22:57 +0200 Subject: MX1 fix include Includes missed irqs.h in devices.c and mx1ads.c. Signed-off-by: Darius Augulis Signed-off-by: Sascha Hauer --- arch/arm/mach-mx1/devices.c | 2 ++ arch/arm/mach-mx1/mx1ads.c | 1 + 2 files changed, 3 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-mx1/devices.c b/arch/arm/mach-mx1/devices.c index 686d8d2dbb2..a95644193f3 100644 --- a/arch/arm/mach-mx1/devices.c +++ b/arch/arm/mach-mx1/devices.c @@ -23,6 +23,8 @@ #include #include #include + +#include #include static struct resource imx_csi_resources[] = { diff --git a/arch/arm/mach-mx1/mx1ads.c b/arch/arm/mach-mx1/mx1ads.c index 2e4b185fe4a..3200cf60e38 100644 --- a/arch/arm/mach-mx1/mx1ads.c +++ b/arch/arm/mach-mx1/mx1ads.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3-70-g09d2 From 446c92b2901bedb3725d29b4e73def8aba623ffc Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 12 Mar 2009 18:03:16 +0100 Subject: [ARM] 5421/1: ftrace: fix crash due to tracing of __naked functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a fix for the following crash observed in 2.6.29-rc3: http://lkml.org/lkml/2009/1/29/150 On ARM it doesn't make sense to trace a naked function because then mcount is called without stack and frame pointer being set up and there is no chance to restore the lr register to the value before mcount was called. Reported-by: Matthias Kaehlcke Tested-by: Matthias Kaehlcke Cc: Abhishek Sagar Cc: Steven Rostedt Cc: Ingo Molnar Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/kernel/fiq.c | 4 ++-- arch/arm/mm/copypage-feroceon.c | 2 +- arch/arm/mm/copypage-v3.c | 2 +- arch/arm/mm/copypage-v4mc.c | 2 +- arch/arm/mm/copypage-v4wb.c | 2 +- arch/arm/mm/copypage-v4wt.c | 2 +- arch/arm/mm/copypage-xsc3.c | 2 +- arch/arm/mm/copypage-xscale.c | 2 +- include/linux/compiler-gcc.h | 10 +++++++++- 9 files changed, 18 insertions(+), 10 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 36f81d96797..6ff7919613d 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -88,7 +88,7 @@ void set_fiq_handler(void *start, unsigned int length) * disable irqs for the duration. Note - these functions are almost * entirely coded in assembly. */ -void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs) +void __naked set_fiq_regs(struct pt_regs *regs) { register unsigned long tmp; asm volatile ( @@ -106,7 +106,7 @@ void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs) : "r" (®s->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)); } -void __attribute__((naked)) get_fiq_regs(struct pt_regs *regs) +void __naked get_fiq_regs(struct pt_regs *regs) { register unsigned long tmp; asm volatile ( diff --git a/arch/arm/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c index c3ba6a94da0..70997d5bee2 100644 --- a/arch/arm/mm/copypage-feroceon.c +++ b/arch/arm/mm/copypage-feroceon.c @@ -13,7 +13,7 @@ #include #include -static void __attribute__((naked)) +static void __naked feroceon_copy_user_page(void *kto, const void *kfrom) { asm("\ diff --git a/arch/arm/mm/copypage-v3.c b/arch/arm/mm/copypage-v3.c index 70ed96c8af8..de9c06854ad 100644 --- a/arch/arm/mm/copypage-v3.c +++ b/arch/arm/mm/copypage-v3.c @@ -15,7 +15,7 @@ * * FIXME: do we need to handle cache stuff... */ -static void __attribute__((naked)) +static void __naked v3_copy_user_page(void *kto, const void *kfrom) { asm("\n\ diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c index 1601698b980..7370a7142b0 100644 --- a/arch/arm/mm/copypage-v4mc.c +++ b/arch/arm/mm/copypage-v4mc.c @@ -44,7 +44,7 @@ static DEFINE_SPINLOCK(minicache_lock); * instruction. If your processor does not supply this, you have to write your * own copy_user_highpage that does the right thing. */ -static void __attribute__((naked)) +static void __naked mc_copy_user_page(void *from, void *to) { asm volatile( diff --git a/arch/arm/mm/copypage-v4wb.c b/arch/arm/mm/copypage-v4wb.c index 3ec93dab765..9ab09841422 100644 --- a/arch/arm/mm/copypage-v4wb.c +++ b/arch/arm/mm/copypage-v4wb.c @@ -22,7 +22,7 @@ * instruction. If your processor does not supply this, you have to write your * own copy_user_highpage that does the right thing. */ -static void __attribute__((naked)) +static void __naked v4wb_copy_user_page(void *kto, const void *kfrom) { asm("\ diff --git a/arch/arm/mm/copypage-v4wt.c b/arch/arm/mm/copypage-v4wt.c index 0f1188efae4..300efafd664 100644 --- a/arch/arm/mm/copypage-v4wt.c +++ b/arch/arm/mm/copypage-v4wt.c @@ -20,7 +20,7 @@ * dirty data in the cache. However, we do have to ensure that * subsequent reads are up to date. */ -static void __attribute__((naked)) +static void __naked v4wt_copy_user_page(void *kto, const void *kfrom) { asm("\ diff --git a/arch/arm/mm/copypage-xsc3.c b/arch/arm/mm/copypage-xsc3.c index 39a994542ca..bc4525f5ab2 100644 --- a/arch/arm/mm/copypage-xsc3.c +++ b/arch/arm/mm/copypage-xsc3.c @@ -29,7 +29,7 @@ * if we eventually end up using our copied page. * */ -static void __attribute__((naked)) +static void __naked xsc3_mc_copy_user_page(void *kto, const void *kfrom) { asm("\ diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c index d18f2397ee2..76824d3e966 100644 --- a/arch/arm/mm/copypage-xscale.c +++ b/arch/arm/mm/copypage-xscale.c @@ -42,7 +42,7 @@ static DEFINE_SPINLOCK(minicache_lock); * Dcache aliasing issue. The writes will be forwarded to the write buffer, * and merged as appropriate. */ -static void __attribute__((naked)) +static void __naked mc_copy_user_page(void *from, void *to) { /* diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 1514d534dee..a3ed7cb8ca3 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -52,7 +52,15 @@ #define __deprecated __attribute__((deprecated)) #define __packed __attribute__((packed)) #define __weak __attribute__((weak)) -#define __naked __attribute__((naked)) + +/* + * it doesn't make sense on ARM (currently the only user of __naked) to trace + * naked functions because then mcount is called without stack and frame pointer + * being set up and there is no chance to restore the lr register to the value + * before mcount was called. + */ +#define __naked __attribute__((naked)) notrace + #define __noreturn __attribute__((noreturn)) /* -- cgit v1.2.3-70-g09d2 From 305b07680f6c6a7e59f996c5bd85f009caff5bb1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 Mar 2009 18:03:01 +0000 Subject: [ARM] update mach-types Signed-off-by: Russell King --- arch/arm/tools/mach-types | 136 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 3 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index fd23c0e9e69..b4211d8b2ac 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Sun Nov 30 16:39:36 2008 +# Last update: Thu Mar 12 18:01:45 2009 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -1811,7 +1811,7 @@ pilz_pmi5 MACH_PILZ_PMI5 PILZ_PMI5 1820 jade MACH_JADE JADE 1821 ks8695_softplc MACH_KS8695_SOFTPLC KS8695_SOFTPLC 1822 gprisc3 MACH_GPRISC3 GPRISC3 1823 -stamp9260 MACH_STAMP9260 STAMP9260 1824 +stamp9g20 MACH_STAMP9G20 STAMP9G20 1824 smdk6430 MACH_SMDK6430 SMDK6430 1825 smdkc100 MACH_SMDKC100 SMDKC100 1826 tavorevb MACH_TAVOREVB TAVOREVB 1827 @@ -1993,4 +1993,134 @@ spark MACH_SPARK SPARK 2002 benzina MACH_BENZINA BENZINA 2003 blaze MACH_BLAZE BLAZE 2004 linkstation_ls_hgl MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL 2005 -htcvenus MACH_HTCVENUS HTCVENUS 2006 +htckovsky MACH_HTCVENUS HTCVENUS 2006 +sony_prs505 MACH_SONY_PRS505 SONY_PRS505 2007 +hanlin_v3 MACH_HANLIN_V3 HANLIN_V3 2008 +sapphira MACH_SAPPHIRA SAPPHIRA 2009 +dack_sda_01 MACH_DACK_SDA_01 DACK_SDA_01 2010 +armbox MACH_ARMBOX ARMBOX 2011 +harris_rvp MACH_HARRIS_RVP HARRIS_RVP 2012 +ribaldo MACH_RIBALDO RIBALDO 2013 +agora MACH_AGORA AGORA 2014 +omap3_mini MACH_OMAP3_MINI OMAP3_MINI 2015 +a9sam6432_b MACH_A9SAM6432_B A9SAM6432_B 2016 +usg2410 MACH_USG2410 USG2410 2017 +pc72052_i10_revb MACH_PC72052_I10_REVB PC72052_I10_REVB 2018 +mx35_exm32 MACH_MX35_EXM32 MX35_EXM32 2019 +topas910 MACH_TOPAS910 TOPAS910 2020 +hyena MACH_HYENA HYENA 2021 +pospax MACH_POSPAX POSPAX 2022 +hdl_gx MACH_HDL_GX HDL_GX 2023 +ctera_4bay MACH_CTERA_4BAY CTERA_4BAY 2024 +ctera_plug_c MACH_CTERA_PLUG_C CTERA_PLUG_C 2025 +crwea_plug_i MACH_CRWEA_PLUG_I CRWEA_PLUG_I 2026 +egauge2 MACH_EGAUGE2 EGAUGE2 2027 +didj MACH_DIDJ DIDJ 2028 +m_s3c2443 MACH_MEISTER MEISTER 2029 +htcblackstone MACH_HTCBLACKSTONE HTCBLACKSTONE 2030 +cpuat9g20 MACH_CPUAT9G20 CPUAT9G20 2031 +smdk6440 MACH_SMDK6440 SMDK6440 2032 +omap_35xx_mvp MACH_OMAP_35XX_MVP OMAP_35XX_MVP 2033 +ctera_plug_i MACH_CTERA_PLUG_I CTERA_PLUG_I 2034 +pvg610_100 MACH_PVG610 PVG610 2035 +hprw6815 MACH_HPRW6815 HPRW6815 2036 +omap3_oswald MACH_OMAP3_OSWALD OMAP3_OSWALD 2037 +nas4220b MACH_NAS4220B NAS4220B 2038 +htcraphael_cdma MACH_HTCRAPHAEL_CDMA HTCRAPHAEL_CDMA 2039 +htcdiamond_cdma MACH_HTCDIAMOND_CDMA HTCDIAMOND_CDMA 2040 +scaler MACH_SCALER SCALER 2041 +zylonite2 MACH_ZYLONITE2 ZYLONITE2 2042 +aspenite MACH_ASPENITE ASPENITE 2043 +teton MACH_TETON TETON 2044 +ttc_dkb MACH_TTC_DKB TTC_DKB 2045 +bishop2 MACH_BISHOP2 BISHOP2 2046 +ippv5 MACH_IPPV5 IPPV5 2047 +farm926 MACH_FARM926 FARM926 2048 +mmccpu MACH_MMCCPU MMCCPU 2049 +sgmsfl MACH_SGMSFL SGMSFL 2050 +tt8000 MACH_TT8000 TT8000 2051 +zrn4300lp MACH_ZRN4300LP ZRN4300LP 2052 +mptc MACH_MPTC MPTC 2053 +h6051 MACH_H6051 H6051 2054 +pvg610_101 MACH_PVG610_101 PVG610_101 2055 +stamp9261_pc_evb MACH_STAMP9261_PC_EVB STAMP9261_PC_EVB 2056 +pelco_odysseus MACH_PELCO_ODYSSEUS PELCO_ODYSSEUS 2057 +tny_a9260 MACH_TNY_A9260 TNY_A9260 2058 +tny_a9g20 MACH_TNY_A9G20 TNY_A9G20 2059 +aesop_mp2530f MACH_AESOP_MP2530F AESOP_MP2530F 2060 +dx900 MACH_DX900 DX900 2061 +cpodc2 MACH_CPODC2 CPODC2 2062 +tilt_8925 MACH_TILT_8925 TILT_8925 2063 +davinci_dm357_evm MACH_DAVINCI_DM357_EVM DAVINCI_DM357_EVM 2064 +swordfish MACH_SWORDFISH SWORDFISH 2065 +corvus MACH_CORVUS CORVUS 2066 +taurus MACH_TAURUS TAURUS 2067 +axm MACH_AXM AXM 2068 +axc MACH_AXC AXC 2069 +baby MACH_BABY BABY 2070 +mp200 MACH_MP200 MP200 2071 +pcm043 MACH_PCM043 PCM043 2072 +hanlin_v3c MACH_HANLIN_V3C HANLIN_V3C 2073 +kbk9g20 MACH_KBK9G20 KBK9G20 2074 +adsturbog5 MACH_ADSTURBOG5 ADSTURBOG5 2075 +avenger_lite1 MACH_AVENGER_LITE1 AVENGER_LITE1 2076 +suc82x MACH_SUC SUC 2077 +at91sam7s256 MACH_AT91SAM7S256 AT91SAM7S256 2078 +mendoza MACH_MENDOZA MENDOZA 2079 +kira MACH_KIRA KIRA 2080 +mx1hbm MACH_MX1HBM MX1HBM 2081 +quatro43xx MACH_QUATRO43XX QUATRO43XX 2082 +quatro4230 MACH_QUATRO4230 QUATRO4230 2083 +nsb400 MACH_NSB400 NSB400 2084 +drp255 MACH_DRP255 DRP255 2085 +thoth MACH_THOTH THOTH 2086 +firestone MACH_FIRESTONE FIRESTONE 2087 +asusp750 MACH_ASUSP750 ASUSP750 2088 +ctera_dl MACH_CTERA_DL CTERA_DL 2089 +socr MACH_SOCR SOCR 2090 +htcoxygen MACH_HTCOXYGEN HTCOXYGEN 2091 +heroc MACH_HEROC HEROC 2092 +zeno6800 MACH_ZENO6800 ZENO6800 2093 +sc2mcs MACH_SC2MCS SC2MCS 2094 +gene100 MACH_GENE100 GENE100 2095 +as353x MACH_AS353X AS353X 2096 +sheevaplug MACH_SHEEVAPLUG SHEEVAPLUG 2097 +at91sam9g20 MACH_AT91SAM9G20 AT91SAM9G20 2098 +mv88f6192gtw_fe MACH_MV88F6192GTW_FE MV88F6192GTW_FE 2099 +cc9200 MACH_CC9200 CC9200 2100 +sm9200 MACH_SM9200 SM9200 2101 +tp9200 MACH_TP9200 TP9200 2102 +snapperdv MACH_SNAPPERDV SNAPPERDV 2103 +avengers_lite MACH_AVENGERS_LITE AVENGERS_LITE 2104 +avengers_lite1 MACH_AVENGERS_LITE1 AVENGERS_LITE1 2105 +omap3axon MACH_OMAP3AXON OMAP3AXON 2106 +ma8xx MACH_MA8XX MA8XX 2107 +mp201ek MACH_MP201EK MP201EK 2108 +davinci_tux MACH_DAVINCI_TUX DAVINCI_TUX 2109 +mpa1600 MACH_MPA1600 MPA1600 2110 +pelco_troy MACH_PELCO_TROY PELCO_TROY 2111 +nsb667 MACH_NSB667 NSB667 2112 +rovers5_4mpix MACH_ROVERS5_4MPIX ROVERS5_4MPIX 2113 +twocom MACH_TWOCOM TWOCOM 2114 +ubisys_p9_rcu3r2 MACH_UBISYS_P9_RCU3R2 UBISYS_P9_RCU3R2 2115 +hero_espresso MACH_HERO_ESPRESSO HERO_ESPRESSO 2116 +afeusb MACH_AFEUSB AFEUSB 2117 +t830 MACH_T830 T830 2118 +spd8020_cc MACH_SPD8020_CC SPD8020_CC 2119 +om_3d7k MACH_OM_3D7K OM_3D7K 2120 +picocom2 MACH_PICOCOM2 PICOCOM2 2121 +uwg4mx27 MACH_UWG4MX27 UWG4MX27 2122 +uwg4mx31 MACH_UWG4MX31 UWG4MX31 2123 +cherry MACH_CHERRY CHERRY 2124 +mx51_babbage MACH_MX51_BABBAGE MX51_BABBAGE 2125 +s3c2440turkiye MACH_S3C2440TURKIYE S3C2440TURKIYE 2126 +tx37 MACH_TX37 TX37 2127 +sbc2800_9g20 MACH_SBC2800_9G20 SBC2800_9G20 2128 +benzglb MACH_BENZGLB BENZGLB 2129 +benztd MACH_BENZTD BENZTD 2130 +cartesio_plus MACH_CARTESIO_PLUS CARTESIO_PLUS 2131 +solrad_g20 MACH_SOLRAD_G20 SOLRAD_G20 2132 +mx27wallace MACH_MX27WALLACE MX27WALLACE 2133 +fmzwebmodul MACH_FMZWEBMODUL FMZWEBMODUL 2134 +rd78x00_masa MACH_RD78X00_MASA RD78X00_MASA 2135 +smallogger MACH_SMALLOGGER SMALLOGGER 2136 -- cgit v1.2.3-70-g09d2 From 1522ac3ec95ff0230e7aa516f86b674fdf72866c Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 Mar 2009 17:03:48 +0000 Subject: [ARM] Fix virtual to physical translation macro corner cases The current use of these macros works well when the conversion is entirely linear. In this case, we can be assured that the following holds true: __va(p + s) - s = __va(p) However, this is not always the case, especially when there is a non-linear conversion (eg, when there is a 3.5GB hole in memory.) In this case, if 's' is the size of the region (eg, PAGE_SIZE) and 'p' is the final page, the above is most definitely not true. So, we must ensure that __va() and __pa() are only used with valid kernel direct mapped RAM addresses. This patch tweaks the code to achieve this. Tested-by: Charles Moschel Signed-off-by: Russell King --- arch/arm/mm/dma-mapping.c | 20 ++++++++++++-------- arch/arm/mm/init.c | 2 +- arch/arm/mm/mmap.c | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 310e479309e..f1ef5613ccd 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -490,26 +490,30 @@ core_initcall(consistent_init); */ void dma_cache_maint(const void *start, size_t size, int direction) { - const void *end = start + size; + void (*inner_op)(const void *, const void *); + void (*outer_op)(unsigned long, unsigned long); - BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end - 1)); + BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(start + size - 1)); switch (direction) { case DMA_FROM_DEVICE: /* invalidate only */ - dmac_inv_range(start, end); - outer_inv_range(__pa(start), __pa(end)); + inner_op = dmac_inv_range; + outer_op = outer_inv_range; break; case DMA_TO_DEVICE: /* writeback only */ - dmac_clean_range(start, end); - outer_clean_range(__pa(start), __pa(end)); + inner_op = dmac_clean_range; + outer_op = outer_clean_range; break; case DMA_BIDIRECTIONAL: /* writeback and invalidate */ - dmac_flush_range(start, end); - outer_flush_range(__pa(start), __pa(end)); + inner_op = dmac_flush_range; + outer_op = outer_flush_range; break; default: BUG(); } + + inner_op(start, start + size); + outer_op(__pa(start), __pa(start) + size); } EXPORT_SYMBOL(dma_cache_maint); diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 34df4d9d03a..80fd3b69ae1 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -382,7 +382,7 @@ void __init bootmem_init(void) for_each_node(node) bootmem_free_node(node, mi); - high_memory = __va(memend_pfn << PAGE_SHIFT); + high_memory = __va((memend_pfn << PAGE_SHIFT) - 1) + 1; /* * This doesn't seem to be used by the Linux memory manager any diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index 5358fcc7f61..f7457fea6de 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -124,7 +124,7 @@ int valid_phys_addr_range(unsigned long addr, size_t size) { if (addr < PHYS_OFFSET) return 0; - if (addr + size > __pa(high_memory)) + if (addr + size >= __pa(high_memory - 1)) return 0; return 1; -- cgit v1.2.3-70-g09d2