mmc: Fixes for Dual Data Rate (DDR) support

The DDR support patch needs the following fixes:

- The block driver does not need to know about DDR, any more
  than it needs to know about bus width.
- Not only the card must be switched to DDR mode.  The host
  controller must also be configured, which is done through
  the 'set_ios()' function.
- Do not set the DDR mode state until after the switch command
  is successful.
- Setting block length is not supported in DDR mode.  Make that
  a core function and change the other place it is used (mmc_test)
  also.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
Adrian Hunter
2010-08-24 13:20:26 +03:00
committed by Chris Ball
parent dfc13e8402
commit 0f8d8ea64e
8 changed files with 53 additions and 42 deletions

View File

@@ -650,13 +650,22 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
mmc_set_ios(host);
}
/*
* Change data bus width and DDR mode of a host.
*/
void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, int ddr)
{
host->ios.bus_width = width;
host->ios.ddr = ddr ? MMC_DDR_MODE : MMC_SDR_MODE;
mmc_set_ios(host);
}
/*
* Change data bus width of a host.
*/
void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
{
host->ios.bus_width = width;
mmc_set_ios(host);
mmc_set_bus_width_ddr(host, width, 0);
}
/**
@@ -1399,6 +1408,21 @@ int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
}
EXPORT_SYMBOL(mmc_erase_group_aligned);
int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
{
struct mmc_command cmd;
if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
return 0;
memset(&cmd, 0, sizeof(struct mmc_command));
cmd.opcode = MMC_SET_BLOCKLEN;
cmd.arg = blocklen;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
return mmc_wait_for_cmd(card->host, &cmd, 5);
}
EXPORT_SYMBOL(mmc_set_blocklen);
void mmc_rescan(struct work_struct *work)
{
struct mmc_host *host =