Shelley Chen submitted this change.

View Change

Approvals: build bot (Jenkins): Verified Shelley Chen: Looks good to me, approved
soc/qualcomm/common: clock: Add support for common clock driver

The clock driver supports configuring the general purpose PLLs,
configuring the root clock generator (RCG), enable clock branch, enable
gdsc and also the block resets.

The common clock driver exposes PLL configuration functions and also
different Agera PLL enable functions for the CPU PLLs.

While at it, the common driver also supports reset of subsystems like
AOP and SHRM.

SC7180 clock driver is also refactored to use the common clock
driver APIs.

BUG=b:182963902
TEST=Validated on qualcomm sc7180 and sc7280 development board.

Change-Id: I03d1b4a2fb90303c7259ec08f312d78b4e33ec39
Signed-off-by: Taniya Das <tdas@codeaurora.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/56588
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Shelley Chen <shchen@google.com>
---
A src/soc/qualcomm/common/clock.c
A src/soc/qualcomm/common/include/soc/clock_common.h
M src/soc/qualcomm/sc7180/Makefile.inc
M src/soc/qualcomm/sc7180/clock.c
M src/soc/qualcomm/sc7180/include/soc/clock.h
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 0000000..e83f979
--- /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 0000000..b924194
--- /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 5ac1f3f..83f9eb5 100644
--- a/src/soc/qualcomm/sc7180/Makefile.inc
+++ b/src/soc/qualcomm/sc7180/Makefile.inc
@@ -11,6 +11,7 @@
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 8bf450a..aa289c4 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 @@
{
.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 @@
{
.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 @@
{
.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 @@
{
.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 int clock_configure_gpll0(void)
{
- setbits32(&gcc->gpll0.user_ctl_u, 1 << SCALE_FREQ_SHFT);
+ struct alpha_pll_reg_val_config gpll0_cfg = {0};

- /* 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);
+ gpll0_cfg.reg_user_ctl_hi = &gcc->gpll0.user_ctl_u;
+ gpll0_cfg.user_ctl_hi_val = 1 << SCALE_FREQ_SHFT;

- return 0;
-}
+ 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);

-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;
-
- return CB_SUCCESS;
-}
-
-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));
-}
-
-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 @@
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 @@
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 @@
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 @@
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 bb46062..4e80fe8 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 QUPV3_WRAP0_CLK_ENA_S(idx) (10 + idx)
+#define QUPV3_WRAP1_CLK_ENA_S(idx) (22 + idx)

-#define AOP_RESET_SHFT 0
-#define RCG_MODE_DUAL_EDGE 2
-
-#define SCALE_FREQ_SHFT 11
-
-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 @@
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 @@
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, 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 @@
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 @@
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 @@
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 @@
};

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 @@
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 @@
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__

To view, visit change 56588. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I03d1b4a2fb90303c7259ec08f312d78b4e33ec39
Gerrit-Change-Number: 56588
Gerrit-PatchSet: 8
Gerrit-Owner: Ravi kumar <rbokka@codeaurora.org>
Gerrit-Reviewer: Julius Werner <jwerner@chromium.org>
Gerrit-Reviewer: Shelley Chen <shchen@google.com>
Gerrit-Reviewer: Taniya Das <tdas@codeaurora.org>
Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org>
Gerrit-Reviewer: mturney mturney <mturney@codeaurora.org>
Gerrit-CC: Paul Menzel <paulepanter@mailbox.org>
Gerrit-CC: Ravi Kumar Bokka <c_rbokka@qualcomm.corp-partner.google.com>
Gerrit-MessageType: merged