aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-lh7a40x
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-lh7a40x')
-rw-r--r--arch/arm/mach-lh7a40x/Kconfig70
-rw-r--r--arch/arm/mach-lh7a40x/Makefile14
-rw-r--r--arch/arm/mach-lh7a40x/Makefile.boot4
-rw-r--r--arch/arm/mach-lh7a40x/arch-kev7a400.c111
-rw-r--r--arch/arm/mach-lh7a40x/arch-lpd7a40x.c286
-rw-r--r--arch/arm/mach-lh7a40x/common.h16
-rw-r--r--arch/arm/mach-lh7a40x/irq-kev7a400.c92
-rw-r--r--arch/arm/mach-lh7a40x/irq-lh7a400.c90
-rw-r--r--arch/arm/mach-lh7a40x/irq-lh7a404.c158
-rw-r--r--arch/arm/mach-lh7a40x/irq-lpd7a40x.c128
-rw-r--r--arch/arm/mach-lh7a40x/time.c75
11 files changed, 1044 insertions, 0 deletions
diff --git a/arch/arm/mach-lh7a40x/Kconfig b/arch/arm/mach-lh7a40x/Kconfig
new file mode 100644
index 000000000000..8a17867a6a24
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/Kconfig
@@ -0,0 +1,70 @@
1if ARCH_LH7A40X
2
3menu "LH7A40X Implementations"
4
5config MACH_KEV7A400
6 bool "KEV7A400"
7 select ARCH_LH7A400
8 help
9 Say Y here if you are using the Sharp KEV7A400 development
10 board. This hardware is discontinued, so I'd be very
11 suprised if you wanted this option.
12
13config MACH_LPD7A400
14 bool "LPD7A400 Card Engine"
15 select ARCH_LH7A400
16# select IDE_POLL
17 help
18 Say Y here if you are using Logic Product Development's
19 LPD7A400 CardEngine. For the time being, the LPD7A400 and
20 LPD7A404 options are mutually exclusive.
21
22config MACH_LPD7A404
23 bool "LPD7A404 Card Engine"
24 select ARCH_LH7A404
25# select IDE_POLL
26 help
27 Say Y here if you are using Logic Product Development's
28 LPD7A404 CardEngine. For the time being, the LPD7A400 and
29 LPD7A404 options are mutually exclusive.
30
31config ARCH_LH7A400
32 bool
33
34config ARCH_LH7A404
35 bool
36
37config LH7A40X_CONTIGMEM
38 bool "Disable NUMA Support"
39 depends on ARCH_LH7A40X
40 help
41 Say Y here if your bootloader sets the SROMLL bit(s) in
42 the SDRAM controller, organizing memory as a contiguous
43 array. This option will disable CONFIG_DISCONTIGMEM and
44 force the kernel to manage all memory in one node.
45
46 Setting this option incorrectly may prevent the kernel from
47 booting. It is OK to leave it N.
48
49 For more information, consult
50 <file:Documentation/arm/Sharp-LH/SDRAM>.
51
52config LH7A40X_ONE_BANK_PER_NODE
53 bool "Optimize NUMA Node Tables for Size"
54 depends on ARCH_LH7A40X && !LH7A40X_CONTIGMEM
55 help
56 Say Y here to produce compact memory node tables. By
57 default pairs of adjacent physical RAM banks are managed
58 together in a single node, incurring some wasted overhead
59 in the node tables, however also maintaining compatibility
60 with systems where physical memory is truly contiguous.
61
62 Setting this option incorrectly may prevent the kernel from
63 booting. It is OK to leave it N.
64
65 For more information, consult
66 <file:Documentation/arm/Sharp-LH/SDRAM>.
67
68endmenu
69
70endif
diff --git a/arch/arm/mach-lh7a40x/Makefile b/arch/arm/mach-lh7a40x/Makefile
new file mode 100644
index 000000000000..e90512dbc2d6
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/Makefile
@@ -0,0 +1,14 @@
1#
2# Makefile for the linux kernel.
3#
4
5# Object file lists.
6
7obj-y := time.o
8obj-$(CONFIG_MACH_KEV7A400) += arch-kev7a400.o irq-lh7a400.o
9obj-$(CONFIG_MACH_LPD7A400) += arch-lpd7a40x.o irq-lh7a400.o
10obj-$(CONFIG_MACH_LPD7A404) += arch-lpd7a40x.o irq-lh7a404.o
11
12obj-m :=
13obj-n :=
14obj- :=
diff --git a/arch/arm/mach-lh7a40x/Makefile.boot b/arch/arm/mach-lh7a40x/Makefile.boot
new file mode 100644
index 000000000000..af941be076eb
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/Makefile.boot
@@ -0,0 +1,4 @@
1 zreladdr-y := 0xc0008000
2params_phys-y := 0xc0000100
3initrd_phys-y := 0xc4000000
4
diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
new file mode 100644
index 000000000000..be5d17fe9dcb
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c
@@ -0,0 +1,111 @@
1/* arch/arm/mach-lh7a40x/arch-kev7a400.c
2 *
3 * Copyright (C) 2004 Logic Product Development
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/tty.h>
12#include <linux/init.h>
13#include <linux/device.h>
14#include <linux/interrupt.h>
15
16#include <asm/hardware.h>
17#include <asm/setup.h>
18#include <asm/mach-types.h>
19#include <asm/mach/arch.h>
20#include <asm/irq.h>
21#include <asm/mach/irq.h>
22#include <asm/mach/map.h>
23
24#include "common.h"
25
26 /* This function calls the board specific IRQ initialization function. */
27
28static struct map_desc kev7a400_io_desc[] __initdata = {
29 { IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE },
30 { CPLD_VIRT, CPLD_PHYS, CPLD_SIZE, MT_DEVICE },
31};
32
33void __init kev7a400_map_io(void)
34{
35 iotable_init (kev7a400_io_desc, ARRAY_SIZE (kev7a400_io_desc));
36}
37
38static u16 CPLD_IRQ_mask; /* Mask for CPLD IRQs, 1 == unmasked */
39
40static void kev7a400_ack_cpld_irq (u32 irq)
41{
42 CPLD_CL_INT = 1 << (irq - IRQ_KEV7A400_CPLD);
43}
44
45static void kev7a400_mask_cpld_irq (u32 irq)
46{
47 CPLD_IRQ_mask &= ~(1 << (irq - IRQ_KEV7A400_CPLD));
48 CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
49}
50
51static void kev7a400_unmask_cpld_irq (u32 irq)
52{
53 CPLD_IRQ_mask |= 1 << (irq - IRQ_KEV7A400_CPLD);
54 CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
55}
56
57static struct irqchip kev7a400_cpld_chip = {
58 .ack = kev7a400_ack_cpld_irq,
59 .mask = kev7a400_mask_cpld_irq,
60 .unmask = kev7a400_unmask_cpld_irq,
61};
62
63
64static void kev7a400_cpld_handler (unsigned int irq, struct irqdesc *desc,
65 struct pt_regs *regs)
66{
67 u32 mask = CPLD_LATCHED_INTS;
68 irq = IRQ_KEV7A400_CPLD;
69 for (; mask; mask >>= 1, ++irq) {
70 if (mask & 1)
71 desc[irq].handle (irq, desc, regs);
72 }
73}
74
75void __init lh7a40x_init_board_irq (void)
76{
77 int irq;
78
79 for (irq = IRQ_KEV7A400_CPLD;
80 irq < IRQ_KEV7A400_CPLD + NR_IRQ_BOARD; ++irq) {
81 set_irq_chip (irq, &kev7a400_cpld_chip);
82 set_irq_handler (irq, do_edge_IRQ);
83 set_irq_flags (irq, IRQF_VALID);
84 }
85 set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler);
86
87 /* Clear all CPLD interrupts */
88 CPLD_CL_INT = 0xff; /* CPLD_INTR_MMC_CD | CPLD_INTR_ETH_INT; */
89
90 GPIO_GPIOINTEN = 0; /* Disable all GPIO interrupts */
91 barrier();
92
93#if 0
94 GPIO_INTTYPE1
95 = (GPIO_INTR_PCC1_CD | GPIO_INTR_PCC1_CD); /* Edge trig. */
96 GPIO_INTTYPE2 = 0; /* Falling edge & low-level */
97 GPIO_GPIOFEOI = 0xff; /* Clear all GPIO interrupts */
98 GPIO_GPIOINTEN = 0xff; /* Enable all GPIO interrupts */
99
100 init_FIQ();
101#endif
102}
103
104MACHINE_START (KEV7A400, "Sharp KEV7a400")
105 MAINTAINER ("Marc Singer")
106 BOOT_MEM (0xc0000000, 0x80000000, io_p2v (0x80000000))
107 BOOT_PARAMS (0xc0000100)
108 MAPIO (kev7a400_map_io)
109 INITIRQ (lh7a400_init_irq)
110 .timer = &lh7a40x_timer,
111MACHINE_END
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
new file mode 100644
index 000000000000..c823447a150f
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -0,0 +1,286 @@
1/* arch/arm/mach-lh7a40x/arch-lpd7a40x.c
2 *
3 * Copyright (C) 2004 Logic Product Development
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/tty.h>
12#include <linux/init.h>
13#include <linux/device.h>
14#include <linux/interrupt.h>
15
16#include <asm/hardware.h>
17#include <asm/setup.h>
18#include <asm/mach-types.h>
19#include <asm/mach/arch.h>
20#include <asm/irq.h>
21#include <asm/mach/irq.h>
22#include <asm/mach/map.h>
23
24#include "common.h"
25
26static struct resource smc91x_resources[] = {
27 [0] = {
28 .start = CPLD00_PHYS,
29 .end = CPLD00_PHYS + CPLD00_SIZE - 1, /* Only needs 16B */
30 .flags = IORESOURCE_MEM,
31 },
32
33 [1] = {
34 .start = IRQ_LPD7A40X_ETH_INT,
35 .end = IRQ_LPD7A40X_ETH_INT,
36 .flags = IORESOURCE_IRQ,
37 },
38
39};
40
41static struct platform_device smc91x_device = {
42 .name = "smc91x",
43 .id = 0,
44 .num_resources = ARRAY_SIZE(smc91x_resources),
45 .resource = smc91x_resources,
46};
47
48static struct resource lh7a40x_usbclient_resources[] = {
49 [0] = {
50 .start = USB_PHYS,
51 .end = (USB_PHYS + 0xFF),
52 .flags = IORESOURCE_MEM,
53 },
54 [1] = {
55 .start = IRQ_USBINTR,
56 .end = IRQ_USBINTR,
57 .flags = IORESOURCE_IRQ,
58 },
59};
60
61static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL;
62
63static struct platform_device lh7a40x_usbclient_device = {
64 .name = "lh7a40x_udc",
65 .id = 0,
66 .dev = {
67 .dma_mask = &lh7a40x_usbclient_dma_mask,
68 .coherent_dma_mask = 0xffffffffUL,
69 },
70 .num_resources = ARRAY_SIZE (lh7a40x_usbclient_resources),
71 .resource = lh7a40x_usbclient_resources,
72};
73
74#if defined (CONFIG_ARCH_LH7A404)
75
76static struct resource lh7a404_usbhost_resources [] = {
77 [0] = {
78 .start = USBH_PHYS,
79 .end = (USBH_PHYS + 0xFF),
80 .flags = IORESOURCE_MEM,
81 },
82 [1] = {
83 .start = IRQ_USHINTR,
84 .end = IRQ_USHINTR,
85 .flags = IORESOURCE_IRQ,
86 },
87};
88
89static u64 lh7a404_usbhost_dma_mask = 0xffffffffUL;
90
91static struct platform_device lh7a404_usbhost_device = {
92 .name = "lh7a404-ohci",
93 .id = 0,
94 .dev = {
95 .dma_mask = &lh7a404_usbhost_dma_mask,
96 .coherent_dma_mask = 0xffffffffUL,
97 },
98 .num_resources = ARRAY_SIZE (lh7a404_usbhost_resources),
99 .resource = lh7a404_usbhost_resources,
100};
101
102#endif
103
104static struct platform_device *lpd7a40x_devs[] __initdata = {
105 &smc91x_device,
106 &lh7a40x_usbclient_device,
107#if defined (CONFIG_ARCH_LH7A404)
108 &lh7a404_usbhost_device,
109#endif
110};
111
112extern void lpd7a400_map_io (void);
113
114static void __init lpd7a40x_init (void)
115{
116 CPLD_CONTROL |= (1<<6); /* Mask USB1 connection IRQ */
117 CPLD_CONTROL &= ~(0
118 | (1<<1) /* Disable LCD */
119 | (1<<0) /* Enable WLAN */
120 );
121
122 platform_add_devices (lpd7a40x_devs, ARRAY_SIZE (lpd7a40x_devs));
123}
124
125static void lh7a40x_ack_cpld_irq (u32 irq)
126{
127 /* CPLD doesn't have ack capability */
128}
129
130static void lh7a40x_mask_cpld_irq (u32 irq)
131{
132 switch (irq) {
133 case IRQ_LPD7A40X_ETH_INT:
134 CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4;
135 break;
136 case IRQ_LPD7A400_TS:
137 CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8;
138 break;
139 }
140}
141
142static void lh7a40x_unmask_cpld_irq (u32 irq)
143{
144 switch (irq) {
145 case IRQ_LPD7A40X_ETH_INT:
146 CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4;
147 break;
148 case IRQ_LPD7A400_TS:
149 CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8;
150 break;
151 }
152}
153
154static struct irqchip lpd7a40x_cpld_chip = {
155 .ack = lh7a40x_ack_cpld_irq,
156 .mask = lh7a40x_mask_cpld_irq,
157 .unmask = lh7a40x_unmask_cpld_irq,
158};
159
160static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
161 struct pt_regs *regs)
162{
163 unsigned int mask = CPLD_INTERRUPTS;
164
165 desc->chip->ack (irq);
166
167 if ((mask & 0x1) == 0) /* WLAN */
168 IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT);
169
170 if ((mask & 0x2) == 0) /* Touch */
171 IRQ_DISPATCH (IRQ_LPD7A400_TS);
172
173 desc->chip->unmask (irq); /* Level-triggered need this */
174}
175
176
177void __init lh7a40x_init_board_irq (void)
178{
179 int irq;
180
181 /* Rev A (v2.8): PF0, PF1, PF2, and PF3 are available IRQs.
182 PF7 supports the CPLD.
183 Rev B (v3.4): PF0, PF1, and PF2 are available IRQs.
184 PF3 supports the CPLD.
185 (Some) LPD7A404 prerelease boards report a version
186 number of 0x16, but we force an override since the
187 hardware is of the newer variety.
188 */
189
190 unsigned char cpld_version = CPLD_REVISION;
191 int pinCPLD = (cpld_version == 0x28) ? 7 : 3;
192
193#if defined CONFIG_MACH_LPD7A404
194 cpld_version = 0x34; /* Coerce LPD7A404 to RevB */
195#endif
196
197 /* First, configure user controlled GPIOF interrupts */
198
199 GPIO_PFDD &= ~0x0f; /* PF0-3 are inputs */
200 GPIO_INTTYPE1 &= ~0x0f; /* PF0-3 are level triggered */
201 GPIO_INTTYPE2 &= ~0x0f; /* PF0-3 are active low */
202 barrier ();
203 GPIO_GPIOFINTEN |= 0x0f; /* Enable PF0, PF1, PF2, and PF3 IRQs */
204
205 /* Then, configure CPLD interrupt */
206
207 CPLD_INTERRUPTS = 0x9c; /* Disable all CPLD interrupts */
208 GPIO_PFDD &= ~(1 << pinCPLD); /* Make input */
209 GPIO_INTTYPE1 |= (1 << pinCPLD); /* Edge triggered */
210 GPIO_INTTYPE2 &= ~(1 << pinCPLD); /* Active low */
211 barrier ();
212 GPIO_GPIOFINTEN |= (1 << pinCPLD); /* Enable */
213
214 /* Cascade CPLD interrupts */
215
216 for (irq = IRQ_BOARD_START;
217 irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
218 set_irq_chip (irq, &lpd7a40x_cpld_chip);
219 set_irq_handler (irq, do_edge_IRQ);
220 set_irq_flags (irq, IRQF_VALID);
221 }
222
223 set_irq_chained_handler ((cpld_version == 0x28)
224 ? IRQ_CPLD_V28
225 : IRQ_CPLD_V34,
226 lpd7a40x_cpld_handler);
227}
228
229static struct map_desc lpd7a400_io_desc[] __initdata = {
230 { IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE },
231 /* Mapping added to work around chip select problems */
232 { IOBARRIER_VIRT, IOBARRIER_PHYS, IOBARRIER_SIZE, MT_DEVICE },
233 { CF_VIRT, CF_PHYS, CF_SIZE, MT_DEVICE },
234 /* This mapping is redundant since the smc driver performs another. */
235/* { CPLD00_VIRT, CPLD00_PHYS, CPLD00_SIZE, MT_DEVICE }, */
236 { CPLD02_VIRT, CPLD02_PHYS, CPLD02_SIZE, MT_DEVICE },
237 { CPLD06_VIRT, CPLD06_PHYS, CPLD06_SIZE, MT_DEVICE },
238 { CPLD08_VIRT, CPLD08_PHYS, CPLD08_SIZE, MT_DEVICE },
239 { CPLD0C_VIRT, CPLD0C_PHYS, CPLD0C_SIZE, MT_DEVICE },
240 { CPLD0E_VIRT, CPLD0E_PHYS, CPLD0E_SIZE, MT_DEVICE },
241 { CPLD10_VIRT, CPLD10_PHYS, CPLD10_SIZE, MT_DEVICE },
242 { CPLD12_VIRT, CPLD12_PHYS, CPLD12_SIZE, MT_DEVICE },
243 { CPLD14_VIRT, CPLD14_PHYS, CPLD14_SIZE, MT_DEVICE },
244 { CPLD16_VIRT, CPLD16_PHYS, CPLD16_SIZE, MT_DEVICE },
245 { CPLD18_VIRT, CPLD18_PHYS, CPLD18_SIZE, MT_DEVICE },
246 { CPLD1A_VIRT, CPLD1A_PHYS, CPLD1A_SIZE, MT_DEVICE },
247};
248
249void __init
250lpd7a400_map_io(void)
251{
252 iotable_init (lpd7a400_io_desc, ARRAY_SIZE (lpd7a400_io_desc));
253
254 /* Fixup (improve) Static Memory Controller settings */
255 SMC_BCR0 = 0x200039af; /* Boot Flash */
256 SMC_BCR6 = 0x1000fbe0; /* CPLD */
257 SMC_BCR7 = 0x1000b2c2; /* Compact Flash */
258}
259
260#ifdef CONFIG_MACH_LPD7A400
261
262MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
263 MAINTAINER ("Marc Singer")
264 BOOT_MEM (0xc0000000, 0x80000000, io_p2v (0x80000000))
265 BOOT_PARAMS (0xc0000100)
266 MAPIO (lpd7a400_map_io)
267 INITIRQ (lh7a400_init_irq)
268 .timer = &lh7a40x_timer,
269 INIT_MACHINE (lpd7a40x_init)
270MACHINE_END
271
272#endif
273
274#ifdef CONFIG_MACH_LPD7A404
275
276MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
277 MAINTAINER ("Marc Singer")
278 BOOT_MEM (0xc0000000, 0x80000000, io_p2v (0x80000000))
279 BOOT_PARAMS (0xc0000100)
280 MAPIO (lpd7a400_map_io)
281 INITIRQ (lh7a404_init_irq)
282 .timer = &lh7a40x_timer,
283 INIT_MACHINE (lpd7a40x_init)
284MACHINE_END
285
286#endif
diff --git a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h
new file mode 100644
index 000000000000..beda7c2602fb
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/common.h
@@ -0,0 +1,16 @@
1/* arch/arm/mach-lh7a40x/common.h
2 *
3 * Copyright (C) 2004 Marc Singer
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 */
10
11extern struct sys_timer lh7a40x_timer;
12
13extern void lh7a400_init_irq (void);
14extern void lh7a404_init_irq (void);
15
16#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs)
diff --git a/arch/arm/mach-lh7a40x/irq-kev7a400.c b/arch/arm/mach-lh7a40x/irq-kev7a400.c
new file mode 100644
index 000000000000..691bb09232a5
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/irq-kev7a400.c
@@ -0,0 +1,92 @@
1/* arch/arm/mach-lh7a40x/irq-kev7a400.c
2 *
3 * Copyright (C) 2004 Coastal Environmental Systems
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/interrupt.h>
12#include <linux/init.h>
13
14#include <asm/irq.h>
15#include <asm/mach/irq.h>
16#include <asm/mach/hardware.h>
17#include <asm/mach/irqs.h>
18
19
20 /* KEV7a400 CPLD IRQ handling */
21
22static u16 CPLD_IRQ_mask; /* Mask for CPLD IRQs, 1 == unmasked */
23
24static void
25lh7a400_ack_cpld_irq (u32 irq)
26{
27 CPLD_CL_INT = 1 << (irq - IRQ_KEV7A400_CPLD);
28}
29
30static void
31lh7a400_mask_cpld_irq (u32 irq)
32{
33 CPLD_IRQ_mask &= ~(1 << (irq - IRQ_KEV7A400_CPLD));
34 CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
35}
36
37static void
38lh7a400_unmask_cpld_irq (u32 irq)
39{
40 CPLD_IRQ_mask |= 1 << (irq - IRQ_KEV7A400_CPLD);
41 CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
42}
43
44static struct
45irqchip lh7a400_cpld_chip = {
46 .ack = lh7a400_ack_cpld_irq,
47 .mask = lh7a400_mask_cpld_irq,
48 .unmask = lh7a400_unmask_cpld_irq,
49};
50
51static void
52lh7a400_cpld_handler (unsigned int irq, struct irqdesc *desc,
53 struct pt_regs *regs)
54{
55 u32 mask = CPLD_LATCHED_INTS;
56 irq = IRQ_KEV_7A400_CPLD;
57 for (; mask; mask >>= 1, ++irq) {
58 if (mask & 1)
59 desc[irq].handle (irq, desc, regs);
60 }
61}
62
63 /* IRQ initialization */
64
65void __init
66lh7a400_init_board_irq (void)
67{
68 int irq;
69
70 for (irq = IRQ_KEV7A400_CPLD;
71 irq < IRQ_KEV7A400_CPLD + NR_IRQ_KEV7A400_CPLD; ++irq) {
72 set_irq_chip (irq, &lh7a400_cpld_chip);
73 set_irq_handler (irq, do_edge_IRQ);
74 set_irq_flags (irq, IRQF_VALID);
75 }
76 set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler);
77
78 /* Clear all CPLD interrupts */
79 CPLD_CL_INT = 0xff; /* CPLD_INTR_MMC_CD | CPLD_INTR_ETH_INT; */
80
81 /* *** FIXME CF enabled in ide-probe.c */
82
83 GPIO_GPIOINTEN = 0; /* Disable all GPIO interrupts */
84 barrier();
85 GPIO_INTTYPE1
86 = (GPIO_INTR_PCC1_CD | GPIO_INTR_PCC1_CD); /* Edge trig. */
87 GPIO_INTTYPE2 = 0; /* Falling edge & low-level */
88 GPIO_GPIOFEOI = 0xff; /* Clear all GPIO interrupts */
89 GPIO_GPIOINTEN = 0xff; /* Enable all GPIO interrupts */
90
91 init_FIQ();
92}
diff --git a/arch/arm/mach-lh7a40x/irq-lh7a400.c b/arch/arm/mach-lh7a40x/irq-lh7a400.c
new file mode 100644
index 000000000000..f334d81c2cd8
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/irq-lh7a400.c
@@ -0,0 +1,90 @@
1/* arch/arm/mach-lh7a40x/irq-lh7a400.c
2 *
3 * Copyright (C) 2004 Coastal Environmental Systems
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/init.h>
12#include <linux/module.h>
13#include <linux/interrupt.h>
14#include <linux/ptrace.h>
15
16#include <asm/hardware.h>
17#include <asm/irq.h>
18#include <asm/mach/irq.h>
19#include <asm/arch/irq.h>
20#include <asm/arch/irqs.h>
21
22
23 /* CPU IRQ handling */
24
25static void lh7a400_mask_irq (u32 irq)
26{
27 INTC_INTENC = (1 << irq);
28}
29
30static void lh7a400_unmask_irq (u32 irq)
31{
32 INTC_INTENS = (1 << irq);
33}
34
35static void lh7a400_ack_gpio_irq (u32 irq)
36{
37 GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (irq));
38 INTC_INTENC = (1 << irq);
39}
40
41static struct irqchip lh7a400_internal_chip = {
42 .ack = lh7a400_mask_irq, /* Level triggering -> mask is ack */
43 .mask = lh7a400_mask_irq,
44 .unmask = lh7a400_unmask_irq,
45};
46
47static struct irqchip lh7a400_gpio_chip = {
48 .ack = lh7a400_ack_gpio_irq,
49 .mask = lh7a400_mask_irq,
50 .unmask = lh7a400_unmask_irq,
51};
52
53
54 /* IRQ initialization */
55
56void __init lh7a400_init_irq (void)
57{
58 int irq;
59
60 INTC_INTENC = 0xffffffff; /* Disable all interrupts */
61 GPIO_GPIOFINTEN = 0x00; /* Disable all GPIOF interrupts */
62 barrier ();
63
64 for (irq = 0; irq < NR_IRQS; ++irq) {
65 switch (irq) {
66 case IRQ_GPIO0INTR:
67 case IRQ_GPIO1INTR:
68 case IRQ_GPIO2INTR:
69 case IRQ_GPIO3INTR:
70 case IRQ_GPIO4INTR:
71 case IRQ_GPIO5INTR:
72 case IRQ_GPIO6INTR:
73 case IRQ_GPIO7INTR:
74 set_irq_chip (irq, &lh7a400_gpio_chip);
75 set_irq_handler (irq, do_level_IRQ); /* OK default */
76 break;
77 default:
78 set_irq_chip (irq, &lh7a400_internal_chip);
79 set_irq_handler (irq, do_level_IRQ);
80 }
81 set_irq_flags (irq, IRQF_VALID);
82 }
83
84 lh7a40x_init_board_irq ();
85
86/* *** FIXME: the LH7a400 does use FIQ interrupts in some cases. For
87 the time being, these are not initialized. */
88
89/* init_FIQ(); */
90}
diff --git a/arch/arm/mach-lh7a40x/irq-lh7a404.c b/arch/arm/mach-lh7a40x/irq-lh7a404.c
new file mode 100644
index 000000000000..122fadabc97d
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/irq-lh7a404.c
@@ -0,0 +1,158 @@
1/* arch/arm/mach-lh7a40x/irq-lh7a404.c
2 *
3 * Copyright (C) 2004 Logic Product Development
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/init.h>
12#include <linux/module.h>
13#include <linux/interrupt.h>
14#include <linux/ptrace.h>
15
16#include <asm/hardware.h>
17#include <asm/irq.h>
18#include <asm/mach/irq.h>
19#include <asm/arch/irq.h>
20#include <asm/arch/irqs.h>
21
22#define USE_PRIORITIES
23
24/* See Documentation/arm/Sharp-LH/VectoredInterruptController for more
25 * information on using the vectored interrupt controller's
26 * prioritizing feature. */
27
28static unsigned char irq_pri_vic1[] = {
29#if defined (USE_PRIORITIES)
30IRQ_GPIO3INTR,
31#endif
32};
33static unsigned char irq_pri_vic2[] = {
34#if defined (USE_PRIORITIES)
35 IRQ_T3UI, IRQ_GPIO7INTR,
36 IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR,
37#endif
38};
39
40 /* CPU IRQ handling */
41
42static void lh7a404_vic1_mask_irq (u32 irq)
43{
44 VIC1_INTENCLR = (1 << irq);
45}
46
47static void lh7a404_vic1_unmask_irq (u32 irq)
48{
49 VIC1_INTEN = (1 << irq);
50}
51
52static void lh7a404_vic2_mask_irq (u32 irq)
53{
54 VIC2_INTENCLR = (1 << (irq - 32));
55}
56
57static void lh7a404_vic2_unmask_irq (u32 irq)
58{
59 VIC2_INTEN = (1 << (irq - 32));
60}
61
62static void lh7a404_vic1_ack_gpio_irq (u32 irq)
63{
64 GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (irq));
65 VIC1_INTENCLR = (1 << irq);
66}
67
68static void lh7a404_vic2_ack_gpio_irq (u32 irq)
69{
70 GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (irq));
71 VIC2_INTENCLR = (1 << irq);
72}
73
74static struct irqchip lh7a404_vic1_chip = {
75 .ack = lh7a404_vic1_mask_irq, /* Because level-triggered */
76 .mask = lh7a404_vic1_mask_irq,
77 .unmask = lh7a404_vic1_unmask_irq,
78};
79
80static struct irqchip lh7a404_vic2_chip = {
81 .ack = lh7a404_vic2_mask_irq, /* Because level-triggered */
82 .mask = lh7a404_vic2_mask_irq,
83 .unmask = lh7a404_vic2_unmask_irq,
84};
85
86static struct irqchip lh7a404_gpio_vic1_chip = {
87 .ack = lh7a404_vic1_ack_gpio_irq,
88 .mask = lh7a404_vic1_mask_irq,
89 .unmask = lh7a404_vic1_unmask_irq,
90};
91
92static struct irqchip lh7a404_gpio_vic2_chip = {
93 .ack = lh7a404_vic2_ack_gpio_irq,
94 .mask = lh7a404_vic2_mask_irq,
95 .unmask = lh7a404_vic2_unmask_irq,
96};
97
98 /* IRQ initialization */
99
100void __init lh7a404_init_irq (void)
101{
102 int irq;
103
104 VIC1_INTENCLR = 0xffffffff;
105 VIC2_INTENCLR = 0xffffffff;
106 VIC1_INTSEL = 0; /* All IRQs */
107 VIC2_INTSEL = 0; /* All IRQs */
108 VIC1_NVADDR = VA_VIC1DEFAULT;
109 VIC2_NVADDR = VA_VIC2DEFAULT;
110 VIC1_VECTADDR = 0;
111 VIC2_VECTADDR = 0;
112
113 GPIO_GPIOFINTEN = 0x00; /* Disable all GPIOF interrupts */
114 barrier ();
115
116 /* Install prioritized interrupts, if there are any. */
117 /* The | 0x20*/
118 for (irq = 0; irq < 16; ++irq) {
119 (&VIC1_VAD0)[irq]
120 = (irq < ARRAY_SIZE (irq_pri_vic1))
121 ? (irq_pri_vic1[irq] | VA_VECTORED) : 0;
122 (&VIC1_VECTCNTL0)[irq]
123 = (irq < ARRAY_SIZE (irq_pri_vic1))
124 ? (irq_pri_vic1[irq] | VIC_CNTL_ENABLE) : 0;
125 (&VIC2_VAD0)[irq]
126 = (irq < ARRAY_SIZE (irq_pri_vic2))
127 ? (irq_pri_vic2[irq] | VA_VECTORED) : 0;
128 (&VIC2_VECTCNTL0)[irq]
129 = (irq < ARRAY_SIZE (irq_pri_vic2))
130 ? (irq_pri_vic2[irq] | VIC_CNTL_ENABLE) : 0;
131 }
132
133 for (irq = 0; irq < NR_IRQS; ++irq) {
134 switch (irq) {
135 case IRQ_GPIO0INTR:
136 case IRQ_GPIO1INTR:
137 case IRQ_GPIO2INTR:
138 case IRQ_GPIO3INTR:
139 case IRQ_GPIO4INTR:
140 case IRQ_GPIO5INTR:
141 case IRQ_GPIO6INTR:
142 case IRQ_GPIO7INTR:
143 set_irq_chip (irq, irq < 32
144 ? &lh7a404_gpio_vic1_chip
145 : &lh7a404_gpio_vic2_chip);
146 set_irq_handler (irq, do_level_IRQ); /* OK default */
147 break;
148 default:
149 set_irq_chip (irq, irq < 32
150 ? &lh7a404_vic1_chip
151 : &lh7a404_vic2_chip);
152 set_irq_handler (irq, do_level_IRQ);
153 }
154 set_irq_flags (irq, IRQF_VALID);
155 }
156
157 lh7a40x_init_board_irq ();
158}
diff --git a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
new file mode 100644
index 000000000000..6262d449120c
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
@@ -0,0 +1,128 @@
1/* arch/arm/mach-lh7a40x/irq-lpd7a40x.c
2 *
3 * Copyright (C) 2004 Coastal Environmental Systems
4 * Copyright (C) 2004 Logic Product Development
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/interrupt.h>
15#include <linux/ptrace.h>
16
17#include <asm/hardware.h>
18#include <asm/irq.h>
19#include <asm/mach/irq.h>
20#include <asm/arch/irqs.h>
21
22
23static void lh7a40x_ack_cpld_irq (u32 irq)
24{
25 /* CPLD doesn't have ack capability */
26}
27
28static void lh7a40x_mask_cpld_irq (u32 irq)
29{
30 switch (irq) {
31 case IRQ_LPD7A40X_ETH_INT:
32 CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4;
33 break;
34 case IRQ_LPD7A400_TS:
35 CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8;
36 break;
37 }
38}
39
40static void lh7a40x_unmask_cpld_irq (u32 irq)
41{
42 switch (irq) {
43 case IRQ_LPD7A40X_ETH_INT:
44 CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4;
45 break;
46 case IRQ_LPD7A400_TS:
47 CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8;
48 break;
49 }
50}
51
52static struct irqchip lh7a40x_cpld_chip = {
53 .ack = lh7a40x_ack_cpld_irq,
54 .mask = lh7a40x_mask_cpld_irq,
55 .unmask = lh7a40x_unmask_cpld_irq,
56};
57
58static void lh7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
59 struct pt_regs *regs)
60{
61 unsigned int mask = CPLD_INTERRUPTS;
62
63 desc->chip->ack (irq);
64
65 if ((mask & 0x1) == 0) /* WLAN */
66 IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT);
67
68 if ((mask & 0x2) == 0) /* Touch */
69 IRQ_DISPATCH (IRQ_LPD7A400_TS);
70
71 desc->chip->unmask (irq); /* Level-triggered need this */
72}
73
74
75 /* IRQ initialization */
76
77void __init lh7a40x_init_board_irq (void)
78{
79 int irq;
80
81 /* Rev A (v2.8): PF0, PF1, PF2, and PF3 are available IRQs.
82 PF7 supports the CPLD.
83 Rev B (v3.4): PF0, PF1, and PF2 are available IRQs.
84 PF3 supports the CPLD.
85 (Some) LPD7A404 prerelease boards report a version
86 number of 0x16, but we force an override since the
87 hardware is of the newer variety.
88 */
89
90 unsigned char cpld_version = CPLD_REVISION;
91 int pinCPLD;
92
93#if defined CONFIG_MACH_LPD7A404
94 cpld_version = 0x34; /* Override, for now */
95#endif
96 pinCPLD = (cpld_version == 0x28) ? 7 : 3;
97
98 /* First, configure user controlled GPIOF interrupts */
99
100 GPIO_PFDD &= ~0x0f; /* PF0-3 are inputs */
101 GPIO_INTTYPE1 &= ~0x0f; /* PF0-3 are level triggered */
102 GPIO_INTTYPE2 &= ~0x0f; /* PF0-3 are active low */
103 barrier ();
104 GPIO_GPIOFINTEN |= 0x0f; /* Enable PF0, PF1, PF2, and PF3 IRQs */
105
106 /* Then, configure CPLD interrupt */
107
108 CPLD_INTERRUPTS = 0x0c; /* Disable all CPLD interrupts */
109 GPIO_PFDD &= ~(1 << pinCPLD); /* Make input */
110 GPIO_INTTYPE1 |= (1 << pinCPLD); /* Edge triggered */
111 GPIO_INTTYPE2 &= ~(1 << pinCPLD); /* Active low */
112 barrier ();
113 GPIO_GPIOFINTEN |= (1 << pinCPLD); /* Enable */
114
115 /* Cascade CPLD interrupts */
116
117 for (irq = IRQ_BOARD_START;
118 irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
119 set_irq_chip (irq, &lh7a40x_cpld_chip);
120 set_irq_handler (irq, do_edge_IRQ);
121 set_irq_flags (irq, IRQF_VALID);
122 }
123
124 set_irq_chained_handler ((cpld_version == 0x28)
125 ? IRQ_CPLD_V28
126 : IRQ_CPLD_V34,
127 lh7a40x_cpld_handler);
128}
diff --git a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c
new file mode 100644
index 000000000000..51e1c814b400
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/time.c
@@ -0,0 +1,75 @@
1/*
2 * arch/arm/mach-lh7a40x/time.c
3 *
4 * Copyright (C) 2004 Logic Product Development
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 */
11#include <linux/config.h>
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/time.h>
16
17#include <asm/hardware.h>
18#include <asm/io.h>
19#include <asm/irq.h>
20#include <asm/leds.h>
21
22#include <asm/mach/time.h>
23#include "common.h"
24
25#if HZ < 100
26# define TIMER_CONTROL TIMER_CONTROL2
27# define TIMER_LOAD TIMER_LOAD2
28# define TIMER_CONSTANT (508469/HZ)
29# define TIMER_MODE (TIMER_C_ENABLE | TIMER_C_PERIODIC | TIMER_C_508KHZ)
30# define TIMER_EOI TIMER_EOI2
31# define TIMER_IRQ IRQ_T2UI
32#else
33# define TIMER_CONTROL TIMER_CONTROL3
34# define TIMER_LOAD TIMER_LOAD3
35# define TIMER_CONSTANT (3686400/HZ)
36# define TIMER_MODE (TIMER_C_ENABLE | TIMER_C_PERIODIC)
37# define TIMER_EOI TIMER_EOI3
38# define TIMER_IRQ IRQ_T3UI
39#endif
40
41static irqreturn_t
42lh7a40x_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
43{
44 write_seqlock(&xtime_lock);
45
46 TIMER_EOI = 0;
47 timer_tick(regs);
48
49 write_sequnlock(&xtime_lock);
50
51 return IRQ_HANDLED;
52}
53
54static struct irqaction lh7a40x_timer_irq = {
55 .name = "LHA740x Timer Tick",
56 .flags = SA_INTERRUPT,
57 .handler = lh7a40x_timer_interrupt
58};
59
60static void __init lh7a40x_timer_init(void)
61{
62 /* Stop/disable all timers */
63 TIMER_CONTROL1 = 0;
64 TIMER_CONTROL2 = 0;
65 TIMER_CONTROL3 = 0;
66
67 setup_irq (TIMER_IRQ, &lh7a40x_timer_irq);
68
69 TIMER_LOAD = TIMER_CONSTANT;
70 TIMER_CONTROL = TIMER_MODE;
71}
72
73struct sys_timer lh7a40x_timer = {
74 .init = &lh7a40x_timer_init,
75};