diff options
-rw-r--r-- | arch/avr32/boards/atngw100/setup.c | 7 | ||||
-rw-r--r-- | arch/avr32/boards/atstk1000/atstk1002.c | 18 | ||||
-rw-r--r-- | arch/avr32/boards/atstk1000/atstk1003.c | 12 | ||||
-rw-r--r-- | arch/avr32/boards/atstk1000/atstk1004.c | 12 | ||||
-rw-r--r-- | arch/avr32/include/asm/atmel-mci.h | 22 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap700x.c | 72 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci-regs.h | 6 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 24 |
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 | ||
55 | static struct mci_platform_data __initdata mci0_data = { | 55 | static 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 | ||
267 | static 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 |
269 | static 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, ð_data[1])); | 336 | set_hw_addr(at32_add_device_eth(1, ð_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 | ||
70 | static 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 |
70 | static void __init atstk1003_setup_extdac(void) | 80 | static 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 | ||
75 | static 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 |
75 | static void __init atstk1004_setup_extdac(void) | 85 | static 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 | ||
4 | struct 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 | */ | ||
15 | struct 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 | */ | ||
25 | struct 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 = { | |||
1272 | struct platform_device *__init | 1272 | struct platform_device *__init |
1273 | at32_add_device_mci(unsigned int id, struct mci_platform_data *data) | 1273 | at32_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) | |||
1014 | static int __init atmci_probe(struct platform_device *pdev) | 1015 | static 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; |