aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig5
-rw-r--r--arch/arm/boot/compressed/.gitignore1
-rw-r--r--arch/arm/boot/compressed/Makefile13
-rw-r--r--arch/arm/boot/compressed/head.S93
-rw-r--r--arch/arm/common/sharpsl_pm.c2
-rw-r--r--arch/arm/kernel/head-common.S40
-rw-r--r--arch/arm/kernel/head.S7
-rw-r--r--arch/arm/kernel/process.c8
-rw-r--r--arch/arm/kernel/setup.c6
-rw-r--r--arch/arm/mach-at91/board-sam9261ek.c130
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c64
-rw-r--r--arch/arm/mach-davinci/Makefile3
-rw-r--r--arch/arm/mach-davinci/board-evm.c2
-rw-r--r--arch/arm/mach-davinci/clock.c323
-rw-r--r--arch/arm/mach-davinci/clock.h33
-rw-r--r--arch/arm/mach-davinci/gpio.c286
-rw-r--r--arch/arm/mach-davinci/io.c6
-rw-r--r--arch/arm/mach-davinci/mux.c41
-rw-r--r--arch/arm/mach-davinci/psc.c87
-rw-r--r--arch/arm/mach-imx/generic.c118
-rw-r--r--arch/arm/mach-imx/time.c121
-rw-r--r--arch/arm/mach-iop13xx/tpmi.c32
-rw-r--r--arch/arm/mach-ks8695/Makefile2
-rw-r--r--arch/arm/mach-ks8695/gpio.c218
-rw-r--r--arch/arm/mach-pxa/clock.c15
-rw-r--r--arch/arm/mach-pxa/corgi.c7
-rw-r--r--arch/arm/mach-pxa/devices.h11
-rw-r--r--arch/arm/mach-pxa/dma.c44
-rw-r--r--arch/arm/mach-pxa/generic.c93
-rw-r--r--arch/arm/mach-pxa/generic.h6
-rw-r--r--arch/arm/mach-pxa/idp.c3
-rw-r--r--arch/arm/mach-pxa/irq.c106
-rw-r--r--arch/arm/mach-pxa/lpd270.c3
-rw-r--r--arch/arm/mach-pxa/lubbock.c3
-rw-r--r--arch/arm/mach-pxa/mainstone.c3
-rw-r--r--arch/arm/mach-pxa/pm.c47
-rw-r--r--arch/arm/mach-pxa/poodle.c3
-rw-r--r--arch/arm/mach-pxa/pxa25x.c62
-rw-r--r--arch/arm/mach-pxa/pxa27x.c78
-rw-r--r--arch/arm/mach-pxa/spitz.c7
-rw-r--r--arch/arm/mach-pxa/time.c9
-rw-r--r--arch/arm/mach-pxa/tosa.c4
-rw-r--r--arch/arm/mach-pxa/trizeps4.c3
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c59
-rw-r--r--arch/arm/mach-s3c2440/mach-anubis.c141
-rw-r--r--arch/arm/mach-s3c2440/mach-osiris.c38
-rw-r--r--arch/arm/mach-sa1100/pm.c9
-rw-r--r--arch/arm/mach-sa1100/time.c24
-rw-r--r--arch/arm/mm/ioremap.c10
49 files changed, 2069 insertions, 360 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 50d9f3e4e0f1..a0fa1ce9ad6c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -241,6 +241,9 @@ config ARCH_H720X
241 241
242config ARCH_IMX 242config ARCH_IMX
243 bool "IMX" 243 bool "IMX"
244 select GENERIC_GPIO
245 select GENERIC_TIME
246 select GENERIC_CLOCKEVENTS
244 help 247 help
245 Support for Motorola's i.MX family of processors (MX1, MXL). 248 Support for Motorola's i.MX family of processors (MX1, MXL).
246 249
@@ -308,6 +311,7 @@ config ARCH_L7200
308 311
309config ARCH_KS8695 312config ARCH_KS8695
310 bool "Micrel/Kendin KS8695" 313 bool "Micrel/Kendin KS8695"
314 select GENERIC_GPIO
311 help 315 help
312 Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based 316 Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
313 System-on-Chip devices. 317 System-on-Chip devices.
@@ -384,6 +388,7 @@ config ARCH_DAVINCI
384 bool "TI DaVinci" 388 bool "TI DaVinci"
385 select GENERIC_TIME 389 select GENERIC_TIME
386 select GENERIC_CLOCKEVENTS 390 select GENERIC_CLOCKEVENTS
391 select GENERIC_GPIO
387 help 392 help
388 Support for TI's DaVinci platform. 393 Support for TI's DaVinci platform.
389 394
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
index aefee20cbf98..b15f927a5926 100644
--- a/arch/arm/boot/compressed/.gitignore
+++ b/arch/arm/boot/compressed/.gitignore
@@ -1 +1,2 @@
1piggy.gz 1piggy.gz
2font.c
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index adddc7131685..a1f1691b67fe 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -6,15 +6,13 @@
6 6
7HEAD = head.o 7HEAD = head.o
8OBJS = misc.o 8OBJS = misc.o
9FONTC = drivers/video/console/font_acorn_8x8.c 9FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c
10
11FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o)
12 10
13# 11#
14# Architecture dependencies 12# Architecture dependencies
15# 13#
16ifeq ($(CONFIG_ARCH_ACORN),y) 14ifeq ($(CONFIG_ARCH_ACORN),y)
17OBJS += ll_char_wr.o $(FONT) 15OBJS += ll_char_wr.o font.o
18endif 16endif
19 17
20ifeq ($(CONFIG_ARCH_SHARK),y) 18ifeq ($(CONFIG_ARCH_SHARK),y)
@@ -73,7 +71,7 @@ endif
73 71
74SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ 72SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
75 73
76targets := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \ 74targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \
77 head.o misc.o $(OBJS) 75 head.o misc.o $(OBJS)
78EXTRA_CFLAGS := -fpic 76EXTRA_CFLAGS := -fpic
79EXTRA_AFLAGS := 77EXTRA_AFLAGS :=
@@ -105,7 +103,10 @@ $(obj)/piggy.gz: $(obj)/../Image FORCE
105 103
106$(obj)/piggy.o: $(obj)/piggy.gz FORCE 104$(obj)/piggy.o: $(obj)/piggy.gz FORCE
107 105
108CFLAGS_font_acorn_8x8.o := -Dstatic= 106CFLAGS_font.o := -Dstatic=
107
108$(obj)/font.c: $(FONTC)
109 $(call cmd,shipped)
109 110
110$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config 111$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config
111 @sed "$(SEDFLAGS)" < $< > $@ 112 @sed "$(SEDFLAGS)" < $< > $@
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 680ea6ed77b8..d7fb5ee1637e 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -436,6 +436,28 @@ __armv4_mmu_cache_on:
436 mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs 436 mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
437 mov pc, r12 437 mov pc, r12
438 438
439__armv7_mmu_cache_on:
440 mov r12, lr
441 mrc p15, 0, r11, c0, c1, 4 @ read ID_MMFR0
442 tst r11, #0xf @ VMSA
443 blne __setup_mmu
444 mov r0, #0
445 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
446 tst r11, #0xf @ VMSA
447 mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
448 mrc p15, 0, r0, c1, c0, 0 @ read control reg
449 orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
450 orr r0, r0, #0x003c @ write buffer
451 orrne r0, r0, #1 @ MMU enabled
452 movne r1, #-1
453 mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer
454 mcrne p15, 0, r1, c3, c0, 0 @ load domain access control
455 mcr p15, 0, r0, c1, c0, 0 @ load control register
456 mrc p15, 0, r0, c1, c0, 0 @ and read it back
457 mov r0, #0
458 mcr p15, 0, r0, c7, c5, 4 @ ISB
459 mov pc, r12
460
439__arm6_mmu_cache_on: 461__arm6_mmu_cache_on:
440 mov r12, lr 462 mov r12, lr
441 bl __setup_mmu 463 bl __setup_mmu
@@ -622,11 +644,17 @@ proc_types:
622 b __armv4_mmu_cache_flush 644 b __armv4_mmu_cache_flush
623 645
624 .word 0x0007b000 @ ARMv6 646 .word 0x0007b000 @ ARMv6
625 .word 0x0007f000 647 .word 0x000ff000
626 b __armv4_mmu_cache_on 648 b __armv4_mmu_cache_on
627 b __armv4_mmu_cache_off 649 b __armv4_mmu_cache_off
628 b __armv6_mmu_cache_flush 650 b __armv6_mmu_cache_flush
629 651
652 .word 0x000f0000 @ new CPU Id
653 .word 0x000f0000
654 b __armv7_mmu_cache_on
655 b __armv7_mmu_cache_off
656 b __armv7_mmu_cache_flush
657
630 .word 0 @ unrecognised type 658 .word 0 @ unrecognised type
631 .word 0 659 .word 0
632 mov pc, lr 660 mov pc, lr
@@ -674,6 +702,16 @@ __armv4_mmu_cache_off:
674 mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4 702 mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4
675 mov pc, lr 703 mov pc, lr
676 704
705__armv7_mmu_cache_off:
706 mrc p15, 0, r0, c1, c0
707 bic r0, r0, #0x000d
708 mcr p15, 0, r0, c1, c0 @ turn MMU and cache off
709 mov r12, lr
710 bl __armv7_mmu_cache_flush
711 mov r0, #0
712 mcr p15, 0, r0, c8, c7, 0 @ invalidate whole TLB
713 mov pc, r12
714
677__arm6_mmu_cache_off: 715__arm6_mmu_cache_off:
678 mov r0, #0x00000030 @ ARM6 control reg. 716 mov r0, #0x00000030 @ ARM6 control reg.
679 b __armv3_mmu_cache_off 717 b __armv3_mmu_cache_off
@@ -730,6 +768,59 @@ __armv6_mmu_cache_flush:
730 mcr p15, 0, r1, c7, c10, 4 @ drain WB 768 mcr p15, 0, r1, c7, c10, 4 @ drain WB
731 mov pc, lr 769 mov pc, lr
732 770
771__armv7_mmu_cache_flush:
772 mrc p15, 0, r10, c0, c1, 5 @ read ID_MMFR1
773 tst r10, #0xf << 16 @ hierarchical cache (ARMv7)
774 beq hierarchical
775 mov r10, #0
776 mcr p15, 0, r10, c7, c14, 0 @ clean+invalidate D
777 b iflush
778hierarchical:
779 stmfd sp!, {r0-r5, r7, r9-r11}
780 mrc p15, 1, r0, c0, c0, 1 @ read clidr
781 ands r3, r0, #0x7000000 @ extract loc from clidr
782 mov r3, r3, lsr #23 @ left align loc bit field
783 beq finished @ if loc is 0, then no need to clean
784 mov r10, #0 @ start clean at cache level 0
785loop1:
786 add r2, r10, r10, lsr #1 @ work out 3x current cache level
787 mov r1, r0, lsr r2 @ extract cache type bits from clidr
788 and r1, r1, #7 @ mask of the bits for current cache only
789 cmp r1, #2 @ see what cache we have at this level
790 blt skip @ skip if no cache, or just i-cache
791 mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
792 mcr p15, 0, r10, c7, c5, 4 @ isb to sych the new cssr&csidr
793 mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
794 and r2, r1, #7 @ extract the length of the cache lines
795 add r2, r2, #4 @ add 4 (line length offset)
796 ldr r4, =0x3ff
797 ands r4, r4, r1, lsr #3 @ find maximum number on the way size
798 .word 0xe16f5f14 @ clz r5, r4 - find bit position of way size increment
799 ldr r7, =0x7fff
800 ands r7, r7, r1, lsr #13 @ extract max number of the index size
801loop2:
802 mov r9, r4 @ create working copy of max way size
803loop3:
804 orr r11, r10, r9, lsl r5 @ factor way and cache number into r11
805 orr r11, r11, r7, lsl r2 @ factor index number into r11
806 mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
807 subs r9, r9, #1 @ decrement the way
808 bge loop3
809 subs r7, r7, #1 @ decrement the index
810 bge loop2
811skip:
812 add r10, r10, #2 @ increment cache number
813 cmp r3, r10
814 bgt loop1
815finished:
816 mov r10, #0 @ swith back to cache level 0
817 mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
818 ldmfd sp!, {r0-r5, r7, r9-r11}
819iflush:
820 mcr p15, 0, r10, c7, c5, 0 @ invalidate I+BTB
821 mcr p15, 0, r10, c7, c10, 4 @ drain WB
822 mov pc, lr
823
733__armv4_mmu_cache_flush: 824__armv4_mmu_cache_flush:
734 mov r2, #64*1024 @ default: 32K dcache size (*2) 825 mov r2, #64*1024 @ default: 32K dcache size (*2)
735 mov r11, #32 @ default: 32 byte line size 826 mov r11, #32 @ default: 32 byte line size
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index 3bf3a927ae22..111a7fa5debe 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -766,9 +766,7 @@ static void sharpsl_apm_get_power_status(struct apm_power_info *info)
766} 766}
767 767
768static struct pm_ops sharpsl_pm_ops = { 768static struct pm_ops sharpsl_pm_ops = {
769 .prepare = pxa_pm_prepare,
770 .enter = corgi_pxa_pm_enter, 769 .enter = corgi_pxa_pm_enter,
771 .finish = pxa_pm_finish,
772 .valid = pm_valid_only_mem, 770 .valid = pm_valid_only_mem,
773}; 771};
774 772
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index a52da0ddb43d..024a9cf469b4 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -20,7 +20,8 @@ __switch_data:
20 .long _end @ r7 20 .long _end @ r7
21 .long processor_id @ r4 21 .long processor_id @ r4
22 .long __machine_arch_type @ r5 22 .long __machine_arch_type @ r5
23 .long cr_alignment @ r6 23 .long __atags_pointer @ r6
24 .long cr_alignment @ r7
24 .long init_thread_union + THREAD_START_SP @ sp 25 .long init_thread_union + THREAD_START_SP @ sp
25 26
26/* 27/*
@@ -29,6 +30,7 @@ __switch_data:
29 * 30 *
30 * r0 = cp#15 control register 31 * r0 = cp#15 control register
31 * r1 = machine ID 32 * r1 = machine ID
33 * r2 = atags pointer
32 * r9 = processor ID 34 * r9 = processor ID
33 */ 35 */
34 .type __mmap_switched, %function 36 .type __mmap_switched, %function
@@ -47,11 +49,12 @@ __mmap_switched:
47 strcc fp, [r6],#4 49 strcc fp, [r6],#4
48 bcc 1b 50 bcc 1b
49 51
50 ldmia r3, {r4, r5, r6, sp} 52 ldmia r3, {r4, r5, r6, r7, sp}
51 str r9, [r4] @ Save processor ID 53 str r9, [r4] @ Save processor ID
52 str r1, [r5] @ Save machine type 54 str r1, [r5] @ Save machine type
55 str r2, [r6] @ Save atags pointer
53 bic r4, r0, #CR_A @ Clear 'A' bit 56 bic r4, r0, #CR_A @ Clear 'A' bit
54 stmia r6, {r0, r4} @ Save control register values 57 stmia r7, {r0, r4} @ Save control register values
55 b start_kernel 58 b start_kernel
56 59
57/* 60/*
@@ -215,3 +218,34 @@ ENTRY(lookup_machine_type)
215 bl __lookup_machine_type 218 bl __lookup_machine_type
216 mov r0, r5 219 mov r0, r5
217 ldmfd sp!, {r4 - r6, pc} 220 ldmfd sp!, {r4 - r6, pc}
221
222/* Determine validity of the r2 atags pointer. The heuristic requires
223 * that the pointer be aligned, in the first 16k of physical RAM and
224 * that the ATAG_CORE marker is first and present. Future revisions
225 * of this function may be more lenient with the physical address and
226 * may also be able to move the ATAGS block if necessary.
227 *
228 * r8 = machinfo
229 *
230 * Returns:
231 * r2 either valid atags pointer, or zero
232 * r5, r6 corrupted
233 */
234
235 .type __vet_atags, %function
236__vet_atags:
237 tst r2, #0x3 @ aligned?
238 bne 1f
239
240 ldr r5, [r2, #0] @ is first tag ATAG_CORE?
241 subs r5, r5, #ATAG_CORE_SIZE
242 bne 1f
243 ldr r5, [r2, #4]
244 ldr r6, =ATAG_CORE
245 cmp r5, r6
246 bne 1f
247
248 mov pc, lr @ atag pointer is ok
249
2501: mov r2, #0
251 mov pc, lr
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 41f98b4ba2ee..7898cbc9861a 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -29,6 +29,10 @@
29#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) 29#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET)
30#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) 30#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET)
31 31
32#define ATAG_CORE 0x54410001
33#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
34
35
32/* 36/*
33 * swapper_pg_dir is the virtual address of the initial page table. 37 * swapper_pg_dir is the virtual address of the initial page table.
34 * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must 38 * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must
@@ -61,7 +65,7 @@
61 * 65 *
62 * This is normally called from the decompressor code. The requirements 66 * This is normally called from the decompressor code. The requirements
63 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, 67 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
64 * r1 = machine nr. 68 * r1 = machine nr, r2 = atags pointer.
65 * 69 *
66 * This code is mostly position independent, so if you link the kernel at 70 * This code is mostly position independent, so if you link the kernel at
67 * 0xc0008000, you call this at __pa(0xc0008000). 71 * 0xc0008000, you call this at __pa(0xc0008000).
@@ -85,6 +89,7 @@ ENTRY(stext)
85 bl __lookup_machine_type @ r5=machinfo 89 bl __lookup_machine_type @ r5=machinfo
86 movs r8, r5 @ invalid machine (r5=0)? 90 movs r8, r5 @ invalid machine (r5=0)?
87 beq __error_a @ yes, error 'a' 91 beq __error_a @ yes, error 'a'
92 bl __vet_atags
88 bl __create_page_tables 93 bl __create_page_tables
89 94
90 /* 95 /*
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 842361777d4e..93b7f8e22dcc 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -44,6 +44,10 @@ static const char *processor_modes[] = {
44 "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" 44 "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
45}; 45};
46 46
47static const char *isa_modes[] = {
48 "ARM" , "Thumb" , "Jazelle", "ThumbEE"
49};
50
47extern void setup_mm_for_reboot(char mode); 51extern void setup_mm_for_reboot(char mode);
48 52
49static volatile int hlt_counter; 53static volatile int hlt_counter;
@@ -230,11 +234,11 @@ void __show_regs(struct pt_regs *regs)
230 buf[3] = flags & PSR_V_BIT ? 'V' : 'v'; 234 buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
231 buf[4] = '\0'; 235 buf[4] = '\0';
232 236
233 printk("Flags: %s IRQs o%s FIQs o%s Mode %s%s Segment %s\n", 237 printk("Flags: %s IRQs o%s FIQs o%s Mode %s ISA %s Segment %s\n",
234 buf, interrupts_enabled(regs) ? "n" : "ff", 238 buf, interrupts_enabled(regs) ? "n" : "ff",
235 fast_interrupts_enabled(regs) ? "n" : "ff", 239 fast_interrupts_enabled(regs) ? "n" : "ff",
236 processor_modes[processor_mode(regs)], 240 processor_modes[processor_mode(regs)],
237 thumb_mode(regs) ? " (T)" : "", 241 isa_modes[isa_mode(regs)],
238 get_fs() == get_ds() ? "kernel" : "user"); 242 get_fs() == get_ds() ? "kernel" : "user");
239#ifdef CONFIG_CPU_CP15 243#ifdef CONFIG_CPU_CP15
240 { 244 {
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 650eac1bc0a6..5be2e987b843 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -63,6 +63,8 @@ unsigned int processor_id;
63unsigned int __machine_arch_type; 63unsigned int __machine_arch_type;
64EXPORT_SYMBOL(__machine_arch_type); 64EXPORT_SYMBOL(__machine_arch_type);
65 65
66unsigned int __atags_pointer __initdata;
67
66unsigned int system_rev; 68unsigned int system_rev;
67EXPORT_SYMBOL(system_rev); 69EXPORT_SYMBOL(system_rev);
68 70
@@ -780,7 +782,9 @@ void __init setup_arch(char **cmdline_p)
780 if (mdesc->soft_reboot) 782 if (mdesc->soft_reboot)
781 reboot_setup("s"); 783 reboot_setup("s");
782 784
783 if (mdesc->boot_params) 785 if (__atags_pointer)
786 tags = phys_to_virt(__atags_pointer);
787 else if (mdesc->boot_params)
784 tags = phys_to_virt(mdesc->boot_params); 788 tags = phys_to_virt(mdesc->boot_params);
785 789
786 /* 790 /*
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 26ca8ab3f62a..42e172cb0f49 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -27,6 +27,11 @@
27#include <linux/spi/spi.h> 27#include <linux/spi/spi.h>
28#include <linux/spi/ads7846.h> 28#include <linux/spi/ads7846.h>
29#include <linux/dm9000.h> 29#include <linux/dm9000.h>
30#include <linux/fb.h>
31#include <linux/gpio_keys.h>
32#include <linux/input.h>
33
34#include <video/atmel_lcdc.h>
30 35
31#include <asm/hardware.h> 36#include <asm/hardware.h>
32#include <asm/setup.h> 37#include <asm/setup.h>
@@ -271,6 +276,127 @@ static struct spi_board_info ek_spi_devices[] = {
271}; 276};
272 277
273 278
279/*
280 * LCD Controller
281 */
282#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
283static struct fb_videomode at91_tft_vga_modes[] = {
284 {
285 .name = "TX09D50VM1CCA @ 60",
286 .refresh = 60,
287 .xres = 240, .yres = 320,
288 .pixclock = KHZ2PICOS(4965),
289
290 .left_margin = 1, .right_margin = 33,
291 .upper_margin = 1, .lower_margin = 0,
292 .hsync_len = 5, .vsync_len = 1,
293
294 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
295 .vmode = FB_VMODE_NONINTERLACED,
296 },
297};
298
299static struct fb_monspecs at91fb_default_monspecs = {
300 .manufacturer = "HIT",
301 .monitor = "TX09D50VM1CCA",
302
303 .modedb = at91_tft_vga_modes,
304 .modedb_len = ARRAY_SIZE(at91_tft_vga_modes),
305 .hfmin = 15000,
306 .hfmax = 64000,
307 .vfmin = 50,
308 .vfmax = 150,
309};
310
311#define AT91SAM9261_DEFAULT_LCDCON2 (ATMEL_LCDC_MEMOR_LITTLE \
312 | ATMEL_LCDC_DISTYPE_TFT \
313 | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
314
315static void at91_lcdc_power_control(int on)
316{
317 if (on)
318 at91_set_gpio_value(AT91_PIN_PA12, 0); /* power up */
319 else
320 at91_set_gpio_value(AT91_PIN_PA12, 1); /* power down */
321}
322
323/* Driver datas */
324static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
325 .default_bpp = 16,
326 .default_dmacon = ATMEL_LCDC_DMAEN,
327 .default_lcdcon2 = AT91SAM9261_DEFAULT_LCDCON2,
328 .default_monspecs = &at91fb_default_monspecs,
329 .atmel_lcdfb_power_control = at91_lcdc_power_control,
330 .guard_time = 1,
331};
332
333#else
334static struct atmel_lcdfb_info __initdata ek_lcdc_data;
335#endif
336
337
338/*
339 * GPIO Buttons
340 */
341#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
342static struct gpio_keys_button ek_buttons[] = {
343 {
344 .gpio = AT91_PIN_PA27,
345 .keycode = BTN_0,
346 .desc = "Button 0",
347 .active_low = 1,
348 },
349 {
350 .gpio = AT91_PIN_PA26,
351 .keycode = BTN_1,
352 .desc = "Button 1",
353 .active_low = 1,
354 },
355 {
356 .gpio = AT91_PIN_PA25,
357 .keycode = BTN_2,
358 .desc = "Button 2",
359 .active_low = 1,
360 },
361 {
362 .gpio = AT91_PIN_PA24,
363 .keycode = BTN_3,
364 .desc = "Button 3",
365 .active_low = 1,
366 }
367};
368
369static struct gpio_keys_platform_data ek_button_data = {
370 .buttons = ek_buttons,
371 .nbuttons = ARRAY_SIZE(ek_buttons),
372};
373
374static struct platform_device ek_button_device = {
375 .name = "gpio-keys",
376 .id = -1,
377 .num_resources = 0,
378 .dev = {
379 .platform_data = &ek_button_data,
380 }
381};
382
383static void __init ek_add_device_buttons(void)
384{
385 at91_set_gpio_input(AT91_PIN_PB27, 0); /* btn0 */
386 at91_set_deglitch(AT91_PIN_PB27, 1);
387 at91_set_gpio_input(AT91_PIN_PB26, 0); /* btn1 */
388 at91_set_deglitch(AT91_PIN_PB26, 1);
389 at91_set_gpio_input(AT91_PIN_PB25, 0); /* btn2 */
390 at91_set_deglitch(AT91_PIN_PB25, 1);
391 at91_set_gpio_input(AT91_PIN_PB24, 0); /* btn3 */
392 at91_set_deglitch(AT91_PIN_PB24, 1);
393
394 platform_device_register(&ek_button_device);
395}
396#else
397static void __init ek_add_device_buttons(void) {}
398#endif
399
274static void __init ek_board_init(void) 400static void __init ek_board_init(void)
275{ 401{
276 /* Serial */ 402 /* Serial */
@@ -296,6 +422,10 @@ static void __init ek_board_init(void)
296 /* MMC */ 422 /* MMC */
297 at91_add_device_mmc(0, &ek_mmc_data); 423 at91_add_device_mmc(0, &ek_mmc_data);
298#endif 424#endif
425 /* LCD Controller */
426 at91_add_device_lcdc(&ek_lcdc_data);
427 /* Push Buttons */
428 ek_add_device_buttons();
299} 429}
300 430
301MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK") 431MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index c164c8e58ae6..2a1cc73390b7 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -26,6 +26,9 @@
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/spi/spi.h> 27#include <linux/spi/spi.h>
28#include <linux/spi/ads7846.h> 28#include <linux/spi/ads7846.h>
29#include <linux/fb.h>
30
31#include <video/atmel_lcdc.h>
29 32
30#include <asm/hardware.h> 33#include <asm/hardware.h>
31#include <asm/setup.h> 34#include <asm/setup.h>
@@ -202,6 +205,65 @@ static struct at91_nand_data __initdata ek_nand_data = {
202 205
203 206
204/* 207/*
208 * LCD Controller
209 */
210#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
211static struct fb_videomode at91_tft_vga_modes[] = {
212 {
213 .name = "TX09D50VM1CCA @ 60",
214 .refresh = 60,
215 .xres = 240, .yres = 320,
216 .pixclock = KHZ2PICOS(4965),
217
218 .left_margin = 1, .right_margin = 33,
219 .upper_margin = 1, .lower_margin = 0,
220 .hsync_len = 5, .vsync_len = 1,
221
222 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
223 .vmode = FB_VMODE_NONINTERLACED,
224 },
225};
226
227static struct fb_monspecs at91fb_default_monspecs = {
228 .manufacturer = "HIT",
229 .monitor = "TX09D70VM1CCA",
230
231 .modedb = at91_tft_vga_modes,
232 .modedb_len = ARRAY_SIZE(at91_tft_vga_modes),
233 .hfmin = 15000,
234 .hfmax = 64000,
235 .vfmin = 50,
236 .vfmax = 150,
237};
238
239#define AT91SAM9263_DEFAULT_LCDCON2 (ATMEL_LCDC_MEMOR_LITTLE \
240 | ATMEL_LCDC_DISTYPE_TFT \
241 | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
242
243static void at91_lcdc_power_control(int on)
244{
245 if (on)
246 at91_set_gpio_value(AT91_PIN_PD12, 0); /* power up */
247 else
248 at91_set_gpio_value(AT91_PIN_PD12, 1); /* power down */
249}
250
251/* Driver datas */
252static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
253 .default_bpp = 16,
254 .default_dmacon = ATMEL_LCDC_DMAEN,
255 .default_lcdcon2 = AT91SAM9263_DEFAULT_LCDCON2,
256 .default_monspecs = &at91fb_default_monspecs,
257 .atmel_lcdfb_power_control = at91_lcdc_power_control,
258 .guard_time = 1,
259};
260
261#else
262static struct atmel_lcdfb_info __initdata ek_lcdc_data;
263#endif
264
265
266/*
205 * AC97 267 * AC97
206 */ 268 */
207static struct atmel_ac97_data ek_ac97_data = { 269static struct atmel_ac97_data ek_ac97_data = {
@@ -230,6 +292,8 @@ static void __init ek_board_init(void)
230 at91_add_device_nand(&ek_nand_data); 292 at91_add_device_nand(&ek_nand_data);
231 /* I2C */ 293 /* I2C */
232 at91_add_device_i2c(); 294 at91_add_device_i2c();
295 /* LCD Controller */
296 at91_add_device_lcdc(&ek_lcdc_data);
233 /* AC97 */ 297 /* AC97 */
234 at91_add_device_ac97(&ek_ac97_data); 298 at91_add_device_ac97(&ek_ac97_data);
235} 299}
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index a8f88cd29905..99ac2e55774d 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -4,7 +4,8 @@
4# 4#
5 5
6# Common objects 6# Common objects
7obj-y := time.o irq.o serial.o io.o id.o psc.o 7obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \
8 gpio.o mux.o
8 9
9# Board specific 10# Board specific
10obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o 11obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o
diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c
index 633c12e43044..9e4024c4965f 100644
--- a/arch/arm/mach-davinci/board-evm.c
+++ b/arch/arm/mach-davinci/board-evm.c
@@ -32,6 +32,7 @@
32void __init davinci_psc_init(void); 32void __init davinci_psc_init(void);
33void __init davinci_irq_init(void); 33void __init davinci_irq_init(void);
34void __init davinci_map_common_io(void); 34void __init davinci_map_common_io(void);
35void __init davinci_init_common_hw(void);
35 36
36/* NOR Flash base address set to CS0 by default */ 37/* NOR Flash base address set to CS0 by default */
37#define NOR_FLASH_PHYS 0x02000000 38#define NOR_FLASH_PHYS 0x02000000
@@ -116,6 +117,7 @@ static __init void davinci_evm_init(void)
116 117
117static __init void davinci_evm_irq_init(void) 118static __init void davinci_evm_irq_init(void)
118{ 119{
120 davinci_init_common_hw();
119 davinci_irq_init(); 121 davinci_irq_init();
120} 122}
121 123
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
new file mode 100644
index 000000000000..139ceaa35e24
--- /dev/null
+++ b/arch/arm/mach-davinci/clock.c
@@ -0,0 +1,323 @@
1/*
2 * TI DaVinci clock config file
3 *
4 * Copyright (C) 2006 Texas Instruments.
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#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/errno.h>
16#include <linux/err.h>
17#include <linux/mutex.h>
18#include <linux/platform_device.h>
19
20#include <asm/hardware.h>
21#include <asm/io.h>
22
23#include <asm/arch/psc.h>
24#include "clock.h"
25
26/* PLL/Reset register offsets */
27#define PLLM 0x110
28
29static LIST_HEAD(clocks);
30static DEFINE_MUTEX(clocks_mutex);
31static DEFINE_SPINLOCK(clockfw_lock);
32
33static unsigned int commonrate;
34static unsigned int armrate;
35static unsigned int fixedrate = 27000000; /* 27 MHZ */
36
37extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable);
38
39/*
40 * Returns a clock. Note that we first try to use device id on the bus
41 * and clock name. If this fails, we try to use clock name only.
42 */
43struct clk *clk_get(struct device *dev, const char *id)
44{
45 struct clk *p, *clk = ERR_PTR(-ENOENT);
46 int idno;
47
48 if (dev == NULL || dev->bus != &platform_bus_type)
49 idno = -1;
50 else
51 idno = to_platform_device(dev)->id;
52
53 mutex_lock(&clocks_mutex);
54
55 list_for_each_entry(p, &clocks, node) {
56 if (p->id == idno &&
57 strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
58 clk = p;
59 goto found;
60 }
61 }
62
63 list_for_each_entry(p, &clocks, node) {
64 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
65 clk = p;
66 break;
67 }
68 }
69
70found:
71 mutex_unlock(&clocks_mutex);
72
73 return clk;
74}
75EXPORT_SYMBOL(clk_get);
76
77void clk_put(struct clk *clk)
78{
79 if (clk && !IS_ERR(clk))
80 module_put(clk->owner);
81}
82EXPORT_SYMBOL(clk_put);
83
84static int __clk_enable(struct clk *clk)
85{
86 if (clk->flags & ALWAYS_ENABLED)
87 return 0;
88
89 davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1);
90 return 0;
91}
92
93static void __clk_disable(struct clk *clk)
94{
95 if (clk->usecount)
96 return;
97
98 davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0);
99}
100
101int clk_enable(struct clk *clk)
102{
103 unsigned long flags;
104 int ret = 0;
105
106 if (clk == NULL || IS_ERR(clk))
107 return -EINVAL;
108
109 if (clk->usecount++ == 0) {
110 spin_lock_irqsave(&clockfw_lock, flags);
111 ret = __clk_enable(clk);
112 spin_unlock_irqrestore(&clockfw_lock, flags);
113 }
114
115 return ret;
116}
117EXPORT_SYMBOL(clk_enable);
118
119void clk_disable(struct clk *clk)
120{
121 unsigned long flags;
122
123 if (clk == NULL || IS_ERR(clk))
124 return;
125
126 if (clk->usecount > 0 && !(--clk->usecount)) {
127 spin_lock_irqsave(&clockfw_lock, flags);
128 __clk_disable(clk);
129 spin_unlock_irqrestore(&clockfw_lock, flags);
130 }
131}
132EXPORT_SYMBOL(clk_disable);
133
134unsigned long clk_get_rate(struct clk *clk)
135{
136 if (clk == NULL || IS_ERR(clk))
137 return -EINVAL;
138
139 return *(clk->rate);
140}
141EXPORT_SYMBOL(clk_get_rate);
142
143long clk_round_rate(struct clk *clk, unsigned long rate)
144{
145 if (clk == NULL || IS_ERR(clk))
146 return -EINVAL;
147
148 return *(clk->rate);
149}
150EXPORT_SYMBOL(clk_round_rate);
151
152int clk_set_rate(struct clk *clk, unsigned long rate)
153{
154 if (clk == NULL || IS_ERR(clk))
155 return -EINVAL;
156
157 /* changing the clk rate is not supported */
158 return -EINVAL;
159}
160EXPORT_SYMBOL(clk_set_rate);
161
162int clk_register(struct clk *clk)
163{
164 if (clk == NULL || IS_ERR(clk))
165 return -EINVAL;
166
167 mutex_lock(&clocks_mutex);
168 list_add(&clk->node, &clocks);
169 mutex_unlock(&clocks_mutex);
170
171 return 0;
172}
173EXPORT_SYMBOL(clk_register);
174
175void clk_unregister(struct clk *clk)
176{
177 if (clk == NULL || IS_ERR(clk))
178 return;
179
180 mutex_lock(&clocks_mutex);
181 list_del(&clk->node);
182 mutex_unlock(&clocks_mutex);
183}
184EXPORT_SYMBOL(clk_unregister);
185
186static struct clk davinci_clks[] = {
187 {
188 .name = "ARMCLK",
189 .rate = &armrate,
190 .lpsc = -1,
191 .flags = ALWAYS_ENABLED,
192 },
193 {
194 .name = "UART",
195 .rate = &fixedrate,
196 .lpsc = DAVINCI_LPSC_UART0,
197 },
198 {
199 .name = "EMACCLK",
200 .rate = &commonrate,
201 .lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
202 },
203 {
204 .name = "I2CCLK",
205 .rate = &fixedrate,
206 .lpsc = DAVINCI_LPSC_I2C,
207 },
208 {
209 .name = "IDECLK",
210 .rate = &commonrate,
211 .lpsc = DAVINCI_LPSC_ATA,
212 },
213 {
214 .name = "McBSPCLK",
215 .rate = &commonrate,
216 .lpsc = DAVINCI_LPSC_McBSP,
217 },
218 {
219 .name = "MMCSDCLK",
220 .rate = &commonrate,
221 .lpsc = DAVINCI_LPSC_MMC_SD,
222 },
223 {
224 .name = "SPICLK",
225 .rate = &commonrate,
226 .lpsc = DAVINCI_LPSC_SPI,
227 },
228 {
229 .name = "gpio",
230 .rate = &commonrate,
231 .lpsc = DAVINCI_LPSC_GPIO,
232 },
233 {
234 .name = "AEMIFCLK",
235 .rate = &commonrate,
236 .lpsc = DAVINCI_LPSC_AEMIF,
237 .usecount = 1,
238 }
239};
240
241int __init davinci_clk_init(void)
242{
243 struct clk *clkp;
244 int count = 0;
245 u32 pll_mult;
246
247 pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM);
248 commonrate = ((pll_mult + 1) * 27000000) / 6;
249 armrate = ((pll_mult + 1) * 27000000) / 2;
250
251 for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks);
252 count++, clkp++) {
253 clk_register(clkp);
254
255 /* Turn on clocks that have been enabled in the
256 * table above */
257 if (clkp->usecount)
258 clk_enable(clkp);
259 }
260
261 return 0;
262}
263
264#ifdef CONFIG_PROC_FS
265#include <linux/proc_fs.h>
266#include <linux/seq_file.h>
267
268static void *davinci_ck_start(struct seq_file *m, loff_t *pos)
269{
270 return *pos < 1 ? (void *)1 : NULL;
271}
272
273static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos)
274{
275 ++*pos;
276 return NULL;
277}
278
279static void davinci_ck_stop(struct seq_file *m, void *v)
280{
281}
282
283static int davinci_ck_show(struct seq_file *m, void *v)
284{
285 struct clk *cp;
286
287 list_for_each_entry(cp, &clocks, node)
288 seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount);
289
290 return 0;
291}
292
293static struct seq_operations davinci_ck_op = {
294 .start = davinci_ck_start,
295 .next = davinci_ck_next,
296 .stop = davinci_ck_stop,
297 .show = davinci_ck_show
298};
299
300static int davinci_ck_open(struct inode *inode, struct file *file)
301{
302 return seq_open(file, &davinci_ck_op);
303}
304
305static struct file_operations proc_davinci_ck_operations = {
306 .open = davinci_ck_open,
307 .read = seq_read,
308 .llseek = seq_lseek,
309 .release = seq_release,
310};
311
312static int __init davinci_ck_proc_init(void)
313{
314 struct proc_dir_entry *entry;
315
316 entry = create_proc_entry("davinci_clocks", 0, NULL);
317 if (entry)
318 entry->proc_fops = &proc_davinci_ck_operations;
319 return 0;
320
321}
322__initcall(davinci_ck_proc_init);
323#endif /* CONFIG_DEBUG_PROC_FS */
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
new file mode 100644
index 000000000000..ed47079a52e4
--- /dev/null
+++ b/arch/arm/mach-davinci/clock.h
@@ -0,0 +1,33 @@
1/*
2 * TI DaVinci clock definitions
3 *
4 * Copyright (C) 2006 Texas Instruments.
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
11#ifndef __ARCH_ARM_DAVINCI_CLOCK_H
12#define __ARCH_ARM_DAVINCI_CLOCK_H
13
14struct clk {
15 struct list_head node;
16 struct module *owner;
17 const char *name;
18 unsigned int *rate;
19 int id;
20 __s8 usecount;
21 __u8 flags;
22 __u8 lpsc;
23};
24
25/* Clock flags */
26#define RATE_CKCTL 1
27#define RATE_FIXED 2
28#define RATE_PROPAGATES 4
29#define VIRTUAL_CLOCK 8
30#define ALWAYS_ENABLED 16
31#define ENABLE_REG_32BIT 32
32
33#endif
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c
new file mode 100644
index 000000000000..9c67886e7189
--- /dev/null
+++ b/arch/arm/mach-davinci/gpio.c
@@ -0,0 +1,286 @@
1/*
2 * TI DaVinci GPIO Support
3 *
4 * Copyright (c) 2006 David Brownell
5 * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
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#include <linux/errno.h>
14#include <linux/kernel.h>
15#include <linux/list.h>
16#include <linux/module.h>
17#include <linux/clk.h>
18#include <linux/err.h>
19#include <linux/io.h>
20#include <linux/irq.h>
21#include <linux/bitops.h>
22
23#include <asm/arch/irqs.h>
24#include <asm/arch/hardware.h>
25#include <asm/arch/gpio.h>
26
27#include <asm/mach/irq.h>
28
29static DEFINE_SPINLOCK(gpio_lock);
30static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO);
31
32int gpio_request(unsigned gpio, const char *tag)
33{
34 if (gpio >= DAVINCI_N_GPIO)
35 return -EINVAL;
36
37 if (test_and_set_bit(gpio, gpio_in_use))
38 return -EBUSY;
39
40 return 0;
41}
42EXPORT_SYMBOL(gpio_request);
43
44void gpio_free(unsigned gpio)
45{
46 if (gpio >= DAVINCI_N_GPIO)
47 return;
48
49 clear_bit(gpio, gpio_in_use);
50}
51EXPORT_SYMBOL(gpio_free);
52
53/* create a non-inlined version */
54static struct gpio_controller *__iomem gpio2controller(unsigned gpio)
55{
56 return __gpio_to_controller(gpio);
57}
58
59/*
60 * Assuming the pin is muxed as a gpio output, set its output value.
61 */
62void __gpio_set(unsigned gpio, int value)
63{
64 struct gpio_controller *__iomem g = gpio2controller(gpio);
65
66 __raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data);
67}
68EXPORT_SYMBOL(__gpio_set);
69
70
71/*
72 * Read the pin's value (works even if it's set up as output);
73 * returns zero/nonzero.
74 *
75 * Note that changes are synched to the GPIO clock, so reading values back
76 * right after you've set them may give old values.
77 */
78int __gpio_get(unsigned gpio)
79{
80 struct gpio_controller *__iomem g = gpio2controller(gpio);
81
82 return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
83}
84EXPORT_SYMBOL(__gpio_get);
85
86
87/*--------------------------------------------------------------------------*/
88
89/*
90 * board setup code *MUST* set PINMUX0 and PINMUX1 as
91 * needed, and enable the GPIO clock.
92 */
93
94int gpio_direction_input(unsigned gpio)
95{
96 struct gpio_controller *__iomem g = gpio2controller(gpio);
97 u32 temp;
98 u32 mask;
99
100 if (!g)
101 return -EINVAL;
102
103 spin_lock(&gpio_lock);
104 mask = __gpio_mask(gpio);
105 temp = __raw_readl(&g->dir);
106 temp |= mask;
107 __raw_writel(temp, &g->dir);
108 spin_unlock(&gpio_lock);
109 return 0;
110}
111EXPORT_SYMBOL(gpio_direction_input);
112
113int gpio_direction_output(unsigned gpio, int value)
114{
115 struct gpio_controller *__iomem g = gpio2controller(gpio);
116 u32 temp;
117 u32 mask;
118
119 if (!g)
120 return -EINVAL;
121
122 spin_lock(&gpio_lock);
123 mask = __gpio_mask(gpio);
124 temp = __raw_readl(&g->dir);
125 temp &= ~mask;
126 __raw_writel(mask, value ? &g->set_data : &g->clr_data);
127 __raw_writel(temp, &g->dir);
128 spin_unlock(&gpio_lock);
129 return 0;
130}
131EXPORT_SYMBOL(gpio_direction_output);
132
133/*
134 * We expect irqs will normally be set up as input pins, but they can also be
135 * used as output pins ... which is convenient for testing.
136 *
137 * NOTE: GPIO0..GPIO7 also have direct INTC hookups, which work in addition
138 * to their GPIOBNK0 irq (but with a bit less overhead). But we don't have
139 * a good way to hook those up ...
140 *
141 * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also
142 * serve as EDMA event triggers.
143 */
144
145static void gpio_irq_disable(unsigned irq)
146{
147 struct gpio_controller *__iomem g = get_irq_chip_data(irq);
148 u32 mask = __gpio_mask(irq_to_gpio(irq));
149
150 __raw_writel(mask, &g->clr_falling);
151 __raw_writel(mask, &g->clr_rising);
152}
153
154static void gpio_irq_enable(unsigned irq)
155{
156 struct gpio_controller *__iomem g = get_irq_chip_data(irq);
157 u32 mask = __gpio_mask(irq_to_gpio(irq));
158
159 if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING)
160 __raw_writel(mask, &g->set_falling);
161 if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING)
162 __raw_writel(mask, &g->set_rising);
163}
164
165static int gpio_irq_type(unsigned irq, unsigned trigger)
166{
167 struct gpio_controller *__iomem g = get_irq_chip_data(irq);
168 u32 mask = __gpio_mask(irq_to_gpio(irq));
169
170 if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
171 return -EINVAL;
172
173 irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
174 irq_desc[irq].status |= trigger;
175
176 __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
177 ? &g->set_falling : &g->clr_falling);
178 __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
179 ? &g->set_rising : &g->clr_rising);
180 return 0;
181}
182
183static struct irq_chip gpio_irqchip = {
184 .name = "GPIO",
185 .enable = gpio_irq_enable,
186 .disable = gpio_irq_disable,
187 .set_type = gpio_irq_type,
188};
189
190static void
191gpio_irq_handler(unsigned irq, struct irq_desc *desc)
192{
193 struct gpio_controller *__iomem g = get_irq_chip_data(irq);
194 u32 mask = 0xffff;
195
196 /* we only care about one bank */
197 if (irq & 1)
198 mask <<= 16;
199
200 /* temporarily mask (level sensitive) parent IRQ */
201 desc->chip->ack(irq);
202 while (1) {
203 u32 status;
204 struct irq_desc *gpio;
205 int n;
206 int res;
207
208 /* ack any irqs */
209 status = __raw_readl(&g->intstat) & mask;
210 if (!status)
211 break;
212 __raw_writel(status, &g->intstat);
213 if (irq & 1)
214 status >>= 16;
215
216 /* now demux them to the right lowlevel handler */
217 n = (int)get_irq_data(irq);
218 gpio = &irq_desc[n];
219 while (status) {
220 res = ffs(status);
221 n += res;
222 gpio += res;
223 desc_handle_irq(n - 1, gpio - 1);
224 status >>= res;
225 }
226 }
227 desc->chip->unmask(irq);
228 /* now it may re-trigger */
229}
230
231/*
232 * NOTE: for suspend/resume, probably best to make a sysdev (and class)
233 * with its suspend/resume calls hooking into the results of the set_wake()
234 * calls ... so if no gpios are wakeup events the clock can be disabled,
235 * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
236 * can be set appropriately for GPIOV33 pins.
237 */
238
239static int __init davinci_gpio_irq_setup(void)
240{
241 unsigned gpio, irq, bank;
242 struct clk *clk;
243
244 clk = clk_get(NULL, "gpio");
245 if (IS_ERR(clk)) {
246 printk(KERN_ERR "Error %ld getting gpio clock?\n",
247 PTR_ERR(clk));
248 return 0;
249 }
250
251 clk_enable(clk);
252
253 for (gpio = 0, irq = gpio_to_irq(0), bank = IRQ_GPIOBNK0;
254 gpio < DAVINCI_N_GPIO; bank++) {
255 struct gpio_controller *__iomem g = gpio2controller(gpio);
256 unsigned i;
257
258 __raw_writel(~0, &g->clr_falling);
259 __raw_writel(~0, &g->clr_rising);
260
261 /* set up all irqs in this bank */
262 set_irq_chained_handler(bank, gpio_irq_handler);
263 set_irq_chip_data(bank, g);
264 set_irq_data(bank, (void *)irq);
265
266 for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO;
267 i++, irq++, gpio++) {
268 set_irq_chip(irq, &gpio_irqchip);
269 set_irq_chip_data(irq, g);
270 set_irq_handler(irq, handle_simple_irq);
271 set_irq_flags(irq, IRQF_VALID);
272 }
273 }
274
275 /* BINTEN -- per-bank interrupt enable. genirq would also let these
276 * bits be set/cleared dynamically.
277 */
278 __raw_writel(0x1f, (void *__iomem)
279 IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));
280
281 printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
282
283 return 0;
284}
285
286arch_initcall(davinci_gpio_irq_setup);
diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c
index 87fae6fb6ecf..47787ff84a6a 100644
--- a/arch/arm/mach-davinci/io.c
+++ b/arch/arm/mach-davinci/io.c
@@ -17,6 +17,7 @@
17#include <asm/memory.h> 17#include <asm/memory.h>
18 18
19#include <asm/mach/map.h> 19#include <asm/mach/map.h>
20#include <asm/arch/clock.h>
20 21
21extern void davinci_check_revision(void); 22extern void davinci_check_revision(void);
22 23
@@ -49,3 +50,8 @@ void __init davinci_map_common_io(void)
49 */ 50 */
50 davinci_check_revision(); 51 davinci_check_revision();
51} 52}
53
54void __init davinci_init_common_hw(void)
55{
56 davinci_clk_init();
57}
diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c
new file mode 100644
index 000000000000..92d26bd305b7
--- /dev/null
+++ b/arch/arm/mach-davinci/mux.c
@@ -0,0 +1,41 @@
1/*
2 * DaVinci pin multiplexing configurations
3 *
4 * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
5 *
6 * 2007 (c) MontaVista Software, Inc. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
9 * or implied.
10 */
11#include <linux/io.h>
12#include <linux/spinlock.h>
13
14#include <asm/hardware.h>
15
16#include <asm/arch/mux.h>
17
18/* System control register offsets */
19#define PINMUX0 0x00
20#define PINMUX1 0x04
21
22static DEFINE_SPINLOCK(mux_lock);
23
24void davinci_mux_peripheral(unsigned int mux, unsigned int enable)
25{
26 u32 pinmux, muxreg = PINMUX0;
27
28 if (mux >= DAVINCI_MUX_LEVEL2) {
29 muxreg = PINMUX1;
30 mux -= DAVINCI_MUX_LEVEL2;
31 }
32
33 spin_lock(&mux_lock);
34 pinmux = davinci_readl(DAVINCI_SYSTEM_MODULE_BASE + muxreg);
35 if (enable)
36 pinmux |= (1 << mux);
37 else
38 pinmux &= ~(1 << mux);
39 davinci_writel(pinmux, DAVINCI_SYSTEM_MODULE_BASE + muxreg);
40 spin_unlock(&mux_lock);
41}
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index e1b0050283a6..1334416559ad 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -25,39 +25,40 @@
25#include <asm/io.h> 25#include <asm/io.h>
26#include <asm/hardware.h> 26#include <asm/hardware.h>
27#include <asm/arch/psc.h> 27#include <asm/arch/psc.h>
28#include <asm/arch/mux.h>
28 29
29#define PTCMD __REG(0x01C41120) 30/* PSC register offsets */
30#define PDSTAT __REG(0x01C41200) 31#define EPCPR 0x070
31#define PDCTL1 __REG(0x01C41304) 32#define PTCMD 0x120
32#define EPCPR __REG(0x01C41070) 33#define PTSTAT 0x128
33#define PTSTAT __REG(0x01C41128) 34#define PDSTAT 0x200
35#define PDCTL1 0x304
36#define MDSTAT 0x800
37#define MDCTL 0xA00
34 38
35#define MDSTAT IO_ADDRESS(0x01C41800) 39/* System control register offsets */
36#define MDCTL IO_ADDRESS(0x01C41A00) 40#define VDD3P3V_PWDN 0x48
37
38#define PINMUX0 __REG(0x01c40000)
39#define PINMUX1 __REG(0x01c40004)
40#define VDD3P3V_PWDN __REG(0x01C40048)
41 41
42static void davinci_psc_mux(unsigned int id) 42static void davinci_psc_mux(unsigned int id)
43{ 43{
44 switch (id) { 44 switch (id) {
45 case DAVINCI_LPSC_ATA: 45 case DAVINCI_LPSC_ATA:
46 PINMUX0 |= (1 << 17) | (1 << 16); 46 davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1);
47 davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1);
47 break; 48 break;
48 case DAVINCI_LPSC_MMC_SD: 49 case DAVINCI_LPSC_MMC_SD:
49 /* VDD power manupulations are done in U-Boot for CPMAC 50 /* VDD power manupulations are done in U-Boot for CPMAC
50 * so applies to MMC as well 51 * so applies to MMC as well
51 */ 52 */
52 /*Set up the pull regiter for MMC */ 53 /*Set up the pull regiter for MMC */
53 VDD3P3V_PWDN = 0x0; 54 davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN);
54 PINMUX1 &= (~(1 << 9)); 55 davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0);
55 break; 56 break;
56 case DAVINCI_LPSC_I2C: 57 case DAVINCI_LPSC_I2C:
57 PINMUX1 |= (1 << 7); 58 davinci_mux_peripheral(DAVINCI_MUX_I2C, 1);
58 break; 59 break;
59 case DAVINCI_LPSC_McBSP: 60 case DAVINCI_LPSC_McBSP:
60 PINMUX1 |= (1 << 10); 61 davinci_mux_peripheral(DAVINCI_MUX_ASP, 1);
61 break; 62 break;
62 default: 63 default:
63 break; 64 break;
@@ -67,33 +68,59 @@ static void davinci_psc_mux(unsigned int id)
67/* Enable or disable a PSC domain */ 68/* Enable or disable a PSC domain */
68void davinci_psc_config(unsigned int domain, unsigned int id, char enable) 69void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
69{ 70{
70 volatile unsigned int *mdstat = (unsigned int *)((int)MDSTAT + 4 * id); 71 u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask;
71 volatile unsigned int *mdctl = (unsigned int *)((int)MDCTL + 4 * id);
72 72
73 if (id < 0) 73 if (id < 0)
74 return; 74 return;
75 75
76 mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
76 if (enable) 77 if (enable)
77 *mdctl |= 0x00000003; /* Enable Module */ 78 mdctl |= 0x00000003; /* Enable Module */
78 else 79 else
79 *mdctl &= 0xFFFFFFF2; /* Disable Module */ 80 mdctl &= 0xFFFFFFF2; /* Disable Module */
81 davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
82
83 pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT);
84 if ((pdstat & 0x00000001) == 0) {
85 pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
86 pdctl1 |= 0x1;
87 davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
88
89 ptcmd = 1 << domain;
90 davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
80 91
81 if ((PDSTAT & 0x00000001) == 0) { 92 do {
82 PDCTL1 |= 0x1; 93 epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
83 PTCMD = (1 << domain); 94 EPCPR);
84 while ((((EPCPR >> domain) & 1) == 0)); 95 } while ((((epcpr >> domain) & 1) == 0));
85 96
86 PDCTL1 |= 0x100; 97 pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
87 while (!(((PTSTAT >> domain) & 1) == 0)); 98 pdctl1 |= 0x100;
99 davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
100
101 do {
102 ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
103 PTSTAT);
104 } while (!(((ptstat >> domain) & 1) == 0));
88 } else { 105 } else {
89 PTCMD = (1 << domain); 106 ptcmd = 1 << domain;
90 while (!(((PTSTAT >> domain) & 1) == 0)); 107 davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
108
109 do {
110 ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
111 PTSTAT);
112 } while (!(((ptstat >> domain) & 1) == 0));
91 } 113 }
92 114
93 if (enable) 115 if (enable)
94 while (!((*mdstat & 0x0000001F) == 0x3)); 116 mdstat_mask = 0x3;
95 else 117 else
96 while (!((*mdstat & 0x0000001F) == 0x2)); 118 mdstat_mask = 0x2;
119
120 do {
121 mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
122 MDSTAT + 4 * id);
123 } while (!((mdstat & 0x0000001F) == mdstat_mask));
97 124
98 if (enable) 125 if (enable)
99 davinci_psc_mux(id); 126 davinci_psc_mux(id);
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 1c474cf709ca..a58b678006df 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -28,12 +28,16 @@
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/string.h> 29#include <linux/string.h>
30 30
31#include <asm/errno.h>
31#include <asm/arch/imxfb.h> 32#include <asm/arch/imxfb.h>
32#include <asm/hardware.h> 33#include <asm/hardware.h>
33#include <asm/arch/imx-regs.h> 34#include <asm/arch/imx-regs.h>
34 35
35#include <asm/mach/map.h> 36#include <asm/mach/map.h>
36#include <asm/arch/mmc.h> 37#include <asm/arch/mmc.h>
38#include <asm/arch/gpio.h>
39
40unsigned long imx_gpio_alloc_map[(GPIO_PORT_MAX + 1) * 32 / BITS_PER_LONG];
37 41
38void imx_gpio_mode(int gpio_mode) 42void imx_gpio_mode(int gpio_mode)
39{ 43{
@@ -95,6 +99,120 @@ void imx_gpio_mode(int gpio_mode)
95 99
96EXPORT_SYMBOL(imx_gpio_mode); 100EXPORT_SYMBOL(imx_gpio_mode);
97 101
102int imx_gpio_request(unsigned gpio, const char *label)
103{
104 if(gpio >= (GPIO_PORT_MAX + 1) * 32)
105 printk(KERN_ERR "imx_gpio: Attempt to request nonexistent GPIO %d for \"%s\"\n",
106 gpio, label ? label : "?");
107 return -EINVAL;
108
109 if(test_and_set_bit(gpio, imx_gpio_alloc_map)) {
110 printk(KERN_ERR "imx_gpio: GPIO %d already used. Allocation for \"%s\" failed\n",
111 gpio, label ? label : "?");
112 return -EBUSY;
113 }
114
115 return 0;
116}
117
118EXPORT_SYMBOL(imx_gpio_request);
119
120void imx_gpio_free(unsigned gpio)
121{
122 if(gpio >= (GPIO_PORT_MAX + 1) * 32)
123 return;
124
125 clear_bit(gpio, imx_gpio_alloc_map);
126}
127
128EXPORT_SYMBOL(imx_gpio_free);
129
130int imx_gpio_direction_input(unsigned gpio)
131{
132 imx_gpio_mode(gpio| GPIO_IN);
133 return 0;
134}
135
136EXPORT_SYMBOL(imx_gpio_direction_input);
137
138int imx_gpio_direction_output(unsigned gpio, int value)
139{
140 imx_gpio_set_value(gpio, value);
141 imx_gpio_mode(gpio| GPIO_OUT);
142 return 0;
143}
144
145EXPORT_SYMBOL(imx_gpio_direction_output);
146
147int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
148 int alloc_mode, const char *label)
149{
150 const int *p = pin_list;
151 int i;
152 unsigned gpio;
153 unsigned mode;
154
155 for (i = 0; i < count; i++) {
156 gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
157 mode = *p & ~(GPIO_PIN_MASK | GPIO_PORT_MASK);
158
159 if (gpio >= (GPIO_PORT_MAX + 1) * 32)
160 goto setup_error;
161
162 if (alloc_mode & IMX_GPIO_ALLOC_MODE_RELEASE)
163 imx_gpio_free(gpio);
164 else if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_NO_ALLOC))
165 if (imx_gpio_request(gpio, label))
166 if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
167 goto setup_error;
168
169 if (!(alloc_mode & (IMX_GPIO_ALLOC_MODE_ALLOC_ONLY |
170 IMX_GPIO_ALLOC_MODE_RELEASE)))
171 imx_gpio_mode(gpio | mode);
172
173 p++;
174 }
175 return 0;
176
177setup_error:
178 if(alloc_mode & (IMX_GPIO_ALLOC_MODE_NO_ALLOC |
179 IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
180 return -EINVAL;
181
182 while (p != pin_list) {
183 p--;
184 gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
185 imx_gpio_free(gpio);
186 }
187
188 return -EINVAL;
189}
190
191EXPORT_SYMBOL(imx_gpio_setup_multiple_pins);
192
193void __imx_gpio_set_value(unsigned gpio, int value)
194{
195 imx_gpio_set_value_inline(gpio, value);
196}
197
198EXPORT_SYMBOL(__imx_gpio_set_value);
199
200int imx_gpio_to_irq(unsigned gpio)
201{
202 return IRQ_GPIOA(0) + gpio;
203}
204
205EXPORT_SYMBOL(imx_gpio_to_irq);
206
207int imx_irq_to_gpio(unsigned irq)
208{
209 if (irq < IRQ_GPIOA(0))
210 return -EINVAL;
211 return irq - IRQ_GPIOA(0);
212}
213
214EXPORT_SYMBOL(imx_irq_to_gpio);
215
98/* 216/*
99 * get the system pll clock in Hz 217 * get the system pll clock in Hz
100 * 218 *
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 6960a9d04217..010f6fa984a6 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (C) 2000-2001 Deep Blue Solutions 4 * Copyright (C) 2000-2001 Deep Blue Solutions
5 * Copyright (C) 2002 Shane Nay (shane@minirl.com) 5 * Copyright (C) 2002 Shane Nay (shane@minirl.com)
6 * Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -15,6 +16,7 @@
15#include <linux/irq.h> 16#include <linux/irq.h>
16#include <linux/time.h> 17#include <linux/time.h>
17#include <linux/clocksource.h> 18#include <linux/clocksource.h>
19#include <linux/clockchips.h>
18 20
19#include <asm/hardware.h> 21#include <asm/hardware.h>
20#include <asm/io.h> 22#include <asm/io.h>
@@ -25,7 +27,8 @@
25/* Use timer 1 as system timer */ 27/* Use timer 1 as system timer */
26#define TIMER_BASE IMX_TIM1_BASE 28#define TIMER_BASE IMX_TIM1_BASE
27 29
28static unsigned long evt_diff; 30static struct clock_event_device clockevent_imx;
31static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
29 32
30/* 33/*
31 * IRQ handler for the timer 34 * IRQ handler for the timer
@@ -33,25 +36,20 @@ static unsigned long evt_diff;
33static irqreturn_t 36static irqreturn_t
34imx_timer_interrupt(int irq, void *dev_id) 37imx_timer_interrupt(int irq, void *dev_id)
35{ 38{
39 struct clock_event_device *evt = &clockevent_imx;
36 uint32_t tstat; 40 uint32_t tstat;
41 irqreturn_t ret = IRQ_NONE;
37 42
38 /* clear the interrupt */ 43 /* clear the interrupt */
39 tstat = IMX_TSTAT(TIMER_BASE); 44 tstat = IMX_TSTAT(TIMER_BASE);
40 IMX_TSTAT(TIMER_BASE) = 0; 45 IMX_TSTAT(TIMER_BASE) = 0;
41 46
42 if (tstat & TSTAT_COMP) { 47 if (tstat & TSTAT_COMP) {
43 do { 48 evt->event_handler(evt);
44 49 ret = IRQ_HANDLED;
45 write_seqlock(&xtime_lock);
46 timer_tick();
47 write_sequnlock(&xtime_lock);
48 IMX_TCMP(TIMER_BASE) += evt_diff;
49
50 } while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE)
51 - IMX_TCN(TIMER_BASE)) < 0));
52 } 50 }
53 51
54 return IRQ_HANDLED; 52 return ret;
55} 53}
56 54
57static struct irqaction imx_timer_irq = { 55static struct irqaction imx_timer_irq = {
@@ -70,10 +68,8 @@ static void __init imx_timer_hardware_init(void)
70 */ 68 */
71 IMX_TCTL(TIMER_BASE) = 0; 69 IMX_TCTL(TIMER_BASE) = 0;
72 IMX_TPRER(TIMER_BASE) = 0; 70 IMX_TPRER(TIMER_BASE) = 0;
73 IMX_TCMP(TIMER_BASE) = LATCH - 1;
74 71
75 IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_IRQEN | TCTL_TEN; 72 IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_TEN;
76 evt_diff = LATCH;
77} 73}
78 74
79cycle_t imx_get_cycles(void) 75cycle_t imx_get_cycles(void)
@@ -99,11 +95,108 @@ static int __init imx_clocksource_init(void)
99 return 0; 95 return 0;
100} 96}
101 97
98static int imx_set_next_event(unsigned long evt,
99 struct clock_event_device *unused)
100{
101 unsigned long tcmp;
102
103 tcmp = IMX_TCN(TIMER_BASE) + evt;
104 IMX_TCMP(TIMER_BASE) = tcmp;
105
106 return (int32_t)(tcmp - IMX_TCN(TIMER_BASE)) < 0 ? -ETIME : 0;
107}
108
109#ifdef DEBUG
110static const char *clock_event_mode_label[]={
111 [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
112 [CLOCK_EVT_MODE_ONESHOT] = "CLOCK_EVT_MODE_ONESHOT",
113 [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
114 [CLOCK_EVT_MODE_UNUSED] = "CLOCK_EVT_MODE_UNUSED"
115};
116#endif /*DEBUG*/
117
118static void imx_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
119{
120 unsigned long flags;
121
122 /*
123 * The timer interrupt generation is disabled at least
124 * for enough time to call imx_set_next_event()
125 */
126 local_irq_save(flags);
127 /* Disable interrupt in GPT module */
128 IMX_TCTL(TIMER_BASE) &= ~TCTL_IRQEN;
129 if (mode != clockevent_mode) {
130 /* Set event time into far-far future */
131 IMX_TCMP(TIMER_BASE) = IMX_TCN(TIMER_BASE) - 3;
132 /* Clear pending interrupt */
133 IMX_TSTAT(TIMER_BASE) &= ~TSTAT_COMP;
134 }
135
136#ifdef DEBUG
137 printk(KERN_INFO "imx_set_mode: changing mode from %s to %s\n",
138 clock_event_mode_label[clockevent_mode], clock_event_mode_label[mode]);
139#endif /*DEBUG*/
140
141 /* Remember timer mode */
142 clockevent_mode = mode;
143 local_irq_restore(flags);
144
145 switch (mode) {
146 case CLOCK_EVT_MODE_PERIODIC:
147 printk(KERN_ERR "imx_set_mode: Periodic mode is not supported for i.MX\n");
148 break;
149 case CLOCK_EVT_MODE_ONESHOT:
150 /*
151 * Do not put overhead of interrupt enable/disable into
152 * imx_set_next_event(), the core has about 4 minutes
153 * to call imx_set_next_event() or shutdown clock after
154 * mode switching
155 */
156 local_irq_save(flags);
157 IMX_TCTL(TIMER_BASE) |= TCTL_IRQEN;
158 local_irq_restore(flags);
159 break;
160 case CLOCK_EVT_MODE_SHUTDOWN:
161 case CLOCK_EVT_MODE_UNUSED:
162 /* Left event sources disabled, no more interrupts appears */
163 break;
164 }
165}
166
167static struct clock_event_device clockevent_imx = {
168 .name = "imx_timer1",
169 .features = CLOCK_EVT_FEAT_ONESHOT,
170 .shift = 32,
171 .set_mode = imx_set_mode,
172 .set_next_event = imx_set_next_event,
173 .rating = 200,
174};
175
176static int __init imx_clockevent_init(void)
177{
178 clockevent_imx.mult = div_sc(imx_get_perclk1(), NSEC_PER_SEC,
179 clockevent_imx.shift);
180 clockevent_imx.max_delta_ns =
181 clockevent_delta2ns(0xfffffffe, &clockevent_imx);
182 clockevent_imx.min_delta_ns =
183 clockevent_delta2ns(0xf, &clockevent_imx);
184
185 clockevent_imx.cpumask = cpumask_of_cpu(0);
186
187 clockevents_register_device(&clockevent_imx);
188
189 return 0;
190}
191
192
102static void __init imx_timer_init(void) 193static void __init imx_timer_init(void)
103{ 194{
104 imx_timer_hardware_init(); 195 imx_timer_hardware_init();
105 imx_clocksource_init(); 196 imx_clocksource_init();
106 197
198 imx_clockevent_init();
199
107 /* 200 /*
108 * Make irqs happen for the system timer 201 * Make irqs happen for the system timer
109 */ 202 */
diff --git a/arch/arm/mach-iop13xx/tpmi.c b/arch/arm/mach-iop13xx/tpmi.c
index d3dc278213da..2476347ea62f 100644
--- a/arch/arm/mach-iop13xx/tpmi.c
+++ b/arch/arm/mach-iop13xx/tpmi.c
@@ -29,13 +29,15 @@
29#define IOP13XX_TPMI_MMR(dev) IOP13XX_REG_ADDR32_PHYS(0x48000 + (dev << 12)) 29#define IOP13XX_TPMI_MMR(dev) IOP13XX_REG_ADDR32_PHYS(0x48000 + (dev << 12))
30#define IOP13XX_TPMI_MEM(dev) IOP13XX_REG_ADDR32_PHYS(0x60000 + (dev << 13)) 30#define IOP13XX_TPMI_MEM(dev) IOP13XX_REG_ADDR32_PHYS(0x60000 + (dev << 13))
31#define IOP13XX_TPMI_CTRL(dev) IOP13XX_REG_ADDR32_PHYS(0x50000 + (dev << 10)) 31#define IOP13XX_TPMI_CTRL(dev) IOP13XX_REG_ADDR32_PHYS(0x50000 + (dev << 10))
32#define IOP13XX_TPMI_IOP_CTRL(dev) (IOP13XX_TPMI_CTRL(dev) + 0x2000)
32#define IOP13XX_TPMI_MMR_SIZE (SZ_4K - 1) 33#define IOP13XX_TPMI_MMR_SIZE (SZ_4K - 1)
33#define IOP13XX_TPMI_MEM_SIZE (255) 34#define IOP13XX_TPMI_MEM_SIZE (255)
34#define IOP13XX_TPMI_MEM_CTRL (SZ_1K - 1) 35#define IOP13XX_TPMI_MEM_CTRL (SZ_1K - 1)
35#define IOP13XX_TPMI_RESOURCE_MMR 0 36#define IOP13XX_TPMI_RESOURCE_MMR 0
36#define IOP13XX_TPMI_RESOURCE_MEM 1 37#define IOP13XX_TPMI_RESOURCE_MEM 1
37#define IOP13XX_TPMI_RESOURCE_CTRL 2 38#define IOP13XX_TPMI_RESOURCE_CTRL 2
38#define IOP13XX_TPMI_RESOURCE_IRQ 3 39#define IOP13XX_TPMI_RESOURCE_IOP_CTRL 3
40#define IOP13XX_TPMI_RESOURCE_IRQ 4
39 41
40static struct resource iop13xx_tpmi_0_resources[] = { 42static struct resource iop13xx_tpmi_0_resources[] = {
41 [IOP13XX_TPMI_RESOURCE_MMR] = { 43 [IOP13XX_TPMI_RESOURCE_MMR] = {
@@ -53,6 +55,11 @@ static struct resource iop13xx_tpmi_0_resources[] = {
53 .end = IOP13XX_TPMI_CTRL(0) + IOP13XX_TPMI_MEM_CTRL, 55 .end = IOP13XX_TPMI_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
54 .flags = IORESOURCE_MEM, 56 .flags = IORESOURCE_MEM,
55 }, 57 },
58 [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
59 .start = IOP13XX_TPMI_IOP_CTRL(0),
60 .end = IOP13XX_TPMI_IOP_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
61 .flags = IORESOURCE_MEM,
62 },
56 [IOP13XX_TPMI_RESOURCE_IRQ] = { 63 [IOP13XX_TPMI_RESOURCE_IRQ] = {
57 .start = IRQ_IOP13XX_TPMI0_OUT, 64 .start = IRQ_IOP13XX_TPMI0_OUT,
58 .end = IRQ_IOP13XX_TPMI0_OUT, 65 .end = IRQ_IOP13XX_TPMI0_OUT,
@@ -76,6 +83,11 @@ static struct resource iop13xx_tpmi_1_resources[] = {
76 .end = IOP13XX_TPMI_CTRL(1) + IOP13XX_TPMI_MEM_CTRL, 83 .end = IOP13XX_TPMI_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
77 .flags = IORESOURCE_MEM, 84 .flags = IORESOURCE_MEM,
78 }, 85 },
86 [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
87 .start = IOP13XX_TPMI_IOP_CTRL(1),
88 .end = IOP13XX_TPMI_IOP_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
89 .flags = IORESOURCE_MEM,
90 },
79 [IOP13XX_TPMI_RESOURCE_IRQ] = { 91 [IOP13XX_TPMI_RESOURCE_IRQ] = {
80 .start = IRQ_IOP13XX_TPMI1_OUT, 92 .start = IRQ_IOP13XX_TPMI1_OUT,
81 .end = IRQ_IOP13XX_TPMI1_OUT, 93 .end = IRQ_IOP13XX_TPMI1_OUT,
@@ -99,6 +111,11 @@ static struct resource iop13xx_tpmi_2_resources[] = {
99 .end = IOP13XX_TPMI_CTRL(2) + IOP13XX_TPMI_MEM_CTRL, 111 .end = IOP13XX_TPMI_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
100 .flags = IORESOURCE_MEM, 112 .flags = IORESOURCE_MEM,
101 }, 113 },
114 [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
115 .start = IOP13XX_TPMI_IOP_CTRL(2),
116 .end = IOP13XX_TPMI_IOP_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
117 .flags = IORESOURCE_MEM,
118 },
102 [IOP13XX_TPMI_RESOURCE_IRQ] = { 119 [IOP13XX_TPMI_RESOURCE_IRQ] = {
103 .start = IRQ_IOP13XX_TPMI2_OUT, 120 .start = IRQ_IOP13XX_TPMI2_OUT,
104 .end = IRQ_IOP13XX_TPMI2_OUT, 121 .end = IRQ_IOP13XX_TPMI2_OUT,
@@ -122,6 +139,11 @@ static struct resource iop13xx_tpmi_3_resources[] = {
122 .end = IOP13XX_TPMI_CTRL(3) + IOP13XX_TPMI_MEM_CTRL, 139 .end = IOP13XX_TPMI_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
123 .flags = IORESOURCE_MEM, 140 .flags = IORESOURCE_MEM,
124 }, 141 },
142 [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
143 .start = IOP13XX_TPMI_IOP_CTRL(3),
144 .end = IOP13XX_TPMI_IOP_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
145 .flags = IORESOURCE_MEM,
146 },
125 [IOP13XX_TPMI_RESOURCE_IRQ] = { 147 [IOP13XX_TPMI_RESOURCE_IRQ] = {
126 .start = IRQ_IOP13XX_TPMI3_OUT, 148 .start = IRQ_IOP13XX_TPMI3_OUT,
127 .end = IRQ_IOP13XX_TPMI3_OUT, 149 .end = IRQ_IOP13XX_TPMI3_OUT,
@@ -133,7 +155,7 @@ u64 iop13xx_tpmi_mask = DMA_64BIT_MASK;
133static struct platform_device iop13xx_tpmi_0_device = { 155static struct platform_device iop13xx_tpmi_0_device = {
134 .name = "iop-tpmi", 156 .name = "iop-tpmi",
135 .id = 0, 157 .id = 0,
136 .num_resources = 4, 158 .num_resources = ARRAY_SIZE(iop13xx_tpmi_0_resources),
137 .resource = iop13xx_tpmi_0_resources, 159 .resource = iop13xx_tpmi_0_resources,
138 .dev = { 160 .dev = {
139 .dma_mask = &iop13xx_tpmi_mask, 161 .dma_mask = &iop13xx_tpmi_mask,
@@ -144,7 +166,7 @@ static struct platform_device iop13xx_tpmi_0_device = {
144static struct platform_device iop13xx_tpmi_1_device = { 166static struct platform_device iop13xx_tpmi_1_device = {
145 .name = "iop-tpmi", 167 .name = "iop-tpmi",
146 .id = 1, 168 .id = 1,
147 .num_resources = 4, 169 .num_resources = ARRAY_SIZE(iop13xx_tpmi_1_resources),
148 .resource = iop13xx_tpmi_1_resources, 170 .resource = iop13xx_tpmi_1_resources,
149 .dev = { 171 .dev = {
150 .dma_mask = &iop13xx_tpmi_mask, 172 .dma_mask = &iop13xx_tpmi_mask,
@@ -155,7 +177,7 @@ static struct platform_device iop13xx_tpmi_1_device = {
155static struct platform_device iop13xx_tpmi_2_device = { 177static struct platform_device iop13xx_tpmi_2_device = {
156 .name = "iop-tpmi", 178 .name = "iop-tpmi",
157 .id = 2, 179 .id = 2,
158 .num_resources = 4, 180 .num_resources = ARRAY_SIZE(iop13xx_tpmi_2_resources),
159 .resource = iop13xx_tpmi_2_resources, 181 .resource = iop13xx_tpmi_2_resources,
160 .dev = { 182 .dev = {
161 .dma_mask = &iop13xx_tpmi_mask, 183 .dma_mask = &iop13xx_tpmi_mask,
@@ -166,7 +188,7 @@ static struct platform_device iop13xx_tpmi_2_device = {
166static struct platform_device iop13xx_tpmi_3_device = { 188static struct platform_device iop13xx_tpmi_3_device = {
167 .name = "iop-tpmi", 189 .name = "iop-tpmi",
168 .id = 3, 190 .id = 3,
169 .num_resources = 4, 191 .num_resources = ARRAY_SIZE(iop13xx_tpmi_3_resources),
170 .resource = iop13xx_tpmi_3_resources, 192 .resource = iop13xx_tpmi_3_resources,
171 .dev = { 193 .dev = {
172 .dma_mask = &iop13xx_tpmi_mask, 194 .dma_mask = &iop13xx_tpmi_mask,
diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
index 56b7d337333a..2a07a281fa8a 100644
--- a/arch/arm/mach-ks8695/Makefile
+++ b/arch/arm/mach-ks8695/Makefile
@@ -3,7 +3,7 @@
3# Makefile for KS8695 architecture support 3# Makefile for KS8695 architecture support
4# 4#
5 5
6obj-y := cpu.o irq.o time.o devices.o 6obj-y := cpu.o irq.o time.o gpio.o devices.o
7obj-m := 7obj-m :=
8obj-n := 8obj-n :=
9obj- := 9obj- :=
diff --git a/arch/arm/mach-ks8695/gpio.c b/arch/arm/mach-ks8695/gpio.c
new file mode 100644
index 000000000000..b1aa3cb3d4a3
--- /dev/null
+++ b/arch/arm/mach-ks8695/gpio.c
@@ -0,0 +1,218 @@
1/*
2 * arch/arm/mach-ks8695/gpio.c
3 *
4 * Copyright (C) 2006 Andrew Victor
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 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/kernel.h>
21#include <linux/mm.h>
22#include <linux/init.h>
23#include <linux/module.h>
24
25#include <asm/io.h>
26#include <asm/hardware.h>
27#include <asm/mach/irq.h>
28
29#include <asm/arch/regs-gpio.h>
30#include <asm/arch/gpio.h>
31
32/*
33 * Configure a GPIO line for either GPIO function, or its internal
34 * function (Interrupt, Timer, etc).
35 */
36static void __init_or_module ks8695_gpio_mode(unsigned int pin, short gpio)
37{
38 unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
39 unsigned long x, flags;
40
41 if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */
42 return;
43
44 local_irq_save(flags);
45
46 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
47 if (gpio) /* GPIO: set bit to 0 */
48 x &= ~enable[pin];
49 else /* Internal function: set bit to 1 */
50 x |= enable[pin];
51 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
52
53 local_irq_restore(flags);
54}
55
56
57static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
58
59/*
60 * Configure GPIO pin as external interrupt source.
61 */
62int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
63{
64 unsigned long x, flags;
65
66 if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */
67 return -EINVAL;
68
69 local_irq_save(flags);
70
71 /* set pin as input */
72 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
73 x &= ~IOPM_(pin);
74 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
75
76 local_irq_restore(flags);
77
78 /* Set IRQ triggering type */
79 set_irq_type(gpio_irq[pin], type);
80
81 /* enable interrupt mode */
82 ks8695_gpio_mode(pin, 0);
83
84 return 0;
85}
86EXPORT_SYMBOL(ks8695_gpio_interrupt);
87
88
89
90/* .... Generic GPIO interface .............................................. */
91
92/*
93 * Configure the GPIO line as an input.
94 */
95int __init_or_module gpio_direction_input(unsigned int pin)
96{
97 unsigned long x, flags;
98
99 if (pin > KS8695_GPIO_15)
100 return -EINVAL;
101
102 /* set pin to GPIO mode */
103 ks8695_gpio_mode(pin, 1);
104
105 local_irq_save(flags);
106
107 /* set pin as input */
108 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
109 x &= ~IOPM_(pin);
110 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
111
112 local_irq_restore(flags);
113
114 return 0;
115}
116EXPORT_SYMBOL(gpio_direction_input);
117
118
119/*
120 * Configure the GPIO line as an output, with default state.
121 */
122int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state)
123{
124 unsigned long x, flags;
125
126 if (pin > KS8695_GPIO_15)
127 return -EINVAL;
128
129 /* set pin to GPIO mode */
130 ks8695_gpio_mode(pin, 1);
131
132 local_irq_save(flags);
133
134 /* set line state */
135 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
136 if (state)
137 x |= (1 << pin);
138 else
139 x &= ~(1 << pin);
140 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
141
142 /* set pin as output */
143 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
144 x |= IOPM_(pin);
145 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
146
147 local_irq_restore(flags);
148
149 return 0;
150}
151EXPORT_SYMBOL(gpio_direction_output);
152
153
154/*
155 * Set the state of an output GPIO line.
156 */
157void gpio_set_value(unsigned int pin, unsigned int state)
158{
159 unsigned long x, flags;
160
161 if (pin > KS8695_GPIO_15)
162 return;
163
164 local_irq_save(flags);
165
166 /* set output line state */
167 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
168 if (state)
169 x |= (1 << pin);
170 else
171 x &= ~(1 << pin);
172 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
173
174 local_irq_restore(flags);
175}
176EXPORT_SYMBOL(gpio_set_value);
177
178
179/*
180 * Read the state of a GPIO line.
181 */
182int gpio_get_value(unsigned int pin)
183{
184 unsigned long x;
185
186 if (pin > KS8695_GPIO_15)
187 return -EINVAL;
188
189 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
190 return (x & (1 << pin)) != 0;
191}
192EXPORT_SYMBOL(gpio_get_value);
193
194
195/*
196 * Map GPIO line to IRQ number.
197 */
198int gpio_to_irq(unsigned int pin)
199{
200 if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */
201 return -EINVAL;
202
203 return gpio_irq[pin];
204}
205EXPORT_SYMBOL(gpio_to_irq);
206
207
208/*
209 * Map IRQ number to GPIO line.
210 */
211int irq_to_gpio(unsigned int irq)
212{
213 if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
214 return -EINVAL;
215
216 return (irq - KS8695_IRQ_EXTERN0);
217}
218EXPORT_SYMBOL(irq_to_gpio);
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index 8f7c90a0593b..34a31caa6f9d 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -12,7 +12,6 @@
12 12
13#include <asm/arch/pxa-regs.h> 13#include <asm/arch/pxa-regs.h>
14#include <asm/hardware.h> 14#include <asm/hardware.h>
15#include <asm/semaphore.h>
16 15
17struct clk { 16struct clk {
18 struct list_head node; 17 struct list_head node;
@@ -25,21 +24,21 @@ struct clk {
25}; 24};
26 25
27static LIST_HEAD(clocks); 26static LIST_HEAD(clocks);
28static DECLARE_MUTEX(clocks_sem); 27static DEFINE_MUTEX(clocks_mutex);
29static DEFINE_SPINLOCK(clocks_lock); 28static DEFINE_SPINLOCK(clocks_lock);
30 29
31struct clk *clk_get(struct device *dev, const char *id) 30struct clk *clk_get(struct device *dev, const char *id)
32{ 31{
33 struct clk *p, *clk = ERR_PTR(-ENOENT); 32 struct clk *p, *clk = ERR_PTR(-ENOENT);
34 33
35 down(&clocks_sem); 34 mutex_lock(&clocks_mutex);
36 list_for_each_entry(p, &clocks, node) { 35 list_for_each_entry(p, &clocks, node) {
37 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { 36 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
38 clk = p; 37 clk = p;
39 break; 38 break;
40 } 39 }
41 } 40 }
42 up(&clocks_sem); 41 mutex_unlock(&clocks_mutex);
43 42
44 return clk; 43 return clk;
45} 44}
@@ -101,18 +100,18 @@ static struct clk clk_gpio27 = {
101 100
102int clk_register(struct clk *clk) 101int clk_register(struct clk *clk)
103{ 102{
104 down(&clocks_sem); 103 mutex_lock(&clocks_mutex);
105 list_add(&clk->node, &clocks); 104 list_add(&clk->node, &clocks);
106 up(&clocks_sem); 105 mutex_unlock(&clocks_mutex);
107 return 0; 106 return 0;
108} 107}
109EXPORT_SYMBOL(clk_register); 108EXPORT_SYMBOL(clk_register);
110 109
111void clk_unregister(struct clk *clk) 110void clk_unregister(struct clk *clk)
112{ 111{
113 down(&clocks_sem); 112 mutex_lock(&clocks_mutex);
114 list_del(&clk->node); 113 list_del(&clk->node);
115 up(&clocks_sem); 114 mutex_unlock(&clocks_mutex);
116} 115}
117EXPORT_SYMBOL(clk_unregister); 116EXPORT_SYMBOL(clk_unregister);
118 117
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index a1a900d16665..aab27297b3c6 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -44,6 +44,7 @@
44#include <asm/hardware/scoop.h> 44#include <asm/hardware/scoop.h>
45 45
46#include "generic.h" 46#include "generic.h"
47#include "devices.h"
47#include "sharpsl.h" 48#include "sharpsl.h"
48 49
49 50
@@ -368,7 +369,7 @@ MACHINE_START(CORGI, "SHARP Corgi")
368 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 369 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
369 .fixup = fixup_corgi, 370 .fixup = fixup_corgi,
370 .map_io = pxa_map_io, 371 .map_io = pxa_map_io,
371 .init_irq = pxa_init_irq, 372 .init_irq = pxa25x_init_irq,
372 .init_machine = corgi_init, 373 .init_machine = corgi_init,
373 .timer = &pxa_timer, 374 .timer = &pxa_timer,
374MACHINE_END 375MACHINE_END
@@ -380,7 +381,7 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd")
380 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 381 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
381 .fixup = fixup_corgi, 382 .fixup = fixup_corgi,
382 .map_io = pxa_map_io, 383 .map_io = pxa_map_io,
383 .init_irq = pxa_init_irq, 384 .init_irq = pxa25x_init_irq,
384 .init_machine = corgi_init, 385 .init_machine = corgi_init,
385 .timer = &pxa_timer, 386 .timer = &pxa_timer,
386MACHINE_END 387MACHINE_END
@@ -392,7 +393,7 @@ MACHINE_START(HUSKY, "SHARP Husky")
392 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 393 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
393 .fixup = fixup_corgi, 394 .fixup = fixup_corgi,
394 .map_io = pxa_map_io, 395 .map_io = pxa_map_io,
395 .init_irq = pxa_init_irq, 396 .init_irq = pxa25x_init_irq,
396 .init_machine = corgi_init, 397 .init_machine = corgi_init,
397 .timer = &pxa_timer, 398 .timer = &pxa_timer,
398MACHINE_END 399MACHINE_END
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
new file mode 100644
index 000000000000..9a6faff8e5a7
--- /dev/null
+++ b/arch/arm/mach-pxa/devices.h
@@ -0,0 +1,11 @@
1extern struct platform_device pxamci_device;
2extern struct platform_device pxaudc_device;
3extern struct platform_device pxafb_device;
4extern struct platform_device ffuart_device;
5extern struct platform_device btuart_device;
6extern struct platform_device stuart_device;
7extern struct platform_device hwuart_device;
8extern struct platform_device pxai2c_device;
9extern struct platform_device pxai2s_device;
10extern struct platform_device pxaficp_device;
11extern struct platform_device pxartc_device;
diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
index 4440babe7b97..93c4f31f127f 100644
--- a/arch/arm/mach-pxa/dma.c
+++ b/arch/arm/mach-pxa/dma.c
@@ -25,12 +25,15 @@
25 25
26#include <asm/arch/pxa-regs.h> 26#include <asm/arch/pxa-regs.h>
27 27
28static struct dma_channel { 28struct dma_channel {
29 char *name; 29 char *name;
30 pxa_dma_prio prio;
30 void (*irq_handler)(int, void *); 31 void (*irq_handler)(int, void *);
31 void *data; 32 void *data;
32} dma_channels[PXA_DMA_CHANNELS]; 33};
33 34
35static struct dma_channel *dma_channels;
36static int num_dma_channels;
34 37
35int pxa_request_dma (char *name, pxa_dma_prio prio, 38int pxa_request_dma (char *name, pxa_dma_prio prio,
36 void (*irq_handler)(int, void *), 39 void (*irq_handler)(int, void *),
@@ -47,8 +50,9 @@ int pxa_request_dma (char *name, pxa_dma_prio prio,
47 50
48 do { 51 do {
49 /* try grabbing a DMA channel with the requested priority */ 52 /* try grabbing a DMA channel with the requested priority */
50 pxa_for_each_dma_prio (i, prio) { 53 for (i = 0; i < num_dma_channels; i++) {
51 if (!dma_channels[i].name) { 54 if ((dma_channels[i].prio == prio) &&
55 !dma_channels[i].name) {
52 found = 1; 56 found = 1;
53 break; 57 break;
54 } 58 }
@@ -91,7 +95,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
91{ 95{
92 int i, dint = DINT; 96 int i, dint = DINT;
93 97
94 for (i = 0; i < PXA_DMA_CHANNELS; i++) { 98 for (i = 0; i < num_dma_channels; i++) {
95 if (dint & (1 << i)) { 99 if (dint & (1 << i)) {
96 struct dma_channel *channel = &dma_channels[i]; 100 struct dma_channel *channel = &dma_channels[i];
97 if (channel->name && channel->irq_handler) { 101 if (channel->name && channel->irq_handler) {
@@ -109,18 +113,32 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
109 return IRQ_HANDLED; 113 return IRQ_HANDLED;
110} 114}
111 115
112static int __init pxa_dma_init (void) 116int __init pxa_init_dma(int num_ch)
113{ 117{
114 int ret; 118 int i, ret;
115 119
116 ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL); 120 dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL);
117 if (ret) 121 if (dma_channels == NULL)
122 return -ENOMEM;
123
124 ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL);
125 if (ret) {
118 printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n"); 126 printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n");
119 return ret; 127 kfree(dma_channels);
120} 128 return ret;
129 }
121 130
122arch_initcall(pxa_dma_init); 131 /* dma channel priorities on pxa2xx processors:
132 * ch 0 - 3, 16 - 19 <--> (0) DMA_PRIO_HIGH
133 * ch 4 - 7, 20 - 23 <--> (1) DMA_PRIO_MEDIUM
134 * ch 8 - 15, 24 - 31 <--> (2) DMA_PRIO_LOW
135 */
136 for (i = 0; i < num_ch; i++)
137 dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW);
138
139 num_dma_channels = num_ch;
140 return 0;
141}
123 142
124EXPORT_SYMBOL(pxa_request_dma); 143EXPORT_SYMBOL(pxa_request_dma);
125EXPORT_SYMBOL(pxa_free_dma); 144EXPORT_SYMBOL(pxa_free_dma);
126
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 64b08b744f9f..296539b6359c 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -43,6 +43,7 @@
43#include <asm/arch/irda.h> 43#include <asm/arch/irda.h>
44#include <asm/arch/i2c.h> 44#include <asm/arch/i2c.h>
45 45
46#include "devices.h"
46#include "generic.h" 47#include "generic.h"
47 48
48/* 49/*
@@ -242,7 +243,7 @@ static struct resource pxamci_resources[] = {
242 243
243static u64 pxamci_dmamask = 0xffffffffUL; 244static u64 pxamci_dmamask = 0xffffffffUL;
244 245
245static struct platform_device pxamci_device = { 246struct platform_device pxamci_device = {
246 .name = "pxa2xx-mci", 247 .name = "pxa2xx-mci",
247 .id = -1, 248 .id = -1,
248 .dev = { 249 .dev = {
@@ -281,7 +282,7 @@ static struct resource pxa2xx_udc_resources[] = {
281 282
282static u64 udc_dma_mask = ~(u32)0; 283static u64 udc_dma_mask = ~(u32)0;
283 284
284static struct platform_device udc_device = { 285struct platform_device pxaudc_device = {
285 .name = "pxa2xx-udc", 286 .name = "pxa2xx-udc",
286 .id = -1, 287 .id = -1,
287 .resource = pxa2xx_udc_resources, 288 .resource = pxa2xx_udc_resources,
@@ -307,7 +308,7 @@ static struct resource pxafb_resources[] = {
307 308
308static u64 fb_dma_mask = ~(u64)0; 309static u64 fb_dma_mask = ~(u64)0;
309 310
310static struct platform_device pxafb_device = { 311struct platform_device pxafb_device = {
311 .name = "pxa2xx-fb", 312 .name = "pxa2xx-fb",
312 .id = -1, 313 .id = -1,
313 .dev = { 314 .dev = {
@@ -328,24 +329,24 @@ void __init set_pxa_fb_parent(struct device *parent_dev)
328 pxafb_device.dev.parent = parent_dev; 329 pxafb_device.dev.parent = parent_dev;
329} 330}
330 331
331static struct platform_device ffuart_device = { 332struct platform_device ffuart_device = {
332 .name = "pxa2xx-uart", 333 .name = "pxa2xx-uart",
333 .id = 0, 334 .id = 0,
334}; 335};
335static struct platform_device btuart_device = { 336struct platform_device btuart_device = {
336 .name = "pxa2xx-uart", 337 .name = "pxa2xx-uart",
337 .id = 1, 338 .id = 1,
338}; 339};
339static struct platform_device stuart_device = { 340struct platform_device stuart_device = {
340 .name = "pxa2xx-uart", 341 .name = "pxa2xx-uart",
341 .id = 2, 342 .id = 2,
342}; 343};
343static struct platform_device hwuart_device = { 344struct platform_device hwuart_device = {
344 .name = "pxa2xx-uart", 345 .name = "pxa2xx-uart",
345 .id = 3, 346 .id = 3,
346}; 347};
347 348
348static struct resource i2c_resources[] = { 349static struct resource pxai2c_resources[] = {
349 { 350 {
350 .start = 0x40301680, 351 .start = 0x40301680,
351 .end = 0x403016a3, 352 .end = 0x403016a3,
@@ -357,40 +358,19 @@ static struct resource i2c_resources[] = {
357 }, 358 },
358}; 359};
359 360
360static struct platform_device i2c_device = { 361struct platform_device pxai2c_device = {
361 .name = "pxa2xx-i2c", 362 .name = "pxa2xx-i2c",
362 .id = 0, 363 .id = 0,
363 .resource = i2c_resources, 364 .resource = pxai2c_resources,
364 .num_resources = ARRAY_SIZE(i2c_resources), 365 .num_resources = ARRAY_SIZE(pxai2c_resources),
365}; 366};
366 367
367#ifdef CONFIG_PXA27x
368static struct resource i2c_power_resources[] = {
369 {
370 .start = 0x40f00180,
371 .end = 0x40f001a3,
372 .flags = IORESOURCE_MEM,
373 }, {
374 .start = IRQ_PWRI2C,
375 .end = IRQ_PWRI2C,
376 .flags = IORESOURCE_IRQ,
377 },
378};
379
380static struct platform_device i2c_power_device = {
381 .name = "pxa2xx-i2c",
382 .id = 1,
383 .resource = i2c_power_resources,
384 .num_resources = ARRAY_SIZE(i2c_resources),
385};
386#endif
387
388void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info) 368void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
389{ 369{
390 i2c_device.dev.platform_data = info; 370 pxai2c_device.dev.platform_data = info;
391} 371}
392 372
393static struct resource i2s_resources[] = { 373static struct resource pxai2s_resources[] = {
394 { 374 {
395 .start = 0x40400000, 375 .start = 0x40400000,
396 .end = 0x40400083, 376 .end = 0x40400083,
@@ -402,16 +382,16 @@ static struct resource i2s_resources[] = {
402 }, 382 },
403}; 383};
404 384
405static struct platform_device i2s_device = { 385struct platform_device pxai2s_device = {
406 .name = "pxa2xx-i2s", 386 .name = "pxa2xx-i2s",
407 .id = -1, 387 .id = -1,
408 .resource = i2s_resources, 388 .resource = pxai2s_resources,
409 .num_resources = ARRAY_SIZE(i2s_resources), 389 .num_resources = ARRAY_SIZE(pxai2s_resources),
410}; 390};
411 391
412static u64 pxaficp_dmamask = ~(u32)0; 392static u64 pxaficp_dmamask = ~(u32)0;
413 393
414static struct platform_device pxaficp_device = { 394struct platform_device pxaficp_device = {
415 .name = "pxa2xx-ir", 395 .name = "pxa2xx-ir",
416 .id = -1, 396 .id = -1,
417 .dev = { 397 .dev = {
@@ -425,42 +405,7 @@ void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
425 pxaficp_device.dev.platform_data = info; 405 pxaficp_device.dev.platform_data = info;
426} 406}
427 407
428static struct platform_device pxartc_device = { 408struct platform_device pxartc_device = {
429 .name = "sa1100-rtc", 409 .name = "sa1100-rtc",
430 .id = -1, 410 .id = -1,
431}; 411};
432
433static struct platform_device *devices[] __initdata = {
434 &pxamci_device,
435 &udc_device,
436 &pxafb_device,
437 &ffuart_device,
438 &btuart_device,
439 &stuart_device,
440 &pxaficp_device,
441 &i2c_device,
442#ifdef CONFIG_PXA27x
443 &i2c_power_device,
444#endif
445 &i2s_device,
446 &pxartc_device,
447};
448
449static int __init pxa_init(void)
450{
451 int cpuid, ret;
452
453 ret = platform_add_devices(devices, ARRAY_SIZE(devices));
454 if (ret)
455 return ret;
456
457 /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
458 cpuid = read_cpuid(CPUID_ID);
459 if (((cpuid >> 4) & 0xfff) == 0x2d0 ||
460 ((cpuid >> 4) & 0xfff) == 0x290)
461 ret = platform_device_register(&hwuart_device);
462
463 return ret;
464}
465
466subsys_initcall(pxa_init);
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index e54a8dd63c17..91ab2ad8b34b 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -12,8 +12,12 @@
12struct sys_timer; 12struct sys_timer;
13 13
14extern struct sys_timer pxa_timer; 14extern struct sys_timer pxa_timer;
15extern void __init pxa_init_irq_low(void);
16extern void __init pxa_init_irq_high(void);
17extern void __init pxa_init_irq_gpio(int gpio_nr);
18extern void __init pxa25x_init_irq(void);
19extern void __init pxa27x_init_irq(void);
15extern void __init pxa_map_io(void); 20extern void __init pxa_map_io(void);
16extern void __init pxa_init_irq(void);
17 21
18extern unsigned int get_clk_frequency_khz(int info); 22extern unsigned int get_clk_frequency_khz(int info);
19 23
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 64df44043a65..465108da2851 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -38,6 +38,7 @@
38#include <asm/arch/mmc.h> 38#include <asm/arch/mmc.h>
39 39
40#include "generic.h" 40#include "generic.h"
41#include "devices.h"
41 42
42/* TODO: 43/* TODO:
43 * - add pxa2xx_audio_ops_t device structure 44 * - add pxa2xx_audio_ops_t device structure
@@ -152,7 +153,7 @@ static void __init idp_init(void)
152static void __init idp_init_irq(void) 153static void __init idp_init_irq(void)
153{ 154{
154 155
155 pxa_init_irq(); 156 pxa25x_init_irq();
156 157
157 set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE); 158 set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
158} 159}
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 4619d5fe606c..4b867b0789d5 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -30,12 +30,12 @@
30 30
31static void pxa_mask_low_irq(unsigned int irq) 31static void pxa_mask_low_irq(unsigned int irq)
32{ 32{
33 ICMR &= ~(1 << (irq + PXA_IRQ_SKIP)); 33 ICMR &= ~(1 << irq);
34} 34}
35 35
36static void pxa_unmask_low_irq(unsigned int irq) 36static void pxa_unmask_low_irq(unsigned int irq)
37{ 37{
38 ICMR |= (1 << (irq + PXA_IRQ_SKIP)); 38 ICMR |= (1 << irq);
39} 39}
40 40
41static int pxa_set_wake(unsigned int irq, unsigned int on) 41static int pxa_set_wake(unsigned int irq, unsigned int on)
@@ -67,7 +67,27 @@ static struct irq_chip pxa_internal_chip_low = {
67 .set_wake = pxa_set_wake, 67 .set_wake = pxa_set_wake,
68}; 68};
69 69
70#if PXA_INTERNAL_IRQS > 32 70void __init pxa_init_irq_low(void)
71{
72 int irq;
73
74 /* disable all IRQs */
75 ICMR = 0;
76
77 /* all IRQs are IRQ, not FIQ */
78 ICLR = 0;
79
80 /* only unmasked interrupts kick us out of idle */
81 ICCR = 1;
82
83 for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) {
84 set_irq_chip(irq, &pxa_internal_chip_low);
85 set_irq_handler(irq, handle_level_irq);
86 set_irq_flags(irq, IRQF_VALID);
87 }
88}
89
90#ifdef CONFIG_PXA27x
71 91
72/* 92/*
73 * This is for the second set of internal IRQs as found on the PXA27x. 93 * This is for the second set of internal IRQs as found on the PXA27x.
@@ -75,12 +95,12 @@ static struct irq_chip pxa_internal_chip_low = {
75 95
76static void pxa_mask_high_irq(unsigned int irq) 96static void pxa_mask_high_irq(unsigned int irq)
77{ 97{
78 ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP)); 98 ICMR2 &= ~(1 << (irq - 32));
79} 99}
80 100
81static void pxa_unmask_high_irq(unsigned int irq) 101static void pxa_unmask_high_irq(unsigned int irq)
82{ 102{
83 ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP)); 103 ICMR2 |= (1 << (irq - 32));
84} 104}
85 105
86static struct irq_chip pxa_internal_chip_high = { 106static struct irq_chip pxa_internal_chip_high = {
@@ -90,6 +110,19 @@ static struct irq_chip pxa_internal_chip_high = {
90 .unmask = pxa_unmask_high_irq, 110 .unmask = pxa_unmask_high_irq,
91}; 111};
92 112
113void __init pxa_init_irq_high(void)
114{
115 int irq;
116
117 ICMR2 = 0;
118 ICLR2 = 0;
119
120 for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) {
121 set_irq_chip(irq, &pxa_internal_chip_high);
122 set_irq_handler(irq, handle_level_irq);
123 set_irq_flags(irq, IRQF_VALID);
124 }
125}
93#endif 126#endif
94 127
95/* Note that if an input/irq line ever gets changed to an output during 128/* Note that if an input/irq line ever gets changed to an output during
@@ -217,7 +250,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
217 do { 250 do {
218 loop = 0; 251 loop = 0;
219 252
220 mask = GEDR0 & ~3; 253 mask = GEDR0 & GPIO_IRQ_mask[0] & ~3;
221 if (mask) { 254 if (mask) {
222 GEDR0 = mask; 255 GEDR0 = mask;
223 irq = IRQ_GPIO(2); 256 irq = IRQ_GPIO(2);
@@ -233,7 +266,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
233 loop = 1; 266 loop = 1;
234 } 267 }
235 268
236 mask = GEDR1; 269 mask = GEDR1 & GPIO_IRQ_mask[1];
237 if (mask) { 270 if (mask) {
238 GEDR1 = mask; 271 GEDR1 = mask;
239 irq = IRQ_GPIO(32); 272 irq = IRQ_GPIO(32);
@@ -248,7 +281,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
248 loop = 1; 281 loop = 1;
249 } 282 }
250 283
251 mask = GEDR2; 284 mask = GEDR2 & GPIO_IRQ_mask[2];
252 if (mask) { 285 if (mask) {
253 GEDR2 = mask; 286 GEDR2 = mask;
254 irq = IRQ_GPIO(64); 287 irq = IRQ_GPIO(64);
@@ -263,8 +296,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
263 loop = 1; 296 loop = 1;
264 } 297 }
265 298
266#if PXA_LAST_GPIO >= 96 299 mask = GEDR3 & GPIO_IRQ_mask[3];
267 mask = GEDR3;
268 if (mask) { 300 if (mask) {
269 GEDR3 = mask; 301 GEDR3 = mask;
270 irq = IRQ_GPIO(96); 302 irq = IRQ_GPIO(96);
@@ -278,7 +310,6 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
278 } while (mask); 310 } while (mask);
279 loop = 1; 311 loop = 1;
280 } 312 }
281#endif
282 } while (loop); 313 } while (loop);
283} 314}
284 315
@@ -314,64 +345,27 @@ static struct irq_chip pxa_muxed_gpio_chip = {
314 .set_wake = pxa_set_gpio_wake, 345 .set_wake = pxa_set_gpio_wake,
315}; 346};
316 347
317 348void __init pxa_init_irq_gpio(int gpio_nr)
318void __init pxa_init_irq(void)
319{ 349{
320 int irq; 350 int irq, i;
321
322 /* disable all IRQs */
323 ICMR = 0;
324
325 /* all IRQs are IRQ, not FIQ */
326 ICLR = 0;
327 351
328 /* clear all GPIO edge detects */ 352 /* clear all GPIO edge detects */
329 GFER0 = 0; 353 for (i = 0; i < gpio_nr; i += 32) {
330 GFER1 = 0; 354 GFER(i) = 0;
331 GFER2 = 0; 355 GRER(i) = 0;
332 GRER0 = 0; 356 GEDR(i) = GEDR(i);
333 GRER1 = 0; 357 }
334 GRER2 = 0;
335 GEDR0 = GEDR0;
336 GEDR1 = GEDR1;
337 GEDR2 = GEDR2;
338
339#ifdef CONFIG_PXA27x
340 /* And similarly for the extra regs on the PXA27x */
341 ICMR2 = 0;
342 ICLR2 = 0;
343 GFER3 = 0;
344 GRER3 = 0;
345 GEDR3 = GEDR3;
346#endif
347
348 /* only unmasked interrupts kick us out of idle */
349 ICCR = 1;
350 358
351 /* GPIO 0 and 1 must have their mask bit always set */ 359 /* GPIO 0 and 1 must have their mask bit always set */
352 GPIO_IRQ_mask[0] = 3; 360 GPIO_IRQ_mask[0] = 3;
353 361
354 for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
355 set_irq_chip(irq, &pxa_internal_chip_low);
356 set_irq_handler(irq, handle_level_irq);
357 set_irq_flags(irq, IRQF_VALID);
358 }
359
360#if PXA_INTERNAL_IRQS > 32
361 for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) {
362 set_irq_chip(irq, &pxa_internal_chip_high);
363 set_irq_handler(irq, handle_level_irq);
364 set_irq_flags(irq, IRQF_VALID);
365 }
366#endif
367
368 for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { 362 for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
369 set_irq_chip(irq, &pxa_low_gpio_chip); 363 set_irq_chip(irq, &pxa_low_gpio_chip);
370 set_irq_handler(irq, handle_edge_irq); 364 set_irq_handler(irq, handle_edge_irq);
371 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 365 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
372 } 366 }
373 367
374 for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) { 368 for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(gpio_nr); irq++) {
375 set_irq_chip(irq, &pxa_muxed_gpio_chip); 369 set_irq_chip(irq, &pxa_muxed_gpio_chip);
376 set_irq_handler(irq, handle_edge_irq); 370 set_irq_handler(irq, handle_edge_irq);
377 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 371 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index e3097664ffe1..26116440a7c9 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -46,6 +46,7 @@
46#include <asm/arch/ohci.h> 46#include <asm/arch/ohci.h>
47 47
48#include "generic.h" 48#include "generic.h"
49#include "devices.h"
49 50
50 51
51static unsigned int lpd270_irq_enabled; 52static unsigned int lpd270_irq_enabled;
@@ -97,7 +98,7 @@ static void __init lpd270_init_irq(void)
97{ 98{
98 int irq; 99 int irq;
99 100
100 pxa_init_irq(); 101 pxa27x_init_irq();
101 102
102 __raw_writew(0, LPD270_INT_MASK); 103 __raw_writew(0, LPD270_INT_MASK);
103 __raw_writew(0, LPD270_INT_STATUS); 104 __raw_writew(0, LPD270_INT_STATUS);
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 6377b2e29ff0..e70048fd00a5 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -48,6 +48,7 @@
48#include <asm/arch/mmc.h> 48#include <asm/arch/mmc.h>
49 49
50#include "generic.h" 50#include "generic.h"
51#include "devices.h"
51 52
52 53
53#define LUB_MISC_WR __LUB_REG(LUBBOCK_FPGA_PHYS + 0x080) 54#define LUB_MISC_WR __LUB_REG(LUBBOCK_FPGA_PHYS + 0x080)
@@ -103,7 +104,7 @@ static void __init lubbock_init_irq(void)
103{ 104{
104 int irq; 105 int irq;
105 106
106 pxa_init_irq(); 107 pxa25x_init_irq();
107 108
108 /* setup extra lubbock irqs */ 109 /* setup extra lubbock irqs */
109 for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) { 110 for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index ed99a81b98f3..b02c79c7e6a3 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -46,6 +46,7 @@
46#include <asm/arch/ohci.h> 46#include <asm/arch/ohci.h>
47 47
48#include "generic.h" 48#include "generic.h"
49#include "devices.h"
49 50
50 51
51static unsigned long mainstone_irq_enabled; 52static unsigned long mainstone_irq_enabled;
@@ -89,7 +90,7 @@ static void __init mainstone_init_irq(void)
89{ 90{
90 int irq; 91 int irq;
91 92
92 pxa_init_irq(); 93 pxa27x_init_irq();
93 94
94 /* setup extra Mainstone irqs */ 95 /* setup extra Mainstone irqs */
95 for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) { 96 for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 6bf15ae73848..e66dbc26add1 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -77,7 +77,6 @@ int pxa_pm_enter(suspend_state_t state)
77{ 77{
78 unsigned long sleep_save[SLEEP_SAVE_SIZE]; 78 unsigned long sleep_save[SLEEP_SAVE_SIZE];
79 unsigned long checksum = 0; 79 unsigned long checksum = 0;
80 struct timespec delta, rtc;
81 int i; 80 int i;
82 extern void pxa_cpu_pm_enter(suspend_state_t state); 81 extern void pxa_cpu_pm_enter(suspend_state_t state);
83 82
@@ -87,11 +86,6 @@ int pxa_pm_enter(suspend_state_t state)
87 iwmmxt_task_disable(NULL); 86 iwmmxt_task_disable(NULL);
88#endif 87#endif
89 88
90 /* preserve current time */
91 rtc.tv_sec = RCNR;
92 rtc.tv_nsec = 0;
93 save_time_delta(&delta, &rtc);
94
95 SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); 89 SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
96 SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); 90 SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
97 SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); 91 SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
@@ -183,10 +177,6 @@ int pxa_pm_enter(suspend_state_t state)
183 177
184 RESTORE(PSTR); 178 RESTORE(PSTR);
185 179
186 /* restore current time */
187 rtc.tv_sec = RCNR;
188 restore_time_delta(&delta, &rtc);
189
190#ifdef DEBUG 180#ifdef DEBUG
191 printk(KERN_DEBUG "*** made it back from resume\n"); 181 printk(KERN_DEBUG "*** made it back from resume\n");
192#endif 182#endif
@@ -200,40 +190,3 @@ unsigned long sleep_phys_sp(void *sp)
200{ 190{
201 return virt_to_phys(sp); 191 return virt_to_phys(sp);
202} 192}
203
204/*
205 * Called after processes are frozen, but before we shut down devices.
206 */
207int pxa_pm_prepare(suspend_state_t state)
208{
209 extern int pxa_cpu_pm_prepare(suspend_state_t state);
210
211 return pxa_cpu_pm_prepare(state);
212}
213
214EXPORT_SYMBOL_GPL(pxa_pm_prepare);
215
216/*
217 * Called after devices are re-setup, but before processes are thawed.
218 */
219int pxa_pm_finish(suspend_state_t state)
220{
221 return 0;
222}
223
224EXPORT_SYMBOL_GPL(pxa_pm_finish);
225
226static struct pm_ops pxa_pm_ops = {
227 .prepare = pxa_pm_prepare,
228 .enter = pxa_pm_enter,
229 .finish = pxa_pm_finish,
230 .valid = pm_valid_only_mem,
231};
232
233static int __init pxa_pm_init(void)
234{
235 pm_set_ops(&pxa_pm_ops);
236 return 0;
237}
238
239device_initcall(pxa_pm_init);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 34fb80b37023..655668d4d0e9 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -45,6 +45,7 @@
45#include <asm/mach/sharpsl_param.h> 45#include <asm/mach/sharpsl_param.h>
46 46
47#include "generic.h" 47#include "generic.h"
48#include "devices.h"
48#include "sharpsl.h" 49#include "sharpsl.h"
49 50
50static struct resource poodle_scoop_resources[] = { 51static struct resource poodle_scoop_resources[] = {
@@ -412,7 +413,7 @@ MACHINE_START(POODLE, "SHARP Poodle")
412 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 413 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
413 .fixup = fixup_poodle, 414 .fixup = fixup_poodle,
414 .map_io = pxa_map_io, 415 .map_io = pxa_map_io,
415 .init_irq = pxa_init_irq, 416 .init_irq = pxa25x_init_irq,
416 .timer = &pxa_timer, 417 .timer = &pxa_timer,
417 .init_machine = poodle_init, 418 .init_machine = poodle_init,
418MACHINE_END 419MACHINE_END
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index c1f21739bf71..f36ca448338e 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -19,12 +19,17 @@
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/platform_device.h>
22#include <linux/pm.h> 23#include <linux/pm.h>
23 24
24#include <asm/hardware.h> 25#include <asm/hardware.h>
26#include <asm/arch/irqs.h>
25#include <asm/arch/pxa-regs.h> 27#include <asm/arch/pxa-regs.h>
28#include <asm/arch/pm.h>
29#include <asm/arch/dma.h>
26 30
27#include "generic.h" 31#include "generic.h"
32#include "devices.h"
28 33
29/* 34/*
30 * Various clock factors driven by the CCCR register. 35 * Various clock factors driven by the CCCR register.
@@ -105,18 +110,6 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
105 110
106#ifdef CONFIG_PM 111#ifdef CONFIG_PM
107 112
108int pxa_cpu_pm_prepare(suspend_state_t state)
109{
110 switch (state) {
111 case PM_SUSPEND_MEM:
112 break;
113 default:
114 return -EINVAL;
115 }
116
117 return 0;
118}
119
120void pxa_cpu_pm_enter(suspend_state_t state) 113void pxa_cpu_pm_enter(suspend_state_t state)
121{ 114{
122 extern void pxa_cpu_suspend(unsigned int); 115 extern void pxa_cpu_suspend(unsigned int);
@@ -133,4 +126,49 @@ void pxa_cpu_pm_enter(suspend_state_t state)
133 } 126 }
134} 127}
135 128
129static struct pm_ops pxa25x_pm_ops = {
130 .enter = pxa_pm_enter,
131 .valid = pm_valid_only_mem,
132};
133#endif
134
135void __init pxa25x_init_irq(void)
136{
137 pxa_init_irq_low();
138 pxa_init_irq_gpio(85);
139}
140
141static struct platform_device *pxa25x_devices[] __initdata = {
142 &pxamci_device,
143 &pxaudc_device,
144 &pxafb_device,
145 &ffuart_device,
146 &btuart_device,
147 &stuart_device,
148 &pxai2c_device,
149 &pxai2s_device,
150 &pxaficp_device,
151 &pxartc_device,
152};
153
154static int __init pxa25x_init(void)
155{
156 int ret = 0;
157
158 if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
159 if ((ret = pxa_init_dma(16)))
160 return ret;
161#ifdef CONFIG_PM
162 pm_set_ops(&pxa25x_pm_ops);
136#endif 163#endif
164 ret = platform_add_devices(pxa25x_devices,
165 ARRAY_SIZE(pxa25x_devices));
166 }
167 /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
168 if (cpu_is_pxa25x())
169 ret = platform_device_register(&hwuart_device);
170
171 return ret;
172}
173
174subsys_initcall(pxa25x_init);
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 1939acc3f9f7..aa5bb02c897b 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -19,10 +19,14 @@
19 19
20#include <asm/hardware.h> 20#include <asm/hardware.h>
21#include <asm/irq.h> 21#include <asm/irq.h>
22#include <asm/arch/irqs.h>
22#include <asm/arch/pxa-regs.h> 23#include <asm/arch/pxa-regs.h>
23#include <asm/arch/ohci.h> 24#include <asm/arch/ohci.h>
25#include <asm/arch/pm.h>
26#include <asm/arch/dma.h>
24 27
25#include "generic.h" 28#include "generic.h"
29#include "devices.h"
26 30
27/* Crystal clock: 13MHz */ 31/* Crystal clock: 13MHz */
28#define BASE_CLK 13000000 32#define BASE_CLK 13000000
@@ -122,17 +126,6 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
122 126
123#ifdef CONFIG_PM 127#ifdef CONFIG_PM
124 128
125int pxa_cpu_pm_prepare(suspend_state_t state)
126{
127 switch (state) {
128 case PM_SUSPEND_MEM:
129 case PM_SUSPEND_STANDBY:
130 return 0;
131 default:
132 return -EINVAL;
133 }
134}
135
136void pxa_cpu_pm_enter(suspend_state_t state) 129void pxa_cpu_pm_enter(suspend_state_t state)
137{ 130{
138 extern void pxa_cpu_standby(void); 131 extern void pxa_cpu_standby(void);
@@ -162,6 +155,15 @@ void pxa_cpu_pm_enter(suspend_state_t state)
162 } 155 }
163} 156}
164 157
158static int pxa27x_pm_valid(suspend_state_t state)
159{
160 return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
161}
162
163static struct pm_ops pxa27x_pm_ops = {
164 .enter = pxa_pm_enter,
165 .valid = pxa27x_pm_valid,
166};
165#endif 167#endif
166 168
167/* 169/*
@@ -183,7 +185,7 @@ static struct resource pxa27x_ohci_resources[] = {
183 }, 185 },
184}; 186};
185 187
186static struct platform_device ohci_device = { 188static struct platform_device pxaohci_device = {
187 .name = "pxa27x-ohci", 189 .name = "pxa27x-ohci",
188 .id = -1, 190 .id = -1,
189 .dev = { 191 .dev = {
@@ -196,16 +198,62 @@ static struct platform_device ohci_device = {
196 198
197void __init pxa_set_ohci_info(struct pxaohci_platform_data *info) 199void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
198{ 200{
199 ohci_device.dev.platform_data = info; 201 pxaohci_device.dev.platform_data = info;
200} 202}
201 203
204static struct resource i2c_power_resources[] = {
205 {
206 .start = 0x40f00180,
207 .end = 0x40f001a3,
208 .flags = IORESOURCE_MEM,
209 }, {
210 .start = IRQ_PWRI2C,
211 .end = IRQ_PWRI2C,
212 .flags = IORESOURCE_IRQ,
213 },
214};
215
216static struct platform_device pxai2c_power_device = {
217 .name = "pxa2xx-i2c",
218 .id = 1,
219 .resource = i2c_power_resources,
220 .num_resources = ARRAY_SIZE(i2c_power_resources),
221};
222
202static struct platform_device *devices[] __initdata = { 223static struct platform_device *devices[] __initdata = {
203 &ohci_device, 224 &pxamci_device,
225 &pxaudc_device,
226 &pxafb_device,
227 &ffuart_device,
228 &btuart_device,
229 &stuart_device,
230 &pxai2c_device,
231 &pxai2c_power_device,
232 &pxai2s_device,
233 &pxaficp_device,
234 &pxartc_device,
235 &pxaohci_device,
204}; 236};
205 237
238void __init pxa27x_init_irq(void)
239{
240 pxa_init_irq_low();
241 pxa_init_irq_high();
242 pxa_init_irq_gpio(128);
243}
244
206static int __init pxa27x_init(void) 245static int __init pxa27x_init(void)
207{ 246{
208 return platform_add_devices(devices, ARRAY_SIZE(devices)); 247 int ret = 0;
248 if (cpu_is_pxa27x()) {
249 if ((ret = pxa_init_dma(32)))
250 return ret;
251#ifdef CONFIG_PM
252 pm_set_ops(&pxa27x_pm_ops);
253#endif
254 ret = platform_add_devices(devices, ARRAY_SIZE(devices));
255 }
256 return ret;
209} 257}
210 258
211subsys_initcall(pxa27x_init); 259subsys_initcall(pxa27x_init);
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 3cbac63bed3c..bae47e145de8 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -48,6 +48,7 @@
48#include <asm/hardware/scoop.h> 48#include <asm/hardware/scoop.h>
49 49
50#include "generic.h" 50#include "generic.h"
51#include "devices.h"
51#include "sharpsl.h" 52#include "sharpsl.h"
52 53
53/* 54/*
@@ -560,7 +561,7 @@ MACHINE_START(SPITZ, "SHARP Spitz")
560 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 561 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
561 .fixup = fixup_spitz, 562 .fixup = fixup_spitz,
562 .map_io = pxa_map_io, 563 .map_io = pxa_map_io,
563 .init_irq = pxa_init_irq, 564 .init_irq = pxa27x_init_irq,
564 .init_machine = spitz_init, 565 .init_machine = spitz_init,
565 .timer = &pxa_timer, 566 .timer = &pxa_timer,
566MACHINE_END 567MACHINE_END
@@ -572,7 +573,7 @@ MACHINE_START(BORZOI, "SHARP Borzoi")
572 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 573 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
573 .fixup = fixup_spitz, 574 .fixup = fixup_spitz,
574 .map_io = pxa_map_io, 575 .map_io = pxa_map_io,
575 .init_irq = pxa_init_irq, 576 .init_irq = pxa27x_init_irq,
576 .init_machine = spitz_init, 577 .init_machine = spitz_init,
577 .timer = &pxa_timer, 578 .timer = &pxa_timer,
578MACHINE_END 579MACHINE_END
@@ -584,7 +585,7 @@ MACHINE_START(AKITA, "SHARP Akita")
584 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 585 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
585 .fixup = fixup_spitz, 586 .fixup = fixup_spitz,
586 .map_io = pxa_map_io, 587 .map_io = pxa_map_io,
587 .init_irq = pxa_init_irq, 588 .init_irq = pxa27x_init_irq,
588 .init_machine = akita_init, 589 .init_machine = akita_init,
589 .timer = &pxa_timer, 590 .timer = &pxa_timer,
590MACHINE_END 591MACHINE_END
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 5248abe334d2..6f91fd2d061a 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -30,11 +30,6 @@
30#include <asm/arch/pxa-regs.h> 30#include <asm/arch/pxa-regs.h>
31 31
32 32
33static inline unsigned long pxa_get_rtc_time(void)
34{
35 return RCNR;
36}
37
38static int pxa_set_rtc(void) 33static int pxa_set_rtc(void)
39{ 34{
40 unsigned long current_time = xtime.tv_sec; 35 unsigned long current_time = xtime.tv_sec;
@@ -122,10 +117,6 @@ static void __init pxa_timer_init(void)
122 117
123 set_rtc = pxa_set_rtc; 118 set_rtc = pxa_set_rtc;
124 119
125 tv.tv_nsec = 0;
126 tv.tv_sec = pxa_get_rtc_time();
127 do_settimeofday(&tv);
128
129 OIER = 0; /* disable any timer interrupts */ 120 OIER = 0; /* disable any timer interrupts */
130 OSSR = 0xf; /* clear status on all timers */ 121 OSSR = 0xf; /* clear status on all timers */
131 setup_irq(IRQ_OST0, &pxa_timer_irq); 122 setup_irq(IRQ_OST0, &pxa_timer_irq);
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 72738771fb57..240fd042083d 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -42,7 +42,7 @@
42#include <asm/mach/sharpsl_param.h> 42#include <asm/mach/sharpsl_param.h>
43 43
44#include "generic.h" 44#include "generic.h"
45 45#include "devices.h"
46 46
47/* 47/*
48 * SCOOP Device 48 * SCOOP Device
@@ -332,7 +332,7 @@ MACHINE_START(TOSA, "SHARP Tosa")
332 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 332 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
333 .fixup = fixup_tosa, 333 .fixup = fixup_tosa,
334 .map_io = pxa_map_io, 334 .map_io = pxa_map_io,
335 .init_irq = pxa_init_irq, 335 .init_irq = pxa25x_init_irq,
336 .init_machine = tosa_init, 336 .init_machine = tosa_init,
337 .timer = &pxa_timer, 337 .timer = &pxa_timer,
338MACHINE_END 338MACHINE_END
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 28c79bd0a3a0..e4ba43bdf85d 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -49,6 +49,7 @@
49#include <asm/arch/ohci.h> 49#include <asm/arch/ohci.h>
50 50
51#include "generic.h" 51#include "generic.h"
52#include "devices.h"
52 53
53/******************************************************************************************** 54/********************************************************************************************
54 * ONBOARD FLASH 55 * ONBOARD FLASH
@@ -503,7 +504,7 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
503 .boot_params = TRIZEPS4_SDRAM_BASE + 0x100, 504 .boot_params = TRIZEPS4_SDRAM_BASE + 0x100,
504 .init_machine = trizeps4_init, 505 .init_machine = trizeps4_init,
505 .map_io = trizeps4_map_io, 506 .map_io = trizeps4_map_io,
506 .init_irq = pxa_init_irq, 507 .init_irq = pxa27x_init_irq,
507 .timer = &pxa_timer, 508 .timer = &pxa_timer,
508MACHINE_END 509MACHINE_END
509 510
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index f01de807b72f..8b52ea95d4f6 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -20,6 +20,8 @@
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/dm9000.h> 21#include <linux/dm9000.h>
22 22
23#include <net/ax88796.h>
24
23#include <asm/mach/arch.h> 25#include <asm/mach/arch.h>
24#include <asm/mach/map.h> 26#include <asm/mach/map.h>
25#include <asm/mach/irq.h> 27#include <asm/mach/irq.h>
@@ -409,6 +411,61 @@ static struct s3c2410_platform_i2c bast_i2c_info = {
409 .max_freq = 130*1000, 411 .max_freq = 130*1000,
410}; 412};
411 413
414/* Asix AX88796 10/100 ethernet controller */
415
416static struct ax_plat_data bast_asix_platdata = {
417 .flags = AXFLG_MAC_FROMDEV,
418 .wordlength = 2,
419 .dcr_val = 0x48,
420 .rcr_val = 0x40,
421};
422
423static struct resource bast_asix_resource[] = {
424 [0] = {
425 .start = S3C2410_CS5 + BAST_PA_ASIXNET,
426 .end = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20) - 1,
427 .flags = IORESOURCE_MEM,
428 },
429 [1] = {
430 .start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20),
431 .end = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20),
432 .flags = IORESOURCE_MEM,
433 },
434 [2] = {
435 .start = IRQ_ASIX,
436 .end = IRQ_ASIX,
437 .flags = IORESOURCE_IRQ
438 }
439};
440
441static struct platform_device bast_device_asix = {
442 .name = "ax88796",
443 .id = 0,
444 .num_resources = ARRAY_SIZE(bast_asix_resource),
445 .resource = bast_asix_resource,
446 .dev = {
447 .platform_data = &bast_asix_platdata
448 }
449};
450
451/* Asix AX88796 10/100 ethernet controller parallel port */
452
453static struct resource bast_asixpp_resource[] = {
454 [0] = {
455 .start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20),
456 .end = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1b * 0x20) - 1,
457 .flags = IORESOURCE_MEM,
458 }
459};
460
461static struct platform_device bast_device_axpp = {
462 .name = "ax88796-pp",
463 .id = 0,
464 .num_resources = ARRAY_SIZE(bast_asixpp_resource),
465 .resource = bast_asixpp_resource,
466};
467
468/* LCD/VGA controller */
412 469
413static struct s3c2410fb_mach_info __initdata bast_lcd_info = { 470static struct s3c2410fb_mach_info __initdata bast_lcd_info = {
414 .width = 640, 471 .width = 640,
@@ -453,6 +510,8 @@ static struct platform_device *bast_devices[] __initdata = {
453 &s3c_device_nand, 510 &s3c_device_nand,
454 &bast_device_nor, 511 &bast_device_nor,
455 &bast_device_dm9k, 512 &bast_device_dm9k,
513 &bast_device_asix,
514 &bast_device_axpp,
456 &bast_sio, 515 &bast_sio,
457}; 516};
458 517
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index bff7ddd06a52..29c163d300d4 100644
--- a/arch/arm/mach-s3c2440/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -18,6 +18,9 @@
18#include <linux/serial_core.h> 18#include <linux/serial_core.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20 20
21#include <linux/sm501.h>
22#include <linux/sm501-regs.h>
23
21#include <asm/mach/arch.h> 24#include <asm/mach/arch.h>
22#include <asm/mach/map.h> 25#include <asm/mach/map.h>
23#include <asm/mach/irq.h> 26#include <asm/mach/irq.h>
@@ -42,6 +45,8 @@
42#include <linux/mtd/nand_ecc.h> 45#include <linux/mtd/nand_ecc.h>
43#include <linux/mtd/partitions.h> 46#include <linux/mtd/partitions.h>
44 47
48#include <net/ax88796.h>
49
45#include <asm/plat-s3c24xx/clock.h> 50#include <asm/plat-s3c24xx/clock.h>
46#include <asm/plat-s3c24xx/devs.h> 51#include <asm/plat-s3c24xx/devs.h>
47#include <asm/plat-s3c24xx/cpu.h> 52#include <asm/plat-s3c24xx/cpu.h>
@@ -153,6 +158,29 @@ static struct mtd_partition anubis_default_nand_part[] = {
153 } 158 }
154}; 159};
155 160
161static struct mtd_partition anubis_default_nand_part_large[] = {
162 [0] = {
163 .name = "Boot Agent",
164 .size = SZ_128K,
165 .offset = 0,
166 },
167 [1] = {
168 .name = "/boot",
169 .size = SZ_4M - SZ_128K,
170 .offset = SZ_128K,
171 },
172 [2] = {
173 .name = "user1",
174 .offset = SZ_4M,
175 .size = SZ_32M - SZ_4M,
176 },
177 [3] = {
178 .name = "user2",
179 .offset = SZ_32M,
180 .size = MTDPART_SIZ_FULL,
181 }
182};
183
156/* the Anubis has 3 selectable slots for nand-flash, the two 184/* the Anubis has 3 selectable slots for nand-flash, the two
157 * on-board chip areas, as well as the external slot. 185 * on-board chip areas, as well as the external slot.
158 * 186 *
@@ -260,6 +288,104 @@ static struct platform_device anubis_device_ide1 = {
260 .resource = anubis_ide1_resource, 288 .resource = anubis_ide1_resource,
261}; 289};
262 290
291/* Asix AX88796 10/100 ethernet controller */
292
293static struct ax_plat_data anubis_asix_platdata = {
294 .flags = AXFLG_MAC_FROMDEV,
295 .wordlength = 2,
296 .dcr_val = 0x48,
297 .rcr_val = 0x40,
298};
299
300static struct resource anubis_asix_resource[] = {
301 [0] = {
302 .start = S3C2410_CS5,
303 .end = S3C2410_CS5 + (0x20 * 0x20) -1,
304 .flags = IORESOURCE_MEM
305 },
306 [1] = {
307 .start = IRQ_ASIX,
308 .end = IRQ_ASIX,
309 .flags = IORESOURCE_IRQ
310 }
311};
312
313static struct platform_device anubis_device_asix = {
314 .name = "ax88796",
315 .id = 0,
316 .num_resources = ARRAY_SIZE(anubis_asix_resource),
317 .resource = anubis_asix_resource,
318 .dev = {
319 .platform_data = &anubis_asix_platdata,
320 }
321};
322
323/* SM501 */
324
325static struct resource anubis_sm501_resource[] = {
326 [0] = {
327 .start = S3C2410_CS2,
328 .end = S3C2410_CS2 + SZ_8M,
329 .flags = IORESOURCE_MEM,
330 },
331 [1] = {
332 .start = S3C2410_CS2 + SZ_64M - SZ_2M,
333 .end = S3C2410_CS2 + SZ_64M - 1,
334 .flags = IORESOURCE_MEM,
335 },
336 [2] = {
337 .start = IRQ_EINT0,
338 .end = IRQ_EINT0,
339 .flags = IORESOURCE_IRQ,
340 },
341};
342
343static struct sm501_initdata anubis_sm501_initdata = {
344 .gpio_high = {
345 .set = 0x3F000000, /* 24bit panel */
346 .mask = 0x0,
347 },
348 .misc_timing = {
349 .set = 0x010100, /* SDRAM timing */
350 .mask = 0x1F1F00,
351 },
352 .misc_control = {
353 .set = SM501_MISC_PNL_24BIT,
354 .mask = 0,
355 },
356
357 /* set the SDRAM and bus clocks */
358 .mclk = 72 * MHZ,
359 .m1xclk = 144 * MHZ,
360};
361
362static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = {
363 [0] = {
364 .pin_scl = 44,
365 .pin_sda = 45,
366 },
367 [1] = {
368 .pin_scl = 40,
369 .pin_sda = 41,
370 },
371};
372
373static struct sm501_platdata anubis_sm501_platdata = {
374 .init = &anubis_sm501_initdata,
375 .gpio_i2c = anubis_sm501_gpio_i2c,
376 .gpio_i2c_nr = ARRAY_SIZE(anubis_sm501_gpio_i2c),
377};
378
379static struct platform_device anubis_device_sm501 = {
380 .name = "sm501",
381 .id = 0,
382 .num_resources = ARRAY_SIZE(anubis_sm501_resource),
383 .resource = anubis_sm501_resource,
384 .dev = {
385 .platform_data = &anubis_sm501_platdata,
386 },
387};
388
263/* Standard Anubis devices */ 389/* Standard Anubis devices */
264 390
265static struct platform_device *anubis_devices[] __initdata = { 391static struct platform_device *anubis_devices[] __initdata = {
@@ -271,6 +397,8 @@ static struct platform_device *anubis_devices[] __initdata = {
271 &s3c_device_nand, 397 &s3c_device_nand,
272 &anubis_device_ide0, 398 &anubis_device_ide0,
273 &anubis_device_ide1, 399 &anubis_device_ide1,
400 &anubis_device_asix,
401 &anubis_device_sm501,
274}; 402};
275 403
276static struct clk *anubis_clocks[] = { 404static struct clk *anubis_clocks[] = {
@@ -304,8 +432,17 @@ static void __init anubis_map_io(void)
304 s3c24xx_init_clocks(0); 432 s3c24xx_init_clocks(0);
305 s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs)); 433 s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
306 434
307 /* ensure that the GPIO is setup */ 435 /* check for the newer revision boards with large page nand */
308 s3c2410_gpio_setpin(S3C2410_GPA0, 1); 436
437 if ((__raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK) >= 4) {
438 printk(KERN_INFO "ANUBIS-B detected (revision %d)\n",
439 __raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK);
440 anubis_nand_sets[0].partitions = anubis_default_nand_part_large;
441 anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large);
442 } else {
443 /* ensure that the GPIO is setup */
444 s3c2410_gpio_setpin(S3C2410_GPA0, 1);
445 }
309} 446}
310 447
311static void __init anubis_init(void) 448static void __init anubis_init(void)
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index 15811601f03d..89f4c9c5777b 100644
--- a/arch/arm/mach-s3c2440/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -166,6 +166,29 @@ static struct mtd_partition osiris_default_nand_part[] = {
166 } 166 }
167}; 167};
168 168
169static struct mtd_partition osiris_default_nand_part_large[] = {
170 [0] = {
171 .name = "Boot Agent",
172 .size = SZ_128K,
173 .offset = 0,
174 },
175 [1] = {
176 .name = "/boot",
177 .size = SZ_4M - SZ_128K,
178 .offset = SZ_128K,
179 },
180 [2] = {
181 .name = "user1",
182 .offset = SZ_4M,
183 .size = SZ_32M - SZ_4M,
184 },
185 [3] = {
186 .name = "user2",
187 .offset = SZ_32M,
188 .size = MTDPART_SIZ_FULL,
189 }
190};
191
169/* the Osiris has 3 selectable slots for nand-flash, the two 192/* the Osiris has 3 selectable slots for nand-flash, the two
170 * on-board chip areas, as well as the external slot. 193 * on-board chip areas, as well as the external slot.
171 * 194 *
@@ -322,14 +345,23 @@ static void __init osiris_map_io(void)
322 s3c24xx_init_clocks(0); 345 s3c24xx_init_clocks(0);
323 s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs)); 346 s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
324 347
348 /* check for the newer revision boards with large page nand */
349
350 if ((__raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK) >= 4) {
351 printk(KERN_INFO "OSIRIS-B detected (revision %d)\n",
352 __raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK);
353 osiris_nand_sets[0].partitions = osiris_default_nand_part_large;
354 osiris_nand_sets[0].nr_partitions = ARRAY_SIZE(osiris_default_nand_part_large);
355 } else {
356 /* write-protect line to the NAND */
357 s3c2410_gpio_setpin(S3C2410_GPA0, 1);
358 }
359
325 /* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */ 360 /* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
326 361
327 local_irq_save(flags); 362 local_irq_save(flags);
328 __raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON); 363 __raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON);
329 local_irq_restore(flags); 364 local_irq_restore(flags);
330
331 /* write-protect line to the NAND */
332 s3c2410_gpio_setpin(S3C2410_GPA0, 1);
333} 365}
334 366
335static void __init osiris_init(void) 367static void __init osiris_init(void)
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index d674cf343156..01a37d3c0727 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -57,12 +57,7 @@ enum { SLEEP_SAVE_SP = 0,
57static int sa11x0_pm_enter(suspend_state_t state) 57static int sa11x0_pm_enter(suspend_state_t state)
58{ 58{
59 unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE]; 59 unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
60 struct timespec delta, rtc;
61 60
62 /* preserve current time */
63 rtc.tv_sec = RCNR;
64 rtc.tv_nsec = 0;
65 save_time_delta(&delta, &rtc);
66 gpio = GPLR; 61 gpio = GPLR;
67 62
68 /* save vital registers */ 63 /* save vital registers */
@@ -119,10 +114,6 @@ static int sa11x0_pm_enter(suspend_state_t state)
119 */ 114 */
120 PSSR = PSSR_PH; 115 PSSR = PSSR_PH;
121 116
122 /* restore current time */
123 rtc.tv_sec = RCNR;
124 restore_time_delta(&delta, &rtc);
125
126 return 0; 117 return 0;
127} 118}
128 119
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 29cb0c1604ab..fdf7b016e7ad 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -21,25 +21,6 @@
21#define RTC_DEF_DIVIDER (32768 - 1) 21#define RTC_DEF_DIVIDER (32768 - 1)
22#define RTC_DEF_TRIM 0 22#define RTC_DEF_TRIM 0
23 23
24static unsigned long __init sa1100_get_rtc_time(void)
25{
26 /*
27 * According to the manual we should be able to let RTTR be zero
28 * and then a default divisor for a 32.768KHz clock is used.
29 * Apparently this doesn't work, at least for my SA1110 rev 5.
30 * If the clock divider is uninitialized then reset it to the
31 * default value to get the 1Hz clock.
32 */
33 if (RTTR == 0) {
34 RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
35 printk(KERN_WARNING "Warning: uninitialized Real Time Clock\n");
36 /* The current RTC value probably doesn't make sense either */
37 RCNR = 0;
38 return 0;
39 }
40 return RCNR;
41}
42
43static int sa1100_set_rtc(void) 24static int sa1100_set_rtc(void)
44{ 25{
45 unsigned long current_time = xtime.tv_sec; 26 unsigned long current_time = xtime.tv_sec;
@@ -117,15 +98,10 @@ static struct irqaction sa1100_timer_irq = {
117 98
118static void __init sa1100_timer_init(void) 99static void __init sa1100_timer_init(void)
119{ 100{
120 struct timespec tv;
121 unsigned long flags; 101 unsigned long flags;
122 102
123 set_rtc = sa1100_set_rtc; 103 set_rtc = sa1100_set_rtc;
124 104
125 tv.tv_nsec = 0;
126 tv.tv_sec = sa1100_get_rtc_time();
127 do_settimeofday(&tv);
128
129 OIER = 0; /* disable any timer interrupts */ 105 OIER = 0; /* disable any timer interrupts */
130 OSSR = 0xf; /* clear status on all timers */ 106 OSSR = 0xf; /* clear status on all timers */
131 setup_irq(IRQ_OST0, &sa1100_timer_irq); 107 setup_irq(IRQ_OST0, &sa1100_timer_irq);
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index f3ade18862aa..75952779ce19 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -280,7 +280,10 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
280 if (!type) 280 if (!type)
281 return NULL; 281 return NULL;
282 282
283 size = PAGE_ALIGN(size); 283 /*
284 * Page align the mapping size, taking account of any offset.
285 */
286 size = PAGE_ALIGN(offset + size);
284 287
285 area = get_vm_area(size, VM_IOREMAP); 288 area = get_vm_area(size, VM_IOREMAP);
286 if (!area) 289 if (!area)
@@ -325,11 +328,6 @@ __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
325 if (!size || last_addr < phys_addr) 328 if (!size || last_addr < phys_addr)
326 return NULL; 329 return NULL;
327 330
328 /*
329 * Page align the mapping size
330 */
331 size = PAGE_ALIGN(last_addr + 1) - phys_addr;
332
333 return __arm_ioremap_pfn(pfn, offset, size, mtype); 331 return __arm_ioremap_pfn(pfn, offset, size, mtype);
334} 332}
335EXPORT_SYMBOL(__arm_ioremap); 333EXPORT_SYMBOL(__arm_ioremap);