]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'mmc/mmc-next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 13 Sep 2012 03:25:51 +0000 (13:25 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 13 Sep 2012 03:25:51 +0000 (13:25 +1000)
29 files changed:
Documentation/devicetree/bindings/mmc/atmel-hsmci.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/mmc.txt
Documentation/devicetree/bindings/mmc/pxa-mmc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/sdhci-dove.txt [new file with mode: 0644]
MAINTAINERS
drivers/mmc/core/core.c
drivers/mmc/core/debugfs.c
drivers/mmc/core/slot-gpio.c
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/bfin_sdh.c
drivers/mmc/host/dw_mmc-pci.c
drivers/mmc/host/dw_mmc-pltfm.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mmc_spi.c
drivers/mmc/host/omap.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/pxamci.c
drivers/mmc/host/sdhci-dove.c
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-pxav2.c
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdhci-tegra.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/via-sdmmc.c
drivers/mmc/host/vub300.c
include/linux/mmc/host.h
include/linux/mmc/sdhci.h

diff --git a/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt b/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt
new file mode 100644 (file)
index 0000000..0a85c70
--- /dev/null
@@ -0,0 +1,68 @@
+* Atmel High Speed MultiMedia Card Interface
+
+This controller on atmel products provides an interface for MMC, SD and SDIO
+types of memory cards.
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the atmel-mci driver.
+
+1) MCI node
+
+Required properties:
+- compatible: should be "atmel,hsmci"
+- #address-cells: should be one. The cell is the slot id.
+- #size-cells: should be zero.
+- at least one slot node
+
+The node contains child nodes for each slot that the platform uses
+
+Example MCI node:
+
+mmc0: mmc@f0008000 {
+       compatible = "atmel,hsmci";
+       reg = <0xf0008000 0x600>;
+       interrupts = <12 4>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       [ child node definitions...]
+};
+
+2) slot nodes
+
+Required properties:
+- reg: should contain the slot id.
+- bus-width: number of data lines connected to the controller
+
+Optional properties:
+- cd-gpios: specify GPIOs for card detection
+- cd-inverted: invert the value of external card detect gpio line
+- wp-gpios: specify GPIOs for write protection
+
+Example slot node:
+
+slot@0 {
+       reg = <0>;
+       bus-width = <4>;
+       cd-gpios = <&pioD 15 0>
+       cd-inverted;
+};
+
+Example full MCI node:
+mmc0: mmc@f0008000 {
+       compatible = "atmel,hsmci";
+       reg = <0xf0008000 0x600>;
+       interrupts = <12 4>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+       slot@0 {
+               reg = <0>;
+               bus-width = <4>;
+               cd-gpios = <&pioD 15 0>
+               cd-inverted;
+       };
+       slot@1 {
+               reg = <1>;
+               bus-width = <4>;
+       };
+};
index 8a6811f4a02f5759e2a793506f1cef40b756e2d8..8e2e0ba2f486c57ca3505e44fa85effd369c4495 100644 (file)
@@ -9,12 +9,17 @@ Interpreted by the OF core:
 Required properties:
 - bus-width: Number of data lines, can be <1>, <4>, or <8>
 
+Card detection:
+If no property below is supplied, standard SDHCI card detect is used.
+Only one of the properties in this section should be supplied:
+  - broken-cd: There is no card detection available; polling must be used.
+  - cd-gpios: Specify GPIOs for card detection, see gpio binding
+  - non-removable: non-removable slot (like eMMC); assume always present.
+
 Optional properties:
-- cd-gpios: Specify GPIOs for card detection, see gpio binding
 - wp-gpios: Specify GPIOs for write protection, see gpio binding
 - cd-inverted: when present, polarity on the cd gpio line is inverted
 - wp-inverted: when present, polarity on the wp gpio line is inverted
-- non-removable: non-removable slot (like eMMC)
 - max-frequency: maximum operating clock frequency
 
 Example:
diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
new file mode 100644 (file)
index 0000000..b7025de
--- /dev/null
@@ -0,0 +1,25 @@
+* PXA MMC drivers
+
+Driver bindings for the PXA MCI (MMC/SDIO) interfaces
+
+Required properties:
+- compatible: Should be "marvell,pxa-mmc".
+- vmmc-supply: A regulator for VMMC
+
+Optional properties:
+- marvell,detect-delay-ms: sets the detection delay timeout in ms.
+- marvell,gpio-power: GPIO spec for the card power enable pin
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the pxa-mmc driver.
+
+Examples:
+
+mmc0: mmc@41100000 {
+       compatible = "marvell,pxa-mmc";
+       reg = <0x41100000 0x1000>;
+       interrupts = <23>;
+       cd-gpios = <&gpio 23 0>;
+       wp-gpios = <&gpio 24 0>;
+};
+
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-dove.txt b/Documentation/devicetree/bindings/mmc/sdhci-dove.txt
new file mode 100644 (file)
index 0000000..ae9aab9
--- /dev/null
@@ -0,0 +1,14 @@
+* Marvell sdhci-dove controller
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the sdhci-pxav2 and sdhci-pxav3 drivers.
+
+- compatible: Should be "marvell,dove-sdhci".
+
+Example:
+
+sdio0: sdio@92000 {
+       compatible = "marvell,dove-sdhci";
+       reg = <0x92000 0x100>;
+       interrupts = <35>;
+};
index d3ba63955b0dc02111959fe373e7cc8a7c25ebe2..7343876f0f6d52ad5155976a06d3c4f14316ee0a 100644 (file)
@@ -1523,7 +1523,7 @@ S:        Supported
 F:     drivers/rtc/rtc-bfin.c
 
 BLACKFIN SDH DRIVER
-M:     Cliff Cai <cliff.cai@analog.com>
+M:     Sonic Zhang <sonic.zhang@analog.com>
 L:     uclinux-dist-devel@blackfin.uclinux.org
 W:     http://blackfin.uclinux.org
 S:     Supported
@@ -4949,8 +4949,10 @@ S:       Maintained
 F:     drivers/mmc/host/omap.c
 
 OMAP HS MMC SUPPORT
+M:     Venkatraman S <svenkatr@ti.com>
+L:     linux-mmc@vger.kernel.org
 L:     linux-omap@vger.kernel.org
-S:     Orphan
+S:     Maintained
 F:     drivers/mmc/host/omap_hsmmc.c
 
 OMAP RANDOM NUMBER GENERATOR SUPPORT
index 8ac5246e2ab2bc85a6ba82ee0a0eab732130fdf6..af2c4d2fd69e6eb9ad24c382388a9f754cd36ebc 100644 (file)
@@ -424,8 +424,9 @@ int mmc_interrupt_hpi(struct mmc_card *card)
        case R1_STATE_IDLE:
        case R1_STATE_READY:
        case R1_STATE_STBY:
+       case R1_STATE_TRAN:
                /*
-                * In idle states, HPI is not needed and the caller
+                * In idle and transfer states, HPI is not needed and the caller
                 * can issue the next intended command immediately
                 */
                goto out;
@@ -2052,6 +2053,11 @@ void mmc_rescan(struct work_struct *work)
        if (host->rescan_disable)
                return;
 
+       /* If there is a non-removable card registered, only scan once */
+       if ((host->caps & MMC_CAP_NONREMOVABLE) && host->rescan_entered)
+               return;
+       host->rescan_entered = 1;
+
        mmc_bus_get(host);
 
        /*
index 9ab5b17d488ae45f63756a43bfe8917e88b52e86..d96c643dde1c1b38eeeeaa0504d92f2d960b4088 100644 (file)
@@ -281,7 +281,7 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
        if (err)
                goto out_free;
 
-       for (i = 511; i >= 0; i--)
+       for (i = 0; i < 512; i++)
                n += sprintf(buf + n, "%02x", ext_csd[i]);
        n += sprintf(buf + n, "\n");
        BUG_ON(n != EXT_CSD_STR_LEN);
index 058242916cef1089ee2a8a22e8901464df7f4997..08c6b3dfe080497509e9f431d0ababdc51626b29 100644 (file)
@@ -100,7 +100,13 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
 
        ctx = host->slot.handler_priv;
 
-       return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label);
+       ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label);
+       if (ret < 0)
+               return ret;
+
+       ctx->ro_gpio = gpio;
+
+       return 0;
 }
 EXPORT_SYMBOL(mmc_gpio_request_ro);
 
index a53c7c478e054c8c47df5a5a219a2b1ed1e6836b..8c72828239b21fb6064ac076a6759052bdb6dd1c 100644 (file)
@@ -19,6 +19,9 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/scatterlist.h>
 #include <linux/seq_file.h>
@@ -500,6 +503,70 @@ err:
        dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id atmci_dt_ids[] = {
+       { .compatible = "atmel,hsmci" },
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, atmci_dt_ids);
+
+static struct mci_platform_data __devinit*
+atmci_of_init(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct device_node *cnp;
+       struct mci_platform_data *pdata;
+       u32 slot_id;
+
+       if (!np) {
+               dev_err(&pdev->dev, "device node not found\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               dev_err(&pdev->dev, "could not allocate memory for pdata\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       for_each_child_of_node(np, cnp) {
+               if (of_property_read_u32(cnp, "reg", &slot_id)) {
+                       dev_warn(&pdev->dev, "reg property is missing for %s\n",
+                                cnp->full_name);
+                       continue;
+               }
+
+               if (slot_id >= ATMCI_MAX_NR_SLOTS) {
+                       dev_warn(&pdev->dev, "can't have more than %d slots\n",
+                                ATMCI_MAX_NR_SLOTS);
+                       break;
+               }
+
+               if (of_property_read_u32(cnp, "bus-width",
+                                        &pdata->slot[slot_id].bus_width))
+                       pdata->slot[slot_id].bus_width = 1;
+
+               pdata->slot[slot_id].detect_pin =
+                       of_get_named_gpio(cnp, "cd-gpios", 0);
+
+               pdata->slot[slot_id].detect_is_active_high =
+                       of_property_read_bool(cnp, "cd-inverted");
+
+               pdata->slot[slot_id].wp_pin =
+                       of_get_named_gpio(cnp, "wp-gpios", 0);
+       }
+
+       return pdata;
+}
+#else /* CONFIG_OF */
+static inline struct mci_platform_data*
+atmci_of_init(struct platform_device *dev)
+{
+       return ERR_PTR(-EINVAL);
+}
+#endif
+
 static inline unsigned int atmci_get_version(struct atmel_mci *host)
 {
        return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
@@ -2046,6 +2113,13 @@ static int __init atmci_init_slot(struct atmel_mci *host,
        slot->sdc_reg = sdc_reg;
        slot->sdio_irq = sdio_irq;
 
+       dev_dbg(&mmc->class_dev,
+               "slot[%u]: bus_width=%u, detect_pin=%d, "
+               "detect_is_active_high=%s, wp_pin=%d\n",
+               id, slot_data->bus_width, slot_data->detect_pin,
+               slot_data->detect_is_active_high ? "true" : "false",
+               slot_data->wp_pin);
+
        mmc->ops = &atmci_ops;
        mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512);
        mmc->f_max = host->bus_hz / 2;
@@ -2268,8 +2342,14 @@ static int __init atmci_probe(struct platform_device *pdev)
        if (!regs)
                return -ENXIO;
        pdata = pdev->dev.platform_data;
-       if (!pdata)
-               return -ENXIO;
+       if (!pdata) {
+               pdata = atmci_of_init(pdev);
+               if (IS_ERR(pdata)) {
+                       dev_err(&pdev->dev, "platform data not available\n");
+                       return PTR_ERR(pdata);
+               }
+       }
+
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
                return irq;
@@ -2487,6 +2567,7 @@ static struct platform_driver atmci_driver = {
        .driver         = {
                .name           = "atmel_mci",
                .pm             = ATMCI_PM_OPS,
+               .of_match_table = of_match_ptr(atmci_dt_ids),
        },
 };
 
index a17dd7363cebedc69c41d28b47b6c4fd895a327a..b9b463eca1ec64a2d608f3362ede48cd418842b6 100644 (file)
@@ -24,9 +24,7 @@
 #include <asm/portmux.h>
 #include <asm/bfin_sdh.h>
 
-#if defined(CONFIG_BF51x)
-#define bfin_read_SDH_PWR_CTL          bfin_read_RSI_PWR_CTL
-#define bfin_write_SDH_PWR_CTL         bfin_write_RSI_PWR_CTL
+#if defined(CONFIG_BF51x) || defined(__ADSPBF60x__)
 #define bfin_read_SDH_CLK_CTL          bfin_read_RSI_CLK_CTL
 #define bfin_write_SDH_CLK_CTL         bfin_write_RSI_CLK_CTL
 #define bfin_write_SDH_ARGUMENT                bfin_write_RSI_ARGUMENT
 #define bfin_write_SDH_E_STATUS                bfin_write_RSI_E_STATUS
 #define bfin_read_SDH_STATUS           bfin_read_RSI_STATUS
 #define bfin_write_SDH_MASK0           bfin_write_RSI_MASK0
+#define bfin_write_SDH_E_MASK          bfin_write_RSI_E_MASK
 #define bfin_read_SDH_CFG              bfin_read_RSI_CFG
 #define bfin_write_SDH_CFG             bfin_write_RSI_CFG
+# if defined(__ADSPBF60x__)
+#  define bfin_read_SDH_BLK_SIZE       bfin_read_RSI_BLKSZ
+#  define bfin_write_SDH_BLK_SIZE      bfin_write_RSI_BLKSZ
+# else
+#  define bfin_read_SDH_PWR_CTL                bfin_read_RSI_PWR_CTL
+#  define bfin_write_SDH_PWR_CTL       bfin_write_RSI_PWR_CTL
+# endif
 #endif
 
 struct sdh_host {
@@ -62,6 +68,7 @@ struct sdh_host {
        dma_addr_t              sg_dma;
        int                     dma_len;
 
+       unsigned long           sclk;
        unsigned int            imask;
        unsigned int            power_mode;
        unsigned int            clk_div;
@@ -127,11 +134,15 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
        /* Only supports power-of-2 block size */
        if (data->blksz & (data->blksz - 1))
                return -EINVAL;
+#ifndef RSI_BLKSZ
        data_ctl |= ((ffs(data->blksz) - 1) << 4);
+#else
+        bfin_write_SDH_BLK_SIZE(data->blksz);
+#endif
 
        bfin_write_SDH_DATA_CTL(data_ctl);
        /* the time of a host clock period in ns */
-       cycle_ns = 1000000000 / (get_sclk() / (2 * (host->clk_div + 1)));
+       cycle_ns = 1000000000 / (host->sclk / (2 * (host->clk_div + 1)));
        timeout = data->timeout_ns / cycle_ns;
        timeout += data->timeout_clks;
        bfin_write_SDH_DATA_TIMER(timeout);
@@ -145,8 +156,13 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
 
        sdh_enable_stat_irq(host, (DAT_CRC_FAIL | DAT_TIME_OUT | DAT_END));
        host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir);
-#if defined(CONFIG_BF54x)
-       dma_cfg |= DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_32 | DMAEN;
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
+       dma_cfg |= DMAFLOW_ARRAY | RESTART | WDSIZE_32 | DMAEN;
+# ifdef RSI_BLKSZ
+       dma_cfg |= PSIZE_32 | NDSIZE_3;
+# else
+       dma_cfg |= NDSIZE_5;
+# endif
        {
                struct scatterlist *sg;
                int i;
@@ -156,7 +172,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
                        host->sg_cpu[i].x_count = sg_dma_len(sg) / 4;
                        host->sg_cpu[i].x_modify = 4;
                        dev_dbg(mmc_dev(host->mmc), "%d: start_addr:0x%lx, "
-                               "cfg:0x%x, x_count:0x%x, x_modify:0x%x\n",
+                               "cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n",
                                i, host->sg_cpu[i].start_addr,
                                host->sg_cpu[i].cfg, host->sg_cpu[i].x_count,
                                host->sg_cpu[i].x_modify);
@@ -172,6 +188,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
        set_dma_curr_desc_addr(host->dma_ch, (unsigned long *)host->sg_dma);
        set_dma_x_count(host->dma_ch, 0);
        set_dma_x_modify(host->dma_ch, 0);
+       SSYNC();
        set_dma_config(host->dma_ch, dma_cfg);
 #elif defined(CONFIG_BF51x)
        /* RSI DMA doesn't work in array mode */
@@ -179,6 +196,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
        set_dma_start_addr(host->dma_ch, sg_dma_address(&data->sg[0]));
        set_dma_x_count(host->dma_ch, length / 4);
        set_dma_x_modify(host->dma_ch, 4);
+       SSYNC();
        set_dma_config(host->dma_ch, dma_cfg);
 #endif
        bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E);
@@ -296,7 +314,6 @@ static int sdh_data_done(struct sdh_host *host, unsigned int stat)
        else
                data->bytes_xfered = 0;
 
-       sdh_disable_stat_irq(host, DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN);
        bfin_write_SDH_STATUS_CLR(DAT_END_STAT | DAT_TIMEOUT_STAT | \
                        DAT_CRC_FAIL_STAT | DAT_BLK_END_STAT | RX_OVERRUN | TX_UNDERRUN);
        bfin_write_SDH_DATA_CTL(0);
@@ -321,74 +338,115 @@ static void sdh_request(struct mmc_host *mmc, struct mmc_request *mrq)
        dev_dbg(mmc_dev(host->mmc), "%s enter, mrp:%p, cmd:%p\n", __func__, mrq, mrq->cmd);
        WARN_ON(host->mrq != NULL);
 
+       spin_lock(&host->lock);
        host->mrq = mrq;
        host->data = mrq->data;
 
        if (mrq->data && mrq->data->flags & MMC_DATA_READ) {
                ret = sdh_setup_data(host, mrq->data);
                if (ret)
-                       return;
+                       goto data_err;
        }
 
        sdh_start_cmd(host, mrq->cmd);
+data_err:
+       spin_unlock(&host->lock);
 }
 
 static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct sdh_host *host;
-       unsigned long flags;
        u16 clk_ctl = 0;
+#ifndef RSI_BLKSZ
        u16 pwr_ctl = 0;
+#endif
        u16 cfg;
        host = mmc_priv(mmc);
 
-       spin_lock_irqsave(&host->lock, flags);
-       if (ios->clock) {
-               unsigned long  sys_clk, ios_clk;
-               unsigned char clk_div;
-               ios_clk = 2 * ios->clock;
-               sys_clk = get_sclk();
-               clk_div = sys_clk / ios_clk;
-               if (sys_clk % ios_clk == 0)
-                       clk_div -= 1;
-               clk_div = min_t(unsigned char, clk_div, 0xFF);
-               clk_ctl |= clk_div;
-               clk_ctl |= CLK_E;
-               host->clk_div = clk_div;
-       } else
-               sdh_stop_clock(host);
-
-       if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
-#ifdef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
-               pwr_ctl |= ROD_CTL;
-#else
-               pwr_ctl |= SD_CMD_OD | ROD_CTL;
-#endif
+       spin_lock(&host->lock);
 
-       if (ios->bus_width == MMC_BUS_WIDTH_4) {
-               cfg = bfin_read_SDH_CFG();
+       cfg = bfin_read_SDH_CFG();
+       cfg |= MWE;
+       switch (ios->bus_width) {
+       case MMC_BUS_WIDTH_4:
+#ifndef RSI_BLKSZ
                cfg &= ~PD_SDDAT3;
+#endif
                cfg |= PUP_SDDAT3;
                /* Enable 4 bit SDIO */
-               cfg |= (SD4E | MWE);
-               bfin_write_SDH_CFG(cfg);
-               clk_ctl |= WIDE_BUS;
-       } else {
-               cfg = bfin_read_SDH_CFG();
-               cfg |= MWE;
-               bfin_write_SDH_CFG(cfg);
+               cfg |= SD4E;
+               clk_ctl |= WIDE_BUS_4;
+               break;
+       case MMC_BUS_WIDTH_8:
+#ifndef RSI_BLKSZ
+               cfg &= ~PD_SDDAT3;
+#endif
+               cfg |= PUP_SDDAT3;
+               /* Disable 4 bit SDIO */
+               cfg &= ~SD4E;
+               clk_ctl |= BYTE_BUS_8;
+               break;
+       default:
+               cfg &= ~PUP_SDDAT3;
+               /* Disable 4 bit SDIO */
+               cfg &= ~SD4E;
        }
 
-       bfin_write_SDH_CLK_CTL(clk_ctl);
-
        host->power_mode = ios->power_mode;
-       if (ios->power_mode == MMC_POWER_ON)
+#ifndef RSI_BLKSZ
+       if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
+               pwr_ctl |= ROD_CTL;
+# ifndef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
+               pwr_ctl |= SD_CMD_OD;
+# endif
+       }
+
+       if (ios->power_mode != MMC_POWER_OFF)
                pwr_ctl |= PWR_ON;
+       else
+               pwr_ctl &= ~PWR_ON;
 
        bfin_write_SDH_PWR_CTL(pwr_ctl);
+#else
+# ifndef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
+       if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
+               cfg |= SD_CMD_OD;
+       else
+               cfg &= ~SD_CMD_OD;
+# endif
+
+
+       if (ios->power_mode != MMC_POWER_OFF)
+               cfg |= PWR_ON;
+       else
+               cfg &= ~PWR_ON;
+
+       bfin_write_SDH_CFG(cfg);
+#endif
        SSYNC();
 
-       spin_unlock_irqrestore(&host->lock, flags);
+       if (ios->power_mode == MMC_POWER_ON && ios->clock) {
+               unsigned char clk_div;
+               clk_div = (get_sclk() / ios->clock - 1) / 2;
+               clk_div = min_t(unsigned char, clk_div, 0xFF);
+               clk_ctl |= clk_div;
+               clk_ctl |= CLK_E;
+               host->clk_div = clk_div;
+               bfin_write_SDH_CLK_CTL(clk_ctl);
+
+       } else
+               sdh_stop_clock(host);
+
+       /* set up sdh interrupt mask*/
+       if (ios->power_mode == MMC_POWER_ON)
+               bfin_write_SDH_MASK0(DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL |
+                       RX_OVERRUN | TX_UNDERRUN | CMD_SENT | CMD_RESP_END |
+                       CMD_TIME_OUT | CMD_CRC_FAIL);
+       else
+               bfin_write_SDH_MASK0(0);
+       SSYNC();
+
+       spin_unlock(&host->lock);
 
        dev_dbg(mmc_dev(host->mmc), "SDH: clk_div = 0x%x actual clock:%ld expected clock:%d\n",
                host->clk_div,
@@ -405,7 +463,7 @@ static irqreturn_t sdh_dma_irq(int irq, void *devid)
 {
        struct sdh_host *host = devid;
 
-       dev_dbg(mmc_dev(host->mmc), "%s enter, irq_stat: 0x%04x\n", __func__,
+       dev_dbg(mmc_dev(host->mmc), "%s enter, irq_stat: 0x%04lx\n", __func__,
                get_dma_curr_irqstat(host->dma_ch));
        clear_dma_irqstat(host->dma_ch);
        SSYNC();
@@ -420,6 +478,9 @@ static irqreturn_t sdh_stat_irq(int irq, void *devid)
        int handled = 0;
 
        dev_dbg(mmc_dev(host->mmc), "%s enter\n", __func__);
+
+       spin_lock(&host->lock);
+
        status = bfin_read_SDH_E_STATUS();
        if (status & SD_CARD_DET) {
                mmc_detect_change(host->mmc, 0);
@@ -437,11 +498,30 @@ static irqreturn_t sdh_stat_irq(int irq, void *devid)
        if (status & (DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN))
                handled |= sdh_data_done(host, status);
 
+       spin_unlock(&host->lock);
+
        dev_dbg(mmc_dev(host->mmc), "%s exit\n\n", __func__);
 
        return IRQ_RETVAL(handled);
 }
 
+static void sdh_reset(void)
+{
+#if defined(CONFIG_BF54x)
+       /* Secure Digital Host shares DMA with Nand controller */
+       bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1);
+#endif
+
+       bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN);
+       SSYNC();
+
+       /* Disable card inserting detection pin. set MMC_CAP_NEEDS_POLL, and
+        * mmc stack will do the detection.
+        */
+       bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3));
+       SSYNC();
+}
+
 static int __devinit sdh_probe(struct platform_device *pdev)
 {
        struct mmc_host *mmc;
@@ -462,8 +542,16 @@ static int __devinit sdh_probe(struct platform_device *pdev)
        }
 
        mmc->ops = &sdh_ops;
-       mmc->max_segs = 32;
+#if defined(CONFIG_BF51x)
+       mmc->max_segs = 1;
+#else
+       mmc->max_segs = PAGE_SIZE / sizeof(struct dma_desc_array);
+#endif
+#ifdef RSI_BLKSZ
+       mmc->max_seg_size = -1;
+#else
        mmc->max_seg_size = 1 << 16;
+#endif
        mmc->max_blk_size = 1 << 11;
        mmc->max_blk_count = 1 << 11;
        mmc->max_req_size = PAGE_SIZE;
@@ -473,6 +561,7 @@ static int __devinit sdh_probe(struct platform_device *pdev)
        mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL;
        host = mmc_priv(mmc);
        host->mmc = mmc;
+       host->sclk = get_sclk();
 
        spin_lock_init(&host->lock);
        host->irq = drv_data->irq_int0;
@@ -497,7 +586,6 @@ static int __devinit sdh_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, mmc);
-       mmc_add_host(mmc);
 
        ret = request_irq(host->irq, sdh_stat_irq, 0, "SDH Status IRQ", host);
        if (ret) {
@@ -510,20 +598,10 @@ static int __devinit sdh_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "unable to request peripheral pins\n");
                goto out4;
        }
-#if defined(CONFIG_BF54x)
-       /* Secure Digital Host shares DMA with Nand controller */
-       bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1);
-#endif
-
-       bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN);
-       SSYNC();
 
-       /* Disable card inserting detection pin. set MMC_CAP_NEES_POLL, and
-        * mmc stack will do the detection.
-        */
-       bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3));
-       SSYNC();
+       sdh_reset();
 
+       mmc_add_host(mmc);
        return 0;
 
 out4:
@@ -571,7 +649,6 @@ static int sdh_suspend(struct platform_device *dev, pm_message_t state)
        if (mmc)
                ret = mmc_suspend_host(mmc);
 
-       bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() & ~PWR_ON);
        peripheral_free_list(drv_data->pin_req);
 
        return ret;
@@ -589,16 +666,7 @@ static int sdh_resume(struct platform_device *dev)
                return ret;
        }
 
-       bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() | PWR_ON);
-#if defined(CONFIG_BF54x)
-       /* Secure Digital Host shares DMA with Nand controller */
-       bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1);
-#endif
-       bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN);
-       SSYNC();
-
-       bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3));
-       SSYNC();
+       sdh_reset();
 
        if (mmc)
                ret = mmc_resume_host(mmc);
index dc0d25a013e043f40536a125a63420cfe923595d..f5ab03d32fb9f44c567befaa8d7d45b6de2626b6 100644 (file)
@@ -140,18 +140,7 @@ static struct pci_driver dw_mci_pci_driver = {
        },
 };
 
-static int __init dw_mci_init(void)
-{
-       return pci_register_driver(&dw_mci_pci_driver);
-}
-
-static void __exit dw_mci_exit(void)
-{
-       pci_unregister_driver(&dw_mci_pci_driver);
-}
-
-module_init(dw_mci_init);
-module_exit(dw_mci_exit);
+module_pci_driver(dw_mci_pci_driver);
 
 MODULE_DESCRIPTION("DW Multimedia Card PCI Interface driver");
 MODULE_AUTHOR("Shashidhar Hiremath <shashidharh@vayavyalabs.com>");
index 92ec3eb3aae767bece2b75da7fc272f7982cd730..a54d3a359ccda2ad90868c295c7e839c28c9e386 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/mmc/dw_mmc.h>
 #include "dw_mmc.h"
 
-static int dw_mci_pltfm_probe(struct platform_device *pdev)
+static int __devinit dw_mci_pltfm_probe(struct platform_device *pdev)
 {
        struct dw_mci *host;
        struct resource *regs;
@@ -62,7 +62,7 @@ err_free:
        return ret;
 }
 
-static int __exit dw_mci_pltfm_remove(struct platform_device *pdev)
+static int __devexit dw_mci_pltfm_remove(struct platform_device *pdev)
 {
        struct dw_mci *host = platform_get_drvdata(pdev);
 
index af40d227bece22ecb51bb0862df913aadc3ce6da..36f98c09715e96bf55d2d2ef72cf45028ff18071 100644 (file)
@@ -1767,7 +1767,7 @@ static void dw_mci_work_routine_card(struct work_struct *work)
        }
 }
 
-static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
+static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 {
        struct mmc_host *mmc;
        struct dw_mci_slot *slot;
index 273306c68d58e916d8a588fffb8fd73385c405f2..a600eabbd6c30671a4b3d318974dc9f8af728590 100644 (file)
@@ -1532,20 +1532,7 @@ static struct spi_driver mmc_spi_driver = {
        .remove =       __devexit_p(mmc_spi_remove),
 };
 
-
-static int __init mmc_spi_init(void)
-{
-       return spi_register_driver(&mmc_spi_driver);
-}
-module_init(mmc_spi_init);
-
-
-static void __exit mmc_spi_exit(void)
-{
-       spi_unregister_driver(&mmc_spi_driver);
-}
-module_exit(mmc_spi_exit);
-
+module_spi_driver(mmc_spi_driver);
 
 MODULE_AUTHOR("Mike Lavender, David Brownell, "
                "Hans-Peter Nilsson, Jan Nikitenko");
index a5999a74496af218c540959ee757b7c1ad3f1365..48ad361613efb2ebaca728ac53f87a147e8beb45 100644 (file)
 #include <linux/mmc/card.h>
 #include <linux/clk.h>
 #include <linux/scatterlist.h>
-#include <linux/i2c/tps65010.h>
 #include <linux/slab.h>
 
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <plat/board.h>
 #include <plat/mmc.h>
-#include <asm/gpio.h>
 #include <plat/dma.h>
-#include <plat/mux.h>
-#include <plat/fpga.h>
 
 #define        OMAP_MMC_REG_CMD        0x00
 #define        OMAP_MMC_REG_ARGL       0x01
@@ -107,7 +99,6 @@ struct mmc_omap_slot {
        u16                     saved_con;
        u16                     bus_mode;
        unsigned int            fclk_freq;
-       unsigned                powered:1;
 
        struct tasklet_struct   cover_tasklet;
        struct timer_list       cover_timer;
@@ -139,7 +130,6 @@ struct mmc_omap_host {
        unsigned int            phys_base;
        int                     irq;
        unsigned char           bus_mode;
-       unsigned char           hw_bus_mode;
        unsigned int            reg_shift;
 
        struct work_struct      cmd_abort_work;
@@ -697,22 +687,29 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
        host->buffer += nwords;
 }
 
-static inline void mmc_omap_report_irq(u16 status)
+#ifdef CONFIG_MMC_DEBUG
+static void mmc_omap_report_irq(struct mmc_omap_host *host, u16 status)
 {
        static const char *mmc_omap_status_bits[] = {
                "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO",
                "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR"
        };
-       int i, c = 0;
+       int i;
+       char res[64], *buf = res;
+
+       buf += sprintf(buf, "MMC IRQ 0x%x:", status);
 
        for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++)
-               if (status & (1 << i)) {
-                       if (c)
-                               printk(" ");
-                       printk("%s", mmc_omap_status_bits[i]);
-                       c++;
-               }
+               if (status & (1 << i))
+                       buf += sprintf(buf, " %s", mmc_omap_status_bits[i]);
+       dev_vdbg(mmc_dev(host->mmc), "%s\n", res);
 }
+#else
+static void mmc_omap_report_irq(struct mmc_omap_host *host, u16 status)
+{
+}
+#endif
+
 
 static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 {
@@ -746,12 +743,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                        cmd = host->cmd->opcode;
                else
                        cmd = -1;
-#ifdef CONFIG_MMC_DEBUG
                dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ",
                        status, cmd);
-               mmc_omap_report_irq(status);
-               printk("\n");
-#endif
+               mmc_omap_report_irq(host, status);
+
                if (host->total_bytes_left) {
                        if ((status & OMAP_MMC_STAT_A_FULL) ||
                            (status & OMAP_MMC_STAT_END_OF_DATA))
index 3a09f93cc3b6f846a2b4cd327a7fd2a4524e31bc..9afdd202b8735bf5e36509c1952f9f0e8a86d7be 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/mmc/core.h>
 #include <linux/mmc/mmc.h>
 #include <linux/io.h>
-#include <linux/semaphore.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
@@ -45,7 +44,6 @@
 #include <plat/cpu.h>
 
 /* OMAP HSMMC Host Controller Registers */
-#define OMAP_HSMMC_SYSCONFIG   0x0010
 #define OMAP_HSMMC_SYSSTATUS   0x0014
 #define OMAP_HSMMC_CON         0x002C
 #define OMAP_HSMMC_BLK         0x0104
@@ -162,8 +160,6 @@ struct omap_hsmmc_host {
        unsigned int            dma_sg_idx;
        unsigned char           bus_mode;
        unsigned char           power_mode;
-       u32                     *buffer;
-       u32                     bytesleft;
        int                     suspended;
        int                     irq;
        int                     use_dma, dma_ch;
@@ -172,7 +168,6 @@ struct omap_hsmmc_host {
        int                     slot_id;
        int                     response_busy;
        int                     context_loss;
-       int                     vdd;
        int                     protect_card;
        int                     reqs_blocked;
        int                     use_reg;
@@ -301,12 +296,12 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
        struct regulator *reg;
        int ocr_value = 0;
 
-       mmc_slot(host).set_power = omap_hsmmc_set_power;
-
        reg = regulator_get(host->dev, "vmmc");
        if (IS_ERR(reg)) {
                dev_dbg(host->dev, "vmmc regulator missing\n");
+               return PTR_ERR(reg);
        } else {
+               mmc_slot(host).set_power = omap_hsmmc_set_power;
                host->vcc = reg;
                ocr_value = mmc_regulator_get_ocrmask(reg);
                if (!mmc_slot(host).ocr_mask) {
@@ -496,7 +491,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
        unsigned long regval;
        unsigned long timeout;
 
-       dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
+       dev_vdbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
 
        omap_hsmmc_stop_clock(host);
 
@@ -580,21 +575,8 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
        if (host->context_loss == context_loss)
                return 1;
 
-       /* Wait for hardware reset */
-       timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
-       while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE
-               && time_before(jiffies, timeout))
-               ;
-
-       /* Do software reset */
-       OMAP_HSMMC_WRITE(host->base, SYSCONFIG, SOFTRESET);
-       timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
-       while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE
-               && time_before(jiffies, timeout))
-               ;
-
-       OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
-                       OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);
+       if (!OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE)
+               return 1;
 
        if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
                if (host->power_mode != MMC_POWER_OFF &&
@@ -746,7 +728,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
 {
        int cmdreg = 0, resptype = 0, cmdtype = 0;
 
-       dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n",
+       dev_vdbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n",
                mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
        host->cmd = cmd;
 
@@ -935,7 +917,7 @@ static void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, u32 status)
                        buf += len;
                }
 
-       dev_dbg(mmc_dev(host->mmc), "%s\n", res);
+       dev_vdbg(mmc_dev(host->mmc), "%s\n", res);
 }
 #else
 static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host,
@@ -982,72 +964,40 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
                        __func__);
 }
 
+static void hsmmc_command_incomplete(struct omap_hsmmc_host *host, int err)
+{
+       omap_hsmmc_reset_controller_fsm(host, SRC);
+       host->cmd->error = err;
+
+       if (host->data) {
+               omap_hsmmc_reset_controller_fsm(host, SRD);
+               omap_hsmmc_dma_cleanup(host, err);
+       }
+
+}
+
 static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
 {
        struct mmc_data *data;
        int end_cmd = 0, end_trans = 0;
 
-       if (!host->req_in_progress) {
-               do {
-                       OMAP_HSMMC_WRITE(host->base, STAT, status);
-                       /* Flush posted write */
-                       status = OMAP_HSMMC_READ(host->base, STAT);
-               } while (status & INT_EN_MASK);
-               return;
-       }
-
        data = host->data;
-       dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
+       dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
 
        if (status & ERR) {
                omap_hsmmc_dbg_report_irq(host, status);
-               if ((status & CMD_TIMEOUT) ||
-                       (status & CMD_CRC)) {
-                       if (host->cmd) {
-                               if (status & CMD_TIMEOUT) {
-                                       omap_hsmmc_reset_controller_fsm(host,
-                                                                       SRC);
-                                       host->cmd->error = -ETIMEDOUT;
-                               } else {
-                                       host->cmd->error = -EILSEQ;
-                               }
-                               end_cmd = 1;
-                       }
-                       if (host->data || host->response_busy) {
-                               if (host->data)
-                                       omap_hsmmc_dma_cleanup(host,
-                                                               -ETIMEDOUT);
-                               host->response_busy = 0;
-                               omap_hsmmc_reset_controller_fsm(host, SRD);
-                       }
-               }
-               if ((status & DATA_TIMEOUT) ||
-                       (status & DATA_CRC)) {
-                       if (host->data || host->response_busy) {
-                               int err = (status & DATA_TIMEOUT) ?
-                                               -ETIMEDOUT : -EILSEQ;
-
-                               if (host->data)
-                                       omap_hsmmc_dma_cleanup(host, err);
-                               else
-                                       host->mrq->cmd->error = err;
-                               host->response_busy = 0;
-                               omap_hsmmc_reset_controller_fsm(host, SRD);
-                               end_trans = 1;
-                       }
-               }
-               if (status & CARD_ERR) {
-                       dev_dbg(mmc_dev(host->mmc),
-                               "Ignoring card err CMD%d\n", host->cmd->opcode);
-                       if (host->cmd)
-                               end_cmd = 1;
-                       if (host->data)
-                               end_trans = 1;
+               if (status & (CMD_TIMEOUT | DATA_TIMEOUT))
+                       hsmmc_command_incomplete(host, -ETIMEDOUT);
+               else if (status & (CMD_CRC | DATA_CRC))
+                       hsmmc_command_incomplete(host, -EILSEQ);
+
+               end_cmd = 1;
+               if (host->data || host->response_busy) {
+                       end_trans = 1;
+                       host->response_busy = 0;
                }
        }
 
-       OMAP_HSMMC_WRITE(host->base, STAT, status);
-
        if (end_cmd || ((status & CC) && host->cmd))
                omap_hsmmc_cmd_done(host, host->cmd);
        if ((end_trans || (status & TC)) && host->mrq)
@@ -1063,11 +1013,13 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
        int status;
 
        status = OMAP_HSMMC_READ(host->base, STAT);
-       do {
+       while (status & INT_EN_MASK && host->req_in_progress) {
                omap_hsmmc_do_irq(host, status);
+
                /* Flush posted write */
+               OMAP_HSMMC_WRITE(host->base, STAT, status);
                status = OMAP_HSMMC_READ(host->base, STAT);
-       } while (status & INT_EN_MASK);
+       }
 
        return IRQ_HANDLED;
 }
@@ -1502,12 +1454,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                case MMC_POWER_OFF:
                        mmc_slot(host).set_power(host->dev, host->slot_id,
                                                 0, 0);
-                       host->vdd = 0;
                        break;
                case MMC_POWER_UP:
                        mmc_slot(host).set_power(host->dev, host->slot_id,
                                                 1, ios->vdd);
-                       host->vdd = ios->vdd;
                        break;
                case MMC_POWER_ON:
                        do_send_init_stream = 1;
@@ -1599,10 +1549,6 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
        value = OMAP_HSMMC_READ(host->base, CAPA);
        OMAP_HSMMC_WRITE(host->base, CAPA, value | capa);
 
-       /* Set the controller to AUTO IDLE mode */
-       value = OMAP_HSMMC_READ(host->base, SYSCONFIG);
-       OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE);
-
        /* Set SD bus power bit */
        set_sd_bus_power(host);
 }
@@ -1660,8 +1606,6 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data)
 
        pm_runtime_get_sync(host->dev);
 
-       seq_printf(s, "SYSCONFIG:\t0x%08x\n",
-                       OMAP_HSMMC_READ(host->base, SYSCONFIG));
        seq_printf(s, "CON:\t\t0x%08x\n",
                        OMAP_HSMMC_READ(host->base, CON));
        seq_printf(s, "HCTL:\t\t0x%08x\n",
index cb2dc0e75ba7fc1ff8d6610176326fa4eb675a5d..11df8006d47e72f1faf7b5a9a78b987216c997b7 100644 (file)
@@ -30,6 +30,9 @@
 #include <linux/regulator/consumer.h>
 #include <linux/gpio.h>
 #include <linux/gfp.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
 
 #include <asm/sizes.h>
 
@@ -573,6 +576,50 @@ static irqreturn_t pxamci_detect_irq(int irq, void *devid)
        return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id pxa_mmc_dt_ids[] = {
+        { .compatible = "marvell,pxa-mmc" },
+        { }
+};
+
+MODULE_DEVICE_TABLE(of, pxa_mmc_dt_ids);
+
+static int __devinit pxamci_of_init(struct platform_device *pdev)
+{
+        struct device_node *np = pdev->dev.of_node;
+        struct pxamci_platform_data *pdata;
+        u32 tmp;
+
+        if (!np)
+                return 0;
+
+        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+        if (!pdata)
+                return -ENOMEM;
+
+       pdata->gpio_card_detect =
+               of_get_named_gpio(np, "cd-gpios", 0);
+       pdata->gpio_card_ro =
+               of_get_named_gpio(np, "wp-gpios", 0);
+
+       /* pxa-mmc specific */
+       pdata->gpio_power =
+               of_get_named_gpio(np, "pxa-mmc,gpio-power", 0);
+
+       if (of_property_read_u32(np, "pxa-mmc,detect-delay-ms", &tmp) == 0)
+               pdata->detect_delay_ms = tmp;
+
+        pdev->dev.platform_data = pdata;
+
+        return 0;
+}
+#else
+static int __devinit pxamci_of_init(struct platform_device *pdev)
+{
+        return 0;
+}
+#endif
+
 static int pxamci_probe(struct platform_device *pdev)
 {
        struct mmc_host *mmc;
@@ -580,6 +627,10 @@ static int pxamci_probe(struct platform_device *pdev)
        struct resource *r, *dmarx, *dmatx;
        int ret, irq, gpio_cd = -1, gpio_ro = -1, gpio_power = -1;
 
+       ret = pxamci_of_init(pdev);
+       if (ret)
+               return ret;
+
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_irq(pdev, 0);
        if (!r || irq < 0)
@@ -866,6 +917,7 @@ static struct platform_driver pxamci_driver = {
        .driver         = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(pxa_mmc_dt_ids),
 #ifdef CONFIG_PM
                .pm     = &pxamci_pm_ops,
 #endif
index a6e53a1ebb0888639a49d75c72f562f45b48e4f1..90140eb03e36a2766ffc40470271a0e63be34845 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/mmc/host.h>
+#include <linux/of.h>
 
 #include "sdhci-pltfm.h"
 
@@ -126,11 +127,18 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev)
        return sdhci_pltfm_unregister(pdev);
 }
 
+static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = {
+       { .compatible = "marvell,dove-sdhci", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, sdhci_dove_of_match_table);
+
 static struct platform_driver sdhci_dove_driver = {
        .driver         = {
                .name   = "sdhci-dove",
                .owner  = THIS_MODULE,
                .pm     = SDHCI_PLTFM_PMOPS,
+               .of_match_table = of_match_ptr(sdhci_dove_of_match_table),
        },
        .probe          = sdhci_dove_probe,
        .remove         = __devexit_p(sdhci_dove_remove),
index f8eb1fb0c9219283c9624f3f0a8adde251bcd5e9..ae5fcbfa1eef5986ec832616ed1ad350106e64ef 100644 (file)
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
 
+#define VENDOR_V_22    0x12
+static u32 esdhc_readl(struct sdhci_host *host, int reg)
+{
+       u32 ret;
+
+       ret = in_be32(host->ioaddr + reg);
+       /*
+        * The bit of ADMA flag in eSDHC is not compatible with standard
+        * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is
+        * supported by eSDHC.
+        * And for many FSL eSDHC controller, the reset value of field
+        * SDHCI_CAN_DO_ADMA1 is one, but some of them can't support ADMA,
+        * only these vendor version is greater than 2.2/0x12 support ADMA.
+        * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the
+        * the verdor version number, oxFE is SDHCI_HOST_VERSION.
+        */
+       if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) {
+               u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+               tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+               if (tmp > VENDOR_V_22)
+                       ret |= SDHCI_CAN_DO_ADMA2;
+       }
+
+       return ret;
+}
+
 static u16 esdhc_readw(struct sdhci_host *host, int reg)
 {
        u16 ret;
@@ -144,7 +170,7 @@ static void esdhc_of_resume(struct sdhci_host *host)
 #endif
 
 static struct sdhci_ops sdhci_esdhc_ops = {
-       .read_l = sdhci_be32bs_readl,
+       .read_l = esdhc_readl,
        .read_w = esdhc_readw,
        .read_b = esdhc_readb,
        .write_l = sdhci_be32bs_writel,
@@ -161,9 +187,13 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 };
 
 static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
-       /* card detection could be handled via GPIO */
+       /*
+        * card detection could be handled via GPIO
+        * eSDHC cannot support End Attribute in NOP ADMA descriptor
+        */
        .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
-               | SDHCI_QUIRK_NO_CARD_NO_RESET,
+               | SDHCI_QUIRK_NO_CARD_NO_RESET
+               | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .ops = &sdhci_esdhc_ops,
 };
 
index 504da715a41ae30f3e5670ff305801167ee60935..3f0794e53b4a31a1bba24f0116b5d66c15f6bcf6 100644 (file)
@@ -1476,24 +1476,7 @@ static struct pci_driver sdhci_driver = {
        },
 };
 
-/*****************************************************************************\
- *                                                                           *
- * Driver init/exit                                                          *
- *                                                                           *
-\*****************************************************************************/
-
-static int __init sdhci_drv_init(void)
-{
-       return pci_register_driver(&sdhci_driver);
-}
-
-static void __exit sdhci_drv_exit(void)
-{
-       pci_unregister_driver(&sdhci_driver);
-}
-
-module_init(sdhci_drv_init);
-module_exit(sdhci_drv_exit);
+module_pci_driver(sdhci_driver);
 
 MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>");
 MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver");
index b6ee8857e226fc163d53c1a66d52eda26121735d..8e63a9c04e3176fd9f8950caa2c461636b6cce47 100644 (file)
@@ -197,7 +197,7 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
                goto err_clk_get;
        }
        pltfm_host->clk = clk;
-       clk_enable(clk);
+       clk_prepare_enable(clk);
 
        host->quirks = SDHCI_QUIRK_BROKEN_ADMA
                | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
@@ -239,7 +239,7 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
        return 0;
 
 err_add_host:
-       clk_disable(clk);
+       clk_disable_unprepare(clk);
        clk_put(clk);
 err_clk_get:
        sdhci_pltfm_free(pdev);
@@ -255,7 +255,7 @@ static int __devexit sdhci_pxav2_remove(struct platform_device *pdev)
 
        sdhci_remove_host(host, 1);
 
-       clk_disable(pltfm_host->clk);
+       clk_disable_unprepare(pltfm_host->clk);
        clk_put(pltfm_host->clk);
        sdhci_pltfm_free(pdev);
        kfree(pxa);
index 07fe3834fe0b224119d0591672de48949dd18105..223a5d4b5dd56d2c8c79138b3c93f8421f5d26ae 100644 (file)
@@ -198,6 +198,16 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
        if (clk_delay_cycles > 0)
                pdata->clk_delay_cycles = clk_delay_cycles;
 
+       if (of_find_property(np, "broken-cd", NULL))
+               pdata->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+
+       if (of_find_property(np, "wp-inverted", NULL))
+               pdata->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
+
+       pdata->ext_cd_gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &gpio_flags);
+       if (gpio_flags != OF_GPIO_ACTIVE_LOW)
+               pdata->host_caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
+
        return pdata;
 }
 #else
@@ -231,14 +241,14 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
        pltfm_host = sdhci_priv(host);
        pltfm_host->priv = pxa;
 
-       clk = clk_get(dev, "PXA-SDHCLK");
+       clk = clk_get(dev, NULL);
        if (IS_ERR(clk)) {
                dev_err(dev, "failed to get io clock\n");
                ret = PTR_ERR(clk);
                goto err_clk_get;
        }
        pltfm_host->clk = clk;
-       clk_enable(clk);
+       clk_prepare_enable(clk);
 
        host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
                | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
@@ -268,6 +278,15 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
                        host->mmc->caps |= pdata->host_caps;
                if (pdata->pm_caps)
                        host->mmc->pm_caps |= pdata->pm_caps;
+
+               if (gpio_is_valid(pdata->ext_cd_gpio)) {
+                       ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio);
+                       if (ret) {
+                               dev_err(mmc_dev(host->mmc),
+                                       "failed to allocate card detect gpio\n");
+                               goto err_cd_req;
+                       }
+               }
        }
 
        host->ops = &pxav3_sdhci_ops;
@@ -283,8 +302,10 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
        return 0;
 
 err_add_host:
-       clk_disable(clk);
+       clk_disable_unprepare(clk);
        clk_put(clk);
+       mmc_gpio_free_cd(host->mmc);
+err_cd_req:
 err_clk_get:
        sdhci_pltfm_free(pdev);
        kfree(pxa);
@@ -299,8 +320,12 @@ static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
 
        sdhci_remove_host(host, 1);
 
-       clk_disable(pltfm_host->clk);
+       clk_disable_unprepare(pltfm_host->clk);
        clk_put(pltfm_host->clk);
+
+       if (gpio_is_valid(pdata->ext_cd_gpio))
+               mmc_gpio_free_cd(host->mmc);
+
        sdhci_pltfm_free(pdev);
        kfree(pxa);
 
index a50c205ea2085f3266ee906b673d062e3a9aaf10..00969ba03277ad027be418865c70333e9b621277 100644 (file)
@@ -166,7 +166,7 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
        dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n",
                src, rate, wanted, rate / div);
 
-       return (wanted - (rate / div));
+       return wanted - (rate / div);
 }
 
 /**
@@ -288,6 +288,7 @@ static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host)
 static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
 {
        struct sdhci_s3c *ourhost = to_s3c(host);
+       struct device *dev = &ourhost->pdev->dev;
        unsigned long timeout;
        u16 clk = 0;
 
@@ -309,8 +310,8 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
        while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
                & SDHCI_CLOCK_INT_STABLE)) {
                if (timeout == 0) {
-                       printk(KERN_ERR "%s: Internal clock never "
-                               "stabilised.\n", mmc_hostname(host->mmc));
+                       dev_err(dev, "%s: Internal clock never stabilised.\n",
+                               mmc_hostname(host->mmc));
                        return;
                }
                timeout--;
@@ -404,7 +405,9 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
                if (sc->ext_cd_irq &&
                    request_threaded_irq(sc->ext_cd_irq, NULL,
                                         sdhci_s3c_gpio_card_detect_thread,
-                                        IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                        IRQF_TRIGGER_RISING |
+                                        IRQF_TRIGGER_FALLING |
+                                        IRQF_ONESHOT,
                                         dev_name(dev), sc) == 0) {
                        int status = gpio_get_value(sc->ext_cd_gpio);
                        if (pdata->ext_cd_gpio_invert)
@@ -486,9 +489,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 
                snprintf(name, 14, "mmc_busclk.%d", ptr);
                clk = clk_get(dev, name);
-               if (IS_ERR(clk)) {
+               if (IS_ERR(clk))
                        continue;
-               }
 
                clks++;
                sc->clk_bus[ptr] = clk;
index 0810ccc23d7e8fb951fecf7b75774b2ae4e5984e..436186ccbbe21c3158426b5c362228fd0b95fe84 100644 (file)
@@ -257,10 +257,9 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
        int rc;
 
        match = of_match_device(sdhci_tegra_dt_match, &pdev->dev);
-       if (match)
-               soc_data = match->data;
-       else
-               soc_data = &soc_data_tegra20;
+       if (!match)
+               return -EINVAL;
+       soc_data = match->data;
 
        host = sdhci_pltfm_init(pdev, soc_data->pdata);
        if (IS_ERR(host))
index 9a11dc39921c06ebdf67a3ed602fbba79cc38b89..d98b1992d778ca8f87ff3a405c783ad506a17f2a 100644 (file)
@@ -1597,57 +1597,65 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
        spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
-                                               struct mmc_ios *ios)
+static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host,
+                                               u16 ctrl)
 {
-       u8 pwr;
-       u16 clk, ctrl;
-       u32 present_state;
+       int ret;
 
-       /*
-        * Signal Voltage Switching is only applicable for Host Controllers
-        * v3.00 and above.
-        */
-       if (host->version < SDHCI_SPEC_300)
-               return 0;
+       /* Set 1.8V Signal Enable in the Host Control2 register to 0 */
+       ctrl &= ~SDHCI_CTRL_VDD_180;
+       sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-       /*
-        * We first check whether the request is to set signalling voltage
-        * to 3.3V. If so, we change the voltage to 3.3V and return quickly.
-        */
+       if (host->vqmmc) {
+               ret = regulator_set_voltage(host->vqmmc, 3300000, 3300000);
+               if (ret) {
+                       pr_warning("%s: Switching to 3.3V signalling voltage "
+                                  " failed\n", mmc_hostname(host->mmc));
+                       return -EIO;
+               }
+       }
+       /* Wait for 5ms */
+       usleep_range(5000, 5500);
+
+       /* 3.3V regulator output should be stable within 5 ms */
        ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-       if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
-               /* Set 1.8V Signal Enable in the Host Control2 register to 0 */
-               ctrl &= ~SDHCI_CTRL_VDD_180;
-               sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+       if (!(ctrl & SDHCI_CTRL_VDD_180))
+               return 0;
 
-               /* Wait for 5ms */
-               usleep_range(5000, 5500);
+       pr_warning("%s: 3.3V regulator output did not became stable\n",
+                  mmc_hostname(host->mmc));
 
-               /* 3.3V regulator output should be stable within 5 ms */
-               ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-               if (!(ctrl & SDHCI_CTRL_VDD_180))
-                       return 0;
-               else {
-                       pr_info(DRIVER_NAME ": Switching to 3.3V "
-                               "signalling voltage failed\n");
-                       return -EIO;
-               }
-       } else if (!(ctrl & SDHCI_CTRL_VDD_180) &&
-                 (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) {
-               /* Stop SDCLK */
-               clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-               clk &= ~SDHCI_CLOCK_CARD_EN;
-               sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+       return -EIO;
+}
 
-               /* Check whether DAT[3:0] is 0000 */
-               present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
-               if (!((present_state & SDHCI_DATA_LVL_MASK) >>
-                      SDHCI_DATA_LVL_SHIFT)) {
-                       /*
-                        * Enable 1.8V Signal Enable in the Host Control2
-                        * register
-                        */
+static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host,
+                                               u16 ctrl)
+{
+       u8 pwr;
+       u16 clk;
+       u32 present_state;
+       int ret;
+
+       /* Stop SDCLK */
+       clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+       clk &= ~SDHCI_CLOCK_CARD_EN;
+       sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+       /* Check whether DAT[3:0] is 0000 */
+       present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
+       if (!((present_state & SDHCI_DATA_LVL_MASK) >>
+              SDHCI_DATA_LVL_SHIFT)) {
+               /*
+                * Enable 1.8V Signal Enable in the Host Control2
+                * register
+                */
+               if (host->vqmmc)
+                       ret = regulator_set_voltage(host->vqmmc,
+                               1800000, 1800000);
+               else
+                       ret = 0;
+
+               if (!ret) {
                        ctrl |= SDHCI_CTRL_VDD_180;
                        sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
@@ -1656,7 +1664,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 
                        ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
                        if (ctrl & SDHCI_CTRL_VDD_180) {
-                               /* Provide SDCLK again and wait for 1ms*/
+                               /* Provide SDCLK again and wait for 1ms */
                                clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
                                clk |= SDHCI_CLOCK_CARD_EN;
                                sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
@@ -1673,29 +1681,55 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
                                        return 0;
                        }
                }
+       }
 
-               /*
-                * If we are here, that means the switch to 1.8V signaling
-                * failed. We power cycle the card, and retry initialization
-                * sequence by setting S18R to 0.
-                */
-               pwr = sdhci_readb(host, SDHCI_POWER_CONTROL);
-               pwr &= ~SDHCI_POWER_ON;
-               sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-               if (host->vmmc)
-                       regulator_disable(host->vmmc);
+       /*
+        * If we are here, that means the switch to 1.8V signaling
+        * failed. We power cycle the card, and retry initialization
+        * sequence by setting S18R to 0.
+        */
+       pwr = sdhci_readb(host, SDHCI_POWER_CONTROL);
+       pwr &= ~SDHCI_POWER_ON;
+       sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+       if (host->vmmc)
+               regulator_disable(host->vmmc);
 
-               /* Wait for 1ms as per the spec */
-               usleep_range(1000, 1500);
-               pwr |= SDHCI_POWER_ON;
-               sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-               if (host->vmmc)
-                       regulator_enable(host->vmmc);
+       /* Wait for 1ms as per the spec */
+       usleep_range(1000, 1500);
+       pwr |= SDHCI_POWER_ON;
+       sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+       if (host->vmmc)
+               regulator_enable(host->vmmc);
 
-               pr_info(DRIVER_NAME ": Switching to 1.8V signalling "
-                       "voltage failed, retrying with S18R set to 0\n");
-               return -EAGAIN;
-       } else
+       pr_warning("%s: Switching to 1.8V signalling voltage failed, "
+                  "retrying with S18R set to 0\n", mmc_hostname(host->mmc));
+
+       return -EAGAIN;
+}
+
+static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
+                                               struct mmc_ios *ios)
+{
+       u16 ctrl;
+
+       /*
+        * Signal Voltage Switching is only applicable for Host Controllers
+        * v3.00 and above.
+        */
+       if (host->version < SDHCI_SPEC_300)
+               return 0;
+
+       /*
+        * We first check whether the request is to set signalling voltage
+        * to 3.3V. If so, we change the voltage to 3.3V and return quickly.
+        */
+       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+       if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
+               return sdhci_do_3_3v_signal_voltage_switch(host, ctrl);
+       else if (!(ctrl & SDHCI_CTRL_VDD_180) &&
+                       (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180))
+               return sdhci_do_1_8v_signal_voltage_switch(host, ctrl);
+       else
                /* No signal voltage switch required */
                return 0;
 }
@@ -2802,6 +2836,18 @@ int sdhci_add_host(struct sdhci_host *host)
            !(host->mmc->caps & MMC_CAP_NONREMOVABLE))
                mmc->caps |= MMC_CAP_NEEDS_POLL;
 
+       /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
+       host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc");
+       if (IS_ERR(host->vqmmc)) {
+               pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc));
+               host->vqmmc = NULL;
+       }
+       else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000))
+               regulator_enable(host->vqmmc);
+       else
+               caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
+                      SDHCI_SUPPORT_DDR50);
+
        /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
        if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
                       SDHCI_SUPPORT_DDR50))
@@ -2862,7 +2908,8 @@ int sdhci_add_host(struct sdhci_host *host)
        if (IS_ERR(host->vmmc)) {
                pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
                host->vmmc = NULL;
-       }
+       } else
+               regulator_enable(host->vmmc);
 
 #ifdef CONFIG_REGULATOR
        if (host->vmmc) {
@@ -3119,8 +3166,15 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
        tasklet_kill(&host->card_tasklet);
        tasklet_kill(&host->finish_tasklet);
 
-       if (host->vmmc)
+       if (host->vmmc) {
+               regulator_disable(host->vmmc);
                regulator_put(host->vmmc);
+       }
+
+       if (host->vqmmc) {
+               regulator_disable(host->vqmmc);
+               regulator_put(host->vqmmc);
+       }
 
        kfree(host->adma_desc);
        kfree(host->align_buffer);
index 4b83c43f950d4634498ae809cbd40e827eec0339..f18becef156d391519cfb6d211bf2b0efa66a372 100644 (file)
@@ -1337,21 +1337,7 @@ static struct pci_driver via_sd_driver = {
        .resume = via_sd_resume,
 };
 
-static int __init via_sd_drv_init(void)
-{
-       pr_info(DRV_NAME ": VIA SD/MMC Card Reader driver "
-               "(C) 2008 VIA Technologies, Inc.\n");
-
-       return pci_register_driver(&via_sd_driver);
-}
-
-static void __exit via_sd_drv_exit(void)
-{
-       pci_unregister_driver(&via_sd_driver);
-}
-
-module_init(via_sd_drv_init);
-module_exit(via_sd_drv_exit);
+module_pci_driver(via_sd_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("VIA Technologies Inc.");
index 3135a1a5d75d004fda64cf0160f14481bc6af333..6c39bf1fd279c26afb1a6304f92d9734b0dff6a1 100644 (file)
@@ -2358,9 +2358,9 @@ error5:
         * which is contained at the end of struct mmc
         */
 error4:
-       usb_free_urb(command_out_urb);
-error1:
        usb_free_urb(command_res_urb);
+error1:
+       usb_free_urb(command_out_urb);
 error0:
        return retval;
 }
index f578a71d82a6b71bd1c9203b53e77713c4543065..d5d9bd4c5aa83678fbbd4bedfa4155e9c0fb2d60 100644 (file)
@@ -300,6 +300,7 @@ struct mmc_host {
 #endif
 
        int                     rescan_disable; /* disable card detection */
+       int                     rescan_entered; /* used with nonremovable devices */
 
        struct mmc_card         *card;          /* device attached to this host */
 
index ac83b105bedd66d2fb051ead198d11297ab650c3..fa8529a859b8b7637a6b25e76e15ba7848cd9f79 100644 (file)
@@ -97,7 +97,8 @@ struct sdhci_host {
 
        const struct sdhci_ops *ops;    /* Low level hw interface */
 
-       struct regulator *vmmc; /* Power regulator */
+       struct regulator *vmmc;         /* Power regulator (vmmc) */
+       struct regulator *vqmmc;        /* Signaling regulator (vccq) */
 
        /* Internal data */
        struct mmc_host *mmc;   /* MMC structure */