Lines Matching +full:srpd +full:- +full:lite +full:- +full:idle +full:- +full:ns

1 // SPDX-License-Identifier: GPL-2.0-only
4 * Author: Lin Huang <hl@rock-chips.com>
7 #include <linux/arm-smccc.h>
12 #include <linux/devfreq-event.h>
28 #define NS_TO_CYCLE(NS, MHz) (((NS) * (MHz)) / NSEC_PER_USEC) argument
74 unsigned long old_clk_rate = dmcfreq->rate; in rk3399_dmcfreq_target()
92 if (dmcfreq->rate == target_rate) in rk3399_dmcfreq_target()
95 mutex_lock(&dmcfreq->lock); in rk3399_dmcfreq_target()
98 * Ensure power-domain transitions don't interfere with ARM Trusted in rk3399_dmcfreq_target()
99 * Firmware power-domain idling. in rk3399_dmcfreq_target()
108 * Some idle parameters may be based on the DDR controller clock, which in rk3399_dmcfreq_target()
117 NS_TO_CYCLE(dmcfreq->pd_idle_ns, ddrcon_mhz), in rk3399_dmcfreq_target()
120 NS_TO_CYCLE(dmcfreq->standby_idle_ns, ddrcon_mhz), in rk3399_dmcfreq_target()
123 DIV_ROUND_UP(NS_TO_CYCLE(dmcfreq->sr_idle_ns, in rk3399_dmcfreq_target()
127 DIV_ROUND_UP(NS_TO_CYCLE(dmcfreq->sr_mc_gate_idle_ns, in rk3399_dmcfreq_target()
131 DIV_ROUND_UP(NS_TO_CYCLE(dmcfreq->srpd_lite_idle_ns, in rk3399_dmcfreq_target()
135 if (dmcfreq->regmap_pmu) { in rk3399_dmcfreq_target()
136 if (target_rate >= dmcfreq->sr_idle_dis_freq) in rk3399_dmcfreq_target()
139 if (target_rate >= dmcfreq->sr_mc_gate_idle_dis_freq) in rk3399_dmcfreq_target()
142 if (target_rate >= dmcfreq->standby_idle_dis_freq) in rk3399_dmcfreq_target()
145 if (target_rate >= dmcfreq->pd_idle_dis_freq) in rk3399_dmcfreq_target()
148 if (target_rate >= dmcfreq->srpd_lite_idle_dis_freq) in rk3399_dmcfreq_target()
151 if (target_rate >= dmcfreq->odt_dis_freq) in rk3399_dmcfreq_target()
155 * This makes a SMC call to the TF-A to set the DDR PD in rk3399_dmcfreq_target()
156 * (power-down) timings and to enable or disable the in rk3399_dmcfreq_target()
157 * ODT (on-die termination) resistors. in rk3399_dmcfreq_target()
169 err = regulator_set_voltage(dmcfreq->vdd_center, target_volt, in rk3399_dmcfreq_target()
178 err = clk_set_rate(dmcfreq->dmc_clk, target_rate); in rk3399_dmcfreq_target()
182 regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt, in rk3399_dmcfreq_target()
183 dmcfreq->volt); in rk3399_dmcfreq_target()
193 dmcfreq->rate = clk_get_rate(dmcfreq->dmc_clk); in rk3399_dmcfreq_target()
196 if (dmcfreq->rate != target_rate) { in rk3399_dmcfreq_target()
198 target_rate, dmcfreq->rate); in rk3399_dmcfreq_target()
199 regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt, in rk3399_dmcfreq_target()
200 dmcfreq->volt); in rk3399_dmcfreq_target()
203 err = regulator_set_voltage(dmcfreq->vdd_center, target_volt, in rk3399_dmcfreq_target()
208 dmcfreq->rate = target_rate; in rk3399_dmcfreq_target()
209 dmcfreq->volt = target_volt; in rk3399_dmcfreq_target()
214 mutex_unlock(&dmcfreq->lock); in rk3399_dmcfreq_target()
225 ret = devfreq_event_get_event(dmcfreq->edev, &edata); in rk3399_dmcfreq_get_dev_status()
229 stat->current_frequency = dmcfreq->rate; in rk3399_dmcfreq_get_dev_status()
230 stat->busy_time = edata.load_count; in rk3399_dmcfreq_get_dev_status()
231 stat->total_time = edata.total_count; in rk3399_dmcfreq_get_dev_status()
240 *freq = dmcfreq->rate; in rk3399_dmcfreq_get_cur_freq()
250 ret = devfreq_event_disable_edev(dmcfreq->edev); in rk3399_dmcfreq_suspend()
252 dev_err(dev, "failed to disable the devfreq-event devices\n"); in rk3399_dmcfreq_suspend()
256 ret = devfreq_suspend_device(dmcfreq->devfreq); in rk3399_dmcfreq_suspend()
270 ret = devfreq_event_enable_edev(dmcfreq->edev); in rk3399_dmcfreq_resume()
272 dev_err(dev, "failed to enable the devfreq-event devices\n"); in rk3399_dmcfreq_resume()
276 ret = devfreq_resume_device(dmcfreq->devfreq); in rk3399_dmcfreq_resume()
296 data->pd_idle_dis_freq = in rk3399_dmcfreq_of_props()
297 data->sr_idle_dis_freq = in rk3399_dmcfreq_of_props()
298 data->sr_mc_gate_idle_dis_freq = in rk3399_dmcfreq_of_props()
299 data->srpd_lite_idle_dis_freq = in rk3399_dmcfreq_of_props()
300 data->standby_idle_dis_freq = UINT_MAX; in rk3399_dmcfreq_of_props()
302 ret |= of_property_read_u32(np, "rockchip,pd-idle-ns", in rk3399_dmcfreq_of_props()
303 &data->pd_idle_ns); in rk3399_dmcfreq_of_props()
304 ret |= of_property_read_u32(np, "rockchip,sr-idle-ns", in rk3399_dmcfreq_of_props()
305 &data->sr_idle_ns); in rk3399_dmcfreq_of_props()
306 ret |= of_property_read_u32(np, "rockchip,sr-mc-gate-idle-ns", in rk3399_dmcfreq_of_props()
307 &data->sr_mc_gate_idle_ns); in rk3399_dmcfreq_of_props()
308 ret |= of_property_read_u32(np, "rockchip,srpd-lite-idle-ns", in rk3399_dmcfreq_of_props()
309 &data->srpd_lite_idle_ns); in rk3399_dmcfreq_of_props()
310 ret |= of_property_read_u32(np, "rockchip,standby-idle-ns", in rk3399_dmcfreq_of_props()
311 &data->standby_idle_ns); in rk3399_dmcfreq_of_props()
313 &data->ddr3_odt_dis_freq); in rk3399_dmcfreq_of_props()
315 &data->lpddr3_odt_dis_freq); in rk3399_dmcfreq_of_props()
317 &data->lpddr4_odt_dis_freq); in rk3399_dmcfreq_of_props()
319 ret |= of_property_read_u32(np, "rockchip,pd-idle-dis-freq-hz", in rk3399_dmcfreq_of_props()
320 &data->pd_idle_dis_freq); in rk3399_dmcfreq_of_props()
321 ret |= of_property_read_u32(np, "rockchip,sr-idle-dis-freq-hz", in rk3399_dmcfreq_of_props()
322 &data->sr_idle_dis_freq); in rk3399_dmcfreq_of_props()
323 ret |= of_property_read_u32(np, "rockchip,sr-mc-gate-idle-dis-freq-hz", in rk3399_dmcfreq_of_props()
324 &data->sr_mc_gate_idle_dis_freq); in rk3399_dmcfreq_of_props()
325 ret |= of_property_read_u32(np, "rockchip,srpd-lite-idle-dis-freq-hz", in rk3399_dmcfreq_of_props()
326 &data->srpd_lite_idle_dis_freq); in rk3399_dmcfreq_of_props()
327 ret |= of_property_read_u32(np, "rockchip,standby-idle-dis-freq-hz", in rk3399_dmcfreq_of_props()
328 &data->standby_idle_dis_freq); in rk3399_dmcfreq_of_props()
336 struct device *dev = &pdev->dev; in rk3399_dmcfreq_probe()
337 struct device_node *np = pdev->dev.of_node, *node; in rk3399_dmcfreq_probe()
346 return -ENOMEM; in rk3399_dmcfreq_probe()
348 mutex_init(&data->lock); in rk3399_dmcfreq_probe()
350 data->vdd_center = devm_regulator_get(dev, "center"); in rk3399_dmcfreq_probe()
351 if (IS_ERR(data->vdd_center)) in rk3399_dmcfreq_probe()
352 return dev_err_probe(dev, PTR_ERR(data->vdd_center), in rk3399_dmcfreq_probe()
355 data->dmc_clk = devm_clk_get(dev, "dmc_clk"); in rk3399_dmcfreq_probe()
356 if (IS_ERR(data->dmc_clk)) in rk3399_dmcfreq_probe()
357 return dev_err_probe(dev, PTR_ERR(data->dmc_clk), in rk3399_dmcfreq_probe()
360 data->edev = devfreq_event_get_edev_by_phandle(dev, "devfreq-events", 0); in rk3399_dmcfreq_probe()
361 if (IS_ERR(data->edev)) in rk3399_dmcfreq_probe()
362 return -EPROBE_DEFER; in rk3399_dmcfreq_probe()
364 ret = devfreq_event_enable_edev(data->edev); in rk3399_dmcfreq_probe()
366 dev_err(dev, "failed to enable devfreq-event devices\n"); in rk3399_dmcfreq_probe()
376 data->regmap_pmu = syscon_node_to_regmap(node); in rk3399_dmcfreq_probe()
378 if (IS_ERR(data->regmap_pmu)) { in rk3399_dmcfreq_probe()
379 ret = PTR_ERR(data->regmap_pmu); in rk3399_dmcfreq_probe()
383 regmap_read(data->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); in rk3399_dmcfreq_probe()
389 data->odt_dis_freq = data->ddr3_odt_dis_freq; in rk3399_dmcfreq_probe()
392 data->odt_dis_freq = data->lpddr3_odt_dis_freq; in rk3399_dmcfreq_probe()
395 data->odt_dis_freq = data->lpddr4_odt_dis_freq; in rk3399_dmcfreq_probe()
398 ret = -EINVAL; in rk3399_dmcfreq_probe()
412 dev_err(dev, "Invalid operating-points in device tree.\n"); in rk3399_dmcfreq_probe()
413 ret = -EINVAL; in rk3399_dmcfreq_probe()
417 data->ondemand_data.upthreshold = 25; in rk3399_dmcfreq_probe()
418 data->ondemand_data.downdifferential = 15; in rk3399_dmcfreq_probe()
420 data->rate = clk_get_rate(data->dmc_clk); in rk3399_dmcfreq_probe()
422 opp = devfreq_recommended_opp(dev, &data->rate, 0); in rk3399_dmcfreq_probe()
428 data->rate = dev_pm_opp_get_freq(opp); in rk3399_dmcfreq_probe()
429 data->volt = dev_pm_opp_get_voltage(opp); in rk3399_dmcfreq_probe()
432 data->profile = (struct devfreq_dev_profile) { in rk3399_dmcfreq_probe()
437 .initial_freq = data->rate, in rk3399_dmcfreq_probe()
440 data->devfreq = devm_devfreq_add_device(dev, in rk3399_dmcfreq_probe()
441 &data->profile, in rk3399_dmcfreq_probe()
443 &data->ondemand_data); in rk3399_dmcfreq_probe()
444 if (IS_ERR(data->devfreq)) { in rk3399_dmcfreq_probe()
445 ret = PTR_ERR(data->devfreq); in rk3399_dmcfreq_probe()
449 devm_devfreq_register_opp_notifier(dev, data->devfreq); in rk3399_dmcfreq_probe()
451 data->dev = dev; in rk3399_dmcfreq_probe()
457 devfreq_event_disable_edev(data->edev); in rk3399_dmcfreq_probe()
464 struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(&pdev->dev); in rk3399_dmcfreq_remove()
466 devfreq_event_disable_edev(dmcfreq->edev); in rk3399_dmcfreq_remove()
472 { .compatible = "rockchip,rk3399-dmc" },
481 .name = "rk3399-dmc-freq",
489 MODULE_AUTHOR("Lin Huang <hl@rock-chips.com>");