From: Jesse Taube Date: Tue, 26 Jul 2022 05:43:43 +0000 (-0400) Subject: clk: imx: Add initial support for i.MXRT1170 clock driver X-Git-Url: http://git.dujemihanovic.xyz/?a=commitdiff_plain;h=79f7632e80e35461812015582e38ea2ff8fe2b8a;p=u-boot.git clk: imx: Add initial support for i.MXRT1170 clock driver Add clock driver support for i.MXRT1170. Signed-off-by: Jesse Taube --- diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index 04d252a1e0..abcb19ce6d 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -124,3 +124,19 @@ config CLK_IMXRT1050 select CLK_COMPOSITE_CCF help This enables support clock driver for i.MXRT1050 platforms. + +config SPL_CLK_IMXRT1170 + bool "SPL clock support for i.MXRT1170" + depends on ARCH_IMXRT && SPL + select SPL_CLK + select SPL_CLK_CCF + help + This enables SPL DM/DTS support for clock driver in i.MXRT1170. + +config CLK_IMXRT1170 + bool "Clock support for i.MXRT1170" + depends on ARCH_IMXRT + select CLK + select CLK_CCF + help + This enables support clock driver for i.MXRT1170 platforms. diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index c5766901f2..b9c197f952 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -21,3 +21,4 @@ obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MQ) += clk-imx8mq.o clk-pll14xx.o \ obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1020) += clk-imxrt1020.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1050) += clk-imxrt1050.o +obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1170) += clk-imxrt1170.o diff --git a/drivers/clk/imx/clk-imxrt1170.c b/drivers/clk/imx/clk-imxrt1170.c new file mode 100644 index 0000000000..077dd1bf02 --- /dev/null +++ b/drivers/clk/imx/clk-imxrt1170.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 + * Author(s): Jesse Taube + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +static ulong imxrt1170_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 imxrt1170_clk_set_rate(struct clk *clk, ulong 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 __imxrt1170_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 imxrt1170_clk_disable(struct clk *clk) +{ + return __imxrt1170_clk_enable(clk, 0); +} + +static int imxrt1170_clk_enable(struct clk *clk) +{ + return __imxrt1170_clk_enable(clk, 1); +} + +static int imxrt1170_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; + + return clk_set_parent(c, cp); +} + +static struct clk_ops imxrt1170_clk_ops = { + .set_rate = imxrt1170_clk_set_rate, + .get_rate = imxrt1170_clk_get_rate, + .enable = imxrt1170_clk_enable, + .disable = imxrt1170_clk_disable, + .set_parent = imxrt1170_clk_set_parent, +}; + +static const char * const lpuart1_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M", +"pll3_div2", "pll1_div5", "pll2_sys", "pll2_pfd3"}; +static const char * const gpt1_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M", +"pll3_div2", "pll1_div5", "pll3_pfd2", "pll3_pfd3"}; +static const char * const usdhc1_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M", +"pll2_pfd2", "pll2_pfd0", "pll1_div5", "pll_arm"}; +static const char * const semc_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M", +"pll1_div5", "pll2_sys", "pll2_pfd2", "pll3_pfd0"}; + +static int imxrt1170_clk_probe(struct udevice *dev) +{ + void *base; + + /* Anatop clocks */ + base = (void *)ofnode_get_addr(ofnode_by_compatible(ofnode_null(), "fsl,imxrt-anatop")); + + + + clk_dm(IMXRT1170_CLK_RCOSC_48M, + imx_clk_fixed_factor("rcosc48M", "rcosc16M", 3, 1)); + clk_dm(IMXRT1170_CLK_RCOSC_400M, + imx_clk_fixed_factor("rcosc400M", "rcosc16M", 25, 1)); + clk_dm(IMXRT1170_CLK_RCOSC_48M_DIV2, + imx_clk_fixed_factor("rcosc48M_div2", "rcosc48M", 1, 2)); + + + clk_dm(IMXRT1170_CLK_PLL_ARM, + imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm", "osc", + base + 0x200, 0xff)); + clk_dm(IMXRT1170_CLK_PLL3, + imx_clk_pllv3(IMX_PLLV3_GENERICV2, "pll3_sys", "osc", + base + 0x210, 1)); + clk_dm(IMXRT1170_CLK_PLL2, + imx_clk_pllv3(IMX_PLLV3_GENERICV2, "pll2_sys", "osc", + base + 0x240, 1)); + + clk_dm(IMXRT1170_CLK_PLL3_PFD0, + imx_clk_pfd("pll3_pfd0", "pll3_sys", base + 0x230, 0)); + clk_dm(IMXRT1170_CLK_PLL3_PFD1, + imx_clk_pfd("pll3_pfd1", "pll3_sys", base + 0x230, 1)); + clk_dm(IMXRT1170_CLK_PLL3_PFD2, + imx_clk_pfd("pll3_pfd2", "pll3_sys", base + 0x230, 2)); + clk_dm(IMXRT1170_CLK_PLL3_PFD3, + imx_clk_pfd("pll3_pfd3", "pll3_sys", base + 0x230, 3)); + + clk_dm(IMXRT1170_CLK_PLL2_PFD0, + imx_clk_pfd("pll2_pfd0", "pll2_sys", base + 0x270, 0)); + clk_dm(IMXRT1170_CLK_PLL2_PFD1, + imx_clk_pfd("pll2_pfd1", "pll2_sys", base + 0x270, 1)); + clk_dm(IMXRT1170_CLK_PLL2_PFD2, + imx_clk_pfd("pll2_pfd2", "pll2_sys", base + 0x270, 2)); + clk_dm(IMXRT1170_CLK_PLL2_PFD3, + imx_clk_pfd("pll2_pfd3", "pll2_sys", base + 0x270, 3)); + + clk_dm(IMXRT1170_CLK_PLL3_DIV2, + imx_clk_fixed_factor("pll3_div2", "pll3_sys", 1, 2)); + + /* CCM clocks */ + base = dev_read_addr_ptr(dev); + if (base == (void *)FDT_ADDR_T_NONE) + return -EINVAL; + + clk_dm(IMXRT1170_CLK_LPUART1_SEL, + imx_clk_mux("lpuart1_sel", base + (25 * 0x80), 8, 3, + lpuart1_sels, ARRAY_SIZE(lpuart1_sels))); + clk_dm(IMXRT1170_CLK_LPUART1, + imx_clk_divider("lpuart1", "lpuart1_sel", + base + (25 * 0x80), 0, 8)); + + clk_dm(IMXRT1170_CLK_USDHC1_SEL, + imx_clk_mux("usdhc1_sel", base + (58 * 0x80), 8, 3, + usdhc1_sels, ARRAY_SIZE(usdhc1_sels))); + clk_dm(IMXRT1170_CLK_USDHC1, + imx_clk_divider("usdhc1", "usdhc1_sel", + base + (58 * 0x80), 0, 8)); + + clk_dm(IMXRT1170_CLK_GPT1_SEL, + imx_clk_mux("gpt1_sel", base + (14 * 0x80), 8, 3, + gpt1_sels, ARRAY_SIZE(gpt1_sels))); + clk_dm(IMXRT1170_CLK_GPT1, + imx_clk_divider("gpt1", "gpt1_sel", + base + (14 * 0x80), 0, 8)); + + clk_dm(IMXRT1170_CLK_SEMC_SEL, + imx_clk_mux("semc_sel", base + (4 * 0x80), 8, 3, + semc_sels, ARRAY_SIZE(semc_sels))); + clk_dm(IMXRT1170_CLK_SEMC, + imx_clk_divider("semc", "semc_sel", + base + (4 * 0x80), 0, 8)); + struct clk *clk, *clk1; + + clk_get_by_id(IMXRT1170_CLK_PLL2_PFD2, &clk); + + clk_get_by_id(IMXRT1170_CLK_SEMC_SEL, &clk1); + clk_enable(clk1); + clk_set_parent(clk1, clk); + + clk_get_by_id(IMXRT1170_CLK_SEMC, &clk); + clk_enable(clk); + clk_set_rate(clk, 132000000UL); + + clk_get_by_id(IMXRT1170_CLK_GPT1, &clk); + clk_enable(clk); + clk_set_rate(clk, 32000000UL); + + return 0; +} + +static const struct udevice_id imxrt1170_clk_ids[] = { + { .compatible = "fsl,imxrt1170-ccm" }, + { }, +}; + +U_BOOT_DRIVER(imxrt1170_clk) = { + .name = "clk_imxrt1170", + .id = UCLASS_CLK, + .of_match = imxrt1170_clk_ids, + .ops = &imxrt1170_clk_ops, + .probe = imxrt1170_clk_probe, + .flags = DM_FLAG_PRE_RELOC, +};