diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-s3c.c')
-rw-r--r-- | drivers/mmc/host/sdhci-s3c.c | 72 |
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); |