Lines Matching +full:clock +full:- +full:phase
1 // SPDX-License-Identifier: GPL-2.0-or-later
11 #include <linux/mmc/slot-gpio.h>
16 #include "dw_mmc-pltfm.h"
31 struct dw_mci_rockchip_priv_data *priv = host->priv; in dw_mci_rk3288_set_ios()
36 if (ios->clock == 0) in dw_mci_rk3288_set_ios()
40 * cclkin: source clock of mmc controller in dw_mci_rk3288_set_ios()
41 * bus_hz: card interface clock generated by CLKGEN in dw_mci_rk3288_set_ios()
43 * ios->clock = (div == 0) ? bus_hz : (bus_hz / (2 * div)) in dw_mci_rk3288_set_ios()
46 * DDR52 8-bit mode. in dw_mci_rk3288_set_ios()
48 if (ios->bus_width == MMC_BUS_WIDTH_8 && in dw_mci_rk3288_set_ios()
49 ios->timing == MMC_TIMING_MMC_DDR52) in dw_mci_rk3288_set_ios()
50 cclkin = 2 * ios->clock * RK3288_CLKGEN_DIV; in dw_mci_rk3288_set_ios()
52 cclkin = ios->clock * RK3288_CLKGEN_DIV; in dw_mci_rk3288_set_ios()
54 ret = clk_set_rate(host->ciu_clk, cclkin); in dw_mci_rk3288_set_ios()
56 dev_warn(host->dev, "failed to set rate %uHz err: %d\n", cclkin, ret); in dw_mci_rk3288_set_ios()
58 bus_hz = clk_get_rate(host->ciu_clk) / RK3288_CLKGEN_DIV; in dw_mci_rk3288_set_ios()
59 if (bus_hz != host->bus_hz) { in dw_mci_rk3288_set_ios()
60 host->bus_hz = bus_hz; in dw_mci_rk3288_set_ios()
62 host->current_speed = 0; in dw_mci_rk3288_set_ios()
66 if (!IS_ERR(priv->sample_clk) && ios->timing <= MMC_TIMING_SD_HS) in dw_mci_rk3288_set_ios()
67 clk_set_phase(priv->sample_clk, priv->default_sample_phase); in dw_mci_rk3288_set_ios()
70 * Set the drive phase offset based on speed mode to achieve hold times. in dw_mci_rk3288_set_ios()
75 * different output clock delays inside their dw_mmc IP block (delay_o), in dw_mci_rk3288_set_ios()
84 * two modes the databook calculations assume a clock in of 50MHz. As in dw_mci_rk3288_set_ios()
85 * seen above, we always use a clock in rate that is exactly the in dw_mci_rk3288_set_ios()
86 * card's input clock (times RK3288_CLKGEN_DIV, but that gets divided in dw_mci_rk3288_set_ios()
95 if (!IS_ERR(priv->drv_clk)) { in dw_mci_rk3288_set_ios()
96 int phase; in dw_mci_rk3288_set_ios() local
99 * In almost all cases a 90 degree phase offset will provide in dw_mci_rk3288_set_ios()
100 * sufficient hold times across all valid input clock rates in dw_mci_rk3288_set_ios()
104 phase = 90; in dw_mci_rk3288_set_ios()
106 switch (ios->timing) { in dw_mci_rk3288_set_ios()
109 * Since clock in rate with MMC_DDR52 is doubled when in dw_mci_rk3288_set_ios()
110 * bus width is 8 we need to double the phase offset in dw_mci_rk3288_set_ios()
113 if (ios->bus_width == MMC_BUS_WIDTH_8) in dw_mci_rk3288_set_ios()
114 phase = 180; in dw_mci_rk3288_set_ios()
119 * In the case of 150 MHz clock (typical max for in dw_mci_rk3288_set_ios()
122 * as long as clock output delay is < .87 ns. On in dw_mci_rk3288_set_ios()
126 phase = 180; in dw_mci_rk3288_set_ios()
130 clk_set_phase(priv->drv_clk, phase); in dw_mci_rk3288_set_ios()
139 struct dw_mci *host = slot->host; in dw_mci_rk3288_execute_tuning()
140 struct dw_mci_rockchip_priv_data *priv = host->priv; in dw_mci_rk3288_execute_tuning()
141 struct mmc_host *mmc = slot->mmc; in dw_mci_rk3288_execute_tuning()
151 int longest_range_len = -1; in dw_mci_rk3288_execute_tuning()
152 int longest_range = -1; in dw_mci_rk3288_execute_tuning()
155 if (IS_ERR(priv->sample_clk)) { in dw_mci_rk3288_execute_tuning()
156 dev_err(host->dev, "Tuning clock (sample_clk) not defined.\n"); in dw_mci_rk3288_execute_tuning()
157 return -EIO; in dw_mci_rk3288_execute_tuning()
160 ranges = kmalloc_array(priv->num_phases / 2 + 1, in dw_mci_rk3288_execute_tuning()
163 return -ENOMEM; in dw_mci_rk3288_execute_tuning()
165 /* Try each phase and extract good ranges */ in dw_mci_rk3288_execute_tuning()
166 for (i = 0; i < priv->num_phases; ) { in dw_mci_rk3288_execute_tuning()
167 clk_set_phase(priv->sample_clk, in dw_mci_rk3288_execute_tuning()
168 TUNING_ITERATION_TO_PHASE(i, priv->num_phases)); in dw_mci_rk3288_execute_tuning()
177 ranges[range_count-1].start = i; in dw_mci_rk3288_execute_tuning()
180 ranges[range_count-1].end = i; in dw_mci_rk3288_execute_tuning()
182 } else if (i == priv->num_phases - 1) { in dw_mci_rk3288_execute_tuning()
191 i += DIV_ROUND_UP(20 * priv->num_phases, 360); in dw_mci_rk3288_execute_tuning()
194 if (i >= priv->num_phases) in dw_mci_rk3288_execute_tuning()
195 i = priv->num_phases - 1; in dw_mci_rk3288_execute_tuning()
202 dev_warn(host->dev, "All phases bad!"); in dw_mci_rk3288_execute_tuning()
203 ret = -EIO; in dw_mci_rk3288_execute_tuning()
209 ranges[0].start = ranges[range_count-1].start; in dw_mci_rk3288_execute_tuning()
210 range_count--; in dw_mci_rk3288_execute_tuning()
213 if (ranges[0].start == 0 && ranges[0].end == priv->num_phases - 1) { in dw_mci_rk3288_execute_tuning()
214 clk_set_phase(priv->sample_clk, priv->default_sample_phase); in dw_mci_rk3288_execute_tuning()
215 dev_info(host->dev, "All phases work, using default phase %d.", in dw_mci_rk3288_execute_tuning()
216 priv->default_sample_phase); in dw_mci_rk3288_execute_tuning()
222 int len = (ranges[i].end - ranges[i].start + 1); in dw_mci_rk3288_execute_tuning()
225 len += priv->num_phases; in dw_mci_rk3288_execute_tuning()
232 dev_dbg(host->dev, "Good phase range %d-%d (%d len)\n", in dw_mci_rk3288_execute_tuning()
234 priv->num_phases), in dw_mci_rk3288_execute_tuning()
236 priv->num_phases), in dw_mci_rk3288_execute_tuning()
241 dev_dbg(host->dev, "Best phase range %d-%d (%d len)\n", in dw_mci_rk3288_execute_tuning()
243 priv->num_phases), in dw_mci_rk3288_execute_tuning()
245 priv->num_phases), in dw_mci_rk3288_execute_tuning()
250 middle_phase %= priv->num_phases; in dw_mci_rk3288_execute_tuning()
251 dev_info(host->dev, "Successfully tuned phase to %d\n", in dw_mci_rk3288_execute_tuning()
252 TUNING_ITERATION_TO_PHASE(middle_phase, priv->num_phases)); in dw_mci_rk3288_execute_tuning()
254 clk_set_phase(priv->sample_clk, in dw_mci_rk3288_execute_tuning()
256 priv->num_phases)); in dw_mci_rk3288_execute_tuning()
265 struct device_node *np = host->dev->of_node; in dw_mci_rk3288_parse_dt()
268 priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); in dw_mci_rk3288_parse_dt()
270 return -ENOMEM; in dw_mci_rk3288_parse_dt()
272 if (of_property_read_u32(np, "rockchip,desired-num-phases", in dw_mci_rk3288_parse_dt()
273 &priv->num_phases)) in dw_mci_rk3288_parse_dt()
274 priv->num_phases = 360; in dw_mci_rk3288_parse_dt()
276 if (of_property_read_u32(np, "rockchip,default-sample-phase", in dw_mci_rk3288_parse_dt()
277 &priv->default_sample_phase)) in dw_mci_rk3288_parse_dt()
278 priv->default_sample_phase = 0; in dw_mci_rk3288_parse_dt()
280 priv->drv_clk = devm_clk_get(host->dev, "ciu-drive"); in dw_mci_rk3288_parse_dt()
281 if (IS_ERR(priv->drv_clk)) in dw_mci_rk3288_parse_dt()
282 dev_dbg(host->dev, "ciu-drive not available\n"); in dw_mci_rk3288_parse_dt()
284 priv->sample_clk = devm_clk_get(host->dev, "ciu-sample"); in dw_mci_rk3288_parse_dt()
285 if (IS_ERR(priv->sample_clk)) in dw_mci_rk3288_parse_dt()
286 dev_dbg(host->dev, "ciu-sample not available\n"); in dw_mci_rk3288_parse_dt()
288 host->priv = priv; in dw_mci_rk3288_parse_dt()
298 host->sdio_id0 = 8; in dw_mci_rockchip_init()
300 if (of_device_is_compatible(host->dev->of_node, "rockchip,rk3288-dw-mshc")) { in dw_mci_rockchip_init()
301 host->bus_hz /= RK3288_CLKGEN_DIV; in dw_mci_rockchip_init()
303 /* clock driver will fail if the clock is less than the lowest source clock in dw_mci_rockchip_init()
304 * divided by the internal clock divider. Test for the lowest available in dw_mci_rockchip_init()
305 * clock and set the minimum freq to clock / clock divider. in dw_mci_rockchip_init()
309 ret = clk_round_rate(host->ciu_clk, freqs[i] * RK3288_CLKGEN_DIV); in dw_mci_rockchip_init()
311 host->minimum_speed = ret / RK3288_CLKGEN_DIV; in dw_mci_rockchip_init()
316 dev_warn(host->dev, "no valid minimum freq: %d\n", ret); in dw_mci_rockchip_init()
335 { .compatible = "rockchip,rk2928-dw-mshc",
337 { .compatible = "rockchip,rk3288-dw-mshc",
349 if (!pdev->dev.of_node) in dw_mci_rockchip_probe()
350 return -ENODEV; in dw_mci_rockchip_probe()
352 match = of_match_node(dw_mci_rockchip_match, pdev->dev.of_node); in dw_mci_rockchip_probe()
353 drv_data = match->data; in dw_mci_rockchip_probe()
355 pm_runtime_get_noresume(&pdev->dev); in dw_mci_rockchip_probe()
356 pm_runtime_set_active(&pdev->dev); in dw_mci_rockchip_probe()
357 pm_runtime_enable(&pdev->dev); in dw_mci_rockchip_probe()
358 pm_runtime_set_autosuspend_delay(&pdev->dev, 50); in dw_mci_rockchip_probe()
359 pm_runtime_use_autosuspend(&pdev->dev); in dw_mci_rockchip_probe()
363 pm_runtime_disable(&pdev->dev); in dw_mci_rockchip_probe()
364 pm_runtime_set_suspended(&pdev->dev); in dw_mci_rockchip_probe()
365 pm_runtime_put_noidle(&pdev->dev); in dw_mci_rockchip_probe()
369 pm_runtime_put_autosuspend(&pdev->dev); in dw_mci_rockchip_probe()
376 pm_runtime_get_sync(&pdev->dev); in dw_mci_rockchip_remove()
377 pm_runtime_disable(&pdev->dev); in dw_mci_rockchip_remove()
378 pm_runtime_put_noidle(&pdev->dev); in dw_mci_rockchip_remove()
404 MODULE_AUTHOR("Addy Ke <addy.ke@rock-chips.com>");
405 MODULE_DESCRIPTION("Rockchip Specific DW-MSHC Driver Extension");