[Gta04-owner] [PATCH V4 1/4] mmc: core: Initial support for MMC power sequences

NeilBrown neilb at suse.de
Sat Feb 7 02:07:23 CET 2015

On Tue, 3 Feb 2015 13:39:13 +0100 Ulf Hansson <ulf.hansson at linaro.org> wrote:

> On 2 February 2015 at 23:10, NeilBrown <neilb at suse.de> wrote:
> > On Mon, 2 Feb 2015 16:10:29 +0100 Ulf Hansson <ulf.hansson at linaro.org> wrote:
> >
> >> On 2 February 2015 at 16:05, Russell King - ARM Linux
> >> <linux at arm.linux.org.uk> wrote:
> >> > On Mon, Feb 02, 2015 at 03:57:37PM +0100, Ulf Hansson wrote:
> >> >> On 30 January 2015 at 23:27, NeilBrown <neilb at suse.de> wrote:
> >> >> > Shortly before this call is
> >> >> >
> >> >> >         host->ios.power_mode = MMC_POWER_ON;
> >> >> >         mmc_set_ios(host);
> >> >> >
> >> >> > and omap_hsmmc_set_ios() contains:
> >> >> >
> >> >> >                 switch (ios->power_mode) {
> >> >> >                 ....
> >> >> >                 case MMC_POWER_ON:
> >> >> >                         do_send_init_stream = 1;
> >> >> >                         break;
> >> >> >
> >> >> >
> >> >> >         if (do_send_init_stream)
> >> >> >                 send_init_stream(host);
> >> >> >
> >> >> > Which sends the "init stream" to the card.
> >> >> > If the card is still being reset at this time, the stream may not
> >> >> > be effective.
> >> >> >
> >> >> > I find that about 10%-20% of the time when I release the reset line
> >> >> > *after* the sequence is sent, my card fails to initialised.  When I
> >> >> > release *before* the sequence is sent, it never fails.
> >> >>
> >> >> Okay, thanks for providing these details.
> >> >
> >> > The right thing to do then is to pulse the reset line at the pre-power-up
> >> > stage.
> >>
> >> I don't think that will work, since the card hasn't yet been powered
> >> and will thus not respond properly to the reset.
> >
> > My understanding, at least in the case of my hardware, is that the power-on
> > is sufficient to reset the device.
> > In my case, the one supply is shared between two devices (wifi and bluetooth)
> > so if the bluetooth is on, then the wifi cannot be power-cycled.  That is
> > when the reset is particularly needed.
> >
> > I'll try to arrange some testing to confirm this is the case.  Of course,
> > this would not be general result, it would only be relevant for my hardware.
> I refreshed my memory for how the cw1200 WLAN device works on the
> ux500 SOC. I decided to post the complete information here, also for
> my own reference.
> These resources need to be controlled during the power sequence of CW1200:
> There are two GPIOs (one reset and one for SPI/SDIO selection), one LP
> (low power) clock and a few power supplies.
> The sequence for power up that needs to be followed are:
> 1. Keep reset GPIO asserted.
> 2. Enable power supplies.
> 3. Enable LP clock.
> 4. Wait a few LP clock cycles to let power/clock stabilize.
> 5. Make sure SPI/SDIO select pin is in SDIO mode. The value will be
> sampled by the WLAN device when reset GPIO is de-asserted.
> 6. De-assert reset GPIO.
> 7. Wait 30 ms for the WLAN device to power up.
> The power supplies may also be shared with a bluetooth device. That
> also means the reset GPIO must be kept asserted in power off state, to
> prevent power up of the WLAN device.
> >From the above, it's clear that toggling the reset GPIOs in the
> ->pre_power_on() phase won't work for CW1200/UX500 case.  That in
> conjunction with the "init stream" issue tells me that we need to
> progress with the below patch:
> "mmc: core: Invoke mmc_pwrseq_post_power_on() prior MMC_POWER_ON state"
> http://www.spinics.net/lists/arm-kernel/msg396592.html
> Kind regards
> Uffe

+ gta04-owner.

Thanks for those details.  They reminded me that I have seen something
similar for the wifi chip I use, and I found it here:


In particular:

  After power-up the reset line should be active for >500us and then
  go high. A short impulse (1-20 us) can later reset the WiFi part.

Also, the wifi and bluetooth share both a power supply and a reset line.

  BT also does not need a reset (unless you try to communicate
  with wrong baudrate and the HCI protocol gets unsynchronized).

  An impulse >5ms does a BT reset. Or a break condition on the
  RX line.

My experiments confirm that if the bluetooth is inactive so that the mmc host
is actually able to power-cycle the wifi, then the reset line isn't needed.
However if the bluetooth is holding the power supply enabled, then we
definitely need the reset to be pulsed low in mmc_power_up(), or the wifi
doesn't initialise properly.

Putting this all together, it seems like the ideal would be:
 - if power supply is already on, pulse reset for 20us, else
   pull reset low
 - enable power supply
 - wait 1ms
 - raise reset line
 - wait 30ms

This should ensure that the BT doesn't get reset, but that the wifi does.

However my further test results raise some questions.
If I have  BT active and pulse the reset for 1ms (using mdelay(1)), the wifi
doesn't initialise.  I get ETIMEDOUT from mmc_send_io_op_cond.
I need to increase the delay to mdelay(10) before that error goes away.

With that in place the wifi seems to work, but I get regular

  Bluetooth: hci0 hardware error 0x37

errors.  So I'm guessing that tying the two reset lines together might not
have been such a good idea.  I don't know yet how that actually affect any
active bluetooth session.

Even with the 10ms delay I do sometimes get errors ... I think.  I only have
concrete evidence when I was testing with "mmc_delay(1)" which in practice
appears to often delay for 10ms or more, probably due to the cond_resched();

However I sometimes got messages like:

[ 5349.438903] mmc1: queuing unknown CIS tuple 0x36 (1 bytes)
[ 5349.502868] mmc1: queuing unknown CIS tuple 0x0c (97 bytes)
[ 5349.518737] mmc1: queuing unknown CIS tuple 0x01 (16 bytes)

If I still get these with the more reliable mdelay(), I'm leaning towards simply trying
sdio_init_card() within mmc_sdio_power_restore().  The errors occur less than 1% of the
time, so this might be effective.

With respect to the current patch, this all simply means that a 10ms down
pulse on the reset is needed.  You currently have mmc_delay(10) in the and
that should be sufficient.  mmc_delay() may take longer than the requested
time, but should never take less time.

I had thought that a strict upper limit on the pulse might be important for
BT.  It seems that I cannot leave BT completely unaffected but, on my device
at least, holding reset low whenever wifi is not enabled would not be good as
it would break BT.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 811 bytes
Desc: OpenPGP digital signature
URL: <http://lists.goldelico.com/pipermail/gta04-owner/attachments/20150207/9d0c0762/attachment.asc>

More information about the Gta04-owner mailing list