diff --git a/src/soc/qualcomm/x1p42100/Kconfig b/src/soc/qualcomm/x1p42100/Kconfig index cb32c2f8b3..8ae8beadde 100644 --- a/src/soc/qualcomm/x1p42100/Kconfig +++ b/src/soc/qualcomm/x1p42100/Kconfig @@ -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 diff --git a/src/soc/qualcomm/x1p42100/Makefile.mk b/src/soc/qualcomm/x1p42100/Makefile.mk index 3140ea2445..da3c25b005 100644 --- a/src/soc/qualcomm/x1p42100/Makefile.mk +++ b/src/soc/qualcomm/x1p42100/Makefile.mk @@ -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 diff --git a/src/soc/qualcomm/x1p42100/clock.c b/src/soc/qualcomm/x1p42100/clock.c index 5e9706f698..283428642e 100644 --- a/src/soc/qualcomm/x1p42100/clock.c +++ b/src/soc/qualcomm/x1p42100/clock.c @@ -1,23 +1,185 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +#include +#include +#include #include +#include + +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(); + } diff --git a/src/soc/qualcomm/x1p42100/include/soc/addressmap.h b/src/soc/qualcomm/x1p42100/include/soc/addressmap.h index a119d17295..818b3463b4 100644 --- a/src/soc/qualcomm/x1p42100/include/soc/addressmap.h +++ b/src/soc/qualcomm/x1p42100/include/soc/addressmap.h @@ -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) diff --git a/src/soc/qualcomm/x1p42100/include/soc/clock.h b/src/soc/qualcomm/x1p42100/include/soc/clock.h index bb327709af..f9848c697a 100644 --- a/src/soc/qualcomm/x1p42100/include/soc/clock.h +++ b/src/soc/qualcomm/x1p42100/include/soc/clock.h @@ -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__