Commit b537f94c authored by Russell King's avatar Russell King Committed by Chris Ball

mmc: sdhci: more efficient interrupt enable register handling

Rather than wasting cycles read-modify-writing the interrupt enable
registers, cache the value locally instead.
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Tested-by: default avatarMarkus Pargmann <mpa@pengutronix.de>
Tested-by: default avatarStephen Warren <swarren@nvidia.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Signed-off-by: default avatarChris Ball <chris@printf.net>
parent be138554
...@@ -131,27 +131,6 @@ static void sdhci_dumpregs(struct sdhci_host *host) ...@@ -131,27 +131,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) static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
{ {
u32 present, irqs; u32 present, irqs;
...@@ -165,9 +144,12 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) ...@@ -165,9 +144,12 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT; irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
if (enable) if (enable)
sdhci_unmask_irqs(host, irqs); host->ier |= irqs;
else 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) static void sdhci_enable_card_detection(struct sdhci_host *host)
...@@ -183,17 +165,12 @@ static void sdhci_disable_card_detection(struct sdhci_host *host) ...@@ -183,17 +165,12 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
static void sdhci_reset(struct sdhci_host *host, u8 mask) static void sdhci_reset(struct sdhci_host *host, u8 mask)
{ {
unsigned long timeout; unsigned long timeout;
u32 uninitialized_var(ier);
if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
SDHCI_CARD_PRESENT)) SDHCI_CARD_PRESENT))
return; return;
} }
if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
ier = sdhci_readl(host, SDHCI_INT_ENABLE);
if (host->ops->platform_reset_enter) if (host->ops->platform_reset_enter)
host->ops->platform_reset_enter(host, mask); host->ops->platform_reset_enter(host, mask);
...@@ -224,8 +201,10 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) ...@@ -224,8 +201,10 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
if (host->ops->platform_reset_exit) if (host->ops->platform_reset_exit)
host->ops->platform_reset_exit(host, mask); host->ops->platform_reset_exit(host, mask);
if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) {
sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); 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->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL)) if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL))
...@@ -242,11 +221,14 @@ static void sdhci_init(struct sdhci_host *host, int soft) ...@@ -242,11 +221,14 @@ static void sdhci_init(struct sdhci_host *host, int soft)
else else
sdhci_reset(host, SDHCI_RESET_ALL); sdhci_reset(host, SDHCI_RESET_ALL);
sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC |
SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); SDHCI_INT_RESPONSE;
sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
if (soft) { if (soft) {
/* force clock reconfiguration */ /* force clock reconfiguration */
...@@ -721,9 +703,12 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) ...@@ -721,9 +703,12 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host)
u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;
if (host->flags & SDHCI_REQ_USE_DMA) 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 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) static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
...@@ -1713,9 +1698,12 @@ static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable) ...@@ -1713,9 +1698,12 @@ static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
{ {
if (!(host->flags & SDHCI_DEVICE_DEAD)) { if (!(host->flags & SDHCI_DEVICE_DEAD)) {
if (enable) if (enable)
sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT); host->ier |= SDHCI_INT_CARD_INT;
else 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);
mmiowb(); mmiowb();
} }
} }
...@@ -1857,7 +1845,6 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) ...@@ -1857,7 +1845,6 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
{ {
struct sdhci_host *host; struct sdhci_host *host;
u16 ctrl; u16 ctrl;
u32 ier;
int tuning_loop_counter = MAX_TUNING_LOOP; int tuning_loop_counter = MAX_TUNING_LOOP;
unsigned long timeout; unsigned long timeout;
int err = 0; int err = 0;
...@@ -1911,8 +1898,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) ...@@ -1911,8 +1898,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
* to make sure we don't hit a controller bug, we _only_ * to make sure we don't hit a controller bug, we _only_
* enable Buffer Read Ready interrupt here. * enable Buffer Read Ready interrupt here.
*/ */
ier = sdhci_readl(host, SDHCI_INT_ENABLE); sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
sdhci_clear_set_irqs(host, ier, SDHCI_INT_DATA_AVAIL); sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
/* /*
* Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number
...@@ -2047,7 +2034,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) ...@@ -2047,7 +2034,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
if (err && (host->flags & SDHCI_USING_RETUNING_TIMER)) if (err && (host->flags & SDHCI_USING_RETUNING_TIMER))
err = 0; 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_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
sdhci_runtime_pm_put(host); sdhci_runtime_pm_put(host);
...@@ -2460,10 +2448,12 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) ...@@ -2460,10 +2448,12 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
* More testing are needed here to ensure it works * More testing are needed here to ensure it works
* for other platforms though. * for other platforms though.
*/ */
sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT : host->ier &= ~(SDHCI_INT_CARD_INSERT |
SDHCI_INT_CARD_REMOVE); SDHCI_INT_CARD_REMOVE);
sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE : host->ier |= present ? SDHCI_INT_CARD_REMOVE :
SDHCI_INT_CARD_INSERT); 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_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
...@@ -2592,7 +2582,9 @@ int sdhci_suspend_host(struct sdhci_host *host) ...@@ -2592,7 +2582,9 @@ int sdhci_suspend_host(struct sdhci_host *host)
} }
if (!device_may_wakeup(mmc_dev(host->mmc))) { 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); free_irq(host->irq, host);
} else { } else {
sdhci_enable_irq_wakeups(host); sdhci_enable_irq_wakeups(host);
...@@ -2691,7 +2683,9 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) ...@@ -2691,7 +2683,9 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
} }
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK & ~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);
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
synchronize_hardirq(host->irq); synchronize_hardirq(host->irq);
...@@ -3282,7 +3276,8 @@ int sdhci_add_host(struct sdhci_host *host) ...@@ -3282,7 +3276,8 @@ int sdhci_add_host(struct sdhci_host *host)
#ifdef SDHCI_USE_LEDS_CLASS #ifdef SDHCI_USE_LEDS_CLASS
reset: reset:
sdhci_reset(host, SDHCI_RESET_ALL); 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); free_irq(host->irq, host);
#endif #endif
untasklet: untasklet:
...@@ -3324,7 +3319,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) ...@@ -3324,7 +3319,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
if (!dead) if (!dead)
sdhci_reset(host, SDHCI_RESET_ALL); 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); free_irq(host->irq, host);
del_timer_sync(&host->timer); del_timer_sync(&host->timer);
......
...@@ -178,6 +178,9 @@ struct sdhci_host { ...@@ -178,6 +178,9 @@ struct sdhci_host {
u32 thread_isr; u32 thread_isr;
/* cached registers */
u32 ier;
wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */ wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */
unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */ unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment