From 277525049252a516f9c74a00b71e7e98eb977598 Mon Sep 17 00:00:00 2001 From: Hiago De Franco Date: Mon, 4 Sep 2023 10:24:37 -0300 Subject: verdin-imx8mp: drop unused tdx easy installer ifdef Drop unused code related to CONFIG_TDX_EASY_INSTALLER, that existed only on toradex downstream branch. Signed-off-by: Hiago De Franco Reviewed-by: Fabio Estevam --- include/configs/verdin-imx8mp.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/configs/verdin-imx8mp.h b/include/configs/verdin-imx8mp.h index 942081ab84d..d980bd66ae5 100644 --- a/include/configs/verdin-imx8mp.h +++ b/include/configs/verdin-imx8mp.h @@ -36,20 +36,14 @@ func(DHCP, dhcp, na) #include -#if defined(CONFIG_TDX_EASY_INSTALLER) -# define BOOT_SCRIPT "boot-tezi.scr" -#else -# define BOOT_SCRIPT "boot.scr" -#endif - /* Initial environment variables */ #define CFG_EXTRA_ENV_SETTINGS \ BOOTENV \ MEM_LAYOUT_ENV_SETTINGS \ "bootcmd_mfg=fastboot 0\0" \ "boot_file=Image\0" \ - "boot_scripts=" BOOT_SCRIPT "\0" \ - "boot_script_dhcp=" BOOT_SCRIPT "\0" \ + "boot_scripts=boot.scr\0" \ + "boot_script_dhcp=boot.scr\0" \ "console=ttymxc2\0" \ "fdt_board=dev\0" \ "initrd_addr=0x43800000\0" \ -- cgit v1.3.1 From 7b9c99b2d928881c89bb2abe6eaf4b0228ba7ad9 Mon Sep 17 00:00:00 2001 From: Joao Paulo Goncalves Date: Wed, 4 Oct 2023 16:13:58 -0300 Subject: toradex: verdin-imx8mm/imx8mp: Remove bootcmd_mfg The bootcmd_mfg env variable is legacy from IMX downstream u-boot branch and is not needed on mainline. Signed-off-by: Joao Paulo Goncalves Signed-off-by: Francesco Dolcini Acked-by: Marcel Ziswiler Reviewed-by: Fabio Estevam --- include/configs/verdin-imx8mm.h | 1 - include/configs/verdin-imx8mp.h | 1 - 2 files changed, 2 deletions(-) (limited to 'include') diff --git a/include/configs/verdin-imx8mm.h b/include/configs/verdin-imx8mm.h index 8cb1f1aff35..8072d5d503f 100644 --- a/include/configs/verdin-imx8mm.h +++ b/include/configs/verdin-imx8mm.h @@ -37,7 +37,6 @@ #define CFG_EXTRA_ENV_SETTINGS \ BOOTENV \ MEM_LAYOUT_ENV_SETTINGS \ - "bootcmd_mfg=fastboot 0\0" \ "boot_file=Image\0" \ "boot_script_dhcp=boot.scr\0" \ "console=ttymxc0\0" \ diff --git a/include/configs/verdin-imx8mp.h b/include/configs/verdin-imx8mp.h index d980bd66ae5..256bab089ff 100644 --- a/include/configs/verdin-imx8mp.h +++ b/include/configs/verdin-imx8mp.h @@ -40,7 +40,6 @@ #define CFG_EXTRA_ENV_SETTINGS \ BOOTENV \ MEM_LAYOUT_ENV_SETTINGS \ - "bootcmd_mfg=fastboot 0\0" \ "boot_file=Image\0" \ "boot_scripts=boot.scr\0" \ "boot_script_dhcp=boot.scr\0" \ -- cgit v1.3.1 From 9c153e46661b70dd96702d68653ba94dc938de96 Mon Sep 17 00:00:00 2001 From: Sébastien Szymanski Date: Tue, 25 Jul 2023 10:08:53 +0200 Subject: clk: imx: add i.MX93 CCF driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add i.MX93 CCF driver support. Modifed from Linux Kernel v6.5-rc2 and adapted for U-Boot. Signed-off-by: Sébastien Szymanski --- drivers/clk/imx/Kconfig | 18 ++ drivers/clk/imx/Makefile | 2 + drivers/clk/imx/clk-composite-93.c | 142 ++++++++++++ drivers/clk/imx/clk-fracn-gppll.c | 382 ++++++++++++++++++++++++++++++++ drivers/clk/imx/clk-gate-93.c | 148 +++++++++++++ drivers/clk/imx/clk-imx93.c | 343 ++++++++++++++++++++++++++++ drivers/clk/imx/clk.h | 42 ++++ include/dt-bindings/clock/imx93-clock.h | 6 +- 8 files changed, 1082 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/imx/clk-composite-93.c create mode 100644 drivers/clk/imx/clk-fracn-gppll.c create mode 100644 drivers/clk/imx/clk-gate-93.c create mode 100644 drivers/clk/imx/clk-imx93.c (limited to 'include') diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index abcb19ce6d5..56d893e0579 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -89,6 +89,24 @@ config CLK_IMX8MQ help This enables support clock driver for i.MX8MQ platforms. +config SPL_CLK_IMX93 + bool "SPL clock support for i.MX93" + depends on ARCH_IMX9 && SPL + select SPL_CLK + select SPL_CLK_CCF + select SPL_CLK_COMPOSITE_CCF + help + This enables SPL DM/DTS support for clock driver in i.MX93 + +config CLK_IMX93 + bool "Clock support for i.MX93" + depends on ARCH_IMX9 + select CLK + select CLK_CCF + select CLK_COMPOSITE_CCF + help + This enables support for clock driver in i.MX93 + 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 b9c197f952e..6d4bcd35714 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -18,6 +18,8 @@ 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_IMX93) += clk-imx93.o clk-fracn-gppll.o \ + clk-gate-93.o clk-composite-93.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-composite-93.c b/drivers/clk/imx/clk-composite-93.c new file mode 100644 index 00000000000..6d71c0c03ff --- /dev/null +++ b/drivers/clk/imx/clk-composite-93.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 NXP + * + * Peng Fan + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "clk.h" +#include + +#define TIMEOUT_US 500U + +#define CCM_DIV_SHIFT 0 +#define CCM_DIV_WIDTH 8 +#define CCM_MUX_SHIFT 8 +#define CCM_MUX_MASK 3 +#define CCM_OFF_SHIFT 24 +#define CCM_BUSY_SHIFT 28 + +#define STAT_OFFSET 0x4 +#define AUTHEN_OFFSET 0x30 +#define TZ_NS_SHIFT 9 +#define TZ_NS_MASK BIT(9) + +#define WHITE_LIST_SHIFT 16 + +#define readl_poll_timeout_atomic readl_poll_timeout + +static int imx93_clk_composite_wait_ready(struct clk *clk, void __iomem *reg) +{ + int ret; + u32 val; + + ret = readl_poll_timeout_atomic(reg + STAT_OFFSET, val, !(val & BIT(CCM_BUSY_SHIFT)), + TIMEOUT_US); + if (ret) + pr_err("Slice[%s] busy timeout\n", "TODO"); + + return ret; +} + +static void imx93_clk_composite_gate_endisable(struct clk *clk, int enable) +{ + struct clk_gate *gate = to_clk_gate(clk); + u32 reg; + + reg = readl(gate->reg); + + if (enable) + reg &= ~BIT(gate->bit_idx); + else + reg |= BIT(gate->bit_idx); + + writel(reg, gate->reg); + + imx93_clk_composite_wait_ready(clk, gate->reg); +} + +static int imx93_clk_composite_gate_enable(struct clk *clk) +{ + imx93_clk_composite_gate_endisable(clk, 1); + + return 0; +} + +static int imx93_clk_composite_gate_disable(struct clk *clk) +{ + imx93_clk_composite_gate_endisable(clk, 0); + + return 0; +} + +static const struct clk_ops imx93_clk_composite_gate_ops = { + .enable = imx93_clk_composite_gate_enable, + .disable = imx93_clk_composite_gate_disable, +}; + +struct clk *imx93_clk_composite_flags(const char *name, + const char * const *parent_names, + int num_parents, void __iomem *reg, u32 domain_id, + unsigned long flags) +{ + struct clk *clk = ERR_PTR(-ENOMEM); + struct clk_divider *div = NULL; + struct clk_gate *gate = NULL; + struct clk_mux *mux = NULL; + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + goto fail; + + mux->reg = reg; + mux->shift = CCM_MUX_SHIFT; + mux->mask = CCM_MUX_MASK; + mux->num_parents = num_parents; + mux->parent_names = parent_names; + mux->flags = flags; + + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) + goto fail; + + div->reg = reg; + div->shift = CCM_DIV_SHIFT; + div->width = CCM_DIV_WIDTH; + div->flags = CLK_DIVIDER_ROUND_CLOSEST | flags; + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + goto fail; + + gate->reg = reg; + gate->bit_idx = CCM_OFF_SHIFT; + gate->flags = flags; + + clk = clk_register_composite(NULL, name, + parent_names, num_parents, + &mux->clk, &clk_mux_ops, + &div->clk, &clk_divider_ops, + &gate->clk, &imx93_clk_composite_gate_ops, + flags); + + if (IS_ERR(clk)) + goto fail; + + return clk; + +fail: + kfree(gate); + kfree(div); + kfree(mux); + return ERR_CAST(clk); +} diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c new file mode 100644 index 00000000000..9228f279e27 --- /dev/null +++ b/drivers/clk/imx/clk-fracn-gppll.c @@ -0,0 +1,382 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2021 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +#define UBOOT_DM_CLK_IMX_FRACN_GPPLL "imx_clk_fracn_gppll" + +#define PLL_CTRL 0x0 +#define HW_CTRL_SEL BIT(16) +#define CLKMUX_BYPASS BIT(2) +#define CLKMUX_EN BIT(1) +#define POWERUP_MASK BIT(0) + +#define PLL_ANA_PRG 0x10 +#define PLL_SPREAD_SPECTRUM 0x30 + +#define PLL_NUMERATOR 0x40 +#define PLL_MFN_MASK GENMASK(31, 2) + +#define PLL_DENOMINATOR 0x50 +#define PLL_MFD_MASK GENMASK(29, 0) + +#define PLL_DIV 0x60 +#define PLL_MFI_MASK GENMASK(24, 16) +#define PLL_RDIV_MASK GENMASK(15, 13) +#define PLL_ODIV_MASK GENMASK(7, 0) + +#define PLL_DFS_CTRL(x) (0x70 + (x) * 0x10) + +#define PLL_STATUS 0xF0 +#define LOCK_STATUS BIT(0) + +#define DFS_STATUS 0xF4 + +#define LOCK_TIMEOUT_US 200 + +#define PLL_FRACN_GP(_rate, _mfi, _mfn, _mfd, _rdiv, _odiv) \ + { \ + .rate = (_rate), \ + .mfi = (_mfi), \ + .mfn = (_mfn), \ + .mfd = (_mfd), \ + .rdiv = (_rdiv), \ + .odiv = (_odiv), \ + } + +#define PLL_FRACN_GP_INTEGER(_rate, _mfi, _rdiv, _odiv) \ + { \ + .rate = (_rate), \ + .mfi = (_mfi), \ + .mfn = 0, \ + .mfd = 0, \ + .rdiv = (_rdiv), \ + .odiv = (_odiv), \ + } + +struct clk_fracn_gppll { + struct clk clk; + void __iomem *base; + const struct imx_fracn_gppll_rate_table *rate_table; + int rate_count; + u32 flags; +}; + +/* + * Fvco = (Fref / rdiv) * (MFI + MFN / MFD) + * Fout = Fvco / odiv + * The (Fref / rdiv) should be in range 20MHz to 40MHz + * The Fvco should be in range 2.5Ghz to 5Ghz + */ +static const struct imx_fracn_gppll_rate_table fracn_tbl[] = { + PLL_FRACN_GP(650000000U, 162, 50, 100, 0, 6), + PLL_FRACN_GP(594000000U, 198, 0, 1, 0, 8), + PLL_FRACN_GP(560000000U, 140, 0, 1, 0, 6), + PLL_FRACN_GP(498000000U, 166, 0, 1, 0, 8), + PLL_FRACN_GP(484000000U, 121, 0, 1, 0, 6), + PLL_FRACN_GP(445333333U, 167, 0, 1, 0, 9), + PLL_FRACN_GP(400000000U, 200, 0, 1, 0, 12), + PLL_FRACN_GP(393216000U, 163, 84, 100, 0, 10), + PLL_FRACN_GP(300000000U, 150, 0, 1, 0, 12) +}; + +struct imx_fracn_gppll_clk imx_fracn_gppll = { + .rate_table = fracn_tbl, + .rate_count = ARRAY_SIZE(fracn_tbl), +}; + +/* + * Fvco = (Fref / rdiv) * MFI + * Fout = Fvco / odiv + * The (Fref / rdiv) should be in range 20MHz to 40MHz + * The Fvco should be in range 2.5Ghz to 5Ghz + */ +static const struct imx_fracn_gppll_rate_table int_tbl[] = { + PLL_FRACN_GP_INTEGER(1700000000U, 141, 1, 2), + PLL_FRACN_GP_INTEGER(1400000000U, 175, 1, 3), + PLL_FRACN_GP_INTEGER(900000000U, 150, 1, 4), +}; + +struct imx_fracn_gppll_clk imx_fracn_gppll_integer = { + .rate_table = int_tbl, + .rate_count = ARRAY_SIZE(int_tbl), +}; + +#define to_clk_fracn_gppll(_clk) container_of(_clk, struct clk_fracn_gppll, clk) + +static const struct imx_fracn_gppll_rate_table * +imx_get_pll_settings(struct clk_fracn_gppll *pll, unsigned long rate) +{ + const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table; + int i; + + for (i = 0; i < pll->rate_count; i++) + if (rate == rate_table[i].rate) + return &rate_table[i]; + + return NULL; +} + +static unsigned long clk_fracn_gppll_round_rate(struct clk *clk, unsigned long rate) +{ + struct clk_fracn_gppll *pll = to_clk_fracn_gppll(clk); + const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table; + int i; + + /* Assuming rate_table is in descending order */ + for (i = 0; i < pll->rate_count; i++) + if (rate >= rate_table[i].rate) + return rate_table[i].rate; + + /* return minimum supported value */ + return rate_table[pll->rate_count - 1].rate; +} + +static unsigned long clk_fracn_gppll_recalc_rate(struct clk *clk) +{ + struct clk_fracn_gppll *pll = to_clk_fracn_gppll(clk); + const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table; + u32 pll_numerator, pll_denominator, pll_div; + u32 mfi, mfn, mfd, rdiv, odiv; + u64 fvco = clk_get_parent_rate(clk); + long rate = 0; + int i; + + pll_numerator = readl_relaxed(pll->base + PLL_NUMERATOR); + mfn = FIELD_GET(PLL_MFN_MASK, pll_numerator); + + pll_denominator = readl_relaxed(pll->base + PLL_DENOMINATOR); + mfd = FIELD_GET(PLL_MFD_MASK, pll_denominator); + + pll_div = readl_relaxed(pll->base + PLL_DIV); + mfi = FIELD_GET(PLL_MFI_MASK, pll_div); + + rdiv = FIELD_GET(PLL_RDIV_MASK, pll_div); + odiv = FIELD_GET(PLL_ODIV_MASK, pll_div); + + /* + * Sometimes, the recalculated rate has deviation due to + * the frac part. So find the accurate pll rate from the table + * first, if no match rate in the table, use the rate calculated + * from the equation below. + */ + for (i = 0; i < pll->rate_count; i++) { + if (rate_table[i].mfn == mfn && rate_table[i].mfi == mfi && + rate_table[i].mfd == mfd && rate_table[i].rdiv == rdiv && + rate_table[i].odiv == odiv) + rate = rate_table[i].rate; + } + + if (rate) + return (unsigned long)rate; + + if (!rdiv) + rdiv = rdiv + 1; + + switch (odiv) { + case 0: + odiv = 2; + break; + case 1: + odiv = 3; + break; + default: + break; + } + + if (pll->flags & CLK_FRACN_GPPLL_INTEGER) { + /* Fvco = (Fref / rdiv) * MFI */ + fvco = fvco * mfi; + do_div(fvco, rdiv * odiv); + } else { + /* Fvco = (Fref / rdiv) * (MFI + MFN / MFD) */ + fvco = fvco * mfi * mfd + fvco * mfn; + do_div(fvco, mfd * rdiv * odiv); + } + + return (unsigned long)fvco; +} + +static int clk_fracn_gppll_wait_lock(struct clk_fracn_gppll *pll) +{ + u32 val; + + return readl_poll_timeout(pll->base + PLL_STATUS, val, + val & LOCK_STATUS, LOCK_TIMEOUT_US); +} + +static ulong clk_fracn_gppll_set_rate(struct clk *clk, unsigned long drate) +{ + struct clk_fracn_gppll *pll = to_clk_fracn_gppll(clk); + const struct imx_fracn_gppll_rate_table *rate; + u32 tmp, pll_div, ana_mfn; + int ret; + + rate = imx_get_pll_settings(pll, drate); + + /* Hardware control select disable. PLL is control by register */ + tmp = readl_relaxed(pll->base + PLL_CTRL); + tmp &= ~HW_CTRL_SEL; + writel_relaxed(tmp, pll->base + PLL_CTRL); + + /* Disable output */ + tmp = readl_relaxed(pll->base + PLL_CTRL); + tmp &= ~CLKMUX_EN; + writel_relaxed(tmp, pll->base + PLL_CTRL); + + /* Power Down */ + tmp &= ~POWERUP_MASK; + writel_relaxed(tmp, pll->base + PLL_CTRL); + + /* Disable BYPASS */ + tmp &= ~CLKMUX_BYPASS; + writel_relaxed(tmp, pll->base + PLL_CTRL); + + pll_div = FIELD_PREP(PLL_RDIV_MASK, rate->rdiv) | rate->odiv | + FIELD_PREP(PLL_MFI_MASK, rate->mfi); + writel_relaxed(pll_div, pll->base + PLL_DIV); + if (pll->flags & CLK_FRACN_GPPLL_FRACN) { + writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR); + writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR); + } + + /* Wait for 5us according to fracn mode pll doc */ + udelay(5); + + /* Enable Powerup */ + tmp |= POWERUP_MASK; + writel_relaxed(tmp, pll->base + PLL_CTRL); + + /* Wait Lock */ + ret = clk_fracn_gppll_wait_lock(pll); + if (ret) + return ret; + + /* Enable output */ + tmp |= CLKMUX_EN; + writel_relaxed(tmp, pll->base + PLL_CTRL); + + ana_mfn = readl_relaxed(pll->base + PLL_STATUS); + ana_mfn = FIELD_GET(PLL_MFN_MASK, ana_mfn); + + WARN(ana_mfn != rate->mfn, "ana_mfn != rate->mfn\n"); + + return 0; +} + +static int clk_fracn_gppll_prepare(struct clk *clk) +{ + struct clk_fracn_gppll *pll = to_clk_fracn_gppll(clk); + u32 val; + int ret; + + val = readl_relaxed(pll->base + PLL_CTRL); + if (val & POWERUP_MASK) + return 0; + + val |= CLKMUX_BYPASS; + writel_relaxed(val, pll->base + PLL_CTRL); + + val |= POWERUP_MASK; + writel_relaxed(val, pll->base + PLL_CTRL); + + val |= CLKMUX_EN; + writel_relaxed(val, pll->base + PLL_CTRL); + + ret = clk_fracn_gppll_wait_lock(pll); + if (ret) + return ret; + + val &= ~CLKMUX_BYPASS; + writel_relaxed(val, pll->base + PLL_CTRL); + + return 0; +} + +static int clk_fracn_gppll_unprepare(struct clk *clk) +{ + struct clk_fracn_gppll *pll = to_clk_fracn_gppll(dev_get_clk_ptr(clk->dev)); + u32 val; + + val = readl_relaxed(pll->base + PLL_CTRL); + val &= ~POWERUP_MASK; + writel_relaxed(val, pll->base + PLL_CTRL); + + return 0; +} + +static const struct clk_ops clk_fracn_gppll_ops = { + .enable = clk_fracn_gppll_prepare, + .disable = clk_fracn_gppll_unprepare, + .get_rate = clk_fracn_gppll_recalc_rate, + .set_rate = clk_fracn_gppll_set_rate, + .round_rate = clk_fracn_gppll_round_rate, +}; + +static struct clk *_imx_clk_fracn_gppll(const char *name, const char *parent_name, + void __iomem *base, + const struct imx_fracn_gppll_clk *pll_clk, + u32 pll_flags) +{ + struct clk_fracn_gppll *pll; + struct clk *clk; + int ret; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + pll->base = base; + pll->rate_table = pll_clk->rate_table; + pll->rate_count = pll_clk->rate_count; + pll->flags = pll_flags; + + clk = &pll->clk; + + ret = clk_register(clk, UBOOT_DM_CLK_IMX_FRACN_GPPLL, + name, parent_name); + if (ret) { + pr_err("%s: failed to register pll %s %d\n", __func__, name, ret); + kfree(pll); + return ERR_PTR(ret); + } + + return clk; +} + +struct clk *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base, + const struct imx_fracn_gppll_clk *pll_clk) +{ + return _imx_clk_fracn_gppll(name, parent_name, base, pll_clk, CLK_FRACN_GPPLL_FRACN); +} + +struct clk *imx_clk_fracn_gppll_integer(const char *name, const char *parent_name, + void __iomem *base, + const struct imx_fracn_gppll_clk *pll_clk) +{ + return _imx_clk_fracn_gppll(name, parent_name, base, pll_clk, CLK_FRACN_GPPLL_INTEGER); +} + +U_BOOT_DRIVER(clk_fracn_gppll) = { + .name = UBOOT_DM_CLK_IMX_FRACN_GPPLL, + .id = UCLASS_CLK, + .ops = &clk_fracn_gppll_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/imx/clk-gate-93.c b/drivers/clk/imx/clk-gate-93.c new file mode 100644 index 00000000000..bc857413713 --- /dev/null +++ b/drivers/clk/imx/clk-gate-93.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2022 NXP + * + * Peng Fan + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "clk.h" +#include + +#define UBOOT_DM_CLK_IMX_GATE93 "imx_clk_gate93" + +#define DIRECT_OFFSET 0x0 + +/* + * 0b000 - LPCG will be OFF in any CPU mode. + * 0b100 - LPCG will be ON in any CPU mode. + */ +#define LPM_SETTING_OFF 0x0 +#define LPM_SETTING_ON 0x4 + +#define LPM_CUR_OFFSET 0x1c + +#define AUTHEN_OFFSET 0x30 +#define CPULPM_EN BIT(2) +#define TZ_NS_SHIFT 9 +#define TZ_NS_MASK BIT(9) + +#define WHITE_LIST_SHIFT 16 + +struct imx93_clk_gate { + struct clk clk; + void __iomem *reg; + u32 bit_idx; + u32 val; + u32 mask; + unsigned int *share_count; +}; + +#define to_imx93_clk_gate(_clk) container_of(_clk, struct imx93_clk_gate, clk) + +static void imx93_clk_gate_do_hardware(struct clk *clk, bool enable) +{ + struct imx93_clk_gate *gate = to_imx93_clk_gate(clk); + u32 val; + + val = readl(gate->reg + AUTHEN_OFFSET); + if (val & CPULPM_EN) { + val = enable ? LPM_SETTING_ON : LPM_SETTING_OFF; + writel(val, gate->reg + LPM_CUR_OFFSET); + } else { + val = readl(gate->reg + DIRECT_OFFSET); + val &= ~(gate->mask << gate->bit_idx); + if (enable) + val |= (gate->val & gate->mask) << gate->bit_idx; + writel(val, gate->reg + DIRECT_OFFSET); + } +} + +static int imx93_clk_gate_enable(struct clk *clk) +{ + struct imx93_clk_gate *gate = to_imx93_clk_gate(clk); + + if (gate->share_count && (*gate->share_count)++ > 0) + return 0; + + imx93_clk_gate_do_hardware(clk, true); + + return 0; +} + +static int imx93_clk_gate_disable(struct clk *clk) +{ + struct imx93_clk_gate *gate = to_imx93_clk_gate(clk); + + if (gate->share_count) { + if (WARN_ON(*gate->share_count == 0)) + return 0; + else if (--(*gate->share_count) > 0) + return 0; + } + + imx93_clk_gate_do_hardware(clk, false); + + return 0; +} + +static ulong imx93_clk_set_rate(struct clk *clk, ulong rate) +{ + struct clk *parent = clk_get_parent(clk); + + if (parent) + return clk_set_rate(parent, rate); + + return -ENODEV; +} + +static const struct clk_ops imx93_clk_gate_ops = { + .enable = imx93_clk_gate_enable, + .disable = imx93_clk_gate_disable, + .get_rate = clk_generic_get_rate, + .set_rate = imx93_clk_set_rate, +}; + +struct clk *imx93_clk_gate(struct device *dev, const char *name, const char *parent_name, + unsigned long flags, void __iomem *reg, u32 bit_idx, u32 val, + u32 mask, u32 domain_id, unsigned int *share_count) +{ + struct imx93_clk_gate *gate; + struct clk *clk; + int ret; + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + gate->reg = reg; + gate->bit_idx = bit_idx; + gate->val = val; + gate->mask = mask; + gate->share_count = share_count; + + clk = &gate->clk; + + ret = clk_register(clk, UBOOT_DM_CLK_IMX_GATE93, name, parent_name); + if (ret) { + kfree(gate); + return ERR_PTR(ret); + } + + return clk; +} + +U_BOOT_DRIVER(clk_gate93) = { + .name = UBOOT_DM_CLK_IMX_GATE93, + .id = UCLASS_CLK, + .ops = &imx93_clk_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c new file mode 100644 index 00000000000..ce10d795316 --- /dev/null +++ b/drivers/clk/imx/clk-imx93.c @@ -0,0 +1,343 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2021 NXP. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +enum clk_sel { + LOW_SPEED_IO_SEL, + NON_IO_SEL, + FAST_SEL, + AUDIO_SEL, + VIDEO_SEL, + TPM_SEL, + CKO1_SEL, + CKO2_SEL, + MISC_SEL, + MAX_SEL +}; + +static u32 share_count_sai1; +static u32 share_count_sai2; +static u32 share_count_sai3; +static u32 share_count_mub; + +static const char * const a55_core_sels[] = {"a55_alt", "arm_pll"}; +static const char *parent_names[MAX_SEL][4] = { + {"clock-osc-24m", "sys_pll_pfd0_div2", "sys_pll_pfd1_div2", "video_pll"}, + {"clock-osc-24m", "sys_pll_pfd0_div2", "sys_pll_pfd1_div2", "sys_pll_pfd2_div2"}, + {"clock-osc-24m", "sys_pll_pfd0", "sys_pll_pfd1", "sys_pll_pfd2"}, + {"clock-osc-24m", "audio_pll", "video_pll", "clk_ext1"}, + {"clock-osc-24m", "audio_pll", "video_pll", "sys_pll_pfd0"}, + {"clock-osc-24m", "sys_pll_pfd0", "audio_pll", "clk_ext1"}, + {"clock-osc-24m", "sys_pll_pfd0", "sys_pll_pfd1", "audio_pll"}, + {"clock-osc-24m", "sys_pll_pfd0", "sys_pll_pfd1", "video_pll"}, + {"clock-osc-24m", "audio_pll", "video_pll", "sys_pll_pfd2"}, +}; + +static const struct imx93_clk_root { + u32 clk; + char *name; + u32 off; + enum clk_sel sel; + unsigned long flags; +} root_array[] = { + /* a55/m33/bus critical clk for system run */ + { IMX93_CLK_A55_PERIPH, "a55_periph_root", 0x0000, FAST_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_A55_MTR_BUS, "a55_mtr_bus_root", 0x0080, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_A55, "a55_alt_root", 0x0100, FAST_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_M33, "m33_root", 0x0180, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_BUS_WAKEUP, "bus_wakeup_root", 0x0280, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_BUS_AON, "bus_aon_root", 0x0300, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_WAKEUP_AXI, "wakeup_axi_root", 0x0380, FAST_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_SWO_TRACE, "swo_trace_root", 0x0400, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_M33_SYSTICK, "m33_systick_root", 0x0480, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_FLEXIO1, "flexio1_root", 0x0500, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_FLEXIO2, "flexio2_root", 0x0580, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPTMR1, "lptmr1_root", 0x0700, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPTMR2, "lptmr2_root", 0x0780, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_TPM2, "tpm2_root", 0x0880, TPM_SEL, }, + { IMX93_CLK_TPM4, "tpm4_root", 0x0980, TPM_SEL, }, + { IMX93_CLK_TPM5, "tpm5_root", 0x0a00, TPM_SEL, }, + { IMX93_CLK_TPM6, "tpm6_root", 0x0a80, TPM_SEL, }, + { IMX93_CLK_FLEXSPI1, "flexspi1_root", 0x0b00, FAST_SEL, }, + { IMX93_CLK_CAN1, "can1_root", 0x0b80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_CAN2, "can2_root", 0x0c00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART1, "lpuart1_root", 0x0c80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART2, "lpuart2_root", 0x0d00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART3, "lpuart3_root", 0x0d80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART4, "lpuart4_root", 0x0e00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART5, "lpuart5_root", 0x0e80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART6, "lpuart6_root", 0x0f00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART7, "lpuart7_root", 0x0f80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART8, "lpuart8_root", 0x1000, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C1, "lpi2c1_root", 0x1080, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C2, "lpi2c2_root", 0x1100, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C3, "lpi2c3_root", 0x1180, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C4, "lpi2c4_root", 0x1200, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C5, "lpi2c5_root", 0x1280, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C6, "lpi2c6_root", 0x1300, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C7, "lpi2c7_root", 0x1380, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C8, "lpi2c8_root", 0x1400, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI1, "lpspi1_root", 0x1480, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI2, "lpspi2_root", 0x1500, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI3, "lpspi3_root", 0x1580, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI4, "lpspi4_root", 0x1600, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI5, "lpspi5_root", 0x1680, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI6, "lpspi6_root", 0x1700, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI7, "lpspi7_root", 0x1780, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI8, "lpspi8_root", 0x1800, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_I3C1, "i3c1_root", 0x1880, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_I3C2, "i3c2_root", 0x1900, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_USDHC1, "usdhc1_root", 0x1980, FAST_SEL, }, + { IMX93_CLK_USDHC2, "usdhc2_root", 0x1a00, FAST_SEL, }, + { IMX93_CLK_USDHC3, "usdhc3_root", 0x1a80, FAST_SEL, }, + { IMX93_CLK_SAI1, "sai1_root", 0x1b00, AUDIO_SEL, }, + { IMX93_CLK_SAI2, "sai2_root", 0x1b80, AUDIO_SEL, }, + { IMX93_CLK_SAI3, "sai3_root", 0x1c00, AUDIO_SEL, }, + { IMX93_CLK_CCM_CKO1, "ccm_cko1_root", 0x1c80, CKO1_SEL, }, + { IMX93_CLK_CCM_CKO2, "ccm_cko2_root", 0x1d00, CKO2_SEL, }, + { IMX93_CLK_CCM_CKO3, "ccm_cko3_root", 0x1d80, CKO1_SEL, }, + { IMX93_CLK_CCM_CKO4, "ccm_cko4_root", 0x1e00, CKO2_SEL, }, + /* + * Critical because clk is used for handshake between HSIOMIX and NICMIX when + * NICMIX power down/on during system suspend/resume + */ + { IMX93_CLK_HSIO, "hsio_root", 0x1e80, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL}, + { IMX93_CLK_HSIO_USB_TEST_60M, "hsio_usb_test_60m_root", 0x1f00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_HSIO_ACSCAN_80M, "hsio_acscan_80m_root", 0x1f80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_HSIO_ACSCAN_480M, "hsio_acscan_480m_root", 0x2000, MISC_SEL, }, + { IMX93_CLK_NIC_AXI, "nic_axi_root", 0x2080, FAST_SEL, CLK_IS_CRITICAL, }, + { IMX93_CLK_ML_APB, "ml_apb_root", 0x2180, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_ML, "ml_root", 0x2200, FAST_SEL, }, + { IMX93_CLK_MEDIA_AXI, "media_axi_root", 0x2280, FAST_SEL, }, + { IMX93_CLK_MEDIA_APB, "media_apb_root", 0x2300, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_MEDIA_LDB, "media_ldb_root", 0x2380, VIDEO_SEL, }, + { IMX93_CLK_MEDIA_DISP_PIX, "media_disp_pix_root", 0x2400, VIDEO_SEL, }, + { IMX93_CLK_CAM_PIX, "cam_pix_root", 0x2480, VIDEO_SEL, }, + { IMX93_CLK_MIPI_TEST_BYTE, "mipi_test_byte_root", 0x2500, VIDEO_SEL, }, + { IMX93_CLK_MIPI_PHY_CFG, "mipi_phy_cfg_root", 0x2580, VIDEO_SEL, }, + { IMX93_CLK_ADC, "adc_root", 0x2700, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_PDM, "pdm_root", 0x2780, AUDIO_SEL, }, + { IMX93_CLK_TSTMR1, "tstmr1_root", 0x2800, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_TSTMR2, "tstmr2_root", 0x2880, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_MQS1, "mqs1_root", 0x2900, AUDIO_SEL, }, + { IMX93_CLK_MQS2, "mqs2_root", 0x2980, AUDIO_SEL, }, + { IMX93_CLK_AUDIO_XCVR, "audio_xcvr_root", 0x2a00, NON_IO_SEL, }, + { IMX93_CLK_SPDIF, "spdif_root", 0x2a80, AUDIO_SEL, }, + { IMX93_CLK_ENET, "enet_root", 0x2b00, NON_IO_SEL, }, + { IMX93_CLK_ENET_TIMER1, "enet_timer1_root", 0x2b80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_ENET_TIMER2, "enet_timer2_root", 0x2c00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_ENET_REF, "enet_ref_root", 0x2c80, NON_IO_SEL, }, + { IMX93_CLK_ENET_REF_PHY, "enet_ref_phy_root", 0x2d00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_I3C1_SLOW, "i3c1_slow_root", 0x2d80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_I3C2_SLOW, "i3c2_slow_root", 0x2e00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_USB_PHY_BURUNIN, "usb_phy_root", 0x2e80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_PAL_CAME_SCAN, "pal_came_scan_root", 0x2f00, MISC_SEL, } +}; + +static const struct imx93_clk_ccgr { + u32 clk; + char *name; + char *parent_name; + u32 off; + unsigned long flags; + u32 *shared_count; +} ccgr_array[] = { + { IMX93_CLK_A55_GATE, "a55_alt", "a55_alt_root", 0x8000, }, + /* M33 critical clk for system run */ + { IMX93_CLK_CM33_GATE, "cm33", "m33_root", 0x8040, CLK_IS_CRITICAL }, + { IMX93_CLK_ADC1_GATE, "adc1", "adc_root", 0x82c0, }, + { IMX93_CLK_WDOG1_GATE, "wdog1", "clock-osc-24m", 0x8300, }, + { IMX93_CLK_WDOG2_GATE, "wdog2", "clock-osc-24m", 0x8340, }, + { IMX93_CLK_WDOG3_GATE, "wdog3", "clock-osc-24m", 0x8380, }, + { IMX93_CLK_WDOG4_GATE, "wdog4", "clock-osc-24m", 0x83c0, }, + { IMX93_CLK_WDOG5_GATE, "wdog5", "clock-osc-24m", 0x8400, }, + { IMX93_CLK_SEMA1_GATE, "sema1", "bus_aon_root", 0x8440, }, + { IMX93_CLK_SEMA2_GATE, "sema2", "bus_wakeup_root", 0x8480, }, + { IMX93_CLK_MU1_A_GATE, "mu1_a", "bus_aon_root", 0x84c0, CLK_IGNORE_UNUSED }, + { IMX93_CLK_MU2_A_GATE, "mu2_a", "bus_wakeup_root", 0x84c0, CLK_IGNORE_UNUSED }, + { IMX93_CLK_MU1_B_GATE, "mu1_b", "bus_aon_root", 0x8500, 0, &share_count_mub }, + { IMX93_CLK_MU2_B_GATE, "mu2_b", "bus_wakeup_root", 0x8500, 0, &share_count_mub }, + { IMX93_CLK_EDMA1_GATE, "edma1", "m33_root", 0x8540, }, + { IMX93_CLK_EDMA2_GATE, "edma2", "wakeup_axi_root", 0x8580, }, + { IMX93_CLK_FLEXSPI1_GATE, "flexspi1", "flexspi1_root", 0x8640, }, + { IMX93_CLK_GPIO1_GATE, "gpio1", "m33_root", 0x8880, }, + { IMX93_CLK_GPIO2_GATE, "gpio2", "bus_wakeup_root", 0x88c0, }, + { IMX93_CLK_GPIO3_GATE, "gpio3", "bus_wakeup_root", 0x8900, }, + { IMX93_CLK_GPIO4_GATE, "gpio4", "bus_wakeup_root", 0x8940, }, + { IMX93_CLK_FLEXIO1_GATE, "flexio1", "flexio1_root", 0x8980, }, + { IMX93_CLK_FLEXIO2_GATE, "flexio2", "flexio2_root", 0x89c0, }, + { IMX93_CLK_LPIT1_GATE, "lpit1", "bus_aon_root", 0x8a00, }, + { IMX93_CLK_LPIT2_GATE, "lpit2", "bus_wakeup_root", 0x8a40, }, + { IMX93_CLK_LPTMR1_GATE, "lptmr1", "lptmr1_root", 0x8a80, }, + { IMX93_CLK_LPTMR2_GATE, "lptmr2", "lptmr2_root", 0x8ac0, }, + { IMX93_CLK_TPM1_GATE, "tpm1", "bus_aon_root", 0x8b00, }, + { IMX93_CLK_TPM2_GATE, "tpm2", "tpm2_root", 0x8b40, }, + { IMX93_CLK_TPM3_GATE, "tpm3", "bus_wakeup_root", 0x8b80, }, + { IMX93_CLK_TPM4_GATE, "tpm4", "tpm4_root", 0x8bc0, }, + { IMX93_CLK_TPM5_GATE, "tpm5", "tpm5_root", 0x8c00, }, + { IMX93_CLK_TPM6_GATE, "tpm6", "tpm6_root", 0x8c40, }, + { IMX93_CLK_CAN1_GATE, "can1", "can1_root", 0x8c80, }, + { IMX93_CLK_CAN2_GATE, "can2", "can2_root", 0x8cc0, }, + { IMX93_CLK_LPUART1_GATE, "lpuart1", "lpuart1_root", 0x8d00, }, + { IMX93_CLK_LPUART2_GATE, "lpuart2", "lpuart2_root", 0x8d40, }, + { IMX93_CLK_LPUART3_GATE, "lpuart3", "lpuart3_root", 0x8d80, }, + { IMX93_CLK_LPUART4_GATE, "lpuart4", "lpuart4_root", 0x8dc0, }, + { IMX93_CLK_LPUART5_GATE, "lpuart5", "lpuart5_root", 0x8e00, }, + { IMX93_CLK_LPUART6_GATE, "lpuart6", "lpuart6_root", 0x8e40, }, + { IMX93_CLK_LPUART7_GATE, "lpuart7", "lpuart7_root", 0x8e80, }, + { IMX93_CLK_LPUART8_GATE, "lpuart8", "lpuart8_root", 0x8ec0, }, + { IMX93_CLK_LPI2C1_GATE, "lpi2c1", "lpi2c1_root", 0x8f00, }, + { IMX93_CLK_LPI2C2_GATE, "lpi2c2", "lpi2c2_root", 0x8f40, }, + { IMX93_CLK_LPI2C3_GATE, "lpi2c3", "lpi2c3_root", 0x8f80, }, + { IMX93_CLK_LPI2C4_GATE, "lpi2c4", "lpi2c4_root", 0x8fc0, }, + { IMX93_CLK_LPI2C5_GATE, "lpi2c5", "lpi2c5_root", 0x9000, }, + { IMX93_CLK_LPI2C6_GATE, "lpi2c6", "lpi2c6_root", 0x9040, }, + { IMX93_CLK_LPI2C7_GATE, "lpi2c7", "lpi2c7_root", 0x9080, }, + { IMX93_CLK_LPI2C8_GATE, "lpi2c8", "lpi2c8_root", 0x90c0, }, + { IMX93_CLK_LPSPI1_GATE, "lpspi1", "lpspi1_root", 0x9100, }, + { IMX93_CLK_LPSPI2_GATE, "lpspi2", "lpspi2_root", 0x9140, }, + { IMX93_CLK_LPSPI3_GATE, "lpspi3", "lpspi3_root", 0x9180, }, + { IMX93_CLK_LPSPI4_GATE, "lpspi4", "lpspi4_root", 0x91c0, }, + { IMX93_CLK_LPSPI5_GATE, "lpspi5", "lpspi5_root", 0x9200, }, + { IMX93_CLK_LPSPI6_GATE, "lpspi6", "lpspi6_root", 0x9240, }, + { IMX93_CLK_LPSPI7_GATE, "lpspi7", "lpspi7_root", 0x9280, }, + { IMX93_CLK_LPSPI8_GATE, "lpspi8", "lpspi8_root", 0x92c0, }, + { IMX93_CLK_I3C1_GATE, "i3c1", "i3c1_root", 0x9300, }, + { IMX93_CLK_I3C2_GATE, "i3c2", "i3c2_root", 0x9340, }, + { IMX93_CLK_USDHC1_GATE, "usdhc1", "usdhc1_root", 0x9380, }, + { IMX93_CLK_USDHC2_GATE, "usdhc2", "usdhc2_root", 0x93c0, }, + { IMX93_CLK_USDHC3_GATE, "usdhc3", "usdhc3_root", 0x9400, }, + { IMX93_CLK_SAI1_GATE, "sai1", "sai1_root", 0x9440, 0, &share_count_sai1}, + { IMX93_CLK_SAI1_IPG, "sai1_ipg_clk", "bus_aon_root", 0x9440, 0, &share_count_sai1}, + { IMX93_CLK_SAI2_GATE, "sai2", "sai2_root", 0x9480, 0, &share_count_sai2}, + { IMX93_CLK_SAI2_IPG, "sai2_ipg_clk", "bus_wakeup_root", 0x9480, 0, &share_count_sai2}, + { IMX93_CLK_SAI3_GATE, "sai3", "sai3_root", 0x94c0, 0, &share_count_sai3}, + { IMX93_CLK_SAI3_IPG, "sai3_ipg_clk", "bus_wakeup_root", 0x94c0, 0, &share_count_sai3}, + { IMX93_CLK_MIPI_CSI_GATE, "mipi_csi", "media_apb_root", 0x9580, }, + { IMX93_CLK_MIPI_DSI_GATE, "mipi_dsi", "media_apb_root", 0x95c0, }, + { IMX93_CLK_LVDS_GATE, "lvds", "media_ldb_root", 0x9600, }, + { IMX93_CLK_LCDIF_GATE, "lcdif", "media_apb_root", 0x9640, }, + { IMX93_CLK_PXP_GATE, "pxp", "media_apb_root", 0x9680, }, + { IMX93_CLK_ISI_GATE, "isi", "media_apb_root", 0x96c0, }, + { IMX93_CLK_NIC_MEDIA_GATE, "nic_media", "media_axi_root", 0x9700, }, + { IMX93_CLK_USB_CONTROLLER_GATE, "usb_controller", "hsio_root", 0x9a00, }, + { IMX93_CLK_USB_TEST_60M_GATE, "usb_test_60m", "hsio_usb_test_60m_root", 0x9a40, }, + { IMX93_CLK_HSIO_TROUT_24M_GATE, "hsio_trout_24m", "clock-osc-24m", 0x9a80, }, + { IMX93_CLK_PDM_GATE, "pdm", "pdm_root", 0x9ac0, }, + { IMX93_CLK_MQS1_GATE, "mqs1", "sai1_root", 0x9b00, }, + { IMX93_CLK_MQS2_GATE, "mqs2", "sai3_root", 0x9b40, }, + { IMX93_CLK_AUD_XCVR_GATE, "aud_xcvr", "audio_xcvr_root", 0x9b80, }, + { IMX93_CLK_SPDIF_GATE, "spdif", "spdif_root", 0x9c00, }, + { IMX93_CLK_HSIO_32K_GATE, "hsio_32k", "clock-osc-24m", 0x9dc0, }, + { IMX93_CLK_ENET1_GATE, "enet1", "wakeup_axi_root", 0x9e00, }, + { IMX93_CLK_ENET_QOS_GATE, "enet_qos", "wakeup_axi_root", 0x9e40, }, + /* Critical because clk accessed during CPU idle */ + { IMX93_CLK_SYS_CNT_GATE, "sys_cnt", "clock-osc-24m", 0x9e80, CLK_IS_CRITICAL}, + { IMX93_CLK_TSTMR1_GATE, "tstmr1", "bus_aon_root", 0x9ec0, }, + { IMX93_CLK_TSTMR2_GATE, "tstmr2", "bus_wakeup_root", 0x9f00, }, + { IMX93_CLK_TMC_GATE, "tmc", "clock-osc-24m", 0x9f40, }, + { IMX93_CLK_PMRO_GATE, "pmro", "clock-osc-24m", 0x9f80, } +}; + +static int imx93_clk_probe(struct udevice *dev) +{ + const struct imx93_clk_root *root; + const struct imx93_clk_ccgr *ccgr; + struct clk osc_24m_clk, osc_32k_clk, ext1_clk; + void __iomem *base, *anatop_base; + int i, ret; + + clk_dm(IMX93_CLK_DUMMY, clk_register_fixed_rate(NULL, "dummy", 0UL)); + + ret = clk_get_by_name(dev, "osc_24m", &osc_24m_clk); + if (ret) + return ret; + clk_dm(IMX93_CLK_24M, dev_get_clk_ptr(osc_24m_clk.dev)); + + ret = clk_get_by_name(dev, "osc_32k", &osc_32k_clk); + if (ret) + return ret; + clk_dm(IMX93_CLK_32K, dev_get_clk_ptr(osc_32k_clk.dev)); + + ret = clk_get_by_name(dev, "clk_ext1", &ext1_clk); + if (ret) + return ret; + clk_dm(IMX93_CLK_EXT1, dev_get_clk_ptr(ext1_clk.dev)); + + clk_dm(IMX93_CLK_SYS_PLL_PFD0, + clk_register_fixed_rate(NULL, "sys_pll_pfd0", 1000000000)); + clk_dm(IMX93_CLK_SYS_PLL_PFD0_DIV2, + imx_clk_fixed_factor("sys_pll_pfd0_div2", "sys_pll_pfd0", 1, 2)); + clk_dm(IMX93_CLK_SYS_PLL_PFD1, + clk_register_fixed_rate(NULL, "sys_pll_pfd1", 800000000)); + clk_dm(IMX93_CLK_SYS_PLL_PFD1_DIV2, + imx_clk_fixed_factor("sys_pll_pfd1_div2", "sys_pll_pfd1", 1, 2)); + clk_dm(IMX93_CLK_SYS_PLL_PFD2, + clk_register_fixed_rate(NULL, "sys_pll_pfd2", 625000000)); + clk_dm(IMX93_CLK_SYS_PLL_PFD2_DIV2, + imx_clk_fixed_factor("sys_pll_pfd2_div2", "sys_pll_pfd2", 1, 2)); + + base = (void *)ANATOP_BASE_ADDR; + + clk_dm(IMX93_CLK_ARM_PLL, + imx_clk_fracn_gppll_integer("arm_pll", "clock-osc-24m", + anatop_base + 0x1000, + &imx_fracn_gppll_integer)); + clk_dm(IMX93_CLK_AUDIO_PLL, + imx_clk_fracn_gppll("audio_pll", "clock-osc-24m", + anatop_base + 0x1200, &imx_fracn_gppll)); + clk_dm(IMX93_CLK_VIDEO_PLL, + imx_clk_fracn_gppll("video_pll", "clock-osc-24m", + anatop_base + 0x1400, &imx_fracn_gppll)); + + base = dev_read_addr_ptr(dev); + if (!base) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(root_array); i++) { + root = &root_array[i]; + clk_dm(root->clk, imx93_clk_composite_flags(root->name, + parent_names[root->sel], + 4, base + root->off, 3, + root->flags)); + } + + for (i = 0; i < ARRAY_SIZE(ccgr_array); i++) { + ccgr = &ccgr_array[i]; + clk_dm(ccgr->clk, imx93_clk_gate(NULL, ccgr->name, ccgr->parent_name, + ccgr->flags, base + ccgr->off, 0, 1, 1, 3, + ccgr->shared_count)); + } + + clk_dm(IMX93_CLK_A55_SEL, + imx_clk_mux2("a55_sel", base + 0x4820, 0, 1, + a55_core_sels, ARRAY_SIZE(a55_core_sels))); + + return 0; +} + +static const struct udevice_id imx93_clk_ids[] = { + { .compatible = "fsl,imx93-ccm" }, + { /* Sentinel */ }, +}; + +U_BOOT_DRIVER(imx93_clk) = { + .name = "clk_imx93", + .id = UCLASS_CLK, + .of_match = imx93_clk_ids, + .ops = &ccf_clk_ops, + .probe = imx93_clk_probe, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index 11f5dca1175..27a53ae5583 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -46,6 +46,34 @@ 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; +#define CLK_FRACN_GPPLL_INTEGER BIT(0) +#define CLK_FRACN_GPPLL_FRACN BIT(1) + +/* NOTE: Rate table should be kept sorted in descending order. */ +struct imx_fracn_gppll_rate_table { + unsigned int rate; + unsigned int mfi; + unsigned int mfn; + unsigned int mfd; + unsigned int rdiv; + unsigned int odiv; +}; + +struct imx_fracn_gppll_clk { + const struct imx_fracn_gppll_rate_table *rate_table; + int rate_count; + int flags; +}; + +struct clk *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base, + const struct imx_fracn_gppll_clk *pll_clk); +struct clk *imx_clk_fracn_gppll_integer(const char *name, const char *parent_name, + void __iomem *base, + const struct imx_fracn_gppll_clk *pll_clk); + +extern struct imx_fracn_gppll_clk imx_fracn_gppll; +extern struct imx_fracn_gppll_clk imx_fracn_gppll_integer; + struct clk *imx_clk_pll14xx(const char *name, const char *parent_name, void __iomem *base, const struct imx_pll14xx_clk *pll_clk); @@ -224,4 +252,18 @@ struct clk *imx8m_clk_composite_flags(const char *name, #define imx8m_clk_composite_critical(name, parent_names, reg) \ __imx8m_clk_composite(name, parent_names, reg, CLK_IS_CRITICAL) +struct clk *imx93_clk_composite_flags(const char *name, + const char * const *parent_names, + int num_parents, + void __iomem *reg, + u32 domain_id, + unsigned long flags); +#define imx93_clk_composite(name, parent_names, num_parents, reg, domain_id) \ + imx93_clk_composite_flags(name, parent_names, num_parents, reg, domain_id \ + CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE) + +struct clk *imx93_clk_gate(struct device *dev, const char *name, const char *parent_name, + unsigned long flags, void __iomem *reg, u32 bit_idx, u32 val, + u32 mask, u32 domain_id, unsigned int *share_count); + #endif /* __MACH_IMX_CLK_H */ diff --git a/include/dt-bindings/clock/imx93-clock.h b/include/dt-bindings/clock/imx93-clock.h index 8e02859d8ce..35a1f62053a 100644 --- a/include/dt-bindings/clock/imx93-clock.h +++ b/include/dt-bindings/clock/imx93-clock.h @@ -199,6 +199,10 @@ #define IMX93_CLK_MU1_B_GATE 194 #define IMX93_CLK_MU2_A_GATE 195 #define IMX93_CLK_MU2_B_GATE 196 -#define IMX93_CLK_END 197 +#define IMX93_CLK_NIC_AXI 197 +#define IMX93_CLK_ARM_PLL 198 +#define IMX93_CLK_A55_SEL 199 +#define IMX93_CLK_A55_CORE 200 +#define IMX93_CLK_END 201 #endif -- cgit v1.3.1 From b13eaf3bb4e64fff117210821b3cf2f106de8ae2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 21 Sep 2023 20:44:16 +0200 Subject: spl: fit: Add board level function to decide application of DTO Add board-specific function used to indicate whether a DTO from fitImage configuration node 'fdt' property DT and DTO list should be applied onto the base DT or not applied. This is useful in case of DTOs which implement e.g. different board revision details, where such DTO should be applied on one board revision, and should not be applied on another board revision. Signed-off-by: Marek Vasut --- common/spl/spl_fit.c | 23 ++++++++++++++++++++--- include/spl.h | 16 ++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index ce6b8aa370a..1409b926372 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -372,6 +372,11 @@ static bool os_takes_devicetree(uint8_t os) } } +__weak int board_spl_fit_append_fdt_skip(const char *name) +{ + return 0; /* Do not skip */ +} + static int spl_fit_append_fdt(struct spl_image_info *spl_image, struct spl_load_info *info, ulong sector, const struct spl_fit_info *ctx) @@ -414,11 +419,23 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, void *tmpbuffer = NULL; for (; ; index++) { - node = spl_fit_get_image_node(ctx, FIT_FDT_PROP, index); - if (node == -E2BIG) { + const char *str; + + ret = spl_fit_get_image_name(ctx, FIT_FDT_PROP, index, &str); + if (ret == -E2BIG) { debug("%s: No additional FDT node\n", __func__); + ret = 0; break; - } else if (node < 0) { + } else if (ret < 0) { + continue; + } + + ret = board_spl_fit_append_fdt_skip(str); + if (ret) + continue; + + node = fdt_subnode_offset(ctx->fit, ctx->images_node, str); + if (node < 0) { debug("%s: unable to find FDT node %d\n", __func__, index); continue; diff --git a/include/spl.h b/include/spl.h index 7d30fb57dac..1d416b4c929 100644 --- a/include/spl.h +++ b/include/spl.h @@ -918,6 +918,22 @@ void spl_perform_fixups(struct spl_image_info *spl_image); */ struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size); +/** + * board_spl_fit_append_fdt_skip(): test whether DTO application should be skipped + * @name: DTO node name within fitImage images node + * + * A board-specific function used to indicate whether a DTO from fitImage + * configuration node 'fdt' property DT and DTO list should be applied onto + * the base DT or not applied. + * + * This is useful in case of DTOs which implement e.g. different board revision + * details, where such DTO should be applied on one board revision, and should + * not be applied on another board revision. + * + * Return: 0 to indicate DTO is not skipped, all else to indicate DTO is skipped. + */ +int board_spl_fit_append_fdt_skip(const char *name); + void board_boot_order(u32 *spl_boot_list); void spl_save_restore_data(void); -- cgit v1.3.1