aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHaavard Skinnemoen <haavard.skinnemoen@atmel.com>2008-08-07 08:08:49 -0400
committerHaavard Skinnemoen <haavard.skinnemoen@atmel.com>2008-10-05 14:39:21 -0400
commit6b918657b7431e4c5c953b8222ae2f4fc1b2576a (patch)
treebb3bb53d91501064821ea860a490dc1b3633df52 /arch
parent945533b538c6c6185afc77ba4a81eeba8f6ef8dd (diff)
atmel-mci: Platform code for supporting multiple mmc slots
Add the necessary platform infrastructure to support multiple mmc/sdcard slots all at once through a single controller. Currently, the driver will use the first valid slot it finds and stick with that, but later patches will add support for switching between several slots on the fly. Extend the platform data structure with per-slot information: MMC/SDcard bus width and card detect/write protect pins. This will affect the pin muxing as well as the capabilities announced to the mmc core. Note that board code is now required to supply a mci_platform_data struct to at32_add_device_mci(). Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/avr32/boards/atngw100/setup.c7
-rw-r--r--arch/avr32/boards/atstk1000/atstk1002.c18
-rw-r--r--arch/avr32/boards/atstk1000/atstk1003.c12
-rw-r--r--arch/avr32/boards/atstk1000/atstk1004.c12
-rw-r--r--arch/avr32/include/asm/atmel-mci.h22
-rw-r--r--arch/avr32/mach-at32ap/at32ap700x.c72
6 files changed, 113 insertions, 30 deletions
diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c
index b8286f1ce854..f3085208959f 100644
--- a/arch/avr32/boards/atngw100/setup.c
+++ b/arch/avr32/boards/atngw100/setup.c
@@ -53,8 +53,11 @@ static struct spi_board_info spi0_board_info[] __initdata = {
53}; 53};
54 54
55static struct mci_platform_data __initdata mci0_data = { 55static struct mci_platform_data __initdata mci0_data = {
56 .detect_pin = GPIO_PIN_PC(25), 56 .slot[0] = {
57 .wp_pin = GPIO_PIN_PE(0), 57 .bus_width = 4,
58 .detect_pin = GPIO_PIN_PC(25),
59 .wp_pin = GPIO_PIN_PE(0),
60 },
58}; 61};
59 62
60/* 63/*
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index dfc3443e23aa..4fedbc4488de 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -264,16 +264,20 @@ void __init setup_board(void)
264 264
265#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM 265#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
266 266
267static struct mci_platform_data __initdata mci0_data = {
268 .slot[0] = {
269 .bus_width = 4,
270
267/* MMC card detect requires MACB0 *NOT* be used */ 271/* MMC card detect requires MACB0 *NOT* be used */
268#ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM 272#ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
269static struct mci_platform_data __initdata mci0_data = { 273 .detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */
270 .detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */ 274 .wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */
271 .wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */
272};
273#define MCI_PDATA &mci0_data
274#else 275#else
275#define MCI_PDATA NULL 276 .detect_pin = -ENODEV,
277 .wp_pin = -ENODEV,
276#endif /* SW6 for sd{cd,wp} routing */ 278#endif /* SW6 for sd{cd,wp} routing */
279 },
280};
277 281
278#endif /* SW2 for MMC signal routing */ 282#endif /* SW2 for MMC signal routing */
279 283
@@ -326,7 +330,7 @@ static int __init atstk1002_init(void)
326 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); 330 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
327#endif 331#endif
328#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM 332#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
329 at32_add_device_mci(0, MCI_PDATA); 333 at32_add_device_mci(0, &mci0_pdata);
330#endif 334#endif
331#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM 335#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
332 set_hw_addr(at32_add_device_eth(1, &eth_data[1])); 336 set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
diff --git a/arch/avr32/boards/atstk1000/atstk1003.c b/arch/avr32/boards/atstk1000/atstk1003.c
index 0cf664174c17..acc61235b895 100644
--- a/arch/avr32/boards/atstk1000/atstk1003.c
+++ b/arch/avr32/boards/atstk1000/atstk1003.c
@@ -66,6 +66,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { {
66} }; 66} };
67#endif 67#endif
68 68
69#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
70static struct mci_platform_data __initdata mci0_data = {
71 .slot[0] = {
72 .bus_width = 4,
73 .detect_pin = -ENODEV,
74 .wp_pin = -ENODEV,
75 },
76};
77#endif
78
69#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC 79#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
70static void __init atstk1003_setup_extdac(void) 80static void __init atstk1003_setup_extdac(void)
71{ 81{
@@ -154,7 +164,7 @@ static int __init atstk1003_init(void)
154 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); 164 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
155#endif 165#endif
156#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM 166#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
157 at32_add_device_mci(0, NULL); 167 at32_add_device_mci(0, &mci0_data);
158#endif 168#endif
159 at32_add_device_usba(0, NULL); 169 at32_add_device_usba(0, NULL);
160#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM 170#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
diff --git a/arch/avr32/boards/atstk1000/atstk1004.c b/arch/avr32/boards/atstk1000/atstk1004.c
index 50a5273e5916..d6a2d02f0329 100644
--- a/arch/avr32/boards/atstk1000/atstk1004.c
+++ b/arch/avr32/boards/atstk1000/atstk1004.c
@@ -71,6 +71,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { {
71} }; 71} };
72#endif 72#endif
73 73
74#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
75static struct mci_platform_data __initdata mci0_data = {
76 .slot[0] = {
77 .bus_width = 4,
78 .detect_pin = -ENODEV,
79 .wp_pin = -ENODEV,
80 },
81};
82#endif
83
74#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC 84#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
75static void __init atstk1004_setup_extdac(void) 85static void __init atstk1004_setup_extdac(void)
76{ 86{
@@ -137,7 +147,7 @@ static int __init atstk1004_init(void)
137 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); 147 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
138#endif 148#endif
139#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM 149#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
140 at32_add_device_mci(0, NULL); 150 at32_add_device_mci(0, &mci0_data);
141#endif 151#endif
142 at32_add_device_lcdc(0, &atstk1000_lcdc_data, 152 at32_add_device_lcdc(0, &atstk1000_lcdc_data,
143 fbmem_start, fbmem_size, 0); 153 fbmem_start, fbmem_size, 0);
diff --git a/arch/avr32/include/asm/atmel-mci.h b/arch/avr32/include/asm/atmel-mci.h
index c2ea6e1c9aa1..d38c64ca41e8 100644
--- a/arch/avr32/include/asm/atmel-mci.h
+++ b/arch/avr32/include/asm/atmel-mci.h
@@ -1,9 +1,29 @@
1#ifndef __ASM_AVR32_ATMEL_MCI_H 1#ifndef __ASM_AVR32_ATMEL_MCI_H
2#define __ASM_AVR32_ATMEL_MCI_H 2#define __ASM_AVR32_ATMEL_MCI_H
3 3
4struct mci_platform_data { 4/**
5 * struct mci_slot_pdata - board-specific per-slot configuration
6 * @bus_width: Number of data lines wired up the slot
7 * @detect_pin: GPIO pin wired to the card detect switch
8 * @wp_pin: GPIO pin wired to the write protect sensor
9 *
10 * If a given slot is not present on the board, @bus_width should be
11 * set to 0. The other fields are ignored in this case.
12 *
13 * Any pins that aren't available should be set to a negative value.
14 */
15struct mci_slot_pdata {
16 unsigned int bus_width;
5 int detect_pin; 17 int detect_pin;
6 int wp_pin; 18 int wp_pin;
7}; 19};
8 20
21/**
22 * struct mci_platform_data - board-specific MMC/SDcard configuration
23 * @slot: Per-slot configuration data.
24 */
25struct mci_platform_data {
26 struct mci_slot_pdata slot[2];
27};
28
9#endif /* __ASM_AVR32_ATMEL_MCI_H */ 29#endif /* __ASM_AVR32_ATMEL_MCI_H */
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index e01dbe4ebb40..9967d5a3b6eb 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -1272,10 +1272,13 @@ static struct clk atmel_mci0_pclk = {
1272struct platform_device *__init 1272struct platform_device *__init
1273at32_add_device_mci(unsigned int id, struct mci_platform_data *data) 1273at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
1274{ 1274{
1275 struct mci_platform_data _data;
1276 struct platform_device *pdev; 1275 struct platform_device *pdev;
1277 1276
1278 if (id != 0) 1277 if (id != 0 || !data)
1278 return NULL;
1279
1280 /* Must have at least one usable slot */
1281 if (!data->slot[0].bus_width && !data->slot[1].bus_width)
1279 return NULL; 1282 return NULL;
1280 1283
1281 pdev = platform_device_alloc("atmel_mci", id); 1284 pdev = platform_device_alloc("atmel_mci", id);
@@ -1286,28 +1289,61 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
1286 ARRAY_SIZE(atmel_mci0_resource))) 1289 ARRAY_SIZE(atmel_mci0_resource)))
1287 goto fail; 1290 goto fail;
1288 1291
1289 if (!data) {
1290 data = &_data;
1291 memset(data, -1, sizeof(struct mci_platform_data));
1292 data->detect_pin = GPIO_PIN_NONE;
1293 data->wp_pin = GPIO_PIN_NONE;
1294 }
1295 1292
1296 if (platform_device_add_data(pdev, data, 1293 if (platform_device_add_data(pdev, data,
1297 sizeof(struct mci_platform_data))) 1294 sizeof(struct mci_platform_data)))
1298 goto fail; 1295 goto fail;
1299 1296
1300 select_peripheral(PA(10), PERIPH_A, 0); /* CLK */ 1297 /* CLK line is common to both slots */
1301 select_peripheral(PA(11), PERIPH_A, 0); /* CMD */ 1298 select_peripheral(PA(10), PERIPH_A, 0);
1302 select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */
1303 select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */
1304 select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
1305 select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
1306 1299
1307 if (gpio_is_valid(data->detect_pin)) 1300 switch (data->slot[0].bus_width) {
1308 at32_select_gpio(data->detect_pin, 0); 1301 case 4:
1309 if (gpio_is_valid(data->wp_pin)) 1302 select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */
1310 at32_select_gpio(data->wp_pin, 0); 1303 select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
1304 select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
1305 /* fall through */
1306 case 1:
1307 select_peripheral(PA(11), PERIPH_A, 0); /* CMD */
1308 select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */
1309
1310 if (gpio_is_valid(data->slot[0].detect_pin))
1311 at32_select_gpio(data->slot[0].detect_pin, 0);
1312 if (gpio_is_valid(data->slot[0].wp_pin))
1313 at32_select_gpio(data->slot[0].wp_pin, 0);
1314 break;
1315 case 0:
1316 /* Slot is unused */
1317 break;
1318 default:
1319 goto fail;
1320 }
1321
1322 switch (data->slot[1].bus_width) {
1323 case 4:
1324 select_peripheral(PB(8), PERIPH_B, 0); /* DATA1 */
1325 select_peripheral(PB(9), PERIPH_B, 0); /* DATA2 */
1326 select_peripheral(PB(10), PERIPH_B, 0); /* DATA3 */
1327 /* fall through */
1328 case 1:
1329 select_peripheral(PB(6), PERIPH_B, 0); /* CMD */
1330 select_peripheral(PB(7), PERIPH_B, 0); /* DATA0 */
1331
1332 if (gpio_is_valid(data->slot[1].detect_pin))
1333 at32_select_gpio(data->slot[1].detect_pin, 0);
1334 if (gpio_is_valid(data->slot[1].wp_pin))
1335 at32_select_gpio(data->slot[1].wp_pin, 0);
1336 break;
1337 case 0:
1338 /* Slot is unused */
1339 break;
1340 default:
1341 if (!data->slot[0].bus_width)
1342 goto fail;
1343
1344 data->slot[1].bus_width = 0;
1345 break;
1346 }
1311 1347
1312 atmel_mci0_pclk.dev = &pdev->dev; 1348 atmel_mci0_pclk.dev = &pdev->dev;
1313 1349