Skip to content

Commit 17ee2fb

Browse files
Sibi Sankarandersson
Sibi Sankar
authored andcommitted
remoteproc: qcom: pas: Vote for active/proxy power domains
On SM8150 SoCs ADSP, CDSP and MPSS need to proxy vote on multiple rpmh ARC resources and active vote on QMP AOSS Power domains. Add support to vote for multiple active and proxy power domains. Signed-off-by: Sibi Sankar <[email protected]> Link: https://lore.kernel.org/r/0101016e8078a71a-9ae99638-9e15-49a5-b769-85552526ae89-000000@us-west-2.amazonses.com Signed-off-by: Bjorn Andersson <[email protected]>
1 parent 22f517e commit 17ee2fb

File tree

1 file changed

+133
-4
lines changed

1 file changed

+133
-4
lines changed

Diff for: drivers/remoteproc/qcom_q6v5_pas.c

+133-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <linux/of_address.h>
1616
#include <linux/of_device.h>
1717
#include <linux/platform_device.h>
18+
#include <linux/pm_domain.h>
19+
#include <linux/pm_runtime.h>
1820
#include <linux/qcom_scm.h>
1921
#include <linux/regulator/consumer.h>
2022
#include <linux/remoteproc.h>
@@ -32,6 +34,9 @@ struct adsp_data {
3234
int pas_id;
3335
bool has_aggre2_clk;
3436

37+
char **active_pd_names;
38+
char **proxy_pd_names;
39+
3540
const char *ssr_name;
3641
const char *sysmon_name;
3742
int ssctl_id;
@@ -49,6 +54,12 @@ struct qcom_adsp {
4954
struct regulator *cx_supply;
5055
struct regulator *px_supply;
5156

57+
struct device *active_pds[1];
58+
struct device *proxy_pds[3];
59+
60+
int active_pd_count;
61+
int proxy_pd_count;
62+
5263
int pas_id;
5364
int crash_reason_smem;
5465
bool has_aggre2_clk;
@@ -67,6 +78,41 @@ struct qcom_adsp {
6778
struct qcom_sysmon *sysmon;
6879
};
6980

81+
static int adsp_pds_enable(struct qcom_adsp *adsp, struct device **pds,
82+
size_t pd_count)
83+
{
84+
int ret;
85+
int i;
86+
87+
for (i = 0; i < pd_count; i++) {
88+
dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
89+
ret = pm_runtime_get_sync(pds[i]);
90+
if (ret < 0)
91+
goto unroll_pd_votes;
92+
}
93+
94+
return 0;
95+
96+
unroll_pd_votes:
97+
for (i--; i >= 0; i--) {
98+
dev_pm_genpd_set_performance_state(pds[i], 0);
99+
pm_runtime_put(pds[i]);
100+
}
101+
102+
return ret;
103+
};
104+
105+
static void adsp_pds_disable(struct qcom_adsp *adsp, struct device **pds,
106+
size_t pd_count)
107+
{
108+
int i;
109+
110+
for (i = 0; i < pd_count; i++) {
111+
dev_pm_genpd_set_performance_state(pds[i], 0);
112+
pm_runtime_put(pds[i]);
113+
}
114+
}
115+
70116
static int adsp_load(struct rproc *rproc, const struct firmware *fw)
71117
{
72118
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
@@ -84,9 +130,17 @@ static int adsp_start(struct rproc *rproc)
84130

85131
qcom_q6v5_prepare(&adsp->q6v5);
86132

133+
ret = adsp_pds_enable(adsp, adsp->active_pds, adsp->active_pd_count);
134+
if (ret < 0)
135+
goto disable_irqs;
136+
137+
ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
138+
if (ret < 0)
139+
goto disable_active_pds;
140+
87141
ret = clk_prepare_enable(adsp->xo);
88142
if (ret)
89-
goto disable_irqs;
143+
goto disable_proxy_pds;
90144

91145
ret = clk_prepare_enable(adsp->aggre2_clk);
92146
if (ret)
@@ -124,6 +178,10 @@ static int adsp_start(struct rproc *rproc)
124178
clk_disable_unprepare(adsp->aggre2_clk);
125179
disable_xo_clk:
126180
clk_disable_unprepare(adsp->xo);
181+
disable_proxy_pds:
182+
adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
183+
disable_active_pds:
184+
adsp_pds_disable(adsp, adsp->active_pds, adsp->active_pd_count);
127185
disable_irqs:
128186
qcom_q6v5_unprepare(&adsp->q6v5);
129187

@@ -138,6 +196,7 @@ static void qcom_pas_handover(struct qcom_q6v5 *q6v5)
138196
regulator_disable(adsp->cx_supply);
139197
clk_disable_unprepare(adsp->aggre2_clk);
140198
clk_disable_unprepare(adsp->xo);
199+
adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
141200
}
142201

143202
static int adsp_stop(struct rproc *rproc)
@@ -154,6 +213,7 @@ static int adsp_stop(struct rproc *rproc)
154213
if (ret)
155214
dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
156215

216+
adsp_pds_disable(adsp, adsp->active_pds, adsp->active_pd_count);
157217
handover = qcom_q6v5_unprepare(&adsp->q6v5);
158218
if (handover)
159219
qcom_pas_handover(&adsp->q6v5);
@@ -219,6 +279,59 @@ static int adsp_init_regulator(struct qcom_adsp *adsp)
219279
return PTR_ERR_OR_ZERO(adsp->px_supply);
220280
}
221281

282+
static int adsp_pds_attach(struct device *dev, struct device **devs,
283+
char **pd_names)
284+
{
285+
size_t num_pds = 0;
286+
int ret;
287+
int i;
288+
289+
if (!pd_names)
290+
return 0;
291+
292+
/* Handle single power domain */
293+
if (dev->pm_domain) {
294+
devs[0] = dev;
295+
pm_runtime_enable(dev);
296+
return 1;
297+
}
298+
299+
while (pd_names[num_pds])
300+
num_pds++;
301+
302+
for (i = 0; i < num_pds; i++) {
303+
devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
304+
if (IS_ERR_OR_NULL(devs[i])) {
305+
ret = PTR_ERR(devs[i]) ? : -ENODATA;
306+
goto unroll_attach;
307+
}
308+
}
309+
310+
return num_pds;
311+
312+
unroll_attach:
313+
for (i--; i >= 0; i--)
314+
dev_pm_domain_detach(devs[i], false);
315+
316+
return ret;
317+
};
318+
319+
static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds,
320+
size_t pd_count)
321+
{
322+
struct device *dev = adsp->dev;
323+
int i;
324+
325+
/* Handle single power domain */
326+
if (dev->pm_domain && pd_count) {
327+
pm_runtime_disable(dev);
328+
return;
329+
}
330+
331+
for (i = 0; i < pd_count; i++)
332+
dev_pm_domain_detach(pds[i], false);
333+
}
334+
222335
static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
223336
{
224337
struct device_node *node;
@@ -294,10 +407,22 @@ static int adsp_probe(struct platform_device *pdev)
294407
if (ret)
295408
goto free_rproc;
296409

410+
ret = adsp_pds_attach(&pdev->dev, adsp->active_pds,
411+
desc->active_pd_names);
412+
if (ret < 0)
413+
goto free_rproc;
414+
adsp->active_pd_count = ret;
415+
416+
ret = adsp_pds_attach(&pdev->dev, adsp->proxy_pds,
417+
desc->proxy_pd_names);
418+
if (ret < 0)
419+
goto detach_active_pds;
420+
adsp->proxy_pd_count = ret;
421+
297422
ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem,
298423
qcom_pas_handover);
299424
if (ret)
300-
goto free_rproc;
425+
goto detach_proxy_pds;
301426

302427
qcom_add_glink_subdev(rproc, &adsp->glink_subdev);
303428
qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
@@ -307,15 +432,19 @@ static int adsp_probe(struct platform_device *pdev)
307432
desc->ssctl_id);
308433
if (IS_ERR(adsp->sysmon)) {
309434
ret = PTR_ERR(adsp->sysmon);
310-
goto free_rproc;
435+
goto detach_proxy_pds;
311436
}
312437

313438
ret = rproc_add(rproc);
314439
if (ret)
315-
goto free_rproc;
440+
goto detach_proxy_pds;
316441

317442
return 0;
318443

444+
detach_proxy_pds:
445+
adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
446+
detach_active_pds:
447+
adsp_pds_detach(adsp, adsp->active_pds, adsp->active_pd_count);
319448
free_rproc:
320449
rproc_free(rproc);
321450

0 commit comments

Comments
 (0)