Commit | Line | Data |
---|---|---|
2a23ec36 JM |
1 | /* |
2 | * linux/arch/arm/mach-pxa/balloon3.c | |
3 | * | |
4 | * Support for Balloonboard.org Balloon3 board. | |
5 | * | |
6 | * Author: Nick Bane, Wookey, Jonathan McDowell | |
7 | * Created: June, 2006 | |
8 | * Copyright: Toby Churchill Ltd | |
9 | * Derived from mainstone.c, by Nico Pitre | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or modify | |
12 | * it under the terms of the GNU General Public License version 2 as | |
13 | * published by the Free Software Foundation. | |
14 | */ | |
15 | ||
61cbaa92 | 16 | #include <linux/export.h> |
2a23ec36 JM |
17 | #include <linux/init.h> |
18 | #include <linux/platform_device.h> | |
2a23ec36 | 19 | #include <linux/interrupt.h> |
40d727a2 | 20 | #include <linux/leds.h> |
2a23ec36 JM |
21 | #include <linux/sched.h> |
22 | #include <linux/bitops.h> | |
23 | #include <linux/fb.h> | |
24 | #include <linux/gpio.h> | |
25 | #include <linux/ioport.h> | |
12a2449c | 26 | #include <linux/ucb1400.h> |
2a23ec36 | 27 | #include <linux/mtd/mtd.h> |
2a23ec36 | 28 | #include <linux/types.h> |
b6480fae | 29 | #include <linux/platform_data/pcf857x.h> |
f15fc9b1 | 30 | #include <linux/platform_data/i2c-pxa.h> |
c7921bb3 | 31 | #include <linux/mtd/platnand.h> |
e6a8ef54 | 32 | #include <linux/mtd/physmap.h> |
3a27f6e0 | 33 | #include <linux/regulator/max1586.h> |
2a23ec36 JM |
34 | |
35 | #include <asm/setup.h> | |
36 | #include <asm/mach-types.h> | |
37 | #include <asm/irq.h> | |
38 | #include <asm/sizes.h> | |
39 | ||
40 | #include <asm/mach/arch.h> | |
41 | #include <asm/mach/map.h> | |
42 | #include <asm/mach/irq.h> | |
43 | #include <asm/mach/flash.h> | |
44 | ||
4c25c5d2 | 45 | #include "pxa27x.h" |
2a23ec36 JM |
46 | #include <mach/balloon3.h> |
47 | #include <mach/audio.h> | |
293b2da1 AB |
48 | #include <linux/platform_data/video-pxafb.h> |
49 | #include <linux/platform_data/mmc-pxamci.h> | |
4c25c5d2 AB |
50 | #include "udc.h" |
51 | #include "pxa27x-udc.h" | |
293b2da1 AB |
52 | #include <linux/platform_data/irda-pxaficp.h> |
53 | #include <linux/platform_data/usb-ohci-pxa27x.h> | |
2a23ec36 | 54 | |
2a23ec36 JM |
55 | #include "generic.h" |
56 | #include "devices.h" | |
57 | ||
b0240bf4 MV |
58 | /****************************************************************************** |
59 | * Pin configuration | |
60 | ******************************************************************************/ | |
61 | static unsigned long balloon3_pin_config[] __initdata = { | |
62 | /* Select BTUART 'COM1/ttyS0' as IO option for pins 42/43/44/45 */ | |
63 | GPIO42_BTUART_RXD, | |
64 | GPIO43_BTUART_TXD, | |
65 | GPIO44_BTUART_CTS, | |
66 | GPIO45_BTUART_RTS, | |
2a23ec36 | 67 | |
12a2449c | 68 | /* Reset, configured as GPIO wakeup source */ |
b0240bf4 | 69 | GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH, |
c11b6a42 EM |
70 | }; |
71 | ||
b0240bf4 | 72 | /****************************************************************************** |
12a2449c | 73 | * Compatibility: Parameter parsing |
b0240bf4 | 74 | ******************************************************************************/ |
12a2449c | 75 | static unsigned long balloon3_irq_enabled; |
b0240bf4 | 76 | |
12a2449c MV |
77 | static unsigned long balloon3_features_present = |
78 | (1 << BALLOON3_FEATURE_OHCI) | (1 << BALLOON3_FEATURE_CF) | | |
79 | (1 << BALLOON3_FEATURE_AUDIO) | | |
80 | (1 << BALLOON3_FEATURE_TOPPOLY); | |
81 | ||
82 | int balloon3_has(enum balloon3_features feature) | |
2a23ec36 | 83 | { |
12a2449c MV |
84 | return (balloon3_features_present & (1 << feature)) ? 1 : 0; |
85 | } | |
86 | EXPORT_SYMBOL_GPL(balloon3_has); | |
87 | ||
88 | int __init parse_balloon3_features(char *arg) | |
89 | { | |
90 | if (!arg) | |
91 | return 0; | |
92 | ||
4fce45b4 | 93 | return kstrtoul(arg, 0, &balloon3_features_present); |
2a23ec36 | 94 | } |
12a2449c | 95 | early_param("balloon3_features", parse_balloon3_features); |
2a23ec36 | 96 | |
b476ef05 MV |
97 | /****************************************************************************** |
98 | * Compact Flash slot | |
99 | ******************************************************************************/ | |
100 | #if defined(CONFIG_PCMCIA_PXA2XX) || defined(CONFIG_PCMCIA_PXA2XX_MODULE) | |
101 | static unsigned long balloon3_cf_pin_config[] __initdata = { | |
102 | GPIO48_nPOE, | |
103 | GPIO49_nPWE, | |
104 | GPIO50_nPIOR, | |
105 | GPIO51_nPIOW, | |
106 | GPIO85_nPCE_1, | |
107 | GPIO54_nPCE_2, | |
108 | GPIO79_PSKTSEL, | |
109 | GPIO55_nPREG, | |
110 | GPIO56_nPWAIT, | |
111 | GPIO57_nIOIS16, | |
112 | }; | |
113 | ||
114 | static void __init balloon3_cf_init(void) | |
115 | { | |
116 | if (!balloon3_has(BALLOON3_FEATURE_CF)) | |
117 | return; | |
118 | ||
119 | pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_cf_pin_config)); | |
120 | } | |
121 | #else | |
122 | static inline void balloon3_cf_init(void) {} | |
123 | #endif | |
124 | ||
12a2449c MV |
125 | /****************************************************************************** |
126 | * NOR Flash | |
127 | ******************************************************************************/ | |
128 | #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) | |
129 | static struct mtd_partition balloon3_nor_partitions[] = { | |
130 | { | |
131 | .name = "Flash", | |
132 | .offset = 0x00000000, | |
133 | .size = MTDPART_SIZ_FULL, | |
134 | } | |
135 | }; | |
136 | ||
137 | static struct physmap_flash_data balloon3_flash_data[] = { | |
138 | { | |
139 | .width = 2, /* bankwidth in bytes */ | |
140 | .parts = balloon3_nor_partitions, | |
141 | .nr_parts = ARRAY_SIZE(balloon3_nor_partitions) | |
142 | } | |
143 | }; | |
144 | ||
145 | static struct resource balloon3_flash_resource = { | |
146 | .start = PXA_CS0_PHYS, | |
147 | .end = PXA_CS0_PHYS + SZ_64M - 1, | |
148 | .flags = IORESOURCE_MEM, | |
149 | }; | |
150 | ||
151 | static struct platform_device balloon3_flash = { | |
152 | .name = "physmap-flash", | |
153 | .id = 0, | |
154 | .resource = &balloon3_flash_resource, | |
155 | .num_resources = 1, | |
156 | .dev = { | |
157 | .platform_data = balloon3_flash_data, | |
158 | }, | |
159 | }; | |
160 | static void __init balloon3_nor_init(void) | |
161 | { | |
162 | platform_device_register(&balloon3_flash); | |
163 | } | |
164 | #else | |
165 | static inline void balloon3_nor_init(void) {} | |
166 | #endif | |
167 | ||
168 | /****************************************************************************** | |
169 | * Audio and Touchscreen | |
170 | ******************************************************************************/ | |
171 | #if defined(CONFIG_TOUCHSCREEN_UCB1400) || \ | |
172 | defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE) | |
b476ef05 MV |
173 | static unsigned long balloon3_ac97_pin_config[] __initdata = { |
174 | GPIO28_AC97_BITCLK, | |
175 | GPIO29_AC97_SDATA_IN_0, | |
176 | GPIO30_AC97_SDATA_OUT, | |
177 | GPIO31_AC97_SYNC, | |
178 | GPIO113_AC97_nRESET, | |
179 | GPIO95_GPIO, | |
180 | }; | |
181 | ||
12a2449c | 182 | static struct ucb1400_pdata vpac270_ucb1400_pdata = { |
6384fdad | 183 | .irq = PXA_GPIO_TO_IRQ(BALLOON3_GPIO_CODEC_IRQ), |
12a2449c MV |
184 | }; |
185 | ||
186 | ||
187 | static struct platform_device balloon3_ucb1400_device = { | |
188 | .name = "ucb1400_core", | |
189 | .id = -1, | |
190 | .dev = { | |
191 | .platform_data = &vpac270_ucb1400_pdata, | |
192 | }, | |
193 | }; | |
194 | ||
195 | static void __init balloon3_ts_init(void) | |
196 | { | |
197 | if (!balloon3_has(BALLOON3_FEATURE_AUDIO)) | |
198 | return; | |
199 | ||
b476ef05 | 200 | pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_ac97_pin_config)); |
12a2449c MV |
201 | pxa_set_ac97_info(NULL); |
202 | platform_device_register(&balloon3_ucb1400_device); | |
203 | } | |
204 | #else | |
205 | static inline void balloon3_ts_init(void) {} | |
206 | #endif | |
207 | ||
208 | /****************************************************************************** | |
209 | * Framebuffer | |
210 | ******************************************************************************/ | |
211 | #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) | |
b476ef05 MV |
212 | static unsigned long balloon3_lcd_pin_config[] __initdata = { |
213 | GPIOxx_LCD_TFT_16BPP, | |
214 | GPIO99_GPIO, | |
215 | }; | |
216 | ||
2a23ec36 JM |
217 | static struct pxafb_mode_info balloon3_lcd_modes[] = { |
218 | { | |
219 | .pixclock = 38000, | |
220 | .xres = 480, | |
221 | .yres = 640, | |
222 | .bpp = 16, | |
223 | .hsync_len = 8, | |
224 | .left_margin = 8, | |
225 | .right_margin = 8, | |
226 | .vsync_len = 2, | |
227 | .upper_margin = 4, | |
228 | .lower_margin = 5, | |
229 | .sync = 0, | |
230 | }, | |
231 | }; | |
232 | ||
12a2449c | 233 | static struct pxafb_mach_info balloon3_lcd_screen = { |
2a23ec36 JM |
234 | .modes = balloon3_lcd_modes, |
235 | .num_modes = ARRAY_SIZE(balloon3_lcd_modes), | |
236 | .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL, | |
2a23ec36 JM |
237 | }; |
238 | ||
12a2449c MV |
239 | static void balloon3_backlight_power(int on) |
240 | { | |
241 | gpio_set_value(BALLOON3_GPIO_RUN_BACKLIGHT, on); | |
242 | } | |
2a23ec36 | 243 | |
12a2449c | 244 | static void __init balloon3_lcd_init(void) |
2a23ec36 | 245 | { |
12a2449c MV |
246 | int ret; |
247 | ||
248 | if (!balloon3_has(BALLOON3_FEATURE_TOPPOLY)) | |
249 | return; | |
250 | ||
b476ef05 MV |
251 | pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_lcd_pin_config)); |
252 | ||
12a2449c MV |
253 | ret = gpio_request(BALLOON3_GPIO_RUN_BACKLIGHT, "BKL-ON"); |
254 | if (ret) { | |
255 | pr_err("Requesting BKL-ON GPIO failed!\n"); | |
256 | goto err; | |
257 | } | |
258 | ||
259 | ret = gpio_direction_output(BALLOON3_GPIO_RUN_BACKLIGHT, 1); | |
260 | if (ret) { | |
261 | pr_err("Setting BKL-ON GPIO direction failed!\n"); | |
262 | goto err2; | |
2a23ec36 | 263 | } |
12a2449c MV |
264 | |
265 | balloon3_lcd_screen.pxafb_backlight_power = balloon3_backlight_power; | |
4321e1a1 | 266 | pxa_set_fb_info(NULL, &balloon3_lcd_screen); |
12a2449c MV |
267 | return; |
268 | ||
269 | err2: | |
270 | gpio_free(BALLOON3_GPIO_RUN_BACKLIGHT); | |
271 | err: | |
272 | return; | |
2a23ec36 | 273 | } |
12a2449c MV |
274 | #else |
275 | static inline void balloon3_lcd_init(void) {} | |
276 | #endif | |
2a23ec36 | 277 | |
12a2449c MV |
278 | /****************************************************************************** |
279 | * SD/MMC card controller | |
280 | ******************************************************************************/ | |
281 | #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) | |
b476ef05 MV |
282 | static unsigned long balloon3_mmc_pin_config[] __initdata = { |
283 | GPIO32_MMC_CLK, | |
284 | GPIO92_MMC_DAT_0, | |
285 | GPIO109_MMC_DAT_1, | |
286 | GPIO110_MMC_DAT_2, | |
287 | GPIO111_MMC_DAT_3, | |
288 | GPIO112_MMC_CMD, | |
289 | }; | |
290 | ||
2a23ec36 | 291 | static struct pxamci_platform_data balloon3_mci_platform_data = { |
12a2449c | 292 | .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, |
12a2449c | 293 | .detect_delay_ms = 200, |
2a23ec36 JM |
294 | }; |
295 | ||
12a2449c MV |
296 | static void __init balloon3_mmc_init(void) |
297 | { | |
b476ef05 | 298 | pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_mmc_pin_config)); |
12a2449c MV |
299 | pxa_set_mci_info(&balloon3_mci_platform_data); |
300 | } | |
301 | #else | |
302 | static inline void balloon3_mmc_init(void) {} | |
303 | #endif | |
304 | ||
b0240bf4 MV |
305 | /****************************************************************************** |
306 | * USB Gadget | |
307 | ******************************************************************************/ | |
c0a39151 | 308 | #if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE) |
12a2449c | 309 | static void balloon3_udc_command(int cmd) |
2a23ec36 | 310 | { |
12a2449c MV |
311 | if (cmd == PXA2XX_UDC_CMD_CONNECT) |
312 | UP2OCR |= UP2OCR_DPPUE | UP2OCR_DPPUBE; | |
313 | else if (cmd == PXA2XX_UDC_CMD_DISCONNECT) | |
314 | UP2OCR &= ~UP2OCR_DPPUE; | |
2a23ec36 JM |
315 | } |
316 | ||
12a2449c | 317 | static int balloon3_udc_is_connected(void) |
2a23ec36 | 318 | { |
12a2449c | 319 | return 1; |
2a23ec36 JM |
320 | } |
321 | ||
12a2449c MV |
322 | static struct pxa2xx_udc_mach_info balloon3_udc_info __initdata = { |
323 | .udc_command = balloon3_udc_command, | |
324 | .udc_is_connected = balloon3_udc_is_connected, | |
325 | .gpio_pullup = -1, | |
2a23ec36 JM |
326 | }; |
327 | ||
12a2449c MV |
328 | static void __init balloon3_udc_init(void) |
329 | { | |
330 | pxa_set_udc_info(&balloon3_udc_info); | |
12a2449c MV |
331 | } |
332 | #else | |
333 | static inline void balloon3_udc_init(void) {} | |
334 | #endif | |
335 | ||
b0240bf4 MV |
336 | /****************************************************************************** |
337 | * IrDA | |
338 | ******************************************************************************/ | |
12a2449c | 339 | #if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE) |
2a23ec36 | 340 | static struct pxaficp_platform_data balloon3_ficp_platform_data = { |
12a2449c | 341 | .transceiver_cap = IR_FIRMODE | IR_SIRMODE | IR_OFF, |
2a23ec36 JM |
342 | }; |
343 | ||
12a2449c MV |
344 | static void __init balloon3_irda_init(void) |
345 | { | |
346 | pxa_set_ficp_info(&balloon3_ficp_platform_data); | |
347 | } | |
348 | #else | |
349 | static inline void balloon3_irda_init(void) {} | |
350 | #endif | |
351 | ||
b0240bf4 MV |
352 | /****************************************************************************** |
353 | * USB Host | |
354 | ******************************************************************************/ | |
12a2449c | 355 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) |
b476ef05 MV |
356 | static unsigned long balloon3_uhc_pin_config[] __initdata = { |
357 | GPIO88_USBH1_PWR, | |
358 | GPIO89_USBH1_PEN, | |
359 | }; | |
360 | ||
12a2449c | 361 | static struct pxaohci_platform_data balloon3_ohci_info = { |
2a23ec36 JM |
362 | .port_mode = PMM_PERPORT_MODE, |
363 | .flags = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW, | |
364 | }; | |
365 | ||
12a2449c MV |
366 | static void __init balloon3_uhc_init(void) |
367 | { | |
368 | if (!balloon3_has(BALLOON3_FEATURE_OHCI)) | |
369 | return; | |
b476ef05 | 370 | pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_uhc_pin_config)); |
12a2449c MV |
371 | pxa_set_ohci_info(&balloon3_ohci_info); |
372 | } | |
373 | #else | |
374 | static inline void balloon3_uhc_init(void) {} | |
375 | #endif | |
376 | ||
b0240bf4 | 377 | /****************************************************************************** |
12a2449c | 378 | * LEDs |
b0240bf4 | 379 | ******************************************************************************/ |
12a2449c | 380 | #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) |
b476ef05 MV |
381 | static unsigned long balloon3_led_pin_config[] __initdata = { |
382 | GPIO9_GPIO, /* NAND activity LED */ | |
383 | GPIO10_GPIO, /* Heartbeat LED */ | |
384 | }; | |
385 | ||
12a2449c | 386 | struct gpio_led balloon3_gpio_leds[] = { |
2a23ec36 JM |
387 | { |
388 | .name = "balloon3:green:idle", | |
389 | .default_trigger = "heartbeat", | |
390 | .gpio = BALLOON3_GPIO_LED_IDLE, | |
391 | .active_low = 1, | |
12a2449c | 392 | }, { |
2a23ec36 JM |
393 | .name = "balloon3:green:nand", |
394 | .default_trigger = "nand-disk", | |
395 | .gpio = BALLOON3_GPIO_LED_NAND, | |
396 | .active_low = 1, | |
397 | }, | |
398 | }; | |
399 | ||
12a2449c | 400 | static struct gpio_led_platform_data balloon3_gpio_led_info = { |
2a23ec36 JM |
401 | .leds = balloon3_gpio_leds, |
402 | .num_leds = ARRAY_SIZE(balloon3_gpio_leds), | |
403 | }; | |
404 | ||
12a2449c | 405 | static struct platform_device balloon3_leds = { |
2a23ec36 | 406 | .name = "leds-gpio", |
02a453e4 | 407 | .id = 0, |
2a23ec36 | 408 | .dev = { |
12a2449c MV |
409 | .platform_data = &balloon3_gpio_led_info, |
410 | } | |
2a23ec36 JM |
411 | }; |
412 | ||
02a453e4 MV |
413 | struct gpio_led balloon3_pcf_gpio_leds[] = { |
414 | { | |
415 | .name = "balloon3:green:led0", | |
416 | .gpio = BALLOON3_PCF_GPIO_LED0, | |
417 | .active_low = 1, | |
418 | }, { | |
419 | .name = "balloon3:green:led1", | |
420 | .gpio = BALLOON3_PCF_GPIO_LED1, | |
421 | .active_low = 1, | |
422 | }, { | |
423 | .name = "balloon3:orange:led2", | |
424 | .gpio = BALLOON3_PCF_GPIO_LED2, | |
425 | .active_low = 1, | |
426 | }, { | |
427 | .name = "balloon3:orange:led3", | |
428 | .gpio = BALLOON3_PCF_GPIO_LED3, | |
429 | .active_low = 1, | |
430 | }, { | |
431 | .name = "balloon3:orange:led4", | |
432 | .gpio = BALLOON3_PCF_GPIO_LED4, | |
433 | .active_low = 1, | |
434 | }, { | |
435 | .name = "balloon3:orange:led5", | |
436 | .gpio = BALLOON3_PCF_GPIO_LED5, | |
437 | .active_low = 1, | |
438 | }, { | |
439 | .name = "balloon3:red:led6", | |
440 | .gpio = BALLOON3_PCF_GPIO_LED6, | |
441 | .active_low = 1, | |
442 | }, { | |
443 | .name = "balloon3:red:led7", | |
444 | .gpio = BALLOON3_PCF_GPIO_LED7, | |
445 | .active_low = 1, | |
446 | }, | |
447 | }; | |
448 | ||
449 | static struct gpio_led_platform_data balloon3_pcf_gpio_led_info = { | |
450 | .leds = balloon3_pcf_gpio_leds, | |
451 | .num_leds = ARRAY_SIZE(balloon3_pcf_gpio_leds), | |
452 | }; | |
453 | ||
454 | static struct platform_device balloon3_pcf_leds = { | |
455 | .name = "leds-gpio", | |
456 | .id = 1, | |
457 | .dev = { | |
458 | .platform_data = &balloon3_pcf_gpio_led_info, | |
459 | } | |
460 | }; | |
461 | ||
12a2449c | 462 | static void __init balloon3_leds_init(void) |
b0240bf4 | 463 | { |
b476ef05 | 464 | pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_led_pin_config)); |
12a2449c | 465 | platform_device_register(&balloon3_leds); |
02a453e4 | 466 | platform_device_register(&balloon3_pcf_leds); |
b0240bf4 | 467 | } |
12a2449c MV |
468 | #else |
469 | static inline void balloon3_leds_init(void) {} | |
470 | #endif | |
b0240bf4 MV |
471 | |
472 | /****************************************************************************** | |
473 | * FPGA IRQ | |
474 | ******************************************************************************/ | |
a3f4c927 | 475 | static void balloon3_mask_irq(struct irq_data *d) |
b0240bf4 | 476 | { |
a3f4c927 | 477 | int balloon3_irq = (d->irq - BALLOON3_IRQ(0)); |
b0240bf4 MV |
478 | balloon3_irq_enabled &= ~(1 << balloon3_irq); |
479 | __raw_writel(~balloon3_irq_enabled, BALLOON3_INT_CONTROL_REG); | |
480 | } | |
481 | ||
a3f4c927 | 482 | static void balloon3_unmask_irq(struct irq_data *d) |
b0240bf4 | 483 | { |
a3f4c927 | 484 | int balloon3_irq = (d->irq - BALLOON3_IRQ(0)); |
b0240bf4 MV |
485 | balloon3_irq_enabled |= (1 << balloon3_irq); |
486 | __raw_writel(~balloon3_irq_enabled, BALLOON3_INT_CONTROL_REG); | |
487 | } | |
488 | ||
489 | static struct irq_chip balloon3_irq_chip = { | |
490 | .name = "FPGA", | |
a3f4c927 LB |
491 | .irq_ack = balloon3_mask_irq, |
492 | .irq_mask = balloon3_mask_irq, | |
493 | .irq_unmask = balloon3_unmask_irq, | |
b0240bf4 MV |
494 | }; |
495 | ||
bd0b9ac4 | 496 | static void balloon3_irq_handler(struct irq_desc *desc) |
b0240bf4 MV |
497 | { |
498 | unsigned long pending = __raw_readl(BALLOON3_INT_CONTROL_REG) & | |
499 | balloon3_irq_enabled; | |
b0240bf4 | 500 | do { |
9ec97561 | 501 | struct irq_data *d = irq_desc_get_irq_data(desc); |
385877c0 | 502 | struct irq_chip *chip = irq_desc_get_chip(desc); |
9ec97561 | 503 | unsigned int irq; |
a3f4c927 | 504 | |
9ec97561 TG |
505 | /* clear useless edge notification */ |
506 | if (chip->irq_ack) | |
507 | chip->irq_ack(d); | |
a3f4c927 | 508 | |
b0240bf4 MV |
509 | while (pending) { |
510 | irq = BALLOON3_IRQ(0) + __ffs(pending); | |
511 | generic_handle_irq(irq); | |
512 | pending &= pending - 1; | |
513 | } | |
514 | pending = __raw_readl(BALLOON3_INT_CONTROL_REG) & | |
515 | balloon3_irq_enabled; | |
516 | } while (pending); | |
517 | } | |
518 | ||
519 | static void __init balloon3_init_irq(void) | |
520 | { | |
521 | int irq; | |
522 | ||
523 | pxa27x_init_irq(); | |
524 | /* setup extra Balloon3 irqs */ | |
525 | for (irq = BALLOON3_IRQ(0); irq <= BALLOON3_IRQ(7); irq++) { | |
f38c02f3 TG |
526 | irq_set_chip_and_handler(irq, &balloon3_irq_chip, |
527 | handle_level_irq); | |
e8d36d5d | 528 | irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); |
b0240bf4 MV |
529 | } |
530 | ||
6845664a TG |
531 | irq_set_chained_handler(BALLOON3_AUX_NIRQ, balloon3_irq_handler); |
532 | irq_set_irq_type(BALLOON3_AUX_NIRQ, IRQ_TYPE_EDGE_FALLING); | |
b0240bf4 MV |
533 | |
534 | pr_debug("%s: chained handler installed - irq %d automatically " | |
535 | "enabled\n", __func__, BALLOON3_AUX_NIRQ); | |
536 | } | |
537 | ||
02a453e4 MV |
538 | /****************************************************************************** |
539 | * GPIO expander | |
540 | ******************************************************************************/ | |
541 | #if defined(CONFIG_GPIO_PCF857X) || defined(CONFIG_GPIO_PCF857X_MODULE) | |
542 | static struct pcf857x_platform_data balloon3_pcf857x_pdata = { | |
543 | .gpio_base = BALLOON3_PCF_GPIO_BASE, | |
544 | .n_latch = 0, | |
545 | .setup = NULL, | |
546 | .teardown = NULL, | |
547 | .context = NULL, | |
548 | }; | |
549 | ||
550 | static struct i2c_board_info __initdata balloon3_i2c_devs[] = { | |
551 | { | |
552 | I2C_BOARD_INFO("pcf8574a", 0x38), | |
553 | .platform_data = &balloon3_pcf857x_pdata, | |
554 | }, | |
555 | }; | |
556 | ||
557 | static void __init balloon3_i2c_init(void) | |
558 | { | |
559 | pxa_set_i2c_info(NULL); | |
560 | i2c_register_board_info(0, ARRAY_AND_SIZE(balloon3_i2c_devs)); | |
561 | } | |
562 | #else | |
563 | static inline void balloon3_i2c_init(void) {} | |
564 | #endif | |
565 | ||
e6a8ef54 MV |
566 | /****************************************************************************** |
567 | * NAND | |
568 | ******************************************************************************/ | |
569 | #if defined(CONFIG_MTD_NAND_PLATFORM)||defined(CONFIG_MTD_NAND_PLATFORM_MODULE) | |
47bd59e5 BB |
570 | static void balloon3_nand_cmd_ctl(struct nand_chip *this, int cmd, |
571 | unsigned int ctrl) | |
e6a8ef54 | 572 | { |
1b9169d8 | 573 | uint8_t balloon3_ctl_set = 0, balloon3_ctl_clr = 0; |
e6a8ef54 MV |
574 | |
575 | if (ctrl & NAND_CTRL_CHANGE) { | |
576 | if (ctrl & NAND_CLE) | |
1b9169d8 | 577 | balloon3_ctl_set |= BALLOON3_NAND_CONTROL_FLCLE; |
e6a8ef54 | 578 | else |
1b9169d8 | 579 | balloon3_ctl_clr |= BALLOON3_NAND_CONTROL_FLCLE; |
e6a8ef54 MV |
580 | |
581 | if (ctrl & NAND_ALE) | |
1b9169d8 | 582 | balloon3_ctl_set |= BALLOON3_NAND_CONTROL_FLALE; |
e6a8ef54 | 583 | else |
1b9169d8 MV |
584 | balloon3_ctl_clr |= BALLOON3_NAND_CONTROL_FLALE; |
585 | ||
586 | if (balloon3_ctl_clr) | |
587 | __raw_writel(balloon3_ctl_clr, | |
588 | BALLOON3_NAND_CONTROL_REG); | |
589 | if (balloon3_ctl_set) | |
590 | __raw_writel(balloon3_ctl_set, | |
97b09da4 | 591 | BALLOON3_NAND_CONTROL_REG + |
1b9169d8 | 592 | BALLOON3_FPGA_SETnCLR); |
e6a8ef54 MV |
593 | } |
594 | ||
595 | if (cmd != NAND_CMD_NONE) | |
82fc5099 | 596 | writeb(cmd, this->legacy.IO_ADDR_W); |
e6a8ef54 MV |
597 | } |
598 | ||
47bd59e5 | 599 | static void balloon3_nand_select_chip(struct nand_chip *this, int chip) |
e6a8ef54 MV |
600 | { |
601 | if (chip < 0 || chip > 3) | |
602 | return; | |
603 | ||
1b9169d8 MV |
604 | /* Assert all nCE lines */ |
605 | __raw_writew( | |
606 | BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 | | |
607 | BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3, | |
97b09da4 | 608 | BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR); |
e6a8ef54 MV |
609 | |
610 | /* Deassert correct nCE line */ | |
1b9169d8 MV |
611 | __raw_writew(BALLOON3_NAND_CONTROL_FLCE0 << chip, |
612 | BALLOON3_NAND_CONTROL_REG); | |
e6a8ef54 MV |
613 | } |
614 | ||
47bd59e5 | 615 | static int balloon3_nand_dev_ready(struct nand_chip *this) |
59bdd133 MV |
616 | { |
617 | return __raw_readl(BALLOON3_NAND_STAT_REG) & BALLOON3_NAND_STAT_RNB; | |
618 | } | |
619 | ||
e6a8ef54 MV |
620 | static int balloon3_nand_probe(struct platform_device *pdev) |
621 | { | |
e6a8ef54 MV |
622 | uint16_t ver; |
623 | int ret; | |
624 | ||
1b9169d8 | 625 | __raw_writew(BALLOON3_NAND_CONTROL2_16BIT, |
97b09da4 | 626 | BALLOON3_NAND_CONTROL2_REG + BALLOON3_FPGA_SETnCLR); |
e6a8ef54 MV |
627 | |
628 | ver = __raw_readw(BALLOON3_FPGA_VER); | |
1b9169d8 MV |
629 | if (ver < 0x4f08) |
630 | pr_warn("The FPGA code, version 0x%04x, is too old. " | |
e6a8ef54 MV |
631 | "NAND support might be broken in this version!", ver); |
632 | ||
633 | /* Power up the NAND chips */ | |
634 | ret = gpio_request(BALLOON3_GPIO_RUN_NAND, "NAND"); | |
635 | if (ret) | |
636 | goto err1; | |
637 | ||
638 | ret = gpio_direction_output(BALLOON3_GPIO_RUN_NAND, 1); | |
639 | if (ret) | |
640 | goto err2; | |
641 | ||
642 | gpio_set_value(BALLOON3_GPIO_RUN_NAND, 1); | |
643 | ||
644 | /* Deassert all nCE lines and write protect line */ | |
1b9169d8 MV |
645 | __raw_writel( |
646 | BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 | | |
647 | BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3 | | |
648 | BALLOON3_NAND_CONTROL_FLWP, | |
97b09da4 | 649 | BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR); |
e6a8ef54 MV |
650 | return 0; |
651 | ||
652 | err2: | |
653 | gpio_free(BALLOON3_GPIO_RUN_NAND); | |
654 | err1: | |
655 | return ret; | |
656 | } | |
657 | ||
658 | static void balloon3_nand_remove(struct platform_device *pdev) | |
659 | { | |
660 | /* Power down the NAND chips */ | |
661 | gpio_set_value(BALLOON3_GPIO_RUN_NAND, 0); | |
662 | gpio_free(BALLOON3_GPIO_RUN_NAND); | |
663 | } | |
664 | ||
665 | static struct mtd_partition balloon3_partition_info[] = { | |
666 | [0] = { | |
667 | .name = "Boot", | |
668 | .offset = 0, | |
669 | .size = SZ_4M, | |
670 | }, | |
671 | [1] = { | |
672 | .name = "RootFS", | |
673 | .offset = MTDPART_OFS_APPEND, | |
674 | .size = MTDPART_SIZ_FULL | |
675 | }, | |
676 | }; | |
677 | ||
e6a8ef54 MV |
678 | struct platform_nand_data balloon3_nand_pdata = { |
679 | .chip = { | |
680 | .nr_chips = 4, | |
681 | .chip_offset = 0, | |
682 | .nr_partitions = ARRAY_SIZE(balloon3_partition_info), | |
683 | .partitions = balloon3_partition_info, | |
684 | .chip_delay = 50, | |
e6a8ef54 MV |
685 | }, |
686 | .ctrl = { | |
59bdd133 | 687 | .dev_ready = balloon3_nand_dev_ready, |
e6a8ef54 MV |
688 | .select_chip = balloon3_nand_select_chip, |
689 | .cmd_ctrl = balloon3_nand_cmd_ctl, | |
690 | .probe = balloon3_nand_probe, | |
691 | .remove = balloon3_nand_remove, | |
692 | }, | |
693 | }; | |
694 | ||
695 | static struct resource balloon3_nand_resource[] = { | |
696 | [0] = { | |
697 | .start = BALLOON3_NAND_BASE, | |
698 | .end = BALLOON3_NAND_BASE + 0x4, | |
699 | .flags = IORESOURCE_MEM, | |
700 | }, | |
701 | }; | |
702 | ||
703 | static struct platform_device balloon3_nand = { | |
704 | .name = "gen_nand", | |
705 | .num_resources = ARRAY_SIZE(balloon3_nand_resource), | |
706 | .resource = balloon3_nand_resource, | |
707 | .id = -1, | |
708 | .dev = { | |
709 | .platform_data = &balloon3_nand_pdata, | |
710 | } | |
711 | }; | |
712 | ||
713 | static void __init balloon3_nand_init(void) | |
714 | { | |
715 | platform_device_register(&balloon3_nand); | |
716 | } | |
717 | #else | |
718 | static inline void balloon3_nand_init(void) {} | |
719 | #endif | |
720 | ||
3a27f6e0 MV |
721 | /****************************************************************************** |
722 | * Core power regulator | |
723 | ******************************************************************************/ | |
724 | #if defined(CONFIG_REGULATOR_MAX1586) || \ | |
725 | defined(CONFIG_REGULATOR_MAX1586_MODULE) | |
726 | static struct regulator_consumer_supply balloon3_max1587a_consumers[] = { | |
0bf189ab | 727 | REGULATOR_SUPPLY("vcc_core", NULL), |
3a27f6e0 MV |
728 | }; |
729 | ||
730 | static struct regulator_init_data balloon3_max1587a_v3_info = { | |
731 | .constraints = { | |
732 | .name = "vcc_core range", | |
733 | .min_uV = 900000, | |
734 | .max_uV = 1705000, | |
735 | .always_on = 1, | |
736 | .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, | |
737 | }, | |
738 | .consumer_supplies = balloon3_max1587a_consumers, | |
739 | .num_consumer_supplies = ARRAY_SIZE(balloon3_max1587a_consumers), | |
740 | }; | |
741 | ||
742 | static struct max1586_subdev_data balloon3_max1587a_subdevs[] = { | |
743 | { | |
744 | .name = "vcc_core", | |
745 | .id = MAX1586_V3, | |
746 | .platform_data = &balloon3_max1587a_v3_info, | |
747 | } | |
748 | }; | |
749 | ||
750 | static struct max1586_platform_data balloon3_max1587a_info = { | |
751 | .subdevs = balloon3_max1587a_subdevs, | |
752 | .num_subdevs = ARRAY_SIZE(balloon3_max1587a_subdevs), | |
753 | .v3_gain = MAX1586_GAIN_R24_3k32, /* 730..1550 mV */ | |
754 | }; | |
755 | ||
756 | static struct i2c_board_info __initdata balloon3_pi2c_board_info[] = { | |
757 | { | |
758 | I2C_BOARD_INFO("max1586", 0x14), | |
759 | .platform_data = &balloon3_max1587a_info, | |
760 | }, | |
761 | }; | |
762 | ||
763 | static void __init balloon3_pmic_init(void) | |
764 | { | |
765 | pxa27x_set_i2c_power_info(NULL); | |
766 | i2c_register_board_info(1, ARRAY_AND_SIZE(balloon3_pi2c_board_info)); | |
767 | } | |
768 | #else | |
769 | static inline void balloon3_pmic_init(void) {} | |
770 | #endif | |
771 | ||
b0240bf4 MV |
772 | /****************************************************************************** |
773 | * Machine init | |
774 | ******************************************************************************/ | |
2a23ec36 JM |
775 | static void __init balloon3_init(void) |
776 | { | |
2a23ec36 JM |
777 | ARB_CNTRL = ARB_CORE_PARK | 0x234; |
778 | ||
12a2449c MV |
779 | pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_pin_config)); |
780 | ||
cc155c6f RK |
781 | pxa_set_ffuart_info(NULL); |
782 | pxa_set_btuart_info(NULL); | |
783 | pxa_set_stuart_info(NULL); | |
784 | ||
02a453e4 | 785 | balloon3_i2c_init(); |
12a2449c MV |
786 | balloon3_irda_init(); |
787 | balloon3_lcd_init(); | |
788 | balloon3_leds_init(); | |
789 | balloon3_mmc_init(); | |
e6a8ef54 | 790 | balloon3_nand_init(); |
12a2449c | 791 | balloon3_nor_init(); |
3a27f6e0 | 792 | balloon3_pmic_init(); |
12a2449c MV |
793 | balloon3_ts_init(); |
794 | balloon3_udc_init(); | |
795 | balloon3_uhc_init(); | |
b476ef05 | 796 | balloon3_cf_init(); |
2a23ec36 JM |
797 | } |
798 | ||
799 | static struct map_desc balloon3_io_desc[] __initdata = { | |
800 | { /* CPLD/FPGA */ | |
97b09da4 | 801 | .virtual = (unsigned long)BALLOON3_FPGA_VIRT, |
2a23ec36 JM |
802 | .pfn = __phys_to_pfn(BALLOON3_FPGA_PHYS), |
803 | .length = BALLOON3_FPGA_LENGTH, | |
804 | .type = MT_DEVICE, | |
805 | }, | |
806 | }; | |
807 | ||
808 | static void __init balloon3_map_io(void) | |
809 | { | |
851982c1 | 810 | pxa27x_map_io(); |
2a23ec36 JM |
811 | iotable_init(balloon3_io_desc, ARRAY_SIZE(balloon3_io_desc)); |
812 | } | |
813 | ||
814 | MACHINE_START(BALLOON3, "Balloon3") | |
815 | /* Maintainer: Nick Bane. */ | |
2a23ec36 | 816 | .map_io = balloon3_map_io, |
6ac6b817 | 817 | .nr_irqs = BALLOON3_NR_IRQS, |
2a23ec36 | 818 | .init_irq = balloon3_init_irq, |
8a97ae2f | 819 | .handle_irq = pxa27x_handle_irq, |
6bb27d73 | 820 | .init_time = pxa_timer_init, |
2a23ec36 | 821 | .init_machine = balloon3_init, |
7375aba6 | 822 | .atag_offset = 0x100, |
271a74fc | 823 | .restart = pxa_restart, |
2a23ec36 | 824 | MACHINE_END |