blob: 07708d4226811236c0c1fd8773f4be50f4ba4a2f [file] [log] [blame]
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001/*
2 * On-Chip devices setup code for the AT91SAM9G45 family
3 *
4 * Copyright (C) 2009 Atmel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 */
12#include <asm/mach/arch.h>
13#include <asm/mach/map.h>
14
15#include <linux/dma-mapping.h>
Russell King2f8163b2011-07-26 10:53:52 +010016#include <linux/gpio.h>
Nicolas Ferre789b23b2009-06-26 15:36:58 +010017#include <linux/platform_device.h>
18#include <linux/i2c-gpio.h>
Nicolas Ferre75305d72010-10-22 18:27:48 +020019#include <linux/atmel-mci.h>
Nicolas Ferre789b23b2009-06-26 15:36:58 +010020
21#include <linux/fb.h>
22#include <video/atmel_lcdc.h>
23
24#include <mach/board.h>
Nicolas Ferre789b23b2009-06-26 15:36:58 +010025#include <mach/at91sam9g45.h>
26#include <mach/at91sam9g45_matrix.h>
27#include <mach/at91sam9_smc.h>
Nicolas Ferre40262b22009-07-24 11:43:01 +010028#include <mach/at_hdmac.h>
Nicolas Ferre75305d72010-10-22 18:27:48 +020029#include <mach/atmel-mci.h>
Nicolas Ferre789b23b2009-06-26 15:36:58 +010030
31#include "generic.h"
32
33
34/* --------------------------------------------------------------------
Nicolas Ferre40262b22009-07-24 11:43:01 +010035 * HDMAC - AHB DMA Controller
36 * -------------------------------------------------------------------- */
37
38#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
39static u64 hdmac_dmamask = DMA_BIT_MASK(32);
40
Nicolas Ferre40262b22009-07-24 11:43:01 +010041static struct resource hdmac_resources[] = {
42 [0] = {
Jean-Christophe PLAGNIOL-VILLARD9627b202011-10-15 15:47:51 +080043 .start = AT91SAM9G45_BASE_DMA,
44 .end = AT91SAM9G45_BASE_DMA + SZ_512 - 1,
Nicolas Ferre40262b22009-07-24 11:43:01 +010045 .flags = IORESOURCE_MEM,
46 },
Nicolas Ferre8d2602e2010-08-20 16:44:33 +020047 [1] = {
Nicolas Ferre40262b22009-07-24 11:43:01 +010048 .start = AT91SAM9G45_ID_DMA,
49 .end = AT91SAM9G45_ID_DMA,
50 .flags = IORESOURCE_IRQ,
51 },
52};
53
54static struct platform_device at_hdmac_device = {
Nicolas Ferrebdad0b92011-10-10 14:55:17 +020055 .name = "at91sam9g45_dma",
Nicolas Ferre40262b22009-07-24 11:43:01 +010056 .id = -1,
57 .dev = {
58 .dma_mask = &hdmac_dmamask,
59 .coherent_dma_mask = DMA_BIT_MASK(32),
Nicolas Ferre40262b22009-07-24 11:43:01 +010060 },
61 .resource = hdmac_resources,
62 .num_resources = ARRAY_SIZE(hdmac_resources),
63};
64
65void __init at91_add_device_hdmac(void)
66{
Nicolas Ferre40262b22009-07-24 11:43:01 +010067 platform_device_register(&at_hdmac_device);
68}
69#else
70void __init at91_add_device_hdmac(void) {}
71#endif
72
73
74/* --------------------------------------------------------------------
Nicolas Ferre789b23b2009-06-26 15:36:58 +010075 * USB Host (OHCI)
76 * -------------------------------------------------------------------- */
77
78#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
79static u64 ohci_dmamask = DMA_BIT_MASK(32);
80static struct at91_usbh_data usbh_ohci_data;
81
82static struct resource usbh_ohci_resources[] = {
83 [0] = {
84 .start = AT91SAM9G45_OHCI_BASE,
85 .end = AT91SAM9G45_OHCI_BASE + SZ_1M - 1,
86 .flags = IORESOURCE_MEM,
87 },
88 [1] = {
89 .start = AT91SAM9G45_ID_UHPHS,
90 .end = AT91SAM9G45_ID_UHPHS,
91 .flags = IORESOURCE_IRQ,
92 },
93};
94
95static struct platform_device at91_usbh_ohci_device = {
96 .name = "at91_ohci",
97 .id = -1,
98 .dev = {
99 .dma_mask = &ohci_dmamask,
100 .coherent_dma_mask = DMA_BIT_MASK(32),
101 .platform_data = &usbh_ohci_data,
102 },
103 .resource = usbh_ohci_resources,
104 .num_resources = ARRAY_SIZE(usbh_ohci_resources),
105};
106
107void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
108{
109 int i;
110
111 if (!data)
112 return;
113
114 /* Enable VBus control for UHP ports */
115 for (i = 0; i < data->ports; i++) {
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800116 if (gpio_is_valid(data->vbus_pin[i]))
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100117 at91_set_gpio_output(data->vbus_pin[i], 0);
118 }
119
Thomas Petazzoni1fcaea72011-07-13 11:29:18 +0200120 /* Enable overcurrent notification */
121 for (i = 0; i < data->ports; i++) {
122 if (data->overcurrent_pin[i])
123 at91_set_gpio_input(data->overcurrent_pin[i], 1);
124 }
125
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100126 usbh_ohci_data = *data;
127 platform_device_register(&at91_usbh_ohci_device);
128}
129#else
130void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {}
131#endif
132
133
134/* --------------------------------------------------------------------
Nicolas Ferref51f78c2009-09-25 12:11:32 +0100135 * USB Host HS (EHCI)
136 * Needs an OHCI host for low and full speed management
137 * -------------------------------------------------------------------- */
138
139#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
140static u64 ehci_dmamask = DMA_BIT_MASK(32);
141static struct at91_usbh_data usbh_ehci_data;
142
143static struct resource usbh_ehci_resources[] = {
144 [0] = {
145 .start = AT91SAM9G45_EHCI_BASE,
146 .end = AT91SAM9G45_EHCI_BASE + SZ_1M - 1,
147 .flags = IORESOURCE_MEM,
148 },
149 [1] = {
150 .start = AT91SAM9G45_ID_UHPHS,
151 .end = AT91SAM9G45_ID_UHPHS,
152 .flags = IORESOURCE_IRQ,
153 },
154};
155
156static struct platform_device at91_usbh_ehci_device = {
157 .name = "atmel-ehci",
158 .id = -1,
159 .dev = {
160 .dma_mask = &ehci_dmamask,
161 .coherent_dma_mask = DMA_BIT_MASK(32),
162 .platform_data = &usbh_ehci_data,
163 },
164 .resource = usbh_ehci_resources,
165 .num_resources = ARRAY_SIZE(usbh_ehci_resources),
166};
167
168void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data)
169{
170 int i;
171
172 if (!data)
173 return;
174
175 /* Enable VBus control for UHP ports */
176 for (i = 0; i < data->ports; i++) {
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800177 if (gpio_is_valid(data->vbus_pin[i]))
Nicolas Ferref51f78c2009-09-25 12:11:32 +0100178 at91_set_gpio_output(data->vbus_pin[i], 0);
179 }
180
181 usbh_ehci_data = *data;
Nicolas Ferref51f78c2009-09-25 12:11:32 +0100182 platform_device_register(&at91_usbh_ehci_device);
183}
184#else
185void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data) {}
186#endif
187
188
189/* --------------------------------------------------------------------
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100190 * USB HS Device (Gadget)
191 * -------------------------------------------------------------------- */
192
Jochen Friedrichdd0b3822011-10-25 20:51:06 +0200193#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100194static struct resource usba_udc_resources[] = {
195 [0] = {
196 .start = AT91SAM9G45_UDPHS_FIFO,
197 .end = AT91SAM9G45_UDPHS_FIFO + SZ_512K - 1,
198 .flags = IORESOURCE_MEM,
199 },
200 [1] = {
201 .start = AT91SAM9G45_BASE_UDPHS,
202 .end = AT91SAM9G45_BASE_UDPHS + SZ_1K - 1,
203 .flags = IORESOURCE_MEM,
204 },
205 [2] = {
206 .start = AT91SAM9G45_ID_UDPHS,
207 .end = AT91SAM9G45_ID_UDPHS,
208 .flags = IORESOURCE_IRQ,
209 },
210};
211
212#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \
213 [idx] = { \
214 .name = nam, \
215 .index = idx, \
216 .fifo_size = maxpkt, \
217 .nr_banks = maxbk, \
218 .can_dma = dma, \
219 .can_isoc = isoc, \
220 }
221
222static struct usba_ep_data usba_udc_ep[] __initdata = {
223 EP("ep0", 0, 64, 1, 0, 0),
224 EP("ep1", 1, 1024, 2, 1, 1),
225 EP("ep2", 2, 1024, 2, 1, 1),
226 EP("ep3", 3, 1024, 3, 1, 0),
227 EP("ep4", 4, 1024, 3, 1, 0),
228 EP("ep5", 5, 1024, 3, 1, 1),
229 EP("ep6", 6, 1024, 3, 1, 1),
230};
231
232#undef EP
233
234/*
235 * pdata doesn't have room for any endpoints, so we need to
236 * append room for the ones we need right after it.
237 */
238static struct {
239 struct usba_platform_data pdata;
240 struct usba_ep_data ep[7];
241} usba_udc_data;
242
243static struct platform_device at91_usba_udc_device = {
244 .name = "atmel_usba_udc",
245 .id = -1,
246 .dev = {
247 .platform_data = &usba_udc_data.pdata,
248 },
249 .resource = usba_udc_resources,
250 .num_resources = ARRAY_SIZE(usba_udc_resources),
251};
252
253void __init at91_add_device_usba(struct usba_platform_data *data)
254{
255 usba_udc_data.pdata.vbus_pin = -EINVAL;
256 usba_udc_data.pdata.num_ep = ARRAY_SIZE(usba_udc_ep);
Justin P. Mattock6eab04a2011-04-08 19:49:08 -0700257 memcpy(usba_udc_data.ep, usba_udc_ep, sizeof(usba_udc_ep));
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100258
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800259 if (data && gpio_is_valid(data->vbus_pin)) {
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100260 at91_set_gpio_input(data->vbus_pin, 0);
261 at91_set_deglitch(data->vbus_pin, 1);
262 usba_udc_data.pdata.vbus_pin = data->vbus_pin;
263 }
264
265 /* Pullup pin is handled internally by USB device peripheral */
266
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100267 platform_device_register(&at91_usba_udc_device);
268}
269#else
270void __init at91_add_device_usba(struct usba_platform_data *data) {}
271#endif
272
273
274/* --------------------------------------------------------------------
275 * Ethernet
276 * -------------------------------------------------------------------- */
277
278#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
279static u64 eth_dmamask = DMA_BIT_MASK(32);
Jamie Iles84e0cdb2011-03-08 20:17:06 +0000280static struct macb_platform_data eth_data;
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100281
282static struct resource eth_resources[] = {
283 [0] = {
284 .start = AT91SAM9G45_BASE_EMAC,
285 .end = AT91SAM9G45_BASE_EMAC + SZ_16K - 1,
286 .flags = IORESOURCE_MEM,
287 },
288 [1] = {
289 .start = AT91SAM9G45_ID_EMAC,
290 .end = AT91SAM9G45_ID_EMAC,
291 .flags = IORESOURCE_IRQ,
292 },
293};
294
295static struct platform_device at91sam9g45_eth_device = {
296 .name = "macb",
297 .id = -1,
298 .dev = {
299 .dma_mask = &eth_dmamask,
300 .coherent_dma_mask = DMA_BIT_MASK(32),
301 .platform_data = &eth_data,
302 },
303 .resource = eth_resources,
304 .num_resources = ARRAY_SIZE(eth_resources),
305};
306
Jamie Iles84e0cdb2011-03-08 20:17:06 +0000307void __init at91_add_device_eth(struct macb_platform_data *data)
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100308{
309 if (!data)
310 return;
311
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800312 if (gpio_is_valid(data->phy_irq_pin)) {
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100313 at91_set_gpio_input(data->phy_irq_pin, 0);
314 at91_set_deglitch(data->phy_irq_pin, 1);
315 }
316
317 /* Pins used for MII and RMII */
318 at91_set_A_periph(AT91_PIN_PA17, 0); /* ETXCK_EREFCK */
319 at91_set_A_periph(AT91_PIN_PA15, 0); /* ERXDV */
320 at91_set_A_periph(AT91_PIN_PA12, 0); /* ERX0 */
321 at91_set_A_periph(AT91_PIN_PA13, 0); /* ERX1 */
322 at91_set_A_periph(AT91_PIN_PA16, 0); /* ERXER */
323 at91_set_A_periph(AT91_PIN_PA14, 0); /* ETXEN */
324 at91_set_A_periph(AT91_PIN_PA10, 0); /* ETX0 */
325 at91_set_A_periph(AT91_PIN_PA11, 0); /* ETX1 */
326 at91_set_A_periph(AT91_PIN_PA19, 0); /* EMDIO */
327 at91_set_A_periph(AT91_PIN_PA18, 0); /* EMDC */
328
329 if (!data->is_rmii) {
330 at91_set_B_periph(AT91_PIN_PA29, 0); /* ECRS */
331 at91_set_B_periph(AT91_PIN_PA30, 0); /* ECOL */
332 at91_set_B_periph(AT91_PIN_PA8, 0); /* ERX2 */
333 at91_set_B_periph(AT91_PIN_PA9, 0); /* ERX3 */
334 at91_set_B_periph(AT91_PIN_PA28, 0); /* ERXCK */
335 at91_set_B_periph(AT91_PIN_PA6, 0); /* ETX2 */
336 at91_set_B_periph(AT91_PIN_PA7, 0); /* ETX3 */
337 at91_set_B_periph(AT91_PIN_PA27, 0); /* ETXER */
338 }
339
340 eth_data = *data;
341 platform_device_register(&at91sam9g45_eth_device);
342}
343#else
Jamie Iles84e0cdb2011-03-08 20:17:06 +0000344void __init at91_add_device_eth(struct macb_platform_data *data) {}
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100345#endif
346
347
348/* --------------------------------------------------------------------
Nicolas Ferre75305d72010-10-22 18:27:48 +0200349 * MMC / SD
350 * -------------------------------------------------------------------- */
351
352#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
353static u64 mmc_dmamask = DMA_BIT_MASK(32);
354static struct mci_platform_data mmc0_data, mmc1_data;
355
356static struct resource mmc0_resources[] = {
357 [0] = {
358 .start = AT91SAM9G45_BASE_MCI0,
359 .end = AT91SAM9G45_BASE_MCI0 + SZ_16K - 1,
360 .flags = IORESOURCE_MEM,
361 },
362 [1] = {
363 .start = AT91SAM9G45_ID_MCI0,
364 .end = AT91SAM9G45_ID_MCI0,
365 .flags = IORESOURCE_IRQ,
366 },
367};
368
369static struct platform_device at91sam9g45_mmc0_device = {
370 .name = "atmel_mci",
371 .id = 0,
372 .dev = {
373 .dma_mask = &mmc_dmamask,
374 .coherent_dma_mask = DMA_BIT_MASK(32),
375 .platform_data = &mmc0_data,
376 },
377 .resource = mmc0_resources,
378 .num_resources = ARRAY_SIZE(mmc0_resources),
379};
380
381static struct resource mmc1_resources[] = {
382 [0] = {
383 .start = AT91SAM9G45_BASE_MCI1,
384 .end = AT91SAM9G45_BASE_MCI1 + SZ_16K - 1,
385 .flags = IORESOURCE_MEM,
386 },
387 [1] = {
388 .start = AT91SAM9G45_ID_MCI1,
389 .end = AT91SAM9G45_ID_MCI1,
390 .flags = IORESOURCE_IRQ,
391 },
392};
393
394static struct platform_device at91sam9g45_mmc1_device = {
395 .name = "atmel_mci",
396 .id = 1,
397 .dev = {
398 .dma_mask = &mmc_dmamask,
399 .coherent_dma_mask = DMA_BIT_MASK(32),
400 .platform_data = &mmc1_data,
401 },
402 .resource = mmc1_resources,
403 .num_resources = ARRAY_SIZE(mmc1_resources),
404};
405
406/* Consider only one slot : slot 0 */
407void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
408{
409
410 if (!data)
411 return;
412
413 /* Must have at least one usable slot */
414 if (!data->slot[0].bus_width)
415 return;
416
417#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
418 {
419 struct at_dma_slave *atslave;
420 struct mci_dma_data *alt_atslave;
421
422 alt_atslave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
423 atslave = &alt_atslave->sdata;
424
425 /* DMA slave channel configuration */
426 atslave->dma_dev = &at_hdmac_device.dev;
427 atslave->reg_width = AT_DMA_SLAVE_WIDTH_32BIT;
428 atslave->cfg = ATC_FIFOCFG_HALFFIFO
429 | ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
430 atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
431 if (mmc_id == 0) /* MCI0 */
432 atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0)
433 | ATC_DST_PER(AT_DMA_ID_MCI0);
434
435 else /* MCI1 */
436 atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1)
437 | ATC_DST_PER(AT_DMA_ID_MCI1);
438
439 data->dma_slave = alt_atslave;
440 }
441#endif
442
443
444 /* input/irq */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800445 if (gpio_is_valid(data->slot[0].detect_pin)) {
Nicolas Ferre75305d72010-10-22 18:27:48 +0200446 at91_set_gpio_input(data->slot[0].detect_pin, 1);
447 at91_set_deglitch(data->slot[0].detect_pin, 1);
448 }
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800449 if (gpio_is_valid(data->slot[0].wp_pin))
Nicolas Ferre75305d72010-10-22 18:27:48 +0200450 at91_set_gpio_input(data->slot[0].wp_pin, 1);
451
452 if (mmc_id == 0) { /* MCI0 */
453
454 /* CLK */
455 at91_set_A_periph(AT91_PIN_PA0, 0);
456
457 /* CMD */
458 at91_set_A_periph(AT91_PIN_PA1, 1);
459
460 /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
461 at91_set_A_periph(AT91_PIN_PA2, 1);
462 if (data->slot[0].bus_width == 4) {
463 at91_set_A_periph(AT91_PIN_PA3, 1);
464 at91_set_A_periph(AT91_PIN_PA4, 1);
465 at91_set_A_periph(AT91_PIN_PA5, 1);
466 if (data->slot[0].bus_width == 8) {
467 at91_set_A_periph(AT91_PIN_PA6, 1);
468 at91_set_A_periph(AT91_PIN_PA7, 1);
469 at91_set_A_periph(AT91_PIN_PA8, 1);
470 at91_set_A_periph(AT91_PIN_PA9, 1);
471 }
472 }
473
474 mmc0_data = *data;
Nicolas Ferre75305d72010-10-22 18:27:48 +0200475 platform_device_register(&at91sam9g45_mmc0_device);
476
477 } else { /* MCI1 */
478
479 /* CLK */
480 at91_set_A_periph(AT91_PIN_PA31, 0);
481
482 /* CMD */
483 at91_set_A_periph(AT91_PIN_PA22, 1);
484
485 /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
486 at91_set_A_periph(AT91_PIN_PA23, 1);
487 if (data->slot[0].bus_width == 4) {
488 at91_set_A_periph(AT91_PIN_PA24, 1);
489 at91_set_A_periph(AT91_PIN_PA25, 1);
490 at91_set_A_periph(AT91_PIN_PA26, 1);
491 if (data->slot[0].bus_width == 8) {
492 at91_set_A_periph(AT91_PIN_PA27, 1);
493 at91_set_A_periph(AT91_PIN_PA28, 1);
494 at91_set_A_periph(AT91_PIN_PA29, 1);
495 at91_set_A_periph(AT91_PIN_PA30, 1);
496 }
497 }
498
499 mmc1_data = *data;
Nicolas Ferre75305d72010-10-22 18:27:48 +0200500 platform_device_register(&at91sam9g45_mmc1_device);
501
502 }
503}
504#else
505void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
506#endif
507
508
509/* --------------------------------------------------------------------
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100510 * NAND / SmartMedia
511 * -------------------------------------------------------------------- */
512
513#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
514static struct atmel_nand_data nand_data;
515
516#define NAND_BASE AT91_CHIPSELECT_3
517
518static struct resource nand_resources[] = {
519 [0] = {
520 .start = NAND_BASE,
521 .end = NAND_BASE + SZ_256M - 1,
522 .flags = IORESOURCE_MEM,
523 },
524 [1] = {
Jean-Christophe PLAGNIOL-VILLARDd28edd12011-09-18 09:31:56 +0800525 .start = AT91SAM9G45_BASE_ECC,
526 .end = AT91SAM9G45_BASE_ECC + SZ_512 - 1,
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100527 .flags = IORESOURCE_MEM,
528 }
529};
530
531static struct platform_device at91sam9g45_nand_device = {
532 .name = "atmel_nand",
533 .id = -1,
534 .dev = {
535 .platform_data = &nand_data,
536 },
537 .resource = nand_resources,
538 .num_resources = ARRAY_SIZE(nand_resources),
539};
540
541void __init at91_add_device_nand(struct atmel_nand_data *data)
542{
543 unsigned long csa;
544
545 if (!data)
546 return;
547
548 csa = at91_sys_read(AT91_MATRIX_EBICSA);
549 at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA);
550
551 /* enable pin */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800552 if (gpio_is_valid(data->enable_pin))
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100553 at91_set_gpio_output(data->enable_pin, 1);
554
555 /* ready/busy pin */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800556 if (gpio_is_valid(data->rdy_pin))
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100557 at91_set_gpio_input(data->rdy_pin, 1);
558
559 /* card detect pin */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800560 if (gpio_is_valid(data->det_pin))
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100561 at91_set_gpio_input(data->det_pin, 1);
562
563 nand_data = *data;
564 platform_device_register(&at91sam9g45_nand_device);
565}
566#else
567void __init at91_add_device_nand(struct atmel_nand_data *data) {}
568#endif
569
570
571/* --------------------------------------------------------------------
572 * TWI (i2c)
573 * -------------------------------------------------------------------- */
574
575/*
576 * Prefer the GPIO code since the TWI controller isn't robust
577 * (gets overruns and underruns under load) and can only issue
578 * repeated STARTs in one scenario (the driver doesn't yet handle them).
579 */
580#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
581static struct i2c_gpio_platform_data pdata_i2c0 = {
582 .sda_pin = AT91_PIN_PA20,
583 .sda_is_open_drain = 1,
584 .scl_pin = AT91_PIN_PA21,
585 .scl_is_open_drain = 1,
Peter Korsgaard1d5b4c02010-09-22 21:29:59 +0100586 .udelay = 5, /* ~100 kHz */
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100587};
588
589static struct platform_device at91sam9g45_twi0_device = {
590 .name = "i2c-gpio",
591 .id = 0,
592 .dev.platform_data = &pdata_i2c0,
593};
594
595static struct i2c_gpio_platform_data pdata_i2c1 = {
596 .sda_pin = AT91_PIN_PB10,
597 .sda_is_open_drain = 1,
598 .scl_pin = AT91_PIN_PB11,
599 .scl_is_open_drain = 1,
Peter Korsgaard1d5b4c02010-09-22 21:29:59 +0100600 .udelay = 5, /* ~100 kHz */
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100601};
602
603static struct platform_device at91sam9g45_twi1_device = {
604 .name = "i2c-gpio",
605 .id = 1,
606 .dev.platform_data = &pdata_i2c1,
607};
608
609void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices)
610{
611 i2c_register_board_info(i2c_id, devices, nr_devices);
612
613 if (i2c_id == 0) {
614 at91_set_GPIO_periph(AT91_PIN_PA20, 1); /* TWD (SDA) */
615 at91_set_multi_drive(AT91_PIN_PA20, 1);
616
617 at91_set_GPIO_periph(AT91_PIN_PA21, 1); /* TWCK (SCL) */
618 at91_set_multi_drive(AT91_PIN_PA21, 1);
619
620 platform_device_register(&at91sam9g45_twi0_device);
621 } else {
622 at91_set_GPIO_periph(AT91_PIN_PB10, 1); /* TWD (SDA) */
623 at91_set_multi_drive(AT91_PIN_PB10, 1);
624
625 at91_set_GPIO_periph(AT91_PIN_PB11, 1); /* TWCK (SCL) */
626 at91_set_multi_drive(AT91_PIN_PB11, 1);
627
628 platform_device_register(&at91sam9g45_twi1_device);
629 }
630}
631
632#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
633static struct resource twi0_resources[] = {
634 [0] = {
635 .start = AT91SAM9G45_BASE_TWI0,
636 .end = AT91SAM9G45_BASE_TWI0 + SZ_16K - 1,
637 .flags = IORESOURCE_MEM,
638 },
639 [1] = {
640 .start = AT91SAM9G45_ID_TWI0,
641 .end = AT91SAM9G45_ID_TWI0,
642 .flags = IORESOURCE_IRQ,
643 },
644};
645
646static struct platform_device at91sam9g45_twi0_device = {
647 .name = "at91_i2c",
648 .id = 0,
649 .resource = twi0_resources,
650 .num_resources = ARRAY_SIZE(twi0_resources),
651};
652
653static struct resource twi1_resources[] = {
654 [0] = {
655 .start = AT91SAM9G45_BASE_TWI1,
656 .end = AT91SAM9G45_BASE_TWI1 + SZ_16K - 1,
657 .flags = IORESOURCE_MEM,
658 },
659 [1] = {
660 .start = AT91SAM9G45_ID_TWI1,
661 .end = AT91SAM9G45_ID_TWI1,
662 .flags = IORESOURCE_IRQ,
663 },
664};
665
666static struct platform_device at91sam9g45_twi1_device = {
667 .name = "at91_i2c",
668 .id = 1,
669 .resource = twi1_resources,
670 .num_resources = ARRAY_SIZE(twi1_resources),
671};
672
673void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices)
674{
675 i2c_register_board_info(i2c_id, devices, nr_devices);
676
677 /* pins used for TWI interface */
678 if (i2c_id == 0) {
679 at91_set_A_periph(AT91_PIN_PA20, 0); /* TWD */
680 at91_set_multi_drive(AT91_PIN_PA20, 1);
681
682 at91_set_A_periph(AT91_PIN_PA21, 0); /* TWCK */
683 at91_set_multi_drive(AT91_PIN_PA21, 1);
684
685 platform_device_register(&at91sam9g45_twi0_device);
686 } else {
687 at91_set_A_periph(AT91_PIN_PB10, 0); /* TWD */
688 at91_set_multi_drive(AT91_PIN_PB10, 1);
689
690 at91_set_A_periph(AT91_PIN_PB11, 0); /* TWCK */
691 at91_set_multi_drive(AT91_PIN_PB11, 1);
692
693 platform_device_register(&at91sam9g45_twi1_device);
694 }
695}
696#else
697void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices) {}
698#endif
699
700
701/* --------------------------------------------------------------------
702 * SPI
703 * -------------------------------------------------------------------- */
704
705#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
706static u64 spi_dmamask = DMA_BIT_MASK(32);
707
708static struct resource spi0_resources[] = {
709 [0] = {
710 .start = AT91SAM9G45_BASE_SPI0,
711 .end = AT91SAM9G45_BASE_SPI0 + SZ_16K - 1,
712 .flags = IORESOURCE_MEM,
713 },
714 [1] = {
715 .start = AT91SAM9G45_ID_SPI0,
716 .end = AT91SAM9G45_ID_SPI0,
717 .flags = IORESOURCE_IRQ,
718 },
719};
720
721static struct platform_device at91sam9g45_spi0_device = {
722 .name = "atmel_spi",
723 .id = 0,
724 .dev = {
725 .dma_mask = &spi_dmamask,
726 .coherent_dma_mask = DMA_BIT_MASK(32),
727 },
728 .resource = spi0_resources,
729 .num_resources = ARRAY_SIZE(spi0_resources),
730};
731
732static const unsigned spi0_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PB18, AT91_PIN_PB19, AT91_PIN_PD27 };
733
734static struct resource spi1_resources[] = {
735 [0] = {
736 .start = AT91SAM9G45_BASE_SPI1,
737 .end = AT91SAM9G45_BASE_SPI1 + SZ_16K - 1,
738 .flags = IORESOURCE_MEM,
739 },
740 [1] = {
741 .start = AT91SAM9G45_ID_SPI1,
742 .end = AT91SAM9G45_ID_SPI1,
743 .flags = IORESOURCE_IRQ,
744 },
745};
746
747static struct platform_device at91sam9g45_spi1_device = {
748 .name = "atmel_spi",
749 .id = 1,
750 .dev = {
751 .dma_mask = &spi_dmamask,
752 .coherent_dma_mask = DMA_BIT_MASK(32),
753 },
754 .resource = spi1_resources,
755 .num_resources = ARRAY_SIZE(spi1_resources),
756};
757
758static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB17, AT91_PIN_PD28, AT91_PIN_PD18, AT91_PIN_PD19 };
759
760void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
761{
762 int i;
763 unsigned long cs_pin;
764 short enable_spi0 = 0;
765 short enable_spi1 = 0;
766
767 /* Choose SPI chip-selects */
768 for (i = 0; i < nr_devices; i++) {
769 if (devices[i].controller_data)
770 cs_pin = (unsigned long) devices[i].controller_data;
771 else if (devices[i].bus_num == 0)
772 cs_pin = spi0_standard_cs[devices[i].chip_select];
773 else
774 cs_pin = spi1_standard_cs[devices[i].chip_select];
775
776 if (devices[i].bus_num == 0)
777 enable_spi0 = 1;
778 else
779 enable_spi1 = 1;
780
781 /* enable chip-select pin */
782 at91_set_gpio_output(cs_pin, 1);
783
784 /* pass chip-select pin to driver */
785 devices[i].controller_data = (void *) cs_pin;
786 }
787
788 spi_register_board_info(devices, nr_devices);
789
790 /* Configure SPI bus(es) */
791 if (enable_spi0) {
792 at91_set_A_periph(AT91_PIN_PB0, 0); /* SPI0_MISO */
793 at91_set_A_periph(AT91_PIN_PB1, 0); /* SPI0_MOSI */
794 at91_set_A_periph(AT91_PIN_PB2, 0); /* SPI0_SPCK */
795
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100796 platform_device_register(&at91sam9g45_spi0_device);
797 }
798 if (enable_spi1) {
799 at91_set_A_periph(AT91_PIN_PB14, 0); /* SPI1_MISO */
800 at91_set_A_periph(AT91_PIN_PB15, 0); /* SPI1_MOSI */
801 at91_set_A_periph(AT91_PIN_PB16, 0); /* SPI1_SPCK */
802
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100803 platform_device_register(&at91sam9g45_spi1_device);
804 }
805}
806#else
807void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
808#endif
809
810
811/* --------------------------------------------------------------------
Nicolas Ferre378ac652009-09-18 16:14:22 +0100812 * AC97
813 * -------------------------------------------------------------------- */
814
815#if defined(CONFIG_SND_ATMEL_AC97C) || defined(CONFIG_SND_ATMEL_AC97C_MODULE)
816static u64 ac97_dmamask = DMA_BIT_MASK(32);
817static struct ac97c_platform_data ac97_data;
818
819static struct resource ac97_resources[] = {
820 [0] = {
821 .start = AT91SAM9G45_BASE_AC97C,
822 .end = AT91SAM9G45_BASE_AC97C + SZ_16K - 1,
823 .flags = IORESOURCE_MEM,
824 },
825 [1] = {
826 .start = AT91SAM9G45_ID_AC97C,
827 .end = AT91SAM9G45_ID_AC97C,
828 .flags = IORESOURCE_IRQ,
829 },
830};
831
832static struct platform_device at91sam9g45_ac97_device = {
833 .name = "atmel_ac97c",
834 .id = 0,
835 .dev = {
836 .dma_mask = &ac97_dmamask,
837 .coherent_dma_mask = DMA_BIT_MASK(32),
838 .platform_data = &ac97_data,
839 },
840 .resource = ac97_resources,
841 .num_resources = ARRAY_SIZE(ac97_resources),
842};
843
844void __init at91_add_device_ac97(struct ac97c_platform_data *data)
845{
846 if (!data)
847 return;
848
849 at91_set_A_periph(AT91_PIN_PD8, 0); /* AC97FS */
850 at91_set_A_periph(AT91_PIN_PD9, 0); /* AC97CK */
851 at91_set_A_periph(AT91_PIN_PD7, 0); /* AC97TX */
852 at91_set_A_periph(AT91_PIN_PD6, 0); /* AC97RX */
853
854 /* reset */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800855 if (gpio_is_valid(data->reset_pin))
Nicolas Ferre378ac652009-09-18 16:14:22 +0100856 at91_set_gpio_output(data->reset_pin, 0);
857
858 ac97_data = *data;
859 platform_device_register(&at91sam9g45_ac97_device);
860}
861#else
862void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
863#endif
864
865
866/* --------------------------------------------------------------------
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100867 * LCD Controller
868 * -------------------------------------------------------------------- */
869
870#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
871static u64 lcdc_dmamask = DMA_BIT_MASK(32);
872static struct atmel_lcdfb_info lcdc_data;
873
874static struct resource lcdc_resources[] = {
875 [0] = {
876 .start = AT91SAM9G45_LCDC_BASE,
877 .end = AT91SAM9G45_LCDC_BASE + SZ_4K - 1,
878 .flags = IORESOURCE_MEM,
879 },
880 [1] = {
881 .start = AT91SAM9G45_ID_LCDC,
882 .end = AT91SAM9G45_ID_LCDC,
883 .flags = IORESOURCE_IRQ,
884 },
885};
886
887static struct platform_device at91_lcdc_device = {
888 .name = "atmel_lcdfb",
889 .id = 0,
890 .dev = {
891 .dma_mask = &lcdc_dmamask,
892 .coherent_dma_mask = DMA_BIT_MASK(32),
893 .platform_data = &lcdc_data,
894 },
895 .resource = lcdc_resources,
896 .num_resources = ARRAY_SIZE(lcdc_resources),
897};
898
899void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
900{
901 if (!data)
902 return;
903
904 at91_set_A_periph(AT91_PIN_PE0, 0); /* LCDDPWR */
905
906 at91_set_A_periph(AT91_PIN_PE2, 0); /* LCDCC */
907 at91_set_A_periph(AT91_PIN_PE3, 0); /* LCDVSYNC */
908 at91_set_A_periph(AT91_PIN_PE4, 0); /* LCDHSYNC */
909 at91_set_A_periph(AT91_PIN_PE5, 0); /* LCDDOTCK */
910 at91_set_A_periph(AT91_PIN_PE6, 0); /* LCDDEN */
911 at91_set_A_periph(AT91_PIN_PE7, 0); /* LCDD0 */
912 at91_set_A_periph(AT91_PIN_PE8, 0); /* LCDD1 */
913 at91_set_A_periph(AT91_PIN_PE9, 0); /* LCDD2 */
914 at91_set_A_periph(AT91_PIN_PE10, 0); /* LCDD3 */
915 at91_set_A_periph(AT91_PIN_PE11, 0); /* LCDD4 */
916 at91_set_A_periph(AT91_PIN_PE12, 0); /* LCDD5 */
917 at91_set_A_periph(AT91_PIN_PE13, 0); /* LCDD6 */
918 at91_set_A_periph(AT91_PIN_PE14, 0); /* LCDD7 */
919 at91_set_A_periph(AT91_PIN_PE15, 0); /* LCDD8 */
920 at91_set_A_periph(AT91_PIN_PE16, 0); /* LCDD9 */
921 at91_set_A_periph(AT91_PIN_PE17, 0); /* LCDD10 */
922 at91_set_A_periph(AT91_PIN_PE18, 0); /* LCDD11 */
923 at91_set_A_periph(AT91_PIN_PE19, 0); /* LCDD12 */
924 at91_set_A_periph(AT91_PIN_PE20, 0); /* LCDD13 */
925 at91_set_A_periph(AT91_PIN_PE21, 0); /* LCDD14 */
926 at91_set_A_periph(AT91_PIN_PE22, 0); /* LCDD15 */
927 at91_set_A_periph(AT91_PIN_PE23, 0); /* LCDD16 */
928 at91_set_A_periph(AT91_PIN_PE24, 0); /* LCDD17 */
929 at91_set_A_periph(AT91_PIN_PE25, 0); /* LCDD18 */
930 at91_set_A_periph(AT91_PIN_PE26, 0); /* LCDD19 */
931 at91_set_A_periph(AT91_PIN_PE27, 0); /* LCDD20 */
932 at91_set_A_periph(AT91_PIN_PE28, 0); /* LCDD21 */
933 at91_set_A_periph(AT91_PIN_PE29, 0); /* LCDD22 */
934 at91_set_A_periph(AT91_PIN_PE30, 0); /* LCDD23 */
935
936 lcdc_data = *data;
937 platform_device_register(&at91_lcdc_device);
938}
939#else
940void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
941#endif
942
943
944/* --------------------------------------------------------------------
945 * Timer/Counter block
946 * -------------------------------------------------------------------- */
947
948#ifdef CONFIG_ATMEL_TCLIB
949static struct resource tcb0_resources[] = {
950 [0] = {
951 .start = AT91SAM9G45_BASE_TCB0,
952 .end = AT91SAM9G45_BASE_TCB0 + SZ_16K - 1,
953 .flags = IORESOURCE_MEM,
954 },
955 [1] = {
956 .start = AT91SAM9G45_ID_TCB,
957 .end = AT91SAM9G45_ID_TCB,
958 .flags = IORESOURCE_IRQ,
959 },
960};
961
962static struct platform_device at91sam9g45_tcb0_device = {
963 .name = "atmel_tcb",
964 .id = 0,
965 .resource = tcb0_resources,
966 .num_resources = ARRAY_SIZE(tcb0_resources),
967};
968
969/* TCB1 begins with TC3 */
970static struct resource tcb1_resources[] = {
971 [0] = {
972 .start = AT91SAM9G45_BASE_TCB1,
973 .end = AT91SAM9G45_BASE_TCB1 + SZ_16K - 1,
974 .flags = IORESOURCE_MEM,
975 },
976 [1] = {
977 .start = AT91SAM9G45_ID_TCB,
978 .end = AT91SAM9G45_ID_TCB,
979 .flags = IORESOURCE_IRQ,
980 },
981};
982
983static struct platform_device at91sam9g45_tcb1_device = {
984 .name = "atmel_tcb",
985 .id = 1,
986 .resource = tcb1_resources,
987 .num_resources = ARRAY_SIZE(tcb1_resources),
988};
989
990static void __init at91_add_device_tc(void)
991{
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100992 platform_device_register(&at91sam9g45_tcb0_device);
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100993 platform_device_register(&at91sam9g45_tcb1_device);
994}
995#else
996static void __init at91_add_device_tc(void) { }
997#endif
998
999
1000/* --------------------------------------------------------------------
1001 * RTC
1002 * -------------------------------------------------------------------- */
1003
1004#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
Jean-Christophe PLAGNIOL-VILLARDd28bdfc2011-11-14 14:24:53 +08001005static struct resource rtc_resources[] = {
1006 [0] = {
1007 .start = AT91SAM9G45_BASE_RTC,
1008 .end = AT91SAM9G45_BASE_RTC + SZ_256 - 1,
1009 .flags = IORESOURCE_MEM,
1010 },
1011 [1] = {
1012 .start = AT91_ID_SYS,
1013 .end = AT91_ID_SYS,
1014 .flags = IORESOURCE_IRQ,
1015 },
1016};
1017
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001018static struct platform_device at91sam9g45_rtc_device = {
1019 .name = "at91_rtc",
1020 .id = -1,
Jean-Christophe PLAGNIOL-VILLARDd28bdfc2011-11-14 14:24:53 +08001021 .resource = rtc_resources,
1022 .num_resources = ARRAY_SIZE(rtc_resources),
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001023};
1024
1025static void __init at91_add_device_rtc(void)
1026{
1027 platform_device_register(&at91sam9g45_rtc_device);
1028}
1029#else
1030static void __init at91_add_device_rtc(void) {}
1031#endif
1032
1033
1034/* --------------------------------------------------------------------
Nicolas Ferre985f37f2009-11-19 09:32:52 -08001035 * Touchscreen
1036 * -------------------------------------------------------------------- */
1037
1038#if defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) || defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC_MODULE)
1039static u64 tsadcc_dmamask = DMA_BIT_MASK(32);
1040static struct at91_tsadcc_data tsadcc_data;
1041
1042static struct resource tsadcc_resources[] = {
1043 [0] = {
1044 .start = AT91SAM9G45_BASE_TSC,
1045 .end = AT91SAM9G45_BASE_TSC + SZ_16K - 1,
1046 .flags = IORESOURCE_MEM,
1047 },
1048 [1] = {
1049 .start = AT91SAM9G45_ID_TSC,
1050 .end = AT91SAM9G45_ID_TSC,
1051 .flags = IORESOURCE_IRQ,
1052 }
1053};
1054
1055static struct platform_device at91sam9g45_tsadcc_device = {
1056 .name = "atmel_tsadcc",
1057 .id = -1,
1058 .dev = {
1059 .dma_mask = &tsadcc_dmamask,
1060 .coherent_dma_mask = DMA_BIT_MASK(32),
1061 .platform_data = &tsadcc_data,
1062 },
1063 .resource = tsadcc_resources,
1064 .num_resources = ARRAY_SIZE(tsadcc_resources),
1065};
1066
1067void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data)
1068{
1069 if (!data)
1070 return;
1071
1072 at91_set_gpio_input(AT91_PIN_PD20, 0); /* AD0_XR */
1073 at91_set_gpio_input(AT91_PIN_PD21, 0); /* AD1_XL */
1074 at91_set_gpio_input(AT91_PIN_PD22, 0); /* AD2_YT */
1075 at91_set_gpio_input(AT91_PIN_PD23, 0); /* AD3_TB */
1076
1077 tsadcc_data = *data;
1078 platform_device_register(&at91sam9g45_tsadcc_device);
1079}
1080#else
1081void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
1082#endif
1083
1084
1085/* --------------------------------------------------------------------
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001086 * RTT
1087 * -------------------------------------------------------------------- */
1088
1089static struct resource rtt_resources[] = {
1090 {
Jean-Christophe PLAGNIOL-VILLARDeab5fd62011-09-18 10:12:00 +08001091 .start = AT91SAM9G45_BASE_RTT,
1092 .end = AT91SAM9G45_BASE_RTT + SZ_16 - 1,
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001093 .flags = IORESOURCE_MEM,
1094 }
1095};
1096
1097static struct platform_device at91sam9g45_rtt_device = {
1098 .name = "at91_rtt",
1099 .id = 0,
1100 .resource = rtt_resources,
1101 .num_resources = ARRAY_SIZE(rtt_resources),
1102};
1103
1104static void __init at91_add_device_rtt(void)
1105{
1106 platform_device_register(&at91sam9g45_rtt_device);
1107}
1108
1109
1110/* --------------------------------------------------------------------
Peter Korsgaard237a62a2011-10-06 17:41:33 +02001111 * TRNG
1112 * -------------------------------------------------------------------- */
1113
1114#if defined(CONFIG_HW_RANDOM_ATMEL) || defined(CONFIG_HW_RANDOM_ATMEL_MODULE)
1115static struct resource trng_resources[] = {
1116 {
1117 .start = AT91SAM9G45_BASE_TRNG,
1118 .end = AT91SAM9G45_BASE_TRNG + SZ_16K - 1,
1119 .flags = IORESOURCE_MEM,
1120 },
1121};
1122
1123static struct platform_device at91sam9g45_trng_device = {
1124 .name = "atmel-trng",
1125 .id = -1,
1126 .resource = trng_resources,
1127 .num_resources = ARRAY_SIZE(trng_resources),
1128};
1129
1130static void __init at91_add_device_trng(void)
1131{
1132 platform_device_register(&at91sam9g45_trng_device);
1133}
1134#else
1135static void __init at91_add_device_trng(void) {}
1136#endif
1137
1138/* --------------------------------------------------------------------
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001139 * Watchdog
1140 * -------------------------------------------------------------------- */
1141
Yegor Yefremov47263742009-10-20 08:39:41 +01001142#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
Jean-Christophe PLAGNIOL-VILLARDc1c30a22011-11-02 01:43:31 +08001143static struct resource wdt_resources[] = {
1144 {
1145 .start = AT91SAM9G45_BASE_WDT,
1146 .end = AT91SAM9G45_BASE_WDT + SZ_16 - 1,
1147 .flags = IORESOURCE_MEM,
1148 }
1149};
1150
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001151static struct platform_device at91sam9g45_wdt_device = {
1152 .name = "at91_wdt",
1153 .id = -1,
Jean-Christophe PLAGNIOL-VILLARDc1c30a22011-11-02 01:43:31 +08001154 .resource = wdt_resources,
1155 .num_resources = ARRAY_SIZE(wdt_resources),
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001156};
1157
1158static void __init at91_add_device_watchdog(void)
1159{
1160 platform_device_register(&at91sam9g45_wdt_device);
1161}
1162#else
1163static void __init at91_add_device_watchdog(void) {}
1164#endif
1165
1166
1167/* --------------------------------------------------------------------
1168 * PWM
1169 * --------------------------------------------------------------------*/
1170
1171#if defined(CONFIG_ATMEL_PWM) || defined(CONFIG_ATMEL_PWM_MODULE)
1172static u32 pwm_mask;
1173
1174static struct resource pwm_resources[] = {
1175 [0] = {
1176 .start = AT91SAM9G45_BASE_PWMC,
1177 .end = AT91SAM9G45_BASE_PWMC + SZ_16K - 1,
1178 .flags = IORESOURCE_MEM,
1179 },
1180 [1] = {
1181 .start = AT91SAM9G45_ID_PWMC,
1182 .end = AT91SAM9G45_ID_PWMC,
1183 .flags = IORESOURCE_IRQ,
1184 },
1185};
1186
1187static struct platform_device at91sam9g45_pwm0_device = {
1188 .name = "atmel_pwm",
1189 .id = -1,
1190 .dev = {
1191 .platform_data = &pwm_mask,
1192 },
1193 .resource = pwm_resources,
1194 .num_resources = ARRAY_SIZE(pwm_resources),
1195};
1196
1197void __init at91_add_device_pwm(u32 mask)
1198{
1199 if (mask & (1 << AT91_PWM0))
1200 at91_set_B_periph(AT91_PIN_PD24, 1); /* enable PWM0 */
1201
1202 if (mask & (1 << AT91_PWM1))
1203 at91_set_B_periph(AT91_PIN_PD31, 1); /* enable PWM1 */
1204
1205 if (mask & (1 << AT91_PWM2))
1206 at91_set_B_periph(AT91_PIN_PD26, 1); /* enable PWM2 */
1207
1208 if (mask & (1 << AT91_PWM3))
1209 at91_set_B_periph(AT91_PIN_PD0, 1); /* enable PWM3 */
1210
1211 pwm_mask = mask;
1212
1213 platform_device_register(&at91sam9g45_pwm0_device);
1214}
1215#else
1216void __init at91_add_device_pwm(u32 mask) {}
1217#endif
1218
1219
1220/* --------------------------------------------------------------------
1221 * SSC -- Synchronous Serial Controller
1222 * -------------------------------------------------------------------- */
1223
1224#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
1225static u64 ssc0_dmamask = DMA_BIT_MASK(32);
1226
1227static struct resource ssc0_resources[] = {
1228 [0] = {
1229 .start = AT91SAM9G45_BASE_SSC0,
1230 .end = AT91SAM9G45_BASE_SSC0 + SZ_16K - 1,
1231 .flags = IORESOURCE_MEM,
1232 },
1233 [1] = {
1234 .start = AT91SAM9G45_ID_SSC0,
1235 .end = AT91SAM9G45_ID_SSC0,
1236 .flags = IORESOURCE_IRQ,
1237 },
1238};
1239
1240static struct platform_device at91sam9g45_ssc0_device = {
1241 .name = "ssc",
1242 .id = 0,
1243 .dev = {
1244 .dma_mask = &ssc0_dmamask,
1245 .coherent_dma_mask = DMA_BIT_MASK(32),
1246 },
1247 .resource = ssc0_resources,
1248 .num_resources = ARRAY_SIZE(ssc0_resources),
1249};
1250
1251static inline void configure_ssc0_pins(unsigned pins)
1252{
1253 if (pins & ATMEL_SSC_TF)
1254 at91_set_A_periph(AT91_PIN_PD1, 1);
1255 if (pins & ATMEL_SSC_TK)
1256 at91_set_A_periph(AT91_PIN_PD0, 1);
1257 if (pins & ATMEL_SSC_TD)
1258 at91_set_A_periph(AT91_PIN_PD2, 1);
1259 if (pins & ATMEL_SSC_RD)
1260 at91_set_A_periph(AT91_PIN_PD3, 1);
1261 if (pins & ATMEL_SSC_RK)
1262 at91_set_A_periph(AT91_PIN_PD4, 1);
1263 if (pins & ATMEL_SSC_RF)
1264 at91_set_A_periph(AT91_PIN_PD5, 1);
1265}
1266
1267static u64 ssc1_dmamask = DMA_BIT_MASK(32);
1268
1269static struct resource ssc1_resources[] = {
1270 [0] = {
1271 .start = AT91SAM9G45_BASE_SSC1,
1272 .end = AT91SAM9G45_BASE_SSC1 + SZ_16K - 1,
1273 .flags = IORESOURCE_MEM,
1274 },
1275 [1] = {
1276 .start = AT91SAM9G45_ID_SSC1,
1277 .end = AT91SAM9G45_ID_SSC1,
1278 .flags = IORESOURCE_IRQ,
1279 },
1280};
1281
1282static struct platform_device at91sam9g45_ssc1_device = {
1283 .name = "ssc",
1284 .id = 1,
1285 .dev = {
1286 .dma_mask = &ssc1_dmamask,
1287 .coherent_dma_mask = DMA_BIT_MASK(32),
1288 },
1289 .resource = ssc1_resources,
1290 .num_resources = ARRAY_SIZE(ssc1_resources),
1291};
1292
1293static inline void configure_ssc1_pins(unsigned pins)
1294{
1295 if (pins & ATMEL_SSC_TF)
1296 at91_set_A_periph(AT91_PIN_PD14, 1);
1297 if (pins & ATMEL_SSC_TK)
1298 at91_set_A_periph(AT91_PIN_PD12, 1);
1299 if (pins & ATMEL_SSC_TD)
1300 at91_set_A_periph(AT91_PIN_PD10, 1);
1301 if (pins & ATMEL_SSC_RD)
1302 at91_set_A_periph(AT91_PIN_PD11, 1);
1303 if (pins & ATMEL_SSC_RK)
1304 at91_set_A_periph(AT91_PIN_PD13, 1);
1305 if (pins & ATMEL_SSC_RF)
1306 at91_set_A_periph(AT91_PIN_PD15, 1);
1307}
1308
1309/*
1310 * SSC controllers are accessed through library code, instead of any
1311 * kind of all-singing/all-dancing driver. For example one could be
1312 * used by a particular I2S audio codec's driver, while another one
1313 * on the same system might be used by a custom data capture driver.
1314 */
1315void __init at91_add_device_ssc(unsigned id, unsigned pins)
1316{
1317 struct platform_device *pdev;
1318
1319 /*
1320 * NOTE: caller is responsible for passing information matching
1321 * "pins" to whatever will be using each particular controller.
1322 */
1323 switch (id) {
1324 case AT91SAM9G45_ID_SSC0:
1325 pdev = &at91sam9g45_ssc0_device;
1326 configure_ssc0_pins(pins);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001327 break;
1328 case AT91SAM9G45_ID_SSC1:
1329 pdev = &at91sam9g45_ssc1_device;
1330 configure_ssc1_pins(pins);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001331 break;
1332 default:
1333 return;
1334 }
1335
1336 platform_device_register(pdev);
1337}
1338
1339#else
1340void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
1341#endif
1342
1343
1344/* --------------------------------------------------------------------
1345 * UART
1346 * -------------------------------------------------------------------- */
1347
1348#if defined(CONFIG_SERIAL_ATMEL)
1349static struct resource dbgu_resources[] = {
1350 [0] = {
Jean-Christophe PLAGNIOL-VILLARD13079a72011-11-02 01:43:31 +08001351 .start = AT91SAM9G45_BASE_DBGU,
1352 .end = AT91SAM9G45_BASE_DBGU + SZ_512 - 1,
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001353 .flags = IORESOURCE_MEM,
1354 },
1355 [1] = {
1356 .start = AT91_ID_SYS,
1357 .end = AT91_ID_SYS,
1358 .flags = IORESOURCE_IRQ,
1359 },
1360};
1361
1362static struct atmel_uart_data dbgu_data = {
1363 .use_dma_tx = 0,
1364 .use_dma_rx = 0,
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001365};
1366
1367static u64 dbgu_dmamask = DMA_BIT_MASK(32);
1368
1369static struct platform_device at91sam9g45_dbgu_device = {
1370 .name = "atmel_usart",
1371 .id = 0,
1372 .dev = {
1373 .dma_mask = &dbgu_dmamask,
1374 .coherent_dma_mask = DMA_BIT_MASK(32),
1375 .platform_data = &dbgu_data,
1376 },
1377 .resource = dbgu_resources,
1378 .num_resources = ARRAY_SIZE(dbgu_resources),
1379};
1380
1381static inline void configure_dbgu_pins(void)
1382{
1383 at91_set_A_periph(AT91_PIN_PB12, 0); /* DRXD */
1384 at91_set_A_periph(AT91_PIN_PB13, 1); /* DTXD */
1385}
1386
1387static struct resource uart0_resources[] = {
1388 [0] = {
1389 .start = AT91SAM9G45_BASE_US0,
1390 .end = AT91SAM9G45_BASE_US0 + SZ_16K - 1,
1391 .flags = IORESOURCE_MEM,
1392 },
1393 [1] = {
1394 .start = AT91SAM9G45_ID_US0,
1395 .end = AT91SAM9G45_ID_US0,
1396 .flags = IORESOURCE_IRQ,
1397 },
1398};
1399
1400static struct atmel_uart_data uart0_data = {
1401 .use_dma_tx = 1,
1402 .use_dma_rx = 1,
1403};
1404
1405static u64 uart0_dmamask = DMA_BIT_MASK(32);
1406
1407static struct platform_device at91sam9g45_uart0_device = {
1408 .name = "atmel_usart",
1409 .id = 1,
1410 .dev = {
1411 .dma_mask = &uart0_dmamask,
1412 .coherent_dma_mask = DMA_BIT_MASK(32),
1413 .platform_data = &uart0_data,
1414 },
1415 .resource = uart0_resources,
1416 .num_resources = ARRAY_SIZE(uart0_resources),
1417};
1418
1419static inline void configure_usart0_pins(unsigned pins)
1420{
1421 at91_set_A_periph(AT91_PIN_PB19, 1); /* TXD0 */
1422 at91_set_A_periph(AT91_PIN_PB18, 0); /* RXD0 */
1423
1424 if (pins & ATMEL_UART_RTS)
1425 at91_set_B_periph(AT91_PIN_PB17, 0); /* RTS0 */
1426 if (pins & ATMEL_UART_CTS)
1427 at91_set_B_periph(AT91_PIN_PB15, 0); /* CTS0 */
1428}
1429
1430static struct resource uart1_resources[] = {
1431 [0] = {
1432 .start = AT91SAM9G45_BASE_US1,
1433 .end = AT91SAM9G45_BASE_US1 + SZ_16K - 1,
1434 .flags = IORESOURCE_MEM,
1435 },
1436 [1] = {
1437 .start = AT91SAM9G45_ID_US1,
1438 .end = AT91SAM9G45_ID_US1,
1439 .flags = IORESOURCE_IRQ,
1440 },
1441};
1442
1443static struct atmel_uart_data uart1_data = {
1444 .use_dma_tx = 1,
1445 .use_dma_rx = 1,
1446};
1447
1448static u64 uart1_dmamask = DMA_BIT_MASK(32);
1449
1450static struct platform_device at91sam9g45_uart1_device = {
1451 .name = "atmel_usart",
1452 .id = 2,
1453 .dev = {
1454 .dma_mask = &uart1_dmamask,
1455 .coherent_dma_mask = DMA_BIT_MASK(32),
1456 .platform_data = &uart1_data,
1457 },
1458 .resource = uart1_resources,
1459 .num_resources = ARRAY_SIZE(uart1_resources),
1460};
1461
1462static inline void configure_usart1_pins(unsigned pins)
1463{
1464 at91_set_A_periph(AT91_PIN_PB4, 1); /* TXD1 */
1465 at91_set_A_periph(AT91_PIN_PB5, 0); /* RXD1 */
1466
1467 if (pins & ATMEL_UART_RTS)
1468 at91_set_A_periph(AT91_PIN_PD16, 0); /* RTS1 */
1469 if (pins & ATMEL_UART_CTS)
1470 at91_set_A_periph(AT91_PIN_PD17, 0); /* CTS1 */
1471}
1472
1473static struct resource uart2_resources[] = {
1474 [0] = {
1475 .start = AT91SAM9G45_BASE_US2,
1476 .end = AT91SAM9G45_BASE_US2 + SZ_16K - 1,
1477 .flags = IORESOURCE_MEM,
1478 },
1479 [1] = {
1480 .start = AT91SAM9G45_ID_US2,
1481 .end = AT91SAM9G45_ID_US2,
1482 .flags = IORESOURCE_IRQ,
1483 },
1484};
1485
1486static struct atmel_uart_data uart2_data = {
1487 .use_dma_tx = 1,
1488 .use_dma_rx = 1,
1489};
1490
1491static u64 uart2_dmamask = DMA_BIT_MASK(32);
1492
1493static struct platform_device at91sam9g45_uart2_device = {
1494 .name = "atmel_usart",
1495 .id = 3,
1496 .dev = {
1497 .dma_mask = &uart2_dmamask,
1498 .coherent_dma_mask = DMA_BIT_MASK(32),
1499 .platform_data = &uart2_data,
1500 },
1501 .resource = uart2_resources,
1502 .num_resources = ARRAY_SIZE(uart2_resources),
1503};
1504
1505static inline void configure_usart2_pins(unsigned pins)
1506{
1507 at91_set_A_periph(AT91_PIN_PB6, 1); /* TXD2 */
1508 at91_set_A_periph(AT91_PIN_PB7, 0); /* RXD2 */
1509
1510 if (pins & ATMEL_UART_RTS)
1511 at91_set_B_periph(AT91_PIN_PC9, 0); /* RTS2 */
1512 if (pins & ATMEL_UART_CTS)
1513 at91_set_B_periph(AT91_PIN_PC11, 0); /* CTS2 */
1514}
1515
1516static struct resource uart3_resources[] = {
1517 [0] = {
1518 .start = AT91SAM9G45_BASE_US3,
1519 .end = AT91SAM9G45_BASE_US3 + SZ_16K - 1,
1520 .flags = IORESOURCE_MEM,
1521 },
1522 [1] = {
1523 .start = AT91SAM9G45_ID_US3,
1524 .end = AT91SAM9G45_ID_US3,
1525 .flags = IORESOURCE_IRQ,
1526 },
1527};
1528
1529static struct atmel_uart_data uart3_data = {
1530 .use_dma_tx = 1,
1531 .use_dma_rx = 1,
1532};
1533
1534static u64 uart3_dmamask = DMA_BIT_MASK(32);
1535
1536static struct platform_device at91sam9g45_uart3_device = {
1537 .name = "atmel_usart",
1538 .id = 4,
1539 .dev = {
1540 .dma_mask = &uart3_dmamask,
1541 .coherent_dma_mask = DMA_BIT_MASK(32),
1542 .platform_data = &uart3_data,
1543 },
1544 .resource = uart3_resources,
1545 .num_resources = ARRAY_SIZE(uart3_resources),
1546};
1547
1548static inline void configure_usart3_pins(unsigned pins)
1549{
1550 at91_set_A_periph(AT91_PIN_PB8, 1); /* TXD3 */
1551 at91_set_A_periph(AT91_PIN_PB9, 0); /* RXD3 */
1552
1553 if (pins & ATMEL_UART_RTS)
1554 at91_set_B_periph(AT91_PIN_PA23, 0); /* RTS3 */
1555 if (pins & ATMEL_UART_CTS)
1556 at91_set_B_periph(AT91_PIN_PA24, 0); /* CTS3 */
1557}
1558
1559static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
1560struct platform_device *atmel_default_console_device; /* the serial console device */
1561
1562void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
1563{
1564 struct platform_device *pdev;
Jean-Christophe PLAGNIOL-VILLARD2b348e22011-04-10 14:10:05 +08001565 struct atmel_uart_data *pdata;
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001566
1567 switch (id) {
1568 case 0: /* DBGU */
1569 pdev = &at91sam9g45_dbgu_device;
1570 configure_dbgu_pins();
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001571 break;
1572 case AT91SAM9G45_ID_US0:
1573 pdev = &at91sam9g45_uart0_device;
1574 configure_usart0_pins(pins);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001575 break;
1576 case AT91SAM9G45_ID_US1:
1577 pdev = &at91sam9g45_uart1_device;
1578 configure_usart1_pins(pins);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001579 break;
1580 case AT91SAM9G45_ID_US2:
1581 pdev = &at91sam9g45_uart2_device;
1582 configure_usart2_pins(pins);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001583 break;
1584 case AT91SAM9G45_ID_US3:
1585 pdev = &at91sam9g45_uart3_device;
1586 configure_usart3_pins(pins);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001587 break;
1588 default:
1589 return;
1590 }
Jean-Christophe PLAGNIOL-VILLARD2b348e22011-04-10 14:10:05 +08001591 pdata = pdev->dev.platform_data;
1592 pdata->num = portnr; /* update to mapped ID */
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001593
1594 if (portnr < ATMEL_MAX_UART)
1595 at91_uarts[portnr] = pdev;
1596}
1597
1598void __init at91_set_serial_console(unsigned portnr)
1599{
Jean-Christophe PLAGNIOL-VILLARDbd602992011-02-02 07:27:07 +01001600 if (portnr < ATMEL_MAX_UART) {
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001601 atmel_default_console_device = at91_uarts[portnr];
Jean-Christophe PLAGNIOL-VILLARD5c1f9662011-06-21 11:24:33 +08001602 at91sam9g45_set_console_clock(at91_uarts[portnr]->id);
Jean-Christophe PLAGNIOL-VILLARDbd602992011-02-02 07:27:07 +01001603 }
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001604}
1605
1606void __init at91_add_device_serial(void)
1607{
1608 int i;
1609
1610 for (i = 0; i < ATMEL_MAX_UART; i++) {
1611 if (at91_uarts[i])
1612 platform_device_register(at91_uarts[i]);
1613 }
1614
1615 if (!atmel_default_console_device)
1616 printk(KERN_INFO "AT91: No default serial console defined.\n");
1617}
1618#else
1619void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
1620void __init at91_set_serial_console(unsigned portnr) {}
1621void __init at91_add_device_serial(void) {}
1622#endif
1623
1624
1625/* -------------------------------------------------------------------- */
1626/*
1627 * These devices are always present and don't need any board-specific
1628 * setup.
1629 */
1630static int __init at91_add_standard_devices(void)
1631{
Nicolas Ferre40262b22009-07-24 11:43:01 +01001632 at91_add_device_hdmac();
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001633 at91_add_device_rtc();
1634 at91_add_device_rtt();
Peter Korsgaard237a62a2011-10-06 17:41:33 +02001635 at91_add_device_trng();
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001636 at91_add_device_watchdog();
1637 at91_add_device_tc();
1638 return 0;
1639}
1640
1641arch_initcall(at91_add_standard_devices);