aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/host/sdhci-st.c88
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 */
150static 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
141static inline void st_mmcss_set_dll(void __iomem *ioaddr) 222static 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
215static int sdhci_st_probe(struct platform_device *pdev) 296static 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