aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci-s3c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/sdhci-s3c.c')
-rw-r--r--drivers/mmc/host/sdhci-s3c.c72
1 files changed, 60 insertions, 12 deletions
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index bfbd2d2..aeeb5ec 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -80,7 +80,7 @@ static void sdhci_s3c_check_sclk(struct sdhci_host *host)
tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
- writel(tmp, host->ioaddr + 0x80);
+ writel(tmp, host->ioaddr + S3C_SDHCI_CONTROL2);
}
}
@@ -114,6 +114,46 @@ static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host)
return max;
}
+static void sdhci_s3c_set_ios(struct sdhci_host *host,
+ struct mmc_ios *ios)
+{
+ struct sdhci_s3c *ourhost = to_s3c(host);
+ struct s3c_sdhci_platdata *pdata = ourhost->pdata;
+ int width;
+ u8 tmp;
+
+ sdhci_s3c_check_sclk(host);
+
+ if (ios->power_mode != MMC_POWER_OFF) {
+ switch (ios->bus_width) {
+ case MMC_BUS_WIDTH_8:
+ width = 8;
+ tmp = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+ writeb(tmp | SDHCI_S3C_CTRL_8BITBUS,
+ host->ioaddr + SDHCI_HOST_CONTROL);
+ break;
+ case MMC_BUS_WIDTH_4:
+ width = 4;
+ break;
+ case MMC_BUS_WIDTH_1:
+ width = 1;
+ break;
+ default:
+ BUG();
+ }
+
+ if (pdata->cfg_gpio)
+ pdata->cfg_gpio(ourhost->pdev, width);
+ }
+
+ if (pdata->cfg_card) {
+ pdata->cfg_card(ourhost->pdev, host->ioaddr,
+ ios, host->mmc->card);
+ pdata->rx_cfg = 0;
+ pdata->tx_cfg = 0;
+ }
+}
+
/**
* sdhci_s3c_consider_clock - consider one the bus clocks for current setting
* @ourhost: Our SDHCI instance.
@@ -203,18 +243,15 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
}
+}
- /* reconfigure the hardware for new clock rate */
-
- {
- struct mmc_ios ios;
-
- ios.clock = clock;
+static int sdhci_s3c_adjust_cfg(struct sdhci_host *host, int rw)
+{
+ struct sdhci_s3c *ourhost = to_s3c(host);
+ struct s3c_sdhci_platdata *pdata = ourhost->pdata;
- if (ourhost->pdata->cfg_card)
- (ourhost->pdata->cfg_card)(ourhost->pdev, host->ioaddr,
- &ios, NULL);
- }
+ if(pdata->adjust_cfg_card)
+ pdata->adjust_cfg_card(pdata, host->ioaddr, rw);
}
/**
@@ -318,6 +355,8 @@ static struct sdhci_ops sdhci_s3c_ops = {
.set_clock = sdhci_s3c_set_clock,
.get_min_clock = sdhci_s3c_get_min_clock,
.platform_8bit_width = sdhci_s3c_platform_8bit_width,
+ .set_ios = sdhci_s3c_set_ios,
+ .adjust_cfg = sdhci_s3c_adjust_cfg,
};
static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
@@ -489,6 +528,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
/* Setup quirks for the controller */
host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
+ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
#ifndef CONFIG_MMC_SDHCI_S3C_DMA
@@ -496,6 +536,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
* support as well. */
host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
+ /* PIO currently has problems with multi-block IO */
+ host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+
#endif /* CONFIG_MMC_SDHCI_S3C_DMA */
/* It seems we do not get an DATA transfer complete on non-busy
@@ -578,11 +621,16 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_s3c *sc = sdhci_priv(host);
- int ptr;
+ int ptr, dead = 0;
+ u32 scratch;
if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup)
pdata->ext_cd_cleanup(&sdhci_s3c_notify_change);
+ scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
+ if (scratch == (u32)-1)
+ dead = 1;
+
if (sc->ext_cd_irq)
free_irq(sc->ext_cd_irq, sc);