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