aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Griffin <peter.griffin@linaro.org>2014-09-23 23:09:11 +0100
committerPeter Griffin <peter.griffin@linaro.org>2014-09-23 23:09:11 +0100
commitd3f078f61bbd3eb5f373edb21c6a3f77026b3b27 (patch)
treea289132ea9fc1f61e0310b0ee4405b0f6cfb7a15
parent0f33be009b89d2268e94194dc4fd01a7851b6d51 (diff)
stih407: code from sti kernel
-rw-r--r--drivers/mmc/host/sdhci-st.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c
index 328f348c7243..4d43a1fcc684 100644
--- a/drivers/mmc/host/sdhci-st.c
+++ b/drivers/mmc/host/sdhci-st.c
@@ -26,6 +26,142 @@
#include "sdhci-pltfm.h"
+/* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407) */
+
+#define ST_MMC_CCONFIG_REG_1 0x400
+#define ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT (1 << 24)
+#define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ (1 << 12)
+#define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT (0x10 << 4)
+#define ST_MMC_CCONFIG_ASYNC_WAKEUP (1 << 0)
+#define ST_MMC_CCONFIG_1_DEFAULT \
+ ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \
+ (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \
+ (ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT) | \
+ (ST_MMC_CCONFIG_ASYNC_WAKEUP))
+
+#define ST_MMC_CCONFIG_REG_2 0x404
+#define ST_MMC_CCONFIG_HIGH_SPEED (1 << 28)
+#define ST_MMC_CCONFIG_ADMA2 (1 << 24)
+#define ST_MMC_CCONFIG_8BIT (1 << 20)
+#define ST_MMC_CCONFIG_MAX_BLK_LEN 16
+#define MAX_BLK_LEN_1024 1
+#define MAX_BLK_LEN_2048 2
+#define BASE_CLK_FREQ_200 (0xc8 << 0)
+#define BASE_CLK_FREQ_100 (0x64 << 0)
+#define BASE_CLK_FREQ_50 (0x32 << 0)
+#define ST_MMC_CCONFIG_2_DEFAULT \
+ (ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \
+ ST_MMC_CCONFIG_8BIT | \
+ (MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN))
+
+#define ST_MMC_CCONFIG_REG_3 0x408
+#define ST_MMC_CCONFIG_EMMC_SLOT_TYPE (1 << 28)
+#define ST_MMC_CCONFIG_64BIT (1 << 24)
+#define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT (1 << 20)
+#define ST_MMC_CCONFIG_1P8_VOLT (1 << 16)
+#define ST_MMC_CCONFIG_3P0_VOLT (1 << 12)
+#define ST_MMC_CCONFIG_3P3_VOLT (1 << 8)
+#define ST_MMC_CCONFIG_SUSP_RES_SUPPORT (1 << 4)
+#define ST_MMC_CCONFIG_SDMA (1 << 0)
+#define ST_MMC_CCONFIG_3_DEFAULT \
+ (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT | \
+ ST_MMC_CCONFIG_3P3_VOLT | \
+ ST_MMC_CCONFIG_SUSP_RES_SUPPORT | \
+ ST_MMC_CCONFIG_SDMA)
+
+#define ST_MMC_CCONFIG_REG_4 0x40c
+#define ST_MMC_CCONFIG_D_DRIVER (1 << 20)
+#define ST_MMC_CCONFIG_C_DRIVER (1 << 16)
+#define ST_MMC_CCONFIG_A_DRIVER (1 << 12)
+#define ST_MMC_CCONFIG_DDR50 (1 << 8)
+#define ST_MMC_CCONFIG_SDR104 (1 << 4)
+#define ST_MMC_CCONFIG_SDR50 (1 << 0)
+#define ST_MMC_CCONFIG_4_DEFAULT (ST_MMC_CCONFIG_D_DRIVER | \
+ ST_MMC_CCONFIG_C_DRIVER | \
+ ST_MMC_CCONFIG_A_DRIVER)
+
+#define ST_MMC_CCONFIG_REG_5 0x410
+#define ST_MMC_CCONFIG_TUNING_FOR_SDR50 (1 << 8)
+#define RETUNING_TIMER_CNT_MAX (0xf << 0)
+#define ST_MMC_CCONFIG_5_DEFAULT 0
+
+/* I/O configuration for Arasan IP */
+#define ST_MMC_GP_OUTPUT 0x450
+#define ST_MMC_GP_OUTPUT_CD (1 << 12)
+
+/**
+ * st_mmcss_cconfig: configure the Arasan HC inside the flashSS.
+ * @np: dt device node.
+ * @ioaddr: base address
+ * Description: this function is to configure the Arasan host controller.
+ * On some ST SoCs, i.e. STiH407, the MMC devices inside a dedicated flashSS
+ * sub-system need to be configured to be compliant to eMMC 4.5 or eMMC4.3.
+ * This has to be done before registering the sdhci host.
+ * There are some default settings for the core-config registers (cconfig) and
+ * others can be provided from device-tree to fix and tuning the IP according to
+ * what has been validated.
+ */
+static void st_mmcss_cconfig(struct device_node *np, void __iomem *ioaddr)
+{
+ u32 cconf2, cconf3, cconf4, cconf5;
+ int f_max;
+
+ if (!of_device_is_compatible(np, "st,sdhci-stih407"))
+ return;
+
+ cconf2 = ST_MMC_CCONFIG_2_DEFAULT;
+ cconf3 = ST_MMC_CCONFIG_3_DEFAULT;
+ cconf4 = ST_MMC_CCONFIG_4_DEFAULT;
+ cconf5 = ST_MMC_CCONFIG_5_DEFAULT;
+
+ writel_relaxed(ST_MMC_CCONFIG_1_DEFAULT, ioaddr + ST_MMC_CCONFIG_REG_1);
+
+ /* Use 50MHz by default and also in case of max-frequency is not
+ * provided */
+ of_property_read_u32(np, "max-frequency", &f_max);
+ if (f_max == 200000000)
+ cconf2 |= BASE_CLK_FREQ_200;
+ else if (f_max == 100000000)
+ cconf2 |= BASE_CLK_FREQ_100;
+ else
+ cconf2 |= BASE_CLK_FREQ_50;
+ writel_relaxed(cconf2, ioaddr + ST_MMC_CCONFIG_REG_2);
+
+ if (of_property_read_bool(np, "non-removable"))
+ cconf3 |= ST_MMC_CCONFIG_EMMC_SLOT_TYPE;
+ else
+ /* CARD _D ET_CTRL */
+ writel_relaxed(ST_MMC_GP_OUTPUT_CD, ioaddr + ST_MMC_GP_OUTPUT);
+
+ if (of_property_read_bool(np, "mmc-cap-1p8"))
+ cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;
+
+ writel_relaxed(cconf3, ioaddr + ST_MMC_CCONFIG_REG_3);
+
+ if (of_property_read_bool(np, "mmc-cap-uhs-sdr50")) {
+ cconf4 |= ST_MMC_CCONFIG_SDR50;
+ cconf5 |= ST_MMC_CCONFIG_TUNING_FOR_SDR50;
+ }
+
+ if (of_property_read_bool(np, "mmc-cap-uhs-sdr104")) {
+ cconf4 |= ST_MMC_CCONFIG_SDR104;
+ /*
+ * SDR104 implies the HC can support HS200 mode, so
+ * it's mandatory to use 1.8V
+ */
+ cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;
+ }
+
+ if (of_property_read_bool(np, "mmc-cap-uhs-ddr50"))
+ cconf4 |= ST_MMC_CCONFIG_DDR50;
+
+ if (of_property_read_bool(np, "mmc-cap-cnt-timer-max"))
+ cconf5 = RETUNING_TIMER_CNT_MAX;
+
+ writel_relaxed(cconf4, ioaddr + ST_MMC_CCONFIG_REG_4);
+ writel_relaxed(cconf5, ioaddr + ST_MMC_CCONFIG_REG_5);
+}
+
static u32 sdhci_st_readl(struct sdhci_host *host, int reg)
{
u32 ret;