From 55be7f8d5ec11342d1ed1a2131f9296e128c3e6b Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 20 Aug 2004 00:10:27 +0100 Subject: [PATCH] [MMC] MMCI optimisations. Optimise register accesses; dereferencing "host" each time introduces extra loads. No need to check MCI_TXFIFOEMPTY when checking if we have a data IRQ. Since we support clock bypass mode, the maximum clock rate is the MCLK rate itself. --- drivers/mmc/mmci.c | 53 +++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 014617e27b19..7bf99a6e2b94 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c @@ -63,6 +63,7 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) { unsigned int datactrl, timeout, irqmask; + void *base; DBG(host, "blksz %04x blks %04x flags %08x\n", 1 << data->blksz_bits, data->blocks, data->flags); @@ -76,8 +77,9 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) ((unsigned long long)data->timeout_ns * host->cclk) / 1000000000ULL; - writel(timeout, host->base + MMCIDATATIMER); - writel(host->size, host->base + MMCIDATALENGTH); + base = host->base; + writel(timeout, base + MMCIDATATIMER); + writel(host->size, base + MMCIDATALENGTH); datactrl = MCI_DPSM_ENABLE | data->blksz_bits << 4; if (data->flags & MMC_DATA_READ) { @@ -91,18 +93,20 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) irqmask = MCI_TXFIFOHALFEMPTYMASK; } - writel(datactrl, host->base + MMCIDATACTRL); - writel(irqmask, host->base + MMCIMASK1); + writel(datactrl, base + MMCIDATACTRL); + writel(irqmask, base + MMCIMASK1); } static void mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) { + void *base = host->base; + DBG(host, "op %02x arg %08x flags %08x\n", cmd->opcode, cmd->arg, cmd->flags); - if (readl(host->base + MMCICOMMAND) & MCI_CPSM_ENABLE) { - writel(0, host->base + MMCICOMMAND); + if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) { + writel(0, base + MMCICOMMAND); udelay(1); } @@ -122,8 +126,8 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) host->cmd = cmd; - writel(cmd->arg, host->base + MMCIARGUMENT); - writel(c, host->base + MMCICOMMAND); + writel(cmd->arg, base + MMCIARGUMENT); + writel(c, base + MMCICOMMAND); } static void @@ -146,7 +150,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, host->data = NULL; if (!data->stop) { mmci_request_end(host, data->mrq); - } else /*if (readl(host->base + MMCIDATACNT) > 6)*/ { + } else { mmci_start_command(host, data->stop, 0); } } @@ -156,12 +160,14 @@ static void mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, unsigned int status) { + void *base = host->base; + host->cmd = NULL; - cmd->resp[0] = readl(host->base + MMCIRESPONSE0); - cmd->resp[1] = readl(host->base + MMCIRESPONSE1); - cmd->resp[2] = readl(host->base + MMCIRESPONSE2); - cmd->resp[3] = readl(host->base + MMCIRESPONSE3); + cmd->resp[0] = readl(base + MMCIRESPONSE0); + cmd->resp[1] = readl(base + MMCIRESPONSE1); + cmd->resp[2] = readl(base + MMCIRESPONSE2); + cmd->resp[3] = readl(base + MMCIRESPONSE3); if (status & MCI_CMDTIMEOUT) { cmd->error = MMC_ERR_TIMEOUT; @@ -176,27 +182,31 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, } } +/* + * PIO data transfer IRQ handler. + */ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs) { struct mmci_host *host = dev_id; + void *base = host->base; u32 status; int ret = 0; do { - status = readl(host->base + MMCISTATUS); + status = readl(base + MMCISTATUS); if (!(status & (MCI_RXDATAAVLBL|MCI_RXFIFOHALFFULL| - MCI_TXFIFOEMPTY|MCI_TXFIFOHALFEMPTY))) + MCI_TXFIFOHALFEMPTY))) break; DBG(host, "irq1 %08x\n", status); if (status & (MCI_RXDATAAVLBL|MCI_RXFIFOHALFFULL)) { - int count = host->size - (readl(host->base + MMCIFIFOCNT) << 2); + unsigned int count = host->size - (readl(base + MMCIFIFOCNT) << 2); if (count < 0) count = 0; if (count && host->buffer) { - readsl(host->base + MMCIFIFO, host->buffer, count >> 2); + readsl(base + MMCIFIFO, host->buffer, count >> 2); host->buffer += count; host->size -= count; if (host->size == 0) @@ -207,7 +217,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs) first = 0; printk(KERN_ERR "MMCI: sinking excessive data\n"); } - readl(host->base + MMCIFIFO); + readl(base + MMCIFIFO); } } @@ -221,7 +231,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs) MCI_FIFOSIZE : MCI_FIFOHALFSIZE; unsigned int count = min(host->size, maxcnt); - writesl(host->base + MMCIFIFO, host->buffer, count >> 2); + writesl(base + MMCIFIFO, host->buffer, count >> 2); host->buffer += count; host->size -= count; @@ -242,6 +252,9 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs) return IRQ_RETVAL(ret); } +/* + * Handle completion of command and data transfers. + */ static irqreturn_t mmci_irq(int irq, void *dev_id, struct pt_regs *regs) { struct mmci_host *host = dev_id; @@ -411,7 +424,7 @@ static int mmci_probe(struct amba_device *dev, void *id) mmc->ops = &mmci_ops; mmc->f_min = (host->mclk + 511) / 512; - mmc->f_max = min(host->mclk / 2, fmax); + mmc->f_max = min(host->mclk, fmax); mmc->ocr_avail = plat->ocr_mask; spin_lock_init(&host->lock); -- 2.39.5