aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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 /drivers
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 'drivers')
-rw-r--r--drivers/mmc/host/atmel-mci-regs.h6
-rw-r--r--drivers/mmc/host/atmel-mci.c24
2 files changed, 24 insertions, 6 deletions
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;