]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/mmc/host/tmio_mmc_pio.c
mmc: tmio: add eMMC support
[karo-tx-linux.git] / drivers / mmc / host / tmio_mmc_pio.c
index 92467efc4e2c9e59676b74a3aee2e280bb0c30e3..700567603107a094381efac7ab02fd2b29b02d58 100644 (file)
@@ -336,7 +336,9 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command
 
        switch (mmc_resp_type(cmd)) {
        case MMC_RSP_NONE: c |= RESP_NONE; break;
-       case MMC_RSP_R1:   c |= RESP_R1;   break;
+       case MMC_RSP_R1:
+       case MMC_RSP_R1_NO_CRC:
+                          c |= RESP_R1;   break;
        case MMC_RSP_R1B:  c |= RESP_R1B;  break;
        case MMC_RSP_R2:   c |= RESP_R2;   break;
        case MMC_RSP_R3:   c |= RESP_R3;   break;
@@ -730,12 +732,13 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host,
        pr_debug("setup data transfer: blocksize %08x  nr_blocks %d\n",
                 data->blksz, data->blocks);
 
-       /* Some hardware cannot perform 2 byte requests in 4 bit mode */
-       if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) {
+       /* Some hardware cannot perform 2 byte requests in 4/8 bit mode */
+       if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4 ||
+           host->mmc->ios.bus_width == MMC_BUS_WIDTH_8) {
                int blksz_2bytes = pdata->flags & TMIO_MMC_BLKSZ_2BYTES;
 
                if (data->blksz < 2 || (data->blksz < 4 && !blksz_2bytes)) {
-                       pr_err("%s: %d byte block unsupported in 4 bit mode\n",
+                       pr_err("%s: %d byte block unsupported in 4/8 bit mode\n",
                               mmc_hostname(host->mmc), data->blksz);
                        return -EINVAL;
                }
@@ -857,14 +860,16 @@ static void tmio_mmc_power_off(struct tmio_mmc_host *host)
 static void tmio_mmc_set_bus_width(struct tmio_mmc_host *host,
                                unsigned char bus_width)
 {
-       switch (bus_width) {
-       case MMC_BUS_WIDTH_1:
-               sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
-               break;
-       case MMC_BUS_WIDTH_4:
-               sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
-               break;
-       }
+       u16 reg = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT)
+                               & ~(CARD_OPT_WIDTH | CARD_OPT_WIDTH8);
+
+       /* reg now applies to MMC_BUS_WIDTH_4 */
+       if (bus_width == MMC_BUS_WIDTH_1)
+               reg |= CARD_OPT_WIDTH;
+       else if (bus_width == MMC_BUS_WIDTH_8)
+               reg |= CARD_OPT_WIDTH8;
+
+       sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, reg);
 }
 
 /* Set MMC clock / power.
@@ -960,20 +965,12 @@ static int tmio_multi_io_quirk(struct mmc_card *card,
        return blk_size;
 }
 
-static int tmio_mmc_card_busy(struct mmc_host *mmc)
-{
-       struct tmio_mmc_host *host = mmc_priv(mmc);
-
-       return !(sd_ctrl_read16_and_16_as_32(host, CTL_STATUS) & TMIO_STAT_DAT0);
-}
-
 static 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         = mmc_gpio_get_cd,
        .enable_sdio_irq = tmio_mmc_enable_sdio_irq,
-       .card_busy      = tmio_mmc_card_busy,
        .multi_io_quirk = tmio_multi_io_quirk,
 };
 
@@ -1072,6 +1069,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host,
                goto host_free;
        }
 
+       tmio_mmc_ops.card_busy = _host->card_busy;
        tmio_mmc_ops.start_signal_voltage_switch = _host->start_signal_voltage_switch;
        mmc->ops = &tmio_mmc_ops;
 
@@ -1089,6 +1087,15 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host,
                                  !mmc_card_is_removable(mmc) ||
                                  mmc->slot.cd_irq >= 0);
 
+       /*
+        * On Gen2+, eMMC with NONREMOVABLE currently fails because native
+        * hotplug gets disabled. It seems RuntimePM related yet we need further
+        * research. Since we are planning a PM overhaul anyway, let's enforce
+        * for now the device being active by enabling native hotplug always.
+        */
+       if (pdata->flags & TMIO_MMC_MIN_RCAR2)
+               _host->native_hotplug = true;
+
        if (tmio_mmc_clk_enable(_host) < 0) {
                mmc->f_max = pdata->hclk;
                mmc->f_min = mmc->f_max / 512;