diff options
Diffstat (limited to 'drivers/gpu/drm/panthor/panthor_devfreq.c')
| -rw-r--r-- | drivers/gpu/drm/panthor/panthor_devfreq.c | 64 |
1 files changed, 50 insertions, 14 deletions
diff --git a/drivers/gpu/drm/panthor/panthor_devfreq.c b/drivers/gpu/drm/panthor/panthor_devfreq.c index 3686515d368d..2249b41ca4af 100644 --- a/drivers/gpu/drm/panthor/panthor_devfreq.c +++ b/drivers/gpu/drm/panthor/panthor_devfreq.c @@ -8,6 +8,7 @@ #include <linux/pm_opp.h> #include <drm/drm_managed.h> +#include <drm/drm_print.h> #include "panthor_devfreq.h" #include "panthor_device.h" @@ -62,7 +63,6 @@ static void panthor_devfreq_update_utilization(struct panthor_devfreq *pdevfreq) static int panthor_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) { - struct panthor_device *ptdev = dev_get_drvdata(dev); struct dev_pm_opp *opp; int err; @@ -72,8 +72,6 @@ static int panthor_devfreq_target(struct device *dev, unsigned long *freq, dev_pm_opp_put(opp); err = dev_pm_opp_set_rate(dev, *freq); - if (!err) - ptdev->current_frequency = *freq; return err; } @@ -115,11 +113,21 @@ static int panthor_devfreq_get_dev_status(struct device *dev, return 0; } +static int panthor_devfreq_get_cur_freq(struct device *dev, unsigned long *freq) +{ + struct panthor_device *ptdev = dev_get_drvdata(dev); + + *freq = clk_get_rate(ptdev->clks.core); + + return 0; +} + static struct devfreq_dev_profile panthor_devfreq_profile = { .timer = DEVFREQ_TIMER_DELAYED, .polling_ms = 50, /* ~3 frames */ .target = panthor_devfreq_target, .get_dev_status = panthor_devfreq_get_dev_status, + .get_cur_freq = panthor_devfreq_get_cur_freq, }; int panthor_devfreq_init(struct panthor_device *ptdev) @@ -134,6 +142,7 @@ int panthor_devfreq_init(struct panthor_device *ptdev) struct thermal_cooling_device *cooling; struct device *dev = ptdev->base.dev; struct panthor_devfreq *pdevfreq; + struct opp_table *table; struct dev_pm_opp *opp; unsigned long cur_freq; unsigned long freq = ULONG_MAX; @@ -145,18 +154,30 @@ int panthor_devfreq_init(struct panthor_device *ptdev) ptdev->devfreq = pdevfreq; - ret = devm_pm_opp_set_regulators(dev, reg_names); - if (ret) { - if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n"); - - return ret; + /* + * The power domain associated with the GPU may have already added an + * OPP table, complete with OPPs, as part of the platform bus + * initialization. If this is the case, the power domain is in charge of + * also controlling the performance, with a set_performance callback. + * Only add a new OPP table from DT if there isn't such a table present + * already. + */ + table = dev_pm_opp_get_opp_table(dev); + if (IS_ERR_OR_NULL(table)) { + ret = devm_pm_opp_set_regulators(dev, reg_names); + if (ret && ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n"); + return ret; + } + + ret = devm_pm_opp_of_add_table(dev); + if (ret) + return ret; + } else { + dev_pm_opp_put_opp_table(table); } - ret = devm_pm_opp_of_add_table(dev); - if (ret) - return ret; - spin_lock_init(&pdevfreq->lock); panthor_devfreq_reset(pdevfreq); @@ -198,7 +219,6 @@ int panthor_devfreq_init(struct panthor_device *ptdev) return PTR_ERR(opp); panthor_devfreq_profile.initial_freq = cur_freq; - ptdev->current_frequency = cur_freq; /* * Set the recommend OPP this will enable and configure the regulator @@ -296,3 +316,19 @@ void panthor_devfreq_record_idle(struct panthor_device *ptdev) spin_unlock_irqrestore(&pdevfreq->lock, irqflags); } + +unsigned long panthor_devfreq_get_freq(struct panthor_device *ptdev) +{ + struct panthor_devfreq *pdevfreq = ptdev->devfreq; + unsigned long freq = 0; + int ret; + + if (!pdevfreq->devfreq) + return 0; + + ret = pdevfreq->devfreq->profile->get_cur_freq(ptdev->base.dev, &freq); + if (ret) + return 0; + + return freq; +} |
