diff options
-rw-r--r-- | drivers/mmc/host/sdhci-st.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 1fbea9af7ae4..10989edb5100 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c | |||
@@ -138,6 +138,87 @@ static inline void st_mmcss_set_static_delay(void __iomem *ioaddr) | |||
138 | ioaddr + ST_TOP_MMC_TX_CLK_DLY); | 138 | ioaddr + ST_TOP_MMC_TX_CLK_DLY); |
139 | } | 139 | } |
140 | 140 | ||
141 | /** | ||
142 | * st_mmcss_cconfig: configure the Arasan HC inside the flashSS. | ||
143 | * @np: dt device node. | ||
144 | * @host: sdhci host | ||
145 | * Description: this function is to configure the Arasan host controller. | ||
146 | * On some ST SoCs, i.e. STiH407 family, the MMC devices inside a dedicated | ||
147 | * flashSS sub-system which needs to be configured to be compliant to eMMC 4.5 | ||
148 | * or eMMC4.3. This has to be done before registering the sdhci host. | ||
149 | */ | ||
150 | static void st_mmcss_cconfig(struct device_node *np, struct sdhci_host *host) | ||
151 | { | ||
152 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
153 | struct mmc_host *mhost = host->mmc; | ||
154 | u32 cconf2, cconf3, cconf4, cconf5; | ||
155 | |||
156 | if (!of_device_is_compatible(np, "st,sdhci-stih407")) | ||
157 | return; | ||
158 | |||
159 | cconf2 = ST_MMC_CCONFIG_2_DEFAULT; | ||
160 | cconf3 = ST_MMC_CCONFIG_3_DEFAULT; | ||
161 | cconf4 = ST_MMC_CCONFIG_4_DEFAULT; | ||
162 | cconf5 = ST_MMC_CCONFIG_5_DEFAULT; | ||
163 | |||
164 | writel_relaxed(ST_MMC_CCONFIG_1_DEFAULT, | ||
165 | host->ioaddr + ST_MMC_CCONFIG_REG_1); | ||
166 | |||
167 | /* Set clock frequency, default to 50MHz if max-frequency is not | ||
168 | * provided */ | ||
169 | |||
170 | switch (mhost->f_max) { | ||
171 | case 200000000: | ||
172 | clk_set_rate(pltfm_host->clk, mhost->f_max); | ||
173 | cconf2 |= BASE_CLK_FREQ_200; | ||
174 | break; | ||
175 | case 100000000: | ||
176 | clk_set_rate(pltfm_host->clk, mhost->f_max); | ||
177 | cconf2 |= BASE_CLK_FREQ_100; | ||
178 | break; | ||
179 | default: | ||
180 | clk_set_rate(pltfm_host->clk, 50000000); | ||
181 | cconf2 |= BASE_CLK_FREQ_50; | ||
182 | } | ||
183 | |||
184 | writel_relaxed(cconf2, host->ioaddr + ST_MMC_CCONFIG_REG_2); | ||
185 | |||
186 | if (mhost->caps & MMC_CAP_NONREMOVABLE) | ||
187 | cconf3 |= ST_MMC_CCONFIG_EMMC_SLOT_TYPE; | ||
188 | else | ||
189 | /* CARD _D ET_CTRL */ | ||
190 | writel_relaxed(ST_MMC_GP_OUTPUT_CD, | ||
191 | host->ioaddr + ST_MMC_GP_OUTPUT); | ||
192 | |||
193 | if (mhost->caps & MMC_CAP_UHS_SDR50) { | ||
194 | /* use 1.8V */ | ||
195 | cconf3 |= ST_MMC_CCONFIG_1P8_VOLT; | ||
196 | cconf4 |= ST_MMC_CCONFIG_SDR50; | ||
197 | /* Use tuning */ | ||
198 | cconf5 |= ST_MMC_CCONFIG_TUNING_FOR_SDR50; | ||
199 | /* Max timeout for retuning */ | ||
200 | cconf5 |= RETUNING_TIMER_CNT_MAX; | ||
201 | } | ||
202 | |||
203 | if (mhost->caps & MMC_CAP_UHS_SDR104) { | ||
204 | /* | ||
205 | * SDR104 implies the HC can support HS200 mode, so | ||
206 | * it's mandatory to use 1.8V | ||
207 | */ | ||
208 | cconf3 |= ST_MMC_CCONFIG_1P8_VOLT; | ||
209 | cconf4 |= ST_MMC_CCONFIG_SDR104; | ||
210 | /* Max timeout for retuning */ | ||
211 | cconf5 |= RETUNING_TIMER_CNT_MAX; | ||
212 | } | ||
213 | |||
214 | if (mhost->caps & MMC_CAP_UHS_DDR50) | ||
215 | cconf4 |= ST_MMC_CCONFIG_DDR50; | ||
216 | |||
217 | writel_relaxed(cconf3, host->ioaddr + ST_MMC_CCONFIG_REG_3); | ||
218 | writel_relaxed(cconf4, host->ioaddr + ST_MMC_CCONFIG_REG_4); | ||
219 | writel_relaxed(cconf5, host->ioaddr + ST_MMC_CCONFIG_REG_5); | ||
220 | } | ||
221 | |||
141 | static inline void st_mmcss_set_dll(void __iomem *ioaddr) | 222 | static inline void st_mmcss_set_dll(void __iomem *ioaddr) |
142 | { | 223 | { |
143 | if (!ioaddr) | 224 | if (!ioaddr) |
@@ -214,6 +295,7 @@ static const struct sdhci_pltfm_data sdhci_st_pdata = { | |||
214 | 295 | ||
215 | static int sdhci_st_probe(struct platform_device *pdev) | 296 | static int sdhci_st_probe(struct platform_device *pdev) |
216 | { | 297 | { |
298 | struct device_node *np = pdev->dev.of_node; | ||
217 | struct sdhci_host *host; | 299 | struct sdhci_host *host; |
218 | struct st_mmc_platform_data *pdata; | 300 | struct st_mmc_platform_data *pdata; |
219 | struct sdhci_pltfm_host *pltfm_host; | 301 | struct sdhci_pltfm_host *pltfm_host; |
@@ -266,6 +348,9 @@ static int sdhci_st_probe(struct platform_device *pdev) | |||
266 | pltfm_host->priv = pdata; | 348 | pltfm_host->priv = pdata; |
267 | pltfm_host->clk = clk; | 349 | pltfm_host->clk = clk; |
268 | 350 | ||
351 | /* Configure the Arasan HC inside the flashSS */ | ||
352 | st_mmcss_cconfig(np, host); | ||
353 | |||
269 | ret = sdhci_add_host(host); | 354 | ret = sdhci_add_host(host); |
270 | if (ret) { | 355 | if (ret) { |
271 | dev_err(&pdev->dev, "Failed sdhci_add_host\n"); | 356 | dev_err(&pdev->dev, "Failed sdhci_add_host\n"); |
@@ -333,12 +418,15 @@ static int sdhci_st_resume(struct device *dev) | |||
333 | struct sdhci_host *host = dev_get_drvdata(dev); | 418 | struct sdhci_host *host = dev_get_drvdata(dev); |
334 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 419 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
335 | struct st_mmc_platform_data *pdata = pltfm_host->priv; | 420 | struct st_mmc_platform_data *pdata = pltfm_host->priv; |
421 | struct device_node *np = dev->of_node; | ||
336 | 422 | ||
337 | clk_prepare_enable(pltfm_host->clk); | 423 | clk_prepare_enable(pltfm_host->clk); |
338 | 424 | ||
339 | if (pdata->rstc) | 425 | if (pdata->rstc) |
340 | reset_control_deassert(pdata->rstc); | 426 | reset_control_deassert(pdata->rstc); |
341 | 427 | ||
428 | st_mmcss_cconfig(np, host); | ||
429 | |||
342 | return sdhci_resume_host(host); | 430 | return sdhci_resume_host(host); |
343 | } | 431 | } |
344 | #endif | 432 | #endif |