soc/qualcomm/x1p42100: Add Clock support for x1p42100

Add support to enable QUPV3, QSPI and GPLL0 clocks. Modify
XO Source clock frequency value to 19.2KHz. The register
details are part of HRD-X1P42100-S1 document.
https://docs.qualcomm.com/bundle/resource/topics/HRD-X1P42100-S1/

TEST=Create an image.serial.bin and ensure it boots on X1P42100

Change-Id: I6252bc1fda3c53a683c65d2ab4a3b9f27ea64618
Signed-off-by: Swathi Tamilselvan <tswathi@qualcomm.corp-partner.google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/88175
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Kapil Porwal <kapilporwal@google.com>
Reviewed-by: Subrata Banik <subratabanik@google.com>
This commit is contained in:
Swathi Tamilselvan 2025-06-27 16:34:11 +05:30 committed by Subrata Banik
commit 8d8d0f9746
5 changed files with 305 additions and 5 deletions

View file

@ -22,6 +22,7 @@ config SOC_QUALCOMM_X1P42100
select MAINBOARD_FORCE_NATIVE_VGA_INIT
select MAINBOARD_HAS_NATIVE_VGA_INIT
select PCI
select QC_COMMON_QUPV3_2
select NO_ECAM_MMCONF_SUPPORT
select SDHCI_CONTROLLER
select SOC_QUALCOMM_COMMON

View file

@ -6,6 +6,7 @@ decompressor-y += mmu.c
decompressor-y += ../common/timer.c
all-y += ../common/timer.c
all-y += ../common/gpio.c
all-y += ../common/clock.c
all-y += clock.c
all-y += ../common/spi.c
all-y += ../common/qspi.c

View file

@ -1,23 +1,185 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h>
#include <commonlib/helpers.h>
#include <device/mmio.h>
#include <soc/clock.h>
#include <types.h>
static struct clock_freq_config qspi_core_cfg[] = {
{
.hz = SRC_XO_HZ, /* 19.2MHz */
.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.2MHz */
.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),
},
};
void clock_configure_qspi(uint32_t hz)
{
/* placeholder */
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)
{
/* placeholder */
struct qupv3_clock *qup_clk;
int s = qup % QUP_WRAP1_S0, clk_en_off;
void *clk_br_en_ptr = NULL; // Pointer to the correct apcs_clk_br_enX
qup_clk = qup < QUP_WRAP1_S0 ? &gcc->qup_wrap0_s[s] : qup < QUP_WRAP2_S0 ?
&gcc->qup_wrap1_s[s] : &gcc->qup_wrap2_s[s];
if (qup <= QUP_WRAP0_S7) {
clk_en_off = QUPV3_WRAP0_CLK_ENA_S(s);
clk_br_en_ptr = &gcc->apcs_clk_br_en4;
} else if (qup >= QUP_WRAP1_S0 && qup <= QUP_WRAP1_S6) {
clk_en_off = QUPV3_WRAP1_CLK_ENA_S(s);
clk_br_en_ptr = &gcc->apcs_clk_br_en1;
} else if (qup >= QUP_WRAP2_S0 && qup <= QUP_WRAP2_S6) {
clk_en_off = QUPV3_WRAP2_CLK_ENA_S(s);
clk_br_en_ptr = &gcc->apcs_clk_br_en2;
} else if (qup == QUP_WRAP1_S7 || qup == QUP_WRAP2_S7) {
clk_en_off = qup == QUP_WRAP1_S7 ? QUPV3_WRAP1_SE7_CLK_ENA : QUPV3_WRAP2_SE7_CLK_ENA;
clk_br_en_ptr = &gcc->apcs_clk_br_en2;
}
/* Only call if a valid pointer was assigned */
if (clk_br_en_ptr)
clock_enable_vote(&qup_clk->cbcr, clk_br_en_ptr, clk_en_off);
}
void clock_configure_dfsr(int qup)
{
/* placeholder */
clock_configure_dfsr_table(qup, qupv3_wrap_cfg,
ARRAY_SIZE(qupv3_wrap_cfg));
}
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 = (read32(gpll0_cfg.reg_user_ctl) |
1 << PLL_POST_DIV_EVEN_SHFT_X1P42100 |
2 << PLL_POST_DIV_ODD_SHFT_X1P42100 |
1 << PLL_PLLOUT_EVEN_SHFT_X1P42100 |
1 << PLL_PLLOUT_MAIN_SHFT_X1P42100 |
1 << PLL_PLLOUT_ODD_SHFT_X1P42100);
return clock_configure_enable_gpll(&gpll0_cfg, false, 0);
}
static void speed_up_boot_cpu(void)
{
/* Placeholder */
}
void clock_init(void)
{
/* placeholder */
clock_configure_gpll0();
clock_enable_vote(&gcc->qup_wrap0_core_2x_cbcr,
&gcc->apcs_clk_br_en4,
QUPV3_WRAP0_CORE_2X_CLK_ENA);
clock_enable_vote(&gcc->qup_wrap0_core_cbcr,
&gcc->apcs_clk_br_en4,
QUPV3_WRAP0_CORE_CLK_ENA);
clock_enable_vote(&gcc->qup_wrap0_m_ahb_cbcr,
&gcc->apcs_clk_br_en4,
QUPV3_WRAP_0_M_AHB_CLK_ENA);
clock_enable_vote(&gcc->qup_wrap0_s_ahb_cbcr,
&gcc->apcs_clk_br_en4,
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);
clock_enable_vote(&gcc->qup_wrap2_core_2x_cbcr,
&gcc->apcs_clk_br_en2,
QUPV3_WRAP2_CORE_2X_CLK_ENA);
clock_enable_vote(&gcc->qup_wrap2_core_cbcr,
&gcc->apcs_clk_br_en2,
QUPV3_WRAP2_CORE_CLK_ENA);
clock_enable_vote(&gcc->qup_wrap2_m_ahb_cbcr,
&gcc->apcs_clk_br_en2,
QUPV3_WRAP_2_M_AHB_CLK_ENA);
clock_enable_vote(&gcc->qup_wrap2_s_ahb_cbcr,
&gcc->apcs_clk_br_en2,
QUPV3_WRAP_2_S_AHB_CLK_ENA);
speed_up_boot_cpu();
}

View file

@ -8,6 +8,7 @@
#define AOSS_CC_BASE 0x0C2A0000
#define QSPI_BASE 0x088DC000
#define TLMM_TILE_BASE 0x0F100000
#define GCC_BASE 0x00100000
/* X1P42100 QSPI GPIO PINS */
#define QSPI_CS GPIO(132)

View file

@ -7,7 +7,141 @@
#ifndef __SOC_QUALCOMM_X1P42100_CLOCK_H__
#define __SOC_QUALCOMM_X1P42100_CLOCK_H__
#define SRC_XO_HZ (38400 * KHz)
#define SRC_XO_HZ (19200 * KHz)
#define GPLL0_EVEN_HZ (300 * MHz)
#define GPLL0_MAIN_HZ (600 * MHz)
#define CLK_100MHZ (100 * MHz)
#define QUPV3_WRAP0_CLK_ENA_S(idx) (10 + idx)
#define QUPV3_WRAP1_CLK_ENA_S(idx) (22 + idx)
#define QUPV3_WRAP2_CLK_ENA_S(idx) (4 + idx)
#define QUPV3_WRAP1_SE7_CLK_ENA 16
#define QUPV3_WRAP2_SE7_CLK_ENA 17
enum clk_ctl_gpll_user_ctl_x1p42100 {
PLL_PLLOUT_MAIN_SHFT_X1P42100 = 0,
PLL_PLLOUT_EVEN_SHFT_X1P42100 = 1,
PLL_PLLOUT_ODD_SHFT_X1P42100 = 2,
PLL_POST_DIV_EVEN_SHFT_X1P42100 = 10,
PLL_POST_DIV_ODD_SHFT_X1P42100 = 14,
};
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 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,
QUPV3_WRAP2_CORE_2X_CLK_ENA = 3,
QUPV3_WRAP2_CORE_CLK_ENA = 0,
QUPV3_WRAP_2_M_AHB_CLK_ENA = 2,
QUPV3_WRAP_2_S_AHB_CLK_ENA = 1,
};
struct x1p42100_gpll {
u32 mode;
u32 opmode;
u32 state;
u32 status;
u32 l;
u32 alpha;
u32 user_ctl;
u32 user_ctl_u;
u32 config_ctl;
u32 config_ctl_u;
u32 config_ctl_u1;
};
struct x1p42100_gcc {
struct x1p42100_gpll gpll0;
u8 _res1[0x18004 - 0x0002c];
struct qupv3_clock qup_wrap1_s[8];
u8 _res2[0x1e004 - 0x189c4];
struct qupv3_clock qup_wrap2_s[8];
u8 _res3[0x23000 - 0x1e9c4];
u32 qup_wrap0_m_ahb_cbcr;
u32 qup_wrap0_s_ahb_cbcr;
u32 qup_wrap0_core_cbcr;
u8 _res4[0x23014 - 0x2300c];
u32 qup_wrap0_core_cdivr;
u32 qup_wrap0_core_2x_cbcr;
u8 _res5[0x23024 - 0x2301c];
struct clock_rcg qup_wrap0_core_2x;
u8 _res6[0x23150 - 0x2302c];
u32 qup_wrap1_m_ahb_cbcr;
u32 qup_wrap1_s_ahb_cbcr;
u32 qup_wrap1_core_cbcr;
u8 _res7[0x23164 - 0x2315c];
u32 qup_wrap1_core_cdivr;
u32 qup_wrap1_core_2x_cbcr;
u8 _res8[0x23174 - 0x2316c];
struct clock_rcg qup_wrap1_core_2x;
u8 _res9[0x232a0 - 0x2317c];
u32 qup_wrap2_m_ahb_cbcr;
u32 qup_wrap2_s_ahb_cbcr;
u32 qup_wrap2_core_cbcr;
u8 _res10[0x232b4 - 0x232ac];
u32 qup_wrap2_core_cdivr;
u32 qup_wrap2_core_2x_cbcr;
u8 _res11[0x232c4 - 0x232bc];
struct clock_rcg qup_wrap2_core_2x;
u8 _res12[0x42004 - 0x232cc];
struct qupv3_clock qup_wrap0_s[8];
u8 _res13[0x4b000 - 0x429c4];
u32 qspi_bcr;
u32 qspi_cnoc_ahb_cbcr;
u32 qspi_core_cbcr;
struct clock_rcg qspi_core;
u8 _res14[0x52000 - 0x4b014];
u32 apcs_clk_br_en;
u8 _res15[0x52008 - 0x52004];
u32 apcs_clk_br_en1;
u8 _res16[0x52010 - 0x5200C];
u32 apcs_clk_br_en2;
u8 _res17[0x52018 - 0x52014];
u32 apcs_clk_br_en3;
u8 _res18[0x52020 - 0x5201c];
u32 apcs_clk_br_en4;
u8 _res19[0x52028 - 0x52024];
u32 apcs_clk_br_en5;
u8 _res20[0x52030 - 0x5202c];
u32 apcs_pll_br_en;
};
check_member(x1p42100_gcc, qup_wrap1_s, 0x18004);
check_member(x1p42100_gcc, qup_wrap2_s, 0x1e004);
check_member(x1p42100_gcc, qup_wrap0_m_ahb_cbcr, 0x23000);
check_member(x1p42100_gcc, qup_wrap0_core_cdivr, 0x23014);
check_member(x1p42100_gcc, qup_wrap0_core_2x, 0x23024);
check_member(x1p42100_gcc, qup_wrap1_m_ahb_cbcr, 0x23150);
check_member(x1p42100_gcc, qup_wrap1_core_cdivr, 0x23164);
check_member(x1p42100_gcc, qup_wrap1_core_2x, 0x23174);
check_member(x1p42100_gcc, qup_wrap2_m_ahb_cbcr, 0x232a0);
check_member(x1p42100_gcc, qup_wrap2_core_cdivr, 0x232b4);
check_member(x1p42100_gcc, qup_wrap2_core_2x, 0x232c4);
check_member(x1p42100_gcc, qup_wrap0_s, 0x42004);
check_member(x1p42100_gcc, qspi_bcr, 0x4b000);
check_member(x1p42100_gcc, apcs_clk_br_en, 0x52000);
check_member(x1p42100_gcc, apcs_clk_br_en1, 0x52008);
check_member(x1p42100_gcc, apcs_clk_br_en2, 0x52010);
check_member(x1p42100_gcc, apcs_clk_br_en3, 0x52018);
check_member(x1p42100_gcc, apcs_clk_br_en4, 0x52020);
check_member(x1p42100_gcc, apcs_clk_br_en5, 0x52028);
check_member(x1p42100_gcc, apcs_pll_br_en, 0x52030);
enum clk_qup {
QUP_WRAP0_S0,
@ -44,5 +178,6 @@ void clock_configure_dfsr(int qup);
/* Subsystem Reset */
static struct aoss *const aoss = (void *)AOSS_CC_BASE;
static struct x1p42100_gcc *const gcc = (void *)GCC_BASE;
#endif // __SOC_QUALCOMM_X1P42100_CLOCK_H__