Message ID | 20190708015333.20411-29-peng.fan@nxp.com |
---|---|
State | Rejected |
Delegated to: | Stefano Babic |
Headers | show |
Series | Support i.MX8MM/N | expand |
Hi Peng, On 08.07.19 03:39, Peng Fan wrote: > Add i.MX8MM clk driver support. > > Signed-off-by: Peng Fan <peng.fan@nxp.com> > --- > arch/arm/mach-imx/imx8m/clock_imx8mm.c | 203 +++++++++++++++++---------------- > drivers/clk/imx/Makefile | 1 + > drivers/clk/imx/clk-imx8mm.c | 106 +++++++++++++++++ > 3 files changed, 211 insertions(+), 99 deletions(-) > create mode 100644 drivers/clk/imx/clk-imx8mm.c > > diff --git a/arch/arm/mach-imx/imx8m/clock_imx8mm.c b/arch/arm/mach-imx/imx8m/clock_imx8mm.c > index 07399023d5..541561f276 100644 > --- a/arch/arm/mach-imx/imx8m/clock_imx8mm.c > +++ b/arch/arm/mach-imx/imx8m/clock_imx8mm.c > @@ -119,6 +119,110 @@ void init_wdog_clk(void) > clock_enable(CCGR_WDOG3, 1); > } > > +static int intpll_configure(enum pll_clocks pll, ulong freq) > +{ > + void __iomem *pll_gnrl_ctl, __iomem *pll_div_ctl; > + u32 pll_div_ctl_val, pll_clke_masks; > + > + switch (pll) { > + case ANATOP_SYSTEM_PLL1: > + pll_gnrl_ctl = &ana_pll->sys_pll1_gnrl_ctl; > + pll_div_ctl = &ana_pll->sys_pll1_div_ctl; > + pll_clke_masks = INTPLL_DIV20_CLKE_MASK | > + INTPLL_DIV10_CLKE_MASK | INTPLL_DIV8_CLKE_MASK | > + INTPLL_DIV6_CLKE_MASK | INTPLL_DIV5_CLKE_MASK | > + INTPLL_DIV4_CLKE_MASK | INTPLL_DIV3_CLKE_MASK | > + INTPLL_DIV2_CLKE_MASK | INTPLL_CLKE_MASK; > + break; > + case ANATOP_SYSTEM_PLL2: > + pll_gnrl_ctl = &ana_pll->sys_pll2_gnrl_ctl; > + pll_div_ctl = &ana_pll->sys_pll2_div_ctl; > + pll_clke_masks = INTPLL_DIV20_CLKE_MASK | > + INTPLL_DIV10_CLKE_MASK | INTPLL_DIV8_CLKE_MASK | > + INTPLL_DIV6_CLKE_MASK | INTPLL_DIV5_CLKE_MASK | > + INTPLL_DIV4_CLKE_MASK | INTPLL_DIV3_CLKE_MASK | > + INTPLL_DIV2_CLKE_MASK | INTPLL_CLKE_MASK; > + break; > + case ANATOP_SYSTEM_PLL3: > + pll_gnrl_ctl = &ana_pll->sys_pll3_gnrl_ctl; > + pll_div_ctl = &ana_pll->sys_pll3_div_ctl; > + pll_clke_masks = INTPLL_CLKE_MASK; > + break; > + case ANATOP_ARM_PLL: > + pll_gnrl_ctl = &ana_pll->arm_pll_gnrl_ctl; > + pll_div_ctl = &ana_pll->arm_pll_div_ctl; > + pll_clke_masks = INTPLL_CLKE_MASK; > + break; > + case ANATOP_GPU_PLL: > + pll_gnrl_ctl = &ana_pll->gpu_pll_gnrl_ctl; > + pll_div_ctl = &ana_pll->gpu_pll_div_ctl; > + pll_clke_masks = INTPLL_CLKE_MASK; > + break; > + case ANATOP_VPU_PLL: > + pll_gnrl_ctl = &ana_pll->vpu_pll_gnrl_ctl; > + pll_div_ctl = &ana_pll->vpu_pll_div_ctl; > + pll_clke_masks = INTPLL_CLKE_MASK; > + break; > + default: > + return -EINVAL; > + }; > + > + switch (freq) { > + case MHZ(600): > + /* 24 * 0x12c / 3 / 2 ^ 2 */ > + pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0x12c) | > + INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(2); > + break; > + case MHZ(750): > + /* 24 * 0xfa / 2 / 2 ^ 2 */ > + pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xfa) | > + INTPLL_PRE_DIV_VAL(2) | INTPLL_POST_DIV_VAL(2); > + break; > + case MHZ(800): > + /* 24 * 0x190 / 3 / 2 ^ 2 */ > + pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0x190) | > + INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(2); > + break; > + case MHZ(1000): > + /* 24 * 0xfa / 3 / 2 ^ 1 */ > + pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xfa) | > + INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(1); > + break; > + case MHZ(1200): > + /* 24 * 0xc8 / 2 / 2 ^ 1 */ > + pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xc8) | > + INTPLL_PRE_DIV_VAL(2) | INTPLL_POST_DIV_VAL(1); > + break; > + case MHZ(2000): > + /* 24 * 0xfa / 3 / 2 ^ 0 */ > + pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xfa) | > + INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(0); > + break; > + default: > + return -EINVAL; > + }; > + /* Bypass clock and set lock to pll output lock */ > + setbits_le32(pll_gnrl_ctl, INTPLL_BYPASS_MASK | > + INTPLL_LOCK_SEL_MASK); > + /* Enable reset */ > + clrbits_le32(pll_gnrl_ctl, INTPLL_RST_MASK); > + /* Configure */ > + writel(pll_div_ctl_val, pll_div_ctl); > + > + __udelay(100); > + > + /* Disable reset */ > + setbits_le32(pll_gnrl_ctl, INTPLL_RST_MASK); > + /* Wait Lock */ > + while (!(readl(pll_gnrl_ctl) & INTPLL_LOCK_MASK)) > + ; > + /* Clear bypass */ > + clrbits_le32(pll_gnrl_ctl, INTPLL_BYPASS_MASK); > + setbits_le32(pll_gnrl_ctl, pll_clke_masks); > + > + return 0; > +} > + > int clock_init(void) > { > u32 val_cfg0; > @@ -467,105 +571,6 @@ int fracpll_configure(enum pll_clocks pll, u32 freq) > return 0; > } > > -int intpll_configure(enum pll_clocks pll, ulong freq) > -{ > - void __iomem *pll_gnrl_ctl, __iomem *pll_div_ctl; > - u32 pll_div_ctl_val, pll_clke_masks; > - > - switch (pll) { > - case ANATOP_SYSTEM_PLL1: > - pll_gnrl_ctl = &ana_pll->sys_pll1_gnrl_ctl; > - pll_div_ctl = &ana_pll->sys_pll1_div_ctl; > - pll_clke_masks = INTPLL_DIV20_CLKE_MASK | > - INTPLL_DIV10_CLKE_MASK | INTPLL_DIV8_CLKE_MASK | > - INTPLL_DIV6_CLKE_MASK | INTPLL_DIV5_CLKE_MASK | > - INTPLL_DIV4_CLKE_MASK | INTPLL_DIV3_CLKE_MASK | > - INTPLL_DIV2_CLKE_MASK | INTPLL_CLKE_MASK; > - break; > - case ANATOP_SYSTEM_PLL2: > - pll_gnrl_ctl = &ana_pll->sys_pll2_gnrl_ctl; > - pll_div_ctl = &ana_pll->sys_pll2_div_ctl; > - pll_clke_masks = INTPLL_DIV20_CLKE_MASK | > - INTPLL_DIV10_CLKE_MASK | INTPLL_DIV8_CLKE_MASK | > - INTPLL_DIV6_CLKE_MASK | INTPLL_DIV5_CLKE_MASK | > - INTPLL_DIV4_CLKE_MASK | INTPLL_DIV3_CLKE_MASK | > - INTPLL_DIV2_CLKE_MASK | INTPLL_CLKE_MASK; > - break; > - case ANATOP_SYSTEM_PLL3: > - pll_gnrl_ctl = &ana_pll->sys_pll3_gnrl_ctl; > - pll_div_ctl = &ana_pll->sys_pll3_div_ctl; > - pll_clke_masks = INTPLL_CLKE_MASK; > - break; > - case ANATOP_ARM_PLL: > - pll_gnrl_ctl = &ana_pll->arm_pll_gnrl_ctl; > - pll_div_ctl = &ana_pll->arm_pll_div_ctl; > - pll_clke_masks = INTPLL_CLKE_MASK; > - break; > - case ANATOP_GPU_PLL: > - pll_gnrl_ctl = &ana_pll->gpu_pll_gnrl_ctl; > - pll_div_ctl = &ana_pll->gpu_pll_div_ctl; > - pll_clke_masks = INTPLL_CLKE_MASK; > - break; > - case ANATOP_VPU_PLL: > - pll_gnrl_ctl = &ana_pll->vpu_pll_gnrl_ctl; > - pll_div_ctl = &ana_pll->vpu_pll_div_ctl; > - pll_clke_masks = INTPLL_CLKE_MASK; > - break; > - default: > - return -EINVAL; > - }; > - > - switch (freq) { > - case MHZ(750): > - /* 24 * 0xfa / 2 / 2 ^ 2 */ > - pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xfa) | > - INTPLL_PRE_DIV_VAL(2) | INTPLL_POST_DIV_VAL(2); > - break; > - case MHZ(800): > - /* 24 * 0x190 / 3 / 2 ^ 2 */ > - pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0x190) | > - INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(2); > - break; > - case MHZ(1000): > - /* 24 * 0xfa / 3 / 2 ^ 1 */ > - pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xfa) | > - INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(1); > - break; > - case MHZ(1200): > - /* 24 * 0xc8 / 2 / 2 ^ 1 */ > - pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xc8) | > - INTPLL_PRE_DIV_VAL(2) | INTPLL_POST_DIV_VAL(1); > - break; > - case MHZ(2000): > - /* 24 * 0xfa / 3 / 2 ^ 0 */ > - pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xfa) | > - INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(0); > - break; > - default: > - return -EINVAL; > - }; > - /* Bypass clock and set lock to pll output lock */ > - setbits_le32(pll_gnrl_ctl, INTPLL_BYPASS_MASK | > - INTPLL_LOCK_SEL_MASK); > - /* Enable reset */ > - clrbits_le32(pll_gnrl_ctl, INTPLL_RST_MASK); > - /* Configure */ > - writel(pll_div_ctl_val, pll_div_ctl); > - > - __udelay(100); > - > - /* Disable reset */ > - setbits_le32(pll_gnrl_ctl, INTPLL_RST_MASK); > - /* Wait Lock */ > - while (!(readl(pll_gnrl_ctl) & INTPLL_LOCK_MASK)) > - ; > - /* Clear bypass */ > - clrbits_le32(pll_gnrl_ctl, INTPLL_BYPASS_MASK); > - setbits_le32(pll_gnrl_ctl, pll_clke_masks); > - > - return 0; > -} > - > u32 get_root_src_clk(enum clk_root_src root_src) > { > switch (root_src) { > diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile > index eb379c188a..b55566f2e9 100644 > --- a/drivers/clk/imx/Makefile > +++ b/drivers/clk/imx/Makefile > @@ -8,3 +8,4 @@ ifdef CONFIG_CLK_IMX8 > obj-$(CONFIG_IMX8QXP) += clk-imx8qxp.o > obj-$(CONFIG_IMX8QM) += clk-imx8qm.o > endif > +obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o > diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c > new file mode 100644 > index 0000000000..1e0669494f > --- /dev/null > +++ b/drivers/clk/imx/clk-imx8mm.c > @@ -0,0 +1,106 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright 2019 NXP > + * Peng Fan <peng.fan@nxp.com> > + */ > + > +#include <common.h> > +#include <clk-uclass.h> > +#include <dm.h> > +#include <asm/arch/clock.h> > +#include <dt-bindings/clock/imx8mm-clock.h> > + > +static ulong imx8mm_clk_get_rate(struct clk *clk) > +{ > + debug("%s(#%lu)\n", __func__, clk->id); > + > + switch (clk->id) { > + case IMX8MM_CLK_USDHC1_ROOT: > + return get_root_clk(USDHC1_CLK_ROOT); > + case IMX8MM_CLK_USDHC2_ROOT: > + return get_root_clk(USDHC2_CLK_ROOT); > + case IMX8MM_CLK_USDHC3_ROOT: > + return get_root_clk(USDHC3_CLK_ROOT); > + case IMX8MM_CLK_I2C1: I tested I2C on my i.MX8MM board and it doesn't work (it did work with the CCF-based patches). It seems like IMX8MM_CLK_I2CX should be IMX8MM_CLK_I2CX_ROOT here and also for all the other occurrences below. Changing this makes I2C work again. And by the way: I'm not sure which side to take in the CCF or non-CCF discussion for i.MX8MM. I can understand both points of view and whichever decision is made I will support it, but it would be nice if we could settle for something soon. Thanks, Frieder > + return get_root_clk(I2C1_CLK_ROOT); > + case IMX8MM_CLK_I2C2: > + return get_root_clk(I2C2_CLK_ROOT); > + case IMX8MM_CLK_I2C3: > + return get_root_clk(I2C3_CLK_ROOT); > + case IMX8MM_CLK_I2C4: > + return get_root_clk(I2C4_CLK_ROOT); > + } > + > + return 0; > +} > + > +static int __imx8mm_clk_enable(struct clk *clk, bool enable) > +{ > + switch (clk->id) { > + case IMX8MM_CLK_USDHC1_ROOT: > + return clock_enable(CCGR_USDHC1, enable); > + case IMX8MM_CLK_USDHC2_ROOT: > + return clock_enable(CCGR_USDHC2, enable); > + case IMX8MM_CLK_USDHC3_ROOT: > + return clock_enable(CCGR_USDHC3, enable); > + case IMX8MM_CLK_I2C1: > + return clock_enable(CCGR_I2C1, enable); > + case IMX8MM_CLK_I2C2: > + return clock_enable(CCGR_I2C2, enable); > + case IMX8MM_CLK_I2C3: > + return clock_enable(CCGR_I2C3, enable); > + case IMX8MM_CLK_I2C4: > + return clock_enable(CCGR_I2C4, enable); > + } > + > + return -EINVAL; > +} > + > +static int imx8mm_clk_disable(struct clk *clk) > +{ > + debug("%s(#%lu)\n", __func__, clk->id); > + > + return __imx8mm_clk_enable(clk, false); > +} > + > +static int imx8mm_clk_enable(struct clk *clk) > +{ > + debug("%s(#%lu)\n", __func__, clk->id); > + > + return __imx8mm_clk_enable(clk, true); > +} > + > +static ulong imx8mm_clk_set_rate(struct clk *clk, unsigned long rate) > +{ > + debug("%s(#%lu)\n", __func__, clk->id); > + > + /* TODO: */ > + > + return imx8mm_clk_get_rate(clk); > +} > + > +static struct clk_ops imx8mm_clk_ops = { > + .set_rate = imx8mm_clk_set_rate, > + .get_rate = imx8mm_clk_get_rate, > + .enable = imx8mm_clk_enable, > + .disable = imx8mm_clk_disable, > +}; > + > +static int imx8mm_clk_probe(struct udevice *dev) > +{ > + return 0; > +} > + > +static const struct udevice_id imx8mm_clk_ids[] = { > + { .compatible = "fsl,imx8mm-ccm" }, > + { }, > +}; > + > +U_BOOT_DRIVER(imx8mm_clk) = { > + .name = "clk_imx8mm", > + .id = UCLASS_CLK, > + .of_match = imx8mm_clk_ids, > + .ops = &imx8mm_clk_ops, > + .probe = imx8mm_clk_probe, > + .flags = DM_FLAG_PRE_RELOC, > +}; >
diff --git a/arch/arm/mach-imx/imx8m/clock_imx8mm.c b/arch/arm/mach-imx/imx8m/clock_imx8mm.c index 07399023d5..541561f276 100644 --- a/arch/arm/mach-imx/imx8m/clock_imx8mm.c +++ b/arch/arm/mach-imx/imx8m/clock_imx8mm.c @@ -119,6 +119,110 @@ void init_wdog_clk(void) clock_enable(CCGR_WDOG3, 1); } +static int intpll_configure(enum pll_clocks pll, ulong freq) +{ + void __iomem *pll_gnrl_ctl, __iomem *pll_div_ctl; + u32 pll_div_ctl_val, pll_clke_masks; + + switch (pll) { + case ANATOP_SYSTEM_PLL1: + pll_gnrl_ctl = &ana_pll->sys_pll1_gnrl_ctl; + pll_div_ctl = &ana_pll->sys_pll1_div_ctl; + pll_clke_masks = INTPLL_DIV20_CLKE_MASK | + INTPLL_DIV10_CLKE_MASK | INTPLL_DIV8_CLKE_MASK | + INTPLL_DIV6_CLKE_MASK | INTPLL_DIV5_CLKE_MASK | + INTPLL_DIV4_CLKE_MASK | INTPLL_DIV3_CLKE_MASK | + INTPLL_DIV2_CLKE_MASK | INTPLL_CLKE_MASK; + break; + case ANATOP_SYSTEM_PLL2: + pll_gnrl_ctl = &ana_pll->sys_pll2_gnrl_ctl; + pll_div_ctl = &ana_pll->sys_pll2_div_ctl; + pll_clke_masks = INTPLL_DIV20_CLKE_MASK | + INTPLL_DIV10_CLKE_MASK | INTPLL_DIV8_CLKE_MASK | + INTPLL_DIV6_CLKE_MASK | INTPLL_DIV5_CLKE_MASK | + INTPLL_DIV4_CLKE_MASK | INTPLL_DIV3_CLKE_MASK | + INTPLL_DIV2_CLKE_MASK | INTPLL_CLKE_MASK; + break; + case ANATOP_SYSTEM_PLL3: + pll_gnrl_ctl = &ana_pll->sys_pll3_gnrl_ctl; + pll_div_ctl = &ana_pll->sys_pll3_div_ctl; + pll_clke_masks = INTPLL_CLKE_MASK; + break; + case ANATOP_ARM_PLL: + pll_gnrl_ctl = &ana_pll->arm_pll_gnrl_ctl; + pll_div_ctl = &ana_pll->arm_pll_div_ctl; + pll_clke_masks = INTPLL_CLKE_MASK; + break; + case ANATOP_GPU_PLL: + pll_gnrl_ctl = &ana_pll->gpu_pll_gnrl_ctl; + pll_div_ctl = &ana_pll->gpu_pll_div_ctl; + pll_clke_masks = INTPLL_CLKE_MASK; + break; + case ANATOP_VPU_PLL: + pll_gnrl_ctl = &ana_pll->vpu_pll_gnrl_ctl; + pll_div_ctl = &ana_pll->vpu_pll_div_ctl; + pll_clke_masks = INTPLL_CLKE_MASK; + break; + default: + return -EINVAL; + }; + + switch (freq) { + case MHZ(600): + /* 24 * 0x12c / 3 / 2 ^ 2 */ + pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0x12c) | + INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(2); + break; + case MHZ(750): + /* 24 * 0xfa / 2 / 2 ^ 2 */ + pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xfa) | + INTPLL_PRE_DIV_VAL(2) | INTPLL_POST_DIV_VAL(2); + break; + case MHZ(800): + /* 24 * 0x190 / 3 / 2 ^ 2 */ + pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0x190) | + INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(2); + break; + case MHZ(1000): + /* 24 * 0xfa / 3 / 2 ^ 1 */ + pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xfa) | + INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(1); + break; + case MHZ(1200): + /* 24 * 0xc8 / 2 / 2 ^ 1 */ + pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xc8) | + INTPLL_PRE_DIV_VAL(2) | INTPLL_POST_DIV_VAL(1); + break; + case MHZ(2000): + /* 24 * 0xfa / 3 / 2 ^ 0 */ + pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xfa) | + INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(0); + break; + default: + return -EINVAL; + }; + /* Bypass clock and set lock to pll output lock */ + setbits_le32(pll_gnrl_ctl, INTPLL_BYPASS_MASK | + INTPLL_LOCK_SEL_MASK); + /* Enable reset */ + clrbits_le32(pll_gnrl_ctl, INTPLL_RST_MASK); + /* Configure */ + writel(pll_div_ctl_val, pll_div_ctl); + + __udelay(100); + + /* Disable reset */ + setbits_le32(pll_gnrl_ctl, INTPLL_RST_MASK); + /* Wait Lock */ + while (!(readl(pll_gnrl_ctl) & INTPLL_LOCK_MASK)) + ; + /* Clear bypass */ + clrbits_le32(pll_gnrl_ctl, INTPLL_BYPASS_MASK); + setbits_le32(pll_gnrl_ctl, pll_clke_masks); + + return 0; +} + int clock_init(void) { u32 val_cfg0; @@ -467,105 +571,6 @@ int fracpll_configure(enum pll_clocks pll, u32 freq) return 0; } -int intpll_configure(enum pll_clocks pll, ulong freq) -{ - void __iomem *pll_gnrl_ctl, __iomem *pll_div_ctl; - u32 pll_div_ctl_val, pll_clke_masks; - - switch (pll) { - case ANATOP_SYSTEM_PLL1: - pll_gnrl_ctl = &ana_pll->sys_pll1_gnrl_ctl; - pll_div_ctl = &ana_pll->sys_pll1_div_ctl; - pll_clke_masks = INTPLL_DIV20_CLKE_MASK | - INTPLL_DIV10_CLKE_MASK | INTPLL_DIV8_CLKE_MASK | - INTPLL_DIV6_CLKE_MASK | INTPLL_DIV5_CLKE_MASK | - INTPLL_DIV4_CLKE_MASK | INTPLL_DIV3_CLKE_MASK | - INTPLL_DIV2_CLKE_MASK | INTPLL_CLKE_MASK; - break; - case ANATOP_SYSTEM_PLL2: - pll_gnrl_ctl = &ana_pll->sys_pll2_gnrl_ctl; - pll_div_ctl = &ana_pll->sys_pll2_div_ctl; - pll_clke_masks = INTPLL_DIV20_CLKE_MASK | - INTPLL_DIV10_CLKE_MASK | INTPLL_DIV8_CLKE_MASK | - INTPLL_DIV6_CLKE_MASK | INTPLL_DIV5_CLKE_MASK | - INTPLL_DIV4_CLKE_MASK | INTPLL_DIV3_CLKE_MASK | - INTPLL_DIV2_CLKE_MASK | INTPLL_CLKE_MASK; - break; - case ANATOP_SYSTEM_PLL3: - pll_gnrl_ctl = &ana_pll->sys_pll3_gnrl_ctl; - pll_div_ctl = &ana_pll->sys_pll3_div_ctl; - pll_clke_masks = INTPLL_CLKE_MASK; - break; - case ANATOP_ARM_PLL: - pll_gnrl_ctl = &ana_pll->arm_pll_gnrl_ctl; - pll_div_ctl = &ana_pll->arm_pll_div_ctl; - pll_clke_masks = INTPLL_CLKE_MASK; - break; - case ANATOP_GPU_PLL: - pll_gnrl_ctl = &ana_pll->gpu_pll_gnrl_ctl; - pll_div_ctl = &ana_pll->gpu_pll_div_ctl; - pll_clke_masks = INTPLL_CLKE_MASK; - break; - case ANATOP_VPU_PLL: - pll_gnrl_ctl = &ana_pll->vpu_pll_gnrl_ctl; - pll_div_ctl = &ana_pll->vpu_pll_div_ctl; - pll_clke_masks = INTPLL_CLKE_MASK; - break; - default: - return -EINVAL; - }; - - switch (freq) { - case MHZ(750): - /* 24 * 0xfa / 2 / 2 ^ 2 */ - pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xfa) | - INTPLL_PRE_DIV_VAL(2) | INTPLL_POST_DIV_VAL(2); - break; - case MHZ(800): - /* 24 * 0x190 / 3 / 2 ^ 2 */ - pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0x190) | - INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(2); - break; - case MHZ(1000): - /* 24 * 0xfa / 3 / 2 ^ 1 */ - pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xfa) | - INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(1); - break; - case MHZ(1200): - /* 24 * 0xc8 / 2 / 2 ^ 1 */ - pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xc8) | - INTPLL_PRE_DIV_VAL(2) | INTPLL_POST_DIV_VAL(1); - break; - case MHZ(2000): - /* 24 * 0xfa / 3 / 2 ^ 0 */ - pll_div_ctl_val = INTPLL_MAIN_DIV_VAL(0xfa) | - INTPLL_PRE_DIV_VAL(3) | INTPLL_POST_DIV_VAL(0); - break; - default: - return -EINVAL; - }; - /* Bypass clock and set lock to pll output lock */ - setbits_le32(pll_gnrl_ctl, INTPLL_BYPASS_MASK | - INTPLL_LOCK_SEL_MASK); - /* Enable reset */ - clrbits_le32(pll_gnrl_ctl, INTPLL_RST_MASK); - /* Configure */ - writel(pll_div_ctl_val, pll_div_ctl); - - __udelay(100); - - /* Disable reset */ - setbits_le32(pll_gnrl_ctl, INTPLL_RST_MASK); - /* Wait Lock */ - while (!(readl(pll_gnrl_ctl) & INTPLL_LOCK_MASK)) - ; - /* Clear bypass */ - clrbits_le32(pll_gnrl_ctl, INTPLL_BYPASS_MASK); - setbits_le32(pll_gnrl_ctl, pll_clke_masks); - - return 0; -} - u32 get_root_src_clk(enum clk_root_src root_src) { switch (root_src) { diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index eb379c188a..b55566f2e9 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -8,3 +8,4 @@ ifdef CONFIG_CLK_IMX8 obj-$(CONFIG_IMX8QXP) += clk-imx8qxp.o obj-$(CONFIG_IMX8QM) += clk-imx8qm.o endif +obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c new file mode 100644 index 0000000000..1e0669494f --- /dev/null +++ b/drivers/clk/imx/clk-imx8mm.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP + * Peng Fan <peng.fan@nxp.com> + */ + +#include <common.h> +#include <clk-uclass.h> +#include <dm.h> +#include <asm/arch/clock.h> +#include <dt-bindings/clock/imx8mm-clock.h> + +static ulong imx8mm_clk_get_rate(struct clk *clk) +{ + debug("%s(#%lu)\n", __func__, clk->id); + + switch (clk->id) { + case IMX8MM_CLK_USDHC1_ROOT: + return get_root_clk(USDHC1_CLK_ROOT); + case IMX8MM_CLK_USDHC2_ROOT: + return get_root_clk(USDHC2_CLK_ROOT); + case IMX8MM_CLK_USDHC3_ROOT: + return get_root_clk(USDHC3_CLK_ROOT); + case IMX8MM_CLK_I2C1: + return get_root_clk(I2C1_CLK_ROOT); + case IMX8MM_CLK_I2C2: + return get_root_clk(I2C2_CLK_ROOT); + case IMX8MM_CLK_I2C3: + return get_root_clk(I2C3_CLK_ROOT); + case IMX8MM_CLK_I2C4: + return get_root_clk(I2C4_CLK_ROOT); + } + + return 0; +} + +static int __imx8mm_clk_enable(struct clk *clk, bool enable) +{ + switch (clk->id) { + case IMX8MM_CLK_USDHC1_ROOT: + return clock_enable(CCGR_USDHC1, enable); + case IMX8MM_CLK_USDHC2_ROOT: + return clock_enable(CCGR_USDHC2, enable); + case IMX8MM_CLK_USDHC3_ROOT: + return clock_enable(CCGR_USDHC3, enable); + case IMX8MM_CLK_I2C1: + return clock_enable(CCGR_I2C1, enable); + case IMX8MM_CLK_I2C2: + return clock_enable(CCGR_I2C2, enable); + case IMX8MM_CLK_I2C3: + return clock_enable(CCGR_I2C3, enable); + case IMX8MM_CLK_I2C4: + return clock_enable(CCGR_I2C4, enable); + } + + return -EINVAL; +} + +static int imx8mm_clk_disable(struct clk *clk) +{ + debug("%s(#%lu)\n", __func__, clk->id); + + return __imx8mm_clk_enable(clk, false); +} + +static int imx8mm_clk_enable(struct clk *clk) +{ + debug("%s(#%lu)\n", __func__, clk->id); + + return __imx8mm_clk_enable(clk, true); +} + +static ulong imx8mm_clk_set_rate(struct clk *clk, unsigned long rate) +{ + debug("%s(#%lu)\n", __func__, clk->id); + + /* TODO: */ + + return imx8mm_clk_get_rate(clk); +} + +static struct clk_ops imx8mm_clk_ops = { + .set_rate = imx8mm_clk_set_rate, + .get_rate = imx8mm_clk_get_rate, + .enable = imx8mm_clk_enable, + .disable = imx8mm_clk_disable, +}; + +static int imx8mm_clk_probe(struct udevice *dev) +{ + return 0; +} + +static const struct udevice_id imx8mm_clk_ids[] = { + { .compatible = "fsl,imx8mm-ccm" }, + { }, +}; + +U_BOOT_DRIVER(imx8mm_clk) = { + .name = "clk_imx8mm", + .id = UCLASS_CLK, + .of_match = imx8mm_clk_ids, + .ops = &imx8mm_clk_ops, + .probe = imx8mm_clk_probe, + .flags = DM_FLAG_PRE_RELOC, +};
Add i.MX8MM clk driver support. Signed-off-by: Peng Fan <peng.fan@nxp.com> --- arch/arm/mach-imx/imx8m/clock_imx8mm.c | 203 +++++++++++++++++---------------- drivers/clk/imx/Makefile | 1 + drivers/clk/imx/clk-imx8mm.c | 106 +++++++++++++++++ 3 files changed, 211 insertions(+), 99 deletions(-) create mode 100644 drivers/clk/imx/clk-imx8mm.c