On 14 December 2012 11:53, Kevin Liu <kliu5@xxxxxxxxxxx> wrote: > 1. if host does NOT implement signal voltage setting function, > should return error. > 2. add the check for data signal before voltage change according > to the spec. If host does NOT detect a low signal level, the host > should abort the voltage switch sequence. (phisical layer spec 4.2.4.2(4)) > 3. if voltage change failed then no need to restore the clock > before cycle power the card. > 4. call mmc_power_cycle here since it's a part of voltage switch. > besides -EAGAIN, any other error returned should also cycle power the card. > > Signed-off-by: Kevin Liu <kliu5@xxxxxxxxxxx> > --- > drivers/mmc/core/core.c | 71 ++++++++++++++++++++++++++++------------------ > 1 files changed, 43 insertions(+), 28 deletions(-) > > diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c > index d1aa8ab..da93186 100644 > --- a/drivers/mmc/core/core.c > +++ b/drivers/mmc/core/core.c > @@ -1226,6 +1226,9 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11 > > BUG_ON(!host); > > + if (!host->ops->start_signal_voltage_switch) > + return -EPERM; > + No, this is not OK. For example, eMMC might default use 1.8V as I/O voltage, you don't want to force host drivers implementing this function to make this work. > /* > * Send CMD11 only if the request is to switch the card to > * 1.8V signalling. > @@ -1245,47 +1248,59 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11 > > host->ios.signal_voltage = signal_voltage; > > - if (host->ops->start_signal_voltage_switch) { > - u32 clock; > + u32 clock; > + > + mmc_host_clk_hold(host); > + > + if (cmd11) { > + if (!host->ops->card_busy) > + pr_warning("%s: cannot verify signal voltage switch\n", > + mmc_hostname(host)); > > - mmc_host_clk_hold(host); > /* > * During a signal voltage level switch, the clock must be gated > * for a certain period of time according to the SD spec > */ > - if (cmd11) { > - clock = host->ios.clock; > - host->ios.clock = 0; > - mmc_set_ios(host); > - } > + clock = host->ios.clock; > + host->ios.clock = 0; > + mmc_set_ios(host); > > - err = host->ops->start_signal_voltage_switch(host, &host->ios); > + if (host->ops->card_busy && !host->ops->card_busy(host)) { > + err = -EAGAIN; > + } else { Great that you spotted this! We should check busy before we do the actual voltage switch. Although, I think it would make sense to do this before the clock is set to 0. Especially important for those host controllers that do support busy-detection, a qualified guess would be that those also could require the clock to be on to detect this. Or what do you think? >From spec point of view it shall be safe to do it before setting clk to 0. > > - if (err && cmd11) { > - host->ios.clock = clock; > - mmc_set_ios(host); > - } else if (cmd11) { > - /* Keep clock gated for at least 5 ms */ > - mmc_delay(5); > - host->ios.clock = clock; > - mmc_set_ios(host); > + err = host->ops->start_signal_voltage_switch(host, &host->ios); > > - /* Wait for at least 1 ms according to spec */ > - mmc_delay(1); > + if (!err) { > + /* Keep clock gated for at least 5 ms */ > + mmc_delay(5); > + host->ios.clock = clock; > + mmc_set_ios(host); > > - /* > - * Failure to switch is indicated by the card holding > - * dat[0:3] low > - */ > - if (!host->ops->card_busy) > - pr_warning("%s: cannot verify signal voltage switch\n", > + /* Wait for at least 1 ms according to spec */ > + mmc_delay(1); > + > + /* > + * Failure to switch is indicated by the card holding > + * dat[0:3] low > + */ > + if (host->ops->card_busy && host->ops->card_busy(host)) > + err = -EAGAIN; > + } > + } > + if (err) { > + /* Power cycle card */ > + pr_debug("%s: Signal voltage switch failed, " > + "power cycling card \n", > mmc_hostname(host)); > - else if (host->ops->card_busy(host)) > - err = -EAGAIN; > + mmc_power_cycle(host); > } > - mmc_host_clk_release(host); > + } else { > + err = host->ops->start_signal_voltage_switch(host, &host->ios); > } > > + mmc_host_clk_release(host); > + > return err; > } > > -- > 1.7.0.4 > Kind regards Ulf Hansson -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html