From 5dd120810b1ce8eed227ed0d85f944466ff911f6 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Tue, 13 Jun 2023 16:54:54 +0200 Subject: [PATCH 1/5] debugcc: support 32 bit systems Unsigned long have a different size in 32 bit system and this cause the malfunction of debugcc returning wrong frequency. Use 64bit unsigned int to correctly support 32 bit system and provide correct frequency. Signed-off-by: Christian Marangi --- debugcc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debugcc.c b/debugcc.c index 047cd6c..e82c841 100644 --- a/debugcc.c +++ b/debugcc.c @@ -116,8 +116,8 @@ void mux_disable(struct debug_mux *mux) unsigned long measure_gcc(const struct measure_clk *clk, const struct debug_mux *mux) { - unsigned long raw_count_short; - unsigned long raw_count_full; + uint64_t raw_count_short; + uint64_t raw_count_full; struct gcc_mux *gcc = container_of(mux, struct gcc_mux, mux); unsigned long xo_div4; From bde23d9858ca5b214fbaaf5815b213ed5bf9b8d1 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Tue, 13 Jun 2023 17:00:41 +0200 Subject: [PATCH 2/5] debugcc: support setting xo_div4 custom value Some xo require special value to set it to /4 divisor. Introduce xo_div4_val to handle this special implementation. Signed-off-by: Christian Marangi --- debugcc.c | 5 ++++- debugcc.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/debugcc.c b/debugcc.c index e82c841..0071647 100644 --- a/debugcc.c +++ b/debugcc.c @@ -122,7 +122,10 @@ unsigned long measure_gcc(const struct measure_clk *clk, unsigned long xo_div4; xo_div4 = readl(mux->base + gcc->xo_div4_reg); - writel(xo_div4 | 1, mux->base + gcc->xo_div4_reg); + if (gcc->xo_div4_val) + writel(xo_div4 | gcc->xo_div4_val, mux->base + gcc->xo_div4_reg); + else + writel(xo_div4 | 1, mux->base + gcc->xo_div4_reg); raw_count_short = measure_ticks(gcc, 0x1000); raw_count_full = measure_ticks(gcc, 0x10000); diff --git a/debugcc.h b/debugcc.h index 8cb220e..517a2ca 100644 --- a/debugcc.h +++ b/debugcc.h @@ -66,6 +66,8 @@ struct gcc_mux { struct debug_mux mux; unsigned int xo_div4_reg; + unsigned int xo_div4_val; + unsigned int debug_ctl_reg; unsigned int debug_status_reg; }; From 93f5ccd03793aa678ea01e2f1891e39a3e264ad5 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Tue, 13 Jun 2023 17:02:32 +0200 Subject: [PATCH 3/5] debugcc: supports custom xo rate Some device have a different rate for the xo debug oscillator. Add support for defining custom xo rate in the primary debug mux. Signed-off-by: Christian Marangi --- debugcc.c | 6 +++++- debugcc.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/debugcc.c b/debugcc.c index 0071647..0299964 100644 --- a/debugcc.c +++ b/debugcc.c @@ -116,11 +116,15 @@ void mux_disable(struct debug_mux *mux) unsigned long measure_gcc(const struct measure_clk *clk, const struct debug_mux *mux) { + unsigned int xo_rate = 4800000; uint64_t raw_count_short; uint64_t raw_count_full; struct gcc_mux *gcc = container_of(mux, struct gcc_mux, mux); unsigned long xo_div4; + if (gcc->xo_rate) + xo_rate = gcc->xo_rate; + xo_div4 = readl(mux->base + gcc->xo_div4_reg); if (gcc->xo_div4_val) writel(xo_div4 | gcc->xo_div4_val, mux->base + gcc->xo_div4_reg); @@ -136,7 +140,7 @@ unsigned long measure_gcc(const struct measure_clk *clk, return 0; } - raw_count_full = ((raw_count_full * 10) + 15) * 4800000; + raw_count_full = ((raw_count_full * 10) + 15) * xo_rate; raw_count_full = raw_count_full / ((0x10000 * 10) + 35); if (mux->div_val) diff --git a/debugcc.h b/debugcc.h index 517a2ca..df9981a 100644 --- a/debugcc.h +++ b/debugcc.h @@ -65,6 +65,8 @@ struct debug_mux { struct gcc_mux { struct debug_mux mux; + unsigned int xo_rate; + unsigned int xo_div4_reg; unsigned int xo_div4_val; From 776a4f281e077b81931e95bc29f6e2068f175ec1 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Wed, 8 Nov 2023 12:26:27 +0100 Subject: [PATCH 4/5] debugcc: add convenient macro GENMASK to calculate mask from bits Add convenient macro GENMASK to calculate masks from bits similar to how it's implemented in kernel linux tools. This is useful to better describe some specific define instead of using comments and raw HEX values. Signed-off-by: Christian Marangi --- debugcc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/debugcc.h b/debugcc.h index df9981a..b165865 100644 --- a/debugcc.h +++ b/debugcc.h @@ -32,6 +32,7 @@ #define __DEBUGCC_H__ #define BIT(x) (1 << (x)) +#define GENMASK(h, l) (((~0UL) << (l)) & (~0UL >> (sizeof(long) * 8 - 1 - (h)))) #define CORE_CC_BLOCK "core" From a601807faeec0224af2655dd73c9ca154fa740de Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Tue, 13 Jun 2023 17:38:16 +0200 Subject: [PATCH 5/5] Add support for IPQ8064 SoC Add support for IPQ8064 SoC. All the debug vector are taken from old pre-dt linux-msm source. To correctly setup the debug oscillator, it's required to operate on 2 different clk, the CXO oscillator and the PDM clock. Then we operate ton the CLK_TEST reg and we setup the required vector. With the use of define we abstract everything for the high speed and the low speed clocks. The CXO oscillator runs at 25Mhz and a different xo_rate is required than the current default one. We can also test the 2 CPU speed and the current L2 speed using the APCS CLK_DIAG reg. To test this we need to setup a special test vector in CLK_TEST and then operate on the APCS reg. For these special clock a different fixed_div is needed to be set. There is currently a bug (probably a hw bug) where the CPU clock of the 2 core is half broken, the correct clock is reported but only for one of the core, the other core will always report a wrong clock. Operating on the CPU mux makes the CLK_DIAG report the correct freq on one of the 2 core from the test vector. Also the L2 clock seems to be half broken with high speed freq. (still has to be confirmed and maybe it's the L2 HFPLL wrongly configured for some reason and on high frequency > 1GHz reports not precise frequency) Note that we currently use a fixed_div of 8 for these special clock. This should be used only for ipq8064 v3 SoC but it was never found an ipq8064 v1 SoC, where 2 should be used as fixed_div. Signed-off-by: Christian Marangi --- ipq8064.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++ meson.build | 1 + 2 files changed, 229 insertions(+) create mode 100644 ipq8064.c diff --git a/ipq8064.c b/ipq8064.c new file mode 100644 index 0000000..ffbc723 --- /dev/null +++ b/ipq8064.c @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debugcc.h" + +#define GCC_PHYS 0x900000 + +#define PDM_CLK_NS_REG 0x2cc0 +#define XO4_CLK_DIV_4 BIT(3) | BIT(4) +#define XO4_CLK_BRANCH_ENA BIT(7) +#define CLK_ROOT_ENA BIT(11) +#define CXO_SRC_BRANCH_ENA BIT(13) + +#define RINGOSC_NS_REG 0x2dc0 +#define RO_CLK_BRANCH_ENA BIT(9) +#define RO_ROOT_ENA BIT(11) + +#define RINGOSC_TCXO_CTL_REG 0x2dc4 +#define RINGOSC_STATUS_REG 0x2dcc + +#define CLK_TEST_REG 0x2fa0 +#define RING_OSC_DBG_SEL BIT(26) // Select cc_dbg_hs_clk instead of default value cc_ringosc_clk +#define TEST_BUS_ENA BIT(23) +#define TEST_BUS_SEL_MASK GENMASK(22, 19) +#define HS_DBG_CLK_BRANCH_ENA BIT(17) +#define DBG_CLK_HS_SEL_MASK GENMASK(16, 10) +#define DBG_CLK_HS_SEL_SHIFT 10 +#define LS_DBG_CLK_BRANCH_ENA BIT(8) +#define DBG_CLK_LS_SEL_MASK GENMASK(7, 0) + +#define APCS_GCC_PHYS 0x2011000 + +#define APCS_CLK_DIAG_REG 0x1c +#define FAST_CLK_EN BIT(7) +#define FAST_CLK_SEL_MASK GENMASK(5, 3) +#define FAST_CLK_SEL_SHIFT 3 +#define SLOW_CLK_SEL_MASK GENMASK(2, 0) + +static struct debug_mux ringosc_mux; + +static struct gcc_mux gcc = { + .mux = { + .phys = GCC_PHYS, + .size = 0x4000, + + .measure = measure_gcc, + + .enable_reg = CLK_TEST_REG, + .enable_mask = RING_OSC_DBG_SEL, + + .parent = &ringosc_mux, + }, + + // PXO == CXO == 25MHz + .xo_rate = (25 * 1000 * 1000) / 4, + + .xo_div4_reg = PDM_CLK_NS_REG, + .xo_div4_val = XO4_CLK_DIV_4 | XO4_CLK_BRANCH_ENA | \ + CLK_ROOT_ENA | CXO_SRC_BRANCH_ENA, + + .debug_ctl_reg = RINGOSC_TCXO_CTL_REG, + .debug_status_reg = RINGOSC_STATUS_REG, +}; + +static struct debug_mux ringosc_mux = { + .phys = GCC_PHYS, + .size = 0x4000, + + .enable_reg = RINGOSC_NS_REG, + .enable_mask = RO_CLK_BRANCH_ENA | RO_ROOT_ENA, +}; + +static struct debug_mux hs_mux = { + .phys = GCC_PHYS, + .size = 0x4000, + .block_name = "hs", + + .measure = measure_leaf, + .parent = &gcc.mux, + + .enable_reg = CLK_TEST_REG, + .enable_mask = HS_DBG_CLK_BRANCH_ENA, + + .mux_reg = CLK_TEST_REG, + .mux_mask = DBG_CLK_HS_SEL_MASK, + .mux_shift = DBG_CLK_HS_SEL_SHIFT, +}; + +static struct debug_mux ls_mux = { + .phys = GCC_PHYS, + .size = 0x4000, + .block_name = "ls", + + .measure = measure_leaf, + .parent = &hs_mux, + // cc_dbg_ls_out_clk + .parent_mux_val = 0x43, + + .enable_reg = CLK_TEST_REG, + .enable_mask = LS_DBG_CLK_BRANCH_ENA, + + .mux_reg = CLK_TEST_REG, + .mux_mask = DBG_CLK_LS_SEL_MASK, +}; + +static struct debug_mux cpul2_mux = { + .phys = APCS_GCC_PHYS, + .size = 0x1000, + .block_name = "cpul2", + + .measure = measure_leaf, + .parent = &hs_mux, + // sc_dbg_hs1_clk + .parent_mux_val = 0x41, + + .enable_reg = APCS_CLK_DIAG_REG, + .enable_mask = FAST_CLK_EN, + + .mux_reg = APCS_CLK_DIAG_REG, + .mux_mask = FAST_CLK_SEL_MASK, + .mux_shift = FAST_CLK_SEL_SHIFT, +}; + +static struct measure_clk ipq8064_clocks[] = { + { "sdc1_p_clk", &ls_mux, 0x12 }, + { "sdc1_clk", &ls_mux, 0x13 }, + { "sdc3_p_clk", &ls_mux, 0x16 }, + { "sdc3_clk", &ls_mux, 0x17 }, + { "gp0_clk", &ls_mux, 0x1F }, + { "gp1_clk", &ls_mux, 0x20 }, + { "gp2_clk", &ls_mux, 0x21 }, + { "dfab_clk", &ls_mux, 0x25 }, + { "dfab_a_clk", &ls_mux, 0x25 }, + { "pmem_clk", &ls_mux, 0x26 }, + { "dma_bam_p_clk", &ls_mux, 0x32 }, + { "cfpb_clk", &ls_mux, 0x33 }, + { "cfpb_a_clk", &ls_mux, 0x33 }, + { "gsbi1_p_clk", &ls_mux, 0x3D }, + { "gsbi1_uart_clk", &ls_mux, 0x3E }, + { "gsbi1_qup_clk", &ls_mux, 0x3F }, + { "gsbi2_p_clk", &ls_mux, 0x41 }, + { "gsbi2_uart_clk", &ls_mux, 0x42 }, + { "gsbi2_qup_clk", &ls_mux, 0x44 }, + { "gsbi4_p_clk", &ls_mux, 0x49 }, + { "gsbi4_uart_clk", &ls_mux, 0x4A }, + { "gsbi5_p_clk", &ls_mux, 0x4D }, + { "gsbi5_uart_clk", &ls_mux, 0x4E }, + { "gsbi5_qup_clk", &ls_mux, 0x50 }, + { "gsbi6_p_clk", &ls_mux, 0x51 }, + { "gsbi6_uart_clk", &ls_mux, 0x52 }, + { "gsbi6_qup_clk", &ls_mux, 0x54 }, + { "gsbi7_p_clk", &ls_mux, 0x55 }, + { "gsbi7_uart_clk", &ls_mux, 0x56 }, + { "gsbi7_qup_clk", &ls_mux, 0x58 }, + { "sfab_sata_s_p_clk", &ls_mux, 0x59 }, + { "sata_p_clk", &ls_mux, 0x5A }, + { "sata_rxoob_clk", &ls_mux, 0x5B }, + { "sata_pmalive_clk", &ls_mux, 0x5C }, + { "pcie_src_clk", &ls_mux, 0x5D }, + { "pcie_p_clk", &ls_mux, 0x5E }, + { "ce5_p_clk", &ls_mux, 0x5F }, + { "ce5_core_clk", &ls_mux, 0x60 }, + { "sata_phy_ref_clk", &ls_mux, 0x6B }, + { "sata_phy_cfg_clk", &ls_mux, 0x6C }, + { "sfpb_clk", &ls_mux, 0x78 }, + { "sfpb_a_clk", &ls_mux, 0x78 }, + { "pmic_ssbi2_clk", &ls_mux, 0x7A }, + { "pmic_arb0_p_clk", &ls_mux, 0x7B }, + { "pmic_arb1_p_clk", &ls_mux, 0x7C }, + { "prng_clk", &ls_mux, 0x7D }, + { "rpm_msg_ram_p_clk", &ls_mux, 0x7F }, + { "adm0_p_clk", &ls_mux, 0x80 }, + { "usb_hs1_p_clk", &ls_mux, 0x84 }, + { "usb_hs1_xcvr_clk", &ls_mux, 0x85 }, + { "usb_hsic_p_clk", &ls_mux, 0x86 }, + { "usb_hsic_system_clk", &ls_mux, 0x87 }, + { "usb_hsic_xcvr_fs_clk", &ls_mux, 0x88 }, + { "usb_fs1_p_clk", &ls_mux, 0x89 }, + { "usb_fs1_sys_clk", &ls_mux, 0x8A }, + { "usb_fs1_xcvr_clk", &ls_mux, 0x8B }, + { "tsif_p_clk", &ls_mux, 0x8F }, + { "tsif_ref_clk", &ls_mux, 0x91 }, + { "ce1_p_clk", &ls_mux, 0x92 }, + { "tssc_clk", &ls_mux, 0x94 }, + { "usb_hsic_hsio_cal_clk", &ls_mux, 0x9D }, + { "ce1_core_clk", &ls_mux, 0xA4 }, + { "pcie1_p_clk", &ls_mux, 0xB0 }, + { "pcie1_src_clk", &ls_mux, 0xB1 }, + { "pcie2_p_clk", &ls_mux, 0xB2 }, + { "pcie2_src_clk", &ls_mux, 0xB3 }, + + { "afab_clk", &hs_mux, 0x07 }, + { "afab_a_clk", &hs_mux, 0x07 }, + { "sfab_clk", &hs_mux, 0x18 }, + { "sfab_a_clk", &hs_mux, 0x18 }, + { "adm0_clk", &hs_mux, 0x2A }, + { "sata_a_clk", &hs_mux, 0x31 }, + { "pcie_aux_clk", &hs_mux, 0x2B }, + { "pcie_phy_ref_clk", &hs_mux, 0x2D }, + { "pcie_a_clk", &hs_mux, 0x32 }, + { "ebi1_clk", &hs_mux, 0x34 }, + { "ebi1_a_clk", &hs_mux, 0x34 }, + { "usb_hsic_hsic_clk", &hs_mux, 0x50 }, + { "pcie1_aux_clk", &hs_mux, 0x55 }, + { "pcie1_phy_ref_clk", &hs_mux, 0x56 }, + { "pcie2_aux_clk", &hs_mux, 0x57 }, + { "pcie2_phy_ref_clk", &hs_mux, 0x58 }, + { "pcie1_a_clk", &hs_mux, 0x66 }, + { "pcie2_a_clk", &hs_mux, 0x67 }, + + { "l2_m_clk", &cpul2_mux, 0x2, 8 }, + { "krait0_m_clk", &cpul2_mux, 0x0, 8 }, + { "krait1_m_clk", &cpul2_mux, 0x1, 8 }, + {} +}; + +struct debugcc_platform ipq8064_debugcc = { + "ipq8064", + ipq8064_clocks, +}; diff --git a/meson.build b/meson.build index 93cb91e..e6d17c2 100644 --- a/meson.build +++ b/meson.build @@ -10,6 +10,7 @@ project('debugcc', ) platforms = [ + 'ipq8064', 'msm8936', 'msm8994', 'msm8996',