@@ -25,6 +25,8 @@ register_phys_mem(MEM_AREA_IO_NSEC, RPMH_PDC_GLOBAL_BASE, RPMH_PDC_GLOBAL_SIZE);
2525register_phys_mem (MEM_AREA_IO_NSEC , RPMH_PDC_COMPUTE_BASE ,
2626 RPMH_PDC_COMPUTE_SIZE );
2727register_phys_mem (MEM_AREA_IO_NSEC , RPMH_PDC_NSP_BASE , RPMH_PDC_NSP_SIZE );
28+ register_phys_mem (MEM_AREA_IO_NSEC , RPMH_PDC_GPDSP0_BASE , RPMH_PDC_GPDSP0_SIZE );
29+ register_phys_mem (MEM_AREA_IO_NSEC , RPMH_PDC_GPDSP1_BASE , RPMH_PDC_GPDSP1_SIZE );
2830register_phys_mem (MEM_AREA_IO_NSEC , TCSR_MUTEX_BASE , TCSR_MUTEX_SIZE );
2931
3032static TEE_Result cdsp_enable (paddr_t turing_base )
@@ -183,6 +185,72 @@ static TEE_Result lpass_setup(void)
183185 Q6RCG_CFG_VALUE );
184186}
185187
188+ static const struct qcom_lucidevo_pll_config gpdsp_q6_pll_cfg = {
189+ .l_val = GPDSP_Q6_PLL_L_VAL ,
190+ .cal_l_val = GPDSP_Q6_PLL_CAL_L_VAL ,
191+ .pre_div = 1 ,
192+ .config_ctl = GPDSP_Q6_PLL_CONFIG_CTL ,
193+ .config_ctl_u = GPDSP_Q6_PLL_CONFIG_CTL_U ,
194+ .config_ctl_u1 = GPDSP_Q6_PLL_CONFIG_CTL_U1 ,
195+ .user_ctl = GPDSP_Q6_PLL_USER_CTL ,
196+ .user_ctl_u = GPDSP_Q6_PLL_USER_CTL_U ,
197+ /* alpha (default) fractional mode */
198+ };
199+
200+ /*
201+ * Set up clocks for a GP-DSP (TURINGGDSP) QDSP6, mirroring
202+ * Setup_TURINGGDSPProcessor in the reference ClockPIL driver. Like LPASS (and
203+ * unlike the Turing NSP), the Q6 PLL and core RCG are configured here, before
204+ * the boot FSM is triggered in gpdspN_fw_start; the core itself is released by
205+ * BOOT_CORE_START in fw_start, so there is no separate post-boot step. The
206+ * subsystem window is mapped by the PAS PTA mem-setup, so each sub-block base
207+ * is resolved via io_pa_or_va against the GP-DSP base + offset.
208+ */
209+ static TEE_Result gpdsp_setup (paddr_t gdsp_base , uint32_t gcc_cfg_ahb_cbcr ,
210+ uint32_t gcc_aggre_axi_cbcr )
211+ {
212+ struct io_pa_va gcc_io = { .pa = GCC_BASE };
213+ vaddr_t gcc_base = io_pa_or_va (& gcc_io , GCC_SIZE );
214+ struct io_pa_va gdsp_io = { .pa = gdsp_base };
215+ vaddr_t base = io_pa_or_va (& gdsp_io , TURING_GDSP_0_SIZE );
216+ vaddr_t gdsp_cc = base + TURINGGDSP_GDSP_CC_OFFSET ;
217+ vaddr_t core_cc = base + TURINGGDSP_CORE_CC_OFFSET ;
218+ vaddr_t pll_base = base + TURINGGDSP_PLL_OFFSET ;
219+ vaddr_t pub = base + TURINGGDSP_PUB_OFFSET ;
220+ TEE_Result res = TEE_SUCCESS ;
221+
222+ if (!gcc_base || !base )
223+ return TEE_ERROR_GENERIC ;
224+
225+ /* Turing slave-way bus clock branch, also on NIU socket. */
226+ res = qcom_clock_enable_cbc (gcc_base + gcc_cfg_ahb_cbcr );
227+ if (res != TEE_SUCCESS )
228+ return res ;
229+
230+ res = qcom_clock_enable_cbc (gcc_base + gcc_aggre_axi_cbcr );
231+ if (res != TEE_SUCCESS )
232+ return res ;
233+
234+ /* Q6SS slave clock, required to reach the QDSP6SS registers. */
235+ res = qcom_clock_enable_cbc (gdsp_cc + TURINGGDSP_Q6SS_AHBS_AON_CBCR );
236+ if (res != TEE_SUCCESS )
237+ return res ;
238+
239+ /* Program the debug config register, then enable core clock. */
240+ io_write32 (pub + TURINGGDSP_QDSP6SS_DBG_CFG , 0 );
241+ io_setbits32 (core_cc + TURINGGDSP_QDSP6SS_CORE_CBCR ,
242+ CBCR_BRANCH_ENABLE_BIT );
243+
244+ /* Configure and lock the Q6 PLL, then switch the core RCG onto it. */
245+ res = qcom_lucidevo_pll_enable (pll_base , & gpdsp_q6_pll_cfg );
246+ if (res != TEE_SUCCESS )
247+ return res ;
248+
249+ return qcom_clock_set_rate (core_cc + TURINGGDSP_QDSP6SS_CORE_CFG_RCGR ,
250+ core_cc + TURINGGDSP_QDSP6SS_CORE_CMD_RCGR ,
251+ Q6RCG_CFG_VALUE );
252+ }
253+
186254TEE_Result qcom_clock_enable_pas_processor (enum qcom_clk_group group )
187255{
188256 switch (group ) {
@@ -199,6 +267,15 @@ TEE_Result qcom_clock_enable_pas_processor(enum qcom_clk_group group)
199267 * there is no separate post-boot step here.
200268 */
201269 return TEE_SUCCESS ;
270+ case QCOM_CLKS_GPDSP0 :
271+ case QCOM_CLKS_GPDSP1 :
272+ /*
273+ * Like LPASS, the GP-DSP Q6 PLL and core RCG are configured in
274+ * gpdsp_setup (before the boot FSM); the core is released by
275+ * BOOT_CORE_START in gpdspN_fw_start, so there is no separate
276+ * post-boot step here.
277+ */
278+ return TEE_SUCCESS ;
202279 default :
203280 return TEE_ERROR_NOT_SUPPORTED ;
204281 }
@@ -348,13 +425,150 @@ static TEE_Result cdsp_reset_processor(const struct cdsp_reset_regs *r)
348425 return TEE_SUCCESS ;
349426}
350427
428+ /*
429+ * Per-instance register selection for the GP-DSP reset sequence. GDSP0 and
430+ * GDSP1 share the QDSP6 PUB offsets (parameterised by gdsp_base) but differ in
431+ * the GCC AHB CBCR, the TCSR halt/idle/power block, and the PDC / AOSS restart
432+ * fields.
433+ */
434+ struct gpdsp_reset_regs {
435+ paddr_t gdsp_base ;
436+ uint32_t gcc_cfg_ahb_cbcr ; /* offset within GCC window */
437+ uint32_t tcsr_haltreq ; /* offsets within TCSR mutex window */
438+ uint32_t tcsr_haltack ;
439+ uint32_t tcsr_il0_master_idle ;
440+ uint32_t tcsr_il1_master_idle ;
441+ uint32_t tcsr_pwr_on ;
442+ paddr_t pdc_status_base ; /* RPMH PDC block for the busy check */
443+ uint32_t pdc_status_size ;
444+ uint32_t pdc_sync_reset_bit ; /* field within RPMH_PDC_SYNC_RESET */
445+ uint32_t gpdsp_restart_bit ; /* field within AOSS_CC_GPDSP_RESTART */
446+ };
447+
448+ static const struct gpdsp_reset_regs gpdsp0_reset_regs = {
449+ .gdsp_base = TURING_GDSP_0_BASE ,
450+ .gcc_cfg_ahb_cbcr = GCC_GPDSP_0_CFG_AHB_CBCR ,
451+ .tcsr_haltreq = TCSR_GPDSP0_HALT_REQ ,
452+ .tcsr_haltack = TCSR_GPDSP0_HALT_ACK ,
453+ .tcsr_il0_master_idle = TCSR_GPDSP0_IL0_MASTER_IDLE ,
454+ .tcsr_il1_master_idle = TCSR_GPDSP0_IL1_MASTER_IDLE ,
455+ .tcsr_pwr_on = TCSR_GPDSP0_PWR_ON ,
456+ .pdc_status_base = RPMH_PDC_GPDSP0_BASE ,
457+ .pdc_status_size = RPMH_PDC_GPDSP0_SIZE ,
458+ .pdc_sync_reset_bit = PDC_SYNC_RESET_GPDSP0_BIT ,
459+ .gpdsp_restart_bit = GPDSP_RESTART_SS_0_BIT ,
460+ };
461+
462+ static const struct gpdsp_reset_regs gpdsp1_reset_regs = {
463+ .gdsp_base = TURING_GDSP_1_BASE ,
464+ .gcc_cfg_ahb_cbcr = GCC_GPDSP_1_CFG_AHB_CBCR ,
465+ .tcsr_haltreq = TCSR_GPDSP1_HALT_REQ ,
466+ .tcsr_haltack = TCSR_GPDSP1_HALT_ACK ,
467+ .tcsr_il0_master_idle = TCSR_GPDSP1_IL0_MASTER_IDLE ,
468+ .tcsr_il1_master_idle = TCSR_GPDSP1_IL1_MASTER_IDLE ,
469+ .tcsr_pwr_on = TCSR_GPDSP1_PWR_ON ,
470+ .pdc_status_base = RPMH_PDC_GPDSP1_BASE ,
471+ .pdc_status_size = RPMH_PDC_GPDSP1_SIZE ,
472+ .pdc_sync_reset_bit = PDC_SYNC_RESET_GPDSP1_BIT ,
473+ .gpdsp_restart_bit = GPDSP_RESTART_SS_1_BIT ,
474+ };
475+
476+ /* HALT_ACK polls for up to 1s (200000 * 5us), matching the reference. */
477+ #define GPDSP_HALT_ACK_TIMEOUT_US (200000 * 5)
478+
479+ /*
480+ * Put a GP-DSP QDSP6 through a full subsystem reset before bring-up, mirroring
481+ * Reset_TURINGGDSPProcessor / Reset_TURINGGDSP1Processor in the reference
482+ * ClockPIL. This returns the core to a clean state (asserting
483+ * AOSS_CC_GPDSP_RESTART and the PDC sync reset) so the Q6 does not come out of
484+ * reset from a stale or partially-initialised state. Unlike the Turing NSP,
485+ * there is no NSPAUX/ALT_RESET retention handling and the master-port idle
486+ * check covers two ports (IL0 and IL1).
487+ */
488+ static TEE_Result gpdsp_reset_processor (const struct gpdsp_reset_regs * r )
489+ {
490+ struct io_pa_va gdsp_io = { .pa = r -> gdsp_base };
491+ vaddr_t base = io_pa_or_va (& gdsp_io , TURING_GDSP_0_SIZE );
492+ vaddr_t pub = base + TURINGGDSP_PUB_OFFSET ;
493+ struct io_pa_va gcc_io = { .pa = GCC_BASE };
494+ vaddr_t gcc_base = io_pa_or_va (& gcc_io , GCC_SIZE );
495+ struct io_pa_va aoss_io = { .pa = AOSS_CC_BASE };
496+ vaddr_t aoss_cc = io_pa_or_va (& aoss_io , AOSS_CC_SIZE );
497+ struct io_pa_va pdc_g_io = { .pa = RPMH_PDC_GLOBAL_BASE };
498+ vaddr_t pdc_global = io_pa_or_va (& pdc_g_io , RPMH_PDC_GLOBAL_SIZE );
499+ struct io_pa_va pdc_s_io = { .pa = r -> pdc_status_base };
500+ vaddr_t pdc_status = io_pa_or_va (& pdc_s_io , r -> pdc_status_size );
501+ struct io_pa_va tcsr_io = { .pa = TCSR_MUTEX_BASE };
502+ vaddr_t tcsr = io_pa_or_va (& tcsr_io , TCSR_MUTEX_SIZE );
503+ uint64_t timeout = 0 ;
504+
505+ if (!base || !gcc_base || !aoss_cc || !pdc_global || !pdc_status ||
506+ !tcsr )
507+ return TEE_ERROR_GENERIC ;
508+
509+ /* Bail if the PDC sequencer is mid-transition. */
510+ if (io_read32 (pdc_status + RPMH_PDC_MODE_STATUS_DRV0 ) &
511+ PDC_MODE_STATUS_SEQ_BUSY_BIT )
512+ return TEE_ERROR_BUSY ;
513+
514+ /* Reset the retention logic and let the write settle. */
515+ io_setbits32 (pub + TURINGGDSP_QDSP6SS_RET_CFG ,
516+ QDSP6SS_RET_CFG_RET_ARES_ENA_BIT );
517+ dsb ();
518+ udelay (2000 );
519+
520+ /* Disconnect the SWAY NIU socket to halt config-NoC traffic. */
521+ io_clrbits32 (gcc_base + r -> gcc_cfg_ahb_cbcr , CBCR_CLK_ENABLE_BIT );
522+
523+ /*
524+ * If powered on and either master port (IL0 or IL1) is busy, halt
525+ * mem-NoC traffic and wait for the acknowledge.
526+ */
527+ if (io_read32 (tcsr + r -> tcsr_pwr_on ) & TCSR_TURING_BIT ) {
528+ if (!(io_read32 (tcsr + r -> tcsr_il0_master_idle ) &
529+ TCSR_TURING_BIT ) ||
530+ !(io_read32 (tcsr + r -> tcsr_il1_master_idle ) &
531+ TCSR_TURING_BIT )) {
532+ io_setbits32 (tcsr + r -> tcsr_haltreq , TCSR_TURING_BIT );
533+
534+ timeout = timeout_init_us (GPDSP_HALT_ACK_TIMEOUT_US );
535+ while (!(io_read32 (tcsr + r -> tcsr_haltack ) &
536+ TCSR_TURING_BIT )) {
537+ if (timeout_elapsed (timeout ))
538+ break ;
539+ udelay (5 );
540+ }
541+ }
542+ }
543+
544+ /* Assert the PDC reset, then pulse the subsystem restart. */
545+ io_setbits32 (pdc_global + RPMH_PDC_SYNC_RESET , r -> pdc_sync_reset_bit );
546+
547+ io_setbits32 (aoss_cc + AOSS_CC_GPDSP_RESTART , r -> gpdsp_restart_bit );
548+ udelay (200 );
549+ io_clrbits32 (aoss_cc + AOSS_CC_GPDSP_RESTART , r -> gpdsp_restart_bit );
550+ dsb ();
551+ udelay (200 );
552+
553+ /* De-assert the PDC reset and clear the halt request. */
554+ io_clrbits32 (pdc_global + RPMH_PDC_SYNC_RESET , r -> pdc_sync_reset_bit );
555+ io_clrbits32 (tcsr + r -> tcsr_haltreq , TCSR_TURING_BIT );
556+ udelay (100 );
557+
558+ return TEE_SUCCESS ;
559+ }
560+
351561TEE_Result qcom_clock_pas_reset (enum qcom_clk_group group )
352562{
353563 switch (group ) {
354564 case QCOM_CLKS_TURING :
355565 return cdsp_reset_processor (& cdsp0_reset_regs );
356566 case QCOM_CLKS_TURING1 :
357567 return cdsp_reset_processor (& cdsp1_reset_regs );
568+ case QCOM_CLKS_GPDSP0 :
569+ return gpdsp_reset_processor (& gpdsp0_reset_regs );
570+ case QCOM_CLKS_GPDSP1 :
571+ return gpdsp_reset_processor (& gpdsp1_reset_regs );
358572 case QCOM_CLKS_LPASS :
359573 /*
360574 * The LPASS subsystem reset (Reset_LPASSProcessor) is
@@ -399,6 +613,12 @@ TEE_Result qcom_clock_enable_pas(enum qcom_clk_group group)
399613 break ;
400614 case QCOM_CLKS_LPASS :
401615 return lpass_setup ();
616+ case QCOM_CLKS_GPDSP0 :
617+ return gpdsp_setup (TURING_GDSP_0_BASE , GCC_GPDSP_0_CFG_AHB_CBCR ,
618+ GCC_AGGRE_NOC_GPDSP_0_AXI_CBCR );
619+ case QCOM_CLKS_GPDSP1 :
620+ return gpdsp_setup (TURING_GDSP_1_BASE , GCC_GPDSP_1_CFG_AHB_CBCR ,
621+ GCC_AGGRE_NOC_GPDSP_1_AXI_CBCR );
402622 default :
403623 return TEE_ERROR_NOT_SUPPORTED ;
404624 }
0 commit comments