libertas_sdio doesn't work after reloading
Dan Williams
dcbw at redhat.com
Tue Feb 3 14:44:58 EST 2009
On Tue, 2009-02-03 at 14:27 -0500, Dan Williams wrote:
> On Tue, 2009-02-03 at 11:09 -0800, Matt Reimer wrote:
> > On Tue, Feb 3, 2009 at 7:42 AM, Dan Williams <dcbw at redhat.com> wrote:
> > > On Tue, 2009-02-03 at 11:20 +0000, Jonathan Cameron wrote:
> > >> Matt Reimer wrote:
> > >> > On Mon, Feb 2, 2009 at 1:58 PM, Andrey Yurovsky <andrey at cozybit.com> wrote:
> > >> >> Hi Matt. Is this on an embedded system or on a desktop PC with some
> > >> >> host controller? If so, which one? I'm curious because module reload
> > >> >> seems to work fine with my Ricoh host controller.
> > >> >
> > >> > This is on an embedded system, using the SD controller on a pxa320.
> > >> >
> > >> > Matt
> > >> >
> > >> I ran into exactly the same issue with a pxa271 board, but never figured
> > >> out what was going on. Very interested to hear if you do!
> > >
> > > The only method I have found to reset the libertas chip is to pull the
> > > power from the card or unplug it. There hasn't been any other method
> > > that we can figure out to hard-reset the card, either with SDIO commands
> > > or with CMD_802_11_RESET. I'd be quite interested if anyone found a
> > > mechanism for doing a full reset while the card's plugged in.
> >
> > Do you think the problem could be that after reset the libertas chip
> > is talking to the controller at the wrong bus speed and bus width?
>
> It could well be. Pierre, I and Philip Rakity are having a side
> conversation right now about this sort of thing. Let me see if Philip
> would mind if I pasted in his debugging patch for that. Basically,
> issue an SDIO ABORT/reset during MMC bus rescan. That could kick the
> card hard enough for it to be re-enumerated and take firmware upload
> again.
Philip's patch is below. The mmc/core/core.c stuff doesn't apply
directly any more, but the function getting patched is mmc_rescan() as
far as I can tell. Give it a shot and see if it helps you.
Pierre tried something similar a while ago but noticed problems with the
cards getting wedged because they saw the SDIO ABORT on the bus before
being fully enumerated, or something like that.
Dan
diff -Nur linux-2.6.22.18-feroceon_4_1_4_KW/drivers/mmc/core/core.c inux-2.6.22.18-feroceon_4_1_4_KW-PATCHED/drivers/mmc/core/core.c
--- linux-2.6.22.18-feroceon_4_1_4_KW/drivers/mmc/core/core.c 2008-11-13 02:55:47.000000000 -0800
+++ inux-2.6.22.18-feroceon_4_1_4_KW-PATCHED/drivers/mmc/core/core.c 2009-01-20 13:14:31.000000000 -0800
@@ -659,6 +659,10 @@
host->mode = MMC_MODE_SDIO;
mmc_set_ios(host);
+
+ /* reset sdio hardware */
+ mmc_force_reset(host);
+
err = mmc_send_io_op_cond(host, 0, &ocr);
if (!err) {
if (mmc_attach_sdio(host, ocr))
diff -Nur linux-2.6.22.18-feroceon_4_1_4_KW/drivers/mmc/core/mmc_ops.c inux-2.6.22.18-feroceon_4_1_4_KW-PATCHED/drivers/mmc/core/mmc_ops.c
--- linux-2.6.22.18-feroceon_4_1_4_KW/drivers/mmc/core/mmc_ops.c 2008-08-26 21:01:15.000000000 -0700
+++ inux-2.6.22.18-feroceon_4_1_4_KW-PATCHED/drivers/mmc/core/mmc_ops.c 2009-01-20 13:17:21.000000000 -0800
@@ -20,6 +20,38 @@
#include "core.h"
#include "mmc_ops.h"
+int mmc_force_reset (struct mmc_host *host)
+
+{
+ struct mmc_command cmd;
+ int err = 0;
+
+ BUG_ON(!host);
+
+#ifndef SD_IO_RW_DIRECT
+#define SD_IO_RW_DIRECT 52
+#endif
+
+#ifndef SDIO_CCCR_ABORT
+#define SDIO_CCCR_ABORT 0x06
+#endif
+
+#ifndef PMR_WRITE
+#define PMR_WRITE 1
+#endif
+
+ memset(&cmd, 0, sizeof(struct mmc_command));
+ cmd.opcode = SD_IO_RW_DIRECT;
+ cmd.arg = PMR_WRITE ? 0x80000000 : 0x00000000;
+ cmd.arg |= 0<<28;
+ cmd.arg |= 0x00000000;
+ cmd.arg |= SDIO_CCCR_ABORT << 9;
+ cmd.arg |= (1<<3) ;
+ cmd.flags = MMC_RSP_NONE;
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ return err;
+}
+
static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
{
int err;
diff -Nur linux-2.6.22.18-feroceon_4_1_4_KW/drivers/mmc/core/mmc_ops.h inux-2.6.22.18-feroceon_4_1_4_KW-PATCHED/drivers/mmc/core/mmc_ops.h
--- linux-2.6.22.18-feroceon_4_1_4_KW/drivers/mmc/core/mmc_ops.h 2008-08-26 21:01:15.000000000 -0700
+++ inux-2.6.22.18-feroceon_4_1_4_KW-PATCHED/drivers/mmc/core/mmc_ops.h 2009-01-20 13:17:30.000000000 -0800
@@ -12,6 +12,7 @@
#ifndef _MMC_MMC_OPS_H
#define _MMC_MMC_OPS_H
+int mmc_force_reset (struct mmc_host *host);
int mmc_select_card(struct mmc_card *card);
int mmc_deselect_cards(struct mmc_host *host);
int mmc_go_idle(struct mmc_host *host);
More information about the libertas-dev
mailing list