If it is felt that the use of the quirk SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS needs
to be protected against being interrupted the following code replaces the last
few lines of set_ios
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
if (host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) {
/*
* Some (ENE) controllers go apeshit on some ios operation,
* signalling timeout and CRC errors even on CMD0. Resetting
* it on each ios seems to solve the problem.
*/
spin_lock_irqsave(&host->lock, flags);
sdhci_unmask_irqs(host, ier);
sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
spin_unlock_irqrestore(&host->lock, flags);
}
else
sdhci_unmask_irqs(host, ier);
out:
mmiowb();
}
On Jan 10, 2011, at 6:51 AM, Philip Rakity wrote:
>
>
> In the current implementation of set_ios -- spin_lock with interrupts
> disabled is held when mdelay is called. This is considered bad form.
>
> This code changes how set_ios works to mask out interrupts on the sdhci
> device rather than disable interrupts.
>
> This code has been tested on mmp2 - linux-next. The code is posted as a RFC
> for review since no amount of testing can
> verify interrupt handling is really correct.
>
> I can post a patch if that is desired as well.
>
> Philip
>
>>
>> static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>> {
>> struct sdhci_host *host;
>> unsigned long flags;
>> u8 ctrl;
>> u32 ier;
>>
>> host = mmc_priv(mmc);
>>
>> if (host->flags & SDHCI_DEVICE_DEAD)
>> goto out;
>>
>> /*
>> * Reset the chip on each power off.
>> * Should clear out any weird states.
>> */
>> spin_lock_irqsave(&host->lock, flags);
>> if (ios->power_mode == MMC_POWER_OFF) {
>> sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
>> sdhci_reinit(host);
>> }
>>
>> ier = sdhci_readl(host, SDHCI_INT_ENABLE);
>> sdhci_mask_irqs(host, ier);
>> spin_unlock_irqrestore(&host->lock, flags);
>>
>> sdhci_set_clock(host, ios->clock);
>> sdhci_set_ddr(host, ios->ddr);
>>
>> if (ios->power_mode == MMC_POWER_OFF)
>> sdhci_set_power(host, -1);
>> else
>> sdhci_set_power(host, ios->vdd);
>>
>> if (host->ops->platform_send_init_74_clocks)
>> host->ops->platform_send_init_74_clocks(host, ios->power_mode);
>>
>> #ifdef CONFIG_MMC_CLKGATE
>> if ((mmc->caps & MMC_CAP_HW_CLOCK_GATING)
>> && host->ops->platform_hw_clk_gate)
>> host->ops->platform_hw_clk_gate(host);
>> #endif
>>
>> /*
>> * If your platform has 8-bit width support but is not a v3 controller,
>> * or if it requires special setup code, you should implement that in
>> * platform_8bit_width().
>> */
>> if (host->ops->platform_8bit_width)
>> host->ops->platform_8bit_width(host, ios->bus_width);
>> else {
>> ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
>> if (ios->bus_width == MMC_BUS_WIDTH_8) {
>> ctrl &= ~SDHCI_CTRL_4BITBUS;
>> if (host->version >= SDHCI_SPEC_300)
>> ctrl |= SDHCI_CTRL_8BITBUS;
>> } else {
>> if (host->version >= SDHCI_SPEC_300)
>> ctrl &= ~SDHCI_CTRL_8BITBUS;
>> if (ios->bus_width == MMC_BUS_WIDTH_4)
>> ctrl |= SDHCI_CTRL_4BITBUS;
>> else
>> ctrl &= ~SDHCI_CTRL_4BITBUS;
>> }
>> sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
>> }
>>
>> ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
>>
>> if ((ios->timing == MMC_TIMING_SD_HS ||
>> ios->timing == MMC_TIMING_MMC_HS)
>> && !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT))
>> ctrl |= SDHCI_CTRL_HISPD;
>> else
>> ctrl &= ~SDHCI_CTRL_HISPD;
>>
>> sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
>> sdhci_unmask_irqs(host, ier);
>>
>> /*
>> * Some (ENE) controllers go apeshit on some ios operation,
>> * signalling timeout and CRC errors even on CMD0. Resetting
>> * it on each ios seems to solve the problem.
>> */
>> if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) {
>> spin_lock_irqsave(&host->lock, flags);
>> sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
>> spin_unlock_irqrestore(&host->lock, flags);
>> }
>>
>> out:
>> mmiowb();
>> }
>> <sdhci.c>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html