diff options
author | Peter Griffin <peter.griffin@linaro.org> | 2014-09-23 23:09:11 +0100 |
---|---|---|
committer | Peter Griffin <peter.griffin@linaro.org> | 2014-09-23 23:09:11 +0100 |
commit | d3f078f61bbd3eb5f373edb21c6a3f77026b3b27 (patch) | |
tree | a289132ea9fc1f61e0310b0ee4405b0f6cfb7a15 | |
parent | 0f33be009b89d2268e94194dc4fd01a7851b6d51 (diff) |
stih407: code from sti kernel
-rw-r--r-- | drivers/mmc/host/sdhci-st.c | 136 |
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; |