diff options
Diffstat (limited to 'drivers/mmc/host/tmio_mmc_pio.c')
-rw-r--r-- | drivers/mmc/host/tmio_mmc_pio.c | 196 |
1 files changed, 74 insertions, 122 deletions
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 0521b4662748..f44e2ab7aea2 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -39,7 +39,6 @@ #include <linux/mmc/host.h> #include <linux/mmc/mmc.h> #include <linux/mmc/slot-gpio.h> -#include <linux/mmc/tmio.h> #include <linux/module.h> #include <linux/pagemap.h> #include <linux/platform_device.h> @@ -56,18 +55,18 @@ void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i) { host->sdcard_irq_mask &= ~(i & TMIO_MASK_IRQ); - sd_ctrl_write32(host, CTL_IRQ_MASK, host->sdcard_irq_mask); + sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask); } void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i) { host->sdcard_irq_mask |= (i & TMIO_MASK_IRQ); - sd_ctrl_write32(host, CTL_IRQ_MASK, host->sdcard_irq_mask); + sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask); } static void tmio_mmc_ack_mmc_irqs(struct tmio_mmc_host *host, u32 i) { - sd_ctrl_write32(host, CTL_STATUS, ~i); + sd_ctrl_write32_as_16_and_16(host, CTL_STATUS, ~i); } static void tmio_mmc_init_sg(struct tmio_mmc_host *host, struct mmc_data *data) @@ -154,31 +153,16 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) } } -static void tmio_mmc_set_clock(struct tmio_mmc_host *host, - unsigned int new_clock) +static void tmio_mmc_clk_start(struct tmio_mmc_host *host) { - u32 clk = 0, clock; - - if (new_clock) { - for (clock = host->mmc->f_min, clk = 0x80000080; - new_clock >= (clock << 1); - clk >>= 1) - clock <<= 1; - - /* 1/1 clock is option */ - if ((host->pdata->flags & TMIO_MMC_CLK_ACTUAL) && - ((clk >> 22) & 0x1)) - clk |= 0xff; - } - - if (host->set_clk_div) - host->set_clk_div(host->pdev, (clk >> 22) & 1); + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | + sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); + msleep(host->pdata->flags & TMIO_MMC_MIN_RCAR2 ? 1 : 10); - sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN & - sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); - sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & CLK_CTL_DIV_MASK); - if (!(host->pdata->flags & TMIO_MMC_FAST_CLK_CHG)) + if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) { + sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100); msleep(10); + } } static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) @@ -190,19 +174,41 @@ static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN & sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); - msleep(host->pdata->flags & TMIO_MMC_FAST_CLK_CHG ? 5 : 10); + msleep(host->pdata->flags & TMIO_MMC_MIN_RCAR2 ? 5 : 10); } -static void tmio_mmc_clk_start(struct tmio_mmc_host *host) +static void tmio_mmc_set_clock(struct tmio_mmc_host *host, + unsigned int new_clock) { - sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | - sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); - msleep(host->pdata->flags & TMIO_MMC_FAST_CLK_CHG ? 1 : 10); + u32 clk = 0, clock; - if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) { - sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100); - msleep(10); + if (new_clock == 0) { + tmio_mmc_clk_stop(host); + return; } + + if (host->clk_update) + clock = host->clk_update(host, new_clock) / 512; + else + clock = host->mmc->f_min; + + for (clk = 0x80000080; new_clock >= (clock << 1); clk >>= 1) + clock <<= 1; + + /* 1/1 clock is option */ + if ((host->pdata->flags & TMIO_MMC_CLK_ACTUAL) && ((clk >> 22) & 0x1)) + clk |= 0xff; + + if (host->set_clk_div) + host->set_clk_div(host->pdev, (clk >> 22) & 1); + + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN & + sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & CLK_CTL_DIV_MASK); + if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2)) + msleep(10); + + tmio_mmc_clk_start(host); } static void tmio_mmc_reset(struct tmio_mmc_host *host) @@ -264,9 +270,6 @@ static void tmio_mmc_reset_work(struct work_struct *work) tmio_mmc_abort_dma(host); mmc_request_done(host->mmc, mrq); - - pm_runtime_mark_last_busy(mmc_dev(host->mmc)); - pm_runtime_put_autosuspend(mmc_dev(host->mmc)); } /* called with host->lock held, interrupts disabled */ @@ -296,9 +299,6 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host) tmio_mmc_abort_dma(host); mmc_request_done(host->mmc, mrq); - - pm_runtime_mark_last_busy(mmc_dev(host->mmc)); - pm_runtime_put_autosuspend(mmc_dev(host->mmc)); } static void tmio_mmc_done_work(struct work_struct *work) @@ -375,7 +375,7 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command tmio_mmc_enable_mmc_irqs(host, irq_mask); /* Fire off the command */ - sd_ctrl_write32(host, CTL_ARG_REG, cmd->arg); + sd_ctrl_write32_as_16_and_16(host, CTL_ARG_REG, cmd->arg); sd_ctrl_write16(host, CTL_SD_CMD, c); return 0; @@ -530,7 +530,7 @@ static void tmio_mmc_data_irq(struct tmio_mmc_host *host) goto out; if (host->chan_tx && (data->flags & MMC_DATA_WRITE) && !host->force_pio) { - u32 status = sd_ctrl_read32(host, CTL_STATUS); + u32 status = sd_ctrl_read16_and_16_as_32(host, CTL_STATUS); bool done = false; /* @@ -542,7 +542,7 @@ static void tmio_mmc_data_irq(struct tmio_mmc_host *host) * waiting for one more interrupt fixes the problem. */ if (host->pdata->flags & TMIO_MMC_HAS_IDLE_WAIT) { - if (status & TMIO_STAT_ILL_FUNC) + if (status & TMIO_STAT_SCLKDIVEN) done = true; } else { if (!(status & TMIO_STAT_CMD_BUSY)) @@ -585,7 +585,7 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, */ for (i = 3, addr = CTL_RESPONSE ; i >= 0 ; i--, addr += 4) - cmd->resp[i] = sd_ctrl_read32(host, addr); + cmd->resp[i] = sd_ctrl_read16_and_16_as_32(host, addr); if (cmd->flags & MMC_RSP_136) { cmd->resp[0] = (cmd->resp[0] << 8) | (cmd->resp[1] >> 24); @@ -625,19 +625,6 @@ out: spin_unlock(&host->lock); } -static void tmio_mmc_card_irq_status(struct tmio_mmc_host *host, - int *ireg, int *status) -{ - *status = sd_ctrl_read32(host, CTL_STATUS); - *ireg = *status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask; - - pr_debug_status(*status); - pr_debug_status(*ireg); - - /* Clear the status except the interrupt status */ - sd_ctrl_write32(host, CTL_STATUS, TMIO_MASK_IRQ); -} - static bool __tmio_mmc_card_detect_irq(struct tmio_mmc_host *host, int ireg, int status) { @@ -657,18 +644,6 @@ static bool __tmio_mmc_card_detect_irq(struct tmio_mmc_host *host, return false; } -irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid) -{ - unsigned int ireg, status; - struct tmio_mmc_host *host = devid; - - tmio_mmc_card_irq_status(host, &ireg, &status); - __tmio_mmc_card_detect_irq(host, ireg, status); - - return IRQ_HANDLED; -} -EXPORT_SYMBOL(tmio_mmc_card_detect_irq); - static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host, int ireg, int status) { @@ -698,19 +673,7 @@ static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host, return false; } -irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid) -{ - unsigned int ireg, status; - struct tmio_mmc_host *host = devid; - - tmio_mmc_card_irq_status(host, &ireg, &status); - __tmio_mmc_sdcard_irq(host, ireg, status); - - return IRQ_HANDLED; -} -EXPORT_SYMBOL(tmio_mmc_sdcard_irq); - -irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid) +static void tmio_mmc_sdio_irq(int irq, void *devid) { struct tmio_mmc_host *host = devid; struct mmc_host *mmc = host->mmc; @@ -719,7 +682,7 @@ irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid) unsigned int sdio_status; if (!(pdata->flags & TMIO_MMC_SDIO_IRQ)) - return IRQ_HANDLED; + return; status = sd_ctrl_read16(host, CTL_SDIO_STATUS); ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdcard_irq_mask; @@ -732,19 +695,22 @@ irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid) if (mmc->caps & MMC_CAP_SDIO_IRQ && ireg & TMIO_SDIO_STAT_IOIRQ) mmc_signal_sdio_irq(mmc); - - return IRQ_HANDLED; } -EXPORT_SYMBOL(tmio_mmc_sdio_irq); irqreturn_t tmio_mmc_irq(int irq, void *devid) { struct tmio_mmc_host *host = devid; unsigned int ireg, status; - pr_debug("MMC IRQ begin\n"); + status = sd_ctrl_read16_and_16_as_32(host, CTL_STATUS); + ireg = status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask; + + pr_debug_status(status); + pr_debug_status(ireg); + + /* Clear the status except the interrupt status */ + sd_ctrl_write32_as_16_and_16(host, CTL_STATUS, TMIO_MASK_IRQ); - tmio_mmc_card_irq_status(host, &ireg, &status); if (__tmio_mmc_card_detect_irq(host, ireg, status)) return IRQ_HANDLED; if (__tmio_mmc_sdcard_irq(host, ireg, status)) @@ -812,8 +778,6 @@ static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) spin_unlock_irqrestore(&host->lock, flags); - pm_runtime_get_sync(mmc_dev(mmc)); - if (mrq->data) { ret = tmio_mmc_start_data(host, mrq->data); if (ret) @@ -832,24 +796,14 @@ fail: host->mrq = NULL; mrq->cmd->error = ret; mmc_request_done(mmc, mrq); - - pm_runtime_mark_last_busy(mmc_dev(mmc)); - pm_runtime_put_autosuspend(mmc_dev(mmc)); } -static int tmio_mmc_clk_update(struct tmio_mmc_host *host) +static int tmio_mmc_clk_enable(struct tmio_mmc_host *host) { - struct mmc_host *mmc = host->mmc; - int ret; - if (!host->clk_enable) return -ENOTSUPP; - ret = host->clk_enable(host->pdev, &mmc->f_max); - if (!ret) - mmc->f_min = mmc->f_max / 512; - - return ret; + return host->clk_enable(host); } static void tmio_mmc_power_on(struct tmio_mmc_host *host, unsigned short vdd) @@ -925,8 +879,6 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) struct device *dev = &host->pdev->dev; unsigned long flags; - pm_runtime_get_sync(mmc_dev(mmc)); - mutex_lock(&host->ios_lock); spin_lock_irqsave(&host->lock, flags); @@ -959,14 +911,12 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) tmio_mmc_clk_stop(host); break; case MMC_POWER_UP: - tmio_mmc_set_clock(host, ios->clock); tmio_mmc_power_on(host, ios->vdd); - tmio_mmc_clk_start(host); + tmio_mmc_set_clock(host, ios->clock); tmio_mmc_set_bus_width(host, ios->bus_width); break; case MMC_POWER_ON: tmio_mmc_set_clock(host, ios->clock); - tmio_mmc_clk_start(host); tmio_mmc_set_bus_width(host, ios->bus_width); break; } @@ -983,9 +933,6 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->clk_cache = ios->clock; mutex_unlock(&host->ios_lock); - - pm_runtime_mark_last_busy(mmc_dev(mmc)); - pm_runtime_put_autosuspend(mmc_dev(mmc)); } static int tmio_mmc_get_ro(struct mmc_host *mmc) @@ -996,11 +943,8 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc) if (ret >= 0) return ret; - pm_runtime_get_sync(mmc_dev(mmc)); ret = !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) || - (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)); - pm_runtime_mark_last_busy(mmc_dev(mmc)); - pm_runtime_put_autosuspend(mmc_dev(mmc)); + (sd_ctrl_read16_and_16_as_32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)); return ret; } @@ -1016,12 +960,20 @@ static int tmio_multi_io_quirk(struct mmc_card *card, return blk_size; } -static const struct mmc_host_ops tmio_mmc_ops = { +static int tmio_mmc_card_busy(struct mmc_host *mmc) +{ + struct tmio_mmc_host *host = mmc_priv(mmc); + + return !(sd_ctrl_read16_and_16_as_32(host, CTL_STATUS) & TMIO_STAT_DAT0); +} + +static struct mmc_host_ops tmio_mmc_ops = { .request = tmio_mmc_request, .set_ios = tmio_mmc_set_ios, .get_ro = tmio_mmc_get_ro, .get_cd = mmc_gpio_get_cd, .enable_sdio_irq = tmio_mmc_enable_sdio_irq, + .card_busy = tmio_mmc_card_busy, .multi_io_quirk = tmio_multi_io_quirk, }; @@ -1120,7 +1072,9 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host, goto host_free; } + tmio_mmc_ops.start_signal_voltage_switch = _host->start_signal_voltage_switch; mmc->ops = &tmio_mmc_ops; + mmc->caps |= MMC_CAP_4_BIT_DATA | pdata->capabilities; mmc->caps2 |= pdata->capabilities2; mmc->max_segs = 32; @@ -1135,7 +1089,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host, mmc->caps & MMC_CAP_NONREMOVABLE || mmc->slot.cd_irq >= 0); - if (tmio_mmc_clk_update(_host) < 0) { + if (tmio_mmc_clk_enable(_host) < 0) { mmc->f_max = pdata->hclk; mmc->f_min = mmc->f_max / 512; } @@ -1159,7 +1113,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host, tmio_mmc_clk_stop(_host); tmio_mmc_reset(_host); - _host->sdcard_irq_mask = sd_ctrl_read32(_host, CTL_IRQ_MASK); + _host->sdcard_irq_mask = sd_ctrl_read16_and_16_as_32(_host, CTL_IRQ_MASK); tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); /* Unmask the IRQs we want to know about */ @@ -1251,7 +1205,7 @@ int tmio_mmc_host_runtime_suspend(struct device *dev) tmio_mmc_clk_stop(host); if (host->clk_disable) - host->clk_disable(host->pdev); + host->clk_disable(host); return 0; } @@ -1263,12 +1217,10 @@ int tmio_mmc_host_runtime_resume(struct device *dev) struct tmio_mmc_host *host = mmc_priv(mmc); tmio_mmc_reset(host); - tmio_mmc_clk_update(host); + tmio_mmc_clk_enable(host); - if (host->clk_cache) { + if (host->clk_cache) tmio_mmc_set_clock(host, host->clk_cache); - tmio_mmc_clk_start(host); - } tmio_mmc_enable_dma(host, true); |