aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2021-10-29 09:46:18 +0800
committerStefano Babic <sbabic@denx.de>2022-02-05 13:38:38 +0100
commit5ff18da34f915df28f2d20e1d72583d35947e858 (patch)
tree434a991b8eea0bd23be9b1fc60aa50e46a6b0633 /arch
parent99de168f7e7173748f3a04cbcec1984fb4c8630b (diff)
downloadu-boot-5ff18da34f915df28f2d20e1d72583d35947e858.zip
u-boot-5ff18da34f915df28f2d20e1d72583d35947e858.tar.gz
u-boot-5ff18da34f915df28f2d20e1d72583d35947e858.tar.bz2
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 <ye.li@nxp.com> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/asm/arch-imx8ulp/cgc.h32
-rw-r--r--arch/arm/include/asm/arch-imx8ulp/pcc.h66
-rw-r--r--arch/arm/mach-imx/imx8ulp/cgc.c314
-rw-r--r--arch/arm/mach-imx/imx8ulp/clock.c48
-rw-r--r--arch/arm/mach-imx/imx8ulp/pcc.c130
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 <asm/arch/cgc.h>
#include <asm/arch/sys_proto.h>
-#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);