From 5ff18da34f915df28f2d20e1d72583d35947e858 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Fri, 29 Oct 2021 09:46:18 +0800 Subject: [PATCH] imx8ulp: clock: Support LPAV clocks in cgc and pcc Add the PCC5 clocks support and more LPAV clocks and PLL4 PFD in CGC. Signed-off-by: Ye Li Signed-off-by: Peng Fan --- arch/arm/include/asm/arch-imx8ulp/cgc.h | 32 +++- arch/arm/include/asm/arch-imx8ulp/pcc.h | 66 ++++++- arch/arm/mach-imx/imx8ulp/cgc.c | 314 +++++++++++++++++++++++++++----- arch/arm/mach-imx/imx8ulp/clock.c | 48 +++-- arch/arm/mach-imx/imx8ulp/pcc.c | 130 +++++++++++-- 5 files changed, 508 insertions(+), 82 deletions(-) diff --git a/arch/arm/include/asm/arch-imx8ulp/cgc.h b/arch/arm/include/asm/arch-imx8ulp/cgc.h index 34a15fb..745fd7f 100644 --- a/arch/arm/include/asm/arch-imx8ulp/cgc.h +++ b/arch/arm/include/asm/arch-imx8ulp/cgc.h @@ -6,11 +6,15 @@ #ifndef _ASM_ARCH_CGC_H #define _ASM_ARCH_CGC_H -enum cgc1_clk { +enum cgc_clk { DUMMY0_CLK, DUMMY1_CLK, LPOSC, + NIC_APCLK, + NIC_PERCLK, + XBAR_APCLK, XBAR_BUSCLK, + AD_SLOWCLK, SOSC, SOSC_DIV1, SOSC_DIV2, @@ -34,6 +38,24 @@ enum cgc1_clk { PLL3_PFD2_DIV2, PLL3_PFD3_DIV1, PLL3_PFD3_DIV2, + LVDS, + LPAV_AXICLK, + LPAV_AHBCLK, + LPAV_BUSCLK, + PLL4, + PLL4_VCODIV, + PLL4_PFD0, + PLL4_PFD1, + PLL4_PFD2, + PLL4_PFD3, + PLL4_PFD0_DIV1, + PLL4_PFD0_DIV2, + PLL4_PFD1_DIV1, + PLL4_PFD1_DIV2, + PLL4_PFD2_DIV1, + PLL4_PFD2_DIV2, + PLL4_PFD3_DIV1, + PLL4_PFD3_DIV2, }; struct cgc1_regs { @@ -119,12 +141,16 @@ struct cgc2_regs { u32 lvdscfg; }; -u32 cgc1_clk_get_rate(enum cgc1_clk clk); +u32 cgc_clk_get_rate(enum cgc_clk clk); void cgc1_pll3_init(void); void cgc1_pll2_init(void); void cgc1_soscdiv_init(void); void cgc1_init_core_clk(void); void cgc2_pll4_init(void); void cgc2_ddrclk_config(u32 src, u32 div); -u32 cgc1_sosc_div(enum cgc1_clk clk); +u32 cgc1_sosc_div(enum cgc_clk clk); +void cgc1_enet_stamp_sel(u32 clk_src); +void cgc2_pll4_pfd_config(enum cgc_clk pllpfd, u32 pfd); +void cgc2_pll4_pfddiv_config(enum cgc_clk pllpfddiv, u32 div); +void cgc2_lpav_init(enum cgc_clk clk); #endif diff --git a/arch/arm/include/asm/arch-imx8ulp/pcc.h b/arch/arm/include/asm/arch-imx8ulp/pcc.h index 091d017..4680154 100644 --- a/arch/arm/include/asm/arch-imx8ulp/pcc.h +++ b/arch/arm/include/asm/arch-imx8ulp/pcc.h @@ -90,6 +90,68 @@ enum pcc4_entry { RGPIOF_PCC4_SLOT = 31, }; +enum pcc5_entry { + DMA2_MP_PCC5_SLOT = 0, + DMA2_CH0_PCC5_SLOT = 1, + DMA2_CH1_PCC5_SLOT = 2, + DMA2_CH2_PCC5_SLOT = 3, + DMA2_CH3_PCC5_SLOT = 4, + DMA2_CH4_PCC5_SLOT = 5, + DMA2_CH5_PCC5_SLOT = 6, + DMA2_CH6_PCC5_SLOT = 7, + DMA2_CH7_PCC5_SLOT = 8, + DMA2_CH8_PCC5_SLOT = 9, + DMA2_CH9_PCC5_SLOT = 10, + DMA2_CH10_PCC5_SLOT = 11, + DMA2_CH11_PCC5_SLOT = 12, + DMA2_CH12_PCC5_SLOT = 13, + DMA2_CH13_PCC5_SLOT = 14, + DMA2_CH14_PCC5_SLOT = 15, + DMA2_CH15_PCC5_SLOT = 16, + DMA2_CH16_PCC5_SLOT = 17, + DMA2_CH17_PCC5_SLOT = 18, + DMA2_CH18_PCC5_SLOT = 19, + DMA2_CH19_PCC5_SLOT = 20, + DMA2_CH20_PCC5_SLOT = 21, + DMA2_CH21_PCC5_SLOT = 22, + DMA2_CH22_PCC5_SLOT = 23, + DMA2_CH23_PCC5_SLOT = 24, + DMA2_CH24_PCC5_SLOT = 25, + DMA2_CH25_PCC5_SLOT = 26, + DMA2_CH26_PCC5_SLOT = 27, + DMA2_CH27_PCC5_SLOT = 28, + DMA2_CH28_PCC5_SLOT = 29, + DMA2_CH29_PCC5_SLOT = 30, + DMA2_CH30_PCC5_SLOT = 31, + DMA2_CH31_PCC5_SLOT = 32, + MU2_B_PCC5_SLOT = 33, + MU3_B_PCC5_SLOT = 34, + SEMA42_2_PCC5_SLOT = 35, + CMC2_PCC5_SLOT = 36, + AVD_SIM_PCC5_SLOT = 37, + LPAV_CGC_PCC5_SLOT = 38, + PCC5_PCC5_SLOT = 39, + TPM8_PCC5_SLOT = 40, + SAI6_PCC5_SLOT = 41, + SAI7_PCC5_SLOT = 42, + SPDIF_PCC5_SLOT = 43, + ISI_PCC5_SLOT = 44, + CSI_REGS_PCC5_SLOT = 45, + CSI_PCC5_SLOT = 47, + DSI_PCC5_SLOT = 48, + WDOG5_PCC5_SLOT = 50, + EPDC_PCC5_SLOT = 51, + PXP_PCC5_SLOT = 52, + SFA2_PCC5_SLOT = 53, + GPU2D_PCC5_SLOT = 60, + GPU3D_PCC5_SLOT = 61, + DCNANO_PCC5_SLOT = 62, + LPDDR4_PCC5_SLOT = 66, + CSI_CLK_UI_PCC5_SLOT = 67, + CSI_CLK_ESC_PCC5_SLOT = 68, + RGPIOD_PCC5_SLOT = 69, +}; + /* PCC registers */ #define PCC_PR_OFFSET 31 #define PCC_PR_MASK (0x1 << PCC_PR_OFFSET) @@ -130,10 +192,10 @@ struct pcc_entry { }; int pcc_clock_enable(int pcc_controller, int pcc_clk_slot, bool enable); -int pcc_clock_sel(int pcc_controller, int pcc_clk_slot, enum cgc1_clk src); +int pcc_clock_sel(int pcc_controller, int pcc_clk_slot, enum cgc_clk src); int pcc_clock_div_config(int pcc_controller, int pcc_clk_slot, bool frac, u8 div); bool pcc_clock_is_enable(int pcc_controller, int pcc_clk_slot); -int pcc_clock_get_clksrc(int pcc_controller, int pcc_clk_slot, enum cgc1_clk *src); +int pcc_clock_get_clksrc(int pcc_controller, int pcc_clk_slot, enum cgc_clk *src); int pcc_reset_peripheral(int pcc_controller, int pcc_clk_slot, bool reset); u32 pcc_clock_get_rate(int pcc_controller, int pcc_clk_slot); #endif diff --git a/arch/arm/mach-imx/imx8ulp/cgc.c b/arch/arm/mach-imx/imx8ulp/cgc.c index 7bfc386..fc84f3f 100644 --- a/arch/arm/mach-imx/imx8ulp/cgc.c +++ b/arch/arm/mach-imx/imx8ulp/cgc.c @@ -189,8 +189,8 @@ void cgc2_pll4_init(void) ; /* Enable all 4 PFDs */ - setbits_le32(&cgc2_regs->pll4pfdcfg, 30 << 0); /* 316.8Mhz for NIC_LPAV */ - setbits_le32(&cgc2_regs->pll4pfdcfg, 18 << 8); + setbits_le32(&cgc2_regs->pll4pfdcfg, 18 << 0); + setbits_le32(&cgc2_regs->pll4pfdcfg, 30 << 8); /* 316.8Mhz for NIC_LPAV */ setbits_le32(&cgc2_regs->pll4pfdcfg, 12 << 16); setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 24); @@ -205,6 +205,68 @@ void cgc2_pll4_init(void) clrbits_le32(&cgc2_regs->pll4div_pfd1, BIT(7) | BIT(15) | BIT(23) | BIT(31)); } +void cgc2_pll4_pfd_config(enum cgc_clk pllpfd, u32 pfd) +{ + void __iomem *reg = &cgc2_regs->pll4div_pfd0; + u32 halt_mask = BIT(7) | BIT(15); + u32 pfd_shift = (pllpfd - PLL4_PFD0) * 8; + u32 val; + + if (pllpfd < PLL4_PFD0 || pllpfd > PLL4_PFD3) + return; + + if ((pllpfd - PLL4_PFD0) >> 1) + reg = &cgc2_regs->pll4div_pfd1; + + halt_mask = halt_mask << (((pllpfd - PLL4_PFD0) & 0x1) * 16); + + /* halt pfd div */ + setbits_le32(reg, halt_mask); + + /* gate pfd */ + setbits_le32(&cgc2_regs->pll4pfdcfg, BIT(7) << pfd_shift); + + val = readl(&cgc2_regs->pll4pfdcfg); + val &= ~(0x3f << pfd_shift); + val |= (pfd << pfd_shift); + writel(val, &cgc2_regs->pll4pfdcfg); + + /* ungate */ + clrbits_le32(&cgc2_regs->pll4pfdcfg, BIT(7) << pfd_shift); + + /* Wait stable */ + while ((readl(&cgc2_regs->pll4pfdcfg) & (BIT(6) << pfd_shift)) + != (BIT(6) << pfd_shift)) + ; + + /* enable pfd div */ + clrbits_le32(reg, halt_mask); +} + +void cgc2_pll4_pfddiv_config(enum cgc_clk pllpfddiv, u32 div) +{ + void __iomem *reg = &cgc2_regs->pll4div_pfd0; + u32 shift = ((pllpfddiv - PLL4_PFD0_DIV1) & 0x3) * 8; + + if (pllpfddiv < PLL4_PFD0_DIV1 || pllpfddiv > PLL4_PFD3_DIV2) + return; + + if ((pllpfddiv - PLL4_PFD0_DIV1) >> 2) + reg = &cgc2_regs->pll4div_pfd1; + + /* Halt pfd div */ + setbits_le32(reg, BIT(7) << shift); + + /* Clear div */ + clrbits_le32(reg, 0x3f << shift); + + /* Set div*/ + setbits_le32(reg, div << shift); + + /* Enable pfd div */ + clrbits_le32(reg, BIT(7) << shift); +} + void cgc2_ddrclk_config(u32 src, u32 div) { writel((src << 28) | (div << 21), &cgc2_regs->ddrclk); @@ -213,7 +275,63 @@ void cgc2_ddrclk_config(u32 src, u32 div) ; } -u32 decode_pll(enum cgc1_clk pll) +void cgc2_lpav_init(enum cgc_clk clk) +{ + u32 i, scs, reg; + const enum cgc_clk src[] = {FRO, PLL4_PFD1, SOSC, LVDS}; + + reg = readl(&cgc2_regs->niclpavclk); + scs = (reg >> 28) & 0x3; + + for (i = 0; i < 4; i++) { + if (clk == src[i]) { + if (scs == i) + return; + + reg &= ~(0x3 << 28); + reg |= (i << 28); + + writel(reg, &cgc2_regs->niclpavclk); + break; + } + } + + if (i == 4) + printf("Invalid clock source [%u] for LPAV\n", clk); +} + +u32 cgc2_nic_get_rate(enum cgc_clk clk) +{ + u32 reg, rate; + u32 scs, lpav_axi_clk, lpav_ahb_clk, lpav_bus_clk; + const enum cgc_clk src[] = {FRO, PLL4_PFD1, SOSC, LVDS}; + + reg = readl(&cgc2_regs->niclpavclk); + scs = (reg >> 28) & 0x3; + lpav_axi_clk = ((reg >> 21) & 0x3f) + 1; + lpav_ahb_clk = ((reg >> 14) & 0x3f) + 1; + lpav_bus_clk = ((reg >> 7) & 0x3f) + 1; + + rate = cgc_clk_get_rate(src[scs]); + + switch (clk) { + case LPAV_AXICLK: + rate = rate / lpav_axi_clk; + break; + case LPAV_AHBCLK: + rate = rate / (lpav_axi_clk * lpav_ahb_clk); + break; + case LPAV_BUSCLK: + rate = rate / (lpav_axi_clk * lpav_bus_clk); + break; + default: + return 0; + } + + return rate; +} + +u32 decode_pll(enum cgc_clk pll) { u32 reg, infreq, mult; u32 num, denom; @@ -247,6 +365,17 @@ u32 decode_pll(enum cgc1_clk pll) num = readl(&cgc1_regs->pll3num) & 0x3FFFFFFF; return (u64)infreq * mult + (u64)infreq * num / denom; + case PLL4: + reg = readl(&cgc2_regs->pll4csr); + if (!(reg & BIT(24))) + return 0; + + reg = readl(&cgc2_regs->pll4cfg); + mult = (reg >> 16) & 0x7F; + denom = readl(&cgc2_regs->pll4denom) & 0x3FFFFFFF; + num = readl(&cgc2_regs->pll4num) & 0x3FFFFFFF; + + return (u64)infreq * mult + (u64)infreq * num / denom; default: printf("Unsupported pll clocks %d\n", pll); break; @@ -255,93 +384,117 @@ u32 decode_pll(enum cgc1_clk pll) return 0; } -u32 cgc1_pll3_vcodiv_rate(void) +u32 cgc_pll_vcodiv_rate(enum cgc_clk clk) { u32 reg, gate, div; + void __iomem *plldiv_vco; + enum cgc_clk pll; + + if (clk == PLL3_VCODIV) { + plldiv_vco = &cgc1_regs->pll3div_vco; + pll = PLL3; + } else { + plldiv_vco = &cgc2_regs->pll4div_vco; + pll = PLL4; + } - reg = readl(&cgc1_regs->pll3div_vco); + reg = readl(plldiv_vco); gate = BIT(7) & reg; div = reg & 0x3F; - return gate ? 0 : decode_pll(PLL3) / (div + 1); + return gate ? 0 : decode_pll(pll) / (div + 1); } -u32 cgc1_pll3_pfd_rate(enum cgc1_clk clk) +u32 cgc_pll_pfd_rate(enum cgc_clk clk) { u32 index, gate, vld, reg; + void __iomem *pllpfdcfg; + enum cgc_clk pll; switch (clk) { case PLL3_PFD0: - index = 0; - break; case PLL3_PFD1: - index = 1; - break; case PLL3_PFD2: - index = 2; - break; case PLL3_PFD3: - index = 3; + index = clk - PLL3_PFD0; + pllpfdcfg = &cgc1_regs->pll3pfdcfg; + pll = PLL3; + break; + case PLL4_PFD0: + case PLL4_PFD1: + case PLL4_PFD2: + case PLL4_PFD3: + index = clk - PLL4_PFD0; + pllpfdcfg = &cgc2_regs->pll4pfdcfg; + pll = PLL4; break; default: return 0; } - reg = readl(&cgc1_regs->pll3pfdcfg); + reg = readl(pllpfdcfg); gate = reg & (BIT(7) << (index * 8)); vld = reg & (BIT(6) << (index * 8)); if (gate || !vld) return 0; - return (u64)decode_pll(PLL3) * 18 / ((reg >> (index * 8)) & 0x3F); + return (u64)decode_pll(pll) * 18 / ((reg >> (index * 8)) & 0x3F); } -u32 cgc1_pll3_pfd_div(enum cgc1_clk clk) +u32 cgc_pll_pfd_div(enum cgc_clk clk) { void __iomem *base; u32 pfd, index, gate, reg; switch (clk) { case PLL3_PFD0_DIV1: - base = &cgc1_regs->pll3div_pfd0; - pfd = PLL3_PFD0; - index = 0; - break; case PLL3_PFD0_DIV2: base = &cgc1_regs->pll3div_pfd0; pfd = PLL3_PFD0; - index = 1; + index = clk - PLL3_PFD0_DIV1; break; case PLL3_PFD1_DIV1: - base = &cgc1_regs->pll3div_pfd0; - pfd = PLL3_PFD1; - index = 2; - break; case PLL3_PFD1_DIV2: base = &cgc1_regs->pll3div_pfd0; pfd = PLL3_PFD1; - index = 3; + index = clk - PLL3_PFD0_DIV1; break; case PLL3_PFD2_DIV1: - base = &cgc1_regs->pll3div_pfd1; - pfd = PLL3_PFD2; - index = 0; - break; case PLL3_PFD2_DIV2: base = &cgc1_regs->pll3div_pfd1; pfd = PLL3_PFD2; - index = 1; + index = clk - PLL3_PFD2_DIV1; break; case PLL3_PFD3_DIV1: - base = &cgc1_regs->pll3div_pfd1; - pfd = PLL3_PFD3; - index = 2; - break; case PLL3_PFD3_DIV2: base = &cgc1_regs->pll3div_pfd1; pfd = PLL3_PFD3; - index = 3; + index = clk - PLL3_PFD2_DIV1; + break; + case PLL4_PFD0_DIV1: + case PLL4_PFD0_DIV2: + base = &cgc2_regs->pll4div_pfd0; + pfd = PLL4_PFD0; + index = clk - PLL4_PFD0_DIV1; + break; + case PLL4_PFD1_DIV1: + case PLL4_PFD1_DIV2: + base = &cgc2_regs->pll4div_pfd0; + pfd = PLL4_PFD1; + index = clk - PLL4_PFD0_DIV1; + break; + case PLL4_PFD2_DIV1: + case PLL4_PFD2_DIV2: + base = &cgc2_regs->pll4div_pfd1; + pfd = PLL4_PFD2; + index = clk - PLL4_PFD2_DIV1; + break; + case PLL4_PFD3_DIV1: + case PLL4_PFD3_DIV2: + base = &cgc2_regs->pll4div_pfd1; + pfd = PLL4_PFD3; + index = clk - PLL4_PFD2_DIV1; break; default: return 0; @@ -353,10 +506,52 @@ u32 cgc1_pll3_pfd_div(enum cgc1_clk clk) if (gate) return 0; - return cgc1_pll3_pfd_rate(pfd) / (((reg >> (index * 8)) & 0x3F) + 1); + return cgc_pll_pfd_rate(pfd) / (((reg >> (index * 8)) & 0x3F) + 1); +} + +u32 cgc1_nic_get_rate(enum cgc_clk clk) +{ + u32 reg, rate; + u32 scs, nic_ad_divplat, nic_per_divplat; + u32 xbar_ad_divplat, xbar_divbus, ad_slow; + const enum cgc_clk src[] = {FRO, PLL3_PFD0, SOSC, LVDS}; + + reg = readl(&cgc1_regs->nicclk); + scs = (reg >> 28) & 0x3; + nic_ad_divplat = ((reg >> 21) & 0x3f) + 1; + nic_per_divplat = ((reg >> 14) & 0x3f) + 1; + + reg = readl(&cgc1_regs->xbarclk); + xbar_ad_divplat = ((reg >> 14) & 0x3f) + 1; + xbar_divbus = ((reg >> 7) & 0x3f) + 1; + ad_slow = (reg & 0x3f) + 1; + + rate = cgc_clk_get_rate(src[scs]); + + switch (clk) { + case NIC_APCLK: + rate = rate / nic_ad_divplat; + break; + case NIC_PERCLK: + rate = rate / (nic_ad_divplat * nic_per_divplat); + break; + case XBAR_APCLK: + rate = rate / (nic_ad_divplat * xbar_ad_divplat); + break; + case XBAR_BUSCLK: + rate = rate / (nic_ad_divplat * xbar_ad_divplat * xbar_divbus); + break; + case AD_SLOWCLK: + rate = rate / (nic_ad_divplat * xbar_ad_divplat * ad_slow); + break; + default: + return 0; + } + + return rate; } -u32 cgc1_sosc_div(enum cgc1_clk clk) +u32 cgc1_sosc_div(enum cgc_clk clk) { u32 reg, gate, index; @@ -385,7 +580,7 @@ u32 cgc1_sosc_div(enum cgc1_clk clk) return 24000000 / (((reg >> (index * 8)) & 0x3F) + 1); } -u32 cgc1_fro_div(enum cgc1_clk clk) +u32 cgc1_fro_div(enum cgc_clk clk) { u32 reg, gate, vld, index; @@ -415,9 +610,11 @@ u32 cgc1_fro_div(enum cgc1_clk clk) return 24000000 / (((reg >> (index * 8)) & 0x3F) + 1); } -u32 cgc1_clk_get_rate(enum cgc1_clk clk) +u32 cgc_clk_get_rate(enum cgc_clk clk) { switch (clk) { + case LVDS: + return 0; /* No external LVDS clock used */ case SOSC: case SOSC_DIV1: case SOSC_DIV2: @@ -429,16 +626,21 @@ u32 cgc1_clk_get_rate(enum cgc1_clk clk) case FRO_DIV3: return cgc1_fro_div(clk); case PLL2: - return decode_pll(PLL2); case PLL3: - return decode_pll(PLL3); + case PLL4: + return decode_pll(clk); case PLL3_VCODIV: - return cgc1_pll3_vcodiv_rate(); + case PLL4_VCODIV: + return cgc_pll_vcodiv_rate(clk); case PLL3_PFD0: case PLL3_PFD1: case PLL3_PFD2: case PLL3_PFD3: - return cgc1_pll3_pfd_rate(clk); + case PLL4_PFD0: + case PLL4_PFD1: + case PLL4_PFD2: + case PLL4_PFD3: + return cgc_pll_pfd_rate(clk); case PLL3_PFD0_DIV1: case PLL3_PFD0_DIV2: case PLL3_PFD1_DIV1: @@ -447,9 +649,27 @@ u32 cgc1_clk_get_rate(enum cgc1_clk clk) case PLL3_PFD2_DIV2: case PLL3_PFD3_DIV1: case PLL3_PFD3_DIV2: - return cgc1_pll3_pfd_div(clk); + case PLL4_PFD0_DIV1: + case PLL4_PFD0_DIV2: + case PLL4_PFD1_DIV1: + case PLL4_PFD1_DIV2: + case PLL4_PFD2_DIV1: + case PLL4_PFD2_DIV2: + case PLL4_PFD3_DIV1: + case PLL4_PFD3_DIV2: + return cgc_pll_pfd_div(clk); + case NIC_APCLK: + case NIC_PERCLK: + case XBAR_APCLK: + case XBAR_BUSCLK: + case AD_SLOWCLK: + return cgc1_nic_get_rate(clk); + case LPAV_AXICLK: + case LPAV_AHBCLK: + case LPAV_BUSCLK: + return cgc2_nic_get_rate(clk); default: - printf("Unsupported cgc1 clock: %d\n", clk); + printf("Unsupported cgc clock: %d\n", clk); return 0; } } diff --git a/arch/arm/mach-imx/imx8ulp/clock.c b/arch/arm/mach-imx/imx8ulp/clock.c index ebbaad4..2beacbc 100644 --- a/arch/arm/mach-imx/imx8ulp/clock.c +++ b/arch/arm/mach-imx/imx8ulp/clock.c @@ -27,7 +27,7 @@ DECLARE_GLOBAL_DATA_PTR; #define PLL_USB_LOCK_MASK (0x01 << 31) #define PCC5_LPDDR4_ADDR 0x2da70108 -static void lpuart_set_clk(u32 index, enum cgc1_clk clk) +static void lpuart_set_clk(u32 index, enum cgc_clk clk) { const u32 lpuart_pcc_slots[] = { LPUART4_PCC3_SLOT, @@ -327,7 +327,7 @@ u32 mxc_get_clock(enum mxc_clock clk) case MXC_ESDHC3_CLK: return pcc_clock_get_rate(4, SDHC2_PCC4_SLOT); case MXC_ARM_CLK: - return cgc1_clk_get_rate(PLL2); + return cgc_clk_get_rate(PLL2); default: return 0; } @@ -376,16 +376,40 @@ int do_mx8ulp_showclocks(struct cmd_tbl *cmdtp, int flag, int argc, char * const printf("SDHC1 %8d MHz\n", pcc_clock_get_rate(4, SDHC1_PCC4_SLOT) / 1000000); printf("SDHC2 %8d MHz\n", pcc_clock_get_rate(4, SDHC2_PCC4_SLOT) / 1000000); - printf("SOSC %8d MHz\n", cgc1_clk_get_rate(SOSC) / 1000000); - printf("FRO %8d MHz\n", cgc1_clk_get_rate(FRO) / 1000000); - printf("PLL2 %8d MHz\n", cgc1_clk_get_rate(PLL2) / 1000000); - printf("PLL3 %8d MHz\n", cgc1_clk_get_rate(PLL3) / 1000000); - printf("PLL3_VCODIV %8d MHz\n", cgc1_clk_get_rate(PLL3_VCODIV) / 1000000); - printf("PLL3_PFD0 %8d MHz\n", cgc1_clk_get_rate(PLL3_PFD0) / 1000000); - printf("PLL3_PFD1 %8d MHz\n", cgc1_clk_get_rate(PLL3_PFD1) / 1000000); - printf("PLL3_PFD2 %8d MHz\n", cgc1_clk_get_rate(PLL3_PFD2) / 1000000); - printf("PLL3_PFD3 %8d MHz\n", cgc1_clk_get_rate(PLL3_PFD3) / 1000000); - + printf("SOSC %8d MHz\n", cgc_clk_get_rate(SOSC) / 1000000); + printf("FRO %8d MHz\n", cgc_clk_get_rate(FRO) / 1000000); + printf("PLL2 %8d MHz\n", cgc_clk_get_rate(PLL2) / 1000000); + printf("PLL3 %8d MHz\n", cgc_clk_get_rate(PLL3) / 1000000); + printf("PLL3_VCODIV %8d MHz\n", cgc_clk_get_rate(PLL3_VCODIV) / 1000000); + printf("PLL3_PFD0 %8d MHz\n", cgc_clk_get_rate(PLL3_PFD0) / 1000000); + printf("PLL3_PFD1 %8d MHz\n", cgc_clk_get_rate(PLL3_PFD1) / 1000000); + printf("PLL3_PFD2 %8d MHz\n", cgc_clk_get_rate(PLL3_PFD2) / 1000000); + printf("PLL3_PFD3 %8d MHz\n", cgc_clk_get_rate(PLL3_PFD3) / 1000000); + + printf("PLL4_PFD0 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD0) / 1000000); + printf("PLL4_PFD1 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD1) / 1000000); + printf("PLL4_PFD2 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD2) / 1000000); + printf("PLL4_PFD3 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD3) / 1000000); + + printf("PLL4_PFD0_DIV1 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD0_DIV1) / 1000000); + printf("PLL4_PFD0_DIV2 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD0_DIV2) / 1000000); + printf("PLL4_PFD1_DIV1 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD1_DIV1) / 1000000); + printf("PLL4_PFD1_DIV2 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD1_DIV2) / 1000000); + + printf("PLL4_PFD2_DIV1 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD2_DIV1) / 1000000); + printf("PLL4_PFD2_DIV2 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD2_DIV2) / 1000000); + printf("PLL4_PFD3_DIV1 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD3_DIV1) / 1000000); + printf("PLL4_PFD3_DIV2 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD3_DIV2) / 1000000); + + printf("LPAV_AXICLK %8d MHz\n", cgc_clk_get_rate(LPAV_AXICLK) / 1000000); + printf("LPAV_AHBCLK %8d MHz\n", cgc_clk_get_rate(LPAV_AHBCLK) / 1000000); + printf("LPAV_BUSCLK %8d MHz\n", cgc_clk_get_rate(LPAV_BUSCLK) / 1000000); + printf("NIC_APCLK %8d MHz\n", cgc_clk_get_rate(NIC_APCLK) / 1000000); + + printf("NIC_PERCLK %8d MHz\n", cgc_clk_get_rate(NIC_PERCLK) / 1000000); + printf("XBAR_APCLK %8d MHz\n", cgc_clk_get_rate(XBAR_APCLK) / 1000000); + printf("XBAR_BUSCLK %8d MHz\n", cgc_clk_get_rate(XBAR_BUSCLK) / 1000000); + printf("AD_SLOWCLK %8d MHz\n", cgc_clk_get_rate(AD_SLOWCLK) / 1000000); return 0; } diff --git a/arch/arm/mach-imx/imx8ulp/pcc.c b/arch/arm/mach-imx/imx8ulp/pcc.c index 711b685..6145b3e 100644 --- a/arch/arm/mach-imx/imx8ulp/pcc.c +++ b/arch/arm/mach-imx/imx8ulp/pcc.c @@ -12,10 +12,10 @@ #include #include -#define cgc1_clk_TYPES 2 -#define cgc1_clk_NUM 8 +#define cgc_clk_TYPES 2 +#define cgc_clk_NUM 8 -static enum cgc1_clk pcc3_clksrc[][8] = { +static enum cgc_clk pcc3_clksrc[][8] = { { }, { DUMMY0_CLK, @@ -29,7 +29,7 @@ static enum cgc1_clk pcc3_clksrc[][8] = { } }; -static enum cgc1_clk pcc4_clksrc[][8] = { +static enum cgc_clk pcc4_clksrc[][8] = { { DUMMY0_CLK, SOSC_DIV1, @@ -52,6 +52,29 @@ static enum cgc1_clk pcc4_clksrc[][8] = { } }; +static enum cgc_clk pcc5_clksrc[][8] = { + { + DUMMY0_CLK, + PLL4_PFD3_DIV2, + PLL4_PFD2_DIV2, + PLL4_PFD2_DIV1, + PLL4_PFD1_DIV2, + PLL4_PFD1_DIV1, + PLL4_PFD0_DIV2, + PLL4_PFD0_DIV1 + }, + { + DUMMY0_CLK, + DUMMY1_CLK, + LPOSC, + SOSC_DIV2, + FRO_DIV2, + LPAV_BUSCLK, + PLL4_VCODIV, + PLL4_PFD3_DIV1 + } +}; + static struct pcc_entry pcc3_arrays[] = { {PCC3_RBASE, DMA1_MP_PCC3_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B}, {PCC3_RBASE, DMA1_CH0_PCC3_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B}, @@ -136,6 +159,69 @@ static struct pcc_entry pcc4_arrays[] = { {} }; +static struct pcc_entry pcc5_arrays[] = { + {PCC5_RBASE, DMA2_MP_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH0_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH1_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH2_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH3_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH4_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH5_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH6_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH7_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH8_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH9_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH10_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH11_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH12_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH13_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH14_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH15_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH16_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH17_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH18_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH19_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH20_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH21_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH22_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH23_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH24_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH25_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH26_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH27_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH28_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH29_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH30_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, DMA2_CH31_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, MU2_B_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, MU3_B_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, SEMA42_2_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, CMC2_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, AVD_SIM_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, LPAV_CGC_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, PCC5_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, TPM8_PCC5_SLOT, CLKSRC_PER_BUS, PCC_HAS_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, SAI6_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, SAI7_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, SPDIF_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, ISI_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, CSI_REGS_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, CSI_PCC5_SLOT, CLKSRC_PER_PLAT, PCC_HAS_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, DSI_PCC5_SLOT, CLKSRC_PER_PLAT, PCC_HAS_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, WDOG5_PCC5_SLOT, CLKSRC_PER_BUS, PCC_HAS_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, EPDC_PCC5_SLOT, CLKSRC_PER_PLAT, PCC_HAS_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, PXP_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, SFA2_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, GPU2D_PCC5_SLOT, CLKSRC_PER_PLAT, PCC_HAS_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, GPU3D_PCC5_SLOT, CLKSRC_PER_PLAT, PCC_HAS_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, DCNANO_PCC5_SLOT, CLKSRC_PER_PLAT, PCC_HAS_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, LPDDR4_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_HAS_RST_B }, + {PCC5_RBASE, CSI_CLK_UI_PCC5_SLOT, CLKSRC_PER_PLAT, PCC_HAS_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, CSI_CLK_ESC_PCC5_SLOT, CLKSRC_PER_PLAT, PCC_HAS_DIV, PCC_NO_RST_B }, + {PCC5_RBASE, RGPIOD_PCC5_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B }, + {} +}; + static int find_pcc_entry(int pcc_controller, int pcc_clk_slot, struct pcc_entry **out) { struct pcc_entry *pcc_array; @@ -150,6 +236,10 @@ static int find_pcc_entry(int pcc_controller, int pcc_clk_slot, struct pcc_entry pcc_array = pcc4_arrays; *out = &pcc4_arrays[0]; break; + case 5: + pcc_array = pcc5_arrays; + *out = &pcc5_arrays[0]; + break; default: printf("Not supported pcc_controller: %d\n", pcc_controller); return -EINVAL; @@ -199,12 +289,12 @@ int pcc_clock_enable(int pcc_controller, int pcc_clk_slot, bool enable) } /* The clock source select needs clock is disabled */ -int pcc_clock_sel(int pcc_controller, int pcc_clk_slot, enum cgc1_clk src) +int pcc_clock_sel(int pcc_controller, int pcc_clk_slot, enum cgc_clk src) { u32 val, i, clksrc_type; void __iomem *reg; struct pcc_entry *pcc_array; - enum cgc1_clk *cgc1_clk_array; + enum cgc_clk *cgc_clk_array; int clk; clk = find_pcc_entry(pcc_controller, pcc_clk_slot, &pcc_array); @@ -221,18 +311,20 @@ int pcc_clock_sel(int pcc_controller, int pcc_clk_slot, enum cgc1_clk src) } if (pcc_controller == 3) - cgc1_clk_array = pcc3_clksrc[clksrc_type]; + cgc_clk_array = pcc3_clksrc[clksrc_type]; + else if (pcc_controller == 4) + cgc_clk_array = pcc4_clksrc[clksrc_type]; else - cgc1_clk_array = pcc4_clksrc[clksrc_type]; + cgc_clk_array = pcc5_clksrc[clksrc_type]; - for (i = 0; i < cgc1_clk_NUM; i++) { - if (cgc1_clk_array[i] == src) { + for (i = 0; i < cgc_clk_NUM; i++) { + if (cgc_clk_array[i] == src) { /* Find the clock src, then set it to PCS */ break; } } - if (i == cgc1_clk_NUM) { + if (i == cgc_clk_NUM) { printf("No parent in PCS of PCC %d, invalid scg_clk %d\n", clk, src); return -EINVAL; } @@ -320,13 +412,13 @@ bool pcc_clock_is_enable(int pcc_controller, int pcc_clk_slot) return false; } -int pcc_clock_get_clksrc(int pcc_controller, int pcc_clk_slot, enum cgc1_clk *src) +int pcc_clock_get_clksrc(int pcc_controller, int pcc_clk_slot, enum cgc_clk *src) { u32 val, clksrc_type; void __iomem *reg; struct pcc_entry *pcc_array; int clk; - enum cgc1_clk *cgc1_clk_array; + enum cgc_clk *cgc_clk_array; clk = find_pcc_entry(pcc_controller, pcc_clk_slot, &pcc_array); if (clk < 0) @@ -360,11 +452,13 @@ int pcc_clock_get_clksrc(int pcc_controller, int pcc_clk_slot, enum cgc1_clk *sr } if (pcc_controller == 3) - cgc1_clk_array = pcc3_clksrc[clksrc_type]; + cgc_clk_array = pcc3_clksrc[clksrc_type]; + else if (pcc_controller == 4) + cgc_clk_array = pcc4_clksrc[clksrc_type]; else - cgc1_clk_array = pcc4_clksrc[clksrc_type]; + cgc_clk_array = pcc5_clksrc[clksrc_type]; - *src = cgc1_clk_array[val]; + *src = cgc_clk_array[val]; debug("%s: parent cgc1 clk %d\n", __func__, *src); @@ -412,7 +506,7 @@ u32 pcc_clock_get_rate(int pcc_controller, int pcc_clk_slot) { u32 val, rate, frac, div; void __iomem *reg; - enum cgc1_clk parent; + enum cgc_clk parent; int ret; int clk; struct pcc_entry *pcc_array; @@ -425,7 +519,7 @@ u32 pcc_clock_get_rate(int pcc_controller, int pcc_clk_slot) if (ret) return 0; - rate = cgc1_clk_get_rate(parent); + rate = cgc_clk_get_rate(parent); debug("%s: parent rate %u\n", __func__, rate); -- 2.7.4