Commit | Line | Data |
---|---|---|
64cd04d0 ML |
1 | /* |
2 | * DBAu1300 init and platform device setup. | |
3 | * | |
4 | * (c) 2009 Manuel Lauss <manuel.lauss@googlemail.com> | |
5 | */ | |
6 | ||
7 | #include <linux/dma-mapping.h> | |
8 | #include <linux/gpio.h> | |
9 | #include <linux/gpio_keys.h> | |
10 | #include <linux/init.h> | |
11 | #include <linux/input.h> /* KEY_* codes */ | |
12 | #include <linux/i2c.h> | |
13 | #include <linux/io.h> | |
14 | #include <linux/leds.h> | |
15 | #include <linux/ata_platform.h> | |
16 | #include <linux/mmc/host.h> | |
17 | #include <linux/module.h> | |
18 | #include <linux/mtd/mtd.h> | |
19 | #include <linux/mtd/nand.h> | |
20 | #include <linux/mtd/partitions.h> | |
21 | #include <linux/platform_device.h> | |
22 | #include <linux/smsc911x.h> | |
23 | ||
24 | #include <asm/mach-au1x00/au1000.h> | |
25 | #include <asm/mach-au1x00/au1100_mmc.h> | |
a9b71a8f | 26 | #include <asm/mach-au1x00/au1200fb.h> |
64cd04d0 ML |
27 | #include <asm/mach-au1x00/au1xxx_dbdma.h> |
28 | #include <asm/mach-au1x00/au1xxx_psc.h> | |
29 | #include <asm/mach-db1x00/db1300.h> | |
30 | #include <asm/mach-db1x00/bcsr.h> | |
31 | #include <asm/mach-au1x00/prom.h> | |
32 | ||
33 | #include "platform.h" | |
34 | ||
35 | static struct i2c_board_info db1300_i2c_devs[] __initdata = { | |
36 | { I2C_BOARD_INFO("wm8731", 0x1b), }, /* I2S audio codec */ | |
37 | { I2C_BOARD_INFO("ne1619", 0x2d), }, /* adm1025-compat hwmon */ | |
38 | }; | |
39 | ||
40 | /* multifunction pins to assign to GPIO controller */ | |
41 | static int db1300_gpio_pins[] __initdata = { | |
42 | AU1300_PIN_LCDPWM0, AU1300_PIN_PSC2SYNC1, AU1300_PIN_WAKE1, | |
43 | AU1300_PIN_WAKE2, AU1300_PIN_WAKE3, AU1300_PIN_FG3AUX, | |
44 | AU1300_PIN_EXTCLK1, | |
45 | -1, /* terminator */ | |
46 | }; | |
47 | ||
48 | /* multifunction pins to assign to device functions */ | |
49 | static int db1300_dev_pins[] __initdata = { | |
50 | /* wake-from-str pins 0-3 */ | |
51 | AU1300_PIN_WAKE0, | |
52 | /* external clock sources for PSC0 */ | |
53 | AU1300_PIN_EXTCLK0, | |
54 | /* 8bit MMC interface on SD0: 6-9 */ | |
55 | AU1300_PIN_SD0DAT4, AU1300_PIN_SD0DAT5, AU1300_PIN_SD0DAT6, | |
56 | AU1300_PIN_SD0DAT7, | |
57 | /* UART1 pins: 11-18 */ | |
58 | AU1300_PIN_U1RI, AU1300_PIN_U1DCD, AU1300_PIN_U1DSR, | |
59 | AU1300_PIN_U1CTS, AU1300_PIN_U1RTS, AU1300_PIN_U1DTR, | |
60 | AU1300_PIN_U1RX, AU1300_PIN_U1TX, | |
61 | /* UART0 pins: 19-24 */ | |
62 | AU1300_PIN_U0RI, AU1300_PIN_U0DCD, AU1300_PIN_U0DSR, | |
63 | AU1300_PIN_U0CTS, AU1300_PIN_U0RTS, AU1300_PIN_U0DTR, | |
64 | /* UART2: 25-26 */ | |
65 | AU1300_PIN_U2RX, AU1300_PIN_U2TX, | |
66 | /* UART3: 27-28 */ | |
67 | AU1300_PIN_U3RX, AU1300_PIN_U3TX, | |
68 | /* LCD controller PWMs, ext pixclock: 30-31 */ | |
69 | AU1300_PIN_LCDPWM1, AU1300_PIN_LCDCLKIN, | |
70 | /* SD1 interface: 32-37 */ | |
71 | AU1300_PIN_SD1DAT0, AU1300_PIN_SD1DAT1, AU1300_PIN_SD1DAT2, | |
72 | AU1300_PIN_SD1DAT3, AU1300_PIN_SD1CMD, AU1300_PIN_SD1CLK, | |
73 | /* SD2 interface: 38-43 */ | |
74 | AU1300_PIN_SD2DAT0, AU1300_PIN_SD2DAT1, AU1300_PIN_SD2DAT2, | |
75 | AU1300_PIN_SD2DAT3, AU1300_PIN_SD2CMD, AU1300_PIN_SD2CLK, | |
76 | /* PSC0/1 clocks: 44-45 */ | |
77 | AU1300_PIN_PSC0CLK, AU1300_PIN_PSC1CLK, | |
78 | /* PSCs: 46-49/50-53/54-57/58-61 */ | |
79 | AU1300_PIN_PSC0SYNC0, AU1300_PIN_PSC0SYNC1, AU1300_PIN_PSC0D0, | |
80 | AU1300_PIN_PSC0D1, | |
81 | AU1300_PIN_PSC1SYNC0, AU1300_PIN_PSC1SYNC1, AU1300_PIN_PSC1D0, | |
82 | AU1300_PIN_PSC1D1, | |
70342287 | 83 | AU1300_PIN_PSC2SYNC0, AU1300_PIN_PSC2D0, |
64cd04d0 ML |
84 | AU1300_PIN_PSC2D1, |
85 | AU1300_PIN_PSC3SYNC0, AU1300_PIN_PSC3SYNC1, AU1300_PIN_PSC3D0, | |
86 | AU1300_PIN_PSC3D1, | |
87 | /* PCMCIA interface: 62-70 */ | |
88 | AU1300_PIN_PCE2, AU1300_PIN_PCE1, AU1300_PIN_PIOS16, | |
89 | AU1300_PIN_PIOR, AU1300_PIN_PWE, AU1300_PIN_PWAIT, | |
90 | AU1300_PIN_PREG, AU1300_PIN_POE, AU1300_PIN_PIOW, | |
91 | /* camera interface H/V sync inputs: 71-72 */ | |
92 | AU1300_PIN_CIMLS, AU1300_PIN_CIMFS, | |
93 | /* PSC2/3 clocks: 73-74 */ | |
94 | AU1300_PIN_PSC2CLK, AU1300_PIN_PSC3CLK, | |
95 | -1, /* terminator */ | |
96 | }; | |
97 | ||
98 | static void __init db1300_gpio_config(void) | |
99 | { | |
100 | int *i; | |
101 | ||
102 | i = &db1300_dev_pins[0]; | |
103 | while (*i != -1) | |
104 | au1300_pinfunc_to_dev(*i++); | |
105 | ||
106 | i = &db1300_gpio_pins[0]; | |
107 | while (*i != -1) | |
108 | au1300_gpio_direction_input(*i++);/* implies pin_to_gpio */ | |
109 | ||
110 | au1300_set_dbdma_gpio(1, AU1300_PIN_FG3AUX); | |
111 | } | |
112 | ||
64cd04d0 ML |
113 | /**********************************************************************/ |
114 | ||
115 | static void au1300_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, | |
116 | unsigned int ctrl) | |
117 | { | |
118 | struct nand_chip *this = mtd->priv; | |
119 | unsigned long ioaddr = (unsigned long)this->IO_ADDR_W; | |
120 | ||
121 | ioaddr &= 0xffffff00; | |
122 | ||
123 | if (ctrl & NAND_CLE) { | |
124 | ioaddr += MEM_STNAND_CMD; | |
125 | } else if (ctrl & NAND_ALE) { | |
126 | ioaddr += MEM_STNAND_ADDR; | |
127 | } else { | |
128 | /* assume we want to r/w real data by default */ | |
129 | ioaddr += MEM_STNAND_DATA; | |
130 | } | |
131 | this->IO_ADDR_R = this->IO_ADDR_W = (void __iomem *)ioaddr; | |
132 | if (cmd != NAND_CMD_NONE) { | |
133 | __raw_writeb(cmd, this->IO_ADDR_W); | |
134 | wmb(); | |
135 | } | |
136 | } | |
137 | ||
138 | static int au1300_nand_device_ready(struct mtd_info *mtd) | |
139 | { | |
140 | return __raw_readl((void __iomem *)MEM_STSTAT) & 1; | |
141 | } | |
142 | ||
64cd04d0 ML |
143 | static struct mtd_partition db1300_nand_parts[] = { |
144 | { | |
145 | .name = "NAND FS 0", | |
70342287 | 146 | .offset = 0, |
64cd04d0 ML |
147 | .size = 8 * 1024 * 1024, |
148 | }, | |
149 | { | |
150 | .name = "NAND FS 1", | |
70342287 | 151 | .offset = MTDPART_OFS_APPEND, |
64cd04d0 ML |
152 | .size = MTDPART_SIZ_FULL |
153 | }, | |
154 | }; | |
155 | ||
156 | struct platform_nand_data db1300_nand_platdata = { | |
157 | .chip = { | |
158 | .nr_chips = 1, | |
159 | .chip_offset = 0, | |
160 | .nr_partitions = ARRAY_SIZE(db1300_nand_parts), | |
161 | .partitions = db1300_nand_parts, | |
162 | .chip_delay = 20, | |
64cd04d0 ML |
163 | }, |
164 | .ctrl = { | |
165 | .dev_ready = au1300_nand_device_ready, | |
166 | .cmd_ctrl = au1300_nand_cmd_ctrl, | |
167 | }, | |
168 | }; | |
169 | ||
170 | static struct resource db1300_nand_res[] = { | |
171 | [0] = { | |
172 | .start = DB1300_NAND_PHYS_ADDR, | |
173 | .end = DB1300_NAND_PHYS_ADDR + 0xff, | |
174 | .flags = IORESOURCE_MEM, | |
175 | }, | |
176 | }; | |
177 | ||
178 | static struct platform_device db1300_nand_dev = { | |
179 | .name = "gen_nand", | |
180 | .num_resources = ARRAY_SIZE(db1300_nand_res), | |
181 | .resource = db1300_nand_res, | |
182 | .id = -1, | |
183 | .dev = { | |
184 | .platform_data = &db1300_nand_platdata, | |
185 | } | |
186 | }; | |
187 | ||
188 | /**********************************************************************/ | |
189 | ||
190 | static struct resource db1300_eth_res[] = { | |
191 | [0] = { | |
192 | .start = DB1300_ETH_PHYS_ADDR, | |
193 | .end = DB1300_ETH_PHYS_END, | |
194 | .flags = IORESOURCE_MEM, | |
195 | }, | |
196 | [1] = { | |
197 | .start = DB1300_ETH_INT, | |
198 | .end = DB1300_ETH_INT, | |
199 | .flags = IORESOURCE_IRQ, | |
200 | }, | |
201 | }; | |
202 | ||
203 | static struct smsc911x_platform_config db1300_eth_config = { | |
204 | .phy_interface = PHY_INTERFACE_MODE_MII, | |
205 | .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, | |
206 | .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, | |
207 | .flags = SMSC911X_USE_32BIT, | |
208 | }; | |
209 | ||
210 | static struct platform_device db1300_eth_dev = { | |
211 | .name = "smsc911x", | |
212 | .id = -1, | |
213 | .num_resources = ARRAY_SIZE(db1300_eth_res), | |
214 | .resource = db1300_eth_res, | |
215 | .dev = { | |
216 | .platform_data = &db1300_eth_config, | |
217 | }, | |
218 | }; | |
219 | ||
220 | /**********************************************************************/ | |
221 | ||
222 | static struct resource au1300_psc1_res[] = { | |
223 | [0] = { | |
224 | .start = AU1300_PSC1_PHYS_ADDR, | |
225 | .end = AU1300_PSC1_PHYS_ADDR + 0x0fff, | |
226 | .flags = IORESOURCE_MEM, | |
227 | }, | |
228 | [1] = { | |
229 | .start = AU1300_PSC1_INT, | |
230 | .end = AU1300_PSC1_INT, | |
231 | .flags = IORESOURCE_IRQ, | |
232 | }, | |
233 | [2] = { | |
234 | .start = AU1300_DSCR_CMD0_PSC1_TX, | |
235 | .end = AU1300_DSCR_CMD0_PSC1_TX, | |
236 | .flags = IORESOURCE_DMA, | |
237 | }, | |
238 | [3] = { | |
239 | .start = AU1300_DSCR_CMD0_PSC1_RX, | |
240 | .end = AU1300_DSCR_CMD0_PSC1_RX, | |
241 | .flags = IORESOURCE_DMA, | |
242 | }, | |
243 | }; | |
244 | ||
245 | static struct platform_device db1300_ac97_dev = { | |
246 | .name = "au1xpsc_ac97", | |
247 | .id = 1, /* PSC ID. match with AC97 codec ID! */ | |
248 | .num_resources = ARRAY_SIZE(au1300_psc1_res), | |
249 | .resource = au1300_psc1_res, | |
250 | }; | |
251 | ||
252 | /**********************************************************************/ | |
253 | ||
254 | static struct resource au1300_psc2_res[] = { | |
255 | [0] = { | |
256 | .start = AU1300_PSC2_PHYS_ADDR, | |
257 | .end = AU1300_PSC2_PHYS_ADDR + 0x0fff, | |
258 | .flags = IORESOURCE_MEM, | |
259 | }, | |
260 | [1] = { | |
261 | .start = AU1300_PSC2_INT, | |
262 | .end = AU1300_PSC2_INT, | |
263 | .flags = IORESOURCE_IRQ, | |
264 | }, | |
265 | [2] = { | |
266 | .start = AU1300_DSCR_CMD0_PSC2_TX, | |
267 | .end = AU1300_DSCR_CMD0_PSC2_TX, | |
268 | .flags = IORESOURCE_DMA, | |
269 | }, | |
270 | [3] = { | |
271 | .start = AU1300_DSCR_CMD0_PSC2_RX, | |
272 | .end = AU1300_DSCR_CMD0_PSC2_RX, | |
273 | .flags = IORESOURCE_DMA, | |
274 | }, | |
275 | }; | |
276 | ||
277 | static struct platform_device db1300_i2s_dev = { | |
278 | .name = "au1xpsc_i2s", | |
279 | .id = 2, /* PSC ID */ | |
280 | .num_resources = ARRAY_SIZE(au1300_psc2_res), | |
281 | .resource = au1300_psc2_res, | |
282 | }; | |
283 | ||
284 | /**********************************************************************/ | |
285 | ||
286 | static struct resource au1300_psc3_res[] = { | |
287 | [0] = { | |
288 | .start = AU1300_PSC3_PHYS_ADDR, | |
289 | .end = AU1300_PSC3_PHYS_ADDR + 0x0fff, | |
290 | .flags = IORESOURCE_MEM, | |
291 | }, | |
292 | [1] = { | |
293 | .start = AU1300_PSC3_INT, | |
294 | .end = AU1300_PSC3_INT, | |
295 | .flags = IORESOURCE_IRQ, | |
296 | }, | |
297 | [2] = { | |
298 | .start = AU1300_DSCR_CMD0_PSC3_TX, | |
299 | .end = AU1300_DSCR_CMD0_PSC3_TX, | |
300 | .flags = IORESOURCE_DMA, | |
301 | }, | |
302 | [3] = { | |
303 | .start = AU1300_DSCR_CMD0_PSC3_RX, | |
304 | .end = AU1300_DSCR_CMD0_PSC3_RX, | |
305 | .flags = IORESOURCE_DMA, | |
306 | }, | |
307 | }; | |
308 | ||
309 | static struct platform_device db1300_i2c_dev = { | |
310 | .name = "au1xpsc_smbus", | |
311 | .id = 0, /* bus number */ | |
312 | .num_resources = ARRAY_SIZE(au1300_psc3_res), | |
313 | .resource = au1300_psc3_res, | |
314 | }; | |
315 | ||
316 | /**********************************************************************/ | |
317 | ||
318 | /* proper key assignments when facing the LCD panel. For key assignments | |
319 | * according to the schematics swap up with down and left with right. | |
320 | * I chose to use it to emulate the arrow keys of a keyboard. | |
321 | */ | |
322 | static struct gpio_keys_button db1300_5waysw_arrowkeys[] = { | |
323 | { | |
324 | .code = KEY_DOWN, | |
325 | .gpio = AU1300_PIN_LCDPWM0, | |
326 | .type = EV_KEY, | |
327 | .debounce_interval = 1, | |
328 | .active_low = 1, | |
329 | .desc = "5waysw-down", | |
330 | }, | |
331 | { | |
332 | .code = KEY_UP, | |
333 | .gpio = AU1300_PIN_PSC2SYNC1, | |
334 | .type = EV_KEY, | |
335 | .debounce_interval = 1, | |
336 | .active_low = 1, | |
337 | .desc = "5waysw-up", | |
338 | }, | |
339 | { | |
340 | .code = KEY_RIGHT, | |
341 | .gpio = AU1300_PIN_WAKE3, | |
342 | .type = EV_KEY, | |
343 | .debounce_interval = 1, | |
344 | .active_low = 1, | |
345 | .desc = "5waysw-right", | |
346 | }, | |
347 | { | |
348 | .code = KEY_LEFT, | |
349 | .gpio = AU1300_PIN_WAKE2, | |
350 | .type = EV_KEY, | |
351 | .debounce_interval = 1, | |
352 | .active_low = 1, | |
353 | .desc = "5waysw-left", | |
354 | }, | |
355 | { | |
356 | .code = KEY_ENTER, | |
357 | .gpio = AU1300_PIN_WAKE1, | |
358 | .type = EV_KEY, | |
359 | .debounce_interval = 1, | |
360 | .active_low = 1, | |
361 | .desc = "5waysw-push", | |
362 | }, | |
363 | }; | |
364 | ||
365 | static struct gpio_keys_platform_data db1300_5waysw_data = { | |
366 | .buttons = db1300_5waysw_arrowkeys, | |
367 | .nbuttons = ARRAY_SIZE(db1300_5waysw_arrowkeys), | |
368 | .rep = 1, | |
369 | .name = "db1300-5wayswitch", | |
370 | }; | |
371 | ||
372 | static struct platform_device db1300_5waysw_dev = { | |
373 | .name = "gpio-keys", | |
374 | .dev = { | |
375 | .platform_data = &db1300_5waysw_data, | |
376 | }, | |
377 | }; | |
378 | ||
379 | /**********************************************************************/ | |
380 | ||
64cd04d0 ML |
381 | static struct pata_platform_info db1300_ide_info = { |
382 | .ioport_shift = DB1300_IDE_REG_SHIFT, | |
383 | }; | |
384 | ||
385 | #define IDE_ALT_START (14 << DB1300_IDE_REG_SHIFT) | |
386 | static struct resource db1300_ide_res[] = { | |
387 | [0] = { | |
388 | .start = DB1300_IDE_PHYS_ADDR, | |
389 | .end = DB1300_IDE_PHYS_ADDR + IDE_ALT_START - 1, | |
390 | .flags = IORESOURCE_MEM, | |
391 | }, | |
392 | [1] = { | |
393 | .start = DB1300_IDE_PHYS_ADDR + IDE_ALT_START, | |
394 | .end = DB1300_IDE_PHYS_ADDR + DB1300_IDE_PHYS_LEN - 1, | |
395 | .flags = IORESOURCE_MEM, | |
396 | }, | |
397 | [2] = { | |
398 | .start = DB1300_IDE_INT, | |
399 | .end = DB1300_IDE_INT, | |
400 | .flags = IORESOURCE_IRQ, | |
401 | }, | |
402 | }; | |
403 | ||
404 | static struct platform_device db1300_ide_dev = { | |
405 | .dev = { | |
406 | .platform_data = &db1300_ide_info, | |
407 | }, | |
408 | .name = "pata_platform", | |
409 | .resource = db1300_ide_res, | |
410 | .num_resources = ARRAY_SIZE(db1300_ide_res), | |
411 | }; | |
412 | ||
413 | /**********************************************************************/ | |
414 | ||
415 | static irqreturn_t db1300_mmc_cd(int irq, void *ptr) | |
416 | { | |
417 | void(*mmc_cd)(struct mmc_host *, unsigned long); | |
418 | ||
419 | /* disable the one currently screaming. No other way to shut it up */ | |
420 | if (irq == DB1300_SD1_INSERT_INT) { | |
421 | disable_irq_nosync(DB1300_SD1_INSERT_INT); | |
422 | enable_irq(DB1300_SD1_EJECT_INT); | |
423 | } else { | |
424 | disable_irq_nosync(DB1300_SD1_EJECT_INT); | |
425 | enable_irq(DB1300_SD1_INSERT_INT); | |
426 | } | |
427 | ||
428 | /* link against CONFIG_MMC=m. We can only be called once MMC core has | |
429 | * initialized the controller, so symbol_get() should always succeed. | |
430 | */ | |
431 | mmc_cd = symbol_get(mmc_detect_change); | |
432 | mmc_cd(ptr, msecs_to_jiffies(500)); | |
433 | symbol_put(mmc_detect_change); | |
434 | ||
435 | return IRQ_HANDLED; | |
436 | } | |
437 | ||
438 | static int db1300_mmc_card_readonly(void *mmc_host) | |
439 | { | |
440 | /* it uses SD1 interface, but the DB1200's SD0 bit in the CPLD */ | |
441 | return bcsr_read(BCSR_STATUS) & BCSR_STATUS_SD0WP; | |
442 | } | |
443 | ||
444 | static int db1300_mmc_card_inserted(void *mmc_host) | |
445 | { | |
446 | return bcsr_read(BCSR_SIGSTAT) & (1 << 12); /* insertion irq signal */ | |
447 | } | |
448 | ||
449 | static int db1300_mmc_cd_setup(void *mmc_host, int en) | |
450 | { | |
451 | int ret; | |
452 | ||
453 | if (en) { | |
454 | ret = request_irq(DB1300_SD1_INSERT_INT, db1300_mmc_cd, 0, | |
455 | "sd_insert", mmc_host); | |
456 | if (ret) | |
457 | goto out; | |
458 | ||
459 | ret = request_irq(DB1300_SD1_EJECT_INT, db1300_mmc_cd, 0, | |
460 | "sd_eject", mmc_host); | |
461 | if (ret) { | |
462 | free_irq(DB1300_SD1_INSERT_INT, mmc_host); | |
463 | goto out; | |
464 | } | |
465 | ||
466 | if (db1300_mmc_card_inserted(mmc_host)) | |
467 | enable_irq(DB1300_SD1_EJECT_INT); | |
468 | else | |
469 | enable_irq(DB1300_SD1_INSERT_INT); | |
470 | ||
471 | } else { | |
472 | free_irq(DB1300_SD1_INSERT_INT, mmc_host); | |
473 | free_irq(DB1300_SD1_EJECT_INT, mmc_host); | |
474 | } | |
475 | ret = 0; | |
476 | out: | |
477 | return ret; | |
478 | } | |
479 | ||
480 | static void db1300_mmcled_set(struct led_classdev *led, | |
481 | enum led_brightness brightness) | |
482 | { | |
483 | if (brightness != LED_OFF) | |
484 | bcsr_mod(BCSR_LEDS, BCSR_LEDS_LED0, 0); | |
485 | else | |
486 | bcsr_mod(BCSR_LEDS, 0, BCSR_LEDS_LED0); | |
487 | } | |
488 | ||
489 | static struct led_classdev db1300_mmc_led = { | |
70342287 | 490 | .brightness_set = db1300_mmcled_set, |
64cd04d0 ML |
491 | }; |
492 | ||
493 | struct au1xmmc_platform_data db1300_sd1_platdata = { | |
494 | .cd_setup = db1300_mmc_cd_setup, | |
495 | .card_inserted = db1300_mmc_card_inserted, | |
496 | .card_readonly = db1300_mmc_card_readonly, | |
497 | .led = &db1300_mmc_led, | |
498 | }; | |
499 | ||
500 | static struct resource au1300_sd1_res[] = { | |
501 | [0] = { | |
502 | .start = AU1300_SD1_PHYS_ADDR, | |
503 | .end = AU1300_SD1_PHYS_ADDR, | |
504 | .flags = IORESOURCE_MEM, | |
505 | }, | |
506 | [1] = { | |
507 | .start = AU1300_SD1_INT, | |
508 | .end = AU1300_SD1_INT, | |
509 | .flags = IORESOURCE_IRQ, | |
510 | }, | |
511 | [2] = { | |
512 | .start = AU1300_DSCR_CMD0_SDMS_TX1, | |
513 | .end = AU1300_DSCR_CMD0_SDMS_TX1, | |
514 | .flags = IORESOURCE_DMA, | |
515 | }, | |
516 | [3] = { | |
517 | .start = AU1300_DSCR_CMD0_SDMS_RX1, | |
518 | .end = AU1300_DSCR_CMD0_SDMS_RX1, | |
519 | .flags = IORESOURCE_DMA, | |
520 | }, | |
521 | }; | |
522 | ||
523 | static struct platform_device db1300_sd1_dev = { | |
524 | .dev = { | |
525 | .platform_data = &db1300_sd1_platdata, | |
526 | }, | |
527 | .name = "au1xxx-mmc", | |
528 | .id = 1, | |
529 | .resource = au1300_sd1_res, | |
530 | .num_resources = ARRAY_SIZE(au1300_sd1_res), | |
531 | }; | |
532 | ||
533 | /**********************************************************************/ | |
534 | ||
535 | static int db1300_movinand_inserted(void *mmc_host) | |
536 | { | |
537 | return 0; /* disable for now, it doesn't work yet */ | |
538 | } | |
539 | ||
540 | static int db1300_movinand_readonly(void *mmc_host) | |
541 | { | |
542 | return 0; | |
543 | } | |
544 | ||
545 | static void db1300_movinand_led_set(struct led_classdev *led, | |
546 | enum led_brightness brightness) | |
547 | { | |
548 | if (brightness != LED_OFF) | |
549 | bcsr_mod(BCSR_LEDS, BCSR_LEDS_LED1, 0); | |
550 | else | |
551 | bcsr_mod(BCSR_LEDS, 0, BCSR_LEDS_LED1); | |
552 | } | |
553 | ||
554 | static struct led_classdev db1300_movinand_led = { | |
555 | .brightness_set = db1300_movinand_led_set, | |
556 | }; | |
557 | ||
558 | struct au1xmmc_platform_data db1300_sd0_platdata = { | |
559 | .card_inserted = db1300_movinand_inserted, | |
560 | .card_readonly = db1300_movinand_readonly, | |
561 | .led = &db1300_movinand_led, | |
562 | .mask_host_caps = MMC_CAP_NEEDS_POLL, | |
563 | }; | |
564 | ||
565 | static struct resource au1300_sd0_res[] = { | |
566 | [0] = { | |
567 | .start = AU1100_SD0_PHYS_ADDR, | |
568 | .end = AU1100_SD0_PHYS_ADDR, | |
569 | .flags = IORESOURCE_MEM, | |
570 | }, | |
571 | [1] = { | |
572 | .start = AU1300_SD0_INT, | |
573 | .end = AU1300_SD0_INT, | |
574 | .flags = IORESOURCE_IRQ, | |
575 | }, | |
576 | [2] = { | |
577 | .start = AU1300_DSCR_CMD0_SDMS_TX0, | |
578 | .end = AU1300_DSCR_CMD0_SDMS_TX0, | |
579 | .flags = IORESOURCE_DMA, | |
580 | }, | |
581 | [3] = { | |
582 | .start = AU1300_DSCR_CMD0_SDMS_RX0, | |
583 | .end = AU1300_DSCR_CMD0_SDMS_RX0, | |
584 | .flags = IORESOURCE_DMA, | |
585 | }, | |
586 | }; | |
587 | ||
588 | static struct platform_device db1300_sd0_dev = { | |
589 | .dev = { | |
590 | .platform_data = &db1300_sd0_platdata, | |
591 | }, | |
592 | .name = "au1xxx-mmc", | |
593 | .id = 0, | |
594 | .resource = au1300_sd0_res, | |
595 | .num_resources = ARRAY_SIZE(au1300_sd0_res), | |
596 | }; | |
597 | ||
598 | /**********************************************************************/ | |
599 | ||
600 | static struct platform_device db1300_wm9715_dev = { | |
601 | .name = "wm9712-codec", | |
602 | .id = 1, /* ID of PSC for AC97 audio, see asoc glue! */ | |
603 | }; | |
604 | ||
605 | static struct platform_device db1300_ac97dma_dev = { | |
606 | .name = "au1xpsc-pcm", | |
607 | .id = 1, /* PSC ID */ | |
608 | }; | |
609 | ||
610 | static struct platform_device db1300_i2sdma_dev = { | |
611 | .name = "au1xpsc-pcm", | |
612 | .id = 2, /* PSC ID */ | |
613 | }; | |
614 | ||
615 | static struct platform_device db1300_sndac97_dev = { | |
616 | .name = "db1300-ac97", | |
617 | }; | |
618 | ||
619 | static struct platform_device db1300_sndi2s_dev = { | |
620 | .name = "db1300-i2s", | |
621 | }; | |
622 | ||
623 | /**********************************************************************/ | |
624 | ||
a9b71a8f ML |
625 | static int db1300fb_panel_index(void) |
626 | { | |
627 | return 9; /* DB1300_800x480 */ | |
628 | } | |
629 | ||
630 | static int db1300fb_panel_init(void) | |
631 | { | |
632 | /* Apply power (Vee/Vdd logic is inverted on Panel DB1300_800x480) */ | |
633 | bcsr_mod(BCSR_BOARD, BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD, | |
634 | BCSR_BOARD_LCDBL); | |
635 | return 0; | |
636 | } | |
637 | ||
638 | static int db1300fb_panel_shutdown(void) | |
639 | { | |
640 | /* Remove power (Vee/Vdd logic is inverted on Panel DB1300_800x480) */ | |
641 | bcsr_mod(BCSR_BOARD, BCSR_BOARD_LCDBL, | |
642 | BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD); | |
643 | return 0; | |
644 | } | |
645 | ||
646 | static struct au1200fb_platdata db1300fb_pd = { | |
647 | .panel_index = db1300fb_panel_index, | |
648 | .panel_init = db1300fb_panel_init, | |
70342287 | 649 | .panel_shutdown = db1300fb_panel_shutdown, |
a9b71a8f ML |
650 | }; |
651 | ||
64cd04d0 ML |
652 | static struct resource au1300_lcd_res[] = { |
653 | [0] = { | |
654 | .start = AU1200_LCD_PHYS_ADDR, | |
655 | .end = AU1200_LCD_PHYS_ADDR + 0x800 - 1, | |
656 | .flags = IORESOURCE_MEM, | |
657 | }, | |
658 | [1] = { | |
659 | .start = AU1300_LCD_INT, | |
660 | .end = AU1300_LCD_INT, | |
661 | .flags = IORESOURCE_IRQ, | |
662 | } | |
663 | }; | |
664 | ||
665 | static u64 au1300_lcd_dmamask = DMA_BIT_MASK(32); | |
666 | ||
667 | static struct platform_device db1300_lcd_dev = { | |
668 | .name = "au1200-lcd", | |
669 | .id = 0, | |
670 | .dev = { | |
671 | .dma_mask = &au1300_lcd_dmamask, | |
672 | .coherent_dma_mask = DMA_BIT_MASK(32), | |
a9b71a8f | 673 | .platform_data = &db1300fb_pd, |
64cd04d0 ML |
674 | }, |
675 | .num_resources = ARRAY_SIZE(au1300_lcd_res), | |
676 | .resource = au1300_lcd_res, | |
677 | }; | |
678 | ||
679 | /**********************************************************************/ | |
680 | ||
681 | static struct platform_device *db1300_dev[] __initdata = { | |
682 | &db1300_eth_dev, | |
683 | &db1300_i2c_dev, | |
684 | &db1300_5waysw_dev, | |
64cd04d0 ML |
685 | &db1300_nand_dev, |
686 | &db1300_ide_dev, | |
687 | &db1300_sd0_dev, | |
688 | &db1300_sd1_dev, | |
689 | &db1300_lcd_dev, | |
690 | &db1300_ac97_dev, | |
691 | &db1300_i2s_dev, | |
692 | &db1300_wm9715_dev, | |
693 | &db1300_ac97dma_dev, | |
694 | &db1300_i2sdma_dev, | |
695 | &db1300_sndac97_dev, | |
696 | &db1300_sndi2s_dev, | |
697 | }; | |
698 | ||
bd8510df | 699 | int __init db1300_dev_setup(void) |
64cd04d0 ML |
700 | { |
701 | int swapped, cpldirq; | |
702 | ||
703 | /* setup CPLD IRQ muxer */ | |
704 | cpldirq = au1300_gpio_to_irq(AU1300_PIN_EXTCLK1); | |
705 | irq_set_irq_type(cpldirq, IRQ_TYPE_LEVEL_HIGH); | |
706 | bcsr_init_irq(DB1300_FIRST_INT, DB1300_LAST_INT, cpldirq); | |
707 | ||
708 | /* insert/eject IRQs: one always triggers so don't enable them | |
709 | * when doing request_irq() on them. DB1200 has this bug too. | |
710 | */ | |
711 | irq_set_status_flags(DB1300_SD1_INSERT_INT, IRQ_NOAUTOEN); | |
712 | irq_set_status_flags(DB1300_SD1_EJECT_INT, IRQ_NOAUTOEN); | |
713 | irq_set_status_flags(DB1300_CF_INSERT_INT, IRQ_NOAUTOEN); | |
714 | irq_set_status_flags(DB1300_CF_EJECT_INT, IRQ_NOAUTOEN); | |
715 | ||
716 | /* | |
717 | * setup board | |
718 | */ | |
719 | prom_get_ethernet_addr(&db1300_eth_config.mac[0]); | |
720 | ||
721 | i2c_register_board_info(0, db1300_i2c_devs, | |
722 | ARRAY_SIZE(db1300_i2c_devs)); | |
723 | ||
724 | /* Audio PSC clock is supplied by codecs (PSC1, 2) */ | |
725 | __raw_writel(PSC_SEL_CLK_SERCLK, | |
726 | (void __iomem *)KSEG1ADDR(AU1300_PSC1_PHYS_ADDR) + PSC_SEL_OFFSET); | |
727 | wmb(); | |
728 | __raw_writel(PSC_SEL_CLK_SERCLK, | |
729 | (void __iomem *)KSEG1ADDR(AU1300_PSC2_PHYS_ADDR) + PSC_SEL_OFFSET); | |
730 | wmb(); | |
731 | /* I2C uses internal 48MHz EXTCLK1 */ | |
732 | __raw_writel(PSC_SEL_CLK_INTCLK, | |
733 | (void __iomem *)KSEG1ADDR(AU1300_PSC3_PHYS_ADDR) + PSC_SEL_OFFSET); | |
734 | wmb(); | |
735 | ||
736 | /* enable power to USB ports */ | |
737 | bcsr_mod(BCSR_RESETS, 0, BCSR_RESETS_USBHPWR | BCSR_RESETS_OTGPWR); | |
738 | ||
739 | /* although it is socket #0, it uses the CPLD bits which previous boards | |
740 | * have used for socket #1. | |
741 | */ | |
742 | db1x_register_pcmcia_socket( | |
743 | AU1000_PCMCIA_ATTR_PHYS_ADDR, | |
744 | AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x00400000 - 1, | |
745 | AU1000_PCMCIA_MEM_PHYS_ADDR, | |
746 | AU1000_PCMCIA_MEM_PHYS_ADDR + 0x00400000 - 1, | |
747 | AU1000_PCMCIA_IO_PHYS_ADDR, | |
748 | AU1000_PCMCIA_IO_PHYS_ADDR + 0x00010000 - 1, | |
749 | DB1300_CF_INT, DB1300_CF_INSERT_INT, 0, DB1300_CF_EJECT_INT, 1); | |
750 | ||
751 | swapped = bcsr_read(BCSR_STATUS) & BCSR_STATUS_DB1200_SWAPBOOT; | |
752 | db1x_register_norflash(64 << 20, 2, swapped); | |
753 | ||
754 | return platform_add_devices(db1300_dev, ARRAY_SIZE(db1300_dev)); | |
755 | } | |
64cd04d0 ML |
756 | |
757 | ||
bd8510df | 758 | int __init db1300_board_setup(void) |
64cd04d0 ML |
759 | { |
760 | unsigned short whoami; | |
761 | ||
762 | db1300_gpio_config(); | |
763 | bcsr_init(DB1300_BCSR_PHYS_ADDR, | |
764 | DB1300_BCSR_PHYS_ADDR + DB1300_BCSR_HEXLED_OFS); | |
765 | ||
766 | whoami = bcsr_read(BCSR_WHOAMI); | |
767 | printk(KERN_INFO "NetLogic DBAu1300 Development Platform.\n\t" | |
768 | "BoardID %d CPLD Rev %d DaughtercardID %d\n", | |
769 | BCSR_WHOAMI_BOARD(whoami), BCSR_WHOAMI_CPLD(whoami), | |
770 | BCSR_WHOAMI_DCID(whoami)); | |
771 | ||
772 | /* enable UARTs, YAMON only enables #2 */ | |
773 | alchemy_uart_enable(AU1300_UART0_PHYS_ADDR); | |
774 | alchemy_uart_enable(AU1300_UART1_PHYS_ADDR); | |
775 | alchemy_uart_enable(AU1300_UART3_PHYS_ADDR); | |
bd8510df ML |
776 | |
777 | return 0; | |
64cd04d0 | 778 | } |