mmc: sh_sdhi: Add 64-bit access to sd_buf support
authorKouei Abe <kouei.abe.cp@renesas.com>
Sat, 13 May 2017 13:51:16 +0000 (15:51 +0200)
committerJaehoon Chung <jh80.chung@samsung.com>
Fri, 9 Jun 2017 11:25:16 +0000 (20:25 +0900)
Renesas SDHI SD/MMC driver has 16-bit width bus access to SD_BUF.
This adds 64-bit width bus access to SD_BUF.

Signed-off-by: Kouei Abe <kouei.abe.cp@renesas.com>
Cc: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com>
Cc: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
Cc: Jaehoon Chung <jh80.chung@samsung.com>
Reviewed-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
arch/arm/mach-rmobile/include/mach/sh_sdhi.h
drivers/mmc/sh_sdhi.c

index 057bf3f8bbfac3bcb106251a0e1298659f882912..a5ea45b70761b77013c64932ebc36e95b409ef73 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * drivers/mmc/sh-sdhi.h
  *
- * SD/MMC driver for Reneas rmobile ARM SoCs
+ * SD/MMC driver for Renesas rmobile ARM SoCs
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2017 Renesas Electronics Corporation
  * Copyright (C) 2008-2009 Renesas Solutions Corp.
  *
  * SPDX-License-Identifier:    GPL-2.0
 #define        CLKDEV_INIT                     400000          /* 100 - 400 KHz */
 
 /* For quirk */
-#define SH_SDHI_QUIRK_16BIT_BUF                (1)
+#define SH_SDHI_QUIRK_16BIT_BUF                BIT(0)
+#define SH_SDHI_QUIRK_64BIT_BUF                BIT(1)
+
 int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks);
 
 #endif /* _SH_SDHI_H */
index 7f0b4c2603dbdb0e72b3bfad600f476a8941730c..d1dd0f0fc313df5321b419a978e7b236824c3607 100644 (file)
@@ -3,7 +3,7 @@
  *
  * SD/MMC driver for Renesas rmobile ARM SoCs.
  *
- * Copyright (C) 2011,2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2011,2013-2017 Renesas Electronics Corporation
  * Copyright (C) 2014 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
  * Copyright (C) 2008-2009 Renesas Solutions Corp.
  *
@@ -29,6 +29,17 @@ struct sh_sdhi_host {
        unsigned char sd_error;
        unsigned char detect_waiting;
 };
+
+static inline void sh_sdhi_writeq(struct sh_sdhi_host *host, int reg, u64 val)
+{
+       writeq(val, host->addr + (reg << host->bus_shift));
+}
+
+static inline u64 sh_sdhi_readq(struct sh_sdhi_host *host, int reg)
+{
+       return readq(host->addr + (reg << host->bus_shift));
+}
+
 static inline void sh_sdhi_writew(struct sh_sdhi_host *host, int reg, u16 val)
 {
        writew(val, host->addr + (reg << host->bus_shift));
@@ -261,6 +272,7 @@ static int sh_sdhi_single_read(struct sh_sdhi_host *host, struct mmc_data *data)
        long time;
        unsigned short blocksize, i;
        unsigned short *p = (unsigned short *)data->dest;
+       u64 *q = (u64 *)data->dest;
 
        if ((unsigned long)p & 0x00000001) {
                debug(DRIVER_NAME": %s: The data pointer is unaligned.",
@@ -281,8 +293,12 @@ static int sh_sdhi_single_read(struct sh_sdhi_host *host, struct mmc_data *data)
 
        host->wait_int = 0;
        blocksize = sh_sdhi_readw(host, SDHI_SIZE);
-       for (i = 0; i < blocksize / 2; i++)
-               *p++ = sh_sdhi_readw(host, SDHI_BUF0);
+       if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
+               for (i = 0; i < blocksize / 8; i++)
+                       *q++ = sh_sdhi_readq(host, SDHI_BUF0);
+       else
+               for (i = 0; i < blocksize / 2; i++)
+                       *p++ = sh_sdhi_readw(host, SDHI_BUF0);
 
        time = sh_sdhi_wait_interrupt_flag(host);
        if (time == 0 || host->sd_error != 0)
@@ -297,6 +313,7 @@ static int sh_sdhi_multi_read(struct sh_sdhi_host *host, struct mmc_data *data)
        long time;
        unsigned short blocksize, i, sec;
        unsigned short *p = (unsigned short *)data->dest;
+       u64 *q = (u64 *)data->dest;
 
        if ((unsigned long)p & 0x00000001) {
                debug(DRIVER_NAME": %s: The data pointer is unaligned.",
@@ -319,8 +336,12 @@ static int sh_sdhi_multi_read(struct sh_sdhi_host *host, struct mmc_data *data)
 
                host->wait_int = 0;
                blocksize = sh_sdhi_readw(host, SDHI_SIZE);
-               for (i = 0; i < blocksize / 2; i++)
-                       *p++ = sh_sdhi_readw(host, SDHI_BUF0);
+               if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
+                       for (i = 0; i < blocksize / 8; i++)
+                               *q++ = sh_sdhi_readq(host, SDHI_BUF0);
+               else
+                       for (i = 0; i < blocksize / 2; i++)
+                               *p++ = sh_sdhi_readw(host, SDHI_BUF0);
        }
 
        return 0;
@@ -332,6 +353,7 @@ static int sh_sdhi_single_write(struct sh_sdhi_host *host,
        long time;
        unsigned short blocksize, i;
        const unsigned short *p = (const unsigned short *)data->src;
+       const u64 *q = (const u64 *)data->src;
 
        if ((unsigned long)p & 0x00000001) {
                debug(DRIVER_NAME": %s: The data pointer is unaligned.",
@@ -356,8 +378,12 @@ static int sh_sdhi_single_write(struct sh_sdhi_host *host,
 
        host->wait_int = 0;
        blocksize = sh_sdhi_readw(host, SDHI_SIZE);
-       for (i = 0; i < blocksize / 2; i++)
-               sh_sdhi_writew(host, SDHI_BUF0, *p++);
+       if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
+               for (i = 0; i < blocksize / 8; i++)
+                       sh_sdhi_writeq(host, SDHI_BUF0, *q++);
+       else
+               for (i = 0; i < blocksize / 2; i++)
+                       sh_sdhi_writew(host, SDHI_BUF0, *p++);
 
        time = sh_sdhi_wait_interrupt_flag(host);
        if (time == 0 || host->sd_error != 0)
@@ -372,6 +398,7 @@ static int sh_sdhi_multi_write(struct sh_sdhi_host *host, struct mmc_data *data)
        long time;
        unsigned short i, sec, blocksize;
        const unsigned short *p = (const unsigned short *)data->src;
+       const u64 *q = (const u64 *)data->src;
 
        debug("%s: blocks = %d, blocksize = %d\n",
              __func__, data->blocks, data->blocksize);
@@ -388,8 +415,12 @@ static int sh_sdhi_multi_write(struct sh_sdhi_host *host, struct mmc_data *data)
 
                host->wait_int = 0;
                blocksize = sh_sdhi_readw(host, SDHI_SIZE);
-               for (i = 0; i < blocksize / 2; i++)
-                       sh_sdhi_writew(host, SDHI_BUF0, *p++);
+               if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
+                       for (i = 0; i < blocksize / 8; i++)
+                               sh_sdhi_writeq(host, SDHI_BUF0, *q++);
+               else
+                       for (i = 0; i < blocksize / 2; i++)
+                               sh_sdhi_writew(host, SDHI_BUF0, *p++);
        }
 
        return 0;
@@ -687,7 +718,9 @@ int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks)
        host->addr = addr;
        host->quirks = quirks;
 
-       if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
+       if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
+               host->bus_shift = 2;
+       else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
                host->bus_shift = 1;
 
        return ret;