From patchwork Tue Aug 16 10:11:24 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Horman X-Patchwork-Id: 1070952 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p7GABdb3020505 for ; Tue, 16 Aug 2011 10:11:40 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752319Ab1HPKLj (ORCPT ); Tue, 16 Aug 2011 06:11:39 -0400 Received: from kirsty.vergenet.net ([202.4.237.240]:38746 "EHLO kirsty.vergenet.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752463Ab1HPKLh (ORCPT ); Tue, 16 Aug 2011 06:11:37 -0400 Received: from joe.akashicho.tokyo.vergenet.net (joe.akashicho.tokyo.vergenet.net [IPv6:2001:470:f44f:403:1ec1:deff:fe98:754d]) by kirsty.vergenet.net (Postfix) with ESMTP id 437E8245A3; Tue, 16 Aug 2011 20:11:34 +1000 (EST) Received: by joe.akashicho.tokyo.vergenet.net (Postfix, from userid 7100) id E71B828A035; Tue, 16 Aug 2011 19:11:30 +0900 (JST) From: Simon Horman To: linux-mmc@vger.kernel.org, linux-sh@vger.kernel.org Cc: Chris Ball , Guennadi Liakhovetski , Magnus Damm , Simon Horman Subject: [PATCH 2/4] mmc: tmio: Provide separate interrupt handlers Date: Tue, 16 Aug 2011 19:11:24 +0900 Message-Id: <1313489486-831-3-git-send-email-horms@verge.net.au> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1313489486-831-1-git-send-email-horms@verge.net.au> References: <1313489486-831-1-git-send-email-horms@verge.net.au> Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Tue, 16 Aug 2011 10:11:41 +0000 (UTC) Provide separate interrupt handlers which may be used by platforms where SDHI has three interrupt sources. This patch also removes the commented-out handling of CRC and other errors. Cc: Guennadi Liakhovetski Cc: Magnus Damm Signed-off-by: Simon Horman --- * SDCARD portion tested on AP4/Mackerel * SDIO portion untested v3 * Rebase for updated "mmc: tmio: Cache interrupt masks" * As suggested by Guennadi Liakhovetski - Do not alter logic to handle more than one interupt at once - Add missing "static" to declartion of __tmio_mmc_sdcard_irq() v2 * As suggested by Guennadi Liakhovetski - Combine 3 patches into one - Reduce the number of __tmio_..._irq() functions - Rename "...card_access..." functions as "...sdcard..." --- drivers/mmc/host/tmio_mmc.h | 3 + drivers/mmc/host/tmio_mmc_pio.c | 131 ++++++++++++++++++++++++-------------- 2 files changed, 86 insertions(+), 48 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 1cf8db5..3020f98 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -97,6 +97,9 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host); void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i); void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i); irqreturn_t tmio_mmc_irq(int irq, void *devid); +irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid); +irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid); +irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid); static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, unsigned long *flags) diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index f0c7830..37adfb2 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -545,44 +545,20 @@ out: spin_unlock(&host->lock); } -irqreturn_t tmio_mmc_irq(int irq, void *devid) +static void tmio_mmc_card_irq_status(struct tmio_mmc_host *host, + int *ireg, int *status) { - struct tmio_mmc_host *host = devid; - struct mmc_host *mmc = host->mmc; - struct tmio_mmc_data *pdata = host->pdata; - unsigned int ireg, status; - unsigned int sdio_ireg, sdio_status; - - pr_debug("MMC IRQ begin\n"); - - status = sd_ctrl_read32(host, CTL_STATUS); - ireg = status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask; - - sdio_ireg = 0; - if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) { - sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS); - sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & - ~host->sdio_irq_mask; + *status = sd_ctrl_read32(host, CTL_STATUS); + *ireg = *status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask; - sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL); - - if (sdio_ireg && !host->sdio_irq_enabled) { - pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n", - sdio_status, host->sdio_irq_mask, sdio_ireg); - tmio_mmc_enable_sdio_irq(mmc, 0); - goto out; - } - - if (mmc->caps & MMC_CAP_SDIO_IRQ && - sdio_ireg & TMIO_SDIO_STAT_IOIRQ) - mmc_signal_sdio_irq(mmc); - - if (sdio_ireg) - goto out; - } + pr_debug_status(*status); + pr_debug_status(*ireg); +} - pr_debug_status(status); - pr_debug_status(ireg); +static int __tmio_mmc_card_detect_irq(struct tmio_mmc_host *host, + int ireg, int status) +{ + struct mmc_host *mmc = host->mmc; /* Card insert / remove attempts */ if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) { @@ -592,43 +568,102 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) ((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) && !work_pending(&mmc->detect.work)) mmc_detect_change(host->mmc, msecs_to_jiffies(100)); - goto out; + return 1; } - /* CRC and other errors */ -/* if (ireg & TMIO_STAT_ERR_IRQ) - * handled |= tmio_error_irq(host, irq, stat); - */ + return 0; +} + +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 int __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host, + int ireg, int status) +{ /* Command completion */ if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) { tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT); tmio_mmc_cmd_irq(host, status); - goto out; + return 1; } /* Data transfer */ if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) { tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ); tmio_mmc_pio_irq(host); - goto out; + return 1; } /* Data transfer completion */ if (ireg & TMIO_STAT_DATAEND) { tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND); tmio_mmc_data_irq(host); - goto out; + return 1; } - pr_warning("tmio_mmc: Spurious irq, disabling! " - "0x%08x 0x%08x 0x%08x\n", status, host->sdcard_irq_mask, ireg); - pr_debug_status(status); - tmio_mmc_disable_mmc_irqs(host, status & ~host->sdcard_irq_mask); + return 0; +} + +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) +{ + struct tmio_mmc_host *host = devid; + struct mmc_host *mmc = host->mmc; + struct tmio_mmc_data *pdata = host->pdata; + unsigned int ireg, status; + + if (!(pdata->flags & TMIO_MMC_SDIO_IRQ)) + return IRQ_HANDLED; + + status = sd_ctrl_read16(host, CTL_SDIO_STATUS); + ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdcard_irq_mask; + + sd_ctrl_write16(host, CTL_SDIO_STATUS, status & ~TMIO_SDIO_MASK_ALL); + + 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"); + + 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)) + return IRQ_HANDLED; + + tmio_mmc_sdio_irq(irq, devid); -out: return IRQ_HANDLED; } EXPORT_SYMBOL(tmio_mmc_irq);