32
32
33
33
/* time out value */
34
34
#define ACK_TIMEOUT 1000
35
+ #define ACK_TIMEOUT_US 1000000
35
36
#define BOOT_FSM_TIMEOUT 10000
36
37
/* mask values */
37
38
#define EVB_MASK GENMASK(27, 4)
51
52
#define QDSP6SS_CORE_CBCR 0x20
52
53
#define QDSP6SS_SLEEP_CBCR 0x3c
53
54
55
+ #define QCOM_Q6V5_RPROC_PROXY_PD_MAX 3
56
+
54
57
struct adsp_pil_data {
55
58
int crash_reason_smem ;
56
59
const char * firmware_name ;
57
60
58
61
const char * ssr_name ;
59
62
const char * sysmon_name ;
60
63
int ssctl_id ;
64
+ bool is_wpss ;
65
+ bool auto_boot ;
61
66
62
67
const char * * clk_ids ;
63
68
int num_clks ;
69
+ const char * * proxy_pd_names ;
70
+ const char * load_state ;
64
71
};
65
72
66
73
struct qcom_adsp {
@@ -93,11 +100,151 @@ struct qcom_adsp {
93
100
void * mem_region ;
94
101
size_t mem_size ;
95
102
103
+ struct device * proxy_pds [QCOM_Q6V5_RPROC_PROXY_PD_MAX ];
104
+ size_t proxy_pd_count ;
105
+
96
106
struct qcom_rproc_glink glink_subdev ;
97
107
struct qcom_rproc_ssr ssr_subdev ;
98
108
struct qcom_sysmon * sysmon ;
109
+
110
+ int (* shutdown )(struct qcom_adsp * adsp );
99
111
};
100
112
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
+
101
248
static int qcom_adsp_shutdown (struct qcom_adsp * adsp )
102
249
{
103
250
unsigned long timeout ;
@@ -193,12 +340,10 @@ static int adsp_start(struct rproc *rproc)
193
340
if (ret )
194
341
goto disable_irqs ;
195
342
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 )
200
346
goto disable_xo_clk ;
201
- }
202
347
203
348
ret = clk_bulk_prepare_enable (adsp -> num_clks , adsp -> clks );
204
349
if (ret ) {
@@ -243,8 +388,7 @@ static int adsp_start(struct rproc *rproc)
243
388
disable_adsp_clks :
244
389
clk_bulk_disable_unprepare (adsp -> num_clks , adsp -> clks );
245
390
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 );
248
392
disable_xo_clk :
249
393
clk_disable_unprepare (adsp -> xo );
250
394
disable_irqs :
@@ -258,8 +402,7 @@ static void qcom_adsp_pil_handover(struct qcom_q6v5 *q6v5)
258
402
struct qcom_adsp * adsp = container_of (q6v5 , struct qcom_adsp , q6v5 );
259
403
260
404
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 );
263
406
}
264
407
265
408
static int adsp_stop (struct rproc * rproc )
@@ -272,7 +415,7 @@ static int adsp_stop(struct rproc *rproc)
272
415
if (ret == - ETIMEDOUT )
273
416
dev_err (adsp -> dev , "timed out on wait\n" );
274
417
275
- ret = qcom_adsp_shutdown (adsp );
418
+ ret = adsp -> shutdown (adsp );
276
419
if (ret )
277
420
dev_err (adsp -> dev , "failed to shutdown: %d\n" , ret );
278
421
@@ -428,6 +571,7 @@ static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
428
571
static int adsp_probe (struct platform_device * pdev )
429
572
{
430
573
const struct adsp_pil_data * desc ;
574
+ const char * firmware_name ;
431
575
struct qcom_adsp * adsp ;
432
576
struct rproc * rproc ;
433
577
int ret ;
@@ -436,12 +580,22 @@ static int adsp_probe(struct platform_device *pdev)
436
580
if (!desc )
437
581
return - EINVAL ;
438
582
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
+
439
591
rproc = rproc_alloc (& pdev -> dev , pdev -> name , & adsp_ops ,
440
- desc -> firmware_name , sizeof (* adsp ));
592
+ firmware_name , sizeof (* adsp ));
441
593
if (!rproc ) {
442
594
dev_err (& pdev -> dev , "unable to allocate remoteproc\n" );
443
595
return - ENOMEM ;
444
596
}
597
+
598
+ rproc -> auto_boot = desc -> auto_boot ;
445
599
rproc_coredump_set_elf_info (rproc , ELFCLASS32 , EM_NONE );
446
600
447
601
adsp = (struct qcom_adsp * )rproc -> priv ;
@@ -450,6 +604,11 @@ static int adsp_probe(struct platform_device *pdev)
450
604
adsp -> info_name = desc -> sysmon_name ;
451
605
platform_set_drvdata (pdev , adsp );
452
606
607
+ if (desc -> is_wpss )
608
+ adsp -> shutdown = qcom_wpss_shutdown ;
609
+ else
610
+ adsp -> shutdown = qcom_adsp_shutdown ;
611
+
453
612
ret = adsp_alloc_memory_region (adsp );
454
613
if (ret )
455
614
goto free_rproc ;
@@ -458,7 +617,13 @@ static int adsp_probe(struct platform_device *pdev)
458
617
if (ret )
459
618
goto free_rproc ;
460
619
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 ;
462
627
463
628
ret = adsp_init_reset (adsp );
464
629
if (ret )
@@ -468,8 +633,8 @@ static int adsp_probe(struct platform_device *pdev)
468
633
if (ret )
469
634
goto disable_pm ;
470
635
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 );
473
638
if (ret )
474
639
goto disable_pm ;
475
640
@@ -490,7 +655,8 @@ static int adsp_probe(struct platform_device *pdev)
490
655
return 0 ;
491
656
492
657
disable_pm :
493
- pm_runtime_disable (adsp -> dev );
658
+ qcom_rproc_pds_detach (adsp , adsp -> proxy_pds , adsp -> proxy_pd_count );
659
+
494
660
free_rproc :
495
661
rproc_free (rproc );
496
662
@@ -507,7 +673,7 @@ static int adsp_remove(struct platform_device *pdev)
507
673
qcom_remove_glink_subdev (adsp -> rproc , & adsp -> glink_subdev );
508
674
qcom_remove_sysmon_subdev (adsp -> sysmon );
509
675
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 );
511
677
rproc_free (adsp -> rproc );
512
678
513
679
return 0 ;
@@ -519,11 +685,16 @@ static const struct adsp_pil_data adsp_resource_init = {
519
685
.ssr_name = "lpass" ,
520
686
.sysmon_name = "adsp" ,
521
687
.ssctl_id = 0x14 ,
688
+ .is_wpss = false,
689
+ .auto_boot = true,
522
690
.clk_ids = (const char * []) {
523
691
"sway_cbcr" , "lpass_ahbs_aon_cbcr" , "lpass_ahbm_aon_cbcr" ,
524
692
"qdsp6ss_xo" , "qdsp6ss_sleep" , "qdsp6ss_core" , NULL
525
693
},
526
694
.num_clks = 7 ,
695
+ .proxy_pd_names = (const char * []) {
696
+ "cx" , NULL
697
+ },
527
698
};
528
699
529
700
static const struct adsp_pil_data cdsp_resource_init = {
@@ -532,15 +703,39 @@ static const struct adsp_pil_data cdsp_resource_init = {
532
703
.ssr_name = "cdsp" ,
533
704
.sysmon_name = "cdsp" ,
534
705
.ssctl_id = 0x17 ,
706
+ .is_wpss = false,
707
+ .auto_boot = true,
535
708
.clk_ids = (const char * []) {
536
709
"sway" , "tbu" , "bimc" , "ahb_aon" , "q6ss_slave" , "q6ss_master" ,
537
710
"q6_axim" , NULL
538
711
},
539
712
.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
+ },
540
734
};
541
735
542
736
static const struct of_device_id adsp_of_match [] = {
543
737
{ .compatible = "qcom,qcs404-cdsp-pil" , .data = & cdsp_resource_init },
738
+ { .compatible = "qcom,sc7280-wpss-pil" , .data = & wpss_resource_init },
544
739
{ .compatible = "qcom,sdm845-adsp-pil" , .data = & adsp_resource_init },
545
740
{ },
546
741
};
0 commit comments