From 850b42933e70c19c7765dd7fad15cb7ad3955b65 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 5 Feb 2007 00:55:27 +0100 Subject: [ARM] 4123/1: xsc3: general cleanup This patch cleans up proc-xsc3: - Correct a number of typos. - Fix up indentation in a number of places. - Change references to the various caches to be more clear about whether we're talking about the L1 D, the L1 I or the unified L2 cache. - Rename "drain write buffer" to "data write barrier", the official name used in the Manzano manual. - Change the xsc3 cpu name from "XScale-Core3" to "XScale-V3 based processor". Also, since a previously merged patch implements proper support for using a MAC or iWMMXt coprocessor on xsc3 platforms, we no longer need to enable access to CP0 on boot. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mm/proc-xsc3.S | 151 ++++++++++++++++++++++++------------------------ 1 file changed, 75 insertions(+), 76 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index 94a58455f346..d95921a2ab99 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -5,23 +5,23 @@ * Current Maintainer: Lennert Buytenhek * * Copyright 2004 (C) Intel Corp. - * Copyright 2005 (c) MontaVista Software, Inc. + * Copyright 2005 (C) MontaVista Software, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * MMU functions for the Intel XScale3 Core (XSC3). The XSC3 core is an - * extension to Intel's original XScale core that adds the following + * MMU functions for the Intel XScale3 Core (XSC3). The XSC3 core is + * an extension to Intel's original XScale core that adds the following * features: * * - ARMv6 Supersections * - Low Locality Reference pages (replaces mini-cache) * - 36-bit addressing * - L2 cache - * - Cache-coherency if chipset supports it + * - Cache coherency if chipset supports it * - * Based on orignal XScale code by Nicolas Pitre + * Based on original XScale code by Nicolas Pitre. */ #include @@ -42,12 +42,12 @@ #define MAX_AREA_SIZE 32768 /* - * The cache line size of the I and D cache. + * The cache line size of the L1 I, L1 D and unified L2 cache. */ #define CACHELINESIZE 32 /* - * The size of the data cache. + * The size of the L1 D cache. */ #define CACHESIZE 32768 @@ -57,9 +57,9 @@ #define L2_CACHE_ENABLE 1 /* - * This macro is used to wait for a CP15 write and is needed - * when we have to ensure that the last operation to the co-pro - * was completed before continuing with operation. + * This macro is used to wait for a CP15 write and is needed when we + * have to ensure that the last operation to the coprocessor was + * completed before continuing with operation. */ .macro cpwait_ret, lr, rd mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15 @@ -68,13 +68,13 @@ .endm /* - * This macro cleans & invalidates the entire xsc3 dcache by set & way. + * This macro cleans and invalidates the entire L1 D cache. */ .macro clean_d_cache rd, rs mov \rd, #0x1f00 orr \rd, \rd, #0x00e0 -1: mcr p15, 0, \rd, c7, c14, 2 @ clean/inv set/way +1: mcr p15, 0, \rd, c7, c14, 2 @ clean/invalidate L1 D line adds \rd, \rd, #0x40000000 bcc 1b subs \rd, \rd, #0x20 @@ -119,15 +119,15 @@ ENTRY(cpu_xsc3_reset) mov r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE msr cpsr_c, r1 @ reset CPSR mrc p15, 0, r1, c1, c0, 0 @ ctrl register - bic r1, r1, #0x0086 @ ........B....CA. bic r1, r1, #0x3900 @ ..VIZ..S........ + bic r1, r1, #0x0086 @ ........B....CA. mcr p15, 0, r1, c1, c0, 0 @ ctrl register - mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB + mcr p15, 0, ip, c7, c7, 0 @ invalidate L1 caches and BTB bic r1, r1, #0x0001 @ ...............M mcr p15, 0, r1, c1, c0, 0 @ ctrl register @ CAUTION: MMU turned off from this point. We count on the pipeline @ already containing those two last instructions to survive. - mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mcr p15, 0, ip, c8, c7, 0 @ invalidate I and D TLBs mov pc, r0 /* @@ -139,14 +139,12 @@ ENTRY(cpu_xsc3_reset) * * XScale supports clock switching, but using idle mode support * allows external hardware to react to system state changes. - - MMG: Come back to this one. */ .align 5 ENTRY(cpu_xsc3_do_idle) mov r0, #1 - mcr p14, 0, r0, c7, c0, 0 @ Go to IDLE + mcr p14, 0, r0, c7, c0, 0 @ go to idle mov pc, lr /* ================================= CACHE ================================ */ @@ -171,9 +169,9 @@ ENTRY(xsc3_flush_kern_cache_all) __flush_whole_cache: clean_d_cache r0, r1 tst r2, #VM_EXEC - mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB - mcrne p15, 0, ip, c7, c10, 4 @ Drain Write Buffer - mcrne p15, 0, ip, c7, c5, 4 @ Prefetch Flush + mcrne p15, 0, ip, c7, c5, 0 @ invalidate L1 I cache and BTB + mcrne p15, 0, ip, c7, c10, 4 @ data write barrier + mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush mov pc, lr /* @@ -194,21 +192,21 @@ ENTRY(xsc3_flush_user_cache_range) bhs __flush_whole_cache 1: tst r2, #VM_EXEC - mcrne p15, 0, r0, c7, c5, 1 @ Invalidate I cache line - mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate D cache line + mcrne p15, 0, r0, c7, c5, 1 @ invalidate L1 I line + mcr p15, 0, r0, c7, c14, 1 @ clean/invalidate L1 D line add r0, r0, #CACHELINESIZE cmp r0, r1 blo 1b tst r2, #VM_EXEC - mcrne p15, 0, ip, c7, c5, 6 @ Invalidate BTB - mcrne p15, 0, ip, c7, c10, 4 @ Drain Write Buffer - mcrne p15, 0, ip, c7, c5, 4 @ Prefetch Flush + mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB + mcrne p15, 0, ip, c7, c10, 4 @ data write barrier + mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush mov pc, lr /* * coherent_kern_range(start, end) * - * Ensure coherency between the Icache and the Dcache in the + * Ensure coherency between the I cache and the D cache in the * region described by start. If you have non-snooping * Harvard caches, you need to implement this function. * @@ -222,34 +220,34 @@ ENTRY(xsc3_coherent_kern_range) /* FALLTHROUGH */ ENTRY(xsc3_coherent_user_range) bic r0, r0, #CACHELINESIZE - 1 -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry +1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line add r0, r0, #CACHELINESIZE cmp r0, r1 blo 1b mov r0, #0 - mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB - mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer - mcr p15, 0, r0, c7, c5, 4 @ Prefetch Flush + mcr p15, 0, r0, c7, c5, 0 @ invalidate L1 I cache and BTB + mcr p15, 0, r0, c7, c10, 4 @ data write barrier + mcr p15, 0, r0, c7, c5, 4 @ prefetch flush mov pc, lr /* * flush_kern_dcache_page(void *page) * * Ensure no D cache aliasing occurs, either with itself or - * the I cache + * the I cache. * * - addr - page aligned address */ ENTRY(xsc3_flush_kern_dcache_page) add r1, r0, #PAGE_SZ -1: mcr p15, 0, r0, c7, c14, 1 @ Clean/Invalidate D Cache line +1: mcr p15, 0, r0, c7, c14, 1 @ clean/invalidate L1 D line add r0, r0, #CACHELINESIZE cmp r0, r1 blo 1b mov r0, #0 - mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB - mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer - mcr p15, 0, r0, c7, c5, 4 @ Prefetch Flush + mcr p15, 0, r0, c7, c5, 0 @ invalidate L1 I cache and BTB + mcr p15, 0, r0, c7, c10, 4 @ data write barrier + mcr p15, 0, r0, c7, c5, 4 @ prefetch flush mov pc, lr /* @@ -266,17 +264,17 @@ ENTRY(xsc3_flush_kern_dcache_page) ENTRY(xsc3_dma_inv_range) tst r0, #CACHELINESIZE - 1 bic r0, r0, #CACHELINESIZE - 1 - mcrne p15, 0, r0, c7, c10, 1 @ clean L1 D entry - mcrne p15, 1, r0, c7, c11, 1 @ clean L2 D entry + mcrne p15, 0, r0, c7, c10, 1 @ clean L1 D line + mcrne p15, 1, r0, c7, c11, 1 @ clean L2 line tst r1, #CACHELINESIZE - 1 - mcrne p15, 0, r1, c7, c10, 1 @ clean L1 D entry - mcrne p15, 1, r1, c7, c11, 1 @ clean L2 D entry -1: mcr p15, 0, r0, c7, c6, 1 @ invalidate L1 D entry - mcr p15, 1, r0, c7, c7, 1 @ Invalidate L2 D cache line + mcrne p15, 0, r1, c7, c10, 1 @ clean L1 D line + mcrne p15, 1, r1, c7, c11, 1 @ clean L2 line +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate L1 D line + mcr p15, 1, r0, c7, c7, 1 @ invalidate L2 line add r0, r0, #CACHELINESIZE cmp r0, r1 blo 1b - mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer + mcr p15, 0, r0, c7, c10, 4 @ data write barrier mov pc, lr /* @@ -289,12 +287,12 @@ ENTRY(xsc3_dma_inv_range) */ ENTRY(xsc3_dma_clean_range) bic r0, r0, #CACHELINESIZE - 1 -1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D entry - mcr p15, 1, r0, c7, c11, 1 @ clean L2 D entry +1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line + mcr p15, 1, r0, c7, c11, 1 @ clean L2 line add r0, r0, #CACHELINESIZE cmp r0, r1 blo 1b - mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer + mcr p15, 0, r0, c7, c10, 4 @ data write barrier mov pc, lr /* @@ -307,13 +305,13 @@ ENTRY(xsc3_dma_clean_range) */ ENTRY(xsc3_dma_flush_range) bic r0, r0, #CACHELINESIZE - 1 -1: mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate L1 D cache line - mcr p15, 1, r0, c7, c11, 1 @ Clean L2 D cache line - mcr p15, 1, r0, c7, c7, 1 @ Invalidate L2 D cache line +1: mcr p15, 0, r0, c7, c14, 1 @ clean/invalidate L1 D line + mcr p15, 1, r0, c7, c11, 1 @ clean L2 line + mcr p15, 1, r0, c7, c7, 1 @ invalidate L2 line add r0, r0, #CACHELINESIZE cmp r0, r1 blo 1b - mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer + mcr p15, 0, r0, c7, c10, 4 @ data write barrier mov pc, lr ENTRY(xsc3_cache_fns) @@ -328,7 +326,7 @@ ENTRY(xsc3_cache_fns) .long xsc3_dma_flush_range ENTRY(cpu_xsc3_dcache_clean_area) -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry +1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line add r0, r0, #CACHELINESIZE subs r1, r1, #CACHELINESIZE bhi 1b @@ -346,14 +344,14 @@ ENTRY(cpu_xsc3_dcache_clean_area) .align 5 ENTRY(cpu_xsc3_switch_mm) clean_d_cache r1, r2 - mcr p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB - mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer - mcr p15, 0, ip, c7, c5, 4 @ Prefetch Flush + mcr p15, 0, ip, c7, c5, 0 @ invalidate L1 I cache and BTB + mcr p15, 0, ip, c7, c10, 4 @ data write barrier + mcr p15, 0, ip, c7, c5, 4 @ prefetch flush #ifdef L2_CACHE_ENABLE orr r0, r0, #0x18 @ cache the page table in L2 #endif mcr p15, 0, r0, c2, c0, 0 @ load page table pointer - mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mcr p15, 0, ip, c8, c7, 0 @ invalidate I and D TLBs cpwait_ret lr, ip /* @@ -366,34 +364,34 @@ ENTRY(cpu_xsc3_switch_mm) ENTRY(cpu_xsc3_set_pte_ext) str r1, [r0], #-2048 @ linux version - bic r2, r1, #0xff0 @ Keep C, B bits + bic r2, r1, #0xff0 @ keep C, B bits orr r2, r2, #PTE_TYPE_EXT @ extended page - tst r1, #L_PTE_SHARED @ Shared? + tst r1, #L_PTE_SHARED @ shared? orrne r2, r2, #0x200 eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY - tst r3, #L_PTE_USER @ User? + tst r3, #L_PTE_USER @ user? orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w - tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty? + tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ write and dirty? orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w @ combined with user -> user r/w #if L2_CACHE_ENABLE - @ If its cacheable it needs to be in L2 also. + @ If it's cacheable, it needs to be in L2 also. eor ip, r1, #L_PTE_CACHEABLE tst ip, #L_PTE_CACHEABLE orreq r2, r2, #PTE_EXT_TEX(0x5) #endif - tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young? + tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? movne r2, #0 @ no -> fault str r2, [r0] @ hardware version mov ip, #0 - mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line mcr - mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer + mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line + mcr p15, 0, ip, c7, c10, 4 @ data write barrier mov pc, lr .ltorg @@ -406,17 +404,18 @@ ENTRY(cpu_xsc3_set_pte_ext) __xsc3_setup: mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE msr cpsr_c, r0 - mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB - mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer - mcr p15, 0, ip, c7, c5, 4 @ Prefetch Flush - mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs + mcr p15, 0, ip, c7, c7, 0 @ invalidate L1 caches and BTB + mcr p15, 0, ip, c7, c10, 4 @ data write barrier + mcr p15, 0, ip, c7, c5, 4 @ prefetch flush + mcr p15, 0, ip, c8, c7, 0 @ invalidate I and D TLBs #if L2_CACHE_ENABLE orr r4, r4, #0x18 @ cache the page table in L2 #endif mcr p15, 0, r4, c2, c0, 0 @ load page table pointer - mov r0, #1 @ Allow access to CP0 and CP13 - orr r0, r0, #1 << 13 @ Its undefined whether this - mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes + + mov r0, #0 @ don't allow CP access + mcr p15, 0, r0, c15, c1, 0 @ write CP access register + mrc p15, 0, r0, c1, c0, 1 @ get auxiliary control reg and r0, r0, #2 @ preserve bit P bit setting #if L2_CACHE_ENABLE @@ -427,9 +426,9 @@ __xsc3_setup: adr r5, xsc3_crval ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0, 0 @ get control register - bic r0, r0, r5 @ .... .... .... ..A. - orr r0, r0, r6 @ .... .... .... .C.M - orr r0, r0, #0x00000800 @ ..VI Z..S .... .... + bic r0, r0, r5 @ ..V. ..R. .... ..A. + orr r0, r0, r6 @ ..VI Z..S .... .C.M (mmu) + @ ...I Z..S .... .... (uc) #if L2_CACHE_ENABLE orr r0, r0, #0x04000000 @ L2 enable #endif @@ -439,7 +438,7 @@ __xsc3_setup: .type xsc3_crval, #object xsc3_crval: - crval clear=0x04003b02, mmuset=0x00003105, ucset=0x00001100 + crval clear=0x04002202, mmuset=0x00003905, ucset=0x00001900 __INITDATA @@ -474,7 +473,7 @@ cpu_elf_name: .type cpu_xsc3_name, #object cpu_xsc3_name: - .asciz "XScale-Core3" + .asciz "XScale-V3 based processor" .size cpu_xsc3_name, . - cpu_xsc3_name .align @@ -490,7 +489,7 @@ __xsc3_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ - .long PMD_TYPE_SECT | \ + .long PMD_TYPE_SECT | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ b __xsc3_setup -- cgit v1.2.3 From 9d99df4b10eef130dacb5f772cd589c625b03634 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 5 Feb 2007 14:47:40 +0100 Subject: [ARM] 4128/1: Architecture compliant TTBR changing sequence On newer architectures (ARMv6, ARMv7), the depth of the prefetch and branch prediction is implementation defined and there is a small risk of wrong ASID tagging when changing TTBR0 before setting the new context id. The recommended solution is to set a reserved ASID during TTBR changing. This patch reserves ASID 0. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mm/context.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 79e800202424..9da43a0fdcdf 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -19,7 +19,8 @@ unsigned int cpu_last_asid = { 1 << ASID_BITS }; /* * We fork()ed a process, and we need a new context for the child * to run in. We reserve version 0 for initial tasks so we will - * always allocate an ASID. + * always allocate an ASID. The ASID 0 is reserved for the TTBR + * register changing sequence. */ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) { @@ -38,8 +39,15 @@ void __new_context(struct mm_struct *mm) * If we've used up all our ASIDs, we need * to start a new version and flush the TLB. */ - if ((asid & ~ASID_MASK) == 0) + if ((asid & ~ASID_MASK) == 0) { + asid = ++cpu_last_asid; + /* set the reserved ASID before flushing the TLB */ + asm("mcr p15, 0, %0, c13, c0, 1 @ set reserved context ID\n" + : + : "r" (0)); + isb(); flush_tlb_all(); + } mm->context.id = asid; } -- cgit v1.2.3 From e6a5d66f58431c66c79e236f722a5ad7dd959ef3 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 5 Feb 2007 14:47:51 +0100 Subject: [ARM] 4129/1: Add barriers after the TLB operations The architecture specification states that TLB operations are guaranteed to be complete only after the execution of a DSB (Data Synchronisation Barrier, former Data Write Barrier or Drain Write Buffer). The branch target cache invalidation is also needed. The ISB (Instruction Synchronisation Barrier, formerly Prefetch Flush) is needed unless there will be a return from exception before the corresponding mapping is used (i.e. user mappings). Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mm/tlb-v6.S | 4 ++++ include/asm-arm/tlbflush.h | 50 +++++++++++++++++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 12 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S index fd6adde39091..20f84bbaa9bb 100644 --- a/arch/arm/mm/tlb-v6.S +++ b/arch/arm/mm/tlb-v6.S @@ -53,6 +53,8 @@ ENTRY(v6wbi_flush_user_tlb_range) add r0, r0, #PAGE_SZ cmp r0, r1 blo 1b + mcr p15, 0, ip, c7, c5, 6 @ flush BTAC/BTB + mcr p15, 0, ip, c7, c10, 4 @ data synchronization barrier mov pc, lr /* @@ -80,7 +82,9 @@ ENTRY(v6wbi_flush_kern_tlb_range) add r0, r0, #PAGE_SZ cmp r0, r1 blo 1b + mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB mcr p15, 0, r2, c7, c10, 4 @ data synchronization barrier + mcr p15, 0, r2, c7, c5, 4 @ prefetch flush mov pc, lr .section ".text.init", #alloc, #execinstr diff --git a/include/asm-arm/tlbflush.h b/include/asm-arm/tlbflush.h index cd10a0b5f8ae..08c6991dc9c9 100644 --- a/include/asm-arm/tlbflush.h +++ b/include/asm-arm/tlbflush.h @@ -247,7 +247,7 @@ static inline void local_flush_tlb_all(void) const unsigned int __tlb_flag = __cpu_tlb_flags; if (tlb_flag(TLB_WB)) - asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc"); + dsb(); if (tlb_flag(TLB_V3_FULL)) asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc"); @@ -257,6 +257,15 @@ static inline void local_flush_tlb_all(void) asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc"); if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL)) asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc"); + + if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | + TLB_V6_I_PAGE | TLB_V6_D_PAGE | + TLB_V6_I_ASID | TLB_V6_D_ASID)) { + /* flush the branch target cache */ + asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); + dsb(); + isb(); + } } static inline void local_flush_tlb_mm(struct mm_struct *mm) @@ -266,7 +275,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm) const unsigned int __tlb_flag = __cpu_tlb_flags; if (tlb_flag(TLB_WB)) - asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc"); + dsb(); if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) { if (tlb_flag(TLB_V3_FULL)) @@ -285,6 +294,14 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm) asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc"); if (tlb_flag(TLB_V6_I_ASID)) asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc"); + + if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | + TLB_V6_I_PAGE | TLB_V6_D_PAGE | + TLB_V6_I_ASID | TLB_V6_D_ASID)) { + /* flush the branch target cache */ + asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); + dsb(); + } } static inline void @@ -296,7 +313,7 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm); if (tlb_flag(TLB_WB)) - asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero)); + dsb(); if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) { if (tlb_flag(TLB_V3_PAGE)) @@ -317,6 +334,14 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc"); if (tlb_flag(TLB_V6_I_PAGE)) asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc"); + + if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | + TLB_V6_I_PAGE | TLB_V6_D_PAGE | + TLB_V6_I_ASID | TLB_V6_D_ASID)) { + /* flush the branch target cache */ + asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); + dsb(); + } } static inline void local_flush_tlb_kernel_page(unsigned long kaddr) @@ -327,7 +352,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr) kaddr &= PAGE_MASK; if (tlb_flag(TLB_WB)) - asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc"); + dsb(); if (tlb_flag(TLB_V3_PAGE)) asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (kaddr) : "cc"); @@ -347,11 +372,14 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr) if (tlb_flag(TLB_V6_I_PAGE)) asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc"); - /* The ARM ARM states that the completion of a TLB maintenance - * operation is only guaranteed by a DSB instruction - */ - if (tlb_flag(TLB_V6_U_PAGE | TLB_V6_D_PAGE | TLB_V6_I_PAGE)) - asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc"); + if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | + TLB_V6_I_PAGE | TLB_V6_D_PAGE | + TLB_V6_I_ASID | TLB_V6_D_ASID)) { + /* flush the branch target cache */ + asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); + dsb(); + isb(); + } } /* @@ -369,15 +397,13 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr) */ static inline void flush_pmd_entry(pmd_t *pmd) { - const unsigned int zero = 0; const unsigned int __tlb_flag = __cpu_tlb_flags; if (tlb_flag(TLB_DCLEAN)) asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pmd" : : "r" (pmd) : "cc"); if (tlb_flag(TLB_WB)) - asm("mcr p15, 0, %0, c7, c10, 4 @ flush_pmd" - : : "r" (zero) : "cc"); + dsb(); } static inline void clean_pmd_entry(pmd_t *pmd) -- cgit v1.2.3 From 953233dc9958ba2b29753d0f24e37a33a076a5f6 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 5 Feb 2007 14:48:08 +0100 Subject: [ARM] 4134/1: Add generic support for outer caches The outer cache can be L2 as on RealView/EB MPCore platform or even L3 or further on ARMv7 cores. This patch adds the generic support for flushing the outer cache in the DMA operations. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/common/dmabounce.c | 1 + arch/arm/kernel/setup.c | 3 +++ arch/arm/mm/Kconfig | 3 +++ arch/arm/mm/consistent.c | 6 ++++++ include/asm-arm/cacheflush.h | 37 +++++++++++++++++++++++++++++++++++++ 5 files changed, 50 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 272702accd8b..b4748e3171c6 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -338,6 +338,7 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, */ ptr = (unsigned long)buf->ptr; dmac_clean_range(ptr, ptr + size); + outer_clean_range(__pa(ptr), __pa(ptr) + size); } free_safe_buffer(device_info, buf); } diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index bbab134cd82d..243aea458057 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -88,6 +88,9 @@ struct cpu_user_fns cpu_user; #ifdef MULTI_CACHE struct cpu_cache_fns cpu_cache; #endif +#ifdef CONFIG_OUTER_CACHE +struct outer_cache_fns outer_cache; +#endif struct stack { u32 irq[3]; diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index aade2f72c920..a84eed9f8542 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -609,3 +609,6 @@ config NEEDS_SYSCALL_FOR_CMPXCHG Forget about fast user space cmpxchg support. It is just not possible. +config OUTER_CACHE + bool + default n diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index 6a9c362fef5e..83bd035c7d5e 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -208,6 +208,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, unsigned long kaddr = (unsigned long)page_address(page); memset(page_address(page), 0, size); dmac_flush_range(kaddr, kaddr + size); + outer_flush_range(__pa(kaddr), __pa(kaddr) + size); } /* @@ -485,15 +486,20 @@ void consistent_sync(void *vaddr, size_t size, int direction) unsigned long start = (unsigned long)vaddr; unsigned long end = start + size; + BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end)); + switch (direction) { case DMA_FROM_DEVICE: /* invalidate only */ dmac_inv_range(start, end); + outer_inv_range(__pa(start), __pa(end)); break; case DMA_TO_DEVICE: /* writeback only */ dmac_clean_range(start, end); + outer_clean_range(__pa(start), __pa(end)); break; case DMA_BIDIRECTIONAL: /* writeback and invalidate */ dmac_flush_range(start, end); + outer_flush_range(__pa(start), __pa(end)); break; default: BUG(); diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index 5f531ea03059..ce60b3702ba5 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h @@ -190,6 +190,12 @@ struct cpu_cache_fns { void (*dma_flush_range)(unsigned long, unsigned long); }; +struct outer_cache_fns { + void (*inv_range)(unsigned long, unsigned long); + void (*clean_range)(unsigned long, unsigned long); + void (*flush_range)(unsigned long, unsigned long); +}; + /* * Select the calling method */ @@ -246,6 +252,37 @@ extern void dmac_flush_range(unsigned long, unsigned long); #endif +#ifdef CONFIG_OUTER_CACHE + +extern struct outer_cache_fns outer_cache; + +static inline void outer_inv_range(unsigned long start, unsigned long end) +{ + if (outer_cache.inv_range) + outer_cache.inv_range(start, end); +} +static inline void outer_clean_range(unsigned long start, unsigned long end) +{ + if (outer_cache.clean_range) + outer_cache.clean_range(start, end); +} +static inline void outer_flush_range(unsigned long start, unsigned long end) +{ + if (outer_cache.flush_range) + outer_cache.flush_range(start, end); +} + +#else + +static inline void outer_inv_range(unsigned long start, unsigned long end) +{ } +static inline void outer_clean_range(unsigned long start, unsigned long end) +{ } +static inline void outer_flush_range(unsigned long start, unsigned long end) +{ } + +#endif + /* * flush_cache_vmap() is used when creating mappings (eg, via vmap, * vmalloc, ioremap etc) in kernel space for pages. Since the -- cgit v1.2.3 From 7ae5a761d2ffc4cf7d3248e09f4d3da234434f30 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 6 Feb 2007 17:39:31 +0000 Subject: [ARM] Convert DMA cache handling to take const void * args The DMA cache handling functions take virtual addresses, but in the form of unsigned long arguments. This leads to a little confusion about what exactly they take. So, convert them to take const void * instead. Signed-off-by: Russell King --- arch/arm/common/dmabounce.c | 7 +++---- arch/arm/mm/consistent.c | 13 ++++++------- include/asm-arm/cacheflush.h | 12 ++++++------ include/asm-arm/dma-mapping.h | 2 +- 4 files changed, 16 insertions(+), 18 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index b4748e3171c6..2362c498f52e 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -321,12 +321,12 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, DO_STATS ( device_info->bounce_count++ ); if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) { - unsigned long ptr; + void *ptr = buf->ptr; dev_dbg(dev, "%s: copy back safe %p to unsafe %p size %d\n", - __func__, buf->safe, buf->ptr, size); - memcpy(buf->ptr, buf->safe, size); + __func__, buf->safe, ptr, size); + memcpy(ptr, buf->safe, size); /* * DMA buffers must have the same cache properties @@ -336,7 +336,6 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, * bidirectional case because we know the cache * lines will be coherent with the data written. */ - ptr = (unsigned long)buf->ptr; dmac_clean_range(ptr, ptr + size); outer_clean_range(__pa(ptr), __pa(ptr) + size); } diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index 83bd035c7d5e..166aee13c4b1 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -205,10 +205,10 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, * kernel direct-mapped region for device DMA. */ { - unsigned long kaddr = (unsigned long)page_address(page); - memset(page_address(page), 0, size); - dmac_flush_range(kaddr, kaddr + size); - outer_flush_range(__pa(kaddr), __pa(kaddr) + size); + void *ptr = page_address(page); + memset(ptr, 0, size); + dmac_flush_range(ptr, ptr + size); + outer_flush_range(__pa(ptr), __pa(ptr) + size); } /* @@ -481,10 +481,9 @@ core_initcall(consistent_init); * platforms with CONFIG_DMABOUNCE. * Use the driver DMA support - see dma-mapping.h (dma_sync_*) */ -void consistent_sync(void *vaddr, size_t size, int direction) +void consistent_sync(const void *start, size_t size, int direction) { - unsigned long start = (unsigned long)vaddr; - unsigned long end = start + size; + const void *end = start + size; BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end)); diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index ce60b3702ba5..afad32c76e6c 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h @@ -185,9 +185,9 @@ struct cpu_cache_fns { void (*coherent_user_range)(unsigned long, unsigned long); void (*flush_kern_dcache_page)(void *); - void (*dma_inv_range)(unsigned long, unsigned long); - void (*dma_clean_range)(unsigned long, unsigned long); - void (*dma_flush_range)(unsigned long, unsigned long); + void (*dma_inv_range)(const void *, const void *); + void (*dma_clean_range)(const void *, const void *); + void (*dma_flush_range)(const void *, const void *); }; struct outer_cache_fns { @@ -246,9 +246,9 @@ extern void __cpuc_flush_dcache_page(void *); #define dmac_clean_range __glue(_CACHE,_dma_clean_range) #define dmac_flush_range __glue(_CACHE,_dma_flush_range) -extern void dmac_inv_range(unsigned long, unsigned long); -extern void dmac_clean_range(unsigned long, unsigned long); -extern void dmac_flush_range(unsigned long, unsigned long); +extern void dmac_inv_range(const void *, const void *); +extern void dmac_clean_range(const void *, const void *); +extern void dmac_flush_range(const void *, const void *); #endif diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h index 9bc46b486afb..a1d574cdcc14 100644 --- a/include/asm-arm/dma-mapping.h +++ b/include/asm-arm/dma-mapping.h @@ -17,7 +17,7 @@ * platforms with CONFIG_DMABOUNCE. * Use the driver DMA support - see dma-mapping.h (dma_sync_*) */ -extern void consistent_sync(void *kaddr, size_t size, int rw); +extern void consistent_sync(const void *kaddr, size_t size, int rw); /* * Return whether the given device DMA address mask can be supported -- cgit v1.2.3 From b2c6561605da4802886cafe96432b8e2968e9edc Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 8 Feb 2007 09:42:40 +0100 Subject: [ARM] 4145/2: AT91: Add support for AT91SAM9263 processor Add support for the Atmel AT91SAM9263 processor. It is similar to the AT91SAM9260 but with more integrated peripherals, 5 GPIO banks, etc. Original patch from Nicolas Ferre. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91/Kconfig | 3 + arch/arm/mach-at91/Makefile | 1 + arch/arm/mach-at91/at91sam9263.c | 313 ++++++++++ arch/arm/mach-at91/at91sam9263_devices.c | 818 +++++++++++++++++++++++++ arch/arm/mach-at91/clock.c | 2 +- arch/arm/mach-at91/generic.h | 2 + arch/arm/mach-at91/pm.c | 2 + arch/arm/mm/Kconfig | 4 +- drivers/usb/gadget/at91_udc.c | 4 +- include/asm-arm/arch-at91/at91sam9263.h | 131 ++++ include/asm-arm/arch-at91/at91sam9263_matrix.h | 129 ++++ include/asm-arm/arch-at91/at91sam926x_mc.h | 7 + include/asm-arm/arch-at91/cpu.h | 7 + include/asm-arm/arch-at91/hardware.h | 2 + include/asm-arm/arch-at91/timex.h | 5 + 15 files changed, 1425 insertions(+), 5 deletions(-) create mode 100644 arch/arm/mach-at91/at91sam9263.c create mode 100644 arch/arm/mach-at91/at91sam9263_devices.c create mode 100644 include/asm-arm/arch-at91/at91sam9263.h create mode 100644 include/asm-arm/arch-at91/at91sam9263_matrix.h (limited to 'arch/arm/mm') diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 9f11db8af233..2499385e22da 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -14,6 +14,9 @@ config ARCH_AT91SAM9260 config ARCH_AT91SAM9261 bool "AT91SAM9261" +config ARCH_AT91SAM9263 + bool "AT91SAM9263" + endchoice # ---------------------------------------------------------- diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index cf777007847a..2fd4cd4a57f8 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o +obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o # AT91RM9200 board-specific support obj-$(CONFIG_MACH_ONEARM) += board-1arm.o diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c new file mode 100644 index 000000000000..fae6a821a61b --- /dev/null +++ b/arch/arm/mach-at91/at91sam9263.c @@ -0,0 +1,313 @@ +/* + * arch/arm/mach-at91/at91sam9263.c + * + * Copyright (C) 2007 Atmel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include + +#include +#include +#include +#include +#include + +#include "generic.h" +#include "clock.h" + +static struct map_desc at91sam9263_io_desc[] __initdata = { + { + .virtual = AT91_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91_BASE_SYS), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE, + .pfn = __phys_to_pfn(AT91SAM9263_SRAM0_BASE), + .length = AT91SAM9263_SRAM0_SIZE, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE - AT91SAM9263_SRAM1_SIZE, + .pfn = __phys_to_pfn(AT91SAM9263_SRAM1_BASE), + .length = AT91SAM9263_SRAM1_SIZE, + .type = MT_DEVICE, + }, +}; + +/* -------------------------------------------------------------------- + * Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioA_clk = { + .name = "pioA_clk", + .pmc_mask = 1 << AT91SAM9263_ID_PIOA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .pmc_mask = 1 << AT91SAM9263_ID_PIOB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioCDE_clk = { + .name = "pioCDE_clk", + .pmc_mask = 1 << AT91SAM9263_ID_PIOCDE, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { + .name = "usart0_clk", + .pmc_mask = 1 << AT91SAM9263_ID_US0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { + .name = "usart1_clk", + .pmc_mask = 1 << AT91SAM9263_ID_US1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { + .name = "usart2_clk", + .pmc_mask = 1 << AT91SAM9263_ID_US2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc0_clk = { + .name = "mci0_clk", + .pmc_mask = 1 << AT91SAM9263_ID_MCI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc1_clk = { + .name = "mci1_clk", + .pmc_mask = 1 << AT91SAM9263_ID_MCI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi_clk = { + .name = "twi_clk", + .pmc_mask = 1 << AT91SAM9263_ID_TWI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { + .name = "spi0_clk", + .pmc_mask = 1 << AT91SAM9263_ID_SPI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { + .name = "spi1_clk", + .pmc_mask = 1 << AT91SAM9263_ID_SPI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk tcb_clk = { + .name = "tcb_clk", + .pmc_mask = 1 << AT91SAM9263_ID_TCB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ether_clk = { + .name = "ether_clk", + .pmc_mask = 1 << AT91SAM9263_ID_EMAC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk udc_clk = { + .name = "udc_clk", + .pmc_mask = 1 << AT91SAM9263_ID_UDP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk isi_clk = { + .name = "isi_clk", + .pmc_mask = 1 << AT91SAM9263_ID_ISI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk lcdc_clk = { + .name = "lcdc_clk", + .pmc_mask = 1 << AT91SAM9263_ID_ISI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ohci_clk = { + .name = "ohci_clk", + .pmc_mask = 1 << AT91SAM9263_ID_UHP, + .type = CLK_TYPE_PERIPHERAL, +}; + +static struct clk *periph_clocks[] __initdata = { + &pioA_clk, + &pioB_clk, + &pioCDE_clk, + &usart0_clk, + &usart1_clk, + &usart2_clk, + &mmc0_clk, + &mmc1_clk, + // can + &twi_clk, + &spi0_clk, + &spi1_clk, + // ssc0 .. ssc1 + // ac97 + &tcb_clk, + // pwmc + ðer_clk, + // 2dge + &udc_clk, + &isi_clk, + &lcdc_clk, + // dma + &ohci_clk, + // irq0 .. irq1 +}; + +/* + * The four programmable clocks. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { + .name = "pck0", + .pmc_mask = AT91_PMC_PCK0, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 0, +}; +static struct clk pck1 = { + .name = "pck1", + .pmc_mask = AT91_PMC_PCK1, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 1, +}; +static struct clk pck2 = { + .name = "pck2", + .pmc_mask = AT91_PMC_PCK2, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 2, +}; +static struct clk pck3 = { + .name = "pck3", + .pmc_mask = AT91_PMC_PCK3, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 3, +}; + +static void __init at91sam9263_register_clocks(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) + clk_register(periph_clocks[i]); + + clk_register(&pck0); + clk_register(&pck1); + clk_register(&pck2); + clk_register(&pck3); +} + +/* -------------------------------------------------------------------- + * GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at91sam9263_gpio[] = { + { + .id = AT91SAM9263_ID_PIOA, + .offset = AT91_PIOA, + .clock = &pioA_clk, + }, { + .id = AT91SAM9263_ID_PIOB, + .offset = AT91_PIOB, + .clock = &pioB_clk, + }, { + .id = AT91SAM9263_ID_PIOCDE, + .offset = AT91_PIOC, + .clock = &pioCDE_clk, + }, { + .id = AT91SAM9263_ID_PIOCDE, + .offset = AT91_PIOD, + .clock = &pioCDE_clk, + }, { + .id = AT91SAM9263_ID_PIOCDE, + .offset = AT91_PIOE, + .clock = &pioCDE_clk, + } +}; + +static void at91sam9263_reset(void) +{ + at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); +} + + +/* -------------------------------------------------------------------- + * AT91SAM9263 processor initialization + * -------------------------------------------------------------------- */ + +void __init at91sam9263_initialize(unsigned long main_clock) +{ + /* Map peripherals */ + iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc)); + + at91_arch_reset = at91sam9263_reset; + at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1); + + /* Init clock subsystem */ + at91_clock_init(main_clock); + + /* Register the processor-specific clocks */ + at91sam9263_register_clocks(); + + /* Register GPIO subsystem */ + at91_gpio_init(at91sam9263_gpio, 5); +} + +/* -------------------------------------------------------------------- + * Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller (FIQ) */ + 7, /* System Peripherals */ + 0, /* Parallel IO Controller A */ + 0, /* Parallel IO Controller B */ + 0, /* Parallel IO Controller C, D and E */ + 0, + 0, + 6, /* USART 0 */ + 6, /* USART 1 */ + 6, /* USART 2 */ + 0, /* Multimedia Card Interface 0 */ + 0, /* Multimedia Card Interface 1 */ + 4, /* CAN */ + 0, /* Two-Wire Interface */ + 6, /* Serial Peripheral Interface 0 */ + 6, /* Serial Peripheral Interface 1 */ + 5, /* Serial Synchronous Controller 0 */ + 5, /* Serial Synchronous Controller 1 */ + 6, /* AC97 Controller */ + 0, /* Timer Counter 0, 1 and 2 */ + 0, /* Pulse Width Modulation Controller */ + 3, /* Ethernet */ + 0, + 0, /* 2D Graphic Engine */ + 3, /* USB Device Port */ + 0, /* Image Sensor Interface */ + 3, /* LDC Controller */ + 0, /* DMA Controller */ + 0, + 3, /* USB Host port */ + 0, /* Advanced Interrupt Controller (IRQ0) */ + 0, /* Advanced Interrupt Controller (IRQ1) */ +}; + +void __init at91sam9263_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ + if (!priority) + priority = at91sam9263_default_irq_priority; + + /* Initialize the AIC interrupt controller */ + at91_aic_init(priority); + + /* Enable GPIO interrupts */ + at91_gpio_irq_setup(); +} diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c new file mode 100644 index 000000000000..d9af7ca58bce --- /dev/null +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -0,0 +1,818 @@ +/* + * arch/arm/mach-at91/at91sam9263_devices.c + * + * Copyright (C) 2007 Atmel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "generic.h" + +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 + +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = 0xffffffffUL; +static struct at91_usbh_data usbh_data; + +static struct resource usbh_resources[] = { + [0] = { + .start = AT91SAM9263_UHP_BASE, + .end = AT91SAM9263_UHP_BASE + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_UHP, + .end = AT91SAM9263_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91_usbh_device = { + .name = "at91_ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbh_data, + }, + .resource = usbh_resources, + .num_resources = ARRAY_SIZE(usbh_resources), +}; + +void __init at91_add_device_usbh(struct at91_usbh_data *data) +{ + int i; + + if (!data) + return; + + /* Enable VBus control for UHP ports */ + for (i = 0; i < data->ports; i++) { + if (data->vbus_pin[i]) + at91_set_gpio_output(data->vbus_pin[i], 0); + } + + usbh_data = *data; + platform_device_register(&at91_usbh_device); +} +#else +void __init at91_add_device_usbh(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * USB Device (Gadget) + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_GADGET_AT91 +static struct at91_udc_data udc_data; + +static struct resource udc_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_UDP, + .end = AT91SAM9263_BASE_UDP + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_UDP, + .end = AT91SAM9263_ID_UDP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91_udc_device = { + .name = "at91_udc", + .id = -1, + .dev = { + .platform_data = &udc_data, + }, + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), +}; + +void __init at91_add_device_udc(struct at91_udc_data *data) +{ + if (!data) + return; + + if (data->vbus_pin) { + at91_set_gpio_input(data->vbus_pin, 0); + at91_set_deglitch(data->vbus_pin, 1); + } + + /* Pullup pin is handled internally by USB device peripheral */ + + udc_data = *data; + platform_device_register(&at91_udc_device); +} +#else +void __init at91_add_device_udc(struct at91_udc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * Ethernet + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) +static u64 eth_dmamask = 0xffffffffUL; +static struct at91_eth_data eth_data; + +static struct resource eth_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_EMAC, + .end = AT91SAM9263_BASE_EMAC + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_EMAC, + .end = AT91SAM9263_ID_EMAC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_eth_device = { + .name = "macb", + .id = -1, + .dev = { + .dma_mask = ð_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = ð_data, + }, + .resource = eth_resources, + .num_resources = ARRAY_SIZE(eth_resources), +}; + +void __init at91_add_device_eth(struct at91_eth_data *data) +{ + if (!data) + return; + + if (data->phy_irq_pin) { + at91_set_gpio_input(data->phy_irq_pin, 0); + at91_set_deglitch(data->phy_irq_pin, 1); + } + + /* Pins used for MII and RMII */ + at91_set_A_periph(AT91_PIN_PE21, 0); /* ETXCK_EREFCK */ + at91_set_B_periph(AT91_PIN_PC25, 0); /* ERXDV */ + at91_set_A_periph(AT91_PIN_PE25, 0); /* ERX0 */ + at91_set_A_periph(AT91_PIN_PE26, 0); /* ERX1 */ + at91_set_A_periph(AT91_PIN_PE27, 0); /* ERXER */ + at91_set_A_periph(AT91_PIN_PE28, 0); /* ETXEN */ + at91_set_A_periph(AT91_PIN_PE23, 0); /* ETX0 */ + at91_set_A_periph(AT91_PIN_PE24, 0); /* ETX1 */ + at91_set_A_periph(AT91_PIN_PE30, 0); /* EMDIO */ + at91_set_A_periph(AT91_PIN_PE29, 0); /* EMDC */ + + if (!data->is_rmii) { + at91_set_A_periph(AT91_PIN_PE22, 0); /* ECRS */ + at91_set_B_periph(AT91_PIN_PC26, 0); /* ECOL */ + at91_set_B_periph(AT91_PIN_PC22, 0); /* ERX2 */ + at91_set_B_periph(AT91_PIN_PC23, 0); /* ERX3 */ + at91_set_B_periph(AT91_PIN_PC27, 0); /* ERXCK */ + at91_set_B_periph(AT91_PIN_PC20, 0); /* ETX2 */ + at91_set_B_periph(AT91_PIN_PC21, 0); /* ETX3 */ + at91_set_B_periph(AT91_PIN_PC24, 0); /* ETXER */ + } + + eth_data = *data; + platform_device_register(&at91sam9263_eth_device); +} +#else +void __init at91_add_device_eth(struct at91_eth_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * MMC / SD + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) +static u64 mmc_dmamask = 0xffffffffUL; +static struct at91_mmc_data mmc0_data, mmc1_data; + +static struct resource mmc0_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_MCI0, + .end = AT91SAM9263_BASE_MCI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_MCI0, + .end = AT91SAM9263_ID_MCI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_mmc0_device = { + .name = "at91_mci", + .id = 0, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &mmc0_data, + }, + .resource = mmc0_resources, + .num_resources = ARRAY_SIZE(mmc0_resources), +}; + +static struct resource mmc1_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_MCI1, + .end = AT91SAM9263_BASE_MCI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_MCI1, + .end = AT91SAM9263_ID_MCI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_mmc1_device = { + .name = "at91_mci", + .id = 1, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &mmc1_data, + }, + .resource = mmc1_resources, + .num_resources = ARRAY_SIZE(mmc1_resources), +}; + +void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) +{ + if (!data) + return; + + /* input/irq */ + if (data->det_pin) { + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + } + if (data->wp_pin) + at91_set_gpio_input(data->wp_pin, 1); + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); + + if (mmc_id == 0) { /* MCI0 */ + /* CLK */ + at91_set_A_periph(AT91_PIN_PA12, 0); + + if (data->slot_b) { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA16, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA17, 1); + if (data->wire4) { + at91_set_A_periph(AT91_PIN_PA18, 1); + at91_set_A_periph(AT91_PIN_PA19, 1); + at91_set_A_periph(AT91_PIN_PA20, 1); + } + } else { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA0, 1); + if (data->wire4) { + at91_set_A_periph(AT91_PIN_PA3, 1); + at91_set_A_periph(AT91_PIN_PA4, 1); + at91_set_A_periph(AT91_PIN_PA5, 1); + } + } + + mmc0_data = *data; + at91_clock_associate("mci0_clk", &at91sam9263_mmc1_device.dev, "mci_clk"); + platform_device_register(&at91sam9263_mmc0_device); + } else { /* MCI1 */ + /* CLK */ + at91_set_A_periph(AT91_PIN_PA6, 0); + + if (data->slot_b) { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA21, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA22, 1); + if (data->wire4) { + at91_set_A_periph(AT91_PIN_PA23, 1); + at91_set_A_periph(AT91_PIN_PA24, 1); + at91_set_A_periph(AT91_PIN_PA25, 1); + } + } else { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA7, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA8, 1); + if (data->wire4) { + at91_set_A_periph(AT91_PIN_PA9, 1); + at91_set_A_periph(AT91_PIN_PA10, 1); + at91_set_A_periph(AT91_PIN_PA11, 1); + } + } + + mmc1_data = *data; + at91_clock_associate("mci1_clk", &at91sam9263_mmc1_device.dev, "mci_clk"); + platform_device_register(&at91sam9263_mmc1_device); + } +} +#else +void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) +static struct at91_nand_data nand_data; + +#define NAND_BASE AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { + { + .start = NAND_BASE, + .end = NAND_BASE + SZ_256M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91sam9263_nand_device = { + .name = "at91_nand", + .id = -1, + .dev = { + .platform_data = &nand_data, + }, + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), +}; + +void __init at91_add_device_nand(struct at91_nand_data *data) +{ + unsigned long csa, mode; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBI0CSA); + at91_sys_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC); + + /* set the bus interface characteristics */ + at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0) + | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0)); + + at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3) + | AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3)); + + at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5)); + + if (data->bus_width_16) + mode = AT91_SMC_DBW_16; + else + mode = AT91_SMC_DBW_8; + at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2)); + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + nand_data = *data; + platform_device_register(&at91sam9263_nand_device); +} +#else +void __init at91_add_device_nand(struct at91_nand_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * TWI (i2c) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_TWI, + .end = AT91SAM9263_BASE_TWI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_TWI, + .end = AT91SAM9263_ID_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_twi_device = { + .name = "at91_i2c", + .id = -1, + .resource = twi_resources, + .num_resources = ARRAY_SIZE(twi_resources), +}; + +void __init at91_add_device_i2c(void) +{ + /* pins used for TWI interface */ + at91_set_A_periph(AT91_PIN_PB4, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PB4, 1); + + at91_set_A_periph(AT91_PIN_PB5, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PB5, 1); + + platform_device_register(&at91sam9263_twi_device); +} +#else +void __init at91_add_device_i2c(void) {} +#endif + + +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) +static u64 spi_dmamask = 0xffffffffUL; + +static struct resource spi0_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_SPI0, + .end = AT91SAM9263_BASE_SPI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_SPI0, + .end = AT91SAM9263_ID_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_spi0_device = { + .name = "atmel_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi0_resources, + .num_resources = ARRAY_SIZE(spi0_resources), +}; + +static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PB11 }; + +static struct resource spi1_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_SPI1, + .end = AT91SAM9263_BASE_SPI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_SPI1, + .end = AT91SAM9263_ID_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_spi1_device = { + .name = "atmel_spi", + .id = 1, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi1_resources, + .num_resources = ARRAY_SIZE(spi1_resources), +}; + +static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ + int i; + unsigned long cs_pin; + short enable_spi0 = 0; + short enable_spi1 = 0; + + /* Choose SPI chip-selects */ + for (i = 0; i < nr_devices; i++) { + if (devices[i].controller_data) + cs_pin = (unsigned long) devices[i].controller_data; + else if (devices[i].bus_num == 0) + cs_pin = spi0_standard_cs[devices[i].chip_select]; + else + cs_pin = spi1_standard_cs[devices[i].chip_select]; + + if (devices[i].bus_num == 0) + enable_spi0 = 1; + else + enable_spi1 = 1; + + /* enable chip-select pin */ + at91_set_gpio_output(cs_pin, 1); + + /* pass chip-select pin to driver */ + devices[i].controller_data = (void *) cs_pin; + } + + spi_register_board_info(devices, nr_devices); + + /* Configure SPI bus(es) */ + if (enable_spi0) { + at91_set_B_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */ + at91_set_B_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */ + at91_set_B_periph(AT91_PIN_PA2, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi0_clk", &at91sam9263_spi0_device.dev, "spi_clk"); + platform_device_register(&at91sam9263_spi0_device); + } + if (enable_spi1) { + at91_set_A_periph(AT91_PIN_PB12, 0); /* SPI1_MISO */ + at91_set_A_periph(AT91_PIN_PB13, 0); /* SPI1_MOSI */ + at91_set_A_periph(AT91_PIN_PB14, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi1_clk", &at91sam9263_spi1_device.dev, "spi_clk"); + platform_device_register(&at91sam9263_spi1_device); + } +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * LEDs + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_LEDS) +u8 at91_leds_cpu; +u8 at91_leds_timer; + +void __init at91_init_leds(u8 cpu_led, u8 timer_led) +{ + /* Enable GPIO to access the LEDs */ + at91_set_gpio_output(cpu_led, 1); + at91_set_gpio_output(timer_led, 1); + + at91_leds_cpu = cpu_led; + at91_leds_timer = timer_led; +} +#else +void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} +#endif + + +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SERIAL_ATMEL) + +static struct resource dbgu_resources[] = { + [0] = { + .start = AT91_VA_BASE_SYS + AT91_DBGU, + .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SYS, + .end = AT91_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data dbgu_data = { + .use_dma_tx = 0, + .use_dma_rx = 0, /* DBGU not capable of receive DMA */ + .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), +}; + +static struct platform_device at91sam9263_dbgu_device = { + .name = "atmel_usart", + .id = 0, + .dev = { + .platform_data = &dbgu_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC30, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PC31, 1); /* DTXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_US0, + .end = AT91SAM9263_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_US0, + .end = AT91SAM9263_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9263_uart0_device = { + .name = "atmel_usart", + .id = 1, + .dev = { + .platform_data = &uart0_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA26, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PA27, 0); /* RXD0 */ + at91_set_A_periph(AT91_PIN_PA28, 0); /* RTS0 */ + at91_set_A_periph(AT91_PIN_PA29, 0); /* CTS0 */ +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_US1, + .end = AT91SAM9263_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_US1, + .end = AT91SAM9263_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9263_uart1_device = { + .name = "atmel_usart", + .id = 2, + .dev = { + .platform_data = &uart1_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(void) +{ + at91_set_A_periph(AT91_PIN_PD0, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PD1, 0); /* RXD1 */ + at91_set_B_periph(AT91_PIN_PD7, 0); /* RTS1 */ + at91_set_B_periph(AT91_PIN_PD8, 0); /* CTS1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_US2, + .end = AT91SAM9263_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_US2, + .end = AT91SAM9263_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9263_uart2_device = { + .name = "atmel_usart", + .id = 3, + .dev = { + .platform_data = &uart2_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(void) +{ + at91_set_A_periph(AT91_PIN_PD2, 1); /* TXD2 */ + at91_set_A_periph(AT91_PIN_PD3, 0); /* RXD2 */ + at91_set_B_periph(AT91_PIN_PD5, 0); /* RTS2 */ + at91_set_B_periph(AT91_PIN_PD6, 0); /* CTS2 */ +} + +struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ +struct platform_device *atmel_default_console_device; /* the serial console device */ + +void __init at91_init_serial(struct at91_uart_config *config) +{ + int i; + + /* Fill in list of supported UARTs */ + for (i = 0; i < config->nr_tty; i++) { + switch (config->tty_map[i]) { + case 0: + configure_usart0_pins(); + at91_uarts[i] = &at91sam9263_uart0_device; + at91_clock_associate("usart0_clk", &at91sam9263_uart0_device.dev, "usart"); + break; + case 1: + configure_usart1_pins(); + at91_uarts[i] = &at91sam9263_uart1_device; + at91_clock_associate("usart1_clk", &at91sam9263_uart1_device.dev, "usart"); + break; + case 2: + configure_usart2_pins(); + at91_uarts[i] = &at91sam9263_uart2_device; + at91_clock_associate("usart2_clk", &at91sam9263_uart2_device.dev, "usart"); + break; + case 3: + configure_dbgu_pins(); + at91_uarts[i] = &at91sam9263_dbgu_device; + at91_clock_associate("mck", &at91sam9263_dbgu_device.dev, "usart"); + break; + default: + continue; + } + at91_uarts[i]->id = i; /* update ID number to mapped ID */ + } + + /* Set serial console device */ + if (config->console_tty < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[config->console_tty]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +void __init at91_add_device_serial(void) +{ + int i; + + for (i = 0; i < ATMEL_MAX_UART; i++) { + if (at91_uarts[i]) + platform_device_register(at91_uarts[i]); + } +} +#else +void __init at91_init_serial(struct at91_uart_config *config) {} +void __init at91_add_device_serial(void) {} +#endif + + +/* -------------------------------------------------------------------- */ +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + return 0; +} + +arch_initcall(at91_add_standard_devices); diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index baab095f6e32..27e7279b5b39 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -598,7 +598,7 @@ int __init at91_clock_init(unsigned long main_clock) udpck.pmc_mask = AT91RM9200_PMC_UDP; at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP); at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); - } else if (cpu_is_at91sam9260()) { + } else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { uhpck.pmc_mask = AT91SAM926x_PMC_UHP; udpck.pmc_mask = AT91SAM926x_PMC_UDP; at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP); diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 10ee37bf6d4d..bda26221c522 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -12,11 +12,13 @@ extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks); extern void __init at91sam9260_initialize(unsigned long main_clock); extern void __init at91sam9261_initialize(unsigned long main_clock); +extern void __init at91sam9263_initialize(unsigned long main_clock); /* Interrupts */ extern void __init at91rm9200_init_interrupts(unsigned int priority[]); extern void __init at91sam9260_init_interrupts(unsigned int priority[]); extern void __init at91sam9261_init_interrupts(unsigned int priority[]); +extern void __init at91sam9263_init_interrupts(unsigned int priority[]); extern void __init at91_aic_init(unsigned int priority[]); /* Timer */ diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index e095b1fe8d8a..b49bfda53d7f 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -80,6 +80,8 @@ static int at91_pm_verify_clocks(void) #warning "Check SAM9260 USB clocks" } else if (cpu_is_at91sam9261()) { #warning "Check SAM9261 USB clocks" + } else if (cpu_is_at91sam9263()) { +#warning "Check SAM9263 USB clocks" } #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index aade2f72c920..b305cbda8b87 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -171,8 +171,8 @@ config CPU_ARM925T # ARM926T config CPU_ARM926T bool "Support ARM926T processor" - depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 - default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 + depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 + default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 select CPU_32v5 select CPU_ABRT_EV5TJ select CPU_CACHE_VIVT diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 812c733ba8ce..8afecb8a98ee 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -913,7 +913,7 @@ static void pullup(struct at91_udc *udc, int is_on) at91_udp_write(udc, AT91_UDP_TXVC, 0); if (cpu_is_at91rm9200()) at91_set_gpio_value(udc->board.pullup_pin, 1); - else if (cpu_is_at91sam9260()) { + else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); txvc |= AT91_UDP_TXVC_PUON; @@ -930,7 +930,7 @@ static void pullup(struct at91_udc *udc, int is_on) at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); if (cpu_is_at91rm9200()) at91_set_gpio_value(udc->board.pullup_pin, 0); - else if (cpu_is_at91sam9260()) { + else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); txvc &= ~AT91_UDP_TXVC_PUON; diff --git a/include/asm-arm/arch-at91/at91sam9263.h b/include/asm-arm/arch-at91/at91sam9263.h new file mode 100644 index 000000000000..f4af68ae0ea9 --- /dev/null +++ b/include/asm-arm/arch-at91/at91sam9263.h @@ -0,0 +1,131 @@ +/* + * include/asm-arm/arch-at91/at91sam9263.h + * + * (C) 2007 Atmel Corporation. + * + * Common definitions. + * Based on AT91SAM9263 datasheet revision B (Preliminary). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91SAM9263_H +#define AT91SAM9263_H + +/* + * Peripheral identifiers/interrupts. + */ +#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */ +#define AT91_ID_SYS 1 /* System Peripherals */ +#define AT91SAM9263_ID_PIOA 2 /* Parallel IO Controller A */ +#define AT91SAM9263_ID_PIOB 3 /* Parallel IO Controller B */ +#define AT91SAM9263_ID_PIOCDE 4 /* Parallel IO Controller C, D and E */ +#define AT91SAM9263_ID_US0 7 /* USART 0 */ +#define AT91SAM9263_ID_US1 8 /* USART 1 */ +#define AT91SAM9263_ID_US2 9 /* USART 2 */ +#define AT91SAM9263_ID_MCI0 10 /* Multimedia Card Interface 0 */ +#define AT91SAM9263_ID_MCI1 11 /* Multimedia Card Interface 1 */ +#define AT91SAM9263_ID_CAN 12 /* CAN */ +#define AT91SAM9263_ID_TWI 13 /* Two-Wire Interface */ +#define AT91SAM9263_ID_SPI0 14 /* Serial Peripheral Interface 0 */ +#define AT91SAM9263_ID_SPI1 15 /* Serial Peripheral Interface 1 */ +#define AT91SAM9263_ID_SSC0 16 /* Serial Synchronous Controller 0 */ +#define AT91SAM9263_ID_SSC1 17 /* Serial Synchronous Controller 1 */ +#define AT91SAM9263_ID_AC97C 18 /* AC97 Controller */ +#define AT91SAM9263_ID_TCB 19 /* Timer Counter 0, 1 and 2 */ +#define AT91SAM9263_ID_PWMC 20 /* Pulse Width Modulation Controller */ +#define AT91SAM9263_ID_EMAC 21 /* Ethernet */ +#define AT91SAM9263_ID_2DGE 23 /* 2D Graphic Engine */ +#define AT91SAM9263_ID_UDP 24 /* USB Device Port */ +#define AT91SAM9263_ID_ISI 25 /* Image Sensor Interface */ +#define AT91SAM9263_ID_LCDC 26 /* LCD Controller */ +#define AT91SAM9263_ID_DMA 27 /* DMA Controller */ +#define AT91SAM9263_ID_UHP 29 /* USB Host port */ +#define AT91SAM9263_ID_IRQ0 30 /* Advanced Interrupt Controller (IRQ0) */ +#define AT91SAM9263_ID_IRQ1 31 /* Advanced Interrupt Controller (IRQ1) */ + + +/* + * User Peripheral physical base addresses. + */ +#define AT91SAM9263_BASE_UDP 0xfff78000 +#define AT91SAM9263_BASE_TCB0 0xfff7c000 +#define AT91SAM9263_BASE_TC0 0xfff7c000 +#define AT91SAM9263_BASE_TC1 0xfff7c040 +#define AT91SAM9263_BASE_TC2 0xfff7c080 +#define AT91SAM9263_BASE_MCI0 0xfff80000 +#define AT91SAM9263_BASE_MCI1 0xfff84000 +#define AT91SAM9263_BASE_TWI 0xfff88000 +#define AT91SAM9263_BASE_US0 0xfff8c000 +#define AT91SAM9263_BASE_US1 0xfff90000 +#define AT91SAM9263_BASE_US2 0xfff94000 +#define AT91SAM9263_BASE_SSC0 0xfff98000 +#define AT91SAM9263_BASE_SSC1 0xfff9c000 +#define AT91SAM9263_BASE_AC97C 0xfffa0000 +#define AT91SAM9263_BASE_SPI0 0xfffa4000 +#define AT91SAM9263_BASE_SPI1 0xfffa8000 +#define AT91SAM9263_BASE_CAN 0xfffac000 +#define AT91SAM9263_BASE_PWMC 0xfffb8000 +#define AT91SAM9263_BASE_EMAC 0xfffbc000 +#define AT91SAM9263_BASE_ISI 0xfffc4000 +#define AT91SAM9263_BASE_2DGE 0xfffc8000 +#define AT91_BASE_SYS 0xffffe000 + +/* + * System Peripherals (offset from AT91_BASE_SYS) + */ +#define AT91_ECC0 (0xffffe000 - AT91_BASE_SYS) +#define AT91_SDRAMC0 (0xffffe200 - AT91_BASE_SYS) +#define AT91_SMC0 (0xffffe400 - AT91_BASE_SYS) +#define AT91_ECC1 (0xffffe600 - AT91_BASE_SYS) +#define AT91_SDRAMC1 (0xffffe800 - AT91_BASE_SYS) +#define AT91_SMC1 (0xffffea00 - AT91_BASE_SYS) +#define AT91_MATRIX (0xffffec00 - AT91_BASE_SYS) +#define AT91_CCFG (0xffffed10 - AT91_BASE_SYS) +#define AT91_DBGU (0xffffee00 - AT91_BASE_SYS) +#define AT91_AIC (0xfffff000 - AT91_BASE_SYS) +#define AT91_PIOA (0xfffff200 - AT91_BASE_SYS) +#define AT91_PIOB (0xfffff400 - AT91_BASE_SYS) +#define AT91_PIOC (0xfffff600 - AT91_BASE_SYS) +#define AT91_PIOD (0xfffff800 - AT91_BASE_SYS) +#define AT91_PIOE (0xfffffa00 - AT91_BASE_SYS) +#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) +#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) +#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS) +#define AT91_RTT0 (0xfffffd20 - AT91_BASE_SYS) +#define AT91_PIT (0xfffffd30 - AT91_BASE_SYS) +#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS) +#define AT91_RTT1 (0xfffffd50 - AT91_BASE_SYS) +#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS) + +#define AT91_SMC AT91_SMC0 + +/* + * Internal Memory. + */ +#define AT91SAM9263_SRAM0_BASE 0x00300000 /* Internal SRAM 0 base address */ +#define AT91SAM9263_SRAM0_SIZE (80 * SZ_1K) /* Internal SRAM 0 size (80Kb) */ + +#define AT91SAM9263_ROM_BASE 0x00400000 /* Internal ROM base address */ +#define AT91SAM9263_ROM_SIZE SZ_128K /* Internal ROM size (128Kb) */ + +#define AT91SAM9263_SRAM1_BASE 0x00500000 /* Internal SRAM 1 base address */ +#define AT91SAM9263_SRAM1_SIZE SZ_16K /* Internal SRAM 1 size (16Kb) */ + +#define AT91SAM9263_LCDC_BASE 0x00700000 /* LCD Controller */ +#define AT91SAM9263_DMAC_BASE 0x00800000 /* DMA Controller */ +#define AT91SAM9263_UHP_BASE 0x00a00000 /* USB Host controller */ + +#if 0 +/* + * PIO pin definitions (peripheral A/B multiplexing). + */ + +// TODO: Add + +#endif + +#endif diff --git a/include/asm-arm/arch-at91/at91sam9263_matrix.h b/include/asm-arm/arch-at91/at91sam9263_matrix.h new file mode 100644 index 000000000000..6fc6e4be624e --- /dev/null +++ b/include/asm-arm/arch-at91/at91sam9263_matrix.h @@ -0,0 +1,129 @@ +/* + * include/asm-arm/arch-at91/at91sam9263_matrix.h + * + * Copyright (C) 2006 Atmel Corporation. + * + * Memory Controllers (MATRIX, EBI) - System peripherals registers. + * Based on AT91SAM9263 datasheet revision B (Preliminary). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91SAM9263_MATRIX_H +#define AT91SAM9263_MATRIX_H + +#define AT91_MATRIX_MCFG0 (AT91_MATRIX + 0x00) /* Master Configuration Register 0 */ +#define AT91_MATRIX_MCFG1 (AT91_MATRIX + 0x04) /* Master Configuration Register 1 */ +#define AT91_MATRIX_MCFG2 (AT91_MATRIX + 0x08) /* Master Configuration Register 2 */ +#define AT91_MATRIX_MCFG3 (AT91_MATRIX + 0x0C) /* Master Configuration Register 3 */ +#define AT91_MATRIX_MCFG4 (AT91_MATRIX + 0x10) /* Master Configuration Register 4 */ +#define AT91_MATRIX_MCFG5 (AT91_MATRIX + 0x14) /* Master Configuration Register 5 */ +#define AT91_MATRIX_MCFG6 (AT91_MATRIX + 0x18) /* Master Configuration Register 6 */ +#define AT91_MATRIX_MCFG7 (AT91_MATRIX + 0x1C) /* Master Configuration Register 7 */ +#define AT91_MATRIX_MCFG8 (AT91_MATRIX + 0x20) /* Master Configuration Register 8 */ +#define AT91_MATRIX_ULBT (7 << 0) /* Undefined Length Burst Type */ +#define AT91_MATRIX_ULBT_INFINITE (0 << 0) +#define AT91_MATRIX_ULBT_SINGLE (1 << 0) +#define AT91_MATRIX_ULBT_FOUR (2 << 0) +#define AT91_MATRIX_ULBT_EIGHT (3 << 0) +#define AT91_MATRIX_ULBT_SIXTEEN (4 << 0) + +#define AT91_MATRIX_SCFG0 (AT91_MATRIX + 0x40) /* Slave Configuration Register 0 */ +#define AT91_MATRIX_SCFG1 (AT91_MATRIX + 0x44) /* Slave Configuration Register 1 */ +#define AT91_MATRIX_SCFG2 (AT91_MATRIX + 0x48) /* Slave Configuration Register 2 */ +#define AT91_MATRIX_SCFG3 (AT91_MATRIX + 0x4C) /* Slave Configuration Register 3 */ +#define AT91_MATRIX_SCFG4 (AT91_MATRIX + 0x50) /* Slave Configuration Register 4 */ +#define AT91_MATRIX_SCFG5 (AT91_MATRIX + 0x54) /* Slave Configuration Register 5 */ +#define AT91_MATRIX_SCFG6 (AT91_MATRIX + 0x58) /* Slave Configuration Register 6 */ +#define AT91_MATRIX_SCFG7 (AT91_MATRIX + 0x5C) /* Slave Configuration Register 7 */ +#define AT91_MATRIX_SLOT_CYCLE (0xff << 0) /* Maximum Number of Allowed Cycles for a Burst */ +#define AT91_MATRIX_DEFMSTR_TYPE (3 << 16) /* Default Master Type */ +#define AT91_MATRIX_DEFMSTR_TYPE_NONE (0 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_LAST (1 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_FIXED (2 << 16) +#define AT91_MATRIX_FIXED_DEFMSTR (7 << 18) /* Fixed Index of Default Master */ +#define AT91_MATRIX_ARBT (3 << 24) /* Arbitration Type */ +#define AT91_MATRIX_ARBT_ROUND_ROBIN (0 << 24) +#define AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24) + +#define AT91_MATRIX_PRAS0 (AT91_MATRIX + 0x80) /* Priority Register A for Slave 0 */ +#define AT91_MATRIX_PRBS0 (AT91_MATRIX + 0x84) /* Priority Register B for Slave 0 */ +#define AT91_MATRIX_PRAS1 (AT91_MATRIX + 0x88) /* Priority Register A for Slave 1 */ +#define AT91_MATRIX_PRBS1 (AT91_MATRIX + 0x8C) /* Priority Register B for Slave 1 */ +#define AT91_MATRIX_PRAS2 (AT91_MATRIX + 0x90) /* Priority Register A for Slave 2 */ +#define AT91_MATRIX_PRBS2 (AT91_MATRIX + 0x94) /* Priority Register B for Slave 2 */ +#define AT91_MATRIX_PRAS3 (AT91_MATRIX + 0x98) /* Priority Register A for Slave 3 */ +#define AT91_MATRIX_PRBS3 (AT91_MATRIX + 0x9C) /* Priority Register B for Slave 3 */ +#define AT91_MATRIX_PRAS4 (AT91_MATRIX + 0xA0) /* Priority Register A for Slave 4 */ +#define AT91_MATRIX_PRBS4 (AT91_MATRIX + 0xA4) /* Priority Register B for Slave 4 */ +#define AT91_MATRIX_PRAS5 (AT91_MATRIX + 0xA8) /* Priority Register A for Slave 5 */ +#define AT91_MATRIX_PRBS5 (AT91_MATRIX + 0xAC) /* Priority Register B for Slave 5 */ +#define AT91_MATRIX_PRAS6 (AT91_MATRIX + 0xB0) /* Priority Register A for Slave 6 */ +#define AT91_MATRIX_PRBS6 (AT91_MATRIX + 0xB4) /* Priority Register B for Slave 6 */ +#define AT91_MATRIX_PRAS7 (AT91_MATRIX + 0xB8) /* Priority Register A for Slave 7 */ +#define AT91_MATRIX_PRBS7 (AT91_MATRIX + 0xBC) /* Priority Register B for Slave 7 */ +#define AT91_MATRIX_M0PR (3 << 0) /* Master 0 Priority */ +#define AT91_MATRIX_M1PR (3 << 4) /* Master 1 Priority */ +#define AT91_MATRIX_M2PR (3 << 8) /* Master 2 Priority */ +#define AT91_MATRIX_M3PR (3 << 12) /* Master 3 Priority */ +#define AT91_MATRIX_M4PR (3 << 16) /* Master 4 Priority */ +#define AT91_MATRIX_M5PR (3 << 20) /* Master 5 Priority */ +#define AT91_MATRIX_M6PR (3 << 24) /* Master 6 Priority */ +#define AT91_MATRIX_M7PR (3 << 28) /* Master 7 Priority */ +#define AT91_MATRIX_M8PR (3 << 0) /* Master 8 Priority (in Register B) */ + +#define AT91_MATRIX_MRCR (AT91_MATRIX + 0x100) /* Master Remap Control Register */ +#define AT91_MATRIX_RCB0 (1 << 0) /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */ +#define AT91_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */ +#define AT91_MATRIX_RCB2 (1 << 2) +#define AT91_MATRIX_RCB3 (1 << 3) +#define AT91_MATRIX_RCB4 (1 << 4) +#define AT91_MATRIX_RCB5 (1 << 5) +#define AT91_MATRIX_RCB6 (1 << 6) +#define AT91_MATRIX_RCB7 (1 << 7) +#define AT91_MATRIX_RCB8 (1 << 8) + +#define AT91_MATRIX_TCMR (AT91_MATRIX + 0x114) /* TCM Configuration Register */ +#define AT91_MATRIX_ITCM_SIZE (0xf << 0) /* Size of ITCM enabled memory block */ +#define AT91_MATRIX_ITCM_0 (0 << 0) +#define AT91_MATRIX_ITCM_16 (5 << 0) +#define AT91_MATRIX_ITCM_32 (6 << 0) +#define AT91_MATRIX_DTCM_SIZE (0xf << 4) /* Size of DTCM enabled memory block */ +#define AT91_MATRIX_DTCM_0 (0 << 4) +#define AT91_MATRIX_DTCM_16 (5 << 4) +#define AT91_MATRIX_DTCM_32 (6 << 4) + +#define AT91_MATRIX_EBI0CSA (AT91_MATRIX + 0x120) /* EBI0 Chip Select Assignment Register */ +#define AT91_MATRIX_EBI0_CS1A (1 << 1) /* Chip Select 1 Assignment */ +#define AT91_MATRIX_EBI0_CS1A_SMC (0 << 1) +#define AT91_MATRIX_EBI0_CS1A_SDRAMC (1 << 1) +#define AT91_MATRIX_EBI0_CS3A (1 << 3) /* Chip Select 3 Assignment */ +#define AT91_MATRIX_EBI0_CS3A_SMC (0 << 3) +#define AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA (1 << 3) +#define AT91_MATRIX_EBI0_CS4A (1 << 4) /* Chip Select 4 Assignment */ +#define AT91_MATRIX_EBI0_CS4A_SMC (0 << 4) +#define AT91_MATRIX_EBI0_CS4A_SMC_CF1 (1 << 4) +#define AT91_MATRIX_EBI0_CS5A (1 << 5) /* Chip Select 5 Assignment */ +#define AT91_MATRIX_EBI0_CS5A_SMC (0 << 5) +#define AT91_MATRIX_EBI0_CS5A_SMC_CF2 (1 << 5) +#define AT91_MATRIX_EBI0_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ +#define AT91_MATRIX_EBI0_VDDIOMSEL (1 << 16) /* Memory voltage selection */ +#define AT91_MATRIX_EBI0_VDDIOMSEL_1_8V (0 << 16) +#define AT91_MATRIX_EBI0_VDDIOMSEL_3_3V (1 << 16) + +#define AT91_MATRIX_EBI1CSA (AT91_MATRIX + 0x124) /* EBI1 Chip Select Assignment Register */ +#define AT91_MATRIX_EBI1_CS1A (1 << 1) /* Chip Select 1 Assignment */ +#define AT91_MATRIX_EBI1_CS1A_SMC (0 << 1) +#define AT91_MATRIX_EBI1_CS1A_SDRAMC (1 << 1) +#define AT91_MATRIX_EBI1_CS2A (1 << 3) /* Chip Select 3 Assignment */ +#define AT91_MATRIX_EBI1_CS2A_SMC (0 << 3) +#define AT91_MATRIX_EBI1_CS2A_SMC_SMARTMEDIA (1 << 3) +#define AT91_MATRIX_EBI1_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ +#define AT91_MATRIX_EBI1_VDDIOMSEL (1 << 16) /* Memory voltage selection */ +#define AT91_MATRIX_EBI1_VDDIOMSEL_1_8V (0 << 16) +#define AT91_MATRIX_EBI1_VDDIOMSEL_3_3V (1 << 16) + +#endif diff --git a/include/asm-arm/arch-at91/at91sam926x_mc.h b/include/asm-arm/arch-at91/at91sam926x_mc.h index 355eee67ebca..d82631c251f1 100644 --- a/include/asm-arm/arch-at91/at91sam926x_mc.h +++ b/include/asm-arm/arch-at91/at91sam926x_mc.h @@ -131,4 +131,11 @@ #define AT91_SMC_PS_16 (2 << 28) #define AT91_SMC_PS_32 (3 << 28) +#if defined(AT91_SMC1) /* The AT91SAM9263 has 2 Static Memory contollers */ +#define AT91_SMC1_SETUP(n) (AT91_SMC1 + 0x00 + ((n)*0x10)) /* Setup Register for CS n */ +#define AT91_SMC1_PULSE(n) (AT91_SMC1 + 0x04 + ((n)*0x10)) /* Pulse Register for CS n */ +#define AT91_SMC1_CYCLE(n) (AT91_SMC1 + 0x08 + ((n)*0x10)) /* Cycle Register for CS n */ +#define AT91_SMC1_MODE(n) (AT91_SMC1 + 0x0c + ((n)*0x10)) /* Mode Register for CS n */ +#endif + #endif diff --git a/include/asm-arm/arch-at91/cpu.h b/include/asm-arm/arch-at91/cpu.h index 762eb41aa675..9efde0dad249 100644 --- a/include/asm-arm/arch-at91/cpu.h +++ b/include/asm-arm/arch-at91/cpu.h @@ -20,6 +20,7 @@ #define ARCH_ID_AT91RM9200 0x09290780 #define ARCH_ID_AT91SAM9260 0x019803a0 #define ARCH_ID_AT91SAM9261 0x019703a0 +#define ARCH_ID_AT91SAM9263 0x019607a0 static inline unsigned long at91_cpu_identify(void) @@ -46,4 +47,10 @@ static inline unsigned long at91_cpu_identify(void) #define cpu_is_at91sam9261() (0) #endif +#ifdef CONFIG_ARCH_AT91SAM9263 +#define cpu_is_at91sam9263() (at91_cpu_identify() == ARCH_ID_AT91SAM9263) +#else +#define cpu_is_at91sam9263() (0) +#endif + #endif diff --git a/include/asm-arm/arch-at91/hardware.h b/include/asm-arm/arch-at91/hardware.h index 1637fc4a0d8f..eaaf1c12b753 100644 --- a/include/asm-arm/arch-at91/hardware.h +++ b/include/asm-arm/arch-at91/hardware.h @@ -22,6 +22,8 @@ #include #elif defined(CONFIG_ARCH_AT91SAM9261) #include +#elif defined(CONFIG_ARCH_AT91SAM9263) +#include #else #error "Unsupported AT91 processor" #endif diff --git a/include/asm-arm/arch-at91/timex.h b/include/asm-arm/arch-at91/timex.h index b24e364997e1..f41636d607a2 100644 --- a/include/asm-arm/arch-at91/timex.h +++ b/include/asm-arm/arch-at91/timex.h @@ -32,6 +32,11 @@ #define AT91SAM9_MASTER_CLOCK 99300000 #define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16) +#elif defined(CONFIG_ARCH_AT91SAM9263) + +#define AT91SAM9_MASTER_CLOCK 99959500 +#define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16) + #endif #endif -- cgit v1.2.3 From 3e1a80f11f89f318e892694b501735abb51ef626 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 8 Feb 2007 16:26:23 +0100 Subject: [ARM] 4153/1: fix consistent_sync() off-by-one BUG check In consistent_sync(), start + size can end up pointing one byte beyond the end of the direct RAM mapping. We shouldn't BUG() when this happens. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mm/consistent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index 166aee13c4b1..1f9f94f9af4b 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -485,7 +485,7 @@ void consistent_sync(const void *start, size_t size, int direction) { const void *end = start + size; - BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end)); + BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end - 1)); switch (direction) { case DMA_FROM_DEVICE: /* invalidate only */ -- cgit v1.2.3 From f2131d348f0bd252801f641018a90d59c987ce48 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 8 Feb 2007 20:46:20 +0000 Subject: [ARM] Always mark ARMv6 PTWs outer cacheable Other platforms other than SMP may have an outer cache. For these, we also need to mark the page table walks outer cacheable. Since marking the walks always outer cacheable apparantly has no side effects, we might as well always mark them so. However, we continue to only mark PTWs shared if we have SMP enabled. Signed-off-by: Russell King --- arch/arm/mm/proc-v6.S | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 7b1843befb9c..d78c0ae7c2c2 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -30,6 +30,12 @@ #define TTB_RGN_WT (2 << 3) #define TTB_RGN_WB (3 << 3) +#ifndef CONFIG_SMP +#define TTB_FLAGS TTB_RGN_WBWA +#else +#define TTB_FLAGS TTB_RGN_WBWA|TTB_S +#endif + ENTRY(cpu_v6_proc_init) mov pc, lr @@ -92,9 +98,7 @@ ENTRY(cpu_v6_switch_mm) #ifdef CONFIG_MMU mov r2, #0 ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id -#ifdef CONFIG_SMP - orr r0, r0, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable -#endif + orr r0, r0, #TTB_FLAGS mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB mcr p15, 0, r2, c7, c10, 4 @ drain write buffer mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 @@ -204,9 +208,7 @@ __v6_setup: #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs mcr p15, 0, r0, c2, c0, 2 @ TTB control register -#ifdef CONFIG_SMP - orr r4, r4, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable -#endif + orr r4, r4, #TTB_FLAGS mcr p15, 0, r4, c2, c0, 1 @ load TTB1 #endif /* CONFIG_MMU */ adr r5, v6_crval -- cgit v1.2.3 From 382266ad5ad4119ec12df889afa5062a0a0cd6ae Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 5 Feb 2007 14:48:19 +0100 Subject: [ARM] 4135/1: Add support for the L210/L220 cache controllers This patch adds the support for the L210/L220 (outer) cache controller. The cache range operations are done by index/way since L2 cache controller only accepts physical addresses. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mm/Kconfig | 4 ++ arch/arm/mm/Makefile | 2 + arch/arm/mm/cache-l2x0.c | 104 ++++++++++++++++++++++++++++++++++ include/asm-arm/hardware/cache-l2x0.h | 56 ++++++++++++++++++ 4 files changed, 166 insertions(+) create mode 100644 arch/arm/mm/cache-l2x0.c create mode 100644 include/asm-arm/hardware/cache-l2x0.h (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index a84eed9f8542..af3fa9d622ff 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -612,3 +612,7 @@ config NEEDS_SYSCALL_FOR_CMPXCHG config OUTER_CACHE bool default n + +config CACHE_L2X0 + bool + select OUTER_CACHE diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index d2f5672ecf62..2f8b95947774 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -66,3 +66,5 @@ obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o obj-$(CONFIG_CPU_V6) += proc-v6.o + +obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c new file mode 100644 index 000000000000..08a36f1b35d2 --- /dev/null +++ b/arch/arm/mm/cache-l2x0.c @@ -0,0 +1,104 @@ +/* + * arch/arm/mm/cache-l2x0.c - L210/L220 cache controller support + * + * Copyright (C) 2007 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include + +#include +#include +#include + +#define CACHE_LINE_SIZE 32 + +static void __iomem *l2x0_base; + +static inline void sync_writel(unsigned long val, unsigned long reg, + unsigned long complete_mask) +{ + writel(val, l2x0_base + reg); + /* wait for the operation to complete */ + while (readl(l2x0_base + reg) & complete_mask) + ; +} + +static inline void cache_sync(void) +{ + sync_writel(0, L2X0_CACHE_SYNC, 1); +} + +static inline void l2x0_inv_all(void) +{ + /* invalidate all ways */ + sync_writel(0xff, L2X0_INV_WAY, 0xff); + cache_sync(); +} + +static void l2x0_inv_range(unsigned long start, unsigned long end) +{ + unsigned long addr; + + start &= ~(CACHE_LINE_SIZE - 1); + for (addr = start; addr < end; addr += CACHE_LINE_SIZE) + sync_writel(addr, L2X0_INV_LINE_PA, 1); + cache_sync(); +} + +static void l2x0_clean_range(unsigned long start, unsigned long end) +{ + unsigned long addr; + + start &= ~(CACHE_LINE_SIZE - 1); + for (addr = start; addr < end; addr += CACHE_LINE_SIZE) + sync_writel(addr, L2X0_CLEAN_LINE_PA, 1); + cache_sync(); +} + +static void l2x0_flush_range(unsigned long start, unsigned long end) +{ + unsigned long addr; + + start &= ~(CACHE_LINE_SIZE - 1); + for (addr = start; addr < end; addr += CACHE_LINE_SIZE) + sync_writel(addr, L2X0_CLEAN_INV_LINE_PA, 1); + cache_sync(); +} + +void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) +{ + __u32 aux; + + l2x0_base = base; + + /* disable L2X0 */ + writel(0, l2x0_base + L2X0_CTRL); + + aux = readl(l2x0_base + L2X0_AUX_CTRL); + aux &= aux_mask; + aux |= aux_val; + writel(aux, l2x0_base + L2X0_AUX_CTRL); + + l2x0_inv_all(); + + /* enable L2X0 */ + writel(1, l2x0_base + L2X0_CTRL); + + outer_cache.inv_range = l2x0_inv_range; + outer_cache.clean_range = l2x0_clean_range; + outer_cache.flush_range = l2x0_flush_range; + + printk(KERN_INFO "L2X0 cache controller enabled\n"); +} diff --git a/include/asm-arm/hardware/cache-l2x0.h b/include/asm-arm/hardware/cache-l2x0.h new file mode 100644 index 000000000000..54029a740396 --- /dev/null +++ b/include/asm-arm/hardware/cache-l2x0.h @@ -0,0 +1,56 @@ +/* + * include/asm-arm/hardware/cache-l2x0.h + * + * Copyright (C) 2007 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARM_HARDWARE_L2X0_H +#define __ASM_ARM_HARDWARE_L2X0_H + +#define L2X0_CACHE_ID 0x000 +#define L2X0_CACHE_TYPE 0x004 +#define L2X0_CTRL 0x100 +#define L2X0_AUX_CTRL 0x104 +#define L2X0_EVENT_CNT_CTRL 0x200 +#define L2X0_EVENT_CNT1_CFG 0x204 +#define L2X0_EVENT_CNT0_CFG 0x208 +#define L2X0_EVENT_CNT1_VAL 0x20C +#define L2X0_EVENT_CNT0_VAL 0x210 +#define L2X0_INTR_MASK 0x214 +#define L2X0_MASKED_INTR_STAT 0x218 +#define L2X0_RAW_INTR_STAT 0x21C +#define L2X0_INTR_CLEAR 0x220 +#define L2X0_CACHE_SYNC 0x730 +#define L2X0_INV_LINE_PA 0x770 +#define L2X0_INV_WAY 0x77C +#define L2X0_CLEAN_LINE_PA 0x7B0 +#define L2X0_CLEAN_LINE_IDX 0x7B8 +#define L2X0_CLEAN_WAY 0x7BC +#define L2X0_CLEAN_INV_LINE_PA 0x7F0 +#define L2X0_CLEAN_INV_LINE_IDX 0x7F8 +#define L2X0_CLEAN_INV_WAY 0x7FC +#define L2X0_LOCKDOWN_WAY_D 0x900 +#define L2X0_LOCKDOWN_WAY_I 0x904 +#define L2X0_TEST_OPERATION 0xF00 +#define L2X0_LINE_DATA 0xF10 +#define L2X0_LINE_TAG 0xF30 +#define L2X0_DEBUG_CTRL 0xF40 + +#ifndef __ASSEMBLY__ +extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); +#endif + +#endif -- cgit v1.2.3 From 4b17244c133689ad0cbdca37ce3e15068f120428 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 14 Feb 2007 19:20:28 +0100 Subject: [ARM] 4109/2: Add support for the RealView/EB MPCore revC platform The kernel originally supported revB only. This patch enables revC by default and adds a config option for building the kernel for the revB platform. Since the SCU base address was hard-coded in the proc-v6.S file (and only valid for RealView/EB revB), this patch also adds a more generic support for defining the SCU information. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mach-realview/Kconfig | 10 ++++++++++ arch/arm/mach-realview/realview_eb.c | 4 ++-- arch/arm/mm/proc-v6.S | 8 +++++--- include/asm-arm/arch-realview/hardware.h | 2 +- include/asm-arm/arch-realview/platform.h | 10 ++++++++++ include/asm-arm/arch-realview/scu.h | 8 ++++++++ include/asm-arm/hardware/arm_scu.h | 2 ++ 7 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 include/asm-arm/arch-realview/scu.h (limited to 'arch/arm/mm') diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index 17f5f4439fe7..68bc6b226ec7 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -16,4 +16,14 @@ config REALVIEW_MPCORE kernel built with this option enabled is not compatible with other tiles. +config REALVIEW_MPCORE_REVB + bool "Support MPcore RevB tile" + depends on REALVIEW_MPCORE + default n + help + Enable support for the MPCore RevB tile on the Realview platform. + Since there are device address differences, a + kernel built with this option enabled is not compatible with + other tiles. + endmenu diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 00139143dcc1..effe243454e0 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -152,9 +152,9 @@ static void __init gic_init_irq(void) #ifdef CONFIG_REALVIEW_MPCORE unsigned int pldctrl; writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK)); - pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + 0xd8); + pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1); pldctrl |= 0x00800000; /* New irq mode */ - writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + 0xd8); + writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1); writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); #endif gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29); diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 7b1843befb9c..f27d9eb64803 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -14,10 +14,13 @@ #include #include #include -#include #include #include +#ifdef CONFIG_SMP +#include +#endif + #include "proc-macros.S" #define D_CACHE_LINE_SIZE 32 @@ -183,8 +186,7 @@ __v6_setup: /* Set up the SCU on core 0 only */ mrc p15, 0, r0, c0, c0, 5 @ CPU core number ands r0, r0, #15 - moveq r0, #0x10000000 @ SCU_BASE - orreq r0, r0, #0x00100000 + ldreq r0, =SCU_BASE ldreq r5, [r0, #SCU_CTRL] orreq r5, r5, #1 streq r5, [r0, #SCU_CTRL] diff --git a/include/asm-arm/arch-realview/hardware.h b/include/asm-arm/arch-realview/hardware.h index 9ca76dc3a7af..aa78fe087ab2 100644 --- a/include/asm-arm/arch-realview/hardware.h +++ b/include/asm-arm/arch-realview/hardware.h @@ -26,7 +26,7 @@ #include /* macro to get at IO space when running virtually */ -#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) +#define IO_ADDRESS(x) ((((x) & 0x0effffff) | (((x) >> 4) & 0x0f000000)) + 0xf0000000) #define __io_address(n) __io(IO_ADDRESS(n)) #endif diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h index bf52ca752a75..87acd9c191e6 100644 --- a/include/asm-arm/arch-realview/platform.h +++ b/include/asm-arm/arch-realview/platform.h @@ -207,11 +207,21 @@ #define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */ #define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */ #else +#ifdef CONFIG_REALVIEW_MPCORE_REVB #define REALVIEW_MPCORE_SCU_BASE 0x10100000 /* SCU registers */ #define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ #define REALVIEW_TWD_BASE 0x10100700 #define REALVIEW_TWD_SIZE 0x00000100 #define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ +#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */ +#else +#define REALVIEW_MPCORE_SCU_BASE 0x1F000000 /* SCU registers */ +#define REALVIEW_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */ +#define REALVIEW_TWD_BASE 0x1F000700 +#define REALVIEW_TWD_SIZE 0x00000100 +#define REALVIEW_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */ +#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */ +#endif #define REALVIEW_GIC1_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */ #define REALVIEW_GIC1_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */ #endif diff --git a/include/asm-arm/arch-realview/scu.h b/include/asm-arm/arch-realview/scu.h new file mode 100644 index 000000000000..cc293640178e --- /dev/null +++ b/include/asm-arm/arch-realview/scu.h @@ -0,0 +1,8 @@ +#ifndef __ASMARM_ARCH_SCU_H +#define __ASMARM_ARCH_SCU_H + +#include + +#define SCU_BASE REALVIEW_MPCORE_SCU_BASE + +#endif diff --git a/include/asm-arm/hardware/arm_scu.h b/include/asm-arm/hardware/arm_scu.h index 9903f60c84b7..7d28eb5a1758 100644 --- a/include/asm-arm/hardware/arm_scu.h +++ b/include/asm-arm/hardware/arm_scu.h @@ -1,6 +1,8 @@ #ifndef ASMARM_HARDWARE_ARM_SCU_H #define ASMARM_HARDWARE_ARM_SCU_H +#include + /* * SCU registers */ -- cgit v1.2.3