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