blob: 428fc412aaf1e223da13a0d675aea08681391210 [file] [log] [blame]
Andrew Victor877d7722007-05-11 20:49:56 +01001/*
2 * Copyright (C) 2007 Atmel Corporation
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file COPYING in the main directory of this archive for
6 * more details.
7 */
8
9#include <asm/mach/arch.h>
10#include <asm/mach/map.h>
11
Andrew Victorc6686ff2008-01-23 09:13:53 +010012#include <linux/dma-mapping.h>
Russell King2f8163b2011-07-26 10:53:52 +010013#include <linux/gpio.h>
Andrew Victor877d7722007-05-11 20:49:56 +010014#include <linux/platform_device.h>
Andrew Victorf230d3f2007-11-19 13:47:20 +010015#include <linux/i2c-gpio.h>
Andrew Victor877d7722007-05-11 20:49:56 +010016
Andrew Victorf230d3f2007-11-19 13:47:20 +010017#include <linux/fb.h>
Andrew Victor877d7722007-05-11 20:49:56 +010018#include <video/atmel_lcdc.h>
19
Russell Kinga09e64f2008-08-05 16:14:15 +010020#include <mach/at91sam9rl.h>
21#include <mach/at91sam9rl_matrix.h>
Jean-Christophe PLAGNIOL-VILLARD4342d642011-11-27 23:15:50 +080022#include <mach/at91_matrix.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010023#include <mach/at91sam9_smc.h>
Uwe Kleine-Königac11a1d2013-11-14 10:49:19 +010024#include <mach/hardware.h>
Arnd Bergmann7cdc39e2012-08-24 15:10:04 +020025#include <linux/platform_data/dma-atmel.h>
Andrew Victor877d7722007-05-11 20:49:56 +010026
Jean-Christophe PLAGNIOL-VILLARD43d2f532012-10-30 05:14:17 +080027#include "board.h"
Andrew Victor877d7722007-05-11 20:49:56 +010028#include "generic.h"
29
Andrew Victor877d7722007-05-11 20:49:56 +010030
31/* --------------------------------------------------------------------
Nicolas Ferre6ff89e92009-07-24 11:43:00 +010032 * HDMAC - AHB DMA Controller
33 * -------------------------------------------------------------------- */
34
35#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
36static u64 hdmac_dmamask = DMA_BIT_MASK(32);
37
Nicolas Ferre6ff89e92009-07-24 11:43:00 +010038static struct resource hdmac_resources[] = {
39 [0] = {
Jean-Christophe PLAGNIOL-VILLARD9627b202011-10-15 15:47:51 +080040 .start = AT91SAM9RL_BASE_DMA,
41 .end = AT91SAM9RL_BASE_DMA + SZ_512 - 1,
Nicolas Ferre6ff89e92009-07-24 11:43:00 +010042 .flags = IORESOURCE_MEM,
43 },
44 [2] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +020045 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_DMA,
46 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_DMA,
Nicolas Ferre6ff89e92009-07-24 11:43:00 +010047 .flags = IORESOURCE_IRQ,
48 },
49};
50
51static struct platform_device at_hdmac_device = {
Nicolas Ferrebdad0b92011-10-10 14:55:17 +020052 .name = "at91sam9rl_dma",
Nicolas Ferre6ff89e92009-07-24 11:43:00 +010053 .id = -1,
54 .dev = {
55 .dma_mask = &hdmac_dmamask,
56 .coherent_dma_mask = DMA_BIT_MASK(32),
Nicolas Ferre6ff89e92009-07-24 11:43:00 +010057 },
58 .resource = hdmac_resources,
59 .num_resources = ARRAY_SIZE(hdmac_resources),
60};
61
62void __init at91_add_device_hdmac(void)
63{
Nicolas Ferre6ff89e92009-07-24 11:43:00 +010064 platform_device_register(&at_hdmac_device);
65}
66#else
67void __init at91_add_device_hdmac(void) {}
68#endif
69
70/* --------------------------------------------------------------------
Nicolas Ferreba45ca42008-04-08 13:59:18 +010071 * USB HS Device (Gadget)
72 * -------------------------------------------------------------------- */
73
Jochen Friedrichdd0b3822011-10-25 20:51:06 +020074#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
Nicolas Ferreba45ca42008-04-08 13:59:18 +010075
76static struct resource usba_udc_resources[] = {
77 [0] = {
78 .start = AT91SAM9RL_UDPHS_FIFO,
79 .end = AT91SAM9RL_UDPHS_FIFO + SZ_512K - 1,
80 .flags = IORESOURCE_MEM,
81 },
82 [1] = {
83 .start = AT91SAM9RL_BASE_UDPHS,
84 .end = AT91SAM9RL_BASE_UDPHS + SZ_1K - 1,
85 .flags = IORESOURCE_MEM,
86 },
87 [2] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +020088 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_UDPHS,
89 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_UDPHS,
Nicolas Ferreba45ca42008-04-08 13:59:18 +010090 .flags = IORESOURCE_IRQ,
91 },
92};
93
94#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \
95 [idx] = { \
96 .name = nam, \
97 .index = idx, \
98 .fifo_size = maxpkt, \
99 .nr_banks = maxbk, \
100 .can_dma = dma, \
101 .can_isoc = isoc, \
102 }
103
104static struct usba_ep_data usba_udc_ep[] __initdata = {
105 EP("ep0", 0, 64, 1, 0, 0),
106 EP("ep1", 1, 1024, 2, 1, 1),
107 EP("ep2", 2, 1024, 2, 1, 1),
108 EP("ep3", 3, 1024, 3, 1, 0),
109 EP("ep4", 4, 1024, 3, 1, 0),
110 EP("ep5", 5, 1024, 3, 1, 1),
111 EP("ep6", 6, 1024, 3, 1, 1),
112};
113
114#undef EP
115
116/*
117 * pdata doesn't have room for any endpoints, so we need to
118 * append room for the ones we need right after it.
119 */
120static struct {
121 struct usba_platform_data pdata;
122 struct usba_ep_data ep[7];
123} usba_udc_data;
124
125static struct platform_device at91_usba_udc_device = {
126 .name = "atmel_usba_udc",
127 .id = -1,
128 .dev = {
129 .platform_data = &usba_udc_data.pdata,
130 },
131 .resource = usba_udc_resources,
132 .num_resources = ARRAY_SIZE(usba_udc_resources),
133};
134
135void __init at91_add_device_usba(struct usba_platform_data *data)
136{
137 /*
138 * Invalid pins are 0 on AT91, but the usba driver is shared
139 * with AVR32, which use negative values instead. Once/if
140 * gpio_is_valid() is ported to AT91, revisit this code.
141 */
142 usba_udc_data.pdata.vbus_pin = -EINVAL;
143 usba_udc_data.pdata.num_ep = ARRAY_SIZE(usba_udc_ep);
Justin P. Mattock6eab04a2011-04-08 19:49:08 -0700144 memcpy(usba_udc_data.ep, usba_udc_ep, sizeof(usba_udc_ep));
Nicolas Ferreba45ca42008-04-08 13:59:18 +0100145
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800146 if (data && gpio_is_valid(data->vbus_pin)) {
Nicolas Ferreba45ca42008-04-08 13:59:18 +0100147 at91_set_gpio_input(data->vbus_pin, 0);
148 at91_set_deglitch(data->vbus_pin, 1);
149 usba_udc_data.pdata.vbus_pin = data->vbus_pin;
150 }
151
152 /* Pullup pin is handled internally by USB device peripheral */
153
Nicolas Ferreba45ca42008-04-08 13:59:18 +0100154 platform_device_register(&at91_usba_udc_device);
155}
156#else
157void __init at91_add_device_usba(struct usba_platform_data *data) {}
158#endif
159
160
161/* --------------------------------------------------------------------
Andrew Victor877d7722007-05-11 20:49:56 +0100162 * MMC / SD
163 * -------------------------------------------------------------------- */
164
Ludovic Desroches4cf33262012-05-21 12:23:27 +0200165#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
Andrew Victorc6686ff2008-01-23 09:13:53 +0100166static u64 mmc_dmamask = DMA_BIT_MASK(32);
Ludovic Desroches4cf33262012-05-21 12:23:27 +0200167static struct mci_platform_data mmc_data;
Andrew Victor877d7722007-05-11 20:49:56 +0100168
169static struct resource mmc_resources[] = {
170 [0] = {
171 .start = AT91SAM9RL_BASE_MCI,
172 .end = AT91SAM9RL_BASE_MCI + SZ_16K - 1,
173 .flags = IORESOURCE_MEM,
174 },
175 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200176 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_MCI,
177 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_MCI,
Andrew Victor877d7722007-05-11 20:49:56 +0100178 .flags = IORESOURCE_IRQ,
179 },
180};
181
182static struct platform_device at91sam9rl_mmc_device = {
Ludovic Desroches4cf33262012-05-21 12:23:27 +0200183 .name = "atmel_mci",
Andrew Victor877d7722007-05-11 20:49:56 +0100184 .id = -1,
185 .dev = {
186 .dma_mask = &mmc_dmamask,
Andrew Victorc6686ff2008-01-23 09:13:53 +0100187 .coherent_dma_mask = DMA_BIT_MASK(32),
Andrew Victor877d7722007-05-11 20:49:56 +0100188 .platform_data = &mmc_data,
189 },
190 .resource = mmc_resources,
191 .num_resources = ARRAY_SIZE(mmc_resources),
192};
193
Ludovic Desroches4cf33262012-05-21 12:23:27 +0200194void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
Andrew Victor877d7722007-05-11 20:49:56 +0100195{
196 if (!data)
197 return;
198
Ludovic Desroches4cf33262012-05-21 12:23:27 +0200199 if (data->slot[0].bus_width) {
200 /* input/irq */
201 if (gpio_is_valid(data->slot[0].detect_pin)) {
202 at91_set_gpio_input(data->slot[0].detect_pin, 1);
203 at91_set_deglitch(data->slot[0].detect_pin, 1);
204 }
205 if (gpio_is_valid(data->slot[0].wp_pin))
206 at91_set_gpio_input(data->slot[0].wp_pin, 1);
207
208 /* CLK */
209 at91_set_A_periph(AT91_PIN_PA2, 0);
210
211 /* CMD */
212 at91_set_A_periph(AT91_PIN_PA1, 1);
213
214 /* DAT0, maybe DAT1..DAT3 */
215 at91_set_A_periph(AT91_PIN_PA0, 1);
216 if (data->slot[0].bus_width == 4) {
217 at91_set_A_periph(AT91_PIN_PA3, 1);
218 at91_set_A_periph(AT91_PIN_PA4, 1);
219 at91_set_A_periph(AT91_PIN_PA5, 1);
220 }
221
222 mmc_data = *data;
223 platform_device_register(&at91sam9rl_mmc_device);
Andrew Victor877d7722007-05-11 20:49:56 +0100224 }
Andrew Victor877d7722007-05-11 20:49:56 +0100225}
226#else
Ludovic Desroches4cf33262012-05-21 12:23:27 +0200227void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
Andrew Victor877d7722007-05-11 20:49:56 +0100228#endif
229
230
231/* --------------------------------------------------------------------
232 * NAND / SmartMedia
233 * -------------------------------------------------------------------- */
234
Pieter du Preezf6ed6f72008-08-01 10:06:40 +0100235#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
Håvard Skinnemoen3c3796c2008-06-06 18:04:53 +0200236static struct atmel_nand_data nand_data;
Andrew Victor877d7722007-05-11 20:49:56 +0100237
238#define NAND_BASE AT91_CHIPSELECT_3
239
240static struct resource nand_resources[] = {
Andrew Victord7a24152008-04-02 21:44:44 +0100241 [0] = {
Andrew Victor877d7722007-05-11 20:49:56 +0100242 .start = NAND_BASE,
243 .end = NAND_BASE + SZ_256M - 1,
244 .flags = IORESOURCE_MEM,
Andrew Victord7a24152008-04-02 21:44:44 +0100245 },
246 [1] = {
Jean-Christophe PLAGNIOL-VILLARDd28edd12011-09-18 09:31:56 +0800247 .start = AT91SAM9RL_BASE_ECC,
248 .end = AT91SAM9RL_BASE_ECC + SZ_512 - 1,
Andrew Victord7a24152008-04-02 21:44:44 +0100249 .flags = IORESOURCE_MEM,
Andrew Victor877d7722007-05-11 20:49:56 +0100250 }
251};
252
Håvard Skinnemoen3c3796c2008-06-06 18:04:53 +0200253static struct platform_device atmel_nand_device = {
254 .name = "atmel_nand",
Andrew Victor877d7722007-05-11 20:49:56 +0100255 .id = -1,
256 .dev = {
257 .platform_data = &nand_data,
258 },
259 .resource = nand_resources,
260 .num_resources = ARRAY_SIZE(nand_resources),
261};
262
Håvard Skinnemoen3c3796c2008-06-06 18:04:53 +0200263void __init at91_add_device_nand(struct atmel_nand_data *data)
Andrew Victor877d7722007-05-11 20:49:56 +0100264{
265 unsigned long csa;
266
267 if (!data)
268 return;
269
Jean-Christophe PLAGNIOL-VILLARD4342d642011-11-27 23:15:50 +0800270 csa = at91_matrix_read(AT91_MATRIX_EBICSA);
271 at91_matrix_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA);
Andrew Victor877d7722007-05-11 20:49:56 +0100272
Andrew Victor877d7722007-05-11 20:49:56 +0100273 /* enable pin */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800274 if (gpio_is_valid(data->enable_pin))
Andrew Victor877d7722007-05-11 20:49:56 +0100275 at91_set_gpio_output(data->enable_pin, 1);
276
277 /* ready/busy pin */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800278 if (gpio_is_valid(data->rdy_pin))
Andrew Victor877d7722007-05-11 20:49:56 +0100279 at91_set_gpio_input(data->rdy_pin, 1);
280
281 /* card detect pin */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800282 if (gpio_is_valid(data->det_pin))
Andrew Victor877d7722007-05-11 20:49:56 +0100283 at91_set_gpio_input(data->det_pin, 1);
284
285 at91_set_A_periph(AT91_PIN_PB4, 0); /* NANDOE */
286 at91_set_A_periph(AT91_PIN_PB5, 0); /* NANDWE */
287
288 nand_data = *data;
Håvard Skinnemoen3c3796c2008-06-06 18:04:53 +0200289 platform_device_register(&atmel_nand_device);
Andrew Victor877d7722007-05-11 20:49:56 +0100290}
291
292#else
Håvard Skinnemoen3c3796c2008-06-06 18:04:53 +0200293void __init at91_add_device_nand(struct atmel_nand_data *data) {}
Andrew Victor877d7722007-05-11 20:49:56 +0100294#endif
295
296
297/* --------------------------------------------------------------------
298 * TWI (i2c)
299 * -------------------------------------------------------------------- */
300
Andrew Victorf230d3f2007-11-19 13:47:20 +0100301/*
302 * Prefer the GPIO code since the TWI controller isn't robust
303 * (gets overruns and underruns under load) and can only issue
304 * repeated STARTs in one scenario (the driver doesn't yet handle them).
305 */
306#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
307
308static struct i2c_gpio_platform_data pdata = {
309 .sda_pin = AT91_PIN_PA23,
310 .sda_is_open_drain = 1,
311 .scl_pin = AT91_PIN_PA24,
312 .scl_is_open_drain = 1,
313 .udelay = 2, /* ~100 kHz */
314};
315
316static struct platform_device at91sam9rl_twi_device = {
317 .name = "i2c-gpio",
Bo Shen78404872012-10-15 17:30:27 +0800318 .id = 0,
Andrew Victorf230d3f2007-11-19 13:47:20 +0100319 .dev.platform_data = &pdata,
320};
321
322void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
323{
324 at91_set_GPIO_periph(AT91_PIN_PA23, 1); /* TWD (SDA) */
325 at91_set_multi_drive(AT91_PIN_PA23, 1);
326
327 at91_set_GPIO_periph(AT91_PIN_PA24, 1); /* TWCK (SCL) */
328 at91_set_multi_drive(AT91_PIN_PA24, 1);
329
330 i2c_register_board_info(0, devices, nr_devices);
331 platform_device_register(&at91sam9rl_twi_device);
332}
333
334#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
Andrew Victor877d7722007-05-11 20:49:56 +0100335
336static struct resource twi_resources[] = {
337 [0] = {
338 .start = AT91SAM9RL_BASE_TWI0,
339 .end = AT91SAM9RL_BASE_TWI0 + SZ_16K - 1,
340 .flags = IORESOURCE_MEM,
341 },
342 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200343 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_TWI0,
344 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_TWI0,
Andrew Victor877d7722007-05-11 20:49:56 +0100345 .flags = IORESOURCE_IRQ,
346 },
347};
348
349static struct platform_device at91sam9rl_twi_device = {
Nikolaus Vossfac368a2011-11-08 11:49:46 +0100350 .name = "i2c-at91sam9g20",
Bo Shen302090a2012-10-15 17:30:28 +0800351 .id = 0,
Andrew Victor877d7722007-05-11 20:49:56 +0100352 .resource = twi_resources,
353 .num_resources = ARRAY_SIZE(twi_resources),
354};
355
Andrew Victorf230d3f2007-11-19 13:47:20 +0100356void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
Andrew Victor877d7722007-05-11 20:49:56 +0100357{
358 /* pins used for TWI interface */
359 at91_set_A_periph(AT91_PIN_PA23, 0); /* TWD */
360 at91_set_multi_drive(AT91_PIN_PA23, 1);
361
362 at91_set_A_periph(AT91_PIN_PA24, 0); /* TWCK */
363 at91_set_multi_drive(AT91_PIN_PA24, 1);
364
Andrew Victorf230d3f2007-11-19 13:47:20 +0100365 i2c_register_board_info(0, devices, nr_devices);
Andrew Victor877d7722007-05-11 20:49:56 +0100366 platform_device_register(&at91sam9rl_twi_device);
367}
368#else
Andrew Victorf230d3f2007-11-19 13:47:20 +0100369void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
Andrew Victor877d7722007-05-11 20:49:56 +0100370#endif
371
372
373/* --------------------------------------------------------------------
374 * SPI
375 * -------------------------------------------------------------------- */
376
377#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
Andrew Victorc6686ff2008-01-23 09:13:53 +0100378static u64 spi_dmamask = DMA_BIT_MASK(32);
Andrew Victor877d7722007-05-11 20:49:56 +0100379
380static struct resource spi_resources[] = {
381 [0] = {
382 .start = AT91SAM9RL_BASE_SPI,
383 .end = AT91SAM9RL_BASE_SPI + SZ_16K - 1,
384 .flags = IORESOURCE_MEM,
385 },
386 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200387 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_SPI,
388 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_SPI,
Andrew Victor877d7722007-05-11 20:49:56 +0100389 .flags = IORESOURCE_IRQ,
390 },
391};
392
393static struct platform_device at91sam9rl_spi_device = {
394 .name = "atmel_spi",
395 .id = 0,
396 .dev = {
397 .dma_mask = &spi_dmamask,
Andrew Victorc6686ff2008-01-23 09:13:53 +0100398 .coherent_dma_mask = DMA_BIT_MASK(32),
Andrew Victor877d7722007-05-11 20:49:56 +0100399 },
400 .resource = spi_resources,
401 .num_resources = ARRAY_SIZE(spi_resources),
402};
403
404static const unsigned spi_standard_cs[4] = { AT91_PIN_PA28, AT91_PIN_PB7, AT91_PIN_PD8, AT91_PIN_PD9 };
405
406
407void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
408{
409 int i;
410 unsigned long cs_pin;
411
412 at91_set_A_periph(AT91_PIN_PA25, 0); /* MISO */
413 at91_set_A_periph(AT91_PIN_PA26, 0); /* MOSI */
414 at91_set_A_periph(AT91_PIN_PA27, 0); /* SPCK */
415
416 /* Enable SPI chip-selects */
417 for (i = 0; i < nr_devices; i++) {
418 if (devices[i].controller_data)
419 cs_pin = (unsigned long) devices[i].controller_data;
420 else
421 cs_pin = spi_standard_cs[devices[i].chip_select];
422
Nicolas Ferre0c2c1f62012-03-28 11:58:58 +0200423 if (!gpio_is_valid(cs_pin))
424 continue;
425
Andrew Victor877d7722007-05-11 20:49:56 +0100426 /* enable chip-select pin */
427 at91_set_gpio_output(cs_pin, 1);
428
429 /* pass chip-select pin to driver */
430 devices[i].controller_data = (void *) cs_pin;
431 }
432
433 spi_register_board_info(devices, nr_devices);
434 platform_device_register(&at91sam9rl_spi_device);
435}
436#else
437void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
438#endif
439
440
441/* --------------------------------------------------------------------
Nicolas Ferre439a3302009-09-18 16:14:21 +0100442 * AC97
443 * -------------------------------------------------------------------- */
444
445#if defined(CONFIG_SND_ATMEL_AC97C) || defined(CONFIG_SND_ATMEL_AC97C_MODULE)
446static u64 ac97_dmamask = DMA_BIT_MASK(32);
447static struct ac97c_platform_data ac97_data;
448
449static struct resource ac97_resources[] = {
450 [0] = {
451 .start = AT91SAM9RL_BASE_AC97C,
452 .end = AT91SAM9RL_BASE_AC97C + SZ_16K - 1,
453 .flags = IORESOURCE_MEM,
454 },
455 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200456 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_AC97C,
457 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_AC97C,
Nicolas Ferre439a3302009-09-18 16:14:21 +0100458 .flags = IORESOURCE_IRQ,
459 },
460};
461
462static struct platform_device at91sam9rl_ac97_device = {
463 .name = "atmel_ac97c",
464 .id = 0,
465 .dev = {
466 .dma_mask = &ac97_dmamask,
467 .coherent_dma_mask = DMA_BIT_MASK(32),
468 .platform_data = &ac97_data,
469 },
470 .resource = ac97_resources,
471 .num_resources = ARRAY_SIZE(ac97_resources),
472};
473
474void __init at91_add_device_ac97(struct ac97c_platform_data *data)
475{
476 if (!data)
477 return;
478
479 at91_set_A_periph(AT91_PIN_PD1, 0); /* AC97FS */
480 at91_set_A_periph(AT91_PIN_PD2, 0); /* AC97CK */
481 at91_set_A_periph(AT91_PIN_PD3, 0); /* AC97TX */
482 at91_set_A_periph(AT91_PIN_PD4, 0); /* AC97RX */
483
484 /* reset */
Jean-Christophe PLAGNIOL-VILLARDcc9f9ae2011-09-19 15:28:25 +0800485 if (gpio_is_valid(data->reset_pin))
Nicolas Ferre439a3302009-09-18 16:14:21 +0100486 at91_set_gpio_output(data->reset_pin, 0);
487
488 ac97_data = *data;
489 platform_device_register(&at91sam9rl_ac97_device);
490}
491#else
492void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
493#endif
494
495
496/* --------------------------------------------------------------------
Andrew Victor877d7722007-05-11 20:49:56 +0100497 * LCD Controller
498 * -------------------------------------------------------------------- */
499
500#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
Andrew Victorc6686ff2008-01-23 09:13:53 +0100501static u64 lcdc_dmamask = DMA_BIT_MASK(32);
Jean-Christophe PLAGNIOL-VILLARD8af2c282013-03-28 22:53:42 +0800502static struct atmel_lcdfb_pdata lcdc_data;
Andrew Victor877d7722007-05-11 20:49:56 +0100503
504static struct resource lcdc_resources[] = {
505 [0] = {
506 .start = AT91SAM9RL_LCDC_BASE,
507 .end = AT91SAM9RL_LCDC_BASE + SZ_4K - 1,
508 .flags = IORESOURCE_MEM,
509 },
510 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200511 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_LCDC,
512 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_LCDC,
Andrew Victor877d7722007-05-11 20:49:56 +0100513 .flags = IORESOURCE_IRQ,
514 },
Andrew Victor877d7722007-05-11 20:49:56 +0100515};
516
517static struct platform_device at91_lcdc_device = {
Johan Hovoldbbd44f6b2013-02-07 16:31:58 +0100518 .name = "at91sam9rl-lcdfb",
Andrew Victor877d7722007-05-11 20:49:56 +0100519 .id = 0,
520 .dev = {
521 .dma_mask = &lcdc_dmamask,
Andrew Victorc6686ff2008-01-23 09:13:53 +0100522 .coherent_dma_mask = DMA_BIT_MASK(32),
Andrew Victor877d7722007-05-11 20:49:56 +0100523 .platform_data = &lcdc_data,
524 },
525 .resource = lcdc_resources,
526 .num_resources = ARRAY_SIZE(lcdc_resources),
527};
528
Jean-Christophe PLAGNIOL-VILLARD8af2c282013-03-28 22:53:42 +0800529void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
Andrew Victor877d7722007-05-11 20:49:56 +0100530{
531 if (!data) {
532 return;
533 }
534
535 at91_set_B_periph(AT91_PIN_PC1, 0); /* LCDPWR */
536 at91_set_A_periph(AT91_PIN_PC5, 0); /* LCDHSYNC */
537 at91_set_A_periph(AT91_PIN_PC6, 0); /* LCDDOTCK */
538 at91_set_A_periph(AT91_PIN_PC7, 0); /* LCDDEN */
539 at91_set_A_periph(AT91_PIN_PC3, 0); /* LCDCC */
540 at91_set_B_periph(AT91_PIN_PC9, 0); /* LCDD3 */
541 at91_set_B_periph(AT91_PIN_PC10, 0); /* LCDD4 */
542 at91_set_B_periph(AT91_PIN_PC11, 0); /* LCDD5 */
543 at91_set_B_periph(AT91_PIN_PC12, 0); /* LCDD6 */
544 at91_set_B_periph(AT91_PIN_PC13, 0); /* LCDD7 */
545 at91_set_B_periph(AT91_PIN_PC15, 0); /* LCDD11 */
546 at91_set_B_periph(AT91_PIN_PC16, 0); /* LCDD12 */
547 at91_set_B_periph(AT91_PIN_PC17, 0); /* LCDD13 */
548 at91_set_B_periph(AT91_PIN_PC18, 0); /* LCDD14 */
549 at91_set_B_periph(AT91_PIN_PC19, 0); /* LCDD15 */
550 at91_set_B_periph(AT91_PIN_PC20, 0); /* LCDD18 */
551 at91_set_B_periph(AT91_PIN_PC21, 0); /* LCDD19 */
552 at91_set_B_periph(AT91_PIN_PC22, 0); /* LCDD20 */
553 at91_set_B_periph(AT91_PIN_PC23, 0); /* LCDD21 */
554 at91_set_B_periph(AT91_PIN_PC24, 0); /* LCDD22 */
555 at91_set_B_periph(AT91_PIN_PC25, 0); /* LCDD23 */
556
557 lcdc_data = *data;
558 platform_device_register(&at91_lcdc_device);
559}
560#else
Jean-Christophe PLAGNIOL-VILLARD8af2c282013-03-28 22:53:42 +0800561void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
Andrew Victor877d7722007-05-11 20:49:56 +0100562#endif
563
564
565/* --------------------------------------------------------------------
Andrew Victore5f40bf2008-04-02 21:58:00 +0100566 * Timer/Counter block
567 * -------------------------------------------------------------------- */
568
569#ifdef CONFIG_ATMEL_TCLIB
570
571static struct resource tcb_resources[] = {
572 [0] = {
573 .start = AT91SAM9RL_BASE_TCB0,
574 .end = AT91SAM9RL_BASE_TCB0 + SZ_16K - 1,
575 .flags = IORESOURCE_MEM,
576 },
577 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200578 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC0,
579 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC0,
Andrew Victore5f40bf2008-04-02 21:58:00 +0100580 .flags = IORESOURCE_IRQ,
581 },
582 [2] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200583 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC1,
584 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC1,
Andrew Victore5f40bf2008-04-02 21:58:00 +0100585 .flags = IORESOURCE_IRQ,
586 },
587 [3] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200588 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC2,
589 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC2,
Andrew Victore5f40bf2008-04-02 21:58:00 +0100590 .flags = IORESOURCE_IRQ,
591 },
592};
593
594static struct platform_device at91sam9rl_tcb_device = {
595 .name = "atmel_tcb",
596 .id = 0,
597 .resource = tcb_resources,
598 .num_resources = ARRAY_SIZE(tcb_resources),
599};
600
601static void __init at91_add_device_tc(void)
602{
Andrew Victore5f40bf2008-04-02 21:58:00 +0100603 platform_device_register(&at91sam9rl_tcb_device);
604}
605#else
606static void __init at91_add_device_tc(void) { }
607#endif
608
609
610/* --------------------------------------------------------------------
Andrew Victorf7647e62008-09-18 19:45:35 +0100611 * Touchscreen
612 * -------------------------------------------------------------------- */
613
614#if defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) || defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC_MODULE)
615static u64 tsadcc_dmamask = DMA_BIT_MASK(32);
Nicolas Ferre423c9b02009-11-19 09:31:20 -0800616static struct at91_tsadcc_data tsadcc_data;
Andrew Victorf7647e62008-09-18 19:45:35 +0100617
618static struct resource tsadcc_resources[] = {
619 [0] = {
620 .start = AT91SAM9RL_BASE_TSC,
621 .end = AT91SAM9RL_BASE_TSC + SZ_16K - 1,
622 .flags = IORESOURCE_MEM,
623 },
624 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200625 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_TSC,
626 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_TSC,
Andrew Victorf7647e62008-09-18 19:45:35 +0100627 .flags = IORESOURCE_IRQ,
628 }
629};
630
631static struct platform_device at91sam9rl_tsadcc_device = {
632 .name = "atmel_tsadcc",
633 .id = -1,
634 .dev = {
635 .dma_mask = &tsadcc_dmamask,
636 .coherent_dma_mask = DMA_BIT_MASK(32),
Nicolas Ferre423c9b02009-11-19 09:31:20 -0800637 .platform_data = &tsadcc_data,
Andrew Victorf7647e62008-09-18 19:45:35 +0100638 },
639 .resource = tsadcc_resources,
640 .num_resources = ARRAY_SIZE(tsadcc_resources),
641};
642
Nicolas Ferre423c9b02009-11-19 09:31:20 -0800643void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data)
Andrew Victorf7647e62008-09-18 19:45:35 +0100644{
Nicolas Ferre423c9b02009-11-19 09:31:20 -0800645 if (!data)
646 return;
647
Andrew Victorf7647e62008-09-18 19:45:35 +0100648 at91_set_A_periph(AT91_PIN_PA17, 0); /* AD0_XR */
649 at91_set_A_periph(AT91_PIN_PA18, 0); /* AD1_XL */
650 at91_set_A_periph(AT91_PIN_PA19, 0); /* AD2_YT */
651 at91_set_A_periph(AT91_PIN_PA20, 0); /* AD3_TB */
652
Nicolas Ferre423c9b02009-11-19 09:31:20 -0800653 tsadcc_data = *data;
Andrew Victorf7647e62008-09-18 19:45:35 +0100654 platform_device_register(&at91sam9rl_tsadcc_device);
655}
656#else
Nicolas Ferre423c9b02009-11-19 09:31:20 -0800657void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
Andrew Victorf7647e62008-09-18 19:45:35 +0100658#endif
659
660
661/* --------------------------------------------------------------------
Andrew Victor884f5a62008-01-23 09:11:13 +0100662 * RTC
663 * -------------------------------------------------------------------- */
664
665#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
666static struct platform_device at91sam9rl_rtc_device = {
667 .name = "at91_rtc",
668 .id = -1,
669 .num_resources = 0,
670};
671
672static void __init at91_add_device_rtc(void)
673{
674 platform_device_register(&at91sam9rl_rtc_device);
675}
676#else
677static void __init at91_add_device_rtc(void) {}
678#endif
679
680
681/* --------------------------------------------------------------------
682 * RTT
683 * -------------------------------------------------------------------- */
684
685static struct resource rtt_resources[] = {
686 {
Jean-Christophe PLAGNIOL-VILLARDeab5fd62011-09-18 10:12:00 +0800687 .start = AT91SAM9RL_BASE_RTT,
688 .end = AT91SAM9RL_BASE_RTT + SZ_16 - 1,
Andrew Victor884f5a62008-01-23 09:11:13 +0100689 .flags = IORESOURCE_MEM,
Jean-Christophe PLAGNIOL-VILLARDb3af8b42012-02-15 21:24:46 +0800690 }, {
691 .flags = IORESOURCE_MEM,
Ludovic Desrochese402af62012-08-14 11:19:22 +0200692 }, {
693 .flags = IORESOURCE_IRQ,
Andrew Victor884f5a62008-01-23 09:11:13 +0100694 }
695};
696
697static struct platform_device at91sam9rl_rtt_device = {
698 .name = "at91_rtt",
Andrew Victor4fd92122008-04-02 21:55:19 +0100699 .id = 0,
Andrew Victor884f5a62008-01-23 09:11:13 +0100700 .resource = rtt_resources,
Andrew Victor884f5a62008-01-23 09:11:13 +0100701};
702
Jean-Christophe PLAGNIOL-VILLARD205056a2012-02-15 20:51:37 +0800703#if IS_ENABLED(CONFIG_RTC_DRV_AT91SAM9)
704static void __init at91_add_device_rtt_rtc(void)
705{
706 at91sam9rl_rtt_device.name = "rtc-at91sam9";
Jean-Christophe PLAGNIOL-VILLARDb3af8b42012-02-15 21:24:46 +0800707 /*
708 * The second resource is needed:
709 * GPBR will serve as the storage for RTC time offset
710 */
Ludovic Desrochese402af62012-08-14 11:19:22 +0200711 at91sam9rl_rtt_device.num_resources = 3;
Jean-Christophe PLAGNIOL-VILLARDb3af8b42012-02-15 21:24:46 +0800712 rtt_resources[1].start = AT91SAM9RL_BASE_GPBR +
713 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
714 rtt_resources[1].end = rtt_resources[1].start + 3;
Ludovic Desrochese402af62012-08-14 11:19:22 +0200715 rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
716 rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
Jean-Christophe PLAGNIOL-VILLARD205056a2012-02-15 20:51:37 +0800717}
718#else
Jean-Christophe PLAGNIOL-VILLARDb3af8b42012-02-15 21:24:46 +0800719static void __init at91_add_device_rtt_rtc(void)
720{
721 /* Only one resource is needed: RTT not used as RTC */
722 at91sam9rl_rtt_device.num_resources = 1;
723}
Jean-Christophe PLAGNIOL-VILLARD205056a2012-02-15 20:51:37 +0800724#endif
725
Andrew Victor884f5a62008-01-23 09:11:13 +0100726static void __init at91_add_device_rtt(void)
727{
Jean-Christophe PLAGNIOL-VILLARD205056a2012-02-15 20:51:37 +0800728 at91_add_device_rtt_rtc();
Andrew Victor884f5a62008-01-23 09:11:13 +0100729 platform_device_register(&at91sam9rl_rtt_device);
730}
731
732
733/* --------------------------------------------------------------------
734 * Watchdog
735 * -------------------------------------------------------------------- */
736
Andrew Victor2af29b72009-02-11 21:23:10 +0100737#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
Jean-Christophe PLAGNIOL-VILLARDc1c30a22011-11-02 01:43:31 +0800738static struct resource wdt_resources[] = {
739 {
740 .start = AT91SAM9RL_BASE_WDT,
741 .end = AT91SAM9RL_BASE_WDT + SZ_16 - 1,
742 .flags = IORESOURCE_MEM,
743 }
744};
745
Andrew Victor884f5a62008-01-23 09:11:13 +0100746static struct platform_device at91sam9rl_wdt_device = {
747 .name = "at91_wdt",
748 .id = -1,
Jean-Christophe PLAGNIOL-VILLARDc1c30a22011-11-02 01:43:31 +0800749 .resource = wdt_resources,
750 .num_resources = ARRAY_SIZE(wdt_resources),
Andrew Victor884f5a62008-01-23 09:11:13 +0100751};
752
753static void __init at91_add_device_watchdog(void)
754{
755 platform_device_register(&at91sam9rl_wdt_device);
756}
757#else
758static void __init at91_add_device_watchdog(void) {}
759#endif
760
761
762/* --------------------------------------------------------------------
Andrew Victorbb1ad682008-09-18 19:42:37 +0100763 * PWM
764 * --------------------------------------------------------------------*/
765
766#if defined(CONFIG_ATMEL_PWM)
767static u32 pwm_mask;
768
769static struct resource pwm_resources[] = {
770 [0] = {
771 .start = AT91SAM9RL_BASE_PWMC,
772 .end = AT91SAM9RL_BASE_PWMC + SZ_16K - 1,
773 .flags = IORESOURCE_MEM,
774 },
775 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200776 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_PWMC,
777 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_PWMC,
Andrew Victorbb1ad682008-09-18 19:42:37 +0100778 .flags = IORESOURCE_IRQ,
779 },
780};
781
782static struct platform_device at91sam9rl_pwm0_device = {
783 .name = "atmel_pwm",
784 .id = -1,
785 .dev = {
786 .platform_data = &pwm_mask,
787 },
788 .resource = pwm_resources,
789 .num_resources = ARRAY_SIZE(pwm_resources),
790};
791
792void __init at91_add_device_pwm(u32 mask)
793{
794 if (mask & (1 << AT91_PWM0))
795 at91_set_B_periph(AT91_PIN_PB8, 1); /* enable PWM0 */
796
797 if (mask & (1 << AT91_PWM1))
798 at91_set_B_periph(AT91_PIN_PB9, 1); /* enable PWM1 */
799
800 if (mask & (1 << AT91_PWM2))
801 at91_set_B_periph(AT91_PIN_PD5, 1); /* enable PWM2 */
802
803 if (mask & (1 << AT91_PWM3))
804 at91_set_B_periph(AT91_PIN_PD8, 1); /* enable PWM3 */
805
806 pwm_mask = mask;
807
808 platform_device_register(&at91sam9rl_pwm0_device);
809}
810#else
811void __init at91_add_device_pwm(u32 mask) {}
812#endif
813
814
815/* --------------------------------------------------------------------
Andrew Victorbfbc3262008-01-23 09:18:06 +0100816 * SSC -- Synchronous Serial Controller
817 * -------------------------------------------------------------------- */
818
819#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
820static u64 ssc0_dmamask = DMA_BIT_MASK(32);
821
822static struct resource ssc0_resources[] = {
823 [0] = {
824 .start = AT91SAM9RL_BASE_SSC0,
825 .end = AT91SAM9RL_BASE_SSC0 + SZ_16K - 1,
826 .flags = IORESOURCE_MEM,
827 },
828 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200829 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC0,
830 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC0,
Andrew Victorbfbc3262008-01-23 09:18:06 +0100831 .flags = IORESOURCE_IRQ,
832 },
833};
834
835static struct platform_device at91sam9rl_ssc0_device = {
Bo Shen636036d22012-11-06 13:57:51 +0800836 .name = "at91rm9200_ssc",
Andrew Victorbfbc3262008-01-23 09:18:06 +0100837 .id = 0,
838 .dev = {
839 .dma_mask = &ssc0_dmamask,
840 .coherent_dma_mask = DMA_BIT_MASK(32),
841 },
842 .resource = ssc0_resources,
843 .num_resources = ARRAY_SIZE(ssc0_resources),
844};
845
846static inline void configure_ssc0_pins(unsigned pins)
847{
848 if (pins & ATMEL_SSC_TF)
849 at91_set_A_periph(AT91_PIN_PC0, 1);
850 if (pins & ATMEL_SSC_TK)
851 at91_set_A_periph(AT91_PIN_PC1, 1);
852 if (pins & ATMEL_SSC_TD)
853 at91_set_A_periph(AT91_PIN_PA15, 1);
854 if (pins & ATMEL_SSC_RD)
855 at91_set_A_periph(AT91_PIN_PA16, 1);
856 if (pins & ATMEL_SSC_RK)
857 at91_set_B_periph(AT91_PIN_PA10, 1);
858 if (pins & ATMEL_SSC_RF)
859 at91_set_B_periph(AT91_PIN_PA22, 1);
860}
861
862static u64 ssc1_dmamask = DMA_BIT_MASK(32);
863
864static struct resource ssc1_resources[] = {
865 [0] = {
866 .start = AT91SAM9RL_BASE_SSC1,
867 .end = AT91SAM9RL_BASE_SSC1 + SZ_16K - 1,
868 .flags = IORESOURCE_MEM,
869 },
870 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200871 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC1,
872 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC1,
Andrew Victorbfbc3262008-01-23 09:18:06 +0100873 .flags = IORESOURCE_IRQ,
874 },
875};
876
877static struct platform_device at91sam9rl_ssc1_device = {
Bo Shen636036d22012-11-06 13:57:51 +0800878 .name = "at91rm9200_ssc",
Andrew Victorbfbc3262008-01-23 09:18:06 +0100879 .id = 1,
880 .dev = {
881 .dma_mask = &ssc1_dmamask,
882 .coherent_dma_mask = DMA_BIT_MASK(32),
883 },
884 .resource = ssc1_resources,
885 .num_resources = ARRAY_SIZE(ssc1_resources),
886};
887
888static inline void configure_ssc1_pins(unsigned pins)
889{
890 if (pins & ATMEL_SSC_TF)
891 at91_set_B_periph(AT91_PIN_PA29, 1);
892 if (pins & ATMEL_SSC_TK)
893 at91_set_B_periph(AT91_PIN_PA30, 1);
894 if (pins & ATMEL_SSC_TD)
895 at91_set_B_periph(AT91_PIN_PA13, 1);
896 if (pins & ATMEL_SSC_RD)
897 at91_set_B_periph(AT91_PIN_PA14, 1);
898 if (pins & ATMEL_SSC_RK)
899 at91_set_B_periph(AT91_PIN_PA9, 1);
900 if (pins & ATMEL_SSC_RF)
901 at91_set_B_periph(AT91_PIN_PA8, 1);
902}
903
904/*
Andrew Victorbfbc3262008-01-23 09:18:06 +0100905 * SSC controllers are accessed through library code, instead of any
906 * kind of all-singing/all-dancing driver. For example one could be
907 * used by a particular I2S audio codec's driver, while another one
908 * on the same system might be used by a custom data capture driver.
909 */
910void __init at91_add_device_ssc(unsigned id, unsigned pins)
911{
912 struct platform_device *pdev;
913
914 /*
915 * NOTE: caller is responsible for passing information matching
916 * "pins" to whatever will be using each particular controller.
917 */
918 switch (id) {
919 case AT91SAM9RL_ID_SSC0:
920 pdev = &at91sam9rl_ssc0_device;
921 configure_ssc0_pins(pins);
Andrew Victorbfbc3262008-01-23 09:18:06 +0100922 break;
923 case AT91SAM9RL_ID_SSC1:
924 pdev = &at91sam9rl_ssc1_device;
925 configure_ssc1_pins(pins);
Andrew Victorbfbc3262008-01-23 09:18:06 +0100926 break;
927 default:
928 return;
929 }
930
931 platform_device_register(pdev);
932}
933
934#else
935void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
936#endif
937
938
939/* --------------------------------------------------------------------
Andrew Victor877d7722007-05-11 20:49:56 +0100940 * UART
941 * -------------------------------------------------------------------- */
942
943#if defined(CONFIG_SERIAL_ATMEL)
944static struct resource dbgu_resources[] = {
945 [0] = {
Jean-Christophe PLAGNIOL-VILLARD13079a72011-11-02 01:43:31 +0800946 .start = AT91SAM9RL_BASE_DBGU,
947 .end = AT91SAM9RL_BASE_DBGU + SZ_512 - 1,
Andrew Victor877d7722007-05-11 20:49:56 +0100948 .flags = IORESOURCE_MEM,
949 },
950 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200951 .start = NR_IRQS_LEGACY + AT91_ID_SYS,
952 .end = NR_IRQS_LEGACY + AT91_ID_SYS,
Andrew Victor877d7722007-05-11 20:49:56 +0100953 .flags = IORESOURCE_IRQ,
954 },
955};
956
957static struct atmel_uart_data dbgu_data = {
958 .use_dma_tx = 0,
959 .use_dma_rx = 0, /* DBGU not capable of receive DMA */
Linus Walleij354e57f2013-11-07 10:25:55 +0100960 .rts_gpio = -EINVAL,
Andrew Victor877d7722007-05-11 20:49:56 +0100961};
962
Andrew Victorc6686ff2008-01-23 09:13:53 +0100963static u64 dbgu_dmamask = DMA_BIT_MASK(32);
964
Andrew Victor877d7722007-05-11 20:49:56 +0100965static struct platform_device at91sam9rl_dbgu_device = {
966 .name = "atmel_usart",
967 .id = 0,
968 .dev = {
Andrew Victorc6686ff2008-01-23 09:13:53 +0100969 .dma_mask = &dbgu_dmamask,
970 .coherent_dma_mask = DMA_BIT_MASK(32),
971 .platform_data = &dbgu_data,
Andrew Victor877d7722007-05-11 20:49:56 +0100972 },
973 .resource = dbgu_resources,
974 .num_resources = ARRAY_SIZE(dbgu_resources),
975};
976
977static inline void configure_dbgu_pins(void)
978{
979 at91_set_A_periph(AT91_PIN_PA21, 0); /* DRXD */
980 at91_set_A_periph(AT91_PIN_PA22, 1); /* DTXD */
981}
982
983static struct resource uart0_resources[] = {
984 [0] = {
985 .start = AT91SAM9RL_BASE_US0,
986 .end = AT91SAM9RL_BASE_US0 + SZ_16K - 1,
987 .flags = IORESOURCE_MEM,
988 },
989 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +0200990 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_US0,
991 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_US0,
Andrew Victor877d7722007-05-11 20:49:56 +0100992 .flags = IORESOURCE_IRQ,
993 },
994};
995
996static struct atmel_uart_data uart0_data = {
997 .use_dma_tx = 1,
998 .use_dma_rx = 1,
Linus Walleij354e57f2013-11-07 10:25:55 +0100999 .rts_gpio = -EINVAL,
Andrew Victor877d7722007-05-11 20:49:56 +01001000};
1001
Andrew Victorc6686ff2008-01-23 09:13:53 +01001002static u64 uart0_dmamask = DMA_BIT_MASK(32);
1003
Andrew Victor877d7722007-05-11 20:49:56 +01001004static struct platform_device at91sam9rl_uart0_device = {
1005 .name = "atmel_usart",
1006 .id = 1,
1007 .dev = {
Andrew Victorc6686ff2008-01-23 09:13:53 +01001008 .dma_mask = &uart0_dmamask,
1009 .coherent_dma_mask = DMA_BIT_MASK(32),
1010 .platform_data = &uart0_data,
Andrew Victor877d7722007-05-11 20:49:56 +01001011 },
1012 .resource = uart0_resources,
1013 .num_resources = ARRAY_SIZE(uart0_resources),
1014};
1015
Andrew Victorc8f385a2008-01-23 09:25:15 +01001016static inline void configure_usart0_pins(unsigned pins)
Andrew Victor877d7722007-05-11 20:49:56 +01001017{
1018 at91_set_A_periph(AT91_PIN_PA6, 1); /* TXD0 */
1019 at91_set_A_periph(AT91_PIN_PA7, 0); /* RXD0 */
Andrew Victorc8f385a2008-01-23 09:25:15 +01001020
1021 if (pins & ATMEL_UART_RTS)
1022 at91_set_A_periph(AT91_PIN_PA9, 0); /* RTS0 */
1023 if (pins & ATMEL_UART_CTS)
1024 at91_set_A_periph(AT91_PIN_PA10, 0); /* CTS0 */
1025 if (pins & ATMEL_UART_DSR)
1026 at91_set_A_periph(AT91_PIN_PD14, 0); /* DSR0 */
1027 if (pins & ATMEL_UART_DTR)
1028 at91_set_A_periph(AT91_PIN_PD15, 0); /* DTR0 */
1029 if (pins & ATMEL_UART_DCD)
1030 at91_set_A_periph(AT91_PIN_PD16, 0); /* DCD0 */
1031 if (pins & ATMEL_UART_RI)
1032 at91_set_A_periph(AT91_PIN_PD17, 0); /* RI0 */
Andrew Victor877d7722007-05-11 20:49:56 +01001033}
1034
1035static struct resource uart1_resources[] = {
1036 [0] = {
1037 .start = AT91SAM9RL_BASE_US1,
1038 .end = AT91SAM9RL_BASE_US1 + SZ_16K - 1,
1039 .flags = IORESOURCE_MEM,
1040 },
1041 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +02001042 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_US1,
1043 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_US1,
Andrew Victor877d7722007-05-11 20:49:56 +01001044 .flags = IORESOURCE_IRQ,
1045 },
1046};
1047
1048static struct atmel_uart_data uart1_data = {
1049 .use_dma_tx = 1,
1050 .use_dma_rx = 1,
Linus Walleij354e57f2013-11-07 10:25:55 +01001051 .rts_gpio = -EINVAL,
Andrew Victor877d7722007-05-11 20:49:56 +01001052};
1053
Andrew Victorc6686ff2008-01-23 09:13:53 +01001054static u64 uart1_dmamask = DMA_BIT_MASK(32);
1055
Andrew Victor877d7722007-05-11 20:49:56 +01001056static struct platform_device at91sam9rl_uart1_device = {
1057 .name = "atmel_usart",
1058 .id = 2,
1059 .dev = {
Andrew Victorc6686ff2008-01-23 09:13:53 +01001060 .dma_mask = &uart1_dmamask,
1061 .coherent_dma_mask = DMA_BIT_MASK(32),
1062 .platform_data = &uart1_data,
Andrew Victor877d7722007-05-11 20:49:56 +01001063 },
1064 .resource = uart1_resources,
1065 .num_resources = ARRAY_SIZE(uart1_resources),
1066};
1067
Andrew Victorc8f385a2008-01-23 09:25:15 +01001068static inline void configure_usart1_pins(unsigned pins)
Andrew Victor877d7722007-05-11 20:49:56 +01001069{
1070 at91_set_A_periph(AT91_PIN_PA11, 1); /* TXD1 */
1071 at91_set_A_periph(AT91_PIN_PA12, 0); /* RXD1 */
Andrew Victorc8f385a2008-01-23 09:25:15 +01001072
1073 if (pins & ATMEL_UART_RTS)
1074 at91_set_B_periph(AT91_PIN_PA18, 0); /* RTS1 */
1075 if (pins & ATMEL_UART_CTS)
1076 at91_set_B_periph(AT91_PIN_PA19, 0); /* CTS1 */
Andrew Victor877d7722007-05-11 20:49:56 +01001077}
1078
1079static struct resource uart2_resources[] = {
1080 [0] = {
1081 .start = AT91SAM9RL_BASE_US2,
1082 .end = AT91SAM9RL_BASE_US2 + SZ_16K - 1,
1083 .flags = IORESOURCE_MEM,
1084 },
1085 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +02001086 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_US2,
1087 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_US2,
Andrew Victor877d7722007-05-11 20:49:56 +01001088 .flags = IORESOURCE_IRQ,
1089 },
1090};
1091
1092static struct atmel_uart_data uart2_data = {
1093 .use_dma_tx = 1,
1094 .use_dma_rx = 1,
Linus Walleij354e57f2013-11-07 10:25:55 +01001095 .rts_gpio = -EINVAL,
Andrew Victor877d7722007-05-11 20:49:56 +01001096};
1097
Andrew Victorc6686ff2008-01-23 09:13:53 +01001098static u64 uart2_dmamask = DMA_BIT_MASK(32);
1099
Andrew Victor877d7722007-05-11 20:49:56 +01001100static struct platform_device at91sam9rl_uart2_device = {
1101 .name = "atmel_usart",
1102 .id = 3,
1103 .dev = {
Andrew Victorc6686ff2008-01-23 09:13:53 +01001104 .dma_mask = &uart2_dmamask,
1105 .coherent_dma_mask = DMA_BIT_MASK(32),
1106 .platform_data = &uart2_data,
Andrew Victor877d7722007-05-11 20:49:56 +01001107 },
1108 .resource = uart2_resources,
1109 .num_resources = ARRAY_SIZE(uart2_resources),
1110};
1111
Andrew Victorc8f385a2008-01-23 09:25:15 +01001112static inline void configure_usart2_pins(unsigned pins)
Andrew Victor877d7722007-05-11 20:49:56 +01001113{
1114 at91_set_A_periph(AT91_PIN_PA13, 1); /* TXD2 */
1115 at91_set_A_periph(AT91_PIN_PA14, 0); /* RXD2 */
Andrew Victorc8f385a2008-01-23 09:25:15 +01001116
1117 if (pins & ATMEL_UART_RTS)
1118 at91_set_A_periph(AT91_PIN_PA29, 0); /* RTS2 */
1119 if (pins & ATMEL_UART_CTS)
1120 at91_set_A_periph(AT91_PIN_PA30, 0); /* CTS2 */
Andrew Victor877d7722007-05-11 20:49:56 +01001121}
1122
1123static struct resource uart3_resources[] = {
1124 [0] = {
1125 .start = AT91SAM9RL_BASE_US3,
1126 .end = AT91SAM9RL_BASE_US3 + SZ_16K - 1,
1127 .flags = IORESOURCE_MEM,
1128 },
1129 [1] = {
Ludovic Desroches8fe82a52012-06-21 14:47:27 +02001130 .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_US3,
1131 .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_US3,
Andrew Victor877d7722007-05-11 20:49:56 +01001132 .flags = IORESOURCE_IRQ,
1133 },
1134};
1135
1136static struct atmel_uart_data uart3_data = {
1137 .use_dma_tx = 1,
1138 .use_dma_rx = 1,
Linus Walleij354e57f2013-11-07 10:25:55 +01001139 .rts_gpio = -EINVAL,
Andrew Victor877d7722007-05-11 20:49:56 +01001140};
1141
Andrew Victorc6686ff2008-01-23 09:13:53 +01001142static u64 uart3_dmamask = DMA_BIT_MASK(32);
1143
Andrew Victor877d7722007-05-11 20:49:56 +01001144static struct platform_device at91sam9rl_uart3_device = {
1145 .name = "atmel_usart",
1146 .id = 4,
1147 .dev = {
Andrew Victorc6686ff2008-01-23 09:13:53 +01001148 .dma_mask = &uart3_dmamask,
1149 .coherent_dma_mask = DMA_BIT_MASK(32),
1150 .platform_data = &uart3_data,
Andrew Victor877d7722007-05-11 20:49:56 +01001151 },
1152 .resource = uart3_resources,
1153 .num_resources = ARRAY_SIZE(uart3_resources),
1154};
1155
Andrew Victorc8f385a2008-01-23 09:25:15 +01001156static inline void configure_usart3_pins(unsigned pins)
Andrew Victor877d7722007-05-11 20:49:56 +01001157{
1158 at91_set_A_periph(AT91_PIN_PB0, 1); /* TXD3 */
1159 at91_set_A_periph(AT91_PIN_PB1, 0); /* RXD3 */
Andrew Victorc8f385a2008-01-23 09:25:15 +01001160
1161 if (pins & ATMEL_UART_RTS)
1162 at91_set_B_periph(AT91_PIN_PD4, 0); /* RTS3 */
1163 if (pins & ATMEL_UART_CTS)
1164 at91_set_B_periph(AT91_PIN_PD3, 0); /* CTS3 */
Andrew Victor877d7722007-05-11 20:49:56 +01001165}
1166
Andrew Victor11aadac2008-04-15 21:16:38 +01001167static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
Andrew Victor877d7722007-05-11 20:49:56 +01001168
Andrew Victorc8f385a2008-01-23 09:25:15 +01001169void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
1170{
1171 struct platform_device *pdev;
Jean-Christophe PLAGNIOL-VILLARD2b348e22011-04-10 14:10:05 +08001172 struct atmel_uart_data *pdata;
Andrew Victorc8f385a2008-01-23 09:25:15 +01001173
1174 switch (id) {
1175 case 0: /* DBGU */
1176 pdev = &at91sam9rl_dbgu_device;
1177 configure_dbgu_pins();
Andrew Victorc8f385a2008-01-23 09:25:15 +01001178 break;
1179 case AT91SAM9RL_ID_US0:
1180 pdev = &at91sam9rl_uart0_device;
1181 configure_usart0_pins(pins);
Andrew Victorc8f385a2008-01-23 09:25:15 +01001182 break;
1183 case AT91SAM9RL_ID_US1:
1184 pdev = &at91sam9rl_uart1_device;
1185 configure_usart1_pins(pins);
Andrew Victorc8f385a2008-01-23 09:25:15 +01001186 break;
1187 case AT91SAM9RL_ID_US2:
1188 pdev = &at91sam9rl_uart2_device;
1189 configure_usart2_pins(pins);
Andrew Victorc8f385a2008-01-23 09:25:15 +01001190 break;
1191 case AT91SAM9RL_ID_US3:
1192 pdev = &at91sam9rl_uart3_device;
1193 configure_usart3_pins(pins);
Andrew Victorc8f385a2008-01-23 09:25:15 +01001194 break;
1195 default:
1196 return;
1197 }
Jean-Christophe PLAGNIOL-VILLARD2b348e22011-04-10 14:10:05 +08001198 pdata = pdev->dev.platform_data;
1199 pdata->num = portnr; /* update to mapped ID */
Andrew Victorc8f385a2008-01-23 09:25:15 +01001200
1201 if (portnr < ATMEL_MAX_UART)
1202 at91_uarts[portnr] = pdev;
1203}
1204
Andrew Victor877d7722007-05-11 20:49:56 +01001205void __init at91_add_device_serial(void)
1206{
1207 int i;
1208
1209 for (i = 0; i < ATMEL_MAX_UART; i++) {
1210 if (at91_uarts[i])
1211 platform_device_register(at91_uarts[i]);
1212 }
1213}
1214#else
Andrew Victorc8f385a2008-01-23 09:25:15 +01001215void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
Andrew Victor877d7722007-05-11 20:49:56 +01001216void __init at91_add_device_serial(void) {}
1217#endif
1218
1219
1220/* -------------------------------------------------------------------- */
1221
1222/*
1223 * These devices are always present and don't need any board-specific
1224 * setup.
1225 */
1226static int __init at91_add_standard_devices(void)
1227{
Nicolas Ferre6ff89e92009-07-24 11:43:00 +01001228 at91_add_device_hdmac();
Andrew Victor884f5a62008-01-23 09:11:13 +01001229 at91_add_device_rtc();
1230 at91_add_device_rtt();
1231 at91_add_device_watchdog();
Andrew Victore5f40bf2008-04-02 21:58:00 +01001232 at91_add_device_tc();
Andrew Victor877d7722007-05-11 20:49:56 +01001233 return 0;
1234}
1235
1236arch_initcall(at91_add_standard_devices);