summaryrefslogtreecommitdiff
path: root/drivers/mmc/host/atmel-mci.c
diff options
context:
space:
mode:
authorHaavard Skinnemoen <haavard.skinnemoen@atmel.com>2008-08-07 16:08:49 +0400
committerHaavard Skinnemoen <haavard.skinnemoen@atmel.com>2008-10-05 22:39:21 +0400
commit6b918657b7431e4c5c953b8222ae2f4fc1b2576a (patch)
treebb3bb53d91501064821ea860a490dc1b3633df52 /drivers/mmc/host/atmel-mci.c
parent945533b538c6c6185afc77ba4a81eeba8f6ef8dd (diff)
downloadlinux-6b918657b7431e4c5c953b8222ae2f4fc1b2576a.tar.xz
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/mmc/host/atmel-mci.c')
-rw-r--r--drivers/mmc/host/atmel-mci.c24
1 files changed, 20 insertions, 4 deletions
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)
{
struct atmel_mci *host = mmc_priv(mmc);
+ host->sdc_reg &= ~MCI_SDCBUS_MASK;
switch (ios->bus_width) {
case MMC_BUS_WIDTH_1:
- host->sdc_reg = 0;
+ host->sdc_reg |= MCI_SDCBUS_1BIT;
break;
case MMC_BUS_WIDTH_4:
host->sdc_reg = MCI_SDCBUS_4BIT;
@@ -1014,9 +1015,11 @@ static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
static int __init atmci_probe(struct platform_device *pdev)
{
struct mci_platform_data *pdata;
+ struct mci_slot_pdata *slot;
struct atmel_mci *host;
struct mmc_host *mmc;
struct resource *regs;
+ u32 sdc_reg;
int irq;
int ret;
@@ -1030,6 +1033,17 @@ static int __init atmci_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
+ /* TODO: Allow using several slots at once */
+ if (pdata->slot[0].bus_width) {
+ sdc_reg = MCI_SDCSEL_SLOT_A;
+ slot = &pdata->slot[0];
+ } else if (pdata->slot[1].bus_width) {
+ sdc_reg = MCI_SDCSEL_SLOT_B;
+ slot = &pdata->slot[1];
+ } else {
+ return -EINVAL;
+ }
+
mmc = mmc_alloc_host(sizeof(struct atmel_mci), &pdev->dev);
if (!mmc)
return -ENOMEM;
@@ -1037,8 +1051,9 @@ static int __init atmci_probe(struct platform_device *pdev)
host = mmc_priv(mmc);
host->pdev = pdev;
host->mmc = mmc;
- host->detect_pin = pdata->detect_pin;
- host->wp_pin = pdata->wp_pin;
+ host->detect_pin = slot->detect_pin;
+ host->wp_pin = slot->wp_pin;
+ host->sdc_reg = sdc_reg;
host->mck = clk_get(&pdev->dev, "mci_clk");
if (IS_ERR(host->mck)) {
@@ -1062,7 +1077,8 @@ static int __init atmci_probe(struct platform_device *pdev)
mmc->f_min = (host->bus_hz + 511) / 512;
mmc->f_max = host->bus_hz / 2;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
- mmc->caps |= MMC_CAP_4_BIT_DATA;
+ if (slot->bus_width >= 4)
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
mmc->max_hw_segs = 64;
mmc->max_phys_segs = 64;