From a58f752d0f2dbc43a2f4b11ca8bd2f75327931d5 Mon Sep 17 00:00:00 2001 From: Hari L Date: Wed, 4 Mar 2026 21:50:27 +0530 Subject: [PATCH] soc/qualcomm/common: add CBCR disable and config helpers Add clock_disable() (clear CBCR EN and poll CLK_OFF). Add CBCR helper APIs and common bit definitions for HW_CTL, FORCE_MEM_CORE_ON, IGNORE_RPMH_CLK_DIS and IGNORE_PMU_CLK_DIS. BUG=None TEST=Built and booted image.serial.bin on Bluey Change-Id: I253414d01ec97aee45df1af0ed8cd06367351ef8 Signed-off-by: Hari L Reviewed-on: https://review.coreboot.org/c/coreboot/+/91546 Reviewed-by: Kapil Porwal Reviewed-by: Jayvik Desai Tested-by: build bot (Jenkins) Reviewed-by: Subrata Banik --- src/soc/qualcomm/common/clock.c | 84 +++++++++++++++++-- .../common/include/soc/clock_common.h | 22 ++++- 2 files changed, 97 insertions(+), 9 deletions(-) diff --git a/src/soc/qualcomm/common/clock.c b/src/soc/qualcomm/common/clock.c index ede523e298..2682721aa0 100644 --- a/src/soc/qualcomm/common/clock.c +++ b/src/soc/qualcomm/common/clock.c @@ -17,7 +17,7 @@ static bool clock_is_off(u32 *cbcr_addr) enum cb_err clock_enable_vote(void *cbcr_addr, void *vote_addr, uint32_t vote_bit) { - int count = 100; + int count = CLK_POLL_COUNT; setbits32(vote_addr, BIT(vote_bit)); @@ -34,7 +34,7 @@ enum cb_err clock_enable_vote(void *cbcr_addr, void *vote_addr, enum cb_err clock_enable(void *cbcr_addr) { - int count = 100; + int count = CLK_POLL_COUNT; /* Set clock enable bit */ setbits32(cbcr_addr, BIT(CLK_CTL_EN_SHFT)); @@ -50,6 +50,74 @@ enum cb_err clock_enable(void *cbcr_addr) return CB_ERR; } +enum cb_err clock_disable(void *cbcr_addr) +{ + int count = CLK_POLL_COUNT; + + if (!cbcr_addr) + return CB_ERR; + + /* Clear clock enable bit */ + clrbits32(cbcr_addr, BIT(CLK_CTL_EN_SHFT)); + + /* Ensure clock is disabled */ + while (count-- > 0) { + if (clock_is_off(cbcr_addr)) + return CB_SUCCESS; + udelay(1); + } + + printk(BIOS_ERR, "Failed to disable clock, register val: 0x%x\n", + read32(cbcr_addr)); + return CB_ERR; +} + +void clock_configure_ignore_rpmh_clk_dis(void *cbcr_addr, bool enable) +{ + if (!cbcr_addr) + return; + + if (enable) + setbits32(cbcr_addr, BIT(CLK_CTL_IGNORE_RPMH_CLK_DIS_SHFT)); + else + clrbits32(cbcr_addr, BIT(CLK_CTL_IGNORE_RPMH_CLK_DIS_SHFT)); +} + +void clock_configure_ignore_pmu_clk_dis(void *cbcr_addr, bool enable) +{ + if (!cbcr_addr) + return; + + if (enable) + setbits32(cbcr_addr, BIT(CLK_CTL_IGNORE_PMU_CLK_DIS_SHFT)); + else + clrbits32(cbcr_addr, BIT(CLK_CTL_IGNORE_PMU_CLK_DIS_SHFT)); +} + +void clock_configure_hw_ctl(void *cbcr_addr, bool enable) +{ + if (!cbcr_addr) + return; + + /* Enable or disable hardware-controlled clock gating */ + if (enable) + setbits32(cbcr_addr, BIT(CLK_CTL_HW_CTL_SHFT)); + else + clrbits32(cbcr_addr, BIT(CLK_CTL_HW_CTL_SHFT)); +} + +void clock_configure_force_mem_core_on(void *cbcr_addr, bool enable) +{ + if (!cbcr_addr) + return; + + /* Forces core-on signal to stay active during clk halt */ + if (enable) + setbits32(cbcr_addr, BIT(CLK_CTL_FORCE_MEM_CORE_ON_SHFT)); + else + clrbits32(cbcr_addr, BIT(CLK_CTL_FORCE_MEM_CORE_ON_SHFT)); +} + /* Clock Block Reset Operations */ void clock_reset_bcr(void *bcr_addr, bool assert) { @@ -77,7 +145,7 @@ enum cb_err enable_and_poll_gdsc_status(void *gdscr_addr) clrbits32(gdscr_addr, BIT(GDSC_ENABLE_BIT)); /* Ensure gdsc is enabled */ - if (!wait_us(100, (read32(gdscr_addr) & CLK_CTL_OFF_BMSK))) + if (!wait_us(CLK_WAIT_US_TIMEOUT, (read32(gdscr_addr) & CLK_CTL_OFF_BMSK))) return CB_ERR; return CB_SUCCESS; @@ -227,7 +295,7 @@ enum cb_err clock_configure_enable_gpll(struct alpha_pll_reg_val_config *cfg, setbits32(cfg->reg_apcs_pll_br_en, BIT(br_enable)); /* Wait for Lock Detection */ - if (!wait_us(100, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) { + if (!wait_us(CLK_WAIT_US_TIMEOUT, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) { printk(BIOS_ERR, "PLL did not lock!\n"); return CB_ERR; } @@ -247,7 +315,7 @@ enum cb_err agera_pll_enable(struct alpha_pll_reg_val_config *cfg) udelay(5); setbits32(cfg->reg_mode, BIT(PLL_RESET_SHFT)); - if (!wait_us(100, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) { + if (!wait_us(CLK_WAIT_US_TIMEOUT, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) { printk(BIOS_ERR, "CPU PLL did not lock!\n"); return CB_ERR; } @@ -269,7 +337,7 @@ enum cb_err zonda_pll_enable(struct alpha_pll_reg_val_config *cfg) setbits32(cfg->reg_mode, BIT(PLL_RESET_SHFT)); setbits32(cfg->reg_opmode, PLL_RUN_MODE); - if (!wait_us(100, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) { + if (!wait_us(CLK_WAIT_US_TIMEOUT, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) { printk(BIOS_ERR, "CPU PLL did not lock!\n"); return CB_ERR; } @@ -292,7 +360,7 @@ enum cb_err zondaole_pll_enable(struct alpha_pll_reg_val_config *cfg) setbits32(cfg->reg_mode, BIT(PLL_RESET_SHFT)); setbits32(cfg->reg_opmode, PLL_RUN_MODE); - if (!wait_us(100, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) { + if (!wait_us(CLK_WAIT_US_TIMEOUT, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) { printk(BIOS_ERR, "CPU PLL did not lock!\n"); return CB_ERR; } @@ -312,7 +380,7 @@ enum cb_err lucidole_pll_enable(struct alpha_pll_reg_val_config *cfg) setbits32(cfg->reg_opmode, PLL_RUN_MODE); setbits32(cfg->reg_mode, BIT(PLL_RESET_SHFT)); - if (!wait_us(100, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) { + if (!wait_us(CLK_WAIT_US_TIMEOUT, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) { printk(BIOS_ERR, "CPU PLL did not lock!\n"); return CB_ERR; } diff --git a/src/soc/qualcomm/common/include/soc/clock_common.h b/src/soc/qualcomm/common/include/soc/clock_common.h index fd3a073d01..20e01b83bc 100644 --- a/src/soc/qualcomm/common/include/soc/clock_common.h +++ b/src/soc/qualcomm/common/include/soc/clock_common.h @@ -4,6 +4,8 @@ #define __SOC_QUALCOMM_COMMON_CLOCK_H__ #define QCOM_CLOCK_DIV(div) (2 * div - 1) +#define CLK_POLL_COUNT 100 +#define CLK_WAIT_US_TIMEOUT 100 /* Root Clock Generator */ struct clock_rcg { @@ -124,11 +126,19 @@ enum clk_ctl_cmd_rcgr { enum clk_ctl_cbcr { CLK_CTL_EN_SHFT = 0, + CLK_CTL_HW_CTL_SHFT = 1, CLK_CTL_ARES_SHFT = 2, + CLK_CTL_FORCE_MEM_CORE_ON_SHFT = 14, + CLK_CTL_IGNORE_RPMH_CLK_DIS_SHFT = 20, + CLK_CTL_IGNORE_PMU_CLK_DIS_SHFT = 21, CLK_CTL_OFF_SHFT = 31, CLK_CTL_EN_BMSK = 0x1, + CLK_CTL_HW_CTL_BMSK = 0x1 << CLK_CTL_HW_CTL_SHFT, CLK_CTL_ARES_BMSK = 0x1 << CLK_CTL_ARES_SHFT, - CLK_CTL_OFF_BMSK = 0x80000000, + CLK_CTL_FORCE_MEM_CORE_ON_BMSK = 0x1 << CLK_CTL_FORCE_MEM_CORE_ON_SHFT, + CLK_CTL_IGNORE_RPMH_CLK_DIS_BMSK = 0x1 << CLK_CTL_IGNORE_RPMH_CLK_DIS_SHFT, + CLK_CTL_IGNORE_PMU_CLK_DIS_BMSK = 0x1 << CLK_CTL_IGNORE_PMU_CLK_DIS_SHFT, + CLK_CTL_OFF_BMSK = 0x1 << CLK_CTL_OFF_SHFT, }; enum clk_ctl_rcg_mnd { @@ -155,6 +165,16 @@ enum cb_err clock_enable_vote(void *cbcr_addr, void *vote_addr, enum cb_err clock_enable(void *cbcr_addr); +enum cb_err clock_disable(void *cbcr_addr); + +void clock_configure_ignore_rpmh_clk_dis(void *cbcr_addr, bool enable); + +void clock_configure_ignore_pmu_clk_dis(void *cbcr_addr, bool enable); + +void clock_configure_hw_ctl(void *cbcr_addr, bool enable); + +void clock_configure_force_mem_core_on(void *cbcr_addr, bool enable); + enum cb_err enable_and_poll_gdsc_status(void *gdscr_addr); void clock_reset_bcr(void *bcr_addr, bool assert);