Merge tag 'mmc-updates-for-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 10 Sep 2013 20:33:09 +0000 (13:33 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 10 Sep 2013 20:33:09 +0000 (13:33 -0700)
Pull MMC updates from Chris Ball:
 "MMC highlights for 3.12:

  Core:
   - Support Allocation Units 8MB-64MB in SD3.0, previous max was 4MB.
   - The slot-gpio helper can now handle GPIO debouncing card-detect.
   - Read supported voltages from DT "voltage-ranges" property.

  Drivers:
   - dw_mmc: Add support for ARC architecture, and support exynos5420.
   - mmc_spi: Support CD/RO GPIOs.
   - sh_mobile_sdhi: Add compatibility for more Renesas SoCs.
   - sh_mmcif: Add DT support for DMA channels"

* tag 'mmc-updates-for-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (50 commits)
  Revert "mmc: tmio-mmc: Remove .set_pwr() callback from platform data"
  mmc: dw_mmc: Add support for ARC
  mmc: sdhci-s3c: initialize host->quirks2 for using quirks2
  mmc: sdhci-s3c: fix the wrong register value, when clock is disabled
  mmc: esdhc: add support to get voltage from device-tree
  mmc: sdhci: get voltage from sdhc host
  mmc: core: parse voltage from device-tree
  mmc: omap_hsmmc: use the generic config for omap2plus devices
  mmc: omap_hsmmc: clear status flags before starting a new command
  mmc: dw_mmc: exynos: Add a new compatible string for exynos5420
  mmc: sh_mmcif: revision-specific CLK_CTRL2 handling
  mmc: sh_mmcif: revision-specific Command Completion Signal handling
  mmc: sh_mmcif: add support for Device Tree DMA bindings
  mmc: sh_mmcif: move header include from header into .c
  mmc: SDHI: add DT compatibility strings for further SoCs
  mmc: dw_mmc-pci: enable bus-mastering mode
  mmc: dw_mmc-pci: get resources from a proper BAR
  mmc: tmio-mmc: Remove .set_pwr() callback from platform data
  mmc: tmio-mmc: Remove .get_cd() callback from platform data
  mmc: sh_mobile_sdhi: Remove .set_pwr() callback from platform data
  ...

42 files changed:
Documentation/devicetree/bindings/mmc/fsl-esdhc.txt
arch/arm/mach-ep93xx/vision_ep9307.c
arch/sh/boards/mach-ecovec24/setup.c
drivers/mmc/card/block.c
drivers/mmc/card/mmc_test.c
drivers/mmc/core/core.c
drivers/mmc/core/host.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/core/sd.c
drivers/mmc/core/slot-gpio.c
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/dw_mmc-exynos.c
drivers/mmc/host/dw_mmc-pci.c
drivers/mmc/host/dw_mmc-pltfm.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/jz4740_mmc.c
drivers/mmc/host/mmc_spi.c
drivers/mmc/host/mvsdio.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/of_mmc_spi.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/sdhci-bcm2835.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdhci-sirf.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sh_mmcif.c
drivers/mmc/host/sh_mobile_sdhi.c
drivers/mmc/host/tmio_mmc_dma.c
drivers/mmc/host/tmio_mmc_pio.c
drivers/mmc/host/vub300.c
include/linux/mfd/tmio.h
include/linux/mmc/core.h
include/linux/mmc/sdhci.h
include/linux/mmc/sh_mmcif.h
include/linux/mmc/sh_mobile_sdhi.h
include/linux/mmc/slot-gpio.h
include/linux/spi/mmc_spi.h

index bd9be0b..b7943f3 100644 (file)
@@ -19,6 +19,9 @@ Optional properties:
     "bus-width = <1>" property.
   - sdhci,auto-cmd12: specifies that a controller can only handle auto
     CMD12.
+  - voltage-ranges : two cells are required, first cell specifies minimum
+    slot voltage (mV), second cell specifies maximum slot voltage (mV).
+    Several ranges could be specified.
 
 Example:
 
@@ -29,4 +32,5 @@ sdhci@2e000 {
        interrupt-parent = <&ipic>;
        /* Filled in by U-Boot */
        clock-frequency = <0>;
+       voltage-ranges = <3300 3300>;
 };
index 64f2e50..6bc1c18 100644 (file)
@@ -224,62 +224,15 @@ static struct ep93xx_spi_chip_ops vision_spi_flash_hw = {
 #define VISION_SPI_MMC_WP      EP93XX_GPIO_LINE_F(0)
 #define VISION_SPI_MMC_CD      EP93XX_GPIO_LINE_EGPIO15
 
-static struct gpio vision_spi_mmc_gpios[] = {
-       { VISION_SPI_MMC_WP, GPIOF_DIR_IN, "mmc_spi:wp" },
-       { VISION_SPI_MMC_CD, GPIOF_DIR_IN, "mmc_spi:cd" },
-};
-
-static int vision_spi_mmc_init(struct device *pdev,
-                       irqreturn_t (*func)(int, void *), void *pdata)
-{
-       int err;
-
-       err = gpio_request_array(vision_spi_mmc_gpios,
-                                ARRAY_SIZE(vision_spi_mmc_gpios));
-       if (err)
-               return err;
-
-       err = gpio_set_debounce(VISION_SPI_MMC_CD, 1);
-       if (err)
-               goto exit_err;
-
-       err = request_irq(gpio_to_irq(VISION_SPI_MMC_CD), func,
-                       IRQ_TYPE_EDGE_BOTH, "mmc_spi:cd", pdata);
-       if (err)
-               goto exit_err;
-
-       return 0;
-
-exit_err:
-       gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
-       return err;
-
-}
-
-static void vision_spi_mmc_exit(struct device *pdev, void *pdata)
-{
-       free_irq(gpio_to_irq(VISION_SPI_MMC_CD), pdata);
-       gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
-}
-
-static int vision_spi_mmc_get_ro(struct device *pdev)
-{
-       return !!gpio_get_value(VISION_SPI_MMC_WP);
-}
-
-static int vision_spi_mmc_get_cd(struct device *pdev)
-{
-       return !gpio_get_value(VISION_SPI_MMC_CD);
-}
-
 static struct mmc_spi_platform_data vision_spi_mmc_data = {
-       .init           = vision_spi_mmc_init,
-       .exit           = vision_spi_mmc_exit,
-       .get_ro         = vision_spi_mmc_get_ro,
-       .get_cd         = vision_spi_mmc_get_cd,
        .detect_delay   = 100,
        .powerup_msecs  = 100,
        .ocr_mask       = MMC_VDD_32_33 | MMC_VDD_33_34,
+       .flags          = MMC_SPI_USE_CD_GPIO | MMC_SPI_USE_RO_GPIO,
+       .cd_gpio        = VISION_SPI_MMC_CD,
+       .cd_debounce    = 1,
+       .ro_gpio        = VISION_SPI_MMC_WP,
+       .caps2          = MMC_CAP2_RO_ACTIVE_HIGH,
 };
 
 static int vision_spi_mmc_hw_setup(struct spi_device *spi)
index 65dd81b..1fa8be4 100644 (file)
@@ -600,37 +600,13 @@ static struct platform_device sdhi0_power = {
        },
 };
 
-static void sdhi0_set_pwr(struct platform_device *pdev, int state)
-{
-       static int power_gpio = -EINVAL;
-
-       if (power_gpio < 0) {
-               int ret = gpio_request(GPIO_PTB6, NULL);
-               if (!ret) {
-                       power_gpio = GPIO_PTB6;
-                       gpio_direction_output(power_gpio, 0);
-               }
-       }
-
-       /*
-        * Toggle the GPIO regardless, whether we managed to grab it above or
-        * the fixed regulator driver did.
-        */
-       gpio_set_value(GPIO_PTB6, state);
-}
-
-static int sdhi0_get_cd(struct platform_device *pdev)
-{
-       return !gpio_get_value(GPIO_PTY7);
-}
-
 static struct sh_mobile_sdhi_info sdhi0_info = {
        .dma_slave_tx   = SHDMA_SLAVE_SDHI0_TX,
        .dma_slave_rx   = SHDMA_SLAVE_SDHI0_RX,
-       .set_pwr        = sdhi0_set_pwr,
        .tmio_caps      = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
                          MMC_CAP_NEEDS_POLL,
-       .get_cd         = sdhi0_get_cd,
+       .tmio_flags     = TMIO_MMC_USE_GPIO_CD,
+       .cd_gpio        = GPIO_PTY7,
 };
 
 static struct resource sdhi0_resources[] = {
@@ -656,39 +632,15 @@ static struct platform_device sdhi0_device = {
        },
 };
 
-static void cn12_set_pwr(struct platform_device *pdev, int state)
-{
-       static int power_gpio = -EINVAL;
-
-       if (power_gpio < 0) {
-               int ret = gpio_request(GPIO_PTB7, NULL);
-               if (!ret) {
-                       power_gpio = GPIO_PTB7;
-                       gpio_direction_output(power_gpio, 0);
-               }
-       }
-
-       /*
-        * Toggle the GPIO regardless, whether we managed to grab it above or
-        * the fixed regulator driver did.
-        */
-       gpio_set_value(GPIO_PTB7, state);
-}
-
 #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
 /* SDHI1 */
-static int sdhi1_get_cd(struct platform_device *pdev)
-{
-       return !gpio_get_value(GPIO_PTW7);
-}
-
 static struct sh_mobile_sdhi_info sdhi1_info = {
        .dma_slave_tx   = SHDMA_SLAVE_SDHI1_TX,
        .dma_slave_rx   = SHDMA_SLAVE_SDHI1_RX,
        .tmio_caps      = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
                          MMC_CAP_NEEDS_POLL,
-       .set_pwr        = cn12_set_pwr,
-       .get_cd         = sdhi1_get_cd,
+       .tmio_flags     = TMIO_MMC_USE_GPIO_CD,
+       .cd_gpio        = GPIO_PTW7,
 };
 
 static struct resource sdhi1_resources[] = {
@@ -718,27 +670,19 @@ static struct platform_device sdhi1_device = {
 #else
 
 /* MMC SPI */
-static int mmc_spi_get_ro(struct device *dev)
-{
-       return gpio_get_value(GPIO_PTY6);
-}
-
-static int mmc_spi_get_cd(struct device *dev)
-{
-       return !gpio_get_value(GPIO_PTY7);
-}
-
 static void mmc_spi_setpower(struct device *dev, unsigned int maskval)
 {
        gpio_set_value(GPIO_PTB6, maskval ? 1 : 0);
 }
 
 static struct mmc_spi_platform_data mmc_spi_info = {
-       .get_ro = mmc_spi_get_ro,
-       .get_cd = mmc_spi_get_cd,
        .caps = MMC_CAP_NEEDS_POLL,
+       .caps2 = MMC_CAP2_RO_ACTIVE_HIGH,
        .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, /* 3.3V only */
        .setpower = mmc_spi_setpower,
+       .flags = MMC_SPI_USE_CD_GPIO | MMC_SPI_USE_RO_GPIO,
+       .cd_gpio = GPIO_PTY7,
+       .ro_gpio = GPIO_PTY6,
 };
 
 static struct spi_board_info spi_bus[] = {
@@ -998,11 +942,6 @@ static struct platform_device vou_device = {
 
 #if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE)
 /* SH_MMCIF */
-static void mmcif_down_pwr(struct platform_device *pdev)
-{
-       cn12_set_pwr(pdev, 0);
-}
-
 static struct resource sh_mmcif_resources[] = {
        [0] = {
                .name   = "SH_MMCIF",
@@ -1023,8 +962,6 @@ static struct resource sh_mmcif_resources[] = {
 };
 
 static struct sh_mmcif_plat_data sh_mmcif_plat = {
-       .set_pwr        = cn12_set_pwr,
-       .down_pwr       = mmcif_down_pwr,
        .sup_pclk       = 0, /* SH7724: Max Pclk/2 */
        .caps           = MMC_CAP_4_BIT_DATA |
                          MMC_CAP_8_BIT_DATA |
@@ -1341,10 +1278,6 @@ static int __init arch_setup(void)
        gpio_direction_input(GPIO_PTR6);
 
        /* SD-card slot CN11 */
-       /* Card-detect, used on CN11, either with SDHI0 or with SPI */
-       gpio_request(GPIO_PTY7, NULL);
-       gpio_direction_input(GPIO_PTY7);
-
 #if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
        /* enable SDHI0 on CN11 (needs DS2.4 set to ON) */
        gpio_request(GPIO_FN_SDHI0WP,  NULL);
@@ -1363,8 +1296,6 @@ static int __init arch_setup(void)
        gpio_direction_output(GPIO_PTM4, 1); /* active low CS */
        gpio_request(GPIO_PTB6, NULL); /* 3.3V power control */
        gpio_direction_output(GPIO_PTB6, 0); /* disable power by default */
-       gpio_request(GPIO_PTY6, NULL); /* write protect */
-       gpio_direction_input(GPIO_PTY6);
 
        spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus));
 #endif
@@ -1394,10 +1325,6 @@ static int __init arch_setup(void)
        gpio_request(GPIO_FN_SDHI1D1,  NULL);
        gpio_request(GPIO_FN_SDHI1D0,  NULL);
 
-       /* Card-detect, used on CN12 with SDHI1 */
-       gpio_request(GPIO_PTW7, NULL);
-       gpio_direction_input(GPIO_PTW7);
-
        cn12_enabled = true;
 #endif
 
index cd0b7f4..1a3163f 100644 (file)
@@ -812,7 +812,7 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
  * Otherwise we don't understand what happened, so abort.
  */
 static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
-       struct mmc_blk_request *brq, int *ecc_err)
+       struct mmc_blk_request *brq, int *ecc_err, int *gen_err)
 {
        bool prev_cmd_status_valid = true;
        u32 status, stop_status = 0;
@@ -850,6 +850,16 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
            (brq->cmd.resp[0] & R1_CARD_ECC_FAILED))
                *ecc_err = 1;
 
+       /* Flag General errors */
+       if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
+               if ((status & R1_ERROR) ||
+                       (brq->stop.resp[0] & R1_ERROR)) {
+                       pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n",
+                              req->rq_disk->disk_name, __func__,
+                              brq->stop.resp[0], status);
+                       *gen_err = 1;
+               }
+
        /*
         * Check the current card state.  If it is in some data transfer
         * mode, tell it to stop (and hopefully transition back to TRAN.)
@@ -869,6 +879,13 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
                        return ERR_ABORT;
                if (stop_status & R1_CARD_ECC_FAILED)
                        *ecc_err = 1;
+               if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
+                       if (stop_status & R1_ERROR) {
+                               pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
+                                      req->rq_disk->disk_name, __func__,
+                                      stop_status);
+                               *gen_err = 1;
+                       }
        }
 
        /* Check for set block count errors */
@@ -1097,7 +1114,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
                                                    mmc_active);
        struct mmc_blk_request *brq = &mq_mrq->brq;
        struct request *req = mq_mrq->req;
-       int ecc_err = 0;
+       int ecc_err = 0, gen_err = 0;
 
        /*
         * sbc.error indicates a problem with the set block count
@@ -1111,7 +1128,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
         */
        if (brq->sbc.error || brq->cmd.error || brq->stop.error ||
            brq->data.error) {
-               switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) {
+               switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) {
                case ERR_RETRY:
                        return MMC_BLK_RETRY;
                case ERR_ABORT:
@@ -1143,6 +1160,14 @@ static int mmc_blk_err_check(struct mmc_card *card,
                u32 status;
                unsigned long timeout;
 
+               /* Check stop command response */
+               if (brq->stop.resp[0] & R1_ERROR) {
+                       pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
+                              req->rq_disk->disk_name, __func__,
+                              brq->stop.resp[0]);
+                       gen_err = 1;
+               }
+
                timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
                do {
                        int err = get_card_status(card, &status, 5);
@@ -1152,6 +1177,13 @@ static int mmc_blk_err_check(struct mmc_card *card,
                                return MMC_BLK_CMD_ERR;
                        }
 
+                       if (status & R1_ERROR) {
+                               pr_err("%s: %s: general error sending status command, card status %#x\n",
+                                      req->rq_disk->disk_name, __func__,
+                                      status);
+                               gen_err = 1;
+                       }
+
                        /* Timeout if the device never becomes ready for data
                         * and never leaves the program state.
                         */
@@ -1171,6 +1203,13 @@ static int mmc_blk_err_check(struct mmc_card *card,
                         (R1_CURRENT_STATE(status) == R1_STATE_PRG));
        }
 
+       /* if general error occurs, retry the write operation. */
+       if (gen_err) {
+               pr_warn("%s: retrying write for general error\n",
+                               req->rq_disk->disk_name);
+               return MMC_BLK_RETRY;
+       }
+
        if (brq->data.error) {
                pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
                       req->rq_disk->disk_name, brq->data.error,
@@ -2191,10 +2230,10 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
                 * is freeing the queue that stops new requests
                 * from being accepted.
                 */
+               card = md->queue.card;
                mmc_cleanup_queue(&md->queue);
                if (md->flags & MMC_BLK_PACKED_CMD)
                        mmc_packed_clean(&md->queue);
-               card = md->queue.card;
                if (md->disk->flags & GENHD_FL_UP) {
                        device_remove_file(disk_to_dev(md->disk), &md->force_ro);
                        if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
index a69df52..0c0fc52 100644 (file)
@@ -2849,18 +2849,12 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,
        struct seq_file *sf = (struct seq_file *)file->private_data;
        struct mmc_card *card = (struct mmc_card *)sf->private;
        struct mmc_test_card *test;
-       char lbuf[12];
        long testcase;
+       int ret;
 
-       if (count >= sizeof(lbuf))
-               return -EINVAL;
-
-       if (copy_from_user(lbuf, buf, count))
-               return -EFAULT;
-       lbuf[count] = '\0';
-
-       if (strict_strtol(lbuf, 10, &testcase))
-               return -EINVAL;
+       ret = kstrtol_from_user(buf, count, 10, &testcase);
+       if (ret)
+               return ret;
 
        test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
        if (!test)
index 5d08855..bf18b6b 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/fault-inject.h>
 #include <linux/random.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -1196,6 +1197,49 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
 }
 EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
 
+#ifdef CONFIG_OF
+
+/**
+ * mmc_of_parse_voltage - return mask of supported voltages
+ * @np: The device node need to be parsed.
+ * @mask: mask of voltages available for MMC/SD/SDIO
+ *
+ * 1. Return zero on success.
+ * 2. Return negative errno: voltage-range is invalid.
+ */
+int mmc_of_parse_voltage(struct device_node *np, u32 *mask)
+{
+       const u32 *voltage_ranges;
+       int num_ranges, i;
+
+       voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
+       num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
+       if (!voltage_ranges || !num_ranges) {
+               pr_info("%s: voltage-ranges unspecified\n", np->full_name);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < num_ranges; i++) {
+               const int j = i * 2;
+               u32 ocr_mask;
+
+               ocr_mask = mmc_vddrange_to_ocrmask(
+                               be32_to_cpu(voltage_ranges[j]),
+                               be32_to_cpu(voltage_ranges[j + 1]));
+               if (!ocr_mask) {
+                       pr_err("%s: voltage-range #%d is invalid\n",
+                               np->full_name, i);
+                       return -EINVAL;
+               }
+               *mask |= ocr_mask;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(mmc_of_parse_voltage);
+
+#endif /* CONFIG_OF */
+
 #ifdef CONFIG_REGULATOR
 
 /**
index 6fb6f77..49bc403 100644 (file)
@@ -374,7 +374,7 @@ int mmc_of_parse(struct mmc_host *host)
                        if (!(flags & OF_GPIO_ACTIVE_LOW))
                                gpio_inv_cd = true;
 
-                       ret = mmc_gpio_request_cd(host, gpio);
+                       ret = mmc_gpio_request_cd(host, gpio, 0);
                        if (ret < 0) {
                                dev_err(host->parent,
                                        "Failed to request CD GPIO #%d: %d!\n",
index 837fc73..ef18348 100644 (file)
@@ -531,6 +531,7 @@ mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
 
        data.sg = &sg;
        data.sg_len = 1;
+       mmc_set_data_timeout(&data, card);
        sg_init_one(&sg, data_buf, len);
        mmc_wait_for_req(host, &mrq);
        err = 0;
index 176d125..5e8823d 100644 (file)
@@ -215,7 +215,7 @@ static int mmc_decode_scr(struct mmc_card *card)
 static int mmc_read_ssr(struct mmc_card *card)
 {
        unsigned int au, es, et, eo;
-       int err, i;
+       int err, i, max_au;
        u32 *ssr;
 
        if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
@@ -239,12 +239,15 @@ static int mmc_read_ssr(struct mmc_card *card)
        for (i = 0; i < 16; i++)
                ssr[i] = be32_to_cpu(ssr[i]);
 
+       /* SD3.0 increases max AU size to 64MB (0xF) from 4MB (0x9) */
+       max_au = card->scr.sda_spec3 ? 0xF : 0x9;
+
        /*
         * UNSTUFF_BITS only works with four u32s so we have to offset the
         * bitfield positions accordingly.
         */
        au = UNSTUFF_BITS(ssr, 428 - 384, 4);
-       if (au > 0 && au <= 9) {
+       if (au > 0 && au <= max_au) {
                card->ssr.au = 1 << (au + 4);
                es = UNSTUFF_BITS(ssr, 408 - 384, 16);
                et = UNSTUFF_BITS(ssr, 402 - 384, 6);
@@ -942,13 +945,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
        if (!mmc_host_is_spi(host)) {
                err = mmc_send_relative_addr(host, &card->rca);
                if (err)
-                       return err;
+                       goto free_card;
        }
 
        if (!oldcard) {
                err = mmc_sd_get_csd(host, card);
                if (err)
-                       return err;
+                       goto free_card;
 
                mmc_decode_cid(card);
        }
@@ -959,7 +962,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
        if (!mmc_host_is_spi(host)) {
                err = mmc_select_card(card);
                if (err)
-                       return err;
+                       goto free_card;
        }
 
        err = mmc_sd_setup_card(host, card, oldcard != NULL);
index 3242351..46596b7 100644 (file)
@@ -135,6 +135,7 @@ EXPORT_SYMBOL(mmc_gpio_request_ro);
  * mmc_gpio_request_cd - request a gpio for card-detection
  * @host: mmc host
  * @gpio: gpio number requested
+ * @debounce: debounce time in microseconds
  *
  * As devm_* managed functions are used in mmc_gpio_request_cd(), client
  * drivers do not need to explicitly call mmc_gpio_free_cd() for freeing up,
@@ -143,9 +144,14 @@ EXPORT_SYMBOL(mmc_gpio_request_ro);
  * switching for card-detection, they are responsible for calling
  * mmc_gpio_request_cd() and mmc_gpio_free_cd() as a pair on their own.
  *
+ * If GPIO debouncing is desired, set the debounce parameter to a non-zero
+ * value. The caller is responsible for ensuring that the GPIO driver associated
+ * with the GPIO supports debouncing, otherwise an error will be returned.
+ *
  * Returns zero on success, else an error.
  */
-int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
+int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,
+                       unsigned int debounce)
 {
        struct mmc_gpio *ctx;
        int irq = gpio_to_irq(gpio);
@@ -167,6 +173,12 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
                 */
                return ret;
 
+       if (debounce) {
+               ret = gpio_set_debounce(gpio, debounce);
+               if (ret < 0)
+                       return ret;
+       }
+
        /*
         * Even if gpio_to_irq() returns a valid IRQ number, the platform might
         * still prefer to poll, e.g., because that IRQ number is already used
index 8a4c066..b7fd5ab 100644 (file)
@@ -284,11 +284,11 @@ config MMC_OMAP
 
 config MMC_OMAP_HS
        tristate "TI OMAP High Speed Multimedia Card Interface support"
-       depends on SOC_OMAP2430 || ARCH_OMAP3 || ARCH_OMAP4
+       depends on ARCH_OMAP2PLUS || COMPILE_TEST
        help
          This selects the TI OMAP High Speed Multimedia card Interface.
-         If you have an OMAP2430 or OMAP3 board or OMAP4 board with a
-         Multimedia Card slot, say Y or M here.
+         If you have an omap2plus board with a Multimedia Card slot,
+         say Y or M here.
 
          If unsure, say N.
 
@@ -530,7 +530,7 @@ config SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
 
 config MMC_DW
        tristate "Synopsys DesignWare Memory Card Interface"
-       depends on ARM
+       depends on ARC || ARM
        help
          This selects support for the Synopsys DesignWare Mobile Storage IP
          block, this provides host support for SD and MMC interfaces, in both
@@ -569,7 +569,7 @@ config MMC_DW_EXYNOS
 
 config MMC_DW_SOCFPGA
        tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface"
-       depends on MMC_DW
+       depends on MMC_DW && MFD_SYSCON
        select MMC_DW_PLTFM
        help
          This selects support for Altera SoCFPGA specific extensions to the
index d422e21..c41d0c3 100644 (file)
@@ -52,8 +52,6 @@ obj-$(CONFIG_MMC_WMT)         += wmt-sdmmc.o
 
 obj-$(CONFIG_MMC_REALTEK_PCI)  += rtsx_pci_sdmmc.o
 
-obj-$(CONFIG_MMC_REALTEK_PCI)  += rtsx_pci_sdmmc.o
-
 obj-$(CONFIG_MMC_SDHCI_PLTFM)          += sdhci-pltfm.o
 obj-$(CONFIG_MMC_SDHCI_CNS3XXX)                += sdhci-cns3xxx.o
 obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX)      += sdhci-esdhc-imx.o
index bdb84da..69e438e 100644 (file)
@@ -378,6 +378,8 @@ static int atmci_regs_show(struct seq_file *s, void *v)
 {
        struct atmel_mci        *host = s->private;
        u32                     *buf;
+       int                     ret = 0;
+
 
        buf = kmalloc(ATMCI_REGS_SIZE, GFP_KERNEL);
        if (!buf)
@@ -388,12 +390,16 @@ static int atmci_regs_show(struct seq_file *s, void *v)
         * not disabling interrupts, so IMR and SR may not be
         * consistent.
         */
+       ret = clk_prepare_enable(host->mck);
+       if (ret)
+               goto out;
+
        spin_lock_bh(&host->lock);
-       clk_enable(host->mck);
        memcpy_fromio(buf, host->regs, ATMCI_REGS_SIZE);
-       clk_disable(host->mck);
        spin_unlock_bh(&host->lock);
 
+       clk_disable_unprepare(host->mck);
+
        seq_printf(s, "MR:\t0x%08x%s%s ",
                        buf[ATMCI_MR / 4],
                        buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "",
@@ -442,9 +448,10 @@ static int atmci_regs_show(struct seq_file *s, void *v)
                                val & ATMCI_CFG_LSYNC ? " LSYNC" : "");
        }
 
+out:
        kfree(buf);
 
-       return 0;
+       return ret;
 }
 
 static int atmci_regs_open(struct inode *inode, struct file *file)
@@ -1262,6 +1269,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        struct atmel_mci_slot   *slot = mmc_priv(mmc);
        struct atmel_mci        *host = slot->host;
        unsigned int            i;
+       bool                    unprepare_clk;
 
        slot->sdc_reg &= ~ATMCI_SDCBUS_MASK;
        switch (ios->bus_width) {
@@ -1277,9 +1285,13 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                unsigned int clock_min = ~0U;
                u32 clkdiv;
 
+               clk_prepare(host->mck);
+               unprepare_clk = true;
+
                spin_lock_bh(&host->lock);
                if (!host->mode_reg) {
                        clk_enable(host->mck);
+                       unprepare_clk = false;
                        atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
                        atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
                        if (host->caps.has_cfg_reg)
@@ -1347,6 +1359,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        } else {
                bool any_slot_active = false;
 
+               unprepare_clk = false;
+
                spin_lock_bh(&host->lock);
                slot->clock = 0;
                for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
@@ -1360,12 +1374,16 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                        if (host->mode_reg) {
                                atmci_readl(host, ATMCI_MR);
                                clk_disable(host->mck);
+                               unprepare_clk = true;
                        }
                        host->mode_reg = 0;
                }
                spin_unlock_bh(&host->lock);
        }
 
+       if (unprepare_clk)
+               clk_unprepare(host->mck);
+
        switch (ios->power_mode) {
        case MMC_POWER_UP:
                set_bit(ATMCI_CARD_NEED_INIT, &slot->flags);
@@ -2376,10 +2394,12 @@ static int __init atmci_probe(struct platform_device *pdev)
        if (!host->regs)
                goto err_ioremap;
 
-       clk_enable(host->mck);
+       ret = clk_prepare_enable(host->mck);
+       if (ret)
+               goto err_request_irq;
        atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
        host->bus_hz = clk_get_rate(host->mck);
-       clk_disable(host->mck);
+       clk_disable_unprepare(host->mck);
 
        host->mapbase = regs->start;
 
@@ -2482,11 +2502,11 @@ static int __exit atmci_remove(struct platform_device *pdev)
                        atmci_cleanup_slot(host->slot[i], i);
        }
 
-       clk_enable(host->mck);
+       clk_prepare_enable(host->mck);
        atmci_writel(host, ATMCI_IDR, ~0UL);
        atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS);
        atmci_readl(host, ATMCI_SR);
-       clk_disable(host->mck);
+       clk_disable_unprepare(host->mck);
 
        if (host->dma.chan)
                dma_release_channel(host->dma.chan);
index 866edef..6a1fa21 100644 (file)
@@ -39,6 +39,7 @@ enum dw_mci_exynos_type {
        DW_MCI_TYPE_EXYNOS4210,
        DW_MCI_TYPE_EXYNOS4412,
        DW_MCI_TYPE_EXYNOS5250,
+       DW_MCI_TYPE_EXYNOS5420,
 };
 
 /* Exynos implementation specific driver private data */
@@ -62,6 +63,9 @@ static struct dw_mci_exynos_compatible {
        }, {
                .compatible     = "samsung,exynos5250-dw-mshc",
                .ctrl_type      = DW_MCI_TYPE_EXYNOS5250,
+       }, {
+               .compatible     = "samsung,exynos5420-dw-mshc",
+               .ctrl_type      = DW_MCI_TYPE_EXYNOS5420,
        },
 };
 
@@ -90,7 +94,8 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host)
 {
        struct dw_mci_exynos_priv_data *priv = host->priv;
 
-       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250)
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420)
                host->bus_hz /= (priv->ciu_div + 1);
        else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
                host->bus_hz /= EXYNOS4412_FIXED_CIU_CLK_DIV;
@@ -173,6 +178,8 @@ static const struct of_device_id dw_mci_exynos_match[] = {
                        .data = &exynos_drv_data, },
        { .compatible = "samsung,exynos5250-dw-mshc",
                        .data = &exynos_drv_data, },
+       { .compatible = "samsung,exynos5420-dw-mshc",
+                       .data = &exynos_drv_data, },
        {},
 };
 MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
index b456b0c..f70546a 100644 (file)
@@ -59,7 +59,9 @@ static int dw_mci_pci_probe(struct pci_dev *pdev,
        if (ret)
                return ret;
 
-       host->regs = pcim_iomap_table(pdev)[0];
+       host->regs = pcim_iomap_table(pdev)[PCI_BAR_NO];
+
+       pci_set_master(pdev);
 
        ret = dw_mci_probe(host);
        if (ret)
index ee52556..2089752 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/of.h>
 
 #include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
 
 static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
 {
index 5424073..018f365 100644 (file)
@@ -1601,18 +1601,17 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 
        pending = mci_readl(host, MINTSTS); /* read-only mask reg */
 
-       if (pending) {
-
-               /*
-                * DTO fix - version 2.10a and below, and only if internal DMA
-                * is configured.
-                */
-               if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) {
-                       if (!pending &&
-                           ((mci_readl(host, STATUS) >> 17) & 0x1fff))
-                               pending |= SDMMC_INT_DATA_OVER;
-               }
+       /*
+        * DTO fix - version 2.10a and below, and only if internal DMA
+        * is configured.
+        */
+       if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) {
+               if (!pending &&
+                   ((mci_readl(host, STATUS) >> 17) & 0x1fff))
+                       pending |= SDMMC_INT_DATA_OVER;
+       }
 
+       if (pending) {
                if (pending & DW_MCI_CMD_ERROR_FLAGS) {
                        mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
                        host->cmd_status = pending;
index 0308c9f..6651633 100644 (file)
@@ -713,7 +713,7 @@ static int jz4740_mmc_request_gpios(struct mmc_host *mmc,
                mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
 
        if (gpio_is_valid(pdata->gpio_card_detect)) {
-               ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect);
+               ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect, 0);
                if (ret)
                        return ret;
        }
@@ -783,9 +783,8 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        host->base = devm_ioremap_resource(&pdev->dev, res);
-       if (!host->base) {
-               ret = -EBUSY;
-               dev_err(&pdev->dev, "Failed to ioremap base memory\n");
+       if (IS_ERR(host->base)) {
+               ret = PTR_ERR(host->base);
                goto err_free_host;
        }
 
index 74145d1..0a87e56 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>             /* for R1_SPI_* bit values */
+#include <linux/mmc/slot-gpio.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/mmc_spi.h>
@@ -1272,33 +1273,11 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        }
 }
 
-static int mmc_spi_get_ro(struct mmc_host *mmc)
-{
-       struct mmc_spi_host *host = mmc_priv(mmc);
-
-       if (host->pdata && host->pdata->get_ro)
-               return !!host->pdata->get_ro(mmc->parent);
-       /*
-        * Board doesn't support read only detection; let the mmc core
-        * decide what to do.
-        */
-       return -ENOSYS;
-}
-
-static int mmc_spi_get_cd(struct mmc_host *mmc)
-{
-       struct mmc_spi_host *host = mmc_priv(mmc);
-
-       if (host->pdata && host->pdata->get_cd)
-               return !!host->pdata->get_cd(mmc->parent);
-       return -ENOSYS;
-}
-
 static const struct mmc_host_ops mmc_spi_ops = {
        .request        = mmc_spi_request,
        .set_ios        = mmc_spi_set_ios,
-       .get_ro         = mmc_spi_get_ro,
-       .get_cd         = mmc_spi_get_cd,
+       .get_ro         = mmc_gpio_get_ro,
+       .get_cd         = mmc_gpio_get_cd,
 };
 
 
@@ -1324,6 +1303,7 @@ static int mmc_spi_probe(struct spi_device *spi)
        struct mmc_host         *mmc;
        struct mmc_spi_host     *host;
        int                     status;
+       bool                    has_ro = false;
 
        /* We rely on full duplex transfers, mostly to reduce
         * per-transfer overheads (by making fewer transfers).
@@ -1448,18 +1428,33 @@ static int mmc_spi_probe(struct spi_device *spi)
        }
 
        /* pass platform capabilities, if any */
-       if (host->pdata)
+       if (host->pdata) {
                mmc->caps |= host->pdata->caps;
+               mmc->caps2 |= host->pdata->caps2;
+       }
 
        status = mmc_add_host(mmc);
        if (status != 0)
                goto fail_add_host;
 
+       if (host->pdata && host->pdata->flags & MMC_SPI_USE_CD_GPIO) {
+               status = mmc_gpio_request_cd(mmc, host->pdata->cd_gpio,
+                                            host->pdata->cd_debounce);
+               if (status != 0)
+                       goto fail_add_host;
+       }
+
+       if (host->pdata && host->pdata->flags & MMC_SPI_USE_RO_GPIO) {
+               has_ro = true;
+               status = mmc_gpio_request_ro(mmc, host->pdata->ro_gpio);
+               if (status != 0)
+                       goto fail_add_host;
+       }
+
        dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n",
                        dev_name(&mmc->class_dev),
                        host->dma_dev ? "" : ", no DMA",
-                       (host->pdata && host->pdata->get_ro)
-                               ? "" : ", no WP",
+                       has_ro ? "" : ", no WP",
                        (host->pdata && host->pdata->setpower)
                                ? "" : ", no poweroff",
                        (mmc->caps & MMC_CAP_NEEDS_POLL)
index 4ddd83f..06c5b0b 100644 (file)
@@ -757,7 +757,8 @@ static int __init mvsd_probe(struct platform_device *pdev)
                if (mvsd_data->gpio_card_detect &&
                    gpio_is_valid(mvsd_data->gpio_card_detect)) {
                        ret = mmc_gpio_request_cd(mmc,
-                                                 mvsd_data->gpio_card_detect);
+                                                 mvsd_data->gpio_card_detect,
+                                                 0);
                        if (ret)
                                goto out;
                } else {
index f38d75f..e1fa3ef 100644 (file)
@@ -102,12 +102,15 @@ static int mxs_mmc_get_cd(struct mmc_host *mmc)
                  BM_SSP_STATUS_CARD_DETECT) ^ host->cd_inverted;
 }
 
-static void mxs_mmc_reset(struct mxs_mmc_host *host)
+static int mxs_mmc_reset(struct mxs_mmc_host *host)
 {
        struct mxs_ssp *ssp = &host->ssp;
        u32 ctrl0, ctrl1;
+       int ret;
 
-       stmp_reset_block(ssp->base);
+       ret = stmp_reset_block(ssp->base);
+       if (ret)
+               return ret;
 
        ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
        ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) |
@@ -132,6 +135,7 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host)
 
        writel(ctrl0, ssp->base + HW_SSP_CTRL0);
        writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp));
+       return 0;
 }
 
 static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
@@ -618,21 +622,25 @@ static int mxs_mmc_probe(struct platform_device *pdev)
                }
        }
 
-       ssp->clk = clk_get(&pdev->dev, NULL);
+       ssp->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(ssp->clk)) {
                ret = PTR_ERR(ssp->clk);
                goto out_mmc_free;
        }
        clk_prepare_enable(ssp->clk);
 
-       mxs_mmc_reset(host);
+       ret = mxs_mmc_reset(host);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to reset mmc: %d\n", ret);
+               goto out_clk_disable;
+       }
 
        ssp->dmach = dma_request_slave_channel(&pdev->dev, "rx-tx");
        if (!ssp->dmach) {
                dev_err(mmc_dev(host->mmc),
                        "%s: failed to request dma\n", __func__);
                ret = -ENODEV;
-               goto out_clk_put;
+               goto out_clk_disable;
        }
 
        /* set mmc core parameters */
@@ -685,9 +693,8 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 out_free_dma:
        if (ssp->dmach)
                dma_release_channel(ssp->dmach);
-out_clk_put:
+out_clk_disable:
        clk_disable_unprepare(ssp->clk);
-       clk_put(ssp->clk);
 out_mmc_free:
        mmc_free_host(mmc);
        return ret;
@@ -705,7 +712,6 @@ static int mxs_mmc_remove(struct platform_device *pdev)
                dma_release_channel(ssp->dmach);
 
        clk_disable_unprepare(ssp->clk);
-       clk_put(ssp->clk);
 
        mmc_free_host(mmc);
 
index d720b5e..6e218fb 100644 (file)
@@ -50,25 +50,6 @@ static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
        return container_of(dev->platform_data, struct of_mmc_spi, pdata);
 }
 
-static int of_mmc_spi_read_gpio(struct device *dev, int gpio_num)
-{
-       struct of_mmc_spi *oms = to_of_mmc_spi(dev);
-       bool active_low = oms->alow_gpios[gpio_num];
-       bool value = gpio_get_value(oms->gpios[gpio_num]);
-
-       return active_low ^ value;
-}
-
-static int of_mmc_spi_get_cd(struct device *dev)
-{
-       return of_mmc_spi_read_gpio(dev, CD_GPIO);
-}
-
-static int of_mmc_spi_get_ro(struct device *dev)
-{
-       return of_mmc_spi_read_gpio(dev, WP_GPIO);
-}
-
 static int of_mmc_spi_init(struct device *dev,
                           irqreturn_t (*irqhandler)(int, void *), void *mmc)
 {
@@ -130,20 +111,22 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
                if (!gpio_is_valid(oms->gpios[i]))
                        continue;
 
-               ret = gpio_request(oms->gpios[i], dev_name(dev));
-               if (ret < 0) {
-                       oms->gpios[i] = -EINVAL;
-                       continue;
-               }
-
                if (gpio_flags & OF_GPIO_ACTIVE_LOW)
                        oms->alow_gpios[i] = true;
        }
 
-       if (gpio_is_valid(oms->gpios[CD_GPIO]))
-               oms->pdata.get_cd = of_mmc_spi_get_cd;
-       if (gpio_is_valid(oms->gpios[WP_GPIO]))
-               oms->pdata.get_ro = of_mmc_spi_get_ro;
+       if (gpio_is_valid(oms->gpios[CD_GPIO])) {
+               oms->pdata.cd_gpio = oms->gpios[CD_GPIO];
+               oms->pdata.flags |= MMC_SPI_USE_CD_GPIO;
+               if (!oms->alow_gpios[CD_GPIO])
+                       oms->pdata.caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
+       }
+       if (gpio_is_valid(oms->gpios[WP_GPIO])) {
+               oms->pdata.ro_gpio = oms->gpios[WP_GPIO];
+               oms->pdata.flags |= MMC_SPI_USE_RO_GPIO;
+               if (!oms->alow_gpios[WP_GPIO])
+                       oms->pdata.caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
+       }
 
        oms->detect_irq = irq_of_parse_and_map(np, 0);
        if (oms->detect_irq != 0) {
@@ -166,15 +149,10 @@ void mmc_spi_put_pdata(struct spi_device *spi)
        struct device *dev = &spi->dev;
        struct device_node *np = dev->of_node;
        struct of_mmc_spi *oms = to_of_mmc_spi(dev);
-       int i;
 
        if (!dev->platform_data || !np)
                return;
 
-       for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) {
-               if (gpio_is_valid(oms->gpios[i]))
-                       gpio_free(oms->gpios[i]);
-       }
        kfree(oms);
        dev->platform_data = NULL;
 }
index 1865321..6ac63df 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/debugfs.h>
 #include <linux/dmaengine.h>
 #include <linux/seq_file.h>
+#include <linux/sizes.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
@@ -1041,6 +1042,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
                }
        }
 
+       OMAP_HSMMC_WRITE(host->base, STAT, status);
        if (end_cmd || ((status & CC_EN) && host->cmd))
                omap_hsmmc_cmd_done(host, host->cmd);
        if ((end_trans || (status & TC_EN)) && host->mrq)
@@ -1060,7 +1062,6 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
                omap_hsmmc_do_irq(host, status);
 
                /* Flush posted write */
-               OMAP_HSMMC_WRITE(host->base, STAT, status);
                status = OMAP_HSMMC_READ(host->base, STAT);
        }
 
index 0584a1c..36fa2df 100644 (file)
@@ -119,7 +119,7 @@ static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg)
        return byte;
 }
 
-unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host)
+static unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host)
 {
        return MIN_FREQ;
 }
index 1dd5ba8..abc8cf0 100644 (file)
@@ -616,7 +616,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
        /* card_detect */
        switch (boarddata->cd_type) {
        case ESDHC_CD_GPIO:
-               err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio);
+               err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0);
                if (err) {
                        dev_err(mmc_dev(host->mmc),
                                "failed to request card-detect gpio!\n");
index 15039e2..e328252 100644 (file)
@@ -316,6 +316,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
 
        /* call to generic mmc_of_parse to support additional capabilities */
        mmc_of_parse(host->mmc);
+       mmc_of_parse_voltage(np, &host->ocr_mask);
 
        ret = sdhci_add_host(host);
        if (ret)
index bf99359..793dacd 100644 (file)
@@ -278,7 +278,8 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
                        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);
+                       ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio,
+                                                 0);
                        if (ret) {
                                dev_err(mmc_dev(host->mmc),
                                        "failed to allocate card detect gpio\n");
index 926aaf6..6debda9 100644 (file)
@@ -296,9 +296,12 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
        unsigned long timeout;
        u16 clk = 0;
 
-       /* don't bother if the clock is going off */
-       if (clock == 0)
+       /* If the clock is going off, set to 0 at clock control register */
+       if (clock == 0) {
+               sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+               host->clock = clock;
                return;
+       }
 
        sdhci_s3c_set_clock(host, clock);
 
@@ -608,6 +611,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
        host->hw_name = "samsung-hsmmc";
        host->ops = &sdhci_s3c_ops;
        host->quirks = 0;
+       host->quirks2 = 0;
        host->irq = irq;
 
        /* Setup quirks for the controller */
index 62a4a83..696122c 100644 (file)
@@ -84,7 +84,7 @@ static int sdhci_sirf_probe(struct platform_device *pdev)
         * gets setup in sdhci_add_host() and we oops.
         */
        if (gpio_is_valid(priv->gpio_cd)) {
-               ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd);
+               ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd, 0);
                if (ret) {
                        dev_err(&pdev->dev, "card detect irq request failed: %d\n",
                                ret);
index dd2c083..7a7fb4f 100644 (file)
@@ -3119,6 +3119,9 @@ int sdhci_add_host(struct sdhci_host *host)
                                   SDHCI_MAX_CURRENT_MULTIPLIER;
        }
 
+       if (host->ocr_mask)
+               ocr_avail = host->ocr_mask;
+
        mmc->ocr_avail = ocr_avail;
        mmc->ocr_avail_sdio = ocr_avail;
        if (host->ocr_avail_sdio)
@@ -3213,6 +3216,8 @@ int sdhci_add_host(struct sdhci_host *host)
                host->tuning_timer.function = sdhci_tuning_timer;
        }
 
+       sdhci_init(host, 0);
+
        ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
                mmc_hostname(mmc), host);
        if (ret) {
@@ -3221,8 +3226,6 @@ int sdhci_add_host(struct sdhci_host *host)
                goto untasklet;
        }
 
-       sdhci_init(host, 0);
-
 #ifdef CONFIG_MMC_DEBUG
        sdhci_dumpregs(host);
 #endif
index 6706b5e..36629a0 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_qos.h>
 #include <linux/pm_runtime.h>
+#include <linux/sh_dma.h>
 #include <linux/spinlock.h>
 #include <linux/module.h>
 
                                 INT_BUFWEN | INT_CMD12DRE | INT_BUFRE | \
                                 INT_DTRANE | INT_CMD12RBE | INT_CMD12CRE)
 
+#define INT_CCS                        (INT_CCSTO | INT_CCSRCV | INT_CCSDE)
+
 /* CE_INT_MASK */
 #define MASK_ALL               0x00000000
 #define MASK_MCCSDE            (1 << 29)
 
 #define MASK_START_CMD         (MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \
                                 MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \
-                                MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | \
+                                MASK_MCRCSTO | MASK_MWDATTO | \
                                 MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO)
 
 #define MASK_CLEAN             (INT_ERR_STS | MASK_MRBSYE | MASK_MCRSPE |      \
@@ -243,6 +246,8 @@ struct sh_mmcif_host {
        int sg_blkidx;
        bool power;
        bool card_present;
+       bool ccs_enable;                /* Command Completion Signal support */
+       bool clk_ctrl2_enable;
        struct mutex thread_lock;
 
        /* DMA support */
@@ -386,25 +391,29 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
 
        host->dma_active = false;
 
-       if (!pdata)
-               return;
-
-       if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
+       if (pdata) {
+               if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
+                       return;
+       } else if (!host->pd->dev.of_node) {
                return;
+       }
 
        /* We can only either use DMA for both Tx and Rx or not use it at all */
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
 
-       host->chan_tx = dma_request_channel(mask, shdma_chan_filter,
-                                           (void *)pdata->slave_id_tx);
+       host->chan_tx = dma_request_slave_channel_compat(mask, shdma_chan_filter,
+                               pdata ? (void *)pdata->slave_id_tx : NULL,
+                               &host->pd->dev, "tx");
        dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
                host->chan_tx);
 
        if (!host->chan_tx)
                return;
 
-       cfg.slave_id = pdata->slave_id_tx;
+       /* In the OF case the driver will get the slave ID from the DT */
+       if (pdata)
+               cfg.slave_id = pdata->slave_id_tx;
        cfg.direction = DMA_MEM_TO_DEV;
        cfg.dst_addr = res->start + MMCIF_CE_DATA;
        cfg.src_addr = 0;
@@ -412,15 +421,17 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
        if (ret < 0)
                goto ecfgtx;
 
-       host->chan_rx = dma_request_channel(mask, shdma_chan_filter,
-                                           (void *)pdata->slave_id_rx);
+       host->chan_rx = dma_request_slave_channel_compat(mask, shdma_chan_filter,
+                               pdata ? (void *)pdata->slave_id_rx : NULL,
+                               &host->pd->dev, "rx");
        dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
                host->chan_rx);
 
        if (!host->chan_rx)
                goto erqrx;
 
-       cfg.slave_id = pdata->slave_id_rx;
+       if (pdata)
+               cfg.slave_id = pdata->slave_id_rx;
        cfg.direction = DMA_DEV_TO_MEM;
        cfg.dst_addr = 0;
        cfg.src_addr = res->start + MMCIF_CE_DATA;
@@ -485,8 +496,12 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host)
 
        sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_ON);
        sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_OFF);
+       if (host->ccs_enable)
+               tmp |= SCCSTO_29;
+       if (host->clk_ctrl2_enable)
+               sh_mmcif_writel(host->addr, MMCIF_CE_CLK_CTRL2, 0x0F0F0000);
        sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, tmp |
-               SRSPTO_256 | SRBSYTO_29 | SRWDTO_29 | SCCSTO_29);
+               SRSPTO_256 | SRBSYTO_29 | SRWDTO_29);
        /* byte swap on */
        sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP);
 }
@@ -866,6 +881,9 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
                break;
        }
 
+       if (host->ccs_enable)
+               mask |= MASK_MCCSTO;
+
        if (mrq->data) {
                sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0);
                sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET,
@@ -873,7 +891,10 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
        }
        opc = sh_mmcif_set_cmd(host, mrq);
 
-       sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0);
+       if (host->ccs_enable)
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0);
+       else
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0 | INT_CCS);
        sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
        /* set arg */
        sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
@@ -956,11 +977,8 @@ static int sh_mmcif_clk_update(struct sh_mmcif_host *host)
 
 static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios)
 {
-       struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
        struct mmc_host *mmc = host->mmc;
 
-       if (pd && pd->set_pwr)
-               pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF);
        if (!IS_ERR(mmc->supply.vmmc))
                /* Errors ignored... */
                mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
@@ -1241,11 +1259,14 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
 static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
 {
        struct sh_mmcif_host *host = dev_id;
-       u32 state;
+       u32 state, mask;
 
        state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
-       sh_mmcif_writel(host->addr, MMCIF_CE_INT,
-                       ~(state & sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK)));
+       mask = sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK);
+       if (host->ccs_enable)
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~(state & mask));
+       else
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT, INT_CCS | ~(state & mask));
        sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN);
 
        if (state & ~MASK_CLEAN)
@@ -1379,6 +1400,8 @@ static int sh_mmcif_probe(struct platform_device *pdev)
        host->mmc       = mmc;
        host->addr      = reg;
        host->timeout   = msecs_to_jiffies(1000);
+       host->ccs_enable = !pd || !pd->ccs_unsupported;
+       host->clk_ctrl2_enable = pd && pd->clk_ctrl2_present;
 
        host->pd = pdev;
 
@@ -1436,7 +1459,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
        }
 
        if (pd && pd->use_cd_gpio) {
-               ret = mmc_gpio_request_cd(mmc, pd->cd_gpio);
+               ret = mmc_gpio_request_cd(mmc, pd->cd_gpio, 0);
                if (ret < 0)
                        goto erqcd;
        }
index ebea749..87ed3fb 100644 (file)
@@ -70,20 +70,6 @@ static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev)
        clk_disable(priv->clk);
 }
 
-static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
-{
-       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-
-       p->set_pwr(pdev, state);
-}
-
-static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
-{
-       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-
-       return p->get_cd(pdev);
-}
-
 static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
 {
        int timeout = 1000;
@@ -129,7 +115,12 @@ static const struct sh_mobile_sdhi_ops sdhi_ops = {
 static const struct of_device_id sh_mobile_sdhi_of_match[] = {
        { .compatible = "renesas,shmobile-sdhi" },
        { .compatible = "renesas,sh7372-sdhi" },
+       { .compatible = "renesas,sh73a0-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
+       { .compatible = "renesas,r8a73a4-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
        { .compatible = "renesas,r8a7740-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
+       { .compatible = "renesas,r8a7778-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
+       { .compatible = "renesas,r8a7779-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
+       { .compatible = "renesas,r8a7790-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
        {},
 };
 MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
@@ -180,10 +171,6 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
                mmc_data->capabilities |= p->tmio_caps;
                mmc_data->capabilities2 |= p->tmio_caps2;
                mmc_data->cd_gpio = p->cd_gpio;
-               if (p->set_pwr)
-                       mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
-               if (p->get_cd)
-                       mmc_data->get_cd = sh_mobile_sdhi_get_cd;
 
                if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
                        /*
index 47bdb8f..65edb4a 100644 (file)
@@ -104,6 +104,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
 pio:
        if (!desc) {
                /* DMA failed, fall back to PIO */
+               tmio_mmc_enable_dma(host, false);
                if (ret >= 0)
                        ret = -EIO;
                host->chan_rx = NULL;
@@ -116,7 +117,6 @@ pio:
                }
                dev_warn(&host->pdev->dev,
                         "DMA failed: %d, falling back to PIO\n", ret);
-               tmio_mmc_enable_dma(host, false);
        }
 
        dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
@@ -185,6 +185,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
 pio:
        if (!desc) {
                /* DMA failed, fall back to PIO */
+               tmio_mmc_enable_dma(host, false);
                if (ret >= 0)
                        ret = -EIO;
                host->chan_tx = NULL;
@@ -197,7 +198,6 @@ pio:
                }
                dev_warn(&host->pdev->dev,
                         "DMA failed: %d, falling back to PIO\n", ret);
-               tmio_mmc_enable_dma(host, false);
        }
 
        dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__,
index b72edb7..b380225 100644 (file)
@@ -795,9 +795,13 @@ static void tmio_mmc_power_on(struct tmio_mmc_host *host, unsigned short vdd)
         * omap_hsmmc.c driver does.
         */
        if (!IS_ERR(mmc->supply.vqmmc) && !ret) {
-               regulator_enable(mmc->supply.vqmmc);
+               ret = regulator_enable(mmc->supply.vqmmc);
                udelay(200);
        }
+
+       if (ret < 0)
+               dev_dbg(&host->pdev->dev, "Regulators failed to power up: %d\n",
+                       ret);
 }
 
 static void tmio_mmc_power_off(struct tmio_mmc_host *host)
@@ -932,25 +936,11 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
                 (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
 }
 
-static int tmio_mmc_get_cd(struct mmc_host *mmc)
-{
-       struct tmio_mmc_host *host = mmc_priv(mmc);
-       struct tmio_mmc_data *pdata = host->pdata;
-       int ret = mmc_gpio_get_cd(mmc);
-       if (ret >= 0)
-               return ret;
-
-       if (!pdata->get_cd)
-               return -ENOSYS;
-       else
-               return pdata->get_cd(host->pdev);
-}
-
 static const struct mmc_host_ops tmio_mmc_ops = {
        .request        = tmio_mmc_request,
        .set_ios        = tmio_mmc_set_ios,
        .get_ro         = tmio_mmc_get_ro,
-       .get_cd         = tmio_mmc_get_cd,
+       .get_cd         = mmc_gpio_get_cd,
        .enable_sdio_irq = tmio_mmc_enable_sdio_irq,
 };
 
@@ -1106,7 +1096,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host,
        dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
 
        if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
-               ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio);
+               ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio, 0);
                if (ret < 0) {
                        tmio_mmc_host_remove(_host);
                        return ret;
index cb9f361..e9028ad 100644 (file)
@@ -2079,7 +2079,7 @@ static void vub300_enable_sdio_irq(struct mmc_host *mmc, int enable)
        kref_put(&vub300->kref, vub300_delete);
 }
 
-void vub300_init_card(struct mmc_host *mmc, struct mmc_card *card)
+static void vub300_init_card(struct mmc_host *mmc, struct mmc_card *card)
 {                              /* NOT irq */
        struct vub300_mmc_host *vub300 = mmc_priv(mmc);
        dev_info(&vub300->udev->dev, "NO host QUIRKS for this card\n");
index ce35113..b22883d 100644 (file)
@@ -108,7 +108,6 @@ struct tmio_mmc_data {
        unsigned int                    cd_gpio;
        void (*set_pwr)(struct platform_device *host, int state);
        void (*set_clk_div)(struct platform_device *host, int state);
-       int (*get_cd)(struct platform_device *host);
        int (*write16_hook)(struct tmio_mmc_host *host, int addr);
        /* clock management callbacks */
        int (*clk_enable)(struct platform_device *pdev, unsigned int *f);
index 443243b..da51bec 100644 (file)
@@ -208,6 +208,8 @@ static inline void mmc_claim_host(struct mmc_host *host)
        __mmc_claim_host(host, NULL);
 }
 
+struct device_node;
 extern u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max);
+extern int mmc_of_parse_voltage(struct device_node *np, u32 *mask);
 
 #endif /* LINUX_MMC_CORE_H */
index e3c6a74..3e781b8 100644 (file)
@@ -171,6 +171,7 @@ struct sdhci_host {
        unsigned int            ocr_avail_sdio; /* OCR bit masks */
        unsigned int            ocr_avail_sd;
        unsigned int            ocr_avail_mmc;
+       u32 ocr_mask;           /* available voltages */
 
        wait_queue_head_t       buf_ready_int;  /* Waitqueue for Buffer Read Ready interrupt */
        unsigned int            tuning_done;    /* Condition flag set when CMD19 succeeds */
index e7d5dd6..ccd8fb2 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <linux/io.h>
 #include <linux/platform_device.h>
-#include <linux/sh_dma.h>
 
 /*
  * MMCIF : CE_CLK_CTRL [19:16]
  */
 
 struct sh_mmcif_plat_data {
-       void (*set_pwr)(struct platform_device *pdev, int state);
-       void (*down_pwr)(struct platform_device *pdev);
        int (*get_cd)(struct platform_device *pdef);
        unsigned int            slave_id_tx;    /* embedded slave_id_[tr]x */
        unsigned int            slave_id_rx;
        bool                    use_cd_gpio : 1;
+       bool                    ccs_unsupported : 1;
+       bool                    clk_ctrl2_present : 1;
        unsigned int            cd_gpio;
        u8                      sup_pclk;       /* 1 :SH7757, 0: SH7724/SH7372 */
        unsigned long           caps;
@@ -62,6 +61,7 @@ struct sh_mmcif_plat_data {
 #define MMCIF_CE_INT_MASK      0x00000044
 #define MMCIF_CE_HOST_STS1     0x00000048
 #define MMCIF_CE_HOST_STS2     0x0000004C
+#define MMCIF_CE_CLK_CTRL2     0x00000070
 #define MMCIF_CE_VERSION       0x0000007C
 
 /* CE_BUF_ACC */
index b76bcf0..68927ae 100644 (file)
@@ -25,8 +25,6 @@ struct sh_mobile_sdhi_info {
        unsigned long tmio_caps2;
        u32 tmio_ocr_mask;      /* available MMC voltages */
        unsigned int cd_gpio;
-       void (*set_pwr)(struct platform_device *pdev, int state);
-       int (*get_cd)(struct platform_device *pdev);
 
        /* callbacks for board specific setup code */
        int (*init)(struct platform_device *pdev,
index 7d88d27..b0c73e4 100644 (file)
@@ -18,7 +18,8 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio);
 void mmc_gpio_free_ro(struct mmc_host *host);
 
 int mmc_gpio_get_cd(struct mmc_host *host);
-int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
+int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,
+                       unsigned int debounce);
 void mmc_gpio_free_cd(struct mmc_host *host);
 
 #endif
index 32be8db..274bc0f 100644 (file)
@@ -7,6 +7,11 @@
 struct device;
 struct mmc_host;
 
+#define MMC_SPI_USE_CD_GPIO                    (1 << 0)
+#define MMC_SPI_USE_RO_GPIO                    (1 << 1)
+#define MMC_SPI_CD_GPIO_ACTIVE_LOW             (1 << 2)
+#define MMC_SPI_RO_GPIO_ACTIVE_LOW             (1 << 3)
+
 /* Put this in platform_data of a device being used to manage an MMC/SD
  * card slot.  (Modeled after PXA mmc glue; see that for usage examples.)
  *
@@ -21,17 +26,19 @@ struct mmc_spi_platform_data {
                void *);
        void (*exit)(struct device *, void *);
 
-       /* sense switch on sd cards */
-       int (*get_ro)(struct device *);
-
        /*
-        * If board does not use CD interrupts, driver can optimize polling
-        * using this function.
+        * Card Detect and Read Only GPIOs. To enable debouncing on the card
+        * detect GPIO, set the cd_debounce to the debounce time in
+        * microseconds.
         */
-       int (*get_cd)(struct device *);
+       unsigned int flags;
+       unsigned int cd_gpio;
+       unsigned int cd_debounce;
+       unsigned int ro_gpio;
 
        /* Capabilities to pass into mmc core (e.g. MMC_CAP_NEEDS_POLL). */
        unsigned long caps;
+       unsigned long caps2;
 
        /* how long to debounce card detect, in msecs */
        u16 detect_delay;