Lines Matching +full:devfreq +full:- +full:event
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.h>
12 #include <linux/devfreq-event.h>
42 struct devfreq *devfreq; member
75 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()
99 * Ensure power-domain transitions don't interfere with ARM Trusted in rk3399_dmcfreq_target()
100 * Firmware power-domain idling. in rk3399_dmcfreq_target()
118 NS_TO_CYCLE(dmcfreq->pd_idle_ns, ddrcon_mhz), in rk3399_dmcfreq_target()
121 NS_TO_CYCLE(dmcfreq->standby_idle_ns, ddrcon_mhz), in rk3399_dmcfreq_target()
124 DIV_ROUND_UP(NS_TO_CYCLE(dmcfreq->sr_idle_ns, in rk3399_dmcfreq_target()
128 DIV_ROUND_UP(NS_TO_CYCLE(dmcfreq->sr_mc_gate_idle_ns, in rk3399_dmcfreq_target()
132 DIV_ROUND_UP(NS_TO_CYCLE(dmcfreq->srpd_lite_idle_ns, in rk3399_dmcfreq_target()
136 if (dmcfreq->regmap_pmu) { in rk3399_dmcfreq_target()
137 if (target_rate >= dmcfreq->sr_idle_dis_freq) in rk3399_dmcfreq_target()
140 if (target_rate >= dmcfreq->sr_mc_gate_idle_dis_freq) in rk3399_dmcfreq_target()
143 if (target_rate >= dmcfreq->standby_idle_dis_freq) in rk3399_dmcfreq_target()
146 if (target_rate >= dmcfreq->pd_idle_dis_freq) in rk3399_dmcfreq_target()
149 if (target_rate >= dmcfreq->srpd_lite_idle_dis_freq) in rk3399_dmcfreq_target()
152 if (target_rate >= dmcfreq->odt_dis_freq) in rk3399_dmcfreq_target()
156 * This makes a SMC call to the TF-A to set the DDR PD in rk3399_dmcfreq_target()
157 * (power-down) timings and to enable or disable the in rk3399_dmcfreq_target()
158 * ODT (on-die termination) resistors. in rk3399_dmcfreq_target()
170 err = regulator_set_voltage(dmcfreq->vdd_center, target_volt, in rk3399_dmcfreq_target()
179 err = clk_set_rate(dmcfreq->dmc_clk, target_rate); in rk3399_dmcfreq_target()
183 regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt, in rk3399_dmcfreq_target()
184 dmcfreq->volt); in rk3399_dmcfreq_target()
194 dmcfreq->rate = clk_get_rate(dmcfreq->dmc_clk); in rk3399_dmcfreq_target()
197 if (dmcfreq->rate != target_rate) { in rk3399_dmcfreq_target()
199 target_rate, dmcfreq->rate); in rk3399_dmcfreq_target()
200 regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt, in rk3399_dmcfreq_target()
201 dmcfreq->volt); in rk3399_dmcfreq_target()
204 err = regulator_set_voltage(dmcfreq->vdd_center, target_volt, in rk3399_dmcfreq_target()
209 dmcfreq->rate = target_rate; in rk3399_dmcfreq_target()
210 dmcfreq->volt = target_volt; in rk3399_dmcfreq_target()
215 mutex_unlock(&dmcfreq->lock); in rk3399_dmcfreq_target()
226 ret = devfreq_event_get_event(dmcfreq->edev, &edata); in rk3399_dmcfreq_get_dev_status()
230 stat->current_frequency = dmcfreq->rate; in rk3399_dmcfreq_get_dev_status()
231 stat->busy_time = edata.load_count; in rk3399_dmcfreq_get_dev_status()
232 stat->total_time = edata.total_count; in rk3399_dmcfreq_get_dev_status()
241 *freq = dmcfreq->rate; in rk3399_dmcfreq_get_cur_freq()
251 ret = devfreq_event_disable_edev(dmcfreq->edev); in rk3399_dmcfreq_suspend()
253 dev_err(dev, "failed to disable the devfreq-event devices\n"); in rk3399_dmcfreq_suspend()
257 ret = devfreq_suspend_device(dmcfreq->devfreq); in rk3399_dmcfreq_suspend()
259 dev_err(dev, "failed to suspend the devfreq devices\n"); in rk3399_dmcfreq_suspend()
271 ret = devfreq_event_enable_edev(dmcfreq->edev); in rk3399_dmcfreq_resume()
273 dev_err(dev, "failed to enable the devfreq-event devices\n"); in rk3399_dmcfreq_resume()
277 ret = devfreq_resume_device(dmcfreq->devfreq); in rk3399_dmcfreq_resume()
279 dev_err(dev, "failed to resume the devfreq devices\n"); in rk3399_dmcfreq_resume()
297 data->pd_idle_dis_freq = in rk3399_dmcfreq_of_props()
298 data->sr_idle_dis_freq = in rk3399_dmcfreq_of_props()
299 data->sr_mc_gate_idle_dis_freq = in rk3399_dmcfreq_of_props()
300 data->srpd_lite_idle_dis_freq = in rk3399_dmcfreq_of_props()
301 data->standby_idle_dis_freq = UINT_MAX; in rk3399_dmcfreq_of_props()
303 ret |= of_property_read_u32(np, "rockchip,pd-idle-ns", in rk3399_dmcfreq_of_props()
304 &data->pd_idle_ns); in rk3399_dmcfreq_of_props()
305 ret |= of_property_read_u32(np, "rockchip,sr-idle-ns", in rk3399_dmcfreq_of_props()
306 &data->sr_idle_ns); in rk3399_dmcfreq_of_props()
307 ret |= of_property_read_u32(np, "rockchip,sr-mc-gate-idle-ns", in rk3399_dmcfreq_of_props()
308 &data->sr_mc_gate_idle_ns); in rk3399_dmcfreq_of_props()
309 ret |= of_property_read_u32(np, "rockchip,srpd-lite-idle-ns", in rk3399_dmcfreq_of_props()
310 &data->srpd_lite_idle_ns); in rk3399_dmcfreq_of_props()
311 ret |= of_property_read_u32(np, "rockchip,standby-idle-ns", in rk3399_dmcfreq_of_props()
312 &data->standby_idle_ns); in rk3399_dmcfreq_of_props()
314 &data->ddr3_odt_dis_freq); in rk3399_dmcfreq_of_props()
316 &data->lpddr3_odt_dis_freq); in rk3399_dmcfreq_of_props()
318 &data->lpddr4_odt_dis_freq); in rk3399_dmcfreq_of_props()
320 ret |= of_property_read_u32(np, "rockchip,pd-idle-dis-freq-hz", in rk3399_dmcfreq_of_props()
321 &data->pd_idle_dis_freq); in rk3399_dmcfreq_of_props()
322 ret |= of_property_read_u32(np, "rockchip,sr-idle-dis-freq-hz", in rk3399_dmcfreq_of_props()
323 &data->sr_idle_dis_freq); in rk3399_dmcfreq_of_props()
324 ret |= of_property_read_u32(np, "rockchip,sr-mc-gate-idle-dis-freq-hz", in rk3399_dmcfreq_of_props()
325 &data->sr_mc_gate_idle_dis_freq); in rk3399_dmcfreq_of_props()
326 ret |= of_property_read_u32(np, "rockchip,srpd-lite-idle-dis-freq-hz", in rk3399_dmcfreq_of_props()
327 &data->srpd_lite_idle_dis_freq); in rk3399_dmcfreq_of_props()
328 ret |= of_property_read_u32(np, "rockchip,standby-idle-dis-freq-hz", in rk3399_dmcfreq_of_props()
329 &data->standby_idle_dis_freq); in rk3399_dmcfreq_of_props()
337 struct device *dev = &pdev->dev; in rk3399_dmcfreq_probe()
338 struct device_node *np = pdev->dev.of_node, *node; in rk3399_dmcfreq_probe()
347 return -ENOMEM; in rk3399_dmcfreq_probe()
349 mutex_init(&data->lock); in rk3399_dmcfreq_probe()
351 data->vdd_center = devm_regulator_get(dev, "center"); in rk3399_dmcfreq_probe()
352 if (IS_ERR(data->vdd_center)) in rk3399_dmcfreq_probe()
353 return dev_err_probe(dev, PTR_ERR(data->vdd_center), in rk3399_dmcfreq_probe()
356 data->dmc_clk = devm_clk_get(dev, "dmc_clk"); in rk3399_dmcfreq_probe()
357 if (IS_ERR(data->dmc_clk)) in rk3399_dmcfreq_probe()
358 return dev_err_probe(dev, PTR_ERR(data->dmc_clk), in rk3399_dmcfreq_probe()
361 data->edev = devfreq_event_get_edev_by_phandle(dev, "devfreq-events", 0); in rk3399_dmcfreq_probe()
362 if (IS_ERR(data->edev)) in rk3399_dmcfreq_probe()
363 return -EPROBE_DEFER; in rk3399_dmcfreq_probe()
365 ret = devfreq_event_enable_edev(data->edev); in rk3399_dmcfreq_probe()
367 dev_err(dev, "failed to enable devfreq-event devices\n"); in rk3399_dmcfreq_probe()
377 data->regmap_pmu = syscon_node_to_regmap(node); in rk3399_dmcfreq_probe()
379 if (IS_ERR(data->regmap_pmu)) { in rk3399_dmcfreq_probe()
380 ret = PTR_ERR(data->regmap_pmu); in rk3399_dmcfreq_probe()
384 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()
408 * We add a devfreq driver to our parent since it has a device tree node 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()
470 { .compatible = "rockchip,rk3399-dmc" },
479 .name = "rk3399-dmc-freq",
487 MODULE_AUTHOR("Lin Huang <hl@rock-chips.com>");
488 MODULE_DESCRIPTION("RK3399 dmcfreq driver with devfreq framework");