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)
5152#define QDSP6SS_CORE_CBCR 0x20
5253#define QDSP6SS_SLEEP_CBCR 0x3c
5354
55+ #define QCOM_Q6V5_RPROC_PROXY_PD_MAX 3
56+
5457struct 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
6673struct 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+
101248static 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)
243388disable_adsp_clks :
244389 clk_bulk_disable_unprepare (adsp -> num_clks , adsp -> clks );
245390disable_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 );
248392disable_xo_clk :
249393 clk_disable_unprepare (adsp -> xo );
250394disable_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
265408static 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)
428571static 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
492657disable_pm :
493- pm_runtime_disable (adsp -> dev );
658+ qcom_rproc_pds_detach (adsp , adsp -> proxy_pds , adsp -> proxy_pd_count );
659+
494660free_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
529700static 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
542736static 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