Lines Matching +full:ciu +full:- +full:sample

1 // SPDX-License-Identifier: GPL-2.0-or-later
18 #include "dw_mmc-pltfm.h"
19 #include "dw_mmc-exynos.h"
21 /* Variations in Exynos specific dw-mshc controller */
54 .compatible = "samsung,exynos4210-dw-mshc",
57 .compatible = "samsung,exynos4412-dw-mshc",
60 .compatible = "samsung,exynos5250-dw-mshc",
63 .compatible = "samsung,exynos5420-dw-mshc",
66 .compatible = "samsung,exynos5420-dw-mshc-smu",
69 .compatible = "samsung,exynos7-dw-mshc",
72 .compatible = "samsung,exynos7-dw-mshc-smu",
75 .compatible = "samsung,exynos7870-dw-mshc",
78 .compatible = "samsung,exynos7870-dw-mshc-smu",
81 .compatible = "axis,artpec8-dw-mshc",
88 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_get_ciu_div()
90 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412) in dw_mci_exynos_get_ciu_div()
92 else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210) in dw_mci_exynos_get_ciu_div()
94 else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || in dw_mci_exynos_get_ciu_div()
95 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || in dw_mci_exynos_get_ciu_div()
96 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || in dw_mci_exynos_get_ciu_div()
97 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || in dw_mci_exynos_get_ciu_div()
98 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) in dw_mci_exynos_get_ciu_div()
106 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_config_smu()
110 * set for non-ecryption mode at this time. in dw_mci_exynos_config_smu()
112 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU || in dw_mci_exynos_config_smu()
113 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || in dw_mci_exynos_config_smu()
114 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) { in dw_mci_exynos_config_smu()
126 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_priv_init()
130 if (priv->ctrl_type >= DW_MCI_TYPE_EXYNOS5420) { in dw_mci_exynos_priv_init()
131 priv->saved_strobe_ctrl = mci_readl(host, HS400_DLINE_CTRL); in dw_mci_exynos_priv_init()
132 priv->saved_dqs_en = mci_readl(host, HS400_DQS_EN); in dw_mci_exynos_priv_init()
133 priv->saved_dqs_en |= AXI_NON_BLOCKING_WR; in dw_mci_exynos_priv_init()
134 mci_writel(host, HS400_DQS_EN, priv->saved_dqs_en); in dw_mci_exynos_priv_init()
135 if (!priv->dqs_delay) in dw_mci_exynos_priv_init()
136 priv->dqs_delay = in dw_mci_exynos_priv_init()
137 DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl); in dw_mci_exynos_priv_init()
140 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || in dw_mci_exynos_priv_init()
141 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) { in dw_mci_exynos_priv_init()
143 host->quirks |= DW_MMC_QUIRK_FIFO64_32; in dw_mci_exynos_priv_init()
146 if (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) { in dw_mci_exynos_priv_init()
147 /* Quirk needed for the ARTPEC-8 SoC */ in dw_mci_exynos_priv_init()
148 host->quirks |= DW_MMC_QUIRK_EXTENDED_TMOUT; in dw_mci_exynos_priv_init()
151 host->bus_hz /= (priv->ciu_div + 1); in dw_mci_exynos_priv_init()
158 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_set_clksel_timing()
161 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || in dw_mci_exynos_set_clksel_timing()
162 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || in dw_mci_exynos_set_clksel_timing()
163 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || in dw_mci_exynos_set_clksel_timing()
164 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || in dw_mci_exynos_set_clksel_timing()
165 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) in dw_mci_exynos_set_clksel_timing()
172 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || in dw_mci_exynos_set_clksel_timing()
173 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || in dw_mci_exynos_set_clksel_timing()
174 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || in dw_mci_exynos_set_clksel_timing()
175 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || in dw_mci_exynos_set_clksel_timing()
176 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) in dw_mci_exynos_set_clksel_timing()
188 if (!SDMMC_CLKSEL_GET_DRV_WD3(clksel) && host->slot) in dw_mci_exynos_set_clksel_timing()
189 set_bit(DW_MMC_CARD_NO_USE_HOLD, &host->slot->flags); in dw_mci_exynos_set_clksel_timing()
210 * dw_mci_exynos_suspend_noirq - Exynos-specific suspend code
223 * dw_mci_exynos_resume_noirq - Exynos-specific resume code
236 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_resume_noirq()
244 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || in dw_mci_exynos_resume_noirq()
245 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || in dw_mci_exynos_resume_noirq()
246 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || in dw_mci_exynos_resume_noirq()
247 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || in dw_mci_exynos_resume_noirq()
248 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) in dw_mci_exynos_resume_noirq()
254 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || in dw_mci_exynos_resume_noirq()
255 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || in dw_mci_exynos_resume_noirq()
256 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || in dw_mci_exynos_resume_noirq()
257 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || in dw_mci_exynos_resume_noirq()
258 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) in dw_mci_exynos_resume_noirq()
272 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_config_hs400()
279 if ((priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420) || in dw_mci_exynos_config_hs400()
280 (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)) { in dw_mci_exynos_config_hs400()
282 dev_warn(host->dev, in dw_mci_exynos_config_hs400()
287 dqs = priv->saved_dqs_en; in dw_mci_exynos_config_hs400()
288 strobe = priv->saved_strobe_ctrl; in dw_mci_exynos_config_hs400()
292 strobe = DQS_CTRL_RD_DELAY(strobe, priv->dqs_delay); in dw_mci_exynos_config_hs400()
305 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_adjust_clock()
311 * ciu clock is unavailable in dw_mci_exynos_adjust_clock()
313 if (!wanted || IS_ERR(host->ciu_clk)) in dw_mci_exynos_adjust_clock()
320 if (wanted == priv->cur_speed) in dw_mci_exynos_adjust_clock()
324 ret = clk_set_rate(host->ciu_clk, wanted * div); in dw_mci_exynos_adjust_clock()
326 dev_warn(host->dev, in dw_mci_exynos_adjust_clock()
327 "failed to set clk-rate %u error: %d\n", in dw_mci_exynos_adjust_clock()
329 actual = clk_get_rate(host->ciu_clk); in dw_mci_exynos_adjust_clock()
330 host->bus_hz = actual / div; in dw_mci_exynos_adjust_clock()
331 priv->cur_speed = wanted; in dw_mci_exynos_adjust_clock()
332 host->current_speed = 0; in dw_mci_exynos_adjust_clock()
337 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_set_ios()
338 unsigned int wanted = ios->clock; in dw_mci_exynos_set_ios()
339 u32 timing = ios->timing, clksel; in dw_mci_exynos_set_ios()
343 /* Update tuned sample timing */ in dw_mci_exynos_set_ios()
345 priv->hs400_timing, priv->tuned_sample); in dw_mci_exynos_set_ios()
349 clksel = priv->ddr_timing; in dw_mci_exynos_set_ios()
351 if (ios->bus_width == MMC_BUS_WIDTH_8) in dw_mci_exynos_set_ios()
356 clksel = (priv->sdr_timing & 0xfff8ffff) | in dw_mci_exynos_set_ios()
357 (priv->ciu_div << 16); in dw_mci_exynos_set_ios()
360 clksel = (priv->ddr_timing & 0xfff8ffff) | in dw_mci_exynos_set_ios()
361 (priv->ciu_div << 16); in dw_mci_exynos_set_ios()
364 clksel = priv->sdr_timing; in dw_mci_exynos_set_ios()
380 struct device_node *np = host->dev->of_node; in dw_mci_exynos_parse_dt()
386 priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); in dw_mci_exynos_parse_dt()
388 return -ENOMEM; in dw_mci_exynos_parse_dt()
392 priv->ctrl_type = exynos_compat[idx].ctrl_type; in dw_mci_exynos_parse_dt()
395 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412) in dw_mci_exynos_parse_dt()
396 priv->ciu_div = EXYNOS4412_FIXED_CIU_CLK_DIV - 1; in dw_mci_exynos_parse_dt()
397 else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210) in dw_mci_exynos_parse_dt()
398 priv->ciu_div = EXYNOS4210_FIXED_CIU_CLK_DIV - 1; in dw_mci_exynos_parse_dt()
400 of_property_read_u32(np, "samsung,dw-mshc-ciu-div", &div); in dw_mci_exynos_parse_dt()
401 priv->ciu_div = div; in dw_mci_exynos_parse_dt()
405 "samsung,dw-mshc-sdr-timing", timing, 2); in dw_mci_exynos_parse_dt()
409 priv->sdr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); in dw_mci_exynos_parse_dt()
412 "samsung,dw-mshc-ddr-timing", timing, 2); in dw_mci_exynos_parse_dt()
416 priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); in dw_mci_exynos_parse_dt()
419 "samsung,dw-mshc-hs400-timing", timing, 2); in dw_mci_exynos_parse_dt()
421 "samsung,read-strobe-delay", &priv->dqs_delay)) in dw_mci_exynos_parse_dt()
422 dev_dbg(host->dev, in dw_mci_exynos_parse_dt()
423 "read-strobe-delay is not found, assuming usage of default value\n"); in dw_mci_exynos_parse_dt()
425 priv->hs400_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], in dw_mci_exynos_parse_dt()
427 host->priv = priv; in dw_mci_exynos_parse_dt()
433 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_get_clksmpl()
435 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || in dw_mci_exynos_get_clksmpl()
436 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || in dw_mci_exynos_get_clksmpl()
437 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || in dw_mci_exynos_get_clksmpl()
438 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || in dw_mci_exynos_get_clksmpl()
439 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) in dw_mci_exynos_get_clksmpl()
445 static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample) in dw_mci_exynos_set_clksmpl() argument
448 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_set_clksmpl()
450 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || in dw_mci_exynos_set_clksmpl()
451 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || in dw_mci_exynos_set_clksmpl()
452 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || in dw_mci_exynos_set_clksmpl()
453 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || in dw_mci_exynos_set_clksmpl()
454 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) in dw_mci_exynos_set_clksmpl()
458 clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample); in dw_mci_exynos_set_clksmpl()
459 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || in dw_mci_exynos_set_clksmpl()
460 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || in dw_mci_exynos_set_clksmpl()
461 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || in dw_mci_exynos_set_clksmpl()
462 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || in dw_mci_exynos_set_clksmpl()
463 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) in dw_mci_exynos_set_clksmpl()
471 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_move_next_clksmpl()
473 u8 sample; in dw_mci_exynos_move_next_clksmpl() local
475 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || in dw_mci_exynos_move_next_clksmpl()
476 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || in dw_mci_exynos_move_next_clksmpl()
477 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || in dw_mci_exynos_move_next_clksmpl()
478 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || in dw_mci_exynos_move_next_clksmpl()
479 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) in dw_mci_exynos_move_next_clksmpl()
484 sample = (clksel + 1) & 0x7; in dw_mci_exynos_move_next_clksmpl()
485 clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample); in dw_mci_exynos_move_next_clksmpl()
487 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || in dw_mci_exynos_move_next_clksmpl()
488 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || in dw_mci_exynos_move_next_clksmpl()
489 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || in dw_mci_exynos_move_next_clksmpl()
490 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || in dw_mci_exynos_move_next_clksmpl()
491 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) in dw_mci_exynos_move_next_clksmpl()
496 return sample; in dw_mci_exynos_move_next_clksmpl()
503 s8 i, loc = -1; in dw_mci_exynos_get_best_clksmpl()
522 * If there is no cadiates value, then it needs to return -EIO. in dw_mci_exynos_get_best_clksmpl()
523 * If there are candidates values and don't find bset clk sample value, in dw_mci_exynos_get_best_clksmpl()
524 * then use a first candidates clock sample value. in dw_mci_exynos_get_best_clksmpl()
539 struct dw_mci *host = slot->host; in dw_mci_exynos_execute_tuning()
540 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_execute_tuning()
541 struct mmc_host *mmc = slot->mmc; in dw_mci_exynos_execute_tuning()
560 priv->tuned_sample = found; in dw_mci_exynos_execute_tuning()
562 ret = -EIO; in dw_mci_exynos_execute_tuning()
563 dev_warn(&mmc->class_dev, in dw_mci_exynos_execute_tuning()
573 struct dw_mci_exynos_priv_data *priv = host->priv; in dw_mci_exynos_prepare_hs400_tuning()
575 dw_mci_exynos_set_clksel_timing(host, priv->hs400_timing); in dw_mci_exynos_prepare_hs400_tuning()
576 dw_mci_exynos_adjust_clock(host, (ios->clock) << 1); in dw_mci_exynos_prepare_hs400_tuning()
592 tmp = DIV_ROUND_UP_ULL((u64)timeout_ns * host->bus_hz, NSEC_PER_SEC); in dw_mci_exynos_set_data_timeout()
600 * ((TMOUT[10:8] - 1) * 0xFFFFFF + TMOUT[31:11] * 8) in dw_mci_exynos_set_data_timeout()
610 tmp = tmp - ((tmp2 - 1) * 0xFFFFFF); in dw_mci_exynos_set_data_timeout()
615 dev_dbg(host->dev, "timeout_ns: %u => TMOUT[31:8]: %#08x", in dw_mci_exynos_set_data_timeout()
625 return (((drto_clks & 0x7) - 1) * 0xFFFFFF) + ((drto_clks & 0xFFFFF8)); in dw_mci_exynos_get_drto_clks()
658 { .compatible = "samsung,exynos4412-dw-mshc",
660 { .compatible = "samsung,exynos5250-dw-mshc",
662 { .compatible = "samsung,exynos5420-dw-mshc",
664 { .compatible = "samsung,exynos5420-dw-mshc-smu",
666 { .compatible = "samsung,exynos7-dw-mshc",
668 { .compatible = "samsung,exynos7-dw-mshc-smu",
670 { .compatible = "samsung,exynos7870-dw-mshc",
672 { .compatible = "samsung,exynos7870-dw-mshc-smu",
674 { .compatible = "axis,artpec8-dw-mshc",
686 match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node); in dw_mci_exynos_probe()
687 drv_data = match->data; in dw_mci_exynos_probe()
689 pm_runtime_get_noresume(&pdev->dev); in dw_mci_exynos_probe()
690 pm_runtime_set_active(&pdev->dev); in dw_mci_exynos_probe()
691 pm_runtime_enable(&pdev->dev); in dw_mci_exynos_probe()
695 pm_runtime_disable(&pdev->dev); in dw_mci_exynos_probe()
696 pm_runtime_set_suspended(&pdev->dev); in dw_mci_exynos_probe()
697 pm_runtime_put_noidle(&pdev->dev); in dw_mci_exynos_probe()
707 pm_runtime_disable(&pdev->dev); in dw_mci_exynos_remove()
708 pm_runtime_set_suspended(&pdev->dev); in dw_mci_exynos_remove()
709 pm_runtime_put_noidle(&pdev->dev); in dw_mci_exynos_remove()
735 MODULE_DESCRIPTION("Samsung Specific DW-MSHC Driver Extension");