diff options
37 files changed, 2162 insertions, 15 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 50725d026da0..03b9fb957548 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -502,6 +502,13 @@ P: Richard Purdie | |||
502 | M: rpurdie@rpsys.net | 502 | M: rpurdie@rpsys.net |
503 | S: Maintained | 503 | S: Maintained |
504 | 504 | ||
505 | ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE | ||
506 | P: Paulius Zaleckas | ||
507 | M: paulius.zaleckas@teltonika.lt | ||
508 | L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) | ||
509 | T: git gitorious.org/linux-gemini/mainline.git | ||
510 | S: Maintained | ||
511 | |||
505 | ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6) | 512 | ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6) |
506 | P: Daniel Ribeiro | 513 | P: Daniel Ribeiro |
507 | M: drwyrm@gmail.com | 514 | M: drwyrm@gmail.com |
@@ -513,6 +520,12 @@ L: openezx-devel@lists.openezx.org (subscribers-only) | |||
513 | W: http://www.openezx.org/ | 520 | W: http://www.openezx.org/ |
514 | S: Maintained | 521 | S: Maintained |
515 | 522 | ||
523 | ARM/FARADAY FA526 PORT | ||
524 | P: Paulius Zaleckas | ||
525 | M: paulius.zaleckas@teltonika.lt | ||
526 | L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) | ||
527 | S: Maintained | ||
528 | |||
516 | ARM/FREESCALE IMX / MXC ARM ARCHITECTURE | 529 | ARM/FREESCALE IMX / MXC ARM ARCHITECTURE |
517 | P: Sascha Hauer | 530 | P: Sascha Hauer |
518 | M: kernel@pengutronix.de | 531 | M: kernel@pengutronix.de |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e62b37a15a1d..e02b893fb909 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -276,6 +276,14 @@ config ARCH_EP93XX | |||
276 | help | 276 | help |
277 | This enables support for the Cirrus EP93xx series of CPUs. | 277 | This enables support for the Cirrus EP93xx series of CPUs. |
278 | 278 | ||
279 | config ARCH_GEMINI | ||
280 | bool "Cortina Systems Gemini" | ||
281 | select CPU_FA526 | ||
282 | select GENERIC_GPIO | ||
283 | select ARCH_REQUIRE_GPIOLIB | ||
284 | help | ||
285 | Support for the Cortina Systems Gemini family SoCs | ||
286 | |||
279 | config ARCH_FOOTBRIDGE | 287 | config ARCH_FOOTBRIDGE |
280 | bool "FootBridge" | 288 | bool "FootBridge" |
281 | select CPU_SA110 | 289 | select CPU_SA110 |
@@ -616,6 +624,8 @@ source "arch/arm/mach-ep93xx/Kconfig" | |||
616 | 624 | ||
617 | source "arch/arm/mach-footbridge/Kconfig" | 625 | source "arch/arm/mach-footbridge/Kconfig" |
618 | 626 | ||
627 | source "arch/arm/mach-gemini/Kconfig" | ||
628 | |||
619 | source "arch/arm/mach-integrator/Kconfig" | 629 | source "arch/arm/mach-integrator/Kconfig" |
620 | 630 | ||
621 | source "arch/arm/mach-iop32x/Kconfig" | 631 | source "arch/arm/mach-iop32x/Kconfig" |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 95186ef17e17..e84729bf13d4 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -72,6 +72,7 @@ tune-$(CONFIG_CPU_ARM920T) :=-mtune=arm9tdmi | |||
72 | tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi | 72 | tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi |
73 | tune-$(CONFIG_CPU_ARM925T) :=-mtune=arm9tdmi | 73 | tune-$(CONFIG_CPU_ARM925T) :=-mtune=arm9tdmi |
74 | tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi | 74 | tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi |
75 | tune-$(CONFIG_CPU_FA526) :=-mtune=arm9tdmi | ||
75 | tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 | 76 | tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 |
76 | tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 | 77 | tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 |
77 | tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale | 78 | tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale |
@@ -113,6 +114,7 @@ endif | |||
113 | plat-$(CONFIG_PLAT_PXA) := pxa | 114 | plat-$(CONFIG_PLAT_PXA) := pxa |
114 | machine-$(CONFIG_ARCH_L7200) := l7200 | 115 | machine-$(CONFIG_ARCH_L7200) := l7200 |
115 | machine-$(CONFIG_ARCH_INTEGRATOR) := integrator | 116 | machine-$(CONFIG_ARCH_INTEGRATOR) := integrator |
117 | machine-$(CONFIG_ARCH_GEMINI) := gemini | ||
116 | textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000 | 118 | textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000 |
117 | machine-$(CONFIG_ARCH_CLPS711X) := clps711x | 119 | machine-$(CONFIG_ARCH_CLPS711X) := clps711x |
118 | machine-$(CONFIG_ARCH_IOP32X) := iop32x | 120 | machine-$(CONFIG_ARCH_IOP32X) := iop32x |
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index d14b827adcd6..b371fba1b954 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S | |||
@@ -465,6 +465,20 @@ __armv7_mmu_cache_on: | |||
465 | mcr p15, 0, r0, c7, c5, 4 @ ISB | 465 | mcr p15, 0, r0, c7, c5, 4 @ ISB |
466 | mov pc, r12 | 466 | mov pc, r12 |
467 | 467 | ||
468 | __fa526_cache_on: | ||
469 | mov r12, lr | ||
470 | bl __setup_mmu | ||
471 | mov r0, #0 | ||
472 | mcr p15, 0, r0, c7, c7, 0 @ Invalidate whole cache | ||
473 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
474 | mcr p15, 0, r0, c8, c7, 0 @ flush UTLB | ||
475 | mrc p15, 0, r0, c1, c0, 0 @ read control reg | ||
476 | orr r0, r0, #0x1000 @ I-cache enable | ||
477 | bl __common_mmu_cache_on | ||
478 | mov r0, #0 | ||
479 | mcr p15, 0, r0, c8, c7, 0 @ flush UTLB | ||
480 | mov pc, r12 | ||
481 | |||
468 | __arm6_mmu_cache_on: | 482 | __arm6_mmu_cache_on: |
469 | mov r12, lr | 483 | mov r12, lr |
470 | bl __setup_mmu | 484 | bl __setup_mmu |
@@ -654,6 +668,12 @@ proc_types: | |||
654 | b __armv4_mmu_cache_off | 668 | b __armv4_mmu_cache_off |
655 | b __armv5tej_mmu_cache_flush | 669 | b __armv5tej_mmu_cache_flush |
656 | 670 | ||
671 | .word 0x66015261 @ FA526 | ||
672 | .word 0xff01fff1 | ||
673 | b __fa526_cache_on | ||
674 | b __armv4_mmu_cache_off | ||
675 | b __fa526_cache_flush | ||
676 | |||
657 | @ These match on the architecture ID | 677 | @ These match on the architecture ID |
658 | 678 | ||
659 | .word 0x00020000 @ ARMv4T | 679 | .word 0x00020000 @ ARMv4T |
@@ -793,6 +813,12 @@ __armv4_mpu_cache_flush: | |||
793 | mcr p15, 0, ip, c7, c10, 4 @ drain WB | 813 | mcr p15, 0, ip, c7, c10, 4 @ drain WB |
794 | mov pc, lr | 814 | mov pc, lr |
795 | 815 | ||
816 | __fa526_cache_flush: | ||
817 | mov r1, #0 | ||
818 | mcr p15, 0, r1, c7, c14, 0 @ clean and invalidate D cache | ||
819 | mcr p15, 0, r1, c7, c5, 0 @ flush I cache | ||
820 | mcr p15, 0, r1, c7, c10, 4 @ drain WB | ||
821 | mov pc, lr | ||
796 | 822 | ||
797 | __armv6_mmu_cache_flush: | 823 | __armv6_mmu_cache_flush: |
798 | mov r1, #0 | 824 | mov r1, #0 |
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index bfb0cb9aaa97..bb7d695f3900 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h | |||
@@ -46,6 +46,14 @@ | |||
46 | # define MULTI_CACHE 1 | 46 | # define MULTI_CACHE 1 |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #if defined(CONFIG_CPU_FA526) | ||
50 | # ifdef _CACHE | ||
51 | # define MULTI_CACHE 1 | ||
52 | # else | ||
53 | # define _CACHE fa | ||
54 | # endif | ||
55 | #endif | ||
56 | |||
49 | #if defined(CONFIG_CPU_ARM926T) | 57 | #if defined(CONFIG_CPU_ARM926T) |
50 | # ifdef _CACHE | 58 | # ifdef _CACHE |
51 | # define MULTI_CACHE 1 | 59 | # define MULTI_CACHE 1 |
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index f341c9dbd662..e6eb8a67b807 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h | |||
@@ -76,6 +76,14 @@ | |||
76 | # endif | 76 | # endif |
77 | #endif | 77 | #endif |
78 | 78 | ||
79 | #ifdef CONFIG_CPU_COPY_FA | ||
80 | # ifdef _USER | ||
81 | # define MULTI_USER 1 | ||
82 | # else | ||
83 | # define _USER fa | ||
84 | # endif | ||
85 | #endif | ||
86 | |||
79 | #ifdef CONFIG_CPU_SA1100 | 87 | #ifdef CONFIG_CPU_SA1100 |
80 | # ifdef _USER | 88 | # ifdef _USER |
81 | # define MULTI_USER 1 | 89 | # define MULTI_USER 1 |
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index c6250311550b..3976412685f8 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h | |||
@@ -89,6 +89,14 @@ | |||
89 | # define CPU_NAME cpu_arm922 | 89 | # define CPU_NAME cpu_arm922 |
90 | # endif | 90 | # endif |
91 | # endif | 91 | # endif |
92 | # ifdef CONFIG_CPU_FA526 | ||
93 | # ifdef CPU_NAME | ||
94 | # undef MULTI_CPU | ||
95 | # define MULTI_CPU | ||
96 | # else | ||
97 | # define CPU_NAME cpu_fa526 | ||
98 | # endif | ||
99 | # endif | ||
92 | # ifdef CONFIG_CPU_ARM925T | 100 | # ifdef CONFIG_CPU_ARM925T |
93 | # ifdef CPU_NAME | 101 | # ifdef CPU_NAME |
94 | # undef MULTI_CPU | 102 | # undef MULTI_CPU |
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 0a0d49ae1e6d..bd4dc8ed53d5 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h | |||
@@ -125,6 +125,12 @@ extern unsigned int user_debug; | |||
125 | : : "r" (0) : "memory") | 125 | : : "r" (0) : "memory") |
126 | #define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \ | 126 | #define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \ |
127 | : : "r" (0) : "memory") | 127 | : : "r" (0) : "memory") |
128 | #elif defined(CONFIG_CPU_FA526) | ||
129 | #define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \ | ||
130 | : : "r" (0) : "memory") | ||
131 | #define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \ | ||
132 | : : "r" (0) : "memory") | ||
133 | #define dmb() __asm__ __volatile__ ("" : : : "memory") | ||
128 | #else | 134 | #else |
129 | #define isb() __asm__ __volatile__ ("" : : : "memory") | 135 | #define isb() __asm__ __volatile__ ("" : : : "memory") |
130 | #define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \ | 136 | #define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \ |
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index b543a054a17e..a62218013c78 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #define TLB_V6_D_ASID (1 << 17) | 39 | #define TLB_V6_D_ASID (1 << 17) |
40 | #define TLB_V6_I_ASID (1 << 18) | 40 | #define TLB_V6_I_ASID (1 << 18) |
41 | 41 | ||
42 | #define TLB_BTB (1 << 28) | ||
42 | #define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */ | 43 | #define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */ |
43 | #define TLB_DCLEAN (1 << 30) | 44 | #define TLB_DCLEAN (1 << 30) |
44 | #define TLB_WB (1 << 31) | 45 | #define TLB_WB (1 << 31) |
@@ -53,6 +54,7 @@ | |||
53 | * v4wb - ARMv4 with write buffer without I TLB flush entry instruction | 54 | * v4wb - ARMv4 with write buffer without I TLB flush entry instruction |
54 | * v4wbi - ARMv4 with write buffer with I TLB flush entry instruction | 55 | * v4wbi - ARMv4 with write buffer with I TLB flush entry instruction |
55 | * fr - Feroceon (v4wbi with non-outer-cacheable page table walks) | 56 | * fr - Feroceon (v4wbi with non-outer-cacheable page table walks) |
57 | * fa - Faraday (v4 with write buffer with UTLB and branch target buffer (BTB)) | ||
56 | * v6wbi - ARMv6 with write buffer with I TLB flush entry instruction | 58 | * v6wbi - ARMv6 with write buffer with I TLB flush entry instruction |
57 | * v7wbi - identical to v6wbi | 59 | * v7wbi - identical to v6wbi |
58 | */ | 60 | */ |
@@ -89,6 +91,22 @@ | |||
89 | # define v4_always_flags (-1UL) | 91 | # define v4_always_flags (-1UL) |
90 | #endif | 92 | #endif |
91 | 93 | ||
94 | #define fa_tlb_flags (TLB_WB | TLB_BTB | TLB_DCLEAN | \ | ||
95 | TLB_V4_U_FULL | TLB_V4_U_PAGE) | ||
96 | |||
97 | #ifdef CONFIG_CPU_TLB_FA | ||
98 | # define fa_possible_flags fa_tlb_flags | ||
99 | # define fa_always_flags fa_tlb_flags | ||
100 | # ifdef _TLB | ||
101 | # define MULTI_TLB 1 | ||
102 | # else | ||
103 | # define _TLB fa | ||
104 | # endif | ||
105 | #else | ||
106 | # define fa_possible_flags 0 | ||
107 | # define fa_always_flags (-1UL) | ||
108 | #endif | ||
109 | |||
92 | #define v4wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \ | 110 | #define v4wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \ |
93 | TLB_V4_I_FULL | TLB_V4_D_FULL | \ | 111 | TLB_V4_I_FULL | TLB_V4_D_FULL | \ |
94 | TLB_V4_I_PAGE | TLB_V4_D_PAGE) | 112 | TLB_V4_I_PAGE | TLB_V4_D_PAGE) |
@@ -140,7 +158,7 @@ | |||
140 | # define v4wb_always_flags (-1UL) | 158 | # define v4wb_always_flags (-1UL) |
141 | #endif | 159 | #endif |
142 | 160 | ||
143 | #define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \ | 161 | #define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \ |
144 | TLB_V6_I_FULL | TLB_V6_D_FULL | \ | 162 | TLB_V6_I_FULL | TLB_V6_D_FULL | \ |
145 | TLB_V6_I_PAGE | TLB_V6_D_PAGE | \ | 163 | TLB_V6_I_PAGE | TLB_V6_D_PAGE | \ |
146 | TLB_V6_I_ASID | TLB_V6_D_ASID) | 164 | TLB_V6_I_ASID | TLB_V6_D_ASID) |
@@ -267,6 +285,7 @@ extern struct cpu_tlb_fns cpu_tlb; | |||
267 | v4wbi_possible_flags | \ | 285 | v4wbi_possible_flags | \ |
268 | fr_possible_flags | \ | 286 | fr_possible_flags | \ |
269 | v4wb_possible_flags | \ | 287 | v4wb_possible_flags | \ |
288 | fa_possible_flags | \ | ||
270 | v6wbi_possible_flags | \ | 289 | v6wbi_possible_flags | \ |
271 | v7wbi_possible_flags) | 290 | v7wbi_possible_flags) |
272 | 291 | ||
@@ -275,6 +294,7 @@ extern struct cpu_tlb_fns cpu_tlb; | |||
275 | v4wbi_always_flags & \ | 294 | v4wbi_always_flags & \ |
276 | fr_always_flags & \ | 295 | fr_always_flags & \ |
277 | v4wb_always_flags & \ | 296 | v4wb_always_flags & \ |
297 | fa_always_flags & \ | ||
278 | v6wbi_always_flags & \ | 298 | v6wbi_always_flags & \ |
279 | v7wbi_always_flags) | 299 | v7wbi_always_flags) |
280 | 300 | ||
@@ -297,9 +317,7 @@ static inline void local_flush_tlb_all(void) | |||
297 | if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL)) | 317 | if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL)) |
298 | asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc"); | 318 | asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc"); |
299 | 319 | ||
300 | if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | | 320 | if (tlb_flag(TLB_BTB)) { |
301 | TLB_V6_I_PAGE | TLB_V6_D_PAGE | | ||
302 | TLB_V6_I_ASID | TLB_V6_D_ASID)) { | ||
303 | /* flush the branch target cache */ | 321 | /* flush the branch target cache */ |
304 | asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); | 322 | asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); |
305 | dsb(); | 323 | dsb(); |
@@ -334,9 +352,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm) | |||
334 | if (tlb_flag(TLB_V6_I_ASID)) | 352 | if (tlb_flag(TLB_V6_I_ASID)) |
335 | asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc"); | 353 | asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc"); |
336 | 354 | ||
337 | if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | | 355 | if (tlb_flag(TLB_BTB)) { |
338 | TLB_V6_I_PAGE | TLB_V6_D_PAGE | | ||
339 | TLB_V6_I_ASID | TLB_V6_D_ASID)) { | ||
340 | /* flush the branch target cache */ | 356 | /* flush the branch target cache */ |
341 | asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); | 357 | asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); |
342 | dsb(); | 358 | dsb(); |
@@ -374,9 +390,7 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) | |||
374 | if (tlb_flag(TLB_V6_I_PAGE)) | 390 | if (tlb_flag(TLB_V6_I_PAGE)) |
375 | asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc"); | 391 | asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc"); |
376 | 392 | ||
377 | if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | | 393 | if (tlb_flag(TLB_BTB)) { |
378 | TLB_V6_I_PAGE | TLB_V6_D_PAGE | | ||
379 | TLB_V6_I_ASID | TLB_V6_D_ASID)) { | ||
380 | /* flush the branch target cache */ | 394 | /* flush the branch target cache */ |
381 | asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); | 395 | asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); |
382 | dsb(); | 396 | dsb(); |
@@ -411,9 +425,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr) | |||
411 | if (tlb_flag(TLB_V6_I_PAGE)) | 425 | if (tlb_flag(TLB_V6_I_PAGE)) |
412 | asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc"); | 426 | asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc"); |
413 | 427 | ||
414 | if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | | 428 | if (tlb_flag(TLB_BTB)) { |
415 | TLB_V6_I_PAGE | TLB_V6_D_PAGE | | ||
416 | TLB_V6_I_ASID | TLB_V6_D_ASID)) { | ||
417 | /* flush the branch target cache */ | 429 | /* flush the branch target cache */ |
418 | asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); | 430 | asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); |
419 | dsb(); | 431 | dsb(); |
diff --git a/arch/arm/mach-gemini/Kconfig b/arch/arm/mach-gemini/Kconfig new file mode 100644 index 000000000000..515b75cf2e8b --- /dev/null +++ b/arch/arm/mach-gemini/Kconfig | |||
@@ -0,0 +1,19 @@ | |||
1 | if ARCH_GEMINI | ||
2 | |||
3 | menu "Cortina Systems Gemini Implementations" | ||
4 | |||
5 | config MACH_RUT100 | ||
6 | bool "Teltonika RUT100" | ||
7 | select GEMINI_MEM_SWAP | ||
8 | help | ||
9 | Say Y here if you intend to run this kernel on a | ||
10 | Teltonika 3G Router RUT100. | ||
11 | |||
12 | endmenu | ||
13 | |||
14 | config GEMINI_MEM_SWAP | ||
15 | bool "Gemini memory is swapped" | ||
16 | help | ||
17 | Say Y here if Gemini memory is swapped by bootloader. | ||
18 | |||
19 | endif | ||
diff --git a/arch/arm/mach-gemini/Makefile b/arch/arm/mach-gemini/Makefile new file mode 100644 index 000000000000..719505b81821 --- /dev/null +++ b/arch/arm/mach-gemini/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | # Object file lists. | ||
6 | |||
7 | obj-y := irq.o mm.o time.o devices.o gpio.o | ||
8 | |||
9 | # Board-specific support | ||
10 | obj-$(CONFIG_MACH_RUT100) += board-rut1xx.o | ||
diff --git a/arch/arm/mach-gemini/Makefile.boot b/arch/arm/mach-gemini/Makefile.boot new file mode 100644 index 000000000000..22a52c228d93 --- /dev/null +++ b/arch/arm/mach-gemini/Makefile.boot | |||
@@ -0,0 +1,9 @@ | |||
1 | ifeq ($(CONFIG_GEMINI_MEM_SWAP),y) | ||
2 | zreladdr-y := 0x00008000 | ||
3 | params_phys-y := 0x00000100 | ||
4 | initrd_phys-y := 0x00800000 | ||
5 | else | ||
6 | zreladdr-y := 0x10008000 | ||
7 | params_phys-y := 0x10000100 | ||
8 | initrd_phys-y := 0x10800000 | ||
9 | endif | ||
diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c new file mode 100644 index 000000000000..e0de968e32a6 --- /dev/null +++ b/arch/arm/mach-gemini/board-rut1xx.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * Support for Teltonika RUT1xx | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/leds.h> | ||
15 | #include <linux/input.h> | ||
16 | #include <linux/gpio_keys.h> | ||
17 | |||
18 | #include <asm/mach-types.h> | ||
19 | #include <asm/mach/arch.h> | ||
20 | #include <asm/mach/time.h> | ||
21 | |||
22 | #include "common.h" | ||
23 | |||
24 | static struct gpio_keys_button rut1xx_keys[] = { | ||
25 | { | ||
26 | .code = KEY_SETUP, | ||
27 | .gpio = 60, | ||
28 | .active_low = 1, | ||
29 | .desc = "Reset to defaults", | ||
30 | .type = EV_KEY, | ||
31 | }, | ||
32 | }; | ||
33 | |||
34 | static struct gpio_keys_platform_data rut1xx_keys_data = { | ||
35 | .buttons = rut1xx_keys, | ||
36 | .nbuttons = ARRAY_SIZE(rut1xx_keys), | ||
37 | }; | ||
38 | |||
39 | static struct platform_device rut1xx_keys_device = { | ||
40 | .name = "gpio-keys", | ||
41 | .id = -1, | ||
42 | .dev = { | ||
43 | .platform_data = &rut1xx_keys_data, | ||
44 | }, | ||
45 | }; | ||
46 | |||
47 | static struct gpio_led rut100_leds[] = { | ||
48 | { | ||
49 | .name = "Power", | ||
50 | .default_trigger = "heartbeat", | ||
51 | .gpio = 17, | ||
52 | }, | ||
53 | { | ||
54 | .name = "GSM", | ||
55 | .default_trigger = "default-on", | ||
56 | .gpio = 7, | ||
57 | .active_low = 1, | ||
58 | }, | ||
59 | }; | ||
60 | |||
61 | static struct gpio_led_platform_data rut100_leds_data = { | ||
62 | .num_leds = ARRAY_SIZE(rut100_leds), | ||
63 | .leds = rut100_leds, | ||
64 | }; | ||
65 | |||
66 | static struct platform_device rut1xx_leds = { | ||
67 | .name = "leds-gpio", | ||
68 | .id = -1, | ||
69 | .dev = { | ||
70 | .platform_data = &rut100_leds_data, | ||
71 | }, | ||
72 | }; | ||
73 | |||
74 | static struct sys_timer rut1xx_timer = { | ||
75 | .init = gemini_timer_init, | ||
76 | }; | ||
77 | |||
78 | static void __init rut1xx_init(void) | ||
79 | { | ||
80 | gemini_gpio_init(); | ||
81 | platform_register_uart(); | ||
82 | platform_register_pflash(SZ_8M, NULL, 0); | ||
83 | platform_device_register(&rut1xx_leds); | ||
84 | platform_device_register(&rut1xx_keys_device); | ||
85 | } | ||
86 | |||
87 | MACHINE_START(RUT100, "Teltonika RUT100") | ||
88 | .phys_io = 0x7fffc000, | ||
89 | .io_pg_offst = ((0xffffc000) >> 18) & 0xfffc, | ||
90 | .boot_params = 0x100, | ||
91 | .map_io = gemini_map_io, | ||
92 | .init_irq = gemini_init_irq, | ||
93 | .timer = &rut1xx_timer, | ||
94 | .init_machine = rut1xx_init, | ||
95 | MACHINE_END | ||
diff --git a/arch/arm/mach-gemini/common.h b/arch/arm/mach-gemini/common.h new file mode 100644 index 000000000000..9392834a214f --- /dev/null +++ b/arch/arm/mach-gemini/common.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Common Gemini architecture functions | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef __GEMINI_COMMON_H__ | ||
13 | #define __GEMINI_COMMON_H__ | ||
14 | |||
15 | struct mtd_partition; | ||
16 | |||
17 | extern void gemini_map_io(void); | ||
18 | extern void gemini_init_irq(void); | ||
19 | extern void gemini_timer_init(void); | ||
20 | extern void gemini_gpio_init(void); | ||
21 | |||
22 | /* Common platform devices registration functions */ | ||
23 | extern int platform_register_uart(void); | ||
24 | extern int platform_register_pflash(unsigned int size, | ||
25 | struct mtd_partition *parts, | ||
26 | unsigned int nr_parts); | ||
27 | |||
28 | #endif /* __GEMINI_COMMON_H__ */ | ||
diff --git a/arch/arm/mach-gemini/devices.c b/arch/arm/mach-gemini/devices.c new file mode 100644 index 000000000000..6b525253d027 --- /dev/null +++ b/arch/arm/mach-gemini/devices.c | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * Common devices definition for Gemini | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/serial_8250.h> | ||
15 | #include <linux/mtd/physmap.h> | ||
16 | |||
17 | #include <mach/irqs.h> | ||
18 | #include <mach/hardware.h> | ||
19 | #include <mach/global_reg.h> | ||
20 | |||
21 | static struct plat_serial8250_port serial_platform_data[] = { | ||
22 | { | ||
23 | .membase = (void *)IO_ADDRESS(GEMINI_UART_BASE), | ||
24 | .mapbase = GEMINI_UART_BASE, | ||
25 | .irq = IRQ_UART, | ||
26 | .uartclk = UART_CLK, | ||
27 | .regshift = 2, | ||
28 | .iotype = UPIO_MEM, | ||
29 | .type = PORT_16550A, | ||
30 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_FIXED_TYPE, | ||
31 | }, | ||
32 | {}, | ||
33 | }; | ||
34 | |||
35 | static struct platform_device serial_device = { | ||
36 | .name = "serial8250", | ||
37 | .id = PLAT8250_DEV_PLATFORM, | ||
38 | .dev = { | ||
39 | .platform_data = serial_platform_data, | ||
40 | }, | ||
41 | }; | ||
42 | |||
43 | int platform_register_uart(void) | ||
44 | { | ||
45 | return platform_device_register(&serial_device); | ||
46 | } | ||
47 | |||
48 | static struct resource flash_resource = { | ||
49 | .start = GEMINI_FLASH_BASE, | ||
50 | .flags = IORESOURCE_MEM, | ||
51 | }; | ||
52 | |||
53 | static struct physmap_flash_data pflash_platform_data = {}; | ||
54 | |||
55 | static struct platform_device pflash_device = { | ||
56 | .name = "physmap-flash", | ||
57 | .id = 0, | ||
58 | .dev = { | ||
59 | .platform_data = &pflash_platform_data, | ||
60 | }, | ||
61 | .resource = &flash_resource, | ||
62 | .num_resources = 1, | ||
63 | }; | ||
64 | |||
65 | int platform_register_pflash(unsigned int size, struct mtd_partition *parts, | ||
66 | unsigned int nr_parts) | ||
67 | { | ||
68 | unsigned int reg; | ||
69 | |||
70 | reg = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_STATUS); | ||
71 | |||
72 | if ((reg & FLASH_TYPE_MASK) != FLASH_TYPE_PARALLEL) | ||
73 | return -ENXIO; | ||
74 | |||
75 | if (reg & FLASH_WIDTH_16BIT) | ||
76 | pflash_platform_data.width = 2; | ||
77 | else | ||
78 | pflash_platform_data.width = 1; | ||
79 | |||
80 | /* enable parallel flash pins and disable others */ | ||
81 | reg = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_MISC_CTRL); | ||
82 | reg &= ~PFLASH_PADS_DISABLE; | ||
83 | reg |= SFLASH_PADS_DISABLE | NAND_PADS_DISABLE; | ||
84 | __raw_writel(reg, IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_MISC_CTRL); | ||
85 | |||
86 | flash_resource.end = flash_resource.start + size - 1; | ||
87 | |||
88 | pflash_platform_data.parts = parts; | ||
89 | pflash_platform_data.nr_parts = nr_parts; | ||
90 | |||
91 | return platform_device_register(&pflash_device); | ||
92 | } | ||
diff --git a/arch/arm/mach-gemini/gpio.c b/arch/arm/mach-gemini/gpio.c new file mode 100644 index 000000000000..e7263854bc7b --- /dev/null +++ b/arch/arm/mach-gemini/gpio.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * Gemini gpiochip and interrupt routines | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
5 | * | ||
6 | * Based on plat-mxc/gpio.c: | ||
7 | * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de> | ||
8 | * Copyright 2008 Juergen Beisert, kernel@pengutronix.de | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/gpio.h> | ||
21 | |||
22 | #include <mach/hardware.h> | ||
23 | #include <mach/irqs.h> | ||
24 | |||
25 | #define GPIO_BASE(x) IO_ADDRESS(GEMINI_GPIO_BASE(x)) | ||
26 | |||
27 | /* GPIO registers definition */ | ||
28 | #define GPIO_DATA_OUT 0x0 | ||
29 | #define GPIO_DATA_IN 0x4 | ||
30 | #define GPIO_DIR 0x8 | ||
31 | #define GPIO_DATA_SET 0x10 | ||
32 | #define GPIO_DATA_CLR 0x14 | ||
33 | #define GPIO_PULL_EN 0x18 | ||
34 | #define GPIO_PULL_TYPE 0x1C | ||
35 | #define GPIO_INT_EN 0x20 | ||
36 | #define GPIO_INT_STAT 0x24 | ||
37 | #define GPIO_INT_MASK 0x2C | ||
38 | #define GPIO_INT_CLR 0x30 | ||
39 | #define GPIO_INT_TYPE 0x34 | ||
40 | #define GPIO_INT_BOTH_EDGE 0x38 | ||
41 | #define GPIO_INT_LEVEL 0x3C | ||
42 | #define GPIO_DEBOUNCE_EN 0x40 | ||
43 | #define GPIO_DEBOUNCE_PRESCALE 0x44 | ||
44 | |||
45 | #define GPIO_PORT_NUM 3 | ||
46 | |||
47 | static void _set_gpio_irqenable(unsigned int base, unsigned int index, | ||
48 | int enable) | ||
49 | { | ||
50 | unsigned int reg; | ||
51 | |||
52 | reg = __raw_readl(base + GPIO_INT_EN); | ||
53 | reg = (reg & (~(1 << index))) | (!!enable << index); | ||
54 | __raw_writel(reg, base + GPIO_INT_EN); | ||
55 | } | ||
56 | |||
57 | static void gpio_ack_irq(unsigned int irq) | ||
58 | { | ||
59 | unsigned int gpio = irq_to_gpio(irq); | ||
60 | unsigned int base = GPIO_BASE(gpio / 32); | ||
61 | |||
62 | __raw_writel(1 << (gpio % 32), base + GPIO_INT_CLR); | ||
63 | } | ||
64 | |||
65 | static void gpio_mask_irq(unsigned int irq) | ||
66 | { | ||
67 | unsigned int gpio = irq_to_gpio(irq); | ||
68 | unsigned int base = GPIO_BASE(gpio / 32); | ||
69 | |||
70 | _set_gpio_irqenable(base, gpio % 32, 0); | ||
71 | } | ||
72 | |||
73 | static void gpio_unmask_irq(unsigned int irq) | ||
74 | { | ||
75 | unsigned int gpio = irq_to_gpio(irq); | ||
76 | unsigned int base = GPIO_BASE(gpio / 32); | ||
77 | |||
78 | _set_gpio_irqenable(base, gpio % 32, 1); | ||
79 | } | ||
80 | |||
81 | static int gpio_set_irq_type(unsigned int irq, unsigned int type) | ||
82 | { | ||
83 | unsigned int gpio = irq_to_gpio(irq); | ||
84 | unsigned int gpio_mask = 1 << (gpio % 32); | ||
85 | unsigned int base = GPIO_BASE(gpio / 32); | ||
86 | unsigned int reg_both, reg_level, reg_type; | ||
87 | |||
88 | reg_type = __raw_readl(base + GPIO_INT_TYPE); | ||
89 | reg_level = __raw_readl(base + GPIO_INT_BOTH_EDGE); | ||
90 | reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE); | ||
91 | |||
92 | switch (type) { | ||
93 | case IRQ_TYPE_EDGE_BOTH: | ||
94 | reg_type &= ~gpio_mask; | ||
95 | reg_both |= gpio_mask; | ||
96 | break; | ||
97 | case IRQ_TYPE_EDGE_RISING: | ||
98 | reg_type &= ~gpio_mask; | ||
99 | reg_both &= ~gpio_mask; | ||
100 | reg_level &= ~gpio_mask; | ||
101 | break; | ||
102 | case IRQ_TYPE_EDGE_FALLING: | ||
103 | reg_type &= ~gpio_mask; | ||
104 | reg_both &= ~gpio_mask; | ||
105 | reg_level |= gpio_mask; | ||
106 | break; | ||
107 | case IRQ_TYPE_LEVEL_HIGH: | ||
108 | reg_type |= gpio_mask; | ||
109 | reg_level &= ~gpio_mask; | ||
110 | break; | ||
111 | case IRQ_TYPE_LEVEL_LOW: | ||
112 | reg_type |= gpio_mask; | ||
113 | reg_level |= gpio_mask; | ||
114 | break; | ||
115 | default: | ||
116 | return -EINVAL; | ||
117 | } | ||
118 | |||
119 | __raw_writel(reg_type, base + GPIO_INT_TYPE); | ||
120 | __raw_writel(reg_level, base + GPIO_INT_BOTH_EDGE); | ||
121 | __raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE); | ||
122 | |||
123 | gpio_ack_irq(irq); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
129 | { | ||
130 | unsigned int gpio_irq_no, irq_stat; | ||
131 | unsigned int port = (unsigned int)get_irq_data(irq); | ||
132 | |||
133 | irq_stat = __raw_readl(GPIO_BASE(port) + GPIO_INT_STAT); | ||
134 | |||
135 | gpio_irq_no = GPIO_IRQ_BASE + port * 32; | ||
136 | for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) { | ||
137 | |||
138 | if ((irq_stat & 1) == 0) | ||
139 | continue; | ||
140 | |||
141 | BUG_ON(!(irq_desc[gpio_irq_no].handle_irq)); | ||
142 | irq_desc[gpio_irq_no].handle_irq(gpio_irq_no, | ||
143 | &irq_desc[gpio_irq_no]); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | static struct irq_chip gpio_irq_chip = { | ||
148 | .name = "GPIO", | ||
149 | .ack = gpio_ack_irq, | ||
150 | .mask = gpio_mask_irq, | ||
151 | .unmask = gpio_unmask_irq, | ||
152 | .set_type = gpio_set_irq_type, | ||
153 | }; | ||
154 | |||
155 | static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, | ||
156 | int dir) | ||
157 | { | ||
158 | unsigned int base = GPIO_BASE(offset / 32); | ||
159 | unsigned int reg; | ||
160 | |||
161 | reg = __raw_readl(base + GPIO_DIR); | ||
162 | if (dir) | ||
163 | reg |= 1 << (offset % 32); | ||
164 | else | ||
165 | reg &= ~(1 << (offset % 32)); | ||
166 | __raw_writel(reg, base + GPIO_DIR); | ||
167 | } | ||
168 | |||
169 | static void gemini_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
170 | { | ||
171 | unsigned int base = GPIO_BASE(offset / 32); | ||
172 | |||
173 | if (value) | ||
174 | __raw_writel(1 << (offset % 32), base + GPIO_DATA_SET); | ||
175 | else | ||
176 | __raw_writel(1 << (offset % 32), base + GPIO_DATA_CLR); | ||
177 | } | ||
178 | |||
179 | static int gemini_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
180 | { | ||
181 | unsigned int base = GPIO_BASE(offset / 32); | ||
182 | |||
183 | return (__raw_readl(base + GPIO_DATA_IN) >> (offset % 32)) & 1; | ||
184 | } | ||
185 | |||
186 | static int gemini_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
187 | { | ||
188 | _set_gpio_direction(chip, offset, 0); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int gemini_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | ||
193 | int value) | ||
194 | { | ||
195 | _set_gpio_direction(chip, offset, 1); | ||
196 | gemini_gpio_set(chip, offset, value); | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static struct gpio_chip gemini_gpio_chip = { | ||
201 | .label = "Gemini", | ||
202 | .direction_input = gemini_gpio_direction_input, | ||
203 | .get = gemini_gpio_get, | ||
204 | .direction_output = gemini_gpio_direction_output, | ||
205 | .set = gemini_gpio_set, | ||
206 | .base = 0, | ||
207 | .ngpio = GPIO_PORT_NUM * 32, | ||
208 | }; | ||
209 | |||
210 | void __init gemini_gpio_init(void) | ||
211 | { | ||
212 | int i, j; | ||
213 | |||
214 | for (i = 0; i < GPIO_PORT_NUM; i++) { | ||
215 | /* disable, unmask and clear all interrupts */ | ||
216 | __raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_EN); | ||
217 | __raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_MASK); | ||
218 | __raw_writel(~0x0, GPIO_BASE(i) + GPIO_INT_CLR); | ||
219 | |||
220 | for (j = GPIO_IRQ_BASE + i * 32; | ||
221 | j < GPIO_IRQ_BASE + (i + 1) * 32; j++) { | ||
222 | set_irq_chip(j, &gpio_irq_chip); | ||
223 | set_irq_handler(j, handle_edge_irq); | ||
224 | set_irq_flags(j, IRQF_VALID); | ||
225 | } | ||
226 | |||
227 | set_irq_chained_handler(IRQ_GPIO(i), gpio_irq_handler); | ||
228 | set_irq_data(IRQ_GPIO(i), (void *)i); | ||
229 | } | ||
230 | |||
231 | BUG_ON(gpiochip_add(&gemini_gpio_chip)); | ||
232 | } | ||
diff --git a/arch/arm/mach-gemini/include/mach/debug-macro.S b/arch/arm/mach-gemini/include/mach/debug-macro.S new file mode 100644 index 000000000000..d04a6eaeae14 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/debug-macro.S | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Debugging macro include header | ||
3 | * | ||
4 | * Copyright (C) 1994-1999 Russell King | ||
5 | * Copyright (C) 2001-2006 Storlink, Corp. | ||
6 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <mach/hardware.h> | ||
13 | |||
14 | .macro addruart,rx | ||
15 | mrc p15, 0, \rx, c1, c0 | ||
16 | tst \rx, #1 @ MMU enabled? | ||
17 | ldreq \rx, =GEMINI_UART_BASE @ physical | ||
18 | ldrne \rx, =IO_ADDRESS(GEMINI_UART_BASE) @ virtual | ||
19 | .endm | ||
20 | |||
21 | #define UART_SHIFT 2 | ||
22 | #define FLOW_CONTROL | ||
23 | #include <asm/hardware/debug-8250.S> | ||
diff --git a/arch/arm/mach-gemini/include/mach/entry-macro.S b/arch/arm/mach-gemini/include/mach/entry-macro.S new file mode 100644 index 000000000000..1624f91a2b8b --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/entry-macro.S | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Low-level IRQ helper macros for Gemini platform. | ||
3 | * | ||
4 | * Copyright (C) 2001-2006 Storlink, Corp. | ||
5 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | #include <mach/hardware.h> | ||
12 | |||
13 | #define IRQ_STATUS 0x14 | ||
14 | |||
15 | .macro disable_fiq | ||
16 | .endm | ||
17 | |||
18 | .macro get_irqnr_preamble, base, tmp | ||
19 | .endm | ||
20 | |||
21 | .macro arch_ret_to_user, tmp1, tmp2 | ||
22 | .endm | ||
23 | |||
24 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
25 | ldr \irqstat, =IO_ADDRESS(GEMINI_INTERRUPT_BASE + IRQ_STATUS) | ||
26 | ldr \irqnr, [\irqstat] | ||
27 | cmp \irqnr, #0 | ||
28 | beq 2313f | ||
29 | mov \tmp, \irqnr | ||
30 | mov \irqnr, #0 | ||
31 | 2312: | ||
32 | tst \tmp, #1 | ||
33 | bne 2313f | ||
34 | add \irqnr, \irqnr, #1 | ||
35 | mov \tmp, \tmp, lsr #1 | ||
36 | cmp \irqnr, #31 | ||
37 | bcc 2312b | ||
38 | 2313: | ||
39 | .endm | ||
diff --git a/arch/arm/mach-gemini/include/mach/global_reg.h b/arch/arm/mach-gemini/include/mach/global_reg.h new file mode 100644 index 000000000000..de7ff7e849fc --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/global_reg.h | |||
@@ -0,0 +1,278 @@ | |||
1 | /* | ||
2 | * This file contains the hardware definitions for Gemini. | ||
3 | * | ||
4 | * Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | #ifndef __MACH_GLOBAL_REG_H | ||
12 | #define __MACH_GLOBAL_REG_H | ||
13 | |||
14 | /* Global Word ID Register*/ | ||
15 | #define GLOBAL_ID 0x00 | ||
16 | |||
17 | #define CHIP_ID(reg) ((reg) >> 8) | ||
18 | #define CHIP_REVISION(reg) ((reg) & 0xFF) | ||
19 | |||
20 | /* Global Status Register */ | ||
21 | #define GLOBAL_STATUS 0x04 | ||
22 | |||
23 | #define CPU_BIG_ENDIAN (1 << 31) | ||
24 | #define PLL_OSC_30M (1 << 30) /* else 60MHz */ | ||
25 | |||
26 | #define OPERATION_MODE_MASK (0xF << 26) | ||
27 | #define OPM_IDDQ (0xF << 26) | ||
28 | #define OPM_NAND (0xE << 26) | ||
29 | #define OPM_RING (0xD << 26) | ||
30 | #define OPM_DIRECT_BOOT (0xC << 26) | ||
31 | #define OPM_USB1_PHY_TEST (0xB << 26) | ||
32 | #define OPM_USB0_PHY_TEST (0xA << 26) | ||
33 | #define OPM_SATA1_PHY_TEST (0x9 << 26) | ||
34 | #define OPM_SATA0_PHY_TEST (0x8 << 26) | ||
35 | #define OPM_ICE_ARM (0x7 << 26) | ||
36 | #define OPM_ICE_FARADAY (0x6 << 26) | ||
37 | #define OPM_PLL_BYPASS (0x5 << 26) | ||
38 | #define OPM_DEBUG (0x4 << 26) | ||
39 | #define OPM_BURN_IN (0x3 << 26) | ||
40 | #define OPM_MBIST (0x2 << 26) | ||
41 | #define OPM_SCAN (0x1 << 26) | ||
42 | #define OPM_REAL (0x0 << 26) | ||
43 | |||
44 | #define FLASH_TYPE_MASK (0x3 << 24) | ||
45 | #define FLASH_TYPE_NAND_2K (0x3 << 24) | ||
46 | #define FLASH_TYPE_NAND_512 (0x2 << 24) | ||
47 | #define FLASH_TYPE_PARALLEL (0x1 << 24) | ||
48 | #define FLASH_TYPE_SERIAL (0x0 << 24) | ||
49 | /* if parallel */ | ||
50 | #define FLASH_WIDTH_16BIT (1 << 23) /* else 8 bit */ | ||
51 | /* if serial */ | ||
52 | #define FLASH_ATMEL (1 << 23) /* else STM */ | ||
53 | |||
54 | #define FLASH_SIZE_MASK (0x3 << 21) | ||
55 | #define NAND_256M (0x3 << 21) /* and more */ | ||
56 | #define NAND_128M (0x2 << 21) | ||
57 | #define NAND_64M (0x1 << 21) | ||
58 | #define NAND_32M (0x0 << 21) | ||
59 | #define ATMEL_16M (0x3 << 21) /* and more */ | ||
60 | #define ATMEL_8M (0x2 << 21) | ||
61 | #define ATMEL_4M_2M (0x1 << 21) | ||
62 | #define ATMEL_1M (0x0 << 21) /* and less */ | ||
63 | #define STM_32M (1 << 22) /* and more */ | ||
64 | #define STM_16M (0 << 22) /* and less */ | ||
65 | |||
66 | #define FLASH_PARALLEL_HIGH_PIN_CNT (1 << 20) /* else low pin cnt */ | ||
67 | |||
68 | #define CPU_AHB_RATIO_MASK (0x3 << 18) | ||
69 | #define CPU_AHB_1_1 (0x0 << 18) | ||
70 | #define CPU_AHB_3_2 (0x1 << 18) | ||
71 | #define CPU_AHB_24_13 (0x2 << 18) | ||
72 | #define CPU_AHB_2_1 (0x3 << 18) | ||
73 | |||
74 | #define REG_TO_AHB_SPEED(reg) ((((reg) >> 15) & 0x7) * 10 + 130) | ||
75 | #define AHB_SPEED_TO_REG(x) ((((x - 130)) / 10) << 15) | ||
76 | |||
77 | /* it is posible to override some settings, use >> OVERRIDE_xxxx_SHIFT */ | ||
78 | #define OVERRIDE_FLASH_TYPE_SHIFT 16 | ||
79 | #define OVERRIDE_FLASH_WIDTH_SHIFT 16 | ||
80 | #define OVERRIDE_FLASH_SIZE_SHIFT 16 | ||
81 | #define OVERRIDE_CPU_AHB_RATIO_SHIFT 15 | ||
82 | #define OVERRIDE_AHB_SPEED_SHIFT 15 | ||
83 | |||
84 | /* Global PLL Control Register */ | ||
85 | #define GLOBAL_PLL_CTRL 0x08 | ||
86 | |||
87 | #define PLL_BYPASS (1 << 31) | ||
88 | #define PLL_POWER_DOWN (1 << 8) | ||
89 | #define PLL_CONTROL_Q (0x1F << 0) | ||
90 | |||
91 | /* Global Soft Reset Control Register */ | ||
92 | #define GLOBAL_RESET 0x0C | ||
93 | |||
94 | #define RESET_GLOBAL (1 << 31) | ||
95 | #define RESET_CPU1 (1 << 30) | ||
96 | #define RESET_TVE (1 << 28) | ||
97 | #define RESET_SATA1 (1 << 27) | ||
98 | #define RESET_SATA0 (1 << 26) | ||
99 | #define RESET_CIR (1 << 25) | ||
100 | #define RESET_EXT_DEV (1 << 24) | ||
101 | #define RESET_WD (1 << 23) | ||
102 | #define RESET_GPIO2 (1 << 22) | ||
103 | #define RESET_GPIO1 (1 << 21) | ||
104 | #define RESET_GPIO0 (1 << 20) | ||
105 | #define RESET_SSP (1 << 19) | ||
106 | #define RESET_UART (1 << 18) | ||
107 | #define RESET_TIMER (1 << 17) | ||
108 | #define RESET_RTC (1 << 16) | ||
109 | #define RESET_INT1 (1 << 15) | ||
110 | #define RESET_INT0 (1 << 14) | ||
111 | #define RESET_LCD (1 << 13) | ||
112 | #define RESET_LPC (1 << 12) | ||
113 | #define RESET_APB (1 << 11) | ||
114 | #define RESET_DMA (1 << 10) | ||
115 | #define RESET_USB1 (1 << 9) | ||
116 | #define RESET_USB0 (1 << 8) | ||
117 | #define RESET_PCI (1 << 7) | ||
118 | #define RESET_GMAC1 (1 << 6) | ||
119 | #define RESET_GMAC0 (1 << 5) | ||
120 | #define RESET_SECURITY (1 << 4) | ||
121 | #define RESET_RAID (1 << 3) | ||
122 | #define RESET_IDE (1 << 2) | ||
123 | #define RESET_FLASH (1 << 1) | ||
124 | #define RESET_DRAM (1 << 0) | ||
125 | |||
126 | /* Global IO Pad Driving Capability Control Register */ | ||
127 | #define GLOBAL_IO_DRIVING_CTRL 0x10 | ||
128 | |||
129 | #define DRIVING_CURRENT_MASK 0x3 | ||
130 | |||
131 | /* here 00-4mA, 01-8mA, 10-12mA, 11-16mA */ | ||
132 | #define GPIO1_PADS_31_28_SHIFT 28 | ||
133 | #define GPIO0_PADS_31_16_SHIFT 26 | ||
134 | #define GPIO0_PADS_15_0_SHIFT 24 | ||
135 | #define PCI_AND_EXT_RESET_PADS_SHIFT 22 | ||
136 | #define IDE_PADS_SHIFT 20 | ||
137 | #define GMAC1_PADS_SHIFT 18 | ||
138 | #define GMAC0_PADS_SHIFT 16 | ||
139 | /* DRAM is not in mA and poorly documented */ | ||
140 | #define DRAM_CLOCK_PADS_SHIFT 8 | ||
141 | #define DRAM_DATA_PADS_SHIFT 4 | ||
142 | #define DRAM_CONTROL_PADS_SHIFT 0 | ||
143 | |||
144 | /* Global IO Pad Slew Rate Control Register */ | ||
145 | #define GLOBAL_IO_SLEW_RATE_CTRL 0x14 | ||
146 | |||
147 | #define GPIO1_PADS_31_28_SLOW (1 << 10) | ||
148 | #define GPIO0_PADS_31_16_SLOW (1 << 9) | ||
149 | #define GPIO0_PADS_15_0_SLOW (1 << 8) | ||
150 | #define PCI_PADS_SLOW (1 << 7) | ||
151 | #define IDE_PADS_SLOW (1 << 6) | ||
152 | #define GMAC1_PADS_SLOW (1 << 5) | ||
153 | #define GMAC0_PADS_SLOW (1 << 4) | ||
154 | #define DRAM_CLOCK_PADS_SLOW (1 << 1) | ||
155 | #define DRAM_IO_PADS_SLOW (1 << 0) | ||
156 | |||
157 | /* | ||
158 | * General skew control defines | ||
159 | * 16 steps, each step is around 0.2ns | ||
160 | */ | ||
161 | #define SKEW_MASK 0xF | ||
162 | |||
163 | /* Global IDE PAD Skew Control Register */ | ||
164 | #define GLOBAL_IDE_SKEW_CTRL 0x18 | ||
165 | |||
166 | #define IDE1_HOST_STROBE_DELAY_SHIFT 28 | ||
167 | #define IDE1_DEVICE_STROBE_DELAY_SHIFT 24 | ||
168 | #define IDE1_OUTPUT_IO_SKEW_SHIFT 20 | ||
169 | #define IDE1_INPUT_IO_SKEW_SHIFT 16 | ||
170 | #define IDE0_HOST_STROBE_DELAY_SHIFT 12 | ||
171 | #define IDE0_DEVICE_STROBE_DELAY_SHIFT 8 | ||
172 | #define IDE0_OUTPUT_IO_SKEW_SHIFT 4 | ||
173 | #define IDE0_INPUT_IO_SKEW_SHIFT 0 | ||
174 | |||
175 | /* Global GMAC Control Pad Skew Control Register */ | ||
176 | #define GLOBAL_GMAC_CTRL_SKEW_CTRL 0x1C | ||
177 | |||
178 | #define GMAC1_TXC_SKEW_SHIFT 28 | ||
179 | #define GMAC1_TXEN_SKEW_SHIFT 24 | ||
180 | #define GMAC1_RXC_SKEW_SHIFT 20 | ||
181 | #define GMAC1_RXDV_SKEW_SHIFT 16 | ||
182 | #define GMAC0_TXC_SKEW_SHIFT 12 | ||
183 | #define GMAC0_TXEN_SKEW_SHIFT 8 | ||
184 | #define GMAC0_RXC_SKEW_SHIFT 4 | ||
185 | #define GMAC0_RXDV_SKEW_SHIFT 0 | ||
186 | |||
187 | /* Global GMAC0 Data PAD Skew Control Register */ | ||
188 | #define GLOBAL_GMAC0_DATA_SKEW_CTRL 0x20 | ||
189 | /* Global GMAC1 Data PAD Skew Control Register */ | ||
190 | #define GLOBAL_GMAC1_DATA_SKEW_CTRL 0x24 | ||
191 | |||
192 | #define GMAC_TXD_SKEW_SHIFT(x) (((x) * 4) + 16) | ||
193 | #define GMAC_RXD_SKEW_SHIFT(x) ((x) * 4) | ||
194 | |||
195 | /* CPU has two AHB busses. */ | ||
196 | |||
197 | /* Global Arbitration0 Control Register */ | ||
198 | #define GLOBAL_ARBITRATION0_CTRL 0x28 | ||
199 | |||
200 | #define BOOT_CONTROLLER_HIGH_PRIO (1 << 3) | ||
201 | #define DMA_BUS1_HIGH_PRIO (1 << 2) | ||
202 | #define CPU0_HIGH_PRIO (1 << 0) | ||
203 | |||
204 | /* Global Arbitration1 Control Register */ | ||
205 | #define GLOBAL_ARBITRATION1_CTRL 0x2C | ||
206 | |||
207 | #define TVE_HIGH_PRIO (1 << 9) | ||
208 | #define PCI_HIGH_PRIO (1 << 8) | ||
209 | #define USB1_HIGH_PRIO (1 << 7) | ||
210 | #define USB0_HIGH_PRIO (1 << 6) | ||
211 | #define GMAC1_HIGH_PRIO (1 << 5) | ||
212 | #define GMAC0_HIGH_PRIO (1 << 4) | ||
213 | #define SECURITY_HIGH_PRIO (1 << 3) | ||
214 | #define RAID_HIGH_PRIO (1 << 2) | ||
215 | #define IDE_HIGH_PRIO (1 << 1) | ||
216 | #define DMA_BUS2_HIGH_PRIO (1 << 0) | ||
217 | |||
218 | /* Common bits for both arbitration registers */ | ||
219 | #define BURST_LENGTH_SHIFT 16 | ||
220 | #define BURST_LENGTH_MASK (0x3F << 16) | ||
221 | |||
222 | /* Miscellaneous Control Register */ | ||
223 | #define GLOBAL_MISC_CTRL 0x30 | ||
224 | |||
225 | #define MEMORY_SPACE_SWAP (1 << 31) | ||
226 | #define USB1_PLUG_MINIB (1 << 30) /* else plug is mini-A */ | ||
227 | #define USB0_PLUG_MINIB (1 << 29) | ||
228 | #define GMAC_GMII (1 << 28) | ||
229 | #define GMAC_1_ENABLE (1 << 27) | ||
230 | /* TODO: define ATA/SATA bits */ | ||
231 | #define USB1_VBUS_ON (1 << 23) | ||
232 | #define USB0_VBUS_ON (1 << 22) | ||
233 | #define APB_CLKOUT_ENABLE (1 << 21) | ||
234 | #define TVC_CLKOUT_ENABLE (1 << 20) | ||
235 | #define EXT_CLKIN_ENABLE (1 << 19) | ||
236 | #define PCI_66MHZ (1 << 18) /* else 33 MHz */ | ||
237 | #define PCI_CLKOUT_ENABLE (1 << 17) | ||
238 | #define LPC_CLKOUT_ENABLE (1 << 16) | ||
239 | #define USB1_WAKEUP_ON (1 << 15) | ||
240 | #define USB0_WAKEUP_ON (1 << 14) | ||
241 | /* TODO: define PCI idle detect bits */ | ||
242 | #define TVC_PADS_ENABLE (1 << 9) | ||
243 | #define SSP_PADS_ENABLE (1 << 8) | ||
244 | #define LCD_PADS_ENABLE (1 << 7) | ||
245 | #define LPC_PADS_ENABLE (1 << 6) | ||
246 | #define PCI_PADS_ENABLE (1 << 5) | ||
247 | #define IDE_PADS_ENABLE (1 << 4) | ||
248 | #define DRAM_PADS_POWER_DOWN (1 << 3) | ||
249 | #define NAND_PADS_DISABLE (1 << 2) | ||
250 | #define PFLASH_PADS_DISABLE (1 << 1) | ||
251 | #define SFLASH_PADS_DISABLE (1 << 0) | ||
252 | |||
253 | /* Global Clock Control Register */ | ||
254 | #define GLOBAL_CLOCK_CTRL 0x34 | ||
255 | |||
256 | #define POWER_STATE_G0 (1 << 31) | ||
257 | #define POWER_STATE_S1 (1 << 30) /* else it is S3/S4 state */ | ||
258 | #define SECURITY_APB_AHB (1 << 29) | ||
259 | /* else Security APB clk will be 0.75xAHB */ | ||
260 | /* TODO: TVC clock divider */ | ||
261 | #define PCI_CLKRUN_ENABLE (1 << 16) | ||
262 | #define BOOT_CLK_DISABLE (1 << 13) | ||
263 | #define TVC_CLK_DISABLE (1 << 12) | ||
264 | #define FLASH_CLK_DISABLE (1 << 11) | ||
265 | #define DDR_CLK_DISABLE (1 << 10) | ||
266 | #define PCI_CLK_DISABLE (1 << 9) | ||
267 | #define IDE_CLK_DISABLE (1 << 8) | ||
268 | #define USB1_CLK_DISABLE (1 << 7) | ||
269 | #define USB0_CLK_DISABLE (1 << 6) | ||
270 | #define SATA1_CLK_DISABLE (1 << 5) | ||
271 | #define SATA0_CLK_DISABLE (1 << 4) | ||
272 | #define GMAC1_CLK_DISABLE (1 << 3) | ||
273 | #define GMAC0_CLK_DISABLE (1 << 2) | ||
274 | #define SECURITY_CLK_DISABLE (1 << 1) | ||
275 | |||
276 | /* TODO: other registers definitions if needed */ | ||
277 | |||
278 | #endif /* __MACH_GLOBAL_REG_H */ | ||
diff --git a/arch/arm/mach-gemini/include/mach/gpio.h b/arch/arm/mach-gemini/include/mach/gpio.h new file mode 100644 index 000000000000..3bc2c70f2989 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/gpio.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Gemini gpiolib specific defines | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef __MACH_GPIO_H__ | ||
13 | #define __MACH_GPIO_H__ | ||
14 | |||
15 | #include <mach/irqs.h> | ||
16 | #include <asm-generic/gpio.h> | ||
17 | |||
18 | #define gpio_get_value __gpio_get_value | ||
19 | #define gpio_set_value __gpio_set_value | ||
20 | #define gpio_cansleep __gpio_cansleep | ||
21 | |||
22 | #define gpio_to_irq(x) ((x) + GPIO_IRQ_BASE) | ||
23 | #define irq_to_gpio(x) ((x) - GPIO_IRQ_BASE) | ||
24 | |||
25 | #endif /* __MACH_GPIO_H__ */ | ||
diff --git a/arch/arm/mach-gemini/include/mach/hardware.h b/arch/arm/mach-gemini/include/mach/hardware.h new file mode 100644 index 000000000000..de6752674c05 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/hardware.h | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * This file contains the hardware definitions for Gemini. | ||
3 | * | ||
4 | * Copyright (C) 2001-2006 Storlink, Corp. | ||
5 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | #ifndef __MACH_HARDWARE_H | ||
13 | #define __MACH_HARDWARE_H | ||
14 | |||
15 | /* | ||
16 | * Memory Map definitions | ||
17 | */ | ||
18 | /* FIXME: Does it really swap SRAM like this? */ | ||
19 | #ifdef CONFIG_GEMINI_MEM_SWAP | ||
20 | # define GEMINI_DRAM_BASE 0x00000000 | ||
21 | # define GEMINI_SRAM_BASE 0x20000000 | ||
22 | #else | ||
23 | # define GEMINI_SRAM_BASE 0x00000000 | ||
24 | # define GEMINI_DRAM_BASE 0x10000000 | ||
25 | #endif | ||
26 | #define GEMINI_FLASH_BASE 0x30000000 | ||
27 | #define GEMINI_GLOBAL_BASE 0x40000000 | ||
28 | #define GEMINI_WAQTCHDOG_BASE 0x41000000 | ||
29 | #define GEMINI_UART_BASE 0x42000000 | ||
30 | #define GEMINI_TIMER_BASE 0x43000000 | ||
31 | #define GEMINI_LCD_BASE 0x44000000 | ||
32 | #define GEMINI_RTC_BASE 0x45000000 | ||
33 | #define GEMINI_SATA_BASE 0x46000000 | ||
34 | #define GEMINI_LPC_HOST_BASE 0x47000000 | ||
35 | #define GEMINI_LPC_IO_BASE 0x47800000 | ||
36 | #define GEMINI_INTERRUPT_BASE 0x48000000 | ||
37 | /* TODO: Different interrupt controlers when SMP | ||
38 | * #define GEMINI_INTERRUPT0_BASE 0x48000000 | ||
39 | * #define GEMINI_INTERRUPT1_BASE 0x49000000 | ||
40 | */ | ||
41 | #define GEMINI_SSP_CTRL_BASE 0x4A000000 | ||
42 | #define GEMINI_POWER_CTRL_BASE 0x4B000000 | ||
43 | #define GEMINI_CIR_BASE 0x4C000000 | ||
44 | #define GEMINI_GPIO_BASE(x) (0x4D000000 + (x) * 0x1000000) | ||
45 | #define GEMINI_PCI_IO_BASE 0x50000000 | ||
46 | #define GEMINI_PCI_MEM_BASE 0x58000000 | ||
47 | #define GEMINI_TOE_BASE 0x60000000 | ||
48 | #define GEMINI_GMAC0_BASE 0x6000A000 | ||
49 | #define GEMINI_GMAC1_BASE 0x6000E000 | ||
50 | #define GEMINI_SECURITY_BASE 0x62000000 | ||
51 | #define GEMINI_IDE0_BASE 0x63000000 | ||
52 | #define GEMINI_IDE1_BASE 0x63400000 | ||
53 | #define GEMINI_RAID_BASE 0x64000000 | ||
54 | #define GEMINI_FLASH_CTRL_BASE 0x65000000 | ||
55 | #define GEMINI_DRAM_CTRL_BASE 0x66000000 | ||
56 | #define GEMINI_GENERAL_DMA_BASE 0x67000000 | ||
57 | #define GEMINI_USB0_BASE 0x68000000 | ||
58 | #define GEMINI_USB1_BASE 0x69000000 | ||
59 | #define GEMINI_BIG_ENDIAN_BASE 0x80000000 | ||
60 | |||
61 | #define GEMINI_TIMER1_BASE GEMINI_TIMER_BASE | ||
62 | #define GEMINI_TIMER2_BASE (GEMINI_TIMER_BASE + 0x10) | ||
63 | #define GEMINI_TIMER3_BASE (GEMINI_TIMER_BASE + 0x20) | ||
64 | |||
65 | /* | ||
66 | * UART Clock when System clk is 150MHz | ||
67 | */ | ||
68 | #define UART_CLK 48000000 | ||
69 | |||
70 | /* | ||
71 | * macro to get at IO space when running virtually | ||
72 | */ | ||
73 | #define IO_ADDRESS(x) ((((x) & 0xFFF00000) >> 4) | ((x) & 0x000FFFFF) | 0xF0000000) | ||
74 | |||
75 | #endif | ||
diff --git a/arch/arm/mach-gemini/include/mach/io.h b/arch/arm/mach-gemini/include/mach/io.h new file mode 100644 index 000000000000..c548056b98b2 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/io.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001-2006 Storlink, Corp. | ||
3 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | */ | ||
10 | #ifndef __MACH_IO_H | ||
11 | #define __MACH_IO_H | ||
12 | |||
13 | #define IO_SPACE_LIMIT 0xffffffff | ||
14 | |||
15 | #define __io(a) __typesafe_io(a) | ||
16 | #define __mem_pci(a) (a) | ||
17 | |||
18 | #endif /* __MACH_IO_H */ | ||
diff --git a/arch/arm/mach-gemini/include/mach/irqs.h b/arch/arm/mach-gemini/include/mach/irqs.h new file mode 100644 index 000000000000..06bc47e77e8b --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/irqs.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001-2006 Storlink, Corp. | ||
3 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | */ | ||
10 | |||
11 | #ifndef __MACH_IRQS_H__ | ||
12 | #define __MACH_IRQS_H__ | ||
13 | |||
14 | #define IRQ_SERIRQ1 31 | ||
15 | #define IRQ_SERIRQ0 30 | ||
16 | #define IRQ_PCID 29 | ||
17 | #define IRQ_PCIC 28 | ||
18 | #define IRQ_PCIB 27 | ||
19 | #define IRQ_PWR 26 | ||
20 | #define IRQ_CIR 25 | ||
21 | #define IRQ_GPIO(x) (22 + (x)) | ||
22 | #define IRQ_SSP 21 | ||
23 | #define IRQ_LPC 20 | ||
24 | #define IRQ_LCD 19 | ||
25 | #define IRQ_UART 18 | ||
26 | #define IRQ_RTC 17 | ||
27 | #define IRQ_TIMER3 16 | ||
28 | #define IRQ_TIMER2 15 | ||
29 | #define IRQ_TIMER1 14 | ||
30 | #define IRQ_FLASH 12 | ||
31 | #define IRQ_USB1 11 | ||
32 | #define IRQ_USB0 10 | ||
33 | #define IRQ_DMA 9 | ||
34 | #define IRQ_PCI 8 | ||
35 | #define IRQ_IPSEC 7 | ||
36 | #define IRQ_RAID 6 | ||
37 | #define IRQ_IDE1 5 | ||
38 | #define IRQ_IDE0 4 | ||
39 | #define IRQ_WATCHDOG 3 | ||
40 | #define IRQ_GMAC1 2 | ||
41 | #define IRQ_GMAC0 1 | ||
42 | #define IRQ_IPI 0 | ||
43 | |||
44 | #define NORMAL_IRQ_NUM 32 | ||
45 | |||
46 | #define GPIO_IRQ_BASE NORMAL_IRQ_NUM | ||
47 | #define GPIO_IRQ_NUM (3 * 32) | ||
48 | |||
49 | #define ARCH_TIMER_IRQ IRQ_TIMER2 | ||
50 | |||
51 | #define NR_IRQS (NORMAL_IRQ_NUM + GPIO_IRQ_NUM) | ||
52 | |||
53 | #endif /* __MACH_IRQS_H__ */ | ||
diff --git a/arch/arm/mach-gemini/include/mach/memory.h b/arch/arm/mach-gemini/include/mach/memory.h new file mode 100644 index 000000000000..2d14d5bf1f9f --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/memory.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001-2006 Storlink, Corp. | ||
3 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | */ | ||
10 | #ifndef __MACH_MEMORY_H | ||
11 | #define __MACH_MEMORY_H | ||
12 | |||
13 | #ifdef CONFIG_GEMINI_MEM_SWAP | ||
14 | # define PHYS_OFFSET UL(0x00000000) | ||
15 | #else | ||
16 | # define PHYS_OFFSET UL(0x10000000) | ||
17 | #endif | ||
18 | |||
19 | #endif /* __MACH_MEMORY_H */ | ||
diff --git a/arch/arm/mach-gemini/include/mach/system.h b/arch/arm/mach-gemini/include/mach/system.h new file mode 100644 index 000000000000..bbbd72767a02 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/system.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001-2006 Storlink, Corp. | ||
3 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | */ | ||
10 | #ifndef __MACH_SYSTEM_H | ||
11 | #define __MACH_SYSTEM_H | ||
12 | |||
13 | #include <linux/io.h> | ||
14 | #include <mach/hardware.h> | ||
15 | #include <mach/global_reg.h> | ||
16 | |||
17 | static inline void arch_idle(void) | ||
18 | { | ||
19 | /* | ||
20 | * Because of broken hardware we have to enable interrupts or the CPU | ||
21 | * will never wakeup... Acctualy it is not very good to enable | ||
22 | * interrupts here since scheduler can miss a tick, but there is | ||
23 | * no other way around this. Platforms that needs it for power saving | ||
24 | * should call enable_hlt() in init code, since by default it is | ||
25 | * disabled. | ||
26 | */ | ||
27 | local_irq_enable(); | ||
28 | cpu_do_idle(); | ||
29 | } | ||
30 | |||
31 | static inline void arch_reset(char mode) | ||
32 | { | ||
33 | __raw_writel(RESET_GLOBAL | RESET_CPU1, | ||
34 | IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_RESET); | ||
35 | } | ||
36 | |||
37 | #endif /* __MACH_SYSTEM_H */ | ||
diff --git a/arch/arm/mach-gemini/include/mach/timex.h b/arch/arm/mach-gemini/include/mach/timex.h new file mode 100644 index 000000000000..dc5690ba975c --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/timex.h | |||
@@ -0,0 +1,13 @@ | |||
1 | /* | ||
2 | * Gemini timex specifications | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | /* When AHB bus frequency is 150MHz */ | ||
13 | #define CLOCK_TICK_RATE 38000000 | ||
diff --git a/arch/arm/mach-gemini/include/mach/uncompress.h b/arch/arm/mach-gemini/include/mach/uncompress.h new file mode 100644 index 000000000000..59c5df7e716c --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/uncompress.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
3 | * | ||
4 | * Based on mach-pxa/include/mach/uncompress.h: | ||
5 | * Copyright: (C) 2001 MontaVista Software Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #ifndef __MACH_UNCOMPRESS_H | ||
14 | #define __MACH_UNCOMPRESS_H | ||
15 | |||
16 | #include <linux/serial_reg.h> | ||
17 | #include <mach/hardware.h> | ||
18 | |||
19 | static volatile unsigned long *UART = (unsigned long *)GEMINI_UART_BASE; | ||
20 | |||
21 | /* | ||
22 | * The following code assumes the serial port has already been | ||
23 | * initialized by the bootloader. If you didn't setup a port in | ||
24 | * your bootloader then nothing will appear (which might be desired). | ||
25 | */ | ||
26 | static inline void putc(char c) | ||
27 | { | ||
28 | while (!(UART[UART_LSR] & UART_LSR_THRE)) | ||
29 | barrier(); | ||
30 | UART[UART_TX] = c; | ||
31 | } | ||
32 | |||
33 | #define flush() do { } while (0) | ||
34 | |||
35 | /* | ||
36 | * nothing to do | ||
37 | */ | ||
38 | #define arch_decomp_setup() | ||
39 | |||
40 | #define arch_decomp_wdog() | ||
41 | |||
42 | #endif /* __MACH_UNCOMPRESS_H */ | ||
diff --git a/arch/arm/mach-gemini/include/mach/vmalloc.h b/arch/arm/mach-gemini/include/mach/vmalloc.h new file mode 100644 index 000000000000..83e536d9436c --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/vmalloc.h | |||
@@ -0,0 +1,10 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #define VMALLOC_END 0xF0000000 | ||
diff --git a/arch/arm/mach-gemini/irq.c b/arch/arm/mach-gemini/irq.c new file mode 100644 index 000000000000..9e613ca8120d --- /dev/null +++ b/arch/arm/mach-gemini/irq.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * Interrupt routines for Gemini | ||
3 | * | ||
4 | * Copyright (C) 2001-2006 Storlink, Corp. | ||
5 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/ioport.h> | ||
15 | #include <linux/stddef.h> | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <asm/irq.h> | ||
19 | #include <asm/mach/irq.h> | ||
20 | #include <mach/hardware.h> | ||
21 | |||
22 | #define IRQ_SOURCE(base_addr) (base_addr + 0x00) | ||
23 | #define IRQ_MASK(base_addr) (base_addr + 0x04) | ||
24 | #define IRQ_CLEAR(base_addr) (base_addr + 0x08) | ||
25 | #define IRQ_TMODE(base_addr) (base_addr + 0x0C) | ||
26 | #define IRQ_TLEVEL(base_addr) (base_addr + 0x10) | ||
27 | #define IRQ_STATUS(base_addr) (base_addr + 0x14) | ||
28 | #define FIQ_SOURCE(base_addr) (base_addr + 0x20) | ||
29 | #define FIQ_MASK(base_addr) (base_addr + 0x24) | ||
30 | #define FIQ_CLEAR(base_addr) (base_addr + 0x28) | ||
31 | #define FIQ_TMODE(base_addr) (base_addr + 0x2C) | ||
32 | #define FIQ_LEVEL(base_addr) (base_addr + 0x30) | ||
33 | #define FIQ_STATUS(base_addr) (base_addr + 0x34) | ||
34 | |||
35 | static void gemini_ack_irq(unsigned int irq) | ||
36 | { | ||
37 | __raw_writel(1 << irq, IRQ_CLEAR(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); | ||
38 | } | ||
39 | |||
40 | static void gemini_mask_irq(unsigned int irq) | ||
41 | { | ||
42 | unsigned int mask; | ||
43 | |||
44 | mask = __raw_readl(IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); | ||
45 | mask &= ~(1 << irq); | ||
46 | __raw_writel(mask, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); | ||
47 | } | ||
48 | |||
49 | static void gemini_unmask_irq(unsigned int irq) | ||
50 | { | ||
51 | unsigned int mask; | ||
52 | |||
53 | mask = __raw_readl(IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); | ||
54 | mask |= (1 << irq); | ||
55 | __raw_writel(mask, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); | ||
56 | } | ||
57 | |||
58 | static struct irq_chip gemini_irq_chip = { | ||
59 | .name = "INTC", | ||
60 | .ack = gemini_ack_irq, | ||
61 | .mask = gemini_mask_irq, | ||
62 | .unmask = gemini_unmask_irq, | ||
63 | }; | ||
64 | |||
65 | static struct resource irq_resource = { | ||
66 | .name = "irq_handler", | ||
67 | .start = IO_ADDRESS(GEMINI_INTERRUPT_BASE), | ||
68 | .end = IO_ADDRESS(FIQ_STATUS(GEMINI_INTERRUPT_BASE)) + 4, | ||
69 | }; | ||
70 | |||
71 | void __init gemini_init_irq(void) | ||
72 | { | ||
73 | unsigned int i, mode = 0, level = 0; | ||
74 | |||
75 | /* | ||
76 | * Disable arch_idle() by default since it is buggy | ||
77 | * For more info see arch/arm/mach-gemini/include/mach/system.h | ||
78 | */ | ||
79 | disable_hlt(); | ||
80 | |||
81 | request_resource(&iomem_resource, &irq_resource); | ||
82 | |||
83 | for (i = 0; i < NR_IRQS; i++) { | ||
84 | set_irq_chip(i, &gemini_irq_chip); | ||
85 | if((i >= IRQ_TIMER1 && i <= IRQ_TIMER3) || (i >= IRQ_SERIRQ0 && i <= IRQ_SERIRQ1)) { | ||
86 | set_irq_handler(i, handle_edge_irq); | ||
87 | mode |= 1 << i; | ||
88 | level |= 1 << i; | ||
89 | } else { | ||
90 | set_irq_handler(i, handle_level_irq); | ||
91 | } | ||
92 | set_irq_flags(i, IRQF_VALID | IRQF_PROBE); | ||
93 | } | ||
94 | |||
95 | /* Disable all interrupts */ | ||
96 | __raw_writel(0, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); | ||
97 | __raw_writel(0, FIQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); | ||
98 | |||
99 | /* Set interrupt mode */ | ||
100 | __raw_writel(mode, IRQ_TMODE(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); | ||
101 | __raw_writel(level, IRQ_TLEVEL(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); | ||
102 | } | ||
diff --git a/arch/arm/mach-gemini/mm.c b/arch/arm/mach-gemini/mm.c new file mode 100644 index 000000000000..51948242ec09 --- /dev/null +++ b/arch/arm/mach-gemini/mm.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * Static mappings for Gemini | ||
3 | * | ||
4 | * Copyright (C) 2001-2006 Storlink, Corp. | ||
5 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | #include <linux/mm.h> | ||
13 | #include <linux/init.h> | ||
14 | |||
15 | #include <asm/mach/map.h> | ||
16 | |||
17 | #include <mach/hardware.h> | ||
18 | |||
19 | /* Page table mapping for I/O region */ | ||
20 | static struct map_desc gemini_io_desc[] __initdata = { | ||
21 | { | ||
22 | .virtual = IO_ADDRESS(GEMINI_GLOBAL_BASE), | ||
23 | .pfn =__phys_to_pfn(GEMINI_GLOBAL_BASE), | ||
24 | .length = SZ_512K, | ||
25 | .type = MT_DEVICE, | ||
26 | }, { | ||
27 | .virtual = IO_ADDRESS(GEMINI_UART_BASE), | ||
28 | .pfn = __phys_to_pfn(GEMINI_UART_BASE), | ||
29 | .length = SZ_512K, | ||
30 | .type = MT_DEVICE, | ||
31 | }, { | ||
32 | .virtual = IO_ADDRESS(GEMINI_TIMER_BASE), | ||
33 | .pfn = __phys_to_pfn(GEMINI_TIMER_BASE), | ||
34 | .length = SZ_512K, | ||
35 | .type = MT_DEVICE, | ||
36 | }, { | ||
37 | .virtual = IO_ADDRESS(GEMINI_INTERRUPT_BASE), | ||
38 | .pfn = __phys_to_pfn(GEMINI_INTERRUPT_BASE), | ||
39 | .length = SZ_512K, | ||
40 | .type = MT_DEVICE, | ||
41 | }, { | ||
42 | .virtual = IO_ADDRESS(GEMINI_POWER_CTRL_BASE), | ||
43 | .pfn = __phys_to_pfn(GEMINI_POWER_CTRL_BASE), | ||
44 | .length = SZ_512K, | ||
45 | .type = MT_DEVICE, | ||
46 | }, { | ||
47 | .virtual = IO_ADDRESS(GEMINI_GPIO_BASE(0)), | ||
48 | .pfn = __phys_to_pfn(GEMINI_GPIO_BASE(0)), | ||
49 | .length = SZ_512K, | ||
50 | .type = MT_DEVICE, | ||
51 | }, { | ||
52 | .virtual = IO_ADDRESS(GEMINI_GPIO_BASE(1)), | ||
53 | .pfn = __phys_to_pfn(GEMINI_GPIO_BASE(1)), | ||
54 | .length = SZ_512K, | ||
55 | .type = MT_DEVICE, | ||
56 | }, { | ||
57 | .virtual = IO_ADDRESS(GEMINI_GPIO_BASE(2)), | ||
58 | .pfn = __phys_to_pfn(GEMINI_GPIO_BASE(2)), | ||
59 | .length = SZ_512K, | ||
60 | .type = MT_DEVICE, | ||
61 | }, { | ||
62 | .virtual = IO_ADDRESS(GEMINI_FLASH_CTRL_BASE), | ||
63 | .pfn = __phys_to_pfn(GEMINI_FLASH_CTRL_BASE), | ||
64 | .length = SZ_512K, | ||
65 | .type = MT_DEVICE, | ||
66 | }, { | ||
67 | .virtual = IO_ADDRESS(GEMINI_DRAM_CTRL_BASE), | ||
68 | .pfn = __phys_to_pfn(GEMINI_DRAM_CTRL_BASE), | ||
69 | .length = SZ_512K, | ||
70 | .type = MT_DEVICE, | ||
71 | }, { | ||
72 | .virtual = IO_ADDRESS(GEMINI_GENERAL_DMA_BASE), | ||
73 | .pfn = __phys_to_pfn(GEMINI_GENERAL_DMA_BASE), | ||
74 | .length = SZ_512K, | ||
75 | .type = MT_DEVICE, | ||
76 | }, | ||
77 | }; | ||
78 | |||
79 | void __init gemini_map_io(void) | ||
80 | { | ||
81 | iotable_init(gemini_io_desc, ARRAY_SIZE(gemini_io_desc)); | ||
82 | } | ||
diff --git a/arch/arm/mach-gemini/time.c b/arch/arm/mach-gemini/time.c new file mode 100644 index 000000000000..21dc5a89d1c4 --- /dev/null +++ b/arch/arm/mach-gemini/time.c | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001-2006 Storlink, Corp. | ||
3 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | */ | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <mach/hardware.h> | ||
14 | #include <mach/global_reg.h> | ||
15 | #include <asm/mach/time.h> | ||
16 | |||
17 | /* | ||
18 | * Register definitions for the timers | ||
19 | */ | ||
20 | #define TIMER_COUNT(BASE_ADDR) (BASE_ADDR + 0x00) | ||
21 | #define TIMER_LOAD(BASE_ADDR) (BASE_ADDR + 0x04) | ||
22 | #define TIMER_MATCH1(BASE_ADDR) (BASE_ADDR + 0x08) | ||
23 | #define TIMER_MATCH2(BASE_ADDR) (BASE_ADDR + 0x0C) | ||
24 | #define TIMER_CR(BASE_ADDR) (BASE_ADDR + 0x30) | ||
25 | |||
26 | #define TIMER_1_CR_ENABLE (1 << 0) | ||
27 | #define TIMER_1_CR_CLOCK (1 << 1) | ||
28 | #define TIMER_1_CR_INT (1 << 2) | ||
29 | #define TIMER_2_CR_ENABLE (1 << 3) | ||
30 | #define TIMER_2_CR_CLOCK (1 << 4) | ||
31 | #define TIMER_2_CR_INT (1 << 5) | ||
32 | #define TIMER_3_CR_ENABLE (1 << 6) | ||
33 | #define TIMER_3_CR_CLOCK (1 << 7) | ||
34 | #define TIMER_3_CR_INT (1 << 8) | ||
35 | |||
36 | /* | ||
37 | * IRQ handler for the timer | ||
38 | */ | ||
39 | static irqreturn_t gemini_timer_interrupt(int irq, void *dev_id) | ||
40 | { | ||
41 | timer_tick(); | ||
42 | |||
43 | return IRQ_HANDLED; | ||
44 | } | ||
45 | |||
46 | static struct irqaction gemini_timer_irq = { | ||
47 | .name = "Gemini Timer Tick", | ||
48 | .flags = IRQF_DISABLED | IRQF_TIMER, | ||
49 | .handler = gemini_timer_interrupt, | ||
50 | }; | ||
51 | |||
52 | /* | ||
53 | * Set up timer interrupt, and return the current time in seconds. | ||
54 | */ | ||
55 | void __init gemini_timer_init(void) | ||
56 | { | ||
57 | unsigned int tick_rate, reg_v; | ||
58 | |||
59 | reg_v = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE + GLOBAL_STATUS)); | ||
60 | tick_rate = REG_TO_AHB_SPEED(reg_v) * 1000000; | ||
61 | |||
62 | printk(KERN_INFO "Bus: %dMHz", tick_rate / 1000000); | ||
63 | |||
64 | tick_rate /= 6; /* APB bus run AHB*(1/6) */ | ||
65 | |||
66 | switch(reg_v & CPU_AHB_RATIO_MASK) { | ||
67 | case CPU_AHB_1_1: | ||
68 | printk(KERN_CONT "(1/1)\n"); | ||
69 | break; | ||
70 | case CPU_AHB_3_2: | ||
71 | printk(KERN_CONT "(3/2)\n"); | ||
72 | break; | ||
73 | case CPU_AHB_24_13: | ||
74 | printk(KERN_CONT "(24/13)\n"); | ||
75 | break; | ||
76 | case CPU_AHB_2_1: | ||
77 | printk(KERN_CONT "(2/1)\n"); | ||
78 | break; | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * Make irqs happen for the system timer | ||
83 | */ | ||
84 | setup_irq(IRQ_TIMER2, &gemini_timer_irq); | ||
85 | /* Start the timer */ | ||
86 | __raw_writel(tick_rate / HZ, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE))); | ||
87 | __raw_writel(tick_rate / HZ, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE))); | ||
88 | __raw_writel(TIMER_2_CR_ENABLE | TIMER_2_CR_INT, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE))); | ||
89 | } | ||
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index a6230f7a24c8..20979564e7ee 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -186,6 +186,24 @@ config CPU_ARM926T | |||
186 | Say Y if you want support for the ARM926T processor. | 186 | Say Y if you want support for the ARM926T processor. |
187 | Otherwise, say N. | 187 | Otherwise, say N. |
188 | 188 | ||
189 | # FA526 | ||
190 | config CPU_FA526 | ||
191 | bool | ||
192 | select CPU_32v4 | ||
193 | select CPU_ABRT_EV4 | ||
194 | select CPU_PABRT_NOIFAR | ||
195 | select CPU_CACHE_VIVT | ||
196 | select CPU_CP15_MMU | ||
197 | select CPU_CACHE_FA | ||
198 | select CPU_COPY_FA if MMU | ||
199 | select CPU_TLB_FA if MMU | ||
200 | help | ||
201 | The FA526 is a version of the ARMv4 compatible processor with | ||
202 | Branch Target Buffer, Unified TLB and cache line size 16. | ||
203 | |||
204 | Say Y if you want support for the FA526 processor. | ||
205 | Otherwise, say N. | ||
206 | |||
189 | # ARM940T | 207 | # ARM940T |
190 | config CPU_ARM940T | 208 | config CPU_ARM940T |
191 | bool "Support ARM940T processor" if ARCH_INTEGRATOR | 209 | bool "Support ARM940T processor" if ARCH_INTEGRATOR |
@@ -495,6 +513,9 @@ config CPU_CACHE_VIVT | |||
495 | config CPU_CACHE_VIPT | 513 | config CPU_CACHE_VIPT |
496 | bool | 514 | bool |
497 | 515 | ||
516 | config CPU_CACHE_FA | ||
517 | bool | ||
518 | |||
498 | if MMU | 519 | if MMU |
499 | # The copy-page model | 520 | # The copy-page model |
500 | config CPU_COPY_V3 | 521 | config CPU_COPY_V3 |
@@ -509,6 +530,9 @@ config CPU_COPY_V4WB | |||
509 | config CPU_COPY_FEROCEON | 530 | config CPU_COPY_FEROCEON |
510 | bool | 531 | bool |
511 | 532 | ||
533 | config CPU_COPY_FA | ||
534 | bool | ||
535 | |||
512 | config CPU_COPY_V6 | 536 | config CPU_COPY_V6 |
513 | bool | 537 | bool |
514 | 538 | ||
@@ -539,6 +563,13 @@ config CPU_TLB_FEROCEON | |||
539 | help | 563 | help |
540 | Feroceon TLB (v4wbi with non-outer-cachable page table walks). | 564 | Feroceon TLB (v4wbi with non-outer-cachable page table walks). |
541 | 565 | ||
566 | config CPU_TLB_FA | ||
567 | bool | ||
568 | help | ||
569 | Faraday ARM FA526 architecture, unified TLB with writeback cache | ||
570 | and invalidate instruction cache entry. Branch target buffer is | ||
571 | also supported. | ||
572 | |||
542 | config CPU_TLB_V6 | 573 | config CPU_TLB_V6 |
543 | bool | 574 | bool |
544 | 575 | ||
@@ -649,7 +680,7 @@ config CPU_DCACHE_SIZE | |||
649 | 680 | ||
650 | config CPU_DCACHE_WRITETHROUGH | 681 | config CPU_DCACHE_WRITETHROUGH |
651 | bool "Force write through D-cache" | 682 | bool "Force write through D-cache" |
652 | depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020) && !CPU_DCACHE_DISABLE | 683 | depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_FA526) && !CPU_DCACHE_DISABLE |
653 | default y if CPU_ARM925T | 684 | default y if CPU_ARM925T |
654 | help | 685 | help |
655 | Say Y here to use the data cache in writethrough mode. Unless you | 686 | Say Y here to use the data cache in writethrough mode. Unless you |
@@ -664,7 +695,7 @@ config CPU_CACHE_ROUND_ROBIN | |||
664 | 695 | ||
665 | config CPU_BPREDICT_DISABLE | 696 | config CPU_BPREDICT_DISABLE |
666 | bool "Disable branch prediction" | 697 | bool "Disable branch prediction" |
667 | depends on CPU_ARM1020 || CPU_V6 || CPU_MOHAWK || CPU_XSC3 || CPU_V7 | 698 | depends on CPU_ARM1020 || CPU_V6 || CPU_MOHAWK || CPU_XSC3 || CPU_V7 || CPU_FA526 |
668 | help | 699 | help |
669 | Say Y here to disable branch prediction. If unsure, say N. | 700 | Say Y here to disable branch prediction. If unsure, say N. |
670 | 701 | ||
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index c264683538bc..63e3f6dd0e21 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile | |||
@@ -33,6 +33,7 @@ obj-$(CONFIG_CPU_CACHE_V4WT) += cache-v4wt.o | |||
33 | obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o | 33 | obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o |
34 | obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o | 34 | obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o |
35 | obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o | 35 | obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o |
36 | obj-$(CONFIG_CPU_CACHE_FA) += cache-fa.o | ||
36 | 37 | ||
37 | obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o | 38 | obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o |
38 | obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o | 39 | obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o |
@@ -42,6 +43,7 @@ obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o context.o | |||
42 | obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o | 43 | obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o |
43 | obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o | 44 | obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o |
44 | obj-$(CONFIG_CPU_XSC3) += copypage-xsc3.o | 45 | obj-$(CONFIG_CPU_XSC3) += copypage-xsc3.o |
46 | obj-$(CONFIG_CPU_COPY_FA) += copypage-fa.o | ||
45 | 47 | ||
46 | obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o | 48 | obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o |
47 | obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o | 49 | obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o |
@@ -50,6 +52,7 @@ obj-$(CONFIG_CPU_TLB_V4WBI) += tlb-v4wbi.o | |||
50 | obj-$(CONFIG_CPU_TLB_FEROCEON) += tlb-v4wbi.o # reuse v4wbi TLB functions | 52 | obj-$(CONFIG_CPU_TLB_FEROCEON) += tlb-v4wbi.o # reuse v4wbi TLB functions |
51 | obj-$(CONFIG_CPU_TLB_V6) += tlb-v6.o | 53 | obj-$(CONFIG_CPU_TLB_V6) += tlb-v6.o |
52 | obj-$(CONFIG_CPU_TLB_V7) += tlb-v7.o | 54 | obj-$(CONFIG_CPU_TLB_V7) += tlb-v7.o |
55 | obj-$(CONFIG_CPU_TLB_FA) += tlb-fa.o | ||
53 | 56 | ||
54 | obj-$(CONFIG_CPU_ARM610) += proc-arm6_7.o | 57 | obj-$(CONFIG_CPU_ARM610) += proc-arm6_7.o |
55 | obj-$(CONFIG_CPU_ARM710) += proc-arm6_7.o | 58 | obj-$(CONFIG_CPU_ARM710) += proc-arm6_7.o |
@@ -63,6 +66,7 @@ obj-$(CONFIG_CPU_ARM925T) += proc-arm925.o | |||
63 | obj-$(CONFIG_CPU_ARM926T) += proc-arm926.o | 66 | obj-$(CONFIG_CPU_ARM926T) += proc-arm926.o |
64 | obj-$(CONFIG_CPU_ARM940T) += proc-arm940.o | 67 | obj-$(CONFIG_CPU_ARM940T) += proc-arm940.o |
65 | obj-$(CONFIG_CPU_ARM946E) += proc-arm946.o | 68 | obj-$(CONFIG_CPU_ARM946E) += proc-arm946.o |
69 | obj-$(CONFIG_CPU_FA526) += proc-fa526.o | ||
66 | obj-$(CONFIG_CPU_ARM1020) += proc-arm1020.o | 70 | obj-$(CONFIG_CPU_ARM1020) += proc-arm1020.o |
67 | obj-$(CONFIG_CPU_ARM1020E) += proc-arm1020e.o | 71 | obj-$(CONFIG_CPU_ARM1020E) += proc-arm1020e.o |
68 | obj-$(CONFIG_CPU_ARM1022) += proc-arm1022.o | 72 | obj-$(CONFIG_CPU_ARM1022) += proc-arm1022.o |
diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S new file mode 100644 index 000000000000..b63a8f7b95cf --- /dev/null +++ b/arch/arm/mm/cache-fa.S | |||
@@ -0,0 +1,220 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mm/cache-fa.S | ||
3 | * | ||
4 | * Copyright (C) 2005 Faraday Corp. | ||
5 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
6 | * | ||
7 | * Based on cache-v4wb.S: | ||
8 | * Copyright (C) 1997-2002 Russell king | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * Processors: FA520 FA526 FA626 | ||
15 | */ | ||
16 | #include <linux/linkage.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <asm/memory.h> | ||
19 | #include <asm/page.h> | ||
20 | |||
21 | #include "proc-macros.S" | ||
22 | |||
23 | /* | ||
24 | * The size of one data cache line. | ||
25 | */ | ||
26 | #define CACHE_DLINESIZE 16 | ||
27 | |||
28 | /* | ||
29 | * The total size of the data cache. | ||
30 | */ | ||
31 | #ifdef CONFIG_ARCH_GEMINI | ||
32 | #define CACHE_DSIZE 8192 | ||
33 | #else | ||
34 | #define CACHE_DSIZE 16384 | ||
35 | #endif | ||
36 | |||
37 | /* FIXME: put optimal value here. Current one is just estimation */ | ||
38 | #define CACHE_DLIMIT (CACHE_DSIZE * 2) | ||
39 | |||
40 | /* | ||
41 | * flush_user_cache_all() | ||
42 | * | ||
43 | * Clean and invalidate all cache entries in a particular address | ||
44 | * space. | ||
45 | */ | ||
46 | ENTRY(fa_flush_user_cache_all) | ||
47 | /* FALLTHROUGH */ | ||
48 | /* | ||
49 | * flush_kern_cache_all() | ||
50 | * | ||
51 | * Clean and invalidate the entire cache. | ||
52 | */ | ||
53 | ENTRY(fa_flush_kern_cache_all) | ||
54 | mov ip, #0 | ||
55 | mov r2, #VM_EXEC | ||
56 | __flush_whole_cache: | ||
57 | mcr p15, 0, ip, c7, c14, 0 @ clean/invalidate D cache | ||
58 | tst r2, #VM_EXEC | ||
59 | mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache | ||
60 | mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB | ||
61 | mcrne p15, 0, ip, c7, c10, 4 @ drain write buffer | ||
62 | mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush | ||
63 | mov pc, lr | ||
64 | |||
65 | /* | ||
66 | * flush_user_cache_range(start, end, flags) | ||
67 | * | ||
68 | * Invalidate a range of cache entries in the specified | ||
69 | * address space. | ||
70 | * | ||
71 | * - start - start address (inclusive, page aligned) | ||
72 | * - end - end address (exclusive, page aligned) | ||
73 | * - flags - vma_area_struct flags describing address space | ||
74 | */ | ||
75 | ENTRY(fa_flush_user_cache_range) | ||
76 | mov ip, #0 | ||
77 | sub r3, r1, r0 @ calculate total size | ||
78 | cmp r3, #CACHE_DLIMIT @ total size >= limit? | ||
79 | bhs __flush_whole_cache @ flush whole D cache | ||
80 | |||
81 | 1: tst r2, #VM_EXEC | ||
82 | mcrne p15, 0, r0, c7, c5, 1 @ invalidate I line | ||
83 | mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry | ||
84 | add r0, r0, #CACHE_DLINESIZE | ||
85 | cmp r0, r1 | ||
86 | blo 1b | ||
87 | tst r2, #VM_EXEC | ||
88 | mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB | ||
89 | mcrne p15, 0, ip, c7, c10, 4 @ data write barrier | ||
90 | mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush | ||
91 | mov pc, lr | ||
92 | |||
93 | /* | ||
94 | * coherent_kern_range(start, end) | ||
95 | * | ||
96 | * Ensure coherency between the Icache and the Dcache in the | ||
97 | * region described by start. If you have non-snooping | ||
98 | * Harvard caches, you need to implement this function. | ||
99 | * | ||
100 | * - start - virtual start address | ||
101 | * - end - virtual end address | ||
102 | */ | ||
103 | ENTRY(fa_coherent_kern_range) | ||
104 | /* fall through */ | ||
105 | |||
106 | /* | ||
107 | * coherent_user_range(start, end) | ||
108 | * | ||
109 | * Ensure coherency between the Icache and the Dcache in the | ||
110 | * region described by start. If you have non-snooping | ||
111 | * Harvard caches, you need to implement this function. | ||
112 | * | ||
113 | * - start - virtual start address | ||
114 | * - end - virtual end address | ||
115 | */ | ||
116 | ENTRY(fa_coherent_user_range) | ||
117 | bic r0, r0, #CACHE_DLINESIZE - 1 | ||
118 | 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry | ||
119 | mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry | ||
120 | add r0, r0, #CACHE_DLINESIZE | ||
121 | cmp r0, r1 | ||
122 | blo 1b | ||
123 | mov r0, #0 | ||
124 | mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB | ||
125 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
126 | mcr p15, 0, r0, c7, c5, 4 @ prefetch flush | ||
127 | mov pc, lr | ||
128 | |||
129 | /* | ||
130 | * flush_kern_dcache_page(kaddr) | ||
131 | * | ||
132 | * Ensure that the data held in the page kaddr is written back | ||
133 | * to the page in question. | ||
134 | * | ||
135 | * - kaddr - kernel address (guaranteed to be page aligned) | ||
136 | */ | ||
137 | ENTRY(fa_flush_kern_dcache_page) | ||
138 | add r1, r0, #PAGE_SZ | ||
139 | 1: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line | ||
140 | add r0, r0, #CACHE_DLINESIZE | ||
141 | cmp r0, r1 | ||
142 | blo 1b | ||
143 | mov r0, #0 | ||
144 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
145 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
146 | mov pc, lr | ||
147 | |||
148 | /* | ||
149 | * dma_inv_range(start, end) | ||
150 | * | ||
151 | * Invalidate (discard) the specified virtual address range. | ||
152 | * May not write back any entries. If 'start' or 'end' | ||
153 | * are not cache line aligned, those lines must be written | ||
154 | * back. | ||
155 | * | ||
156 | * - start - virtual start address | ||
157 | * - end - virtual end address | ||
158 | */ | ||
159 | ENTRY(fa_dma_inv_range) | ||
160 | tst r0, #CACHE_DLINESIZE - 1 | ||
161 | bic r0, r0, #CACHE_DLINESIZE - 1 | ||
162 | mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry | ||
163 | tst r1, #CACHE_DLINESIZE - 1 | ||
164 | bic r1, r1, #CACHE_DLINESIZE - 1 | ||
165 | mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D entry | ||
166 | 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry | ||
167 | add r0, r0, #CACHE_DLINESIZE | ||
168 | cmp r0, r1 | ||
169 | blo 1b | ||
170 | mov r0, #0 | ||
171 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
172 | mov pc, lr | ||
173 | |||
174 | /* | ||
175 | * dma_clean_range(start, end) | ||
176 | * | ||
177 | * Clean (write back) the specified virtual address range. | ||
178 | * | ||
179 | * - start - virtual start address | ||
180 | * - end - virtual end address | ||
181 | */ | ||
182 | ENTRY(fa_dma_clean_range) | ||
183 | bic r0, r0, #CACHE_DLINESIZE - 1 | ||
184 | 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry | ||
185 | add r0, r0, #CACHE_DLINESIZE | ||
186 | cmp r0, r1 | ||
187 | blo 1b | ||
188 | mov r0, #0 | ||
189 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
190 | mov pc, lr | ||
191 | |||
192 | /* | ||
193 | * dma_flush_range(start,end) | ||
194 | * - start - virtual start address of region | ||
195 | * - end - virtual end address of region | ||
196 | */ | ||
197 | ENTRY(fa_dma_flush_range) | ||
198 | bic r0, r0, #CACHE_DLINESIZE - 1 | ||
199 | 1: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry | ||
200 | add r0, r0, #CACHE_DLINESIZE | ||
201 | cmp r0, r1 | ||
202 | blo 1b | ||
203 | mov r0, #0 | ||
204 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
205 | mov pc, lr | ||
206 | |||
207 | __INITDATA | ||
208 | |||
209 | .type fa_cache_fns, #object | ||
210 | ENTRY(fa_cache_fns) | ||
211 | .long fa_flush_kern_cache_all | ||
212 | .long fa_flush_user_cache_all | ||
213 | .long fa_flush_user_cache_range | ||
214 | .long fa_coherent_kern_range | ||
215 | .long fa_coherent_user_range | ||
216 | .long fa_flush_kern_dcache_page | ||
217 | .long fa_dma_inv_range | ||
218 | .long fa_dma_clean_range | ||
219 | .long fa_dma_flush_range | ||
220 | .size fa_cache_fns, . - fa_cache_fns | ||
diff --git a/arch/arm/mm/copypage-fa.c b/arch/arm/mm/copypage-fa.c new file mode 100644 index 000000000000..b2a6008b0111 --- /dev/null +++ b/arch/arm/mm/copypage-fa.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/lib/copypage-fa.S | ||
3 | * | ||
4 | * Copyright (C) 2005 Faraday Corp. | ||
5 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
6 | * | ||
7 | * Based on copypage-v4wb.S: | ||
8 | * Copyright (C) 1995-1999 Russell King | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/highmem.h> | ||
16 | |||
17 | /* | ||
18 | * Faraday optimised copy_user_page | ||
19 | */ | ||
20 | static void __naked | ||
21 | fa_copy_user_page(void *kto, const void *kfrom) | ||
22 | { | ||
23 | asm("\ | ||
24 | stmfd sp!, {r4, lr} @ 2\n\ | ||
25 | mov r2, %0 @ 1\n\ | ||
26 | 1: ldmia r1!, {r3, r4, ip, lr} @ 4\n\ | ||
27 | stmia r0, {r3, r4, ip, lr} @ 4\n\ | ||
28 | mcr p15, 0, r0, c7, c14, 1 @ 1 clean and invalidate D line\n\ | ||
29 | add r0, r0, #16 @ 1\n\ | ||
30 | ldmia r1!, {r3, r4, ip, lr} @ 4\n\ | ||
31 | stmia r0, {r3, r4, ip, lr} @ 4\n\ | ||
32 | mcr p15, 0, r0, c7, c14, 1 @ 1 clean and invalidate D line\n\ | ||
33 | add r0, r0, #16 @ 1\n\ | ||
34 | subs r2, r2, #1 @ 1\n\ | ||
35 | bne 1b @ 1\n\ | ||
36 | mcr p15, 0, r2, c7, c10, 4 @ 1 drain WB\n\ | ||
37 | ldmfd sp!, {r4, pc} @ 3" | ||
38 | : | ||
39 | : "I" (PAGE_SIZE / 32)); | ||
40 | } | ||
41 | |||
42 | void fa_copy_user_highpage(struct page *to, struct page *from, | ||
43 | unsigned long vaddr) | ||
44 | { | ||
45 | void *kto, *kfrom; | ||
46 | |||
47 | kto = kmap_atomic(to, KM_USER0); | ||
48 | kfrom = kmap_atomic(from, KM_USER1); | ||
49 | fa_copy_user_page(kto, kfrom); | ||
50 | kunmap_atomic(kfrom, KM_USER1); | ||
51 | kunmap_atomic(kto, KM_USER0); | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * Faraday optimised clear_user_page | ||
56 | * | ||
57 | * Same story as above. | ||
58 | */ | ||
59 | void fa_clear_user_highpage(struct page *page, unsigned long vaddr) | ||
60 | { | ||
61 | void *ptr, *kaddr = kmap_atomic(page, KM_USER0); | ||
62 | asm volatile("\ | ||
63 | mov r1, %2 @ 1\n\ | ||
64 | mov r2, #0 @ 1\n\ | ||
65 | mov r3, #0 @ 1\n\ | ||
66 | mov ip, #0 @ 1\n\ | ||
67 | mov lr, #0 @ 1\n\ | ||
68 | 1: stmia %0, {r2, r3, ip, lr} @ 4\n\ | ||
69 | mcr p15, 0, %0, c7, c14, 1 @ 1 clean and invalidate D line\n\ | ||
70 | add %0, %0, #16 @ 1\n\ | ||
71 | stmia %0, {r2, r3, ip, lr} @ 4\n\ | ||
72 | mcr p15, 0, %0, c7, c14, 1 @ 1 clean and invalidate D line\n\ | ||
73 | add %0, %0, #16 @ 1\n\ | ||
74 | subs r1, r1, #1 @ 1\n\ | ||
75 | bne 1b @ 1\n\ | ||
76 | mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB" | ||
77 | : "=r" (ptr) | ||
78 | : "0" (kaddr), "I" (PAGE_SIZE / 32) | ||
79 | : "r1", "r2", "r3", "ip", "lr"); | ||
80 | kunmap_atomic(kaddr, KM_USER0); | ||
81 | } | ||
82 | |||
83 | struct cpu_user_fns fa_user_fns __initdata = { | ||
84 | .cpu_clear_user_highpage = fa_clear_user_highpage, | ||
85 | .cpu_copy_user_highpage = fa_copy_user_highpage, | ||
86 | }; | ||
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S new file mode 100644 index 000000000000..08b8a955d5d7 --- /dev/null +++ b/arch/arm/mm/proc-fa526.S | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mm/proc-fa526.S: MMU functions for FA526 | ||
3 | * | ||
4 | * Written by : Luke Lee | ||
5 | * Copyright (C) 2005 Faraday Corp. | ||
6 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * | ||
14 | * These are the low level assembler for performing cache and TLB | ||
15 | * functions on the fa526. | ||
16 | */ | ||
17 | #include <linux/linkage.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <asm/assembler.h> | ||
20 | #include <asm/hwcap.h> | ||
21 | #include <asm/pgtable-hwdef.h> | ||
22 | #include <asm/pgtable.h> | ||
23 | #include <asm/page.h> | ||
24 | #include <asm/ptrace.h> | ||
25 | #include <asm/system.h> | ||
26 | |||
27 | #include "proc-macros.S" | ||
28 | |||
29 | #define CACHE_DLINESIZE 16 | ||
30 | |||
31 | .text | ||
32 | /* | ||
33 | * cpu_fa526_proc_init() | ||
34 | */ | ||
35 | ENTRY(cpu_fa526_proc_init) | ||
36 | mov pc, lr | ||
37 | |||
38 | /* | ||
39 | * cpu_fa526_proc_fin() | ||
40 | */ | ||
41 | ENTRY(cpu_fa526_proc_fin) | ||
42 | stmfd sp!, {lr} | ||
43 | mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE | ||
44 | msr cpsr_c, ip | ||
45 | bl fa_flush_kern_cache_all | ||
46 | mrc p15, 0, r0, c1, c0, 0 @ ctrl register | ||
47 | bic r0, r0, #0x1000 @ ...i............ | ||
48 | bic r0, r0, #0x000e @ ............wca. | ||
49 | mcr p15, 0, r0, c1, c0, 0 @ disable caches | ||
50 | nop | ||
51 | nop | ||
52 | ldmfd sp!, {pc} | ||
53 | |||
54 | /* | ||
55 | * cpu_fa526_reset(loc) | ||
56 | * | ||
57 | * Perform a soft reset of the system. Put the CPU into the | ||
58 | * same state as it would be if it had been reset, and branch | ||
59 | * to what would be the reset vector. | ||
60 | * | ||
61 | * loc: location to jump to for soft reset | ||
62 | */ | ||
63 | .align 4 | ||
64 | ENTRY(cpu_fa526_reset) | ||
65 | /* TODO: Use CP8 if possible... */ | ||
66 | mov ip, #0 | ||
67 | mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches | ||
68 | mcr p15, 0, ip, c7, c10, 4 @ drain WB | ||
69 | #ifdef CONFIG_MMU | ||
70 | mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs | ||
71 | #endif | ||
72 | mrc p15, 0, ip, c1, c0, 0 @ ctrl register | ||
73 | bic ip, ip, #0x000f @ ............wcam | ||
74 | bic ip, ip, #0x1100 @ ...i...s........ | ||
75 | bic ip, ip, #0x0800 @ BTB off | ||
76 | mcr p15, 0, ip, c1, c0, 0 @ ctrl register | ||
77 | nop | ||
78 | nop | ||
79 | mov pc, r0 | ||
80 | |||
81 | /* | ||
82 | * cpu_fa526_do_idle() | ||
83 | */ | ||
84 | .align 4 | ||
85 | ENTRY(cpu_fa526_do_idle) | ||
86 | mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt | ||
87 | mov pc, lr | ||
88 | |||
89 | |||
90 | ENTRY(cpu_fa526_dcache_clean_area) | ||
91 | 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry | ||
92 | add r0, r0, #CACHE_DLINESIZE | ||
93 | subs r1, r1, #CACHE_DLINESIZE | ||
94 | bhi 1b | ||
95 | mcr p15, 0, r0, c7, c10, 4 @ drain WB | ||
96 | mov pc, lr | ||
97 | |||
98 | /* =============================== PageTable ============================== */ | ||
99 | |||
100 | /* | ||
101 | * cpu_fa526_switch_mm(pgd) | ||
102 | * | ||
103 | * Set the translation base pointer to be as described by pgd. | ||
104 | * | ||
105 | * pgd: new page tables | ||
106 | */ | ||
107 | .align 4 | ||
108 | ENTRY(cpu_fa526_switch_mm) | ||
109 | #ifdef CONFIG_MMU | ||
110 | mov ip, #0 | ||
111 | #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH | ||
112 | mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache | ||
113 | #else | ||
114 | mcr p15, 0, ip, c7, c14, 0 @ clean and invalidate whole D cache | ||
115 | #endif | ||
116 | mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache | ||
117 | mcr p15, 0, ip, c7, c5, 6 @ invalidate BTB since mm changed | ||
118 | mcr p15, 0, ip, c7, c10, 4 @ data write barrier | ||
119 | mcr p15, 0, ip, c7, c5, 4 @ prefetch flush | ||
120 | mcr p15, 0, r0, c2, c0, 0 @ load page table pointer | ||
121 | mcr p15, 0, ip, c8, c7, 0 @ invalidate UTLB | ||
122 | #endif | ||
123 | mov pc, lr | ||
124 | |||
125 | /* | ||
126 | * cpu_fa526_set_pte_ext(ptep, pte, ext) | ||
127 | * | ||
128 | * Set a PTE and flush it out | ||
129 | */ | ||
130 | .align 4 | ||
131 | ENTRY(cpu_fa526_set_pte_ext) | ||
132 | #ifdef CONFIG_MMU | ||
133 | armv3_set_pte_ext | ||
134 | mov r0, r0 | ||
135 | mcr p15, 0, r0, c7, c10, 1 @ clean D entry | ||
136 | mov r0, #0 | ||
137 | mcr p15, 0, r0, c7, c10, 4 @ drain WB | ||
138 | #endif | ||
139 | mov pc, lr | ||
140 | |||
141 | __INIT | ||
142 | |||
143 | .type __fa526_setup, #function | ||
144 | __fa526_setup: | ||
145 | /* On return of this routine, r0 must carry correct flags for CFG register */ | ||
146 | mov r0, #0 | ||
147 | mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 | ||
148 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 | ||
149 | #ifdef CONFIG_MMU | ||
150 | mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 | ||
151 | #endif | ||
152 | mcr p15, 0, r0, c7, c5, 5 @ invalidate IScratchpad RAM | ||
153 | |||
154 | mov r0, #1 | ||
155 | mcr p15, 0, r0, c1, c1, 0 @ turn-on ECR | ||
156 | |||
157 | mov r0, #0 | ||
158 | mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB All | ||
159 | mcr p15, 0, r0, c7, c10, 4 @ data write barrier | ||
160 | mcr p15, 0, r0, c7, c5, 4 @ prefetch flush | ||
161 | |||
162 | mov r0, #0x1f @ Domains 0, 1 = manager, 2 = client | ||
163 | mcr p15, 0, r0, c3, c0 @ load domain access register | ||
164 | |||
165 | mrc p15, 0, r0, c1, c0 @ get control register v4 | ||
166 | ldr r5, fa526_cr1_clear | ||
167 | bic r0, r0, r5 | ||
168 | ldr r5, fa526_cr1_set | ||
169 | orr r0, r0, r5 | ||
170 | mov pc, lr | ||
171 | .size __fa526_setup, . - __fa526_setup | ||
172 | |||
173 | /* | ||
174 | * .RVI ZFRS BLDP WCAM | ||
175 | * ..11 1001 .111 1101 | ||
176 | * | ||
177 | */ | ||
178 | .type fa526_cr1_clear, #object | ||
179 | .type fa526_cr1_set, #object | ||
180 | fa526_cr1_clear: | ||
181 | .word 0x3f3f | ||
182 | fa526_cr1_set: | ||
183 | .word 0x397D | ||
184 | |||
185 | __INITDATA | ||
186 | |||
187 | /* | ||
188 | * Purpose : Function pointers used to access above functions - all calls | ||
189 | * come through these | ||
190 | */ | ||
191 | .type fa526_processor_functions, #object | ||
192 | fa526_processor_functions: | ||
193 | .word v4_early_abort | ||
194 | .word pabort_noifar | ||
195 | .word cpu_fa526_proc_init | ||
196 | .word cpu_fa526_proc_fin | ||
197 | .word cpu_fa526_reset | ||
198 | .word cpu_fa526_do_idle | ||
199 | .word cpu_fa526_dcache_clean_area | ||
200 | .word cpu_fa526_switch_mm | ||
201 | .word cpu_fa526_set_pte_ext | ||
202 | .size fa526_processor_functions, . - fa526_processor_functions | ||
203 | |||
204 | .section ".rodata" | ||
205 | |||
206 | .type cpu_arch_name, #object | ||
207 | cpu_arch_name: | ||
208 | .asciz "armv4" | ||
209 | .size cpu_arch_name, . - cpu_arch_name | ||
210 | |||
211 | .type cpu_elf_name, #object | ||
212 | cpu_elf_name: | ||
213 | .asciz "v4" | ||
214 | .size cpu_elf_name, . - cpu_elf_name | ||
215 | |||
216 | .type cpu_fa526_name, #object | ||
217 | cpu_fa526_name: | ||
218 | .asciz "FA526" | ||
219 | .size cpu_fa526_name, . - cpu_fa526_name | ||
220 | |||
221 | .align | ||
222 | |||
223 | .section ".proc.info.init", #alloc, #execinstr | ||
224 | |||
225 | .type __fa526_proc_info,#object | ||
226 | __fa526_proc_info: | ||
227 | .long 0x66015261 | ||
228 | .long 0xff01fff1 | ||
229 | .long PMD_TYPE_SECT | \ | ||
230 | PMD_SECT_BUFFERABLE | \ | ||
231 | PMD_SECT_CACHEABLE | \ | ||
232 | PMD_BIT4 | \ | ||
233 | PMD_SECT_AP_WRITE | \ | ||
234 | PMD_SECT_AP_READ | ||
235 | .long PMD_TYPE_SECT | \ | ||
236 | PMD_BIT4 | \ | ||
237 | PMD_SECT_AP_WRITE | \ | ||
238 | PMD_SECT_AP_READ | ||
239 | b __fa526_setup | ||
240 | .long cpu_arch_name | ||
241 | .long cpu_elf_name | ||
242 | .long HWCAP_SWP | HWCAP_HALF | ||
243 | .long cpu_fa526_name | ||
244 | .long fa526_processor_functions | ||
245 | .long fa_tlb_fns | ||
246 | .long fa_user_fns | ||
247 | .long fa_cache_fns | ||
248 | .size __fa526_proc_info, . - __fa526_proc_info | ||
diff --git a/arch/arm/mm/tlb-fa.S b/arch/arm/mm/tlb-fa.S new file mode 100644 index 000000000000..9694f1f6f485 --- /dev/null +++ b/arch/arm/mm/tlb-fa.S | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mm/tlb-fa.S | ||
3 | * | ||
4 | * Copyright (C) 2005 Faraday Corp. | ||
5 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
6 | * | ||
7 | * Based on tlb-v4wbi.S: | ||
8 | * Copyright (C) 1997-2002 Russell King | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * ARM architecture version 4, Faraday variation. | ||
15 | * This assume an unified TLBs, with a write buffer, and branch target buffer (BTB) | ||
16 | * | ||
17 | * Processors: FA520 FA526 FA626 | ||
18 | */ | ||
19 | #include <linux/linkage.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <asm/asm-offsets.h> | ||
22 | #include <asm/tlbflush.h> | ||
23 | #include "proc-macros.S" | ||
24 | |||
25 | |||
26 | /* | ||
27 | * flush_user_tlb_range(start, end, mm) | ||
28 | * | ||
29 | * Invalidate a range of TLB entries in the specified address space. | ||
30 | * | ||
31 | * - start - range start address | ||
32 | * - end - range end address | ||
33 | * - mm - mm_struct describing address space | ||
34 | */ | ||
35 | .align 4 | ||
36 | ENTRY(fa_flush_user_tlb_range) | ||
37 | vma_vm_mm ip, r2 | ||
38 | act_mm r3 @ get current->active_mm | ||
39 | eors r3, ip, r3 @ == mm ? | ||
40 | movne pc, lr @ no, we dont do anything | ||
41 | mov r3, #0 | ||
42 | mcr p15, 0, r3, c7, c10, 4 @ drain WB | ||
43 | bic r0, r0, #0x0ff | ||
44 | bic r0, r0, #0xf00 | ||
45 | 1: mcr p15, 0, r0, c8, c7, 1 @ invalidate UTLB entry | ||
46 | add r0, r0, #PAGE_SZ | ||
47 | cmp r0, r1 | ||
48 | blo 1b | ||
49 | mcr p15, 0, r3, c7, c5, 6 @ invalidate BTB | ||
50 | mcr p15, 0, r3, c7, c10, 4 @ data write barrier | ||
51 | mov pc, lr | ||
52 | |||
53 | |||
54 | ENTRY(fa_flush_kern_tlb_range) | ||
55 | mov r3, #0 | ||
56 | mcr p15, 0, r3, c7, c10, 4 @ drain WB | ||
57 | bic r0, r0, #0x0ff | ||
58 | bic r0, r0, #0xf00 | ||
59 | 1: mcr p15, 0, r0, c8, c7, 1 @ invalidate UTLB entry | ||
60 | add r0, r0, #PAGE_SZ | ||
61 | cmp r0, r1 | ||
62 | blo 1b | ||
63 | mcr p15, 0, r3, c7, c5, 6 @ invalidate BTB | ||
64 | mcr p15, 0, r3, c7, c10, 4 @ data write barrier | ||
65 | mcr p15, 0, r3, c7, c5, 4 @ prefetch flush | ||
66 | mov pc, lr | ||
67 | |||
68 | __INITDATA | ||
69 | |||
70 | .type fa_tlb_fns, #object | ||
71 | ENTRY(fa_tlb_fns) | ||
72 | .long fa_flush_user_tlb_range | ||
73 | .long fa_flush_kern_tlb_range | ||
74 | .long fa_tlb_flags | ||
75 | .size fa_tlb_fns, . - fa_tlb_fns | ||