From: Tom Rini Date: Mon, 22 Sep 2025 14:23:41 +0000 (-0600) Subject: Merge tag 'u-boot-imx-next-20250922' of https://gitlab.denx.de/u-boot/custodians... X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d81c1118580f3481b864b830fe5b789519993bd3;p=pandora-u-boot.git Merge tag 'u-boot-imx-next-20250922' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx into next CI: https://source.denx.de/u-boot/custodians/u-boot-imx/-/pipelines/27684 - Add i.MX8 ahab-commit command. - Add support for flashing board with UUU on imx93_frdm. - Fix the acces of PFUZE100 regulator desc. - Add more i.MX6 PWM clock definitions. - Enable OP-TEE on phytec-imx8m and update documentation. - Enable PCI host controller on iMX95 19x19 EVK. [trini: Fixup spacing issues] Signed-off-by: Tom Rini --- d81c1118580f3481b864b830fe5b789519993bd3 diff --cc drivers/clk/imx/clk-imx95-blkctrl.c index 00000000000,3bf6f9415e2..3e6f53b4a16 mode 000000,100644..100644 --- a/drivers/clk/imx/clk-imx95-blkctrl.c +++ b/drivers/clk/imx/clk-imx95-blkctrl.c @@@ -1,0 -1,170 +1,183 @@@ + // SPDX-License-Identifier: GPL-2.0+ + /* + * Copyright 2023-2025 NXP + * + */ + + #include + #include + #include + #include + #include + #include + + #include "clk.h" + + enum { + CLK_GATE, + CLK_DIVIDER, + CLK_MUX, + }; + + struct imx95_blk_ctl_clk_dev_data { + const char *name; + const char * const *parent_names; + u32 num_parents; + u32 reg; + u32 bit_idx; + u32 clk_type; + u32 flags; + u32 flags2; + u32 type; + }; + + struct imx95_blk_ctl_dev_data { + const struct imx95_blk_ctl_clk_dev_data *clk_dev_data; + u32 num_clks; + u32 clk_reg_offset; + }; + + static const struct imx95_blk_ctl_clk_dev_data hsio_blk_ctl_clk_dev_data[] = { + [0] = { + .name = "hsio_blk_ctl_clk", + .parent_names = (const char *[]){ "hsiopll", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 6, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + } + }; + + static const struct imx95_blk_ctl_dev_data hsio_blk_ctl_dev_data = { + .num_clks = 1, + .clk_dev_data = hsio_blk_ctl_clk_dev_data, + .clk_reg_offset = 0, + }; + + static const struct imx95_blk_ctl_clk_dev_data imx95_lvds_clk_dev_data[] = { + [IMX95_CLK_DISPMIX_LVDS_PHY_DIV] = { + .name = "ldb_phy_div", + .parent_names = (const char *[]){ "ldbpll", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 0, + .type = CLK_DIVIDER, + .flags2 = CLK_DIVIDER_POWER_OF_TWO, + }, + - [IMX95_CLK_DISPMIX_LVDS_CH0_GATE] = { ++ [IMX95_CLK_DISPMIX_LVDS_CH0_GATE] = { + .name = "lvds_ch0_gate", + .parent_names = (const char *[]){ "ldb_phy_div", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 1, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, - }, - [IMX95_CLK_DISPMIX_LVDS_CH1_GATE] = { ++ }, ++ [IMX95_CLK_DISPMIX_LVDS_CH1_GATE] = { + .name = "lvds_ch1_gate", + .parent_names = (const char *[]){ "ldb_phy_div", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 2, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, - }, - [IMX95_CLK_DISPMIX_PIX_DI0_GATE] = { ++ }, ++ [IMX95_CLK_DISPMIX_PIX_DI0_GATE] = { + .name = "lvds_di0_gate", + .parent_names = (const char *[]){ "ldb_pll_div7", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 3, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, - }, - [IMX95_CLK_DISPMIX_PIX_DI1_GATE] = { ++ }, ++ [IMX95_CLK_DISPMIX_PIX_DI1_GATE] = { + .name = "lvds_di1_gate", + .parent_names = (const char *[]){ "ldb_pll_div7", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 4, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, - }, ++ }, + }; + + static const struct imx95_blk_ctl_dev_data imx95_lvds_csr_dev_data = { + .num_clks = ARRAY_SIZE(imx95_lvds_clk_dev_data), + .clk_dev_data = imx95_lvds_clk_dev_data, + .clk_reg_offset = 0, + }; + + static int imx95_blkctrl_clk_probe(struct udevice *dev) + { + int i; + void __iomem *addr; + struct imx95_blk_ctl_dev_data *dev_data = (void *)dev_get_driver_data(dev); + const struct imx95_blk_ctl_clk_dev_data *clk_dev_data; + + addr = dev_read_addr_ptr(dev); + if (addr == (void *)FDT_ADDR_T_NONE) { + dev_err(dev, "No blkctrl register base address\n"); + return -EINVAL; + } + + if (!dev_data) { + dev_err(dev, "driver data is NULL\n"); + return -EINVAL; + } + + clk_dev_data = dev_data->clk_dev_data; + for (i = 0; i < dev_data->num_clks; i++) { + if (clk_dev_data[i].clk_type == CLK_GATE) { - dev_clk_dm(dev, i, clk_register_gate(dev, clk_dev_data[i].name, clk_dev_data[i].parent_names[0], - clk_dev_data[i].flags, addr + dev_data->clk_reg_offset, clk_dev_data[i].bit_idx, - clk_dev_data[i].flags2, NULL)); ++ dev_clk_dm(dev, i, ++ clk_register_gate(dev, ++ clk_dev_data[i].name, ++ clk_dev_data[i].parent_names[0], ++ clk_dev_data[i].flags, addr + ++ dev_data->clk_reg_offset, ++ clk_dev_data[i].bit_idx, ++ clk_dev_data[i].flags2, NULL)); + } else if (clk_dev_data[i].clk_type == CLK_DIVIDER) { + dev_clk_dm(dev, i, - clk_register_divider(dev, clk_dev_data[i].name, clk_dev_data[i].parent_names[0], - clk_dev_data[i].flags, addr + dev_data->clk_reg_offset, clk_dev_data[i].bit_idx, 1, - clk_dev_data[i].flags2)); ++ clk_register_divider(dev, clk_dev_data[i].name, ++ clk_dev_data[i].parent_names[0], ++ clk_dev_data[i].flags, addr + ++ dev_data->clk_reg_offset, ++ clk_dev_data[i].bit_idx, 1, ++ clk_dev_data[i].flags2)); + } else if (clk_dev_data[i].clk_type == CLK_MUX) { + dev_clk_dm(dev, i, - clk_register_mux(dev, clk_dev_data[i].name, clk_dev_data[i].parent_names, - clk_dev_data[i].num_parents, clk_dev_data[i].flags, addr + dev_data->clk_reg_offset, - clk_dev_data[i].bit_idx, 1, clk_dev_data[i].flags2)); ++ clk_register_mux(dev, ++ clk_dev_data[i].name, ++ clk_dev_data[i].parent_names, ++ clk_dev_data[i].num_parents, ++ clk_dev_data[i].flags, addr + ++ dev_data->clk_reg_offset, ++ clk_dev_data[i].bit_idx, 1, ++ clk_dev_data[i].flags2)); + } + } + + return 0; + } + + static const struct udevice_id imx95_blkctrl_clk_ids[] = { + { .compatible = "nxp,imx95-lvds-csr", .data = (ulong)&imx95_lvds_csr_dev_data, }, + { .compatible = "nxp,imx95-hsio-blk-ctl", .data = (ulong)&hsio_blk_ctl_dev_data, }, + { }, + }; + + U_BOOT_DRIVER(imx95_blkctrl_clk) = { + .name = "imx95_blkctrl_clk", + .id = UCLASS_CLK, + .of_match = imx95_blkctrl_clk_ids, + .ops = &ccf_clk_ops, + .probe = imx95_blkctrl_clk_probe, + .flags = DM_FLAG_PRE_RELOC, + }; diff --cc drivers/pci/pcie_dw_imx.c index fdb463710ba,f84c7180560..41d9f3c20b9 --- a/drivers/pci/pcie_dw_imx.c +++ b/drivers/pci/pcie_dw_imx.c @@@ -57,11 -103,159 +103,152 @@@ struct pcie_dw_imx }; struct pcie_chip_info { + u32 flags; + const u32 ltssm_off; + const u32 ltssm_mask; + const u32 mode_off[IMX_PCIE_MAX_INSTANCES]; + const u32 mode_mask[IMX_PCIE_MAX_INSTANCES]; const char *gpr; + void (*init_phy)(struct pcie_dw_imx *priv); + int (*enable_ref_clk)(struct pcie_dw_imx *priv, bool enable); + int (*core_reset)(struct pcie_dw_imx *priv, bool assert); + int (*wait_pll_lock)(struct pcie_dw_imx *priv); + void (*post_config)(struct pcie_dw_imx *priv); }; + static void imx95_pcie_init_phy(struct pcie_dw_imx *priv) + { + /* + * Workaround for ERR051624: The Controller Without Vaux Cannot + * Exit L23 Ready Through Beacon or PERST# De-assertion + * + * When the auxiliary power is not available the controller + * cannot exit from L23 Ready with beacon or PERST# de-assertion + * when main power is not removed. + * + * Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1. + */ + regmap_update_bits(priv->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1, - IMX95_PCIE_SYS_AUX_PWR_DET, IMX95_PCIE_SYS_AUX_PWR_DET); ++ IMX95_PCIE_SYS_AUX_PWR_DET, ++ IMX95_PCIE_SYS_AUX_PWR_DET); + - regmap_update_bits(priv->iomuxc_gpr, - IMX95_PCIE_SS_RW_REG_0, - IMX95_PCIE_PHY_CR_PARA_SEL, - IMX95_PCIE_PHY_CR_PARA_SEL); ++ regmap_update_bits(priv->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_0, ++ IMX95_PCIE_PHY_CR_PARA_SEL, ++ IMX95_PCIE_PHY_CR_PARA_SEL); + + if (priv->enable_ext_refclk) { + /* External clock is used as reference clock */ - regmap_update_bits(priv->iomuxc_gpr, - IMX95_PCIE_PHY_GEN_CTRL, - IMX95_PCIE_REF_USE_PAD, - IMX95_PCIE_REF_USE_PAD); - regmap_update_bits(priv->iomuxc_gpr, - IMX95_PCIE_SS_RW_REG_0, - IMX95_PCIE_REF_CLKEN, 0); ++ regmap_update_bits(priv->iomuxc_gpr, IMX95_PCIE_PHY_GEN_CTRL, ++ IMX95_PCIE_REF_USE_PAD, ++ IMX95_PCIE_REF_USE_PAD); ++ regmap_update_bits(priv->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_0, ++ IMX95_PCIE_REF_CLKEN, 0); + } else { - regmap_update_bits(priv->iomuxc_gpr, - IMX95_PCIE_PHY_GEN_CTRL, - IMX95_PCIE_REF_USE_PAD, 0); ++ regmap_update_bits(priv->iomuxc_gpr, IMX95_PCIE_PHY_GEN_CTRL, ++ IMX95_PCIE_REF_USE_PAD, 0); + - regmap_update_bits(priv->iomuxc_gpr, - IMX95_PCIE_SS_RW_REG_0, - IMX95_PCIE_REF_CLKEN, - IMX95_PCIE_REF_CLKEN); ++ regmap_update_bits(priv->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_0, ++ IMX95_PCIE_REF_CLKEN, IMX95_PCIE_REF_CLKEN); + } + + /* Force CLKREQ# low by override */ + if (!priv->supports_clkreq) + regmap_update_bits(priv->iomuxc_gpr, + IMX95_PCIE_SS_RW_REG_1, + IMX95_PCIE_CLKREQ_OVERRIDE_EN | + IMX95_PCIE_CLKREQ_OVERRIDE_VAL, + IMX95_PCIE_CLKREQ_OVERRIDE_EN | + IMX95_PCIE_CLKREQ_OVERRIDE_VAL); + } + + static int imx95_pcie_wait_for_phy_pll_lock(struct pcie_dw_imx *priv) + { + u32 val; + + if (regmap_read_poll_timeout(priv->iomuxc_gpr, + IMX95_PCIE_PHY_MPLLA_CTRL, val, + val & IMX95_PCIE_PHY_MPLL_STATE, + PHY_PLL_LOCK_WAIT_USLEEP_MAX, + PHY_PLL_LOCK_WAIT_TIMEOUT)) { + printf("PCIe PLL lock timeout\n"); + return -ETIMEDOUT; + } + + return 0; + } + + static int imx95_pcie_core_reset(struct pcie_dw_imx *priv, bool assert) + { + u32 val; + + if (assert) { + /* + * From i.MX95 PCIe PHY perspective, the COLD reset toggle + * should be complete after power-up by the following sequence. + * > 10us(at power-up) + * > 10ns(warm reset) + * |<------------>| + * ______________ + * phy_reset ____/ \________________ + * ____________ + * ref_clk_en_______________________/ + * Toggle COLD reset aligned with this sequence for i.MX95 PCIe. + */ + regmap_update_bits(priv->iomuxc_gpr, IMX95_PCIE_RST_CTRL, + IMX95_PCIE_COLD_RST, IMX95_PCIE_COLD_RST); + /* + * Make sure the write to IMX95_PCIE_RST_CTRL is flushed to the + * hardware by doing a read. Otherwise, there is no guarantee + * that the write has reached the hardware before udelay(). + */ - regmap_read(priv->iomuxc_gpr, IMX95_PCIE_RST_CTRL, - &val); ++ regmap_read(priv->iomuxc_gpr, IMX95_PCIE_RST_CTRL, &val); + udelay(15); + regmap_update_bits(priv->iomuxc_gpr, IMX95_PCIE_RST_CTRL, - IMX95_PCIE_COLD_RST, 0); - regmap_read(priv->iomuxc_gpr, IMX95_PCIE_RST_CTRL, - &val); ++ IMX95_PCIE_COLD_RST, 0); ++ regmap_read(priv->iomuxc_gpr, IMX95_PCIE_RST_CTRL, &val); + udelay(10); + } + + return 0; + } + + static void imx95_pcie_post_config(struct pcie_dw_imx *priv) + { + u32 val; + + /* + * Workaround for ERR051586: Compliance with 8GT/s Receiver + * Impedance ECN + * + * The default value of GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] is + * 1 which makes receiver non-compliant with the ZRX-DC + * parameter for 2.5 GT/s when operating at 8 GT/s or higher. It + * causes unnecessary timeout in L1. + * + * Workaround: Program GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] to 0. + */ + dw_pcie_dbi_write_enable(&priv->dw, true); + val = readl(priv->dw.dbi_base + GEN3_RELATED_OFF); + val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL; + writel(val, priv->dw.dbi_base + GEN3_RELATED_OFF); + dw_pcie_dbi_write_enable(&priv->dw, false); + } + + static int imx8mm_pcie_enable_ref_clk(struct pcie_dw_imx *priv, bool enable) + { + regmap_update_bits(priv->iomuxc_gpr, IOMUXC_GPR14_OFFSET, + IMX8M_GPR_PCIE_CLK_REQ_OVERRIDE, + enable ? 0 : IMX8M_GPR_PCIE_CLK_REQ_OVERRIDE); + regmap_update_bits(priv->iomuxc_gpr, IOMUXC_GPR14_OFFSET, + IMX8M_GPR_PCIE_CLK_REQ_OVERRIDE_EN, + enable ? IMX8M_GPR_PCIE_CLK_REQ_OVERRIDE_EN : 0); + return 0; + } + static const struct pcie_chip_info imx8mm_chip_info = { + .flags = IMX_PCIE_FLAG_HAS_APP_RESET | IMX_PCIE_FLAG_HAS_PHYDRV, .gpr = "fsl,imx8mm-iomuxc-gpr", + .enable_ref_clk = imx8mm_pcie_enable_ref_clk, }; static const struct pcie_chip_info imx8mp_chip_info = {