[PATCH V2 6/7] mmc: sdhci-sprd: added Spreadtrum's initial host controller
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
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