aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig10
-rw-r--r--arch/arm/Makefile2
-rw-r--r--arch/arm/boot/compressed/head.S26
-rw-r--r--arch/arm/include/asm/cacheflush.h8
-rw-r--r--arch/arm/include/asm/page.h8
-rw-r--r--arch/arm/include/asm/proc-fns.h8
-rw-r--r--arch/arm/include/asm/system.h6
-rw-r--r--arch/arm/include/asm/tlbflush.h38
-rw-r--r--arch/arm/mach-gemini/Kconfig19
-rw-r--r--arch/arm/mach-gemini/Makefile10
-rw-r--r--arch/arm/mach-gemini/Makefile.boot9
-rw-r--r--arch/arm/mach-gemini/board-rut1xx.c95
-rw-r--r--arch/arm/mach-gemini/common.h28
-rw-r--r--arch/arm/mach-gemini/devices.c92
-rw-r--r--arch/arm/mach-gemini/gpio.c232
-rw-r--r--arch/arm/mach-gemini/include/mach/debug-macro.S23
-rw-r--r--arch/arm/mach-gemini/include/mach/entry-macro.S39
-rw-r--r--arch/arm/mach-gemini/include/mach/global_reg.h278
-rw-r--r--arch/arm/mach-gemini/include/mach/gpio.h25
-rw-r--r--arch/arm/mach-gemini/include/mach/hardware.h75
-rw-r--r--arch/arm/mach-gemini/include/mach/io.h18
-rw-r--r--arch/arm/mach-gemini/include/mach/irqs.h53
-rw-r--r--arch/arm/mach-gemini/include/mach/memory.h19
-rw-r--r--arch/arm/mach-gemini/include/mach/system.h37
-rw-r--r--arch/arm/mach-gemini/include/mach/timex.h13
-rw-r--r--arch/arm/mach-gemini/include/mach/uncompress.h42
-rw-r--r--arch/arm/mach-gemini/include/mach/vmalloc.h10
-rw-r--r--arch/arm/mach-gemini/irq.c102
-rw-r--r--arch/arm/mach-gemini/mm.c82
-rw-r--r--arch/arm/mach-gemini/time.c89
-rw-r--r--arch/arm/mm/Kconfig35
-rw-r--r--arch/arm/mm/Makefile4
-rw-r--r--arch/arm/mm/cache-fa.S220
-rw-r--r--arch/arm/mm/copypage-fa.c86
-rw-r--r--arch/arm/mm/proc-fa526.S248
-rw-r--r--arch/arm/mm/tlb-fa.S75
36 files changed, 2149 insertions, 15 deletions
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
279config 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
279config ARCH_FOOTBRIDGE 287config 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
617source "arch/arm/mach-footbridge/Kconfig" 625source "arch/arm/mach-footbridge/Kconfig"
618 626
627source "arch/arm/mach-gemini/Kconfig"
628
619source "arch/arm/mach-integrator/Kconfig" 629source "arch/arm/mach-integrator/Kconfig"
620 630
621source "arch/arm/mach-iop32x/Kconfig" 631source "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
72tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi 72tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi
73tune-$(CONFIG_CPU_ARM925T) :=-mtune=arm9tdmi 73tune-$(CONFIG_CPU_ARM925T) :=-mtune=arm9tdmi
74tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi 74tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi
75tune-$(CONFIG_CPU_FA526) :=-mtune=arm9tdmi
75tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 76tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
76tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 77tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
77tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale 78tune-$(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 @@
1if ARCH_GEMINI
2
3menu "Cortina Systems Gemini Implementations"
4
5config 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
12endmenu
13
14config GEMINI_MEM_SWAP
15 bool "Gemini memory is swapped"
16 help
17 Say Y here if Gemini memory is swapped by bootloader.
18
19endif
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
7obj-y := irq.o mm.o time.o devices.o gpio.o
8
9# Board-specific support
10obj-$(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 @@
1ifeq ($(CONFIG_GEMINI_MEM_SWAP),y)
2 zreladdr-y := 0x00008000
3params_phys-y := 0x00000100
4initrd_phys-y := 0x00800000
5else
6 zreladdr-y := 0x10008000
7params_phys-y := 0x10000100
8initrd_phys-y := 0x10800000
9endif
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
24static 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
34static struct gpio_keys_platform_data rut1xx_keys_data = {
35 .buttons = rut1xx_keys,
36 .nbuttons = ARRAY_SIZE(rut1xx_keys),
37};
38
39static struct platform_device rut1xx_keys_device = {
40 .name = "gpio-keys",
41 .id = -1,
42 .dev = {
43 .platform_data = &rut1xx_keys_data,
44 },
45};
46
47static 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
61static struct gpio_led_platform_data rut100_leds_data = {
62 .num_leds = ARRAY_SIZE(rut100_leds),
63 .leds = rut100_leds,
64};
65
66static struct platform_device rut1xx_leds = {
67 .name = "leds-gpio",
68 .id = -1,
69 .dev = {
70 .platform_data = &rut100_leds_data,
71 },
72};
73
74static struct sys_timer rut1xx_timer = {
75 .init = gemini_timer_init,
76};
77
78static 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
87MACHINE_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,
95MACHINE_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
15struct mtd_partition;
16
17extern void gemini_map_io(void);
18extern void gemini_init_irq(void);
19extern void gemini_timer_init(void);
20extern void gemini_gpio_init(void);
21
22/* Common platform devices registration functions */
23extern int platform_register_uart(void);
24extern 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
21static 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
35static struct platform_device serial_device = {
36 .name = "serial8250",
37 .id = PLAT8250_DEV_PLATFORM,
38 .dev = {
39 .platform_data = serial_platform_data,
40 },
41};
42
43int platform_register_uart(void)
44{
45 return platform_device_register(&serial_device);
46}
47
48static struct resource flash_resource = {
49 .start = GEMINI_FLASH_BASE,
50 .flags = IORESOURCE_MEM,
51};
52
53static struct physmap_flash_data pflash_platform_data = {};
54
55static 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
65int 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
47static 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
57static 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
65static 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
73static 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
81static 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
128static 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
147static 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
155static 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
169static 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
179static 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
186static int gemini_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
187{
188 _set_gpio_direction(chip, offset, 0);
189 return 0;
190}
191
192static 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
200static 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
210void __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
312312:
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
382313:
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
17static 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
31static 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
19static 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 */
26static 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
35static void gemini_ack_irq(unsigned int irq)
36{
37 __raw_writel(1 << irq, IRQ_CLEAR(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
38}
39
40static 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
49static 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
58static 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
65static 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
71void __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 */
20static 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
79void __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 */
39static irqreturn_t gemini_timer_interrupt(int irq, void *dev_id)
40{
41 timer_tick();
42
43 return IRQ_HANDLED;
44}
45
46static 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 */
55void __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
190config 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
190config CPU_ARM940T 208config 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
495config CPU_CACHE_VIPT 513config CPU_CACHE_VIPT
496 bool 514 bool
497 515
516config CPU_CACHE_FA
517 bool
518
498if MMU 519if MMU
499# The copy-page model 520# The copy-page model
500config CPU_COPY_V3 521config CPU_COPY_V3
@@ -509,6 +530,9 @@ config CPU_COPY_V4WB
509config CPU_COPY_FEROCEON 530config CPU_COPY_FEROCEON
510 bool 531 bool
511 532
533config CPU_COPY_FA
534 bool
535
512config CPU_COPY_V6 536config 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
566config 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
542config CPU_TLB_V6 573config CPU_TLB_V6
543 bool 574 bool
544 575
@@ -649,7 +680,7 @@ config CPU_DCACHE_SIZE
649 680
650config CPU_DCACHE_WRITETHROUGH 681config 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
665config CPU_BPREDICT_DISABLE 696config 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
33obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o 33obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o
34obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o 34obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o
35obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o 35obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o
36obj-$(CONFIG_CPU_CACHE_FA) += cache-fa.o
36 37
37obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o 38obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o
38obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o 39obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o
@@ -42,6 +43,7 @@ obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o context.o
42obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o 43obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o
43obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o 44obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o
44obj-$(CONFIG_CPU_XSC3) += copypage-xsc3.o 45obj-$(CONFIG_CPU_XSC3) += copypage-xsc3.o
46obj-$(CONFIG_CPU_COPY_FA) += copypage-fa.o
45 47
46obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o 48obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o
47obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o 49obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o
@@ -50,6 +52,7 @@ obj-$(CONFIG_CPU_TLB_V4WBI) += tlb-v4wbi.o
50obj-$(CONFIG_CPU_TLB_FEROCEON) += tlb-v4wbi.o # reuse v4wbi TLB functions 52obj-$(CONFIG_CPU_TLB_FEROCEON) += tlb-v4wbi.o # reuse v4wbi TLB functions
51obj-$(CONFIG_CPU_TLB_V6) += tlb-v6.o 53obj-$(CONFIG_CPU_TLB_V6) += tlb-v6.o
52obj-$(CONFIG_CPU_TLB_V7) += tlb-v7.o 54obj-$(CONFIG_CPU_TLB_V7) += tlb-v7.o
55obj-$(CONFIG_CPU_TLB_FA) += tlb-fa.o
53 56
54obj-$(CONFIG_CPU_ARM610) += proc-arm6_7.o 57obj-$(CONFIG_CPU_ARM610) += proc-arm6_7.o
55obj-$(CONFIG_CPU_ARM710) += proc-arm6_7.o 58obj-$(CONFIG_CPU_ARM710) += proc-arm6_7.o
@@ -63,6 +66,7 @@ obj-$(CONFIG_CPU_ARM925T) += proc-arm925.o
63obj-$(CONFIG_CPU_ARM926T) += proc-arm926.o 66obj-$(CONFIG_CPU_ARM926T) += proc-arm926.o
64obj-$(CONFIG_CPU_ARM940T) += proc-arm940.o 67obj-$(CONFIG_CPU_ARM940T) += proc-arm940.o
65obj-$(CONFIG_CPU_ARM946E) += proc-arm946.o 68obj-$(CONFIG_CPU_ARM946E) += proc-arm946.o
69obj-$(CONFIG_CPU_FA526) += proc-fa526.o
66obj-$(CONFIG_CPU_ARM1020) += proc-arm1020.o 70obj-$(CONFIG_CPU_ARM1020) += proc-arm1020.o
67obj-$(CONFIG_CPU_ARM1020E) += proc-arm1020e.o 71obj-$(CONFIG_CPU_ARM1020E) += proc-arm1020e.o
68obj-$(CONFIG_CPU_ARM1022) += proc-arm1022.o 72obj-$(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 */
46ENTRY(fa_flush_user_cache_all)
47 /* FALLTHROUGH */
48/*
49 * flush_kern_cache_all()
50 *
51 * Clean and invalidate the entire cache.
52 */
53ENTRY(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 */
75ENTRY(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
811: 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 */
103ENTRY(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 */
116ENTRY(fa_coherent_user_range)
117 bic r0, r0, #CACHE_DLINESIZE - 1
1181: 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 */
137ENTRY(fa_flush_kern_dcache_page)
138 add r1, r0, #PAGE_SZ
1391: 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 */
159ENTRY(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
1661: 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 */
182ENTRY(fa_dma_clean_range)
183 bic r0, r0, #CACHE_DLINESIZE - 1
1841: 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 */
197ENTRY(fa_dma_flush_range)
198 bic r0, r0, #CACHE_DLINESIZE - 1
1991: 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
210ENTRY(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 */
20static void __naked
21fa_copy_user_page(void *kto, const void *kfrom)
22{
23 asm("\
24 stmfd sp!, {r4, lr} @ 2\n\
25 mov r2, %0 @ 1\n\
261: 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
42void 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 */
59void 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\
681: 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
83struct 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 */
35ENTRY(cpu_fa526_proc_init)
36 mov pc, lr
37
38/*
39 * cpu_fa526_proc_fin()
40 */
41ENTRY(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
64ENTRY(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
85ENTRY(cpu_fa526_do_idle)
86 mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
87 mov pc, lr
88
89
90ENTRY(cpu_fa526_dcache_clean_area)
911: 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
108ENTRY(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
131ENTRY(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
180fa526_cr1_clear:
181 .word 0x3f3f
182fa526_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
192fa526_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
207cpu_arch_name:
208 .asciz "armv4"
209 .size cpu_arch_name, . - cpu_arch_name
210
211 .type cpu_elf_name, #object
212cpu_elf_name:
213 .asciz "v4"
214 .size cpu_elf_name, . - cpu_elf_name
215
216 .type cpu_fa526_name, #object
217cpu_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
36ENTRY(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
451: 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
54ENTRY(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
591: 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
71ENTRY(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