diff options
Diffstat (limited to 'arch/arm/mach-lh7a40x/arch-lpd7a40x.c')
-rw-r--r-- | arch/arm/mach-lh7a40x/arch-lpd7a40x.c | 286 |
1 files changed, 286 insertions, 0 deletions
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 | |||
26 | static 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 | |||
41 | static struct platform_device smc91x_device = { | ||
42 | .name = "smc91x", | ||
43 | .id = 0, | ||
44 | .num_resources = ARRAY_SIZE(smc91x_resources), | ||
45 | .resource = smc91x_resources, | ||
46 | }; | ||
47 | |||
48 | static 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 | |||
61 | static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL; | ||
62 | |||
63 | static 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 | |||
76 | static 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 | |||
89 | static u64 lh7a404_usbhost_dma_mask = 0xffffffffUL; | ||
90 | |||
91 | static 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 | |||
104 | static 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 | |||
112 | extern void lpd7a400_map_io (void); | ||
113 | |||
114 | static 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 | |||
125 | static void lh7a40x_ack_cpld_irq (u32 irq) | ||
126 | { | ||
127 | /* CPLD doesn't have ack capability */ | ||
128 | } | ||
129 | |||
130 | static 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 | |||
142 | static 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 | |||
154 | static 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 | |||
160 | static 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 | |||
177 | void __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 | |||
229 | static 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 | |||
249 | void __init | ||
250 | lpd7a400_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 | |||
262 | MACHINE_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) | ||
270 | MACHINE_END | ||
271 | |||
272 | #endif | ||
273 | |||
274 | #ifdef CONFIG_MACH_LPD7A404 | ||
275 | |||
276 | MACHINE_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) | ||
284 | MACHINE_END | ||
285 | |||
286 | #endif | ||