aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Griffin <peter.griffin@linaro.org>2014-09-28 22:08:10 +0100
committerPeter Griffin <peter.griffin@linaro.org>2014-09-28 22:08:10 +0100
commitfba6b0863766f5de8bbed91472f13af5f6b6be58 (patch)
treeba3c1e41d390fac0f480f6e232f2f01ef30c598f
parentd3f078f61bbd3eb5f373edb21c6a3f77026b3b27 (diff)
WiP: stih407 sdhci driverstih407-sdhci
-rw-r--r--drivers/mmc/host/sdhci-st.c98
-rw-r--r--include/linux/mmc/host.h3
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;