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