Attention is currently required from: Taniya Das. Hello Taniya Das,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/50580
to review the following change.
Change subject: sc7280: clk: Add clock driver in coreboot ......................................................................
sc7280: clk: Add clock driver in coreboot
Add support for clock driver on SC7280.
Change-Id: I590a93cda0d6eccb51b54692b620d43ccacede77 Signed-off-by: Taniya Das tdas@codeaurora.org --- M src/soc/qualcomm/sc7280/bootblock.c A src/soc/qualcomm/sc7280/clock.c M src/soc/qualcomm/sc7280/include/soc/addressmap.h A src/soc/qualcomm/sc7280/include/soc/clock.h 4 files changed, 863 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/80/50580/1
diff --git a/src/soc/qualcomm/sc7280/bootblock.c b/src/soc/qualcomm/sc7280/bootblock.c index 807bb25..0d7c5d1 100644 --- a/src/soc/qualcomm/sc7280/bootblock.c +++ b/src/soc/qualcomm/sc7280/bootblock.c @@ -1,9 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0-only */
#include <bootblock_common.h> +#include <soc/clock.h> #include <soc/mmu.h>
void bootblock_soc_init(void) { + clock_init(); sc7280_mmu_init(); } diff --git a/src/soc/qualcomm/sc7280/clock.c b/src/soc/qualcomm/sc7280/clock.c new file mode 100644 index 0000000..8ee096a --- /dev/null +++ b/src/soc/qualcomm/sc7280/clock.c @@ -0,0 +1,468 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <assert.h> +#include <commonlib/helpers.h> +#include <delay.h> +#include <device/mmio.h> +#include <soc/clock.h> +#include <timer.h> +#include <types.h> + +struct clock_config qspi_core_cfg[] = { + { + .hz = SRC_XO_HZ, /* 19.2KHz */ + .src = SRC_XO_19_2MHZ, + .div = DIV(1), + }, + { + .hz = 100 * MHz, + .src = SRC_GPLL0_MAIN_600MHZ, + .div = DIV(6), + }, + { + .hz = 150 * MHz, + .src = SRC_GPLL0_MAIN_600MHZ, + .div = DIV(4), + }, + { + .hz = 200 * MHz, + .src = SRC_GPLL0_MAIN_600MHZ, + .div = DIV(3), + }, + { + .hz = 400 * MHz, + .src = SRC_GPLL0_MAIN_600MHZ, + .div = DIV(1.5), + }, +}; + +struct clock_config qupv3_wrap[] = { + { + .hz = SRC_XO_HZ, /* 19.2KHz */ + .src = SRC_XO_19_2MHZ, + .div = DIV(1), + }, + { + .hz = 32 * MHz, + .src = SRC_GPLL0_EVEN_300MHZ, + .div = DIV(1), + .m = 8, + .n = 75, + .d_2 = 75, + }, + { + .hz = 48 * MHz, + .src = SRC_GPLL0_EVEN_300MHZ, + .div = DIV(1), + .m = 4, + .n = 25, + .d_2 = 25, + }, + { + .hz = 64 * MHz, + .src = SRC_GPLL0_EVEN_300MHZ, + .div = DIV(1), + .m = 16, + .n = 75, + .d_2 = 75, + }, + { + .hz = 96 * MHz, + .src = SRC_GPLL0_EVEN_300MHZ, + .div = DIV(1), + .m = 8, + .n = 25, + .d_2 = 25, + }, + { + .hz = 100 * MHz, + .src = SRC_GPLL0_MAIN_600MHZ, + .div = DIV(6), + }, + { + .hz = SRC_XO_HZ, /* 19.2KHz */ + .src = SRC_XO_19_2MHZ, + .div = DIV(1), + }, + { + .hz = SRC_XO_HZ, /* 19.2KHz */ + .src = SRC_XO_19_2MHZ, + .div = DIV(1), + }, +}; + +struct clock_config sdcc1_core_cfg[] = { + { + .hz = 100 * MHz, + .src = SRC_GPLL0_EVEN_300MHZ, + .div = DIV(3), + }, + { + .hz = 192 * MHz, + .src = SRC_GPLL10_MAIN_384MHZ, + .div = DIV(2), + }, + { + .hz = 384 * MHz, + .src = SRC_GPLL10_MAIN_384MHZ, + .div = DIV(1), + }, +}; + +struct clock_config sdcc2_core_cfg[] = { + { + .hz = 50 * MHz, + .src = SRC_GPLL0_EVEN_300MHZ, + .div = DIV(6), + }, + { + .hz = 202 * MHz, + .src = SRC_GPLL9_MAIN_808MHZ, + .div = DIV(4), + }, +}; + +static int clock_configure_gpll0(void) +{ + /* Keep existing GPLL0 configuration, in RUN mode @600Mhz. */ + setbits32(&gcc->gpll0.user_ctl, + 1 << PLL_PLLOUT_EVEN_SHFT | + 1 << PLL_PLLOUT_MAIN_SHFT | + 1 << PLL_PLLOUT_ODD_SHFT); + + return CB_SUCCESS; +} + +static int clock_configure_gpll(struct sc7280_gpll *gpll, int pll_l_val, + int pll_alpha_val, int br_enable) +{ + setbits32(&gpll->l_val, pll_l_val); + setbits32(&gpll->cal_l_val, PLL_CAL_L_VAL); + setbits32(&gpll->alpha_val, pll_alpha_val); + setbits32(&gpll->mode, BIT(PLL_FSM_EN_SHFT)); + setbits32(&gpll->opmode, BIT(PLL_OPMODE_STANDBY)); + udelay(1); + setbits32(&gpll->mode, BIT(PLL_RESET_N_SHFT)); + udelay(10); + + setbits32(&gcc->apcs_pll_br_en, BIT(br_enable)); + + if (!wait_us(100, read32(&gpll->mode) & PLL_LOCK_DET_BMSK)) { + printk(BIOS_ERR, "ERROR: PLL did not lock!\n"); + return CB_ERR; + } + + return CB_SUCCESS; +} + +static int clock_configure_mnd(struct sc7280_clock *clk, uint32_t m, uint32_t n, + uint32_t d_2) +{ + struct sc7280_mnd_clock *mnd = (struct sc7280_mnd_clock *)clk; + + setbits32(&clk->rcg_cfg, + RCG_MODE_DUAL_EDGE << CLK_CTL_CFG_MODE_SHFT); + + write32(&mnd->m, m & CLK_CTL_RCG_MND_BMSK); + write32(&mnd->n, ~(n-m) & CLK_CTL_RCG_MND_BMSK); + write32(&mnd->d_2, ~(d_2) & CLK_CTL_RCG_MND_BMSK); + + return CB_SUCCESS; +} + +static int clock_configure(struct sc7280_clock *clk, + struct clock_config *clk_cfg, + uint32_t hz, uint32_t num_perfs) +{ + uint32_t reg_val, idx; + + for (idx = 0; idx < num_perfs; idx++) + if (hz <= clk_cfg[idx].hz) + break; + + assert(hz == clk_cfg[idx].hz); + + reg_val = (clk_cfg[idx].src << CLK_CTL_CFG_SRC_SEL_SHFT) | + (clk_cfg[idx].div << CLK_CTL_CFG_SRC_DIV_SHFT); + + /* Set clock config */ + write32(&clk->rcg_cfg, reg_val); + + if (clk_cfg[idx].m != 0) + clock_configure_mnd(clk, clk_cfg[idx].m, clk_cfg[idx].n, + clk_cfg[idx].d_2); + + /* Commit config to RCG*/ + setbits32(&clk->rcg_cmd, BIT(CLK_CTL_CMD_UPDATE_SHFT)); + + return CB_SUCCESS; +} + +static bool clock_is_off(u32 *cbcr_addr) +{ + return (read32(cbcr_addr) & CLK_CTL_OFF_BMSK); +} + +static int clock_enable_vote(void *cbcr_addr, void *vote_addr, + uint32_t vote_bit) +{ + /* Set clock vote bit */ + setbits32(vote_addr, BIT(vote_bit)); + + /* Ensure clock is enabled */ + if (!wait_us(100, clock_is_off(cbcr_addr))) + return CB_ERR; + + return CB_SUCCESS; +} + +static int clock_enable(void *cbcr_addr) +{ + /* Set clock enable bit */ + setbits32(cbcr_addr, BIT(CLK_CTL_EN_SHFT)); + + /* Ensure clock is enabled */ + if (!wait_us(100, clock_is_off(cbcr_addr))) + return CB_ERR; + + return CB_SUCCESS; +} + +void clock_reset_aop(void) +{ + /* Bring AOP out of RESET */ + clrbits32(&aoss->aoss_cc_apcs_misc, BIT(AOP_RESET_SHFT)); +} + +void clock_reset_shrm(void) +{ + /* Bring SHRM out of RESET */ + clrbits32(&shrm->shrm_sproc_ctrl, BIT(SHRM_RUN_STALL)); +} + +void clock_configure_qspi(uint32_t hz) +{ + clock_configure(&gcc->qspi_core, + qspi_core_cfg, hz, + ARRAY_SIZE(qspi_core_cfg)); + clock_enable(&gcc->qspi_cnoc_ahb_cbcr); + clock_enable(&gcc->qspi_core_cbcr); +} + +int clock_reset_bcr(void *bcr_addr, bool assert) +{ + struct sc7280_bcr *bcr = bcr_addr; + + if (assert) + setbits32(bcr, BIT(CLK_CTL_BCR_BLK_SHFT)); + else + clrbits32(bcr, BIT(CLK_CTL_BCR_BLK_SHFT)); + + return CB_SUCCESS; +} + +void clock_configure_dfsr(int qup) +{ + struct sc7280_qupv3_clock *qup_clk; + int idx, s = qup % QUP_WRAP1_S0; + uint32_t reg_val; + + qup_clk = qup < QUP_WRAP1_S0 ? + &gcc->qup_wrap0_s[s] : &gcc->qup_wrap1_s[s]; + + clrsetbits32(&qup_clk->dfsr_clk.cmd_dfsr, + BIT(CLK_CTL_CMD_RCG_SW_CTL_SHFT), + BIT(CLK_CTL_CMD_DFSR_SHFT)); + + for (idx = 0; idx < ARRAY_SIZE(qupv3_wrap); idx++) { + reg_val = (qupv3_wrap[idx].src << CLK_CTL_CFG_SRC_SEL_SHFT) | + (qupv3_wrap[idx].div << CLK_CTL_CFG_SRC_DIV_SHFT); + + write32(&qup_clk->dfsr_clk.perf_dfsr[idx], reg_val); + + if (qupv3_wrap[idx].m == 0) + continue; + + setbits32(&qup_clk->dfsr_clk.perf_dfsr[idx], + RCG_MODE_DUAL_EDGE << CLK_CTL_CFG_MODE_SHFT); + + reg_val = qupv3_wrap[idx].m & CLK_CTL_RCG_MND_BMSK; + write32(&qup_clk->dfsr_clk.perf_m_dfsr[idx], reg_val); + + reg_val = ~(qupv3_wrap[idx].n - qupv3_wrap[idx].m) + & CLK_CTL_RCG_MND_BMSK; + write32(&qup_clk->dfsr_clk.perf_n_dfsr[idx], reg_val); + + reg_val = ~(qupv3_wrap[idx].d_2) & CLK_CTL_RCG_MND_BMSK; + write32(&qup_clk->dfsr_clk.perf_d_dfsr[idx], reg_val); + } +} + +void clock_enable_qup(int qup) +{ + struct sc7280_qupv3_clock *qup_clk; + int s = qup % QUP_WRAP1_S0, clk_en_off; + + qup_clk = qup < QUP_WRAP1_S0 ? + &gcc->qup_wrap0_s[s] : &gcc->qup_wrap1_s[s]; + + if(qup < QUP_WRAP1_S6) { + clk_en_off = qup < QUP_WRAP1_S0 ? + QUPV3_WRAP0_CLK_ENA_S(s) : QUPV3_WRAP1_CLK_ENA_S(s); + clock_enable_vote(&qup_clk->mnd_clk, &gcc->apcs_clk_br_en1, + clk_en_off); + } + else { + clk_en_off = QUPV3_WRAP1_CLK_ENA_1_S(s); + clock_enable_vote(&qup_clk->mnd_clk, &gcc->apcs_clk_br_en, + clk_en_off); + } +} + +static int sdcc_clock_configure(struct sc7280_sdcc_clock *clk, + struct clock_config *clk_cfg, + uint32_t hz, uint32_t num_perfs) +{ + uint32_t reg_val; + uint32_t idx; + + for (idx = 0; idx < num_perfs; idx++) + if (hz <= clk_cfg[idx].hz) + break; + + assert(hz == clk_cfg[idx].hz); + + reg_val = (clk_cfg[idx].src << CLK_CTL_CFG_SRC_SEL_SHFT) | + (clk_cfg[idx].div << CLK_CTL_CFG_SRC_DIV_SHFT); + + /* Set clock config */ + write32(&clk->rcg_cfg, reg_val); + + if (clk_cfg[idx].m != 0) { + setbits32(&clk->rcg_cfg, + RCG_MODE_DUAL_EDGE << CLK_CTL_CFG_MODE_SHFT); + + write32(&clk->m, clk_cfg[idx].m & CLK_CTL_RCG_MND_BMSK); + write32(&clk->n, ~(clk_cfg[idx].n - clk_cfg[idx].m) & CLK_CTL_RCG_MND_BMSK); + write32(&clk->d_2, ~(clk_cfg[idx].d_2) & CLK_CTL_RCG_MND_BMSK); + } + + /* Commit config to RCG*/ + setbits32(&clk->rcg_cmd, BIT(CLK_CTL_CMD_UPDATE_SHFT)); + + return CB_SUCCESS; +} + +void clock_configure_sdcc(int sdcc, uint32_t hz) +{ + if(sdcc == SDCC1_CLK) { + if(hz > SDCC_CLK_100MHZ) + clock_configure_gpll(&gcc->gpll10, PLL10_L_VAL, + PLL10_ALPHA_VAL, PLL10_BRANCH_ENA_SHFT); + + sdcc_clock_configure(&gcc->sdcc1, sdcc1_core_cfg, hz, + ARRAY_SIZE(sdcc1_core_cfg)); + clock_enable(&gcc->sdcc1_ahb_cbcr); + clock_enable(&gcc->sdcc1_apps_cbcr); + } + else if(sdcc == SDCC2_CLK) { + if(hz > SDCC_CLK_100MHZ) + clock_configure_gpll(&gcc->gpll9, PLL9_L_VAL, + PLL9_ALPHA_VAL, PLL9_BRANCH_ENA_SHFT); + + sdcc_clock_configure(&gcc->sdcc2, sdcc2_core_cfg, hz, + ARRAY_SIZE(sdcc2_core_cfg)); + clock_enable(&gcc->sdcc2_ahb_cbcr); + clock_enable(&gcc->sdcc2_apps_cbcr); + } +} + +static int pll_init_and_set(struct sc7180_apss_clock *apss, u32 l_val) +{ + u32 gfmux_val, ret = 0; + + /* Configure PLL */ + write32(&apss->pll.l_val, l_val); + clrbits32(&apss->pll.config_ctl_lo, 0x2 << K_P_SHFT | + 0x2 << K_I_SHFT); + clrsetbits32(&apss->pll.config_ctl_hi, 0x4 << KLSB_SHFT, + BIT(KLSB_SHFT) | BIT(RON_MODE_SHFT)); + clrsetbits32(&apss->pll.config_ctl_u1, BIT(DCO_BIAS_ADJ_SHFT), + BIT(FAST_LOCK_LOW_L_SHFT)); + + clrbits32(&apss->pll.mode, BIT(PLL_BYPASSNL_SHFT)); + ret |= read32(&apss->pll.mode) & PLL_BYPASSNL_BMSK; + + /* Disable PLL output */ + clrbits32(&apss->pll.mode, BIT(PLL_OUTCTRL_SHFT)); + ret |= read32(&apss->pll.mode) & PLL_OUTCTRL_BMSK; + + /* Place the PLL in STANDBY mode */ + setbits32(&apss->pll.opmode, PLL_STANDBY_MODE); + ret |= read32(&apss->pll.opmode); + if(ret) + return CB_ERR; + + /* Enable PLL */ + setbits32(&apss->pll.mode, BIT(PLL_BYPASSNL_SHFT)); + udelay(1); + setbits32(&apss->pll.mode, BIT(PLL_RESET_SHFT)); + setbits32(&apss->pll.opmode, PLL_RUN_MODE); + + if (!wait_us(100, read32(&apss->pll.mode) & PLL_LOCK_DET_BMSK)) { + printk(BIOS_ERR, "ERROR: PLL did not lock!\n"); + return CB_ERR; + } + + setbits32(&apss->pll.mode, BIT(PLL_OUTCTRL_SHFT)); + + gfmux_val = read32(&apss->cfg_gfmux) & ~GFMUX_SRC_SEL_BMSK; + gfmux_val |= APCS_SRC_EARLY; + write32(&apss->cfg_gfmux, gfmux_val); + + return CB_SUCCESS; +} + +static void speed_up_boot_cpu(void) +{ + /* 1516.8 MHz */ + if (!pll_init_and_set(apss_silver, L_VAL_1516P8MHz)) + printk(BIOS_DEBUG, "Silver Frequency bumped to 1.5168(GHz)\n"); + + /* 1190.4 MHz */ + if (!pll_init_and_set(apss_l3, L_VAL_1190P4MHz)) + printk(BIOS_DEBUG, "L3 Frequency bumped to 1.1904(GHz)\n"); +} + +void clock_init(void) +{ + clock_configure_gpll0(); + + clock_enable_vote(&gcc->qup_wrap0_core_2x_cbcr, + &gcc->apcs_clk_br_en1, + QUPV3_WRAP0_CORE_2X_CLK_ENA); + clock_enable_vote(&gcc->qup_wrap0_core_cbcr, + &gcc->apcs_clk_br_en1, + QUPV3_WRAP0_CORE_CLK_ENA); + clock_enable_vote(&gcc->qup_wrap0_m_ahb_cbcr, + &gcc->apcs_clk_br_en1, + QUPV3_WRAP_0_M_AHB_CLK_ENA); + clock_enable_vote(&gcc->qup_wrap0_s_ahb_cbcr, + &gcc->apcs_clk_br_en1, + QUPV3_WRAP_0_S_AHB_CLK_ENA); + + clock_enable_vote(&gcc->qup_wrap1_core_2x_cbcr, + &gcc->apcs_clk_br_en1, + QUPV3_WRAP1_CORE_2X_CLK_ENA); + clock_enable_vote(&gcc->qup_wrap1_core_cbcr, + &gcc->apcs_clk_br_en1, + QUPV3_WRAP1_CORE_CLK_ENA); + clock_enable_vote(&gcc->qup_wrap1_m_ahb_cbcr, + &gcc->apcs_clk_br_en1, + QUPV3_WRAP_1_M_AHB_CLK_ENA); + clock_enable_vote(&gcc->qup_wrap1_s_ahb_cbcr, + &gcc->apcs_clk_br_en1, + QUPV3_WRAP_1_S_AHB_CLK_ENA); + + speed_up_boot_cpu(); +} diff --git a/src/soc/qualcomm/sc7280/include/soc/addressmap.h b/src/soc/qualcomm/sc7280/include/soc/addressmap.h index 70d17be..cf95fc1 100644 --- a/src/soc/qualcomm/sc7280/include/soc/addressmap.h +++ b/src/soc/qualcomm/sc7280/include/soc/addressmap.h @@ -5,4 +5,37 @@
#include <stdint.h>
+#define AOSS_CC_BASE 0x0C2A0000 +#define GCC_BASE 0x00100000 +#define QSPI_BASE 0x088DC000 +#define SHRM_SPROC_BASE 0x09051000 +#define SILVER_PLL_BASE 0x18280000 +#define L3_PLL_BASE 0x18284000 +#define TLMM_TILE_BASE 0x0F100000 + +/* + * QUP SERIAL ENGINE BASE ADDRESSES + */ +/* QUPV3_0 */ +#define QUP_SERIAL0_BASE 0x00980000 +#define QUP_SERIAL1_BASE 0x00984000 +#define QUP_SERIAL2_BASE 0x00988000 +#define QUP_SERIAL3_BASE 0x0098C000 +#define QUP_SERIAL4_BASE 0x00990000 +#define QUP_SERIAL5_BASE 0x00994000 +#define QUP_SERIAL6_BASE 0x00998000 +#define QUP_SERIAL7_BASE 0x0099C000 +#define QUP_WRAP0_BASE 0x009C0000 + +/* QUPV3_1 */ +#define QUP_SERIAL8_BASE 0x00A80000 +#define QUP_SERIAL9_BASE 0x00A84000 +#define QUP_SERIAL10_BASE 0x00A88000 +#define QUP_SERIAL11_BASE 0x00A8C000 +#define QUP_SERIAL12_BASE 0x00A90000 +#define QUP_SERIAL13_BASE 0x00A94000 +#define QUP_SERIAL14_BASE 0x00A98000 +#define QUP_SERIAL15_BASE 0x00A9C000 +#define QUP_WRAP1_BASE 0x00AC0000 + #endif /* __SOC_QUALCOMM_SC7280_ADDRESS_MAP_H__ */ diff --git a/src/soc/qualcomm/sc7280/include/soc/clock.h b/src/soc/qualcomm/sc7280/include/soc/clock.h new file mode 100644 index 0000000..4907930 --- /dev/null +++ b/src/soc/qualcomm/sc7280/include/soc/clock.h @@ -0,0 +1,360 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <soc/addressmap.h> +#include <types.h> + +#ifndef __SOC_QUALCOMM_SC7280_CLOCK_H__ +#define __SOC_QUALCOMM_SC7280_CLOCK_H__ + +#define SRC_XO_HZ (19200 * KHz) +#define GPLL0_EVEN_HZ (300 * MHz) +#define GPLL0_MAIN_HZ (600 * MHz) + +#define SRC_XO_19_2MHZ 0 +#define SRC_GPLL0_MAIN_600MHZ 1 +#define SRC_GPLL9_MAIN_808MHZ 2 +#define SRC_GPLL10_MAIN_384MHZ 5 +#define SRC_GPLL0_EVEN_300MHZ 6 + +#define PLL9_L_VAL 0x0000002A +#define PLL9_ALPHA_VAL 0x00001555 +#define PLL10_ALPHA_VAL 0x0 +#define PLL10_L_VAL 0x00000014 +#define PLL_CAL_L_VAL 0x00000044 +#define PLL_OPMODE_STANDBY 0x0 + +#define PLL9_BRANCH_ENA_SHFT 8 +#define PLL10_BRANCH_ENA_SHFT 9 + +#define GDSC_ENABLE_BIT 0 + +#define QUPV3_WRAP_0_M_AHB_CLK_ENA 6 +#define QUPV3_WRAP_0_S_AHB_CLK_ENA 7 +#define QUPV3_WRAP0_CORE_2X_CLK_ENA 9 +#define QUPV3_WRAP0_CORE_CLK_ENA 8 +#define QUPV3_WRAP1_CORE_2X_CLK_ENA 18 +#define QUPV3_WRAP1_CORE_CLK_ENA 19 +#define QUPV3_WRAP_1_M_AHB_CLK_ENA 20 +#define QUPV3_WRAP_1_S_AHB_CLK_ENA 21 +#define QUPV3_WRAP0_CLK_ENA_S(idx) (10 + idx) +#define QUPV3_WRAP1_CLK_ENA_S(idx) (22 + idx) +#define QUPV3_WRAP1_CLK_ENA_1_S(idx) (7 + idx) + +#define AOP_RESET_SHFT 0 +#define SHRM_RUN_STALL 0 +#define RCG_MODE_DUAL_EDGE 2 + +#define SDCC1_CLK 1 +#define SDCC2_CLK 2 +#define SDCC_CLK_100MHZ (100 * MHz) + +/* CPU PLL */ +#define L_VAL_1516P8MHz 0x4F +#define L_VAL_1190P4MHz 0x3E + +#define DIV(div) (2 * div - 1) + +struct sc7280_clock { + u32 rcg_cmd; + u32 rcg_cfg; +}; + +struct sc7280_mnd_clock { + struct sc7280_clock clock; + u32 m; + u32 n; + u32 d_2; +}; + +struct sc7280_dfsr_clock { + u32 cmd_dfsr; + u8 _res0[0x20 - 0x1c]; + u32 perf_dfsr[8]; + u8 _res1[0x60 - 0x40]; + u32 perf_m_dfsr[8]; + u8 _res2[0xa0 - 0x80]; + u32 perf_n_dfsr[8]; + u8 _res3[0xe0 - 0xc0]; + u32 perf_d_dfsr[8]; + u8 _res4[0x130 - 0x100]; +}; + +struct sc7280_qupv3_clock { + u32 cbcr; + struct sc7280_mnd_clock mnd_clk; + struct sc7280_dfsr_clock dfsr_clk; +}; + +struct sc7280_gpll { + u32 mode; + u32 l_val; + u32 cal_l_val; + u32 user_ctl; + u32 user_ctl_u; + u32 user_ctl_u1; + u32 config_ctl; + u32 config_ctl_u; + u32 config_ctl_u1; + u32 test_ctl; + u32 test_ctl_u; + u32 test_ctl_u1; + u8 _res0[0x38 - 0x30]; + u32 opmode; + u8 _res1[0x40 - 0x3c]; + u32 alpha_val; +}; + +struct sc7280_sdcc_clock { + u32 rcg_cmd; + u32 rcg_cfg; + u32 m; + u32 n; + u32 d_2; +}; + +struct sc7280_gcc { + struct sc7280_gpll gpll0; + u8 _res0[0xf000 - 0x44]; + u32 usb30_prim_bcr; + u8 _res1[0x12000 - 0xf004]; + u32 qusb2phy_prim_bcr; + u32 qusb2phy_sec_bcr; + u8 _res2[0x14004 - 0x12008]; + u32 sdcc2_apps_cbcr; + u32 sdcc2_ahb_cbcr; + struct sc7280_sdcc_clock sdcc2; + u8 _res3[0x16004 - 0x14020]; + u32 sdcc4_apps_cbcr; + u32 sdcc4_ahb_cbcr; + struct sc7280_sdcc_clock sdcc4; + u8 _res4[0x17000 - 0x16020]; + u32 qup_wrap0_bcr; + u32 qup_wrap0_m_ahb_cbcr; + u32 qup_wrap0_s_ahb_cbcr; + struct sc7280_qupv3_clock qup_wrap0_s[8]; + u8 _res5[0x18000 - 0x1798c]; + u32 qup_wrap1_bcr; + u32 qup_wrap1_m_ahb_cbcr; + u32 qup_wrap1_s_ahb_cbcr; + struct sc7280_qupv3_clock qup_wrap1_s[8]; + u8 _res6[0x1c000 - 0x1898c]; + struct sc7280_gpll gpll9; + u8 _res7[0x1e000 - 0x1c044]; + struct sc7280_gpll gpll10; + u8 _res8[0x23000 - 0x1e044]; + u32 qup_wrap0_core_cbcr; + u32 qup_wrap0_core_cdivr; + u32 qup_wrap0_core_2x_cbcr; + struct sc7280_clock qup_wrap0_core_2x; + u8 _res9[0x23138 - 0x23014]; + u32 qup_wrap1_core_cbcr; + u32 qup_wrap1_core_cdivr; + u32 qup_wrap1_core_2x_cbcr; + struct sc7280_clock qup_wrap1_core_2x; + u8 _res10[0x4b000 - 0x2314c]; + u32 qspi_bcr; + u32 qspi_cnoc_ahb_cbcr; + u32 qspi_core_cbcr; + struct sc7280_clock qspi_core; + u8 _res11[0x50000 - 0x4b014]; + u32 usb3_phy_prim_bcr; + u32 usb3phy_phy_prim_bcr; + u32 usb3_dp_phy_prim_bcr; + u8 _res12[0x52000 - 0x5000c]; + u32 apcs_clk_br_en; + u8 _res13[0x52008 - 0x52004]; + u32 apcs_clk_br_en1; + u8 _res14[0x52010 - 0x5200c]; + u32 apcs_pll_br_en; + u8 _res15[0x6a000 - 0x52014]; + u32 usb_phy_cfg_ahb2phy_bcr; + u8 _res17[0x75004 - 0x6a004]; + u32 sdcc1_ahb_cbcr; + u32 sdcc1_apps_cbcr; + struct sc7280_sdcc_clock sdcc1; + u8 _res18[0x9e000 - 0x75020]; + u32 usb30_sec_bcr; + u8 _res22[0x1000000 - 0x90014]; +}; +check_member(sc7280_gcc, qusb2phy_prim_bcr, 0x12000); +check_member(sc7280_gcc, sdcc2_apps_cbcr, 0x14004); +check_member(sc7280_gcc, sdcc4_apps_cbcr, 0x16004); +check_member(sc7280_gcc, qup_wrap0_bcr, 0x17000); +check_member(sc7280_gcc, qup_wrap1_bcr, 0x18000); +check_member(sc7280_gcc, qup_wrap1_core_cbcr, 0x23138); +check_member(sc7280_gcc, qspi_bcr, 0x4b000); +check_member(sc7280_gcc, usb3_phy_prim_bcr, 0x50000); +check_member(sc7280_gcc, apcs_clk_br_en1, 0x52008); +check_member(sc7280_gcc, apcs_pll_br_en, 0x52010); +check_member(sc7280_gcc, usb_phy_cfg_ahb2phy_bcr, 0x6a000); +check_member(sc7280_gcc, sdcc1_ahb_cbcr, 0x75004); +check_member(sc7280_gcc, usb30_sec_bcr, 0x9e000); + +struct sc7280_aoss { + u8 _res0[0x50020]; + u32 aoss_cc_reset_status; + u8 _res1[0x5002C - 0x50024]; + u32 aoss_cc_apcs_misc; +}; +check_member(sc7280_aoss, aoss_cc_reset_status, 0x50020); +check_member(sc7280_aoss, aoss_cc_apcs_misc, 0x5002C); + +struct sc7180_apss_pll { + u32 mode; + u32 l_val; + u32 alpha_val; + u32 user_ctl; + u32 config_ctl_lo; + u32 config_ctl_hi; + u32 config_ctl_u1; + u32 test_ctl_lo; + u32 test_ctl_hi; + u32 test_ctl_u1; + u32 opmode; + u8 _res0[0x38 - 0x2c]; + u32 status; +}; + +struct sc7180_apss_clock { + struct sc7180_apss_pll pll; + u8 _res0[0x84 - 0x3c]; + u32 cfg_gfmux; +}; + +struct clock_config { + uint32_t hz; + uint8_t src; + uint8_t div; + uint16_t m; + uint16_t n; + uint16_t d_2; +}; + +struct sc7280_shrm { + u32 shrm_sproc_ctrl; +}; + +enum clk_ctl_gpll_user_ctl { + PLL_PLLOUT_EVEN_BMSK = 0x2, + PLL_PLLOUT_MAIN_SHFT = 0, + PLL_PLLOUT_EVEN_SHFT = 1, + PLL_PLLOUT_ODD_SHFT = 2 +}; + +enum clk_ctl_cfg_rcgr { + CLK_CTL_CFG_MODE_SHFT = 12, + CLK_CTL_CFG_SRC_SEL_SHFT = 8, + CLK_CTL_CFG_SRC_DIV_SHFT = 0 +}; + +enum clk_ctl_cmd_rcgr { + CLK_CTL_CMD_UPDATE_SHFT = 0 +}; + +enum clk_ctl_cbcr { + CLK_CTL_OFF_BMSK = 0x80000000, + CLK_CTL_OFF_SHFT = 31, + CLK_CTL_EN_BMSK = 0x1, + CLK_CTL_EN_SHFT = 0 +}; + +enum clk_ctl_rcg_mnd { + CLK_CTL_RCG_MND_BMSK = 0xFFFF, + CLK_CTL_RCG_MND_SHFT = 0, +}; + +enum clk_ctl_bcr { + CLK_CTL_BCR_BLK_BMSK = 0x1, + CLK_CTL_BCR_BLK_SHFT = 0, +}; + +enum clk_ctl_dfsr { + CLK_CTL_CMD_DFSR_BMSK = 0x1, + CLK_CTL_CMD_DFSR_SHFT = 0, + CLK_CTL_CMD_RCG_SW_CTL_SHFT = 15, +}; + +enum clk_qup { + QUP_WRAP0_S0, + QUP_WRAP0_S1, + QUP_WRAP0_S2, + QUP_WRAP0_S3, + QUP_WRAP0_S4, + QUP_WRAP0_S5, + QUP_WRAP0_S6, + QUP_WRAP0_S7, + QUP_WRAP1_S0, + QUP_WRAP1_S1, + QUP_WRAP1_S2, + QUP_WRAP1_S3, + QUP_WRAP1_S4, + QUP_WRAP1_S5, + QUP_WRAP1_S6, + QUP_WRAP1_S7, +}; + +enum pll_config_ctl_lo { + CTUNE_SHFT = 2, + K_I_SHFT = 4, + K_P_SHFT = 7, + PFA_MSB_SHFT = 10, + RES_BIT_SHFT = 14, + RON_DEGEN_MUL_SHFT = 18, + ALPHA_CAL_SHFT = 20, + DCO_ADDER_EN_SHFT = 22, + PLL_COUNTER_EN = 27, +}; + +enum pll_config_ctl_hi { + CUR_TRIM_SHFT = 0, + FREQ_DOUBLE_SHFT = 4, + ADJ_ENABLE_SHFT = 5, + ADJ_VALUE_SHFT = 6, + KLSB_SHFT = 13, + RON_MODE_SHFT = 17, + CHP_REF_SHFT = 19, + CHP_STARTUP = 21, + ADC_KMSB_VAL = 23, +}; + +enum pll_config_ctl_u1 { + FAST_LOCK_LOW_L_SHFT = 4, + DCO_BIAS_ADJ_SHFT = 26, +}; + +enum pll_mode { + PLL_LOCK_DET_BMSK = 0x80000000, + PLL_BYPASSNL_BMSK = 0x2, + PLL_OUTCTRL_BMSK = 0x1, + PLL_STANDBY_MODE = 0, + PLL_RUN_MODE = 1, + PLL_OPMODE_SHFT = 0, + PLL_OUTCTRL_SHFT = 0, + PLL_BYPASSNL_SHFT = 1, + PLL_RESET_SHFT = 2, + PLL_RESET_N_SHFT = 2, + PLL_FSM_EN_SHFT = 20, +}; + +enum apss_gfmux { + GFMUX_SRC_SEL_BMSK = 0x3, + APCS_SRC_EARLY = 0x2, +}; + +static struct sc7280_gcc *const gcc = (void *)GCC_BASE; +static struct sc7280_aoss *const aoss = (void *)AOSS_CC_BASE; +static struct sc7280_shrm *const shrm = (void *)SHRM_SPROC_BASE; +static struct sc7180_apss_clock *const apss_silver = (void *)SILVER_PLL_BASE; +static struct sc7180_apss_clock *const apss_l3 = (void *)L3_PLL_BASE; + +void clock_init(void); +void clock_reset_aop(void); +void clock_reset_shrm(void); +void clock_configure_qspi(uint32_t hz); +int clock_reset_bcr(void *bcr_addr, bool reset); +void clock_configure_qup(int qup, uint32_t hz); +void clock_enable_qup(int qup); +void clock_configure_dfsr(int qup); +void clock_configure_sdcc(int sdcc, uint32_t hz); + +#endif // __SOC_QUALCOMM_SC7280_CLOCK_H__