blob: 35bd42d02195be3555e4b347fde6de2848bddaa8 [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>
Josh Wu343754f2011-10-22 15:17:40 +080017#include <linux/clk.h>
Nicolas Ferre789b23b2009-06-26 15:36:58 +010018#include <linux/platform_device.h>
19#include <linux/i2c-gpio.h>
Nicolas Ferre75305d72010-10-22 18:27:48 +020020#include <linux/atmel-mci.h>
Nicolas Ferre789b23b2009-06-26 15:36:58 +010021
22#include <linux/fb.h>
23#include <video/atmel_lcdc.h>
24
25#include <mach/board.h>
Nicolas Ferre789b23b2009-06-26 15:36:58 +010026#include <mach/at91sam9g45.h>
27#include <mach/at91sam9g45_matrix.h>
Jean-Christophe PLAGNIOL-VILLARD4342d642011-11-27 23:15:50 +080028#include <mach/at91_matrix.h>
Nicolas Ferre789b23b2009-06-26 15:36:58 +010029#include <mach/at91sam9_smc.h>
Nicolas Ferre40262b22009-07-24 11:43:01 +010030#include <mach/at_hdmac.h>
Nicolas Ferre75305d72010-10-22 18:27:48 +020031#include <mach/atmel-mci.h>
Nicolas Ferre789b23b2009-06-26 15:36:58 +010032
Josh Wu343754f2011-10-22 15:17:40 +080033#include <media/atmel-isi.h>
34
Nicolas Ferre789b23b2009-06-26 15:36:58 +010035#include "generic.h"
Josh Wu343754f2011-10-22 15:17:40 +080036#include "clock.h"
Nicolas Ferre789b23b2009-06-26 15:36:58 +010037
38
39/* --------------------------------------------------------------------
Nicolas Ferre40262b22009-07-24 11:43:01 +010040 * HDMAC - AHB DMA Controller
41 * -------------------------------------------------------------------- */
42
43#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
44static u64 hdmac_dmamask = DMA_BIT_MASK(32);
45
Nicolas Ferre40262b22009-07-24 11:43:01 +010046static struct resource hdmac_resources[] = {
47 [0] = {
Jean-Christophe PLAGNIOL-VILLARD9627b202011-10-15 15:47:51 +080048 .start = AT91SAM9G45_BASE_DMA,
49 .end = AT91SAM9G45_BASE_DMA + SZ_512 - 1,
Nicolas Ferre40262b22009-07-24 11:43:01 +010050 .flags = IORESOURCE_MEM,
51 },
Nicolas Ferre8d2602e2010-08-20 16:44:33 +020052 [1] = {
Nicolas Ferre40262b22009-07-24 11:43:01 +010053 .start = AT91SAM9G45_ID_DMA,
54 .end = AT91SAM9G45_ID_DMA,
55 .flags = IORESOURCE_IRQ,
56 },
57};
58
59static struct platform_device at_hdmac_device = {
Nicolas Ferrebdad0b92011-10-10 14:55:17 +020060 .name = "at91sam9g45_dma",
Nicolas Ferre40262b22009-07-24 11:43:01 +010061 .id = -1,
62 .dev = {
63 .dma_mask = &hdmac_dmamask,
64 .coherent_dma_mask = DMA_BIT_MASK(32),
Nicolas Ferre40262b22009-07-24 11:43:01 +010065 },
66 .resource = hdmac_resources,
67 .num_resources = ARRAY_SIZE(hdmac_resources),
68};
69
70void __init at91_add_device_hdmac(void)
71{
Jean-Christophe PLAGNIOL-VILLARD8cf93b92012-02-28 15:23:43 +080072 platform_device_register(&at_hdmac_device);
Nicolas Ferre40262b22009-07-24 11:43:01 +010073}
74#else
75void __init at91_add_device_hdmac(void) {}
76#endif
77
78
79/* --------------------------------------------------------------------
Nicolas Ferre789b23b2009-06-26 15:36:58 +010080 * USB Host (OHCI)
81 * -------------------------------------------------------------------- */
82
83#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
84static u64 ohci_dmamask = DMA_BIT_MASK(32);
85static struct at91_usbh_data usbh_ohci_data;
86
87static struct resource usbh_ohci_resources[] = {
88 [0] = {
89 .start = AT91SAM9G45_OHCI_BASE,
90 .end = AT91SAM9G45_OHCI_BASE + SZ_1M - 1,
91 .flags = IORESOURCE_MEM,
92 },
93 [1] = {
94 .start = AT91SAM9G45_ID_UHPHS,
95 .end = AT91SAM9G45_ID_UHPHS,
96 .flags = IORESOURCE_IRQ,
97 },
98};
99
100static struct platform_device at91_usbh_ohci_device = {
101 .name = "at91_ohci",
102 .id = -1,
103 .dev = {
104 .dma_mask = &ohci_dmamask,
105 .coherent_dma_mask = DMA_BIT_MASK(32),
106 .platform_data = &usbh_ohci_data,
107 },
108 .resource = usbh_ohci_resources,
109 .num_resources = ARRAY_SIZE(usbh_ohci_resources),
110};
111
112void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
113{
114 int i;
115
116 if (!data)
117 return;
118
119 /* Enable VBus control for UHP ports */
120 for (i = 0; i < data->ports; i++) {
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800121 if (gpio_is_valid(data->vbus_pin[i]))
Nicolas Ferrecca03552012-03-28 11:56:28 +0200122 at91_set_gpio_output(data->vbus_pin[i],
123 data->vbus_pin_active_low[i]);
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100124 }
125
Thomas Petazzoni1fcaea72011-07-13 11:29:18 +0200126 /* Enable overcurrent notification */
127 for (i = 0; i < data->ports; i++) {
Nicolas Ferre0c2c1f62012-03-28 11:58:58 +0200128 if (gpio_is_valid(data->overcurrent_pin[i]))
Thomas Petazzoni1fcaea72011-07-13 11:29:18 +0200129 at91_set_gpio_input(data->overcurrent_pin[i], 1);
130 }
131
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100132 usbh_ohci_data = *data;
133 platform_device_register(&at91_usbh_ohci_device);
134}
135#else
136void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {}
137#endif
138
139
140/* --------------------------------------------------------------------
Nicolas Ferref51f78c2009-09-25 12:11:32 +0100141 * USB Host HS (EHCI)
142 * Needs an OHCI host for low and full speed management
143 * -------------------------------------------------------------------- */
144
145#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
146static u64 ehci_dmamask = DMA_BIT_MASK(32);
147static struct at91_usbh_data usbh_ehci_data;
148
149static struct resource usbh_ehci_resources[] = {
150 [0] = {
151 .start = AT91SAM9G45_EHCI_BASE,
152 .end = AT91SAM9G45_EHCI_BASE + SZ_1M - 1,
153 .flags = IORESOURCE_MEM,
154 },
155 [1] = {
156 .start = AT91SAM9G45_ID_UHPHS,
157 .end = AT91SAM9G45_ID_UHPHS,
158 .flags = IORESOURCE_IRQ,
159 },
160};
161
162static struct platform_device at91_usbh_ehci_device = {
163 .name = "atmel-ehci",
164 .id = -1,
165 .dev = {
166 .dma_mask = &ehci_dmamask,
167 .coherent_dma_mask = DMA_BIT_MASK(32),
168 .platform_data = &usbh_ehci_data,
169 },
170 .resource = usbh_ehci_resources,
171 .num_resources = ARRAY_SIZE(usbh_ehci_resources),
172};
173
174void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data)
175{
176 int i;
177
178 if (!data)
179 return;
180
181 /* Enable VBus control for UHP ports */
182 for (i = 0; i < data->ports; i++) {
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800183 if (gpio_is_valid(data->vbus_pin[i]))
Nicolas Ferrecca03552012-03-28 11:56:28 +0200184 at91_set_gpio_output(data->vbus_pin[i],
185 data->vbus_pin_active_low[i]);
Nicolas Ferref51f78c2009-09-25 12:11:32 +0100186 }
187
188 usbh_ehci_data = *data;
Nicolas Ferref51f78c2009-09-25 12:11:32 +0100189 platform_device_register(&at91_usbh_ehci_device);
190}
191#else
192void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data) {}
193#endif
194
195
196/* --------------------------------------------------------------------
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100197 * USB HS Device (Gadget)
198 * -------------------------------------------------------------------- */
199
Jochen Friedrichdd0b3822011-10-25 20:51:06 +0200200#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100201static struct resource usba_udc_resources[] = {
202 [0] = {
203 .start = AT91SAM9G45_UDPHS_FIFO,
204 .end = AT91SAM9G45_UDPHS_FIFO + SZ_512K - 1,
205 .flags = IORESOURCE_MEM,
206 },
207 [1] = {
208 .start = AT91SAM9G45_BASE_UDPHS,
209 .end = AT91SAM9G45_BASE_UDPHS + SZ_1K - 1,
210 .flags = IORESOURCE_MEM,
211 },
212 [2] = {
213 .start = AT91SAM9G45_ID_UDPHS,
214 .end = AT91SAM9G45_ID_UDPHS,
215 .flags = IORESOURCE_IRQ,
216 },
217};
218
219#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \
220 [idx] = { \
221 .name = nam, \
222 .index = idx, \
223 .fifo_size = maxpkt, \
224 .nr_banks = maxbk, \
225 .can_dma = dma, \
226 .can_isoc = isoc, \
227 }
228
229static struct usba_ep_data usba_udc_ep[] __initdata = {
230 EP("ep0", 0, 64, 1, 0, 0),
231 EP("ep1", 1, 1024, 2, 1, 1),
232 EP("ep2", 2, 1024, 2, 1, 1),
233 EP("ep3", 3, 1024, 3, 1, 0),
234 EP("ep4", 4, 1024, 3, 1, 0),
235 EP("ep5", 5, 1024, 3, 1, 1),
236 EP("ep6", 6, 1024, 3, 1, 1),
237};
238
239#undef EP
240
241/*
242 * pdata doesn't have room for any endpoints, so we need to
243 * append room for the ones we need right after it.
244 */
245static struct {
246 struct usba_platform_data pdata;
247 struct usba_ep_data ep[7];
248} usba_udc_data;
249
250static struct platform_device at91_usba_udc_device = {
251 .name = "atmel_usba_udc",
252 .id = -1,
253 .dev = {
254 .platform_data = &usba_udc_data.pdata,
255 },
256 .resource = usba_udc_resources,
257 .num_resources = ARRAY_SIZE(usba_udc_resources),
258};
259
260void __init at91_add_device_usba(struct usba_platform_data *data)
261{
262 usba_udc_data.pdata.vbus_pin = -EINVAL;
263 usba_udc_data.pdata.num_ep = ARRAY_SIZE(usba_udc_ep);
Justin P. Mattock6eab04a2011-04-08 19:49:08 -0700264 memcpy(usba_udc_data.ep, usba_udc_ep, sizeof(usba_udc_ep));
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100265
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800266 if (data && gpio_is_valid(data->vbus_pin)) {
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100267 at91_set_gpio_input(data->vbus_pin, 0);
268 at91_set_deglitch(data->vbus_pin, 1);
269 usba_udc_data.pdata.vbus_pin = data->vbus_pin;
270 }
271
272 /* Pullup pin is handled internally by USB device peripheral */
273
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100274 platform_device_register(&at91_usba_udc_device);
275}
276#else
277void __init at91_add_device_usba(struct usba_platform_data *data) {}
278#endif
279
280
281/* --------------------------------------------------------------------
282 * Ethernet
283 * -------------------------------------------------------------------- */
284
285#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
286static u64 eth_dmamask = DMA_BIT_MASK(32);
Jamie Iles84e0cdb2011-03-08 20:17:06 +0000287static struct macb_platform_data eth_data;
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100288
289static struct resource eth_resources[] = {
290 [0] = {
291 .start = AT91SAM9G45_BASE_EMAC,
292 .end = AT91SAM9G45_BASE_EMAC + SZ_16K - 1,
293 .flags = IORESOURCE_MEM,
294 },
295 [1] = {
296 .start = AT91SAM9G45_ID_EMAC,
297 .end = AT91SAM9G45_ID_EMAC,
298 .flags = IORESOURCE_IRQ,
299 },
300};
301
302static struct platform_device at91sam9g45_eth_device = {
303 .name = "macb",
304 .id = -1,
305 .dev = {
306 .dma_mask = &eth_dmamask,
307 .coherent_dma_mask = DMA_BIT_MASK(32),
308 .platform_data = &eth_data,
309 },
310 .resource = eth_resources,
311 .num_resources = ARRAY_SIZE(eth_resources),
312};
313
Jamie Iles84e0cdb2011-03-08 20:17:06 +0000314void __init at91_add_device_eth(struct macb_platform_data *data)
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100315{
316 if (!data)
317 return;
318
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800319 if (gpio_is_valid(data->phy_irq_pin)) {
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100320 at91_set_gpio_input(data->phy_irq_pin, 0);
321 at91_set_deglitch(data->phy_irq_pin, 1);
322 }
323
324 /* Pins used for MII and RMII */
325 at91_set_A_periph(AT91_PIN_PA17, 0); /* ETXCK_EREFCK */
326 at91_set_A_periph(AT91_PIN_PA15, 0); /* ERXDV */
327 at91_set_A_periph(AT91_PIN_PA12, 0); /* ERX0 */
328 at91_set_A_periph(AT91_PIN_PA13, 0); /* ERX1 */
329 at91_set_A_periph(AT91_PIN_PA16, 0); /* ERXER */
330 at91_set_A_periph(AT91_PIN_PA14, 0); /* ETXEN */
331 at91_set_A_periph(AT91_PIN_PA10, 0); /* ETX0 */
332 at91_set_A_periph(AT91_PIN_PA11, 0); /* ETX1 */
333 at91_set_A_periph(AT91_PIN_PA19, 0); /* EMDIO */
334 at91_set_A_periph(AT91_PIN_PA18, 0); /* EMDC */
335
336 if (!data->is_rmii) {
337 at91_set_B_periph(AT91_PIN_PA29, 0); /* ECRS */
338 at91_set_B_periph(AT91_PIN_PA30, 0); /* ECOL */
339 at91_set_B_periph(AT91_PIN_PA8, 0); /* ERX2 */
340 at91_set_B_periph(AT91_PIN_PA9, 0); /* ERX3 */
341 at91_set_B_periph(AT91_PIN_PA28, 0); /* ERXCK */
342 at91_set_B_periph(AT91_PIN_PA6, 0); /* ETX2 */
343 at91_set_B_periph(AT91_PIN_PA7, 0); /* ETX3 */
344 at91_set_B_periph(AT91_PIN_PA27, 0); /* ETXER */
345 }
346
347 eth_data = *data;
348 platform_device_register(&at91sam9g45_eth_device);
349}
350#else
Jamie Iles84e0cdb2011-03-08 20:17:06 +0000351void __init at91_add_device_eth(struct macb_platform_data *data) {}
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100352#endif
353
354
355/* --------------------------------------------------------------------
Nicolas Ferre75305d72010-10-22 18:27:48 +0200356 * MMC / SD
357 * -------------------------------------------------------------------- */
358
359#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
360static u64 mmc_dmamask = DMA_BIT_MASK(32);
361static struct mci_platform_data mmc0_data, mmc1_data;
362
363static struct resource mmc0_resources[] = {
364 [0] = {
365 .start = AT91SAM9G45_BASE_MCI0,
366 .end = AT91SAM9G45_BASE_MCI0 + SZ_16K - 1,
367 .flags = IORESOURCE_MEM,
368 },
369 [1] = {
370 .start = AT91SAM9G45_ID_MCI0,
371 .end = AT91SAM9G45_ID_MCI0,
372 .flags = IORESOURCE_IRQ,
373 },
374};
375
376static struct platform_device at91sam9g45_mmc0_device = {
377 .name = "atmel_mci",
378 .id = 0,
379 .dev = {
380 .dma_mask = &mmc_dmamask,
381 .coherent_dma_mask = DMA_BIT_MASK(32),
382 .platform_data = &mmc0_data,
383 },
384 .resource = mmc0_resources,
385 .num_resources = ARRAY_SIZE(mmc0_resources),
386};
387
388static struct resource mmc1_resources[] = {
389 [0] = {
390 .start = AT91SAM9G45_BASE_MCI1,
391 .end = AT91SAM9G45_BASE_MCI1 + SZ_16K - 1,
392 .flags = IORESOURCE_MEM,
393 },
394 [1] = {
395 .start = AT91SAM9G45_ID_MCI1,
396 .end = AT91SAM9G45_ID_MCI1,
397 .flags = IORESOURCE_IRQ,
398 },
399};
400
401static struct platform_device at91sam9g45_mmc1_device = {
402 .name = "atmel_mci",
403 .id = 1,
404 .dev = {
405 .dma_mask = &mmc_dmamask,
406 .coherent_dma_mask = DMA_BIT_MASK(32),
407 .platform_data = &mmc1_data,
408 },
409 .resource = mmc1_resources,
410 .num_resources = ARRAY_SIZE(mmc1_resources),
411};
412
413/* Consider only one slot : slot 0 */
414void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
415{
416
417 if (!data)
418 return;
419
420 /* Must have at least one usable slot */
421 if (!data->slot[0].bus_width)
422 return;
423
424#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
425 {
426 struct at_dma_slave *atslave;
427 struct mci_dma_data *alt_atslave;
428
429 alt_atslave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
430 atslave = &alt_atslave->sdata;
431
432 /* DMA slave channel configuration */
433 atslave->dma_dev = &at_hdmac_device.dev;
Nicolas Ferre75305d72010-10-22 18:27:48 +0200434 atslave->cfg = ATC_FIFOCFG_HALFFIFO
435 | ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
436 atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
437 if (mmc_id == 0) /* MCI0 */
438 atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0)
439 | ATC_DST_PER(AT_DMA_ID_MCI0);
440
441 else /* MCI1 */
442 atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1)
443 | ATC_DST_PER(AT_DMA_ID_MCI1);
444
445 data->dma_slave = alt_atslave;
446 }
447#endif
448
449
450 /* input/irq */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800451 if (gpio_is_valid(data->slot[0].detect_pin)) {
Nicolas Ferre75305d72010-10-22 18:27:48 +0200452 at91_set_gpio_input(data->slot[0].detect_pin, 1);
453 at91_set_deglitch(data->slot[0].detect_pin, 1);
454 }
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800455 if (gpio_is_valid(data->slot[0].wp_pin))
Nicolas Ferre75305d72010-10-22 18:27:48 +0200456 at91_set_gpio_input(data->slot[0].wp_pin, 1);
457
458 if (mmc_id == 0) { /* MCI0 */
459
460 /* CLK */
461 at91_set_A_periph(AT91_PIN_PA0, 0);
462
463 /* CMD */
464 at91_set_A_periph(AT91_PIN_PA1, 1);
465
466 /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
467 at91_set_A_periph(AT91_PIN_PA2, 1);
468 if (data->slot[0].bus_width == 4) {
469 at91_set_A_periph(AT91_PIN_PA3, 1);
470 at91_set_A_periph(AT91_PIN_PA4, 1);
471 at91_set_A_periph(AT91_PIN_PA5, 1);
472 if (data->slot[0].bus_width == 8) {
473 at91_set_A_periph(AT91_PIN_PA6, 1);
474 at91_set_A_periph(AT91_PIN_PA7, 1);
475 at91_set_A_periph(AT91_PIN_PA8, 1);
476 at91_set_A_periph(AT91_PIN_PA9, 1);
477 }
478 }
479
480 mmc0_data = *data;
Nicolas Ferre75305d72010-10-22 18:27:48 +0200481 platform_device_register(&at91sam9g45_mmc0_device);
482
483 } else { /* MCI1 */
484
485 /* CLK */
486 at91_set_A_periph(AT91_PIN_PA31, 0);
487
488 /* CMD */
489 at91_set_A_periph(AT91_PIN_PA22, 1);
490
491 /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
492 at91_set_A_periph(AT91_PIN_PA23, 1);
493 if (data->slot[0].bus_width == 4) {
494 at91_set_A_periph(AT91_PIN_PA24, 1);
495 at91_set_A_periph(AT91_PIN_PA25, 1);
496 at91_set_A_periph(AT91_PIN_PA26, 1);
497 if (data->slot[0].bus_width == 8) {
498 at91_set_A_periph(AT91_PIN_PA27, 1);
499 at91_set_A_periph(AT91_PIN_PA28, 1);
500 at91_set_A_periph(AT91_PIN_PA29, 1);
501 at91_set_A_periph(AT91_PIN_PA30, 1);
502 }
503 }
504
505 mmc1_data = *data;
Nicolas Ferre75305d72010-10-22 18:27:48 +0200506 platform_device_register(&at91sam9g45_mmc1_device);
507
508 }
509}
510#else
511void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
512#endif
513
514
515/* --------------------------------------------------------------------
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100516 * NAND / SmartMedia
517 * -------------------------------------------------------------------- */
518
519#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
520static struct atmel_nand_data nand_data;
521
522#define NAND_BASE AT91_CHIPSELECT_3
523
524static struct resource nand_resources[] = {
525 [0] = {
526 .start = NAND_BASE,
527 .end = NAND_BASE + SZ_256M - 1,
528 .flags = IORESOURCE_MEM,
529 },
530 [1] = {
Jean-Christophe PLAGNIOL-VILLARDd28edd12011-09-18 09:31:56 +0800531 .start = AT91SAM9G45_BASE_ECC,
532 .end = AT91SAM9G45_BASE_ECC + SZ_512 - 1,
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100533 .flags = IORESOURCE_MEM,
534 }
535};
536
537static struct platform_device at91sam9g45_nand_device = {
538 .name = "atmel_nand",
539 .id = -1,
540 .dev = {
541 .platform_data = &nand_data,
542 },
543 .resource = nand_resources,
544 .num_resources = ARRAY_SIZE(nand_resources),
545};
546
547void __init at91_add_device_nand(struct atmel_nand_data *data)
548{
549 unsigned long csa;
550
551 if (!data)
552 return;
553
Jean-Christophe PLAGNIOL-VILLARD4342d642011-11-27 23:15:50 +0800554 csa = at91_matrix_read(AT91_MATRIX_EBICSA);
555 at91_matrix_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA);
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100556
557 /* enable pin */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800558 if (gpio_is_valid(data->enable_pin))
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100559 at91_set_gpio_output(data->enable_pin, 1);
560
561 /* ready/busy pin */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800562 if (gpio_is_valid(data->rdy_pin))
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100563 at91_set_gpio_input(data->rdy_pin, 1);
564
565 /* card detect pin */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800566 if (gpio_is_valid(data->det_pin))
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100567 at91_set_gpio_input(data->det_pin, 1);
568
569 nand_data = *data;
570 platform_device_register(&at91sam9g45_nand_device);
571}
572#else
573void __init at91_add_device_nand(struct atmel_nand_data *data) {}
574#endif
575
576
577/* --------------------------------------------------------------------
578 * TWI (i2c)
579 * -------------------------------------------------------------------- */
580
581/*
582 * Prefer the GPIO code since the TWI controller isn't robust
583 * (gets overruns and underruns under load) and can only issue
584 * repeated STARTs in one scenario (the driver doesn't yet handle them).
585 */
586#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
587static struct i2c_gpio_platform_data pdata_i2c0 = {
588 .sda_pin = AT91_PIN_PA20,
589 .sda_is_open_drain = 1,
590 .scl_pin = AT91_PIN_PA21,
591 .scl_is_open_drain = 1,
Peter Korsgaard1d5b4c02010-09-22 21:29:59 +0100592 .udelay = 5, /* ~100 kHz */
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100593};
594
595static struct platform_device at91sam9g45_twi0_device = {
596 .name = "i2c-gpio",
597 .id = 0,
598 .dev.platform_data = &pdata_i2c0,
599};
600
601static struct i2c_gpio_platform_data pdata_i2c1 = {
602 .sda_pin = AT91_PIN_PB10,
603 .sda_is_open_drain = 1,
604 .scl_pin = AT91_PIN_PB11,
605 .scl_is_open_drain = 1,
Peter Korsgaard1d5b4c02010-09-22 21:29:59 +0100606 .udelay = 5, /* ~100 kHz */
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100607};
608
609static struct platform_device at91sam9g45_twi1_device = {
610 .name = "i2c-gpio",
611 .id = 1,
612 .dev.platform_data = &pdata_i2c1,
613};
614
615void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices)
616{
617 i2c_register_board_info(i2c_id, devices, nr_devices);
618
619 if (i2c_id == 0) {
620 at91_set_GPIO_periph(AT91_PIN_PA20, 1); /* TWD (SDA) */
621 at91_set_multi_drive(AT91_PIN_PA20, 1);
622
623 at91_set_GPIO_periph(AT91_PIN_PA21, 1); /* TWCK (SCL) */
624 at91_set_multi_drive(AT91_PIN_PA21, 1);
625
626 platform_device_register(&at91sam9g45_twi0_device);
627 } else {
628 at91_set_GPIO_periph(AT91_PIN_PB10, 1); /* TWD (SDA) */
629 at91_set_multi_drive(AT91_PIN_PB10, 1);
630
631 at91_set_GPIO_periph(AT91_PIN_PB11, 1); /* TWCK (SCL) */
632 at91_set_multi_drive(AT91_PIN_PB11, 1);
633
634 platform_device_register(&at91sam9g45_twi1_device);
635 }
636}
637
638#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
639static struct resource twi0_resources[] = {
640 [0] = {
641 .start = AT91SAM9G45_BASE_TWI0,
642 .end = AT91SAM9G45_BASE_TWI0 + SZ_16K - 1,
643 .flags = IORESOURCE_MEM,
644 },
645 [1] = {
646 .start = AT91SAM9G45_ID_TWI0,
647 .end = AT91SAM9G45_ID_TWI0,
648 .flags = IORESOURCE_IRQ,
649 },
650};
651
652static struct platform_device at91sam9g45_twi0_device = {
653 .name = "at91_i2c",
654 .id = 0,
655 .resource = twi0_resources,
656 .num_resources = ARRAY_SIZE(twi0_resources),
657};
658
659static struct resource twi1_resources[] = {
660 [0] = {
661 .start = AT91SAM9G45_BASE_TWI1,
662 .end = AT91SAM9G45_BASE_TWI1 + SZ_16K - 1,
663 .flags = IORESOURCE_MEM,
664 },
665 [1] = {
666 .start = AT91SAM9G45_ID_TWI1,
667 .end = AT91SAM9G45_ID_TWI1,
668 .flags = IORESOURCE_IRQ,
669 },
670};
671
672static struct platform_device at91sam9g45_twi1_device = {
673 .name = "at91_i2c",
674 .id = 1,
675 .resource = twi1_resources,
676 .num_resources = ARRAY_SIZE(twi1_resources),
677};
678
679void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices)
680{
681 i2c_register_board_info(i2c_id, devices, nr_devices);
682
683 /* pins used for TWI interface */
684 if (i2c_id == 0) {
685 at91_set_A_periph(AT91_PIN_PA20, 0); /* TWD */
686 at91_set_multi_drive(AT91_PIN_PA20, 1);
687
688 at91_set_A_periph(AT91_PIN_PA21, 0); /* TWCK */
689 at91_set_multi_drive(AT91_PIN_PA21, 1);
690
691 platform_device_register(&at91sam9g45_twi0_device);
692 } else {
693 at91_set_A_periph(AT91_PIN_PB10, 0); /* TWD */
694 at91_set_multi_drive(AT91_PIN_PB10, 1);
695
696 at91_set_A_periph(AT91_PIN_PB11, 0); /* TWCK */
697 at91_set_multi_drive(AT91_PIN_PB11, 1);
698
699 platform_device_register(&at91sam9g45_twi1_device);
700 }
701}
702#else
703void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices) {}
704#endif
705
706
707/* --------------------------------------------------------------------
708 * SPI
709 * -------------------------------------------------------------------- */
710
711#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
712static u64 spi_dmamask = DMA_BIT_MASK(32);
713
714static struct resource spi0_resources[] = {
715 [0] = {
716 .start = AT91SAM9G45_BASE_SPI0,
717 .end = AT91SAM9G45_BASE_SPI0 + SZ_16K - 1,
718 .flags = IORESOURCE_MEM,
719 },
720 [1] = {
721 .start = AT91SAM9G45_ID_SPI0,
722 .end = AT91SAM9G45_ID_SPI0,
723 .flags = IORESOURCE_IRQ,
724 },
725};
726
727static struct platform_device at91sam9g45_spi0_device = {
728 .name = "atmel_spi",
729 .id = 0,
730 .dev = {
731 .dma_mask = &spi_dmamask,
732 .coherent_dma_mask = DMA_BIT_MASK(32),
733 },
734 .resource = spi0_resources,
735 .num_resources = ARRAY_SIZE(spi0_resources),
736};
737
738static const unsigned spi0_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PB18, AT91_PIN_PB19, AT91_PIN_PD27 };
739
740static struct resource spi1_resources[] = {
741 [0] = {
742 .start = AT91SAM9G45_BASE_SPI1,
743 .end = AT91SAM9G45_BASE_SPI1 + SZ_16K - 1,
744 .flags = IORESOURCE_MEM,
745 },
746 [1] = {
747 .start = AT91SAM9G45_ID_SPI1,
748 .end = AT91SAM9G45_ID_SPI1,
749 .flags = IORESOURCE_IRQ,
750 },
751};
752
753static struct platform_device at91sam9g45_spi1_device = {
754 .name = "atmel_spi",
755 .id = 1,
756 .dev = {
757 .dma_mask = &spi_dmamask,
758 .coherent_dma_mask = DMA_BIT_MASK(32),
759 },
760 .resource = spi1_resources,
761 .num_resources = ARRAY_SIZE(spi1_resources),
762};
763
764static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB17, AT91_PIN_PD28, AT91_PIN_PD18, AT91_PIN_PD19 };
765
766void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
767{
768 int i;
769 unsigned long cs_pin;
770 short enable_spi0 = 0;
771 short enable_spi1 = 0;
772
773 /* Choose SPI chip-selects */
774 for (i = 0; i < nr_devices; i++) {
775 if (devices[i].controller_data)
776 cs_pin = (unsigned long) devices[i].controller_data;
777 else if (devices[i].bus_num == 0)
778 cs_pin = spi0_standard_cs[devices[i].chip_select];
779 else
780 cs_pin = spi1_standard_cs[devices[i].chip_select];
781
Nicolas Ferre0c2c1f62012-03-28 11:58:58 +0200782 if (!gpio_is_valid(cs_pin))
783 continue;
784
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100785 if (devices[i].bus_num == 0)
786 enable_spi0 = 1;
787 else
788 enable_spi1 = 1;
789
790 /* enable chip-select pin */
791 at91_set_gpio_output(cs_pin, 1);
792
793 /* pass chip-select pin to driver */
794 devices[i].controller_data = (void *) cs_pin;
795 }
796
797 spi_register_board_info(devices, nr_devices);
798
799 /* Configure SPI bus(es) */
800 if (enable_spi0) {
801 at91_set_A_periph(AT91_PIN_PB0, 0); /* SPI0_MISO */
802 at91_set_A_periph(AT91_PIN_PB1, 0); /* SPI0_MOSI */
803 at91_set_A_periph(AT91_PIN_PB2, 0); /* SPI0_SPCK */
804
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100805 platform_device_register(&at91sam9g45_spi0_device);
806 }
807 if (enable_spi1) {
808 at91_set_A_periph(AT91_PIN_PB14, 0); /* SPI1_MISO */
809 at91_set_A_periph(AT91_PIN_PB15, 0); /* SPI1_MOSI */
810 at91_set_A_periph(AT91_PIN_PB16, 0); /* SPI1_SPCK */
811
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100812 platform_device_register(&at91sam9g45_spi1_device);
813 }
814}
815#else
816void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
817#endif
818
819
820/* --------------------------------------------------------------------
Nicolas Ferre378ac652009-09-18 16:14:22 +0100821 * AC97
822 * -------------------------------------------------------------------- */
823
824#if defined(CONFIG_SND_ATMEL_AC97C) || defined(CONFIG_SND_ATMEL_AC97C_MODULE)
825static u64 ac97_dmamask = DMA_BIT_MASK(32);
826static struct ac97c_platform_data ac97_data;
827
828static struct resource ac97_resources[] = {
829 [0] = {
830 .start = AT91SAM9G45_BASE_AC97C,
831 .end = AT91SAM9G45_BASE_AC97C + SZ_16K - 1,
832 .flags = IORESOURCE_MEM,
833 },
834 [1] = {
835 .start = AT91SAM9G45_ID_AC97C,
836 .end = AT91SAM9G45_ID_AC97C,
837 .flags = IORESOURCE_IRQ,
838 },
839};
840
841static struct platform_device at91sam9g45_ac97_device = {
842 .name = "atmel_ac97c",
843 .id = 0,
844 .dev = {
845 .dma_mask = &ac97_dmamask,
846 .coherent_dma_mask = DMA_BIT_MASK(32),
847 .platform_data = &ac97_data,
848 },
849 .resource = ac97_resources,
850 .num_resources = ARRAY_SIZE(ac97_resources),
851};
852
853void __init at91_add_device_ac97(struct ac97c_platform_data *data)
854{
855 if (!data)
856 return;
857
858 at91_set_A_periph(AT91_PIN_PD8, 0); /* AC97FS */
859 at91_set_A_periph(AT91_PIN_PD9, 0); /* AC97CK */
860 at91_set_A_periph(AT91_PIN_PD7, 0); /* AC97TX */
861 at91_set_A_periph(AT91_PIN_PD6, 0); /* AC97RX */
862
863 /* reset */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800864 if (gpio_is_valid(data->reset_pin))
Nicolas Ferre378ac652009-09-18 16:14:22 +0100865 at91_set_gpio_output(data->reset_pin, 0);
866
867 ac97_data = *data;
868 platform_device_register(&at91sam9g45_ac97_device);
869}
870#else
871void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
872#endif
873
Josh Wu343754f2011-10-22 15:17:40 +0800874/* --------------------------------------------------------------------
875 * Image Sensor Interface
876 * -------------------------------------------------------------------- */
877#if defined(CONFIG_VIDEO_ATMEL_ISI) || defined(CONFIG_VIDEO_ATMEL_ISI_MODULE)
878static u64 isi_dmamask = DMA_BIT_MASK(32);
879static struct isi_platform_data isi_data;
880
881struct resource isi_resources[] = {
882 [0] = {
883 .start = AT91SAM9G45_BASE_ISI,
884 .end = AT91SAM9G45_BASE_ISI + SZ_16K - 1,
885 .flags = IORESOURCE_MEM,
886 },
887 [1] = {
888 .start = AT91SAM9G45_ID_ISI,
889 .end = AT91SAM9G45_ID_ISI,
890 .flags = IORESOURCE_IRQ,
891 },
892};
893
894static struct platform_device at91sam9g45_isi_device = {
895 .name = "atmel_isi",
896 .id = 0,
897 .dev = {
898 .dma_mask = &isi_dmamask,
899 .coherent_dma_mask = DMA_BIT_MASK(32),
900 .platform_data = &isi_data,
901 },
902 .resource = isi_resources,
903 .num_resources = ARRAY_SIZE(isi_resources),
904};
905
906static struct clk_lookup isi_mck_lookups[] = {
907 CLKDEV_CON_DEV_ID("isi_mck", "atmel_isi.0", NULL),
908};
909
910void __init at91_add_device_isi(struct isi_platform_data *data,
911 bool use_pck_as_mck)
912{
913 struct clk *pck;
914 struct clk *parent;
915
916 if (!data)
917 return;
918 isi_data = *data;
919
920 at91_set_A_periph(AT91_PIN_PB20, 0); /* ISI_D0 */
921 at91_set_A_periph(AT91_PIN_PB21, 0); /* ISI_D1 */
922 at91_set_A_periph(AT91_PIN_PB22, 0); /* ISI_D2 */
923 at91_set_A_periph(AT91_PIN_PB23, 0); /* ISI_D3 */
924 at91_set_A_periph(AT91_PIN_PB24, 0); /* ISI_D4 */
925 at91_set_A_periph(AT91_PIN_PB25, 0); /* ISI_D5 */
926 at91_set_A_periph(AT91_PIN_PB26, 0); /* ISI_D6 */
927 at91_set_A_periph(AT91_PIN_PB27, 0); /* ISI_D7 */
928 at91_set_A_periph(AT91_PIN_PB28, 0); /* ISI_PCK */
929 at91_set_A_periph(AT91_PIN_PB30, 0); /* ISI_HSYNC */
930 at91_set_A_periph(AT91_PIN_PB29, 0); /* ISI_VSYNC */
931 at91_set_B_periph(AT91_PIN_PB8, 0); /* ISI_PD8 */
932 at91_set_B_periph(AT91_PIN_PB9, 0); /* ISI_PD9 */
933 at91_set_B_periph(AT91_PIN_PB10, 0); /* ISI_PD10 */
934 at91_set_B_periph(AT91_PIN_PB11, 0); /* ISI_PD11 */
935
936 platform_device_register(&at91sam9g45_isi_device);
937
938 if (use_pck_as_mck) {
939 at91_set_B_periph(AT91_PIN_PB31, 0); /* ISI_MCK (PCK1) */
940
941 pck = clk_get(NULL, "pck1");
942 parent = clk_get(NULL, "plla");
943
944 BUG_ON(IS_ERR(pck) || IS_ERR(parent));
945
946 if (clk_set_parent(pck, parent)) {
947 pr_err("Failed to set PCK's parent\n");
948 } else {
949 /* Register PCK as ISI_MCK */
950 isi_mck_lookups[0].clk = pck;
951 clkdev_add_table(isi_mck_lookups,
952 ARRAY_SIZE(isi_mck_lookups));
953 }
954
955 clk_put(pck);
956 clk_put(parent);
957 }
958}
959#else
960void __init at91_add_device_isi(struct isi_platform_data *data,
961 bool use_pck_as_mck) {}
962#endif
963
Nicolas Ferre378ac652009-09-18 16:14:22 +0100964
965/* --------------------------------------------------------------------
Nicolas Ferre789b23b2009-06-26 15:36:58 +0100966 * LCD Controller
967 * -------------------------------------------------------------------- */
968
969#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
970static u64 lcdc_dmamask = DMA_BIT_MASK(32);
971static struct atmel_lcdfb_info lcdc_data;
972
973static struct resource lcdc_resources[] = {
974 [0] = {
975 .start = AT91SAM9G45_LCDC_BASE,
976 .end = AT91SAM9G45_LCDC_BASE + SZ_4K - 1,
977 .flags = IORESOURCE_MEM,
978 },
979 [1] = {
980 .start = AT91SAM9G45_ID_LCDC,
981 .end = AT91SAM9G45_ID_LCDC,
982 .flags = IORESOURCE_IRQ,
983 },
984};
985
986static struct platform_device at91_lcdc_device = {
987 .name = "atmel_lcdfb",
988 .id = 0,
989 .dev = {
990 .dma_mask = &lcdc_dmamask,
991 .coherent_dma_mask = DMA_BIT_MASK(32),
992 .platform_data = &lcdc_data,
993 },
994 .resource = lcdc_resources,
995 .num_resources = ARRAY_SIZE(lcdc_resources),
996};
997
998void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
999{
1000 if (!data)
1001 return;
1002
1003 at91_set_A_periph(AT91_PIN_PE0, 0); /* LCDDPWR */
1004
1005 at91_set_A_periph(AT91_PIN_PE2, 0); /* LCDCC */
1006 at91_set_A_periph(AT91_PIN_PE3, 0); /* LCDVSYNC */
1007 at91_set_A_periph(AT91_PIN_PE4, 0); /* LCDHSYNC */
1008 at91_set_A_periph(AT91_PIN_PE5, 0); /* LCDDOTCK */
1009 at91_set_A_periph(AT91_PIN_PE6, 0); /* LCDDEN */
1010 at91_set_A_periph(AT91_PIN_PE7, 0); /* LCDD0 */
1011 at91_set_A_periph(AT91_PIN_PE8, 0); /* LCDD1 */
1012 at91_set_A_periph(AT91_PIN_PE9, 0); /* LCDD2 */
1013 at91_set_A_periph(AT91_PIN_PE10, 0); /* LCDD3 */
1014 at91_set_A_periph(AT91_PIN_PE11, 0); /* LCDD4 */
1015 at91_set_A_periph(AT91_PIN_PE12, 0); /* LCDD5 */
1016 at91_set_A_periph(AT91_PIN_PE13, 0); /* LCDD6 */
1017 at91_set_A_periph(AT91_PIN_PE14, 0); /* LCDD7 */
1018 at91_set_A_periph(AT91_PIN_PE15, 0); /* LCDD8 */
1019 at91_set_A_periph(AT91_PIN_PE16, 0); /* LCDD9 */
1020 at91_set_A_periph(AT91_PIN_PE17, 0); /* LCDD10 */
1021 at91_set_A_periph(AT91_PIN_PE18, 0); /* LCDD11 */
1022 at91_set_A_periph(AT91_PIN_PE19, 0); /* LCDD12 */
1023 at91_set_A_periph(AT91_PIN_PE20, 0); /* LCDD13 */
1024 at91_set_A_periph(AT91_PIN_PE21, 0); /* LCDD14 */
1025 at91_set_A_periph(AT91_PIN_PE22, 0); /* LCDD15 */
1026 at91_set_A_periph(AT91_PIN_PE23, 0); /* LCDD16 */
1027 at91_set_A_periph(AT91_PIN_PE24, 0); /* LCDD17 */
1028 at91_set_A_periph(AT91_PIN_PE25, 0); /* LCDD18 */
1029 at91_set_A_periph(AT91_PIN_PE26, 0); /* LCDD19 */
1030 at91_set_A_periph(AT91_PIN_PE27, 0); /* LCDD20 */
1031 at91_set_A_periph(AT91_PIN_PE28, 0); /* LCDD21 */
1032 at91_set_A_periph(AT91_PIN_PE29, 0); /* LCDD22 */
1033 at91_set_A_periph(AT91_PIN_PE30, 0); /* LCDD23 */
1034
1035 lcdc_data = *data;
1036 platform_device_register(&at91_lcdc_device);
1037}
1038#else
1039void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
1040#endif
1041
1042
1043/* --------------------------------------------------------------------
1044 * Timer/Counter block
1045 * -------------------------------------------------------------------- */
1046
1047#ifdef CONFIG_ATMEL_TCLIB
1048static struct resource tcb0_resources[] = {
1049 [0] = {
1050 .start = AT91SAM9G45_BASE_TCB0,
Nicolas Ferre29831292012-01-18 16:56:36 +01001051 .end = AT91SAM9G45_BASE_TCB0 + SZ_256 - 1,
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001052 .flags = IORESOURCE_MEM,
1053 },
1054 [1] = {
1055 .start = AT91SAM9G45_ID_TCB,
1056 .end = AT91SAM9G45_ID_TCB,
1057 .flags = IORESOURCE_IRQ,
1058 },
1059};
1060
1061static struct platform_device at91sam9g45_tcb0_device = {
1062 .name = "atmel_tcb",
1063 .id = 0,
1064 .resource = tcb0_resources,
1065 .num_resources = ARRAY_SIZE(tcb0_resources),
1066};
1067
1068/* TCB1 begins with TC3 */
1069static struct resource tcb1_resources[] = {
1070 [0] = {
1071 .start = AT91SAM9G45_BASE_TCB1,
Nicolas Ferre29831292012-01-18 16:56:36 +01001072 .end = AT91SAM9G45_BASE_TCB1 + SZ_256 - 1,
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001073 .flags = IORESOURCE_MEM,
1074 },
1075 [1] = {
1076 .start = AT91SAM9G45_ID_TCB,
1077 .end = AT91SAM9G45_ID_TCB,
1078 .flags = IORESOURCE_IRQ,
1079 },
1080};
1081
1082static struct platform_device at91sam9g45_tcb1_device = {
1083 .name = "atmel_tcb",
1084 .id = 1,
1085 .resource = tcb1_resources,
1086 .num_resources = ARRAY_SIZE(tcb1_resources),
1087};
1088
1089static void __init at91_add_device_tc(void)
1090{
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001091 platform_device_register(&at91sam9g45_tcb0_device);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001092 platform_device_register(&at91sam9g45_tcb1_device);
1093}
1094#else
1095static void __init at91_add_device_tc(void) { }
1096#endif
1097
1098
1099/* --------------------------------------------------------------------
1100 * RTC
1101 * -------------------------------------------------------------------- */
1102
1103#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
Jean-Christophe PLAGNIOL-VILLARDd28bdfc2011-11-14 14:24:53 +08001104static struct resource rtc_resources[] = {
1105 [0] = {
1106 .start = AT91SAM9G45_BASE_RTC,
1107 .end = AT91SAM9G45_BASE_RTC + SZ_256 - 1,
1108 .flags = IORESOURCE_MEM,
1109 },
1110 [1] = {
1111 .start = AT91_ID_SYS,
1112 .end = AT91_ID_SYS,
1113 .flags = IORESOURCE_IRQ,
1114 },
1115};
1116
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001117static struct platform_device at91sam9g45_rtc_device = {
1118 .name = "at91_rtc",
1119 .id = -1,
Jean-Christophe PLAGNIOL-VILLARDd28bdfc2011-11-14 14:24:53 +08001120 .resource = rtc_resources,
1121 .num_resources = ARRAY_SIZE(rtc_resources),
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001122};
1123
1124static void __init at91_add_device_rtc(void)
1125{
1126 platform_device_register(&at91sam9g45_rtc_device);
1127}
1128#else
1129static void __init at91_add_device_rtc(void) {}
1130#endif
1131
1132
1133/* --------------------------------------------------------------------
Nicolas Ferre985f37f2009-11-19 09:32:52 -08001134 * Touchscreen
1135 * -------------------------------------------------------------------- */
1136
1137#if defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) || defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC_MODULE)
1138static u64 tsadcc_dmamask = DMA_BIT_MASK(32);
1139static struct at91_tsadcc_data tsadcc_data;
1140
1141static struct resource tsadcc_resources[] = {
1142 [0] = {
1143 .start = AT91SAM9G45_BASE_TSC,
1144 .end = AT91SAM9G45_BASE_TSC + SZ_16K - 1,
1145 .flags = IORESOURCE_MEM,
1146 },
1147 [1] = {
1148 .start = AT91SAM9G45_ID_TSC,
1149 .end = AT91SAM9G45_ID_TSC,
1150 .flags = IORESOURCE_IRQ,
1151 }
1152};
1153
1154static struct platform_device at91sam9g45_tsadcc_device = {
1155 .name = "atmel_tsadcc",
1156 .id = -1,
1157 .dev = {
1158 .dma_mask = &tsadcc_dmamask,
1159 .coherent_dma_mask = DMA_BIT_MASK(32),
1160 .platform_data = &tsadcc_data,
1161 },
1162 .resource = tsadcc_resources,
1163 .num_resources = ARRAY_SIZE(tsadcc_resources),
1164};
1165
1166void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data)
1167{
1168 if (!data)
1169 return;
1170
1171 at91_set_gpio_input(AT91_PIN_PD20, 0); /* AD0_XR */
1172 at91_set_gpio_input(AT91_PIN_PD21, 0); /* AD1_XL */
1173 at91_set_gpio_input(AT91_PIN_PD22, 0); /* AD2_YT */
1174 at91_set_gpio_input(AT91_PIN_PD23, 0); /* AD3_TB */
1175
1176 tsadcc_data = *data;
1177 platform_device_register(&at91sam9g45_tsadcc_device);
1178}
1179#else
1180void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
1181#endif
1182
1183
1184/* --------------------------------------------------------------------
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001185 * RTT
1186 * -------------------------------------------------------------------- */
1187
1188static struct resource rtt_resources[] = {
1189 {
Jean-Christophe PLAGNIOL-VILLARDeab5fd62011-09-18 10:12:00 +08001190 .start = AT91SAM9G45_BASE_RTT,
1191 .end = AT91SAM9G45_BASE_RTT + SZ_16 - 1,
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001192 .flags = IORESOURCE_MEM,
Jean-Christophe PLAGNIOL-VILLARDb3af8b42012-02-15 21:24:46 +08001193 }, {
1194 .flags = IORESOURCE_MEM,
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001195 }
1196};
1197
1198static struct platform_device at91sam9g45_rtt_device = {
1199 .name = "at91_rtt",
1200 .id = 0,
1201 .resource = rtt_resources,
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001202};
1203
Jean-Christophe PLAGNIOL-VILLARD205056a2012-02-15 20:51:37 +08001204#if IS_ENABLED(CONFIG_RTC_DRV_AT91SAM9)
1205static void __init at91_add_device_rtt_rtc(void)
1206{
1207 at91sam9g45_rtt_device.name = "rtc-at91sam9";
Jean-Christophe PLAGNIOL-VILLARDb3af8b42012-02-15 21:24:46 +08001208 /*
1209 * The second resource is needed:
1210 * GPBR will serve as the storage for RTC time offset
1211 */
1212 at91sam9g45_rtt_device.num_resources = 2;
1213 rtt_resources[1].start = AT91SAM9G45_BASE_GPBR +
1214 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
1215 rtt_resources[1].end = rtt_resources[1].start + 3;
Jean-Christophe PLAGNIOL-VILLARD205056a2012-02-15 20:51:37 +08001216}
1217#else
Jean-Christophe PLAGNIOL-VILLARDb3af8b42012-02-15 21:24:46 +08001218static void __init at91_add_device_rtt_rtc(void)
1219{
1220 /* Only one resource is needed: RTT not used as RTC */
1221 at91sam9g45_rtt_device.num_resources = 1;
1222}
Jean-Christophe PLAGNIOL-VILLARD205056a2012-02-15 20:51:37 +08001223#endif
1224
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001225static void __init at91_add_device_rtt(void)
1226{
Jean-Christophe PLAGNIOL-VILLARD205056a2012-02-15 20:51:37 +08001227 at91_add_device_rtt_rtc();
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001228 platform_device_register(&at91sam9g45_rtt_device);
1229}
1230
1231
1232/* --------------------------------------------------------------------
Peter Korsgaard237a62a2011-10-06 17:41:33 +02001233 * TRNG
1234 * -------------------------------------------------------------------- */
1235
1236#if defined(CONFIG_HW_RANDOM_ATMEL) || defined(CONFIG_HW_RANDOM_ATMEL_MODULE)
1237static struct resource trng_resources[] = {
1238 {
1239 .start = AT91SAM9G45_BASE_TRNG,
1240 .end = AT91SAM9G45_BASE_TRNG + SZ_16K - 1,
1241 .flags = IORESOURCE_MEM,
1242 },
1243};
1244
1245static struct platform_device at91sam9g45_trng_device = {
1246 .name = "atmel-trng",
1247 .id = -1,
1248 .resource = trng_resources,
1249 .num_resources = ARRAY_SIZE(trng_resources),
1250};
1251
1252static void __init at91_add_device_trng(void)
1253{
1254 platform_device_register(&at91sam9g45_trng_device);
1255}
1256#else
1257static void __init at91_add_device_trng(void) {}
1258#endif
1259
1260/* --------------------------------------------------------------------
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001261 * Watchdog
1262 * -------------------------------------------------------------------- */
1263
Yegor Yefremov47263742009-10-20 08:39:41 +01001264#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
Jean-Christophe PLAGNIOL-VILLARDc1c30a22011-11-02 01:43:31 +08001265static struct resource wdt_resources[] = {
1266 {
1267 .start = AT91SAM9G45_BASE_WDT,
1268 .end = AT91SAM9G45_BASE_WDT + SZ_16 - 1,
1269 .flags = IORESOURCE_MEM,
1270 }
1271};
1272
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001273static struct platform_device at91sam9g45_wdt_device = {
1274 .name = "at91_wdt",
1275 .id = -1,
Jean-Christophe PLAGNIOL-VILLARDc1c30a22011-11-02 01:43:31 +08001276 .resource = wdt_resources,
1277 .num_resources = ARRAY_SIZE(wdt_resources),
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001278};
1279
1280static void __init at91_add_device_watchdog(void)
1281{
1282 platform_device_register(&at91sam9g45_wdt_device);
1283}
1284#else
1285static void __init at91_add_device_watchdog(void) {}
1286#endif
1287
1288
1289/* --------------------------------------------------------------------
1290 * PWM
1291 * --------------------------------------------------------------------*/
1292
1293#if defined(CONFIG_ATMEL_PWM) || defined(CONFIG_ATMEL_PWM_MODULE)
1294static u32 pwm_mask;
1295
1296static struct resource pwm_resources[] = {
1297 [0] = {
1298 .start = AT91SAM9G45_BASE_PWMC,
1299 .end = AT91SAM9G45_BASE_PWMC + SZ_16K - 1,
1300 .flags = IORESOURCE_MEM,
1301 },
1302 [1] = {
1303 .start = AT91SAM9G45_ID_PWMC,
1304 .end = AT91SAM9G45_ID_PWMC,
1305 .flags = IORESOURCE_IRQ,
1306 },
1307};
1308
1309static struct platform_device at91sam9g45_pwm0_device = {
1310 .name = "atmel_pwm",
1311 .id = -1,
1312 .dev = {
1313 .platform_data = &pwm_mask,
1314 },
1315 .resource = pwm_resources,
1316 .num_resources = ARRAY_SIZE(pwm_resources),
1317};
1318
1319void __init at91_add_device_pwm(u32 mask)
1320{
1321 if (mask & (1 << AT91_PWM0))
1322 at91_set_B_periph(AT91_PIN_PD24, 1); /* enable PWM0 */
1323
1324 if (mask & (1 << AT91_PWM1))
1325 at91_set_B_periph(AT91_PIN_PD31, 1); /* enable PWM1 */
1326
1327 if (mask & (1 << AT91_PWM2))
1328 at91_set_B_periph(AT91_PIN_PD26, 1); /* enable PWM2 */
1329
1330 if (mask & (1 << AT91_PWM3))
1331 at91_set_B_periph(AT91_PIN_PD0, 1); /* enable PWM3 */
1332
1333 pwm_mask = mask;
1334
1335 platform_device_register(&at91sam9g45_pwm0_device);
1336}
1337#else
1338void __init at91_add_device_pwm(u32 mask) {}
1339#endif
1340
1341
1342/* --------------------------------------------------------------------
1343 * SSC -- Synchronous Serial Controller
1344 * -------------------------------------------------------------------- */
1345
1346#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
1347static u64 ssc0_dmamask = DMA_BIT_MASK(32);
1348
1349static struct resource ssc0_resources[] = {
1350 [0] = {
1351 .start = AT91SAM9G45_BASE_SSC0,
1352 .end = AT91SAM9G45_BASE_SSC0 + SZ_16K - 1,
1353 .flags = IORESOURCE_MEM,
1354 },
1355 [1] = {
1356 .start = AT91SAM9G45_ID_SSC0,
1357 .end = AT91SAM9G45_ID_SSC0,
1358 .flags = IORESOURCE_IRQ,
1359 },
1360};
1361
1362static struct platform_device at91sam9g45_ssc0_device = {
1363 .name = "ssc",
1364 .id = 0,
1365 .dev = {
1366 .dma_mask = &ssc0_dmamask,
1367 .coherent_dma_mask = DMA_BIT_MASK(32),
1368 },
1369 .resource = ssc0_resources,
1370 .num_resources = ARRAY_SIZE(ssc0_resources),
1371};
1372
1373static inline void configure_ssc0_pins(unsigned pins)
1374{
1375 if (pins & ATMEL_SSC_TF)
1376 at91_set_A_periph(AT91_PIN_PD1, 1);
1377 if (pins & ATMEL_SSC_TK)
1378 at91_set_A_periph(AT91_PIN_PD0, 1);
1379 if (pins & ATMEL_SSC_TD)
1380 at91_set_A_periph(AT91_PIN_PD2, 1);
1381 if (pins & ATMEL_SSC_RD)
1382 at91_set_A_periph(AT91_PIN_PD3, 1);
1383 if (pins & ATMEL_SSC_RK)
1384 at91_set_A_periph(AT91_PIN_PD4, 1);
1385 if (pins & ATMEL_SSC_RF)
1386 at91_set_A_periph(AT91_PIN_PD5, 1);
1387}
1388
1389static u64 ssc1_dmamask = DMA_BIT_MASK(32);
1390
1391static struct resource ssc1_resources[] = {
1392 [0] = {
1393 .start = AT91SAM9G45_BASE_SSC1,
1394 .end = AT91SAM9G45_BASE_SSC1 + SZ_16K - 1,
1395 .flags = IORESOURCE_MEM,
1396 },
1397 [1] = {
1398 .start = AT91SAM9G45_ID_SSC1,
1399 .end = AT91SAM9G45_ID_SSC1,
1400 .flags = IORESOURCE_IRQ,
1401 },
1402};
1403
1404static struct platform_device at91sam9g45_ssc1_device = {
1405 .name = "ssc",
1406 .id = 1,
1407 .dev = {
1408 .dma_mask = &ssc1_dmamask,
1409 .coherent_dma_mask = DMA_BIT_MASK(32),
1410 },
1411 .resource = ssc1_resources,
1412 .num_resources = ARRAY_SIZE(ssc1_resources),
1413};
1414
1415static inline void configure_ssc1_pins(unsigned pins)
1416{
1417 if (pins & ATMEL_SSC_TF)
1418 at91_set_A_periph(AT91_PIN_PD14, 1);
1419 if (pins & ATMEL_SSC_TK)
1420 at91_set_A_periph(AT91_PIN_PD12, 1);
1421 if (pins & ATMEL_SSC_TD)
1422 at91_set_A_periph(AT91_PIN_PD10, 1);
1423 if (pins & ATMEL_SSC_RD)
1424 at91_set_A_periph(AT91_PIN_PD11, 1);
1425 if (pins & ATMEL_SSC_RK)
1426 at91_set_A_periph(AT91_PIN_PD13, 1);
1427 if (pins & ATMEL_SSC_RF)
1428 at91_set_A_periph(AT91_PIN_PD15, 1);
1429}
1430
1431/*
1432 * SSC controllers are accessed through library code, instead of any
1433 * kind of all-singing/all-dancing driver. For example one could be
1434 * used by a particular I2S audio codec's driver, while another one
1435 * on the same system might be used by a custom data capture driver.
1436 */
1437void __init at91_add_device_ssc(unsigned id, unsigned pins)
1438{
1439 struct platform_device *pdev;
1440
1441 /*
1442 * NOTE: caller is responsible for passing information matching
1443 * "pins" to whatever will be using each particular controller.
1444 */
1445 switch (id) {
1446 case AT91SAM9G45_ID_SSC0:
1447 pdev = &at91sam9g45_ssc0_device;
1448 configure_ssc0_pins(pins);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001449 break;
1450 case AT91SAM9G45_ID_SSC1:
1451 pdev = &at91sam9g45_ssc1_device;
1452 configure_ssc1_pins(pins);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001453 break;
1454 default:
1455 return;
1456 }
1457
1458 platform_device_register(pdev);
1459}
1460
1461#else
1462void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
1463#endif
1464
1465
1466/* --------------------------------------------------------------------
1467 * UART
1468 * -------------------------------------------------------------------- */
1469
1470#if defined(CONFIG_SERIAL_ATMEL)
1471static struct resource dbgu_resources[] = {
1472 [0] = {
Jean-Christophe PLAGNIOL-VILLARD13079a72011-11-02 01:43:31 +08001473 .start = AT91SAM9G45_BASE_DBGU,
1474 .end = AT91SAM9G45_BASE_DBGU + SZ_512 - 1,
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001475 .flags = IORESOURCE_MEM,
1476 },
1477 [1] = {
1478 .start = AT91_ID_SYS,
1479 .end = AT91_ID_SYS,
1480 .flags = IORESOURCE_IRQ,
1481 },
1482};
1483
1484static struct atmel_uart_data dbgu_data = {
1485 .use_dma_tx = 0,
1486 .use_dma_rx = 0,
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001487};
1488
1489static u64 dbgu_dmamask = DMA_BIT_MASK(32);
1490
1491static struct platform_device at91sam9g45_dbgu_device = {
1492 .name = "atmel_usart",
1493 .id = 0,
1494 .dev = {
1495 .dma_mask = &dbgu_dmamask,
1496 .coherent_dma_mask = DMA_BIT_MASK(32),
1497 .platform_data = &dbgu_data,
1498 },
1499 .resource = dbgu_resources,
1500 .num_resources = ARRAY_SIZE(dbgu_resources),
1501};
1502
1503static inline void configure_dbgu_pins(void)
1504{
1505 at91_set_A_periph(AT91_PIN_PB12, 0); /* DRXD */
1506 at91_set_A_periph(AT91_PIN_PB13, 1); /* DTXD */
1507}
1508
1509static struct resource uart0_resources[] = {
1510 [0] = {
1511 .start = AT91SAM9G45_BASE_US0,
1512 .end = AT91SAM9G45_BASE_US0 + SZ_16K - 1,
1513 .flags = IORESOURCE_MEM,
1514 },
1515 [1] = {
1516 .start = AT91SAM9G45_ID_US0,
1517 .end = AT91SAM9G45_ID_US0,
1518 .flags = IORESOURCE_IRQ,
1519 },
1520};
1521
1522static struct atmel_uart_data uart0_data = {
1523 .use_dma_tx = 1,
1524 .use_dma_rx = 1,
1525};
1526
1527static u64 uart0_dmamask = DMA_BIT_MASK(32);
1528
1529static struct platform_device at91sam9g45_uart0_device = {
1530 .name = "atmel_usart",
1531 .id = 1,
1532 .dev = {
1533 .dma_mask = &uart0_dmamask,
1534 .coherent_dma_mask = DMA_BIT_MASK(32),
1535 .platform_data = &uart0_data,
1536 },
1537 .resource = uart0_resources,
1538 .num_resources = ARRAY_SIZE(uart0_resources),
1539};
1540
1541static inline void configure_usart0_pins(unsigned pins)
1542{
1543 at91_set_A_periph(AT91_PIN_PB19, 1); /* TXD0 */
1544 at91_set_A_periph(AT91_PIN_PB18, 0); /* RXD0 */
1545
1546 if (pins & ATMEL_UART_RTS)
1547 at91_set_B_periph(AT91_PIN_PB17, 0); /* RTS0 */
1548 if (pins & ATMEL_UART_CTS)
1549 at91_set_B_periph(AT91_PIN_PB15, 0); /* CTS0 */
1550}
1551
1552static struct resource uart1_resources[] = {
1553 [0] = {
1554 .start = AT91SAM9G45_BASE_US1,
1555 .end = AT91SAM9G45_BASE_US1 + SZ_16K - 1,
1556 .flags = IORESOURCE_MEM,
1557 },
1558 [1] = {
1559 .start = AT91SAM9G45_ID_US1,
1560 .end = AT91SAM9G45_ID_US1,
1561 .flags = IORESOURCE_IRQ,
1562 },
1563};
1564
1565static struct atmel_uart_data uart1_data = {
1566 .use_dma_tx = 1,
1567 .use_dma_rx = 1,
1568};
1569
1570static u64 uart1_dmamask = DMA_BIT_MASK(32);
1571
1572static struct platform_device at91sam9g45_uart1_device = {
1573 .name = "atmel_usart",
1574 .id = 2,
1575 .dev = {
1576 .dma_mask = &uart1_dmamask,
1577 .coherent_dma_mask = DMA_BIT_MASK(32),
1578 .platform_data = &uart1_data,
1579 },
1580 .resource = uart1_resources,
1581 .num_resources = ARRAY_SIZE(uart1_resources),
1582};
1583
1584static inline void configure_usart1_pins(unsigned pins)
1585{
1586 at91_set_A_periph(AT91_PIN_PB4, 1); /* TXD1 */
1587 at91_set_A_periph(AT91_PIN_PB5, 0); /* RXD1 */
1588
1589 if (pins & ATMEL_UART_RTS)
1590 at91_set_A_periph(AT91_PIN_PD16, 0); /* RTS1 */
1591 if (pins & ATMEL_UART_CTS)
1592 at91_set_A_periph(AT91_PIN_PD17, 0); /* CTS1 */
1593}
1594
1595static struct resource uart2_resources[] = {
1596 [0] = {
1597 .start = AT91SAM9G45_BASE_US2,
1598 .end = AT91SAM9G45_BASE_US2 + SZ_16K - 1,
1599 .flags = IORESOURCE_MEM,
1600 },
1601 [1] = {
1602 .start = AT91SAM9G45_ID_US2,
1603 .end = AT91SAM9G45_ID_US2,
1604 .flags = IORESOURCE_IRQ,
1605 },
1606};
1607
1608static struct atmel_uart_data uart2_data = {
1609 .use_dma_tx = 1,
1610 .use_dma_rx = 1,
1611};
1612
1613static u64 uart2_dmamask = DMA_BIT_MASK(32);
1614
1615static struct platform_device at91sam9g45_uart2_device = {
1616 .name = "atmel_usart",
1617 .id = 3,
1618 .dev = {
1619 .dma_mask = &uart2_dmamask,
1620 .coherent_dma_mask = DMA_BIT_MASK(32),
1621 .platform_data = &uart2_data,
1622 },
1623 .resource = uart2_resources,
1624 .num_resources = ARRAY_SIZE(uart2_resources),
1625};
1626
1627static inline void configure_usart2_pins(unsigned pins)
1628{
1629 at91_set_A_periph(AT91_PIN_PB6, 1); /* TXD2 */
1630 at91_set_A_periph(AT91_PIN_PB7, 0); /* RXD2 */
1631
1632 if (pins & ATMEL_UART_RTS)
1633 at91_set_B_periph(AT91_PIN_PC9, 0); /* RTS2 */
1634 if (pins & ATMEL_UART_CTS)
1635 at91_set_B_periph(AT91_PIN_PC11, 0); /* CTS2 */
1636}
1637
1638static struct resource uart3_resources[] = {
1639 [0] = {
1640 .start = AT91SAM9G45_BASE_US3,
1641 .end = AT91SAM9G45_BASE_US3 + SZ_16K - 1,
1642 .flags = IORESOURCE_MEM,
1643 },
1644 [1] = {
1645 .start = AT91SAM9G45_ID_US3,
1646 .end = AT91SAM9G45_ID_US3,
1647 .flags = IORESOURCE_IRQ,
1648 },
1649};
1650
1651static struct atmel_uart_data uart3_data = {
1652 .use_dma_tx = 1,
1653 .use_dma_rx = 1,
1654};
1655
1656static u64 uart3_dmamask = DMA_BIT_MASK(32);
1657
1658static struct platform_device at91sam9g45_uart3_device = {
1659 .name = "atmel_usart",
1660 .id = 4,
1661 .dev = {
1662 .dma_mask = &uart3_dmamask,
1663 .coherent_dma_mask = DMA_BIT_MASK(32),
1664 .platform_data = &uart3_data,
1665 },
1666 .resource = uart3_resources,
1667 .num_resources = ARRAY_SIZE(uart3_resources),
1668};
1669
1670static inline void configure_usart3_pins(unsigned pins)
1671{
1672 at91_set_A_periph(AT91_PIN_PB8, 1); /* TXD3 */
1673 at91_set_A_periph(AT91_PIN_PB9, 0); /* RXD3 */
1674
1675 if (pins & ATMEL_UART_RTS)
1676 at91_set_B_periph(AT91_PIN_PA23, 0); /* RTS3 */
1677 if (pins & ATMEL_UART_CTS)
1678 at91_set_B_periph(AT91_PIN_PA24, 0); /* CTS3 */
1679}
1680
1681static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001682
1683void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
1684{
1685 struct platform_device *pdev;
Jean-Christophe PLAGNIOL-VILLARD2b348e22011-04-10 14:10:05 +08001686 struct atmel_uart_data *pdata;
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001687
1688 switch (id) {
1689 case 0: /* DBGU */
1690 pdev = &at91sam9g45_dbgu_device;
1691 configure_dbgu_pins();
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001692 break;
1693 case AT91SAM9G45_ID_US0:
1694 pdev = &at91sam9g45_uart0_device;
1695 configure_usart0_pins(pins);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001696 break;
1697 case AT91SAM9G45_ID_US1:
1698 pdev = &at91sam9g45_uart1_device;
1699 configure_usart1_pins(pins);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001700 break;
1701 case AT91SAM9G45_ID_US2:
1702 pdev = &at91sam9g45_uart2_device;
1703 configure_usart2_pins(pins);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001704 break;
1705 case AT91SAM9G45_ID_US3:
1706 pdev = &at91sam9g45_uart3_device;
1707 configure_usart3_pins(pins);
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001708 break;
1709 default:
1710 return;
1711 }
Jean-Christophe PLAGNIOL-VILLARD2b348e22011-04-10 14:10:05 +08001712 pdata = pdev->dev.platform_data;
1713 pdata->num = portnr; /* update to mapped ID */
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001714
1715 if (portnr < ATMEL_MAX_UART)
1716 at91_uarts[portnr] = pdev;
1717}
1718
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001719void __init at91_add_device_serial(void)
1720{
1721 int i;
1722
1723 for (i = 0; i < ATMEL_MAX_UART; i++) {
1724 if (at91_uarts[i])
1725 platform_device_register(at91_uarts[i]);
1726 }
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001727}
1728#else
1729void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001730void __init at91_add_device_serial(void) {}
1731#endif
1732
1733
1734/* -------------------------------------------------------------------- */
1735/*
1736 * These devices are always present and don't need any board-specific
1737 * setup.
1738 */
1739static int __init at91_add_standard_devices(void)
1740{
Jean-Christophe PLAGNIOL-VILLARD8cf93b92012-02-28 15:23:43 +08001741 if (of_have_populated_dt())
1742 return 0;
1743
Nicolas Ferre40262b22009-07-24 11:43:01 +01001744 at91_add_device_hdmac();
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001745 at91_add_device_rtc();
1746 at91_add_device_rtt();
Peter Korsgaard237a62a2011-10-06 17:41:33 +02001747 at91_add_device_trng();
Nicolas Ferre789b23b2009-06-26 15:36:58 +01001748 at91_add_device_watchdog();
1749 at91_add_device_tc();
1750 return 0;
1751}
1752
1753arch_initcall(at91_add_standard_devices);