Lines Matching +full:imx8m +full:- +full:clock
1 // SPDX-License-Identifier: GPL-2.0
13 #include <linux/clk-provider.h>
14 #include <linux/arm-smccc.h>
40 * +----------+ |\ +------+
41 * | dram_pll |-------|M| dram_core | |
42 * +----------+ |U|---------->| D |
43 * /--|X| | D |
46 * +---------+ | |
48 * +---------+ | |
50 * +----------+ | | |
51 * | dram_alt |----/ | |
52 * +----------+ | |
53 * | dram_apb |-------------------->| |
54 * +----------+ +------+
58 * Frequency switching is implemented in TF-A (via SMC call) and can change the
86 * Firmware reports values in MT/s, so we round-down from Hz in imx8m_ddrc_find_freq()
90 for (i = 0; i < priv->freq_count; ++i) { in imx8m_ddrc_find_freq()
91 freq = &priv->freq_table[i]; in imx8m_ddrc_find_freq()
92 if (freq->rate == rate || in imx8m_ddrc_find_freq()
93 freq->rate + 1 == rate || in imx8m_ddrc_find_freq()
94 freq->rate - 1 == rate) in imx8m_ddrc_find_freq()
125 return hw ? hw->clk : NULL; in clk_get_parent_by_index()
143 priv->dram_core, freq->dram_core_parent_index - 1); in imx8m_ddrc_set_freq()
146 return -EINVAL; in imx8m_ddrc_set_freq()
148 if (freq->dram_alt_parent_index) { in imx8m_ddrc_set_freq()
150 priv->dram_alt, in imx8m_ddrc_set_freq()
151 freq->dram_alt_parent_index - 1); in imx8m_ddrc_set_freq()
154 return -EINVAL; in imx8m_ddrc_set_freq()
159 if (freq->dram_apb_parent_index) { in imx8m_ddrc_set_freq()
161 priv->dram_apb, in imx8m_ddrc_set_freq()
162 freq->dram_apb_parent_index - 1); in imx8m_ddrc_set_freq()
165 return -EINVAL; in imx8m_ddrc_set_freq()
190 imx8m_ddrc_smc_set_freq(freq->smcarg); in imx8m_ddrc_set_freq()
193 ret = clk_set_parent(priv->dram_core, new_dram_core_parent); in imx8m_ddrc_set_freq()
197 ret = clk_set_parent(priv->dram_alt, new_dram_alt_parent); in imx8m_ddrc_set_freq()
203 ret = clk_set_parent(priv->dram_apb, new_dram_apb_parent); in imx8m_ddrc_set_freq()
215 clk_get_rate(priv->dram_pll); in imx8m_ddrc_set_freq()
246 old_freq = clk_get_rate(priv->dram_core); in imx8m_ddrc_target()
252 return -EINVAL; in imx8m_ddrc_target()
260 new_freq = clk_get_rate(priv->dram_core); in imx8m_ddrc_target()
278 *freq = clk_get_rate(priv->dram_core); in imx8m_ddrc_get_cur_freq()
288 stat->busy_time = 0; in imx8m_ddrc_get_dev_status()
289 stat->total_time = 0; in imx8m_ddrc_get_dev_status()
290 stat->current_frequency = clk_get_rate(priv->dram_core); in imx8m_ddrc_get_dev_status()
304 priv->freq_count = res.a0; in imx8m_ddrc_init_freq_info()
305 if (priv->freq_count <= 0 || in imx8m_ddrc_init_freq_info()
306 priv->freq_count > IMX8M_DDRC_MAX_FREQ_COUNT) in imx8m_ddrc_init_freq_info()
307 return -ENODEV; in imx8m_ddrc_init_freq_info()
309 for (index = 0; index < priv->freq_count; ++index) { in imx8m_ddrc_init_freq_info()
310 struct imx8m_ddrc_freq *freq = &priv->freq_table[index]; in imx8m_ddrc_init_freq_info()
316 return -ENODEV; in imx8m_ddrc_init_freq_info()
318 freq->rate = res.a0; in imx8m_ddrc_init_freq_info()
319 freq->smcarg = index; in imx8m_ddrc_init_freq_info()
320 freq->dram_core_parent_index = res.a1; in imx8m_ddrc_init_freq_info()
321 freq->dram_alt_parent_index = res.a2; in imx8m_ddrc_init_freq_info()
322 freq->dram_apb_parent_index = res.a3; in imx8m_ddrc_init_freq_info()
325 if (freq->dram_core_parent_index != 1 && in imx8m_ddrc_init_freq_info()
326 freq->dram_core_parent_index != 2) in imx8m_ddrc_init_freq_info()
327 return -ENODEV; in imx8m_ddrc_init_freq_info()
329 if (freq->dram_alt_parent_index > 8 || in imx8m_ddrc_init_freq_info()
330 freq->dram_apb_parent_index > 8) in imx8m_ddrc_init_freq_info()
331 return -ENODEV; in imx8m_ddrc_init_freq_info()
333 if (freq->dram_core_parent_index == 2 && in imx8m_ddrc_init_freq_info()
334 freq->dram_alt_parent_index == 0) in imx8m_ddrc_init_freq_info()
335 return -ENODEV; in imx8m_ddrc_init_freq_info()
380 struct device *dev = &pdev->dev; in imx8m_ddrc_probe()
387 return -ENOMEM; in imx8m_ddrc_probe()
397 priv->dram_core = devm_clk_get(dev, "core"); in imx8m_ddrc_probe()
398 if (IS_ERR(priv->dram_core)) { in imx8m_ddrc_probe()
399 ret = PTR_ERR(priv->dram_core); in imx8m_ddrc_probe()
400 dev_err(dev, "failed to fetch core clock: %d\n", ret); in imx8m_ddrc_probe()
403 priv->dram_pll = devm_clk_get(dev, "pll"); in imx8m_ddrc_probe()
404 if (IS_ERR(priv->dram_pll)) { in imx8m_ddrc_probe()
405 ret = PTR_ERR(priv->dram_pll); in imx8m_ddrc_probe()
406 dev_err(dev, "failed to fetch pll clock: %d\n", ret); in imx8m_ddrc_probe()
409 priv->dram_alt = devm_clk_get(dev, "alt"); in imx8m_ddrc_probe()
410 if (IS_ERR(priv->dram_alt)) { in imx8m_ddrc_probe()
411 ret = PTR_ERR(priv->dram_alt); in imx8m_ddrc_probe()
412 dev_err(dev, "failed to fetch alt clock: %d\n", ret); in imx8m_ddrc_probe()
415 priv->dram_apb = devm_clk_get(dev, "apb"); in imx8m_ddrc_probe()
416 if (IS_ERR(priv->dram_apb)) { in imx8m_ddrc_probe()
417 ret = PTR_ERR(priv->dram_apb); in imx8m_ddrc_probe()
418 dev_err(dev, "failed to fetch apb clock: %d\n", ret); in imx8m_ddrc_probe()
432 priv->profile.polling_ms = 1000; in imx8m_ddrc_probe()
433 priv->profile.target = imx8m_ddrc_target; in imx8m_ddrc_probe()
434 priv->profile.get_dev_status = imx8m_ddrc_get_dev_status; in imx8m_ddrc_probe()
435 priv->profile.exit = imx8m_ddrc_exit; in imx8m_ddrc_probe()
436 priv->profile.get_cur_freq = imx8m_ddrc_get_cur_freq; in imx8m_ddrc_probe()
437 priv->profile.initial_freq = clk_get_rate(priv->dram_core); in imx8m_ddrc_probe()
439 priv->devfreq = devm_devfreq_add_device(dev, &priv->profile, in imx8m_ddrc_probe()
441 if (IS_ERR(priv->devfreq)) { in imx8m_ddrc_probe()
442 ret = PTR_ERR(priv->devfreq); in imx8m_ddrc_probe()
455 { .compatible = "fsl,imx8m-ddrc", },
463 .name = "imx8m-ddrc-devfreq",