diff options
-rw-r--r-- | src/soc/qualcomm/common/clock.c | 243 | ||||
-rw-r--r-- | src/soc/qualcomm/common/include/soc/clock_common.h | 173 | ||||
-rw-r--r-- | src/soc/qualcomm/sc7180/Makefile.inc | 1 | ||||
-rw-r--r-- | src/soc/qualcomm/sc7180/clock.c | 258 | ||||
-rw-r--r-- | src/soc/qualcomm/sc7180/include/soc/clock.h | 191 |
5 files changed, 513 insertions, 353 deletions
diff --git a/src/soc/qualcomm/common/clock.c b/src/soc/qualcomm/common/clock.c new file mode 100644 index 0000000000..e83f979e81 --- /dev/null +++ b/src/soc/qualcomm/common/clock.c @@ -0,0 +1,243 @@ +/* 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> + +/* Clock Branch Operations */ +static bool clock_is_off(u32 *cbcr_addr) +{ + return (read32(cbcr_addr) & CLK_CTL_OFF_BMSK); +} + +enum cb_err clock_enable_vote(void *cbcr_addr, void *vote_addr, + uint32_t vote_bit) +{ + int count = 100; + + setbits32(vote_addr, BIT(vote_bit)); + + /* Ensure clock is enabled */ + while (count-- > 0) { + if (!clock_is_off(cbcr_addr)) + return CB_SUCCESS; + udelay(1); + } + printk(BIOS_ERR, "ERROR: Failed to enable clock, register val: 0x%x\n", + read32(cbcr_addr)); + return CB_ERR; +} + +enum cb_err clock_enable(void *cbcr_addr) +{ + int count = 100; + + /* Set clock enable bit */ + setbits32(cbcr_addr, BIT(CLK_CTL_EN_SHFT)); + + /* Ensure clock is enabled */ + while (count-- > 0) { + if (!clock_is_off(cbcr_addr)) + return CB_SUCCESS; + udelay(1); + } + printk(BIOS_ERR, "ERROR: Failed to enable clock, register val: 0x%x\n", + read32(cbcr_addr)); + return CB_ERR; +} + +/* Clock Block Reset Operations */ +void clock_reset_bcr(void *bcr_addr, bool assert) +{ + if (assert) + setbits32(bcr_addr, BIT(CLK_CTL_BCR_BLK_SHFT)); + else + clrbits32(bcr_addr, BIT(CLK_CTL_BCR_BLK_SHFT)); +} + +/* Clock GDSC Operations */ +enum cb_err enable_and_poll_gdsc_status(void *gdscr_addr) +{ + if (read32(gdscr_addr) & CLK_CTL_OFF_BMSK) + return CB_SUCCESS; + + clrbits32(gdscr_addr, BIT(GDSC_ENABLE_BIT)); + + /* Ensure gdsc is enabled */ + if (!wait_us(100, (read32(gdscr_addr) & CLK_CTL_OFF_BMSK))) + return CB_ERR; + + return CB_SUCCESS; +} + +/* Clock Root clock Generator with MND Operations */ +static void clock_configure_mnd(struct clock_rcg *clk, uint32_t m, uint32_t n, + uint32_t d_2) +{ + struct clock_rcg_mnd *mnd = (struct clock_rcg_mnd *)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); +} + +/* Clock Root clock Generator Operations */ +enum cb_err clock_configure(struct clock_rcg *clk, + struct clock_freq_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; + + 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; +} + +/* Clock Root clock Generator with DFS Operations */ +void clock_configure_dfsr_table(int qup, struct clock_freq_config *clk_cfg, + uint32_t num_perfs) +{ + struct qupv3_clock *qup_clk; + unsigned 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 < num_perfs; idx++) { + reg_val = (clk_cfg[idx].src << CLK_CTL_CFG_SRC_SEL_SHFT) | + (clk_cfg[idx].div << CLK_CTL_CFG_SRC_DIV_SHFT); + + write32(&qup_clk->dfsr_clk.perf_dfsr[idx], reg_val); + + if (clk_cfg[idx].m == 0) + continue; + + setbits32(&qup_clk->dfsr_clk.perf_dfsr[idx], + RCG_MODE_DUAL_EDGE << CLK_CTL_CFG_MODE_SHFT); + + reg_val = clk_cfg[idx].m & CLK_CTL_RCG_MND_BMSK; + write32(&qup_clk->dfsr_clk.perf_m_dfsr[idx], reg_val); + + reg_val = ~(clk_cfg[idx].n - clk_cfg[idx].m) + & CLK_CTL_RCG_MND_BMSK; + write32(&qup_clk->dfsr_clk.perf_n_dfsr[idx], reg_val); + + reg_val = ~(clk_cfg[idx].d_2) & CLK_CTL_RCG_MND_BMSK; + write32(&qup_clk->dfsr_clk.perf_d_dfsr[idx], reg_val); + } +} + +/* General Purpose PLL configuration and enable Operations */ +enum cb_err clock_configure_enable_gpll(struct alpha_pll_reg_val_config *cfg, + bool enable, int br_enable) +{ + if (cfg->l_val) + write32(cfg->reg_l, cfg->l_val); + + if (cfg->cal_l_val) + write32(cfg->reg_cal_l, cfg->cal_l_val); + + if (cfg->alpha_val) + write32(cfg->reg_alpha, cfg->alpha_val); + + if (cfg->user_ctl_val) + write32(cfg->reg_user_ctl, cfg->user_ctl_val); + + if (cfg->user_ctl_hi_val) + write32(cfg->reg_user_ctl_hi, cfg->user_ctl_hi_val); + + if (cfg->user_ctl_hi1_val) + write32(cfg->reg_user_ctl_hi1, cfg->user_ctl_hi1_val); + + if (cfg->config_ctl_val) + write32(cfg->reg_config_ctl, cfg->config_ctl_val); + + if (cfg->config_ctl_hi_val) + write32(cfg->reg_config_ctl_hi, cfg->config_ctl_hi_val); + + if (cfg->config_ctl_hi1_val) + write32(cfg->reg_config_ctl_hi1, cfg->config_ctl_hi1_val); + + if (cfg->fsm_enable) + setbits32(cfg->reg_mode, BIT(PLL_FSM_EN_SHFT)); + + if (enable) { + setbits32(cfg->reg_opmode, BIT(PLL_STANDBY_MODE)); + + /* + * H/W requires a 1us delay between placing PLL in STANDBY and + * de-asserting the reset. + */ + udelay(1); + setbits32(cfg->reg_mode, BIT(PLL_RESET_N_SHFT)); + + /* + * H/W requires a 10us delay between de-asserting the reset and + * enabling the PLL branch bit. + */ + udelay(10); + 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)) { + printk(BIOS_ERR, "ERROR: PLL did not lock!\n"); + return CB_ERR; + } + } + + return CB_SUCCESS; +} + +enum cb_err agera_pll_enable(struct alpha_pll_reg_val_config *cfg) +{ + setbits32(cfg->reg_mode, BIT(PLL_BYPASSNL_SHFT)); + + /* + * H/W requires a 5us delay between disabling the bypass and + * de-asserting the reset. + */ + udelay(5); + setbits32(cfg->reg_mode, BIT(PLL_RESET_SHFT)); + + if (!wait_us(100, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) { + printk(BIOS_ERR, "ERROR: CPU PLL did not lock!\n"); + return CB_ERR; + } + + setbits32(cfg->reg_mode, BIT(PLL_OUTCTRL_SHFT)); + + return CB_SUCCESS; +} + +/* Bring subsystem out of RESET */ +void clock_reset_subsystem(u32 *misc, u32 shft) +{ + clrbits32(misc, BIT(shft)); +} diff --git a/src/soc/qualcomm/common/include/soc/clock_common.h b/src/soc/qualcomm/common/include/soc/clock_common.h new file mode 100644 index 0000000000..b9241944c2 --- /dev/null +++ b/src/soc/qualcomm/common/include/soc/clock_common.h @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_QUALCOMM_COMMON_CLOCK_H__ +#define __SOC_QUALCOMM_COMMON_CLOCK_H__ + +#define QCOM_CLOCK_DIV(div) (2 * div - 1) + +/* Root Clock Generator */ +struct clock_rcg { + u32 rcg_cmd; + u32 rcg_cfg; +}; + +/* Root Clock Generator with MND */ +struct clock_rcg_mnd { + struct clock_rcg clock; + u32 m; + u32 n; + u32 d_2; +}; + +/* DFS controlled Root Clock Generator */ +struct clock_rcg_dfsr { + 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]; +}; + +/* Clock Frequency Table */ +struct clock_freq_config { + uint32_t hz; + uint8_t src; + uint8_t div; + uint16_t m; + uint16_t n; + uint16_t d_2; +}; + +struct qupv3_clock { + u32 cbcr; + struct clock_rcg_mnd clk; + struct clock_rcg_dfsr dfsr_clk; +}; + +/* PLL Configuration */ +struct alpha_pll_reg_val_config { + void *reg_mode; + u32 mode_val; + void *reg_l; + u32 l_val; + void *reg_cal_l; + u32 cal_l_val; + void *reg_user_ctl; + u32 user_ctl_val; + void *reg_user_ctl_hi; + u32 user_ctl_hi_val; + void *reg_user_ctl_hi1; + u32 user_ctl_hi1_val; + void *reg_config_ctl; + u32 config_ctl_val; + void *reg_config_ctl_hi; + u32 config_ctl_hi_val; + void *reg_config_ctl_hi1; + u32 config_ctl_hi1_val; + void *reg_alpha; + u32 alpha_val; + void *reg_opmode; + void *reg_apcs_pll_br_en; + bool fsm_enable; +}; + +enum clk_ctl_gpll_user_ctl { + PLL_PLLOUT_MAIN_SHFT = 0, + PLL_PLLOUT_EVEN_SHFT = 1, + PLL_PLLOUT_ODD_SHFT = 2, + PLL_POST_DIV_EVEN_SHFT = 8, + PLL_POST_DIV_ODD_SHFT = 12, + PLL_PLLOUT_EVEN_BMSK = 0x2, +}; + +enum gpll_mode { + PLL_LOCK_DET_BMSK = 0x80000000, + PLL_BYPASSNL_BMSK = 0x2, + PLL_OUTCTRL_BMSK = 0x1, + PLL_USERCTL_BMSK = 0xF, + 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 clk_ctl_cfg_rcgr { + CLK_CTL_CFG_SRC_DIV_SHFT = 0, + CLK_CTL_CFG_SRC_SEL_SHFT = 8, + CLK_CTL_CFG_MODE_SHFT = 12, +}; + +enum clk_ctl_cmd_rcgr { + CLK_CTL_CMD_UPDATE_SHFT = 0, +}; + +enum clk_ctl_cbcr { + CLK_CTL_EN_SHFT = 0, + CLK_CTL_OFF_SHFT = 31, + CLK_CTL_EN_BMSK = 0x1, + CLK_CTL_OFF_BMSK = 0x80000000, +}; + +enum clk_ctl_rcg_mnd { + RCG_MODE_DUAL_EDGE = 2, + CLK_CTL_RCG_MND_SHFT = 0, + CLK_CTL_RCG_MND_BMSK = 0xFFFF, +}; + +enum clk_ctl_bcr { + CLK_CTL_BCR_BLK_SHFT = 0, + CLK_CTL_BCR_BLK_BMSK = 0x1, +}; + +enum clk_ctl_dfsr { + CLK_CTL_CMD_DFSR_SHFT = 0, + CLK_CTL_CMD_RCG_SW_CTL_SHFT = 15, + CLK_CTL_CMD_DFSR_BMSK = 0x1, +}; + +#define GDSC_ENABLE_BIT 0 + +enum cb_err clock_enable_vote(void *cbcr_addr, void *vote_addr, + uint32_t vote_bit); + +enum cb_err clock_enable(void *cbcr_addr); + +enum cb_err enable_and_poll_gdsc_status(void *gdscr_addr); + +void clock_reset_bcr(void *bcr_addr, bool assert); + +enum cb_err clock_configure(struct clock_rcg *clk, struct clock_freq_config *clk_cfg, + uint32_t hz, uint32_t num_perfs); + +void clock_configure_dfsr_table(int qup, struct clock_freq_config *clk_cfg, + uint32_t num_perfs); + +enum cb_err clock_configure_enable_gpll(struct alpha_pll_reg_val_config *cfg, + bool enable, int br_enable); +enum cb_err agera_pll_enable(struct alpha_pll_reg_val_config *cfg); + +struct aoss { + u8 _res0[0x50020]; + u32 aoss_cc_reset_status; + u8 _res1[0x5002c - 0x50024]; + u32 aoss_cc_apcs_misc; +}; +check_member(aoss, aoss_cc_reset_status, 0x50020); +check_member(aoss, aoss_cc_apcs_misc, 0x5002c); + +struct shrm { + u32 shrm_sproc_ctrl; +}; + +void clock_reset_subsystem(u32 *misc, u32 shft); + +#endif diff --git a/src/soc/qualcomm/sc7180/Makefile.inc b/src/soc/qualcomm/sc7180/Makefile.inc index 5ac1f3fe6c..83f9eb5127 100644 --- a/src/soc/qualcomm/sc7180/Makefile.inc +++ b/src/soc/qualcomm/sc7180/Makefile.inc @@ -11,6 +11,7 @@ all-y += qupv3_i2c.c all-y += qupv3_spi.c all-y += clock.c all-$(CONFIG_SC7180_QSPI) += qspi.c +all-y += ../common/clock.c all-y += qcom_qup_se.c all-y += qupv3_config.c diff --git a/src/soc/qualcomm/sc7180/clock.c b/src/soc/qualcomm/sc7180/clock.c index 8bf450ab08..aa289c4c79 100644 --- a/src/soc/qualcomm/sc7180/clock.c +++ b/src/soc/qualcomm/sc7180/clock.c @@ -2,48 +2,45 @@ #include <assert.h> #include <commonlib/helpers.h> -#include <console/console.h> #include <delay.h> #include <device/mmio.h> #include <soc/clock.h> #include <timer.h> #include <types.h> -#define DIV(div) (2 * div - 1) - -struct clock_config qspi_core_cfg[] = { +static struct clock_freq_config qspi_core_cfg[] = { { .hz = SRC_XO_HZ, /* 19.2KHz */ .src = SRC_XO_19_2MHZ, - .div = DIV(1), + .div = QCOM_CLOCK_DIV(1), }, { .hz = 100 * MHz, .src = SRC_GPLL0_EVEN_300MHZ, - .div = DIV(3), + .div = QCOM_CLOCK_DIV(3), }, { .hz = 150 * MHz, .src = SRC_GPLL0_EVEN_300MHZ, - .div = DIV(2), + .div = QCOM_CLOCK_DIV(2), }, { .hz = GPLL0_EVEN_HZ, /* 300MHz */ .src = SRC_GPLL0_EVEN_300MHZ, - .div = DIV(1), + .div = QCOM_CLOCK_DIV(1), } }; -struct clock_config qupv3_wrap_cfg[] = { +static struct clock_freq_config qupv3_wrap_cfg[] = { { .hz = SRC_XO_HZ, /* 19.2KHz */ .src = SRC_XO_19_2MHZ, - .div = DIV(1), + .div = QCOM_CLOCK_DIV(1), }, { .hz = 32 * MHz, .src = SRC_GPLL0_EVEN_300MHZ, - .div = DIV(1), + .div = QCOM_CLOCK_DIV(1), .m = 8, .n = 75, .d_2 = 75, @@ -51,7 +48,7 @@ struct clock_config qupv3_wrap_cfg[] = { { .hz = 48 * MHz, .src = SRC_GPLL0_EVEN_300MHZ, - .div = DIV(1), + .div = QCOM_CLOCK_DIV(1), .m = 4, .n = 25, .d_2 = 25, @@ -59,7 +56,7 @@ struct clock_config qupv3_wrap_cfg[] = { { .hz = 64 * MHz, .src = SRC_GPLL0_EVEN_300MHZ, - .div = DIV(1), + .div = QCOM_CLOCK_DIV(1), .m = 16, .n = 75, .d_2 = 75, @@ -67,7 +64,7 @@ struct clock_config qupv3_wrap_cfg[] = { { .hz = 96 * MHz, .src = SRC_GPLL0_EVEN_300MHZ, - .div = DIV(1), + .div = QCOM_CLOCK_DIV(1), .m = 8, .n = 25, .d_2 = 25, @@ -75,21 +72,21 @@ struct clock_config qupv3_wrap_cfg[] = { { .hz = 100 * MHz, .src = SRC_GPLL0_EVEN_300MHZ, - .div = DIV(3), + .div = QCOM_CLOCK_DIV(3), }, { .hz = SRC_XO_HZ, /* 19.2KHz */ .src = SRC_XO_19_2MHZ, - .div = DIV(1), + .div = QCOM_CLOCK_DIV(1), }, { .hz = SRC_XO_HZ, /* 19.2KHz */ .src = SRC_XO_19_2MHZ, - .div = DIV(1), + .div = QCOM_CLOCK_DIV(1), }, }; -static struct sc7180_mnd_clock *mdss_clock[MDSS_CLK_COUNT] = { +static struct clock_rcg_mnd *mdss_clock[MDSS_CLK_COUNT] = { [MDSS_CLK_ESC0] = &mdss->esc0, [MDSS_CLK_PCLK0] = &mdss->pclk0, [MDSS_CLK_BYTE0] = &mdss->byte0, @@ -105,96 +102,18 @@ static u32 *mdss_cbcr[MDSS_CLK_COUNT] = { static int clock_configure_gpll0(void) { - setbits32(&gcc->gpll0.user_ctl_u, 1 << SCALE_FREQ_SHFT); - - /* Keep existing GPLL0 configuration, in RUN mode @600Mhz. */ - setbits32(&gcc->gpll0.user_ctl, - 1 << CLK_CTL_GPLL_PLLOUT_EVEN_SHFT | - 1 << CLK_CTL_GPLL_PLLOUT_MAIN_SHFT | - 1 << CLK_CTL_GPLL_PLLOUT_ODD_SHFT); - - return 0; -} - -static void clock_configure_mnd(struct sc7180_clock *clk, uint32_t m, - uint32_t n, uint32_t d_2) -{ - struct sc7180_mnd_clock *mnd = (struct sc7180_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); -} - -static enum cb_err clock_configure(struct sc7180_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) - 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_CBC_CLK_OFF_BMSK); -} - -static enum cb_err 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; + struct alpha_pll_reg_val_config gpll0_cfg = {0}; - return CB_SUCCESS; -} + gpll0_cfg.reg_user_ctl_hi = &gcc->gpll0.user_ctl_u; + gpll0_cfg.user_ctl_hi_val = 1 << SCALE_FREQ_SHFT; -static enum cb_err clock_enable(void *cbcr_addr) -{ - /* Set clock enable bit */ - setbits32(cbcr_addr, BIT(CLK_CTL_CBC_CLK_EN_SHFT)); - - if (!wait_us(100, clock_is_off(cbcr_addr))) - return CB_ERR; - - return CB_SUCCESS; -} - -static void clock_reset_subsystem(u32 *misc, u32 shft) -{ - clrbits32(misc, BIT(shft)); -} + gpll0_cfg.reg_user_ctl = &gcc->gpll0.user_ctl; + gpll0_cfg.user_ctl_val = (1 << PLL_POST_DIV_EVEN_SHFT | + 1 << PLL_PLLOUT_EVEN_SHFT | + 1 << PLL_PLLOUT_MAIN_SHFT | + 1 << PLL_PLLOUT_ODD_SHFT); -void clock_reset_aop(void) -{ - /* Bring AOP out of RESET */ - clock_reset_subsystem(&aoss->aoss_cc_apcs_misc, AOP_RESET_SHFT); + return clock_configure_enable_gpll(&gpll0_cfg, false, 0); } void clock_configure_qspi(uint32_t hz) @@ -206,57 +125,10 @@ void clock_configure_qspi(uint32_t hz) clock_enable(&gcc->qspi_core_cbcr); } -void clock_reset_bcr(void *bcr_addr, bool reset) -{ - struct sc7180_bcr *bcr = bcr_addr; - - if (reset) - setbits32(bcr, BIT(CLK_CTL_BCR_BLK_ARES_SHFT)); - else - clrbits32(bcr, BIT(CLK_CTL_BCR_BLK_ARES_SHFT)); -} - -static void clock_configure_dfsr_table(int qup, struct clock_config *clk_cfg, - uint32_t num_perfs) -{ - int idx; - int s = qup % QUP_WRAP1_S0; - uint32_t reg_val; - struct sc7180_qupv3_clock *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 < num_perfs; idx++) { - reg_val = (clk_cfg[idx].src << CLK_CTL_CFG_SRC_SEL_SHFT) | - (clk_cfg[idx].div << CLK_CTL_CFG_SRC_DIV_SHFT); - - write32(&qup_clk->dfsr_clk.perf_dfsr[idx], reg_val); - - if (clk_cfg[idx].m == 0) - continue; - - setbits32(&qup_clk->dfsr_clk.perf_dfsr[idx], - RCG_MODE_DUAL_EDGE << CLK_CTL_CFG_MODE_SHFT); - - reg_val = clk_cfg[idx].m & CLK_CTL_RCG_MND_BMSK; - write32(&qup_clk->dfsr_clk.perf_m_dfsr[idx], reg_val); - - reg_val = ~(clk_cfg[idx].n - clk_cfg[idx].m) - & CLK_CTL_RCG_MND_BMSK; - write32(&qup_clk->dfsr_clk.perf_n_dfsr[idx], reg_val); - - reg_val = ~(clk_cfg[idx].d_2) & CLK_CTL_RCG_MND_BMSK; - write32(&qup_clk->dfsr_clk.perf_d_dfsr[idx], reg_val); - } -} - void clock_configure_dfsr(int qup) { clock_configure_dfsr_table(qup, qupv3_wrap_cfg, - ARRAY_SIZE(qupv3_wrap_cfg)); + ARRAY_SIZE(qupv3_wrap_cfg)); } void clock_enable_qup(int qup) @@ -264,51 +136,40 @@ void clock_enable_qup(int qup) int s = qup % QUP_WRAP1_S0; int clk_en_off = qup < QUP_WRAP1_S0 ? QUPV3_WRAP0_CLK_ENA_S(s) : QUPV3_WRAP1_CLK_ENA_S(s); - struct sc7180_qupv3_clock *qup_clk = qup < QUP_WRAP1_S0 ? + struct qupv3_clock *qup_clk = qup < QUP_WRAP1_S0 ? &gcc->qup_wrap0_s[s] : &gcc->qup_wrap1_s[s]; - clock_enable_vote(&qup_clk->mnd_clk, &gcc->apcs_clk_br_en1, - clk_en_off); -} - -static enum cb_err agera_pll_enable(u32 *mode, u32 *opmode) -{ - setbits32(mode, BIT(BYPASSNL_SHFT)); - udelay(5); - setbits32(mode, BIT(RESET_SHFT)); - - setbits32(opmode, RUN_MODE); - - if (!wait_us(100, read32(mode) & LOCK_DET_BMSK)) { - printk(BIOS_ERR, "ERROR: PLL did not lock!\n"); - return CB_ERR; - } - - setbits32(mode, BIT(OUTCTRL_SHFT)); - - return CB_SUCCESS; + clock_enable_vote(&qup_clk->cbcr, &gcc->apcs_clk_br_en1, + clk_en_off); } static enum cb_err pll_init_and_set(struct sc7180_apss_clock *apss, u32 l_val) { + struct alpha_pll_reg_val_config pll_cfg = {0}; int ret; u32 gfmux_val; - /* Configure and Enable PLL */ - write32(&apss->pll.config_ctl_lo, 0x0); - setbits32(&apss->pll.config_ctl_lo, 0x2 << CTUNE_SHFT | - 0x2 << K_I_SHFT | 0x5 << K_P_SHFT | - 0x2 << PFA_MSB_SHFT | 0x2 << REF_CONT_SHFT); + pll_cfg.reg_config_ctl = &apss->pll.config_ctl_lo; + pll_cfg.reg_config_ctl_hi = &apss->pll.config_ctl_hi; + pll_cfg.reg_config_ctl_hi1 = &apss->pll.config_ctl_u1; - write32(&apss->pll.config_ctl_hi, 0x0); - setbits32(&apss->pll.config_ctl_hi, 0x2 << CUR_ADJ_SHFT | - BIT(DMET_SHFT) | 0xF << RES_SHFT); + pll_cfg.config_ctl_val = (0x2 << CTUNE_SHFT | 0x2 << K_I_SHFT | + 0x5 << K_P_SHFT | 0x2 << PFA_MSB_SHFT | + 0x2 << REF_CONT_SHFT); + pll_cfg.config_ctl_hi_val = (0x2 << CUR_ADJ_SHFT | BIT(DMET_SHFT) | + 0xF << RES_SHFT); write32(&apss->pll.config_ctl_u1, 0x0); - write32(&apss->pll.l_val, l_val); + pll_cfg.reg_l = &apss->pll.l; + pll_cfg.l_val = l_val; - ret = agera_pll_enable(&apss->pll.mode, &apss->pll.opmode); - if (ret != CB_SUCCESS) + ret = clock_configure_enable_gpll(&pll_cfg, false, 0); + if (ret < 0) + return CB_ERR; + + pll_cfg.reg_mode = &apss->pll.mode; + ret = agera_pll_enable(&pll_cfg); + if (ret < 0) return CB_ERR; gfmux_val = read32(&apss->cfg_gfmux) & ~GFMUX_SRC_SEL_BMSK; @@ -333,8 +194,7 @@ enum cb_err mdss_clock_configure(enum mdss_clock clk_type, uint32_t source, uint32_t divider, uint32_t m, uint32_t n, uint32_t d_2) { - struct clock_config mdss_clk_cfg; - uint32_t reg_val; + struct clock_freq_config mdss_clk_cfg; if (clk_type >= MDSS_CLK_COUNT) return CB_ERR; @@ -355,33 +215,17 @@ enum cb_err mdss_clock_configure(enum mdss_clock clk_type, uint32_t source, mdss_clk_cfg.n = n; mdss_clk_cfg.d_2 = d_2; - /* configure and set the clock */ - reg_val = (mdss_clk_cfg.src << CLK_CTL_CFG_SRC_SEL_SHFT) | - (mdss_clk_cfg.div << CLK_CTL_CFG_SRC_DIV_SHFT); - - write32(&mdss_clock[clk_type]->clock.rcg_cfg, reg_val); - - /* Set m/n/d values for a specific clock */ - if (mdss_clk_cfg.m != 0) - clock_configure_mnd((struct sc7180_clock *)mdss_clock[clk_type], - mdss_clk_cfg.m, mdss_clk_cfg.n, mdss_clk_cfg.d_2); - - /* Commit config to RCG */ - setbits32(&mdss_clock[clk_type]->clock.rcg_cmd, - BIT(CLK_CTL_CMD_UPDATE_SHFT)); - - return CB_SUCCESS; + return clock_configure((struct clock_rcg *)mdss_clock[clk_type], + &mdss_clk_cfg, 0, 0); } int mdss_clock_enable(enum mdss_clock clk_type) { if (clk_type >= MDSS_CLK_COUNT) - return -1; + return CB_ERR; /* Enable clock*/ - clock_enable(mdss_cbcr[clk_type]); - - return 0; + return clock_enable(mdss_cbcr[clk_type]); } void clock_init(void) diff --git a/src/soc/qualcomm/sc7180/include/soc/clock.h b/src/soc/qualcomm/sc7180/include/soc/clock.h index bb46062e11..4e80fe8b63 100644 --- a/src/soc/qualcomm/sc7180/include/soc/clock.h +++ b/src/soc/qualcomm/sc7180/include/soc/clock.h @@ -2,69 +2,46 @@ #include <soc/addressmap.h> #include <types.h> +#include <soc/clock_common.h> #ifndef __SOC_QUALCOMM_SC7180_CLOCK_H__ #define __SOC_QUALCOMM_SC7180_CLOCK_H__ -#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 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_GPLL0_EVEN_300MHZ 6 - -#define AOP_RESET_SHFT 0 -#define RCG_MODE_DUAL_EDGE 2 - -#define SCALE_FREQ_SHFT 11 +#define QUPV3_WRAP0_CLK_ENA_S(idx) (10 + idx) +#define QUPV3_WRAP1_CLK_ENA_S(idx) (22 + idx) -struct sc7180_clock { - u32 rcg_cmd; - u32 rcg_cfg; +enum apcs_branch_en_vote { + QUPV3_WRAP_0_M_AHB_CLK_ENA = 6, + QUPV3_WRAP_0_S_AHB_CLK_ENA = 7, + QUPV3_WRAP0_CORE_CLK_ENA = 8, + QUPV3_WRAP0_CORE_2X_CLK_ENA = 9, + QUPV3_WRAP1_CORE_2X_CLK_ENA = 18, + QUPV3_WRAP1_CORE_CLK_ENA = 19, + QUPV3_WRAP_1_M_AHB_CLK_ENA = 20, + QUPV3_WRAP_1_S_AHB_CLK_ENA = 21, }; -struct sc7180_mnd_clock { - struct sc7180_clock clock; - u32 m; - u32 n; - u32 d_2; +enum clk_pll_src { + SRC_XO_19_2MHZ = 0, + SRC_GPLL0_MAIN_600MHZ = 1, + SRC_GPLL0_EVEN_300MHZ = 6, }; -struct sc7180_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]; -}; +/* CPU PLL */ +#define L_VAL_1516P8MHz 0x4F +#define L_VAL_1209P6MHz 0x3F -struct sc7180_qupv3_clock { - u32 cbcr; - struct sc7180_mnd_clock mnd_clk; - struct sc7180_dfsr_clock dfsr_clk; -}; +#define AOP_RESET_SHFT 0 +#define SCALE_FREQ_SHFT 11 struct sc7180_gpll { u32 mode; - u32 l_val; - u32 cal_l_val; + u32 l; + u32 cal_l; u32 user_ctl; u32 user_ctl_u; u32 config_ctl; @@ -85,16 +62,16 @@ struct sc7180_gcc { u32 qup_wrap0_core_cbcr; u32 qup_wrap0_core_cdivr; u32 qup_wrap0_core_2x_cbcr; - struct sc7180_clock qup_wrap0_core_2x; + struct clock_rcg qup_wrap0_core_2x; u8 _res2[0x17030 - 0x17020]; - struct sc7180_qupv3_clock qup_wrap0_s[6]; + struct qupv3_clock qup_wrap0_s[6]; u8 _res3[0x18000 - 0x17750]; u32 qup_wrap1_bcr; u32 qup_wrap1_core_2x_cbcr; u32 qup_wrap1_core_cbcr; u32 qup_wrap1_m_ahb_cbcr; u32 qup_wrap1_s_ahb_cbcr; - struct sc7180_qupv3_clock qup_wrap1_s[6]; + struct qupv3_clock qup_wrap1_s[6]; u8 _res4[0x18994 - 0x18734]; u32 qup_wrap1_core_cdivr; u8 _res5[0x26000 - 0x18998]; @@ -103,7 +80,7 @@ struct sc7180_gcc { u32 qspi_bcr; u32 qspi_cnoc_ahb_cbcr; u32 qspi_core_cbcr; - struct sc7180_clock qspi_core; + struct clock_rcg qspi_core; u8 _res7[0x50000 - 0x4b014]; u32 usb3_phy_prim_bcr; u32 usb3phy_phy_prim_bcr; @@ -124,15 +101,6 @@ check_member(sc7180_gcc, usb3phy_phy_prim_bcr, 0x50004); check_member(sc7180_gcc, usb3_phy_prim_bcr, 0x50000); check_member(sc7180_gcc, apcs_clk_br_en1, 0x52008); -struct sc7180_aoss { - u8 _res0[0x50020]; - u32 aoss_cc_reset_status; - u8 _res1[0x5002C - 0x50024]; - u32 aoss_cc_apcs_misc; -}; -check_member(sc7180_aoss, aoss_cc_reset_status, 0x50020); -check_member(sc7180_aoss, aoss_cc_apcs_misc, 0x5002C); - struct sc7180_disp_cc { u8 _res0[0x2004]; u32 pclk0_cbcr; @@ -142,11 +110,11 @@ struct sc7180_disp_cc { u8 _res2[0x2038 - 0x2030]; u32 esc0_cbcr; u8 _res3[0x2098 - 0x203C]; - struct sc7180_mnd_clock pclk0; + struct clock_rcg_mnd pclk0; u8 _res4[0x2110 - 0x20AC]; - struct sc7180_mnd_clock byte0; + struct clock_rcg_mnd byte0; u8 _res5[0x2148 - 0x2124]; - struct sc7180_mnd_clock esc0; + struct clock_rcg_mnd esc0; u8 _res6[0x10000 - 0x215C]; }; check_member(sc7180_disp_cc, byte0_cbcr, 0x2028); @@ -160,56 +128,6 @@ enum mdss_clock { MDSS_CLK_COUNT }; -enum clk_ctl_gpll_user_ctl { - CLK_CTL_GPLL_PLLOUT_EVEN_BMSK = 0x2, - CLK_CTL_GPLL_PLLOUT_MAIN_SHFT = 0, - CLK_CTL_GPLL_PLLOUT_EVEN_SHFT = 1, - CLK_CTL_GPLL_PLLOUT_ODD_SHFT = 2 -}; - -enum clk_ctl_cfg_rcgr { - CLK_CTL_CFG_HW_CTL_BMSK = 0x100000, - CLK_CTL_CFG_HW_CTL_SHFT = 20, - CLK_CTL_CFG_MODE_BMSK = 0x3000, - CLK_CTL_CFG_MODE_SHFT = 12, - CLK_CTL_CFG_SRC_SEL_BMSK = 0x700, - CLK_CTL_CFG_SRC_SEL_SHFT = 8, - CLK_CTL_CFG_SRC_DIV_BMSK = 0x1F, - CLK_CTL_CFG_SRC_DIV_SHFT = 0 -}; - -enum clk_ctl_cmd_rcgr { - CLK_CTL_CMD_ROOT_OFF_BMSK = 0x80000000, - CLK_CTL_CMD_ROOT_OFF_SHFT = 31, - CLK_CTL_CMD_ROOT_EN_BMSK = 0x2, - CLK_CTL_CMD_ROOT_EN_SHFT = 1, - CLK_CTL_CMD_UPDATE_BMSK = 0x1, - CLK_CTL_CMD_UPDATE_SHFT = 0 -}; - -enum clk_ctl_cbcr { - CLK_CTL_CBC_CLK_OFF_BMSK = 0x80000000, - CLK_CTL_CBC_CLK_OFF_SHFT = 31, - CLK_CTL_CBC_CLK_EN_BMSK = 0x1, - CLK_CTL_CBC_CLK_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_ARES_BMSK = 0x1, - CLK_CTL_BCR_BLK_ARES_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, @@ -225,23 +143,10 @@ enum clk_qup { QUP_WRAP1_S5, }; -struct clock_config { - uint32_t hz; - uint8_t src; - uint8_t div; - uint16_t m; - uint16_t n; - uint16_t d_2; -}; - -/* CPU PLL */ -#define L_VAL_1516P8MHz 0x4F -#define L_VAL_1209P6MHz 0x3F - struct sc7180_apss_pll { u32 mode; - u32 l_val; - u32 alpha_val; + u32 l; + u32 alpha; u32 user_ctl; u32 config_ctl_lo; u32 config_ctl_hi; @@ -261,34 +166,25 @@ struct sc7180_apss_clock { }; enum pll_config_ctl_lo { - CTUNE_SHFT = 2, - K_I_SHFT = 4, - K_P_SHFT = 7, - PFA_MSB_SHFT = 10, - REF_CONT_SHFT = 28, + CTUNE_SHFT = 2, + K_I_SHFT = 4, + K_P_SHFT = 7, + PFA_MSB_SHFT = 10, + REF_CONT_SHFT = 28, }; enum pll_config_ctl_hi { - CUR_ADJ_SHFT = 0, - DMET_SHFT = 4, - RES_SHFT = 6, -}; - -enum pll_mode { - LOCK_DET_BMSK = 0x80000000, - RUN_MODE = 1, - OUTCTRL_SHFT = 0, - BYPASSNL_SHFT = 1, - RESET_SHFT = 2, + CUR_ADJ_SHFT = 0, + DMET_SHFT = 4, + RES_SHFT = 6, }; enum apss_gfmux { GFMUX_SRC_SEL_BMSK = 0x3, - APCS_SRC_EARLY = 0x2, + APCS_SRC_EARLY = 0x2, }; static struct sc7180_gcc *const gcc = (void *)GCC_BASE; -static struct sc7180_aoss *const aoss = (void *)AOSS_CC_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; static struct sc7180_disp_cc *const mdss = (void *)DISP_CC_BASE; @@ -296,7 +192,6 @@ static struct sc7180_disp_cc *const mdss = (void *)DISP_CC_BASE; void clock_init(void); void clock_reset_aop(void); void clock_configure_qspi(uint32_t hz); -void 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); @@ -304,4 +199,8 @@ int mdss_clock_configure(enum mdss_clock clk_type, uint32_t source, uint32_t divider, uint32_t m, uint32_t n, uint32_t d); int mdss_clock_enable(enum mdss_clock clk_type); +static struct aoss *const aoss = (void *)AOSS_CC_BASE; +#define clock_reset_aop() \ + clock_reset_subsystem(&aoss->aoss_cc_apcs_misc, AOP_RESET_SHFT) + #endif // __SOC_QUALCOMM_SC7180_CLOCK_H__ |