Commit f5c70d79 authored by Robin Murphy's avatar Robin Murphy
Browse files

WIP: drm/panfrost: Add devfreq support for MT8183



Wire up the necessary helper to adjust the two separate power supplies
when changing OPPs. The downstream vendor driver appears to always
adjust VGPU before VSRAM, so we'll do the same here.
Signed-off-by: Robin Murphy's avatarRobin Murphy <robin.murphy@arm.com>
parent e73f0f0e
...@@ -92,13 +92,16 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) ...@@ -92,13 +92,16 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
struct thermal_cooling_device *cooling; struct thermal_cooling_device *cooling;
struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
/* GPUs with more than 1 supply require platform-specific handling */
if (pfdev->comp->num_supplies > 1) { if (pfdev->comp->num_supplies > 1) {
/* if (!pfdev->comp->set_opp) {
* GPUs with more than 1 supply require platform-specific handling: /* Continue without devfreq */
* continue without devfreq DRM_DEV_INFO(dev, "More than 1 supply is not supported yet\n");
*/ return 0;
DRM_DEV_INFO(dev, "More than 1 supply is not supported yet\n"); }
return 0; ret = devm_pm_opp_register_set_opp_helper(dev, pfdev->comp->set_opp);
if (ret)
return ret;
} }
ret = devm_pm_opp_set_regulators(dev, pfdev->comp->supply_names, ret = devm_pm_opp_set_regulators(dev, pfdev->comp->supply_names,
...@@ -221,3 +224,58 @@ void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq) ...@@ -221,3 +224,58 @@ void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq)
spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); spin_unlock_irqrestore(&pfdevfreq->lock, irqflags);
} }
/* Vendor-specific shenanigans */
static int panfrost_set_opp_supply(struct regulator *reg, struct dev_pm_opp_supply *s)
{
return regulator_set_voltage_triplet(reg, s->u_volt_min, s->u_volt, s->u_volt_max);
}
int panfrost_mt8183_set_opp(struct dev_pm_set_opp_data *data)
{
unsigned long old_freq = data->old_opp.rate, freq = data->new_opp.rate;
struct regulator *gpu = data->regulators[0], *sram = data->regulators[1];
int ret;
if (freq > old_freq) {
ret = panfrost_set_opp_supply(gpu, &data->new_opp.supplies[0]);
if (ret)
return ret;
ret = panfrost_set_opp_supply(sram, &data->new_opp.supplies[1]);
if (ret)
goto restore_vgpu;
}
ret = clk_set_rate(data->clk, freq);
if (ret)
goto restore_vsram;
if (freq < old_freq) {
ret = panfrost_set_opp_supply(gpu, &data->new_opp.supplies[0]);
if (ret)
goto restore_freq;
ret = panfrost_set_opp_supply(sram, &data->new_opp.supplies[1]);
if (ret)
goto restore_freq;
}
//FIXME: how are we supposed to do the right thing to pair with the disable in dev_pm_opp_put_regulators()?
if (unlikely(!opp_table->enabled)) {
ret = regulator_enable(gpu);
if (!ret)
ret = regulator_enable(sram);
if (ret)
dev_warn(data->dev, "Failed to enable regulators: %d", ret);
}
return ret;
restore_freq:
clk_set_rate(data->clk, old_freq);
restore_vsram:
panfrost_set_opp_supply(sram, &data->old_opp.supplies[1]);
restore_vgpu:
panfrost_set_opp_supply(gpu, &data->old_opp.supplies[0]);
return ret;
}
...@@ -39,4 +39,6 @@ void panfrost_devfreq_suspend(struct panfrost_device *pfdev); ...@@ -39,4 +39,6 @@ void panfrost_devfreq_suspend(struct panfrost_device *pfdev);
void panfrost_devfreq_record_busy(struct panfrost_devfreq *devfreq); void panfrost_devfreq_record_busy(struct panfrost_devfreq *devfreq);
void panfrost_devfreq_record_idle(struct panfrost_devfreq *devfreq); void panfrost_devfreq_record_idle(struct panfrost_devfreq *devfreq);
int panfrost_mt8183_set_opp(struct dev_pm_set_opp_data *data);
#endif /* __PANFROST_DEVFREQ_H__ */ #endif /* __PANFROST_DEVFREQ_H__ */
...@@ -71,6 +71,8 @@ struct panfrost_compatible { ...@@ -71,6 +71,8 @@ struct panfrost_compatible {
int num_pm_domains; int num_pm_domains;
/* Only required if num_pm_domains > 1. */ /* Only required if num_pm_domains > 1. */
const char * const *pm_domain_names; const char * const *pm_domain_names;
/* OPP callback for handling multiple domains */
int (*set_opp)(struct dev_pm_set_opp_data *data);
/* Vendor implementation quirks callback */ /* Vendor implementation quirks callback */
void (*vendor_quirk)(struct panfrost_device *pfdev); void (*vendor_quirk)(struct panfrost_device *pfdev);
......
...@@ -673,6 +673,7 @@ static const struct panfrost_compatible mediatek_mt8183_data = { ...@@ -673,6 +673,7 @@ static const struct panfrost_compatible mediatek_mt8183_data = {
.supply_names = mediatek_mt8183_supplies, .supply_names = mediatek_mt8183_supplies,
.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains), .num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
.pm_domain_names = mediatek_mt8183_pm_domains, .pm_domain_names = mediatek_mt8183_pm_domains,
.set_opp = panfrost_mt8183_set_opp,
}; };
static const struct of_device_id dt_match[] = { static const struct of_device_id dt_match[] = {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment