Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[linux.git] / drivers / mmc / host / omap_hsmmc.c
index dbd32ad3b749337a196c98915694b0c013685186..e91ee21549d03ad22c2bcf2287f61074cc3d889b 100644 (file)
@@ -45,6 +45,7 @@
 /* OMAP HSMMC Host Controller Registers */
 #define OMAP_HSMMC_SYSSTATUS   0x0014
 #define OMAP_HSMMC_CON         0x002C
+#define OMAP_HSMMC_SDMASA      0x0100
 #define OMAP_HSMMC_BLK         0x0104
 #define OMAP_HSMMC_ARG         0x0108
 #define OMAP_HSMMC_CMD         0x010C
@@ -58,6 +59,7 @@
 #define OMAP_HSMMC_STAT                0x0130
 #define OMAP_HSMMC_IE          0x0134
 #define OMAP_HSMMC_ISE         0x0138
+#define OMAP_HSMMC_AC12                0x013C
 #define OMAP_HSMMC_CAPA                0x0140
 
 #define VS18                   (1 << 26)
@@ -81,6 +83,7 @@
 #define DTO_MASK               0x000F0000
 #define DTO_SHIFT              16
 #define INIT_STREAM            (1 << 1)
+#define ACEN_ACMD23            (2 << 2)
 #define DP_SELECT              (1 << 21)
 #define DDIR                   (1 << 4)
 #define DMAE                   0x1
 #define SRC                    (1 << 25)
 #define SRD                    (1 << 26)
 #define SOFTRESET              (1 << 1)
-#define RESETDONE              (1 << 0)
 
 /* Interrupt masks for IE and ISE register */
 #define CC_EN                  (1 << 0)
 #define DTO_EN                 (1 << 20)
 #define DCRC_EN                        (1 << 21)
 #define DEB_EN                 (1 << 22)
+#define ACE_EN                 (1 << 24)
 #define CERR_EN                        (1 << 28)
 #define BADA_EN                        (1 << 29)
 
-#define INT_EN_MASK            (BADA_EN | CERR_EN | DEB_EN | DCRC_EN |\
+#define INT_EN_MASK (BADA_EN | CERR_EN | ACE_EN | DEB_EN | DCRC_EN |\
                DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \
                BRR_EN | BWR_EN | TC_EN | CC_EN)
 
+#define CNI    (1 << 7)
+#define ACIE   (1 << 4)
+#define ACEB   (1 << 3)
+#define ACCE   (1 << 2)
+#define ACTO   (1 << 1)
+#define ACNE   (1 << 0)
+
 #define MMC_AUTOSUSPEND_DELAY  100
 #define MMC_TIMEOUT_MS         20              /* 20 mSec */
 #define MMC_TIMEOUT_US         20000           /* 20000 micro Sec */
 #define OMAP_MMC_MAX_CLOCK     52000000
 #define DRIVER_NAME            "omap_hsmmc"
 
+#define VDD_1V8                        1800000         /* 180000 uV */
+#define VDD_3V0                        3000000         /* 300000 uV */
+#define VDD_165_195            (ffs(MMC_VDD_165_195) - 1)
+
+#define AUTO_CMD23             (1 << 1)        /* Auto CMD23 support */
 /*
  * One controller can have multiple slots, like on some omap boards using
  * omap.c controller driver. Luckily this is not currently done on any known
@@ -164,7 +179,8 @@ struct omap_hsmmc_host {
         */
        struct  regulator       *vcc;
        struct  regulator       *vcc_aux;
-       int                     pbias_disable;
+       struct  regulator       *pbias;
+       bool                    pbias_enabled;
        void    __iomem         *base;
        resource_size_t         mapbase;
        spinlock_t              irq_lock; /* Prevent races with irq handler */
@@ -188,10 +204,19 @@ struct omap_hsmmc_host {
        int                     reqs_blocked;
        int                     use_reg;
        int                     req_in_progress;
+       unsigned long           clk_rate;
+       unsigned int            flags;
        struct omap_hsmmc_next  next_data;
        struct  omap_mmc_platform_data  *pdata;
 };
 
+struct omap_mmc_of_data {
+       u32 reg_offset;
+       u8 controller_flags;
+};
+
+static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host);
+
 static int omap_hsmmc_card_detect(struct device *dev, int slot)
 {
        struct omap_hsmmc_host *host = dev_get_drvdata(dev);
@@ -261,17 +286,19 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on,
         */
        if (!host->vcc)
                return 0;
-       /*
-        * With DT, never turn OFF the regulator for MMC1. This is because
-        * the pbias cell programming support is still missing when
-        * booting with Device tree
-        */
-       if (host->pbias_disable && !vdd)
-               return 0;
 
        if (mmc_slot(host).before_set_reg)
                mmc_slot(host).before_set_reg(dev, slot, power_on, vdd);
 
+       if (host->pbias) {
+               if (host->pbias_enabled == 1) {
+                       ret = regulator_disable(host->pbias);
+                       if (!ret)
+                               host->pbias_enabled = 0;
+               }
+               regulator_set_voltage(host->pbias, VDD_3V0, VDD_3V0);
+       }
+
        /*
         * Assume Vcc regulator is used only to power the card ... OMAP
         * VDDS is used to power the pins, optionally with a transceiver to
@@ -286,11 +313,12 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on,
         * chips/cards need an interface voltage rail too.
         */
        if (power_on) {
-               ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd);
+               if (host->vcc)
+                       ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd);
                /* Enable interface voltage rail, if needed */
                if (ret == 0 && host->vcc_aux) {
                        ret = regulator_enable(host->vcc_aux);
-                       if (ret < 0)
+                       if (ret < 0 && host->vcc)
                                ret = mmc_regulator_set_ocr(host->mmc,
                                                        host->vcc, 0);
                }
@@ -298,16 +326,34 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on,
                /* Shut down the rail */
                if (host->vcc_aux)
                        ret = regulator_disable(host->vcc_aux);
-               if (!ret) {
+               if (host->vcc) {
                        /* Then proceed to shut down the local regulator */
                        ret = mmc_regulator_set_ocr(host->mmc,
                                                host->vcc, 0);
                }
        }
 
+       if (host->pbias) {
+               if (vdd <= VDD_165_195)
+                       ret = regulator_set_voltage(host->pbias, VDD_1V8,
+                                                               VDD_1V8);
+               else
+                       ret = regulator_set_voltage(host->pbias, VDD_3V0,
+                                                               VDD_3V0);
+               if (ret < 0)
+                       goto error_set_power;
+
+               if (host->pbias_enabled == 0) {
+                       ret = regulator_enable(host->pbias);
+                       if (!ret)
+                               host->pbias_enabled = 1;
+               }
+       }
+
        if (mmc_slot(host).after_set_reg)
                mmc_slot(host).after_set_reg(dev, slot, power_on, vdd);
 
+error_set_power:
        return ret;
 }
 
@@ -316,12 +362,12 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
        struct regulator *reg;
        int ocr_value = 0;
 
-       reg = regulator_get(host->dev, "vmmc");
+       reg = devm_regulator_get(host->dev, "vmmc");
        if (IS_ERR(reg)) {
-               dev_err(host->dev, "vmmc regulator missing\n");
+               dev_err(host->dev, "unable to get vmmc regulator %ld\n",
+                       PTR_ERR(reg));
                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) {
@@ -334,31 +380,29 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
                                return -EINVAL;
                        }
                }
+       }
+       mmc_slot(host).set_power = omap_hsmmc_set_power;
 
-               /* Allow an aux regulator */
-               reg = regulator_get(host->dev, "vmmc_aux");
-               host->vcc_aux = IS_ERR(reg) ? NULL : reg;
+       /* Allow an aux regulator */
+       reg = devm_regulator_get_optional(host->dev, "vmmc_aux");
+       host->vcc_aux = IS_ERR(reg) ? NULL : reg;
 
-               /* For eMMC do not power off when not in sleep state */
-               if (mmc_slot(host).no_regulator_off_init)
-                       return 0;
-               /*
-               * UGLY HACK:  workaround regulator framework bugs.
-               * When the bootloader leaves a supply active, it's
-               * initialized with zero usecount ... and we can't
-               * disable it without first enabling it.  Until the
-               * framework is fixed, we need a workaround like this
-               * (which is safe for MMC, but not in general).
-               */
-               if (regulator_is_enabled(host->vcc) > 0 ||
-                   (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) {
-                       int vdd = ffs(mmc_slot(host).ocr_mask) - 1;
+       reg = devm_regulator_get_optional(host->dev, "pbias");
+       host->pbias = IS_ERR(reg) ? NULL : reg;
 
-                       mmc_slot(host).set_power(host->dev, host->slot_id,
-                                                1, vdd);
-                       mmc_slot(host).set_power(host->dev, host->slot_id,
-                                                0, 0);
-               }
+       /* For eMMC do not power off when not in sleep state */
+       if (mmc_slot(host).no_regulator_off_init)
+               return 0;
+       /*
+        * To disable boot_on regulator, enable regulator
+        * to increase usecount and then disable it.
+        */
+       if ((host->vcc && regulator_is_enabled(host->vcc) > 0) ||
+           (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) {
+               int vdd = ffs(mmc_slot(host).ocr_mask) - 1;
+
+               mmc_slot(host).set_power(host->dev, host->slot_id, 1, vdd);
+               mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
        }
 
        return 0;
@@ -366,8 +410,6 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
 
 static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host)
 {
-       regulator_put(host->vcc);
-       regulator_put(host->vcc_aux);
        mmc_slot(host).set_power = NULL;
 }
 
@@ -605,9 +647,6 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
        u32 hctl, capa;
        unsigned long timeout;
 
-       if (!OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE)
-               return 1;
-
        if (host->con == OMAP_HSMMC_READ(host->base, CON) &&
            host->hctl == OMAP_HSMMC_READ(host->base, HCTL) &&
            host->sysctl == OMAP_HSMMC_READ(host->base, SYSCTL) &&
@@ -787,6 +826,11 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
 
        cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22);
 
+       if ((host->flags & AUTO_CMD23) && mmc_op_multi(cmd->opcode) &&
+           host->mrq->sbc) {
+               cmdreg |= ACEN_ACMD23;
+               OMAP_HSMMC_WRITE(host->base, SDMASA, host->mrq->sbc->arg);
+       }
        if (data) {
                cmdreg |= DP_SELECT | MSBS | BCE;
                if (data->flags & MMC_DATA_READ)
@@ -864,11 +908,10 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data)
        else
                data->bytes_xfered = 0;
 
-       if (!data->stop) {
+       if (data->stop && (data->error || !host->mrq->sbc))
+               omap_hsmmc_start_command(host, data->stop, NULL);
+       else
                omap_hsmmc_request_done(host, data->mrq);
-               return;
-       }
-       omap_hsmmc_start_command(host, data->stop, NULL);
 }
 
 /*
@@ -879,6 +922,14 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd)
 {
        host->cmd = NULL;
 
+       if (host->mrq->sbc && (host->cmd == host->mrq->sbc) &&
+           !host->mrq->sbc->error && !(host->flags & AUTO_CMD23)) {
+               omap_hsmmc_start_dma_transfer(host);
+               omap_hsmmc_start_command(host, host->mrq->cmd,
+                                               host->mrq->data);
+               return;
+       }
+
        if (cmd->flags & MMC_RSP_PRESENT) {
                if (cmd->flags & MMC_RSP_136) {
                        /* response type 2 */
@@ -892,7 +943,7 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd)
                }
        }
        if ((host->data == NULL && !host->response_busy) || cmd->error)
-               omap_hsmmc_request_done(host, cmd->mrq);
+               omap_hsmmc_request_done(host, host->mrq);
 }
 
 /*
@@ -1015,6 +1066,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
 {
        struct mmc_data *data;
        int end_cmd = 0, end_trans = 0;
+       int error = 0;
 
        data = host->data;
        dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
@@ -1029,6 +1081,20 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
                else if (status & (CCRC_EN | DCRC_EN))
                        hsmmc_command_incomplete(host, -EILSEQ, end_cmd);
 
+               if (status & ACE_EN) {
+                       u32 ac12;
+                       ac12 = OMAP_HSMMC_READ(host->base, AC12);
+                       if (!(ac12 & ACNE) && host->mrq->sbc) {
+                               end_cmd = 1;
+                               if (ac12 & ACTO)
+                                       error =  -ETIMEDOUT;
+                               else if (ac12 & (ACCE | ACEB | ACIE))
+                                       error = -EILSEQ;
+                               host->mrq->sbc->error = error;
+                               hsmmc_command_incomplete(host, error, end_cmd);
+                       }
+                       dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12);
+               }
                if (host->data || host->response_busy) {
                        end_trans = !end_cmd;
                        host->response_busy = 0;
@@ -1236,8 +1302,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
        }
 
        /* Check if next job is already prepared */
-       if (next ||
-           (!next && data->host_cookie != host->next_data.cookie)) {
+       if (next || data->host_cookie != host->next_data.cookie) {
                dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len,
                                     omap_hsmmc_get_dma_dir(host, data));
 
@@ -1262,7 +1327,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
 /*
  * Routine to configure and start DMA for the MMC card
  */
-static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host,
+static int omap_hsmmc_setup_dma_transfer(struct omap_hsmmc_host *host,
                                        struct mmc_request *req)
 {
        struct dma_slave_config cfg;
@@ -1321,8 +1386,6 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host,
 
        host->dma_ch = 1;
 
-       dma_async_issue_pending(chan);
-
        return 0;
 }
 
@@ -1338,7 +1401,7 @@ static void set_data_timeout(struct omap_hsmmc_host *host,
        if (clkd == 0)
                clkd = 1;
 
-       cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd);
+       cycle_ns = 1000000000 / (host->clk_rate / clkd);
        timeout = timeout_ns / cycle_ns;
        timeout += timeout_clks;
        if (timeout) {
@@ -1363,6 +1426,21 @@ static void set_data_timeout(struct omap_hsmmc_host *host,
        OMAP_HSMMC_WRITE(host->base, SYSCTL, reg);
 }
 
+static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host)
+{
+       struct mmc_request *req = host->mrq;
+       struct dma_chan *chan;
+
+       if (!req->data)
+               return;
+       OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz)
+                               | (req->data->blocks << 16));
+       set_data_timeout(host, req->data->timeout_ns,
+                               req->data->timeout_clks);
+       chan = omap_hsmmc_get_dma_chan(host, req->data);
+       dma_async_issue_pending(chan);
+}
+
 /*
  * Configure block length for MMC/SD cards and initiate the transfer.
  */
@@ -1383,12 +1461,8 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
                return 0;
        }
 
-       OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz)
-                                       | (req->data->blocks << 16));
-       set_data_timeout(host, req->data->timeout_ns, req->data->timeout_clks);
-
        if (host->use_dma) {
-               ret = omap_hsmmc_start_dma_transfer(host, req);
+               ret = omap_hsmmc_setup_dma_transfer(host, req);
                if (ret != 0) {
                        dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
                        return ret;
@@ -1462,6 +1536,7 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
                host->reqs_blocked = 0;
        WARN_ON(host->mrq != NULL);
        host->mrq = req;
+       host->clk_rate = clk_get_rate(host->fclk);
        err = omap_hsmmc_prepare_data(host, req);
        if (err) {
                req->cmd->error = err;
@@ -1471,7 +1546,12 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
                mmc_request_done(mmc, req);
                return;
        }
+       if (req->sbc && !(host->flags & AUTO_CMD23)) {
+               omap_hsmmc_start_command(host, req->sbc, NULL);
+               return;
+       }
 
+       omap_hsmmc_start_dma_transfer(host);
        omap_hsmmc_start_command(host, req->cmd, req->data);
 }
 
@@ -1509,13 +1589,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                 * of external transceiver; but they all handle 1.8V.
                 */
                if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) &&
-                       (ios->vdd == DUAL_VOLT_OCR_BIT) &&
-                       /*
-                        * With pbias cell programming missing, this
-                        * can't be allowed on MMC1 when booting with device
-                        * tree.
-                        */
-                       !host->pbias_disable) {
+                       (ios->vdd == DUAL_VOLT_OCR_BIT)) {
                                /*
                                 * The mmc_select_voltage fn of the core does
                                 * not seem to set the power_mode to
@@ -1678,18 +1752,29 @@ static void omap_hsmmc_debugfs(struct mmc_host *mmc)
 #endif
 
 #ifdef CONFIG_OF
-static u16 omap4_reg_offset = 0x100;
+static const struct omap_mmc_of_data omap3_pre_es3_mmc_of_data = {
+       /* See 35xx errata 2.1.1.128 in SPRZ278F */
+       .controller_flags = OMAP_HSMMC_BROKEN_MULTIBLOCK_READ,
+};
+
+static const struct omap_mmc_of_data omap4_mmc_of_data = {
+       .reg_offset = 0x100,
+};
 
 static const struct of_device_id omap_mmc_of_match[] = {
        {
                .compatible = "ti,omap2-hsmmc",
        },
+       {
+               .compatible = "ti,omap3-pre-es3-hsmmc",
+               .data = &omap3_pre_es3_mmc_of_data,
+       },
        {
                .compatible = "ti,omap3-hsmmc",
        },
        {
                .compatible = "ti,omap4-hsmmc",
-               .data = &omap4_reg_offset,
+               .data = &omap4_mmc_of_data,
        },
        {},
 };
@@ -1709,7 +1794,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
-               return NULL; /* out of memory */
+               return ERR_PTR(-ENOMEM); /* out of memory */
 
        if (of_find_property(np, "ti,dual-volt", NULL))
                pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT;
@@ -1738,13 +1823,19 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
        if (of_find_property(np, "ti,needs-special-hs-handling", NULL))
                pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT;
 
+       if (of_find_property(np, "keep-power-in-suspend", NULL))
+               pdata->slots[0].pm_caps |= MMC_PM_KEEP_POWER;
+
+       if (of_find_property(np, "enable-sdio-wakeup", NULL))
+               pdata->slots[0].pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+
        return pdata;
 }
 #else
 static inline struct omap_mmc_platform_data
                        *of_get_hsmmc_pdata(struct device *dev)
 {
-       return NULL;
+       return ERR_PTR(-EINVAL);
 }
 #endif
 
@@ -1759,6 +1850,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
        dma_cap_mask_t mask;
        unsigned tx_req, rx_req;
        struct pinctrl *pinctrl;
+       const struct omap_mmc_of_data *data;
 
        match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
        if (match) {
@@ -1768,8 +1860,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
                        return PTR_ERR(pdata);
 
                if (match->data) {
-                       const u16 *offsetp = match->data;
-                       pdata->reg_offset = *offsetp;
+                       data = match->data;
+                       pdata->reg_offset = data->reg_offset;
+                       pdata->controller_flags |= data->controller_flags;
                }
        }
 
@@ -1814,6 +1907,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
        host->base      = ioremap(host->mapbase, SZ_4K);
        host->power_mode = MMC_POWER_OFF;
        host->next_data.cookie = 1;
+       host->pbias_enabled = 0;
 
        platform_set_drvdata(pdev, host);
 
@@ -1847,10 +1941,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 
        omap_hsmmc_context_save(host);
 
-       /* This can be removed once we support PBIAS with DT */
-       if (host->dev->of_node && res->start == 0x4809c000)
-               host->pbias_disable = 1;
-
        host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
        /*
         * MMC can still work without debounce clock.