summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/qualcomm/common/clock.c23
-rw-r--r--src/soc/qualcomm/common/include/soc/clock_common.h2
-rw-r--r--src/soc/qualcomm/sc7280/Makefile.inc2
-rw-r--r--src/soc/qualcomm/sc7280/clock.c490
-rw-r--r--src/soc/qualcomm/sc7280/include/soc/addressmap.h7
-rw-r--r--src/soc/qualcomm/sc7280/include/soc/clock.h390
6 files changed, 914 insertions, 0 deletions
diff --git a/src/soc/qualcomm/common/clock.c b/src/soc/qualcomm/common/clock.c
index e83f979e81..09cd95c88a 100644
--- a/src/soc/qualcomm/common/clock.c
+++ b/src/soc/qualcomm/common/clock.c
@@ -236,6 +236,29 @@ enum cb_err agera_pll_enable(struct alpha_pll_reg_val_config *cfg)
return CB_SUCCESS;
}
+enum cb_err zonda_pll_enable(struct alpha_pll_reg_val_config *cfg)
+{
+ setbits32(cfg->reg_mode, BIT(PLL_BYPASSNL_SHFT));
+
+ /*
+ * H/W requires a 1us delay between disabling the bypass and
+ * de-asserting the reset.
+ */
+ udelay(1);
+ 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)) {
+ printk(BIOS_ERR, "ERROR: CPU PLL did not lock!\n");
+ return CB_ERR;
+ }
+
+ setbits32(cfg->reg_user_ctl, PLL_USERCTL_BMSK);
+ setbits32(cfg->reg_mode, BIT(PLL_OUTCTRL_SHFT));
+
+ return CB_SUCCESS;
+}
+
/* Bring subsystem out of RESET */
void clock_reset_subsystem(u32 *misc, u32 shft)
{
diff --git a/src/soc/qualcomm/common/include/soc/clock_common.h b/src/soc/qualcomm/common/include/soc/clock_common.h
index b9241944c2..0911827149 100644
--- a/src/soc/qualcomm/common/include/soc/clock_common.h
+++ b/src/soc/qualcomm/common/include/soc/clock_common.h
@@ -155,6 +155,8 @@ 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);
+enum cb_err zonda_pll_enable(struct alpha_pll_reg_val_config *cfg);
+
struct aoss {
u8 _res0[0x50020];
u32 aoss_cc_reset_status;
diff --git a/src/soc/qualcomm/sc7280/Makefile.inc b/src/soc/qualcomm/sc7280/Makefile.inc
index 3c34be010c..b44c754c16 100644
--- a/src/soc/qualcomm/sc7280/Makefile.inc
+++ b/src/soc/qualcomm/sc7280/Makefile.inc
@@ -3,6 +3,8 @@ ifeq ($(CONFIG_SOC_QUALCOMM_SC7280),y)
all-y += ../common/timer.c
all-y += spi.c
all-y += ../common/gpio.c
+all-y += ../common/clock.c
+all-y += clock.c
################################################################################
bootblock-y += bootblock.c
diff --git a/src/soc/qualcomm/sc7280/clock.c b/src/soc/qualcomm/sc7280/clock.c
new file mode 100644
index 0000000000..871fb9bbd8
--- /dev/null
+++ b/src/soc/qualcomm/sc7280/clock.c
@@ -0,0 +1,490 @@
+/* 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>
+
+static struct clock_freq_config qspi_core_cfg[] = {
+ {
+ .hz = SRC_XO_HZ, /* 19.2KHz */
+ .src = SRC_XO_19_2MHZ,
+ .div = QCOM_CLOCK_DIV(1),
+ },
+ {
+ .hz = 100 * MHz,
+ .src = SRC_GPLL0_MAIN_600MHZ,
+ .div = QCOM_CLOCK_DIV(6),
+ },
+ {
+ .hz = 150 * MHz,
+ .src = SRC_GPLL0_MAIN_600MHZ,
+ .div = QCOM_CLOCK_DIV(4),
+ },
+ {
+ .hz = 200 * MHz,
+ .src = SRC_GPLL0_MAIN_600MHZ,
+ .div = QCOM_CLOCK_DIV(3),
+ },
+ {
+ .hz = 400 * MHz,
+ .src = SRC_GPLL0_MAIN_600MHZ,
+ .div = QCOM_CLOCK_DIV(1.5),
+ },
+};
+
+static struct clock_freq_config qupv3_wrap_cfg[] = {
+ {
+ .hz = SRC_XO_HZ, /* 19.2KHz */
+ .src = SRC_XO_19_2MHZ,
+ .div = QCOM_CLOCK_DIV(1),
+ },
+ {
+ .hz = 32 * MHz,
+ .src = SRC_GPLL0_EVEN_300MHZ,
+ .div = QCOM_CLOCK_DIV(1),
+ .m = 8,
+ .n = 75,
+ .d_2 = 75,
+ },
+ {
+ .hz = 48 * MHz,
+ .src = SRC_GPLL0_EVEN_300MHZ,
+ .div = QCOM_CLOCK_DIV(1),
+ .m = 4,
+ .n = 25,
+ .d_2 = 25,
+ },
+ {
+ .hz = 64 * MHz,
+ .src = SRC_GPLL0_EVEN_300MHZ,
+ .div = QCOM_CLOCK_DIV(1),
+ .m = 16,
+ .n = 75,
+ .d_2 = 75,
+ },
+ {
+ .hz = 96 * MHz,
+ .src = SRC_GPLL0_EVEN_300MHZ,
+ .div = QCOM_CLOCK_DIV(1),
+ .m = 8,
+ .n = 25,
+ .d_2 = 25,
+ },
+ {
+ .hz = 100 * MHz,
+ .src = SRC_GPLL0_MAIN_600MHZ,
+ .div = QCOM_CLOCK_DIV(6),
+ },
+ {
+ .hz = SRC_XO_HZ, /* 19.2KHz */
+ .src = SRC_XO_19_2MHZ,
+ .div = QCOM_CLOCK_DIV(1),
+ },
+ {
+ .hz = SRC_XO_HZ, /* 19.2KHz */
+ .src = SRC_XO_19_2MHZ,
+ .div = QCOM_CLOCK_DIV(1),
+ },
+};
+
+static struct clock_freq_config sdcc1_core_cfg[] = {
+ {
+ .hz = 100 * MHz,
+ .src = SRC_GPLL0_EVEN_300MHZ,
+ .div = QCOM_CLOCK_DIV(3),
+ },
+ {
+ .hz = 192 * MHz,
+ .src = SRC_GPLL10_MAIN_384MHZ,
+ .div = QCOM_CLOCK_DIV(2),
+ },
+ {
+ .hz = 384 * MHz,
+ .src = SRC_GPLL10_MAIN_384MHZ,
+ .div = QCOM_CLOCK_DIV(1),
+ },
+};
+
+static struct clock_freq_config sdcc2_core_cfg[] = {
+ {
+ .hz = 50 * MHz,
+ .src = SRC_GPLL0_EVEN_300MHZ,
+ .div = QCOM_CLOCK_DIV(6),
+ },
+ {
+ .hz = 202 * MHz,
+ .src = SRC_GPLL9_MAIN_808MHZ,
+ .div = QCOM_CLOCK_DIV(4),
+ },
+};
+
+static struct pcie pcie_cfg[] = {
+ [PCIE_1_GDSC] = {
+ .gdscr = &gcc->pcie_1.gdscr,
+ },
+ [PCIE_1_SLV_Q2A_AXI_CLK] = {
+ .clk = &gcc->pcie_1.slv_q2a_axi_cbcr,
+ .clk_br_en = &gcc->apcs_clk_br_en,
+ .vote_bit = PCIE_1_SLV_Q2A_AXI_CLK_ENA,
+ },
+ [PCIE_1_SLV_AXI_CLK] = {
+ .clk = &gcc->pcie_1.slv_axi_cbcr,
+ .clk_br_en = &gcc->apcs_clk_br_en,
+ .vote_bit = PCIE_1_SLV_AXI_CLK_ENA,
+ },
+ [PCIE_1_MSTR_AXI_CLK] = {
+ .clk = &gcc->pcie_1.mstr_axi_cbcr,
+ .clk_br_en = &gcc->apcs_clk_br_en,
+ .vote_bit = PCIE_1_MSTR_AXI_CLK_ENA,
+ },
+ [PCIE_1_CFG_AHB_CLK] = {
+ .clk = &gcc->pcie_1.cfg_ahb_cbcr,
+ .clk_br_en = &gcc->apcs_clk_br_en,
+ .vote_bit = PCIE_1_CFG_AHB_CLK_ENA,
+ },
+ [PCIE_1_AUX_CLK] = {
+ .clk = &gcc->pcie_1.aux_cbcr,
+ .clk_br_en = &gcc->apcs_clk_br_en,
+ .vote_bit = PCIE_1_AUX_CLK_ENA,
+ },
+ [AGGRE_NOC_PCIE_TBU_CLK] = {
+ .clk = &gcc->aggre_noc_pcie_tbu_cbcr,
+ .clk_br_en = &gcc->apcs_clk_br_en,
+ .vote_bit = AGGRE_NOC_PCIE_TBU_CLK_ENA,
+ },
+ [AGGRE_NOC_PCIE_1_AXI_CLK] = {
+ .clk = &gcc->pcie_1.aggre_noc_pcie_axi_cbcr,
+ .clk_br_en = &gcc->apcs_clk_br_en,
+ .vote_bit = AGGRE_NOC_PCIE_1_AXI_CLK_ENA,
+ },
+ [DDRSS_PCIE_SF_CLK] = {
+ .clk = &gcc->pcie_1.ddrss_pcie_sf_cbcr,
+ .clk_br_en = &gcc->apcs_clk_br_en,
+ .vote_bit = DDRSS_PCIE_SF_CLK_ENA,
+ },
+ [PCIE1_PHY_RCHNG_CLK] = {
+ .clk = &gcc->pcie_1.phy_rchng_cbcr,
+ .clk_br_en = &gcc->apcs_clk_br_en,
+ .vote_bit = PCIE1_PHY_RCHNG_CLK_ENA,
+ },
+ [AGGRE_NOC_PCIE_CENTER_SF_AXI_CLK] = {
+ .clk = &gcc->pcie_1.aggre_noc_pcie_center_sf_axi_cbcr,
+ .clk_br_en = &gcc->apcs_clk_br_en1,
+ .vote_bit = AGGRE_NOC_PCIE_CENTER_SF_AXI_CLK_ENA,
+ },
+ [PCIE_1_PIPE_CLK] = {
+ .clk = &gcc->pcie_1.pipe_cbcr,
+ .clk_br_en = &gcc->apcs_clk_br_en,
+ .vote_bit = PCIE_1_PIPE_CLK_ENA,
+ },
+ [PCIE_CLKREF_EN] = {
+ .clk = &gcc->pcie_clkref_en,
+ .vote_bit = NO_VOTE_BIT,
+ },
+ [GCC_PCIE_1_PIPE_MUXR] = {
+ .clk = &gcc->pcie_1.pipe_muxr,
+ .vote_bit = NO_VOTE_BIT,
+ },
+};
+
+static struct clock_freq_config mdss_mdp_cfg[] = {
+ {
+ .hz = 200 * MHz,
+ .src = SRC_GCC_DISP_GPLL0_CLK,
+ .div = QCOM_CLOCK_DIV(3),
+ },
+ {
+ .hz = 300 * MHz,
+ .src = SRC_GCC_DISP_GPLL0_CLK,
+ .div = QCOM_CLOCK_DIV(2),
+ },
+};
+
+static struct clock_rcg_mnd *mdss_clock[MDSS_CLK_COUNT] = {
+ [MDSS_CLK_PCLK0] = &mdss->pclk0,
+ [MDSS_CLK_MDP] = &mdss->mdp,
+ [MDSS_CLK_VSYNC] = &mdss->vsync,
+ [MDSS_CLK_ESC0] = &mdss->esc0,
+ [MDSS_CLK_BYTE0] = &mdss->byte0,
+ [MDSS_CLK_BYTE0_INTF] = &mdss->byte0,
+ [MDSS_CLK_AHB] = &mdss->ahb,
+};
+
+static u32 *mdss_cbcr[MDSS_CLK_COUNT] = {
+ [GCC_DISP_AHB] = &gcc->disp_ahb_cbcr,
+ [GCC_DISP_HF_AXI] = &gcc->disp_hf_axi_cbcr,
+ [GCC_DISP_SF_AXI] = &gcc->disp_sf_axi_cbcr,
+ [MDSS_CLK_PCLK0] = &mdss->pclk0_cbcr,
+ [MDSS_CLK_MDP] = &mdss->mdp_cbcr,
+ [MDSS_CLK_VSYNC] = &mdss->vsync_cbcr,
+ [MDSS_CLK_BYTE0] = &mdss->byte0_cbcr,
+ [MDSS_CLK_BYTE0_INTF] = &mdss->byte0_intf_cbcr,
+ [MDSS_CLK_ESC0] = &mdss->esc0_cbcr,
+ [MDSS_CLK_AHB] = &mdss->ahb_cbcr,
+};
+
+static u32 *gdsc[MAX_GDSC] = {
+ [PCIE_1_GDSC] = &gcc->pcie_1.gdscr,
+ [MDSS_CORE_GDSC] = &mdss->core_gdsc,
+};
+
+static enum cb_err clock_configure_gpll0(void)
+{
+ struct alpha_pll_reg_val_config gpll0_cfg = {0};
+
+ gpll0_cfg.reg_user_ctl = &gcc->gpll0.user_ctl;
+ gpll0_cfg.user_ctl_val = (1 << PLL_POST_DIV_EVEN_SHFT |
+ 3 << PLL_POST_DIV_ODD_SHFT |
+ 1 << PLL_PLLOUT_EVEN_SHFT |
+ 1 << PLL_PLLOUT_MAIN_SHFT |
+ 1 << PLL_PLLOUT_ODD_SHFT);
+
+ return clock_configure_enable_gpll(&gpll0_cfg, false, 0);
+}
+
+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);
+}
+
+
+void clock_enable_qup(int qup)
+{
+ struct 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->cbcr, &gcc->apcs_clk_br_en1,
+ clk_en_off);
+ } else {
+ clk_en_off = QUPV3_WRAP1_CLK_ENA_1_S(s);
+ clock_enable_vote(&qup_clk->cbcr, &gcc->apcs_clk_br_en,
+ clk_en_off);
+ }
+}
+
+void clock_configure_sdcc(enum clk_sdcc sdcc, uint32_t hz)
+{
+ if (sdcc == SDCC1_CLK) {
+ if (hz > CLK_100MHZ) {
+ struct alpha_pll_reg_val_config gpll10_cfg = {0};
+ gpll10_cfg.reg_mode = &gcc->gpll10.mode;
+ gpll10_cfg.reg_opmode = &gcc->gpll10.opmode;
+ gpll10_cfg.reg_l = &gcc->gpll10.l;
+ gpll10_cfg.l_val = 0x14;
+ gpll10_cfg.reg_cal_l = &gcc->gpll10.cal_l;
+ gpll10_cfg.cal_l_val = 0x44;
+ gpll10_cfg.fsm_enable = true;
+ gpll10_cfg.reg_apcs_pll_br_en = &gcc->apcs_pll_br_en;
+ clock_configure_enable_gpll(&gpll10_cfg, true, 9);
+ }
+ clock_configure((struct clock_rcg *)&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 > CLK_100MHZ) {
+ struct alpha_pll_reg_val_config gpll9_cfg = {0};
+ gpll9_cfg.reg_mode = &gcc->gpll9.mode;
+ gpll9_cfg.reg_opmode = &gcc->gpll9.opmode;
+ gpll9_cfg.reg_alpha = &gcc->gpll9.alpha;
+ gpll9_cfg.alpha_val = 0x1555;
+ gpll9_cfg.reg_l = &gcc->gpll9.l;
+ gpll9_cfg.l_val = 0x2A;
+ gpll9_cfg.reg_cal_l = &gcc->gpll9.cal_l;
+ gpll9_cfg.cal_l_val = 0x44;
+ gpll9_cfg.fsm_enable = true;
+ gpll9_cfg.reg_apcs_pll_br_en = &gcc->apcs_pll_br_en;
+ clock_configure_enable_gpll(&gpll9_cfg, true, 8);
+ }
+ clock_configure((struct clock_rcg *)&gcc->sdcc2, sdcc2_core_cfg,
+ hz, ARRAY_SIZE(sdcc2_core_cfg));
+ clock_enable(&gcc->sdcc2_ahb_cbcr);
+ clock_enable(&gcc->sdcc2_apps_cbcr);
+ }
+}
+
+void clock_configure_dfsr(int qup)
+{
+ clock_configure_dfsr_table(qup, qupv3_wrap_cfg,
+ ARRAY_SIZE(qupv3_wrap_cfg));
+}
+
+static enum cb_err pll_init_and_set(struct sc7280_apss_clock *apss, u32 l_val)
+{
+ struct alpha_pll_reg_val_config pll_cfg = {0};
+ int ret;
+ u32 gfmux_val, regval;
+
+ pll_cfg.reg_l = &apss->pll.l;
+ pll_cfg.l_val = l_val;
+
+ 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;
+
+ regval = read32(&apss->pll.config_ctl_lo);
+ pll_cfg.config_ctl_val = regval &
+ (~(0x2 << K_P_SHFT | 0x2 << K_I_SHFT));
+
+ regval = read32(&apss->pll.config_ctl_hi);
+ pll_cfg.config_ctl_hi_val = (regval | (BIT(KLSB_SHFT) |
+ BIT(RON_MODE_SHFT))) & (~(0x4 << KLSB_SHFT));
+
+ regval = read32(&apss->pll.config_ctl_u1);
+ pll_cfg.config_ctl_hi1_val = (regval | BIT(FAST_LOCK_LOW_L_SHFT)) &
+ ~BIT(DCO_BIAS_ADJ_SHFT);
+
+ ret = clock_configure_enable_gpll(&pll_cfg, false, 0);
+ if (ret != CB_SUCCESS)
+ return CB_ERR;
+
+ pll_cfg.reg_mode = &apss->pll.mode;
+ pll_cfg.reg_opmode = &apss->pll.opmode;
+ pll_cfg.reg_user_ctl = &apss->pll.user_ctl;
+
+ ret = zonda_pll_enable(&pll_cfg);
+ if (ret != CB_SUCCESS)
+ return CB_ERR;
+
+ gfmux_val = read32(&apss->cfg_gfmux) & ~GFMUX_SRC_SEL_BMSK;
+ gfmux_val |= APCS_SRC_EARLY;
+ write32(&apss->cfg_gfmux, gfmux_val);
+
+ return CB_SUCCESS;
+}
+
+enum cb_err clock_enable_gdsc(enum clk_gdsc gdsc_type)
+{
+ if (gdsc_type > MAX_GDSC)
+ return CB_ERR;
+
+ return enable_and_poll_gdsc_status(gdsc[gdsc_type]);
+}
+
+enum cb_err mdss_clock_configure(enum clk_mdss clk_type, uint32_t hz,
+ uint32_t source, uint32_t divider, uint32_t m,
+ uint32_t n, uint32_t d_2)
+{
+ struct clock_freq_config mdss_clk_cfg;
+ uint32_t idx;
+
+ if (clk_type >= MDSS_CLK_COUNT)
+ return CB_ERR;
+
+ /* Initialize it with received arguments */
+ mdss_clk_cfg.div = divider ? QCOM_CLOCK_DIV(divider) : 0;
+
+ if (clk_type == MDSS_CLK_MDP) {
+ for (idx = 0; idx < ARRAY_SIZE(mdss_mdp_cfg); idx++) {
+ if (hz <= mdss_mdp_cfg[idx].hz) {
+ source = mdss_mdp_cfg[idx].src;
+ mdss_clk_cfg.div = mdss_mdp_cfg[idx].div;
+ m = 0;
+ break;
+ }
+ }
+ }
+ mdss_clk_cfg.src = source;
+ mdss_clk_cfg.m = m;
+ mdss_clk_cfg.n = n;
+ mdss_clk_cfg.d_2 = d_2;
+
+ return clock_configure((struct clock_rcg *)mdss_clock[clk_type],
+ &mdss_clk_cfg, hz, 0);
+}
+
+enum cb_err mdss_clock_enable(enum clk_mdss clk_type)
+{
+ if (clk_type >= MDSS_CLK_COUNT)
+ return CB_ERR;
+
+ /* Enable clock*/
+ return clock_enable(mdss_cbcr[clk_type]);
+}
+
+enum cb_err clock_enable_pcie(enum clk_pcie clk_type)
+{
+ int clk_vote_bit;
+
+ if (clk_type >= PCIE_CLK_COUNT)
+ return CB_ERR;
+
+ clk_vote_bit = pcie_cfg[clk_type].vote_bit;
+ if (clk_vote_bit < 0)
+ return clock_enable(pcie_cfg[clk_type].clk);
+
+ clock_enable_vote(pcie_cfg[clk_type].clk,
+ pcie_cfg[clk_type].clk_br_en,
+ pcie_cfg[clk_type].vote_bit);
+
+ return CB_SUCCESS;
+}
+
+enum cb_err clock_configure_mux(enum clk_pcie clk_type, u32 src_type)
+{
+ if (clk_type >= PCIE_CLK_COUNT)
+ return CB_ERR;
+
+ /* Set clock src */
+ write32(pcie_cfg[clk_type].clk, src_type);
+
+ 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 5b515bd2d1..82c84ae2f8 100644
--- a/src/soc/qualcomm/sc7280/include/soc/addressmap.h
+++ b/src/soc/qualcomm/sc7280/include/soc/addressmap.h
@@ -5,6 +5,13 @@
#include <stdint.h>
+#define AOSS_CC_BASE 0x0C2A0000
+#define DISP_CC_BASE 0x0AF00000
+#define GCC_BASE 0x00100000
+#define L3_PLL_BASE 0x18284000
+#define QSPI_BASE 0x088DC000
+#define SHRM_SPROC_BASE 0x09051000
+#define SILVER_PLL_BASE 0x18280000
#define TLMM_TILE_BASE 0x0F100000
#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 0000000000..a0694ba6bc
--- /dev/null
+++ b/src/soc/qualcomm/sc7280/include/soc/clock.h
@@ -0,0 +1,390 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <soc/addressmap.h>
+#include <types.h>
+#include <soc/clock_common.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 CLK_100MHZ (100 * MHz)
+
+/* CPU PLL */
+#define L_VAL_1516P8MHz 0x4F
+#define L_VAL_1190P4MHz 0x3E
+
+#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)
+
+enum clk_pll_src {
+ SRC_XO_19_2MHZ = 0,
+ SRC_GPLL0_MAIN_600MHZ = 1,
+ SRC_GPLL9_MAIN_808MHZ = 2,
+ SRC_GCC_DISP_GPLL0_CLK = 4,
+ SRC_GPLL10_MAIN_384MHZ = 5,
+ SRC_GPLL0_EVEN_300MHZ = 6,
+};
+
+enum clk_pcie_src_sel {
+ PCIE_1_PIPE_SRC_SEL = 0,
+ PCIE_1_XO_SRC_SEL = 2,
+};
+
+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,
+ AGGRE_NOC_PCIE_1_AXI_CLK_ENA = 11,
+ QUPV3_WRAP1_CORE_2X_CLK_ENA = 18,
+ AGGRE_NOC_PCIE_TBU_CLK_ENA = 18,
+ QUPV3_WRAP1_CORE_CLK_ENA = 19,
+ DDRSS_PCIE_SF_CLK_ENA = 19,
+ QUPV3_WRAP_1_M_AHB_CLK_ENA = 20,
+ QUPV3_WRAP_1_S_AHB_CLK_ENA = 21,
+ PCIE1_PHY_RCHNG_CLK_ENA = 23,
+ PCIE_1_SLV_Q2A_AXI_CLK_ENA = 25,
+ PCIE_1_SLV_AXI_CLK_ENA = 26,
+ PCIE_1_MSTR_AXI_CLK_ENA = 27,
+ PCIE_1_CFG_AHB_CLK_ENA = 28,
+ AGGRE_NOC_PCIE_CENTER_SF_AXI_CLK_ENA = 28,
+ PCIE_1_AUX_CLK_ENA = 29,
+ PCIE_1_PIPE_CLK_ENA = 30,
+ NO_VOTE_BIT = -1,
+};
+
+struct sc7280_gpll {
+ u32 mode;
+ u32 l;
+ u32 cal_l;
+ 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;
+};
+
+struct sc7280_disp_cc {
+ u8 _res0[0x1004];
+ u32 core_gdsc;
+ u8 _res1[0x1010 - 0x1008];
+ u32 pclk0_cbcr;
+ u32 mdp_cbcr;
+ u8 _res2[0x102c - 0x1018];
+ u32 vsync_cbcr;
+ u32 byte0_cbcr;
+ u32 byte0_intf_cbcr;
+ u32 esc0_cbcr;
+ u8 _res3[0x1050 - 0x103c];
+ u32 ahb_cbcr;
+ u8 _res4[0x1078 - 0x1054];
+ struct clock_rcg_mnd pclk0;
+ u8 _res5[0x1090 - 0x108c];
+ struct clock_rcg_mnd mdp;
+ u8 _res6[0x10c0 - 0x1098];
+ struct clock_rcg_mnd vsync;
+ u8 _res7[0x10d8 - 0x10c8];
+ struct clock_rcg_mnd byte0;
+ u8 _res8[0x10f4 - 0x10ec];
+ struct clock_rcg_mnd esc0;
+ u8 _res9[0x1170 - 0x1108];
+ struct clock_rcg_mnd ahb;
+ u8 _res10[0x20000 - 0x1178];
+};
+check_member(sc7280_disp_cc, pclk0_cbcr, 0x1010);
+check_member(sc7280_disp_cc, vsync_cbcr, 0x102c);
+check_member(sc7280_disp_cc, ahb_cbcr, 0x1050);
+
+struct sc7280_pcie {
+ u32 pcie_1_bcr;
+ u32 gdscr;
+ u8 _res1[0x18d010 - 0x18d008];
+ u32 slv_q2a_axi_cbcr;
+ u32 slv_axi_cbcr;
+ u8 _res2[0x18d01c - 0x18d018];
+ u32 mstr_axi_cbcr;
+ u8 _res3[0x18d024 - 0x18d020];
+ u32 cfg_ahb_cbcr;
+ u32 aux_cbcr;
+ u8 _res4[0x18d030 - 0x18d02c];
+ u32 pipe_cbcr;
+ u8 _res5[0x18d038 - 0x18d034];
+ u32 phy_rchng_cbcr;
+ u8 _res6[0x18d054 - 0x18d03c];
+ u32 pipe_muxr;
+ u8 _res7[0x18d080 - 0x18d058];
+ u32 ddrss_pcie_sf_cbcr;
+ u32 aggre_noc_pcie_axi_cbcr;
+ u32 aggre_noc_pcie_center_sf_axi_cbcr;
+ u8 _res8[0x18e01c - 0x18d08c];
+ u32 phy_bcr;
+};
+check_member(sc7280_pcie, slv_q2a_axi_cbcr, 0x10);
+check_member(sc7280_pcie, mstr_axi_cbcr, 0x1c);
+check_member(sc7280_pcie, pipe_cbcr, 0x30);
+check_member(sc7280_pcie, ddrss_pcie_sf_cbcr, 0x80);
+check_member(sc7280_pcie, phy_bcr, 0x101c);
+
+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 clock_rcg_mnd sdcc2;
+ u8 _res3[0x16004 - 0x14020];
+ u32 sdcc4_apps_cbcr;
+ u32 sdcc4_ahb_cbcr;
+ struct clock_rcg_mnd sdcc4;
+ u8 _res4[0x17000 - 0x16020];
+ u32 qup_wrap0_bcr;
+ u32 qup_wrap0_m_ahb_cbcr;
+ u32 qup_wrap0_s_ahb_cbcr;
+ struct 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 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 clock_rcg 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 clock_rcg qup_wrap1_core_2x;
+ u8 _res10[0x27004 - 0x2314c];
+ u32 disp_ahb_cbcr;
+ u8 _res11[0x2700c - 0x27008];
+ u32 disp_hf_axi_cbcr;
+ u8 _res12[0x27014 - 0x27010];
+ u32 disp_sf_axi_cbcr;
+ u8 _res13[0x4b000 - 0x27018];
+ u32 qspi_bcr;
+ u32 qspi_cnoc_ahb_cbcr;
+ u32 qspi_core_cbcr;
+ struct clock_rcg qspi_core;
+ u8 _res14[0x50000 - 0x4b014];
+ u32 usb3_phy_prim_bcr;
+ u32 usb3phy_phy_prim_bcr;
+ u32 usb3_dp_phy_prim_bcr;
+ u8 _res15[0x52000 - 0x5000c];
+ u32 apcs_clk_br_en;
+ u8 _res16[0x52008 - 0x52004];
+ u32 apcs_clk_br_en1;
+ u8 _res17[0x52010 - 0x5200c];
+ u32 apcs_pll_br_en;
+ u8 _res18[0x6a000 - 0x52014];
+ u32 usb_phy_cfg_ahb2phy_bcr;
+ u8 _res19[0x75004 - 0x6a004];
+ u32 sdcc1_ahb_cbcr;
+ u32 sdcc1_apps_cbcr;
+ struct clock_rcg_mnd sdcc1;
+ u8 _res20[0x8c004 - 0x75020];
+ u32 pcie_clkref_en;
+ u8 _res21[0x8d000 - 0x8c008];
+ struct sc7280_pcie pcie_1;
+ u8 _res22[0x90010 - 0x8e020];
+ u32 aggre_noc_pcie_tbu_cbcr;
+ u8 _res23[0x9e000 - 0x90014];
+ u32 usb30_sec_bcr;
+ u8 _res24[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, pcie_clkref_en, 0x8c004);
+check_member(sc7280_gcc, aggre_noc_pcie_tbu_cbcr, 0x90010);
+check_member(sc7280_gcc, usb30_sec_bcr, 0x9e000);
+
+
+struct sc7280_apss_pll {
+ u32 mode;
+ u32 l;
+ u32 alpha;
+ 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 sc7280_apss_clock {
+ struct sc7280_apss_pll pll;
+ u8 _res0[0x84 - 0x3c];
+ u32 cfg_gfmux;
+};
+
+struct pcie {
+ uint32_t *gdscr;
+ uint32_t *clk;
+ uint32_t *clk_br_en;
+ int vote_bit;
+};
+
+enum clk_sdcc {
+ SDCC1_CLK,
+ SDCC2_CLK,
+};
+
+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 clk_gdsc {
+ MDSS_CORE_GDSC,
+ PCIE_1_GDSC,
+ MAX_GDSC
+};
+
+enum clk_mdss {
+ GCC_DISP_AHB,
+ GCC_DISP_HF_AXI,
+ GCC_DISP_SF_AXI,
+ MDSS_CLK_PCLK0,
+ MDSS_CLK_MDP,
+ MDSS_CLK_VSYNC,
+ MDSS_CLK_BYTE0,
+ MDSS_CLK_BYTE0_INTF,
+ MDSS_CLK_ESC0,
+ MDSS_CLK_AHB,
+ MDSS_CLK_COUNT
+};
+
+enum clk_pcie {
+ PCIE_1_SLV_Q2A_AXI_CLK,
+ PCIE_1_SLV_AXI_CLK,
+ PCIE_1_MSTR_AXI_CLK,
+ PCIE_1_CFG_AHB_CLK,
+ PCIE_1_AUX_CLK,
+ AGGRE_NOC_PCIE_TBU_CLK,
+ AGGRE_NOC_PCIE_1_AXI_CLK,
+ DDRSS_PCIE_SF_CLK,
+ PCIE1_PHY_RCHNG_CLK,
+ AGGRE_NOC_PCIE_CENTER_SF_AXI_CLK,
+ PCIE_1_PIPE_CLK,
+ PCIE_CLKREF_EN,
+ GCC_PCIE_1_PIPE_MUXR,
+ PCIE_CLK_COUNT,
+};
+
+enum subsystem_reset {
+ AOP_RESET_SHFT = 0,
+ SHRM_RUN_STALL = 0,
+};
+
+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 apss_gfmux {
+ GFMUX_SRC_SEL_BMSK = 0x3,
+ APCS_SRC_EARLY = 0x2,
+};
+
+static struct sc7280_gcc *const gcc = (void *)GCC_BASE;
+static struct sc7280_apss_clock *const apss_silver = (void *)SILVER_PLL_BASE;
+static struct sc7280_apss_clock *const apss_l3 = (void *)L3_PLL_BASE;
+static struct sc7280_disp_cc *const mdss = (void *)DISP_CC_BASE;
+
+void clock_init(void);
+void clock_configure_qspi(uint32_t hz);
+void clock_enable_qup(int qup);
+void clock_configure_sdcc(enum clk_sdcc, uint32_t hz);
+void clock_configure_dfsr(int qup);
+int clock_enable_gdsc(enum clk_gdsc gdsc_type);
+
+int mdss_clock_configure(enum clk_mdss clk_type, uint32_t hz,
+ uint32_t source, uint32_t divider,
+ uint32_t m, uint32_t n, uint32_t d);
+int mdss_clock_enable(enum clk_mdss clk_type);
+int clock_enable_pcie(enum clk_pcie clk_type);
+int clock_configure_mux(enum clk_pcie clk_type, u32 src_type);
+
+/* Subsystem Reset */
+static struct aoss *const aoss = (void *)AOSS_CC_BASE;
+static struct shrm *const shrm = (void *)SHRM_SPROC_BASE;
+
+#define clock_reset_aop() \
+ clock_reset_subsystem(&aoss->aoss_cc_apcs_misc, AOP_RESET_SHFT)
+#define clock_reset_shrm() \
+ clock_reset_subsystem(&shrm->shrm_sproc_ctrl, SHRM_RUN_STALL)
+
+#endif // __SOC_QUALCOMM_SC7280_CLOCK_H__