diff options
author | Peter Griffin <peter.griffin@linaro.org> | 2014-09-28 22:08:10 +0100 |
---|---|---|
committer | Peter Griffin <peter.griffin@linaro.org> | 2014-09-28 22:08:10 +0100 |
commit | fba6b0863766f5de8bbed91472f13af5f6b6be58 (patch) | |
tree | ba3c1e41d390fac0f480f6e232f2f01ef30c598f | |
parent | d3f078f61bbd3eb5f373edb21c6a3f77026b3b27 (diff) |
WiP: stih407 sdhci driverstih407-sdhci
-rw-r--r-- | drivers/mmc/host/sdhci-st.c | 98 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 3 |
2 files changed, 65 insertions, 36 deletions
diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 4d43a1fcc684..cb8b368c64bf 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -29,10 +29,10 @@ /* 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_TIMEOUT_CLK_UNIT BIT(24) +#define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ BIT(12) #define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT (0x10 << 4) -#define ST_MMC_CCONFIG_ASYNC_WAKEUP (1 << 0) +#define ST_MMC_CCONFIG_ASYNC_WAKEUP BIT(0) #define ST_MMC_CCONFIG_1_DEFAULT \ ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \ (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \ @@ -40,12 +40,12 @@ (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_HIGH_SPEED BIT(28) +#define ST_MMC_CCONFIG_ADMA2 BIT(24) +#define ST_MMC_CCONFIG_8BIT BIT(20) #define ST_MMC_CCONFIG_MAX_BLK_LEN 16 -#define MAX_BLK_LEN_1024 1 -#define MAX_BLK_LEN_2048 2 +#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) @@ -55,14 +55,14 @@ (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_EMMC_SLOT_TYPE BIT(28) +#define ST_MMC_CCONFIG_64BIT BIT(24) +#define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT BIT(20) +#define ST_MMC_CCONFIG_1P8_VOLT BIT(16) +#define ST_MMC_CCONFIG_3P0_VOLT BIT(12) +#define ST_MMC_CCONFIG_3P3_VOLT BIT(8) +#define ST_MMC_CCONFIG_SUSP_RES_SUPPORT BIT(4) +#define ST_MMC_CCONFIG_SDMA BIT(0) #define ST_MMC_CCONFIG_3_DEFAULT \ (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT | \ ST_MMC_CCONFIG_3P3_VOLT | \ @@ -70,24 +70,24 @@ 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_D_DRIVER BIT(20) +#define ST_MMC_CCONFIG_C_DRIVER BIT(16) +#define ST_MMC_CCONFIG_A_DRIVER BIT(12) +#define ST_MMC_CCONFIG_DDR50 BIT(8) +#define ST_MMC_CCONFIG_SDR104 BIT(4) +#define ST_MMC_CCONFIG_SDR50 BIT(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 ST_MMC_CCONFIG_TUNING_FOR_SDR50 BIT(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) +#define ST_MMC_GP_OUTPUT_CD BIT(12) /** * st_mmcss_cconfig: configure the Arasan HC inside the flashSS. @@ -101,7 +101,7 @@ * 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) +static void st_mmcss_cconfig(struct device_node *np, void __iomem *ioaddr, sdhci_host *host) { u32 cconf2, cconf3, cconf4, cconf5; int f_max; @@ -109,6 +109,8 @@ static void st_mmcss_cconfig(struct device_node *np, void __iomem *ioaddr) if (!of_device_is_compatible(np, "st,sdhci-stih407")) return; + host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; + cconf2 = ST_MMC_CCONFIG_2_DEFAULT; cconf3 = ST_MMC_CCONFIG_3_DEFAULT; cconf4 = ST_MMC_CCONFIG_4_DEFAULT; @@ -118,7 +120,6 @@ static void st_mmcss_cconfig(struct device_node *np, void __iomem *ioaddr) /* 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) @@ -127,32 +128,37 @@ static void st_mmcss_cconfig(struct device_node *np, void __iomem *ioaddr) cconf2 |= BASE_CLK_FREQ_50; writel_relaxed(cconf2, ioaddr + ST_MMC_CCONFIG_REG_2); - if (of_property_read_bool(np, "non-removable")) + + if (mmc->caps & MMC_CAP_NONREMOVABLE) 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")) +// if (of_property_read_bool(np, "mmc-cap-1p8")) + //TODO CHECK this is equivalent + if (mmc->caps & MMC_CAP_1_8V_DDR) 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")) { + + if (mmc->caps & 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")) { + if (mmc->caps & 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 - */ + /* + * 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")) + if (mmc->caps & MMC_CAP_UHS_DDR50) cconf4 |= ST_MMC_CCONFIG_DDR50; if (of_property_read_bool(np, "mmc-cap-cnt-timer-max")) @@ -222,6 +228,14 @@ static int sdhci_st_probe(struct platform_device *pdev) clk_prepare_enable(clk); + host->mmc->rstc = devm_reset_control_get_optional(&pdev->dev, NULL); + if (IS_ERR(host->mmc->rstc)) + host->mmc->rstc = NULL; + else + reset_control_deassert(host->mmc->rstc); + + st_mmcss_cconfig(np, host->ioaddr, host->mmc); + pltfm_host = sdhci_priv(host); pltfm_host->clk = clk; @@ -253,10 +267,14 @@ static int sdhci_st_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + int ret; clk_disable_unprepare(pltfm_host->clk); - return sdhci_pltfm_unregister(pdev); + ret = sdhci_pltfm_unregister(pdev); + + if (host->mmc->rstc) + reset_control_assert(host->mmc->rstc); } #ifdef CONFIG_PM_SLEEP @@ -269,6 +287,9 @@ static int sdhci_st_suspend(struct device *dev) if (ret) goto out; + if (host->mmc->rstc) + reset_control_assert(host->mmc->rstc); + clk_disable_unprepare(pltfm_host->clk); out: return ret; @@ -281,6 +302,11 @@ static int sdhci_st_resume(struct device *dev) clk_prepare_enable(pltfm_host->clk); + if (host->mmc->rstc) + reset_control_deassert(host->mmc->rstc); + + st_mmcss_cconfig(np, host->ioaddr); + return sdhci_resume_host(host); } #endif diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 7960424d0bc0..20b28bbb615a 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -350,6 +350,9 @@ struct mmc_host { #ifdef CONFIG_REGULATOR bool regulator_enabled; /* regulator state */ #endif + + struct reset_control *rstc; + struct mmc_supply supply; struct dentry *debugfs_root; |