From 06c1a121805d7870abbf037d3ccd9a609a5219f2 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 12 Oct 2012 14:01:50 +0100 Subject: ARM: 7551/1: mmc: mmci: Fix incorrect handling of HW flow control for SDIO For data writes <= 8 bytes, HW flow control was disabled but never re-enabled when the transfer was completed. This meant that a following read request would give buffer overrun errors. Signed-off-by: Ulf Hansson Acked-by: Linus Walleij Acked-by: Johan Rudholm Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'drivers/mmc/host') diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index edc3e9baf0e..877079e778c 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -654,9 +654,29 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) /* The ST Micro variants has a special bit to enable SDIO */ if (variant->sdio && host->mmc->card) - if (mmc_card_sdio(host->mmc->card)) + if (mmc_card_sdio(host->mmc->card)) { + /* + * The ST Micro variants has a special bit + * to enable SDIO. + */ + u32 clk; + datactrl |= MCI_ST_DPSM_SDIOEN; + /* + * The ST Micro variant for SDIO transfer sizes + * less then 8 bytes should have clock H/W flow + * control disabled. + */ + if ((host->size < 8) && + (data->flags & MMC_DATA_WRITE)) + clk = host->clk_reg & ~variant->clkreg_enable; + else + clk = host->clk_reg | variant->clkreg_enable; + + mmci_write_clkreg(host, clk); + } + /* * Attempt to use DMA operation mode, if this * should fail, fall back to PIO mode @@ -876,22 +896,6 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem variant->fifosize : variant->fifohalfsize; count = min(remain, maxcnt); - /* - * The ST Micro variant for SDIO transfer sizes - * less then 8 bytes should have clock H/W flow - * control disabled. - */ - if (variant->sdio && - mmc_card_sdio(host->mmc->card)) { - u32 clk; - if (count < 8) - clk = host->clk_reg & ~variant->clkreg_enable; - else - clk = host->clk_reg | variant->clkreg_enable; - - mmci_write_clkreg(host, clk); - } - /* * SDIO especially may want to send something that is * not divisible by 4 (as opposed to card sectors -- cgit v1.2.3-18-g5258 From 70ac09358cc52f3ddbf73555dc150d486a7133bb Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 12 Oct 2012 14:07:36 +0100 Subject: ARM: 7552/1: mmc: mmci: Switching off HWFC for SDIO depends on MCLK For writes, HWFC shall be switched off when transfer size <= 8 bytes and when MCLK rate is above 50 MHz. For 50MHz and below it shall be switched off when transfer size < 8 bytes. Signed-off-by: Ulf Hansson Acked-by: Linus Walleij Acked-by: Johan Rudholm Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/mmc/host') diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 877079e778c..cd0fbee0b1c 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -664,12 +664,14 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) datactrl |= MCI_ST_DPSM_SDIOEN; /* - * The ST Micro variant for SDIO transfer sizes - * less then 8 bytes should have clock H/W flow - * control disabled. + * The ST Micro variant for SDIO small write transfers + * needs to have clock H/W flow control disabled, + * otherwise the transfer will not start. The threshold + * depends on the rate of MCLK. */ - if ((host->size < 8) && - (data->flags & MMC_DATA_WRITE)) + if (data->flags & MMC_DATA_WRITE && + (host->size < 8 || + (host->size <= 8 && host->mclk > 50000000))) clk = host->clk_reg & ~variant->clkreg_enable; else clk = host->clk_reg | variant->clkreg_enable; -- cgit v1.2.3-18-g5258 From a9a83785def8bf9142b37c86ffcb0fdc93fb851e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 29 Oct 2012 14:39:30 +0100 Subject: ARM: 7562/2: MMCI: fetch pinctrl handle and set default state This fetches the pinctrl resource for the MMCI driver, and if a "default" state is found, it is activated. Acked-by: Ulf Hansson Signed-off-by: Linus Walleij Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 18 ++++++++++++++++++ drivers/mmc/host/mmci.h | 4 ++++ 2 files changed, 22 insertions(+) (limited to 'drivers/mmc/host') diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index cd0fbee0b1c..9446c176e74 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -1366,6 +1367,23 @@ static int __devinit mmci_probe(struct amba_device *dev, mmc->f_max = min(host->mclk, fmax); dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); + host->pinctrl = devm_pinctrl_get(&dev->dev); + if (IS_ERR(host->pinctrl)) { + ret = PTR_ERR(host->pinctrl); + goto clk_disable; + } + + host->pins_default = pinctrl_lookup_state(host->pinctrl, + PINCTRL_STATE_DEFAULT); + + /* enable pins to be muxed in and configured */ + if (!IS_ERR(host->pins_default)) { + ret = pinctrl_select_state(host->pinctrl, host->pins_default); + if (ret) + dev_warn(&dev->dev, "could not set default pins\n"); + } else + dev_warn(&dev->dev, "could not get default pinstate\n"); + #ifdef CONFIG_REGULATOR /* If we're using the regulator framework, try to fetch a regulator */ host->vcc = regulator_get(&dev->dev, "vmmc"); diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index d437ccf62d6..d34d8c0add8 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -195,6 +195,10 @@ struct mmci_host { unsigned int size; struct regulator *vcc; + /* pinctrl handles */ + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + #ifdef CONFIG_DMA_ENGINE /* DMA stuff */ struct dma_chan *dma_current; -- cgit v1.2.3-18-g5258 From 4b85da08c4d19f5de48d904d4f879dcfa04ec14c Mon Sep 17 00:00:00 2001 From: Davide Ciminaghi Date: Mon, 10 Dec 2012 14:47:21 +0100 Subject: ARM: 7596/1: mmci: replace readsl/writesl with ioread32_rep/iowrite32_rep Not all the architectures have readsl/writesl, use the more portable ioread32_rep/iowrite32_rep functions instead. Signed-off-by: Davide Ciminaghi Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/mmc/host') diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 9446c176e74..5e39b312c7c 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -863,14 +863,14 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema if (unlikely(count & 0x3)) { if (count < 4) { unsigned char buf[4]; - readsl(base + MMCIFIFO, buf, 1); + ioread32_rep(base + MMCIFIFO, buf, 1); memcpy(ptr, buf, count); } else { - readsl(base + MMCIFIFO, ptr, count >> 2); + ioread32_rep(base + MMCIFIFO, ptr, count >> 2); count &= ~0x3; } } else { - readsl(base + MMCIFIFO, ptr, count >> 2); + ioread32_rep(base + MMCIFIFO, ptr, count >> 2); } ptr += count; @@ -907,7 +907,7 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem * byte become a 32bit write, 7 bytes will be two * 32bit writes etc. */ - writesl(base + MMCIFIFO, ptr, (count + 3) >> 2); + iowrite32_rep(base + MMCIFIFO, ptr, (count + 3) >> 2); ptr += count; remain -= count; -- cgit v1.2.3-18-g5258