From 87f9260bf1fb7ec4c3f88c6bb353df17ca1e1c19 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 8 Feb 2014 21:18:24 +0000 Subject: ARM: dts: fix spdif pinmux configuration The spdif pinmux configuration must be connected to the spdif device to take effect, not the spdif-transmitter. Signed-off-by: Russell King --- arch/arm/boot/dts/imx6dl-hummingboard.dts | 10 +++------- arch/arm/boot/dts/imx6qdl-cubox-i.dtsi | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/imx6dl-hummingboard.dts b/arch/arm/boot/dts/imx6dl-hummingboard.dts index fd8fc7c..5bfae54 100644 --- a/arch/arm/boot/dts/imx6dl-hummingboard.dts +++ b/arch/arm/boot/dts/imx6dl-hummingboard.dts @@ -52,12 +52,6 @@ }; }; - codec: spdif-transmitter { - compatible = "linux,spdif-dit"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_hummingboard_spdif>; - }; - sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; @@ -111,7 +105,7 @@ }; pinctrl_hummingboard_spdif: hummingboard-spdif { - fsl,pins = ; + fsl,pins = ; }; pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus { @@ -142,6 +136,8 @@ }; &spdif { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hummingboard_spdif>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi index 64daa3b..c2a2488 100644 --- a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi +++ b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi @@ -46,12 +46,6 @@ }; }; - codec: spdif-transmitter { - compatible = "linux,spdif-dit"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_cubox_i_spdif>; - }; - sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; @@ -89,7 +83,7 @@ }; pinctrl_cubox_i_spdif: cubox-i-spdif { - fsl,pins = ; + fsl,pins = ; }; pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus { @@ -121,6 +115,8 @@ }; &spdif { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_cubox_i_spdif>; status = "okay"; }; -- cgit v1.1 From 4d9c5b89cf3605bbc39c6e274351ff25f0d83e6a Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Sun, 2 Feb 2014 22:21:31 +0100 Subject: ARM: 7950/1: mm: Fix stage-2 device memory attributes The stage-2 memory attributes are distinct from the Hyp memory attributes and the Stage-1 memory attributes. We were using the stage-1 memory attributes for stage-2 mappings causing device mappings to be mapped as normal memory. Add the S2 equivalent defines for memory attributes and fix the comments explaining the defines while at it. Add a prot_pte_s2 field to the mem_type struct and fill out the field for device mappings accordingly. Cc: [3.9+] Acked-by: Marc Zyngier Acked-by: Catalin Marinas Signed-off-by: Christoffer Dall Signed-off-by: Russell King --- arch/arm/include/asm/pgtable-3level.h | 15 +++++++++------ arch/arm/mm/mm.h | 1 + arch/arm/mm/mmu.c | 7 ++++++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h index 03243f7..85c60ad 100644 --- a/arch/arm/include/asm/pgtable-3level.h +++ b/arch/arm/include/asm/pgtable-3level.h @@ -120,13 +120,16 @@ /* * 2nd stage PTE definitions for LPAE. */ -#define L_PTE_S2_MT_UNCACHED (_AT(pteval_t, 0x5) << 2) /* MemAttr[3:0] */ -#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* MemAttr[3:0] */ -#define L_PTE_S2_MT_WRITEBACK (_AT(pteval_t, 0xf) << 2) /* MemAttr[3:0] */ -#define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */ -#define L_PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */ +#define L_PTE_S2_MT_UNCACHED (_AT(pteval_t, 0x0) << 2) /* strongly ordered */ +#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* normal inner write-through */ +#define L_PTE_S2_MT_WRITEBACK (_AT(pteval_t, 0xf) << 2) /* normal inner write-back */ +#define L_PTE_S2_MT_DEV_SHARED (_AT(pteval_t, 0x1) << 2) /* device */ +#define L_PTE_S2_MT_MASK (_AT(pteval_t, 0xf) << 2) -#define L_PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */ +#define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */ +#define L_PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */ + +#define L_PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */ /* * Hyp-mode PL2 PTE definitions for LPAE. diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index d5a982d..7ea641b 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -38,6 +38,7 @@ static inline pmd_t *pmd_off_k(unsigned long virt) struct mem_type { pteval_t prot_pte; + pteval_t prot_pte_s2; pmdval_t prot_l1; pmdval_t prot_sect; unsigned int domain; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4f08c13..a623cb3 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -232,12 +232,16 @@ __setup("noalign", noalign_setup); #endif /* ifdef CONFIG_CPU_CP15 / else */ #define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN +#define PROT_PTE_S2_DEVICE PROT_PTE_DEVICE #define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE static struct mem_type mem_types[] = { [MT_DEVICE] = { /* Strongly ordered / ARMv6 shared device */ .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED | L_PTE_SHARED, + .prot_pte_s2 = s2_policy(PROT_PTE_S2_DEVICE) | + s2_policy(L_PTE_S2_MT_DEV_SHARED) | + L_PTE_SHARED, .prot_l1 = PMD_TYPE_TABLE, .prot_sect = PROT_SECT_DEVICE | PMD_SECT_S, .domain = DOMAIN_IO, @@ -508,7 +512,8 @@ static void __init build_mem_type_table(void) cp = &cache_policies[cachepolicy]; vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; s2_pgprot = cp->pte_s2; - hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte; + hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte; + s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2; /* * ARMv6 and above have extended page tables. -- cgit v1.1 From ca4744084772e1fee999391bee0fcdca5d91a757 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 6 Feb 2014 19:50:35 +0100 Subject: ARM: 7952/1: mm: Fix the memblock allocation for LPAE machines Commit ad6492b8 added much needed memblock_virt_alloc_low() and further commit 07bacb3 {memblock, bootmem: restore goal for alloc_low} fixed the issue with low memory limit thanks to Yinghai. But even after all these fixes, there is still one case where the limit check done with ARCH_LOW_ADDRESS_LIMIT for low memory fails. Russell pointed out the issue with 32 bit LPAE machines in below thread. https://lkml.org/lkml/2014/1/28/364 Since on some LPAE machines where memory start address is beyond 4GB, the low memory marker in memblock will be set to default ARCH_LOW_ADDRESS_LIMIT which is wrong. We can fix this by letting architectures set the ARCH_LOW_ADDRESS_LIMIT using another export similar to memblock_set_current_limit() but am not sure whether its worth the trouble. Tell me if you think otherwise. Rather am just trying to fix that one broken case using memblock_virt_alloc() in setup code since the memblock.current_limit is updated appropriately makes it work on all ARM 32 bit machines. Cc: Yinghai Lu Cc: Strashko, Grygorii Cc: Andrew Morton Signed-off-by: Santosh Shilimkar Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index b0df976..1e8b030 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -731,7 +731,7 @@ static void __init request_standard_resources(const struct machine_desc *mdesc) kernel_data.end = virt_to_phys(_end - 1); for_each_memblock(memory, region) { - res = memblock_virt_alloc_low(sizeof(*res), 0); + res = memblock_virt_alloc(sizeof(*res), 0); res->name = "System RAM"; res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; -- cgit v1.1 From bae0ca2bc550d1ec6a118fb8f2696f18c4da3d8e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 7 Feb 2014 19:12:20 +0100 Subject: ARM: 7953/1: mm: ensure TLB invalidation is complete before enabling MMU During __v{6,7}_setup, we invalidate the TLBs since we are about to enable the MMU on return to head.S. Unfortunately, without a subsequent dsb instruction, the invalidation is not guaranteed to have completed by the time we write to the sctlr, potentially exposing us to junk/stale translations cached in the TLB. This patch reworks the init functions so that the dsb used to ensure completion of cache/predictor maintenance is also used to ensure completion of the TLB invalidation. Cc: Reported-by: Albin Tonnerre Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/proc-v6.S | 3 ++- arch/arm/mm/proc-v7.S | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 45dc29f..32b3558 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -208,7 +208,6 @@ __v6_setup: mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache - mcr p15, 0, r0, c7, c10, 4 @ drain write buffer #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs mcr p15, 0, r0, c2, c0, 2 @ TTB control register @@ -218,6 +217,8 @@ __v6_setup: ALT_UP(orr r8, r8, #TTB_FLAGS_UP) mcr p15, 0, r8, c2, c0, 1 @ load TTB1 #endif /* CONFIG_MMU */ + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer and + @ complete invalidations adr r5, v6_crval ldmia r5, {r5, r6} ARM_BE8(orr r6, r6, #1 << 25) @ big-endian page tables diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index bd17819..74f6033 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -351,7 +351,6 @@ __v7_setup: 4: mov r10, #0 mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate - dsb #ifdef CONFIG_MMU mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs v7_ttb_setup r10, r4, r8, r5 @ TTBCR, TTBRx setup @@ -360,6 +359,7 @@ __v7_setup: mcr p15, 0, r5, c10, c2, 0 @ write PRRR mcr p15, 0, r6, c10, c2, 1 @ write NMRR #endif + dsb @ Complete invalidations #ifndef CONFIG_ARM_THUMBEE mrc p15, 0, r0, c0, c1, 0 @ read ID_PFR0 for ThumbEE and r0, r0, #(0xf << 12) @ ThumbEE enabled field -- cgit v1.1 From 7c8746a9eb287642deaad0e7c2cdf482dce5e4be Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 7 Feb 2014 19:12:32 +0100 Subject: ARM: 7955/1: spinlock: ensure we have a compiler barrier before sev When unlocking a spinlock, we require the following, strictly ordered sequence of events: /* dmb */ /* dsb */ Whilst the code does indeed reflect this in terms of the architecture, the final + have been contracted into a single inline asm without a "memory" clobber, therefore the compiler is at liberty to reorder the unlock to the end of the above sequence. In such a case, a waiting CPU may be woken up before the lock has been unlocked, leading to extremely poor performance. This patch reworks the dsb_sev() function to make use of the dsb() macro and ensure ordering against the unlock. Cc: Reported-by: Mark Rutland Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/spinlock.h | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h index ef3c607..ac4bfae 100644 --- a/arch/arm/include/asm/spinlock.h +++ b/arch/arm/include/asm/spinlock.h @@ -37,18 +37,9 @@ static inline void dsb_sev(void) { -#if __LINUX_ARM_ARCH__ >= 7 - __asm__ __volatile__ ( - "dsb ishst\n" - SEV - ); -#else - __asm__ __volatile__ ( - "mcr p15, 0, %0, c7, c10, 4\n" - SEV - : : "r" (0) - ); -#endif + + dsb(ishst); + __asm__(SEV); } /* -- cgit v1.1 From ddb2ff731b53ae28ec3a2af0da96a108b8bad814 Mon Sep 17 00:00:00 2001 From: Jonathan Austin Date: Mon, 13 Jan 2014 12:10:57 +0100 Subject: ARM: 7940/1: add support for the Cortex-A12 processor The A12 behaves as the A7/A15 does with respect to setting the SMP bit, and doesn't require TLB ops broadcasting to be explicitly enabled like the A9 does. Note that as the ACTLR cannot (usually) be written from non-secure, it is the responsibility of the bootloader/firmware to set this bit per core - it is done here in Linux as last resort in case of bad firmware. Acked-by: Catalin Marinas Acked-by: Will Deacon Signed-off-by: Jonathan Austin Signed-off-by: Russell King --- arch/arm/include/asm/cputype.h | 1 + arch/arm/mm/proc-v7.S | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index acdde76..42f0889 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h @@ -71,6 +71,7 @@ #define ARM_CPU_PART_CORTEX_A5 0xC050 #define ARM_CPU_PART_CORTEX_A15 0xC0F0 #define ARM_CPU_PART_CORTEX_A7 0xC070 +#define ARM_CPU_PART_CORTEX_A12 0xC0D0 #define ARM_CPU_XSCALE_ARCH_MASK 0xe000 #define ARM_CPU_XSCALE_ARCH_V1 0x2000 diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index bd17819..7f9de7e 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -192,6 +192,7 @@ __v7_cr7mp_setup: mov r10, #(1 << 0) @ Cache/TLB ops broadcasting b 1f __v7_ca7mp_setup: +__v7_ca12mp_setup: __v7_ca15mp_setup: mov r10, #0 1: @@ -484,6 +485,16 @@ __v7_ca7mp_proc_info: .size __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info /* + * ARM Ltd. Cortex A12 processor. + */ + .type __v7_ca12mp_proc_info, #object +__v7_ca12mp_proc_info: + .long 0x410fc0d0 + .long 0xff0ffff0 + __v7_proc __v7_ca12mp_setup + .size __v7_ca12mp_proc_info, . - __v7_ca12mp_proc_info + + /* * ARM Ltd. Cortex A15 processor. */ .type __v7_ca15mp_proc_info, #object -- cgit v1.1 From 889f172d920b6f275408199ec836df62979bcd52 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 17 Jan 2014 20:42:48 +0100 Subject: ARM: 7945/1: footbridge: Switch to sched_clock_register() The 32 bit sched_clock interface supports 64 bits since 3.13-rc1. Upgrade to the 64 bit function to allow us to remove the 32 bit registration interface. Signed-off-by: Stephen Boyd Signed-off-by: Russell King --- arch/arm/mach-footbridge/dc21285-timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index 3971104..5d2725f 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -125,7 +125,7 @@ void __init footbridge_timer_init(void) clockevents_config_and_register(ce, rate, 0x4, 0xffffff); } -static u32 notrace footbridge_read_sched_clock(void) +static u64 notrace footbridge_read_sched_clock(void) { return ~*CSR_TIMER3_VALUE; } @@ -138,5 +138,5 @@ void __init footbridge_sched_clock(void) *CSR_TIMER3_CLR = 0; *CSR_TIMER3_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16; - setup_sched_clock(footbridge_read_sched_clock, 24, rate); + sched_clock_register(footbridge_read_sched_clock, 24, rate); } -- cgit v1.1 From 5b61d4a5d6676b5bb4c3c101683d3c7fd0df2a38 Mon Sep 17 00:00:00 2001 From: Christopher Covington Date: Wed, 29 Jan 2014 22:01:31 +0100 Subject: ARM: 7948/1: hw_breakpoint: Add ARMv8 support Add the trivial support necessary to get hardware breakpoints working for GDB on ARMv8 simulators running in AArch32 mode. Acked-by: Will Deacon Signed-off-by: Christopher Covington Signed-off-by: Russell King --- arch/arm/include/asm/hw_breakpoint.h | 1 + arch/arm/kernel/hw_breakpoint.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h index eef55ea..8e427c7 100644 --- a/arch/arm/include/asm/hw_breakpoint.h +++ b/arch/arm/include/asm/hw_breakpoint.h @@ -51,6 +51,7 @@ static inline void decode_ctrl_reg(u32 reg, #define ARM_DEBUG_ARCH_V7_ECP14 3 #define ARM_DEBUG_ARCH_V7_MM 4 #define ARM_DEBUG_ARCH_V7_1 5 +#define ARM_DEBUG_ARCH_V8 6 /* Breakpoint */ #define ARM_BREAKPOINT_EXECUTE 0 diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 3d44660..9da35c6 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -167,7 +167,7 @@ static int debug_arch_supported(void) /* Can we determine the watchpoint access type from the fsr? */ static int debug_exception_updates_fsr(void) { - return 0; + return get_debug_arch() >= ARM_DEBUG_ARCH_V8; } /* Determine number of WRP registers available. */ @@ -257,6 +257,7 @@ static int enable_monitor_mode(void) break; case ARM_DEBUG_ARCH_V7_ECP14: case ARM_DEBUG_ARCH_V7_1: + case ARM_DEBUG_ARCH_V8: ARM_DBG_WRITE(c0, c2, 2, (dscr | ARM_DSCR_MDBGEN)); isb(); break; -- cgit v1.1 From 0f054e3ceab33a7fd3b41a9708286bce420d570d Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Fri, 31 Jan 2014 19:49:24 +0100 Subject: ARM: 7949/1: feroceon: Log a FW_BUG if the L2 cache is turned on at boot Booting on feroceon CPUS requires the L2 cache to be turned off. With some kernel configurations (notably CONFIG_ARM_PATCH_PHYS_VIRT disabled) the kernel will boot even if the L2 is turned on. However there may be subtle breakage, and when PATCH_PHYS_VIRT is enabled it is very likely that booting with L2 will crash at early boot before any kernel diagnostic output. The diagnostic message is intended to discourage people from shipping bootloaders that leave the L2 turned on. The issue on feroceon is that the L2 is bypassed when the L1 caches are disabled. So the decompressor will place parts of the kernel image into the L2 and the early cache-off boot code in head.S will write to parts of the kernel image, bypassing the L2 and creating inconsistency. Tested on ARM Kirkwood. Signed-off-by: Jason Gunthorpe Acked-by: Jason Cooper Signed-off-by: Russell King --- arch/arm/mm/cache-feroceon-l2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index 48bc3c0..aae8918 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c @@ -331,7 +331,9 @@ static void __init enable_l2(void) enable_icache(); if (d) enable_dcache(); - } + } else + pr_err(FW_BUG + "Feroceon L2: bootloader left the L2 cache on!\n"); } void __init feroceon_l2_init(int __l2_wt_override) -- cgit v1.1 From afdd3bba3ca18e6b0515b2e60101a932f5fa9afa Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 4 Feb 2014 13:23:48 +0100 Subject: ARM: 7951/1: uaccess: use CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS Now that we select HAVE_EFFICIENT_UNALIGNED_ACCESS for ARMv6+ CPUs, replace the __LINUX_ARM_ARCH__ check in uaccess.h with the new symbol. Signed-off-by: Nicolas Pitre Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 72abdc5..12c3a5d 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -19,7 +19,7 @@ #include #include -#if __LINUX_ARM_ARCH__ < 6 +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #include #else #define __get_user_unaligned __get_user -- cgit v1.1 From b6ccb9803e90c16b212cf4ed62913a7591e79a39 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 7 Feb 2014 19:12:27 +0100 Subject: ARM: 7954/1: mm: remove remaining domain support from ARMv6 CPU_32v6 currently selects CPU_USE_DOMAINS if CPU_V6 and MMU. This is because ARM 1136 r0pX CPUs lack the v6k extensions, and therefore do not have hardware thread registers. The lack of these registers requires the kernel to update the vectors page at each context switch in order to write a new TLS pointer. This write must be done via the userspace mapping, since aliasing caches can lead to expensive flushing when using kmap. Finally, this requires the vectors page to be mapped r/w for kernel and r/o for user, which has implications for things like put_user which must trigger CoW appropriately when targetting user pages. The upshot of all this is that a v6/v7 kernel makes use of domains to segregate kernel and user memory accesses. This has the nasty side-effect of making device mappings executable, which has been observed to cause subtle bugs on recent cores (e.g. Cortex-A15 performing a speculative instruction fetch from the GIC and acking an interrupt in the process). This patch solves this problem by removing the remaining domain support from ARMv6. A new memory type is added specifically for the vectors page which allows that page (and only that page) to be mapped as user r/o, kernel r/w. All other user r/o pages are mapped also as kernel r/o. Patch co-developed with Russell King. Cc: Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/futex.h | 6 ------ arch/arm/include/asm/pgtable-2level.h | 1 + arch/arm/mm/Kconfig | 3 +-- arch/arm/mm/mmu.c | 10 ++++++++++ arch/arm/mm/proc-macros.S | 19 ++++++------------- arch/arm/mm/proc-v7-2level.S | 7 ------- 6 files changed, 18 insertions(+), 28 deletions(-) diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h index e42cf59..2aff798 100644 --- a/arch/arm/include/asm/futex.h +++ b/arch/arm/include/asm/futex.h @@ -3,11 +3,6 @@ #ifdef __KERNEL__ -#if defined(CONFIG_CPU_USE_DOMAINS) && defined(CONFIG_SMP) -/* ARM doesn't provide unprivileged exclusive memory accessors */ -#include -#else - #include #include #include @@ -164,6 +159,5 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) return ret; } -#endif /* !(CPU_USE_DOMAINS && SMP) */ #endif /* __KERNEL__ */ #endif /* _ASM_ARM_FUTEX_H */ diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h index dfff709..219ac88 100644 --- a/arch/arm/include/asm/pgtable-2level.h +++ b/arch/arm/include/asm/pgtable-2level.h @@ -140,6 +140,7 @@ #define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */ #define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */ #define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ +#define L_PTE_MT_VECTORS (_AT(pteval_t, 0x0f) << 2) /* 1111 */ #define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) #ifndef __ASSEMBLY__ diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 1f8fed9..ca8ecde 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -446,7 +446,6 @@ config CPU_32v5 config CPU_32v6 bool - select CPU_USE_DOMAINS if CPU_V6 && MMU select TLS_REG_EMUL if !CPU_32v6K && !MMU config CPU_32v6K @@ -671,7 +670,7 @@ config ARM_VIRT_EXT config SWP_EMULATE bool "Emulate SWP/SWPB instructions" - depends on !CPU_USE_DOMAINS && CPU_V7 + depends on CPU_V7 default y if SMP select HAVE_PROC_CPU if PROC_FS help diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4f08c13..6ec07a8 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -511,6 +511,16 @@ static void __init build_mem_type_table(void) hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte; /* + * We don't use domains on ARMv6 (since this causes problems with + * v6/v7 kernels), so we must use a separate memory type for user + * r/o, kernel r/w to map the vectors page. + */ +#ifndef CONFIG_ARM_LPAE + if (cpu_arch == CPU_ARCH_ARMv6) + vecs_pgprot |= L_PTE_MT_VECTORS; +#endif + + /* * ARMv6 and above have extended page tables. */ if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) { diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index e3c48a3..ee1d805 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S @@ -112,13 +112,9 @@ * 100x 1 0 1 r/o no acc * 10x0 1 0 1 r/o no acc * 1011 0 0 1 r/w no acc - * 110x 0 1 0 r/w r/o - * 11x0 0 1 0 r/w r/o - * 1111 0 1 1 r/w r/w - * - * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed: * 110x 1 1 1 r/o r/o * 11x0 1 1 1 r/o r/o + * 1111 0 1 1 r/w r/w */ .macro armv6_mt_table pfx \pfx\()_mt_table: @@ -137,7 +133,7 @@ .long PTE_EXT_TEX(2) @ L_PTE_MT_DEV_NONSHARED .long 0x00 @ unused .long 0x00 @ unused - .long 0x00 @ unused + .long PTE_CACHEABLE | PTE_BUFFERABLE | PTE_EXT_APX @ L_PTE_MT_VECTORS .endm .macro armv6_set_pte_ext pfx @@ -158,24 +154,21 @@ tst r1, #L_PTE_USER orrne r3, r3, #PTE_EXT_AP1 -#ifdef CONFIG_CPU_USE_DOMAINS - @ allow kernel read/write access to read-only user pages tstne r3, #PTE_EXT_APX - bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 -#endif + + @ user read-only -> kernel read-only + bicne r3, r3, #PTE_EXT_AP0 tst r1, #L_PTE_XN orrne r3, r3, #PTE_EXT_XN - orr r3, r3, r2 + eor r3, r3, r2 tst r1, #L_PTE_YOUNG tstne r1, #L_PTE_PRESENT moveq r3, #0 -#ifndef CONFIG_CPU_USE_DOMAINS tstne r1, #L_PTE_NONE movne r3, #0 -#endif str r3, [r0] mcr p15, 0, r0, c7, c10, 1 @ flush_pte diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S index bdd3be4..1f52915 100644 --- a/arch/arm/mm/proc-v7-2level.S +++ b/arch/arm/mm/proc-v7-2level.S @@ -90,21 +90,14 @@ ENTRY(cpu_v7_set_pte_ext) tst r1, #L_PTE_USER orrne r3, r3, #PTE_EXT_AP1 -#ifdef CONFIG_CPU_USE_DOMAINS - @ allow kernel read/write access to read-only user pages - tstne r3, #PTE_EXT_APX - bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 -#endif tst r1, #L_PTE_XN orrne r3, r3, #PTE_EXT_XN tst r1, #L_PTE_YOUNG tstne r1, #L_PTE_VALID -#ifndef CONFIG_CPU_USE_DOMAINS eorne r1, r1, #L_PTE_NONE tstne r1, #L_PTE_NONE -#endif moveq r3, #0 ARM( str r3, [r0, #2048]! ) -- cgit v1.1 From eb02313d2c96e1793cf37693d432fd2c129ae170 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 26 Nov 2013 11:11:00 +0100 Subject: ARM: 7902/1: sa1100: h3xxx: move serial port GPIO handling to common place Both h3100 and h3600 request UART gpios during init_machine time. As sa1100 gpio driver is going to become proper machine driver, move gpio handling to UART port functions. Request all gpios using gpio_request array once and then guard them from rerequesting with bool variable. Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-sa1100/h3100.c | 7 ------- arch/arm/mach-sa1100/h3600.c | 7 ------- arch/arm/mach-sa1100/h3xxx.c | 27 +++++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-sa1100/h3100.c b/arch/arm/mach-sa1100/h3100.c index daa27c4..3c43219 100644 --- a/arch/arm/mach-sa1100/h3100.c +++ b/arch/arm/mach-sa1100/h3100.c @@ -122,15 +122,8 @@ static struct irda_platform_data h3100_irda_data = { .shutdown = h3100_irda_shutdown, }; -static struct gpio_default_state h3100_default_gpio[] = { - { H3XXX_GPIO_COM_DCD, GPIO_MODE_IN, "COM DCD" }, - { H3XXX_GPIO_COM_CTS, GPIO_MODE_IN, "COM CTS" }, - { H3XXX_GPIO_COM_RTS, GPIO_MODE_OUT0, "COM RTS" }, -}; - static void __init h3100_mach_init(void) { - h3xxx_init_gpio(h3100_default_gpio, ARRAY_SIZE(h3100_default_gpio)); h3xxx_mach_init(); sa11x0_register_lcd(&h3100_lcd_info); diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index a663e72..5be54c2 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -130,15 +130,8 @@ static struct irda_platform_data h3600_irda_data = { .shutdown = h3600_irda_shutdown, }; -static struct gpio_default_state h3600_default_gpio[] = { - { H3XXX_GPIO_COM_DCD, GPIO_MODE_IN, "COM DCD" }, - { H3XXX_GPIO_COM_CTS, GPIO_MODE_IN, "COM CTS" }, - { H3XXX_GPIO_COM_RTS, GPIO_MODE_OUT0, "COM RTS" }, -}; - static void __init h3600_mach_init(void) { - h3xxx_init_gpio(h3600_default_gpio, ARRAY_SIZE(h3600_default_gpio)); h3xxx_mach_init(); sa11x0_register_lcd(&h3600_lcd_info); diff --git a/arch/arm/mach-sa1100/h3xxx.c b/arch/arm/mach-sa1100/h3xxx.c index f17e738..82e8702 100644 --- a/arch/arm/mach-sa1100/h3xxx.c +++ b/arch/arm/mach-sa1100/h3xxx.c @@ -116,9 +116,34 @@ static struct resource h3xxx_flash_resource = /* * H3xxx uart support */ +static struct gpio h3xxx_uart_gpio[] = { + { H3XXX_GPIO_COM_DCD, GPIOF_IN, "COM DCD" }, + { H3XXX_GPIO_COM_CTS, GPIOF_IN, "COM CTS" }, + { H3XXX_GPIO_COM_RTS, GPIOF_OUT_INIT_LOW, "COM RTS" }, +}; + +static bool h3xxx_uart_request_gpios(void) +{ + static bool h3xxx_uart_gpio_ok; + int rc; + + if (h3xxx_uart_gpio_ok) + return true; + + rc = gpio_request_array(h3xxx_uart_gpio, ARRAY_SIZE(h3xxx_uart_gpio)); + if (rc) + pr_err("h3xxx_uart_request_gpios: error %d\n", rc); + else + h3xxx_uart_gpio_ok = true; + + return h3xxx_uart_gpio_ok; +} + static void h3xxx_uart_set_mctrl(struct uart_port *port, u_int mctrl) { if (port->mapbase == _Ser3UTCR0) { + if (!h3xxx_uart_request_gpios()) + return; gpio_set_value(H3XXX_GPIO_COM_RTS, !(mctrl & TIOCM_RTS)); } } @@ -128,6 +153,8 @@ static u_int h3xxx_uart_get_mctrl(struct uart_port *port) u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR; if (port->mapbase == _Ser3UTCR0) { + if (!h3xxx_uart_request_gpios()) + return ret; /* * DCD and CTS bits are inverted in GPLR by RS232 transceiver */ -- cgit v1.1 From 75916d5549e4c134f69068de175c90c170c17a7a Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 26 Nov 2013 11:11:21 +0100 Subject: ARM: 7903/1: sa1100: h3xxx: drop hand-coded gpio_request_array analogue h3xxx_init_gpio() behaves alsmost like gpio_request_array. Also after all GPIO refactoring it is unused. Drop it now. Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-sa1100/h3xxx.c | 31 ------------------------------- arch/arm/mach-sa1100/include/mach/h3xxx.h | 11 ----------- 2 files changed, 42 deletions(-) diff --git a/arch/arm/mach-sa1100/h3xxx.c b/arch/arm/mach-sa1100/h3xxx.c index 82e8702..c79bf46 100644 --- a/arch/arm/mach-sa1100/h3xxx.c +++ b/arch/arm/mach-sa1100/h3xxx.c @@ -28,37 +28,6 @@ #include "generic.h" -void h3xxx_init_gpio(struct gpio_default_state *s, size_t n) -{ - while (n--) { - const char *name = s->name; - int err; - - if (!name) - name = "[init]"; - err = gpio_request(s->gpio, name); - if (err) { - printk(KERN_ERR "gpio%u: unable to request: %d\n", - s->gpio, err); - continue; - } - if (s->mode >= 0) { - err = gpio_direction_output(s->gpio, s->mode); - } else { - err = gpio_direction_input(s->gpio); - } - if (err) { - printk(KERN_ERR "gpio%u: unable to set direction: %d\n", - s->gpio, err); - continue; - } - if (!s->name) - gpio_free(s->gpio); - s++; - } -} - - /* * H3xxx flash support */ diff --git a/arch/arm/mach-sa1100/include/mach/h3xxx.h b/arch/arm/mach-sa1100/include/mach/h3xxx.h index c810620..603d434 100644 --- a/arch/arm/mach-sa1100/include/mach/h3xxx.h +++ b/arch/arm/mach-sa1100/include/mach/h3xxx.h @@ -79,17 +79,6 @@ #define H3600_EGPIO_LCD_5V_ON (H3XXX_EGPIO_BASE + 14) /* enable 5V to LCD. active high. */ #define H3600_EGPIO_LVDD_ON (H3XXX_EGPIO_BASE + 15) /* enable 9V and -6.5V to LCD. */ -struct gpio_default_state { - int gpio; - int mode; - const char *name; -}; - -#define GPIO_MODE_IN -1 -#define GPIO_MODE_OUT0 0 -#define GPIO_MODE_OUT1 1 - -void h3xxx_init_gpio(struct gpio_default_state *s, size_t n); void __init h3xxx_map_io(void); void __init h3xxx_mach_init(void); -- cgit v1.1 From 287d4d51e6bb1cd43cb77352bdec5bac1b2e1226 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 9 Jan 2014 13:32:18 +0100 Subject: ARM: 7936/1: sa1100: collie: add support for IrDA transceiver Collie has onboard IrDA transceiver controlled via active-low gpio. Add corresponding platform data. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Russell King --- arch/arm/mach-sa1100/collie.c | 33 ++++++++++++++++++++++++++++++ arch/arm/mach-sa1100/include/mach/collie.h | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 831a158..f9874ba 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -96,6 +97,37 @@ static struct mcp_plat_data collie_mcp_data = { .codec_pdata = &collie_ucb1x00_data, }; +static int collie_ir_startup(struct device *dev) +{ + int rc = gpio_request(COLLIE_GPIO_IR_ON, "IrDA"); + if (rc) + return rc; + rc = gpio_direction_output(COLLIE_GPIO_IR_ON, 1); + + if (!rc) + return 0; + + gpio_free(COLLIE_GPIO_IR_ON); + return rc; +} + +static void collie_ir_shutdown(struct device *dev) +{ + gpio_free(COLLIE_GPIO_IR_ON); +} + +static int collie_ir_set_power(struct device *dev, unsigned int state) +{ + gpio_set_value(COLLIE_GPIO_IR_ON, !state); + return 0; +} + +static struct irda_platform_data collie_ir_data = { + .startup = collie_ir_startup, + .shutdown = collie_ir_shutdown, + .set_power = collie_ir_set_power, +}; + /* * Collie AC IN */ @@ -400,6 +432,7 @@ static void __init collie_init(void) sa11x0_register_mtd(&collie_flash_data, collie_flash_resources, ARRAY_SIZE(collie_flash_resources)); sa11x0_register_mcp(&collie_mcp_data); + sa11x0_register_irda(&collie_ir_data); sharpsl_save_param(); } diff --git a/arch/arm/mach-sa1100/include/mach/collie.h b/arch/arm/mach-sa1100/include/mach/collie.h index f33679d..0ef22f9 100644 --- a/arch/arm/mach-sa1100/include/mach/collie.h +++ b/arch/arm/mach-sa1100/include/mach/collie.h @@ -78,7 +78,7 @@ extern void locomolcd_power(int on); #define COLLIE_TC35143_GPIO_VERSION0 UCB_IO_0 #define COLLIE_TC35143_GPIO_TBL_CHK UCB_IO_1 #define COLLIE_TC35143_GPIO_VPEN_ON UCB_IO_2 -#define COLLIE_TC35143_GPIO_IR_ON UCB_IO_3 +#define COLLIE_GPIO_IR_ON (COLLIE_TC35143_GPIO_BASE + 3) #define COLLIE_TC35143_GPIO_AMP_ON UCB_IO_4 #define COLLIE_TC35143_GPIO_VERSION1 UCB_IO_5 #define COLLIE_TC35143_GPIO_FS8KLPF UCB_IO_5 -- cgit v1.1 From dfdf5f63b4380b9e719145c7cb2cb450a3d06ac4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 11 Feb 2014 09:28:09 +0100 Subject: ARM: 7956/1: mmci: rename some extended flags These four (so far unused) flags are only found in the ST Micro versions of MMCI, so infix them properly with the _ST_ infix. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- drivers/mmc/host/mmci.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 168bc72..84c0e59 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -38,10 +38,11 @@ #define MCI_CPSM_INTERRUPT (1 << 8) #define MCI_CPSM_PENDING (1 << 9) #define MCI_CPSM_ENABLE (1 << 10) -#define MCI_SDIO_SUSP (1 << 11) -#define MCI_ENCMD_COMPL (1 << 12) -#define MCI_NIEN (1 << 13) -#define MCI_CE_ATACMD (1 << 14) +/* Argument flag extenstions in the ST Micro versions */ +#define MCI_ST_SDIO_SUSP (1 << 11) +#define MCI_ST_ENCMD_COMPL (1 << 12) +#define MCI_ST_NIEN (1 << 13) +#define MCI_ST_CE_ATACMD (1 << 14) #define MMCIRESPCMD 0x010 #define MMCIRESPONSE0 0x014 -- cgit v1.1 From e83b366487b5582274374f8226e489cb214ae5a6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 11 Feb 2014 17:11:04 +0000 Subject: Fix uses of dma_max_pfn() when converting to a limiting address We must use a 64-bit for this, otherwise overflowed bits get lost, and that can result in a lower than intended value set. Fixes: 8e0cb8a1f6ac ("ARM: 7797/1: mmc: Use dma_max_pfn(dev) helper for bounce_limit calculations") Fixes: 7d35496dd982 ("ARM: 7796/1: scsi: Use dma_max_pfn(dev) helper for bounce_limit calculations") Tested-Acked-by: Santosh Shilimkar Reviewed-by: Ulf Hansson Signed-off-by: Russell King --- drivers/mmc/card/queue.c | 2 +- drivers/scsi/scsi_lib.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 357bbc5..3e049c1 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -197,7 +197,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, struct mmc_queue_req *mqrq_prev = &mq->mqrq[1]; if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) - limit = dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; + limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; mq->card = card; mq->queue = blk_init_queue(mmc_request_fn, lock); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7bd7f0d..62ec84b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1684,7 +1684,7 @@ u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) host_dev = scsi_get_device(shost); if (host_dev && host_dev->dma_mask) - bounce_limit = dma_max_pfn(host_dev) << PAGE_SHIFT; + bounce_limit = (u64)dma_max_pfn(host_dev) << PAGE_SHIFT; return bounce_limit; } -- cgit v1.1 From 39544ac9df20f73e49fc6b9ac19ff533388c82c0 Mon Sep 17 00:00:00 2001 From: Vinayak Kale Date: Wed, 12 Feb 2014 07:30:01 +0100 Subject: ARM: 7957/1: add DSB after icache flush in __flush_icache_all() Add DSB after icache flush to complete the cache maintenance operation. Signed-off-by: Vinayak Kale Acked-by: Catalin Marinas Cc: Signed-off-by: Russell King --- arch/arm/include/asm/cacheflush.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index e9a49fe..8b8b616 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -212,6 +212,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *, static inline void __flush_icache_all(void) { __flush_icache_preferred(); + dsb(); } /* -- cgit v1.1 From ea36d2ab1a04d38bb24145b2b8fa8c8109cbe64d Mon Sep 17 00:00:00 2001 From: Dave Martin Date: Fri, 14 Feb 2014 12:46:02 +0100 Subject: ARM: 7962/2: Make all mcpm functions notrace The functions in mcpm_entry.c are mostly intended for use during scary cache and coherency disabling sequences, or do other things which confuse trace ... like powering a CPU down and not returning. Similarly for the backend code. For simplicity, this patch just makes whole files notrace. There should be more than enough traceable points on the paths to these functions, but we can be more fine-grained later if there is a need for it. Jon Medhurst: Also added spc.o to the list of files as it contains functions used by MCPM code which have comments comments like: "might be used in code paths where normal cacheable locks are not working" Signed-off-by: Dave Martin Signed-off-by: Jon Medhurst Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/common/Makefile | 1 + arch/arm/mach-vexpress/Makefile | 3 +++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 4bdc416..70b1eff 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_SHARP_SCOOP) += scoop.o obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o +CFLAGS_REMOVE_mcpm_entry.o = -pg AFLAGS_mcpm_head.o := -march=armv7-a AFLAGS_vlock.o := -march=armv7-a obj-$(CONFIG_TI_PRIV_EDMA) += edma.o diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile index 0997e0b..fc649bc 100644 --- a/arch/arm/mach-vexpress/Makefile +++ b/arch/arm/mach-vexpress/Makefile @@ -8,8 +8,11 @@ obj-y := v2m.o obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o obj-$(CONFIG_ARCH_VEXPRESS_DCSCB) += dcscb.o dcscb_setup.o CFLAGS_dcscb.o += -march=armv7-a +CFLAGS_REMOVE_dcscb.o = -pg obj-$(CONFIG_ARCH_VEXPRESS_SPC) += spc.o +CFLAGS_REMOVE_spc.o = -pg obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM) += tc2_pm.o CFLAGS_tc2_pm.o += -march=armv7-a +CFLAGS_REMOVE_tc2_pm.o = -pg obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -- cgit v1.1 From cd91b2fecfa66967e6ad732a9af860eb96c31ba4 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 14 Feb 2014 20:19:03 +0100 Subject: ARM: 7963/1: mm: report both sections from PMD On 2-level page table systems, the PMD has 2 section entries. Report these, otherwise ARM_PTDUMP will miss reporting permission changes on odd section boundaries. Signed-off-by: Kees Cook Acked-by: Catalin Marinas Tested-by: Steve Capper Signed-off-by: Russell King --- arch/arm/mm/dump.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c index 2b3a564..ef69152 100644 --- a/arch/arm/mm/dump.c +++ b/arch/arm/mm/dump.c @@ -264,6 +264,9 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start) note_page(st, addr, 3, pmd_val(*pmd)); else walk_pte(st, pmd, addr); + + if (SECTION_SIZE < PMD_SIZE && pmd_large(pmd[1])) + note_page(st, addr + SECTION_SIZE, 3, pmd_val(pmd[1])); } } -- cgit v1.1 From c9698e5cd6ad1ff2844bc44fabddc0f2e0562047 Mon Sep 17 00:00:00 2001 From: "David A. Long" Date: Fri, 14 Feb 2014 22:41:18 +0100 Subject: ARM: 7964/1: Detect section mismatches in thumb relocations Add processing for normally encountered thumb relocation types so that section mismatches will be detected. Comment from Rusty Russell follows: Happiest for this to go through an ARM tree, so: Signed-off-by: David A. Long Acked-by: Rusty Russell Signed-off-by: Russell King --- scripts/mod/modpost.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 4061098..99a45fd 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1502,6 +1502,16 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) #define R_ARM_JUMP24 29 #endif +#ifndef R_ARM_THM_CALL +#define R_ARM_THM_CALL 10 +#endif +#ifndef R_ARM_THM_JUMP24 +#define R_ARM_THM_JUMP24 30 +#endif +#ifndef R_ARM_THM_JUMP19 +#define R_ARM_THM_JUMP19 51 +#endif + static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) { unsigned int r_typ = ELF_R_TYPE(r->r_info); @@ -1515,6 +1525,9 @@ static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) case R_ARM_PC24: case R_ARM_CALL: case R_ARM_JUMP24: + case R_ARM_THM_CALL: + case R_ARM_THM_JUMP24: + case R_ARM_THM_JUMP19: /* From ARM ABI: ((S + A) | T) - P */ r->r_addend = (int)(long)(elf->hdr + sechdr->sh_offset + -- cgit v1.1 From 6ea41c80115f49e7d8b80312ffc99973d283471f Mon Sep 17 00:00:00 2001 From: Steven Capper Date: Tue, 18 Feb 2014 16:56:55 +0100 Subject: ARM: 7979/1: mm: Remove hugetlb warning from Coherent DMA allocator The Coherant DMA allocator allocates pages of high order then splits them up into smaller pages. This splitting logic would run into problems if the allocator was given compound pages. Thus the Coherant DMA allocator was originally incompatible with compound pages existing and, by extension, huge pages. A compile #error was put in place whenever huge pages were enabled. Compatibility with compound pages has since been introduced by the following commit (which merely excludes GFP_COMP pages from being requested by the coherant DMA allocator): ea2e705 ARM: 7172/1: dma: Drop GFP_COMP for DMA memory allocations When huge page support was introduced to ARM, the compile #error in dma-mapping.c was replaced by a #warning when it should have been removed instead. This patch removes the compile #warning in dma-mapping.c when huge pages are enabled. Signed-off-by: Steve Capper Signed-off-by: Russell King --- arch/arm/mm/dma-mapping.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 1a77450..5bb4e00 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -284,9 +284,6 @@ static void __dma_free_buffer(struct page *page, size_t size) } #ifdef CONFIG_MMU -#ifdef CONFIG_HUGETLB_PAGE -#warning ARM Coherent DMA allocator does not (yet) support huge TLB -#endif static void *__alloc_from_contiguous(struct device *dev, size_t size, pgprot_t prot, struct page **ret_page, -- cgit v1.1 From b3634575930857724d5c3987a2739b0637999b4e Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 18 Feb 2014 17:02:54 +0100 Subject: ARM: 7980/1: kernel: improve error message when LPAE config doesn't match CPU Currently, when the kernel is configured with LPAE support, but the CPU doesn't support it, the error message is fairly cryptic: Error: unrecognized/unsupported processor variant (0x561f5811). This messages is normally shown when there is an issue when comparing the processor ID (CP15 0, c0, c0) with the values/masks described in proc-v7.S. However, the same message is displayed when LPAE support is enabled in the kernel configuration, but not available in the CPU, after looking at ID_MMFR0 (CP15 0, c0, c1, 4). Having the same error message is highly misleading. This commit improves this by showing a different error message when this situation occurs: Error: Kernel with LPAE support, but CPU does not support LPAE. Signed-off-by: Thomas Petazzoni Signed-off-by: Russell King --- arch/arm/kernel/head-common.S | 12 ++++++++++++ arch/arm/kernel/head.S | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 47cd974..c96ecac 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -177,6 +177,18 @@ __lookup_processor_type_data: .long __proc_info_end .size __lookup_processor_type_data, . - __lookup_processor_type_data +__error_lpae: +#ifdef CONFIG_DEBUG_LL + adr r0, str_lpae + bl printascii + b __error +str_lpae: .asciz "\nError: Kernel with LPAE support, but CPU does not support LPAE.\n" +#else + b __error +#endif + .align +ENDPROC(__error_lpae) + __error_p: #ifdef CONFIG_DEBUG_LL adr r0, str_p1 diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 914616e..f5f381d 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -102,7 +102,7 @@ ENTRY(stext) and r3, r3, #0xf @ extract VMSA support cmp r3, #5 @ long-descriptor translation table format? THUMB( it lo ) @ force fixup-able long branch encoding - blo __error_p @ only classic page table format + blo __error_lpae @ only classic page table format #endif #ifndef CONFIG_XIP_KERNEL -- cgit v1.1 From c32ffce0f66e5d1d4856254516e24f5ef275cd00 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 21 Feb 2014 17:01:48 +0100 Subject: ARM: 7984/1: prefetch: add prefetchw invocations for barriered atomics After a bunch of benchmarking on the interaction between dmb and pldw, it turns out that issuing the pldw *after* the dmb instruction can give modest performance gains (~3% atomic_add_return improvement on a dual A15). This patch adds prefetchw invocations to our barriered atomic operations including cmpxchg, test_and_xxx and futexes. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/atomic.h | 9 +++++++++ arch/arm/include/asm/cmpxchg.h | 6 ++++++ arch/arm/include/asm/futex.h | 3 +++ arch/arm/lib/bitops.h | 5 +++++ 4 files changed, 23 insertions(+) diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h index 62d2cb5..6e41009 100644 --- a/arch/arm/include/asm/atomic.h +++ b/arch/arm/include/asm/atomic.h @@ -60,6 +60,7 @@ static inline int atomic_add_return(int i, atomic_t *v) int result; smp_mb(); + prefetchw(&v->counter); __asm__ __volatile__("@ atomic_add_return\n" "1: ldrex %0, [%3]\n" @@ -99,6 +100,7 @@ static inline int atomic_sub_return(int i, atomic_t *v) int result; smp_mb(); + prefetchw(&v->counter); __asm__ __volatile__("@ atomic_sub_return\n" "1: ldrex %0, [%3]\n" @@ -121,6 +123,7 @@ static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new) unsigned long res; smp_mb(); + prefetchw(&ptr->counter); do { __asm__ __volatile__("@ atomic_cmpxchg\n" @@ -299,6 +302,7 @@ static inline long long atomic64_add_return(long long i, atomic64_t *v) unsigned long tmp; smp_mb(); + prefetchw(&v->counter); __asm__ __volatile__("@ atomic64_add_return\n" "1: ldrexd %0, %H0, [%3]\n" @@ -340,6 +344,7 @@ static inline long long atomic64_sub_return(long long i, atomic64_t *v) unsigned long tmp; smp_mb(); + prefetchw(&v->counter); __asm__ __volatile__("@ atomic64_sub_return\n" "1: ldrexd %0, %H0, [%3]\n" @@ -364,6 +369,7 @@ static inline long long atomic64_cmpxchg(atomic64_t *ptr, long long old, unsigned long res; smp_mb(); + prefetchw(&ptr->counter); do { __asm__ __volatile__("@ atomic64_cmpxchg\n" @@ -388,6 +394,7 @@ static inline long long atomic64_xchg(atomic64_t *ptr, long long new) unsigned long tmp; smp_mb(); + prefetchw(&ptr->counter); __asm__ __volatile__("@ atomic64_xchg\n" "1: ldrexd %0, %H0, [%3]\n" @@ -409,6 +416,7 @@ static inline long long atomic64_dec_if_positive(atomic64_t *v) unsigned long tmp; smp_mb(); + prefetchw(&v->counter); __asm__ __volatile__("@ atomic64_dec_if_positive\n" "1: ldrexd %0, %H0, [%3]\n" @@ -436,6 +444,7 @@ static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u) int ret = 1; smp_mb(); + prefetchw(&v->counter); __asm__ __volatile__("@ atomic64_add_unless\n" "1: ldrexd %0, %H0, [%4]\n" diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h index df2fbba..abb2c37 100644 --- a/arch/arm/include/asm/cmpxchg.h +++ b/arch/arm/include/asm/cmpxchg.h @@ -2,6 +2,7 @@ #define __ASM_ARM_CMPXCHG_H #include +#include #include #if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110) @@ -35,6 +36,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size #endif smp_mb(); + prefetchw((const void *)ptr); switch (size) { #if __LINUX_ARM_ARCH__ >= 6 @@ -138,6 +140,8 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, { unsigned long oldval, res; + prefetchw((const void *)ptr); + switch (size) { #ifndef CONFIG_CPU_V6 /* min ARCH >= ARMv6K */ case 1: @@ -230,6 +234,8 @@ static inline unsigned long long __cmpxchg64(unsigned long long *ptr, unsigned long long oldval; unsigned long res; + prefetchw(ptr); + __asm__ __volatile__( "1: ldrexd %1, %H1, [%3]\n" " teq %1, %4\n" diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h index 2aff798..53e69da 100644 --- a/arch/arm/include/asm/futex.h +++ b/arch/arm/include/asm/futex.h @@ -23,6 +23,7 @@ #define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \ smp_mb(); \ + prefetchw(uaddr); \ __asm__ __volatile__( \ "1: ldrex %1, [%3]\n" \ " " insn "\n" \ @@ -46,6 +47,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, return -EFAULT; smp_mb(); + /* Prefetching cannot fault */ + prefetchw(uaddr); __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" "1: ldrex %1, [%4]\n" " teq %1, %2\n" diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h index 52886b8..9f12ed1 100644 --- a/arch/arm/lib/bitops.h +++ b/arch/arm/lib/bitops.h @@ -37,6 +37,11 @@ UNWIND( .fnstart ) add r1, r1, r0, lsl #2 @ Get word offset mov r3, r2, lsl r3 @ create mask smp_dmb +#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) + .arch_extension mp + ALT_SMP(W(pldw) [r1]) + ALT_UP(W(nop)) +#endif 1: ldrex r2, [r1] ands r0, r2, r3 @ save old value of bit \instr r2, r2, r3 @ toggle bit -- cgit v1.1 From 1971188aa19651d8f447211c6535fb68661d77c5 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 21 Feb 2014 17:01:48 +0100 Subject: ARM: 7985/1: mm: implement pte_accessible for faulting mappings The pte_accessible macro can be used to identify page table entries capable of being cached by a TLB. In principle, this differs from pte_present, since PROT_NONE mappings are mapped using invalid entries identified as present and ptes designated as `old' can use either invalid entries or those with the access flag cleared (guaranteed not to be in the TLB). However, there is a race to take care of, as described in 20841405940e ("mm: fix TLB flush race between migration, and change_protection_range"), between a page being migrated and mprotected at the same time. In this case, we can check whether a TLB invalidation is pending for the mm and if so, temporarily consider PROT_NONE mappings as valid. This patch implements a quick pte_accessible macro for ARM by simply checking if the pte is valid/present depending on the mm. For classic MMU, these checks are identical and will generate some false positives for PROT_NONE mappings, but this is better than the current asm-generic definition of ((void)(pte),1). Finally, pte_present_user is moved to use pte_valid (and renamed appropriately) since we don't care about cache flushing for faulting mappings. Acked-by: Steve Capper Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/pgtable.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 7d59b52..5478e5d 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -216,13 +216,16 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) #define pte_none(pte) (!pte_val(pte)) #define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) +#define pte_valid(pte) (pte_val(pte) & L_PTE_VALID) +#define pte_accessible(mm, pte) (mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid(pte)) #define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) #define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) #define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) #define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) #define pte_special(pte) (0) -#define pte_present_user(pte) (pte_present(pte) && (pte_val(pte) & L_PTE_USER)) +#define pte_valid_user(pte) \ + (pte_valid(pte) && (pte_val(pte) & L_PTE_USER) && pte_young(pte)) #if __LINUX_ARM_ARCH__ < 6 static inline void __sync_icache_dcache(pte_t pteval) @@ -237,7 +240,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, { unsigned long ext = 0; - if (addr < TASK_SIZE && pte_present_user(pteval)) { + if (addr < TASK_SIZE && pte_valid_user(pteval)) { __sync_icache_dcache(pteval); ext |= PTE_EXT_NG; } -- cgit v1.1 From 74c4137b2a9c73e7e6887ea1bac93d7012827012 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 24 Feb 2014 16:48:26 +0100 Subject: ARM: 7989/1: Delete asm/system.h Delete ARM's asm/system.h. It's the last holdout and should be got rid of. This builds for defconfig, lpc32xx_defconfig, exynos_defconfig + XEN, the previous changed to a Gemini system and an omap3 config with TI_DAVINCI_EMAC. Signed-off-by: David Howells Acked-by: Arnd Bergmann Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Russell King --- arch/arm/include/asm/jump_label.h | 1 - arch/arm/include/asm/sync_bitops.h | 1 - arch/arm/include/asm/system.h | 7 ------- arch/arm/mach-gemini/idle.c | 2 +- arch/arm/mach-omap2/am35xx-emac.c | 1 - drivers/usb/gadget/lpc32xx_udc.c | 1 - 6 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 arch/arm/include/asm/system.h diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h index 863c892..70f9b9b 100644 --- a/arch/arm/include/asm/jump_label.h +++ b/arch/arm/include/asm/jump_label.h @@ -4,7 +4,6 @@ #ifdef __KERNEL__ #include -#include #define JUMP_LABEL_NOP_SIZE 4 diff --git a/arch/arm/include/asm/sync_bitops.h b/arch/arm/include/asm/sync_bitops.h index 63479ee..9732b8e 100644 --- a/arch/arm/include/asm/sync_bitops.h +++ b/arch/arm/include/asm/sync_bitops.h @@ -2,7 +2,6 @@ #define __ASM_SYNC_BITOPS_H__ #include -#include /* sync_bitops functions are equivalent to the SMP implementation of the * original functions, independently from CONFIG_SMP being defined. diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h deleted file mode 100644 index 368165e..0000000 --- a/arch/arm/include/asm/system.h +++ /dev/null @@ -1,7 +0,0 @@ -/* FILE TO BE DELETED. DO NOT ADD STUFF HERE! */ -#include -#include -#include -#include -#include -#include diff --git a/arch/arm/mach-gemini/idle.c b/arch/arm/mach-gemini/idle.c index 87dff4f..ddf8ec9 100644 --- a/arch/arm/mach-gemini/idle.c +++ b/arch/arm/mach-gemini/idle.c @@ -3,7 +3,7 @@ */ #include -#include +#include #include static void gemini_idle(void) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 25b79a29..6a6935c 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -17,7 +17,6 @@ #include #include -#include #include "omap_device.h" #include "am35xx.h" #include "control.h" diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index 049ebab..a94bb10 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include -- cgit v1.1 From d98b90ea22b0a28d9d787769704a9cf1ea5a513a Mon Sep 17 00:00:00 2001 From: Victor Kamensky Date: Tue, 25 Feb 2014 08:41:09 +0100 Subject: ARM: 7990/1: asm: rename logical shift macros push pull into lspush lspull Renames logical shift macros, 'push' and 'pull', defined in arch/arm/include/asm/assembler.h, into 'lspush' and 'lspull'. That eliminates name conflict between 'push' logical shift macro and 'push' instruction mnemonic. That allows assembler.h to be included in .S files that use 'push' instruction. Suggested-by: Will Deacon Signed-off-by: Victor Kamensky Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/include/asm/assembler.h | 8 +- arch/arm/lib/copy_template.S | 36 +++---- arch/arm/lib/csumpartialcopygeneric.S | 96 ++++++++--------- arch/arm/lib/io-readsl.S | 12 +-- arch/arm/lib/io-writesl.S | 12 +-- arch/arm/lib/memmove.S | 36 +++---- arch/arm/lib/uaccess.S | 192 +++++++++++++++++----------------- 7 files changed, 196 insertions(+), 196 deletions(-) diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 5c22851..380ac4f 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -30,8 +30,8 @@ * Endian independent macros for shifting bytes within registers. */ #ifndef __ARMEB__ -#define pull lsr -#define push lsl +#define lspull lsr +#define lspush lsl #define get_byte_0 lsl #0 #define get_byte_1 lsr #8 #define get_byte_2 lsr #16 @@ -41,8 +41,8 @@ #define put_byte_2 lsl #16 #define put_byte_3 lsl #24 #else -#define pull lsl -#define push lsr +#define lspull lsl +#define lspush lsr #define get_byte_0 lsr #24 #define get_byte_1 lsr #16 #define get_byte_2 lsr #8 diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S index 805e3f8..3bc8eb8 100644 --- a/arch/arm/lib/copy_template.S +++ b/arch/arm/lib/copy_template.S @@ -197,24 +197,24 @@ 12: PLD( pld [r1, #124] ) 13: ldr4w r1, r4, r5, r6, r7, abort=19f - mov r3, lr, pull #\pull + mov r3, lr, lspull #\pull subs r2, r2, #32 ldr4w r1, r8, r9, ip, lr, abort=19f - orr r3, r3, r4, push #\push - mov r4, r4, pull #\pull - orr r4, r4, r5, push #\push - mov r5, r5, pull #\pull - orr r5, r5, r6, push #\push - mov r6, r6, pull #\pull - orr r6, r6, r7, push #\push - mov r7, r7, pull #\pull - orr r7, r7, r8, push #\push - mov r8, r8, pull #\pull - orr r8, r8, r9, push #\push - mov r9, r9, pull #\pull - orr r9, r9, ip, push #\push - mov ip, ip, pull #\pull - orr ip, ip, lr, push #\push + orr r3, r3, r4, lspush #\push + mov r4, r4, lspull #\pull + orr r4, r4, r5, lspush #\push + mov r5, r5, lspull #\pull + orr r5, r5, r6, lspush #\push + mov r6, r6, lspull #\pull + orr r6, r6, r7, lspush #\push + mov r7, r7, lspull #\pull + orr r7, r7, r8, lspush #\push + mov r8, r8, lspull #\pull + orr r8, r8, r9, lspush #\push + mov r9, r9, lspull #\pull + orr r9, r9, ip, lspush #\push + mov ip, ip, lspull #\pull + orr ip, ip, lr, lspush #\push str8w r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f bge 12b PLD( cmn r2, #96 ) @@ -225,10 +225,10 @@ 14: ands ip, r2, #28 beq 16f -15: mov r3, lr, pull #\pull +15: mov r3, lr, lspull #\pull ldr1w r1, lr, abort=21f subs ip, ip, #4 - orr r3, r3, lr, push #\push + orr r3, r3, lr, lspush #\push str1w r0, r3, abort=21f bgt 15b CALGN( cmp r2, #0 ) diff --git a/arch/arm/lib/csumpartialcopygeneric.S b/arch/arm/lib/csumpartialcopygeneric.S index d620a5f..d6e742d 100644 --- a/arch/arm/lib/csumpartialcopygeneric.S +++ b/arch/arm/lib/csumpartialcopygeneric.S @@ -141,7 +141,7 @@ FN_ENTRY tst len, #2 mov r5, r4, get_byte_0 beq .Lexit - adcs sum, sum, r4, push #16 + adcs sum, sum, r4, lspush #16 strb r5, [dst], #1 mov r5, r4, get_byte_1 strb r5, [dst], #1 @@ -171,23 +171,23 @@ FN_ENTRY cmp ip, #2 beq .Lsrc2_aligned bhi .Lsrc3_aligned - mov r4, r5, pull #8 @ C = 0 + mov r4, r5, lspull #8 @ C = 0 bics ip, len, #15 beq 2f 1: load4l r5, r6, r7, r8 - orr r4, r4, r5, push #24 - mov r5, r5, pull #8 - orr r5, r5, r6, push #24 - mov r6, r6, pull #8 - orr r6, r6, r7, push #24 - mov r7, r7, pull #8 - orr r7, r7, r8, push #24 + orr r4, r4, r5, lspush #24 + mov r5, r5, lspull #8 + orr r5, r5, r6, lspush #24 + mov r6, r6, lspull #8 + orr r6, r6, r7, lspush #24 + mov r7, r7, lspull #8 + orr r7, r7, r8, lspush #24 stmia dst!, {r4, r5, r6, r7} adcs sum, sum, r4 adcs sum, sum, r5 adcs sum, sum, r6 adcs sum, sum, r7 - mov r4, r8, pull #8 + mov r4, r8, lspull #8 sub ip, ip, #16 teq ip, #0 bne 1b @@ -196,50 +196,50 @@ FN_ENTRY tst ip, #8 beq 3f load2l r5, r6 - orr r4, r4, r5, push #24 - mov r5, r5, pull #8 - orr r5, r5, r6, push #24 + orr r4, r4, r5, lspush #24 + mov r5, r5, lspull #8 + orr r5, r5, r6, lspush #24 stmia dst!, {r4, r5} adcs sum, sum, r4 adcs sum, sum, r5 - mov r4, r6, pull #8 + mov r4, r6, lspull #8 tst ip, #4 beq 4f 3: load1l r5 - orr r4, r4, r5, push #24 + orr r4, r4, r5, lspush #24 str r4, [dst], #4 adcs sum, sum, r4 - mov r4, r5, pull #8 + mov r4, r5, lspull #8 4: ands len, len, #3 beq .Ldone mov r5, r4, get_byte_0 tst len, #2 beq .Lexit - adcs sum, sum, r4, push #16 + adcs sum, sum, r4, lspush #16 strb r5, [dst], #1 mov r5, r4, get_byte_1 strb r5, [dst], #1 mov r5, r4, get_byte_2 b .Lexit -.Lsrc2_aligned: mov r4, r5, pull #16 +.Lsrc2_aligned: mov r4, r5, lspull #16 adds sum, sum, #0 bics ip, len, #15 beq 2f 1: load4l r5, r6, r7, r8 - orr r4, r4, r5, push #16 - mov r5, r5, pull #16 - orr r5, r5, r6, push #16 - mov r6, r6, pull #16 - orr r6, r6, r7, push #16 - mov r7, r7, pull #16 - orr r7, r7, r8, push #16 + orr r4, r4, r5, lspush #16 + mov r5, r5, lspull #16 + orr r5, r5, r6, lspush #16 + mov r6, r6, lspull #16 + orr r6, r6, r7, lspush #16 + mov r7, r7, lspull #16 + orr r7, r7, r8, lspush #16 stmia dst!, {r4, r5, r6, r7} adcs sum, sum, r4 adcs sum, sum, r5 adcs sum, sum, r6 adcs sum, sum, r7 - mov r4, r8, pull #16 + mov r4, r8, lspull #16 sub ip, ip, #16 teq ip, #0 bne 1b @@ -248,20 +248,20 @@ FN_ENTRY tst ip, #8 beq 3f load2l r5, r6 - orr r4, r4, r5, push #16 - mov r5, r5, pull #16 - orr r5, r5, r6, push #16 + orr r4, r4, r5, lspush #16 + mov r5, r5, lspull #16 + orr r5, r5, r6, lspush #16 stmia dst!, {r4, r5} adcs sum, sum, r4 adcs sum, sum, r5 - mov r4, r6, pull #16 + mov r4, r6, lspull #16 tst ip, #4 beq 4f 3: load1l r5 - orr r4, r4, r5, push #16 + orr r4, r4, r5, lspush #16 str r4, [dst], #4 adcs sum, sum, r4 - mov r4, r5, pull #16 + mov r4, r5, lspull #16 4: ands len, len, #3 beq .Ldone mov r5, r4, get_byte_0 @@ -276,24 +276,24 @@ FN_ENTRY load1b r5 b .Lexit -.Lsrc3_aligned: mov r4, r5, pull #24 +.Lsrc3_aligned: mov r4, r5, lspull #24 adds sum, sum, #0 bics ip, len, #15 beq 2f 1: load4l r5, r6, r7, r8 - orr r4, r4, r5, push #8 - mov r5, r5, pull #24 - orr r5, r5, r6, push #8 - mov r6, r6, pull #24 - orr r6, r6, r7, push #8 - mov r7, r7, pull #24 - orr r7, r7, r8, push #8 + orr r4, r4, r5, lspush #8 + mov r5, r5, lspull #24 + orr r5, r5, r6, lspush #8 + mov r6, r6, lspull #24 + orr r6, r6, r7, lspush #8 + mov r7, r7, lspull #24 + orr r7, r7, r8, lspush #8 stmia dst!, {r4, r5, r6, r7} adcs sum, sum, r4 adcs sum, sum, r5 adcs sum, sum, r6 adcs sum, sum, r7 - mov r4, r8, pull #24 + mov r4, r8, lspull #24 sub ip, ip, #16 teq ip, #0 bne 1b @@ -302,20 +302,20 @@ FN_ENTRY tst ip, #8 beq 3f load2l r5, r6 - orr r4, r4, r5, push #8 - mov r5, r5, pull #24 - orr r5, r5, r6, push #8 + orr r4, r4, r5, lspush #8 + mov r5, r5, lspull #24 + orr r5, r5, r6, lspush #8 stmia dst!, {r4, r5} adcs sum, sum, r4 adcs sum, sum, r5 - mov r4, r6, pull #24 + mov r4, r6, lspull #24 tst ip, #4 beq 4f 3: load1l r5 - orr r4, r4, r5, push #8 + orr r4, r4, r5, lspush #8 str r4, [dst], #4 adcs sum, sum, r4 - mov r4, r5, pull #24 + mov r4, r5, lspull #24 4: ands len, len, #3 beq .Ldone mov r5, r4, get_byte_0 @@ -326,7 +326,7 @@ FN_ENTRY load1l r4 mov r5, r4, get_byte_0 strb r5, [dst], #1 - adcs sum, sum, r4, push #24 + adcs sum, sum, r4, lspush #24 mov r5, r4, get_byte_1 b .Lexit FN_EXIT diff --git a/arch/arm/lib/io-readsl.S b/arch/arm/lib/io-readsl.S index 5fb97e7..7a74309 100644 --- a/arch/arm/lib/io-readsl.S +++ b/arch/arm/lib/io-readsl.S @@ -47,25 +47,25 @@ ENTRY(__raw_readsl) strb ip, [r1], #1 4: subs r2, r2, #1 - mov ip, r3, pull #24 + mov ip, r3, lspull #24 ldrne r3, [r0] - orrne ip, ip, r3, push #8 + orrne ip, ip, r3, lspush #8 strne ip, [r1], #4 bne 4b b 8f 5: subs r2, r2, #1 - mov ip, r3, pull #16 + mov ip, r3, lspull #16 ldrne r3, [r0] - orrne ip, ip, r3, push #16 + orrne ip, ip, r3, lspush #16 strne ip, [r1], #4 bne 5b b 7f 6: subs r2, r2, #1 - mov ip, r3, pull #8 + mov ip, r3, lspull #8 ldrne r3, [r0] - orrne ip, ip, r3, push #24 + orrne ip, ip, r3, lspush #24 strne ip, [r1], #4 bne 6b diff --git a/arch/arm/lib/io-writesl.S b/arch/arm/lib/io-writesl.S index 8d3b781..d0d104a 100644 --- a/arch/arm/lib/io-writesl.S +++ b/arch/arm/lib/io-writesl.S @@ -41,26 +41,26 @@ ENTRY(__raw_writesl) blt 5f bgt 6f -4: mov ip, r3, pull #16 +4: mov ip, r3, lspull #16 ldr r3, [r1], #4 subs r2, r2, #1 - orr ip, ip, r3, push #16 + orr ip, ip, r3, lspush #16 str ip, [r0] bne 4b mov pc, lr -5: mov ip, r3, pull #8 +5: mov ip, r3, lspull #8 ldr r3, [r1], #4 subs r2, r2, #1 - orr ip, ip, r3, push #24 + orr ip, ip, r3, lspush #24 str ip, [r0] bne 5b mov pc, lr -6: mov ip, r3, pull #24 +6: mov ip, r3, lspull #24 ldr r3, [r1], #4 subs r2, r2, #1 - orr ip, ip, r3, push #8 + orr ip, ip, r3, lspush #8 str ip, [r0] bne 6b mov pc, lr diff --git a/arch/arm/lib/memmove.S b/arch/arm/lib/memmove.S index 938fc14..d1fc0c0 100644 --- a/arch/arm/lib/memmove.S +++ b/arch/arm/lib/memmove.S @@ -147,24 +147,24 @@ ENTRY(memmove) 12: PLD( pld [r1, #-128] ) 13: ldmdb r1!, {r7, r8, r9, ip} - mov lr, r3, push #\push + mov lr, r3, lspush #\push subs r2, r2, #32 ldmdb r1!, {r3, r4, r5, r6} - orr lr, lr, ip, pull #\pull - mov ip, ip, push #\push - orr ip, ip, r9, pull #\pull - mov r9, r9, push #\push - orr r9, r9, r8, pull #\pull - mov r8, r8, push #\push - orr r8, r8, r7, pull #\pull - mov r7, r7, push #\push - orr r7, r7, r6, pull #\pull - mov r6, r6, push #\push - orr r6, r6, r5, pull #\pull - mov r5, r5, push #\push - orr r5, r5, r4, pull #\pull - mov r4, r4, push #\push - orr r4, r4, r3, pull #\pull + orr lr, lr, ip, lspull #\pull + mov ip, ip, lspush #\push + orr ip, ip, r9, lspull #\pull + mov r9, r9, lspush #\push + orr r9, r9, r8, lspull #\pull + mov r8, r8, lspush #\push + orr r8, r8, r7, lspull #\pull + mov r7, r7, lspush #\push + orr r7, r7, r6, lspull #\pull + mov r6, r6, lspush #\push + orr r6, r6, r5, lspull #\pull + mov r5, r5, lspush #\push + orr r5, r5, r4, lspull #\pull + mov r4, r4, lspush #\push + orr r4, r4, r3, lspull #\pull stmdb r0!, {r4 - r9, ip, lr} bge 12b PLD( cmn r2, #96 ) @@ -175,10 +175,10 @@ ENTRY(memmove) 14: ands ip, r2, #28 beq 16f -15: mov lr, r3, push #\push +15: mov lr, r3, lspush #\push ldr r3, [r1, #-4]! subs ip, ip, #4 - orr lr, lr, r3, pull #\pull + orr lr, lr, r3, lspull #\pull str lr, [r0, #-4]! bgt 15b CALGN( cmp r2, #0 ) diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S index 5c908b1..e505209 100644 --- a/arch/arm/lib/uaccess.S +++ b/arch/arm/lib/uaccess.S @@ -117,9 +117,9 @@ USER( TUSER( strgtb) r3, [r0], #1) @ May fault .Lc2u_1fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .Lc2u_1nowords - mov r3, r7, pull #8 + mov r3, r7, lspull #8 ldr r7, [r1], #4 - orr r3, r3, r7, push #24 + orr r3, r3, r7, lspush #24 USER( TUSER( str) r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 @@ -131,30 +131,30 @@ USER( TUSER( str) r3, [r0], #4) @ May fault subs ip, ip, #16 blt .Lc2u_1rem8lp -.Lc2u_1cpy8lp: mov r3, r7, pull #8 +.Lc2u_1cpy8lp: mov r3, r7, lspull #8 ldmia r1!, {r4 - r7} subs ip, ip, #16 - orr r3, r3, r4, push #24 - mov r4, r4, pull #8 - orr r4, r4, r5, push #24 - mov r5, r5, pull #8 - orr r5, r5, r6, push #24 - mov r6, r6, pull #8 - orr r6, r6, r7, push #24 + orr r3, r3, r4, lspush #24 + mov r4, r4, lspull #8 + orr r4, r4, r5, lspush #24 + mov r5, r5, lspull #8 + orr r5, r5, r6, lspush #24 + mov r6, r6, lspull #8 + orr r6, r6, r7, lspush #24 stmia r0!, {r3 - r6} @ Shouldnt fault bpl .Lc2u_1cpy8lp .Lc2u_1rem8lp: tst ip, #8 - movne r3, r7, pull #8 + movne r3, r7, lspull #8 ldmneia r1!, {r4, r7} - orrne r3, r3, r4, push #24 - movne r4, r4, pull #8 - orrne r4, r4, r7, push #24 + orrne r3, r3, r4, lspush #24 + movne r4, r4, lspull #8 + orrne r4, r4, r7, lspush #24 stmneia r0!, {r3 - r4} @ Shouldnt fault tst ip, #4 - movne r3, r7, pull #8 + movne r3, r7, lspull #8 ldrne r7, [r1], #4 - orrne r3, r3, r7, push #24 + orrne r3, r3, r7, lspush #24 TUSER( strne) r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .Lc2u_1fupi @@ -172,9 +172,9 @@ USER( TUSER( strgtb) r3, [r0], #1) @ May fault .Lc2u_2fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .Lc2u_2nowords - mov r3, r7, pull #16 + mov r3, r7, lspull #16 ldr r7, [r1], #4 - orr r3, r3, r7, push #16 + orr r3, r3, r7, lspush #16 USER( TUSER( str) r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 @@ -186,30 +186,30 @@ USER( TUSER( str) r3, [r0], #4) @ May fault subs ip, ip, #16 blt .Lc2u_2rem8lp -.Lc2u_2cpy8lp: mov r3, r7, pull #16 +.Lc2u_2cpy8lp: mov r3, r7, lspull #16 ldmia r1!, {r4 - r7} subs ip, ip, #16 - orr r3, r3, r4, push #16 - mov r4, r4, pull #16 - orr r4, r4, r5, push #16 - mov r5, r5, pull #16 - orr r5, r5, r6, push #16 - mov r6, r6, pull #16 - orr r6, r6, r7, push #16 + orr r3, r3, r4, lspush #16 + mov r4, r4, lspull #16 + orr r4, r4, r5, lspush #16 + mov r5, r5, lspull #16 + orr r5, r5, r6, lspush #16 + mov r6, r6, lspull #16 + orr r6, r6, r7, lspush #16 stmia r0!, {r3 - r6} @ Shouldnt fault bpl .Lc2u_2cpy8lp .Lc2u_2rem8lp: tst ip, #8 - movne r3, r7, pull #16 + movne r3, r7, lspull #16 ldmneia r1!, {r4, r7} - orrne r3, r3, r4, push #16 - movne r4, r4, pull #16 - orrne r4, r4, r7, push #16 + orrne r3, r3, r4, lspush #16 + movne r4, r4, lspull #16 + orrne r4, r4, r7, lspush #16 stmneia r0!, {r3 - r4} @ Shouldnt fault tst ip, #4 - movne r3, r7, pull #16 + movne r3, r7, lspull #16 ldrne r7, [r1], #4 - orrne r3, r3, r7, push #16 + orrne r3, r3, r7, lspush #16 TUSER( strne) r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .Lc2u_2fupi @@ -227,9 +227,9 @@ USER( TUSER( strgtb) r3, [r0], #1) @ May fault .Lc2u_3fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .Lc2u_3nowords - mov r3, r7, pull #24 + mov r3, r7, lspull #24 ldr r7, [r1], #4 - orr r3, r3, r7, push #8 + orr r3, r3, r7, lspush #8 USER( TUSER( str) r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 @@ -241,30 +241,30 @@ USER( TUSER( str) r3, [r0], #4) @ May fault subs ip, ip, #16 blt .Lc2u_3rem8lp -.Lc2u_3cpy8lp: mov r3, r7, pull #24 +.Lc2u_3cpy8lp: mov r3, r7, lspull #24 ldmia r1!, {r4 - r7} subs ip, ip, #16 - orr r3, r3, r4, push #8 - mov r4, r4, pull #24 - orr r4, r4, r5, push #8 - mov r5, r5, pull #24 - orr r5, r5, r6, push #8 - mov r6, r6, pull #24 - orr r6, r6, r7, push #8 + orr r3, r3, r4, lspush #8 + mov r4, r4, lspull #24 + orr r4, r4, r5, lspush #8 + mov r5, r5, lspull #24 + orr r5, r5, r6, lspush #8 + mov r6, r6, lspull #24 + orr r6, r6, r7, lspush #8 stmia r0!, {r3 - r6} @ Shouldnt fault bpl .Lc2u_3cpy8lp .Lc2u_3rem8lp: tst ip, #8 - movne r3, r7, pull #24 + movne r3, r7, lspull #24 ldmneia r1!, {r4, r7} - orrne r3, r3, r4, push #8 - movne r4, r4, pull #24 - orrne r4, r4, r7, push #8 + orrne r3, r3, r4, lspush #8 + movne r4, r4, lspull #24 + orrne r4, r4, r7, lspush #8 stmneia r0!, {r3 - r4} @ Shouldnt fault tst ip, #4 - movne r3, r7, pull #24 + movne r3, r7, lspull #24 ldrne r7, [r1], #4 - orrne r3, r3, r7, push #8 + orrne r3, r3, r7, lspush #8 TUSER( strne) r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .Lc2u_3fupi @@ -382,9 +382,9 @@ USER( TUSER( ldr) r7, [r1], #4) @ May fault .Lcfu_1fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .Lcfu_1nowords - mov r3, r7, pull #8 + mov r3, r7, lspull #8 USER( TUSER( ldr) r7, [r1], #4) @ May fault - orr r3, r3, r7, push #24 + orr r3, r3, r7, lspush #24 str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 @@ -396,30 +396,30 @@ USER( TUSER( ldr) r7, [r1], #4) @ May fault subs ip, ip, #16 blt .Lcfu_1rem8lp -.Lcfu_1cpy8lp: mov r3, r7, pull #8 +.Lcfu_1cpy8lp: mov r3, r7, lspull #8 ldmia r1!, {r4 - r7} @ Shouldnt fault subs ip, ip, #16 - orr r3, r3, r4, push #24 - mov r4, r4, pull #8 - orr r4, r4, r5, push #24 - mov r5, r5, pull #8 - orr r5, r5, r6, push #24 - mov r6, r6, pull #8 - orr r6, r6, r7, push #24 + orr r3, r3, r4, lspush #24 + mov r4, r4, lspull #8 + orr r4, r4, r5, lspush #24 + mov r5, r5, lspull #8 + orr r5, r5, r6, lspush #24 + mov r6, r6, lspull #8 + orr r6, r6, r7, lspush #24 stmia r0!, {r3 - r6} bpl .Lcfu_1cpy8lp .Lcfu_1rem8lp: tst ip, #8 - movne r3, r7, pull #8 + movne r3, r7, lspull #8 ldmneia r1!, {r4, r7} @ Shouldnt fault - orrne r3, r3, r4, push #24 - movne r4, r4, pull #8 - orrne r4, r4, r7, push #24 + orrne r3, r3, r4, lspush #24 + movne r4, r4, lspull #8 + orrne r4, r4, r7, lspush #24 stmneia r0!, {r3 - r4} tst ip, #4 - movne r3, r7, pull #8 + movne r3, r7, lspull #8 USER( TUSER( ldrne) r7, [r1], #4) @ May fault - orrne r3, r3, r7, push #24 + orrne r3, r3, r7, lspush #24 strne r3, [r0], #4 ands ip, ip, #3 beq .Lcfu_1fupi @@ -437,9 +437,9 @@ USER( TUSER( ldrne) r7, [r1], #4) @ May fault .Lcfu_2fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .Lcfu_2nowords - mov r3, r7, pull #16 + mov r3, r7, lspull #16 USER( TUSER( ldr) r7, [r1], #4) @ May fault - orr r3, r3, r7, push #16 + orr r3, r3, r7, lspush #16 str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 @@ -452,30 +452,30 @@ USER( TUSER( ldr) r7, [r1], #4) @ May fault blt .Lcfu_2rem8lp -.Lcfu_2cpy8lp: mov r3, r7, pull #16 +.Lcfu_2cpy8lp: mov r3, r7, lspull #16 ldmia r1!, {r4 - r7} @ Shouldnt fault subs ip, ip, #16 - orr r3, r3, r4, push #16 - mov r4, r4, pull #16 - orr r4, r4, r5, push #16 - mov r5, r5, pull #16 - orr r5, r5, r6, push #16 - mov r6, r6, pull #16 - orr r6, r6, r7, push #16 + orr r3, r3, r4, lspush #16 + mov r4, r4, lspull #16 + orr r4, r4, r5, lspush #16 + mov r5, r5, lspull #16 + orr r5, r5, r6, lspush #16 + mov r6, r6, lspull #16 + orr r6, r6, r7, lspush #16 stmia r0!, {r3 - r6} bpl .Lcfu_2cpy8lp .Lcfu_2rem8lp: tst ip, #8 - movne r3, r7, pull #16 + movne r3, r7, lspull #16 ldmneia r1!, {r4, r7} @ Shouldnt fault - orrne r3, r3, r4, push #16 - movne r4, r4, pull #16 - orrne r4, r4, r7, push #16 + orrne r3, r3, r4, lspush #16 + movne r4, r4, lspull #16 + orrne r4, r4, r7, lspush #16 stmneia r0!, {r3 - r4} tst ip, #4 - movne r3, r7, pull #16 + movne r3, r7, lspull #16 USER( TUSER( ldrne) r7, [r1], #4) @ May fault - orrne r3, r3, r7, push #16 + orrne r3, r3, r7, lspush #16 strne r3, [r0], #4 ands ip, ip, #3 beq .Lcfu_2fupi @@ -493,9 +493,9 @@ USER( TUSER( ldrgtb) r3, [r1], #0) @ May fault .Lcfu_3fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .Lcfu_3nowords - mov r3, r7, pull #24 + mov r3, r7, lspull #24 USER( TUSER( ldr) r7, [r1], #4) @ May fault - orr r3, r3, r7, push #8 + orr r3, r3, r7, lspush #8 str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 @@ -507,30 +507,30 @@ USER( TUSER( ldr) r7, [r1], #4) @ May fault subs ip, ip, #16 blt .Lcfu_3rem8lp -.Lcfu_3cpy8lp: mov r3, r7, pull #24 +.Lcfu_3cpy8lp: mov r3, r7, lspull #24 ldmia r1!, {r4 - r7} @ Shouldnt fault - orr r3, r3, r4, push #8 - mov r4, r4, pull #24 - orr r4, r4, r5, push #8 - mov r5, r5, pull #24 - orr r5, r5, r6, push #8 - mov r6, r6, pull #24 - orr r6, r6, r7, push #8 + orr r3, r3, r4, lspush #8 + mov r4, r4, lspull #24 + orr r4, r4, r5, lspush #8 + mov r5, r5, lspull #24 + orr r5, r5, r6, lspush #8 + mov r6, r6, lspull #24 + orr r6, r6, r7, lspush #8 stmia r0!, {r3 - r6} subs ip, ip, #16 bpl .Lcfu_3cpy8lp .Lcfu_3rem8lp: tst ip, #8 - movne r3, r7, pull #24 + movne r3, r7, lspull #24 ldmneia r1!, {r4, r7} @ Shouldnt fault - orrne r3, r3, r4, push #8 - movne r4, r4, pull #24 - orrne r4, r4, r7, push #8 + orrne r3, r3, r4, lspush #8 + movne r4, r4, lspull #24 + orrne r4, r4, r7, lspush #8 stmneia r0!, {r3 - r4} tst ip, #4 - movne r3, r7, pull #24 + movne r3, r7, lspull #24 USER( TUSER( ldrne) r7, [r1], #4) @ May fault - orrne r3, r3, r7, push #8 + orrne r3, r3, r7, lspush #8 strne r3, [r0], #4 ands ip, ip, #3 beq .Lcfu_3fupi -- cgit v1.1 From db38ee874c48713d0723221d08332242e0088970 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 21 Feb 2014 17:01:48 +0100 Subject: ARM: 7983/1: atomics: implement a better __atomic_add_unless for v6+ Looking at perf profiles of multi-threaded hackbench runs, a significant performance hit appears to manifest from the cmpxchg loop used to implement the 32-bit atomic_add_unless function. This can be mitigated by writing a direct implementation of __atomic_add_unless which doesn't require iteration outside of the atomic operation. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/atomic.h | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h index 6e41009..9a92fd7 100644 --- a/arch/arm/include/asm/atomic.h +++ b/arch/arm/include/asm/atomic.h @@ -141,6 +141,33 @@ static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new) return oldval; } +static inline int __atomic_add_unless(atomic_t *v, int a, int u) +{ + int oldval, newval; + unsigned long tmp; + + smp_mb(); + prefetchw(&v->counter); + + __asm__ __volatile__ ("@ atomic_add_unless\n" +"1: ldrex %0, [%4]\n" +" teq %0, %5\n" +" beq 2f\n" +" add %1, %0, %6\n" +" strex %2, %1, [%4]\n" +" teq %2, #0\n" +" bne 1b\n" +"2:" + : "=&r" (oldval), "=&r" (newval), "=&r" (tmp), "+Qo" (v->counter) + : "r" (&v->counter), "r" (u), "r" (a) + : "cc"); + + if (oldval != u) + smp_mb(); + + return oldval; +} + #else /* ARM_ARCH_6 */ #ifdef CONFIG_SMP @@ -189,10 +216,6 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new) return ret; } -#endif /* __LINUX_ARM_ARCH__ */ - -#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) - static inline int __atomic_add_unless(atomic_t *v, int a, int u) { int c, old; @@ -203,6 +226,10 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) return c; } +#endif /* __LINUX_ARM_ARCH__ */ + +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) + #define atomic_inc(v) atomic_add(1, v) #define atomic_dec(v) atomic_sub(1, v) -- cgit v1.1 From 27e8efdbf1aecb65dd712fd93766f1a04b86ac22 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 21 Feb 2014 18:48:01 +0100 Subject: ARM: 7986/1: bios32: use pci_enable_resource to enable PCI resources This patch moves bios32 over to using the generic code for enabling PCI resources. Since the core code takes care of bridge resources too, we can also drop the explicit IO and MEMORY enabling for them in the arch code. A side-effect of this change is that we no longer explicitly enable devices when running in PCI_PROBE_ONLY mode. This stays closer to the meaning of the option and prevents us from trying to enable devices without any assigned resources (the core code refuses to enable resources without parents). Tested-by: Jason Gunthorpe Tested-by: Jingoo Han Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/bios32.c | 37 +++---------------------------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 317da88..91f4880 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -608,41 +608,10 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res, */ int pcibios_enable_device(struct pci_dev *dev, int mask) { - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for (idx = 0; idx < 6; idx++) { - /* Only set up the requested stuff */ - if (!(mask & (1 << idx))) - continue; - - r = dev->resource + idx; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because" - " of resource collisions\n", pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } + if (pci_has_flag(PCI_PROBE_ONLY)) + return 0; - /* - * Bridges (eg, cardbus bridges) need to be fully enabled - */ - if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) - cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY; - - if (cmd != old_cmd) { - printk("PCI: enabling device %s (%04x -> %04x)\n", - pci_name(dev), old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; + return pci_enable_resources(dev, mask); } int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, -- cgit v1.1 From b342ea4e4ff970518264c81eefd05f637e3f193a Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 19 Feb 2014 22:28:40 +0100 Subject: ARM: 7981/1: add support for AT_HWCAP2 ELF auxv entry This enables AT_HWCAP2 for ARM. The generic support for this new ELF auxv entry was added in commit 2171364d1a9 (powerpc: Add HWCAP2 aux entry) Signed-off-by: Ard Biesheuvel Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/asm/hwcap.h | 3 ++- arch/arm/include/uapi/asm/hwcap.h | 4 ++++ arch/arm/kernel/setup.c | 11 +++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/hwcap.h b/arch/arm/include/asm/hwcap.h index 6ff56ec..6e183fd 100644 --- a/arch/arm/include/asm/hwcap.h +++ b/arch/arm/include/asm/hwcap.h @@ -9,6 +9,7 @@ * instruction set this cpu supports. */ #define ELF_HWCAP (elf_hwcap) -extern unsigned int elf_hwcap; +#define ELF_HWCAP2 (elf_hwcap2) +extern unsigned int elf_hwcap, elf_hwcap2; #endif #endif diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h index 7dcc10d..87768b5 100644 --- a/arch/arm/include/uapi/asm/hwcap.h +++ b/arch/arm/include/uapi/asm/hwcap.h @@ -28,4 +28,8 @@ #define HWCAP_LPAE (1 << 20) #define HWCAP_EVTSTRM (1 << 21) +/* + * HWCAP2 flags - for elf_hwcap2 (in kernel) and AT_HWCAP2 + */ + #endif /* _UAPI__ASMARM_HWCAP_H */ diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index b0df976..dbb5449 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -100,6 +100,9 @@ EXPORT_SYMBOL(system_serial_high); unsigned int elf_hwcap __read_mostly; EXPORT_SYMBOL(elf_hwcap); +unsigned int elf_hwcap2 __read_mostly; +EXPORT_SYMBOL(elf_hwcap2); + #ifdef MULTI_CPU struct processor processor __read_mostly; @@ -1005,6 +1008,10 @@ static const char *hwcap_str[] = { NULL }; +static const char *hwcap2_str[] = { + NULL +}; + static int c_show(struct seq_file *m, void *v) { int i, j; @@ -1028,6 +1035,10 @@ static int c_show(struct seq_file *m, void *v) if (elf_hwcap & (1 << j)) seq_printf(m, "%s ", hwcap_str[j]); + for (j = 0; hwcap2_str[j]; j++) + if (elf_hwcap2 & (1 << j)) + seq_printf(m, "%s ", hwcap2_str[j]); + seq_printf(m, "\nCPU implementer\t: 0x%02x\n", cpuid >> 24); seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]); -- cgit v1.1 From 8258a9895c99cdaacad8edc4748c0a624c710961 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 19 Feb 2014 22:29:40 +0100 Subject: ARM: 7982/1: introduce HWCAP2 feature bits for ARMv8 Crypto Extensions This allocates feature bits 0-4 in HWCAP2 for the crypto and CRC extensions introduced in ARMv8. Signed-off-by: Ard Biesheuvel Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/uapi/asm/hwcap.h | 5 +++++ arch/arm/kernel/setup.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h index 87768b5..20d12f2 100644 --- a/arch/arm/include/uapi/asm/hwcap.h +++ b/arch/arm/include/uapi/asm/hwcap.h @@ -31,5 +31,10 @@ /* * HWCAP2 flags - for elf_hwcap2 (in kernel) and AT_HWCAP2 */ +#define HWCAP2_AES (1 << 0) +#define HWCAP2_PMULL (1 << 1) +#define HWCAP2_SHA1 (1 << 2) +#define HWCAP2_SHA2 (1 << 3) +#define HWCAP2_CRC32 (1 << 4) #endif /* _UAPI__ASMARM_HWCAP_H */ diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index dbb5449..0a6c70b 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -1009,6 +1009,11 @@ static const char *hwcap_str[] = { }; static const char *hwcap2_str[] = { + "aes", + "pmull", + "sha1", + "sha2", + "crc32", NULL }; -- cgit v1.1 From a51345770e519552e749ff457a2a9f83171a67b5 Mon Sep 17 00:00:00 2001 From: Anurag Aggarwal Date: Mon, 24 Feb 2014 11:17:36 +0100 Subject: ARM: 7987/1: ARM : unwinder : Prevent data abort due to stack overflow While unwinding backtrace, stack overflow is possible. This stack overflow can sometimes lead to data abort in system if the area after stack is not mapped to physical memory. To prevent this problem from happening, execute the instructions that can cause a data abort in separate helper functions, where a check for feasibility is made before reading each word from the stack. Signed-off-by: Anurag Aggarwal Reviewed-by: Dave Martin Signed-off-by: Russell King --- arch/arm/kernel/unwind.c | 137 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 100 insertions(+), 37 deletions(-) diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 00df012..3c21769 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -68,6 +68,12 @@ EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2); struct unwind_ctrl_block { unsigned long vrs[16]; /* virtual register set */ const unsigned long *insn; /* pointer to the current instructions word */ + unsigned long sp_high; /* highest value of sp allowed */ + /* + * 1 : check for stack overflow for each register pop. + * 0 : save overhead if there is plenty of stack remaining. + */ + int check_each_pop; int entries; /* number of entries left to interpret */ int byte; /* current byte number in the instructions word */ }; @@ -235,12 +241,85 @@ static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl) return ret; } +/* Before poping a register check whether it is feasible or not */ +static int unwind_pop_register(struct unwind_ctrl_block *ctrl, + unsigned long **vsp, unsigned int reg) +{ + if (unlikely(ctrl->check_each_pop)) + if (*vsp >= (unsigned long *)ctrl->sp_high) + return -URC_FAILURE; + + ctrl->vrs[reg] = *(*vsp)++; + return URC_OK; +} + +/* Helper functions to execute the instructions */ +static int unwind_exec_pop_subset_r4_to_r13(struct unwind_ctrl_block *ctrl, + unsigned long mask) +{ + unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; + int load_sp, reg = 4; + + load_sp = mask & (1 << (13 - 4)); + while (mask) { + if (mask & 1) + if (unwind_pop_register(ctrl, &vsp, reg)) + return -URC_FAILURE; + mask >>= 1; + reg++; + } + if (!load_sp) + ctrl->vrs[SP] = (unsigned long)vsp; + + return URC_OK; +} + +static int unwind_exec_pop_r4_to_rN(struct unwind_ctrl_block *ctrl, + unsigned long insn) +{ + unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; + int reg; + + /* pop R4-R[4+bbb] */ + for (reg = 4; reg <= 4 + (insn & 7); reg++) + if (unwind_pop_register(ctrl, &vsp, reg)) + return -URC_FAILURE; + + if (insn & 0x80) + if (unwind_pop_register(ctrl, &vsp, 14)) + return -URC_FAILURE; + + ctrl->vrs[SP] = (unsigned long)vsp; + + return URC_OK; +} + +static int unwind_exec_pop_subset_r0_to_r3(struct unwind_ctrl_block *ctrl, + unsigned long mask) +{ + unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; + int reg = 0; + + /* pop R0-R3 according to mask */ + while (mask) { + if (mask & 1) + if (unwind_pop_register(ctrl, &vsp, reg)) + return -URC_FAILURE; + mask >>= 1; + reg++; + } + ctrl->vrs[SP] = (unsigned long)vsp; + + return URC_OK; +} + /* * Execute the current unwind instruction. */ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) { unsigned long insn = unwind_get_byte(ctrl); + int ret = URC_OK; pr_debug("%s: insn = %08lx\n", __func__, insn); @@ -250,8 +329,6 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) ctrl->vrs[SP] -= ((insn & 0x3f) << 2) + 4; else if ((insn & 0xf0) == 0x80) { unsigned long mask; - unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; - int load_sp, reg = 4; insn = (insn << 8) | unwind_get_byte(ctrl); mask = insn & 0x0fff; @@ -261,29 +338,16 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) return -URC_FAILURE; } - /* pop R4-R15 according to mask */ - load_sp = mask & (1 << (13 - 4)); - while (mask) { - if (mask & 1) - ctrl->vrs[reg] = *vsp++; - mask >>= 1; - reg++; - } - if (!load_sp) - ctrl->vrs[SP] = (unsigned long)vsp; + ret = unwind_exec_pop_subset_r4_to_r13(ctrl, mask); + if (ret) + goto error; } else if ((insn & 0xf0) == 0x90 && (insn & 0x0d) != 0x0d) ctrl->vrs[SP] = ctrl->vrs[insn & 0x0f]; else if ((insn & 0xf0) == 0xa0) { - unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; - int reg; - - /* pop R4-R[4+bbb] */ - for (reg = 4; reg <= 4 + (insn & 7); reg++) - ctrl->vrs[reg] = *vsp++; - if (insn & 0x80) - ctrl->vrs[14] = *vsp++; - ctrl->vrs[SP] = (unsigned long)vsp; + ret = unwind_exec_pop_r4_to_rN(ctrl, insn); + if (ret) + goto error; } else if (insn == 0xb0) { if (ctrl->vrs[PC] == 0) ctrl->vrs[PC] = ctrl->vrs[LR]; @@ -291,8 +355,6 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) ctrl->entries = 0; } else if (insn == 0xb1) { unsigned long mask = unwind_get_byte(ctrl); - unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; - int reg = 0; if (mask == 0 || mask & 0xf0) { pr_warning("unwind: Spare encoding %04lx\n", @@ -300,14 +362,9 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) return -URC_FAILURE; } - /* pop R0-R3 according to mask */ - while (mask) { - if (mask & 1) - ctrl->vrs[reg] = *vsp++; - mask >>= 1; - reg++; - } - ctrl->vrs[SP] = (unsigned long)vsp; + ret = unwind_exec_pop_subset_r0_to_r3(ctrl, mask); + if (ret) + goto error; } else if (insn == 0xb2) { unsigned long uleb128 = unwind_get_byte(ctrl); @@ -320,7 +377,8 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) pr_debug("%s: fp = %08lx sp = %08lx lr = %08lx pc = %08lx\n", __func__, ctrl->vrs[FP], ctrl->vrs[SP], ctrl->vrs[LR], ctrl->vrs[PC]); - return URC_OK; +error: + return ret; } /* @@ -329,13 +387,13 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) */ int unwind_frame(struct stackframe *frame) { - unsigned long high, low; + unsigned long low; const struct unwind_idx *idx; struct unwind_ctrl_block ctrl; - /* only go to a higher address on the stack */ + /* store the highest address on the stack to avoid crossing it*/ low = frame->sp; - high = ALIGN(low, THREAD_SIZE); + ctrl.sp_high = ALIGN(low, THREAD_SIZE); pr_debug("%s(pc = %08lx lr = %08lx sp = %08lx)\n", __func__, frame->pc, frame->lr, frame->sp); @@ -382,11 +440,16 @@ int unwind_frame(struct stackframe *frame) return -URC_FAILURE; } + ctrl.check_each_pop = 0; + while (ctrl.entries > 0) { - int urc = unwind_exec_insn(&ctrl); + int urc; + if ((ctrl.sp_high - ctrl.vrs[SP]) < sizeof(ctrl.vrs)) + ctrl.check_each_pop = 1; + urc = unwind_exec_insn(&ctrl); if (urc < 0) return urc; - if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= high) + if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= ctrl.sp_high) return -URC_FAILURE; } -- cgit v1.1 From 006fa2599bf0daf107cbb7a8a99fcfb9a998a169 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 26 Feb 2014 19:40:46 +0000 Subject: ARM: fix noMMU kallsyms symbol filtering With noMMU, CONFIG_PAGE_OFFSET was not being set correctly. As there's no MMU, PAGE_OFFSET should be equal to PHYS_OFFSET in all cases. This commit makes that explicit. Since we do this, we don't need to mess around in asm/memory.h with ifdefs to sort this out, so let's get rid of that, and there's no point offering the "Memory split" option for noMMU as that's meaningless there. Fixes: b9b32bf70f2f ("ARM: use linker magic for vectors and vector stubs") Cc: Signed-off-by: Russell King --- arch/arm/Kconfig | 2 ++ arch/arm/include/asm/memory.h | 9 +++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e254198..2a232ce 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1578,6 +1578,7 @@ config BL_SWITCHER_DUMMY_IF choice prompt "Memory split" + depends on MMU default VMSPLIT_3G help Select the desired split between kernel and user memory. @@ -1595,6 +1596,7 @@ endchoice config PAGE_OFFSET hex + default PHYS_OFFSET if !MMU default 0x40000000 if VMSPLIT_1G default 0x80000000 if VMSPLIT_2G default 0xC0000000 diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 8756e4b..4afb376 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -30,14 +30,15 @@ */ #define UL(x) _AC(x, UL) +/* PAGE_OFFSET - the virtual address of the start of the kernel image */ +#define PAGE_OFFSET UL(CONFIG_PAGE_OFFSET) + #ifdef CONFIG_MMU /* - * PAGE_OFFSET - the virtual address of the start of the kernel image * TASK_SIZE - the maximum size of a user space task. * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area */ -#define PAGE_OFFSET UL(CONFIG_PAGE_OFFSET) #define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_16M)) #define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M) @@ -104,10 +105,6 @@ #define END_MEM (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE) #endif -#ifndef PAGE_OFFSET -#define PAGE_OFFSET PLAT_PHYS_OFFSET -#endif - /* * The module can be at any place in ram in nommu mode. */ -- cgit v1.1 From 052450fdc55894a39fbae93d9bbe43947956f663 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 25 Feb 2014 22:41:41 +0100 Subject: ARM: 7991/1: sa1100: fix compile problem on Collie Due to a problem in the MFD Kconfig it was not possible to compile the UCB battery driver for the Collie SA1100 system, in turn making it impossible to compile in the battery driver. (See patch "mfd: include all drivers in subsystem menu".) After fixing the MFD Kconfig (separate patch) a compile error appears in the Collie battery driver due to the implicitly requiring through via prior to commit 40ca061b "ARM: 7841/1: sa1100: remove complex GPIO interface". Fix this up by including the required header into . Cc: stable@vger.kernel.org Cc: Andrea Adami Cc: Dmitry Eremin-Solenikov Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-sa1100/include/mach/collie.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-sa1100/include/mach/collie.h b/arch/arm/mach-sa1100/include/mach/collie.h index f33679d..50e1d85 100644 --- a/arch/arm/mach-sa1100/include/mach/collie.h +++ b/arch/arm/mach-sa1100/include/mach/collie.h @@ -13,6 +13,8 @@ #ifndef __ASM_ARCH_COLLIE_H #define __ASM_ARCH_COLLIE_H +#include "hardware.h" /* Gives GPIO_MAX */ + extern void locomolcd_power(int on); #define COLLIE_SCOOP_GPIO_BASE (GPIO_MAX + 1) -- cgit v1.1 From 38e0b088d322e5762ac21fb4df433e83faf128eb Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 26 Feb 2014 17:21:26 +0100 Subject: ARM: 7992/1: boot: compressed: ignore bswapsdi2.S Commit 017f161a55b4 (ARM: 7877/1: use built-in byte swap function) added bswapsdi2.{o,S} to arch/arm/boot/compressed/Makefile, but didn't update the .gitignore. Thus after a a build git status shows bswapsdi2.S as a new file, which is a little annoying. This patch updates arch/arm/boot/compressed/.gitignore to ignore bswapsdi2.S, as we already do for ashldi3.S and others. Signed-off-by: Mark Rutland Acked-by: Nicolas Pitre Acked-by: Kim Phillips Cc: David Woodhouse Signed-off-by: Russell King --- arch/arm/boot/compressed/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore index 47279aa..0714e03 100644 --- a/arch/arm/boot/compressed/.gitignore +++ b/arch/arm/boot/compressed/.gitignore @@ -1,4 +1,5 @@ ashldi3.S +bswapsdi2.S font.c lib1funcs.S hyp-stub.S -- cgit v1.1 From fec510141088ca1f15d1b79f9f6838810d668b77 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Thu, 27 Feb 2014 01:23:43 +0100 Subject: ARM: 7993/1: mm/memblock: add memblock_get_current_limit Apart from setting the limit of memblock, it's also useful to be able to get the limit to avoid recalculating it every time. Add the function to do so. Acked-by: Catalin Marinas Acked-by: Santosh Shilimkar Acked-by: Andrew Morton Acked-by: Nicolas Pitre Signed-off-by: Laura Abbott Signed-off-by: Russell King --- include/linux/memblock.h | 2 ++ mm/memblock.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 1ef6636..8a20a51 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -252,6 +252,8 @@ static inline void memblock_dump_all(void) void memblock_set_current_limit(phys_addr_t limit); +phys_addr_t memblock_get_current_limit(void); + /* * pfn conversion functions * diff --git a/mm/memblock.c b/mm/memblock.c index 39a31e7..7fe5354 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1407,6 +1407,11 @@ void __init_memblock memblock_set_current_limit(phys_addr_t limit) memblock.current_limit = limit; } +phys_addr_t __init_memblock memblock_get_current_limit(void) +{ + return memblock.current_limit; +} + static void __init_memblock memblock_dump(struct memblock_type *type, char *name) { unsigned long long base, size; -- cgit v1.1 From 26632becc3c126599567d7fec69c9d91cf3dc124 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Tue, 4 Mar 2014 21:45:48 +0100 Subject: ARM: 7995/1: footbridge: remove obsolete IRQF_DISABLED This patch removes the IRQF_DISABLED flag from footbridge code. It's a NOOP since 2.6.35. Signed-off-by: Michael Opdenacker Signed-off-by: Russell King --- arch/arm/mach-footbridge/dc21285-timer.c | 2 +- arch/arm/mach-footbridge/dc21285.c | 10 +++++----- arch/arm/mach-footbridge/isa-timer.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index 5d2725f..bf7aa7d 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -105,7 +105,7 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id) static struct irqaction footbridge_timer_irq = { .name = "dc21285_timer1", .handler = timer1_interrupt, - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .dev_id = &ckevt_dc21285, }; diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c index 7c2fdae..96a3d73 100644 --- a/arch/arm/mach-footbridge/dc21285.c +++ b/arch/arm/mach-footbridge/dc21285.c @@ -334,15 +334,15 @@ void __init dc21285_preinit(void) /* * We don't care if these fail. */ - dc21285_request_irq(IRQ_PCI_SERR, dc21285_serr_irq, IRQF_DISABLED, + dc21285_request_irq(IRQ_PCI_SERR, dc21285_serr_irq, 0, "PCI system error", &serr_timer); - dc21285_request_irq(IRQ_PCI_PERR, dc21285_parity_irq, IRQF_DISABLED, + dc21285_request_irq(IRQ_PCI_PERR, dc21285_parity_irq, 0, "PCI parity error", &perr_timer); - dc21285_request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, IRQF_DISABLED, + dc21285_request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, 0, "PCI abort", NULL); - dc21285_request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, IRQF_DISABLED, + dc21285_request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, 0, "Discard timer", NULL); - dc21285_request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, IRQF_DISABLED, + dc21285_request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, 0, "PCI data parity", NULL); if (cfn_mode) { diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c index d9301dd..b73f52e 100644 --- a/arch/arm/mach-footbridge/isa-timer.c +++ b/arch/arm/mach-footbridge/isa-timer.c @@ -27,7 +27,7 @@ static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) static struct irqaction pit_timer_irq = { .name = "pit", .handler = pit_timer_interrupt, - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .dev_id = &i8253_clockevent, }; -- cgit v1.1 From 57c06a8ed7db71e14a4388590ad258c5b557e557 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Tue, 4 Mar 2014 21:51:44 +0100 Subject: ARM: 7996/1: floppy.h: remove deprecated IRQF_DISABLED This patch removes the use of the IRQF_DISABLED flag in arch/arm/include/asm/floppy.h It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Signed-off-by: Russell King --- arch/arm/include/asm/floppy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/include/asm/floppy.h b/arch/arm/include/asm/floppy.h index c9f03ec..f488255 100644 --- a/arch/arm/include/asm/floppy.h +++ b/arch/arm/include/asm/floppy.h @@ -25,7 +25,7 @@ #define fd_inb(port) inb((port)) #define fd_request_irq() request_irq(IRQ_FLOPPYDISK,floppy_interrupt,\ - IRQF_DISABLED,"floppy",NULL) + 0,"floppy",NULL) #define fd_free_irq() free_irq(IRQ_FLOPPYDISK,NULL) #define fd_disable_irq() disable_irq(IRQ_FLOPPYDISK) #define fd_enable_irq() enable_irq(IRQ_FLOPPYDISK) -- cgit v1.1 From 19bd9b286da6f28f4cb04757dd8509a38f9f34d7 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Tue, 4 Mar 2014 21:56:10 +0100 Subject: ARM: 7997/1: cns3xxx: remove deprecated IRQF_DISABLED This patch removes the use of the IRQF_DISABLED flag from arch/arm/mach-cns3xxx/core.c It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Signed-off-by: Russell King --- arch/arm/mach-cns3xxx/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c index e38b279..384dc85 100644 --- a/arch/arm/mach-cns3xxx/core.c +++ b/arch/arm/mach-cns3xxx/core.c @@ -155,7 +155,7 @@ static irqreturn_t cns3xxx_timer_interrupt(int irq, void *dev_id) static struct irqaction cns3xxx_timer_irq = { .name = "timer", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = cns3xxx_timer_interrupt, }; -- cgit v1.1 From 1ee6564d72ce718bf4e50d5684aa98d9d895f859 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Tue, 4 Mar 2014 21:59:03 +0100 Subject: ARM: 7998/1: IXP4xx: remove deprecated IRQF_DISABLED This patch removes the use of the IRQF_DISABLED flag from code in arch/arm/mach-ixp4xx It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Signed-off-by: Russell King --- arch/arm/mach-ixp4xx/common.c | 2 +- arch/arm/mach-ixp4xx/dsmg600-setup.c | 3 +-- arch/arm/mach-ixp4xx/fsg-setup.c | 6 ++---- arch/arm/mach-ixp4xx/nas100d-setup.c | 3 +-- arch/arm/mach-ixp4xx/nslu2-setup.c | 6 ++---- 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 6d68aed..a465f27 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -312,7 +312,7 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id) static struct irqaction ixp4xx_timer_irq = { .name = "timer1", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = ixp4xx_timer_interrupt, .dev_id = &clockevent_ixp4xx, }; diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c index 736dc69..43ee06d 100644 --- a/arch/arm/mach-ixp4xx/dsmg600-setup.c +++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c @@ -233,8 +233,7 @@ static int __init dsmg600_gpio_init(void) gpio_request(DSMG600_RB_GPIO, "reset button"); if (request_irq(gpio_to_irq(DSMG600_RB_GPIO), &dsmg600_reset_handler, - IRQF_DISABLED | IRQF_TRIGGER_LOW, - "DSM-G600 reset button", NULL) < 0) { + IRQF_TRIGGER_LOW, "DSM-G600 reset button", NULL) < 0) { printk(KERN_DEBUG "Reset Button IRQ %d not available\n", gpio_to_irq(DSMG600_RB_GPIO)); diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c index 429966b7..5c4b0c4 100644 --- a/arch/arm/mach-ixp4xx/fsg-setup.c +++ b/arch/arm/mach-ixp4xx/fsg-setup.c @@ -208,16 +208,14 @@ static void __init fsg_init(void) platform_add_devices(fsg_devices, ARRAY_SIZE(fsg_devices)); if (request_irq(gpio_to_irq(FSG_RB_GPIO), &fsg_reset_handler, - IRQF_DISABLED | IRQF_TRIGGER_LOW, - "FSG reset button", NULL) < 0) { + IRQF_TRIGGER_LOW, "FSG reset button", NULL) < 0) { printk(KERN_DEBUG "Reset Button IRQ %d not available\n", gpio_to_irq(FSG_RB_GPIO)); } if (request_irq(gpio_to_irq(FSG_SB_GPIO), &fsg_power_handler, - IRQF_DISABLED | IRQF_TRIGGER_LOW, - "FSG power button", NULL) < 0) { + IRQF_TRIGGER_LOW, "FSG power button", NULL) < 0) { printk(KERN_DEBUG "Power Button IRQ %d not available\n", gpio_to_irq(FSG_SB_GPIO)); diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c index 507cb52..4e0f762 100644 --- a/arch/arm/mach-ixp4xx/nas100d-setup.c +++ b/arch/arm/mach-ixp4xx/nas100d-setup.c @@ -295,8 +295,7 @@ static void __init nas100d_init(void) pm_power_off = nas100d_power_off; if (request_irq(gpio_to_irq(NAS100D_RB_GPIO), &nas100d_reset_handler, - IRQF_DISABLED | IRQF_TRIGGER_LOW, - "NAS100D reset button", NULL) < 0) { + IRQF_TRIGGER_LOW, "NAS100D reset button", NULL) < 0) { printk(KERN_DEBUG "Reset Button IRQ %d not available\n", gpio_to_irq(NAS100D_RB_GPIO)); diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c index ba5f1cd..88c025f 100644 --- a/arch/arm/mach-ixp4xx/nslu2-setup.c +++ b/arch/arm/mach-ixp4xx/nslu2-setup.c @@ -265,16 +265,14 @@ static void __init nslu2_init(void) pm_power_off = nslu2_power_off; if (request_irq(gpio_to_irq(NSLU2_RB_GPIO), &nslu2_reset_handler, - IRQF_DISABLED | IRQF_TRIGGER_LOW, - "NSLU2 reset button", NULL) < 0) { + IRQF_TRIGGER_LOW, "NSLU2 reset button", NULL) < 0) { printk(KERN_DEBUG "Reset Button IRQ %d not available\n", gpio_to_irq(NSLU2_RB_GPIO)); } if (request_irq(gpio_to_irq(NSLU2_PB_GPIO), &nslu2_power_handler, - IRQF_DISABLED | IRQF_TRIGGER_HIGH, - "NSLU2 power button", NULL) < 0) { + IRQF_TRIGGER_HIGH, "NSLU2 power button", NULL) < 0) { printk(KERN_DEBUG "Power Button IRQ %d not available\n", gpio_to_irq(NSLU2_PB_GPIO)); -- cgit v1.1 From a09df10585d3b3b7a2f640b11fabea262e751091 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Tue, 4 Mar 2014 22:02:14 +0100 Subject: ARM: 7999/1: arch/arm/mach-lpc32xx-remove-irqf-disabled This patch removes the use of the IRQF_DISABLED flag from arch/arm/mach-lpc32xx/timer.c It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Signed-off-by: Russell King --- arch/arm/mach-lpc32xx/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c index 20eab63..4e583729 100644 --- a/arch/arm/mach-lpc32xx/timer.c +++ b/arch/arm/mach-lpc32xx/timer.c @@ -90,7 +90,7 @@ static irqreturn_t lpc32xx_timer_interrupt(int irq, void *dev_id) static struct irqaction lpc32xx_timer_irq = { .name = "LPC32XX Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = lpc32xx_timer_interrupt, }; -- cgit v1.1 From 78f6db99522bbdd2f2a90c963744bd51c8602990 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Tue, 4 Mar 2014 22:04:50 +0100 Subject: ARM: 8000/1: misc: remove deprecated IRQF_DISABLED This patch removes the use of the IRQF_DISABLED flag from miscellaneous code in mach-xxx and plat-xxx This flag is a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Acked-by: Linus Walleij Acked-by: Greg Ungerer Signed-off-by: Russell King --- arch/arm/mach-ebsa110/core.c | 2 +- arch/arm/mach-integrator/integrator_ap.c | 2 +- arch/arm/mach-ks8695/time.c | 2 +- arch/arm/mach-netx/time.c | 2 +- arch/arm/mach-rpc/dma.c | 2 +- arch/arm/mach-rpc/time.c | 1 - arch/arm/mach-sa1100/time.c | 2 +- arch/arm/mach-u300/timer.c | 2 +- arch/arm/plat-iop/time.c | 2 +- 9 files changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c index 68ac934..8254e71 100644 --- a/arch/arm/mach-ebsa110/core.c +++ b/arch/arm/mach-ebsa110/core.c @@ -206,7 +206,7 @@ ebsa110_timer_interrupt(int irq, void *dev_id) static struct irqaction ebsa110_timer_irq = { .name = "EBSA110 Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = ebsa110_timer_interrupt, }; diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 17c0fe6..e4f27f0 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -358,7 +358,7 @@ static struct clock_event_device integrator_clockevent = { static struct irqaction integrator_timer_irq = { .name = "timer", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = integrator_timer_interrupt, .dev_id = &integrator_clockevent, }; diff --git a/arch/arm/mach-ks8695/time.c b/arch/arm/mach-ks8695/time.c index 426c976..a197874 100644 --- a/arch/arm/mach-ks8695/time.c +++ b/arch/arm/mach-ks8695/time.c @@ -122,7 +122,7 @@ static irqreturn_t ks8695_timer_interrupt(int irq, void *dev_id) static struct irqaction ks8695_timer_irq = { .name = "ks8695_tick", - .flags = IRQF_DISABLED | IRQF_TIMER, + .flags = IRQF_TIMER, .handler = ks8695_timer_interrupt, }; diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c index 6df42e6..3177c7a 100644 --- a/arch/arm/mach-netx/time.c +++ b/arch/arm/mach-netx/time.c @@ -99,7 +99,7 @@ netx_timer_interrupt(int irq, void *dev_id) static struct irqaction netx_timer_irq = { .name = "NetX Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = netx_timer_interrupt, }; diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c index 85883b2..6d3517d 100644 --- a/arch/arm/mach-rpc/dma.c +++ b/arch/arm/mach-rpc/dma.c @@ -141,7 +141,7 @@ static int iomd_request_dma(unsigned int chan, dma_t *dma) struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma); return request_irq(idma->irq, iomd_dma_handle, - IRQF_DISABLED, idma->dma.device_id, idma); + 0, idma->dma.device_id, idma); } static void iomd_free_dma(unsigned int chan, dma_t *dma) diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c index 9a6def1..9a51588 100644 --- a/arch/arm/mach-rpc/time.c +++ b/arch/arm/mach-rpc/time.c @@ -75,7 +75,6 @@ ioc_timer_interrupt(int irq, void *dev_id) static struct irqaction ioc_timer_irq = { .name = "timer", - .flags = IRQF_DISABLED, .handler = ioc_timer_interrupt }; diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 6fd4acb..4852c08 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -112,7 +112,7 @@ static struct clock_event_device ckevt_sa1100_osmr0 = { static struct irqaction sa1100_timer_irq = { .name = "ost0", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = sa1100_ost0_interrupt, .dev_id = &ckevt_sa1100_osmr0, }; diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index fe08fd3..de52cb3 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c @@ -337,7 +337,7 @@ static irqreturn_t u300_timer_interrupt(int irq, void *dev_id) static struct irqaction u300_timer_irq = { .name = "U300 Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = u300_timer_interrupt, }; diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index d70b733..6ad65d8 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c @@ -127,7 +127,7 @@ iop_timer_interrupt(int irq, void *dev_id) static struct irqaction iop_timer_irq = { .name = "IOP Timer Tick", .handler = iop_timer_interrupt, - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .dev_id = &iop_clockevent, }; -- cgit v1.1 From 9929eedc0c3495105018f3c632ee73b7fb4c1f72 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Tue, 4 Mar 2014 22:07:26 +0100 Subject: ARM: 8001/1: mmp: remove deprecated IRQF_DISABLED This patch removes the use of the IRQF_DISABLED flag from arch/arm/mach-mmp/time.c It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Signed-off-by: Russell King --- arch/arm/mach-mmp/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index 024022d..bbcd232 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c @@ -186,7 +186,7 @@ static void __init timer_config(void) static struct irqaction timer_irq = { .name = "timer", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = timer_interrupt, .dev_id = &ckevt, }; -- cgit v1.1 From 49710fa4d20cf4e210fa1dc59d7dd39181eeea11 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Tue, 4 Mar 2014 22:09:18 +0100 Subject: ARM: 8002/1: spear: remove deprecated IRQF_DISABLED This patch removes the use of the IRQF_DISABLED flag from arch/arm/mach-spear/time.c It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Signed-off-by: Russell King --- arch/arm/mach-spear/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-spear/time.c b/arch/arm/mach-spear/time.c index d449673..218ba5b 100644 --- a/arch/arm/mach-spear/time.c +++ b/arch/arm/mach-spear/time.c @@ -172,7 +172,7 @@ static irqreturn_t spear_timer_interrupt(int irq, void *dev_id) static struct irqaction spear_timer_irq = { .name = "timer", - .flags = IRQF_DISABLED | IRQF_TIMER, + .flags = IRQF_TIMER, .handler = spear_timer_interrupt }; -- cgit v1.1 From 2ed71e7531878b74c0d018891a55ca190a2f1f1b Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Tue, 4 Mar 2014 22:11:56 +0100 Subject: ARM: 8003/1: w90x900: remove deprecated IRQF_DISABLED This patch removes the use of the IRQF_DISABLED flag from arch/arm/mach-w90x900/time.c It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Acked-by: Wan zongshun Signed-off-by: Russell King --- arch/arm/mach-w90x900/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c index 30fbca8..9230d37 100644 --- a/arch/arm/mach-w90x900/time.c +++ b/arch/arm/mach-w90x900/time.c @@ -111,7 +111,7 @@ static irqreturn_t nuc900_timer0_interrupt(int irq, void *dev_id) static struct irqaction nuc900_timer0_irq = { .name = "nuc900-timer0", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = nuc900_timer0_interrupt, }; -- cgit v1.1 From 83b3f64d46d1d9bf1e0be1d16f805ccdd52d31c6 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Wed, 5 Mar 2014 06:23:13 +0100 Subject: ARM: 8004/1: [SCSI]: remove deprecated IRQF_DISABLED This patch removes the use of the IRQF_DISABLED flag from drivers/scsi/arm It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Signed-off-by: Russell King --- drivers/scsi/arm/acornscsi.c | 2 +- drivers/scsi/arm/cumana_1.c | 2 +- drivers/scsi/arm/cumana_2.c | 2 +- drivers/scsi/arm/powertec.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index 09ba186..059ff47 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -2971,7 +2971,7 @@ static int acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id) ec->irqaddr = ashost->fast + INT_REG; ec->irqmask = 0x0a; - ret = request_irq(host->irq, acornscsi_intr, IRQF_DISABLED, "acornscsi", ashost); + ret = request_irq(host->irq, acornscsi_intr, 0, "acornscsi", ashost); if (ret) { printk(KERN_CRIT "scsi%d: IRQ%d not free: %d\n", host->host_no, ashost->scsi.irq, ret); diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index b679778..f8e0609 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -262,7 +262,7 @@ static int cumanascsi1_probe(struct expansion_card *ec, goto out_unmap; } - ret = request_irq(host->irq, cumanascsi_intr, IRQF_DISABLED, + ret = request_irq(host->irq, cumanascsi_intr, 0, "CumanaSCSI-1", host); if (ret) { printk("scsi%d: IRQ%d not free: %d\n", diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index 58915f2..abc66f5 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -431,7 +431,7 @@ static int cumanascsi2_probe(struct expansion_card *ec, goto out_free; ret = request_irq(ec->irq, cumanascsi_2_intr, - IRQF_DISABLED, "cumanascsi2", info); + 0, "cumanascsi2", info); if (ret) { printk("scsi%d: IRQ%d not free: %d\n", host->host_no, ec->irq, ret); diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index abc9593..5e1b73e 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -358,7 +358,7 @@ static int powertecscsi_probe(struct expansion_card *ec, goto out_free; ret = request_irq(ec->irq, powertecscsi_intr, - IRQF_DISABLED, "powertec", info); + 0, "powertec", info); if (ret) { printk("scsi%d: IRQ%d not free: %d\n", host->host_no, ec->irq, ret); -- cgit v1.1 From 1ef2bf8227abe928e149772f9e6ee9d59c1bd97e Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sun, 16 Mar 2014 05:54:57 +0100 Subject: ARM: 8006/1: Remove redundant code Statements following return will never be executed. This patch removes this code. Signed-off-by: Alexander Shiyan Signed-off-by: Russell King --- arch/arm/common/scoop.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index a5c3dc3..6ef146e 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c @@ -232,8 +232,6 @@ static int scoop_probe(struct platform_device *pdev) return 0; - if (devptr->gpio.base != -1) - temp = gpiochip_remove(&devptr->gpio); err_gpio: platform_set_drvdata(pdev, NULL); err_ioremap: -- cgit v1.1 From 95c52fe063351192e0f4ffb70ef9bac1aa26f5a4 Mon Sep 17 00:00:00 2001 From: Christopher Covington Date: Wed, 19 Mar 2014 18:12:25 +0100 Subject: ARM: 8007/1: Remove extraneous kcmp syscall ignore The kcmp system call was ported to ARM in commit 3f7d1fe108dbaefd0c57a41753fc2c90b395f458 "ARM: 7665/1: Wire up kcmp syscall". Fixes: 3f7d1fe108db ("ARM: 7665/1: Wire up kcmp syscall") Signed-off-by: Christopher Covington Signed-off-by: Russell King --- arch/arm/include/asm/unistd.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index acabef1..4387624 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h @@ -48,6 +48,5 @@ */ #define __IGNORE_fadvise64_64 #define __IGNORE_migrate_pages -#define __IGNORE_kcmp #endif /* __ASM_ARM_UNISTD_H */ -- cgit v1.1 From e26a9e00afc482b971afcaef1db8c9034d4d6d7c Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 25 Mar 2014 19:45:31 +0000 Subject: ARM: Better virt_to_page() handling virt_to_page() is incredibly inefficient when virt-to-phys patching is enabled. This is because we end up with this calculation: page = &mem_map[asm virt_to_phys(addr) >> 12 - __pv_phys_offset >> 12] in assembly. The asm virt_to_phys() is equivalent this this operation: addr - PAGE_OFFSET + __pv_phys_offset and we can see that because this is assembly, the compiler has no chance to optimise some of that away. This should reduce down to: page = &mem_map[(addr - PAGE_OFFSET) >> 12] for the common cases. Permit the compiler to make this optimisation by giving it more of the information it needs - do this by providing a virt_to_pfn() macro. Another issue which makes this more complex is that __pv_phys_offset is a 64-bit type on all platforms. This is needlessly wasteful - if we store the physical offset as a PFN, we can save a lot of work having to deal with 64-bit values, which sometimes ends up producing incredibly horrid code: a4c: e3009000 movw r9, #0 a4c: R_ARM_MOVW_ABS_NC __pv_phys_offset a50: e3409000 movt r9, #0 ; r9 = &__pv_phys_offset a50: R_ARM_MOVT_ABS __pv_phys_offset a54: e3002000 movw r2, #0 a54: R_ARM_MOVW_ABS_NC __pv_phys_offset a58: e3402000 movt r2, #0 ; r2 = &__pv_phys_offset a58: R_ARM_MOVT_ABS __pv_phys_offset a5c: e5999004 ldr r9, [r9, #4] ; r9 = high word of __pv_phys_offset a60: e3001000 movw r1, #0 a60: R_ARM_MOVW_ABS_NC mem_map a64: e592c000 ldr ip, [r2] ; ip = low word of __pv_phys_offset Reviewed-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/include/asm/memory.h | 41 ++++++++++++++++++++++++----------------- arch/arm/kernel/armksyms.c | 2 +- arch/arm/kernel/head.S | 17 +++++++++-------- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 8756e4b..2438d72cf 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -169,9 +169,17 @@ * Physical vs virtual RAM address space conversion. These are * private definitions which should NOT be used outside memory.h * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. + * + * PFNs are used to describe any physical page; this means + * PFN 0 == physical address 0. */ -#ifndef __virt_to_phys -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT +#if defined(__virt_to_phys) +#define PHYS_OFFSET PLAT_PHYS_OFFSET +#define PHYS_PFN_OFFSET ((unsigned long)(PHYS_OFFSET >> PAGE_SHIFT)) + +#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) + +#elif defined(CONFIG_ARM_PATCH_PHYS_VIRT) /* * Constants used to force the right instruction encodings and shifts @@ -180,12 +188,17 @@ #define __PV_BITS_31_24 0x81000000 #define __PV_BITS_7_0 0x81 -extern u64 __pv_phys_offset; +extern unsigned long __pv_phys_pfn_offset; extern u64 __pv_offset; extern void fixup_pv_table(const void *, unsigned long); extern const void *__pv_table_begin, *__pv_table_end; -#define PHYS_OFFSET __pv_phys_offset +#define PHYS_OFFSET ((phys_addr_t)__pv_phys_pfn_offset << PAGE_SHIFT) +#define PHYS_PFN_OFFSET (__pv_phys_pfn_offset) + +#define virt_to_pfn(kaddr) \ + ((((unsigned long)(kaddr) - PAGE_OFFSET) >> PAGE_SHIFT) + \ + PHYS_PFN_OFFSET) #define __pv_stub(from,to,instr,type) \ __asm__("@ __pv_stub\n" \ @@ -246,6 +259,7 @@ static inline unsigned long __phys_to_virt(phys_addr_t x) #else #define PHYS_OFFSET PLAT_PHYS_OFFSET +#define PHYS_PFN_OFFSET ((unsigned long)(PHYS_OFFSET >> PAGE_SHIFT)) static inline phys_addr_t __virt_to_phys(unsigned long x) { @@ -257,18 +271,11 @@ static inline unsigned long __phys_to_virt(phys_addr_t x) return x - PHYS_OFFSET + PAGE_OFFSET; } -#endif -#endif +#define virt_to_pfn(kaddr) \ + ((((unsigned long)(kaddr) - PAGE_OFFSET) >> PAGE_SHIFT) + \ + PHYS_PFN_OFFSET) -/* - * PFNs are used to describe any physical page; this means - * PFN 0 == physical address 0. - * - * This is the PFN of the first RAM page in the kernel - * direct-mapped view. We assume this is the first page - * of RAM in the mem_map as well. - */ -#define PHYS_PFN_OFFSET ((unsigned long)(PHYS_OFFSET >> PAGE_SHIFT)) +#endif /* * These are *only* valid on the kernel direct mapped RAM memory. @@ -346,9 +353,9 @@ static inline __deprecated void *bus_to_virt(unsigned long x) */ #define ARCH_PFN_OFFSET PHYS_PFN_OFFSET -#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) +#define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr)) #define virt_addr_valid(kaddr) (((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory) \ - && pfn_valid(__pa(kaddr) >> PAGE_SHIFT) ) + && pfn_valid(virt_to_pfn(kaddr))) #endif diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 85e664b..f7b450f 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -158,6 +158,6 @@ EXPORT_SYMBOL(__gnu_mcount_nc); #endif #ifdef CONFIG_ARM_PATCH_PHYS_VIRT -EXPORT_SYMBOL(__pv_phys_offset); +EXPORT_SYMBOL(__pv_phys_pfn_offset); EXPORT_SYMBOL(__pv_offset); #endif diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 914616e..3aca959 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -584,9 +584,10 @@ __fixup_pv_table: subs r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET add r4, r4, r3 @ adjust table start address add r5, r5, r3 @ adjust table end address - add r6, r6, r3 @ adjust __pv_phys_offset address + add r6, r6, r3 @ adjust __pv_phys_pfn_offset address add r7, r7, r3 @ adjust __pv_offset address - str r8, [r6, #LOW_OFFSET] @ save computed PHYS_OFFSET to __pv_phys_offset + mov r0, r8, lsr #12 @ convert to PFN + str r0, [r6, #LOW_OFFSET] @ save computed PHYS_OFFSET to __pv_phys_pfn_offset strcc ip, [r7, #HIGH_OFFSET] @ save to __pv_offset high bits mov r6, r3, lsr #24 @ constant for add/sub instructions teq r3, r6, lsl #24 @ must be 16MiB aligned @@ -600,7 +601,7 @@ ENDPROC(__fixup_pv_table) 1: .long . .long __pv_table_begin .long __pv_table_end -2: .long __pv_phys_offset +2: .long __pv_phys_pfn_offset .long __pv_offset .text @@ -688,11 +689,11 @@ ENTRY(fixup_pv_table) ENDPROC(fixup_pv_table) .data - .globl __pv_phys_offset - .type __pv_phys_offset, %object -__pv_phys_offset: - .quad 0 - .size __pv_phys_offset, . -__pv_phys_offset + .globl __pv_phys_pfn_offset + .type __pv_phys_pfn_offset, %object +__pv_phys_pfn_offset: + .word 0 + .size __pv_phys_pfn_offset, . -__pv_phys_pfn_offset .globl __pv_offset .type __pv_offset, %object -- cgit v1.1 From 104fce73fdbd174eb08a493eeb2920fd59e6d3f4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 12:58:29 +0000 Subject: dmaengine: omap-dma: use devm_kzalloc() to allocate omap_dmadev. Use devm_kzalloc() to allocate omap_dmadev() so that we don't need complex error cleanup paths. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 362e7c4..98034e8 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -594,7 +594,6 @@ static void omap_dma_free(struct omap_dmadev *od) tasklet_kill(&c->vc.task); kfree(c); } - kfree(od); } static int omap_dma_probe(struct platform_device *pdev) @@ -602,7 +601,7 @@ static int omap_dma_probe(struct platform_device *pdev) struct omap_dmadev *od; int rc, i; - od = kzalloc(sizeof(*od), GFP_KERNEL); + od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL); if (!od) return -ENOMEM; -- cgit v1.1 From 1b416c4b41351c3eb8fc42dbb4cd8eba463c0813 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 13:00:03 +0000 Subject: dmaengine: omap-dma: provide a hook to get the underlying DMA platform ops Provide and use a hook to obtain the underlying DMA platform operations so that omap-dma.c can access the hardware more directly without involving the legacy DMA driver. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- arch/arm/plat-omap/dma.c | 6 ++++++ drivers/dma/omap-dma.c | 7 +++++++ include/linux/omap-dma.h | 2 ++ 3 files changed, 15 insertions(+) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 01619c2..d4d9a5e 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -2000,6 +2000,12 @@ void omap_dma_global_context_restore(void) omap_clear_dma(ch); } +struct omap_system_dma_plat_info *omap_get_plat_info(void) +{ + return p; +} +EXPORT_SYMBOL_GPL(omap_get_plat_info); + static int omap_system_dma_probe(struct platform_device *pdev) { int ch, ret = 0; diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 98034e8..4ac26bf 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -26,11 +26,13 @@ struct omap_dmadev { spinlock_t lock; struct tasklet_struct task; struct list_head pending; + struct omap_system_dma_plat_info *plat; }; struct omap_chan { struct virt_dma_chan vc; struct list_head node; + struct omap_system_dma_plat_info *plat; struct dma_slave_config cfg; unsigned dma_sig; @@ -573,6 +575,7 @@ static int omap_dma_chan_init(struct omap_dmadev *od, int dma_sig) if (!c) return -ENOMEM; + c->plat = od->plat; c->dma_sig = dma_sig; c->vc.desc_free = omap_dma_desc_free; vchan_init(&c->vc, &od->ddev); @@ -605,6 +608,10 @@ static int omap_dma_probe(struct platform_device *pdev) if (!od) return -ENOMEM; + od->plat = omap_get_plat_info(); + if (!od->plat) + return -EPROBE_DEFER; + dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources; diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 7af25a9..14742fc 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h @@ -292,6 +292,8 @@ struct omap_system_dma_plat_info { #define dma_omap15xx() ((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE))) #define dma_omap16xx() ((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE))) +extern struct omap_system_dma_plat_info *omap_get_plat_info(void); + extern void omap_set_dma_priority(int lch, int dst_port, int priority); extern int omap_request_dma(int dev_id, const char *dev_name, void (*callback)(int lch, u16 ch_status, void *data), -- cgit v1.1 From b9e97822da374f52aaf99cb502f531ff2184b8f5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 13:26:57 +0000 Subject: dmaengine: omap-dma: program hardware directly Program the transfer parameters directly into the hardware, rather than using the functions in arch/arm/plat-omap/dma.c. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 142 +++++++++++++++++++++++++++++++++++++++++------ include/linux/omap-dma.h | 6 +- 2 files changed, 130 insertions(+), 18 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 4ac26bf..47a3fa5 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -99,16 +99,94 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, unsigned idx) { struct omap_sg *sg = d->sg + idx; + uint32_t val; + + if (d->dir == DMA_DEV_TO_MEM) { + if (dma_omap1()) { + val = c->plat->dma_read(CSDP, c->dma_ch); + val &= ~(0x1f << 9); + val |= OMAP_DMA_PORT_EMIFF << 9; + c->plat->dma_write(val, CSDP, c->dma_ch); + } - if (d->dir == DMA_DEV_TO_MEM) - omap_set_dma_dest_params(c->dma_ch, OMAP_DMA_PORT_EMIFF, - OMAP_DMA_AMODE_POST_INC, sg->addr, 0, 0); - else - omap_set_dma_src_params(c->dma_ch, OMAP_DMA_PORT_EMIFF, - OMAP_DMA_AMODE_POST_INC, sg->addr, 0, 0); + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~(0x03 << 14); + val |= OMAP_DMA_AMODE_POST_INC << 14; + c->plat->dma_write(val, CCR, c->dma_ch); + + c->plat->dma_write(sg->addr, CDSA, c->dma_ch); + c->plat->dma_write(0, CDEI, c->dma_ch); + c->plat->dma_write(0, CDFI, c->dma_ch); + } else { + if (dma_omap1()) { + val = c->plat->dma_read(CSDP, c->dma_ch); + val &= ~(0x1f << 2); + val |= OMAP_DMA_PORT_EMIFF << 2; + c->plat->dma_write(val, CSDP, c->dma_ch); + } + + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~(0x03 << 12); + val |= OMAP_DMA_AMODE_POST_INC << 12; + c->plat->dma_write(val, CCR, c->dma_ch); + + c->plat->dma_write(sg->addr, CSSA, c->dma_ch); + c->plat->dma_write(0, CSEI, c->dma_ch); + c->plat->dma_write(0, CSFI, c->dma_ch); + } + + val = c->plat->dma_read(CSDP, c->dma_ch); + val &= ~0x03; + val |= d->es; + c->plat->dma_write(val, CSDP, c->dma_ch); + + if (dma_omap1()) { + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~(1 << 5); + if (d->sync_mode == OMAP_DMA_SYNC_FRAME) + val |= 1 << 5; + c->plat->dma_write(val, CCR, c->dma_ch); + + val = c->plat->dma_read(CCR2, c->dma_ch); + val &= ~(1 << 2); + if (d->sync_mode == OMAP_DMA_SYNC_BLOCK) + val |= 1 << 2; + c->plat->dma_write(val, CCR2, c->dma_ch); + } else if (c->dma_sig) { + val = c->plat->dma_read(CCR, c->dma_ch); + + /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ + val &= ~((1 << 23) | (3 << 19) | 0x1f); + val |= (c->dma_sig & ~0x1f) << 14; + val |= c->dma_sig & 0x1f; + + if (d->sync_mode & OMAP_DMA_SYNC_FRAME) + val |= 1 << 5; + else + val &= ~(1 << 5); + + if (d->sync_mode & OMAP_DMA_SYNC_BLOCK) + val |= 1 << 18; + else + val &= ~(1 << 18); + + switch (d->sync_type) { + case OMAP_DMA_DST_SYNC_PREFETCH: + val &= ~(1 << 24); /* dest synch */ + val |= 1 << 23; /* Prefetch */ + break; + case 0: + val &= ~(1 << 24); /* dest synch */ + break; + default: + val |= 1 << 24; /* source synch */ + break; + } + c->plat->dma_write(val, CCR, c->dma_ch); + } - omap_set_dma_transfer_params(c->dma_ch, d->es, sg->en, sg->fn, - d->sync_mode, c->dma_sig, d->sync_type); + c->plat->dma_write(sg->en, CEN, c->dma_ch); + c->plat->dma_write(sg->fn, CFN, c->dma_ch); omap_start_dma(c->dma_ch); } @@ -117,6 +195,7 @@ static void omap_dma_start_desc(struct omap_chan *c) { struct virt_dma_desc *vd = vchan_next_desc(&c->vc); struct omap_desc *d; + uint32_t val; if (!vd) { c->desc = NULL; @@ -128,12 +207,39 @@ static void omap_dma_start_desc(struct omap_chan *c) c->desc = d = to_omap_dma_desc(&vd->tx); c->sgidx = 0; - if (d->dir == DMA_DEV_TO_MEM) - omap_set_dma_src_params(c->dma_ch, d->periph_port, - OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi); - else - omap_set_dma_dest_params(c->dma_ch, d->periph_port, - OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi); + if (d->dir == DMA_DEV_TO_MEM) { + if (dma_omap1()) { + val = c->plat->dma_read(CSDP, c->dma_ch); + val &= ~(0x1f << 2); + val |= d->periph_port << 2; + c->plat->dma_write(val, CSDP, c->dma_ch); + } + + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~(0x03 << 12); + val |= OMAP_DMA_AMODE_CONSTANT << 12; + c->plat->dma_write(val, CCR, c->dma_ch); + + c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch); + c->plat->dma_write(0, CSEI, c->dma_ch); + c->plat->dma_write(d->fi, CSFI, c->dma_ch); + } else { + if (dma_omap1()) { + val = c->plat->dma_read(CSDP, c->dma_ch); + val &= ~(0x1f << 9); + val |= d->periph_port << 9; + c->plat->dma_write(val, CSDP, c->dma_ch); + } + + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~(0x03 << 14); + val |= OMAP_DMA_AMODE_CONSTANT << 14; + c->plat->dma_write(val, CCR, c->dma_ch); + + c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch); + c->plat->dma_write(0, CDEI, c->dma_ch); + c->plat->dma_write(d->fi, CDFI, c->dma_ch); + } omap_dma_start_sg(c, d, 0); } @@ -452,8 +558,12 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( } if (dma_omap2plus()) { - omap_set_dma_src_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16); - omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16); + uint32_t val; + + val = c->plat->dma_read(CSDP, c->dma_ch); + val |= 0x03 << 7; /* src burst mode 16 */ + val |= 0x03 << 14; /* dst burst mode 16 */ + c->plat->dma_write(val, CSDP, c->dma_ch); } return vchan_tx_prep(&c->vc, &d->vd, flags); diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 14742fc..d631658 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h @@ -289,8 +289,10 @@ struct omap_system_dma_plat_info { #define dma_omap2plus() 0 #endif #define dma_omap1() (!dma_omap2plus()) -#define dma_omap15xx() ((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE))) -#define dma_omap16xx() ((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE))) +#define __dma_omap15xx(d) (dma_omap1() && (d)->dev_caps & ENABLE_1510_MODE) +#define __dma_omap16xx(d) (dma_omap1() && (d)->dev_caps & ENABLE_16XX_MODE) +#define dma_omap15xx() __dma_omap15xx(d) +#define dma_omap16xx() __dma_omap16xx(d) extern struct omap_system_dma_plat_info *omap_get_plat_info(void); -- cgit v1.1 From 913a2d0c6952283bc9323cb9152af87f792ff4c4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 14:41:42 +0000 Subject: dmaengine: omap-dma: consolidate writes to DMA registers There's no need to keep writing registers which don't change value in omap_dma_start_sg(). Move this into omap_dma_start_desc() and merge the register updates together. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 123 +++++++++++++++++++------------------------------ 1 file changed, 48 insertions(+), 75 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 47a3fa5..8c5c862 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -99,40 +99,75 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, unsigned idx) { struct omap_sg *sg = d->sg + idx; + + if (d->dir == DMA_DEV_TO_MEM) { + c->plat->dma_write(sg->addr, CDSA, c->dma_ch); + c->plat->dma_write(0, CDEI, c->dma_ch); + c->plat->dma_write(0, CDFI, c->dma_ch); + } else { + c->plat->dma_write(sg->addr, CSSA, c->dma_ch); + c->plat->dma_write(0, CSEI, c->dma_ch); + c->plat->dma_write(0, CSFI, c->dma_ch); + } + + c->plat->dma_write(sg->en, CEN, c->dma_ch); + c->plat->dma_write(sg->fn, CFN, c->dma_ch); + + omap_start_dma(c->dma_ch); +} + +static void omap_dma_start_desc(struct omap_chan *c) +{ + struct virt_dma_desc *vd = vchan_next_desc(&c->vc); + struct omap_desc *d; uint32_t val; + if (!vd) { + c->desc = NULL; + return; + } + + list_del(&vd->node); + + c->desc = d = to_omap_dma_desc(&vd->tx); + c->sgidx = 0; + if (d->dir == DMA_DEV_TO_MEM) { if (dma_omap1()) { val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~(0x1f << 9); + val &= ~(0x1f << 9 | 0x1f << 2); val |= OMAP_DMA_PORT_EMIFF << 9; + val |= d->periph_port << 2; c->plat->dma_write(val, CSDP, c->dma_ch); } val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 14); + val &= ~(0x03 << 14 | 0x03 << 12); val |= OMAP_DMA_AMODE_POST_INC << 14; + val |= OMAP_DMA_AMODE_CONSTANT << 12; c->plat->dma_write(val, CCR, c->dma_ch); - c->plat->dma_write(sg->addr, CDSA, c->dma_ch); - c->plat->dma_write(0, CDEI, c->dma_ch); - c->plat->dma_write(0, CDFI, c->dma_ch); + c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch); + c->plat->dma_write(0, CSEI, c->dma_ch); + c->plat->dma_write(d->fi, CSFI, c->dma_ch); } else { if (dma_omap1()) { val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~(0x1f << 2); + val &= ~(0x1f << 9 | 0x1f << 2); + val |= d->periph_port << 9; val |= OMAP_DMA_PORT_EMIFF << 2; c->plat->dma_write(val, CSDP, c->dma_ch); } val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 12); + val &= ~(0x03 << 12 | 0x03 << 14); + val |= OMAP_DMA_AMODE_CONSTANT << 14; val |= OMAP_DMA_AMODE_POST_INC << 12; c->plat->dma_write(val, CCR, c->dma_ch); - c->plat->dma_write(sg->addr, CSSA, c->dma_ch); - c->plat->dma_write(0, CSEI, c->dma_ch); - c->plat->dma_write(0, CSFI, c->dma_ch); + c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch); + c->plat->dma_write(0, CDEI, c->dma_ch); + c->plat->dma_write(d->fi, CDFI, c->dma_ch); } val = c->plat->dma_read(CSDP, c->dma_ch); @@ -156,91 +191,29 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, val = c->plat->dma_read(CCR, c->dma_ch); /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ - val &= ~((1 << 23) | (3 << 19) | 0x1f); + val &= ~(1 << 24 | 1 << 23 | 3 << 19 | 1 << 18 | 1 << 5 | 0x1f); val |= (c->dma_sig & ~0x1f) << 14; val |= c->dma_sig & 0x1f; if (d->sync_mode & OMAP_DMA_SYNC_FRAME) val |= 1 << 5; - else - val &= ~(1 << 5); if (d->sync_mode & OMAP_DMA_SYNC_BLOCK) val |= 1 << 18; - else - val &= ~(1 << 18); switch (d->sync_type) { - case OMAP_DMA_DST_SYNC_PREFETCH: - val &= ~(1 << 24); /* dest synch */ + case OMAP_DMA_DST_SYNC_PREFETCH:/* dest synch */ val |= 1 << 23; /* Prefetch */ break; case 0: - val &= ~(1 << 24); /* dest synch */ break; default: - val |= 1 << 24; /* source synch */ + val |= 1 << 24; /* source synch */ break; } c->plat->dma_write(val, CCR, c->dma_ch); } - c->plat->dma_write(sg->en, CEN, c->dma_ch); - c->plat->dma_write(sg->fn, CFN, c->dma_ch); - - omap_start_dma(c->dma_ch); -} - -static void omap_dma_start_desc(struct omap_chan *c) -{ - struct virt_dma_desc *vd = vchan_next_desc(&c->vc); - struct omap_desc *d; - uint32_t val; - - if (!vd) { - c->desc = NULL; - return; - } - - list_del(&vd->node); - - c->desc = d = to_omap_dma_desc(&vd->tx); - c->sgidx = 0; - - if (d->dir == DMA_DEV_TO_MEM) { - if (dma_omap1()) { - val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~(0x1f << 2); - val |= d->periph_port << 2; - c->plat->dma_write(val, CSDP, c->dma_ch); - } - - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 12); - val |= OMAP_DMA_AMODE_CONSTANT << 12; - c->plat->dma_write(val, CCR, c->dma_ch); - - c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch); - c->plat->dma_write(0, CSEI, c->dma_ch); - c->plat->dma_write(d->fi, CSFI, c->dma_ch); - } else { - if (dma_omap1()) { - val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~(0x1f << 9); - val |= d->periph_port << 9; - c->plat->dma_write(val, CSDP, c->dma_ch); - } - - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 14); - val |= OMAP_DMA_AMODE_CONSTANT << 14; - c->plat->dma_write(val, CCR, c->dma_ch); - - c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch); - c->plat->dma_write(0, CDEI, c->dma_ch); - c->plat->dma_write(d->fi, CDFI, c->dma_ch); - } - omap_dma_start_sg(c, d, 0); } -- cgit v1.1 From fa3ad86ae0576b2c721800cc4d46864aa6d31ffd Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 17:07:09 +0000 Subject: dmaengine: omap-dma: control start/stop directly Program the non-cyclic mode DMA start/stop directly, rather than via arch/arm/plat-omap/dma.c. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 151 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 141 insertions(+), 10 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 8c5c862..7aa5ff7 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -5,6 +5,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -60,6 +61,7 @@ struct omap_desc { uint8_t sync_mode; /* OMAP_DMA_SYNC_xxx */ uint8_t sync_type; /* OMAP_DMA_xxx_SYNC* */ uint8_t periph_port; /* Peripheral port */ + uint16_t cicr; /* CICR value */ unsigned sglen; struct omap_sg sg[0]; @@ -95,6 +97,111 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd) kfree(container_of(vd, struct omap_desc, vd)); } +static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) +{ + struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); + uint32_t val; + + if (__dma_omap15xx(od->plat->dma_attr)) + c->plat->dma_write(0, CPC, c->dma_ch); + else + c->plat->dma_write(0, CDAC, c->dma_ch); + + if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) { + val = c->plat->dma_read(CLNK_CTRL, c->dma_ch); + + if (dma_omap1()) + val &= ~(1 << 14); + + val |= c->dma_ch | 1 << 15; + + c->plat->dma_write(val, CLNK_CTRL, c->dma_ch); + } else if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) + c->plat->dma_write(c->dma_ch, CLNK_CTRL, c->dma_ch); + + /* Clear CSR */ + if (dma_omap1()) + c->plat->dma_read(CSR, c->dma_ch); + else + c->plat->dma_write(~0, CSR, c->dma_ch); + + /* Enable interrupts */ + c->plat->dma_write(d->cicr, CICR, c->dma_ch); + + val = c->plat->dma_read(CCR, c->dma_ch); + if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) + val |= OMAP_DMA_CCR_BUFFERING_DISABLE; + val |= OMAP_DMA_CCR_EN; + mb(); + c->plat->dma_write(val, CCR, c->dma_ch); +} + +static void omap_dma_stop(struct omap_chan *c) +{ + struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); + uint32_t val; + + /* disable irq */ + c->plat->dma_write(0, CICR, c->dma_ch); + + /* Clear CSR */ + if (dma_omap1()) + c->plat->dma_read(CSR, c->dma_ch); + else + c->plat->dma_write(~0, CSR, c->dma_ch); + + val = c->plat->dma_read(CCR, c->dma_ch); + if (od->plat->errata & DMA_ERRATA_i541 && + val & OMAP_DMA_CCR_SEL_SRC_DST_SYNC) { + uint32_t sysconfig; + unsigned i; + + sysconfig = c->plat->dma_read(OCP_SYSCONFIG, c->dma_ch); + val = sysconfig & ~DMA_SYSCONFIG_MIDLEMODE_MASK; + val |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); + c->plat->dma_write(val, OCP_SYSCONFIG, c->dma_ch); + + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~OMAP_DMA_CCR_EN; + c->plat->dma_write(val, CCR, c->dma_ch); + + /* Wait for sDMA FIFO to drain */ + for (i = 0; ; i++) { + val = c->plat->dma_read(CCR, c->dma_ch); + if (!(val & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE))) + break; + + if (i > 100) + break; + + udelay(5); + } + + if (val & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE)) + dev_err(c->vc.chan.device->dev, + "DMA drain did not complete on lch %d\n", + c->dma_ch); + + c->plat->dma_write(sysconfig, OCP_SYSCONFIG, c->dma_ch); + } else { + val &= ~OMAP_DMA_CCR_EN; + c->plat->dma_write(val, CCR, c->dma_ch); + } + + mb(); + + if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) { + val = c->plat->dma_read(CLNK_CTRL, c->dma_ch); + + if (dma_omap1()) + val |= 1 << 14; /* set the STOP_LNK bit */ + else + val &= ~(1 << 15); /* Clear the ENABLE_LNK bit */ + + c->plat->dma_write(val, CLNK_CTRL, c->dma_ch); + } +} + static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, unsigned idx) { @@ -113,7 +220,7 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, c->plat->dma_write(sg->en, CEN, c->dma_ch); c->plat->dma_write(sg->fn, CFN, c->dma_ch); - omap_start_dma(c->dma_ch); + omap_dma_start(c, d); } static void omap_dma_start_desc(struct omap_chan *c) @@ -434,6 +541,12 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->sync_mode = OMAP_DMA_SYNC_FRAME; d->sync_type = sync_type; d->periph_port = OMAP_DMA_PORT_TIPB; + d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; + + if (dma_omap1()) + d->cicr |= OMAP1_DMA_TOUT_IRQ; + else + d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; /* * Build our scatterlist entries: each contains the address, @@ -463,6 +576,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( size_t period_len, enum dma_transfer_direction dir, unsigned long flags, void *context) { + struct omap_dmadev *od = to_omap_dma_dev(chan->device); struct omap_chan *c = to_omap_dma_chan(chan); enum dma_slave_buswidth dev_width; struct omap_desc *d; @@ -519,15 +633,25 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->sg[0].en = period_len / es_bytes[es]; d->sg[0].fn = buf_len / period_len; d->sglen = 1; + d->cicr = OMAP_DMA_DROP_IRQ; + if (flags & DMA_PREP_INTERRUPT) + d->cicr |= OMAP_DMA_FRAME_IRQ; + + if (dma_omap1()) + d->cicr |= OMAP1_DMA_TOUT_IRQ; + else + d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; if (!c->cyclic) { c->cyclic = true; - omap_dma_link_lch(c->dma_ch, c->dma_ch); - if (flags & DMA_PREP_INTERRUPT) - omap_enable_dma_irq(c->dma_ch, OMAP_DMA_FRAME_IRQ); + if (__dma_omap15xx(od->plat->dma_attr)) { + uint32_t val; - omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ); + val = c->plat->dma_read(CCR, c->dma_ch); + val |= 3 << 8; + c->plat->dma_write(val, CCR, c->dma_ch); + } } if (dma_omap2plus()) { @@ -568,20 +692,27 @@ static int omap_dma_terminate_all(struct omap_chan *c) /* * Stop DMA activity: we assume the callback will not be called - * after omap_stop_dma() returns (even if it does, it will see + * after omap_dma_stop() returns (even if it does, it will see * c->desc is NULL and exit.) */ if (c->desc) { c->desc = NULL; /* Avoid stopping the dma twice */ if (!c->paused) - omap_stop_dma(c->dma_ch); + omap_dma_stop(c); } if (c->cyclic) { c->cyclic = false; c->paused = false; - omap_dma_unlink_lch(c->dma_ch, c->dma_ch); + + if (__dma_omap15xx(od->plat->dma_attr)) { + uint32_t val; + + val = c->plat->dma_read(CCR, c->dma_ch); + val &= ~(3 << 8); + c->plat->dma_write(val, CCR, c->dma_ch); + } } vchan_get_all_descriptors(&c->vc, &head); @@ -598,7 +729,7 @@ static int omap_dma_pause(struct omap_chan *c) return -EINVAL; if (!c->paused) { - omap_stop_dma(c->dma_ch); + omap_dma_stop(c); c->paused = true; } @@ -612,7 +743,7 @@ static int omap_dma_resume(struct omap_chan *c) return -EINVAL; if (c->paused) { - omap_start_dma(c->dma_ch); + omap_dma_start(c, c->desc); c->paused = false; } -- cgit v1.1 From 3997cab391b38e126f217e36ad7bdc9672c9fb4d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 18:04:17 +0000 Subject: dmaengine: omap-dma: move reading of dma position to omap-dma.c Read the current DMA position from the hardware directly rather than via arch/arm/plat-omap/dma.c. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 7aa5ff7..323eae2 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -427,6 +427,68 @@ static size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr) return size; } +static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c) +{ + struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); + dma_addr_t addr; + + if (__dma_omap15xx(od->plat->dma_attr)) + addr = c->plat->dma_read(CPC, c->dma_ch); + else + addr = c->plat->dma_read(CSAC, c->dma_ch); + + if (od->plat->errata & DMA_ERRATA_3_3 && addr == 0) + addr = c->plat->dma_read(CSAC, c->dma_ch); + + if (!__dma_omap15xx(od->plat->dma_attr)) { + /* + * CDAC == 0 indicates that the DMA transfer on the channel has + * not been started (no data has been transferred so far). + * Return the programmed source start address in this case. + */ + if (c->plat->dma_read(CDAC, c->dma_ch)) + addr = c->plat->dma_read(CSAC, c->dma_ch); + else + addr = c->plat->dma_read(CSSA, c->dma_ch); + } + + if (dma_omap1()) + addr |= c->plat->dma_read(CSSA, c->dma_ch) & 0xffff0000; + + return addr; +} + +static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c) +{ + struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); + dma_addr_t addr; + + if (__dma_omap15xx(od->plat->dma_attr)) + addr = c->plat->dma_read(CPC, c->dma_ch); + else + addr = c->plat->dma_read(CDAC, c->dma_ch); + + /* + * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is + * read before the DMA controller finished disabling the channel. + */ + if (!__dma_omap15xx(od->plat->dma_attr) && addr == 0) { + addr = c->plat->dma_read(CDAC, c->dma_ch); + /* + * CDAC == 0 indicates that the DMA transfer on the channel has + * not been started (no data has been transferred so far). + * Return the programmed destination start address in this case. + */ + if (addr == 0) + addr = c->plat->dma_read(CDSA, c->dma_ch); + } + + if (dma_omap1()) + addr |= c->plat->dma_read(CDSA, c->dma_ch) & 0xffff0000; + + return addr; +} + static enum dma_status omap_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, struct dma_tx_state *txstate) { @@ -448,9 +510,9 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan, dma_addr_t pos; if (d->dir == DMA_MEM_TO_DEV) - pos = omap_get_dma_src_pos(c->dma_ch); + pos = omap_dma_get_src_pos(c); else if (d->dir == DMA_DEV_TO_MEM) - pos = omap_get_dma_dst_pos(c->dma_ch); + pos = omap_dma_get_dst_pos(c); else pos = 0; -- cgit v1.1 From 2f0d13bdf6440906bb52fe94681ce7927145f4d7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 18:51:53 +0000 Subject: dmaengine: omap-dma: consolidate setup of CSDP Consolidate the setup of the channel source destination parameters register. This way, we calculate the required CSDP value when we setup a transfer descriptor, and only write it to the device registers once when we start the descriptor. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 64 ++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 323eae2..ec7cc10 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -60,8 +60,8 @@ struct omap_desc { uint8_t es; /* OMAP_DMA_DATA_TYPE_xxx */ uint8_t sync_mode; /* OMAP_DMA_SYNC_xxx */ uint8_t sync_type; /* OMAP_DMA_xxx_SYNC* */ - uint8_t periph_port; /* Peripheral port */ uint16_t cicr; /* CICR value */ + uint32_t csdp; /* CSDP value */ unsigned sglen; struct omap_sg sg[0]; @@ -240,14 +240,6 @@ static void omap_dma_start_desc(struct omap_chan *c) c->sgidx = 0; if (d->dir == DMA_DEV_TO_MEM) { - if (dma_omap1()) { - val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~(0x1f << 9 | 0x1f << 2); - val |= OMAP_DMA_PORT_EMIFF << 9; - val |= d->periph_port << 2; - c->plat->dma_write(val, CSDP, c->dma_ch); - } - val = c->plat->dma_read(CCR, c->dma_ch); val &= ~(0x03 << 14 | 0x03 << 12); val |= OMAP_DMA_AMODE_POST_INC << 14; @@ -258,14 +250,6 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write(0, CSEI, c->dma_ch); c->plat->dma_write(d->fi, CSFI, c->dma_ch); } else { - if (dma_omap1()) { - val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~(0x1f << 9 | 0x1f << 2); - val |= d->periph_port << 9; - val |= OMAP_DMA_PORT_EMIFF << 2; - c->plat->dma_write(val, CSDP, c->dma_ch); - } - val = c->plat->dma_read(CCR, c->dma_ch); val &= ~(0x03 << 12 | 0x03 << 14); val |= OMAP_DMA_AMODE_CONSTANT << 14; @@ -277,10 +261,7 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write(d->fi, CDFI, c->dma_ch); } - val = c->plat->dma_read(CSDP, c->dma_ch); - val &= ~0x03; - val |= d->es; - c->plat->dma_write(val, CSDP, c->dma_ch); + c->plat->dma_write(d->csdp, CSDP, c->dma_ch); if (dma_omap1()) { val = c->plat->dma_read(CCR, c->dma_ch); @@ -602,13 +583,21 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->es = es; d->sync_mode = OMAP_DMA_SYNC_FRAME; d->sync_type = sync_type; - d->periph_port = OMAP_DMA_PORT_TIPB; d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; + d->csdp = es; - if (dma_omap1()) + if (dma_omap1()) { d->cicr |= OMAP1_DMA_TOUT_IRQ; - else + + if (dir == DMA_DEV_TO_MEM) + d->csdp |= OMAP_DMA_PORT_EMIFF << 9 | + OMAP_DMA_PORT_TIPB << 2; + else + d->csdp |= OMAP_DMA_PORT_TIPB << 9 | + OMAP_DMA_PORT_EMIFF << 2; + } else { d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; + } /* * Build our scatterlist entries: each contains the address, @@ -690,7 +679,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( else d->sync_mode = OMAP_DMA_SYNC_ELEMENT; d->sync_type = sync_type; - d->periph_port = OMAP_DMA_PORT_MPUI; d->sg[0].addr = buf_addr; d->sg[0].en = period_len / es_bytes[es]; d->sg[0].fn = buf_len / period_len; @@ -699,11 +687,24 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( if (flags & DMA_PREP_INTERRUPT) d->cicr |= OMAP_DMA_FRAME_IRQ; - if (dma_omap1()) + d->csdp = es; + + if (dma_omap1()) { d->cicr |= OMAP1_DMA_TOUT_IRQ; - else + + if (dir == DMA_DEV_TO_MEM) + d->csdp |= OMAP_DMA_PORT_EMIFF << 9 | + OMAP_DMA_PORT_MPUI << 2; + else + d->csdp |= OMAP_DMA_PORT_MPUI << 9 | + OMAP_DMA_PORT_EMIFF << 2; + } else { d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; + /* src and dst burst mode 16 */ + d->csdp |= 3 << 14 | 3 << 7; + } + if (!c->cyclic) { c->cyclic = true; @@ -716,15 +717,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( } } - if (dma_omap2plus()) { - uint32_t val; - - val = c->plat->dma_read(CSDP, c->dma_ch); - val |= 0x03 << 7; /* src burst mode 16 */ - val |= 0x03 << 14; /* dst burst mode 16 */ - c->plat->dma_write(val, CSDP, c->dma_ch); - } - return vchan_tx_prep(&c->vc, &d->vd, flags); } -- cgit v1.1 From 3ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 19:16:09 +0000 Subject: dmaengine: omap-dma: consolidate setup of CCR Consolidate the setup of the channel control register. Prepare the basic value in the preparation of the DMA descriptor, and write it into the register upon descriptor execution. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 147 ++++++++++++++++++++----------------------------- 1 file changed, 61 insertions(+), 86 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index ec7cc10..9a9e819 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -58,8 +58,7 @@ struct omap_desc { int16_t fi; /* for OMAP_DMA_SYNC_PACKET */ uint8_t es; /* OMAP_DMA_DATA_TYPE_xxx */ - uint8_t sync_mode; /* OMAP_DMA_SYNC_xxx */ - uint8_t sync_type; /* OMAP_DMA_xxx_SYNC* */ + uint32_t ccr; /* CCR value */ uint16_t cicr; /* CICR value */ uint32_t csdp; /* CSDP value */ @@ -227,7 +226,6 @@ static void omap_dma_start_desc(struct omap_chan *c) { struct virt_dma_desc *vd = vchan_next_desc(&c->vc); struct omap_desc *d; - uint32_t val; if (!vd) { c->desc = NULL; @@ -239,23 +237,15 @@ static void omap_dma_start_desc(struct omap_chan *c) c->desc = d = to_omap_dma_desc(&vd->tx); c->sgidx = 0; - if (d->dir == DMA_DEV_TO_MEM) { - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 14 | 0x03 << 12); - val |= OMAP_DMA_AMODE_POST_INC << 14; - val |= OMAP_DMA_AMODE_CONSTANT << 12; - c->plat->dma_write(val, CCR, c->dma_ch); + c->plat->dma_write(d->ccr, CCR, c->dma_ch); + if (dma_omap1()) + c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch); + if (d->dir == DMA_DEV_TO_MEM) { c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch); c->plat->dma_write(0, CSEI, c->dma_ch); c->plat->dma_write(d->fi, CSFI, c->dma_ch); } else { - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 12 | 0x03 << 14); - val |= OMAP_DMA_AMODE_CONSTANT << 14; - val |= OMAP_DMA_AMODE_POST_INC << 12; - c->plat->dma_write(val, CCR, c->dma_ch); - c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch); c->plat->dma_write(0, CDEI, c->dma_ch); c->plat->dma_write(d->fi, CDFI, c->dma_ch); @@ -263,45 +253,6 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write(d->csdp, CSDP, c->dma_ch); - if (dma_omap1()) { - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(1 << 5); - if (d->sync_mode == OMAP_DMA_SYNC_FRAME) - val |= 1 << 5; - c->plat->dma_write(val, CCR, c->dma_ch); - - val = c->plat->dma_read(CCR2, c->dma_ch); - val &= ~(1 << 2); - if (d->sync_mode == OMAP_DMA_SYNC_BLOCK) - val |= 1 << 2; - c->plat->dma_write(val, CCR2, c->dma_ch); - } else if (c->dma_sig) { - val = c->plat->dma_read(CCR, c->dma_ch); - - /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ - val &= ~(1 << 24 | 1 << 23 | 3 << 19 | 1 << 18 | 1 << 5 | 0x1f); - val |= (c->dma_sig & ~0x1f) << 14; - val |= c->dma_sig & 0x1f; - - if (d->sync_mode & OMAP_DMA_SYNC_FRAME) - val |= 1 << 5; - - if (d->sync_mode & OMAP_DMA_SYNC_BLOCK) - val |= 1 << 18; - - switch (d->sync_type) { - case OMAP_DMA_DST_SYNC_PREFETCH:/* dest synch */ - val |= 1 << 23; /* Prefetch */ - break; - case 0: - break; - default: - val |= 1 << 24; /* source synch */ - break; - } - c->plat->dma_write(val, CCR, c->dma_ch); - } - omap_dma_start_sg(c, d, 0); } @@ -540,19 +491,17 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( struct scatterlist *sgent; struct omap_desc *d; dma_addr_t dev_addr; - unsigned i, j = 0, es, en, frame_bytes, sync_type; + unsigned i, j = 0, es, en, frame_bytes; u32 burst; if (dir == DMA_DEV_TO_MEM) { dev_addr = c->cfg.src_addr; dev_width = c->cfg.src_addr_width; burst = c->cfg.src_maxburst; - sync_type = OMAP_DMA_SRC_SYNC; } else if (dir == DMA_MEM_TO_DEV) { dev_addr = c->cfg.dst_addr; dev_width = c->cfg.dst_addr_width; burst = c->cfg.dst_maxburst; - sync_type = OMAP_DMA_DST_SYNC; } else { dev_err(chan->device->dev, "%s: bad direction?\n", __func__); return NULL; @@ -581,12 +530,28 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->dir = dir; d->dev_addr = dev_addr; d->es = es; - d->sync_mode = OMAP_DMA_SYNC_FRAME; - d->sync_type = sync_type; + + d->ccr = 0; + if (dir == DMA_DEV_TO_MEM) + d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 | + OMAP_DMA_AMODE_CONSTANT << 12; + else + d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 | + OMAP_DMA_AMODE_POST_INC << 12; + d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; d->csdp = es; if (dma_omap1()) { + d->ccr |= 1 << 5; /* frame sync */ + if (__dma_omap16xx(od->plat->dma_attr)) { + d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */ + /* Duplicate what plat-omap/dma.c does */ + d->ccr |= c->dma_ch + 1; + } else { + d->ccr |= c->dma_sig & 0x1f; + } + d->cicr |= OMAP1_DMA_TOUT_IRQ; if (dir == DMA_DEV_TO_MEM) @@ -596,6 +561,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->csdp |= OMAP_DMA_PORT_TIPB << 9 | OMAP_DMA_PORT_EMIFF << 2; } else { + d->ccr |= (c->dma_sig & ~0x1f) << 14; + d->ccr |= c->dma_sig & 0x1f; + d->ccr |= 1 << 5; /* frame sync */ + + if (dir == DMA_DEV_TO_MEM) + d->ccr |= 1 << 24; /* source synch */ + d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; } @@ -632,19 +604,17 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( enum dma_slave_buswidth dev_width; struct omap_desc *d; dma_addr_t dev_addr; - unsigned es, sync_type; + unsigned es; u32 burst; if (dir == DMA_DEV_TO_MEM) { dev_addr = c->cfg.src_addr; dev_width = c->cfg.src_addr_width; burst = c->cfg.src_maxburst; - sync_type = OMAP_DMA_SRC_SYNC; } else if (dir == DMA_MEM_TO_DEV) { dev_addr = c->cfg.dst_addr; dev_width = c->cfg.dst_addr_width; burst = c->cfg.dst_maxburst; - sync_type = OMAP_DMA_DST_SYNC; } else { dev_err(chan->device->dev, "%s: bad direction?\n", __func__); return NULL; @@ -674,15 +644,21 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->dev_addr = dev_addr; d->fi = burst; d->es = es; - if (burst) - d->sync_mode = OMAP_DMA_SYNC_PACKET; - else - d->sync_mode = OMAP_DMA_SYNC_ELEMENT; - d->sync_type = sync_type; d->sg[0].addr = buf_addr; d->sg[0].en = period_len / es_bytes[es]; d->sg[0].fn = buf_len / period_len; d->sglen = 1; + + d->ccr = 0; + if (__dma_omap15xx(od->plat->dma_attr)) + d->ccr = 3 << 8; + if (dir == DMA_DEV_TO_MEM) + d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 | + OMAP_DMA_AMODE_CONSTANT << 12; + else + d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 | + OMAP_DMA_AMODE_POST_INC << 12; + d->cicr = OMAP_DMA_DROP_IRQ; if (flags & DMA_PREP_INTERRUPT) d->cicr |= OMAP_DMA_FRAME_IRQ; @@ -690,6 +666,14 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp = es; if (dma_omap1()) { + if (__dma_omap16xx(od->plat->dma_attr)) { + d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */ + /* Duplicate what plat-omap/dma.c does */ + d->ccr |= c->dma_ch + 1; + } else { + d->ccr |= c->dma_sig & 0x1f; + } + d->cicr |= OMAP1_DMA_TOUT_IRQ; if (dir == DMA_DEV_TO_MEM) @@ -699,23 +683,22 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp |= OMAP_DMA_PORT_MPUI << 9 | OMAP_DMA_PORT_EMIFF << 2; } else { + d->ccr |= (c->dma_sig & ~0x1f) << 14; + d->ccr |= c->dma_sig & 0x1f; + + if (burst) + d->ccr |= 1 << 18 | 1 << 5; /* packet */ + + if (dir == DMA_DEV_TO_MEM) + d->ccr |= 1 << 24; /* source synch */ + d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; /* src and dst burst mode 16 */ d->csdp |= 3 << 14 | 3 << 7; } - if (!c->cyclic) { - c->cyclic = true; - - if (__dma_omap15xx(od->plat->dma_attr)) { - uint32_t val; - - val = c->plat->dma_read(CCR, c->dma_ch); - val |= 3 << 8; - c->plat->dma_write(val, CCR, c->dma_ch); - } - } + c->cyclic = true; return vchan_tx_prep(&c->vc, &d->vd, flags); } @@ -759,14 +742,6 @@ static int omap_dma_terminate_all(struct omap_chan *c) if (c->cyclic) { c->cyclic = false; c->paused = false; - - if (__dma_omap15xx(od->plat->dma_attr)) { - uint32_t val; - - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(3 << 8); - c->plat->dma_write(val, CCR, c->dma_ch); - } } vchan_get_all_descriptors(&c->vc, &head); -- cgit v1.1 From 9043826d88467091543c1d3ab06eb4afeed34789 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 19:57:06 +0000 Subject: dmaengine: omap-dma: provide register definitions Provide our own set of more complete register definitions; this allows us to get rid of the meaningless 1 << n constants scattered throughout this code. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 171 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 117 insertions(+), 54 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 9a9e819..6cf66e6 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -57,7 +57,7 @@ struct omap_desc { dma_addr_t dev_addr; int16_t fi; /* for OMAP_DMA_SYNC_PACKET */ - uint8_t es; /* OMAP_DMA_DATA_TYPE_xxx */ + uint8_t es; /* CSDP_DATA_TYPE_xxx */ uint32_t ccr; /* CCR value */ uint16_t cicr; /* CICR value */ uint32_t csdp; /* CSDP value */ @@ -66,10 +66,83 @@ struct omap_desc { struct omap_sg sg[0]; }; +enum { + CCR_FS = BIT(5), + CCR_READ_PRIORITY = BIT(6), + CCR_ENABLE = BIT(7), + CCR_AUTO_INIT = BIT(8), /* OMAP1 only */ + CCR_REPEAT = BIT(9), /* OMAP1 only */ + CCR_OMAP31_DISABLE = BIT(10), /* OMAP1 only */ + CCR_SUSPEND_SENSITIVE = BIT(8), /* OMAP2+ only */ + CCR_RD_ACTIVE = BIT(9), /* OMAP2+ only */ + CCR_WR_ACTIVE = BIT(10), /* OMAP2+ only */ + CCR_SRC_AMODE_CONSTANT = 0 << 12, + CCR_SRC_AMODE_POSTINC = 1 << 12, + CCR_SRC_AMODE_SGLIDX = 2 << 12, + CCR_SRC_AMODE_DBLIDX = 3 << 12, + CCR_DST_AMODE_CONSTANT = 0 << 14, + CCR_DST_AMODE_POSTINC = 1 << 14, + CCR_DST_AMODE_SGLIDX = 2 << 14, + CCR_DST_AMODE_DBLIDX = 3 << 14, + CCR_CONSTANT_FILL = BIT(16), + CCR_TRANSPARENT_COPY = BIT(17), + CCR_BS = BIT(18), + CCR_SUPERVISOR = BIT(22), + CCR_PREFETCH = BIT(23), + CCR_TRIGGER_SRC = BIT(24), + CCR_BUFFERING_DISABLE = BIT(25), + CCR_WRITE_PRIORITY = BIT(26), + CCR_SYNC_ELEMENT = 0, + CCR_SYNC_FRAME = CCR_FS, + CCR_SYNC_BLOCK = CCR_BS, + CCR_SYNC_PACKET = CCR_BS | CCR_FS, + + CSDP_DATA_TYPE_8 = 0, + CSDP_DATA_TYPE_16 = 1, + CSDP_DATA_TYPE_32 = 2, + CSDP_SRC_PORT_EMIFF = 0 << 2, /* OMAP1 only */ + CSDP_SRC_PORT_EMIFS = 1 << 2, /* OMAP1 only */ + CSDP_SRC_PORT_OCP_T1 = 2 << 2, /* OMAP1 only */ + CSDP_SRC_PORT_TIPB = 3 << 2, /* OMAP1 only */ + CSDP_SRC_PORT_OCP_T2 = 4 << 2, /* OMAP1 only */ + CSDP_SRC_PORT_MPUI = 5 << 2, /* OMAP1 only */ + CSDP_SRC_PACKED = BIT(6), + CSDP_SRC_BURST_1 = 0 << 7, + CSDP_SRC_BURST_16 = 1 << 7, + CSDP_SRC_BURST_32 = 2 << 7, + CSDP_SRC_BURST_64 = 3 << 7, + CSDP_DST_PORT_EMIFF = 0 << 9, /* OMAP1 only */ + CSDP_DST_PORT_EMIFS = 1 << 9, /* OMAP1 only */ + CSDP_DST_PORT_OCP_T1 = 2 << 9, /* OMAP1 only */ + CSDP_DST_PORT_TIPB = 3 << 9, /* OMAP1 only */ + CSDP_DST_PORT_OCP_T2 = 4 << 9, /* OMAP1 only */ + CSDP_DST_PORT_MPUI = 5 << 9, /* OMAP1 only */ + CSDP_DST_PACKED = BIT(13), + CSDP_DST_BURST_1 = 0 << 14, + CSDP_DST_BURST_16 = 1 << 14, + CSDP_DST_BURST_32 = 2 << 14, + CSDP_DST_BURST_64 = 3 << 14, + + CICR_TOUT_IE = BIT(0), /* OMAP1 only */ + CICR_DROP_IE = BIT(1), + CICR_HALF_IE = BIT(2), + CICR_FRAME_IE = BIT(3), + CICR_LAST_IE = BIT(4), + CICR_BLOCK_IE = BIT(5), + CICR_PKT_IE = BIT(7), /* OMAP2+ only */ + CICR_TRANS_ERR_IE = BIT(8), /* OMAP2+ only */ + CICR_SUPERVISOR_ERR_IE = BIT(10), /* OMAP2+ only */ + CICR_MISALIGNED_ERR_IE = BIT(11), /* OMAP2+ only */ + CICR_DRAIN_IE = BIT(12), /* OMAP2+ only */ + CICR_SUPER_BLOCK_IE = BIT(14), /* OMAP2+ only */ + + CLNK_CTRL_ENABLE_LNK = BIT(15), +}; + static const unsigned es_bytes[] = { - [OMAP_DMA_DATA_TYPE_S8] = 1, - [OMAP_DMA_DATA_TYPE_S16] = 2, - [OMAP_DMA_DATA_TYPE_S32] = 4, + [CSDP_DATA_TYPE_8] = 1, + [CSDP_DATA_TYPE_16] = 2, + [CSDP_DATA_TYPE_32] = 4, }; static struct of_dma_filter_info omap_dma_info = { @@ -112,7 +185,7 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) if (dma_omap1()) val &= ~(1 << 14); - val |= c->dma_ch | 1 << 15; + val |= c->dma_ch | CLNK_CTRL_ENABLE_LNK; c->plat->dma_write(val, CLNK_CTRL, c->dma_ch); } else if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) @@ -129,8 +202,8 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) val = c->plat->dma_read(CCR, c->dma_ch); if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) - val |= OMAP_DMA_CCR_BUFFERING_DISABLE; - val |= OMAP_DMA_CCR_EN; + val |= CCR_BUFFERING_DISABLE; + val |= CCR_ENABLE; mb(); c->plat->dma_write(val, CCR, c->dma_ch); } @@ -150,8 +223,7 @@ static void omap_dma_stop(struct omap_chan *c) c->plat->dma_write(~0, CSR, c->dma_ch); val = c->plat->dma_read(CCR, c->dma_ch); - if (od->plat->errata & DMA_ERRATA_i541 && - val & OMAP_DMA_CCR_SEL_SRC_DST_SYNC) { + if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) { uint32_t sysconfig; unsigned i; @@ -161,13 +233,13 @@ static void omap_dma_stop(struct omap_chan *c) c->plat->dma_write(val, OCP_SYSCONFIG, c->dma_ch); val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~OMAP_DMA_CCR_EN; + val &= ~CCR_ENABLE; c->plat->dma_write(val, CCR, c->dma_ch); /* Wait for sDMA FIFO to drain */ for (i = 0; ; i++) { val = c->plat->dma_read(CCR, c->dma_ch); - if (!(val & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE))) + if (!(val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE))) break; if (i > 100) @@ -176,14 +248,14 @@ static void omap_dma_stop(struct omap_chan *c) udelay(5); } - if (val & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE)) + if (val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE)) dev_err(c->vc.chan.device->dev, "DMA drain did not complete on lch %d\n", c->dma_ch); c->plat->dma_write(sysconfig, OCP_SYSCONFIG, c->dma_ch); } else { - val &= ~OMAP_DMA_CCR_EN; + val &= ~CCR_ENABLE; c->plat->dma_write(val, CCR, c->dma_ch); } @@ -195,7 +267,7 @@ static void omap_dma_stop(struct omap_chan *c) if (dma_omap1()) val |= 1 << 14; /* set the STOP_LNK bit */ else - val &= ~(1 << 15); /* Clear the ENABLE_LNK bit */ + val &= ~CLNK_CTRL_ENABLE_LNK; c->plat->dma_write(val, CLNK_CTRL, c->dma_ch); } @@ -510,13 +582,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( /* Bus width translates to the element size (ES) */ switch (dev_width) { case DMA_SLAVE_BUSWIDTH_1_BYTE: - es = OMAP_DMA_DATA_TYPE_S8; + es = CSDP_DATA_TYPE_8; break; case DMA_SLAVE_BUSWIDTH_2_BYTES: - es = OMAP_DMA_DATA_TYPE_S16; + es = CSDP_DATA_TYPE_16; break; case DMA_SLAVE_BUSWIDTH_4_BYTES: - es = OMAP_DMA_DATA_TYPE_S32; + es = CSDP_DATA_TYPE_32; break; default: /* not reached */ return NULL; @@ -531,44 +603,38 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->dev_addr = dev_addr; d->es = es; - d->ccr = 0; + d->ccr = CCR_SYNC_FRAME; if (dir == DMA_DEV_TO_MEM) - d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 | - OMAP_DMA_AMODE_CONSTANT << 12; + d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; else - d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 | - OMAP_DMA_AMODE_POST_INC << 12; + d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC; - d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; + d->cicr = CICR_DROP_IE | CICR_BLOCK_IE; d->csdp = es; if (dma_omap1()) { - d->ccr |= 1 << 5; /* frame sync */ if (__dma_omap16xx(od->plat->dma_attr)) { - d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */ + d->ccr |= CCR_OMAP31_DISABLE; /* Duplicate what plat-omap/dma.c does */ d->ccr |= c->dma_ch + 1; } else { d->ccr |= c->dma_sig & 0x1f; } - d->cicr |= OMAP1_DMA_TOUT_IRQ; + d->cicr |= CICR_TOUT_IE; if (dir == DMA_DEV_TO_MEM) - d->csdp |= OMAP_DMA_PORT_EMIFF << 9 | - OMAP_DMA_PORT_TIPB << 2; + d->csdp |= CSDP_DST_PORT_EMIFF | CSDP_SRC_PORT_TIPB; else - d->csdp |= OMAP_DMA_PORT_TIPB << 9 | - OMAP_DMA_PORT_EMIFF << 2; + d->csdp |= CSDP_DST_PORT_TIPB | CSDP_SRC_PORT_EMIFF; } else { d->ccr |= (c->dma_sig & ~0x1f) << 14; d->ccr |= c->dma_sig & 0x1f; - d->ccr |= 1 << 5; /* frame sync */ if (dir == DMA_DEV_TO_MEM) - d->ccr |= 1 << 24; /* source synch */ + d->ccr |= CCR_TRIGGER_SRC; - d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; + d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; } /* @@ -623,13 +689,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( /* Bus width translates to the element size (ES) */ switch (dev_width) { case DMA_SLAVE_BUSWIDTH_1_BYTE: - es = OMAP_DMA_DATA_TYPE_S8; + es = CSDP_DATA_TYPE_8; break; case DMA_SLAVE_BUSWIDTH_2_BYTES: - es = OMAP_DMA_DATA_TYPE_S16; + es = CSDP_DATA_TYPE_16; break; case DMA_SLAVE_BUSWIDTH_4_BYTES: - es = OMAP_DMA_DATA_TYPE_S32; + es = CSDP_DATA_TYPE_32; break; default: /* not reached */ return NULL; @@ -651,51 +717,48 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->ccr = 0; if (__dma_omap15xx(od->plat->dma_attr)) - d->ccr = 3 << 8; + d->ccr = CCR_AUTO_INIT | CCR_REPEAT; if (dir == DMA_DEV_TO_MEM) - d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 | - OMAP_DMA_AMODE_CONSTANT << 12; + d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; else - d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 | - OMAP_DMA_AMODE_POST_INC << 12; + d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC; - d->cicr = OMAP_DMA_DROP_IRQ; + d->cicr = CICR_DROP_IE; if (flags & DMA_PREP_INTERRUPT) - d->cicr |= OMAP_DMA_FRAME_IRQ; + d->cicr |= CICR_FRAME_IE; d->csdp = es; if (dma_omap1()) { if (__dma_omap16xx(od->plat->dma_attr)) { - d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */ + d->ccr |= CCR_OMAP31_DISABLE; /* Duplicate what plat-omap/dma.c does */ d->ccr |= c->dma_ch + 1; } else { d->ccr |= c->dma_sig & 0x1f; } - d->cicr |= OMAP1_DMA_TOUT_IRQ; + d->cicr |= CICR_TOUT_IE; if (dir == DMA_DEV_TO_MEM) - d->csdp |= OMAP_DMA_PORT_EMIFF << 9 | - OMAP_DMA_PORT_MPUI << 2; + d->csdp |= CSDP_DST_PORT_EMIFF | CSDP_SRC_PORT_MPUI; else - d->csdp |= OMAP_DMA_PORT_MPUI << 9 | - OMAP_DMA_PORT_EMIFF << 2; + d->csdp |= CSDP_DST_PORT_MPUI | CSDP_SRC_PORT_EMIFF; } else { d->ccr |= (c->dma_sig & ~0x1f) << 14; d->ccr |= c->dma_sig & 0x1f; if (burst) - d->ccr |= 1 << 18 | 1 << 5; /* packet */ + d->ccr |= CCR_SYNC_PACKET; + else + d->ccr |= CCR_SYNC_ELEMENT; if (dir == DMA_DEV_TO_MEM) - d->ccr |= 1 << 24; /* source synch */ + d->ccr |= CCR_TRIGGER_SRC; - d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; + d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; - /* src and dst burst mode 16 */ - d->csdp |= 3 << 14 | 3 << 7; + d->csdp |= CSDP_DST_BURST_64 | CSDP_SRC_BURST_64; } c->cyclic = true; -- cgit v1.1 From 49ae0b29439446cff81c32bf01fb7b7cce195373 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 21:09:18 +0000 Subject: dmaengine: omap-dma: move CCR buffering disable errata out of the fast path Since we record the CCR register in the dma transaction, we can move the processing of the iframe buffering errata out of the omap_dma_start(). Move it to the preparation functions. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 6cf66e6..324f4c7 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -201,8 +201,6 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) c->plat->dma_write(d->cicr, CICR, c->dma_ch); val = c->plat->dma_read(CCR, c->dma_ch); - if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) - val |= CCR_BUFFERING_DISABLE; val |= CCR_ENABLE; mb(); c->plat->dma_write(val, CCR, c->dma_ch); @@ -558,6 +556,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, unsigned sglen, enum dma_transfer_direction dir, unsigned long tx_flags, void *context) { + struct omap_dmadev *od = to_omap_dma_dev(chan->device); struct omap_chan *c = to_omap_dma_chan(chan); enum dma_slave_buswidth dev_width; struct scatterlist *sgent; @@ -636,6 +635,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; } + if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) + d->ccr |= CCR_BUFFERING_DISABLE; /* * Build our scatterlist entries: each contains the address, @@ -760,6 +761,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp |= CSDP_DST_BURST_64 | CSDP_SRC_BURST_64; } + if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) + d->ccr |= CCR_BUFFERING_DISABLE; c->cyclic = true; -- cgit v1.1 From 470b23f7308dd2af25bd075d14a724f8ccd93985 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Nov 2013 21:23:06 +0000 Subject: dmaengine: omap-dma: consolidate clearing channel status register Consolidate clearing of the channel status register, rather than open coding the same functionality in two places. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 324f4c7..d1641aa 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -169,6 +169,14 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd) kfree(container_of(vd, struct omap_desc, vd)); } +static void omap_dma_clear_csr(struct omap_chan *c) +{ + if (dma_omap1()) + c->plat->dma_read(CSR, c->dma_ch); + else + c->plat->dma_write(~0, CSR, c->dma_ch); +} + static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) { struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); @@ -191,11 +199,7 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) } else if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) c->plat->dma_write(c->dma_ch, CLNK_CTRL, c->dma_ch); - /* Clear CSR */ - if (dma_omap1()) - c->plat->dma_read(CSR, c->dma_ch); - else - c->plat->dma_write(~0, CSR, c->dma_ch); + omap_dma_clear_csr(c); /* Enable interrupts */ c->plat->dma_write(d->cicr, CICR, c->dma_ch); @@ -214,11 +218,7 @@ static void omap_dma_stop(struct omap_chan *c) /* disable irq */ c->plat->dma_write(0, CICR, c->dma_ch); - /* Clear CSR */ - if (dma_omap1()) - c->plat->dma_read(CSR, c->dma_ch); - else - c->plat->dma_write(~0, CSR, c->dma_ch); + omap_dma_clear_csr(c); val = c->plat->dma_read(CCR, c->dma_ch); if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) { -- cgit v1.1 From 893e63e301e37cd3be7afb55c95eb8ef6ead304b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 3 Nov 2013 11:17:11 +0000 Subject: dmaengine: omap-dma: improve efficiency loading C.SA/C.EI/C.FI registers The only thing which changes is which registers are written, so put this in local variables instead. This results in smaller code. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index d1641aa..06727a7 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -275,17 +275,21 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, unsigned idx) { struct omap_sg *sg = d->sg + idx; + unsigned cxsa, cxei, cxfi; if (d->dir == DMA_DEV_TO_MEM) { - c->plat->dma_write(sg->addr, CDSA, c->dma_ch); - c->plat->dma_write(0, CDEI, c->dma_ch); - c->plat->dma_write(0, CDFI, c->dma_ch); + cxsa = CDSA; + cxei = CDEI; + cxfi = CDFI; } else { - c->plat->dma_write(sg->addr, CSSA, c->dma_ch); - c->plat->dma_write(0, CSEI, c->dma_ch); - c->plat->dma_write(0, CSFI, c->dma_ch); + cxsa = CSSA; + cxei = CSEI; + cxfi = CSFI; } + c->plat->dma_write(sg->addr, cxsa, c->dma_ch); + c->plat->dma_write(0, cxei, c->dma_ch); + c->plat->dma_write(0, cxfi, c->dma_ch); c->plat->dma_write(sg->en, CEN, c->dma_ch); c->plat->dma_write(sg->fn, CFN, c->dma_ch); @@ -296,6 +300,7 @@ static void omap_dma_start_desc(struct omap_chan *c) { struct virt_dma_desc *vd = vchan_next_desc(&c->vc); struct omap_desc *d; + unsigned cxsa, cxei, cxfi; if (!vd) { c->desc = NULL; @@ -312,15 +317,18 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch); if (d->dir == DMA_DEV_TO_MEM) { - c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch); - c->plat->dma_write(0, CSEI, c->dma_ch); - c->plat->dma_write(d->fi, CSFI, c->dma_ch); + cxsa = CSSA; + cxei = CSEI; + cxfi = CSFI; } else { - c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch); - c->plat->dma_write(0, CDEI, c->dma_ch); - c->plat->dma_write(d->fi, CDFI, c->dma_ch); + cxsa = CDSA; + cxei = CDEI; + cxfi = CDFI; } + c->plat->dma_write(d->dev_addr, cxsa, c->dma_ch); + c->plat->dma_write(0, cxei, c->dma_ch); + c->plat->dma_write(d->fi, cxfi, c->dma_ch); c->plat->dma_write(d->csdp, CSDP, c->dma_ch); omap_dma_start_sg(c, d, 0); -- cgit v1.1 From 965aeb4df1f2142f5a6407c6d40b7196be719582 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 6 Nov 2013 17:12:30 +0000 Subject: dmaengine: omap-dma: move clnk_ctrl setting to preparation functions Move the clnk_ctrl setup to the preparation functions, saving its value in the omap_desc. This only needs to be set once per descriptor, not for each segment, so set it in omap_dma_start_desc() rather than omap_dma_start(). Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 06727a7..4960927 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -59,6 +59,7 @@ struct omap_desc { int16_t fi; /* for OMAP_DMA_SYNC_PACKET */ uint8_t es; /* CSDP_DATA_TYPE_xxx */ uint32_t ccr; /* CCR value */ + uint16_t clnk_ctrl; /* CLNK_CTRL value */ uint16_t cicr; /* CICR value */ uint32_t csdp; /* CSDP value */ @@ -187,18 +188,6 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) else c->plat->dma_write(0, CDAC, c->dma_ch); - if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) { - val = c->plat->dma_read(CLNK_CTRL, c->dma_ch); - - if (dma_omap1()) - val &= ~(1 << 14); - - val |= c->dma_ch | CLNK_CTRL_ENABLE_LNK; - - c->plat->dma_write(val, CLNK_CTRL, c->dma_ch); - } else if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) - c->plat->dma_write(c->dma_ch, CLNK_CTRL, c->dma_ch); - omap_dma_clear_csr(c); /* Enable interrupts */ @@ -330,6 +319,7 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write(0, cxei, c->dma_ch); c->plat->dma_write(d->fi, cxfi, c->dma_ch); c->plat->dma_write(d->csdp, CSDP, c->dma_ch); + c->plat->dma_write(d->clnk_ctrl, CLNK_CTRL, c->dma_ch); omap_dma_start_sg(c, d, 0); } @@ -645,6 +635,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( } if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) d->ccr |= CCR_BUFFERING_DISABLE; + if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) + d->clnk_ctrl = c->dma_ch; /* * Build our scatterlist entries: each contains the address, @@ -725,8 +717,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->sglen = 1; d->ccr = 0; - if (__dma_omap15xx(od->plat->dma_attr)) - d->ccr = CCR_AUTO_INIT | CCR_REPEAT; if (dir == DMA_DEV_TO_MEM) d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; else @@ -772,6 +762,11 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) d->ccr |= CCR_BUFFERING_DISABLE; + if (__dma_omap15xx(od->plat->dma_attr)) + d->ccr |= CCR_AUTO_INIT | CCR_REPEAT; + else + d->clnk_ctrl = c->dma_ch | CLNK_CTRL_ENABLE_LNK; + c->cyclic = true; return vchan_tx_prep(&c->vc, &d->vd, flags); -- cgit v1.1 From 59871902703c47acc730555be41bd9cb36d3700c Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 6 Nov 2013 17:15:16 +0000 Subject: dmaengine: omap-dma: move barrier to omap_dma_start_desc() We don't need to issue a barrier for every segment of a DMA transfer; doing this just once per descriptor will do. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 4960927..49b3032 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -195,7 +195,6 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) val = c->plat->dma_read(CCR, c->dma_ch); val |= CCR_ENABLE; - mb(); c->plat->dma_write(val, CCR, c->dma_ch); } @@ -301,6 +300,13 @@ static void omap_dma_start_desc(struct omap_chan *c) c->desc = d = to_omap_dma_desc(&vd->tx); c->sgidx = 0; + /* + * This provides the necessary barrier to ensure data held in + * DMA coherent memory is visible to the DMA engine prior to + * the transfer starting. + */ + mb(); + c->plat->dma_write(d->ccr, CCR, c->dma_ch); if (dma_omap1()) c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch); -- cgit v1.1 From 45da7b0451b1fe15e882b08c79be58458cbe7a2f Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 6 Nov 2013 17:18:42 +0000 Subject: dmaengine: omap-dma: use cached CCR value when enabling DMA We don't need to read-modify-write the CCR register; we already know what value it should contain at this point. Use the cached CCR value when setting the enable bit. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 49b3032..b270aed 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -181,7 +181,6 @@ static void omap_dma_clear_csr(struct omap_chan *c) static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) { struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); - uint32_t val; if (__dma_omap15xx(od->plat->dma_attr)) c->plat->dma_write(0, CPC, c->dma_ch); @@ -193,9 +192,8 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) /* Enable interrupts */ c->plat->dma_write(d->cicr, CICR, c->dma_ch); - val = c->plat->dma_read(CCR, c->dma_ch); - val |= CCR_ENABLE; - c->plat->dma_write(val, CCR, c->dma_ch); + /* Enable channel */ + c->plat->dma_write(d->ccr | CCR_ENABLE, CCR, c->dma_ch); } static void omap_dma_stop(struct omap_chan *c) -- cgit v1.1 From c5ed98b6ae79545284b7855a07ded32934865a6d Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 6 Nov 2013 17:33:09 +0000 Subject: dmaengine: omap-dma: provide register read/write functions Provide a pair of channel register accessors, and a pair of global accessors for non-channel specific registers. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 102 +++++++++++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 41 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index b270aed..a1baada 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -170,12 +170,32 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd) kfree(container_of(vd, struct omap_desc, vd)); } +static void omap_dma_glbl_write(struct omap_dmadev *od, unsigned reg, unsigned val) +{ + od->plat->dma_write(val, reg, 0); +} + +static unsigned omap_dma_glbl_read(struct omap_dmadev *od, unsigned reg) +{ + return od->plat->dma_read(reg, 0); +} + +static void omap_dma_chan_write(struct omap_chan *c, unsigned reg, unsigned val) +{ + c->plat->dma_write(val, reg, c->dma_ch); +} + +static unsigned omap_dma_chan_read(struct omap_chan *c, unsigned reg) +{ + return c->plat->dma_read(reg, c->dma_ch); +} + static void omap_dma_clear_csr(struct omap_chan *c) { if (dma_omap1()) - c->plat->dma_read(CSR, c->dma_ch); + omap_dma_chan_read(c, CSR); else - c->plat->dma_write(~0, CSR, c->dma_ch); + omap_dma_chan_write(c, CSR, ~0); } static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) @@ -183,17 +203,17 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); if (__dma_omap15xx(od->plat->dma_attr)) - c->plat->dma_write(0, CPC, c->dma_ch); + omap_dma_chan_write(c, CPC, 0); else - c->plat->dma_write(0, CDAC, c->dma_ch); + omap_dma_chan_write(c, CDAC, 0); omap_dma_clear_csr(c); /* Enable interrupts */ - c->plat->dma_write(d->cicr, CICR, c->dma_ch); + omap_dma_chan_write(c, CICR, d->cicr); /* Enable channel */ - c->plat->dma_write(d->ccr | CCR_ENABLE, CCR, c->dma_ch); + omap_dma_chan_write(c, CCR, d->ccr | CCR_ENABLE); } static void omap_dma_stop(struct omap_chan *c) @@ -202,27 +222,27 @@ static void omap_dma_stop(struct omap_chan *c) uint32_t val; /* disable irq */ - c->plat->dma_write(0, CICR, c->dma_ch); + omap_dma_chan_write(c, CICR, 0); omap_dma_clear_csr(c); - val = c->plat->dma_read(CCR, c->dma_ch); + val = omap_dma_chan_read(c, CCR); if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) { uint32_t sysconfig; unsigned i; - sysconfig = c->plat->dma_read(OCP_SYSCONFIG, c->dma_ch); + sysconfig = omap_dma_glbl_read(od, OCP_SYSCONFIG); val = sysconfig & ~DMA_SYSCONFIG_MIDLEMODE_MASK; val |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); - c->plat->dma_write(val, OCP_SYSCONFIG, c->dma_ch); + omap_dma_glbl_write(od, OCP_SYSCONFIG, val); - val = c->plat->dma_read(CCR, c->dma_ch); + val = omap_dma_chan_read(c, CCR); val &= ~CCR_ENABLE; - c->plat->dma_write(val, CCR, c->dma_ch); + omap_dma_chan_write(c, CCR, val); /* Wait for sDMA FIFO to drain */ for (i = 0; ; i++) { - val = c->plat->dma_read(CCR, c->dma_ch); + val = omap_dma_chan_read(c, CCR); if (!(val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE))) break; @@ -237,23 +257,23 @@ static void omap_dma_stop(struct omap_chan *c) "DMA drain did not complete on lch %d\n", c->dma_ch); - c->plat->dma_write(sysconfig, OCP_SYSCONFIG, c->dma_ch); + omap_dma_glbl_write(od, OCP_SYSCONFIG, sysconfig); } else { val &= ~CCR_ENABLE; - c->plat->dma_write(val, CCR, c->dma_ch); + omap_dma_chan_write(c, CCR, val); } mb(); if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) { - val = c->plat->dma_read(CLNK_CTRL, c->dma_ch); + val = omap_dma_chan_read(c, CLNK_CTRL); if (dma_omap1()) val |= 1 << 14; /* set the STOP_LNK bit */ else val &= ~CLNK_CTRL_ENABLE_LNK; - c->plat->dma_write(val, CLNK_CTRL, c->dma_ch); + omap_dma_chan_write(c, CLNK_CTRL, val); } } @@ -273,11 +293,11 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, cxfi = CSFI; } - c->plat->dma_write(sg->addr, cxsa, c->dma_ch); - c->plat->dma_write(0, cxei, c->dma_ch); - c->plat->dma_write(0, cxfi, c->dma_ch); - c->plat->dma_write(sg->en, CEN, c->dma_ch); - c->plat->dma_write(sg->fn, CFN, c->dma_ch); + omap_dma_chan_write(c, cxsa, sg->addr); + omap_dma_chan_write(c, cxei, 0); + omap_dma_chan_write(c, cxfi, 0); + omap_dma_chan_write(c, CEN, sg->en); + omap_dma_chan_write(c, CFN, sg->fn); omap_dma_start(c, d); } @@ -305,9 +325,9 @@ static void omap_dma_start_desc(struct omap_chan *c) */ mb(); - c->plat->dma_write(d->ccr, CCR, c->dma_ch); + omap_dma_chan_write(c, CCR, d->ccr); if (dma_omap1()) - c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch); + omap_dma_chan_write(c, CCR2, d->ccr >> 16); if (d->dir == DMA_DEV_TO_MEM) { cxsa = CSSA; @@ -319,11 +339,11 @@ static void omap_dma_start_desc(struct omap_chan *c) cxfi = CDFI; } - c->plat->dma_write(d->dev_addr, cxsa, c->dma_ch); - c->plat->dma_write(0, cxei, c->dma_ch); - c->plat->dma_write(d->fi, cxfi, c->dma_ch); - c->plat->dma_write(d->csdp, CSDP, c->dma_ch); - c->plat->dma_write(d->clnk_ctrl, CLNK_CTRL, c->dma_ch); + omap_dma_chan_write(c, cxsa, d->dev_addr); + omap_dma_chan_write(c, cxei, 0); + omap_dma_chan_write(c, cxfi, d->fi); + omap_dma_chan_write(c, CSDP, d->csdp); + omap_dma_chan_write(c, CLNK_CTRL, d->clnk_ctrl); omap_dma_start_sg(c, d, 0); } @@ -437,12 +457,12 @@ static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c) dma_addr_t addr; if (__dma_omap15xx(od->plat->dma_attr)) - addr = c->plat->dma_read(CPC, c->dma_ch); + addr = omap_dma_chan_read(c, CPC); else - addr = c->plat->dma_read(CSAC, c->dma_ch); + addr = omap_dma_chan_read(c, CSAC); if (od->plat->errata & DMA_ERRATA_3_3 && addr == 0) - addr = c->plat->dma_read(CSAC, c->dma_ch); + addr = omap_dma_chan_read(c, CSAC); if (!__dma_omap15xx(od->plat->dma_attr)) { /* @@ -450,14 +470,14 @@ static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c) * not been started (no data has been transferred so far). * Return the programmed source start address in this case. */ - if (c->plat->dma_read(CDAC, c->dma_ch)) - addr = c->plat->dma_read(CSAC, c->dma_ch); + if (omap_dma_chan_read(c, CDAC)) + addr = omap_dma_chan_read(c, CSAC); else - addr = c->plat->dma_read(CSSA, c->dma_ch); + addr = omap_dma_chan_read(c, CSSA); } if (dma_omap1()) - addr |= c->plat->dma_read(CSSA, c->dma_ch) & 0xffff0000; + addr |= omap_dma_chan_read(c, CSSA) & 0xffff0000; return addr; } @@ -468,27 +488,27 @@ static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c) dma_addr_t addr; if (__dma_omap15xx(od->plat->dma_attr)) - addr = c->plat->dma_read(CPC, c->dma_ch); + addr = omap_dma_chan_read(c, CPC); else - addr = c->plat->dma_read(CDAC, c->dma_ch); + addr = omap_dma_chan_read(c, CDAC); /* * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is * read before the DMA controller finished disabling the channel. */ if (!__dma_omap15xx(od->plat->dma_attr) && addr == 0) { - addr = c->plat->dma_read(CDAC, c->dma_ch); + addr = omap_dma_chan_read(c, CDAC); /* * CDAC == 0 indicates that the DMA transfer on the channel has * not been started (no data has been transferred so far). * Return the programmed destination start address in this case. */ if (addr == 0) - addr = c->plat->dma_read(CDSA, c->dma_ch); + addr = omap_dma_chan_read(c, CDSA); } if (dma_omap1()) - addr |= c->plat->dma_read(CDSA, c->dma_ch) & 0xffff0000; + addr |= omap_dma_chan_read(c, CDSA) & 0xffff0000; return addr; } -- cgit v1.1 From b07fd625ac9df7412bd996edbdc298eb343dd501 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 6 Nov 2013 19:26:45 +0000 Subject: dmaengine: omap-dma: cleanup errata 3.3 handling Provide a function to read the CSAC/CDAC register, working around the OMAP 3.2/3.3 erratum (which requires two reads of the register if the first returned zero. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 52 ++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index a1baada..1e0018f3 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -451,28 +451,39 @@ static size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr) return size; } +/* + * OMAP 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is + * read before the DMA controller finished disabling the channel. + */ +static uint32_t omap_dma_chan_read_3_3(struct omap_chan *c, unsigned reg) +{ + struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); + uint32_t val; + + val = omap_dma_chan_read(c, reg); + if (val == 0 && od->plat->errata & DMA_ERRATA_3_3) + val = omap_dma_chan_read(c, reg); + + return val; +} + static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c) { struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); - dma_addr_t addr; + dma_addr_t addr, cdac; - if (__dma_omap15xx(od->plat->dma_attr)) + if (__dma_omap15xx(od->plat->dma_attr)) { addr = omap_dma_chan_read(c, CPC); - else - addr = omap_dma_chan_read(c, CSAC); - - if (od->plat->errata & DMA_ERRATA_3_3 && addr == 0) - addr = omap_dma_chan_read(c, CSAC); + } else { + addr = omap_dma_chan_read_3_3(c, CSAC); + cdac = omap_dma_chan_read_3_3(c, CDAC); - if (!__dma_omap15xx(od->plat->dma_attr)) { /* * CDAC == 0 indicates that the DMA transfer on the channel has * not been started (no data has been transferred so far). * Return the programmed source start address in this case. */ - if (omap_dma_chan_read(c, CDAC)) - addr = omap_dma_chan_read(c, CSAC); - else + if (cdac == 0) addr = omap_dma_chan_read(c, CSSA); } @@ -487,21 +498,16 @@ static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c) struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); dma_addr_t addr; - if (__dma_omap15xx(od->plat->dma_attr)) + if (__dma_omap15xx(od->plat->dma_attr)) { addr = omap_dma_chan_read(c, CPC); - else - addr = omap_dma_chan_read(c, CDAC); + } else { + addr = omap_dma_chan_read_3_3(c, CDAC); - /* - * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is - * read before the DMA controller finished disabling the channel. - */ - if (!__dma_omap15xx(od->plat->dma_attr) && addr == 0) { - addr = omap_dma_chan_read(c, CDAC); /* - * CDAC == 0 indicates that the DMA transfer on the channel has - * not been started (no data has been transferred so far). - * Return the programmed destination start address in this case. + * CDAC == 0 indicates that the DMA transfer on the channel + * has not been started (no data has been transferred so + * far). Return the programmed destination start address in + * this case. */ if (addr == 0) addr = omap_dma_chan_read(c, CDSA); -- cgit v1.1 From e38b1485fde832f72ab478f947f6e78a8e28c58b Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 8 Nov 2013 14:48:55 +0000 Subject: ARM: omap: remove references to disable_irq_lch The disable_irq_lch method is never actually used, so there's not much point it existing; remove it. Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap1/dma.c | 1 - arch/arm/mach-omap2/dma.c | 10 ---------- include/linux/omap-dma.h | 1 - 3 files changed, 12 deletions(-) diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index 5bb8ce8..d292055 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c @@ -363,7 +363,6 @@ static int __init omap1_system_dma_init(void) p->clear_dma = omap1_clear_dma; p->dma_write = dma_write; p->dma_read = dma_read; - p->disable_irq_lch = NULL; p->errata = configure_dma_errata(); diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index 49fd0d5..81c2d33 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -112,15 +112,6 @@ static inline u32 dma_read(int reg, int lch) return val; } -static inline void omap2_disable_irq_lch(int lch) -{ - u32 val; - - val = dma_read(IRQENABLE_L0, lch); - val &= ~(1 << lch); - dma_write(val, IRQENABLE_L0, lch); -} - static void omap2_clear_dma(int lch) { int i = dma_common_ch_start; @@ -239,7 +230,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) } p->dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr; - p->disable_irq_lch = omap2_disable_irq_lch; p->show_dma_caps = omap2_show_dma_caps; p->clear_dma = omap2_clear_dma; p->dma_write = dma_write; diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index d631658..0bb7de7 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h @@ -275,7 +275,6 @@ struct omap_dma_dev_attr { struct omap_system_dma_plat_info { struct omap_dma_dev_attr *dma_attr; u32 errata; - void (*disable_irq_lch)(int lch); void (*show_dma_caps)(void); void (*clear_lch_regs)(int lch); void (*clear_dma)(int lch); -- cgit v1.1 From ad0c381a8b3a15b8edfca0996729ea45692470ca Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 8 Nov 2013 14:53:35 +0000 Subject: ARM: omap: remove almost-const variables dma_stride and dma_common_ch_start are only ever initialised to one known value at initialisation, and are private to each of these files. There's no point these being variables at all. Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap1/dma.c | 14 ++++---------- arch/arm/mach-omap2/dma.c | 14 +++++--------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index d292055..11f0b0e 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c @@ -36,8 +36,6 @@ static u32 errata; static u32 enable_1510_mode; -static u8 dma_stride; -static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; static u16 reg_map[] = { [GCR] = 0x400, @@ -184,7 +182,7 @@ static inline void dma_write(u32 val, int reg, int lch) u8 stride; u32 offset; - stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + stride = (reg >= CPC) ? OMAP1_DMA_STRIDE : 0; offset = reg_map[reg] + (stride * lch); __raw_writew(val, dma_base + offset); @@ -200,7 +198,7 @@ static inline u32 dma_read(int reg, int lch) u8 stride; u32 offset, val; - stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + stride = (reg >= CPC) ? OMAP1_DMA_STRIDE : 0; offset = reg_map[reg] + (stride * lch); val = __raw_readw(dma_base + offset); @@ -216,9 +214,9 @@ static inline u32 dma_read(int reg, int lch) static void omap1_clear_lch_regs(int lch) { - int i = dma_common_ch_start; + int i; - for (; i <= dma_common_ch_end; i += 1) + for (i = CPC; i <= COLOR; i += 1) dma_write(0, i, lch); } @@ -380,10 +378,6 @@ static int __init omap1_system_dma_init(void) goto exit_release_chan; } - dma_stride = OMAP1_DMA_STRIDE; - dma_common_ch_start = CPC; - dma_common_ch_end = COLOR; - dma_pdev = platform_device_register_full(&omap_dma_dev_info); if (IS_ERR(dma_pdev)) { ret = PTR_ERR(dma_pdev); diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index 81c2d33..e4ac7ac 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -38,11 +38,10 @@ #define OMAP2_DMA_STRIDE 0x60 static u32 errata; -static u8 dma_stride; static struct omap_dma_dev_attr *d; -static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; +static enum omap_reg_offsets dma_common_ch_end; static u16 reg_map[] = { [REVISION] = 0x00, @@ -96,7 +95,7 @@ static inline void dma_write(u32 val, int reg, int lch) u8 stride; u32 offset; - stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + stride = (reg >= CSDP) ? OMAP2_DMA_STRIDE : 0; offset = reg_map[reg] + (stride * lch); __raw_writel(val, dma_base + offset); } @@ -106,7 +105,7 @@ static inline u32 dma_read(int reg, int lch) u8 stride; u32 offset, val; - stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + stride = (reg >= CSDP) ? OMAP2_DMA_STRIDE : 0; offset = reg_map[reg] + (stride * lch); val = __raw_readl(dma_base + offset); return val; @@ -114,9 +113,9 @@ static inline u32 dma_read(int reg, int lch) static void omap2_clear_dma(int lch) { - int i = dma_common_ch_start; + int i; - for (; i <= dma_common_ch_end; i += 1) + for (i = CSDP; i <= dma_common_ch_end; i += 1) dma_write(0, i, lch); } @@ -219,9 +218,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) struct resource *mem; char *name = "omap_dma_system"; - dma_stride = OMAP2_DMA_STRIDE; - dma_common_ch_start = CSDP; - p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); if (!p) { pr_err("%s: Unable to allocate pdata for %s:%s\n", -- cgit v1.1 From 64a2dc3d3de4235eb73921d870a674a23d9888f0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 8 Nov 2013 18:04:06 +0000 Subject: ARM: omap: clean up DMA register accesses We can do much better with this by using a structure to describe each register, rather than code. Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap1/dma.c | 117 +++++++++++++++++++++------------------------- arch/arm/mach-omap2/dma.c | 99 +++++++++++++++++++-------------------- include/linux/omap-dma.h | 13 ++++++ 3 files changed, 115 insertions(+), 114 deletions(-) diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index 11f0b0e..b680db7 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c @@ -32,53 +32,52 @@ #define OMAP1_DMA_BASE (0xfffed800) #define OMAP1_LOGICAL_DMA_CH_COUNT 17 -#define OMAP1_DMA_STRIDE 0x40 static u32 errata; static u32 enable_1510_mode; -static u16 reg_map[] = { - [GCR] = 0x400, - [GSCR] = 0x404, - [GRST1] = 0x408, - [HW_ID] = 0x442, - [PCH2_ID] = 0x444, - [PCH0_ID] = 0x446, - [PCH1_ID] = 0x448, - [PCHG_ID] = 0x44a, - [PCHD_ID] = 0x44c, - [CAPS_0] = 0x44e, - [CAPS_1] = 0x452, - [CAPS_2] = 0x456, - [CAPS_3] = 0x458, - [CAPS_4] = 0x45a, - [PCH2_SR] = 0x460, - [PCH0_SR] = 0x480, - [PCH1_SR] = 0x482, - [PCHD_SR] = 0x4c0, +static const struct omap_dma_reg reg_map[] = { + [GCR] = { 0x0400, 0x00, OMAP_DMA_REG_16BIT }, + [GSCR] = { 0x0404, 0x00, OMAP_DMA_REG_16BIT }, + [GRST1] = { 0x0408, 0x00, OMAP_DMA_REG_16BIT }, + [HW_ID] = { 0x0442, 0x00, OMAP_DMA_REG_16BIT }, + [PCH2_ID] = { 0x0444, 0x00, OMAP_DMA_REG_16BIT }, + [PCH0_ID] = { 0x0446, 0x00, OMAP_DMA_REG_16BIT }, + [PCH1_ID] = { 0x0448, 0x00, OMAP_DMA_REG_16BIT }, + [PCHG_ID] = { 0x044a, 0x00, OMAP_DMA_REG_16BIT }, + [PCHD_ID] = { 0x044c, 0x00, OMAP_DMA_REG_16BIT }, + [CAPS_0] = { 0x044e, 0x00, OMAP_DMA_REG_2X16BIT }, + [CAPS_1] = { 0x0452, 0x00, OMAP_DMA_REG_2X16BIT }, + [CAPS_2] = { 0x0456, 0x00, OMAP_DMA_REG_16BIT }, + [CAPS_3] = { 0x0458, 0x00, OMAP_DMA_REG_16BIT }, + [CAPS_4] = { 0x045a, 0x00, OMAP_DMA_REG_16BIT }, + [PCH2_SR] = { 0x0460, 0x00, OMAP_DMA_REG_16BIT }, + [PCH0_SR] = { 0x0480, 0x00, OMAP_DMA_REG_16BIT }, + [PCH1_SR] = { 0x0482, 0x00, OMAP_DMA_REG_16BIT }, + [PCHD_SR] = { 0x04c0, 0x00, OMAP_DMA_REG_16BIT }, /* Common Registers */ - [CSDP] = 0x00, - [CCR] = 0x02, - [CICR] = 0x04, - [CSR] = 0x06, - [CEN] = 0x10, - [CFN] = 0x12, - [CSFI] = 0x14, - [CSEI] = 0x16, - [CPC] = 0x18, /* 15xx only */ - [CSAC] = 0x18, - [CDAC] = 0x1a, - [CDEI] = 0x1c, - [CDFI] = 0x1e, - [CLNK_CTRL] = 0x28, + [CSDP] = { 0x0000, 0x40, OMAP_DMA_REG_16BIT }, + [CCR] = { 0x0002, 0x40, OMAP_DMA_REG_16BIT }, + [CICR] = { 0x0004, 0x40, OMAP_DMA_REG_16BIT }, + [CSR] = { 0x0006, 0x40, OMAP_DMA_REG_16BIT }, + [CEN] = { 0x0010, 0x40, OMAP_DMA_REG_16BIT }, + [CFN] = { 0x0012, 0x40, OMAP_DMA_REG_16BIT }, + [CSFI] = { 0x0014, 0x40, OMAP_DMA_REG_16BIT }, + [CSEI] = { 0x0016, 0x40, OMAP_DMA_REG_16BIT }, + [CPC] = { 0x0018, 0x40, OMAP_DMA_REG_16BIT }, /* 15xx only */ + [CSAC] = { 0x0018, 0x40, OMAP_DMA_REG_16BIT }, + [CDAC] = { 0x001a, 0x40, OMAP_DMA_REG_16BIT }, + [CDEI] = { 0x001c, 0x40, OMAP_DMA_REG_16BIT }, + [CDFI] = { 0x001e, 0x40, OMAP_DMA_REG_16BIT }, + [CLNK_CTRL] = { 0x0028, 0x40, OMAP_DMA_REG_16BIT }, /* Channel specific register offsets */ - [CSSA] = 0x08, - [CDSA] = 0x0c, - [COLOR] = 0x20, - [CCR2] = 0x24, - [LCH_CTRL] = 0x2a, + [CSSA] = { 0x0008, 0x40, OMAP_DMA_REG_2X16BIT }, + [CDSA] = { 0x000c, 0x40, OMAP_DMA_REG_2X16BIT }, + [COLOR] = { 0x0020, 0x40, OMAP_DMA_REG_2X16BIT }, + [CCR2] = { 0x0024, 0x40, OMAP_DMA_REG_16BIT }, + [LCH_CTRL] = { 0x002a, 0x40, OMAP_DMA_REG_16BIT }, }; static struct resource res[] __initdata = { @@ -179,36 +178,28 @@ static struct resource res[] __initdata = { static void __iomem *dma_base; static inline void dma_write(u32 val, int reg, int lch) { - u8 stride; - u32 offset; + void __iomem *addr = dma_base; - stride = (reg >= CPC) ? OMAP1_DMA_STRIDE : 0; - offset = reg_map[reg] + (stride * lch); + addr += reg_map[reg].offset; + addr += reg_map[reg].stride * lch; - __raw_writew(val, dma_base + offset); - if ((reg > CLNK_CTRL && reg < CCEN) || - (reg > PCHD_ID && reg < CAPS_2)) { - u32 offset2 = reg_map[reg] + 2 + (stride * lch); - __raw_writew(val >> 16, dma_base + offset2); - } + __raw_writew(val, addr); + if (reg_map[reg].type == OMAP_DMA_REG_2X16BIT) + __raw_writew(val >> 16, addr + 2); } static inline u32 dma_read(int reg, int lch) { - u8 stride; - u32 offset, val; - - stride = (reg >= CPC) ? OMAP1_DMA_STRIDE : 0; - offset = reg_map[reg] + (stride * lch); - - val = __raw_readw(dma_base + offset); - if ((reg > CLNK_CTRL && reg < CCEN) || - (reg > PCHD_ID && reg < CAPS_2)) { - u16 upper; - u32 offset2 = reg_map[reg] + 2 + (stride * lch); - upper = __raw_readw(dma_base + offset2); - val |= (upper << 16); - } + void __iomem *addr = dma_base; + uint32_t val; + + addr += reg_map[reg].offset; + addr += reg_map[reg].stride * lch; + + val = __raw_readw(addr); + if (reg_map[reg].type == OMAP_DMA_REG_2X16BIT) + val |= __raw_readw(addr + 2) << 16; + return val; } diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index e4ac7ac..e633b48 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -35,80 +35,77 @@ #include "omap_hwmod.h" #include "omap_device.h" -#define OMAP2_DMA_STRIDE 0x60 - static u32 errata; static struct omap_dma_dev_attr *d; static enum omap_reg_offsets dma_common_ch_end; -static u16 reg_map[] = { - [REVISION] = 0x00, - [GCR] = 0x78, - [IRQSTATUS_L0] = 0x08, - [IRQSTATUS_L1] = 0x0c, - [IRQSTATUS_L2] = 0x10, - [IRQSTATUS_L3] = 0x14, - [IRQENABLE_L0] = 0x18, - [IRQENABLE_L1] = 0x1c, - [IRQENABLE_L2] = 0x20, - [IRQENABLE_L3] = 0x24, - [SYSSTATUS] = 0x28, - [OCP_SYSCONFIG] = 0x2c, - [CAPS_0] = 0x64, - [CAPS_2] = 0x6c, - [CAPS_3] = 0x70, - [CAPS_4] = 0x74, +static const struct omap_dma_reg reg_map[] = { + [REVISION] = { 0x0000, 0x00, OMAP_DMA_REG_32BIT }, + [GCR] = { 0x0078, 0x00, OMAP_DMA_REG_32BIT }, + [IRQSTATUS_L0] = { 0x0008, 0x00, OMAP_DMA_REG_32BIT }, + [IRQSTATUS_L1] = { 0x000c, 0x00, OMAP_DMA_REG_32BIT }, + [IRQSTATUS_L2] = { 0x0010, 0x00, OMAP_DMA_REG_32BIT }, + [IRQSTATUS_L3] = { 0x0014, 0x00, OMAP_DMA_REG_32BIT }, + [IRQENABLE_L0] = { 0x0018, 0x00, OMAP_DMA_REG_32BIT }, + [IRQENABLE_L1] = { 0x001c, 0x00, OMAP_DMA_REG_32BIT }, + [IRQENABLE_L2] = { 0x0020, 0x00, OMAP_DMA_REG_32BIT }, + [IRQENABLE_L3] = { 0x0024, 0x00, OMAP_DMA_REG_32BIT }, + [SYSSTATUS] = { 0x0028, 0x00, OMAP_DMA_REG_32BIT }, + [OCP_SYSCONFIG] = { 0x002c, 0x00, OMAP_DMA_REG_32BIT }, + [CAPS_0] = { 0x0064, 0x00, OMAP_DMA_REG_32BIT }, + [CAPS_2] = { 0x006c, 0x00, OMAP_DMA_REG_32BIT }, + [CAPS_3] = { 0x0070, 0x00, OMAP_DMA_REG_32BIT }, + [CAPS_4] = { 0x0074, 0x00, OMAP_DMA_REG_32BIT }, /* Common register offsets */ - [CCR] = 0x80, - [CLNK_CTRL] = 0x84, - [CICR] = 0x88, - [CSR] = 0x8c, - [CSDP] = 0x90, - [CEN] = 0x94, - [CFN] = 0x98, - [CSEI] = 0xa4, - [CSFI] = 0xa8, - [CDEI] = 0xac, - [CDFI] = 0xb0, - [CSAC] = 0xb4, - [CDAC] = 0xb8, + [CCR] = { 0x0080, 0x60, OMAP_DMA_REG_32BIT }, + [CLNK_CTRL] = { 0x0084, 0x60, OMAP_DMA_REG_32BIT }, + [CICR] = { 0x0088, 0x60, OMAP_DMA_REG_32BIT }, + [CSR] = { 0x008c, 0x60, OMAP_DMA_REG_32BIT }, + [CSDP] = { 0x0090, 0x60, OMAP_DMA_REG_32BIT }, + [CEN] = { 0x0094, 0x60, OMAP_DMA_REG_32BIT }, + [CFN] = { 0x0098, 0x60, OMAP_DMA_REG_32BIT }, + [CSEI] = { 0x00a4, 0x60, OMAP_DMA_REG_32BIT }, + [CSFI] = { 0x00a8, 0x60, OMAP_DMA_REG_32BIT }, + [CDEI] = { 0x00ac, 0x60, OMAP_DMA_REG_32BIT }, + [CDFI] = { 0x00b0, 0x60, OMAP_DMA_REG_32BIT }, + [CSAC] = { 0x00b4, 0x60, OMAP_DMA_REG_32BIT }, + [CDAC] = { 0x00b8, 0x60, OMAP_DMA_REG_32BIT }, /* Channel specific register offsets */ - [CSSA] = 0x9c, - [CDSA] = 0xa0, - [CCEN] = 0xbc, - [CCFN] = 0xc0, - [COLOR] = 0xc4, + [CSSA] = { 0x009c, 0x60, OMAP_DMA_REG_32BIT }, + [CDSA] = { 0x00a0, 0x60, OMAP_DMA_REG_32BIT }, + [CCEN] = { 0x00bc, 0x60, OMAP_DMA_REG_32BIT }, + [CCFN] = { 0x00c0, 0x60, OMAP_DMA_REG_32BIT }, + [COLOR] = { 0x00c4, 0x60, OMAP_DMA_REG_32BIT }, /* OMAP4 specific registers */ - [CDP] = 0xd0, - [CNDP] = 0xd4, - [CCDN] = 0xd8, + [CDP] = { 0x00d0, 0x60, OMAP_DMA_REG_32BIT }, + [CNDP] = { 0x00d4, 0x60, OMAP_DMA_REG_32BIT }, + [CCDN] = { 0x00d8, 0x60, OMAP_DMA_REG_32BIT }, }; static void __iomem *dma_base; static inline void dma_write(u32 val, int reg, int lch) { - u8 stride; - u32 offset; + void __iomem *addr = dma_base; + + addr += reg_map[reg].offset; + addr += reg_map[reg].stride * lch; - stride = (reg >= CSDP) ? OMAP2_DMA_STRIDE : 0; - offset = reg_map[reg] + (stride * lch); - __raw_writel(val, dma_base + offset); + __raw_writel(val, addr); } static inline u32 dma_read(int reg, int lch) { - u8 stride; - u32 offset, val; + void __iomem *addr = dma_base; + + addr += reg_map[reg].offset; + addr += reg_map[reg].stride * lch; - stride = (reg >= CSDP) ? OMAP2_DMA_STRIDE : 0; - offset = reg_map[reg] + (stride * lch); - val = __raw_readl(dma_base + offset); - return val; + return __raw_readl(addr); } static void omap2_clear_dma(int lch) diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 0bb7de7..4132872 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h @@ -271,6 +271,19 @@ struct omap_dma_dev_attr { struct omap_dma_lch *chan; }; +enum { + OMAP_DMA_REG_NONE, + OMAP_DMA_REG_16BIT, + OMAP_DMA_REG_2X16BIT, + OMAP_DMA_REG_32BIT, +}; + +struct omap_dma_reg { + u16 offset; + u8 stride; + u8 type; +}; + /* System DMA platform data structure */ struct omap_system_dma_plat_info { struct omap_dma_dev_attr *dma_attr; -- cgit v1.1 From 0ef64986d69602ba8df933c62d0b6d6edfaf0557 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 8 Nov 2013 18:06:37 +0000 Subject: ARM: omap: dma: get rid of errata global There's no need for this to be a global variable; move it into the errata configuration function instead. Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap1/dma.c | 4 ++-- arch/arm/mach-omap2/dma.c | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index b680db7..c979e3f 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c @@ -33,7 +33,6 @@ #define OMAP1_DMA_BASE (0xfffed800) #define OMAP1_LOGICAL_DMA_CH_COUNT 17 -static u32 errata; static u32 enable_1510_mode; static const struct omap_dma_reg reg_map[] = { @@ -244,8 +243,9 @@ static void omap1_show_dma_caps(void) return; } -static u32 configure_dma_errata(void) +static unsigned configure_dma_errata(void) { + unsigned errata = 0; /* * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index e633b48..244ff50 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -35,8 +35,6 @@ #include "omap_hwmod.h" #include "omap_device.h" -static u32 errata; - static struct omap_dma_dev_attr *d; static enum omap_reg_offsets dma_common_ch_end; @@ -124,8 +122,9 @@ static void omap2_show_dma_caps(void) return; } -static u32 configure_dma_errata(void) +static unsigned configure_dma_errata(void) { + unsigned errata = 0; /* * Errata applicable for OMAP2430ES1.0 and all omap2420 -- cgit v1.1 From 9834f81314b2a5b1bb3cd0d8f46e61528b60d580 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 8 Nov 2013 18:10:42 +0000 Subject: ARM: omap: move dma channel allocation into plat-omap code This really needs to be there, because otherwise the plat-omap code can kfree() this data structure, and then re-use the pointer later. Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap1/dma.c | 17 ++--------------- arch/arm/mach-omap2/dma.c | 7 ------- arch/arm/plat-omap/dma.c | 11 ++++++++--- include/linux/omap-dma.h | 1 - 4 files changed, 10 insertions(+), 26 deletions(-) diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index c979e3f..d170f7d 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c @@ -325,17 +325,6 @@ static int __init omap1_system_dma_init(void) d->dev_caps |= CLEAR_CSR_ON_READ; d->dev_caps |= IS_WORD_16; - - d->chan = kzalloc(sizeof(struct omap_dma_lch) * - (d->lch_count), GFP_KERNEL); - if (!d->chan) { - dev_err(&pdev->dev, - "%s: Memory allocation failed for d->chan!\n", - __func__); - ret = -ENOMEM; - goto exit_release_d; - } - if (cpu_is_omap15xx()) d->chan_count = 9; else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { @@ -359,14 +348,14 @@ static int __init omap1_system_dma_init(void) if (ret) { dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", __func__, pdev->name, pdev->id); - goto exit_release_chan; + goto exit_release_d; } ret = platform_device_add(pdev); if (ret) { dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", __func__, pdev->name, pdev->id); - goto exit_release_chan; + goto exit_release_d; } dma_pdev = platform_device_register_full(&omap_dma_dev_info); @@ -379,8 +368,6 @@ static int __init omap1_system_dma_init(void) exit_release_pdev: platform_device_del(pdev); -exit_release_chan: - kfree(d->chan); exit_release_d: kfree(d); exit_release_p: diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index 244ff50..9f210d6 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -251,13 +251,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) } d = oh->dev_attr; - d->chan = kzalloc(sizeof(struct omap_dma_lch) * - (d->lch_count), GFP_KERNEL); - - if (!d->chan) { - dev_err(&pdev->dev, "%s: kzalloc fail\n", __func__); - return -ENOMEM; - } if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) d->dev_caps |= HS_CHANNELS_RESERVED; diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index d4d9a5e..5f5b975 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -2030,9 +2030,16 @@ static int omap_system_dma_probe(struct platform_device *pdev) dma_lch_count = d->lch_count; dma_chan_count = dma_lch_count; - dma_chan = d->chan; enable_1510_mode = d->dev_caps & ENABLE_1510_MODE; + dma_chan = devm_kcalloc(&pdev->dev, dma_lch_count, + sizeof(struct omap_dma_lch), GFP_KERNEL); + if (!dma_chan) { + dev_err(&pdev->dev, "%s: kzalloc fail\n", __func__); + return -ENOMEM; + } + + if (dma_omap2plus()) { dma_linked_lch = kzalloc(sizeof(struct dma_link_info) * dma_lch_count, GFP_KERNEL); @@ -2117,7 +2124,6 @@ exit_dma_irq_fail: } exit_dma_lch_fail: - kfree(dma_chan); return ret; } @@ -2137,7 +2143,6 @@ static int omap_system_dma_remove(struct platform_device *pdev) free_irq(dma_irq, (void *)(irq_rel + 1)); } } - kfree(dma_chan); return 0; } diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 4132872..7813636 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h @@ -268,7 +268,6 @@ struct omap_dma_dev_attr { u32 dev_caps; u16 lch_count; u16 chan_count; - struct omap_dma_lch *chan; }; enum { -- cgit v1.1 From 34a378fcb9273d73dbd6b209952d2f6bf88a3dd0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 8 Nov 2013 18:21:35 +0000 Subject: ARM: omap: dma: get rid of 'p' allocation and clean up The omap_system_dma_plat_info structure is only seven words, it's not worth the expense of kmalloc()'ing backing store for this only to release it later. Note that platform_device_add_data() copies the data anyway. Clean up the initialisation of this structure - we don't even need code to initialise most of this structure. Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap1/dma.c | 36 ++++++++++++++---------------------- arch/arm/mach-omap2/dma.c | 34 +++++++++++++--------------------- 2 files changed, 27 insertions(+), 43 deletions(-) diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index d170f7d..a8c83cc 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c @@ -263,9 +263,17 @@ static const struct platform_device_info omap_dma_dev_info = { .dma_mask = DMA_BIT_MASK(32), }; +static struct omap_system_dma_plat_info dma_plat_info __initdata = { + .show_dma_caps = omap1_show_dma_caps, + .clear_lch_regs = omap1_clear_lch_regs, + .clear_dma = omap1_clear_dma, + .dma_write = dma_write, + .dma_read = dma_read, +}; + static int __init omap1_system_dma_init(void) { - struct omap_system_dma_plat_info *p; + struct omap_system_dma_plat_info p; struct omap_dma_dev_attr *d; struct platform_device *pdev, *dma_pdev; int ret; @@ -291,20 +299,12 @@ static int __init omap1_system_dma_init(void) goto exit_iounmap; } - p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); - if (!p) { - dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n", - __func__, pdev->name); - ret = -ENOMEM; - goto exit_iounmap; - } - d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL); if (!d) { dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n", __func__, pdev->name); ret = -ENOMEM; - goto exit_release_p; + goto exit_iounmap; } d->lch_count = OMAP1_LOGICAL_DMA_CH_COUNT; @@ -334,17 +334,11 @@ static int __init omap1_system_dma_init(void) d->chan_count = 9; } - p->dma_attr = d; - - p->show_dma_caps = omap1_show_dma_caps; - p->clear_lch_regs = omap1_clear_lch_regs; - p->clear_dma = omap1_clear_dma; - p->dma_write = dma_write; - p->dma_read = dma_read; - - p->errata = configure_dma_errata(); + p = dma_plat_info; + p.dma_attr = d; + p.errata = configure_dma_errata(); - ret = platform_device_add_data(pdev, p, sizeof(*p)); + ret = platform_device_add_data(pdev, &p, sizeof(p)); if (ret) { dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", __func__, pdev->name, pdev->id); @@ -370,8 +364,6 @@ exit_release_pdev: platform_device_del(pdev); exit_release_d: kfree(d); -exit_release_p: - kfree(p); exit_iounmap: iounmap(dma_base); exit_device_put: diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index 9f210d6..6331fc4 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -35,8 +35,6 @@ #include "omap_hwmod.h" #include "omap_device.h" -static struct omap_dma_dev_attr *d; - static enum omap_reg_offsets dma_common_ch_end; static const struct omap_dma_reg reg_map[] = { @@ -206,33 +204,27 @@ static unsigned configure_dma_errata(void) return errata; } +static struct omap_system_dma_plat_info dma_plat_info __initdata = { + .show_dma_caps = omap2_show_dma_caps, + .clear_dma = omap2_clear_dma, + .dma_write = dma_write, + .dma_read = dma_read, +}; + /* One time initializations */ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) { struct platform_device *pdev; - struct omap_system_dma_plat_info *p; + struct omap_system_dma_plat_info p; + struct omap_dma_dev_attr *d; struct resource *mem; char *name = "omap_dma_system"; - p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); - if (!p) { - pr_err("%s: Unable to allocate pdata for %s:%s\n", - __func__, name, oh->name); - return -ENOMEM; - } - - p->dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr; - p->show_dma_caps = omap2_show_dma_caps; - p->clear_dma = omap2_clear_dma; - p->dma_write = dma_write; - p->dma_read = dma_read; - - p->clear_lch_regs = NULL; - - p->errata = configure_dma_errata(); + p = dma_plat_info; + p.dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr; + p.errata = configure_dma_errata(); - pdev = omap_device_build(name, 0, oh, p, sizeof(*p)); - kfree(p); + pdev = omap_device_build(name, 0, oh, &p, sizeof(p)); if (IS_ERR(pdev)) { pr_err("%s: Can't build omap_device for %s:%s.\n", __func__, name, oh->name); -- cgit v1.1 From 596c471b69249764d8e241b004736878204daa0f Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 10 Dec 2013 11:08:01 +0000 Subject: dmaengine: omap-dma: move register read/writes into omap-dma.c Export the DMA register information from the SoC specific data, such that we can access the registers directly in omap-dma.c, mapping the register region ourselves as well. Rather than calculating the DMA channel register in its entirety for each access, we pre-calculate an offset base address for the allocated DMA channel and then just use the appropriate register offset. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- arch/arm/mach-omap1/dma.c | 4 ++ arch/arm/mach-omap2/dma.c | 18 ++++++--- drivers/dma/omap-dma.c | 96 ++++++++++++++++++++++++++++++++++++++++++----- include/linux/omap-dma.h | 2 + 4 files changed, 105 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index a8c83cc..4be601b6 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c @@ -261,9 +261,13 @@ static const struct platform_device_info omap_dma_dev_info = { .name = "omap-dma-engine", .id = -1, .dma_mask = DMA_BIT_MASK(32), + .res = res, + .num_res = 1, }; static struct omap_system_dma_plat_info dma_plat_info __initdata = { + .reg_map = reg_map, + .channel_stride = 0x40, .show_dma_caps = omap1_show_dma_caps, .clear_lch_regs = omap1_clear_lch_regs, .clear_dma = omap1_clear_dma, diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index 6331fc4..5689c88 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -205,12 +205,20 @@ static unsigned configure_dma_errata(void) } static struct omap_system_dma_plat_info dma_plat_info __initdata = { + .reg_map = reg_map, + .channel_stride = 0x60, .show_dma_caps = omap2_show_dma_caps, .clear_dma = omap2_clear_dma, .dma_write = dma_write, .dma_read = dma_read, }; +static struct platform_device_info omap_dma_dev_info = { + .name = "omap-dma-engine", + .id = -1, + .dma_mask = DMA_BIT_MASK(32), +}; + /* One time initializations */ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) { @@ -231,11 +239,15 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) return PTR_ERR(pdev); } + omap_dma_dev_info.res = pdev->resource; + omap_dma_dev_info.num_res = pdev->num_resources; + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { dev_err(&pdev->dev, "%s: no mem resource\n", __func__); return -EINVAL; } + dma_base = ioremap(mem->start, resource_size(mem)); if (!dma_base) { dev_err(&pdev->dev, "%s: ioremap fail\n", __func__); @@ -256,12 +268,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) return 0; } -static const struct platform_device_info omap_dma_dev_info = { - .name = "omap-dma-engine", - .id = -1, - .dma_mask = DMA_BIT_MASK(32), -}; - static int __init omap2_system_dma_init(void) { struct platform_device *pdev; diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 1e0018f3..00f8e56 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -27,13 +27,16 @@ struct omap_dmadev { spinlock_t lock; struct tasklet_struct task; struct list_head pending; + void __iomem *base; + const struct omap_dma_reg *reg_map; struct omap_system_dma_plat_info *plat; }; struct omap_chan { struct virt_dma_chan vc; struct list_head node; - struct omap_system_dma_plat_info *plat; + void __iomem *channel_base; + const struct omap_dma_reg *reg_map; struct dma_slave_config cfg; unsigned dma_sig; @@ -170,24 +173,77 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd) kfree(container_of(vd, struct omap_desc, vd)); } +static void omap_dma_write(uint32_t val, unsigned type, void __iomem *addr) +{ + switch (type) { + case OMAP_DMA_REG_16BIT: + writew_relaxed(val, addr); + break; + case OMAP_DMA_REG_2X16BIT: + writew_relaxed(val, addr); + writew_relaxed(val >> 16, addr + 2); + break; + case OMAP_DMA_REG_32BIT: + writel_relaxed(val, addr); + break; + default: + WARN_ON(1); + } +} + +static unsigned omap_dma_read(unsigned type, void __iomem *addr) +{ + unsigned val; + + switch (type) { + case OMAP_DMA_REG_16BIT: + val = readw_relaxed(addr); + break; + case OMAP_DMA_REG_2X16BIT: + val = readw_relaxed(addr); + val |= readw_relaxed(addr + 2) << 16; + break; + case OMAP_DMA_REG_32BIT: + val = readl_relaxed(addr); + break; + default: + WARN_ON(1); + val = 0; + } + + return val; +} + static void omap_dma_glbl_write(struct omap_dmadev *od, unsigned reg, unsigned val) { - od->plat->dma_write(val, reg, 0); + const struct omap_dma_reg *r = od->reg_map + reg; + + WARN_ON(r->stride); + + omap_dma_write(val, r->type, od->base + r->offset); } static unsigned omap_dma_glbl_read(struct omap_dmadev *od, unsigned reg) { - return od->plat->dma_read(reg, 0); + const struct omap_dma_reg *r = od->reg_map + reg; + + WARN_ON(r->stride); + + return omap_dma_read(r->type, od->base + r->offset); } static void omap_dma_chan_write(struct omap_chan *c, unsigned reg, unsigned val) { - c->plat->dma_write(val, reg, c->dma_ch); + const struct omap_dma_reg *r = c->reg_map + reg; + + omap_dma_write(val, r->type, c->channel_base + r->offset); } static unsigned omap_dma_chan_read(struct omap_chan *c, unsigned reg) { - return c->plat->dma_read(reg, c->dma_ch); + const struct omap_dma_reg *r = c->reg_map + reg; + + return omap_dma_read(r->type, c->channel_base + r->offset); } static void omap_dma_clear_csr(struct omap_chan *c) @@ -198,6 +254,12 @@ static void omap_dma_clear_csr(struct omap_chan *c) omap_dma_chan_write(c, CSR, ~0); } +static void omap_dma_assign(struct omap_dmadev *od, struct omap_chan *c, + unsigned lch) +{ + c->channel_base = od->base + od->plat->channel_stride * lch; +} + static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) { struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); @@ -400,18 +462,26 @@ static void omap_dma_sched(unsigned long data) static int omap_dma_alloc_chan_resources(struct dma_chan *chan) { + struct omap_dmadev *od = to_omap_dma_dev(chan->device); struct omap_chan *c = to_omap_dma_chan(chan); + int ret; + + dev_dbg(od->ddev.dev, "allocating channel for %u\n", c->dma_sig); - dev_dbg(c->vc.chan.device->dev, "allocating channel for %u\n", c->dma_sig); + ret = omap_request_dma(c->dma_sig, "DMA engine", omap_dma_callback, + c, &c->dma_ch); - return omap_request_dma(c->dma_sig, "DMA engine", - omap_dma_callback, c, &c->dma_ch); + if (ret >= 0) + omap_dma_assign(od, c, c->dma_ch); + + return ret; } static void omap_dma_free_chan_resources(struct dma_chan *chan) { struct omap_chan *c = to_omap_dma_chan(chan); + c->channel_base = NULL; vchan_free_chan_resources(&c->vc); omap_free_dma(c->dma_ch); @@ -917,7 +987,7 @@ static int omap_dma_chan_init(struct omap_dmadev *od, int dma_sig) if (!c) return -ENOMEM; - c->plat = od->plat; + c->reg_map = od->reg_map; c->dma_sig = dma_sig; c->vc.desc_free = omap_dma_desc_free; vchan_init(&c->vc, &od->ddev); @@ -944,16 +1014,24 @@ static void omap_dma_free(struct omap_dmadev *od) static int omap_dma_probe(struct platform_device *pdev) { struct omap_dmadev *od; + struct resource *res; int rc, i; od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL); if (!od) return -ENOMEM; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + od->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(od->base)) + return PTR_ERR(od->base); + od->plat = omap_get_plat_info(); if (!od->plat) return -EPROBE_DEFER; + od->reg_map = od->plat->reg_map; + dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources; diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 7813636..41a13e7 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h @@ -285,6 +285,8 @@ struct omap_dma_reg { /* System DMA platform data structure */ struct omap_system_dma_plat_info { + const struct omap_dma_reg *reg_map; + unsigned channel_stride; struct omap_dma_dev_attr *dma_attr; u32 errata; void (*show_dma_caps)(void); -- cgit v1.1 From 6ddeb6d844596cac13c4a3665c0bd61f074a81a7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 10 Dec 2013 19:05:50 +0000 Subject: dmaengine: omap-dma: move IRQ handling to omap-dma Move the interrupt handling for OMAP2+ into omap-dma, rather than using the legacy support in the platform code. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 115 insertions(+), 6 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 00f8e56..ec98e71 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -30,6 +30,10 @@ struct omap_dmadev { void __iomem *base; const struct omap_dma_reg *reg_map; struct omap_system_dma_plat_info *plat; + bool legacy; + spinlock_t irq_lock; + uint32_t irq_enable_mask; + struct omap_chan *lch_map[32]; }; struct omap_chan { @@ -254,10 +258,22 @@ static void omap_dma_clear_csr(struct omap_chan *c) omap_dma_chan_write(c, CSR, ~0); } +static unsigned omap_dma_get_csr(struct omap_chan *c) +{ + unsigned val = omap_dma_chan_read(c, CSR); + + if (!dma_omap1()) + omap_dma_chan_write(c, CSR, val); + + return val; +} + static void omap_dma_assign(struct omap_dmadev *od, struct omap_chan *c, unsigned lch) { c->channel_base = od->base + od->plat->channel_stride * lch; + + od->lch_map[lch] = c; } static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) @@ -460,32 +476,103 @@ static void omap_dma_sched(unsigned long data) } } +static irqreturn_t omap_dma_irq(int irq, void *devid) +{ + struct omap_dmadev *od = devid; + unsigned status, channel; + + spin_lock(&od->irq_lock); + + status = omap_dma_glbl_read(od, IRQSTATUS_L1); + status &= od->irq_enable_mask; + if (status == 0) { + spin_unlock(&od->irq_lock); + return IRQ_NONE; + } + + while ((channel = ffs(status)) != 0) { + unsigned mask, csr; + struct omap_chan *c; + + channel -= 1; + mask = BIT(channel); + status &= ~mask; + + c = od->lch_map[channel]; + if (c == NULL) { + /* This should never happen */ + dev_err(od->ddev.dev, "invalid channel %u\n", channel); + continue; + } + + csr = omap_dma_get_csr(c); + omap_dma_glbl_write(od, IRQSTATUS_L1, mask); + + omap_dma_callback(channel, csr, c); + } + + spin_unlock(&od->irq_lock); + + return IRQ_HANDLED; +} + static int omap_dma_alloc_chan_resources(struct dma_chan *chan) { struct omap_dmadev *od = to_omap_dma_dev(chan->device); struct omap_chan *c = to_omap_dma_chan(chan); int ret; - dev_dbg(od->ddev.dev, "allocating channel for %u\n", c->dma_sig); + if (od->legacy) { + ret = omap_request_dma(c->dma_sig, "DMA engine", + omap_dma_callback, c, &c->dma_ch); + } else { + ret = omap_request_dma(c->dma_sig, "DMA engine", NULL, NULL, + &c->dma_ch); + } - ret = omap_request_dma(c->dma_sig, "DMA engine", omap_dma_callback, - c, &c->dma_ch); + dev_dbg(od->ddev.dev, "allocating channel %u for %u\n", + c->dma_ch, c->dma_sig); - if (ret >= 0) + if (ret >= 0) { omap_dma_assign(od, c, c->dma_ch); + if (!od->legacy) { + unsigned val; + + spin_lock_irq(&od->irq_lock); + val = BIT(c->dma_ch); + omap_dma_glbl_write(od, IRQSTATUS_L1, val); + od->irq_enable_mask |= val; + omap_dma_glbl_write(od, IRQENABLE_L1, od->irq_enable_mask); + + val = omap_dma_glbl_read(od, IRQENABLE_L0); + val &= ~BIT(c->dma_ch); + omap_dma_glbl_write(od, IRQENABLE_L0, val); + spin_unlock_irq(&od->irq_lock); + } + } + return ret; } static void omap_dma_free_chan_resources(struct dma_chan *chan) { + struct omap_dmadev *od = to_omap_dma_dev(chan->device); struct omap_chan *c = to_omap_dma_chan(chan); + if (!od->legacy) { + spin_lock_irq(&od->irq_lock); + od->irq_enable_mask &= ~BIT(c->dma_ch); + omap_dma_glbl_write(od, IRQENABLE_L1, od->irq_enable_mask); + spin_unlock_irq(&od->irq_lock); + } + c->channel_base = NULL; + od->lch_map[c->dma_ch] = NULL; vchan_free_chan_resources(&c->vc); omap_free_dma(c->dma_ch); - dev_dbg(c->vc.chan.device->dev, "freeing channel for %u\n", c->dma_sig); + dev_dbg(od->ddev.dev, "freeing channel for %u\n", c->dma_sig); } static size_t omap_dma_sg_size(struct omap_sg *sg) @@ -1015,7 +1102,7 @@ static int omap_dma_probe(struct platform_device *pdev) { struct omap_dmadev *od; struct resource *res; - int rc, i; + int rc, i, irq; od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL); if (!od) @@ -1045,6 +1132,7 @@ static int omap_dma_probe(struct platform_device *pdev) INIT_LIST_HEAD(&od->ddev.channels); INIT_LIST_HEAD(&od->pending); spin_lock_init(&od->lock); + spin_lock_init(&od->irq_lock); tasklet_init(&od->task, omap_dma_sched, (unsigned long)od); @@ -1056,6 +1144,21 @@ static int omap_dma_probe(struct platform_device *pdev) } } + irq = platform_get_irq(pdev, 1); + if (irq <= 0) { + dev_info(&pdev->dev, "failed to get L1 IRQ: %d\n", irq); + od->legacy = true; + } else { + /* Disable all interrupts */ + od->irq_enable_mask = 0; + omap_dma_glbl_write(od, IRQENABLE_L1, 0); + + rc = devm_request_irq(&pdev->dev, irq, omap_dma_irq, + IRQF_SHARED, "omap-dma-engine", od); + if (rc) + return rc; + } + rc = dma_async_device_register(&od->ddev); if (rc) { pr_warn("OMAP-DMA: failed to register slave DMA engine device: %d\n", @@ -1092,6 +1195,12 @@ static int omap_dma_remove(struct platform_device *pdev) of_dma_controller_free(pdev->dev.of_node); dma_async_device_unregister(&od->ddev); + + if (!od->legacy) { + /* Disable all interrupts */ + omap_dma_glbl_write(od, IRQENABLE_L0, 0); + } + omap_dma_free(od); return 0; -- cgit v1.1 From aa4c5b962a7a03eb6b43b3d2677c3677022c1223 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 14 Jan 2014 23:58:10 +0000 Subject: dmaengine: omap-dma: more consolidation of CCR register setup We can move the handling of the DMA synchronisation control out of the prepare functions; this can be pre-calculated when the DMA channel has been allocated, so we don't need to duplicate this in both prepare functions. Acked-by: Tony Lindgren Acked-by: Vinod Koul Signed-off-by: Russell King --- drivers/dma/omap-dma.c | 46 ++++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index ec98e71..64ceca2 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -41,6 +41,7 @@ struct omap_chan { struct list_head node; void __iomem *channel_base; const struct omap_dma_reg *reg_map; + uint32_t ccr; struct dma_slave_config cfg; unsigned dma_sig; @@ -552,6 +553,21 @@ static int omap_dma_alloc_chan_resources(struct dma_chan *chan) } } + if (dma_omap1()) { + if (__dma_omap16xx(od->plat->dma_attr)) { + c->ccr = CCR_OMAP31_DISABLE; + /* Duplicate what plat-omap/dma.c does */ + c->ccr |= c->dma_ch + 1; + } else { + c->ccr = c->dma_sig & 0x1f; + } + } else { + c->ccr = c->dma_sig & 0x1f; + c->ccr |= (c->dma_sig & ~0x1f) << 14; + } + if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) + c->ccr |= CCR_BUFFERING_DISABLE; + return ret; } @@ -787,7 +803,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->dev_addr = dev_addr; d->es = es; - d->ccr = CCR_SYNC_FRAME; + d->ccr = c->ccr | CCR_SYNC_FRAME; if (dir == DMA_DEV_TO_MEM) d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; else @@ -797,14 +813,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->csdp = es; if (dma_omap1()) { - if (__dma_omap16xx(od->plat->dma_attr)) { - d->ccr |= CCR_OMAP31_DISABLE; - /* Duplicate what plat-omap/dma.c does */ - d->ccr |= c->dma_ch + 1; - } else { - d->ccr |= c->dma_sig & 0x1f; - } - d->cicr |= CICR_TOUT_IE; if (dir == DMA_DEV_TO_MEM) @@ -812,16 +820,11 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( else d->csdp |= CSDP_DST_PORT_TIPB | CSDP_SRC_PORT_EMIFF; } else { - d->ccr |= (c->dma_sig & ~0x1f) << 14; - d->ccr |= c->dma_sig & 0x1f; - if (dir == DMA_DEV_TO_MEM) d->ccr |= CCR_TRIGGER_SRC; d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; } - if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) - d->ccr |= CCR_BUFFERING_DISABLE; if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) d->clnk_ctrl = c->dma_ch; @@ -903,7 +906,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->sg[0].fn = buf_len / period_len; d->sglen = 1; - d->ccr = 0; + d->ccr = c->ccr; if (dir == DMA_DEV_TO_MEM) d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; else @@ -916,14 +919,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp = es; if (dma_omap1()) { - if (__dma_omap16xx(od->plat->dma_attr)) { - d->ccr |= CCR_OMAP31_DISABLE; - /* Duplicate what plat-omap/dma.c does */ - d->ccr |= c->dma_ch + 1; - } else { - d->ccr |= c->dma_sig & 0x1f; - } - d->cicr |= CICR_TOUT_IE; if (dir == DMA_DEV_TO_MEM) @@ -931,9 +926,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( else d->csdp |= CSDP_DST_PORT_MPUI | CSDP_SRC_PORT_EMIFF; } else { - d->ccr |= (c->dma_sig & ~0x1f) << 14; - d->ccr |= c->dma_sig & 0x1f; - if (burst) d->ccr |= CCR_SYNC_PACKET; else @@ -946,8 +938,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp |= CSDP_DST_BURST_64 | CSDP_SRC_BURST_64; } - if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) - d->ccr |= CCR_BUFFERING_DISABLE; if (__dma_omap15xx(od->plat->dma_attr)) d->ccr |= CCR_AUTO_INIT | CCR_REPEAT; -- cgit v1.1