summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYangbo Lu <yangbo.lu@freescale.com>2015-06-11 10:16:36 (GMT)
committerZhengxiong Jin <Jason.Jin@freescale.com>2015-06-16 03:00:33 (GMT)
commit8d0408666626bd157649dbba34ac1e44b4d55caf (patch)
treed5dc08e0366f4548673823b82581c3fc88548369
parente08d8bf61be6163f3bb4840042d8463c8c5b70a9 (diff)
downloadlinux-fsl-qoriq-8d0408666626bd157649dbba34ac1e44b4d55caf.tar.xz
mmc: sdhci: more efficient interrupt enable register handling
Rather than wasting cycles read-modify-writing the interrupt enable registers, cache the value locally instead. This patch is from upstreaming linux, commit id b537f94ce19583de1882f539a5cc49aa99260aca Signed-off-by: Yangbo Lu <yangbo.lu@freescale.com> Change-Id: I3c1bb4d4b3f7d7dccbaa4748816bfe381edc484c Reviewed-on: http://git.am.freescale.net:8181/37869 Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com> Reviewed-by: Xiaobo Xie <X.Xie@freescale.com> Reviewed-by: Zhengxiong Jin <Jason.Jin@freescale.com>
-rw-r--r--drivers/mmc/host/sdhci.c94
-rw-r--r--include/linux/mmc/sdhci.h3
2 files changed, 47 insertions, 50 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 7a0baef..8f0e396 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -132,27 +132,6 @@ static void sdhci_dumpregs(struct sdhci_host *host)
* *
\*****************************************************************************/
-static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
-{
- u32 ier;
-
- ier = sdhci_readl(host, SDHCI_INT_ENABLE);
- ier &= ~clear;
- ier |= set;
- sdhci_writel(host, ier, SDHCI_INT_ENABLE);
- sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
-}
-
-static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs)
-{
- sdhci_clear_set_irqs(host, 0, irqs);
-}
-
-static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
-{
- sdhci_clear_set_irqs(host, irqs, 0);
-}
-
static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
{
u32 present, irqs;
@@ -166,9 +145,12 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
if (enable)
- sdhci_unmask_irqs(host, irqs);
+ host->ier |= irqs;
else
- sdhci_mask_irqs(host, irqs);
+ host->ier &= ~irqs;
+
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
}
static void sdhci_enable_card_detection(struct sdhci_host *host)
@@ -184,7 +166,6 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
void sdhci_reset(struct sdhci_host *host, u8 mask)
{
unsigned long timeout;
- u32 uninitialized_var(ier);
if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
@@ -192,9 +173,6 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)
return;
}
- if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
- ier = sdhci_readl(host, SDHCI_INT_ENABLE);
-
if (host->ops->platform_reset_enter)
host->ops->platform_reset_enter(host, mask);
@@ -225,8 +203,10 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)
if (host->ops->platform_reset_exit)
host->ops->platform_reset_exit(host, mask);
- if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
- sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier);
+ if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) {
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ }
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL))
@@ -238,25 +218,26 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
static void sdhci_init(struct sdhci_host *host, int soft)
{
- u32 pltm_irq = 0, irq = 0;
+ u32 pltm_irq = 0;
if (soft)
sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
else
sdhci_reset(host, SDHCI_RESET_ALL);
- irq = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
+ host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE;
if (pltm_irq)
- irq |= pltm_irq;
+ host->ier |= pltm_irq;
if (host->flags & SDHCI_AUTO_CMD12)
- irq |= SDHCI_INT_ACMD12ERR;
+ host->ier |= SDHCI_INT_ACMD12ERR;
- sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, irq);
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
if (soft) {
/* force clock reconfiguration */
@@ -731,9 +712,12 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host)
u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;
if (host->flags & SDHCI_REQ_USE_DMA)
- sdhci_clear_set_irqs(host, pio_irqs, dma_irqs);
+ host->ier = (host->ier & ~pio_irqs) | dma_irqs;
else
- sdhci_clear_set_irqs(host, dma_irqs, pio_irqs);
+ host->ier = (host->ier & ~dma_irqs) | pio_irqs;
+
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
}
static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
@@ -1733,9 +1717,12 @@ static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
goto out;
if (enable)
- sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT);
+ host->ier |= SDHCI_INT_CARD_INT;
else
- sdhci_mask_irqs(host, SDHCI_INT_CARD_INT);
+ host->ier &= ~SDHCI_INT_CARD_INT;
+
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
out:
mmiowb();
}
@@ -1868,7 +1855,6 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
struct sdhci_host *host;
u16 ctrl;
- u32 ier;
int tuning_loop_counter = MAX_TUNING_LOOP;
unsigned long timeout;
int err = 0;
@@ -1916,8 +1902,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
* to make sure we don't hit a controller bug, we _only_
* enable Buffer Read Ready interrupt here.
*/
- ier = sdhci_readl(host, SDHCI_INT_ENABLE);
- sdhci_clear_set_irqs(host, ier, SDHCI_INT_DATA_AVAIL);
+ sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
+ sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
/*
* Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number
@@ -2052,7 +2038,8 @@ out:
if (err && (host->flags & SDHCI_USING_RETUNING_TIMER))
err = 0;
- sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
spin_unlock(&host->lock);
enable_irq(host->irq);
sdhci_runtime_pm_put(host);
@@ -2480,10 +2467,11 @@ again:
* More testing are needed here to ensure it works for other
* platforms though.
*/
- sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
- SDHCI_INT_CARD_REMOVE);
- sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
- SDHCI_INT_CARD_INSERT);
+ host->ier &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
+ host->ier |= present ? SDHCI_INT_CARD_REMOVE :
+ SDHCI_INT_CARD_INSERT;
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
@@ -2609,7 +2597,9 @@ int sdhci_suspend_host(struct sdhci_host *host)
}
if (!device_may_wakeup(mmc_dev(host->mmc))) {
- sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
+ host->ier = 0;
+ sdhci_writel(host, 0, SDHCI_INT_ENABLE);
+ sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
free_irq(host->irq, host);
} else {
sdhci_enable_irq_wakeups(host);
@@ -2708,7 +2698,9 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
}
spin_lock_irqsave(&host->lock, flags);
- sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
+ host->ier = 0;
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
spin_unlock_irqrestore(&host->lock, flags);
synchronize_irq(host->irq);
@@ -3307,7 +3299,8 @@ int sdhci_add_host(struct sdhci_host *host)
#ifdef SDHCI_USE_LEDS_CLASS
reset:
sdhci_reset(host, SDHCI_RESET_ALL);
- sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
+ sdhci_writel(host, 0, SDHCI_INT_ENABLE);
+ sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
free_irq(host->irq, host);
#endif
untasklet:
@@ -3350,7 +3343,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
if (!dead)
sdhci_reset(host, SDHCI_RESET_ALL);
- sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
+ sdhci_writel(host, 0, SDHCI_INT_ENABLE);
+ sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
free_irq(host->irq, host);
del_timer_sync(&host->timer);
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 91bb4c9..1539790 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -185,6 +185,9 @@ struct sdhci_host {
unsigned int ocr_avail_mmc;
u32 ocr_mask; /* available voltages */
+ /* cached registers */
+ u32 ier;
+
wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */
unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */