Lines Matching +full:ddr +full:- +full:pmu

1 // SPDX-License-Identifier: GPL-2.0-only
4 * Author: Lin Huang <hl@rock-chips.com>
7 #include <linux/arm-smccc.h>
11 #include <linux/devfreq-event.h>
79 unsigned long old_clk_rate = dmcfreq->rate; in rk3399_dmcfreq_target()
93 if (dmcfreq->rate == target_rate) in rk3399_dmcfreq_target()
96 mutex_lock(&dmcfreq->lock); in rk3399_dmcfreq_target()
98 if (dmcfreq->regmap_pmu) { in rk3399_dmcfreq_target()
99 if (target_rate >= dmcfreq->odt_dis_freq) in rk3399_dmcfreq_target()
103 * This makes a SMC call to the TF-A to set the DDR PD in rk3399_dmcfreq_target()
104 * (power-down) timings and to enable or disable the in rk3399_dmcfreq_target()
105 * ODT (on-die termination) resistors. in rk3399_dmcfreq_target()
107 arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, dmcfreq->odt_pd_arg0, in rk3399_dmcfreq_target()
108 dmcfreq->odt_pd_arg1, in rk3399_dmcfreq_target()
118 err = regulator_set_voltage(dmcfreq->vdd_center, target_volt, in rk3399_dmcfreq_target()
127 err = clk_set_rate(dmcfreq->dmc_clk, target_rate); in rk3399_dmcfreq_target()
131 regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt, in rk3399_dmcfreq_target()
132 dmcfreq->volt); in rk3399_dmcfreq_target()
139 * 1. Ddr frequency scaling fail, we still get the old rate. in rk3399_dmcfreq_target()
140 * 2. Ddr frequency scaling sucessful, we get the rate we set. in rk3399_dmcfreq_target()
142 dmcfreq->rate = clk_get_rate(dmcfreq->dmc_clk); in rk3399_dmcfreq_target()
145 if (dmcfreq->rate != target_rate) { in rk3399_dmcfreq_target()
147 target_rate, dmcfreq->rate); in rk3399_dmcfreq_target()
148 regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt, in rk3399_dmcfreq_target()
149 dmcfreq->volt); in rk3399_dmcfreq_target()
152 err = regulator_set_voltage(dmcfreq->vdd_center, target_volt, in rk3399_dmcfreq_target()
157 dmcfreq->rate = target_rate; in rk3399_dmcfreq_target()
158 dmcfreq->volt = target_volt; in rk3399_dmcfreq_target()
161 mutex_unlock(&dmcfreq->lock); in rk3399_dmcfreq_target()
172 ret = devfreq_event_get_event(dmcfreq->edev, &edata); in rk3399_dmcfreq_get_dev_status()
176 stat->current_frequency = dmcfreq->rate; in rk3399_dmcfreq_get_dev_status()
177 stat->busy_time = edata.load_count; in rk3399_dmcfreq_get_dev_status()
178 stat->total_time = edata.total_count; in rk3399_dmcfreq_get_dev_status()
187 *freq = dmcfreq->rate; in rk3399_dmcfreq_get_cur_freq()
204 ret = devfreq_event_disable_edev(dmcfreq->edev); in rk3399_dmcfreq_suspend()
206 dev_err(dev, "failed to disable the devfreq-event devices\n"); in rk3399_dmcfreq_suspend()
210 ret = devfreq_suspend_device(dmcfreq->devfreq); in rk3399_dmcfreq_suspend()
224 ret = devfreq_event_enable_edev(dmcfreq->edev); in rk3399_dmcfreq_resume()
226 dev_err(dev, "failed to enable the devfreq-event devices\n"); in rk3399_dmcfreq_resume()
230 ret = devfreq_resume_device(dmcfreq->devfreq); in rk3399_dmcfreq_resume()
247 &timing->ddr3_speed_bin); in of_get_ddr_timings()
249 &timing->pd_idle); in of_get_ddr_timings()
251 &timing->sr_idle); in of_get_ddr_timings()
253 &timing->sr_mc_gate_idle); in of_get_ddr_timings()
255 &timing->srpd_lite_idle); in of_get_ddr_timings()
257 &timing->standby_idle); in of_get_ddr_timings()
259 &timing->auto_pd_dis_freq); in of_get_ddr_timings()
261 &timing->dram_dll_dis_freq); in of_get_ddr_timings()
263 &timing->phy_dll_dis_freq); in of_get_ddr_timings()
265 &timing->ddr3_odt_dis_freq); in of_get_ddr_timings()
267 &timing->ddr3_drv); in of_get_ddr_timings()
269 &timing->ddr3_odt); in of_get_ddr_timings()
271 &timing->phy_ddr3_ca_drv); in of_get_ddr_timings()
273 &timing->phy_ddr3_dq_drv); in of_get_ddr_timings()
275 &timing->phy_ddr3_odt); in of_get_ddr_timings()
277 &timing->lpddr3_odt_dis_freq); in of_get_ddr_timings()
279 &timing->lpddr3_drv); in of_get_ddr_timings()
281 &timing->lpddr3_odt); in of_get_ddr_timings()
283 &timing->phy_lpddr3_ca_drv); in of_get_ddr_timings()
285 &timing->phy_lpddr3_dq_drv); in of_get_ddr_timings()
287 &timing->phy_lpddr3_odt); in of_get_ddr_timings()
289 &timing->lpddr4_odt_dis_freq); in of_get_ddr_timings()
291 &timing->lpddr4_drv); in of_get_ddr_timings()
293 &timing->lpddr4_dq_odt); in of_get_ddr_timings()
295 &timing->lpddr4_ca_odt); in of_get_ddr_timings()
297 &timing->phy_lpddr4_ca_drv); in of_get_ddr_timings()
299 &timing->phy_lpddr4_ck_cs_drv); in of_get_ddr_timings()
301 &timing->phy_lpddr4_dq_drv); in of_get_ddr_timings()
303 &timing->phy_lpddr4_odt); in of_get_ddr_timings()
311 struct device *dev = &pdev->dev; in rk3399_dmcfreq_probe()
312 struct device_node *np = pdev->dev.of_node, *node; in rk3399_dmcfreq_probe()
322 return -ENOMEM; in rk3399_dmcfreq_probe()
324 mutex_init(&data->lock); in rk3399_dmcfreq_probe()
326 data->vdd_center = devm_regulator_get(dev, "center"); in rk3399_dmcfreq_probe()
327 if (IS_ERR(data->vdd_center)) { in rk3399_dmcfreq_probe()
328 if (PTR_ERR(data->vdd_center) == -EPROBE_DEFER) in rk3399_dmcfreq_probe()
329 return -EPROBE_DEFER; in rk3399_dmcfreq_probe()
332 return PTR_ERR(data->vdd_center); in rk3399_dmcfreq_probe()
335 data->dmc_clk = devm_clk_get(dev, "dmc_clk"); in rk3399_dmcfreq_probe()
336 if (IS_ERR(data->dmc_clk)) { in rk3399_dmcfreq_probe()
337 if (PTR_ERR(data->dmc_clk) == -EPROBE_DEFER) in rk3399_dmcfreq_probe()
338 return -EPROBE_DEFER; in rk3399_dmcfreq_probe()
341 return PTR_ERR(data->dmc_clk); in rk3399_dmcfreq_probe()
344 data->edev = devfreq_event_get_edev_by_phandle(dev, "devfreq-events", 0); in rk3399_dmcfreq_probe()
345 if (IS_ERR(data->edev)) in rk3399_dmcfreq_probe()
346 return -EPROBE_DEFER; in rk3399_dmcfreq_probe()
348 ret = devfreq_event_enable_edev(data->edev); in rk3399_dmcfreq_probe()
350 dev_err(dev, "failed to enable devfreq-event devices\n"); in rk3399_dmcfreq_probe()
359 if (!of_get_ddr_timings(&data->timing, np)) { in rk3399_dmcfreq_probe()
360 timing = &data->timing.ddr3_speed_bin; in rk3399_dmcfreq_probe()
369 ret = -EINVAL; in rk3399_dmcfreq_probe()
375 node = of_parse_phandle(np, "rockchip,pmu", 0); in rk3399_dmcfreq_probe()
379 data->regmap_pmu = syscon_node_to_regmap(node); in rk3399_dmcfreq_probe()
381 if (IS_ERR(data->regmap_pmu)) { in rk3399_dmcfreq_probe()
382 ret = PTR_ERR(data->regmap_pmu); in rk3399_dmcfreq_probe()
386 regmap_read(data->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); in rk3399_dmcfreq_probe()
392 data->odt_dis_freq = data->timing.ddr3_odt_dis_freq; in rk3399_dmcfreq_probe()
395 data->odt_dis_freq = data->timing.lpddr3_odt_dis_freq; in rk3399_dmcfreq_probe()
398 data->odt_dis_freq = data->timing.lpddr4_odt_dis_freq; in rk3399_dmcfreq_probe()
401 ret = -EINVAL; in rk3399_dmcfreq_probe()
411 * In TF-A there is a platform SIP call to set the PD (power-down) in rk3399_dmcfreq_probe()
412 * timings and to enable or disable the ODT (on-die termination). in rk3399_dmcfreq_probe()
416 * bit[0-7] : sr_idle in rk3399_dmcfreq_probe()
417 * bit[8-15] : sr_mc_gate_idle in rk3399_dmcfreq_probe()
418 * bit[16-31] : standby idle in rk3399_dmcfreq_probe()
420 * bit[0-11] : pd_idle in rk3399_dmcfreq_probe()
421 * bit[16-27] : srpd_lite_idle in rk3399_dmcfreq_probe()
425 data->odt_pd_arg0 = (data->timing.sr_idle & 0xff) | in rk3399_dmcfreq_probe()
426 ((data->timing.sr_mc_gate_idle & 0xff) << 8) | in rk3399_dmcfreq_probe()
427 ((data->timing.standby_idle & 0xffff) << 16); in rk3399_dmcfreq_probe()
428 data->odt_pd_arg1 = (data->timing.pd_idle & 0xfff) | in rk3399_dmcfreq_probe()
429 ((data->timing.srpd_lite_idle & 0xfff) << 16); in rk3399_dmcfreq_probe()
436 dev_err(dev, "Invalid operating-points in device tree.\n"); in rk3399_dmcfreq_probe()
437 ret = -EINVAL; in rk3399_dmcfreq_probe()
442 &data->ondemand_data.upthreshold); in rk3399_dmcfreq_probe()
444 &data->ondemand_data.downdifferential); in rk3399_dmcfreq_probe()
446 data->rate = clk_get_rate(data->dmc_clk); in rk3399_dmcfreq_probe()
448 opp = devfreq_recommended_opp(dev, &data->rate, 0); in rk3399_dmcfreq_probe()
454 data->rate = dev_pm_opp_get_freq(opp); in rk3399_dmcfreq_probe()
455 data->volt = dev_pm_opp_get_voltage(opp); in rk3399_dmcfreq_probe()
458 rk3399_devfreq_dmc_profile.initial_freq = data->rate; in rk3399_dmcfreq_probe()
460 data->devfreq = devm_devfreq_add_device(dev, in rk3399_dmcfreq_probe()
463 &data->ondemand_data); in rk3399_dmcfreq_probe()
464 if (IS_ERR(data->devfreq)) { in rk3399_dmcfreq_probe()
465 ret = PTR_ERR(data->devfreq); in rk3399_dmcfreq_probe()
469 devm_devfreq_register_opp_notifier(dev, data->devfreq); in rk3399_dmcfreq_probe()
471 data->dev = dev; in rk3399_dmcfreq_probe()
477 dev_pm_opp_of_remove_table(&pdev->dev); in rk3399_dmcfreq_probe()
479 devfreq_event_disable_edev(data->edev); in rk3399_dmcfreq_probe()
486 struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(&pdev->dev); in rk3399_dmcfreq_remove()
491 devm_devfreq_unregister_opp_notifier(dmcfreq->dev, dmcfreq->devfreq); in rk3399_dmcfreq_remove()
492 dev_pm_opp_of_remove_table(dmcfreq->dev); in rk3399_dmcfreq_remove()
498 { .compatible = "rockchip,rk3399-dmc" },
507 .name = "rk3399-dmc-freq",
515 MODULE_AUTHOR("Lin Huang <hl@rock-chips.com>");