diff options
Diffstat (limited to 'arch/arm')
55 files changed, 2297 insertions, 366 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 | ||
242 | config ARCH_IMX | 242 | config 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 | ||
309 | config ARCH_KS8695 | 312 | config 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 @@ | |||
1 | piggy.gz | 1 | piggy.gz |
2 | font.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 | ||
7 | HEAD = head.o | 7 | HEAD = head.o |
8 | OBJS = misc.o | 8 | OBJS = misc.o |
9 | FONTC = drivers/video/console/font_acorn_8x8.c | 9 | FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c |
10 | |||
11 | FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o) | ||
12 | 10 | ||
13 | # | 11 | # |
14 | # Architecture dependencies | 12 | # Architecture dependencies |
15 | # | 13 | # |
16 | ifeq ($(CONFIG_ARCH_ACORN),y) | 14 | ifeq ($(CONFIG_ARCH_ACORN),y) |
17 | OBJS += ll_char_wr.o $(FONT) | 15 | OBJS += ll_char_wr.o font.o |
18 | endif | 16 | endif |
19 | 17 | ||
20 | ifeq ($(CONFIG_ARCH_SHARK),y) | 18 | ifeq ($(CONFIG_ARCH_SHARK),y) |
@@ -73,7 +71,7 @@ endif | |||
73 | 71 | ||
74 | SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ | 72 | SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ |
75 | 73 | ||
76 | targets := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \ | 74 | targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \ |
77 | head.o misc.o $(OBJS) | 75 | head.o misc.o $(OBJS) |
78 | EXTRA_CFLAGS := -fpic | 76 | EXTRA_CFLAGS := -fpic |
79 | EXTRA_AFLAGS := | 77 | EXTRA_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 | ||
108 | CFLAGS_font_acorn_8x8.o := -Dstatic= | 106 | CFLAGS_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-xscale.S b/arch/arm/boot/compressed/head-xscale.S index 73c5d9e0201c..236bbe578312 100644 --- a/arch/arm/boot/compressed/head-xscale.S +++ b/arch/arm/boot/compressed/head-xscale.S | |||
@@ -41,11 +41,6 @@ __XScale_start: | |||
41 | mov r7, #MACH_TYPE_COTULLA_IDP | 41 | mov r7, #MACH_TYPE_COTULLA_IDP |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | #ifdef CONFIG_MACH_GTWX5715 | ||
45 | mov r7, #(MACH_TYPE_GTWX5715 & 0xff) | ||
46 | orr r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00) | ||
47 | #endif | ||
48 | |||
49 | #ifdef CONFIG_ARCH_IXP2000 | 44 | #ifdef CONFIG_ARCH_IXP2000 |
50 | mov r1, #-1 | 45 | mov r1, #-1 |
51 | mov r0, #0xd6000000 | 46 | mov r0, #0xd6000000 |
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 | ||
778 | hierarchical: | ||
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 | ||
785 | loop1: | ||
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 | ||
801 | loop2: | ||
802 | mov r9, r4 @ create working copy of max way size | ||
803 | loop3: | ||
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 | ||
811 | skip: | ||
812 | add r10, r10, #2 @ increment cache number | ||
813 | cmp r3, r10 | ||
814 | bgt loop1 | ||
815 | finished: | ||
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} | ||
819 | iflush: | ||
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 | ||
768 | static struct pm_ops sharpsl_pm_ops = { | 768 | static 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 | |||
250 | 1: 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 | ||
47 | static const char *isa_modes[] = { | ||
48 | "ARM" , "Thumb" , "Jazelle", "ThumbEE" | ||
49 | }; | ||
50 | |||
47 | extern void setup_mm_for_reboot(char mode); | 51 | extern void setup_mm_for_reboot(char mode); |
48 | 52 | ||
49 | static volatile int hlt_counter; | 53 | static 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; | |||
63 | unsigned int __machine_arch_type; | 63 | unsigned int __machine_arch_type; |
64 | EXPORT_SYMBOL(__machine_arch_type); | 64 | EXPORT_SYMBOL(__machine_arch_type); |
65 | 65 | ||
66 | unsigned int __atags_pointer __initdata; | ||
67 | |||
66 | unsigned int system_rev; | 68 | unsigned int system_rev; |
67 | EXPORT_SYMBOL(system_rev); | 69 | EXPORT_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) | ||
283 | static 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 | |||
299 | static 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 | |||
315 | static 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 */ | ||
324 | static 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 | ||
334 | static 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) | ||
342 | static 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 | |||
369 | static struct gpio_keys_platform_data ek_button_data = { | ||
370 | .buttons = ek_buttons, | ||
371 | .nbuttons = ARRAY_SIZE(ek_buttons), | ||
372 | }; | ||
373 | |||
374 | static 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 | |||
383 | static 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 | ||
397 | static void __init ek_add_device_buttons(void) {} | ||
398 | #endif | ||
399 | |||
274 | static void __init ek_board_init(void) | 400 | static 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 | ||
301 | MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK") | 431 | MACHINE_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) | ||
211 | static 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 | |||
227 | static 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 | |||
243 | static 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 */ | ||
252 | static 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 | ||
262 | static struct atmel_lcdfb_info __initdata ek_lcdc_data; | ||
263 | #endif | ||
264 | |||
265 | |||
266 | /* | ||
205 | * AC97 | 267 | * AC97 |
206 | */ | 268 | */ |
207 | static struct atmel_ac97_data ek_ac97_data = { | 269 | static 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 |
7 | obj-y := time.o irq.o serial.o io.o id.o psc.o | 7 | obj-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 |
10 | obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o | 11 | obj-$(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 @@ | |||
32 | void __init davinci_psc_init(void); | 32 | void __init davinci_psc_init(void); |
33 | void __init davinci_irq_init(void); | 33 | void __init davinci_irq_init(void); |
34 | void __init davinci_map_common_io(void); | 34 | void __init davinci_map_common_io(void); |
35 | void __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 | ||
117 | static __init void davinci_evm_irq_init(void) | 118 | static __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 | |||
29 | static LIST_HEAD(clocks); | ||
30 | static DEFINE_MUTEX(clocks_mutex); | ||
31 | static DEFINE_SPINLOCK(clockfw_lock); | ||
32 | |||
33 | static unsigned int commonrate; | ||
34 | static unsigned int armrate; | ||
35 | static unsigned int fixedrate = 27000000; /* 27 MHZ */ | ||
36 | |||
37 | extern 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 | */ | ||
43 | struct 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 | |||
70 | found: | ||
71 | mutex_unlock(&clocks_mutex); | ||
72 | |||
73 | return clk; | ||
74 | } | ||
75 | EXPORT_SYMBOL(clk_get); | ||
76 | |||
77 | void clk_put(struct clk *clk) | ||
78 | { | ||
79 | if (clk && !IS_ERR(clk)) | ||
80 | module_put(clk->owner); | ||
81 | } | ||
82 | EXPORT_SYMBOL(clk_put); | ||
83 | |||
84 | static 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 | |||
93 | static 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 | |||
101 | int 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 | } | ||
117 | EXPORT_SYMBOL(clk_enable); | ||
118 | |||
119 | void 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 | } | ||
132 | EXPORT_SYMBOL(clk_disable); | ||
133 | |||
134 | unsigned long clk_get_rate(struct clk *clk) | ||
135 | { | ||
136 | if (clk == NULL || IS_ERR(clk)) | ||
137 | return -EINVAL; | ||
138 | |||
139 | return *(clk->rate); | ||
140 | } | ||
141 | EXPORT_SYMBOL(clk_get_rate); | ||
142 | |||
143 | long 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 | } | ||
150 | EXPORT_SYMBOL(clk_round_rate); | ||
151 | |||
152 | int 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 | } | ||
160 | EXPORT_SYMBOL(clk_set_rate); | ||
161 | |||
162 | int 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 | } | ||
173 | EXPORT_SYMBOL(clk_register); | ||
174 | |||
175 | void 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 | } | ||
184 | EXPORT_SYMBOL(clk_unregister); | ||
185 | |||
186 | static 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 | |||
241 | int __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 | |||
268 | static void *davinci_ck_start(struct seq_file *m, loff_t *pos) | ||
269 | { | ||
270 | return *pos < 1 ? (void *)1 : NULL; | ||
271 | } | ||
272 | |||
273 | static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos) | ||
274 | { | ||
275 | ++*pos; | ||
276 | return NULL; | ||
277 | } | ||
278 | |||
279 | static void davinci_ck_stop(struct seq_file *m, void *v) | ||
280 | { | ||
281 | } | ||
282 | |||
283 | static 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 | |||
293 | static 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 | |||
300 | static int davinci_ck_open(struct inode *inode, struct file *file) | ||
301 | { | ||
302 | return seq_open(file, &davinci_ck_op); | ||
303 | } | ||
304 | |||
305 | static 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 | |||
312 | static 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 | |||
14 | struct 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 | |||
29 | static DEFINE_SPINLOCK(gpio_lock); | ||
30 | static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO); | ||
31 | |||
32 | int 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 | } | ||
42 | EXPORT_SYMBOL(gpio_request); | ||
43 | |||
44 | void gpio_free(unsigned gpio) | ||
45 | { | ||
46 | if (gpio >= DAVINCI_N_GPIO) | ||
47 | return; | ||
48 | |||
49 | clear_bit(gpio, gpio_in_use); | ||
50 | } | ||
51 | EXPORT_SYMBOL(gpio_free); | ||
52 | |||
53 | /* create a non-inlined version */ | ||
54 | static 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 | */ | ||
62 | void __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 | } | ||
68 | EXPORT_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 | */ | ||
78 | int __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 | } | ||
84 | EXPORT_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 | |||
94 | int 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 | } | ||
111 | EXPORT_SYMBOL(gpio_direction_input); | ||
112 | |||
113 | int 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 | } | ||
131 | EXPORT_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 | |||
145 | static 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 | |||
154 | static 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 | |||
165 | static 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 | |||
183 | static 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 | |||
190 | static void | ||
191 | gpio_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 | |||
239 | static 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 | |||
286 | arch_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 | ||
21 | extern void davinci_check_revision(void); | 22 | extern 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 | |||
54 | void __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 | |||
22 | static DEFINE_SPINLOCK(mux_lock); | ||
23 | |||
24 | void 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 | ||
42 | static void davinci_psc_mux(unsigned int id) | 42 | static 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 */ |
68 | void davinci_psc_config(unsigned int domain, unsigned int id, char enable) | 69 | void 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 | |||
40 | unsigned long imx_gpio_alloc_map[(GPIO_PORT_MAX + 1) * 32 / BITS_PER_LONG]; | ||
37 | 41 | ||
38 | void imx_gpio_mode(int gpio_mode) | 42 | void imx_gpio_mode(int gpio_mode) |
39 | { | 43 | { |
@@ -95,6 +99,120 @@ void imx_gpio_mode(int gpio_mode) | |||
95 | 99 | ||
96 | EXPORT_SYMBOL(imx_gpio_mode); | 100 | EXPORT_SYMBOL(imx_gpio_mode); |
97 | 101 | ||
102 | int 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 | |||
118 | EXPORT_SYMBOL(imx_gpio_request); | ||
119 | |||
120 | void 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 | |||
128 | EXPORT_SYMBOL(imx_gpio_free); | ||
129 | |||
130 | int imx_gpio_direction_input(unsigned gpio) | ||
131 | { | ||
132 | imx_gpio_mode(gpio| GPIO_IN); | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | EXPORT_SYMBOL(imx_gpio_direction_input); | ||
137 | |||
138 | int 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 | |||
145 | EXPORT_SYMBOL(imx_gpio_direction_output); | ||
146 | |||
147 | int 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 | |||
177 | setup_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 | |||
191 | EXPORT_SYMBOL(imx_gpio_setup_multiple_pins); | ||
192 | |||
193 | void __imx_gpio_set_value(unsigned gpio, int value) | ||
194 | { | ||
195 | imx_gpio_set_value_inline(gpio, value); | ||
196 | } | ||
197 | |||
198 | EXPORT_SYMBOL(__imx_gpio_set_value); | ||
199 | |||
200 | int imx_gpio_to_irq(unsigned gpio) | ||
201 | { | ||
202 | return IRQ_GPIOA(0) + gpio; | ||
203 | } | ||
204 | |||
205 | EXPORT_SYMBOL(imx_gpio_to_irq); | ||
206 | |||
207 | int imx_irq_to_gpio(unsigned irq) | ||
208 | { | ||
209 | if (irq < IRQ_GPIOA(0)) | ||
210 | return -EINVAL; | ||
211 | return irq - IRQ_GPIOA(0); | ||
212 | } | ||
213 | |||
214 | EXPORT_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 | ||
28 | static unsigned long evt_diff; | 30 | static struct clock_event_device clockevent_imx; |
31 | static 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; | |||
33 | static irqreturn_t | 36 | static irqreturn_t |
34 | imx_timer_interrupt(int irq, void *dev_id) | 37 | imx_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 | ||
57 | static struct irqaction imx_timer_irq = { | 55 | static 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 | ||
79 | cycle_t imx_get_cycles(void) | 75 | cycle_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 | ||
98 | static 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 | ||
110 | static 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 | |||
118 | static 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 | |||
167 | static 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 | |||
176 | static 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 | |||
102 | static void __init imx_timer_init(void) | 193 | static 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 | ||
40 | static struct resource iop13xx_tpmi_0_resources[] = { | 42 | static 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; | |||
133 | static struct platform_device iop13xx_tpmi_0_device = { | 155 | static 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 = { | |||
144 | static struct platform_device iop13xx_tpmi_1_device = { | 166 | static 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 = { | |||
155 | static struct platform_device iop13xx_tpmi_2_device = { | 177 | static 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 = { | |||
166 | static struct platform_device iop13xx_tpmi_3_device = { | 188 | static 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-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig index 060909870b50..61b2dfcb89d6 100644 --- a/arch/arm/mach-ixp4xx/Kconfig +++ b/arch/arm/mach-ixp4xx/Kconfig | |||
@@ -41,6 +41,22 @@ config ARCH_ADI_COYOTE | |||
41 | Engineering Coyote Gateway Reference Platform. For more | 41 | Engineering Coyote Gateway Reference Platform. For more |
42 | information on this platform, see <file:Documentation/arm/IXP4xx>. | 42 | information on this platform, see <file:Documentation/arm/IXP4xx>. |
43 | 43 | ||
44 | config MACH_GATEWAY7001 | ||
45 | bool "Gateway 7001" | ||
46 | select PCI | ||
47 | help | ||
48 | Say 'Y' here if you want your kernel to support Gateway's | ||
49 | 7001 Access Point. For more information on this platform, | ||
50 | see http://openwrt.org | ||
51 | |||
52 | config MACH_WG302V2 | ||
53 | bool "Netgear WG302 v2 / WAG302 v2" | ||
54 | select PCI | ||
55 | help | ||
56 | Say 'Y' here if you want your kernel to support Netgear's | ||
57 | WG302 v2 or WAG302 v2 Access Points. For more information | ||
58 | on this platform, see http://openwrt.org | ||
59 | |||
44 | config ARCH_IXDP425 | 60 | config ARCH_IXDP425 |
45 | bool "IXDP425" | 61 | bool "IXDP425" |
46 | help | 62 | help |
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile index 3b87c47e06cf..77e00ade5585 100644 --- a/arch/arm/mach-ixp4xx/Makefile +++ b/arch/arm/mach-ixp4xx/Makefile | |||
@@ -13,6 +13,8 @@ obj-pci-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o | |||
13 | obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-pci.o | 13 | obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-pci.o |
14 | obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o | 14 | obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o |
15 | obj-pci-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o | 15 | obj-pci-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o |
16 | obj-pci-$(CONFIG_MACH_GATEWAY7001) += gateway7001-pci.o | ||
17 | obj-pci-$(CONFIG_MACH_WG302V2) += wg302v2-pci.o | ||
16 | 18 | ||
17 | obj-y += common.o | 19 | obj-y += common.o |
18 | 20 | ||
@@ -24,5 +26,7 @@ obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o | |||
24 | obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o nslu2-power.o | 26 | obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o nslu2-power.o |
25 | obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o nas100d-power.o | 27 | obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o nas100d-power.o |
26 | obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o dsmg600-power.o | 28 | obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o dsmg600-power.o |
29 | obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-setup.o | ||
30 | obj-$(CONFIG_MACH_WG302V2) += wg302v2-setup.o | ||
27 | 31 | ||
28 | obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o | 32 | obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o |
diff --git a/arch/arm/mach-ixp4xx/gateway7001-pci.c b/arch/arm/mach-ixp4xx/gateway7001-pci.c new file mode 100644 index 000000000000..6abf568322d3 --- /dev/null +++ b/arch/arm/mach-ixp4xx/gateway7001-pci.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * arch/arch/mach-ixp4xx/gateway7001-pci.c | ||
3 | * | ||
4 | * PCI setup routines for Gateway 7001 | ||
5 | * | ||
6 | * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org> | ||
7 | * | ||
8 | * based on coyote-pci.c: | ||
9 | * Copyright (C) 2002 Jungo Software Technologies. | ||
10 | * Copyright (C) 2003 MontaVista Softwrae, Inc. | ||
11 | * | ||
12 | * Maintainer: Imre Kaloz <kaloz@openwrt.org> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/irq.h> | ||
24 | |||
25 | #include <asm/mach-types.h> | ||
26 | #include <asm/hardware.h> | ||
27 | |||
28 | #include <asm/mach/pci.h> | ||
29 | |||
30 | void __init gateway7001_pci_preinit(void) | ||
31 | { | ||
32 | set_irq_type(IRQ_IXP4XX_GPIO10, IRQT_LOW); | ||
33 | set_irq_type(IRQ_IXP4XX_GPIO11, IRQT_LOW); | ||
34 | |||
35 | ixp4xx_pci_preinit(); | ||
36 | } | ||
37 | |||
38 | static int __init gateway7001_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
39 | { | ||
40 | if (slot == 1) | ||
41 | return IRQ_IXP4XX_GPIO11; | ||
42 | else if (slot == 2) | ||
43 | return IRQ_IXP4XX_GPIO10; | ||
44 | else return -1; | ||
45 | } | ||
46 | |||
47 | struct hw_pci gateway7001_pci __initdata = { | ||
48 | .nr_controllers = 1, | ||
49 | .preinit = gateway7001_pci_preinit, | ||
50 | .swizzle = pci_std_swizzle, | ||
51 | .setup = ixp4xx_setup, | ||
52 | .scan = ixp4xx_scan_bus, | ||
53 | .map_irq = gateway7001_map_irq, | ||
54 | }; | ||
55 | |||
56 | int __init gateway7001_pci_init(void) | ||
57 | { | ||
58 | if (machine_is_gateway7001()) | ||
59 | pci_common_init(&gateway7001_pci); | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | subsys_initcall(gateway7001_pci_init); | ||
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c new file mode 100644 index 000000000000..37876832e141 --- /dev/null +++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-ixp4xx/gateway7001-setup.c | ||
3 | * | ||
4 | * Board setup for the Gateway 7001 board | ||
5 | * | ||
6 | * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org> | ||
7 | * | ||
8 | * based on coyote-setup.c: | ||
9 | * Copyright (C) 2003-2005 MontaVista Software, Inc. | ||
10 | * | ||
11 | * Author: Imre Kaloz <Kaloz@openwrt.org> | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/serial.h> | ||
18 | #include <linux/tty.h> | ||
19 | #include <linux/serial_8250.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include <asm/types.h> | ||
23 | #include <asm/setup.h> | ||
24 | #include <asm/memory.h> | ||
25 | #include <asm/hardware.h> | ||
26 | #include <asm/irq.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | #include <asm/mach/arch.h> | ||
29 | #include <asm/mach/flash.h> | ||
30 | |||
31 | static struct flash_platform_data gateway7001_flash_data = { | ||
32 | .map_name = "cfi_probe", | ||
33 | .width = 2, | ||
34 | }; | ||
35 | |||
36 | static struct resource gateway7001_flash_resource = { | ||
37 | .flags = IORESOURCE_MEM, | ||
38 | }; | ||
39 | |||
40 | static struct platform_device gateway7001_flash = { | ||
41 | .name = "IXP4XX-Flash", | ||
42 | .id = 0, | ||
43 | .dev = { | ||
44 | .platform_data = &gateway7001_flash_data, | ||
45 | }, | ||
46 | .num_resources = 1, | ||
47 | .resource = &gateway7001_flash_resource, | ||
48 | }; | ||
49 | |||
50 | static struct resource gateway7001_uart_resource = { | ||
51 | .start = IXP4XX_UART2_BASE_PHYS, | ||
52 | .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, | ||
53 | .flags = IORESOURCE_MEM, | ||
54 | }; | ||
55 | |||
56 | static struct plat_serial8250_port gateway7001_uart_data[] = { | ||
57 | { | ||
58 | .mapbase = IXP4XX_UART2_BASE_PHYS, | ||
59 | .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, | ||
60 | .irq = IRQ_IXP4XX_UART2, | ||
61 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, | ||
62 | .iotype = UPIO_MEM, | ||
63 | .regshift = 2, | ||
64 | .uartclk = IXP4XX_UART_XTAL, | ||
65 | }, | ||
66 | { }, | ||
67 | }; | ||
68 | |||
69 | static struct platform_device gateway7001_uart = { | ||
70 | .name = "serial8250", | ||
71 | .id = PLAT8250_DEV_PLATFORM, | ||
72 | .dev = { | ||
73 | .platform_data = gateway7001_uart_data, | ||
74 | }, | ||
75 | .num_resources = 1, | ||
76 | .resource = &gateway7001_uart_resource, | ||
77 | }; | ||
78 | |||
79 | static struct platform_device *gateway7001_devices[] __initdata = { | ||
80 | &gateway7001_flash, | ||
81 | &gateway7001_uart | ||
82 | }; | ||
83 | |||
84 | static void __init gateway7001_init(void) | ||
85 | { | ||
86 | ixp4xx_sys_init(); | ||
87 | |||
88 | gateway7001_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); | ||
89 | gateway7001_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; | ||
90 | |||
91 | *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; | ||
92 | *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; | ||
93 | |||
94 | platform_add_devices(gateway7001_devices, ARRAY_SIZE(gateway7001_devices)); | ||
95 | } | ||
96 | |||
97 | #ifdef CONFIG_MACH_GATEWAY7001 | ||
98 | MACHINE_START(GATEWAY7001, "Gateway 7001 AP") | ||
99 | /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */ | ||
100 | .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, | ||
101 | .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, | ||
102 | .map_io = ixp4xx_map_io, | ||
103 | .init_irq = ixp4xx_init_irq, | ||
104 | .timer = &ixp4xx_timer, | ||
105 | .boot_params = 0x0100, | ||
106 | .init_machine = gateway7001_init, | ||
107 | MACHINE_END | ||
108 | #endif | ||
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c index a66484b63d36..0d5a42455820 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c | |||
@@ -25,17 +25,13 @@ | |||
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/irq.h> | ||
29 | |||
28 | #include <asm/mach-types.h> | 30 | #include <asm/mach-types.h> |
29 | #include <asm/hardware.h> | 31 | #include <asm/hardware.h> |
30 | #include <asm/irq.h> | ||
31 | #include <asm/arch/gtwx5715.h> | 32 | #include <asm/arch/gtwx5715.h> |
32 | #include <asm/mach/pci.h> | 33 | #include <asm/mach/pci.h> |
33 | 34 | ||
34 | extern void ixp4xx_pci_preinit(void); | ||
35 | extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); | ||
36 | extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); | ||
37 | |||
38 | |||
39 | /* | 35 | /* |
40 | * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h | 36 | * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h |
41 | * Slot 0 isn't actually populated with a card connector but | 37 | * Slot 0 isn't actually populated with a card connector but |
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index ec4f07950ec6..d5008d8fc9a5 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c | |||
@@ -15,6 +15,10 @@ | |||
15 | #include <linux/tty.h> | 15 | #include <linux/tty.h> |
16 | #include <linux/serial_8250.h> | 16 | #include <linux/serial_8250.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/io.h> | ||
19 | #include <linux/mtd/mtd.h> | ||
20 | #include <linux/mtd/nand.h> | ||
21 | #include <linux/mtd/partitions.h> | ||
18 | 22 | ||
19 | #include <asm/types.h> | 23 | #include <asm/types.h> |
20 | #include <asm/setup.h> | 24 | #include <asm/setup.h> |
@@ -24,6 +28,7 @@ | |||
24 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
25 | #include <asm/mach/arch.h> | 29 | #include <asm/mach/arch.h> |
26 | #include <asm/mach/flash.h> | 30 | #include <asm/mach/flash.h> |
31 | #include <asm/delay.h> | ||
27 | 32 | ||
28 | static struct flash_platform_data ixdp425_flash_data = { | 33 | static struct flash_platform_data ixdp425_flash_data = { |
29 | .map_name = "cfi_probe", | 34 | .map_name = "cfi_probe", |
@@ -44,6 +49,77 @@ static struct platform_device ixdp425_flash = { | |||
44 | .resource = &ixdp425_flash_resource, | 49 | .resource = &ixdp425_flash_resource, |
45 | }; | 50 | }; |
46 | 51 | ||
52 | #if defined(CONFIG_MTD_NAND_PLATFORM) || \ | ||
53 | defined(CONFIG_MTD_NAND_PLATFORM_MODULE) | ||
54 | |||
55 | #ifdef CONFIG_MTD_PARTITIONS | ||
56 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
57 | |||
58 | static struct mtd_partition ixdp425_partitions[] = { | ||
59 | { | ||
60 | .name = "ixp400 NAND FS 0", | ||
61 | .offset = 0, | ||
62 | .size = SZ_8M | ||
63 | }, { | ||
64 | .name = "ixp400 NAND FS 1", | ||
65 | .offset = MTDPART_OFS_APPEND, | ||
66 | .size = MTDPART_SIZ_FULL | ||
67 | }, | ||
68 | }; | ||
69 | #endif | ||
70 | |||
71 | static void | ||
72 | ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | ||
73 | { | ||
74 | struct nand_chip *this = mtd->priv; | ||
75 | int offset = (int)this->priv; | ||
76 | |||
77 | if (ctrl & NAND_CTRL_CHANGE) { | ||
78 | if (ctrl & NAND_NCE) { | ||
79 | gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_LOW); | ||
80 | udelay(5); | ||
81 | } else | ||
82 | gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_HIGH); | ||
83 | |||
84 | offset = (ctrl & NAND_CLE) ? IXDP425_NAND_CMD_BYTE : 0; | ||
85 | offset |= (ctrl & NAND_ALE) ? IXDP425_NAND_ADDR_BYTE : 0; | ||
86 | this->priv = (void *)offset; | ||
87 | } | ||
88 | |||
89 | if (cmd != NAND_CMD_NONE) | ||
90 | writeb(cmd, this->IO_ADDR_W + offset); | ||
91 | } | ||
92 | |||
93 | static struct platform_nand_data ixdp425_flash_nand_data = { | ||
94 | .chip = { | ||
95 | .chip_delay = 30, | ||
96 | .options = NAND_NO_AUTOINCR, | ||
97 | #ifdef CONFIG_MTD_PARTITIONS | ||
98 | .part_probe_types = part_probes, | ||
99 | .partitions = ixdp425_partitions, | ||
100 | .nr_partitions = ARRAY_SIZE(ixdp425_partitions), | ||
101 | #endif | ||
102 | }, | ||
103 | .ctrl = { | ||
104 | .cmd_ctrl = ixdp425_flash_nand_cmd_ctrl | ||
105 | } | ||
106 | }; | ||
107 | |||
108 | static struct resource ixdp425_flash_nand_resource = { | ||
109 | .flags = IORESOURCE_MEM, | ||
110 | }; | ||
111 | |||
112 | static struct platform_device ixdp425_flash_nand = { | ||
113 | .name = "gen_nand", | ||
114 | .id = -1, | ||
115 | .dev = { | ||
116 | .platform_data = &ixdp425_flash_nand_data, | ||
117 | }, | ||
118 | .num_resources = 1, | ||
119 | .resource = &ixdp425_flash_nand_resource, | ||
120 | }; | ||
121 | #endif /* CONFIG_MTD_NAND_PLATFORM */ | ||
122 | |||
47 | static struct ixp4xx_i2c_pins ixdp425_i2c_gpio_pins = { | 123 | static struct ixp4xx_i2c_pins ixdp425_i2c_gpio_pins = { |
48 | .sda_pin = IXDP425_SDA_PIN, | 124 | .sda_pin = IXDP425_SDA_PIN, |
49 | .scl_pin = IXDP425_SCL_PIN, | 125 | .scl_pin = IXDP425_SCL_PIN, |
@@ -104,6 +180,10 @@ static struct platform_device ixdp425_uart = { | |||
104 | static struct platform_device *ixdp425_devices[] __initdata = { | 180 | static struct platform_device *ixdp425_devices[] __initdata = { |
105 | &ixdp425_i2c_controller, | 181 | &ixdp425_i2c_controller, |
106 | &ixdp425_flash, | 182 | &ixdp425_flash, |
183 | #if defined(CONFIG_MTD_NAND_PLATFORM) || \ | ||
184 | defined(CONFIG_MTD_NAND_PLATFORM_MODULE) | ||
185 | &ixdp425_flash_nand, | ||
186 | #endif | ||
107 | &ixdp425_uart | 187 | &ixdp425_uart |
108 | }; | 188 | }; |
109 | 189 | ||
@@ -115,6 +195,22 @@ static void __init ixdp425_init(void) | |||
115 | ixdp425_flash_resource.end = | 195 | ixdp425_flash_resource.end = |
116 | IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; | 196 | IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; |
117 | 197 | ||
198 | #if defined(CONFIG_MTD_NAND_PLATFORM) || \ | ||
199 | defined(CONFIG_MTD_NAND_PLATFORM_MODULE) | ||
200 | ixdp425_flash_nand_resource.start = IXP4XX_EXP_BUS_BASE(3), | ||
201 | ixdp425_flash_nand_resource.end = IXP4XX_EXP_BUS_BASE(3) + 0x10 - 1; | ||
202 | |||
203 | gpio_line_config(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_OUT); | ||
204 | |||
205 | /* Configure expansion bus for NAND Flash */ | ||
206 | *IXP4XX_EXP_CS3 = IXP4XX_EXP_BUS_CS_EN | | ||
207 | IXP4XX_EXP_BUS_STROBE_T(1) | /* extend by 1 clock */ | ||
208 | IXP4XX_EXP_BUS_CYCLES(0) | /* Intel cycles */ | ||
209 | IXP4XX_EXP_BUS_SIZE(0) | /* 512bytes addr space*/ | ||
210 | IXP4XX_EXP_BUS_WR_EN | | ||
211 | IXP4XX_EXP_BUS_BYTE_EN; /* 8 bit data bus */ | ||
212 | #endif | ||
213 | |||
118 | if (cpu_is_ixp43x()) { | 214 | if (cpu_is_ixp43x()) { |
119 | ixdp425_uart.num_resources = 1; | 215 | ixdp425_uart.num_resources = 1; |
120 | ixdp425_uart_data[1].flags = 0; | 216 | ixdp425_uart_data[1].flags = 0; |
diff --git a/arch/arm/mach-ixp4xx/wg302v2-pci.c b/arch/arm/mach-ixp4xx/wg302v2-pci.c new file mode 100644 index 000000000000..6588f2c758e2 --- /dev/null +++ b/arch/arm/mach-ixp4xx/wg302v2-pci.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * arch/arch/mach-ixp4xx/wg302v2-pci.c | ||
3 | * | ||
4 | * PCI setup routines for the Netgear WG302 v2 and WAG302 v2 | ||
5 | * | ||
6 | * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org> | ||
7 | * | ||
8 | * based on coyote-pci.c: | ||
9 | * Copyright (C) 2002 Jungo Software Technologies. | ||
10 | * Copyright (C) 2003 MontaVista Software, Inc. | ||
11 | * | ||
12 | * Maintainer: Imre Kaloz <kaloz@openwrt.org> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/irq.h> | ||
24 | |||
25 | #include <asm/mach-types.h> | ||
26 | #include <asm/hardware.h> | ||
27 | |||
28 | #include <asm/mach/pci.h> | ||
29 | |||
30 | void __init wg302v2_pci_preinit(void) | ||
31 | { | ||
32 | set_irq_type(IRQ_IXP4XX_GPIO8, IRQT_LOW); | ||
33 | set_irq_type(IRQ_IXP4XX_GPIO9, IRQT_LOW); | ||
34 | |||
35 | ixp4xx_pci_preinit(); | ||
36 | } | ||
37 | |||
38 | static int __init wg302v2_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
39 | { | ||
40 | if (slot == 1) | ||
41 | return IRQ_IXP4XX_GPIO8; | ||
42 | else if (slot == 2) | ||
43 | return IRQ_IXP4XX_GPIO9; | ||
44 | else return -1; | ||
45 | } | ||
46 | |||
47 | struct hw_pci wg302v2_pci __initdata = { | ||
48 | .nr_controllers = 1, | ||
49 | .preinit = wg302v2_pci_preinit, | ||
50 | .swizzle = pci_std_swizzle, | ||
51 | .setup = ixp4xx_setup, | ||
52 | .scan = ixp4xx_scan_bus, | ||
53 | .map_irq = wg302v2_map_irq, | ||
54 | }; | ||
55 | |||
56 | int __init wg302v2_pci_init(void) | ||
57 | { | ||
58 | if (machine_is_wg302v2()) | ||
59 | pci_common_init(&wg302v2_pci); | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | subsys_initcall(wg302v2_pci_init); | ||
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c new file mode 100644 index 000000000000..f7e09ad804e8 --- /dev/null +++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-ixp4xx/wg302-setup.c | ||
3 | * | ||
4 | * Board setup for the Netgear WG302 v2 and WAG302 v2 | ||
5 | * | ||
6 | * Copyright (C) 2007 Imre Kaloz <Kaloz@openwrt.org> | ||
7 | * | ||
8 | * based on coyote-setup.c: | ||
9 | * Copyright (C) 2003-2005 MontaVista Software, Inc. | ||
10 | * | ||
11 | * Author: Imre Kaloz <kaloz@openwrt.org> | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/serial.h> | ||
19 | #include <linux/tty.h> | ||
20 | #include <linux/serial_8250.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | #include <asm/types.h> | ||
24 | #include <asm/setup.h> | ||
25 | #include <asm/memory.h> | ||
26 | #include <asm/hardware.h> | ||
27 | #include <asm/irq.h> | ||
28 | #include <asm/mach-types.h> | ||
29 | #include <asm/mach/arch.h> | ||
30 | #include <asm/mach/flash.h> | ||
31 | |||
32 | static struct flash_platform_data wg302v2_flash_data = { | ||
33 | .map_name = "cfi_probe", | ||
34 | .width = 2, | ||
35 | }; | ||
36 | |||
37 | static struct resource wg302v2_flash_resource = { | ||
38 | .flags = IORESOURCE_MEM, | ||
39 | }; | ||
40 | |||
41 | static struct platform_device wg302v2_flash = { | ||
42 | .name = "IXP4XX-Flash", | ||
43 | .id = 0, | ||
44 | .dev = { | ||
45 | .platform_data = &wg302v2_flash_data, | ||
46 | }, | ||
47 | .num_resources = 1, | ||
48 | .resource = &wg302v2_flash_resource, | ||
49 | }; | ||
50 | |||
51 | static struct resource wg302v2_uart_resource = { | ||
52 | .start = IXP4XX_UART2_BASE_PHYS, | ||
53 | .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, | ||
54 | .flags = IORESOURCE_MEM, | ||
55 | }; | ||
56 | |||
57 | static struct plat_serial8250_port wg302v2_uart_data[] = { | ||
58 | { | ||
59 | .mapbase = IXP4XX_UART2_BASE_PHYS, | ||
60 | .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, | ||
61 | .irq = IRQ_IXP4XX_UART2, | ||
62 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, | ||
63 | .iotype = UPIO_MEM, | ||
64 | .regshift = 2, | ||
65 | .uartclk = IXP4XX_UART_XTAL, | ||
66 | }, | ||
67 | { }, | ||
68 | }; | ||
69 | |||
70 | static struct platform_device wg302v2_uart = { | ||
71 | .name = "serial8250", | ||
72 | .id = PLAT8250_DEV_PLATFORM, | ||
73 | .dev = { | ||
74 | .platform_data = wg302v2_uart_data, | ||
75 | }, | ||
76 | .num_resources = 1, | ||
77 | .resource = &wg302v2_uart_resource, | ||
78 | }; | ||
79 | |||
80 | static struct platform_device *wg302v2_devices[] __initdata = { | ||
81 | &wg302v2_flash, | ||
82 | &wg302v2_uart, | ||
83 | }; | ||
84 | |||
85 | static void __init wg302v2_init(void) | ||
86 | { | ||
87 | ixp4xx_sys_init(); | ||
88 | |||
89 | wg302v2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); | ||
90 | wg302v2_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; | ||
91 | |||
92 | *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; | ||
93 | *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; | ||
94 | |||
95 | platform_add_devices(wg302v2_devices, ARRAY_SIZE(wg302v2_devices)); | ||
96 | } | ||
97 | |||
98 | #ifdef CONFIG_MACH_WG302V2 | ||
99 | MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2") | ||
100 | /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */ | ||
101 | .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, | ||
102 | .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, | ||
103 | .map_io = ixp4xx_map_io, | ||
104 | .init_irq = ixp4xx_init_irq, | ||
105 | .timer = &ixp4xx_timer, | ||
106 | .boot_params = 0x0100, | ||
107 | .init_machine = wg302v2_init, | ||
108 | MACHINE_END | ||
109 | #endif | ||
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 | ||
6 | obj-y := cpu.o irq.o time.o devices.o | 6 | obj-y := cpu.o irq.o time.o gpio.o devices.o |
7 | obj-m := | 7 | obj-m := |
8 | obj-n := | 8 | obj-n := |
9 | obj- := | 9 | obj- := |
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 | */ | ||
36 | static 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 | |||
57 | static 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 | */ | ||
62 | int __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 | } | ||
86 | EXPORT_SYMBOL(ks8695_gpio_interrupt); | ||
87 | |||
88 | |||
89 | |||
90 | /* .... Generic GPIO interface .............................................. */ | ||
91 | |||
92 | /* | ||
93 | * Configure the GPIO line as an input. | ||
94 | */ | ||
95 | int __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 | } | ||
116 | EXPORT_SYMBOL(gpio_direction_input); | ||
117 | |||
118 | |||
119 | /* | ||
120 | * Configure the GPIO line as an output, with default state. | ||
121 | */ | ||
122 | int __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 | } | ||
151 | EXPORT_SYMBOL(gpio_direction_output); | ||
152 | |||
153 | |||
154 | /* | ||
155 | * Set the state of an output GPIO line. | ||
156 | */ | ||
157 | void 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 | } | ||
176 | EXPORT_SYMBOL(gpio_set_value); | ||
177 | |||
178 | |||
179 | /* | ||
180 | * Read the state of a GPIO line. | ||
181 | */ | ||
182 | int 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 | } | ||
192 | EXPORT_SYMBOL(gpio_get_value); | ||
193 | |||
194 | |||
195 | /* | ||
196 | * Map GPIO line to IRQ number. | ||
197 | */ | ||
198 | int 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 | } | ||
205 | EXPORT_SYMBOL(gpio_to_irq); | ||
206 | |||
207 | |||
208 | /* | ||
209 | * Map IRQ number to GPIO line. | ||
210 | */ | ||
211 | int 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 | } | ||
218 | EXPORT_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 | ||
17 | struct clk { | 16 | struct clk { |
18 | struct list_head node; | 17 | struct list_head node; |
@@ -25,21 +24,21 @@ struct clk { | |||
25 | }; | 24 | }; |
26 | 25 | ||
27 | static LIST_HEAD(clocks); | 26 | static LIST_HEAD(clocks); |
28 | static DECLARE_MUTEX(clocks_sem); | 27 | static DEFINE_MUTEX(clocks_mutex); |
29 | static DEFINE_SPINLOCK(clocks_lock); | 28 | static DEFINE_SPINLOCK(clocks_lock); |
30 | 29 | ||
31 | struct clk *clk_get(struct device *dev, const char *id) | 30 | struct 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 | ||
102 | int clk_register(struct clk *clk) | 101 | int 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 | } |
109 | EXPORT_SYMBOL(clk_register); | 108 | EXPORT_SYMBOL(clk_register); |
110 | 109 | ||
111 | void clk_unregister(struct clk *clk) | 110 | void 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 | } |
117 | EXPORT_SYMBOL(clk_unregister); | 116 | EXPORT_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, |
374 | MACHINE_END | 375 | MACHINE_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, |
386 | MACHINE_END | 387 | MACHINE_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, |
398 | MACHINE_END | 399 | MACHINE_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 @@ | |||
1 | extern struct platform_device pxamci_device; | ||
2 | extern struct platform_device pxaudc_device; | ||
3 | extern struct platform_device pxafb_device; | ||
4 | extern struct platform_device ffuart_device; | ||
5 | extern struct platform_device btuart_device; | ||
6 | extern struct platform_device stuart_device; | ||
7 | extern struct platform_device hwuart_device; | ||
8 | extern struct platform_device pxai2c_device; | ||
9 | extern struct platform_device pxai2s_device; | ||
10 | extern struct platform_device pxaficp_device; | ||
11 | extern 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 | ||
28 | static struct dma_channel { | 28 | struct 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 | ||
35 | static struct dma_channel *dma_channels; | ||
36 | static int num_dma_channels; | ||
34 | 37 | ||
35 | int pxa_request_dma (char *name, pxa_dma_prio prio, | 38 | int 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 | ||
112 | static int __init pxa_dma_init (void) | 116 | int __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 | ||
122 | arch_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 | ||
124 | EXPORT_SYMBOL(pxa_request_dma); | 143 | EXPORT_SYMBOL(pxa_request_dma); |
125 | EXPORT_SYMBOL(pxa_free_dma); | 144 | EXPORT_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 | ||
243 | static u64 pxamci_dmamask = 0xffffffffUL; | 244 | static u64 pxamci_dmamask = 0xffffffffUL; |
244 | 245 | ||
245 | static struct platform_device pxamci_device = { | 246 | struct 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 | ||
282 | static u64 udc_dma_mask = ~(u32)0; | 283 | static u64 udc_dma_mask = ~(u32)0; |
283 | 284 | ||
284 | static struct platform_device udc_device = { | 285 | struct 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 | ||
308 | static u64 fb_dma_mask = ~(u64)0; | 309 | static u64 fb_dma_mask = ~(u64)0; |
309 | 310 | ||
310 | static struct platform_device pxafb_device = { | 311 | struct 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 | ||
331 | static struct platform_device ffuart_device = { | 332 | struct platform_device ffuart_device = { |
332 | .name = "pxa2xx-uart", | 333 | .name = "pxa2xx-uart", |
333 | .id = 0, | 334 | .id = 0, |
334 | }; | 335 | }; |
335 | static struct platform_device btuart_device = { | 336 | struct platform_device btuart_device = { |
336 | .name = "pxa2xx-uart", | 337 | .name = "pxa2xx-uart", |
337 | .id = 1, | 338 | .id = 1, |
338 | }; | 339 | }; |
339 | static struct platform_device stuart_device = { | 340 | struct platform_device stuart_device = { |
340 | .name = "pxa2xx-uart", | 341 | .name = "pxa2xx-uart", |
341 | .id = 2, | 342 | .id = 2, |
342 | }; | 343 | }; |
343 | static struct platform_device hwuart_device = { | 344 | struct platform_device hwuart_device = { |
344 | .name = "pxa2xx-uart", | 345 | .name = "pxa2xx-uart", |
345 | .id = 3, | 346 | .id = 3, |
346 | }; | 347 | }; |
347 | 348 | ||
348 | static struct resource i2c_resources[] = { | 349 | static 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 | ||
360 | static struct platform_device i2c_device = { | 361 | struct 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 | ||
368 | static 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 | |||
380 | static 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 | |||
388 | void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info) | 368 | void __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 | ||
393 | static struct resource i2s_resources[] = { | 373 | static 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 | ||
405 | static struct platform_device i2s_device = { | 385 | struct 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 | ||
412 | static u64 pxaficp_dmamask = ~(u32)0; | 392 | static u64 pxaficp_dmamask = ~(u32)0; |
413 | 393 | ||
414 | static struct platform_device pxaficp_device = { | 394 | struct 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 | ||
428 | static struct platform_device pxartc_device = { | 408 | struct platform_device pxartc_device = { |
429 | .name = "sa1100-rtc", | 409 | .name = "sa1100-rtc", |
430 | .id = -1, | 410 | .id = -1, |
431 | }; | 411 | }; |
432 | |||
433 | static 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 | |||
449 | static 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 | |||
466 | subsys_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 @@ | |||
12 | struct sys_timer; | 12 | struct sys_timer; |
13 | 13 | ||
14 | extern struct sys_timer pxa_timer; | 14 | extern struct sys_timer pxa_timer; |
15 | extern void __init pxa_init_irq_low(void); | ||
16 | extern void __init pxa_init_irq_high(void); | ||
17 | extern void __init pxa_init_irq_gpio(int gpio_nr); | ||
18 | extern void __init pxa25x_init_irq(void); | ||
19 | extern void __init pxa27x_init_irq(void); | ||
15 | extern void __init pxa_map_io(void); | 20 | extern void __init pxa_map_io(void); |
16 | extern void __init pxa_init_irq(void); | ||
17 | 21 | ||
18 | extern unsigned int get_clk_frequency_khz(int info); | 22 | extern 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) | |||
152 | static void __init idp_init_irq(void) | 153 | static 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 | ||
31 | static void pxa_mask_low_irq(unsigned int irq) | 31 | static 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 | ||
36 | static void pxa_unmask_low_irq(unsigned int irq) | 36 | static 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 | ||
41 | static int pxa_set_wake(unsigned int irq, unsigned int on) | 41 | static 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 | 70 | void __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 | ||
76 | static void pxa_mask_high_irq(unsigned int irq) | 96 | static 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 | ||
81 | static void pxa_unmask_high_irq(unsigned int irq) | 101 | static 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 | ||
86 | static struct irq_chip pxa_internal_chip_high = { | 106 | static 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 | ||
113 | void __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 | 348 | void __init pxa_init_irq_gpio(int gpio_nr) | |
318 | void __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 | ||
51 | static unsigned int lpd270_irq_enabled; | 52 | static 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 | ||
51 | static unsigned long mainstone_irq_enabled; | 52 | static 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 | */ | ||
207 | int 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 | |||
214 | EXPORT_SYMBOL_GPL(pxa_pm_prepare); | ||
215 | |||
216 | /* | ||
217 | * Called after devices are re-setup, but before processes are thawed. | ||
218 | */ | ||
219 | int pxa_pm_finish(suspend_state_t state) | ||
220 | { | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | EXPORT_SYMBOL_GPL(pxa_pm_finish); | ||
225 | |||
226 | static 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 | |||
233 | static int __init pxa_pm_init(void) | ||
234 | { | ||
235 | pm_set_ops(&pxa_pm_ops); | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | device_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 | ||
50 | static struct resource poodle_scoop_resources[] = { | 51 | static 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, |
418 | MACHINE_END | 419 | MACHINE_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 | ||
108 | int 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 | |||
120 | void pxa_cpu_pm_enter(suspend_state_t state) | 113 | void 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 | ||
129 | static struct pm_ops pxa25x_pm_ops = { | ||
130 | .enter = pxa_pm_enter, | ||
131 | .valid = pm_valid_only_mem, | ||
132 | }; | ||
133 | #endif | ||
134 | |||
135 | void __init pxa25x_init_irq(void) | ||
136 | { | ||
137 | pxa_init_irq_low(); | ||
138 | pxa_init_irq_gpio(85); | ||
139 | } | ||
140 | |||
141 | static 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 | |||
154 | static 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 | |||
174 | subsys_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 | ||
125 | int 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 | |||
136 | void pxa_cpu_pm_enter(suspend_state_t state) | 129 | void 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 | ||
158 | static int pxa27x_pm_valid(suspend_state_t state) | ||
159 | { | ||
160 | return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY; | ||
161 | } | ||
162 | |||
163 | static 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 | ||
186 | static struct platform_device ohci_device = { | 188 | static 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 | ||
197 | void __init pxa_set_ohci_info(struct pxaohci_platform_data *info) | 199 | void __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 | ||
204 | static 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 | |||
216 | static 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 | |||
202 | static struct platform_device *devices[] __initdata = { | 223 | static 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 | ||
238 | void __init pxa27x_init_irq(void) | ||
239 | { | ||
240 | pxa_init_irq_low(); | ||
241 | pxa_init_irq_high(); | ||
242 | pxa_init_irq_gpio(128); | ||
243 | } | ||
244 | |||
206 | static int __init pxa27x_init(void) | 245 | static 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 | ||
211 | subsys_initcall(pxa27x_init); | 259 | subsys_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, |
566 | MACHINE_END | 567 | MACHINE_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, |
578 | MACHINE_END | 579 | MACHINE_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, |
590 | MACHINE_END | 591 | MACHINE_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 | ||
33 | static inline unsigned long pxa_get_rtc_time(void) | ||
34 | { | ||
35 | return RCNR; | ||
36 | } | ||
37 | |||
38 | static int pxa_set_rtc(void) | 33 | static 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, |
338 | MACHINE_END | 338 | MACHINE_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, |
508 | MACHINE_END | 509 | MACHINE_END |
509 | 510 | ||
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, | |||
57 | static int sa11x0_pm_enter(suspend_state_t state) | 57 | static 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 | ||
24 | static 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 | |||
43 | static int sa1100_set_rtc(void) | 24 | static 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 | ||
118 | static void __init sa1100_timer_init(void) | 99 | static 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 | } |
335 | EXPORT_SYMBOL(__arm_ioremap); | 333 | EXPORT_SYMBOL(__arm_ioremap); |