]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
mmc: sdhci: add 64bit addressing support
authorR Raj Kumar <rrajk@nvidia.com>
Mon, 29 Apr 2013 11:24:35 +0000 (16:54 +0530)
committerR Raj Kumar <rrajk@nvidia.com>
Fri, 24 Jun 2016 09:00:07 +0000 (02:00 -0700)
- Configure ADMA_ADDRESS_HI register if controller version
  is 4.0 and supports 64 bit DMA addressing
- Set HOST_VERSION_4_EN and ADDRESSING_64BIT_EN bits of HOST_CONTROL2
  register for controller version >4.00 in sdhci_reset().
- If len < 4, the extra transfer for alignment can do all job.
  No need to creating another descriptor for aligned transfer.
- Select ADMA2 for DMA_SELECT in Host control register if
  controller version is 4.0 or more.

Bug 1276024
Bug 200211270

Change-Id: Id588971b235d0faf87ae381aa2ae359704df57c4
Signed-off-by: Shridhar Rasal <srasal@nvidia.com>
Signed-off-by: Pavan Kunapuli <pkunapuli@nvidia.com>
Signed-off-by: R Raj Kumar <rrajk@nvidia.com>
Reviewed-on: http://git-master/r/1168224
Reviewed-by: Venu Byravarasu <vbyravarasu@nvidia.com>
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h

index fbfeeb56a70a3c4e927ca5c48d5a63b7ba699ade..58a87eb418c9b1d1788934a9406eb1eaaa92200d 100644 (file)
@@ -188,6 +188,7 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
 void sdhci_reset(struct sdhci_host *host, u8 mask)
 {
        unsigned long timeout;
+       u16 ctrl;
 
        sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
 
@@ -212,6 +213,14 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)
                timeout--;
                mdelay(1);
        }
+
+       if ((mask & SDHCI_RESET_ALL) && (host->version >= SDHCI_SPEC_400)) {
+               ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+               ctrl |= SDHCI_HOST_VERSION_4_EN;
+               if (host->quirks2 & SDHCI_QUIRK2_USE_64BIT_ADDR)
+                       ctrl |= SDHCI_ADDRESSING_64BIT_EN;
+               sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+       }
 }
 EXPORT_SYMBOL_GPL(sdhci_reset);
 
@@ -552,9 +561,12 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
 
                BUG_ON(len > 65536);
 
-               /* tran, valid */
-               sdhci_adma_write_desc(host, desc, addr, len, ADMA2_TRAN_VALID);
-               desc += host->desc_sz;
+               if (len > 0) {
+                       /* tran, valid */
+                       sdhci_adma_write_desc(host, desc, addr, len,
+                                       ADMA2_TRAN_VALID);
+                       desc += host->desc_sz;
+               }
 
                /*
                 * If this triggers then we have a calculation bug
@@ -835,12 +847,21 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
                                WARN_ON(1);
                                host->flags &= ~SDHCI_REQ_USE_DMA;
                        } else {
-                               sdhci_writel(host, host->adma_addr,
+                               sdhci_writel(host,
+                                       (host->adma_addr & 0xFFFFFFFF),
                                        SDHCI_ADMA_ADDRESS);
-                               if (host->flags & SDHCI_USE_64_BIT_DMA)
-                                       sdhci_writel(host,
-                                                    (u64)host->adma_addr >> 32,
-                                                    SDHCI_ADMA_ADDRESS_HI);
+                               if (host->flags & SDHCI_USE_64_BIT_DMA) {
+                                       if (host->quirks2 &
+                                           SDHCI_QUIRK2_USE_64BIT_ADDR) {
+                                               sdhci_writel(host,
+                                               ((u64)host->adma_addr >> 32)
+                                                       & 0xFFFFFFFF,
+                                               SDHCI_ADMA_ADDRESS_HI);
+                                       } else {
+                                               sdhci_writel(host, 0,
+                                               SDHCI_ADMA_ADDRESS_HI);
+                                       }
+                               }
                        }
                } else {
                        int sg_cnt;
@@ -871,8 +892,9 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
                ctrl &= ~SDHCI_CTRL_DMA_MASK;
                if ((host->flags & SDHCI_REQ_USE_DMA) &&
                        (host->flags & SDHCI_USE_ADMA)) {
-                       if (host->flags & SDHCI_USE_64_BIT_DMA)
-                               ctrl |= SDHCI_CTRL_ADMA64;
+                       if ((host->flags & SDHCI_USE_64_BIT_DMA) &&
+                               (host->version < SDHCI_SPEC_400))
+                                       ctrl |= SDHCI_CTRL_ADMA64;
                        else
                                ctrl |= SDHCI_CTRL_ADMA32;
                } else {
@@ -3223,11 +3245,14 @@ int sdhci_add_host(struct sdhci_host *host)
                 * all multipled by the descriptor size.
                 */
                if (host->flags & SDHCI_USE_64_BIT_DMA) {
+                       if (host->quirks2 & SDHCI_QUIRK2_USE_64BIT_ADDR)
+                               host->desc_sz = SDHCI_ADMA2_64_ADDR_DESC_SZ;
+                       else
+                               host->desc_sz = SDHCI_ADMA2_64_DESC_SZ;
                        host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *
-                                             SDHCI_ADMA2_64_DESC_SZ;
+                                               host->desc_sz;
                        host->align_buffer_sz = SDHCI_MAX_SEGS *
                                                SDHCI_ADMA2_64_ALIGN;
-                       host->desc_sz = SDHCI_ADMA2_64_DESC_SZ;
                        host->align_sz = SDHCI_ADMA2_64_ALIGN;
                        host->align_mask = SDHCI_ADMA2_64_ALIGN - 1;
                } else {
@@ -3672,11 +3697,12 @@ int sdhci_add_host(struct sdhci_host *host)
 
        mmc_add_host(mmc);
 
-       pr_info("%s: SDHCI controller on %s [%s] using %s\n",
+       pr_info("%s: SDHCI controller on %s [%s] using %s with %s bit addr\n",
                mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
                (host->flags & SDHCI_USE_ADMA) ?
                (host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" :
-               (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");
+               (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO",
+               (host->quirks2 & SDHCI_QUIRK2_USE_64BIT_ADDR) ? "64" : "32");
 
        sdhci_enable_card_detection(host);
 
index 30d5af25177f6599753f4a58f0752349656922a3..a9c28bc59df24cb9560ab6f07d841729282917c1 100644 (file)
 #define   SDHCI_CTRL_DRV_TYPE_D                0x0030
 #define  SDHCI_CTRL_EXEC_TUNING                0x0040
 #define  SDHCI_CTRL_TUNED_CLK          0x0080
+#define  SDHCI_HOST_VERSION_4_EN       0x1000
+#define  SDHCI_ADDRESSING_64BIT_EN     0x2000
 #define  SDHCI_CTRL_PRESET_VAL_ENABLE  0x8000
 
 #define SDHCI_CAPABILITIES     0x40
 #define   SDHCI_SPEC_100       0
 #define   SDHCI_SPEC_200       1
 #define   SDHCI_SPEC_300       2
+#define   SDHCI_SPEC_400       3
 #define   SDHCI_SPEC_410       4
 
 /*
@@ -294,6 +297,9 @@ struct sdhci_adma2_32_desc {
 /* ADMA2 64-bit DMA descriptor size */
 #define SDHCI_ADMA2_64_DESC_SZ 12
 
+/* ADMA2 64-bit Addressing DMA descriptor size */
+#define SDHCI_ADMA2_64_ADDR_DESC_SZ    16
+
 /* ADMA2 64-bit DMA alignment */
 #define SDHCI_ADMA2_64_ALIGN   8
 
@@ -429,6 +435,7 @@ struct sdhci_host {
 #define SDHCI_QUIRK2_DDR_FIXED_DIVISOR                 (1<<17)
 /* Turn off/on card clock before sending/after tuning command*/
 #define SDHCI_QUIRK2_NON_STD_TUN_CARD_CLOCK             (1<<18)
+#define SDHCI_QUIRK2_USE_64BIT_ADDR             (1<<19)
 
 
        int irq;                /* Device IRQ */