Merge tag 'v3.14.25' into backport/v3.14.24-ltsi-rc1+v3.14.25/snapshot-merge.wip
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / mmc / host / tmio_mmc_pio.c
index 7cfe939..e487ba4 100644 (file)
@@ -159,6 +159,11 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host,
                for (clock = host->mmc->f_min, clk = 0x80000080;
                        new_clock >= (clock<<1); clk >>= 1)
                        clock <<= 1;
+
+               /* 1/1 clock is option */
+               if ((host->pdata->flags & TMIO_MMC_CLK_ACTUAL) &&
+                   ((clk >> 22) & 0x1))
+                       clk |= 0xff;
        }
 
        if (host->set_clk_div)
@@ -371,6 +376,40 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command
        return 0;
 }
 
+static void tmio_mmc_transfer_data(struct tmio_mmc_host *host,
+                                  unsigned short *buf,
+                                  unsigned int count)
+{
+       int is_read = host->data->flags & MMC_DATA_READ;
+       u8  *buf8;
+
+       /*
+        * Transfer the data
+        */
+       if (is_read)
+               sd_ctrl_read16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
+       else
+               sd_ctrl_write16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
+
+       /* if count was even number */
+       if (!(count & 0x1))
+               return;
+
+       /* if count was odd number */
+       buf8 = (u8 *)(buf + (count >> 1));
+
+       /*
+        * FIXME
+        *
+        * driver and this function are assuming that
+        * it is used as little endian
+        */
+       if (is_read)
+               *buf8 = sd_ctrl_read16(host, CTL_SD_DATA_PORT) & 0xff;
+       else
+               sd_ctrl_write16(host, CTL_SD_DATA_PORT, *buf8);
+}
+
 /*
  * This chip always returns (at least?) as much data as you ask for.
  * I'm unsure what happens if you ask for less than a block. This should be
@@ -403,10 +442,7 @@ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
                 count, host->sg_off, data->flags);
 
        /* Transfer the data */
-       if (data->flags & MMC_DATA_READ)
-               sd_ctrl_read16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
-       else
-               sd_ctrl_write16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
+       tmio_mmc_transfer_data(host, buf, count);
 
        host->sg_off += count;
 
@@ -965,12 +1001,25 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
        return ret;
 }
 
+static int tmio_multi_io_quirk(struct mmc_card *card,
+                              unsigned int direction, int blk_size)
+{
+       struct tmio_mmc_host *host = mmc_priv(card->host);
+       struct tmio_mmc_data *pdata = host->pdata;
+
+       if (pdata->multi_io_quirk)
+               return pdata->multi_io_quirk(card, direction, blk_size);
+
+       return blk_size;
+}
+
 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         = mmc_gpio_get_cd,
        .enable_sdio_irq = tmio_mmc_enable_sdio_irq,
+       .multi_io_quirk = tmio_multi_io_quirk,
 };
 
 static int tmio_mmc_init_ocr(struct tmio_mmc_host *host)
@@ -1073,6 +1122,15 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host,
        }
 
        /*
+        * Check the sanity of mmc->f_min to prevent tmio_mmc_set_clock() from
+        * looping forever...
+        */
+       if (mmc->f_min == 0) {
+               ret = -EINVAL;
+               goto host_free;
+       }
+
+       /*
         * While using internal tmio hardware logic for card detection, we need
         * to ensure it stays powered for it to work.
         */