sdio: recognize io card without powercycle
SDIO Simplified Specification V2.00 states that it is strongly recommended that the host executes either a power reset or issues a CMD52 (I/O Reset) to re-initialize an I/O only card or the I/O portion of a combo card. Additionally, the CMD52 must be issued first because it cannot be issued after a CMD0. With this patch the Nintendo Wii SDIO-based WLAN card is detected after a system reset, without requiring a complete system powercycle. Signed-off-by: Albert Herranz <albert_herranz@yahoo.es> Cc: <linux-mmc@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
committed by
Linus Torvalds
parent
d0ab4a4d50
commit
516a824222
@@ -1089,6 +1089,7 @@ void mmc_rescan(struct work_struct *work)
|
|||||||
mmc_claim_host(host);
|
mmc_claim_host(host);
|
||||||
|
|
||||||
mmc_power_up(host);
|
mmc_power_up(host);
|
||||||
|
sdio_reset(host);
|
||||||
mmc_go_idle(host);
|
mmc_go_idle(host);
|
||||||
|
|
||||||
mmc_send_if_cond(host, host->ocr_avail);
|
mmc_send_if_cond(host, host->ocr_avail);
|
||||||
|
@@ -67,13 +67,13 @@ int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
|
static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn,
|
||||||
unsigned addr, u8 in, u8 *out)
|
unsigned addr, u8 in, u8 *out)
|
||||||
{
|
{
|
||||||
struct mmc_command cmd;
|
struct mmc_command cmd;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
BUG_ON(!card);
|
BUG_ON(!host);
|
||||||
BUG_ON(fn > 7);
|
BUG_ON(fn > 7);
|
||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
@@ -90,11 +90,11 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
|
|||||||
cmd.arg |= in;
|
cmd.arg |= in;
|
||||||
cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC;
|
cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC;
|
||||||
|
|
||||||
err = mmc_wait_for_cmd(card->host, &cmd, 0);
|
err = mmc_wait_for_cmd(host, &cmd, 0);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (mmc_host_is_spi(card->host)) {
|
if (mmc_host_is_spi(host)) {
|
||||||
/* host driver already reported errors */
|
/* host driver already reported errors */
|
||||||
} else {
|
} else {
|
||||||
if (cmd.resp[0] & R5_ERROR)
|
if (cmd.resp[0] & R5_ERROR)
|
||||||
@@ -106,7 +106,7 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (out) {
|
if (out) {
|
||||||
if (mmc_host_is_spi(card->host))
|
if (mmc_host_is_spi(host))
|
||||||
*out = (cmd.resp[0] >> 8) & 0xFF;
|
*out = (cmd.resp[0] >> 8) & 0xFF;
|
||||||
else
|
else
|
||||||
*out = cmd.resp[0] & 0xFF;
|
*out = cmd.resp[0] & 0xFF;
|
||||||
@@ -115,6 +115,13 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
|
||||||
|
unsigned addr, u8 in, u8 *out)
|
||||||
|
{
|
||||||
|
BUG_ON(!card);
|
||||||
|
return mmc_io_rw_direct_host(card->host, write, fn, addr, in, out);
|
||||||
|
}
|
||||||
|
|
||||||
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
|
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
|
||||||
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
|
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
|
||||||
{
|
{
|
||||||
@@ -182,3 +189,20 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sdio_reset(struct mmc_host *host)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u8 abort;
|
||||||
|
|
||||||
|
/* SDIO Simplified Specification V2.0, 4.4 Reset for SDIO */
|
||||||
|
|
||||||
|
ret = mmc_io_rw_direct_host(host, 0, 0, SDIO_CCCR_ABORT, 0, &abort);
|
||||||
|
if (ret)
|
||||||
|
abort = 0x08;
|
||||||
|
else
|
||||||
|
abort |= 0x08;
|
||||||
|
|
||||||
|
ret = mmc_io_rw_direct_host(host, 1, 0, SDIO_CCCR_ABORT, abort, NULL);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -17,6 +17,7 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
|
|||||||
unsigned addr, u8 in, u8* out);
|
unsigned addr, u8 in, u8* out);
|
||||||
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
|
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
|
||||||
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz);
|
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz);
|
||||||
|
int sdio_reset(struct mmc_host *host);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user