Package: linux-2.6 Version: 2.6.26~rc4-1~experimental.1 Severity: normal This diff was extracted from OLPC branch. Without it, MMC cards are not detected.
I'm not setting the patch tag since the last hunks look like a kludge (specially the off-by-one thing). Putting Andres Salomon on CC, as he probably knows about the reasons this was added. -- System Information: Debian Release: lenny/sid APT prefers testing APT policy: (500, 'testing') Architecture: i386 (i586) Kernel: Linux 2.6.26-rc4-486 Locale: LANG=ca_AD.UTF-8, LC_CTYPE=ca_AD.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 91ded3e..43a6c2b 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -237,6 +237,12 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) if (brq.data.blocks > card->host->max_blk_count) brq.data.blocks = card->host->max_blk_count; + if (mmc_card_sd(card) && !card->host->ios.clock) { + printk(KERN_ERR "%s: I/O to stopped card\n", + req->rq_disk->disk_name); + goto cmd_err; + } + /* * If the host doesn't support multiple block writes, force * block writes to single block. SD cards are excepted from diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 07c2048..9ac2c2b 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -469,6 +469,12 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) break; } + /* + * There's an off-by-one error in the hw that we need to + * compensate for. + */ + count++; + if (count >= 0xF) { printk(KERN_WARNING "%s: Too large timeout requested!\n", mmc_hostname(host->mmc)); @@ -756,19 +762,17 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); - pwr = SDHCI_POWER_ON; - switch (1 << power) { case MMC_VDD_165_195: - pwr |= SDHCI_POWER_180; + pwr = SDHCI_POWER_180; break; case MMC_VDD_29_30: case MMC_VDD_30_31: - pwr |= SDHCI_POWER_300; + pwr = SDHCI_POWER_300; break; case MMC_VDD_32_33: case MMC_VDD_33_34: - pwr |= SDHCI_POWER_330; + pwr = SDHCI_POWER_330; break; default: BUG(); @@ -776,6 +780,10 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL); + pwr |= SDHCI_POWER_ON; + + writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL); + out: host->power = power; }