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 majord...@vger.kernel.org
> 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to