aboutsummaryrefslogtreecommitdiffstats
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
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>
-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
-rw-r--r--drivers/mmc/host/atmel-mci-regs.h6
-rw-r--r--drivers/mmc/host/atmel-mci.c24
8 files changed, 137 insertions, 36 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
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h
index 26bd80e65031..b58364ed6bba 100644
--- a/drivers/mmc/host/atmel-mci-regs.h
+++ b/drivers/mmc/host/atmel-mci-regs.h
@@ -25,8 +25,10 @@
25#define MCI_SDCR 0x000c /* SD Card / SDIO */ 25#define MCI_SDCR 0x000c /* SD Card / SDIO */
26# define MCI_SDCSEL_SLOT_A ( 0 << 0) /* Select SD slot A */ 26# define MCI_SDCSEL_SLOT_A ( 0 << 0) /* Select SD slot A */
27# define MCI_SDCSEL_SLOT_B ( 1 << 0) /* Select SD slot A */ 27# define MCI_SDCSEL_SLOT_B ( 1 << 0) /* Select SD slot A */
28# define MCI_SDCBUS_1BIT ( 0 << 7) /* 1-bit data bus */ 28# define MCI_SDCSEL_MASK ( 3 << 0)
29# define MCI_SDCBUS_4BIT ( 1 << 7) /* 4-bit data bus */ 29# define MCI_SDCBUS_1BIT ( 0 << 6) /* 1-bit data bus */
30# define MCI_SDCBUS_4BIT ( 2 << 6) /* 4-bit data bus */
31# define MCI_SDCBUS_MASK ( 3 << 6)
30#define MCI_ARGR 0x0010 /* Command Argument */ 32#define MCI_ARGR 0x0010 /* Command Argument */
31#define MCI_CMDR 0x0014 /* Command */ 33#define MCI_CMDR 0x0014 /* Command */
32# define MCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */ 34# define MCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 14ab28da7fa8..8170905a0401 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -508,9 +508,10 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
508{ 508{
509 struct atmel_mci *host = mmc_priv(mmc); 509 struct atmel_mci *host = mmc_priv(mmc);
510 510
511 host->sdc_reg &= ~MCI_SDCBUS_MASK;
511 switch (ios->bus_width) { 512 switch (ios->bus_width) {
512 case MMC_BUS_WIDTH_1: 513 case MMC_BUS_WIDTH_1:
513 host->sdc_reg = 0; 514 host->sdc_reg |= MCI_SDCBUS_1BIT;
514 break; 515 break;
515 case MMC_BUS_WIDTH_4: 516 case MMC_BUS_WIDTH_4:
516 host->sdc_reg = MCI_SDCBUS_4BIT; 517 host->sdc_reg = MCI_SDCBUS_4BIT;
@@ -1014,9 +1015,11 @@ static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
1014static int __init atmci_probe(struct platform_device *pdev) 1015static int __init atmci_probe(struct platform_device *pdev)
1015{ 1016{
1016 struct mci_platform_data *pdata; 1017 struct mci_platform_data *pdata;
1018 struct mci_slot_pdata *slot;
1017 struct atmel_mci *host; 1019 struct atmel_mci *host;
1018 struct mmc_host *mmc; 1020 struct mmc_host *mmc;
1019 struct resource *regs; 1021 struct resource *regs;
1022 u32 sdc_reg;
1020 int irq; 1023 int irq;
1021 int ret; 1024 int ret;
1022 1025
@@ -1030,6 +1033,17 @@ static int __init atmci_probe(struct platform_device *pdev)
1030 if (irq < 0) 1033 if (irq < 0)
1031 return irq; 1034 return irq;
1032 1035
1036 /* TODO: Allow using several slots at once */
1037 if (pdata->slot[0].bus_width) {
1038 sdc_reg = MCI_SDCSEL_SLOT_A;
1039 slot = &pdata->slot[0];
1040 } else if (pdata->slot[1].bus_width) {
1041 sdc_reg = MCI_SDCSEL_SLOT_B;
1042 slot = &pdata->slot[1];
1043 } else {
1044 return -EINVAL;
1045 }
1046
1033 mmc = mmc_alloc_host(sizeof(struct atmel_mci), &pdev->dev); 1047 mmc = mmc_alloc_host(sizeof(struct atmel_mci), &pdev->dev);
1034 if (!mmc) 1048 if (!mmc)
1035 return -ENOMEM; 1049 return -ENOMEM;
@@ -1037,8 +1051,9 @@ static int __init atmci_probe(struct platform_device *pdev)
1037 host = mmc_priv(mmc); 1051 host = mmc_priv(mmc);
1038 host->pdev = pdev; 1052 host->pdev = pdev;
1039 host->mmc = mmc; 1053 host->mmc = mmc;
1040 host->detect_pin = pdata->detect_pin; 1054 host->detect_pin = slot->detect_pin;
1041 host->wp_pin = pdata->wp_pin; 1055 host->wp_pin = slot->wp_pin;
1056 host->sdc_reg = sdc_reg;
1042 1057
1043 host->mck = clk_get(&pdev->dev, "mci_clk"); 1058 host->mck = clk_get(&pdev->dev, "mci_clk");
1044 if (IS_ERR(host->mck)) { 1059 if (IS_ERR(host->mck)) {
@@ -1062,7 +1077,8 @@ static int __init atmci_probe(struct platform_device *pdev)
1062 mmc->f_min = (host->bus_hz + 511) / 512; 1077 mmc->f_min = (host->bus_hz + 511) / 512;
1063 mmc->f_max = host->bus_hz / 2; 1078 mmc->f_max = host->bus_hz / 2;
1064 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; 1079 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
1065 mmc->caps |= MMC_CAP_4_BIT_DATA; 1080 if (slot->bus_width >= 4)
1081 mmc->caps |= MMC_CAP_4_BIT_DATA;
1066 1082
1067 mmc->max_hw_segs = 64; 1083 mmc->max_hw_segs = 64;
1068 mmc->max_phys_segs = 64; 1084 mmc->max_phys_segs = 64;