mmc: require explicit support for high-speed
The new high-speed timings are similar to each other and the old system, but not identical. And although things "just work" most of the time, sometimes it does not. So we need to start marking which hosts are known to fully comply with the new timings. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
This commit is contained in:
parent
c5f93cf19d
commit
cd9277c011
|
@ -376,10 +376,11 @@ static inline void mmc_set_ios(struct mmc_host *host)
|
||||||
{
|
{
|
||||||
struct mmc_ios *ios = &host->ios;
|
struct mmc_ios *ios = &host->ios;
|
||||||
|
|
||||||
pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
|
pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
|
||||||
|
"width %u timing %u\n",
|
||||||
mmc_hostname(host), ios->clock, ios->bus_mode,
|
mmc_hostname(host), ios->clock, ios->bus_mode,
|
||||||
ios->power_mode, ios->chip_select, ios->vdd,
|
ios->power_mode, ios->chip_select, ios->vdd,
|
||||||
ios->bus_width);
|
ios->bus_width, ios->timing);
|
||||||
|
|
||||||
host->ops->set_ios(host, ios);
|
host->ops->set_ios(host, ios);
|
||||||
}
|
}
|
||||||
|
@ -809,6 +810,7 @@ static void mmc_power_up(struct mmc_host *host)
|
||||||
host->ios.chip_select = MMC_CS_DONTCARE;
|
host->ios.chip_select = MMC_CS_DONTCARE;
|
||||||
host->ios.power_mode = MMC_POWER_UP;
|
host->ios.power_mode = MMC_POWER_UP;
|
||||||
host->ios.bus_width = MMC_BUS_WIDTH_1;
|
host->ios.bus_width = MMC_BUS_WIDTH_1;
|
||||||
|
host->ios.timing = MMC_TIMING_LEGACY;
|
||||||
mmc_set_ios(host);
|
mmc_set_ios(host);
|
||||||
|
|
||||||
mmc_delay(1);
|
mmc_delay(1);
|
||||||
|
@ -828,6 +830,7 @@ static void mmc_power_off(struct mmc_host *host)
|
||||||
host->ios.chip_select = MMC_CS_DONTCARE;
|
host->ios.chip_select = MMC_CS_DONTCARE;
|
||||||
host->ios.power_mode = MMC_POWER_OFF;
|
host->ios.power_mode = MMC_POWER_OFF;
|
||||||
host->ios.bus_width = MMC_BUS_WIDTH_1;
|
host->ios.bus_width = MMC_BUS_WIDTH_1;
|
||||||
|
host->ios.timing = MMC_TIMING_LEGACY;
|
||||||
mmc_set_ios(host);
|
mmc_set_ios(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1112,46 +1115,50 @@ static void mmc_process_ext_csds(struct mmc_host *host)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Activate highspeed support. */
|
if (host->caps & MMC_CAP_MMC_HIGHSPEED) {
|
||||||
cmd.opcode = MMC_SWITCH;
|
/* Activate highspeed support. */
|
||||||
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
|
cmd.opcode = MMC_SWITCH;
|
||||||
(EXT_CSD_HS_TIMING << 16) |
|
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
|
||||||
(1 << 8) |
|
(EXT_CSD_HS_TIMING << 16) |
|
||||||
EXT_CSD_CMD_SET_NORMAL;
|
(1 << 8) |
|
||||||
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
EXT_CSD_CMD_SET_NORMAL;
|
||||||
|
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
||||||
|
|
||||||
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
|
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
|
||||||
if (err != MMC_ERR_NONE) {
|
if (err != MMC_ERR_NONE) {
|
||||||
printk("%s: failed to switch card to mmc v4 "
|
printk("%s: failed to switch card to mmc v4 "
|
||||||
"high-speed mode.\n",
|
"high-speed mode.\n",
|
||||||
mmc_hostname(card->host));
|
mmc_hostname(card->host));
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
mmc_card_set_highspeed(card);
|
||||||
|
|
||||||
|
host->ios.timing = MMC_TIMING_SD_HS;
|
||||||
|
mmc_set_ios(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
mmc_card_set_highspeed(card);
|
|
||||||
|
|
||||||
/* Check for host support for wide-bus modes. */
|
/* Check for host support for wide-bus modes. */
|
||||||
if (!(host->caps & MMC_CAP_4_BIT_DATA)) {
|
if (host->caps & MMC_CAP_4_BIT_DATA) {
|
||||||
continue;
|
/* Activate 4-bit support. */
|
||||||
|
cmd.opcode = MMC_SWITCH;
|
||||||
|
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
|
||||||
|
(EXT_CSD_BUS_WIDTH << 16) |
|
||||||
|
(EXT_CSD_BUS_WIDTH_4 << 8) |
|
||||||
|
EXT_CSD_CMD_SET_NORMAL;
|
||||||
|
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
||||||
|
|
||||||
|
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
|
||||||
|
if (err != MMC_ERR_NONE) {
|
||||||
|
printk("%s: failed to switch card to "
|
||||||
|
"mmc v4 4-bit bus mode.\n",
|
||||||
|
mmc_hostname(card->host));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
host->ios.bus_width = MMC_BUS_WIDTH_4;
|
||||||
|
mmc_set_ios(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Activate 4-bit support. */
|
|
||||||
cmd.opcode = MMC_SWITCH;
|
|
||||||
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
|
|
||||||
(EXT_CSD_BUS_WIDTH << 16) |
|
|
||||||
(EXT_CSD_BUS_WIDTH_4 << 8) |
|
|
||||||
EXT_CSD_CMD_SET_NORMAL;
|
|
||||||
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
|
||||||
|
|
||||||
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
|
|
||||||
if (err != MMC_ERR_NONE) {
|
|
||||||
printk("%s: failed to switch card to "
|
|
||||||
"mmc v4 4-bit bus mode.\n",
|
|
||||||
mmc_hostname(card->host));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
host->ios.bus_width = MMC_BUS_WIDTH_4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(ext_csd);
|
kfree(ext_csd);
|
||||||
|
@ -1241,6 +1248,9 @@ static void mmc_read_switch_caps(struct mmc_host *host)
|
||||||
unsigned char *status;
|
unsigned char *status;
|
||||||
struct scatterlist sg;
|
struct scatterlist sg;
|
||||||
|
|
||||||
|
if (!(host->caps & MMC_CAP_SD_HIGHSPEED))
|
||||||
|
return;
|
||||||
|
|
||||||
status = kmalloc(64, GFP_KERNEL);
|
status = kmalloc(64, GFP_KERNEL);
|
||||||
if (!status) {
|
if (!status) {
|
||||||
printk(KERN_WARNING "%s: Unable to allocate buffer for "
|
printk(KERN_WARNING "%s: Unable to allocate buffer for "
|
||||||
|
@ -1332,6 +1342,9 @@ static void mmc_read_switch_caps(struct mmc_host *host)
|
||||||
}
|
}
|
||||||
|
|
||||||
mmc_card_set_highspeed(card);
|
mmc_card_set_highspeed(card);
|
||||||
|
|
||||||
|
host->ios.timing = MMC_TIMING_SD_HS;
|
||||||
|
mmc_set_ios(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(status);
|
kfree(status);
|
||||||
|
|
|
@ -606,7 +606,6 @@ static void sdhci_finish_command(struct sdhci_host *host)
|
||||||
static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
|
static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
|
||||||
{
|
{
|
||||||
int div;
|
int div;
|
||||||
u8 ctrl;
|
|
||||||
u16 clk;
|
u16 clk;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
|
@ -615,13 +614,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
|
||||||
|
|
||||||
writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
|
writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
|
||||||
|
|
||||||
ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
|
|
||||||
if (clock > 25000000)
|
|
||||||
ctrl |= SDHCI_CTRL_HISPD;
|
|
||||||
else
|
|
||||||
ctrl &= ~SDHCI_CTRL_HISPD;
|
|
||||||
writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
|
|
||||||
|
|
||||||
if (clock == 0)
|
if (clock == 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -761,10 +753,17 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||||
sdhci_set_power(host, ios->vdd);
|
sdhci_set_power(host, ios->vdd);
|
||||||
|
|
||||||
ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
|
ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
|
||||||
|
|
||||||
if (ios->bus_width == MMC_BUS_WIDTH_4)
|
if (ios->bus_width == MMC_BUS_WIDTH_4)
|
||||||
ctrl |= SDHCI_CTRL_4BITBUS;
|
ctrl |= SDHCI_CTRL_4BITBUS;
|
||||||
else
|
else
|
||||||
ctrl &= ~SDHCI_CTRL_4BITBUS;
|
ctrl &= ~SDHCI_CTRL_4BITBUS;
|
||||||
|
|
||||||
|
if (ios->timing == MMC_TIMING_SD_HS)
|
||||||
|
ctrl |= SDHCI_CTRL_HISPD;
|
||||||
|
else
|
||||||
|
ctrl &= ~SDHCI_CTRL_HISPD;
|
||||||
|
|
||||||
writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
|
writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
|
||||||
|
|
||||||
mmiowb();
|
mmiowb();
|
||||||
|
@ -1274,6 +1273,9 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
|
||||||
mmc->f_max = host->max_clk;
|
mmc->f_max = host->max_clk;
|
||||||
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
|
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
|
||||||
|
|
||||||
|
if (caps & SDHCI_CAN_DO_HISPD)
|
||||||
|
mmc->caps |= MMC_CAP_SD_HIGHSPEED;
|
||||||
|
|
||||||
mmc->ocr_avail = 0;
|
mmc->ocr_avail = 0;
|
||||||
if (caps & SDHCI_CAN_VDD_330)
|
if (caps & SDHCI_CAN_VDD_330)
|
||||||
mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
|
mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
|
||||||
|
@ -1282,13 +1284,6 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
|
||||||
if (caps & SDHCI_CAN_VDD_180)
|
if (caps & SDHCI_CAN_VDD_180)
|
||||||
mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
|
mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
|
||||||
|
|
||||||
if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) {
|
|
||||||
printk(KERN_ERR "%s: Controller reports > 25 MHz base clock,"
|
|
||||||
" but no high speed support.\n",
|
|
||||||
host->slot_descr);
|
|
||||||
mmc->f_max = 25000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mmc->ocr_avail == 0) {
|
if (mmc->ocr_avail == 0) {
|
||||||
printk(KERN_ERR "%s: Hardware doesn't report any "
|
printk(KERN_ERR "%s: Hardware doesn't report any "
|
||||||
"support voltages.\n", host->slot_descr);
|
"support voltages.\n", host->slot_descr);
|
||||||
|
|
|
@ -62,6 +62,12 @@ struct mmc_ios {
|
||||||
|
|
||||||
#define MMC_BUS_WIDTH_1 0
|
#define MMC_BUS_WIDTH_1 0
|
||||||
#define MMC_BUS_WIDTH_4 2
|
#define MMC_BUS_WIDTH_4 2
|
||||||
|
|
||||||
|
unsigned char timing; /* timing specification used */
|
||||||
|
|
||||||
|
#define MMC_TIMING_LEGACY 0
|
||||||
|
#define MMC_TIMING_MMC_HS 1
|
||||||
|
#define MMC_TIMING_SD_HS 2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mmc_host_ops {
|
struct mmc_host_ops {
|
||||||
|
@ -87,6 +93,8 @@ struct mmc_host {
|
||||||
#define MMC_CAP_4_BIT_DATA (1 << 0) /* Can the host do 4 bit transfers */
|
#define MMC_CAP_4_BIT_DATA (1 << 0) /* Can the host do 4 bit transfers */
|
||||||
#define MMC_CAP_MULTIWRITE (1 << 1) /* Can accurately report bytes sent to card on error */
|
#define MMC_CAP_MULTIWRITE (1 << 1) /* Can accurately report bytes sent to card on error */
|
||||||
#define MMC_CAP_BYTEBLOCK (1 << 2) /* Can do non-log2 block sizes */
|
#define MMC_CAP_BYTEBLOCK (1 << 2) /* Can do non-log2 block sizes */
|
||||||
|
#define MMC_CAP_MMC_HIGHSPEED (1 << 3) /* Can do MMC high-speed timing */
|
||||||
|
#define MMC_CAP_SD_HIGHSPEED (1 << 4) /* Can do SD high-speed timing */
|
||||||
|
|
||||||
/* host specific block data */
|
/* host specific block data */
|
||||||
unsigned int max_seg_size; /* see blk_queue_max_segment_size */
|
unsigned int max_seg_size; /* see blk_queue_max_segment_size */
|
||||||
|
|
Loading…
Reference in a new issue