2020-08-14 00:11:24

by Dmitry Osipenko

[permalink] [raw]
Subject: [PATCH v5 12/36] PM / devfreq: tegra20: Use MC timings for building OPP table

The clk_round_rate() won't be usable for building OPP table once
interconnect support will be added to the EMC driver because that CLK API
function limits the rounded rate based on the clk rate that is imposed by
active clk-users, and thus, the rounding won't work as expected if
interconnect will set the minimum EMC clock rate before devfreq driver is
loaded. The struct tegra_mc contains memory timings which could be used by
the devfreq driver for building up OPP table instead of rounding clock
rate, this patch implements this idea.

Signed-off-by: Dmitry Osipenko <[email protected]>
---
drivers/devfreq/tegra20-devfreq.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/devfreq/tegra20-devfreq.c b/drivers/devfreq/tegra20-devfreq.c
index 6469dc69c5e0..a985f24098f5 100644
--- a/drivers/devfreq/tegra20-devfreq.c
+++ b/drivers/devfreq/tegra20-devfreq.c
@@ -123,8 +123,7 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
{
struct tegra_devfreq *tegra;
struct tegra_mc *mc;
- unsigned long max_rate;
- unsigned long rate;
+ unsigned int i;
int err;

mc = tegra_get_memory_controller();
@@ -135,6 +134,11 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
return err;
}

+ if (!mc->num_timings) {
+ dev_info(&pdev->dev, "memory controller has no timings\n");
+ return -ENODEV;
+ }
+
tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
if (!tegra)
return -ENOMEM;
@@ -151,12 +155,8 @@ static int tegra_devfreq_probe(struct platform_device *pdev)

tegra->regs = mc->regs;

- max_rate = clk_round_rate(tegra->emc_clock, ULONG_MAX);
-
- for (rate = 0; rate <= max_rate; rate++) {
- rate = clk_round_rate(tegra->emc_clock, rate);
-
- err = dev_pm_opp_add(&pdev->dev, rate, 0);
+ for (i = 0; i < mc->num_timings; i++) {
+ err = dev_pm_opp_add(&pdev->dev, mc->timings[i].rate, 0);
if (err) {
dev_err(&pdev->dev, "failed to add opp: %d\n", err);
goto remove_opps;
--
2.27.0


2020-08-14 00:51:11

by Chanwoo Choi

[permalink] [raw]
Subject: Re: [PATCH v5 12/36] PM / devfreq: tegra20: Use MC timings for building OPP table

Hi Dmitry,

On 8/14/20 9:05 AM, Dmitry Osipenko wrote:
> The clk_round_rate() won't be usable for building OPP table once
> interconnect support will be added to the EMC driver because that CLK API
> function limits the rounded rate based on the clk rate that is imposed by
> active clk-users, and thus, the rounding won't work as expected if
> interconnect will set the minimum EMC clock rate before devfreq driver is
> loaded. The struct tegra_mc contains memory timings which could be used by
> the devfreq driver for building up OPP table instead of rounding clock
> rate, this patch implements this idea.
>
> Signed-off-by: Dmitry Osipenko <[email protected]>
> ---
> drivers/devfreq/tegra20-devfreq.c | 16 ++++++++--------
> 1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/devfreq/tegra20-devfreq.c b/drivers/devfreq/tegra20-devfreq.c
> index 6469dc69c5e0..a985f24098f5 100644
> --- a/drivers/devfreq/tegra20-devfreq.c
> +++ b/drivers/devfreq/tegra20-devfreq.c
> @@ -123,8 +123,7 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
> {
> struct tegra_devfreq *tegra;
> struct tegra_mc *mc;
> - unsigned long max_rate;
> - unsigned long rate;
> + unsigned int i;
> int err;
>
> mc = tegra_get_memory_controller();
> @@ -135,6 +134,11 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
> return err;
> }
>
> + if (!mc->num_timings) {
> + dev_info(&pdev->dev, "memory controller has no timings\n");
> + return -ENODEV;
> + }
> +
> tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
> if (!tegra)
> return -ENOMEM;
> @@ -151,12 +155,8 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
>
> tegra->regs = mc->regs;
>
> - max_rate = clk_round_rate(tegra->emc_clock, ULONG_MAX);
> -
> - for (rate = 0; rate <= max_rate; rate++) {
> - rate = clk_round_rate(tegra->emc_clock, rate);
> -
> - err = dev_pm_opp_add(&pdev->dev, rate, 0);
> + for (i = 0; i < mc->num_timings; i++) {
> + err = dev_pm_opp_add(&pdev->dev, mc->timings[i].rate, 0);
> if (err) {
> dev_err(&pdev->dev, "failed to add opp: %d\n", err);
> goto remove_opps;
>

Ackded-by: Chanwoo Choi <[email protected]>

--
Best Regards,
Chanwoo Choi
Samsung Electronics