soc/qualcomm/x1p42100: Add LPASS bring-up sequence for ADSP cold boot

Add LPASS(QDSP6) cold-boot support required to start the ADSP/LPASS
subsystem. Extend LPASS base/address definitions and register blocks,
add QDSP6SS register coverage with offset validation, and implement the
LPASS/Q6 bring-up sequence including RPMh votes, clock and GDSC enablement,
QDSP6SS PLL and core clock programming, TCM initialization, and Q6 boot
FSM start.

This enables correct ADSP initialization during cold boot on X1P42100 and
is required for off-mode charging support.

Reference:
  - HRD-X1P42100-S1
    https://docs.qualcomm.com/bundle/resource/topics/HRD-X1P42100-S1/

TEST:
  - Built image.serial.bin and verified boot on X1P42100.
  - Verified that ADSP Q6 comes out of reset and is enabled during cold boot.

Logs:
[INFO ]  SOC: LPASS/ADSP image loaded successfully
[INFO ]  RPMH RSC: Already initialized, skipping re-initialization
[DEBUG]  RPMH_REG: lcx.lvl ARC hlvl= 0 --> vlvl=   0
[DEBUG]  RPMH_REG: lcx.lvl ARC hlvl= 1 --> vlvl=  16
[DEBUG]  RPMH_REG: lcx.lvl ARC hlvl= 2 --> vlvl=  56
[DEBUG]  RPMH_REG: lcx.lvl ARC hlvl= 3 --> vlvl=  64
[DEBUG]  RPMH_REG: lcx.lvl ARC hlvl= 4 --> vlvl= 128
[DEBUG]  RPMH_REG: lcx.lvl ARC hlvl= 5 --> vlvl= 192
[DEBUG]  RPMH_REG: lcx.lvl ARC hlvl= 6 --> vlvl= 256
[DEBUG]  RPMH_REG: lcx.lvl ARC hlvl= 7 --> vlvl= 384
[INFO ]  RPMH_REG: Initialized lcx.lvl at addr=0x30030
[DEBUG]  RPMH_REG: Sent active request for lcx.lvl
[DEBUG]  BCM: Found address 0x00050048 for resource LP0
[INFO ]  BCM: Successfully voted for LP0 (addr=0x00050048, val=0x60004001)
[INFO ]  LPASS: BCM vote for LP0 and LPASS Init completed successfully
[INFO ]  LPASS: Processor setup complete
[INFO ]  LPASS: Q6 processor enabled

Change-Id: Icb06575be0c225c3b8fa7894f49ccc197ee7e072
Signed-off-by: Hari L <haril@qualcomm.corp-partner.google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/91563
Reviewed-by: Subrata Banik <subratabanik@google.com>
Reviewed-by: Jayvik Desai <jayvik@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Kapil Porwal <kapilporwal@google.com>
This commit is contained in:
Hari L 2026-03-05 14:22:14 +05:30 committed by Subrata Banik
commit 8beca96470
6 changed files with 780 additions and 43 deletions

View file

@ -24,7 +24,15 @@
#define LPASS_AON_CC_BASE (LPASS_BASE + 0x00E08000)
#define LPASS_AON_CC_PLL_CM_BASE (LPASS_BASE + 0x00E01000)
#define LPASS_CORE_GDSC_REG_BASE (LPASS_BASE + 0x01E00000)
#define LPASS_LPASS_CORE_CC_REG_BASE (LPASS_BASE + 0x01B08000)
#define LPASS_LPICX_NOC_BASE (LPASS_BASE + 0x01430000)
#define LPASS_LPI_TCM_REG_BASE (LPASS_BASE + 0x0126A000)
#define LPASS_MCC_LPASS_REG_BASE (LPASS_BASE + 0x01250000)
#define LPASS_QDSP6SS_PUB_BASE (LPASS_BASE + 0x00800000)
#define LPASS_QDSP6SS_PLL_BASE (LPASS_BASE + 0x00840000)
#define LPASS_QDSP6SS_CORE_CC_BASE (LPASS_BASE + 0x00848000)
#define LPASS_SSC_SCC_BASE (LPASS_BASE + 0x01A01000)
#define LPASS_EFUSE_Q6SS_BASE (LPASS_BASE + 0x0125B000)
#define RPMH_BASE 0x17520000
@ -172,6 +180,7 @@
#define PCIE6A_BQPHY_PCS_PCIE_LANE1 0x01BFFE00
/* TCSR */
#define TCSR_BASE 0x01FC0000
#define TCSR_GCC_PCIE_4L_CLKREF_EN_PCIE_ENABLE ((void *)0x1FD512C)
#define TCSR_PCIE_CTRL_4LN_CONFIG_SEL ((void *)0x1FDA000)

View file

@ -16,12 +16,22 @@
struct x1p42100_lpass_qdsp6ss {
u8 _res0[0x10];
u32 rst_evb;
u8 _res1[0x60 - 0x14];
u8 _res1[0x18 - 0x14];
u32 dbg_cfg;
u32 ret_cfg;
u8 _res2[0x60 - 0x20];
u32 boot_params[6];
u8 _res3[0x400 - 0x78];
u32 boot_core_start;
u32 boot_cmd;
u32 boot_status;
};
check_member(x1p42100_lpass_qdsp6ss, rst_evb, 0x10);
check_member(x1p42100_lpass_qdsp6ss, dbg_cfg, 0x18);
check_member(x1p42100_lpass_qdsp6ss, boot_params, 0x60);
check_member(x1p42100_lpass_qdsp6ss, boot_core_start, 0x400);
check_member(x1p42100_lpass_qdsp6ss, boot_status, 0x408);
/* LPASS EFUSE Q6SS Register Structure */
struct x1p42100_lpass_efuse_q6ss {

View file

@ -223,6 +223,36 @@ struct x1p42100_lpass_aon_cc_pll_clock {
u32 pll_test_ctl_u2;
};
/* LPASS QDSP6SS PLL register structure */
struct x1p42100_lpass_qdsp6ss_pll_clock {
u32 pll_mode;
u32 pll_opmode;
u32 pll_state;
u32 pll_status;
u32 pll_l_val;
u32 pll_alpha_val;
u32 pll_user_ctl;
u32 pll_user_ctl_u;
u32 pll_config_ctl;
u32 pll_config_ctl_u;
u32 pll_config_ctl_u1;
u32 pll_test_ctl;
u32 pll_test_ctl_u;
u32 pll_test_ctl_u1;
u32 pll_test_ctl_u2;
};
/* LPASS QDSP6SS Core CC register structure */
struct x1p42100_lpass_qdsp6ss_core_cc {
u32 core_cmd_rcgr;
u32 core_cfg_rcgr;
u8 _res0[0x0020 - 0x0008];
u32 core_cbcr;
};
check_member(x1p42100_lpass_qdsp6ss_core_cc, core_cfg_rcgr, 0x0004);
check_member(x1p42100_lpass_qdsp6ss_core_cc, core_cbcr, 0x0020);
/* LPASS Audio CC register structure */
struct x1p42100_lpass_audio_cc {
u8 _res0[0x28018];
@ -277,28 +307,102 @@ struct x1p42100_lpass_core_gdsc {
check_member(x1p42100_lpass_core_gdsc, lpass_core_gds_hm_ready, 0x000B8);
check_member(x1p42100_lpass_core_gdsc, lpass_top_cc_lpass_core_sway_ahb_ls_cbcr, 0x09000);
/* LPASS AON CC register structure */
struct x1p42100_lpass_aon_cc {
u8 _res0[0x9060];
u32 va_mem0_cbcr;
u8 _res1[0x2c];
u32 lpass_audio_hm_gdscr;
u8 _res2[0x2f6c];
u32 lpass_hm_collapse_vote_for_q6;
u8 _res3[0x6008];
u32 va_2x_cbcr;
u8 _res4[0x4];
u32 va_cbcr;
u8 _res5[0xffc];
u32 tx_mclk_cbcr;
/* LPASS Core CC register structure */
struct x1p42100_lpass_core_cc {
u8 _res0[0x23000];
u32 lpass_lpass_core_cc_sysnoc_mport_core_cbcr;
};
check_member(x1p42100_lpass_core_cc, lpass_lpass_core_cc_sysnoc_mport_core_cbcr, 0x23000);
/* LPASS AON CC register structure */
struct x1p42100_lpass_aon_cc {
u8 _res0[0x2000];
u32 lpass_noc_island_isolation;
u8 _res1[0x801C - 0x2004];
u32 q6_xo_cbcr;
u8 _res2[0x901C - 0x8020];
u32 q6_ahbm_cbcr;
u8 _res3[0x9060 - 0x9020];
u32 va_mem0_cbcr;
u8 _res4[0x9090 - 0x9064];
u32 lpass_audio_hm_gdscr;
u8 _res5[0x0A014 - 0x9094];
u32 pclkdbg_cbcr;
u8 _res6[0x0A020 - 0x0A018];
u32 at_cbcr;
u8 _res7[0xC000 - 0x0A024];
u32 lpass_hm_collapse_vote_for_q6;
u8 _res8[0x1200C - 0xC004];
u32 va_2x_cbcr;
u8 _res9[0x12014 - 0x12010];
u32 va_cbcr;
u8 _res10[0x13014 - 0x12018];
u32 tx_mclk_cbcr;
u8 _res11[0x19008 - 0x13018];
u32 lpi_noc_hs_cbcr;
u8 _res12[0x1902C - 0x1900C];
u32 q6_axim_cbcr;
};
check_member(x1p42100_lpass_aon_cc, lpass_noc_island_isolation, 0x02000);
check_member(x1p42100_lpass_aon_cc, q6_xo_cbcr, 0x801C);
check_member(x1p42100_lpass_aon_cc, q6_ahbm_cbcr, 0x901C);
check_member(x1p42100_lpass_aon_cc, va_mem0_cbcr, 0x9060);
check_member(x1p42100_lpass_aon_cc, lpass_audio_hm_gdscr, 0x9090);
check_member(x1p42100_lpass_aon_cc, pclkdbg_cbcr, 0x0A014);
check_member(x1p42100_lpass_aon_cc, at_cbcr, 0x0A020);
check_member(x1p42100_lpass_aon_cc, lpass_hm_collapse_vote_for_q6, 0xc000);
check_member(x1p42100_lpass_aon_cc, va_2x_cbcr, 0x1200C);
check_member(x1p42100_lpass_aon_cc, va_cbcr, 0x12014);
check_member(x1p42100_lpass_aon_cc, tx_mclk_cbcr, 0x13014);
check_member(x1p42100_lpass_aon_cc, lpi_noc_hs_cbcr, 0x19008);
check_member(x1p42100_lpass_aon_cc, q6_axim_cbcr, 0x1902C);
/* LPASS LPICX NOC register structure */
struct x1p42100_lpass_lpicx_noc {
u8 _res0[0x2040];
u32 sidebandmanager_chipcx_sbm_faultinen0_low;
u8 _res1[0x6090 - 0x2044];
u32 sidebandmanager_rcg_sbm_flagoutstatus0_low;
};
check_member(x1p42100_lpass_lpicx_noc, sidebandmanager_chipcx_sbm_faultinen0_low, 0x2040);
check_member(x1p42100_lpass_lpicx_noc, sidebandmanager_rcg_sbm_flagoutstatus0_low, 0x6090);
/* LPASS MCC_LPASS_REG register block */
struct x1p42100_lpass_mcc_lpass_reg {
u8 _res0[0x18];
u32 rsc_wait_event_ovrd_mask;
u8 _res1[0x5014 - 0x001c];
u32 atb_low_power_handshake;
u32 apb_low_power_handshake;
u8 _res2[0x5020 - 0x501c];
u32 nts_low_power_handshake;
u32 dap_low_power_handshake;
};
check_member(x1p42100_lpass_mcc_lpass_reg, rsc_wait_event_ovrd_mask, 0x0018);
check_member(x1p42100_lpass_mcc_lpass_reg, atb_low_power_handshake, 0x5014);
check_member(x1p42100_lpass_mcc_lpass_reg, nts_low_power_handshake, 0x5020);
/* LPASS SSC_SCC register block */
struct x1p42100_lpass_ssc_scc {
u8 _res0[0x30];
u32 ssc_scc_smem_cbcr;
};
check_member(x1p42100_lpass_ssc_scc, ssc_scc_smem_cbcr, 0x0030);
/* LPASS LPI TCM register block */
struct x1p42100_lpass_lpi_tcm {
u32 tcm_256kb_block_cbcr[10];
u8 _res0[0x0300 - 0x0028];
u32 axis_hs_cbcr;
};
check_member(x1p42100_lpass_lpi_tcm, tcm_256kb_block_cbcr, 0x0000);
check_member(x1p42100_lpass_lpi_tcm, axis_hs_cbcr, 0x0300);
struct x1p42100_disp_cc {
uint8_t _res0[0x00C];
@ -335,7 +439,7 @@ struct x1p42100_disp_cc {
uint32_t xo_cbcr;
};
/* Offset checks (relative to DISP_CC_BASE) */
/* Offset checks */
check_member(x1p42100_disp_cc, mdss_mdp_cbcr, 0x00000C);
check_member(x1p42100_disp_cc, mdss_vsync_cbcr, 0x000024);
check_member(x1p42100_disp_cc, mdss_dptx3_pixel0_cbcr, 0x000094);
@ -521,82 +625,111 @@ struct x1p42100_gcc {
u32 gcc_aggre_usb3_prim_axi_cbcr;
u8 _res36[0x42004 - 0x39094];
struct qupv3_clock qup_wrap0_s[8];
u8 _res37[0x47000 - 0x429c4];
u32 lpass_cfg_noc_sway_cbcr;
u8 _res38[0x4b000 - 0x47004];
u8 _res37[0x45150 - 0x429c4];
/* LPASS boot clock */
u32 gcc_noc_lpass_dcd_xo_cbcr;
u32 gcc_ddrss_lpass_shub_cbcr;
u8 _res38[0x47000 - 0x45158];
u32 gcc_lpass_cfg_noc_sway_cbcr;
u32 gcc_qmip_lpass_qtb_ahb_cbcr;
u8 _res39[0x47010 - 0x47008];
u32 gcc_lpass_aon_noc_ddrss_shub_cbcr;
u32 gcc_lpass_aggre_noc_mpu_client_ddrss_shub_cbcr;
u32 gcc_lpass_hw_af_noc_ddrss_shub_cbcr;
u8 _res40[0x47024 - 0x4701c];
u32 gcc_lpass_aggre_noc_ddrss_shub_cbcr;
u8 _res41[0x4702c - 0x47028];
struct clock_rcg lpass_ddrss_shub_rcg;
u8 _res42[0x47160 - 0x47034];
u32 gcc_cfg_noc_lpass_cbcr;
u8 _res43[0x4b000 - 0x47164];
u32 qspi_bcr;
u32 qspi_cnoc_ahb_cbcr;
u32 qspi_core_cbcr;
struct clock_rcg qspi_core;
u8 _res39[0x50000 - 0x4b014];
u8 _res44[0x50000 - 0x4b014];
u32 gcc_usb3_phy_prim_bcr;
u32 gcc_usb3phy_phy_prim_bcr;
u8 _res40[0x50010 - 0x50008];
u8 _res45[0x50010 - 0x50008];
u32 gcc_usb4_0_dp0_phy_prim_bcr;
u8 _res41[0x52000 - 0x50014];
u8 _res46[0x52000 - 0x50014];
u32 apcs_clk_br_en;
u8 _res42[0x52008 - 0x52004];
u8 _res47[0x52008 - 0x52004];
u32 apcs_clk_br_en1;
u8 _res43[0x52010 - 0x5200c];
u8 _res48[0x52010 - 0x5200c];
u32 apcs_clk_br_en2;
u8 _res44[0x52018 - 0x52014];
u8 _res49[0x52018 - 0x52014];
u32 apcs_clk_br_en3;
u8 _res45[0x52020 - 0x5201c];
u8 _res50[0x52020 - 0x5201c];
u32 apcs_clk_br_en4;
u8 _res46[0x52028 - 0x52024];
u8 _res51[0x52028 - 0x52024];
u32 apcs_clk_br_en5;
u8 _res47[0x52030 - 0x5202c];
u8 _res52[0x52030 - 0x5202c];
u32 apcs_pll_br_en;
u8 _res48[0x54000 - 0x52034];
u8 _res53[0x54000 - 0x52034];
u32 usb3_uniphy_mp1_bcr;
u32 usb3uniphy_phy_mp1_bcr;
u32 gcc_usb3_mp_ss1_phy_bcr;
u32 gcc_usb3_mp_ss1_phy_gdscr;
u8 _res49[0x8e000 - 0x54010];
u8 _res54[0x55224 - 0x54010];
u32 gcc_lpass_dsp_gdsc_sleep_ena_vote;
u8 _res55[0x8e000 - 0x55228];
u32 pcie_6_phy_gdscr;
u8 _res50[0xa1000 - 0x8e004];
u8 _res56[0x99000 - 0x8e004];
u32 gcc_lpass_qtb_gdscr;
u8 _res57[0x99014 - 0x99004];
u32 gcc_lpass_qtb_ahb_cbcr;
u32 gcc_lpass_audio_qtb_cbcr;
u8 _res58[0x99024 - 0x9901c];
u32 gcc_lpass_qosgen_extref_cbcr;
u32 gcc_lpass_qdss_tsctr_cbcr;
u32 gcc_lpass_qtb_at_cbcr;
u32 gcc_lpass_xo_cbcr;
u32 gcc_lpass_pwrctl_cbcr;
u32 gcc_tcu_lpass_audio_qtb_cbcr;
u8 _res59[0xa1000 - 0x9903c];
u32 gcc_usb30_sec_bcr;
u32 gcc_usb30_sec_gdscr;
u8 _res51[0xa1018 - 0xa1008];
u8 _res60[0xa1018 - 0xa1008];
u32 gcc_usb30_sec_master_cbcr;
u8 _res52[0xa1024 - 0xa101c];
u8 _res61[0xa1024 - 0xa101c];
u32 gcc_usb30_sec_sleep_cbcr;
u32 gcc_usb30_sec_mock_utmi_cbcr;
struct clock_rcg usb30_sec_master_rcg;
u8 _res53[0xa1060 - 0xa1034];
u8 _res62[0xa1060 - 0xa1034];
u32 gcc_usb3_sec_phy_aux_cbcr;
u32 gcc_usb3_sec_phy_com_aux_cbcr;
u32 gcc_usb3_sec_phy_pipe_cbcr;
u32 gcc_usb3_sec_phy_pipe_muxr;
u8 _res54[0xa108c - 0xa1070];
u8 _res63[0xa108c - 0xa1070];
u32 gcc_cfg_noc_usb3_sec_axi_cbcr;
u32 gcc_aggre_usb3_sec_axi_cbcr;
u8 _res55[0xa2000 - 0xa1094];
u8 _res64[0xa2000 - 0xa1094];
u32 gcc_usb30_tert_bcr;
u32 gcc_usb30_tert_gdscr;
u8 _res56[0xa2018 - 0xa2008];
u8 _res65[0xa2018 - 0xa2008];
u32 gcc_usb30_tert_master_cbcr;
u8 _res57[0xa2024 - 0xa201c];
u8 _res66[0xa2024 - 0xa201c];
u32 gcc_usb30_tert_sleep_cbcr;
u32 gcc_usb30_tert_mock_utmi_cbcr;
u8 _res58[0xa2034 - 0xa202c];
u8 _res67[0xa2034 - 0xa202c];
u32 gcc_usb30_tert_master_m;
u32 gcc_usb30_tert_master_n;
u32 gcc_usb30_tert_master_d;
u8 _res59[0xa2060 - 0xa2040];
u8 _res68[0xa2060 - 0xa2040];
u32 gcc_usb3_tert_phy_aux_cbcr;
u32 gcc_usb3_tert_phy_com_aux_cbcr;
u32 gcc_usb3_tert_phy_pipe_cbcr;
u32 gcc_usb3_tert_phy_pipe_muxr;
u8 _res60[0xa208c - 0xa2070];
u8 _res69[0xa208c - 0xa2070];
u32 gcc_cfg_noc_usb3_tert_axi_cbcr;
u32 gcc_aggre_usb3_tert_axi_cbcr;
u8 _res61[0xa3000 - 0xa2094];
u8 _res70[0xa3000 - 0xa2094];
u32 gcc_usb3_phy_tert_bcr;
u32 gcc_usb3phy_phy_tert_bcr;
u8 _res62[0xa3010 - 0xa3008];
u8 _res71[0xa3010 - 0xa3008];
u32 gcc_usb4_2_dp0_phy_tert_bcr;
u8 _res63[0xac01c - 0xa3014];
u8 _res72[0xac01c - 0xa3014];
u32 pcie_6a_phy_bcr;
};
@ -645,7 +778,16 @@ check_member(x1p42100_gcc, gcc_aggre_usb_noc_axi_cbcr, 0x2d034);
check_member(x1p42100_gcc, gcc_aggre_noc_usb_south_axi_cbcr, 0x2d174);
check_member(x1p42100_gcc, gcc_aggre_noc_usb_north_axi_cbcr, 0x2d17c);
check_member(x1p42100_gcc, qup_wrap0_s, 0x42004);
check_member(x1p42100_gcc, lpass_cfg_noc_sway_cbcr, 0x47000);
check_member(x1p42100_gcc, gcc_noc_lpass_dcd_xo_cbcr, 0x45150);
check_member(x1p42100_gcc, gcc_ddrss_lpass_shub_cbcr, 0x45154);
check_member(x1p42100_gcc, gcc_lpass_cfg_noc_sway_cbcr, 0x47000);
check_member(x1p42100_gcc, gcc_qmip_lpass_qtb_ahb_cbcr, 0x47004);
check_member(x1p42100_gcc, gcc_lpass_aon_noc_ddrss_shub_cbcr, 0x47010);
check_member(x1p42100_gcc, gcc_lpass_aggre_noc_mpu_client_ddrss_shub_cbcr, 0x47014);
check_member(x1p42100_gcc, gcc_lpass_hw_af_noc_ddrss_shub_cbcr, 0x47018);
check_member(x1p42100_gcc, gcc_lpass_aggre_noc_ddrss_shub_cbcr, 0x47024);
check_member(x1p42100_gcc, lpass_ddrss_shub_rcg, 0x4702c);
check_member(x1p42100_gcc, gcc_cfg_noc_lpass_cbcr, 0x47160);
check_member(x1p42100_gcc, qspi_bcr, 0x4b000);
check_member(x1p42100_gcc, apcs_clk_br_en, 0x52000);
check_member(x1p42100_gcc, apcs_clk_br_en1, 0x52008);
@ -655,6 +797,16 @@ check_member(x1p42100_gcc, apcs_clk_br_en4, 0x52020);
check_member(x1p42100_gcc, apcs_clk_br_en5, 0x52028);
check_member(x1p42100_gcc, apcs_pll_br_en, 0x52030);
check_member(x1p42100_gcc, pcie_6_phy_gdscr, 0x8e000);
check_member(x1p42100_gcc, gcc_lpass_qtb_gdscr, 0x99000);
check_member(x1p42100_gcc, gcc_lpass_qtb_ahb_cbcr, 0x99014);
check_member(x1p42100_gcc, gcc_lpass_audio_qtb_cbcr, 0x99018);
check_member(x1p42100_gcc, gcc_lpass_qosgen_extref_cbcr, 0x99024);
check_member(x1p42100_gcc, gcc_lpass_qdss_tsctr_cbcr, 0x99028);
check_member(x1p42100_gcc, gcc_lpass_qtb_at_cbcr, 0x9902c);
check_member(x1p42100_gcc, gcc_lpass_xo_cbcr, 0x99030);
check_member(x1p42100_gcc, gcc_lpass_pwrctl_cbcr, 0x99034);
check_member(x1p42100_gcc, gcc_tcu_lpass_audio_qtb_cbcr, 0x99038);
check_member(x1p42100_gcc, gcc_lpass_dsp_gdsc_sleep_ena_vote, 0x55224);
check_member(x1p42100_gcc, pcie_6a_phy_bcr, 0xac01c);
/* Generic QUPV3 wrapper structure - all wrappers have identical layout */
@ -868,6 +1020,25 @@ enum clk_lpass {
LPASS_CLK_COUNT
};
enum lpass_boot_clk {
DDRSS_LPASS_SHUB_CBCR,
LPASS_AGGRE_NOC_DDRSS_SHUB_CBCR,
LPASS_AGGRE_NOC_MPU_CLIENT_DDRSS_SHUB_CBCR,
LPASS_AON_NOC_DDRSS_SHUB_CBCR,
LPASS_AUDIO_QTB_CBCR,
LPASS_HW_AF_NOC_DDRSS_SHUB_CBCR,
LPASS_PWRCTL_CBCR,
LPASS_QDSS_TSCTR_CBCR,
LPASS_QOSGEN_EXTREF_CBCR,
LPASS_QTB_AHB_CBCR,
LPASS_QTB_AT_CBCR,
LPASS_XO_CBCR,
NOC_LPASS_DCD_XO_CBCR,
QMIP_LPASS_QTB_AHB_CBCR,
TCU_LPASS_AUDIO_QTB_CBCR,
LPASS_BOOT_CLK_COUNT
};
enum subsystem_reset {
AOP_RESET_SHFT,
CORE_SW_RESET,
@ -919,6 +1090,13 @@ static struct x1p42100_lpass_audio_cc *const lpass_audio_cc = (void *)LPASS_AUDI
static struct x1p42100_lpass_aon_cc *const lpass_aon_cc = (void *)LPASS_AON_CC_BASE;
static struct x1p42100_lpass_aon_cc_pll_clock *const lpass_aon_cc_pll = (void *)LPASS_AON_CC_PLL_CM_BASE;
static struct x1p42100_lpass_core_gdsc *const lpass_core_gdsc = (void *)LPASS_CORE_GDSC_REG_BASE;
static struct x1p42100_lpass_core_cc *const lpass_core_cc = (void *)LPASS_LPASS_CORE_CC_REG_BASE;
static struct x1p42100_lpass_lpicx_noc *const lpass_lpicx_noc = (void *)LPASS_LPICX_NOC_BASE;
static struct x1p42100_lpass_qdsp6ss_pll_clock *const lpass_qdsp6ss_pll = (void *)LPASS_QDSP6SS_PLL_BASE;
static struct x1p42100_lpass_qdsp6ss_core_cc *const lpass_qdsp6ss_core_cc = (void *)LPASS_QDSP6SS_CORE_CC_BASE;
static struct x1p42100_lpass_mcc_lpass_reg *const lpass_mcc_lpass_reg = (void *)LPASS_MCC_LPASS_REG_BASE;
static struct x1p42100_lpass_ssc_scc *const lpass_ssc_scc = (void *)LPASS_SSC_SCC_BASE;
static struct x1p42100_lpass_lpi_tcm *const lpass_lpi_tcm = (void *)LPASS_LPI_TCM_REG_BASE;
/* Does nothing */
#define clock_reset_aop() do {} while (0)

View file

@ -3,6 +3,7 @@
#ifndef _SOC_QUALCOMM_X1P42100_LPASS_H_
#define _SOC_QUALCOMM_X1P42100_LPASS_H_
#include <soc/addressmap.h>
#include <types.h>
/* LPASS AON CC PLL Settings */
@ -20,12 +21,110 @@
#define HAL_CLK_LPASS_AON_CC_PLL_USER_CTL 0x00E00041
#define HAL_CLK_LPASS_AON_CC_PLL_USER_CTL_U 0x00000105
#define LPASS_CORE_HM_READY BIT(0)
#define HW_CTL BIT(1)
enum lpass_voltage_level {
LPASS_VOLTAGE_LOWSVS_D1,
LPASS_VOLTAGE_LOWSVS,
LPASS_VOLTAGE_SVS,
LPASS_VOLTAGE_SVS_L1,
LPASS_VOLTAGE_NOMINAL,
LPASS_VOLTAGE_TURBO,
LPASS_VOLTAGE_MAX
};
/* Default voltage level for boot */
#define LPASS_DEFAULT_VOLTAGE_LEVEL LPASS_VOLTAGE_SVS_L1
/* LPASS QDSP6SS PLL user control bit shifts */
#define QDSP6SS_PLL_PLLOUT_MAIN_SHFT 0
/* LPASS QDSP6SS PLL Settings - Voltage-dependent values */
#define HAL_CLK_LPASS_QDSP6SS_PLL_L_VALUE_LOWSVS_D1 0x00000018
#define HAL_CLK_LPASS_QDSP6SS_PLL_ALPHA_VALUE_LOWSVS_D1 0x00000000
#define HAL_CLK_LPASS_QDSP6SS_PLL_L_VALUE_LOWSVS 0x0000001F
#define HAL_CLK_LPASS_QDSP6SS_PLL_ALPHA_VALUE_LOWSVS 0x00000000
#define HAL_CLK_LPASS_QDSP6SS_PLL_L_VALUE_SVS 0x00000029
#define HAL_CLK_LPASS_QDSP6SS_PLL_ALPHA_VALUE_SVS 0x00000000
#define HAL_CLK_LPASS_QDSP6SS_PLL_L_VALUE_SVS_L1 0x00000032
#define HAL_CLK_LPASS_QDSP6SS_PLL_ALPHA_VALUE_SVS_L1 0x00000000
#define HAL_CLK_LPASS_QDSP6SS_PLL_L_VALUE_NOMINAL 0x0000003E
#define HAL_CLK_LPASS_QDSP6SS_PLL_ALPHA_VALUE_NOMINAL 0x00000000
#define HAL_CLK_LPASS_QDSP6SS_PLL_L_VALUE_TURBO 0x0000004E
#define HAL_CLK_LPASS_QDSP6SS_PLL_ALPHA_VALUE_TURBO 0x00000000
#define HAL_CLK_LPASS_QDSP6SS_PLL_L_VALUE HAL_CLK_LPASS_QDSP6SS_PLL_L_VALUE_SVS_L1
#define HAL_CLK_LPASS_QDSP6SS_PLL_ALPHA_VALUE HAL_CLK_LPASS_QDSP6SS_PLL_ALPHA_VALUE_SVS_L1
#define HAL_CLK_LPASS_QDSP6SS_PLL_CAL_L_VALUE 0x00000044
#define HAL_CLK_LPASS_QDSP6SS_PLL_CONFIG_CTL 0x20485699
#define HAL_CLK_LPASS_QDSP6SS_PLL_CONFIG_CTL_U 0x00182261
#define HAL_CLK_LPASS_QDSP6SS_PLL_CONFIG_CTL_U1 0x82AA299C
#define HAL_CLK_LPASS_QDSP6SS_PLL_TEST_CTL 0x00000000
#define HAL_CLK_LPASS_QDSP6SS_PLL_TEST_CTL_U 0x00000003
#define HAL_CLK_LPASS_QDSP6SS_PLL_TEST_CTL_U1 0x00009000
#define HAL_CLK_LPASS_QDSP6SS_PLL_TEST_CTL_U2 0x00000034
#define HAL_CLK_LPASS_QDSP6SS_PLL_USER_CTL 0x00000000
#define HAL_CLK_LPASS_QDSP6SS_PLL_USER_CTL_U 0x00000005
#define LPASS_CORE_HM_READY (1 << 0)
#define HW_CTL (1 << 1)
#define GDSC_ENABLE_BIT 0
#define GDSC_RETAIN_FF_ENABLE (1 << 11)
#define LPASS_CORE_HM_VOTE_POWER_ON 0x0
#define GDSC_PWR_ON BIT(31)
#define LPASS_CORE_HM_VOTE_POWER_DOWN 0x1
#define BCM_LP0_VOTE_VALUE 0x60004001
/* NanoRCG status bits */
#define LPASS_NANO_RCG_PORT2 (1 << 2)
/* Low power handshake bits */
#define LPASS_LP_HANDSHAKE_ACK (1 << 0) /* Bit 0: ACK status (RO) */
#define LPASS_LP_HANDSHAKE_ACTIVE (1 << 1) /* Bit 1: ACTIVE status (RO) */
#define LPASS_LP_HANDSHAKE_REQUEST (1 << 2) /* Bit 2: REQUEST control (RW) */
/* NTS debug bridge handshake tuning */
#define LPASS_NTS_HANDSHAKE_TIMEOUT_US 500000
#define LPASS_NTS_HANDSHAKE_DELAY_US 100
/* Q6 Core RCG configuration */
#define Q6_CORE_RCG_CFG 0x201
#define CLK_CTL_CMD_UPDATE_SHFT 0
#define LPASS_RCG_UPDATE_TIMEOUT_US 100000
/* RSC wait event override mask */
#define LPASS_RSC_WAIT_EVENT_MASK 0x8
/* CR QCTDD10442361 workaround - NOC island isolation bits */
#define CHIP_CX_RSCC_BYPASS_EN (1 << 21)
#define AON_NOC_STALL_MASK (1 << 22)
#define CHIPCX_SBM_FAULTINEN0_PORT0 (1 << 0)
/* TCM (Tightly Coupled Memory) control bits */
#define LPASS_TCM_MAX_BLOCKS 9
/* Q6 Boot control bits */
#define BOOT_CORE_START (1 << 0)
#define BOOT_FSM_START (1 << 0)
#define LPASS_BOOT_FSM_TIMEOUT_US 1000000
#define TCSR_BOOT_IMEM_DISABLE_OFF 0x013300
#define TCSR_BOOT_IMEM_DISABLE ((void *)(TCSR_BASE + TCSR_BOOT_IMEM_DISABLE_OFF))
enum cb_err lpass_bring_up(void);
/*
* Clock workarounds for LPASS clocks.
*
* Keep these lists declarative (CBCR pointers only); apply behavior in
* lpass_apply_clock_workarounds().
*/
struct lpass_cbcr_list {
uint32_t *cbcr;
};
#endif /* _SOC_QUALCOMM_X1P42100_LPASS_H_ */

View file

@ -31,6 +31,7 @@
#define RPMH_REGULATOR_LEVEL_MIN_MM0 1
#define RPMH_REGULATOR_LEVEL_TURBO_MM0 6
#define RPMH_REGULATOR_LEVEL_NOM_L1 5
#define BCM_MM0_VOTE_VALUE 0x60004001
#define AOP_BOOT_COOKIE 0xA0C00C1E

View file

@ -1,12 +1,40 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <console/console.h>
#include <delay.h>
#include <device/mmio.h>
#include <soc/adsp.h>
#include <soc/addressmap.h>
#include <soc/clock.h>
#include <soc/cmd_db.h>
#include <soc/lpass.h>
#include <soc/rpmh_bcm.h>
#include <soc/rpmh_config.h>
#include <soc/rpmh_regulator.h>
#include <timer.h>
/* Debug configuration value (0 = no debug, non-zero = 0x20000000 = enable debug) */
u32 lpass_q6_debug_val = 0;
static struct clock_freq_config lpass_ddrss_shub_cfg[] = {
{
.hz = 400 * MHz,
.src = SRC_GPLL0_MAIN_600MHZ,
.div = QCOM_CLOCK_DIV(1.5),
},
};
/* Configure LPASS DDRSS SHUB RCG (RCGR + M/N) to 400 MHz */
static void lpass_configure_ddrss_shub_rcg(void)
{
if (clock_configure(&gcc->lpass_ddrss_shub_rcg,
lpass_ddrss_shub_cfg,
400 * MHz, ARRAY_SIZE(lpass_ddrss_shub_cfg)) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to configure DDRSS SHUB RCG\n");
return;
}
}
static enum cb_err lpass_aon_cc_pll_enable(void)
{
struct alpha_pll_reg_val_config pll_cfg = {0};
@ -55,15 +83,79 @@ static enum cb_err lpass_aon_cc_pll_enable(void)
return CB_SUCCESS;
}
static enum cb_err lpass_qdsp6ss_pll_enable(void)
{
struct alpha_pll_reg_val_config pll_cfg = {0};
pll_cfg.reg_mode = &lpass_qdsp6ss_pll->pll_mode;
pll_cfg.reg_l = &lpass_qdsp6ss_pll->pll_l_val;
pll_cfg.l_val = HAL_CLK_LPASS_QDSP6SS_PLL_L_VALUE_SVS_L1;
pll_cfg.reg_alpha = &lpass_qdsp6ss_pll->pll_alpha_val;
pll_cfg.alpha_val = HAL_CLK_LPASS_QDSP6SS_PLL_ALPHA_VALUE_SVS_L1;
pll_cfg.reg_cal_l = &lpass_qdsp6ss_pll->pll_l_val;
pll_cfg.cal_l_val = HAL_CLK_LPASS_QDSP6SS_PLL_CAL_L_VALUE;
pll_cfg.reg_config_ctl = &lpass_qdsp6ss_pll->pll_config_ctl;
pll_cfg.config_ctl_val = HAL_CLK_LPASS_QDSP6SS_PLL_CONFIG_CTL;
pll_cfg.reg_config_ctl_hi = &lpass_qdsp6ss_pll->pll_config_ctl_u;
pll_cfg.config_ctl_hi_val = HAL_CLK_LPASS_QDSP6SS_PLL_CONFIG_CTL_U;
pll_cfg.reg_config_ctl_hi1 = &lpass_qdsp6ss_pll->pll_config_ctl_u1;
pll_cfg.config_ctl_hi1_val = HAL_CLK_LPASS_QDSP6SS_PLL_CONFIG_CTL_U1;
pll_cfg.reg_user_ctl = &lpass_qdsp6ss_pll->pll_user_ctl;
pll_cfg.user_ctl_val = HAL_CLK_LPASS_QDSP6SS_PLL_USER_CTL;
pll_cfg.reg_user_ctl_hi = &lpass_qdsp6ss_pll->pll_user_ctl_u;
pll_cfg.user_ctl_hi_val = HAL_CLK_LPASS_QDSP6SS_PLL_USER_CTL_U;
pll_cfg.reg_opmode = &lpass_qdsp6ss_pll->pll_opmode;
if (clock_configure_enable_gpll(&pll_cfg, false, 0) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: QDSP6SS PLL configuration failed\n");
return CB_ERR;
}
write32(&lpass_qdsp6ss_pll->pll_test_ctl, HAL_CLK_LPASS_QDSP6SS_PLL_TEST_CTL);
write32(&lpass_qdsp6ss_pll->pll_test_ctl_u, HAL_CLK_LPASS_QDSP6SS_PLL_TEST_CTL_U);
write32(&lpass_qdsp6ss_pll->pll_test_ctl_u1, HAL_CLK_LPASS_QDSP6SS_PLL_TEST_CTL_U1);
write32(&lpass_qdsp6ss_pll->pll_test_ctl_u2, HAL_CLK_LPASS_QDSP6SS_PLL_TEST_CTL_U2);
if (lucidole_pll_enable(&pll_cfg) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: QDSP6SS PLL enable failed\n");
return CB_ERR;
}
/* Enable PLLOUT_MAIN for QDSP6SS PLL */
setbits32(&lpass_qdsp6ss_pll->pll_user_ctl, BIT(QDSP6SS_PLL_PLLOUT_MAIN_SHFT));
/* Configure Q6 Core RCG */
write32(&lpass_qdsp6ss_core_cc->core_cfg_rcgr, Q6_CORE_RCG_CFG);
setbits32(&lpass_qdsp6ss_core_cc->core_cmd_rcgr, BIT(CLK_CTL_CMD_UPDATE_SHFT));
/* Wait for RCG update */
if (!wait_us(LPASS_RCG_UPDATE_TIMEOUT_US,
!(read32(&lpass_qdsp6ss_core_cc->core_cmd_rcgr) &
BIT(CLK_CTL_CMD_UPDATE_SHFT)))) {
printk(BIOS_ERR, "LPASS: RCG update timeout\n");
return CB_ERR;
}
/* Enable QDSP6 core clock */
setbits32(&lpass_qdsp6ss_core_cc->core_cbcr, BIT(CLK_CTL_EN_SHFT));
return CB_SUCCESS;
}
static enum cb_err lpass_setup_core_infrastructure(void)
{
if (clock_enable(&gcc->lpass_cfg_noc_sway_cbcr) != CB_SUCCESS) {
if (clock_enable(&gcc->gcc_lpass_cfg_noc_sway_cbcr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable CFG NOC SWAY clock\n");
return CB_ERR;
}
setbits32(&lpass_core_gdsc->lpass_top_cc_lpass_core_sway_ahb_ls_cbcr, HW_CTL);
clock_configure_hw_ctl(&lpass_core_gdsc->lpass_top_cc_lpass_core_sway_ahb_ls_cbcr, true);
write32(&lpass_aon_cc->lpass_hm_collapse_vote_for_q6, LPASS_CORE_HM_VOTE_POWER_ON);
@ -77,9 +169,49 @@ static enum cb_err lpass_setup_core_infrastructure(void)
return CB_ERR;
}
/* Enable retention */
setbits32(&lpass_core_gdsc->core_hm_gdscr, GDSC_RETAIN_FF_ENABLE);
/* Enable SYSNOC interface */
if (clock_enable(&lpass_core_cc->lpass_lpass_core_cc_sysnoc_mport_core_cbcr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable SYSNOC interface\n");
return CB_ERR;
}
return CB_SUCCESS;
}
static const struct lpass_cbcr_list lpass_rpmh_ignore_clks[] = {
{ &gcc->gcc_ddrss_lpass_shub_cbcr },
{ &gcc->gcc_tcu_lpass_audio_qtb_cbcr },
};
static const struct lpass_cbcr_list lpass_pmu_ignore_clks[] = {
{ &gcc->gcc_lpass_hw_af_noc_ddrss_shub_cbcr },
{ &gcc->gcc_lpass_aggre_noc_ddrss_shub_cbcr },
{ &gcc->gcc_lpass_aggre_noc_mpu_client_ddrss_shub_cbcr },
};
/* Boot clocks (GCC CBCRs). */
static u32 *lpass_boot_cbcr[LPASS_BOOT_CLK_COUNT] = {
[DDRSS_LPASS_SHUB_CBCR] = &gcc->gcc_ddrss_lpass_shub_cbcr,
[LPASS_AGGRE_NOC_DDRSS_SHUB_CBCR] = &gcc->gcc_lpass_aggre_noc_ddrss_shub_cbcr,
[LPASS_AGGRE_NOC_MPU_CLIENT_DDRSS_SHUB_CBCR] = &gcc->gcc_lpass_aggre_noc_mpu_client_ddrss_shub_cbcr,
[LPASS_AON_NOC_DDRSS_SHUB_CBCR] = &gcc->gcc_lpass_aon_noc_ddrss_shub_cbcr,
[LPASS_AUDIO_QTB_CBCR] = &gcc->gcc_lpass_audio_qtb_cbcr,
[LPASS_HW_AF_NOC_DDRSS_SHUB_CBCR] = &gcc->gcc_lpass_hw_af_noc_ddrss_shub_cbcr,
[LPASS_PWRCTL_CBCR] = &gcc->gcc_lpass_pwrctl_cbcr,
[LPASS_QDSS_TSCTR_CBCR] = &gcc->gcc_lpass_qdss_tsctr_cbcr,
[LPASS_QOSGEN_EXTREF_CBCR] = &gcc->gcc_lpass_qosgen_extref_cbcr,
[LPASS_QTB_AHB_CBCR] = &gcc->gcc_lpass_qtb_ahb_cbcr,
[LPASS_QTB_AT_CBCR] = &gcc->gcc_lpass_qtb_at_cbcr,
[LPASS_XO_CBCR] = &gcc->gcc_lpass_xo_cbcr,
[NOC_LPASS_DCD_XO_CBCR] = &gcc->gcc_noc_lpass_dcd_xo_cbcr,
[QMIP_LPASS_QTB_AHB_CBCR] = &gcc->gcc_qmip_lpass_qtb_ahb_cbcr,
[TCU_LPASS_AUDIO_QTB_CBCR] = &gcc->gcc_tcu_lpass_audio_qtb_cbcr,
};
/* Array mapping enum clk_lpass to actual CBCR registers */
static u32 *lpass_cbcr[LPASS_CLK_COUNT] = {
[LPASS_CODEC_MEM_CBCR] = &lpass_audio_cc->codec_mem_cbcr,
[LPASS_CODEC_MEM0_CBCR] = &lpass_audio_cc->codec_mem0_cbcr,
@ -114,15 +246,323 @@ static enum cb_err lpass_audio_clocks_enable(void)
return CB_SUCCESS;
}
enum cb_err lpass_init(void)
static enum cb_err lpass_rpmh_bcm_vote(void)
{
struct rpmh_vreg arc_reg;
enum cb_err ret;
int rc;
volatile u32 *boot_cookie = (volatile u32 *)AOP_BOOT_COOKIE_ADDR;
if (!wait_us(AOP_BOOT_TIMEOUT_US, *boot_cookie == AOP_BOOT_COOKIE)) {
printk(BIOS_ERR,
"AOP not booted after %dus (cookie: 0x%x, expected: 0x%x)\n",
AOP_BOOT_TIMEOUT_US, *boot_cookie, AOP_BOOT_COOKIE);
return CB_ERR;
}
ret = cmd_db_ready();
if (ret != CB_SUCCESS) {
ret = cmd_db_init(CMD_DB_BASE_ADDR, CMD_DB_SIZE);
if (ret != CB_SUCCESS) {
printk(BIOS_ERR, "CMD_DB: init failed\n");
return CB_ERR;
}
}
rc = rpmh_rsc_init();
if (rc) {
printk(BIOS_ERR, "RPMH_RSC: init failed\n");
return CB_ERR;
}
/* Initialize LCX ARC regulator for LPASS power rail */
rc = rpmh_regulator_init(&arc_reg, "lcx.lvl", RPMH_REGULATOR_TYPE_ARC);
if (rc) {
printk(BIOS_ERR, "Failed to initialize LPASS power rail lcx ARC regulator\n");
return CB_ERR;
}
/* Set LCX level to NOM_L1 */
rc = rpmh_regulator_arc_set_level(&arc_reg, RPMH_REGULATOR_LEVEL_NOM_L1, true, false);
if (rc) {
printk(BIOS_ERR, "Failed to set LCX ARC level\n");
return CB_ERR;
}
rc = rpmh_bcm_vote("LP0", BCM_LP0_VOTE_VALUE);
if (rc) {
printk(BIOS_ERR, "LPASS: Failed to send BCM vote for LPASS bus clock manager LP0\n");
return CB_ERR;
}
return CB_SUCCESS;
}
static void lpass_apply_clock_workarounds(void)
{
size_t i;
/* CR QCTDD08205470: ignore RPMh clock disable for TCU-QTB link clocks. */
for (i = 0; i < ARRAY_SIZE(lpass_rpmh_ignore_clks); i++)
clock_configure_ignore_rpmh_clk_dis(lpass_rpmh_ignore_clks[i].cbcr, true);
/* CR-3409636: keep AON NOC DDRSS SHUB clock enabled during sleep fencing. */
clock_configure_ignore_rpmh_clk_dis(&gcc->gcc_lpass_aon_noc_ddrss_shub_cbcr, true);
/* PMU-GCC spec: ignore PMU clock disable for these clocks. */
for (i = 0; i < ARRAY_SIZE(lpass_pmu_ignore_clks); i++)
clock_configure_ignore_pmu_clk_dis(lpass_pmu_ignore_clks[i].cbcr, true);
/* Prevent automatic GDSC collapse (HW defaults enable it). */
write32(&gcc->gcc_lpass_dsp_gdsc_sleep_ena_vote, 0x0);
}
static enum cb_err lpass_enable_boot_clocks(void)
{
size_t i;
enum cb_err ret;
/* Configure LPASS DDRSS SHUB RCG */
lpass_configure_ddrss_shub_rcg();
/* Enable QTB power domain */
if (enable_and_poll_gdsc_status(&gcc->gcc_lpass_qtb_gdscr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable QTB GDSC\n");
return CB_ERR;
}
/* Ensure IGNORE_RPMH_CLK_DIS is set before enabling TCU-QTB link clock. */
clock_configure_ignore_rpmh_clk_dis(&gcc->gcc_tcu_lpass_audio_qtb_cbcr, true);
for (i = 0; i < LPASS_BOOT_CLK_COUNT; i++) {
ret = clock_enable(lpass_boot_cbcr[i]);
if (ret != CB_SUCCESS)
printk(BIOS_WARNING, "LPASS: Failed to enable boot clock %zu: %p\n", i, lpass_boot_cbcr[i]);
}
return CB_SUCCESS;
}
static enum cb_err lpass_enable_ssc_smem_clock(void)
{
if (clock_enable(&lpass_ssc_scc->ssc_scc_smem_cbcr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable SSC_SCC_SMEM clock\n");
return CB_ERR;
}
return CB_SUCCESS;
}
static enum cb_err lpass_debug_bridge_setup(void)
{
if (clock_enable(&lpass_aon_cc->at_cbcr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable AT clock\n");
return CB_ERR;
}
if (clock_enable(&lpass_aon_cc->pclkdbg_cbcr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable PCLKDBG clock\n");
return CB_ERR;
}
/* Allow debug bridge clocks/paths to settle before requesting handshake. */
udelay(LPASS_NTS_HANDSHAKE_DELAY_US);
/*
* In order to attach debugger T32 APB, DAP and NTS bridges need to be enabled
*/
setbits32(&lpass_mcc_lpass_reg->atb_low_power_handshake, LPASS_LP_HANDSHAKE_REQUEST);
setbits32(&lpass_mcc_lpass_reg->apb_low_power_handshake, LPASS_LP_HANDSHAKE_REQUEST);
setbits32(&lpass_mcc_lpass_reg->nts_low_power_handshake, LPASS_LP_HANDSHAKE_REQUEST);
dsb();
/*
* Wait for NTS ACK
*/
if (!wait_us(LPASS_NTS_HANDSHAKE_TIMEOUT_US,
read32(&lpass_mcc_lpass_reg->nts_low_power_handshake) & LPASS_LP_HANDSHAKE_ACK)) {
printk(BIOS_WARNING, "LPASS: NTS handshake timeout (NTS=0x%x)\n",
read32(&lpass_mcc_lpass_reg->nts_low_power_handshake));
/* Non-fatal: continue boot even if debug bridge handshake doesn't complete */
}
return CB_SUCCESS;
}
/* Enable TCM blocks for LPASS processor memory access. */
static void lpass_tcm_init(void)
{
uint32_t block;
if (clock_enable(&lpass_lpi_tcm->axis_hs_cbcr) != CB_SUCCESS) {
printk(BIOS_WARNING, "LPASS: Failed to enable TCM AXIS HS clock\n");
return;
}
/* Initialize all TCM 256KB blocks (n=0..9) */
for (block = 0; block <= LPASS_TCM_MAX_BLOCKS; block++) {
clock_configure_force_mem_core_on(&lpass_lpi_tcm->tcm_256kb_block_cbcr[block], true);
if (clock_enable(&lpass_lpi_tcm->tcm_256kb_block_cbcr[block]) != CB_SUCCESS) {
printk(BIOS_WARNING, "LPASS: Failed to enable TCM block %d clock\n", block);
return;
}
}
}
static enum cb_err setup_lpass_processor(void)
{
/* HW_CTL settings */
clock_configure_hw_ctl(&gcc->gcc_ddrss_lpass_shub_cbcr, false);
/* Enable boot clocks */
if (lpass_enable_boot_clocks() != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable boot clocks\n");
return CB_ERR;
}
/* Apply clock workarounds */
lpass_apply_clock_workarounds();
/* HPG Step 4: Enable LPASS access */
if (clock_enable(&gcc->gcc_cfg_noc_lpass_cbcr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable CFG NOC access\n");
return CB_ERR;
}
/* HPG Step 11: Program LPASS_QDSP6SS_RET_CFG = 0x0 (CR QCTDD10415825) */
write32(&lpass_qdsp6ss->ret_cfg, 0);
/* HPG Step 12: Check NanoRCG and enable LPI_NOC_HS conditionally */
if ((read32(&lpass_lpicx_noc->sidebandmanager_rcg_sbm_flagoutstatus0_low) & LPASS_NANO_RCG_PORT2) == 0) {
if (clock_enable(&lpass_aon_cc->lpi_noc_hs_cbcr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable LPI NOC HS clock\n");
return CB_ERR;
}
} else {
if (clock_disable(&lpass_aon_cc->lpi_noc_hs_cbcr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to disable LPI NOC HS clock\n");
return CB_ERR;
}
}
/* HPG Step 13: Enable Q6 AXIM clock after NanoRCG-based LPI_NOC_HS handling */
if (clock_enable(&lpass_aon_cc->q6_axim_cbcr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable Q6 AXIM clock\n");
return CB_ERR;
}
/* Configure debug register */
write32(&lpass_qdsp6ss->dbg_cfg, lpass_q6_debug_val);
write32(&lpass_mcc_lpass_reg->rsc_wait_event_ovrd_mask, LPASS_RSC_WAIT_EVENT_MASK);
/* Initialize TCM */
lpass_tcm_init();
/* Enable Q6_AHBM clock for PRAM access */
if (clock_enable(&lpass_aon_cc->q6_ahbm_cbcr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable Q6_AHBM clock\n");
return CB_ERR;
}
/* Enable SSC_SCC_SMEM clock */
if (lpass_enable_ssc_smem_clock() != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable SSC_SCC_SMEM clock\n");
return CB_ERR;
}
/* Setup debug bridges if debug is enabled */
if (lpass_q6_debug_val != 0) {
if (lpass_debug_bridge_setup() != CB_SUCCESS)
printk(BIOS_WARNING, "LPASS: Debug bridge setup failed\n");
}
/* Enable QDSP6SS PLL */
if (lpass_qdsp6ss_pll_enable() != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable QDSP6SS PLL\n");
return CB_ERR;
}
/* CR QCTDD10442361: mask RSCp trigger and disable CHIP_CX QCHANNEL timeout SBM. */
/* HPG Step 24.e: Set CHIP_CX_RSCC_BYPASS_EN = 1 */
setbits32(&lpass_aon_cc->lpass_noc_island_isolation, CHIP_CX_RSCC_BYPASS_EN);
/* HPG Step 24.f: Set AON_NOC_STALL_MASK = 0 */
clrbits32(&lpass_aon_cc->lpass_noc_island_isolation, AON_NOC_STALL_MASK);
/* HPG Step 24.g: Set Port0 = 0 */
clrbits32(&lpass_lpicx_noc->sidebandmanager_chipcx_sbm_faultinen0_low,
CHIPCX_SBM_FAULTINEN0_PORT0);
clock_configure_hw_ctl(&gcc->gcc_lpass_aon_noc_ddrss_shub_cbcr, true);
printk(BIOS_INFO, "LPASS: Processor setup complete\n");
return CB_SUCCESS;
}
static enum cb_err enable_lpass_processor(void)
{
/* HPG Step 14: Q6 boot sequence */
/*
* De-assert QDSP6 stop core. QDSP6 will execute instructions after out of reset.
*/
setbits32(&lpass_qdsp6ss->boot_core_start, BOOT_CORE_START);
/*
* Trigger boot FSM to start QDSP6 out of reset sequence.
*/
write32(&lpass_qdsp6ss->boot_cmd, BOOT_FSM_START);
dsb();
/* Wait for boot FSM completion */
if (!wait_us(LPASS_BOOT_FSM_TIMEOUT_US, read32(&lpass_qdsp6ss->boot_status) != 0)) {
printk(BIOS_ERR, "LPASS: Boot FSM timeout (boot_status=0x%x)\n",
read32(&lpass_qdsp6ss->boot_status));
return CB_ERR;
}
/* Wait for core to come out of reset */
udelay(5);
/* HPG Step 19: Disable Q6_AXIM clock after Q6 boots */
if (clock_disable(&lpass_aon_cc->q6_axim_cbcr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to disable Q6_AXIM clock\n");
return CB_ERR;
}
printk(BIOS_INFO, "LPASS: Q6 processor enabled\n");
return CB_SUCCESS;
}
enum cb_err lpass_bring_up(void)
{
if (lpass_init() != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: lpass_init() failed\n");
return CB_ERR;
}
if (setup_lpass_processor() != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to setup LPASS processor\n");
return CB_ERR;
}
/* Disable BOOT IMEM */
write32((void *)TCSR_BOOT_IMEM_DISABLE, 0x1);
/* Boot the LPASS Q6 processor */
if (enable_lpass_processor() != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable LPASS processor\n");
return CB_ERR;
}
return CB_SUCCESS;
}
enum cb_err lpass_init(void)
{
if (lpass_rpmh_bcm_vote() != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to initialize RPMH BCM vote\n");
return CB_ERR;
}
if (enable_and_poll_gdsc_status(&lpass_aon_cc->lpass_audio_hm_gdscr) != CB_SUCCESS) {
printk(BIOS_ERR, "LPASS: Failed to enable Core HM GDSC\n");
return CB_ERR;