diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 0dc905b..f12d65a 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -136,7 +136,8 @@ static const struct sdhci_pci_fixes sdhci_ene_712 = { static const struct sdhci_pci_fixes sdhci_ene_714 = { .quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE | SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS | - SDHCI_QUIRK_BROKEN_DMA, + SDHCI_QUIRK_BROKEN_DMA | + SDHCI_QUIRK_1BIT_INTERRUPT, }; static const struct sdhci_pci_fixes sdhci_cafe = { diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9e15f41..d46248f 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -245,6 +245,21 @@ static void sdhci_led_control(struct led_classdev *led, } #endif +/* handle bus case where controller cannot detect CIRQ reliably when in 4-bit mode */ +static void sdhci_idle_bus_adjust(struct sdhci_host *host, u8 idle) +{ + u8 ctrl; + if ((host->flags & SDHCI_IN_4BIT_MODE) && (host->quirks & SDHCI_QUIRK_1BIT_INTERRUPT)){ + /* while bus is idle, leave it in 1-bit mode at the controller level */ + ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); + ctrl &= ~SDHCI_CTRL_4BITBUS; + if (!idle) { + ctrl |= SDHCI_CTRL_4BITBUS; + } + writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); + } +} + /*****************************************************************************\ * * * Core functions * @@ -892,7 +907,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) WARN_ON(host->cmd); /* Wait max 10 ms */ - timeout = 10; + timeout = (10*256) + 255; mask = SDHCI_CMD_INHIBIT; if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) @@ -913,11 +928,14 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) return; } timeout--; - mdelay(1); + if (!(timeout & 0xFF)) + mdelay(1); } mod_timer(&host->timer, jiffies + 10 * HZ); + sdhci_idle_bus_adjust(host, 0); + host->cmd = cmd; sdhci_prepare_data(host, cmd->data); @@ -1205,10 +1223,13 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } else { if (host->version >= SDHCI_SPEC_300) ctrl &= ~SDHCI_CTRL_8BITBUS; - if (ios->bus_width == MMC_BUS_WIDTH_4) + if (ios->bus_width == MMC_BUS_WIDTH_4) { ctrl |= SDHCI_CTRL_4BITBUS; - else + host->flags |= SDHCI_IN_4BIT_MODE; + } else { ctrl &= ~SDHCI_CTRL_4BITBUS; + host->flags &= ~SDHCI_IN_4BIT_MODE; + } } sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); } @@ -1370,6 +1391,8 @@ static void sdhci_tasklet_finish(unsigned long param) host->cmd = NULL; host->data = NULL; + sdhci_idle_bus_adjust(host, 1); + #ifndef SDHCI_USE_LEDS_CLASS sdhci_deactivate_led(host); #endif @@ -1615,8 +1638,11 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) intmask &= ~SDHCI_INT_BUS_POWER; - if (intmask & SDHCI_INT_CARD_INT) - cardint = 1; + if (intmask & SDHCI_INT_CARD_INT) { + if (readl(host->ioaddr + SDHCI_INT_ENABLE) & SDHCI_INT_CARD_INT) { + cardint = 1; + } + } intmask &= ~SDHCI_INT_CARD_INT; @@ -1949,14 +1975,11 @@ int sdhci_add_host(struct sdhci_host *host) * of bytes. When doing hardware scatter/gather, each entry cannot * be larger than 64 KiB though. */ - if (host->flags & SDHCI_USE_ADMA) { - if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) - mmc->max_seg_size = 65535; - else - mmc->max_seg_size = 65536; - } else { + if (host->flags & SDHCI_USE_ADMA) + mmc->max_seg_size = 65536; + else mmc->max_seg_size = mmc->max_req_size; - } + /* * Maximum block size. This varies from controller to controller and struct wireless_dev * diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 83bd9f7..73bfc3f 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -84,7 +84,7 @@ struct sdhci_host { /* Controller doesn't have HISPD bit field in HI-SPEED SD card */ #define SDHCI_QUIRK_NO_HISPD_BIT (1<<29) /* Controller treats ADMA descriptors with length 0000h incorrectly */ -#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1<<30) +#define SDHCI_QUIRK_1BIT_INTERRUPT (1<<30) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ @@ -109,6 +109,8 @@ struct sdhci_host { #define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */ #define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */ #define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */ +#define SDHCI_IN_4BIT_MODE (1<<4) /* bus is in 4-bit mode */ + unsigned int version; /* SDHCI spec. version */