[PATCH V2 6/7] mmc: sdhci-sprd: added Spreadtrum's initial host controller

2018-06-14 Thread Chunyan Zhang
From: Chunyan Zhang 

This patch adds the initial support of Secure Digital Host Controller
Interface compliant controller found in some latest Spreadtrum chipsets.
This patch has been tested on the version of SPRD-R11 controller.

R11 is a variant based on SD v4.0 specification.

With this driver, R11 mmc can be initialized, can be mounted, read and
written.

Original-by: Billows Wu 
Signed-off-by: Chunyan Zhang 
---
 drivers/mmc/host/Kconfig  |  13 ++
 drivers/mmc/host/Makefile |   1 +
 drivers/mmc/host/sdhci-sprd.c | 426 ++
 3 files changed, 440 insertions(+)
 create mode 100644 drivers/mmc/host/sdhci-sprd.c

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 9589f9c..1b0ee11 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -584,6 +584,19 @@ config MMC_SDRICOH_CS
  To compile this driver as a module, choose M here: the
  module will be called sdricoh_cs.
 
+config MMC_SDHCI_SPRD
+   tristate "Spreadtrum SDIO host Controller"
+   depends on ARCH_SPRD
+   depends on MMC_SDHCI_PLTFM
+   select MMC_SDHCI_IO_ACCESSORS
+   help
+ This selects the SDIO Host Controller in Spreadtrum
+ SoCs, this driver supports R11(IP version: R11P0).
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
+
 config MMC_TMIO_CORE
tristate
 
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 6aead24..5835bc4 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_MMC_SDHCI_ST)+= sdhci-st.o
 obj-$(CONFIG_MMC_SDHCI_MICROCHIP_PIC32)+= sdhci-pic32.o
 obj-$(CONFIG_MMC_SDHCI_BRCMSTB)+= sdhci-brcmstb.o
 obj-$(CONFIG_MMC_SDHCI_OMAP)   += sdhci-omap.o
+obj-$(CONFIG_MMC_SDHCI_SPRD)   += sdhci-sprd.o
 obj-$(CONFIG_MMC_CQHCI)+= cqhci.o
 
 ifeq ($(CONFIG_CB710_DEBUG),y)
diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c
new file mode 100644
index 000..f1b0f2b
--- /dev/null
+++ b/drivers/mmc/host/sdhci-sprd.c
@@ -0,0 +1,426 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Secure Digital Host Controller
+//
+// Copyright (C) 2018 Spreadtrum, Inc.
+// Author: Chunyan Zhang 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "sdhci-pltfm.h"
+
+#define SDHCI_SPRD_REG_32_DLL_DLY_OFFSET   0x208
+#define  SDHCIBSPRD_IT_WR_DLY_INV  (1 << 5)
+#define  SDHCI_SPRD_BIT_CMD_DLY_INV(1 << 13)
+#define  SDHCI_SPRD_BIT_POSRD_DLY_INV  (1 << 21)
+#define  SDHCI_SPRD_BIT_NEGRD_DLY_INV  (1 << 29)
+
+#define SDHCI_SPRD_REG_32_BUSY_POSI0x250
+#define  SDHCI_SPRD_BIT_OUTR_CLK_AUTO_EN   (1 << 25)
+#define  SDHCI_SPRD_BIT_INNR_CLK_AUTO_EN   (1 << 24)
+
+#define SDHCI_SPRD_REG_DEBOUNCE0x28C
+#define  SDHCI_SPRD_BIT_DLL_BAK(1 << 0)
+#define  SDHCI_SPRD_BIT_DLL_VAL(1 << 1)
+
+#define  SDHCI_SPRD_INT_SIGNAL_MASK0x1B7F410B
+
+/* SDHCI_HOST_CONTROL2 */
+#define  SDHCI_SPRD_CTRL_HS200 0x0005
+#define  SDHCI_SPRD_CTRL_HS400 0x0006
+
+/* SDHCI_SOFTWARE_RESET */
+#define  SDHCI_HW_RESET_CARD   0x8 /* For Spreadtrum's design */
+
+#define SDHCI_SPRD_MAX_CUR 0xFF
+#define SDHCI_SPRD_CLK_MAX_DIV 0x3FF
+
+#define SDHCI_SPRD_CLK_DEF_RATE2600
+
+struct sdhci_sprd_host {
+   u32 version;
+   struct clk *clk_sdio;
+   struct clk *clk_enable;
+   u32 base_rate;
+};
+
+#define TO_SPRD_HOST(host) sdhci_pltfm_priv(sdhci_priv(host))
+
+static void sdhci_sprd_init_config(struct sdhci_host *host)
+{
+   u16 val;
+
+   /* set 64-bit addressing modes */
+   val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+   val |= SDHCI_CTRL_64BIT_ADDR;
+   sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
+
+   /* set dll backup mode */
+   val = sdhci_readl(host, SDHCI_SPRD_REG_DEBOUNCE);
+   val |= SDHCI_SPRD_BIT_DLL_BAK | SDHCI_SPRD_BIT_DLL_VAL;
+   sdhci_writel(host, val, SDHCI_SPRD_REG_DEBOUNCE);
+}
+
+static inline u32 sdhci_sprd_readl(struct sdhci_host *host, int reg)
+{
+   if (unlikely(reg == SDHCI_MAX_CURRENT))
+   return SDHCI_SPRD_MAX_CUR;
+
+   return readl_relaxed(host->ioaddr + reg);
+}
+
+static inline void sdhci_sprd_writel(struct sdhci_host *host, u32 val, int reg)
+{
+   /* SDHCI_MAX_CURRENT is reserved on Spreadtrum's platform */
+   if (unlikely(reg == SDHCI_MAX_CURRENT))
+   return;
+
+   if (unlikely(reg == SDHCI_SIGNAL_ENABLE || reg == SDHCI_INT_ENABLE))
+   val = val & SDHCI_SPRD_INT_SIGNAL_MASK;
+
+   return writel_relaxed(val, host->ioaddr + reg);
+}
+
+static inline void sdhci_sprd_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+   if 

[PATCH V2 6/7] mmc: sdhci-sprd: added Spreadtrum's initial host controller

2018-06-14 Thread Chunyan Zhang
From: Chunyan Zhang 

This patch adds the initial support of Secure Digital Host Controller
Interface compliant controller found in some latest Spreadtrum chipsets.
This patch has been tested on the version of SPRD-R11 controller.

R11 is a variant based on SD v4.0 specification.

With this driver, R11 mmc can be initialized, can be mounted, read and
written.

Original-by: Billows Wu 
Signed-off-by: Chunyan Zhang 
---
 drivers/mmc/host/Kconfig  |  13 ++
 drivers/mmc/host/Makefile |   1 +
 drivers/mmc/host/sdhci-sprd.c | 426 ++
 3 files changed, 440 insertions(+)
 create mode 100644 drivers/mmc/host/sdhci-sprd.c

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 9589f9c..1b0ee11 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -584,6 +584,19 @@ config MMC_SDRICOH_CS
  To compile this driver as a module, choose M here: the
  module will be called sdricoh_cs.
 
+config MMC_SDHCI_SPRD
+   tristate "Spreadtrum SDIO host Controller"
+   depends on ARCH_SPRD
+   depends on MMC_SDHCI_PLTFM
+   select MMC_SDHCI_IO_ACCESSORS
+   help
+ This selects the SDIO Host Controller in Spreadtrum
+ SoCs, this driver supports R11(IP version: R11P0).
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
+
 config MMC_TMIO_CORE
tristate
 
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 6aead24..5835bc4 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_MMC_SDHCI_ST)+= sdhci-st.o
 obj-$(CONFIG_MMC_SDHCI_MICROCHIP_PIC32)+= sdhci-pic32.o
 obj-$(CONFIG_MMC_SDHCI_BRCMSTB)+= sdhci-brcmstb.o
 obj-$(CONFIG_MMC_SDHCI_OMAP)   += sdhci-omap.o
+obj-$(CONFIG_MMC_SDHCI_SPRD)   += sdhci-sprd.o
 obj-$(CONFIG_MMC_CQHCI)+= cqhci.o
 
 ifeq ($(CONFIG_CB710_DEBUG),y)
diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c
new file mode 100644
index 000..f1b0f2b
--- /dev/null
+++ b/drivers/mmc/host/sdhci-sprd.c
@@ -0,0 +1,426 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Secure Digital Host Controller
+//
+// Copyright (C) 2018 Spreadtrum, Inc.
+// Author: Chunyan Zhang 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "sdhci-pltfm.h"
+
+#define SDHCI_SPRD_REG_32_DLL_DLY_OFFSET   0x208
+#define  SDHCIBSPRD_IT_WR_DLY_INV  (1 << 5)
+#define  SDHCI_SPRD_BIT_CMD_DLY_INV(1 << 13)
+#define  SDHCI_SPRD_BIT_POSRD_DLY_INV  (1 << 21)
+#define  SDHCI_SPRD_BIT_NEGRD_DLY_INV  (1 << 29)
+
+#define SDHCI_SPRD_REG_32_BUSY_POSI0x250
+#define  SDHCI_SPRD_BIT_OUTR_CLK_AUTO_EN   (1 << 25)
+#define  SDHCI_SPRD_BIT_INNR_CLK_AUTO_EN   (1 << 24)
+
+#define SDHCI_SPRD_REG_DEBOUNCE0x28C
+#define  SDHCI_SPRD_BIT_DLL_BAK(1 << 0)
+#define  SDHCI_SPRD_BIT_DLL_VAL(1 << 1)
+
+#define  SDHCI_SPRD_INT_SIGNAL_MASK0x1B7F410B
+
+/* SDHCI_HOST_CONTROL2 */
+#define  SDHCI_SPRD_CTRL_HS200 0x0005
+#define  SDHCI_SPRD_CTRL_HS400 0x0006
+
+/* SDHCI_SOFTWARE_RESET */
+#define  SDHCI_HW_RESET_CARD   0x8 /* For Spreadtrum's design */
+
+#define SDHCI_SPRD_MAX_CUR 0xFF
+#define SDHCI_SPRD_CLK_MAX_DIV 0x3FF
+
+#define SDHCI_SPRD_CLK_DEF_RATE2600
+
+struct sdhci_sprd_host {
+   u32 version;
+   struct clk *clk_sdio;
+   struct clk *clk_enable;
+   u32 base_rate;
+};
+
+#define TO_SPRD_HOST(host) sdhci_pltfm_priv(sdhci_priv(host))
+
+static void sdhci_sprd_init_config(struct sdhci_host *host)
+{
+   u16 val;
+
+   /* set 64-bit addressing modes */
+   val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+   val |= SDHCI_CTRL_64BIT_ADDR;
+   sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
+
+   /* set dll backup mode */
+   val = sdhci_readl(host, SDHCI_SPRD_REG_DEBOUNCE);
+   val |= SDHCI_SPRD_BIT_DLL_BAK | SDHCI_SPRD_BIT_DLL_VAL;
+   sdhci_writel(host, val, SDHCI_SPRD_REG_DEBOUNCE);
+}
+
+static inline u32 sdhci_sprd_readl(struct sdhci_host *host, int reg)
+{
+   if (unlikely(reg == SDHCI_MAX_CURRENT))
+   return SDHCI_SPRD_MAX_CUR;
+
+   return readl_relaxed(host->ioaddr + reg);
+}
+
+static inline void sdhci_sprd_writel(struct sdhci_host *host, u32 val, int reg)
+{
+   /* SDHCI_MAX_CURRENT is reserved on Spreadtrum's platform */
+   if (unlikely(reg == SDHCI_MAX_CURRENT))
+   return;
+
+   if (unlikely(reg == SDHCI_SIGNAL_ENABLE || reg == SDHCI_INT_ENABLE))
+   val = val & SDHCI_SPRD_INT_SIGNAL_MASK;
+
+   return writel_relaxed(val, host->ioaddr + reg);
+}
+
+static inline void sdhci_sprd_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+   if