Skip to content

Commit 358b586

Browse files
Rakesh Pillaiandersson
authored andcommitted
remoteproc: qcom: q6v5_wpss: Add support for sc7280 WPSS
Add support for PIL loading of WPSS processor for SC7280 - WPSS boot will be requested by the wifi driver and hence disable auto-boot for WPSS. - Add a separate shutdown sequence handler for WPSS. - Add multiple power-domain voting support - Parse firmware-name from dtsi entry Reviewed-by: Stephen Boyd <swboyd@chromium.org> Signed-off-by: Rakesh Pillai <pillair@codeaurora.org> Signed-off-by: Manikanta Pubbisetty <quic_mpubbise@quicinc.com> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> Link: https://lore.kernel.org/r/1643712724-12436-4-git-send-email-quic_mpubbise@quicinc.com
1 parent 2630504 commit 358b586

File tree

1 file changed

+211
-16
lines changed

1 file changed

+211
-16
lines changed

drivers/remoteproc/qcom_q6v5_adsp.c

Lines changed: 211 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
/* time out value */
3434
#define ACK_TIMEOUT 1000
35+
#define ACK_TIMEOUT_US 1000000
3536
#define BOOT_FSM_TIMEOUT 10000
3637
/* mask values */
3738
#define EVB_MASK GENMASK(27, 4)
@@ -51,16 +52,22 @@
5152
#define QDSP6SS_CORE_CBCR 0x20
5253
#define QDSP6SS_SLEEP_CBCR 0x3c
5354

55+
#define QCOM_Q6V5_RPROC_PROXY_PD_MAX 3
56+
5457
struct adsp_pil_data {
5558
int crash_reason_smem;
5659
const char *firmware_name;
5760

5861
const char *ssr_name;
5962
const char *sysmon_name;
6063
int ssctl_id;
64+
bool is_wpss;
65+
bool auto_boot;
6166

6267
const char **clk_ids;
6368
int num_clks;
69+
const char **proxy_pd_names;
70+
const char *load_state;
6471
};
6572

6673
struct qcom_adsp {
@@ -93,11 +100,151 @@ struct qcom_adsp {
93100
void *mem_region;
94101
size_t mem_size;
95102

103+
struct device *proxy_pds[QCOM_Q6V5_RPROC_PROXY_PD_MAX];
104+
size_t proxy_pd_count;
105+
96106
struct qcom_rproc_glink glink_subdev;
97107
struct qcom_rproc_ssr ssr_subdev;
98108
struct qcom_sysmon *sysmon;
109+
110+
int (*shutdown)(struct qcom_adsp *adsp);
99111
};
100112

113+
static int qcom_rproc_pds_attach(struct device *dev, struct qcom_adsp *adsp,
114+
const char **pd_names)
115+
{
116+
struct device **devs = adsp->proxy_pds;
117+
size_t num_pds = 0;
118+
int ret;
119+
int i;
120+
121+
if (!pd_names)
122+
return 0;
123+
124+
/* Handle single power domain */
125+
if (dev->pm_domain) {
126+
devs[0] = dev;
127+
pm_runtime_enable(dev);
128+
return 1;
129+
}
130+
131+
while (pd_names[num_pds])
132+
num_pds++;
133+
134+
if (num_pds > ARRAY_SIZE(adsp->proxy_pds))
135+
return -E2BIG;
136+
137+
for (i = 0; i < num_pds; i++) {
138+
devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
139+
if (IS_ERR_OR_NULL(devs[i])) {
140+
ret = PTR_ERR(devs[i]) ? : -ENODATA;
141+
goto unroll_attach;
142+
}
143+
}
144+
145+
return num_pds;
146+
147+
unroll_attach:
148+
for (i--; i >= 0; i--)
149+
dev_pm_domain_detach(devs[i], false);
150+
151+
return ret;
152+
}
153+
154+
static void qcom_rproc_pds_detach(struct qcom_adsp *adsp, struct device **pds,
155+
size_t pd_count)
156+
{
157+
struct device *dev = adsp->dev;
158+
int i;
159+
160+
/* Handle single power domain */
161+
if (dev->pm_domain && pd_count) {
162+
pm_runtime_disable(dev);
163+
return;
164+
}
165+
166+
for (i = 0; i < pd_count; i++)
167+
dev_pm_domain_detach(pds[i], false);
168+
}
169+
170+
static int qcom_rproc_pds_enable(struct qcom_adsp *adsp, struct device **pds,
171+
size_t pd_count)
172+
{
173+
int ret;
174+
int i;
175+
176+
for (i = 0; i < pd_count; i++) {
177+
dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
178+
ret = pm_runtime_get_sync(pds[i]);
179+
if (ret < 0) {
180+
pm_runtime_put_noidle(pds[i]);
181+
dev_pm_genpd_set_performance_state(pds[i], 0);
182+
goto unroll_pd_votes;
183+
}
184+
}
185+
186+
return 0;
187+
188+
unroll_pd_votes:
189+
for (i--; i >= 0; i--) {
190+
dev_pm_genpd_set_performance_state(pds[i], 0);
191+
pm_runtime_put(pds[i]);
192+
}
193+
194+
return ret;
195+
}
196+
197+
static void qcom_rproc_pds_disable(struct qcom_adsp *adsp, struct device **pds,
198+
size_t pd_count)
199+
{
200+
int i;
201+
202+
for (i = 0; i < pd_count; i++) {
203+
dev_pm_genpd_set_performance_state(pds[i], 0);
204+
pm_runtime_put(pds[i]);
205+
}
206+
}
207+
208+
static int qcom_wpss_shutdown(struct qcom_adsp *adsp)
209+
{
210+
unsigned int val;
211+
212+
regmap_write(adsp->halt_map, adsp->halt_lpass + LPASS_HALTREQ_REG, 1);
213+
214+
/* Wait for halt ACK from QDSP6 */
215+
regmap_read_poll_timeout(adsp->halt_map,
216+
adsp->halt_lpass + LPASS_HALTACK_REG, val,
217+
val, 1000, ACK_TIMEOUT_US);
218+
219+
/* Assert the WPSS PDC Reset */
220+
reset_control_assert(adsp->pdc_sync_reset);
221+
222+
/* Place the WPSS processor into reset */
223+
reset_control_assert(adsp->restart);
224+
225+
/* wait after asserting subsystem restart from AOSS */
226+
usleep_range(200, 205);
227+
228+
/* Remove the WPSS reset */
229+
reset_control_deassert(adsp->restart);
230+
231+
/* De-assert the WPSS PDC Reset */
232+
reset_control_deassert(adsp->pdc_sync_reset);
233+
234+
usleep_range(100, 105);
235+
236+
clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks);
237+
238+
regmap_write(adsp->halt_map, adsp->halt_lpass + LPASS_HALTREQ_REG, 0);
239+
240+
/* Wait for halt ACK from QDSP6 */
241+
regmap_read_poll_timeout(adsp->halt_map,
242+
adsp->halt_lpass + LPASS_HALTACK_REG, val,
243+
!val, 1000, ACK_TIMEOUT_US);
244+
245+
return 0;
246+
}
247+
101248
static int qcom_adsp_shutdown(struct qcom_adsp *adsp)
102249
{
103250
unsigned long timeout;
@@ -193,12 +340,10 @@ static int adsp_start(struct rproc *rproc)
193340
if (ret)
194341
goto disable_irqs;
195342

196-
dev_pm_genpd_set_performance_state(adsp->dev, INT_MAX);
197-
ret = pm_runtime_get_sync(adsp->dev);
198-
if (ret) {
199-
pm_runtime_put_noidle(adsp->dev);
343+
ret = qcom_rproc_pds_enable(adsp, adsp->proxy_pds,
344+
adsp->proxy_pd_count);
345+
if (ret < 0)
200346
goto disable_xo_clk;
201-
}
202347

203348
ret = clk_bulk_prepare_enable(adsp->num_clks, adsp->clks);
204349
if (ret) {
@@ -243,8 +388,7 @@ static int adsp_start(struct rproc *rproc)
243388
disable_adsp_clks:
244389
clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks);
245390
disable_power_domain:
246-
dev_pm_genpd_set_performance_state(adsp->dev, 0);
247-
pm_runtime_put(adsp->dev);
391+
qcom_rproc_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
248392
disable_xo_clk:
249393
clk_disable_unprepare(adsp->xo);
250394
disable_irqs:
@@ -258,8 +402,7 @@ static void qcom_adsp_pil_handover(struct qcom_q6v5 *q6v5)
258402
struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5);
259403

260404
clk_disable_unprepare(adsp->xo);
261-
dev_pm_genpd_set_performance_state(adsp->dev, 0);
262-
pm_runtime_put(adsp->dev);
405+
qcom_rproc_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
263406
}
264407

265408
static int adsp_stop(struct rproc *rproc)
@@ -272,7 +415,7 @@ static int adsp_stop(struct rproc *rproc)
272415
if (ret == -ETIMEDOUT)
273416
dev_err(adsp->dev, "timed out on wait\n");
274417

275-
ret = qcom_adsp_shutdown(adsp);
418+
ret = adsp->shutdown(adsp);
276419
if (ret)
277420
dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
278421

@@ -428,6 +571,7 @@ static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
428571
static int adsp_probe(struct platform_device *pdev)
429572
{
430573
const struct adsp_pil_data *desc;
574+
const char *firmware_name;
431575
struct qcom_adsp *adsp;
432576
struct rproc *rproc;
433577
int ret;
@@ -436,12 +580,22 @@ static int adsp_probe(struct platform_device *pdev)
436580
if (!desc)
437581
return -EINVAL;
438582

583+
firmware_name = desc->firmware_name;
584+
ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
585+
&firmware_name);
586+
if (ret < 0 && ret != -EINVAL) {
587+
dev_err(&pdev->dev, "unable to read firmware-name\n");
588+
return ret;
589+
}
590+
439591
rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops,
440-
desc->firmware_name, sizeof(*adsp));
592+
firmware_name, sizeof(*adsp));
441593
if (!rproc) {
442594
dev_err(&pdev->dev, "unable to allocate remoteproc\n");
443595
return -ENOMEM;
444596
}
597+
598+
rproc->auto_boot = desc->auto_boot;
445599
rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
446600

447601
adsp = (struct qcom_adsp *)rproc->priv;
@@ -450,6 +604,11 @@ static int adsp_probe(struct platform_device *pdev)
450604
adsp->info_name = desc->sysmon_name;
451605
platform_set_drvdata(pdev, adsp);
452606

607+
if (desc->is_wpss)
608+
adsp->shutdown = qcom_wpss_shutdown;
609+
else
610+
adsp->shutdown = qcom_adsp_shutdown;
611+
453612
ret = adsp_alloc_memory_region(adsp);
454613
if (ret)
455614
goto free_rproc;
@@ -458,7 +617,13 @@ static int adsp_probe(struct platform_device *pdev)
458617
if (ret)
459618
goto free_rproc;
460619

461-
pm_runtime_enable(adsp->dev);
620+
ret = qcom_rproc_pds_attach(adsp->dev, adsp,
621+
desc->proxy_pd_names);
622+
if (ret < 0) {
623+
dev_err(&pdev->dev, "Failed to attach proxy power domains\n");
624+
goto free_rproc;
625+
}
626+
adsp->proxy_pd_count = ret;
462627

463628
ret = adsp_init_reset(adsp);
464629
if (ret)
@@ -468,8 +633,8 @@ static int adsp_probe(struct platform_device *pdev)
468633
if (ret)
469634
goto disable_pm;
470635

471-
ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, NULL,
472-
qcom_adsp_pil_handover);
636+
ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem,
637+
desc->load_state, qcom_adsp_pil_handover);
473638
if (ret)
474639
goto disable_pm;
475640

@@ -490,7 +655,8 @@ static int adsp_probe(struct platform_device *pdev)
490655
return 0;
491656

492657
disable_pm:
493-
pm_runtime_disable(adsp->dev);
658+
qcom_rproc_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
659+
494660
free_rproc:
495661
rproc_free(rproc);
496662

@@ -507,7 +673,7 @@ static int adsp_remove(struct platform_device *pdev)
507673
qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
508674
qcom_remove_sysmon_subdev(adsp->sysmon);
509675
qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
510-
pm_runtime_disable(adsp->dev);
676+
qcom_rproc_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
511677
rproc_free(adsp->rproc);
512678

513679
return 0;
@@ -519,11 +685,16 @@ static const struct adsp_pil_data adsp_resource_init = {
519685
.ssr_name = "lpass",
520686
.sysmon_name = "adsp",
521687
.ssctl_id = 0x14,
688+
.is_wpss = false,
689+
.auto_boot = true,
522690
.clk_ids = (const char*[]) {
523691
"sway_cbcr", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr",
524692
"qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core", NULL
525693
},
526694
.num_clks = 7,
695+
.proxy_pd_names = (const char*[]) {
696+
"cx", NULL
697+
},
527698
};
528699

529700
static const struct adsp_pil_data cdsp_resource_init = {
@@ -532,15 +703,39 @@ static const struct adsp_pil_data cdsp_resource_init = {
532703
.ssr_name = "cdsp",
533704
.sysmon_name = "cdsp",
534705
.ssctl_id = 0x17,
706+
.is_wpss = false,
707+
.auto_boot = true,
535708
.clk_ids = (const char*[]) {
536709
"sway", "tbu", "bimc", "ahb_aon", "q6ss_slave", "q6ss_master",
537710
"q6_axim", NULL
538711
},
539712
.num_clks = 7,
713+
.proxy_pd_names = (const char*[]) {
714+
"cx", NULL
715+
},
716+
};
717+
718+
static const struct adsp_pil_data wpss_resource_init = {
719+
.crash_reason_smem = 626,
720+
.firmware_name = "wpss.mdt",
721+
.ssr_name = "wpss",
722+
.sysmon_name = "wpss",
723+
.ssctl_id = 0x19,
724+
.is_wpss = true,
725+
.auto_boot = false,
726+
.load_state = "wpss",
727+
.clk_ids = (const char*[]) {
728+
"ahb_bdg", "ahb", "rscp", NULL
729+
},
730+
.num_clks = 3,
731+
.proxy_pd_names = (const char*[]) {
732+
"cx", "mx", NULL
733+
},
540734
};
541735

542736
static const struct of_device_id adsp_of_match[] = {
543737
{ .compatible = "qcom,qcs404-cdsp-pil", .data = &cdsp_resource_init },
738+
{ .compatible = "qcom,sc7280-wpss-pil", .data = &wpss_resource_init },
544739
{ .compatible = "qcom,sdm845-adsp-pil", .data = &adsp_resource_init },
545740
{ },
546741
};

0 commit comments

Comments
 (0)