[PATCH v4 0/4] Add a clock driver for the imx8mq

This is a DM clock driver for the imx8mq based on the linux kernel driver and the u-boot imx8mm clock driver.
It also removes some code duplication in the imx8m[nmp] clock drivers.
Changes since v3:
Fixed driver spelling Moved rate macros out of the header into the dot c
Changes since v2:
Added kernel commit IDs Re-factored rate table code to remove duplication Remove duplicate code by creating a common clk-imx8m
Changes since v1:
More verbose clock driver description Added forgotten dt-bindings Synced PLL frequencies with mainline kernel
Angus Ainslie (4): dt-bindings: imx8mq-clock: add mainline definitions clk: imx8mq: Add a clock driver for the imx8mq clk: imx8m: reduce rate table duplication clk: imx8m: remove code duplication
drivers/clk/imx/Kconfig | 16 + drivers/clk/imx/Makefile | 8 +- drivers/clk/imx/clk-imx8m.c | 108 ++++++ drivers/clk/imx/clk-imx8m.h | 12 + drivers/clk/imx/clk-imx8mm.c | 149 +------- drivers/clk/imx/clk-imx8mn.c | 149 +------- drivers/clk/imx/clk-imx8mp.c | 156 +------- drivers/clk/imx/clk-imx8mq.c | 441 +++++++++++++++++++++++ drivers/clk/imx/clk-pll14xx.c | 61 ++++ drivers/clk/imx/clk.h | 4 + include/dt-bindings/clock/imx8mq-clock.h | 16 +- 11 files changed, 688 insertions(+), 432 deletions(-) create mode 100644 drivers/clk/imx/clk-imx8m.c create mode 100644 drivers/clk/imx/clk-imx8m.h create mode 100644 drivers/clk/imx/clk-imx8mq.c

Sync the clock ids with the mainline kernel
077de6e1c9f ("clk: imx8mq: add PLL monitor output")
Signed-off-by: Angus Ainslie angus@akkea.ca Reviewed-by: Marek Vasut marex@denx.de --- include/dt-bindings/clock/imx8mq-clock.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/include/dt-bindings/clock/imx8mq-clock.h b/include/dt-bindings/clock/imx8mq-clock.h index 9b8045d75b8..82e907ce7bd 100644 --- a/include/dt-bindings/clock/imx8mq-clock.h +++ b/include/dt-bindings/clock/imx8mq-clock.h @@ -431,6 +431,20 @@
#define IMX8MQ_CLK_A53_CORE 289
-#define IMX8MQ_CLK_END 290 +#define IMX8MQ_CLK_MON_AUDIO_PLL1_DIV 290 +#define IMX8MQ_CLK_MON_AUDIO_PLL2_DIV 291 +#define IMX8MQ_CLK_MON_VIDEO_PLL1_DIV 292 +#define IMX8MQ_CLK_MON_GPU_PLL_DIV 293 +#define IMX8MQ_CLK_MON_VPU_PLL_DIV 294 +#define IMX8MQ_CLK_MON_ARM_PLL_DIV 295 +#define IMX8MQ_CLK_MON_SYS_PLL1_DIV 296 +#define IMX8MQ_CLK_MON_SYS_PLL2_DIV 297 +#define IMX8MQ_CLK_MON_SYS_PLL3_DIV 298 +#define IMX8MQ_CLK_MON_DRAM_PLL_DIV 299 +#define IMX8MQ_CLK_MON_VIDEO_PLL2_DIV 300 +#define IMX8MQ_CLK_MON_SEL 301 +#define IMX8MQ_CLK_MON_CLK2_OUT 302 + +#define IMX8MQ_CLK_END 303
#endif /* __DT_BINDINGS_CLOCK_IMX8MQ_H */

This is a DM clock driver based off the imx8mm u-boot driver and the linux kernel driver.
All of the PLLs and clocks are initialized so the subsystems below are functional and tested.
1) USB host and peripheral 2) ECSPI 3) UART 4) I2C all busses 5) USDHC for eMMC support 6) USB storage 7) GPIO 8) DRAM
Signed-off-by: Angus Ainslie angus@akkea.ca --- drivers/clk/imx/Kconfig | 16 + drivers/clk/imx/Makefile | 2 + drivers/clk/imx/clk-imx8mq.c | 575 +++++++++++++++++++++++++++++++++++ 3 files changed, 593 insertions(+) create mode 100644 drivers/clk/imx/clk-imx8mq.c
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index cdd348020b0..06d8c1a5dd3 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -71,6 +71,22 @@ config CLK_IMX8MP help This enables support clock driver for i.MX8MP platforms.
+config SPL_CLK_IMX8MQ + bool "SPL clock support for i.MX8MQ" + depends on ARCH_IMX8M && SPL + select SPL_CLK + select SPL_CLK_CCF + help + This enables SPL DM/DTS support for clock driver in i.MX8MQ + +config CLK_IMX8MQ + bool "Clock support for i.MX8MQ" + depends on ARCH_IMX8M + select CLK + select CLK_CCF + help + This enables support clock driver for i.MX8MQ platforms. + config SPL_CLK_IMXRT1020 bool "SPL clock support for i.MXRT1020" depends on ARCH_IMXRT && SPL diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 01bbbdf3aea..c5766901f2b 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -16,6 +16,8 @@ obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MN) += clk-imx8mn.o clk-pll14xx.o \ clk-composite-8m.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MP) += clk-imx8mp.o clk-pll14xx.o \ clk-composite-8m.o +obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MQ) += clk-imx8mq.o clk-pll14xx.o \ + clk-composite-8m.o
obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1020) += clk-imxrt1020.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1050) += clk-imxrt1050.o diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c new file mode 100644 index 00000000000..0aea417a29b --- /dev/null +++ b/drivers/clk/imx/clk-imx8mq.c @@ -0,0 +1,575 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP + * Copyright 2022 Purism + * Peng Fan peng.fan@nxp.com + */ + +#include <common.h> +#include <clk.h> +#include <clk-uclass.h> +#include <dm.h> +#include <log.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <dt-bindings/clock/imx8mq-clock.h> + +#include "clk.h" + +#define PLL_1416X_RATE(_rate, _m, _p, _s) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + } + +#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + .kdiv = (_k), \ + } + +static const struct imx_pll14xx_rate_table imx8mq_pll1416x_tbl[] = { + PLL_1416X_RATE(1800000000U, 225, 3, 0), + PLL_1416X_RATE(1600000000U, 200, 3, 0), + PLL_1416X_RATE(1200000000U, 300, 3, 1), + PLL_1416X_RATE(1000000000U, 250, 3, 1), + PLL_1416X_RATE(800000000U, 200, 3, 1), + PLL_1416X_RATE(750000000U, 250, 2, 2), + PLL_1416X_RATE(700000000U, 350, 3, 2), + PLL_1416X_RATE(600000000U, 300, 3, 2), +}; + +const struct imx_pll14xx_rate_table imx8mq_pll1443x_tbl[] = { + PLL_1443X_RATE(650000000U, 325, 3, 2, 0), + PLL_1443X_RATE(594000000U, 198, 2, 2, 0), + PLL_1443X_RATE(393216000U, 262, 2, 3, 9437), + PLL_1443X_RATE(361267200U, 361, 3, 3, 17511), +}; + +static struct imx_pll14xx_clk imx8mq_1416x_pll __initdata = { + .type = PLL_1416X, + .rate_table = imx8mq_pll1416x_tbl, + .rate_count = ARRAY_SIZE(imx8mq_pll1416x_tbl), +}; + +static struct imx_pll14xx_clk imx8mq_1443x_pll __initdata = { + .type = PLL_1443X, + .rate_table = imx8mq_pll1443x_tbl, + .rate_count = ARRAY_SIZE(imx8mq_pll1443x_tbl), +}; + +static const char *pll_ref_sels[] = { "clock-osc-25m", "clock-osc-27m", "clock-phy-27m", "dummy", }; +static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; +static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", }; +static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", }; +static const char *audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", }; +static const char *audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", }; +static const char *video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", }; + +static const char *imx8mq_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", }; +static const char *imx8mq_a53_sels[] = {"clock-osc-25m", "arm_pll_out", "sys_pll2_500m", + "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m", + "audio_pll1_out", "sys_pll3_out", }; + +static const char *imx8mq_ahb_sels[] = {"clock-osc-25m", "sys_pll1_133m", "sys_pll1_800m", + "sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out", + "audio_pll1_out", "video_pll1_out", }; + +static const char *imx8mq_enet_axi_sels[] = {"clock-osc-25m", "sys_pll1_266m", "sys_pll1_800m", + "sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out", + "video_pll1_out", "sys_pll3_out", }; + +static const char *imx8mq_enet_ref_sels[] = {"clock-osc-25m", "sys_pll2_125m", "sys_pll2_50m", + "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out", + "video_pll1_out", "clk_ext4", }; + +static const char *imx8mq_enet_timer_sels[] = {"clock-osc-25m", "sys_pll2_100m", "audio_pll1_out", + "clk_ext1", "clk_ext2", "clk_ext3", "clk_ext4", + "video_pll1_out", }; + +static const char *imx8mq_enet_phy_sels[] = {"clock-osc-25m", "sys_pll2_50m", "sys_pll2_125m", + "sys_pll2_200m", "sys_pll2_500m", "video_pll1_out", + "audio_pll2_out", }; + +static const char *imx8mq_nand_usdhc_sels[] = {"clock-osc-25m", "sys_pll1_266m", "sys_pll1_800m", + "sys_pll2_200m", "sys_pll1_133m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll1_out", }; + +static const char *imx8mq_usb_bus_sels[] = {"clock-osc-25m", "sys_pll2_500m", "sys_pll1_800m", + "sys_pll2_100m", "sys_pll2_200m", "clk_ext2", + "clk_ext4", "audio_pll2_out", }; + +static const char *imx8mq_usdhc1_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll1_800m", + "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m", + "audio_pll2_out", "sys_pll1_100m", }; + +static const char *imx8mq_usdhc2_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll1_800m", + "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m", + "audio_pll2_out", "sys_pll1_100m", }; + +static const char *imx8mq_i2c1_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", + "audio_pll2_out", "sys_pll1_133m", }; + +static const char *imx8mq_i2c2_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", + "audio_pll2_out", "sys_pll1_133m", }; + +static const char *imx8mq_i2c3_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", + "audio_pll2_out", "sys_pll1_133m", }; + +static const char *imx8mq_i2c4_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", + "audio_pll2_out", "sys_pll1_133m", }; + +static const char *imx8mq_wdog_sels[] = {"clock-osc-25m", "sys_pll1_133m", "sys_pll1_160m", + "vpu_pll_out", "sys_pll2_125m", "sys_pll3_out", + "sys_pll1_80m", "sys_pll2_166m", }; + +static const char *imx8mq_qspi_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll2_333m", + "sys_pll2_500m", "audio_pll2_out", "sys_pll1_266m", + "sys_pll3_out", "sys_pll1_100m", }; + +static const char *imx8mq_usb_core_sels[] = {"clock-osc-25m", "sys_pll1_100m", "sys_pll1_40m", + "sys_pll2_100m", "sys_pll2_200m", "clk_ext2", + "clk_ext3", "audio_pll2_out", }; + +static const char *imx8mq_usb_phy_sels[] = {"clock-osc-25m", "sys_pll1_100m", "sys_pll1_40m", + "sys_pll2_100m", "sys_pll2_200m", "clk_ext2", + "clk_ext3", "audio_pll2_out", }; + +static const char *imx8mq_ecspi1_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m", + "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll2_out", }; + +static const char *imx8mq_ecspi2_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m", + "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll2_out", }; + +static const char *imx8mq_ecspi3_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m", + "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll2_out", }; + +static const char *pllout_monitor_sels[] = {"clock-osc-25m", "clock-osc-27m", "clock-phy-27m", + "dummy", "clock-ckil", "audio_pll1_out_monitor", + "audio_pll2_out_monitor", "gpu_pll_out_monitor", + "vpu_pll_out_monitor", "video_pll1_out_monitor", + "arm_pll_out_monitor", "sys_pll1_out_monitor", + "sys_pll2_out_monitor", "sys_pll3_out_monitor", + "dummy", "dram_pll_out_monitor", }; + +static ulong imx8mq_clk_get_rate(struct clk *clk) +{ + struct clk *c; + int ret; + + debug("%s(#%lu)\n", __func__, clk->id); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + return clk_get_rate(c); +} + +static ulong imx8mq_clk_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *c; + int ret; + + debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + return clk_set_rate(c, rate); +} + +static int __imx8mq_clk_enable(struct clk *clk, bool enable) +{ + struct clk *c; + int ret; + + debug("%s(#%lu) en: %d\n", __func__, clk->id, enable); + + ret = clk_get_by_id(clk->id, &c); + if (ret) { + debug("%s: clk_get_by_id failed\n", __func__); + return ret; + } + + if (enable) + ret = clk_enable(c); + else + ret = clk_disable(c); + + return ret; +} + +static int imx8mq_clk_disable(struct clk *clk) +{ + return __imx8mq_clk_enable(clk, 0); +} + +static int imx8mq_clk_enable(struct clk *clk) +{ + return __imx8mq_clk_enable(clk, 1); +} + +static int imx8mq_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk *c, *cp; + int ret; + + debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + ret = clk_get_by_id(parent->id, &cp); + if (ret) + return ret; + + ret = clk_set_parent(c, cp); + c->dev->parent = cp->dev; + + return ret; +} + +static struct clk_ops imx8mq_clk_ops = { + .set_rate = imx8mq_clk_set_rate, + .get_rate = imx8mq_clk_get_rate, + .enable = imx8mq_clk_enable, + .disable = imx8mq_clk_disable, + .set_parent = imx8mq_clk_set_parent, +}; + +static int imx8mq_clk_probe(struct udevice *dev) +{ + void __iomem *base; + + base = (void *)ANATOP_BASE_ADDR; + + clk_dm(IMX8MQ_CLK_32K, clk_register_fixed_rate(NULL, "ckil", 32768)); + + clk_dm(IMX8MQ_DRAM_PLL1_REF_SEL, + imx_clk_mux("dram_pll_ref_sel", base + 0x60, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_ARM_PLL_REF_SEL, + imx_clk_mux("arm_pll_ref_sel", base + 0x28, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_GPU_PLL_REF_SEL, + imx_clk_mux("gpu_pll_ref_sel", base + 0x18, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_VPU_PLL_REF_SEL, + imx_clk_mux("vpu_pll_ref_sel", base + 0x20, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_SYS3_PLL1_REF_SEL, + imx_clk_mux("sys3_pll_ref_sel", base + 0x48, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_AUDIO_PLL1_REF_SEL, + imx_clk_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_AUDIO_PLL2_REF_SEL, + imx_clk_mux("audio_pll2_ref_sel", base + 0x8, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_VIDEO_PLL1_REF_SEL, + imx_clk_mux("video_pll1_ref_sel", base + 0x10, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + + clk_dm(IMX8MQ_ARM_PLL, + imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", + base + 0x28, &imx8mq_1416x_pll)); + clk_dm(IMX8MQ_GPU_PLL, + imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel", + base + 0x18, &imx8mq_1416x_pll)); + clk_dm(IMX8MQ_VPU_PLL, + imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel", + base + 0x20, &imx8mq_1416x_pll)); + + clk_dm(IMX8MQ_SYS1_PLL1, + clk_register_fixed_rate(NULL, "sys1_pll", 800000000)); + clk_dm(IMX8MQ_SYS2_PLL1, + clk_register_fixed_rate(NULL, "sys2_pll", 1000000000)); + clk_dm(IMX8MQ_SYS2_PLL1, + clk_register_fixed_rate(NULL, "sys3_pll", 1000000000)); + clk_dm(IMX8MQ_AUDIO_PLL1, + imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel", + base + 0x0, &imx8mq_1443x_pll)); + clk_dm(IMX8MQ_AUDIO_PLL2, + imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel", + base + 0x8, &imx8mq_1443x_pll)); + clk_dm(IMX8MQ_VIDEO_PLL1, + imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel", + base + 0x10, &imx8mq_1443x_pll)); + + /* PLL bypass out */ + clk_dm(IMX8MQ_ARM_PLL_BYPASS, + imx_clk_mux_flags("arm_pll_bypass", base + 0x28, 4, 1, + arm_pll_bypass_sels, + ARRAY_SIZE(arm_pll_bypass_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX8MQ_GPU_PLL_BYPASS, + imx_clk_mux_flags("gpu_pll_bypass", base + 0x18, 4, 1, + gpu_pll_bypass_sels, + ARRAY_SIZE(gpu_pll_bypass_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX8MQ_VPU_PLL_BYPASS, + imx_clk_mux_flags("vpu_pll_bypass", base + 0x20, 4, 1, + vpu_pll_bypass_sels, + ARRAY_SIZE(vpu_pll_bypass_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX8MQ_AUDIO_PLL1_BYPASS, + imx_clk_mux_flags("audio_pll1_bypass", base + 0x0, 4, 1, + audio_pll1_bypass_sels, + ARRAY_SIZE(audio_pll1_bypass_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX8MQ_AUDIO_PLL2_BYPASS, + imx_clk_mux_flags("audio_pll2_bypass", base + 0x8, 4, 1, + audio_pll2_bypass_sels, + ARRAY_SIZE(audio_pll2_bypass_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX8MQ_VIDEO_PLL1_BYPASS, + imx_clk_mux_flags("video_pll1_bypass", base + 0x10, 4, 1, + video_pll1_bypass_sels, + ARRAY_SIZE(video_pll1_bypass_sels), + CLK_SET_RATE_PARENT)); + + /* PLL out gate */ + clk_dm(IMX8MQ_DRAM_PLL_OUT, + imx_clk_gate("dram_pll_out", "dram_pll_ref_sel", + base + 0x60, 13)); + clk_dm(IMX8MQ_ARM_PLL_OUT, + imx_clk_gate("arm_pll_out", "arm_pll_bypass", + base + 0x28, 11)); + clk_dm(IMX8MQ_GPU_PLL_OUT, + imx_clk_gate("gpu_pll_out", "gpu_pll_bypass", + base + 0x18, 11)); + clk_dm(IMX8MQ_VPU_PLL_OUT, + imx_clk_gate("vpu_pll_out", "vpu_pll_bypass", + base + 0x20, 11)); + clk_dm(IMX8MQ_AUDIO_PLL1_OUT, + imx_clk_gate("audio_pll1_out", "audio_pll1_bypass", + base + 0x0, 11)); + clk_dm(IMX8MQ_AUDIO_PLL2_OUT, + imx_clk_gate("audio_pll2_out", "audio_pll2_bypass", + base + 0x8, 11)); + clk_dm(IMX8MQ_VIDEO_PLL1_OUT, + imx_clk_gate("video_pll1_out", "video_pll1_bypass", + base + 0x10, 11)); + + clk_dm(IMX8MQ_SYS1_PLL_OUT, + imx_clk_gate("sys_pll1_out", "sys1_pll", + base + 0x30, 11)); + clk_dm(IMX8MQ_SYS2_PLL_OUT, + imx_clk_gate("sys_pll2_out", "sys2_pll", + base + 0x3c, 11)); + clk_dm(IMX8MQ_SYS3_PLL_OUT, + imx_clk_gate("sys_pll3_out", "sys3_pll", + base + 0x48, 11)); + + /* SYS PLL fixed output */ + clk_dm(IMX8MQ_SYS1_PLL_40M, + imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20)); + clk_dm(IMX8MQ_SYS1_PLL_80M, + imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10)); + clk_dm(IMX8MQ_SYS1_PLL_100M, + imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8)); + clk_dm(IMX8MQ_SYS1_PLL_133M, + imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6)); + clk_dm(IMX8MQ_SYS1_PLL_160M, + imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5)); + clk_dm(IMX8MQ_SYS1_PLL_200M, + imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4)); + clk_dm(IMX8MQ_SYS1_PLL_266M, + imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3)); + clk_dm(IMX8MQ_SYS1_PLL_400M, + imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2)); + clk_dm(IMX8MQ_SYS1_PLL_800M, + imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1)); + + clk_dm(IMX8MQ_SYS2_PLL_50M, + imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20)); + clk_dm(IMX8MQ_SYS2_PLL_100M, + imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10)); + clk_dm(IMX8MQ_SYS2_PLL_125M, + imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8)); + clk_dm(IMX8MQ_SYS2_PLL_166M, + imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6)); + clk_dm(IMX8MQ_SYS2_PLL_200M, + imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5)); + clk_dm(IMX8MQ_SYS2_PLL_250M, + imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4)); + clk_dm(IMX8MQ_SYS2_PLL_333M, + imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3)); + clk_dm(IMX8MQ_SYS2_PLL_500M, + imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2)); + clk_dm(IMX8MQ_SYS2_PLL_1000M, + imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1)); + + clk_dm(IMX8MQ_CLK_MON_AUDIO_PLL1_DIV, + imx_clk_divider("audio_pll1_out_monitor", "audio_pll1_bypass", base + 0x78, 0, 3)); + clk_dm(IMX8MQ_CLK_MON_AUDIO_PLL2_DIV, + imx_clk_divider("audio_pll2_out_monitor", "audio_pll2_bypass", base + 0x78, 4, 3)); + clk_dm(IMX8MQ_CLK_MON_VIDEO_PLL1_DIV, + imx_clk_divider("video_pll1_out_monitor", "video_pll1_bypass", base + 0x78, 8, 3)); + clk_dm(IMX8MQ_CLK_MON_GPU_PLL_DIV, + imx_clk_divider("gpu_pll_out_monitor", "gpu_pll_bypass", base + 0x78, 12, 3)); + clk_dm(IMX8MQ_CLK_MON_VPU_PLL_DIV, + imx_clk_divider("vpu_pll_out_monitor", "vpu_pll_bypass", base + 0x78, 16, 3)); + clk_dm(IMX8MQ_CLK_MON_ARM_PLL_DIV, + imx_clk_divider("arm_pll_out_monitor", "arm_pll_bypass", base + 0x78, 20, 3)); + clk_dm(IMX8MQ_CLK_MON_SYS_PLL1_DIV, + imx_clk_divider("sys_pll1_out_monitor", "sys_pll1_out", base + 0x7c, 0, 3)); + clk_dm(IMX8MQ_CLK_MON_SYS_PLL2_DIV, + imx_clk_divider("sys_pll2_out_monitor", "sys_pll2_out", base + 0x7c, 4, 3)); + clk_dm(IMX8MQ_CLK_MON_SYS_PLL3_DIV, + imx_clk_divider("sys_pll3_out_monitor", "sys_pll3_out", base + 0x7c, 8, 3)); + clk_dm(IMX8MQ_CLK_MON_DRAM_PLL_DIV, + imx_clk_divider("dram_pll_out_monitor", "dram_pll_out", base + 0x7c, 12, 3)); + clk_dm(IMX8MQ_CLK_MON_SEL, + imx_clk_mux_flags("pllout_monitor_sel", base + 0x74, 0, 4, + pllout_monitor_sels, + ARRAY_SIZE(pllout_monitor_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX8MQ_CLK_MON_CLK2_OUT, + imx_clk_gate4("pllout_monitor_clk2", "pllout_monitor_sel", base + 0x74, 4)); + + base = dev_read_addr_ptr(dev); + if (!base) { + printf("%s : base failed\n", __func__); + return -EINVAL; + } + + clk_dm(IMX8MQ_CLK_A53_SRC, + imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3, + imx8mq_a53_sels, ARRAY_SIZE(imx8mq_a53_sels))); + clk_dm(IMX8MQ_CLK_A53_CG, + imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28)); + clk_dm(IMX8MQ_CLK_A53_DIV, + imx_clk_divider2("arm_a53_div", "arm_a53_cg", + base + 0x8000, 0, 3)); + clk_dm(IMX8MQ_CLK_A53_CORE, + imx_clk_mux2("arm_a53_src", base + 0x9880, 24, 1, + imx8mq_a53_core_sels, ARRAY_SIZE(imx8mq_a53_core_sels))); + + clk_dm(IMX8MQ_CLK_AHB, + imx8m_clk_composite_critical("ahb", imx8mq_ahb_sels, + base + 0x9000)); + clk_dm(IMX8MQ_CLK_IPG_ROOT, + imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1)); + + clk_dm(IMX8MQ_CLK_ENET_AXI, + imx8m_clk_composite("enet_axi", imx8mq_enet_axi_sels, + base + 0x8880)); + clk_dm(IMX8MQ_CLK_NAND_USDHC_BUS, + imx8m_clk_composite_critical("nand_usdhc_bus", + imx8mq_nand_usdhc_sels, + base + 0x8900)); + clk_dm(IMX8MQ_CLK_USB_BUS, + imx8m_clk_composite("usb_bus", imx8mq_usb_bus_sels, base + 0x8b80)); + + /* IP */ + clk_dm(IMX8MQ_CLK_USDHC1, + imx8m_clk_composite("usdhc1", imx8mq_usdhc1_sels, + base + 0xac00)); + clk_dm(IMX8MQ_CLK_USDHC2, + imx8m_clk_composite("usdhc2", imx8mq_usdhc2_sels, + base + 0xac80)); + clk_dm(IMX8MQ_CLK_I2C1, + imx8m_clk_composite("i2c1", imx8mq_i2c1_sels, base + 0xad00)); + clk_dm(IMX8MQ_CLK_I2C2, + imx8m_clk_composite("i2c2", imx8mq_i2c2_sels, base + 0xad80)); + clk_dm(IMX8MQ_CLK_I2C3, + imx8m_clk_composite("i2c3", imx8mq_i2c3_sels, base + 0xae00)); + clk_dm(IMX8MQ_CLK_I2C4, + imx8m_clk_composite("i2c4", imx8mq_i2c4_sels, base + 0xae80)); + clk_dm(IMX8MQ_CLK_WDOG, + imx8m_clk_composite("wdog", imx8mq_wdog_sels, base + 0xb900)); + clk_dm(IMX8MQ_CLK_QSPI, + imx8m_clk_composite("qspi", imx8mq_qspi_sels, base + 0xab80)); + clk_dm(IMX8MQ_CLK_USB_CORE_REF, + imx8m_clk_composite("usb_core_ref", imx8mq_usb_core_sels, base + 0xb100)); + clk_dm(IMX8MQ_CLK_USB_PHY_REF, + imx8m_clk_composite("usb_phy_ref", imx8mq_usb_phy_sels, base + 0xb180)); + clk_dm(IMX8MQ_CLK_ECSPI1, + imx8m_clk_composite("ecspi1", imx8mq_ecspi1_sels, base + 0xb280)); + clk_dm(IMX8MQ_CLK_ECSPI2, + imx8m_clk_composite("ecspi2", imx8mq_ecspi2_sels, base + 0xb300)); + clk_dm(IMX8MQ_CLK_ECSPI3, + imx8m_clk_composite("ecspi3", imx8mq_ecspi3_sels, base + 0xc180)); + + clk_dm(IMX8MQ_CLK_ECSPI1_ROOT, + imx_clk_gate4("ecspi1_root_clk", "ecspi1", base + 0x4070, 0)); + clk_dm(IMX8MQ_CLK_ECSPI2_ROOT, + imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0)); + clk_dm(IMX8MQ_CLK_ECSPI3_ROOT, + imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0)); + clk_dm(IMX8MQ_CLK_I2C1_ROOT, + imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0)); + clk_dm(IMX8MQ_CLK_I2C2_ROOT, + imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0)); + clk_dm(IMX8MQ_CLK_I2C3_ROOT, + imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0)); + clk_dm(IMX8MQ_CLK_I2C4_ROOT, + imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0)); + clk_dm(IMX8MQ_CLK_OCOTP_ROOT, + imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0)); + clk_dm(IMX8MQ_CLK_USDHC1_ROOT, + imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0)); + clk_dm(IMX8MQ_CLK_USDHC2_ROOT, + imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0)); + clk_dm(IMX8MQ_CLK_WDOG1_ROOT, + imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0)); + clk_dm(IMX8MQ_CLK_WDOG2_ROOT, + imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0)); + clk_dm(IMX8MQ_CLK_WDOG3_ROOT, + imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0)); + clk_dm(IMX8MQ_CLK_QSPI_ROOT, + imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0)); + clk_dm(IMX8MQ_CLK_USB1_CTRL_ROOT, + imx_clk_gate4("usb1_ctrl_root_clk", "usb_bus", base + 0x44d0, 0)); + clk_dm(IMX8MQ_CLK_USB2_CTRL_ROOT, + imx_clk_gate4("usb2_ctrl_root_clk", "usb_bus", base + 0x44e0, 0)); + clk_dm(IMX8MQ_CLK_USB1_PHY_ROOT, + imx_clk_gate4("usb1_phy_root_clk", "usb_phy_ref", base + 0x44f0, 0)); + clk_dm(IMX8MQ_CLK_USB2_PHY_ROOT, + imx_clk_gate4("usb2_phy_root_clk", "usb_phy_ref", base + 0x4500, 0)); + + clk_dm(IMX8MQ_CLK_ENET_REF, + imx8m_clk_composite("enet_ref", imx8mq_enet_ref_sels, + base + 0xa980)); + clk_dm(IMX8MQ_CLK_ENET_TIMER, + imx8m_clk_composite("enet_timer", imx8mq_enet_timer_sels, + base + 0xaa00)); + clk_dm(IMX8MQ_CLK_ENET_PHY_REF, + imx8m_clk_composite("enet_phy", imx8mq_enet_phy_sels, + base + 0xaa80)); + clk_dm(IMX8MQ_CLK_ENET1_ROOT, + imx_clk_gate4("enet1_root_clk", "enet_axi", + base + 0x40a0, 0)); + + return 0; +} + +static const struct udevice_id imx8mq_clk_ids[] = { + { .compatible = "fsl,imx8mq-ccm" }, + { }, +}; + +U_BOOT_DRIVER(imx8mq_clk) = { + .name = "clk_imx8mq", + .id = UCLASS_CLK, + .of_match = imx8mq_clk_ids, + .ops = &imx8mq_clk_ops, + .probe = imx8mq_clk_probe, + .flags = DM_FLAG_PRE_RELOC, +};

Hi Angus,
Am Di., 15. März 2022 um 14:09 Uhr schrieb Angus Ainslie angus@akkea.ca:
This is a DM clock driver based off the imx8mm u-boot driver and the linux kernel driver.
All of the PLLs and clocks are initialized so the subsystems below are functional and tested.
- USB host and peripheral
- ECSPI
- UART
- I2C all busses
- USDHC for eMMC support
- USB storage
- GPIO
- DRAM
Signed-off-by: Angus Ainslie angus@akkea.ca
drivers/clk/imx/Kconfig | 16 + drivers/clk/imx/Makefile | 2 + drivers/clk/imx/clk-imx8mq.c | 575 +++++++++++++++++++++++++++++++++++ 3 files changed, 593 insertions(+) create mode 100644 drivers/clk/imx/clk-imx8mq.c
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index cdd348020b0..06d8c1a5dd3 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -71,6 +71,22 @@ config CLK_IMX8MP help This enables support clock driver for i.MX8MP platforms.
+config SPL_CLK_IMX8MQ
bool "SPL clock support for i.MX8MQ"
depends on ARCH_IMX8M && SPL
select SPL_CLK
select SPL_CLK_CCF
you should select SPL_CLK_COMPOSITE_CCF ...
help
This enables SPL DM/DTS support for clock driver in i.MX8MQ
+config CLK_IMX8MQ
bool "Clock support for i.MX8MQ"
depends on ARCH_IMX8M
select CLK
select CLK_CCF
.. and select CLK_COMPOSITE_CCF here.
help
This enables support clock driver for i.MX8MQ platforms.
config SPL_CLK_IMXRT1020 bool "SPL clock support for i.MXRT1020" depends on ARCH_IMXRT && SPL
[SNIP]

Hi Angus and all,
Am Di., 15. März 2022 um 14:09 Uhr schrieb Angus Ainslie angus@akkea.ca:
This is a DM clock driver based off the imx8mm u-boot driver and the linux kernel driver.
All of the PLLs and clocks are initialized so the subsystems below are functional and tested.
- USB host and peripheral
- ECSPI
- UART
- I2C all busses
- USDHC for eMMC support
- USB storage
- GPIO
- DRAM
Signed-off-by: Angus Ainslie angus@akkea.ca
drivers/clk/imx/Kconfig | 16 + drivers/clk/imx/Makefile | 2 + drivers/clk/imx/clk-imx8mq.c | 575 +++++++++++++++++++++++++++++++++++ 3 files changed, 593 insertions(+) create mode 100644 drivers/clk/imx/clk-imx8mq.c
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index cdd348020b0..06d8c1a5dd3 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -71,6 +71,22 @@ config CLK_IMX8MP help This enables support clock driver for i.MX8MP platforms.
+config SPL_CLK_IMX8MQ
bool "SPL clock support for i.MX8MQ"
depends on ARCH_IMX8M && SPL
select SPL_CLK
select SPL_CLK_CCF
help
This enables SPL DM/DTS support for clock driver in i.MX8MQ
+config CLK_IMX8MQ
bool "Clock support for i.MX8MQ"
depends on ARCH_IMX8M
select CLK
select CLK_CCF
help
This enables support clock driver for i.MX8MQ platforms.
config SPL_CLK_IMXRT1020 bool "SPL clock support for i.MXRT1020" depends on ARCH_IMXRT && SPL diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 01bbbdf3aea..c5766901f2b 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -16,6 +16,8 @@ obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MN) += clk-imx8mn.o clk-pll14xx.o \ clk-composite-8m.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MP) += clk-imx8mp.o clk-pll14xx.o \ clk-composite-8m.o +obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MQ) += clk-imx8mq.o clk-pll14xx.o \
clk-composite-8m.o
obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1020) += clk-imxrt1020.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1050) += clk-imxrt1050.o diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c new file mode 100644 index 00000000000..0aea417a29b --- /dev/null +++ b/drivers/clk/imx/clk-imx8mq.c @@ -0,0 +1,575 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- Copyright 2019 NXP
- Copyright 2022 Purism
- Peng Fan peng.fan@nxp.com
- */
+#include <common.h> +#include <clk.h> +#include <clk-uclass.h> +#include <dm.h> +#include <log.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <dt-bindings/clock/imx8mq-clock.h>
+#include "clk.h"
+#define PLL_1416X_RATE(_rate, _m, _p, _s) \
{ \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
}
+#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \
{ \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.kdiv = (_k), \
}
+static const struct imx_pll14xx_rate_table imx8mq_pll1416x_tbl[] = {
PLL_1416X_RATE(1800000000U, 225, 3, 0),
PLL_1416X_RATE(1600000000U, 200, 3, 0),
PLL_1416X_RATE(1200000000U, 300, 3, 1),
PLL_1416X_RATE(1000000000U, 250, 3, 1),
PLL_1416X_RATE(800000000U, 200, 3, 1),
PLL_1416X_RATE(750000000U, 250, 2, 2),
PLL_1416X_RATE(700000000U, 350, 3, 2),
PLL_1416X_RATE(600000000U, 300, 3, 2),
+};
+const struct imx_pll14xx_rate_table imx8mq_pll1443x_tbl[] = {
PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
PLL_1443X_RATE(594000000U, 198, 2, 2, 0),
PLL_1443X_RATE(393216000U, 262, 2, 3, 9437),
PLL_1443X_RATE(361267200U, 361, 3, 3, 17511),
+};
+static struct imx_pll14xx_clk imx8mq_1416x_pll __initdata = {
.type = PLL_1416X,
.rate_table = imx8mq_pll1416x_tbl,
.rate_count = ARRAY_SIZE(imx8mq_pll1416x_tbl),
+};
+static struct imx_pll14xx_clk imx8mq_1443x_pll __initdata = {
.type = PLL_1443X,
.rate_table = imx8mq_pll1443x_tbl,
.rate_count = ARRAY_SIZE(imx8mq_pll1443x_tbl),
+};
+static const char *pll_ref_sels[] = { "clock-osc-25m", "clock-osc-27m", "clock-phy-27m", "dummy", }; +static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; +static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", }; +static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", }; +static const char *audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", }; +static const char *audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", }; +static const char *video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
+static const char *imx8mq_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", }; +static const char *imx8mq_a53_sels[] = {"clock-osc-25m", "arm_pll_out", "sys_pll2_500m",
"sys_pll2_1000m", "sys_pll1_800m",
"sys_pll1_400m",
"audio_pll1_out", "sys_pll3_out",
};
+static const char *imx8mq_ahb_sels[] = {"clock-osc-25m", "sys_pll1_133m", "sys_pll1_800m",
"sys_pll1_400m", "sys_pll2_125m",
"sys_pll3_out",
"audio_pll1_out",
"video_pll1_out", };
+static const char *imx8mq_enet_axi_sels[] = {"clock-osc-25m", "sys_pll1_266m", "sys_pll1_800m",
"sys_pll2_250m",
"sys_pll2_200m", "audio_pll1_out",
"video_pll1_out",
"sys_pll3_out", };
+static const char *imx8mq_enet_ref_sels[] = {"clock-osc-25m", "sys_pll2_125m", "sys_pll2_50m",
"sys_pll2_100m",
"sys_pll1_160m", "audio_pll1_out",
"video_pll1_out", "clk_ext4",
};
+static const char *imx8mq_enet_timer_sels[] = {"clock-osc-25m", "sys_pll2_100m", "audio_pll1_out",
"clk_ext1", "clk_ext2",
"clk_ext3", "clk_ext4",
"video_pll1_out", };
+static const char *imx8mq_enet_phy_sels[] = {"clock-osc-25m", "sys_pll2_50m", "sys_pll2_125m",
"sys_pll2_200m",
"sys_pll2_500m", "video_pll1_out",
"audio_pll2_out", };
+static const char *imx8mq_nand_usdhc_sels[] = {"clock-osc-25m", "sys_pll1_266m", "sys_pll1_800m",
"sys_pll2_200m",
"sys_pll1_133m", "sys_pll3_out",
"sys_pll2_250m",
"audio_pll1_out", };
+static const char *imx8mq_usb_bus_sels[] = {"clock-osc-25m", "sys_pll2_500m", "sys_pll1_800m",
"sys_pll2_100m",
"sys_pll2_200m", "clk_ext2",
"clk_ext4", "audio_pll2_out",
};
+static const char *imx8mq_usdhc1_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll1_800m",
"sys_pll2_500m",
"sys_pll3_out", "sys_pll1_266m",
"audio_pll2_out",
"sys_pll1_100m", };
+static const char *imx8mq_usdhc2_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll1_800m",
"sys_pll2_500m",
"sys_pll3_out", "sys_pll1_266m",
"audio_pll2_out",
"sys_pll1_100m", };
+static const char *imx8mq_i2c1_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m",
"sys_pll3_out", "audio_pll1_out",
"video_pll1_out",
"audio_pll2_out",
"sys_pll1_133m", };
+static const char *imx8mq_i2c2_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m",
"sys_pll3_out", "audio_pll1_out",
"video_pll1_out",
"audio_pll2_out",
"sys_pll1_133m", };
+static const char *imx8mq_i2c3_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m",
"sys_pll3_out", "audio_pll1_out",
"video_pll1_out",
"audio_pll2_out",
"sys_pll1_133m", };
+static const char *imx8mq_i2c4_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m",
"sys_pll3_out", "audio_pll1_out",
"video_pll1_out",
"audio_pll2_out",
"sys_pll1_133m", };
+static const char *imx8mq_wdog_sels[] = {"clock-osc-25m", "sys_pll1_133m", "sys_pll1_160m",
"vpu_pll_out", "sys_pll2_125m",
"sys_pll3_out",
"sys_pll1_80m", "sys_pll2_166m",
};
+static const char *imx8mq_qspi_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll2_333m",
"sys_pll2_500m",
"audio_pll2_out", "sys_pll1_266m",
"sys_pll3_out", "sys_pll1_100m",
};
+static const char *imx8mq_usb_core_sels[] = {"clock-osc-25m", "sys_pll1_100m", "sys_pll1_40m",
"sys_pll2_100m",
"sys_pll2_200m", "clk_ext2",
"clk_ext3", "audio_pll2_out",
};
+static const char *imx8mq_usb_phy_sels[] = {"clock-osc-25m", "sys_pll1_100m", "sys_pll1_40m",
"sys_pll2_100m",
"sys_pll2_200m", "clk_ext2",
"clk_ext3", "audio_pll2_out",
};
+static const char *imx8mq_ecspi1_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m",
"sys_pll1_160m",
"sys_pll1_800m", "sys_pll3_out",
"sys_pll2_250m",
"audio_pll2_out", };
+static const char *imx8mq_ecspi2_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m",
"sys_pll1_160m",
"sys_pll1_800m", "sys_pll3_out",
"sys_pll2_250m",
"audio_pll2_out", };
+static const char *imx8mq_ecspi3_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m",
"sys_pll1_160m",
"sys_pll1_800m", "sys_pll3_out",
"sys_pll2_250m",
"audio_pll2_out", };
+static const char *pllout_monitor_sels[] = {"clock-osc-25m", "clock-osc-27m", "clock-phy-27m",
"dummy", "clock-ckil",
"audio_pll1_out_monitor",
"audio_pll2_out_monitor",
"gpu_pll_out_monitor",
"vpu_pll_out_monitor",
"video_pll1_out_monitor",
"arm_pll_out_monitor",
"sys_pll1_out_monitor",
"sys_pll2_out_monitor",
"sys_pll3_out_monitor",
"dummy",
"dram_pll_out_monitor", };
+static ulong imx8mq_clk_get_rate(struct clk *clk) +{
struct clk *c;
int ret;
debug("%s(#%lu)\n", __func__, clk->id);
ret = clk_get_by_id(clk->id, &c);
if (ret)
return ret;
return clk_get_rate(c);
+}
+static ulong imx8mq_clk_set_rate(struct clk *clk, unsigned long rate) +{
struct clk *c;
int ret;
debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
ret = clk_get_by_id(clk->id, &c);
if (ret)
return ret;
return clk_set_rate(c, rate);
+}
+static int __imx8mq_clk_enable(struct clk *clk, bool enable) +{
struct clk *c;
int ret;
debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
ret = clk_get_by_id(clk->id, &c);
if (ret) {
debug("%s: clk_get_by_id failed\n", __func__);
return ret;
}
if (enable)
ret = clk_enable(c);
else
ret = clk_disable(c);
return ret;
+}
+static int imx8mq_clk_disable(struct clk *clk) +{
return __imx8mq_clk_enable(clk, 0);
+}
+static int imx8mq_clk_enable(struct clk *clk) +{
return __imx8mq_clk_enable(clk, 1);
+}
+static int imx8mq_clk_set_parent(struct clk *clk, struct clk *parent) +{
struct clk *c, *cp;
int ret;
debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
ret = clk_get_by_id(clk->id, &c);
if (ret)
return ret;
ret = clk_get_by_id(parent->id, &cp);
if (ret)
return ret;
ret = clk_set_parent(c, cp);
c->dev->parent = cp->dev;
return ret;
+}
+static struct clk_ops imx8mq_clk_ops = {
.set_rate = imx8mq_clk_set_rate,
.get_rate = imx8mq_clk_get_rate,
.enable = imx8mq_clk_enable,
.disable = imx8mq_clk_disable,
.set_parent = imx8mq_clk_set_parent,
+};
+static int imx8mq_clk_probe(struct udevice *dev) +{
void __iomem *base;
base = (void *)ANATOP_BASE_ADDR;
clk_dm(IMX8MQ_CLK_32K, clk_register_fixed_rate(NULL, "ckil",
32768));
clk_dm(IMX8MQ_DRAM_PLL1_REF_SEL,
imx_clk_mux("dram_pll_ref_sel", base + 0x60, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
clk_dm(IMX8MQ_ARM_PLL_REF_SEL,
imx_clk_mux("arm_pll_ref_sel", base + 0x28, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
clk_dm(IMX8MQ_GPU_PLL_REF_SEL,
imx_clk_mux("gpu_pll_ref_sel", base + 0x18, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
clk_dm(IMX8MQ_VPU_PLL_REF_SEL,
imx_clk_mux("vpu_pll_ref_sel", base + 0x20, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
clk_dm(IMX8MQ_SYS3_PLL1_REF_SEL,
imx_clk_mux("sys3_pll_ref_sel", base + 0x48, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
clk_dm(IMX8MQ_AUDIO_PLL1_REF_SEL,
imx_clk_mux("audio_pll1_ref_sel", base + 0x0, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
clk_dm(IMX8MQ_AUDIO_PLL2_REF_SEL,
imx_clk_mux("audio_pll2_ref_sel", base + 0x8, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
clk_dm(IMX8MQ_VIDEO_PLL1_REF_SEL,
imx_clk_mux("video_pll1_ref_sel", base + 0x10, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
clk_dm(IMX8MQ_ARM_PLL,
imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel",
base + 0x28, &imx8mq_1416x_pll));
clk_dm(IMX8MQ_GPU_PLL,
imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel",
base + 0x18, &imx8mq_1416x_pll));
clk_dm(IMX8MQ_VPU_PLL,
imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel",
base + 0x20, &imx8mq_1416x_pll));
clk_dm(IMX8MQ_SYS1_PLL1,
clk_register_fixed_rate(NULL, "sys1_pll", 800000000));
clk_dm(IMX8MQ_SYS2_PLL1,
clk_register_fixed_rate(NULL, "sys2_pll", 1000000000));
clk_dm(IMX8MQ_SYS2_PLL1,
clk_register_fixed_rate(NULL, "sys3_pll", 1000000000));
clk_dm(IMX8MQ_AUDIO_PLL1,
imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel",
base + 0x0, &imx8mq_1443x_pll));
clk_dm(IMX8MQ_AUDIO_PLL2,
imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel",
base + 0x8, &imx8mq_1443x_pll));
clk_dm(IMX8MQ_VIDEO_PLL1,
imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel",
base + 0x10, &imx8mq_1443x_pll));
/* PLL bypass out */
clk_dm(IMX8MQ_ARM_PLL_BYPASS,
imx_clk_mux_flags("arm_pll_bypass", base + 0x28, 4, 1,
arm_pll_bypass_sels,
ARRAY_SIZE(arm_pll_bypass_sels),
CLK_SET_RATE_PARENT));
clk_dm(IMX8MQ_GPU_PLL_BYPASS,
imx_clk_mux_flags("gpu_pll_bypass", base + 0x18, 4, 1,
gpu_pll_bypass_sels,
ARRAY_SIZE(gpu_pll_bypass_sels),
CLK_SET_RATE_PARENT));
clk_dm(IMX8MQ_VPU_PLL_BYPASS,
imx_clk_mux_flags("vpu_pll_bypass", base + 0x20, 4, 1,
vpu_pll_bypass_sels,
ARRAY_SIZE(vpu_pll_bypass_sels),
CLK_SET_RATE_PARENT));
clk_dm(IMX8MQ_AUDIO_PLL1_BYPASS,
imx_clk_mux_flags("audio_pll1_bypass", base + 0x0, 4, 1,
audio_pll1_bypass_sels,
ARRAY_SIZE(audio_pll1_bypass_sels),
CLK_SET_RATE_PARENT));
clk_dm(IMX8MQ_AUDIO_PLL2_BYPASS,
imx_clk_mux_flags("audio_pll2_bypass", base + 0x8, 4, 1,
audio_pll2_bypass_sels,
ARRAY_SIZE(audio_pll2_bypass_sels),
CLK_SET_RATE_PARENT));
clk_dm(IMX8MQ_VIDEO_PLL1_BYPASS,
imx_clk_mux_flags("video_pll1_bypass", base + 0x10, 4, 1,
video_pll1_bypass_sels,
ARRAY_SIZE(video_pll1_bypass_sels),
CLK_SET_RATE_PARENT));
/* PLL out gate */
clk_dm(IMX8MQ_DRAM_PLL_OUT,
imx_clk_gate("dram_pll_out", "dram_pll_ref_sel",
base + 0x60, 13));
clk_dm(IMX8MQ_ARM_PLL_OUT,
imx_clk_gate("arm_pll_out", "arm_pll_bypass",
base + 0x28, 11));
clk_dm(IMX8MQ_GPU_PLL_OUT,
imx_clk_gate("gpu_pll_out", "gpu_pll_bypass",
base + 0x18, 11));
clk_dm(IMX8MQ_VPU_PLL_OUT,
imx_clk_gate("vpu_pll_out", "vpu_pll_bypass",
base + 0x20, 11));
clk_dm(IMX8MQ_AUDIO_PLL1_OUT,
imx_clk_gate("audio_pll1_out", "audio_pll1_bypass",
base + 0x0, 11));
clk_dm(IMX8MQ_AUDIO_PLL2_OUT,
imx_clk_gate("audio_pll2_out", "audio_pll2_bypass",
base + 0x8, 11));
clk_dm(IMX8MQ_VIDEO_PLL1_OUT,
imx_clk_gate("video_pll1_out", "video_pll1_bypass",
base + 0x10, 11));
clk_dm(IMX8MQ_SYS1_PLL_OUT,
imx_clk_gate("sys_pll1_out", "sys1_pll",
base + 0x30, 11));
clk_dm(IMX8MQ_SYS2_PLL_OUT,
imx_clk_gate("sys_pll2_out", "sys2_pll",
base + 0x3c, 11));
clk_dm(IMX8MQ_SYS3_PLL_OUT,
imx_clk_gate("sys_pll3_out", "sys3_pll",
base + 0x48, 11));
/* SYS PLL fixed output */
clk_dm(IMX8MQ_SYS1_PLL_40M,
imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1,
20));
clk_dm(IMX8MQ_SYS1_PLL_80M,
imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1,
10));
clk_dm(IMX8MQ_SYS1_PLL_100M,
imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1,
8));
clk_dm(IMX8MQ_SYS1_PLL_133M,
imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1,
6));
clk_dm(IMX8MQ_SYS1_PLL_160M,
imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1,
5));
clk_dm(IMX8MQ_SYS1_PLL_200M,
imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1,
4));
clk_dm(IMX8MQ_SYS1_PLL_266M,
imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1,
3));
clk_dm(IMX8MQ_SYS1_PLL_400M,
imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1,
2));
clk_dm(IMX8MQ_SYS1_PLL_800M,
imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1,
1));
clk_dm(IMX8MQ_SYS2_PLL_50M,
imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1,
20));
clk_dm(IMX8MQ_SYS2_PLL_100M,
imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1,
10));
clk_dm(IMX8MQ_SYS2_PLL_125M,
imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1,
8));
clk_dm(IMX8MQ_SYS2_PLL_166M,
imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1,
6));
clk_dm(IMX8MQ_SYS2_PLL_200M,
imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1,
5));
clk_dm(IMX8MQ_SYS2_PLL_250M,
imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1,
4));
clk_dm(IMX8MQ_SYS2_PLL_333M,
imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1,
3));
clk_dm(IMX8MQ_SYS2_PLL_500M,
imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1,
2));
clk_dm(IMX8MQ_SYS2_PLL_1000M,
imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1,
1));
clk_dm(IMX8MQ_CLK_MON_AUDIO_PLL1_DIV,
imx_clk_divider("audio_pll1_out_monitor",
"audio_pll1_bypass", base + 0x78, 0, 3));
clk_dm(IMX8MQ_CLK_MON_AUDIO_PLL2_DIV,
imx_clk_divider("audio_pll2_out_monitor",
"audio_pll2_bypass", base + 0x78, 4, 3));
clk_dm(IMX8MQ_CLK_MON_VIDEO_PLL1_DIV,
imx_clk_divider("video_pll1_out_monitor",
"video_pll1_bypass", base + 0x78, 8, 3));
clk_dm(IMX8MQ_CLK_MON_GPU_PLL_DIV,
imx_clk_divider("gpu_pll_out_monitor", "gpu_pll_bypass",
base + 0x78, 12, 3));
clk_dm(IMX8MQ_CLK_MON_VPU_PLL_DIV,
imx_clk_divider("vpu_pll_out_monitor", "vpu_pll_bypass",
base + 0x78, 16, 3));
clk_dm(IMX8MQ_CLK_MON_ARM_PLL_DIV,
imx_clk_divider("arm_pll_out_monitor", "arm_pll_bypass",
base + 0x78, 20, 3));
clk_dm(IMX8MQ_CLK_MON_SYS_PLL1_DIV,
imx_clk_divider("sys_pll1_out_monitor", "sys_pll1_out",
base + 0x7c, 0, 3));
clk_dm(IMX8MQ_CLK_MON_SYS_PLL2_DIV,
imx_clk_divider("sys_pll2_out_monitor", "sys_pll2_out",
base + 0x7c, 4, 3));
clk_dm(IMX8MQ_CLK_MON_SYS_PLL3_DIV,
imx_clk_divider("sys_pll3_out_monitor", "sys_pll3_out",
base + 0x7c, 8, 3));
clk_dm(IMX8MQ_CLK_MON_DRAM_PLL_DIV,
imx_clk_divider("dram_pll_out_monitor", "dram_pll_out",
base + 0x7c, 12, 3));
clk_dm(IMX8MQ_CLK_MON_SEL,
imx_clk_mux_flags("pllout_monitor_sel", base + 0x74, 0, 4,
pllout_monitor_sels,
ARRAY_SIZE(pllout_monitor_sels),
CLK_SET_RATE_PARENT));
clk_dm(IMX8MQ_CLK_MON_CLK2_OUT,
imx_clk_gate4("pllout_monitor_clk2", "pllout_monitor_sel",
base + 0x74, 4));
base = dev_read_addr_ptr(dev);
if (!base) {
printf("%s : base failed\n", __func__);
return -EINVAL;
}
clk_dm(IMX8MQ_CLK_A53_SRC,
imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3,
imx8mq_a53_sels, ARRAY_SIZE(imx8mq_a53_sels)));
clk_dm(IMX8MQ_CLK_A53_CG,
imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000,
28));
clk_dm(IMX8MQ_CLK_A53_DIV,
imx_clk_divider2("arm_a53_div", "arm_a53_cg",
base + 0x8000, 0, 3));
clk_dm(IMX8MQ_CLK_A53_CORE,
imx_clk_mux2("arm_a53_src", base + 0x9880, 24, 1,
imx8mq_a53_core_sels,
ARRAY_SIZE(imx8mq_a53_core_sels)));
clk_dm(IMX8MQ_CLK_AHB,
imx8m_clk_composite_critical("ahb", imx8mq_ahb_sels,
base + 0x9000));
clk_dm(IMX8MQ_CLK_IPG_ROOT,
imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1));
clk_dm(IMX8MQ_CLK_ENET_AXI,
imx8m_clk_composite("enet_axi", imx8mq_enet_axi_sels,
base + 0x8880));
clk_dm(IMX8MQ_CLK_NAND_USDHC_BUS,
imx8m_clk_composite_critical("nand_usdhc_bus",
imx8mq_nand_usdhc_sels,
base + 0x8900));
clk_dm(IMX8MQ_CLK_USB_BUS,
imx8m_clk_composite("usb_bus", imx8mq_usb_bus_sels, base +
0x8b80));
/* IP */
clk_dm(IMX8MQ_CLK_USDHC1,
imx8m_clk_composite("usdhc1", imx8mq_usdhc1_sels,
base + 0xac00));
clk_dm(IMX8MQ_CLK_USDHC2,
imx8m_clk_composite("usdhc2", imx8mq_usdhc2_sels,
base + 0xac80));
clk_dm(IMX8MQ_CLK_I2C1,
imx8m_clk_composite("i2c1", imx8mq_i2c1_sels, base +
0xad00));
clk_dm(IMX8MQ_CLK_I2C2,
imx8m_clk_composite("i2c2", imx8mq_i2c2_sels, base +
0xad80));
clk_dm(IMX8MQ_CLK_I2C3,
imx8m_clk_composite("i2c3", imx8mq_i2c3_sels, base +
0xae00));
clk_dm(IMX8MQ_CLK_I2C4,
imx8m_clk_composite("i2c4", imx8mq_i2c4_sels, base +
0xae80));
clk_dm(IMX8MQ_CLK_WDOG,
imx8m_clk_composite("wdog", imx8mq_wdog_sels, base +
0xb900));
clk_dm(IMX8MQ_CLK_QSPI,
imx8m_clk_composite("qspi", imx8mq_qspi_sels, base +
0xab80));
clk_dm(IMX8MQ_CLK_USB_CORE_REF,
imx8m_clk_composite("usb_core_ref", imx8mq_usb_core_sels,
base + 0xb100));
clk_dm(IMX8MQ_CLK_USB_PHY_REF,
imx8m_clk_composite("usb_phy_ref", imx8mq_usb_phy_sels,
base + 0xb180));
clk_dm(IMX8MQ_CLK_ECSPI1,
imx8m_clk_composite("ecspi1", imx8mq_ecspi1_sels, base +
0xb280));
clk_dm(IMX8MQ_CLK_ECSPI2,
imx8m_clk_composite("ecspi2", imx8mq_ecspi2_sels, base +
0xb300));
clk_dm(IMX8MQ_CLK_ECSPI3,
imx8m_clk_composite("ecspi3", imx8mq_ecspi3_sels, base +
0xc180));
clk_dm(IMX8MQ_CLK_ECSPI1_ROOT,
imx_clk_gate4("ecspi1_root_clk", "ecspi1", base + 0x4070,
0));
clk_dm(IMX8MQ_CLK_ECSPI2_ROOT,
imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080,
0));
clk_dm(IMX8MQ_CLK_ECSPI3_ROOT,
imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090,
0));
clk_dm(IMX8MQ_CLK_I2C1_ROOT,
imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0));
clk_dm(IMX8MQ_CLK_I2C2_ROOT,
imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0));
clk_dm(IMX8MQ_CLK_I2C3_ROOT,
imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0));
clk_dm(IMX8MQ_CLK_I2C4_ROOT,
imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0));
clk_dm(IMX8MQ_CLK_OCOTP_ROOT,
imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220,
0));
clk_dm(IMX8MQ_CLK_USDHC1_ROOT,
imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510,
0));
clk_dm(IMX8MQ_CLK_USDHC2_ROOT,
imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520,
0));
clk_dm(IMX8MQ_CLK_WDOG1_ROOT,
imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0));
clk_dm(IMX8MQ_CLK_WDOG2_ROOT,
imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0));
clk_dm(IMX8MQ_CLK_WDOG3_ROOT,
imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0));
clk_dm(IMX8MQ_CLK_QSPI_ROOT,
imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0));
clk_dm(IMX8MQ_CLK_USB1_CTRL_ROOT,
imx_clk_gate4("usb1_ctrl_root_clk", "usb_bus", base +
0x44d0, 0));
clk_dm(IMX8MQ_CLK_USB2_CTRL_ROOT,
imx_clk_gate4("usb2_ctrl_root_clk", "usb_bus", base +
0x44e0, 0));
clk_dm(IMX8MQ_CLK_USB1_PHY_ROOT,
imx_clk_gate4("usb1_phy_root_clk", "usb_phy_ref", base +
0x44f0, 0));
clk_dm(IMX8MQ_CLK_USB2_PHY_ROOT,
imx_clk_gate4("usb2_phy_root_clk", "usb_phy_ref", base +
0x4500, 0));
clk_dm(IMX8MQ_CLK_ENET_REF,
imx8m_clk_composite("enet_ref", imx8mq_enet_ref_sels,
base + 0xa980));
clk_dm(IMX8MQ_CLK_ENET_TIMER,
imx8m_clk_composite("enet_timer", imx8mq_enet_timer_sels,
base + 0xaa00));
clk_dm(IMX8MQ_CLK_ENET_PHY_REF,
imx8m_clk_composite("enet_phy", imx8mq_enet_phy_sels,
base + 0xaa80));
clk_dm(IMX8MQ_CLK_ENET1_ROOT,
imx_clk_gate4("enet1_root_clk", "enet_axi",
base + 0x40a0, 0));
return 0;
+}
+static const struct udevice_id imx8mq_clk_ids[] = {
{ .compatible = "fsl,imx8mq-ccm" },
{ },
+};
+U_BOOT_DRIVER(imx8mq_clk) = {
.name = "clk_imx8mq",
.id = UCLASS_CLK,
.of_match = imx8mq_clk_ids,
.ops = &imx8mq_clk_ops,
.probe = imx8mq_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
+};
2.25.1
when adding this patch and enabling CLK_IMX8MQ I see the following on my board .. Any idea what I missed here?
--- >8 --- U-Boot SPL 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100) Trying to boot from SD card
U-Boot 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100)
CPU: Freescale i.MX8MQ rev2.1 at 800 MHz Reset cause: POR Model: Kontron pITX-imx8m DRAM: alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted 4 GiB clk_register: failed to get <NULL> device (parent of ckil) clk_register: failed to get <NULL> device (parent of sys1_pll) clk_register: failed to get <NULL> device (parent of sys2_pll) clk_register: failed to get <NULL> device (parent of sys3_pll) No serial driver found resetting ...
--- >8 ---

Hi Heiko,
On 2022-03-15 08:35, Heiko Thiery wrote:
Hi Angus and all,
Am Di., 15. März 2022 um 14:09 Uhr schrieb Angus Ainslie angus@akkea.ca:
This is a DM clock driver based off the imx8mm u-boot driver and the linux kernel driver. All of the PLLs and clocks are initialized so the subsystems below are functional and tested. 1) USB host and peripheral 2) ECSPI 3) UART 4) I2C all busses 5) USDHC for eMMC support 6) USB storage 7) GPIO 8) DRAM
Snip
when adding this patch and enabling CLK_IMX8MQ I see the following on my board .. Any idea what I missed here?
--- >8 --- U-Boot SPL 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100) Trying to boot from SD card
U-Boot 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100)
CPU: Freescale i.MX8MQ rev2.1 at 800 MHz Reset cause: POR Model: Kontron pITX-imx8m DRAM: alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted 4 GiB
My guess is that there was static code that was setting up the DRAM pll that isn't get executed now that there's a DM clock driver.
I'd try enabling DEBUG in the clk-uclass and clk-composite drivers.
Also look at what DRAM initialization code is not being run now. Our board doesn't have an DRAM specific initialization so there could be a bug in the DRAM setup.
clk_register: failed to get <NULL> device (parent of ckil) clk_register: failed to get <NULL> device (parent of sys1_pll) clk_register: failed to get <NULL> device (parent of sys2_pll) clk_register: failed to get <NULL> device (parent of sys3_pll)
These are warnings and shouldn't affect the functioning of the driver.
No serial driver found
Are you using the DM serial driver ?
Again this is not something that is running on our board. But I can try enabling it.
Thanks
Angus
resetting ...
--- >8 ---
-- Heiko

On 2022-03-15 08:46, Angus Ainslie wrote:
Hi Heiko,
On 2022-03-15 08:35, Heiko Thiery wrote:
Hi Angus and all,
Am Di., 15. März 2022 um 14:09 Uhr schrieb Angus Ainslie angus@akkea.ca:
This is a DM clock driver based off the imx8mm u-boot driver and the linux kernel driver. All of the PLLs and clocks are initialized so the subsystems below are functional and tested. 1) USB host and peripheral 2) ECSPI 3) UART 4) I2C all busses 5) USDHC for eMMC support 6) USB storage 7) GPIO 8) DRAM
Snip
when adding this patch and enabling CLK_IMX8MQ I see the following on my board .. Any idea what I missed here?
--- >8 --- U-Boot SPL 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100) Trying to boot from SD card
U-Boot 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100)
CPU: Freescale i.MX8MQ rev2.1 at 800 MHz Reset cause: POR Model: Kontron pITX-imx8m DRAM: alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted 4 GiB
My guess is that there was static code that was setting up the DRAM pll that isn't get executed now that there's a DM clock driver.
I'd try enabling DEBUG in the clk-uclass and clk-composite drivers.
Also look at what DRAM initialization code is not being run now. Our board doesn't have an DRAM specific initialization so there could be a bug in the DRAM setup.
clk_register: failed to get <NULL> device (parent of ckil) clk_register: failed to get <NULL> device (parent of sys1_pll) clk_register: failed to get <NULL> device (parent of sys2_pll) clk_register: failed to get <NULL> device (parent of sys3_pll)
These are warnings and shouldn't affect the functioning of the driver.
No serial driver found
Are you using the DM serial driver ?
Again this is not something that is running on our board. But I can try enabling it.
With DM_SERIAL enabled and SPL_DM_SERIAL disabled
U-Boot SPL 2022.04-rc3-00076-gb363332dc70-dirty (Mar 15 2022 - 09:09:24 -0700) [0/1906] Initializing pinmux Initializing ECSPI Initializing DRAM USB Boot Trying to boot from USB SDP board_usb_init : index 0 type 1 SDP: initialize... SDP: handle requests... Downloading file of size 868420 to 0x40400000... done Jumping to header at 0x40400000 Header Tag is not an IMX image Found header at 0x40406e00 board_usb_cleanup : 0 Status: -108
U-Boot 2022.04-rc3-00076-gb363332dc70-dirty (Mar 15 2022 - 09:09:24 -0700)
CPU: Freescale i.MX8MQ rev2.1 1500 MHz (running at 1000 MHz) CPU: Commercial temperature grade (0C to 95C) at 60C Reset cause: POR Model: Purism Librem 5r4 DRAM: 3 GiB Enabling regulator-hub clk_register: failed to get <NULL> device (parent of ckil) clk_register: failed to get <NULL> device (parent of sys1_pll) clk_register: failed to get <NULL> device (parent of sys2_pll) clk_register: failed to get <NULL> device (parent of sys3_pll) tps65982 boot successful Core: 178 devices, 23 uclasses, devicetree: separate MMC: FSL_SDHC: 0, FSL_SDHC: 1 Loading Environment from MMC... *** Warning - bad CRC, using default environment
In: serial Out: serial Err: serial
BuildInfo: - ATF 1fd3ff8
Board name: librem5 Board rev: 4 USB Boot vol_down_key_pressed : 1 Net: No ethernet found. Hit any key to stop autoboot: 0
Thanks
Angus
resetting ...
--- >8 ---
-- Heiko

Hi Angus,
Am Di., 15. März 2022 um 16:46 Uhr schrieb Angus Ainslie angus.ainslie@puri.sm:
Hi Heiko,
On 2022-03-15 08:35, Heiko Thiery wrote:
Hi Angus and all,
Am Di., 15. März 2022 um 14:09 Uhr schrieb Angus Ainslie angus@akkea.ca:
This is a DM clock driver based off the imx8mm u-boot driver and the linux kernel driver.
All of the PLLs and clocks are initialized so the subsystems below are functional and tested.
- USB host and peripheral
- ECSPI
- UART
- I2C all busses
- USDHC for eMMC support
- USB storage
- GPIO
- DRAM
Snip
when adding this patch and enabling CLK_IMX8MQ I see the following on my board .. Any idea what I missed here?
--- >8 --- U-Boot SPL 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100) Trying to boot from SD card
U-Boot 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100)
CPU: Freescale i.MX8MQ rev2.1 at 800 MHz Reset cause: POR Model: Kontron pITX-imx8m DRAM: alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted 4 GiB
My guess is that there was static code that was setting up the DRAM pll that isn't get executed now that there's a DM clock driver.
I'd try enabling DEBUG in the clk-uclass and clk-composite drivers.
Also look at what DRAM initialization code is not being run now. Our board doesn't have an DRAM specific initialization so there could be a bug in the DRAM setup.
The problem was the MALLOC_F_LEN value. Increasing that the "alloc space exhausted" is gone.
But with the enabled DM_SERIAL the problem of "No serial driver found" is still there and the board reboots. You said you have DM_SERIAL enabled and it works?
[snip]

Hi,
Am Mi., 16. März 2022 um 08:14 Uhr schrieb Heiko Thiery heiko.thiery@gmail.com:
Hi Angus,
Am Di., 15. März 2022 um 16:46 Uhr schrieb Angus Ainslie angus.ainslie@puri.sm:
Hi Heiko,
On 2022-03-15 08:35, Heiko Thiery wrote:
Hi Angus and all,
Am Di., 15. März 2022 um 14:09 Uhr schrieb Angus Ainslie angus@akkea.ca:
This is a DM clock driver based off the imx8mm u-boot driver and the linux kernel driver.
All of the PLLs and clocks are initialized so the subsystems below are functional and tested.
- USB host and peripheral
- ECSPI
- UART
- I2C all busses
- USDHC for eMMC support
- USB storage
- GPIO
- DRAM
Snip
when adding this patch and enabling CLK_IMX8MQ I see the following on my board .. Any idea what I missed here?
--- >8 --- U-Boot SPL 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100) Trying to boot from SD card
U-Boot 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100)
CPU: Freescale i.MX8MQ rev2.1 at 800 MHz Reset cause: POR Model: Kontron pITX-imx8m DRAM: alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted 4 GiB
My guess is that there was static code that was setting up the DRAM pll that isn't get executed now that there's a DM clock driver.
I'd try enabling DEBUG in the clk-uclass and clk-composite drivers.
Also look at what DRAM initialization code is not being run now. Our board doesn't have an DRAM specific initialization so there could be a bug in the DRAM setup.
The problem was the MALLOC_F_LEN value. Increasing that the "alloc space exhausted" is gone.
But with the enabled DM_SERIAL the problem of "No serial driver found" is still there and the board reboots. You said you have DM_SERIAL enabled and it works?
Meanwhile I figured out what the problem is with the 'No serial driver found'. In the used dtb there are 'assigned-clocks' and 'assigned-clock-parents' set in the uart nodes. When removing this the serial will work. I have to admit that I do not know why this is set that way. I can only imagine that this was taken from the uboot-imx tree.
--- assigned-clocks = <&clk IMX8MQ_CLK_UART1>; assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>; ---
see also here: https://source.denx.de/u-boot/u-boot/-/blob/master/arch/arm/dts/imx8mq-kontr...

On 2022-03-16 05:26, Heiko Thiery wrote:
Hi,
Am Mi., 16. März 2022 um 08:14 Uhr schrieb Heiko Thiery heiko.thiery@gmail.com:
Hi Angus,
Am Di., 15. März 2022 um 16:46 Uhr schrieb Angus Ainslie angus.ainslie@puri.sm:
Hi Heiko,
On 2022-03-15 08:35, Heiko Thiery wrote:
Hi Angus and all,
Am Di., 15. März 2022 um 14:09 Uhr schrieb Angus Ainslie angus@akkea.ca:
This is a DM clock driver based off the imx8mm u-boot driver and the linux kernel driver.
All of the PLLs and clocks are initialized so the subsystems below are functional and tested.
- USB host and peripheral
- ECSPI
- UART
- I2C all busses
- USDHC for eMMC support
- USB storage
- GPIO
- DRAM
Snip
when adding this patch and enabling CLK_IMX8MQ I see the following on my board .. Any idea what I missed here?
--- >8 --- U-Boot SPL 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100) Trying to boot from SD card
U-Boot 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100)
CPU: Freescale i.MX8MQ rev2.1 at 800 MHz Reset cause: POR Model: Kontron pITX-imx8m DRAM: alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted 4 GiB
My guess is that there was static code that was setting up the DRAM pll that isn't get executed now that there's a DM clock driver.
I'd try enabling DEBUG in the clk-uclass and clk-composite drivers.
Also look at what DRAM initialization code is not being run now. Our board doesn't have an DRAM specific initialization so there could be a bug in the DRAM setup.
The problem was the MALLOC_F_LEN value. Increasing that the "alloc space exhausted" is gone.
But with the enabled DM_SERIAL the problem of "No serial driver found" is still there and the board reboots. You said you have DM_SERIAL enabled and it works?
Meanwhile I figured out what the problem is with the 'No serial driver found'. In the used dtb there are 'assigned-clocks' and 'assigned-clock-parents' set in the uart nodes. When removing this the serial will work. I have to admit that I do not know why this is set that way. I can only imagine that this was taken from the uboot-imx tree.
assigned-clocks = <&clk IMX8MQ_CLK_UART1>; assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;
Does that solve the reboot ?
see also here: https://source.denx.de/u-boot/u-boot/-/blob/master/arch/arm/dts/imx8mq-kontr...
If that works for Linux it should also work for u-boot. It may be that the SYS1_PLL_80M isn't set correctly or that the CLK_UART1 mux isn't correctly setup. If you enable DEBUG in clk-uclass I might be able to figure out were the problem is.

Hi Angus,
[snip]
Meanwhile I figured out what the problem is with the 'No serial driver found'. In the used dtb there are 'assigned-clocks' and 'assigned-clock-parents' set in the uart nodes. When removing this the serial will work. I have to admit that I do not know why this is set that way. I can only imagine that this was taken from the uboot-imx tree.
assigned-clocks = <&clk IMX8MQ_CLK_UART1>; assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;
Does that solve the reboot ?
Yes, when I remove these assigned-clocks from my dtb the issue is solved and the board finds the serial driver and starts correctly.
see also here: https://source.denx.de/u-boot/u-boot/-/blob/master/arch/arm/dts/imx8mq-kontr...
If that works for Linux it should also work for u-boot. It may be that the SYS1_PLL_80M isn't set correctly or that the CLK_UART1 mux isn't correctly setup. If you enable DEBUG in clk-uclass I might be able to figure out were the problem is.
The problem is that the IMX8MQ_CLK_UART1 is not found and that is the reason that the probe fails. I tried to add the missing clocks to how it is done in the kernel.
see here: https://pastebin.com/raw/iYYMHEdy
But then something went wrong when probing uart3 ... the baudrate switched for the uart2 (console) and the serial output became broken. Later when the kernel starts the output becomes correct again. So the kernel seems to configure it correctly.
see here: https://pastebin.com/raw/qXVShb3Q
When I remove the "assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;" for uart3 the output of uart2 (console) keeps ok.

On 2022-03-16 07:02, Heiko Thiery wrote:
Hi Angus,
[snip]
Meanwhile I figured out what the problem is with the 'No serial driver found'. In the used dtb there are 'assigned-clocks' and 'assigned-clock-parents' set in the uart nodes. When removing this the serial will work. I have to admit that I do not know why this is set that way. I can only imagine that this was taken from the uboot-imx tree.
assigned-clocks = <&clk IMX8MQ_CLK_UART1>; assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;
Does that solve the reboot ?
Yes, when I remove these assigned-clocks from my dtb the issue is solved and the board finds the serial driver and starts correctly.
see also here: https://source.denx.de/u-boot/u-boot/-/blob/master/arch/arm/dts/imx8mq-kontr...
If that works for Linux it should also work for u-boot. It may be that the SYS1_PLL_80M isn't set correctly or that the CLK_UART1 mux isn't correctly setup. If you enable DEBUG in clk-uclass I might be able to figure out were the problem is.
The problem is that the IMX8MQ_CLK_UART1 is not found and that is the reason that the probe fails. I tried to add the missing clocks to how it is done in the kernel.
see here: https://pastebin.com/raw/iYYMHEdy
Looking at that you shouldn't need
+ clk_dm(IMX8MQ_CLK_25M, clk_register_fixed_rate(NULL, "clock-osc-25m", 25000000)); + clk_dm(IMX8MQ_CLK_25M, clk_register_fixed_rate(NULL, "clock-osc-27m", 27000000));
Those get correctly probed by the clock-controller.
The rest of it looks OK and could be a follow on patch to the clock driver,
But then something went wrong when probing uart3 ... the baudrate switched for the uart2 (console) and the serial output became broken. Later when the kernel starts the output becomes correct again. So the kernel seems to configure it correctly.
see here: https://pastebin.com/raw/qXVShb3Q
When I remove the "assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;" for uart3 the output of uart2 (console) keeps ok.
If that "fixes" it then it means that the parent IMX8MQ_SYS1_PLL_80M clock rate is getting changed by the uart3 stanza.
Are you using the mainline devicetree file for your board ? If not could you provide a link ?

Am Mi., 16. März 2022 um 15:15 Uhr schrieb Angus Ainslie angus@akkea.ca:
On 2022-03-16 07:02, Heiko Thiery wrote:
Hi Angus,
[snip]
Meanwhile I figured out what the problem is with the 'No serial driver found'. In the used dtb there are 'assigned-clocks' and 'assigned-clock-parents' set in the uart nodes. When removing this the serial will work. I have to admit that I do not know why this is set that way. I can only imagine that this was taken from the uboot-imx tree.
assigned-clocks = <&clk IMX8MQ_CLK_UART1>; assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;
Does that solve the reboot ?
Yes, when I remove these assigned-clocks from my dtb the issue is solved and the board finds the serial driver and starts correctly.
see also here: https://source.denx.de/u-boot/u-boot/-/blob/master/arch/arm/dts/imx8mq-kontr...
If that works for Linux it should also work for u-boot. It may be that the SYS1_PLL_80M isn't set correctly or that the CLK_UART1 mux isn't correctly setup. If you enable DEBUG in clk-uclass I might be able to figure out were the problem is.
The problem is that the IMX8MQ_CLK_UART1 is not found and that is the reason that the probe fails. I tried to add the missing clocks to how it is done in the kernel.
see here: https://pastebin.com/raw/iYYMHEdy
Looking at that you shouldn't need
clk_dm(IMX8MQ_CLK_25M, clk_register_fixed_rate(NULL,
"clock-osc-25m", 25000000));
clk_dm(IMX8MQ_CLK_25M, clk_register_fixed_rate(NULL,
"clock-osc-27m", 27000000));
Those get correctly probed by the clock-controller.
The rest of it looks OK and could be a follow on patch to the clock driver,
But then something went wrong when probing uart3 ... the baudrate switched for the uart2 (console) and the serial output became broken. Later when the kernel starts the output becomes correct again. So the kernel seems to configure it correctly.
see here: https://pastebin.com/raw/qXVShb3Q
When I remove the "assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;" for uart3 the output of uart2 (console) keeps ok.
If that "fixes" it then it means that the parent IMX8MQ_SYS1_PLL_80M clock rate is getting changed by the uart3 stanza.
Are you using the mainline devicetree file for your board ? If not could you provide a link ?
I use the mainline u-boot/linux one.

Hi Angus,
[snip]
But then something went wrong when probing uart3 ... the baudrate switched for the uart2 (console) and the serial output became broken. Later when the kernel starts the output becomes correct again. So the kernel seems to configure it correctly.
see here: https://pastebin.com/raw/qXVShb3Q
When I remove the "assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;" for uart3 the output of uart2 (console) keeps ok.
If that "fixes" it then it means that the parent IMX8MQ_SYS1_PLL_80M clock rate is getting changed by the uart3 stanza.
Are you using the mainline devicetree file for your board ? If not could you provide a link ?
I use the mainline u-boot/linux one.
We (thanks to Michael) found the issue. For the imx8mq the imx_get_uartclk() returns always the values for UART1_CLK_ROOT [1]. This is wrong. Here we have to get the value dependent on the used UART.
[1] https://source.denx.de/u-boot/u-boot/-/blob/master/arch/arm/mach-imx/imx8m/c...

Hi Heiko,
On 2022-03-16 08:55, Heiko Thiery wrote:
Hi Angus,
[snip]
But then something went wrong when probing uart3 ... the baudrate switched for the uart2 (console) and the serial output became broken. Later when the kernel starts the output becomes correct again. So the kernel seems to configure it correctly.
see here: https://pastebin.com/raw/qXVShb3Q
When I remove the "assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;" for uart3 the output of uart2 (console) keeps ok.
If that "fixes" it then it means that the parent IMX8MQ_SYS1_PLL_80M clock rate is getting changed by the uart3 stanza.
Are you using the mainline devicetree file for your board ? If not could you provide a link ?
I use the mainline u-boot/linux one.
We (thanks to Michael) found the issue. For the imx8mq the imx_get_uartclk() returns always the values for UART1_CLK_ROOT [1]. This is wrong. Here we have to get the value dependent on the used UART.
[1] https://source.denx.de/u-boot/u-boot/-/blob/master/arch/arm/mach-imx/imx8m/c...
Yeah that driver could do with an overhaul as it also does that for the ECSPI clocks which can also break things.
Angus

Am 2022-03-16 17:00, schrieb Angus Ainslie:
Hi Heiko,
On 2022-03-16 08:55, Heiko Thiery wrote:
Hi Angus,
[snip]
But then something went wrong when probing uart3 ... the baudrate switched for the uart2 (console) and the serial output became broken. Later when the kernel starts the output becomes correct again. So the kernel seems to configure it correctly.
see here: https://pastebin.com/raw/qXVShb3Q
When I remove the "assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;" for uart3 the output of uart2 (console) keeps ok.
If that "fixes" it then it means that the parent IMX8MQ_SYS1_PLL_80M clock rate is getting changed by the uart3 stanza.
Are you using the mainline devicetree file for your board ? If not could you provide a link ?
I use the mainline u-boot/linux one.
We (thanks to Michael) found the issue. For the imx8mq the imx_get_uartclk() returns always the values for UART1_CLK_ROOT [1]. This is wrong. Here we have to get the value dependent on the used UART.
[1] https://source.denx.de/u-boot/u-boot/-/blob/master/arch/arm/mach-imx/imx8m/c...
Yeah that driver could do with an overhaul as it also does that for the ECSPI clocks which can also break things.
IMHO the imx serial driver should get its clock from the device tree. Not sure about the debug serial part though.
-michael

On 2022/3/16 23:55, Heiko Thiery wrote:
Hi Angus,
[snip]
But then something went wrong when probing uart3 ... the baudrate switched for the uart2 (console) and the serial output became broken. Later when the kernel starts the output becomes correct again. So the kernel seems to configure it correctly.
see here: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpastebin.c...
When I remove the "assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;" for uart3 the output of uart2 (console) keeps ok.
If that "fixes" it then it means that the parent IMX8MQ_SYS1_PLL_80M clock rate is getting changed by the uart3 stanza.
Are you using the mainline devicetree file for your board ? If not could you provide a link ?
I use the mainline u-boot/linux one.
We (thanks to Michael) found the issue. For the imx8mq the imx_get_uartclk() returns always the values for UART1_CLK_ROOT [1]. This is wrong. Here we have to get the value dependent on the used UART.
Yes, this needs to be fixed! Previously in U-Boot, we suppose people not configure CCM for Uart, so all uart works at 25M OSC if not configure CCM to other mux. Since you have CLK DM with assigned clock parents, so this needs update.
Regards, Peng.
[1] https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsource.den...

On 3/15/22 16:35, Heiko Thiery wrote:
Hi Angus and all,
Hi,
[...]
U-Boot 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100)
CPU: Freescale i.MX8MQ rev2.1 at 800 MHz Reset cause: POR Model: Kontron pITX-imx8m DRAM: alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted
Try increasing MALLOC_F_LEN in your .config , that should do the trick I think. There is now a lot of clock drivers that are being instantiated early, so your early malloc area is likely exhausted.

Hi Marek,
Am Di., 15. März 2022 um 20:01 Uhr schrieb Marek Vasut marex@denx.de:
On 3/15/22 16:35, Heiko Thiery wrote:
Hi Angus and all,
Hi,
[...]
U-Boot 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100)
CPU: Freescale i.MX8MQ rev2.1 at 800 MHz Reset cause: POR Model: Kontron pITX-imx8m DRAM: alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted
Try increasing MALLOC_F_LEN in your .config , that should do the trick I think. There is now a lot of clock drivers that are being instantiated early, so your early malloc area is likely exhausted.
You're right. Increasing the value from 0x2000 to 0x10000 fixes this problem.
Thanks

On 2022/3/15 23:35, Heiko Thiery wrote:
Hi Angus and all,
Am Di., 15. März 2022 um 14:09 Uhr schrieb Angus Ainslie <angus@akkea.ca mailto:angus@akkea.ca>:
This is a DM clock driver based off the imx8mm u-boot driver and the linux kernel driver. All of the PLLs and clocks are initialized so the subsystems below are functional and tested. 1) USB host and peripheral 2) ECSPI 3) UART 4) I2C all busses 5) USDHC for eMMC support 6) USB storage 7) GPIO 8) DRAM Signed-off-by: Angus Ainslie <angus@akkea.ca <mailto:angus@akkea.ca>> --- drivers/clk/imx/Kconfig | 16 + drivers/clk/imx/Makefile | 2 + drivers/clk/imx/clk-imx8mq.c | 575 +++++++++++++++++++++++++++++++++++ 3 files changed, 593 insertions(+) create mode 100644 drivers/clk/imx/clk-imx8mq.c diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index cdd348020b0..06d8c1a5dd3 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -71,6 +71,22 @@ config CLK_IMX8MP help This enables support clock driver for i.MX8MP platforms. +config SPL_CLK_IMX8MQ + bool "SPL clock support for i.MX8MQ" + depends on ARCH_IMX8M && SPL + select SPL_CLK + select SPL_CLK_CCF + help + This enables SPL DM/DTS support for clock driver in i.MX8MQ + +config CLK_IMX8MQ + bool "Clock support for i.MX8MQ" + depends on ARCH_IMX8M + select CLK + select CLK_CCF + help + This enables support clock driver for i.MX8MQ platforms. + config SPL_CLK_IMXRT1020 bool "SPL clock support for i.MXRT1020" depends on ARCH_IMXRT && SPL diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 01bbbdf3aea..c5766901f2b 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -16,6 +16,8 @@ obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MN) += clk-imx8mn.o clk-pll14xx.o \ clk-composite-8m.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MP) += clk-imx8mp.o clk-pll14xx.o \ clk-composite-8m.o +obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MQ) += clk-imx8mq.o clk-pll14xx.o \ + clk-composite-8m.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1020) += clk-imxrt1020.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1050) += clk-imxrt1050.o diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c new file mode 100644 index 00000000000..0aea417a29b --- /dev/null +++ b/drivers/clk/imx/clk-imx8mq.c @@ -0,0 +1,575 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP + * Copyright 2022 Purism + * Peng Fan <peng.fan@nxp.com <mailto:peng.fan@nxp.com>> + */ + +#include <common.h> +#include <clk.h> +#include <clk-uclass.h> +#include <dm.h> +#include <log.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <dt-bindings/clock/imx8mq-clock.h> + +#include "clk.h" + +#define PLL_1416X_RATE(_rate, _m, _p, _s) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + } + +#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + .kdiv = (_k), \ + } + +static const struct imx_pll14xx_rate_table imx8mq_pll1416x_tbl[] = { + PLL_1416X_RATE(1800000000U, 225, 3, 0), + PLL_1416X_RATE(1600000000U, 200, 3, 0), + PLL_1416X_RATE(1200000000U, 300, 3, 1), + PLL_1416X_RATE(1000000000U, 250, 3, 1), + PLL_1416X_RATE(800000000U, 200, 3, 1), + PLL_1416X_RATE(750000000U, 250, 2, 2), + PLL_1416X_RATE(700000000U, 350, 3, 2), + PLL_1416X_RATE(600000000U, 300, 3, 2), +}; + +const struct imx_pll14xx_rate_table imx8mq_pll1443x_tbl[] = { + PLL_1443X_RATE(650000000U, 325, 3, 2, 0), + PLL_1443X_RATE(594000000U, 198, 2, 2, 0), + PLL_1443X_RATE(393216000U, 262, 2, 3, 9437), + PLL_1443X_RATE(361267200U, 361, 3, 3, 17511), +}; + +static struct imx_pll14xx_clk imx8mq_1416x_pll __initdata = { + .type = PLL_1416X, + .rate_table = imx8mq_pll1416x_tbl, + .rate_count = ARRAY_SIZE(imx8mq_pll1416x_tbl), +}; + +static struct imx_pll14xx_clk imx8mq_1443x_pll __initdata = { + .type = PLL_1443X, + .rate_table = imx8mq_pll1443x_tbl, + .rate_count = ARRAY_SIZE(imx8mq_pll1443x_tbl), +}; + +static const char *pll_ref_sels[] = { "clock-osc-25m", "clock-osc-27m", "clock-phy-27m", "dummy", }; +static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; +static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", }; +static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", }; +static const char *audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", }; +static const char *audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", }; +static const char *video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", }; + +static const char *imx8mq_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", }; +static const char *imx8mq_a53_sels[] = {"clock-osc-25m", "arm_pll_out", "sys_pll2_500m", + "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m", + "audio_pll1_out", "sys_pll3_out", }; + +static const char *imx8mq_ahb_sels[] = {"clock-osc-25m", "sys_pll1_133m", "sys_pll1_800m", + "sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out", + "audio_pll1_out", "video_pll1_out", }; + +static const char *imx8mq_enet_axi_sels[] = {"clock-osc-25m", "sys_pll1_266m", "sys_pll1_800m", + "sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out", + "video_pll1_out", "sys_pll3_out", }; + +static const char *imx8mq_enet_ref_sels[] = {"clock-osc-25m", "sys_pll2_125m", "sys_pll2_50m", + "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out", + "video_pll1_out", "clk_ext4", }; + +static const char *imx8mq_enet_timer_sels[] = {"clock-osc-25m", "sys_pll2_100m", "audio_pll1_out", + "clk_ext1", "clk_ext2", "clk_ext3", "clk_ext4", + "video_pll1_out", }; + +static const char *imx8mq_enet_phy_sels[] = {"clock-osc-25m", "sys_pll2_50m", "sys_pll2_125m", + "sys_pll2_200m", "sys_pll2_500m", "video_pll1_out", + "audio_pll2_out", }; + +static const char *imx8mq_nand_usdhc_sels[] = {"clock-osc-25m", "sys_pll1_266m", "sys_pll1_800m", + "sys_pll2_200m", "sys_pll1_133m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll1_out", }; + +static const char *imx8mq_usb_bus_sels[] = {"clock-osc-25m", "sys_pll2_500m", "sys_pll1_800m", + "sys_pll2_100m", "sys_pll2_200m", "clk_ext2", + "clk_ext4", "audio_pll2_out", }; + +static const char *imx8mq_usdhc1_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll1_800m", + "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m", + "audio_pll2_out", "sys_pll1_100m", }; + +static const char *imx8mq_usdhc2_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll1_800m", + "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m", + "audio_pll2_out", "sys_pll1_100m", }; + +static const char *imx8mq_i2c1_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", + "audio_pll2_out", "sys_pll1_133m", }; + +static const char *imx8mq_i2c2_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", + "audio_pll2_out", "sys_pll1_133m", }; + +static const char *imx8mq_i2c3_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", + "audio_pll2_out", "sys_pll1_133m", }; + +static const char *imx8mq_i2c4_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", + "audio_pll2_out", "sys_pll1_133m", }; + +static const char *imx8mq_wdog_sels[] = {"clock-osc-25m", "sys_pll1_133m", "sys_pll1_160m", + "vpu_pll_out", "sys_pll2_125m", "sys_pll3_out", + "sys_pll1_80m", "sys_pll2_166m", }; + +static const char *imx8mq_qspi_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll2_333m", + "sys_pll2_500m", "audio_pll2_out", "sys_pll1_266m", + "sys_pll3_out", "sys_pll1_100m", }; + +static const char *imx8mq_usb_core_sels[] = {"clock-osc-25m", "sys_pll1_100m", "sys_pll1_40m", + "sys_pll2_100m", "sys_pll2_200m", "clk_ext2", + "clk_ext3", "audio_pll2_out", }; + +static const char *imx8mq_usb_phy_sels[] = {"clock-osc-25m", "sys_pll1_100m", "sys_pll1_40m", + "sys_pll2_100m", "sys_pll2_200m", "clk_ext2", + "clk_ext3", "audio_pll2_out", }; + +static const char *imx8mq_ecspi1_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m", + "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll2_out", }; + +static const char *imx8mq_ecspi2_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m", + "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll2_out", }; + +static const char *imx8mq_ecspi3_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m", + "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll2_out", }; + +static const char *pllout_monitor_sels[] = {"clock-osc-25m", "clock-osc-27m", "clock-phy-27m", + "dummy", "clock-ckil", "audio_pll1_out_monitor", + "audio_pll2_out_monitor", "gpu_pll_out_monitor", + "vpu_pll_out_monitor", "video_pll1_out_monitor", + "arm_pll_out_monitor", "sys_pll1_out_monitor", + "sys_pll2_out_monitor", "sys_pll3_out_monitor", + "dummy", "dram_pll_out_monitor", }; + +static ulong imx8mq_clk_get_rate(struct clk *clk) +{ + struct clk *c; + int ret; + + debug("%s(#%lu)\n", __func__, clk->id); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + return clk_get_rate(c); +} + +static ulong imx8mq_clk_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *c; + int ret; + + debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + return clk_set_rate(c, rate); +} + +static int __imx8mq_clk_enable(struct clk *clk, bool enable) +{ + struct clk *c; + int ret; + + debug("%s(#%lu) en: %d\n", __func__, clk->id, enable); + + ret = clk_get_by_id(clk->id, &c); + if (ret) { + debug("%s: clk_get_by_id failed\n", __func__); + return ret; + } + + if (enable) + ret = clk_enable(c); + else + ret = clk_disable(c); + + return ret; +} + +static int imx8mq_clk_disable(struct clk *clk) +{ + return __imx8mq_clk_enable(clk, 0); +} + +static int imx8mq_clk_enable(struct clk *clk) +{ + return __imx8mq_clk_enable(clk, 1); +} + +static int imx8mq_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk *c, *cp; + int ret; + + debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + ret = clk_get_by_id(parent->id, &cp); + if (ret) + return ret; + + ret = clk_set_parent(c, cp); + c->dev->parent = cp->dev; + + return ret; +} + +static struct clk_ops imx8mq_clk_ops = { + .set_rate = imx8mq_clk_set_rate, + .get_rate = imx8mq_clk_get_rate, + .enable = imx8mq_clk_enable, + .disable = imx8mq_clk_disable, + .set_parent = imx8mq_clk_set_parent, +}; + +static int imx8mq_clk_probe(struct udevice *dev) +{ + void __iomem *base; + + base = (void *)ANATOP_BASE_ADDR; + + clk_dm(IMX8MQ_CLK_32K, clk_register_fixed_rate(NULL, "ckil", 32768)); + + clk_dm(IMX8MQ_DRAM_PLL1_REF_SEL, + imx_clk_mux("dram_pll_ref_sel", base + 0x60, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_ARM_PLL_REF_SEL, + imx_clk_mux("arm_pll_ref_sel", base + 0x28, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_GPU_PLL_REF_SEL, + imx_clk_mux("gpu_pll_ref_sel", base + 0x18, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_VPU_PLL_REF_SEL, + imx_clk_mux("vpu_pll_ref_sel", base + 0x20, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_SYS3_PLL1_REF_SEL, + imx_clk_mux("sys3_pll_ref_sel", base + 0x48, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_AUDIO_PLL1_REF_SEL, + imx_clk_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_AUDIO_PLL2_REF_SEL, + imx_clk_mux("audio_pll2_ref_sel", base + 0x8, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + clk_dm(IMX8MQ_VIDEO_PLL1_REF_SEL, + imx_clk_mux("video_pll1_ref_sel", base + 0x10, 0, 2, + pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); + + clk_dm(IMX8MQ_ARM_PLL, + imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", + base + 0x28, &imx8mq_1416x_pll)); + clk_dm(IMX8MQ_GPU_PLL, + imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel", + base + 0x18, &imx8mq_1416x_pll)); + clk_dm(IMX8MQ_VPU_PLL, + imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel", + base + 0x20, &imx8mq_1416x_pll)); + + clk_dm(IMX8MQ_SYS1_PLL1, + clk_register_fixed_rate(NULL, "sys1_pll", 800000000)); + clk_dm(IMX8MQ_SYS2_PLL1, + clk_register_fixed_rate(NULL, "sys2_pll", 1000000000)); + clk_dm(IMX8MQ_SYS2_PLL1, + clk_register_fixed_rate(NULL, "sys3_pll", 1000000000)); + clk_dm(IMX8MQ_AUDIO_PLL1, + imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel", + base + 0x0, &imx8mq_1443x_pll)); + clk_dm(IMX8MQ_AUDIO_PLL2, + imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel", + base + 0x8, &imx8mq_1443x_pll)); + clk_dm(IMX8MQ_VIDEO_PLL1, + imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel", + base + 0x10, &imx8mq_1443x_pll)); + + /* PLL bypass out */ + clk_dm(IMX8MQ_ARM_PLL_BYPASS, + imx_clk_mux_flags("arm_pll_bypass", base + 0x28, 4, 1, + arm_pll_bypass_sels, + ARRAY_SIZE(arm_pll_bypass_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX8MQ_GPU_PLL_BYPASS, + imx_clk_mux_flags("gpu_pll_bypass", base + 0x18, 4, 1, + gpu_pll_bypass_sels, + ARRAY_SIZE(gpu_pll_bypass_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX8MQ_VPU_PLL_BYPASS, + imx_clk_mux_flags("vpu_pll_bypass", base + 0x20, 4, 1, + vpu_pll_bypass_sels, + ARRAY_SIZE(vpu_pll_bypass_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX8MQ_AUDIO_PLL1_BYPASS, + imx_clk_mux_flags("audio_pll1_bypass", base + 0x0, 4, 1, + audio_pll1_bypass_sels, + ARRAY_SIZE(audio_pll1_bypass_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX8MQ_AUDIO_PLL2_BYPASS, + imx_clk_mux_flags("audio_pll2_bypass", base + 0x8, 4, 1, + audio_pll2_bypass_sels, + ARRAY_SIZE(audio_pll2_bypass_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX8MQ_VIDEO_PLL1_BYPASS, + imx_clk_mux_flags("video_pll1_bypass", base + 0x10, 4, 1, + video_pll1_bypass_sels, + ARRAY_SIZE(video_pll1_bypass_sels), + CLK_SET_RATE_PARENT)); + + /* PLL out gate */ + clk_dm(IMX8MQ_DRAM_PLL_OUT, + imx_clk_gate("dram_pll_out", "dram_pll_ref_sel", + base + 0x60, 13)); + clk_dm(IMX8MQ_ARM_PLL_OUT, + imx_clk_gate("arm_pll_out", "arm_pll_bypass", + base + 0x28, 11)); + clk_dm(IMX8MQ_GPU_PLL_OUT, + imx_clk_gate("gpu_pll_out", "gpu_pll_bypass", + base + 0x18, 11)); + clk_dm(IMX8MQ_VPU_PLL_OUT, + imx_clk_gate("vpu_pll_out", "vpu_pll_bypass", + base + 0x20, 11)); + clk_dm(IMX8MQ_AUDIO_PLL1_OUT, + imx_clk_gate("audio_pll1_out", "audio_pll1_bypass", + base + 0x0, 11)); + clk_dm(IMX8MQ_AUDIO_PLL2_OUT, + imx_clk_gate("audio_pll2_out", "audio_pll2_bypass", + base + 0x8, 11)); + clk_dm(IMX8MQ_VIDEO_PLL1_OUT, + imx_clk_gate("video_pll1_out", "video_pll1_bypass", + base + 0x10, 11)); + + clk_dm(IMX8MQ_SYS1_PLL_OUT, + imx_clk_gate("sys_pll1_out", "sys1_pll", + base + 0x30, 11)); + clk_dm(IMX8MQ_SYS2_PLL_OUT, + imx_clk_gate("sys_pll2_out", "sys2_pll", + base + 0x3c, 11)); + clk_dm(IMX8MQ_SYS3_PLL_OUT, + imx_clk_gate("sys_pll3_out", "sys3_pll", + base + 0x48, 11)); + + /* SYS PLL fixed output */ + clk_dm(IMX8MQ_SYS1_PLL_40M, + imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20)); + clk_dm(IMX8MQ_SYS1_PLL_80M, + imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10)); + clk_dm(IMX8MQ_SYS1_PLL_100M, + imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8)); + clk_dm(IMX8MQ_SYS1_PLL_133M, + imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6)); + clk_dm(IMX8MQ_SYS1_PLL_160M, + imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5)); + clk_dm(IMX8MQ_SYS1_PLL_200M, + imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4)); + clk_dm(IMX8MQ_SYS1_PLL_266M, + imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3)); + clk_dm(IMX8MQ_SYS1_PLL_400M, + imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2)); + clk_dm(IMX8MQ_SYS1_PLL_800M, + imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1)); + + clk_dm(IMX8MQ_SYS2_PLL_50M, + imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20)); + clk_dm(IMX8MQ_SYS2_PLL_100M, + imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10)); + clk_dm(IMX8MQ_SYS2_PLL_125M, + imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8)); + clk_dm(IMX8MQ_SYS2_PLL_166M, + imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6)); + clk_dm(IMX8MQ_SYS2_PLL_200M, + imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5)); + clk_dm(IMX8MQ_SYS2_PLL_250M, + imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4)); + clk_dm(IMX8MQ_SYS2_PLL_333M, + imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3)); + clk_dm(IMX8MQ_SYS2_PLL_500M, + imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2)); + clk_dm(IMX8MQ_SYS2_PLL_1000M, + imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1)); + + clk_dm(IMX8MQ_CLK_MON_AUDIO_PLL1_DIV, + imx_clk_divider("audio_pll1_out_monitor", "audio_pll1_bypass", base + 0x78, 0, 3)); + clk_dm(IMX8MQ_CLK_MON_AUDIO_PLL2_DIV, + imx_clk_divider("audio_pll2_out_monitor", "audio_pll2_bypass", base + 0x78, 4, 3)); + clk_dm(IMX8MQ_CLK_MON_VIDEO_PLL1_DIV, + imx_clk_divider("video_pll1_out_monitor", "video_pll1_bypass", base + 0x78, 8, 3)); + clk_dm(IMX8MQ_CLK_MON_GPU_PLL_DIV, + imx_clk_divider("gpu_pll_out_monitor", "gpu_pll_bypass", base + 0x78, 12, 3)); + clk_dm(IMX8MQ_CLK_MON_VPU_PLL_DIV, + imx_clk_divider("vpu_pll_out_monitor", "vpu_pll_bypass", base + 0x78, 16, 3)); + clk_dm(IMX8MQ_CLK_MON_ARM_PLL_DIV, + imx_clk_divider("arm_pll_out_monitor", "arm_pll_bypass", base + 0x78, 20, 3)); + clk_dm(IMX8MQ_CLK_MON_SYS_PLL1_DIV, + imx_clk_divider("sys_pll1_out_monitor", "sys_pll1_out", base + 0x7c, 0, 3)); + clk_dm(IMX8MQ_CLK_MON_SYS_PLL2_DIV, + imx_clk_divider("sys_pll2_out_monitor", "sys_pll2_out", base + 0x7c, 4, 3)); + clk_dm(IMX8MQ_CLK_MON_SYS_PLL3_DIV, + imx_clk_divider("sys_pll3_out_monitor", "sys_pll3_out", base + 0x7c, 8, 3)); + clk_dm(IMX8MQ_CLK_MON_DRAM_PLL_DIV, + imx_clk_divider("dram_pll_out_monitor", "dram_pll_out", base + 0x7c, 12, 3)); + clk_dm(IMX8MQ_CLK_MON_SEL, + imx_clk_mux_flags("pllout_monitor_sel", base + 0x74, 0, 4, + pllout_monitor_sels, + ARRAY_SIZE(pllout_monitor_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX8MQ_CLK_MON_CLK2_OUT, + imx_clk_gate4("pllout_monitor_clk2", "pllout_monitor_sel", base + 0x74, 4)); + + base = dev_read_addr_ptr(dev); + if (!base) { + printf("%s : base failed\n", __func__); + return -EINVAL; + } + + clk_dm(IMX8MQ_CLK_A53_SRC, + imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3, + imx8mq_a53_sels, ARRAY_SIZE(imx8mq_a53_sels))); + clk_dm(IMX8MQ_CLK_A53_CG, + imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28)); + clk_dm(IMX8MQ_CLK_A53_DIV, + imx_clk_divider2("arm_a53_div", "arm_a53_cg", + base + 0x8000, 0, 3)); + clk_dm(IMX8MQ_CLK_A53_CORE, + imx_clk_mux2("arm_a53_src", base + 0x9880, 24, 1, + imx8mq_a53_core_sels, ARRAY_SIZE(imx8mq_a53_core_sels))); + + clk_dm(IMX8MQ_CLK_AHB, + imx8m_clk_composite_critical("ahb", imx8mq_ahb_sels, + base + 0x9000)); + clk_dm(IMX8MQ_CLK_IPG_ROOT, + imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1)); + + clk_dm(IMX8MQ_CLK_ENET_AXI, + imx8m_clk_composite("enet_axi", imx8mq_enet_axi_sels, + base + 0x8880)); + clk_dm(IMX8MQ_CLK_NAND_USDHC_BUS, + imx8m_clk_composite_critical("nand_usdhc_bus", + imx8mq_nand_usdhc_sels, + base + 0x8900)); + clk_dm(IMX8MQ_CLK_USB_BUS, + imx8m_clk_composite("usb_bus", imx8mq_usb_bus_sels, base + 0x8b80)); + + /* IP */ + clk_dm(IMX8MQ_CLK_USDHC1, + imx8m_clk_composite("usdhc1", imx8mq_usdhc1_sels, + base + 0xac00)); + clk_dm(IMX8MQ_CLK_USDHC2, + imx8m_clk_composite("usdhc2", imx8mq_usdhc2_sels, + base + 0xac80)); + clk_dm(IMX8MQ_CLK_I2C1, + imx8m_clk_composite("i2c1", imx8mq_i2c1_sels, base + 0xad00)); + clk_dm(IMX8MQ_CLK_I2C2, + imx8m_clk_composite("i2c2", imx8mq_i2c2_sels, base + 0xad80)); + clk_dm(IMX8MQ_CLK_I2C3, + imx8m_clk_composite("i2c3", imx8mq_i2c3_sels, base + 0xae00)); + clk_dm(IMX8MQ_CLK_I2C4, + imx8m_clk_composite("i2c4", imx8mq_i2c4_sels, base + 0xae80)); + clk_dm(IMX8MQ_CLK_WDOG, + imx8m_clk_composite("wdog", imx8mq_wdog_sels, base + 0xb900)); + clk_dm(IMX8MQ_CLK_QSPI, + imx8m_clk_composite("qspi", imx8mq_qspi_sels, base + 0xab80)); + clk_dm(IMX8MQ_CLK_USB_CORE_REF, + imx8m_clk_composite("usb_core_ref", imx8mq_usb_core_sels, base + 0xb100)); + clk_dm(IMX8MQ_CLK_USB_PHY_REF, + imx8m_clk_composite("usb_phy_ref", imx8mq_usb_phy_sels, base + 0xb180)); + clk_dm(IMX8MQ_CLK_ECSPI1, + imx8m_clk_composite("ecspi1", imx8mq_ecspi1_sels, base + 0xb280)); + clk_dm(IMX8MQ_CLK_ECSPI2, + imx8m_clk_composite("ecspi2", imx8mq_ecspi2_sels, base + 0xb300)); + clk_dm(IMX8MQ_CLK_ECSPI3, + imx8m_clk_composite("ecspi3", imx8mq_ecspi3_sels, base + 0xc180)); + + clk_dm(IMX8MQ_CLK_ECSPI1_ROOT, + imx_clk_gate4("ecspi1_root_clk", "ecspi1", base + 0x4070, 0)); + clk_dm(IMX8MQ_CLK_ECSPI2_ROOT, + imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0)); + clk_dm(IMX8MQ_CLK_ECSPI3_ROOT, + imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0)); + clk_dm(IMX8MQ_CLK_I2C1_ROOT, + imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0)); + clk_dm(IMX8MQ_CLK_I2C2_ROOT, + imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0)); + clk_dm(IMX8MQ_CLK_I2C3_ROOT, + imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0)); + clk_dm(IMX8MQ_CLK_I2C4_ROOT, + imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0)); + clk_dm(IMX8MQ_CLK_OCOTP_ROOT, + imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0)); + clk_dm(IMX8MQ_CLK_USDHC1_ROOT, + imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0)); + clk_dm(IMX8MQ_CLK_USDHC2_ROOT, + imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0)); + clk_dm(IMX8MQ_CLK_WDOG1_ROOT, + imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0)); + clk_dm(IMX8MQ_CLK_WDOG2_ROOT, + imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0)); + clk_dm(IMX8MQ_CLK_WDOG3_ROOT, + imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0)); + clk_dm(IMX8MQ_CLK_QSPI_ROOT, + imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0)); + clk_dm(IMX8MQ_CLK_USB1_CTRL_ROOT, + imx_clk_gate4("usb1_ctrl_root_clk", "usb_bus", base + 0x44d0, 0)); + clk_dm(IMX8MQ_CLK_USB2_CTRL_ROOT, + imx_clk_gate4("usb2_ctrl_root_clk", "usb_bus", base + 0x44e0, 0)); + clk_dm(IMX8MQ_CLK_USB1_PHY_ROOT, + imx_clk_gate4("usb1_phy_root_clk", "usb_phy_ref", base + 0x44f0, 0)); + clk_dm(IMX8MQ_CLK_USB2_PHY_ROOT, + imx_clk_gate4("usb2_phy_root_clk", "usb_phy_ref", base + 0x4500, 0)); + + clk_dm(IMX8MQ_CLK_ENET_REF, + imx8m_clk_composite("enet_ref", imx8mq_enet_ref_sels, + base + 0xa980)); + clk_dm(IMX8MQ_CLK_ENET_TIMER, + imx8m_clk_composite("enet_timer", imx8mq_enet_timer_sels, + base + 0xaa00)); + clk_dm(IMX8MQ_CLK_ENET_PHY_REF, + imx8m_clk_composite("enet_phy", imx8mq_enet_phy_sels, + base + 0xaa80)); + clk_dm(IMX8MQ_CLK_ENET1_ROOT, + imx_clk_gate4("enet1_root_clk", "enet_axi", + base + 0x40a0, 0)); + + return 0; +} + +static const struct udevice_id imx8mq_clk_ids[] = { + { .compatible = "fsl,imx8mq-ccm" }, + { }, +}; + +U_BOOT_DRIVER(imx8mq_clk) = { + .name = "clk_imx8mq", + .id = UCLASS_CLK, + .of_match = imx8mq_clk_ids, + .ops = &imx8mq_clk_ops, + .probe = imx8mq_clk_probe, + .flags = DM_FLAG_PRE_RELOC, +}; -- 2.25.1
when adding this patch and enabling CLK_IMX8MQ I see the following on my board .. Any idea what I missed here?
--- >8 --- U-Boot SPL 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100) Trying to boot from SD card
U-Boot 2022.04-rc4-00008-g390d9bf9a1 (Mar 15 2022 - 16:26:59 +0100)
CPU: Freescale i.MX8MQ rev2.1 at 800 MHz Reset cause: POR Model: Kontron pITX-imx8m DRAM: alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted alloc space exhausted
There maybe not enough space with MALLOC_F_LEN
Regards, Peng.
4 GiB clk_register: failed to get <NULL> device (parent of ckil) clk_register: failed to get <NULL> device (parent of sys1_pll) clk_register: failed to get <NULL> device (parent of sys2_pll) clk_register: failed to get <NULL> device (parent of sys3_pll) No serial driver found resetting ...
--- >8 ---
-- Heiko

On 3/15/22 9:08 AM, Angus Ainslie wrote:
This is a DM clock driver based off the imx8mm u-boot driver and the linux kernel driver.
All of the PLLs and clocks are initialized so the subsystems below are functional and tested.
- USB host and peripheral
- ECSPI
- UART
- I2C all busses
- USDHC for eMMC support
- USB storage
- GPIO
- DRAM
Signed-off-by: Angus Ainslie angus@akkea.ca
drivers/clk/imx/Kconfig | 16 + drivers/clk/imx/Makefile | 2 + drivers/clk/imx/clk-imx8mq.c | 575 +++++++++++++++++++++++++++++++++++ 3 files changed, 593 insertions(+) create mode 100644 drivers/clk/imx/clk-imx8mq.c
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index cdd348020b0..06d8c1a5dd3 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -71,6 +71,22 @@ config CLK_IMX8MP help This enables support clock driver for i.MX8MP platforms.
+config SPL_CLK_IMX8MQ
- bool "SPL clock support for i.MX8MQ"
- depends on ARCH_IMX8M && SPL
- select SPL_CLK
- select SPL_CLK_CCF
- help
This enables SPL DM/DTS support for clock driver in i.MX8MQ
+config CLK_IMX8MQ
- bool "Clock support for i.MX8MQ"
- depends on ARCH_IMX8M
- select CLK
- select CLK_CCF
- help
This enables support clock driver for i.MX8MQ platforms.
- config SPL_CLK_IMXRT1020 bool "SPL clock support for i.MXRT1020" depends on ARCH_IMXRT && SPL
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 01bbbdf3aea..c5766901f2b 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -16,6 +16,8 @@ obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MN) += clk-imx8mn.o clk-pll14xx.o \ clk-composite-8m.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MP) += clk-imx8mp.o clk-pll14xx.o \ clk-composite-8m.o +obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MQ) += clk-imx8mq.o clk-pll14xx.o \
clk-composite-8m.o
obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1020) += clk-imxrt1020.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1050) += clk-imxrt1050.o
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c new file mode 100644 index 00000000000..0aea417a29b --- /dev/null +++ b/drivers/clk/imx/clk-imx8mq.c @@ -0,0 +1,575 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- Copyright 2019 NXP
- Copyright 2022 Purism
- Peng Fan peng.fan@nxp.com
- */
+#include <common.h> +#include <clk.h> +#include <clk-uclass.h> +#include <dm.h> +#include <log.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <dt-bindings/clock/imx8mq-clock.h>
+#include "clk.h"
+#define PLL_1416X_RATE(_rate, _m, _p, _s) \
- { \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
- }
+#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \
- { \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.kdiv = (_k), \
- }
+static const struct imx_pll14xx_rate_table imx8mq_pll1416x_tbl[] = {
- PLL_1416X_RATE(1800000000U, 225, 3, 0),
- PLL_1416X_RATE(1600000000U, 200, 3, 0),
- PLL_1416X_RATE(1200000000U, 300, 3, 1),
- PLL_1416X_RATE(1000000000U, 250, 3, 1),
- PLL_1416X_RATE(800000000U, 200, 3, 1),
- PLL_1416X_RATE(750000000U, 250, 2, 2),
- PLL_1416X_RATE(700000000U, 350, 3, 2),
- PLL_1416X_RATE(600000000U, 300, 3, 2),
+};
+const struct imx_pll14xx_rate_table imx8mq_pll1443x_tbl[] = {
- PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
- PLL_1443X_RATE(594000000U, 198, 2, 2, 0),
- PLL_1443X_RATE(393216000U, 262, 2, 3, 9437),
- PLL_1443X_RATE(361267200U, 361, 3, 3, 17511),
+};
+static struct imx_pll14xx_clk imx8mq_1416x_pll __initdata = {
.type = PLL_1416X,
.rate_table = imx8mq_pll1416x_tbl,
.rate_count = ARRAY_SIZE(imx8mq_pll1416x_tbl),
+};
+static struct imx_pll14xx_clk imx8mq_1443x_pll __initdata = {
.type = PLL_1443X,
.rate_table = imx8mq_pll1443x_tbl,
.rate_count = ARRAY_SIZE(imx8mq_pll1443x_tbl),
+};
+static const char *pll_ref_sels[] = { "clock-osc-25m", "clock-osc-27m", "clock-phy-27m", "dummy", };
static const char *const?
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; +static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", }; +static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", }; +static const char *audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", }; +static const char *audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", }; +static const char *video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
+static const char *imx8mq_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", }; +static const char *imx8mq_a53_sels[] = {"clock-osc-25m", "arm_pll_out", "sys_pll2_500m",
"sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
"audio_pll1_out", "sys_pll3_out", };
+static const char *imx8mq_ahb_sels[] = {"clock-osc-25m", "sys_pll1_133m", "sys_pll1_800m",
"sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out",
"audio_pll1_out", "video_pll1_out", };
+static const char *imx8mq_enet_axi_sels[] = {"clock-osc-25m", "sys_pll1_266m", "sys_pll1_800m",
"sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out",
"video_pll1_out", "sys_pll3_out", };
+static const char *imx8mq_enet_ref_sels[] = {"clock-osc-25m", "sys_pll2_125m", "sys_pll2_50m",
"sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out",
"video_pll1_out", "clk_ext4", };
+static const char *imx8mq_enet_timer_sels[] = {"clock-osc-25m", "sys_pll2_100m", "audio_pll1_out",
"clk_ext1", "clk_ext2", "clk_ext3", "clk_ext4",
"video_pll1_out", };
+static const char *imx8mq_enet_phy_sels[] = {"clock-osc-25m", "sys_pll2_50m", "sys_pll2_125m",
"sys_pll2_200m", "sys_pll2_500m", "video_pll1_out",
"audio_pll2_out", };
+static const char *imx8mq_nand_usdhc_sels[] = {"clock-osc-25m", "sys_pll1_266m", "sys_pll1_800m",
"sys_pll2_200m", "sys_pll1_133m", "sys_pll3_out",
"sys_pll2_250m", "audio_pll1_out", };
+static const char *imx8mq_usb_bus_sels[] = {"clock-osc-25m", "sys_pll2_500m", "sys_pll1_800m",
"sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
"clk_ext4", "audio_pll2_out", };
+static const char *imx8mq_usdhc1_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll1_800m",
"sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
"audio_pll2_out", "sys_pll1_100m", };
+static const char *imx8mq_usdhc2_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll1_800m",
"sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
"audio_pll2_out", "sys_pll1_100m", };
+static const char *imx8mq_i2c1_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m",
"sys_pll3_out", "audio_pll1_out", "video_pll1_out",
"audio_pll2_out", "sys_pll1_133m", };
+static const char *imx8mq_i2c2_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m",
"sys_pll3_out", "audio_pll1_out", "video_pll1_out",
"audio_pll2_out", "sys_pll1_133m", };
+static const char *imx8mq_i2c3_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m",
"sys_pll3_out", "audio_pll1_out", "video_pll1_out",
"audio_pll2_out", "sys_pll1_133m", };
+static const char *imx8mq_i2c4_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m",
"sys_pll3_out", "audio_pll1_out", "video_pll1_out",
"audio_pll2_out", "sys_pll1_133m", };
+static const char *imx8mq_wdog_sels[] = {"clock-osc-25m", "sys_pll1_133m", "sys_pll1_160m",
"vpu_pll_out", "sys_pll2_125m", "sys_pll3_out",
"sys_pll1_80m", "sys_pll2_166m", };
+static const char *imx8mq_qspi_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll2_333m",
"sys_pll2_500m", "audio_pll2_out", "sys_pll1_266m",
"sys_pll3_out", "sys_pll1_100m", };
+static const char *imx8mq_usb_core_sels[] = {"clock-osc-25m", "sys_pll1_100m", "sys_pll1_40m",
"sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
"clk_ext3", "audio_pll2_out", };
+static const char *imx8mq_usb_phy_sels[] = {"clock-osc-25m", "sys_pll1_100m", "sys_pll1_40m",
"sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
"clk_ext3", "audio_pll2_out", };
+static const char *imx8mq_ecspi1_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m",
"sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
"sys_pll2_250m", "audio_pll2_out", };
+static const char *imx8mq_ecspi2_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m",
"sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
"sys_pll2_250m", "audio_pll2_out", };
+static const char *imx8mq_ecspi3_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m",
"sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
"sys_pll2_250m", "audio_pll2_out", };
+static const char *pllout_monitor_sels[] = {"clock-osc-25m", "clock-osc-27m", "clock-phy-27m",
"dummy", "clock-ckil", "audio_pll1_out_monitor",
"audio_pll2_out_monitor", "gpu_pll_out_monitor",
"vpu_pll_out_monitor", "video_pll1_out_monitor",
"arm_pll_out_monitor", "sys_pll1_out_monitor",
"sys_pll2_out_monitor", "sys_pll3_out_monitor",
"dummy", "dram_pll_out_monitor", };
+static ulong imx8mq_clk_get_rate(struct clk *clk) +{
- struct clk *c;
- int ret;
- debug("%s(#%lu)\n", __func__, clk->id);
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
return ret;
- return clk_get_rate(c);
+}
+static ulong imx8mq_clk_set_rate(struct clk *clk, unsigned long rate) +{
- struct clk *c;
- int ret;
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
return ret;
- return clk_set_rate(c, rate);
+}
+static int __imx8mq_clk_enable(struct clk *clk, bool enable) +{
- struct clk *c;
- int ret;
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
- ret = clk_get_by_id(clk->id, &c);
- if (ret) {
debug("%s: clk_get_by_id failed\n", __func__);
return ret;
- }
- if (enable)
ret = clk_enable(c);
- else
ret = clk_disable(c);
- return ret;
+}
+static int imx8mq_clk_disable(struct clk *clk) +{
- return __imx8mq_clk_enable(clk, 0);
+}
+static int imx8mq_clk_enable(struct clk *clk) +{
- return __imx8mq_clk_enable(clk, 1);
+}
+static int imx8mq_clk_set_parent(struct clk *clk, struct clk *parent) +{
- struct clk *c, *cp;
- int ret;
- debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
return ret;
- ret = clk_get_by_id(parent->id, &cp);
- if (ret)
return ret;
- ret = clk_set_parent(c, cp);
- c->dev->parent = cp->dev;
- return ret;
+}
+static struct clk_ops imx8mq_clk_ops = {
- .set_rate = imx8mq_clk_set_rate,
- .get_rate = imx8mq_clk_get_rate,
- .enable = imx8mq_clk_enable,
- .disable = imx8mq_clk_disable,
- .set_parent = imx8mq_clk_set_parent,
+};
+static int imx8mq_clk_probe(struct udevice *dev) +{
- void __iomem *base;
- base = (void *)ANATOP_BASE_ADDR;
- clk_dm(IMX8MQ_CLK_32K, clk_register_fixed_rate(NULL, "ckil", 32768));
- clk_dm(IMX8MQ_DRAM_PLL1_REF_SEL,
imx_clk_mux("dram_pll_ref_sel", base + 0x60, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
- clk_dm(IMX8MQ_ARM_PLL_REF_SEL,
imx_clk_mux("arm_pll_ref_sel", base + 0x28, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
- clk_dm(IMX8MQ_GPU_PLL_REF_SEL,
imx_clk_mux("gpu_pll_ref_sel", base + 0x18, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
- clk_dm(IMX8MQ_VPU_PLL_REF_SEL,
imx_clk_mux("vpu_pll_ref_sel", base + 0x20, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
- clk_dm(IMX8MQ_SYS3_PLL1_REF_SEL,
imx_clk_mux("sys3_pll_ref_sel", base + 0x48, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
- clk_dm(IMX8MQ_AUDIO_PLL1_REF_SEL,
imx_clk_mux("audio_pll1_ref_sel", base + 0x0, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
- clk_dm(IMX8MQ_AUDIO_PLL2_REF_SEL,
imx_clk_mux("audio_pll2_ref_sel", base + 0x8, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
- clk_dm(IMX8MQ_VIDEO_PLL1_REF_SEL,
imx_clk_mux("video_pll1_ref_sel", base + 0x10, 0, 2,
pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
- clk_dm(IMX8MQ_ARM_PLL,
imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel",
base + 0x28, &imx8mq_1416x_pll));
- clk_dm(IMX8MQ_GPU_PLL,
imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel",
base + 0x18, &imx8mq_1416x_pll));
- clk_dm(IMX8MQ_VPU_PLL,
imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel",
base + 0x20, &imx8mq_1416x_pll));
- clk_dm(IMX8MQ_SYS1_PLL1,
clk_register_fixed_rate(NULL, "sys1_pll", 800000000));
- clk_dm(IMX8MQ_SYS2_PLL1,
clk_register_fixed_rate(NULL, "sys2_pll", 1000000000));
- clk_dm(IMX8MQ_SYS2_PLL1,
clk_register_fixed_rate(NULL, "sys3_pll", 1000000000));
- clk_dm(IMX8MQ_AUDIO_PLL1,
imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel",
base + 0x0, &imx8mq_1443x_pll));
- clk_dm(IMX8MQ_AUDIO_PLL2,
imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel",
base + 0x8, &imx8mq_1443x_pll));
- clk_dm(IMX8MQ_VIDEO_PLL1,
imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel",
base + 0x10, &imx8mq_1443x_pll));
- /* PLL bypass out */
- clk_dm(IMX8MQ_ARM_PLL_BYPASS,
imx_clk_mux_flags("arm_pll_bypass", base + 0x28, 4, 1,
arm_pll_bypass_sels,
ARRAY_SIZE(arm_pll_bypass_sels),
CLK_SET_RATE_PARENT));
- clk_dm(IMX8MQ_GPU_PLL_BYPASS,
imx_clk_mux_flags("gpu_pll_bypass", base + 0x18, 4, 1,
gpu_pll_bypass_sels,
ARRAY_SIZE(gpu_pll_bypass_sels),
CLK_SET_RATE_PARENT));
- clk_dm(IMX8MQ_VPU_PLL_BYPASS,
imx_clk_mux_flags("vpu_pll_bypass", base + 0x20, 4, 1,
vpu_pll_bypass_sels,
ARRAY_SIZE(vpu_pll_bypass_sels),
CLK_SET_RATE_PARENT));
- clk_dm(IMX8MQ_AUDIO_PLL1_BYPASS,
imx_clk_mux_flags("audio_pll1_bypass", base + 0x0, 4, 1,
audio_pll1_bypass_sels,
ARRAY_SIZE(audio_pll1_bypass_sels),
CLK_SET_RATE_PARENT));
- clk_dm(IMX8MQ_AUDIO_PLL2_BYPASS,
imx_clk_mux_flags("audio_pll2_bypass", base + 0x8, 4, 1,
audio_pll2_bypass_sels,
ARRAY_SIZE(audio_pll2_bypass_sels),
CLK_SET_RATE_PARENT));
- clk_dm(IMX8MQ_VIDEO_PLL1_BYPASS,
imx_clk_mux_flags("video_pll1_bypass", base + 0x10, 4, 1,
video_pll1_bypass_sels,
ARRAY_SIZE(video_pll1_bypass_sels),
CLK_SET_RATE_PARENT));
- /* PLL out gate */
- clk_dm(IMX8MQ_DRAM_PLL_OUT,
imx_clk_gate("dram_pll_out", "dram_pll_ref_sel",
base + 0x60, 13));
- clk_dm(IMX8MQ_ARM_PLL_OUT,
imx_clk_gate("arm_pll_out", "arm_pll_bypass",
base + 0x28, 11));
- clk_dm(IMX8MQ_GPU_PLL_OUT,
imx_clk_gate("gpu_pll_out", "gpu_pll_bypass",
base + 0x18, 11));
- clk_dm(IMX8MQ_VPU_PLL_OUT,
imx_clk_gate("vpu_pll_out", "vpu_pll_bypass",
base + 0x20, 11));
- clk_dm(IMX8MQ_AUDIO_PLL1_OUT,
imx_clk_gate("audio_pll1_out", "audio_pll1_bypass",
base + 0x0, 11));
- clk_dm(IMX8MQ_AUDIO_PLL2_OUT,
imx_clk_gate("audio_pll2_out", "audio_pll2_bypass",
base + 0x8, 11));
- clk_dm(IMX8MQ_VIDEO_PLL1_OUT,
imx_clk_gate("video_pll1_out", "video_pll1_bypass",
base + 0x10, 11));
- clk_dm(IMX8MQ_SYS1_PLL_OUT,
imx_clk_gate("sys_pll1_out", "sys1_pll",
base + 0x30, 11));
- clk_dm(IMX8MQ_SYS2_PLL_OUT,
imx_clk_gate("sys_pll2_out", "sys2_pll",
base + 0x3c, 11));
- clk_dm(IMX8MQ_SYS3_PLL_OUT,
imx_clk_gate("sys_pll3_out", "sys3_pll",
base + 0x48, 11));
- /* SYS PLL fixed output */
- clk_dm(IMX8MQ_SYS1_PLL_40M,
imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20));
- clk_dm(IMX8MQ_SYS1_PLL_80M,
imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10));
- clk_dm(IMX8MQ_SYS1_PLL_100M,
imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8));
- clk_dm(IMX8MQ_SYS1_PLL_133M,
imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6));
- clk_dm(IMX8MQ_SYS1_PLL_160M,
imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5));
- clk_dm(IMX8MQ_SYS1_PLL_200M,
imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4));
- clk_dm(IMX8MQ_SYS1_PLL_266M,
imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3));
- clk_dm(IMX8MQ_SYS1_PLL_400M,
imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2));
- clk_dm(IMX8MQ_SYS1_PLL_800M,
imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1));
- clk_dm(IMX8MQ_SYS2_PLL_50M,
imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20));
- clk_dm(IMX8MQ_SYS2_PLL_100M,
imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10));
- clk_dm(IMX8MQ_SYS2_PLL_125M,
imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8));
- clk_dm(IMX8MQ_SYS2_PLL_166M,
imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6));
- clk_dm(IMX8MQ_SYS2_PLL_200M,
imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5));
- clk_dm(IMX8MQ_SYS2_PLL_250M,
imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4));
- clk_dm(IMX8MQ_SYS2_PLL_333M,
imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3));
- clk_dm(IMX8MQ_SYS2_PLL_500M,
imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2));
- clk_dm(IMX8MQ_SYS2_PLL_1000M,
imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1));
- clk_dm(IMX8MQ_CLK_MON_AUDIO_PLL1_DIV,
imx_clk_divider("audio_pll1_out_monitor", "audio_pll1_bypass", base + 0x78, 0, 3));
- clk_dm(IMX8MQ_CLK_MON_AUDIO_PLL2_DIV,
imx_clk_divider("audio_pll2_out_monitor", "audio_pll2_bypass", base + 0x78, 4, 3));
- clk_dm(IMX8MQ_CLK_MON_VIDEO_PLL1_DIV,
imx_clk_divider("video_pll1_out_monitor", "video_pll1_bypass", base + 0x78, 8, 3));
- clk_dm(IMX8MQ_CLK_MON_GPU_PLL_DIV,
imx_clk_divider("gpu_pll_out_monitor", "gpu_pll_bypass", base + 0x78, 12, 3));
- clk_dm(IMX8MQ_CLK_MON_VPU_PLL_DIV,
imx_clk_divider("vpu_pll_out_monitor", "vpu_pll_bypass", base + 0x78, 16, 3));
- clk_dm(IMX8MQ_CLK_MON_ARM_PLL_DIV,
imx_clk_divider("arm_pll_out_monitor", "arm_pll_bypass", base + 0x78, 20, 3));
- clk_dm(IMX8MQ_CLK_MON_SYS_PLL1_DIV,
imx_clk_divider("sys_pll1_out_monitor", "sys_pll1_out", base + 0x7c, 0, 3));
- clk_dm(IMX8MQ_CLK_MON_SYS_PLL2_DIV,
imx_clk_divider("sys_pll2_out_monitor", "sys_pll2_out", base + 0x7c, 4, 3));
- clk_dm(IMX8MQ_CLK_MON_SYS_PLL3_DIV,
imx_clk_divider("sys_pll3_out_monitor", "sys_pll3_out", base + 0x7c, 8, 3));
- clk_dm(IMX8MQ_CLK_MON_DRAM_PLL_DIV,
imx_clk_divider("dram_pll_out_monitor", "dram_pll_out", base + 0x7c, 12, 3));
- clk_dm(IMX8MQ_CLK_MON_SEL,
imx_clk_mux_flags("pllout_monitor_sel", base + 0x74, 0, 4,
pllout_monitor_sels,
ARRAY_SIZE(pllout_monitor_sels),
CLK_SET_RATE_PARENT));
- clk_dm(IMX8MQ_CLK_MON_CLK2_OUT,
imx_clk_gate4("pllout_monitor_clk2", "pllout_monitor_sel", base + 0x74, 4));
- base = dev_read_addr_ptr(dev);
- if (!base) {
printf("%s : base failed\n", __func__);
return -EINVAL;
- }
- clk_dm(IMX8MQ_CLK_A53_SRC,
imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3,
imx8mq_a53_sels, ARRAY_SIZE(imx8mq_a53_sels)));
- clk_dm(IMX8MQ_CLK_A53_CG,
imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28));
- clk_dm(IMX8MQ_CLK_A53_DIV,
imx_clk_divider2("arm_a53_div", "arm_a53_cg",
base + 0x8000, 0, 3));
- clk_dm(IMX8MQ_CLK_A53_CORE,
imx_clk_mux2("arm_a53_src", base + 0x9880, 24, 1,
imx8mq_a53_core_sels, ARRAY_SIZE(imx8mq_a53_core_sels)));
- clk_dm(IMX8MQ_CLK_AHB,
imx8m_clk_composite_critical("ahb", imx8mq_ahb_sels,
base + 0x9000));
- clk_dm(IMX8MQ_CLK_IPG_ROOT,
imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1));
- clk_dm(IMX8MQ_CLK_ENET_AXI,
imx8m_clk_composite("enet_axi", imx8mq_enet_axi_sels,
base + 0x8880));
- clk_dm(IMX8MQ_CLK_NAND_USDHC_BUS,
imx8m_clk_composite_critical("nand_usdhc_bus",
imx8mq_nand_usdhc_sels,
base + 0x8900));
- clk_dm(IMX8MQ_CLK_USB_BUS,
imx8m_clk_composite("usb_bus", imx8mq_usb_bus_sels, base + 0x8b80));
- /* IP */
- clk_dm(IMX8MQ_CLK_USDHC1,
imx8m_clk_composite("usdhc1", imx8mq_usdhc1_sels,
base + 0xac00));
- clk_dm(IMX8MQ_CLK_USDHC2,
imx8m_clk_composite("usdhc2", imx8mq_usdhc2_sels,
base + 0xac80));
- clk_dm(IMX8MQ_CLK_I2C1,
imx8m_clk_composite("i2c1", imx8mq_i2c1_sels, base + 0xad00));
- clk_dm(IMX8MQ_CLK_I2C2,
imx8m_clk_composite("i2c2", imx8mq_i2c2_sels, base + 0xad80));
- clk_dm(IMX8MQ_CLK_I2C3,
imx8m_clk_composite("i2c3", imx8mq_i2c3_sels, base + 0xae00));
- clk_dm(IMX8MQ_CLK_I2C4,
imx8m_clk_composite("i2c4", imx8mq_i2c4_sels, base + 0xae80));
- clk_dm(IMX8MQ_CLK_WDOG,
imx8m_clk_composite("wdog", imx8mq_wdog_sels, base + 0xb900));
- clk_dm(IMX8MQ_CLK_QSPI,
imx8m_clk_composite("qspi", imx8mq_qspi_sels, base + 0xab80));
- clk_dm(IMX8MQ_CLK_USB_CORE_REF,
imx8m_clk_composite("usb_core_ref", imx8mq_usb_core_sels, base + 0xb100));
- clk_dm(IMX8MQ_CLK_USB_PHY_REF,
imx8m_clk_composite("usb_phy_ref", imx8mq_usb_phy_sels, base + 0xb180));
- clk_dm(IMX8MQ_CLK_ECSPI1,
imx8m_clk_composite("ecspi1", imx8mq_ecspi1_sels, base + 0xb280));
- clk_dm(IMX8MQ_CLK_ECSPI2,
imx8m_clk_composite("ecspi2", imx8mq_ecspi2_sels, base + 0xb300));
- clk_dm(IMX8MQ_CLK_ECSPI3,
imx8m_clk_composite("ecspi3", imx8mq_ecspi3_sels, base + 0xc180));
- clk_dm(IMX8MQ_CLK_ECSPI1_ROOT,
imx_clk_gate4("ecspi1_root_clk", "ecspi1", base + 0x4070, 0));
- clk_dm(IMX8MQ_CLK_ECSPI2_ROOT,
imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0));
- clk_dm(IMX8MQ_CLK_ECSPI3_ROOT,
imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0));
- clk_dm(IMX8MQ_CLK_I2C1_ROOT,
imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0));
- clk_dm(IMX8MQ_CLK_I2C2_ROOT,
imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0));
- clk_dm(IMX8MQ_CLK_I2C3_ROOT,
imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0));
- clk_dm(IMX8MQ_CLK_I2C4_ROOT,
imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0));
- clk_dm(IMX8MQ_CLK_OCOTP_ROOT,
imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0));
- clk_dm(IMX8MQ_CLK_USDHC1_ROOT,
imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0));
- clk_dm(IMX8MQ_CLK_USDHC2_ROOT,
imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0));
- clk_dm(IMX8MQ_CLK_WDOG1_ROOT,
imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0));
- clk_dm(IMX8MQ_CLK_WDOG2_ROOT,
imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0));
- clk_dm(IMX8MQ_CLK_WDOG3_ROOT,
imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0));
- clk_dm(IMX8MQ_CLK_QSPI_ROOT,
imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0));
- clk_dm(IMX8MQ_CLK_USB1_CTRL_ROOT,
imx_clk_gate4("usb1_ctrl_root_clk", "usb_bus", base + 0x44d0, 0));
- clk_dm(IMX8MQ_CLK_USB2_CTRL_ROOT,
imx_clk_gate4("usb2_ctrl_root_clk", "usb_bus", base + 0x44e0, 0));
- clk_dm(IMX8MQ_CLK_USB1_PHY_ROOT,
imx_clk_gate4("usb1_phy_root_clk", "usb_phy_ref", base + 0x44f0, 0));
- clk_dm(IMX8MQ_CLK_USB2_PHY_ROOT,
imx_clk_gate4("usb2_phy_root_clk", "usb_phy_ref", base + 0x4500, 0));
- clk_dm(IMX8MQ_CLK_ENET_REF,
imx8m_clk_composite("enet_ref", imx8mq_enet_ref_sels,
base + 0xa980));
- clk_dm(IMX8MQ_CLK_ENET_TIMER,
imx8m_clk_composite("enet_timer", imx8mq_enet_timer_sels,
base + 0xaa00));
- clk_dm(IMX8MQ_CLK_ENET_PHY_REF,
imx8m_clk_composite("enet_phy", imx8mq_enet_phy_sels,
base + 0xaa80));
- clk_dm(IMX8MQ_CLK_ENET1_ROOT,
imx_clk_gate4("enet1_root_clk", "enet_axi",
base + 0x40a0, 0));
- return 0;
+}
+static const struct udevice_id imx8mq_clk_ids[] = {
- { .compatible = "fsl,imx8mq-ccm" },
- { },
+};
+U_BOOT_DRIVER(imx8mq_clk) = {
- .name = "clk_imx8mq",
- .id = UCLASS_CLK,
- .of_match = imx8mq_clk_ids,
- .ops = &imx8mq_clk_ops,
- .probe = imx8mq_clk_probe,
- .flags = DM_FLAG_PRE_RELOC,
+};
With Heiko's comments fixed,
Acked-by: Sean Anderson seanga2@gmail.com

Hi Angus,
could you include the UART clocks?
Am Di., 15. März 2022 um 14:09 Uhr schrieb Angus Ainslie angus@akkea.ca:
This is a DM clock driver based off the imx8mm u-boot driver and the linux kernel driver.
All of the PLLs and clocks are initialized so the subsystems below are functional and tested.
- USB host and peripheral
- ECSPI
- UART
- I2C all busses
- USDHC for eMMC support
- USB storage
- GPIO
- DRAM
Signed-off-by: Angus Ainslie angus@akkea.ca
Could you include the UART clocks? Or should I wait until your patch is accepted and then send this one after?
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index c3b685dbaa..b2d92f4776 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -82,6 +82,23 @@ static const char *imx8mq_i2c4_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_ "sys_pll3_out", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+static const char * const imx8mq_uart1_sels[] = {"clock-osc-25m", "sys_pll1_80m", "sys_pll2_200m", + "sys_pll2_100m", "sys_pll3_out", "clk_ext2", + "clk_ext4", "audio_pll2_out", }; + +static const char * const imx8mq_uart2_sels[] = {"clock-osc-25m", "sys_pll1_80m", "sys_pll2_200m", + "sys_pll2_100m", "sys_pll3_out", "clk_ext2", + "clk_ext3", "audio_pll2_out", }; + +static const char * const imx8mq_uart3_sels[] = {"clock-osc-25m", "sys_pll1_80m", "sys_pll2_200m", + "sys_pll2_100m", "sys_pll3_out", "clk_ext2", + "clk_ext4", "audio_pll2_out", }; + +static const char * const imx8mq_uart4_sels[] = {"clock-osc-25m", "sys_pll1_80m", "sys_pll2_200m", + "sys_pll2_100m", "sys_pll3_out", "clk_ext2", + "clk_ext3", "audio_pll2_out", }; + + static const char *imx8mq_wdog_sels[] = {"clock-osc-25m", "sys_pll1_133m", "sys_pll1_160m", "vpu_pll_out", "sys_pll2_125m", "sys_pll3_out", "sys_pll1_80m", "sys_pll2_166m", }; @@ -358,6 +375,16 @@ static int imx8mq_clk_probe(struct udevice *dev) imx8m_clk_composite("i2c3", imx8mq_i2c3_sels, base + 0xae00)); clk_dm(IMX8MQ_CLK_I2C4, imx8m_clk_composite("i2c4", imx8mq_i2c4_sels, base + 0xae80)); + + clk_dm(IMX8MQ_CLK_UART1, + imx8m_clk_composite("uart1", imx8mq_uart1_sels, base + 0xaf00)); + clk_dm(IMX8MQ_CLK_UART2, + imx8m_clk_composite("uart2", imx8mq_uart2_sels, base + 0xaf80)); + clk_dm(IMX8MQ_CLK_UART3, + imx8m_clk_composite("uart3", imx8mq_uart3_sels, base + 0xb000)); + clk_dm(IMX8MQ_CLK_UART4, + imx8m_clk_composite("uart4", imx8mq_uart4_sels, base + 0xb080)); + clk_dm(IMX8MQ_CLK_WDOG, imx8m_clk_composite("wdog", imx8mq_wdog_sels, base + 0xb900)); clk_dm(IMX8MQ_CLK_QSPI, @@ -387,6 +414,16 @@ static int imx8mq_clk_probe(struct udevice *dev) imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0)); clk_dm(IMX8MQ_CLK_I2C4_ROOT, imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0)); + + clk_dm(IMX8MQ_CLK_UART1_ROOT, + imx_clk_gate4("uart1_root_clk", "uart1", base + 0x4490, 0)); + clk_dm(IMX8MQ_CLK_UART2_ROOT, + imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0)); + clk_dm(IMX8MQ_CLK_UART3_ROOT, + imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0)); + clk_dm(IMX8MQ_CLK_UART4_ROOT, + imx_clk_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0)); + clk_dm(IMX8MQ_CLK_OCOTP_ROOT, imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0)); clk_dm(IMX8MQ_CLK_USDHC1_ROOT,
[SNIP]

Hi Heiko,
On 2022-03-24 01:28, Heiko Thiery wrote:
Hi Angus,
could you include the UART clocks?
Sure I can add the UART clocks.
We've also found an issue with devfreq using the current setup so it might be a few days before I send an update.
Angus

Re-factor the imx8m[nmpq] rate tables into the common pll1416x clock driver.
43cdaa1567ad3 ("clk: imx8mm: Move 1443X/1416X PLL clock structure to common place")
Signed-off-by: Angus Ainslie angus@akkea.ca --- drivers/clk/imx/clk-imx8mm.c | 60 +++----------------------------- drivers/clk/imx/clk-imx8mn.c | 60 +++----------------------------- drivers/clk/imx/clk-imx8mp.c | 65 ++++++----------------------------- drivers/clk/imx/clk-imx8mq.c | 59 ++++--------------------------- drivers/clk/imx/clk-pll14xx.c | 61 ++++++++++++++++++++++++++++++++ drivers/clk/imx/clk.h | 4 +++ 6 files changed, 91 insertions(+), 218 deletions(-)
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index 3aa8c641f9a..ab8f9b4d6b9 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -15,56 +15,6 @@
#include "clk.h"
-#define PLL_1416X_RATE(_rate, _m, _p, _s) \ - { \ - .rate = (_rate), \ - .mdiv = (_m), \ - .pdiv = (_p), \ - .sdiv = (_s), \ - } - -#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \ - { \ - .rate = (_rate), \ - .mdiv = (_m), \ - .pdiv = (_p), \ - .sdiv = (_s), \ - .kdiv = (_k), \ - } - -static const struct imx_pll14xx_rate_table imx8mm_pll1416x_tbl[] = { - PLL_1416X_RATE(1800000000U, 225, 3, 0), - PLL_1416X_RATE(1600000000U, 200, 3, 0), - PLL_1416X_RATE(1200000000U, 300, 3, 1), - PLL_1416X_RATE(1000000000U, 250, 3, 1), - PLL_1416X_RATE(800000000U, 200, 3, 1), - PLL_1416X_RATE(750000000U, 250, 2, 2), - PLL_1416X_RATE(700000000U, 350, 3, 2), - PLL_1416X_RATE(600000000U, 300, 3, 2), -}; - -static const struct imx_pll14xx_rate_table imx8mm_drampll_tbl[] = { - PLL_1443X_RATE(650000000U, 325, 3, 2, 0), -}; - -static struct imx_pll14xx_clk imx8mm_dram_pll __initdata = { - .type = PLL_1443X, - .rate_table = imx8mm_drampll_tbl, - .rate_count = ARRAY_SIZE(imx8mm_drampll_tbl), -}; - -static struct imx_pll14xx_clk imx8mm_arm_pll __initdata = { - .type = PLL_1416X, - .rate_table = imx8mm_pll1416x_tbl, - .rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl), -}; - -static struct imx_pll14xx_clk imx8mm_sys_pll __initdata = { - .type = PLL_1416X, - .rate_table = imx8mm_pll1416x_tbl, - .rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl), -}; - static const char *pll_ref_sels[] = { "clock-osc-24m", "dummy", "dummy", "dummy", }; static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", }; static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; @@ -250,19 +200,19 @@ static int imx8mm_clk_probe(struct udevice *dev)
clk_dm(IMX8MM_DRAM_PLL, imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel", - base + 0x50, &imx8mm_dram_pll)); + base + 0x50, &imx_1443x_dram_pll)); clk_dm(IMX8MM_ARM_PLL, imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", - base + 0x84, &imx8mm_arm_pll)); + base + 0x84, &imx_1416x_pll)); clk_dm(IMX8MM_SYS_PLL1, imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel", - base + 0x94, &imx8mm_sys_pll)); + base + 0x94, &imx_1416x_pll)); clk_dm(IMX8MM_SYS_PLL2, imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel", - base + 0x104, &imx8mm_sys_pll)); + base + 0x104, &imx_1416x_pll)); clk_dm(IMX8MM_SYS_PLL3, imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", - base + 0x114, &imx8mm_sys_pll)); + base + 0x114, &imx_1416x_pll));
/* PLL bypass out */ clk_dm(IMX8MM_DRAM_PLL_BYPASS, diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index e398d7de02a..c3d60ad057c 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -15,56 +15,6 @@
#include "clk.h"
-#define PLL_1416X_RATE(_rate, _m, _p, _s) \ - { \ - .rate = (_rate), \ - .mdiv = (_m), \ - .pdiv = (_p), \ - .sdiv = (_s), \ - } - -#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \ - { \ - .rate = (_rate), \ - .mdiv = (_m), \ - .pdiv = (_p), \ - .sdiv = (_s), \ - .kdiv = (_k), \ - } - -static const struct imx_pll14xx_rate_table imx8mn_pll1416x_tbl[] = { - PLL_1416X_RATE(1800000000U, 225, 3, 0), - PLL_1416X_RATE(1600000000U, 200, 3, 0), - PLL_1416X_RATE(1200000000U, 300, 3, 1), - PLL_1416X_RATE(1000000000U, 250, 3, 1), - PLL_1416X_RATE(800000000U, 200, 3, 1), - PLL_1416X_RATE(750000000U, 250, 2, 2), - PLL_1416X_RATE(700000000U, 350, 3, 2), - PLL_1416X_RATE(600000000U, 300, 3, 2), -}; - -static const struct imx_pll14xx_rate_table imx8mn_drampll_tbl[] = { - PLL_1443X_RATE(650000000U, 325, 3, 2, 0), -}; - -static struct imx_pll14xx_clk imx8mn_dram_pll __initdata = { - .type = PLL_1443X, - .rate_table = imx8mn_drampll_tbl, - .rate_count = ARRAY_SIZE(imx8mn_drampll_tbl), -}; - -static struct imx_pll14xx_clk imx8mn_arm_pll __initdata = { - .type = PLL_1416X, - .rate_table = imx8mn_pll1416x_tbl, - .rate_count = ARRAY_SIZE(imx8mn_pll1416x_tbl), -}; - -static struct imx_pll14xx_clk imx8mn_sys_pll __initdata = { - .type = PLL_1416X, - .rate_table = imx8mn_pll1416x_tbl, - .rate_count = ARRAY_SIZE(imx8mn_pll1416x_tbl), -}; - static const char *pll_ref_sels[] = { "clock-osc-24m", "dummy", "dummy", "dummy", }; static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", }; static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; @@ -258,19 +208,19 @@ static int imx8mn_clk_probe(struct udevice *dev)
clk_dm(IMX8MN_DRAM_PLL, imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel", - base + 0x50, &imx8mn_dram_pll)); + base + 0x50, &imx_1443x_dram_pll)); clk_dm(IMX8MN_ARM_PLL, imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", - base + 0x84, &imx8mn_arm_pll)); + base + 0x84, &imx_1416x_pll)); clk_dm(IMX8MN_SYS_PLL1, imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel", - base + 0x94, &imx8mn_sys_pll)); + base + 0x94, &imx_1416x_pll)); clk_dm(IMX8MN_SYS_PLL2, imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel", - base + 0x104, &imx8mn_sys_pll)); + base + 0x104, &imx_1416x_pll)); clk_dm(IMX8MN_SYS_PLL3, imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", - base + 0x114, &imx8mn_sys_pll)); + base + 0x114, &imx_1416x_pll));
/* PLL bypass out */ clk_dm(IMX8MN_DRAM_PLL_BYPASS, diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index c77500bcce0..5ccb969da3b 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -15,56 +15,6 @@
#include "clk.h"
-#define PLL_1416X_RATE(_rate, _m, _p, _s) \ - { \ - .rate = (_rate), \ - .mdiv = (_m), \ - .pdiv = (_p), \ - .sdiv = (_s), \ - } - -#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \ - { \ - .rate = (_rate), \ - .mdiv = (_m), \ - .pdiv = (_p), \ - .sdiv = (_s), \ - .kdiv = (_k), \ - } - -static const struct imx_pll14xx_rate_table imx8mp_pll1416x_tbl[] = { - PLL_1416X_RATE(1800000000U, 225, 3, 0), - PLL_1416X_RATE(1600000000U, 200, 3, 0), - PLL_1416X_RATE(1200000000U, 300, 3, 1), - PLL_1416X_RATE(1000000000U, 250, 3, 1), - PLL_1416X_RATE(800000000U, 200, 3, 1), - PLL_1416X_RATE(750000000U, 250, 2, 2), - PLL_1416X_RATE(700000000U, 350, 3, 2), - PLL_1416X_RATE(600000000U, 300, 3, 2), -}; - -static const struct imx_pll14xx_rate_table imx8mp_drampll_tbl[] = { - PLL_1443X_RATE(650000000U, 325, 3, 2, 0), -}; - -static struct imx_pll14xx_clk imx8mp_dram_pll __initdata = { - .type = PLL_1443X, - .rate_table = imx8mp_drampll_tbl, - .rate_count = ARRAY_SIZE(imx8mp_drampll_tbl), -}; - -static struct imx_pll14xx_clk imx8mp_arm_pll __initdata = { - .type = PLL_1416X, - .rate_table = imx8mp_pll1416x_tbl, - .rate_count = ARRAY_SIZE(imx8mp_pll1416x_tbl), -}; - -static struct imx_pll14xx_clk imx8mp_sys_pll __initdata = { - .type = PLL_1416X, - .rate_table = imx8mp_pll1416x_tbl, - .rate_count = ARRAY_SIZE(imx8mp_pll1416x_tbl), -}; - static const char *pll_ref_sels[] = { "clock-osc-24m", "dummy", "dummy", "dummy", }; static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", }; static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; @@ -286,11 +236,16 @@ static int imx8mp_clk_probe(struct udevice *dev) clk_dm(IMX8MP_SYS_PLL2_REF_SEL, imx_clk_mux("sys_pll2_ref_sel", base + 0x104, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); clk_dm(IMX8MP_SYS_PLL3_REF_SEL, imx_clk_mux("sys_pll3_ref_sel", base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
- clk_dm(IMX8MP_DRAM_PLL, imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx8mp_dram_pll)); - clk_dm(IMX8MP_ARM_PLL, imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, &imx8mp_arm_pll)); - clk_dm(IMX8MP_SYS_PLL1, imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel", base + 0x94, &imx8mp_sys_pll)); - clk_dm(IMX8MP_SYS_PLL2, imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel", base + 0x104, &imx8mp_sys_pll)); - clk_dm(IMX8MP_SYS_PLL3, imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114, &imx8mp_sys_pll)); + clk_dm(IMX8MP_DRAM_PLL, imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, + &imx_1443x_dram_pll)); + clk_dm(IMX8MP_ARM_PLL, imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, + &imx_1416x_pll)); + clk_dm(IMX8MP_SYS_PLL1, imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel", base + 0x94, + &imx_1416x_pll)); + clk_dm(IMX8MP_SYS_PLL2, imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel", base + 0x104, + &imx_1416x_pll)); + clk_dm(IMX8MP_SYS_PLL3, imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114, + &imx_1416x_pll));
clk_dm(IMX8MP_DRAM_PLL_BYPASS, imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 4, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT)); clk_dm(IMX8MP_ARM_PLL_BYPASS, imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 4, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT)); diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index 0aea417a29b..e753613f6c3 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -16,53 +16,6 @@
#include "clk.h"
-#define PLL_1416X_RATE(_rate, _m, _p, _s) \ - { \ - .rate = (_rate), \ - .mdiv = (_m), \ - .pdiv = (_p), \ - .sdiv = (_s), \ - } - -#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \ - { \ - .rate = (_rate), \ - .mdiv = (_m), \ - .pdiv = (_p), \ - .sdiv = (_s), \ - .kdiv = (_k), \ - } - -static const struct imx_pll14xx_rate_table imx8mq_pll1416x_tbl[] = { - PLL_1416X_RATE(1800000000U, 225, 3, 0), - PLL_1416X_RATE(1600000000U, 200, 3, 0), - PLL_1416X_RATE(1200000000U, 300, 3, 1), - PLL_1416X_RATE(1000000000U, 250, 3, 1), - PLL_1416X_RATE(800000000U, 200, 3, 1), - PLL_1416X_RATE(750000000U, 250, 2, 2), - PLL_1416X_RATE(700000000U, 350, 3, 2), - PLL_1416X_RATE(600000000U, 300, 3, 2), -}; - -const struct imx_pll14xx_rate_table imx8mq_pll1443x_tbl[] = { - PLL_1443X_RATE(650000000U, 325, 3, 2, 0), - PLL_1443X_RATE(594000000U, 198, 2, 2, 0), - PLL_1443X_RATE(393216000U, 262, 2, 3, 9437), - PLL_1443X_RATE(361267200U, 361, 3, 3, 17511), -}; - -static struct imx_pll14xx_clk imx8mq_1416x_pll __initdata = { - .type = PLL_1416X, - .rate_table = imx8mq_pll1416x_tbl, - .rate_count = ARRAY_SIZE(imx8mq_pll1416x_tbl), -}; - -static struct imx_pll14xx_clk imx8mq_1443x_pll __initdata = { - .type = PLL_1443X, - .rate_table = imx8mq_pll1443x_tbl, - .rate_count = ARRAY_SIZE(imx8mq_pll1443x_tbl), -}; - static const char *pll_ref_sels[] = { "clock-osc-25m", "clock-osc-27m", "clock-phy-27m", "dummy", }; static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", }; @@ -287,13 +240,13 @@ static int imx8mq_clk_probe(struct udevice *dev)
clk_dm(IMX8MQ_ARM_PLL, imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", - base + 0x28, &imx8mq_1416x_pll)); + base + 0x28, &imx_1416x_pll)); clk_dm(IMX8MQ_GPU_PLL, imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel", - base + 0x18, &imx8mq_1416x_pll)); + base + 0x18, &imx_1416x_pll)); clk_dm(IMX8MQ_VPU_PLL, imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel", - base + 0x20, &imx8mq_1416x_pll)); + base + 0x20, &imx_1416x_pll));
clk_dm(IMX8MQ_SYS1_PLL1, clk_register_fixed_rate(NULL, "sys1_pll", 800000000)); @@ -303,13 +256,13 @@ static int imx8mq_clk_probe(struct udevice *dev) clk_register_fixed_rate(NULL, "sys3_pll", 1000000000)); clk_dm(IMX8MQ_AUDIO_PLL1, imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel", - base + 0x0, &imx8mq_1443x_pll)); + base + 0x0, &imx_1443x_pll)); clk_dm(IMX8MQ_AUDIO_PLL2, imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel", - base + 0x8, &imx8mq_1443x_pll)); + base + 0x8, &imx_1443x_pll)); clk_dm(IMX8MQ_VIDEO_PLL1, imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel", - base + 0x10, &imx8mq_1443x_pll)); + base + 0x10, &imx_1443x_pll));
/* PLL bypass out */ clk_dm(IMX8MQ_ARM_PLL_BYPASS, diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c index b0ccb6c8eda..b93c0bc64e7 100644 --- a/drivers/clk/imx/clk-pll14xx.c +++ b/drivers/clk/imx/clk-pll14xx.c @@ -52,6 +52,67 @@ struct clk_pll14xx {
#define to_clk_pll14xx(_clk) container_of(_clk, struct clk_pll14xx, clk)
+#define PLL_1416X_RATE(_rate, _m, _p, _s) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + } + +#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + .kdiv = (_k), \ + } + +static const struct imx_pll14xx_rate_table imx_pll1416x_tbl[] = { + PLL_1416X_RATE(1800000000U, 225, 3, 0), + PLL_1416X_RATE(1600000000U, 200, 3, 0), + PLL_1416X_RATE(1500000000U, 375, 3, 1), + PLL_1416X_RATE(1400000000U, 350, 3, 1), + PLL_1416X_RATE(1200000000U, 300, 3, 1), + PLL_1416X_RATE(1000000000U, 250, 3, 1), + PLL_1416X_RATE(800000000U, 200, 3, 1), + PLL_1416X_RATE(750000000U, 250, 2, 2), + PLL_1416X_RATE(700000000U, 350, 3, 2), + PLL_1416X_RATE(600000000U, 300, 3, 2), +}; + +const struct imx_pll14xx_rate_table imx_pll1443x_tbl[] = { + PLL_1443X_RATE(1039500000U, 173, 2, 1, 16384), + PLL_1443X_RATE(650000000U, 325, 3, 2, 0), + PLL_1443X_RATE(594000000U, 198, 2, 2, 0), + PLL_1443X_RATE(519750000U, 173, 2, 2, 16384), + PLL_1443X_RATE(393216000U, 262, 2, 3, 9437), + PLL_1443X_RATE(361267200U, 361, 3, 3, 17511), +}; + +struct imx_pll14xx_clk imx_1443x_pll __initdata = { + .type = PLL_1443X, + .rate_table = imx_pll1443x_tbl, + .rate_count = ARRAY_SIZE(imx_pll1443x_tbl), +}; +EXPORT_SYMBOL_GPL(imx_1443x_pll); + +struct imx_pll14xx_clk imx_1443x_dram_pll __initdata = { + .type = PLL_1443X, + .rate_table = imx_pll1443x_tbl, + .rate_count = ARRAY_SIZE(imx_pll1443x_tbl), + .flags = CLK_GET_RATE_NOCACHE, +}; +EXPORT_SYMBOL_GPL(imx_1443x_dram_pll); + +struct imx_pll14xx_clk imx_1416x_pll __initdata = { + .type = PLL_1416X, + .rate_table = imx_pll1416x_tbl, + .rate_count = ARRAY_SIZE(imx_pll1416x_tbl), +}; +EXPORT_SYMBOL_GPL(imx_1416x_pll); + static const struct imx_pll14xx_rate_table *imx_get_pll_settings( struct clk_pll14xx *pll, unsigned long rate) { diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index 60f287046b9..0e1eaf03d41 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -41,6 +41,10 @@ struct imx_pll14xx_clk { int flags; };
+extern struct imx_pll14xx_clk imx_1416x_pll; +extern struct imx_pll14xx_clk imx_1443x_pll; +extern struct imx_pll14xx_clk imx_1443x_dram_pll; + struct clk *imx_clk_pll14xx(const char *name, const char *parent_name, void __iomem *base, const struct imx_pll14xx_clk *pll_clk);

All of the imx8m[nmpq] use the same clk_ops functions so move them to a common file.
Signed-off-by: Angus Ainslie angus@akkea.ca Reviewed-by: Marek Vasut marex@denx.de --- drivers/clk/imx/Makefile | 8 +-- drivers/clk/imx/clk-imx8m.c | 108 +++++++++++++++++++++++++++++++++++ drivers/clk/imx/clk-imx8m.h | 12 ++++ drivers/clk/imx/clk-imx8mm.c | 89 +---------------------------- drivers/clk/imx/clk-imx8mn.c | 89 +---------------------------- drivers/clk/imx/clk-imx8mp.c | 91 +---------------------------- drivers/clk/imx/clk-imx8mq.c | 91 +---------------------------- 7 files changed, 132 insertions(+), 356 deletions(-) create mode 100644 drivers/clk/imx/clk-imx8m.c create mode 100644 drivers/clk/imx/clk-imx8m.h
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index c5766901f2b..09030f1ded2 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -11,13 +11,13 @@ obj-$(CONFIG_IMX8QXP) += clk-imx8qxp.o obj-$(CONFIG_IMX8QM) += clk-imx8qm.o endif obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MM) += clk-imx8mm.o clk-pll14xx.o \ - clk-composite-8m.o + clk-composite-8m.o clk-imx8m.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MN) += clk-imx8mn.o clk-pll14xx.o \ - clk-composite-8m.o + clk-composite-8m.o clk-imx8m.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MP) += clk-imx8mp.o clk-pll14xx.o \ - clk-composite-8m.o + clk-composite-8m.o clk-imx8m.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MQ) += clk-imx8mq.o clk-pll14xx.o \ - clk-composite-8m.o + clk-composite-8m.o clk-imx8m.o
obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1020) += clk-imxrt1020.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1050) += clk-imxrt1050.o diff --git a/drivers/clk/imx/clk-imx8m.c b/drivers/clk/imx/clk-imx8m.c new file mode 100644 index 00000000000..d3e9f8aaee0 --- /dev/null +++ b/drivers/clk/imx/clk-imx8m.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2018 NXP + * Copyright 2022 Purism SPC + * Peng Fan peng.fan@nxp.com + */ + +#include <common.h> +#include <clk-uclass.h> +#include <dm.h> +#include <log.h> +#include <malloc.h> +#include <asm/arch/clock.h> +#include <misc.h> + +#include "clk-imx8m.h" + +ulong imx8m_clk_get_rate(struct clk *clk) +{ + struct clk *c; + int ret; + + debug("%s(#%lu)\n", __func__, clk->id); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + return clk_get_rate(c); +} +EXPORT_SYMBOL_GPL(imx8m_clk_get_rate); + +ulong imx8m_clk_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *c; + int ret; + + debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + return clk_set_rate(c, rate); +} +EXPORT_SYMBOL_GPL(imx8m_clk_set_rate); + +static int __imx8m_clk_enable(struct clk *clk, bool enable) +{ + struct clk *c; + int ret; + + debug("%s(#%lu) en: %d\n", __func__, clk->id, enable); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + if (enable) + ret = clk_enable(c); + else + ret = clk_disable(c); + + return ret; +} + +int imx8m_clk_disable(struct clk *clk) +{ + return __imx8m_clk_enable(clk, 0); +} +EXPORT_SYMBOL_GPL(imx8m_clk_disable); + +int imx8m_clk_enable(struct clk *clk) +{ + return __imx8m_clk_enable(clk, 1); +} +EXPORT_SYMBOL_GPL(imx8m_clk_enable); + +int imx8m_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk *c, *cp; + int ret; + + debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + ret = clk_get_by_id(parent->id, &cp); + if (ret) + return ret; + + ret = clk_set_parent(c, cp); + c->dev->parent = cp->dev; + + return ret; +} +EXPORT_SYMBOL_GPL(imx8m_clk_set_parent); + +struct clk_ops imx8m_clk_ops = { + .set_rate = imx8m_clk_set_rate, + .get_rate = imx8m_clk_get_rate, + .enable = imx8m_clk_enable, + .disable = imx8m_clk_disable, + .set_parent = imx8m_clk_set_parent, +}; +EXPORT_SYMBOL_GPL(imx8m_clk_ops); diff --git a/drivers/clk/imx/clk-imx8m.h b/drivers/clk/imx/clk-imx8m.h new file mode 100644 index 00000000000..7c0892e148d --- /dev/null +++ b/drivers/clk/imx/clk-imx8m.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2022 Purism SPC + */ + +extern ulong imx8m_clk_get_rate(struct clk *clk); +extern ulong imx8m_clk_set_rate(struct clk *clk, unsigned long rate); +extern int imx8m_clk_disable(struct clk *clk); +extern int imx8m_clk_enable(struct clk *clk); +extern int imx8m_clk_set_parent(struct clk *clk, struct clk *parent); + +extern struct clk_ops imx8m_clk_ops; diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index ab8f9b4d6b9..fb3e4e7d0df 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -14,6 +14,7 @@ #include <dt-bindings/clock/imx8mm-clock.h>
#include "clk.h" +#include "clk-imx8m.h"
static const char *pll_ref_sels[] = { "clock-osc-24m", "dummy", "dummy", "dummy", }; static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", }; @@ -90,92 +91,6 @@ static const char *imx8mm_ecspi2_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sy static const char *imx8mm_ecspi3_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
-static ulong imx8mm_clk_get_rate(struct clk *clk) -{ - struct clk *c; - int ret; - - debug("%s(#%lu)\n", __func__, clk->id); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - return clk_get_rate(c); -} - -static ulong imx8mm_clk_set_rate(struct clk *clk, unsigned long rate) -{ - struct clk *c; - int ret; - - debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - return clk_set_rate(c, rate); -} - -static int __imx8mm_clk_enable(struct clk *clk, bool enable) -{ - struct clk *c; - int ret; - - debug("%s(#%lu) en: %d\n", __func__, clk->id, enable); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - if (enable) - ret = clk_enable(c); - else - ret = clk_disable(c); - - return ret; -} - -static int imx8mm_clk_disable(struct clk *clk) -{ - return __imx8mm_clk_enable(clk, 0); -} - -static int imx8mm_clk_enable(struct clk *clk) -{ - return __imx8mm_clk_enable(clk, 1); -} - -static int imx8mm_clk_set_parent(struct clk *clk, struct clk *parent) -{ - struct clk *c, *cp; - int ret; - - debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - ret = clk_get_by_id(parent->id, &cp); - if (ret) - return ret; - - ret = clk_set_parent(c, cp); - c->dev->parent = cp->dev; - - return ret; -} - -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, - .set_parent = imx8mm_clk_set_parent, -}; - static int imx8mm_clk_probe(struct udevice *dev) { void __iomem *base; @@ -420,7 +335,7 @@ U_BOOT_DRIVER(imx8mm_clk) = { .name = "clk_imx8mm", .id = UCLASS_CLK, .of_match = imx8mm_clk_ids, - .ops = &imx8mm_clk_ops, + .ops = &imx8m_clk_ops, .probe = imx8mm_clk_probe, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index c3d60ad057c..08fdcf5d86d 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -14,6 +14,7 @@ #include <dt-bindings/clock/imx8mn-clock.h>
#include "clk.h" +#include "clk-imx8m.h"
static const char *pll_ref_sels[] = { "clock-osc-24m", "dummy", "dummy", "dummy", }; static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", }; @@ -98,92 +99,6 @@ static const char * const imx8mn_usb_phy_sels[] = {"clock-osc-24m", "sys_pll1_10 "sys_pll2_100m", "sys_pll2_200m", "clk_ext2", "clk_ext3", "audio_pll2_out", };
-static ulong imx8mn_clk_get_rate(struct clk *clk) -{ - struct clk *c; - int ret; - - debug("%s(#%lu)\n", __func__, clk->id); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - return clk_get_rate(c); -} - -static ulong imx8mn_clk_set_rate(struct clk *clk, unsigned long rate) -{ - struct clk *c; - int ret; - - debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - return clk_set_rate(c, rate); -} - -static int __imx8mn_clk_enable(struct clk *clk, bool enable) -{ - struct clk *c; - int ret; - - debug("%s(#%lu) en: %d\n", __func__, clk->id, enable); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - if (enable) - ret = clk_enable(c); - else - ret = clk_disable(c); - - return ret; -} - -static int imx8mn_clk_disable(struct clk *clk) -{ - return __imx8mn_clk_enable(clk, 0); -} - -static int imx8mn_clk_enable(struct clk *clk) -{ - return __imx8mn_clk_enable(clk, 1); -} - -static int imx8mn_clk_set_parent(struct clk *clk, struct clk *parent) -{ - struct clk *c, *cp; - int ret; - - debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - ret = clk_get_by_id(parent->id, &cp); - if (ret) - return ret; - - ret = clk_set_parent(c, cp); - c->dev->parent = cp->dev; - - return ret; -} - -static struct clk_ops imx8mn_clk_ops = { - .set_rate = imx8mn_clk_set_rate, - .get_rate = imx8mn_clk_get_rate, - .enable = imx8mn_clk_enable, - .disable = imx8mn_clk_disable, - .set_parent = imx8mn_clk_set_parent, -}; - static int imx8mn_clk_probe(struct udevice *dev) { void __iomem *base; @@ -431,7 +346,7 @@ U_BOOT_DRIVER(imx8mn_clk) = { .name = "clk_imx8mn", .id = UCLASS_CLK, .of_match = imx8mn_clk_ids, - .ops = &imx8mn_clk_ops, + .ops = &imx8m_clk_ops, .probe = imx8mn_clk_probe, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index 5ccb969da3b..00c0fbcbcb2 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -14,6 +14,7 @@ #include <dt-bindings/clock/imx8mp-clock.h>
#include "clk.h" +#include "clk-imx8m.h"
static const char *pll_ref_sels[] = { "clock-osc-24m", "dummy", "dummy", "dummy", }; static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", }; @@ -136,94 +137,6 @@ static const char *imx8mp_enet_phy_ref_sels[] = {"clock-osc-24m", "sys_pll2_50m"
static const char *imx8mp_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
- -static ulong imx8mp_clk_get_rate(struct clk *clk) -{ - struct clk *c; - int ret; - - debug("%s(#%lu)\n", __func__, clk->id); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - return clk_get_rate(c); -} - -static ulong imx8mp_clk_set_rate(struct clk *clk, unsigned long rate) -{ - struct clk *c; - int ret; - - debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - return clk_set_rate(c, rate); -} - -static int __imx8mp_clk_enable(struct clk *clk, bool enable) -{ - struct clk *c; - int ret; - - debug("%s(#%lu) en: %d\n", __func__, clk->id, enable); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - if (enable) - ret = clk_enable(c); - else - ret = clk_disable(c); - - return ret; -} - -static int imx8mp_clk_disable(struct clk *clk) -{ - return __imx8mp_clk_enable(clk, 0); -} - -static int imx8mp_clk_enable(struct clk *clk) -{ - return __imx8mp_clk_enable(clk, 1); -} - -static int imx8mp_clk_set_parent(struct clk *clk, struct clk *parent) -{ - struct clk *c, *cp; - int ret; - - debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - ret = clk_get_by_id(parent->id, &cp); - if (ret) - return ret; - - ret = clk_set_parent(c, cp); - - c->dev->parent = cp->dev; - - return ret; -} - -static struct clk_ops imx8mp_clk_ops = { - .set_rate = imx8mp_clk_set_rate, - .get_rate = imx8mp_clk_get_rate, - .enable = imx8mp_clk_enable, - .disable = imx8mp_clk_disable, - .set_parent = imx8mp_clk_set_parent, -}; - static int imx8mp_clk_probe(struct udevice *dev) { void __iomem *base; @@ -364,7 +277,7 @@ U_BOOT_DRIVER(imx8mp_clk) = { .name = "clk_imx8mp", .id = UCLASS_CLK, .of_match = imx8mp_clk_ids, - .ops = &imx8mp_clk_ops, + .ops = &imx8m_clk_ops, .probe = imx8mp_clk_probe, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index e753613f6c3..c3b685dbaab 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -15,6 +15,7 @@ #include <dt-bindings/clock/imx8mq-clock.h>
#include "clk.h" +#include "clk-imx8m.h"
static const char *pll_ref_sels[] = { "clock-osc-25m", "clock-osc-27m", "clock-phy-27m", "dummy", }; static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; @@ -117,94 +118,6 @@ static const char *pllout_monitor_sels[] = {"clock-osc-25m", "clock-osc-27m", "c "sys_pll2_out_monitor", "sys_pll3_out_monitor", "dummy", "dram_pll_out_monitor", };
-static ulong imx8mq_clk_get_rate(struct clk *clk) -{ - struct clk *c; - int ret; - - debug("%s(#%lu)\n", __func__, clk->id); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - return clk_get_rate(c); -} - -static ulong imx8mq_clk_set_rate(struct clk *clk, unsigned long rate) -{ - struct clk *c; - int ret; - - debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - return clk_set_rate(c, rate); -} - -static int __imx8mq_clk_enable(struct clk *clk, bool enable) -{ - struct clk *c; - int ret; - - debug("%s(#%lu) en: %d\n", __func__, clk->id, enable); - - ret = clk_get_by_id(clk->id, &c); - if (ret) { - debug("%s: clk_get_by_id failed\n", __func__); - return ret; - } - - if (enable) - ret = clk_enable(c); - else - ret = clk_disable(c); - - return ret; -} - -static int imx8mq_clk_disable(struct clk *clk) -{ - return __imx8mq_clk_enable(clk, 0); -} - -static int imx8mq_clk_enable(struct clk *clk) -{ - return __imx8mq_clk_enable(clk, 1); -} - -static int imx8mq_clk_set_parent(struct clk *clk, struct clk *parent) -{ - struct clk *c, *cp; - int ret; - - debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id); - - ret = clk_get_by_id(clk->id, &c); - if (ret) - return ret; - - ret = clk_get_by_id(parent->id, &cp); - if (ret) - return ret; - - ret = clk_set_parent(c, cp); - c->dev->parent = cp->dev; - - return ret; -} - -static struct clk_ops imx8mq_clk_ops = { - .set_rate = imx8mq_clk_set_rate, - .get_rate = imx8mq_clk_get_rate, - .enable = imx8mq_clk_enable, - .disable = imx8mq_clk_disable, - .set_parent = imx8mq_clk_set_parent, -}; - static int imx8mq_clk_probe(struct udevice *dev) { void __iomem *base; @@ -522,7 +435,7 @@ U_BOOT_DRIVER(imx8mq_clk) = { .name = "clk_imx8mq", .id = UCLASS_CLK, .of_match = imx8mq_clk_ids, - .ops = &imx8mq_clk_ops, + .ops = &imx8m_clk_ops, .probe = imx8mq_clk_probe, .flags = DM_FLAG_PRE_RELOC, };

Hi Angus,
On 3/15/22 9:08 AM, Angus Ainslie wrote:
All of the imx8m[nmpq] use the same clk_ops functions so move them to a common file.
Signed-off-by: Angus Ainslie angus@akkea.ca Reviewed-by: Marek Vasut marex@denx.de
drivers/clk/imx/Makefile | 8 +-- drivers/clk/imx/clk-imx8m.c | 108 +++++++++++++++++++++++++++++++++++ drivers/clk/imx/clk-imx8m.h | 12 ++++ drivers/clk/imx/clk-imx8mm.c | 89 +---------------------------- drivers/clk/imx/clk-imx8mn.c | 89 +---------------------------- drivers/clk/imx/clk-imx8mp.c | 91 +---------------------------- drivers/clk/imx/clk-imx8mq.c | 91 +---------------------------- 7 files changed, 132 insertions(+), 356 deletions(-) create mode 100644 drivers/clk/imx/clk-imx8m.c create mode 100644 drivers/clk/imx/clk-imx8m.h
Looks like this is accomplishing the same thing as [1], which also covers at91 and mpfs. Great minds think alike :)
Would it be possible for you to rebase your series on mine?
--Sean
[1] https://patchwork.ozlabs.org/project/uboot/patch/20220320203446.740178-2-sea...
participants (7)
-
Angus Ainslie
-
Angus Ainslie
-
Heiko Thiery
-
Marek Vasut
-
Michael Walle
-
Peng Fan (OSS)
-
Sean Anderson