diff options
| author | Tom Rini <[email protected]> | 2026-02-07 07:50:05 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-02-07 07:50:05 -0600 |
| commit | 717cd8d54c81f16c2c062a4ac80463956628d4c1 (patch) | |
| tree | e40228615d856862b10b7b37647f44c05b8f33c5 /drivers | |
| parent | e5e75ea8c7b8e6d9ce1ca8ec7a25fa8b3f6029a9 (diff) | |
| parent | 470ea759aa60890271fba0b8d0bcc7bb29e0b459 (diff) | |
Merge tag 'u-boot-imx-master-20260206' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
CI: https://source.denx.de/u-boot/custodians/u-boot-imx/-/pipelines/29216
- Convert imx8mn_var_som to OF_UPSTREAM and several cleanups.
- Fix ele_ahab buid error on imx93_qsb.
- Add i.MX95 EVK remoteproc support.
- Several i.MX8/9 EVK cleanups.
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/net/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/net/fec_mxc.c | 4 | ||||
| -rw-r--r-- | drivers/remoteproc/imx_rproc.c | 189 | ||||
| -rw-r--r-- | drivers/remoteproc/imx_rproc.h | 3 |
4 files changed, 190 insertions, 8 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 4fda1b0c28c..eb6a1cab565 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -423,7 +423,7 @@ config FEC_MXC_MDIO_BASE config FEC_MXC bool "FEC Ethernet controller" - depends on MX28 || MX5 || MX6 || MX7 || IMX8 || IMX8M || IMX8ULP || IMX93 || VF610 + depends on MX28 || MX5 || MX6 || MX7 || IMX8 || IMX8M || IMX8ULP || IMX91 || IMX93 || VF610 help This driver supports the 10/100 Fast Ethernet controller for NXP i.MX processors. diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index fee9973c4dc..1c51e936b5b 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -594,7 +594,7 @@ static int fecmxc_init(struct udevice *dev) /* Do not access reserved register */ if (!is_mx6ul() && !is_mx6ull() && !is_imx8() && !is_imx8m() && !is_imx8ulp() && - !is_imx93()) { + !is_imx91() && !is_imx93()) { /* clear MIB RAM */ for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4) writel(0, i); @@ -1236,7 +1236,7 @@ static int fecmxc_set_ref_clk(struct clk *clk_ref, phy_interface_t interface) interface == PHY_INTERFACE_MODE_RGMII_RXID || interface == PHY_INTERFACE_MODE_RGMII_TXID) { freq = 125000000; - if (is_imx93()) + if (is_imx91() || is_imx93()) freq = freq << 1; } else { return -EINVAL; diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 9bb55327998..3f8cea127ec 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -11,6 +11,7 @@ #include <linux/types.h> #include <regmap.h> #include <remoteproc.h> +#include <scmi_nxp_protocols.h> #include <syscon.h> #include "imx_rproc.h" @@ -37,15 +38,32 @@ #define IMX_SIP_RPROC_STARTED 0x01 #define IMX_SIP_RPROC_STOP 0x02 +/* Must align with System Manager Firmware */ +#define IMX95_M7_CPUID 1 +#define IMX95_M7_LMID 1 + +/* Logical Machine API Operation */ +#define IMX_RPROC_FLAGS_SM_LMM_OP BIT(0) +/* CPU API Operation */ +#define IMX_RPROC_FLAGS_SM_CPU_OP BIT(1) +/* Linux has permission to handle the Logical Machine of remote cores */ +#define IMX_RPROC_FLAGS_SM_LMM_AVAIL BIT(2) + struct imx_rproc { const struct imx_rproc_dcfg *dcfg; struct regmap *regmap; + u32 flags; + /* For System Manager based system */ + struct udevice *lmm_dev; + struct udevice *cpu_dev; + ulong reset_vector; }; /* att flags: lower 16 bits specifying core, higher 16 bits for flags */ /* M4 own area. Can be mapped at probe */ #define ATT_OWN BIT(31) #define ATT_IOMEM BIT(30) +#define ATT_ECC BIT(29) static int imx_rproc_arm_smc_start(struct udevice *dev) { @@ -64,6 +82,41 @@ static int imx_rproc_mmio_start(struct udevice *dev) return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_start); } +static int imx_rproc_sm_start(struct udevice *dev) +{ + struct imx_rproc *priv = dev_get_priv(dev); + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + int ret; + + if (priv->flags & IMX_RPROC_FLAGS_SM_CPU_OP) { + ret = scmi_imx_cpu_reset_vector_set(priv->cpu_dev, dcfg->cpuid, 0, + priv->reset_vector, true, false, false); + if (ret) { + dev_err(dev, "Failed to set reset vector cpuid(%u): %d\n", + dcfg->cpuid, ret); + return ret; + } + + return scmi_imx_cpu_start(priv->cpu_dev, dcfg->cpuid, true); + } + + ret = scmi_imx_lmm_reset_vector_set(priv->lmm_dev, dcfg->lmid, dcfg->cpuid, 0, + priv->reset_vector); + if (ret) { + dev_err(dev, "Failed to set reset vector lmid(%u), cpuid(%u): %d\n", + dcfg->lmid, dcfg->cpuid, ret); + return ret; + } + + ret = scmi_imx_lmm_power_boot(priv->lmm_dev, dcfg->lmid, true); + if (ret) { + dev_err(dev, "Failed to boot lmm(%d): %d\n", ret, dcfg->lmid); + return ret; + } + + return 0; +} + static int imx_rproc_start(struct udevice *dev) { struct imx_rproc *priv = dev_get_priv(dev); @@ -99,6 +152,17 @@ static int imx_rproc_mmio_stop(struct udevice *dev) return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_stop); } +static int imx_rproc_sm_stop(struct udevice *dev) +{ + struct imx_rproc *priv = dev_get_priv(dev); + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + + if (priv->flags & IMX_RPROC_FLAGS_SM_CPU_OP) + return scmi_imx_cpu_start(priv->cpu_dev, dcfg->cpuid, false); + + return scmi_imx_lmm_shutdown(priv->lmm_dev, dcfg->lmid, 0); +} + static int imx_rproc_stop(struct udevice *dev) { struct imx_rproc *priv = dev_get_priv(dev); @@ -145,6 +209,20 @@ static int imx_rproc_mmio_is_running(struct udevice *dev) return 1; } +static int imx_rproc_sm_is_running(struct udevice *dev) +{ + struct imx_rproc *priv = dev_get_priv(dev); + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + int ret; + bool started = false; + + ret = scmi_imx_cpu_started(priv->cpu_dev, dcfg->cpuid, &started); + if (ret || !started) + return 1; + + return 0; +} + static int imx_rproc_is_running(struct udevice *dev) { struct imx_rproc *priv = dev_get_priv(dev); @@ -202,6 +280,34 @@ static void *imx_rproc_device_to_virt(struct udevice *dev, ulong da, ulong size, static int imx_rproc_load(struct udevice *dev, ulong addr, ulong size) { + struct imx_rproc *priv = dev_get_priv(dev); + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + int i; + + if (IS_ENABLED(CONFIG_IMX_SM_LMM)) { + if (!(priv->flags & (IMX_RPROC_FLAGS_SM_LMM_AVAIL | IMX_RPROC_FLAGS_SM_CPU_OP))) + return -EACCES; + } + + /* Only used for SM based System */ + priv->reset_vector = rproc_elf_get_boot_addr(dev, addr) & GENMASK(31, 16); + + /* + * Before loading elf, need do ECC initialization by clearing the memory + * region, if ATT_ECC is set. + */ + for (i = 0; i < dcfg->att_size; i++) { + const struct imx_rproc_att *att = &dcfg->att[i]; + + if (!(att->flags & ATT_ECC)) + continue; + + if (att->flags & ATT_IOMEM) + memset_io((void __iomem *)(long)att->sa, 0, att->size); + else + memset((void *)(long)att->sa, 0, att->size); + } + return rproc_elf_load_image(dev, addr, size); } @@ -218,19 +324,65 @@ static int imx_rproc_probe(struct udevice *dev) { struct imx_rproc *priv = dev_get_priv(dev); struct imx_rproc_dcfg *dcfg = (struct imx_rproc_dcfg *)dev_get_driver_data(dev); + struct scmi_imx_lmm_info info; ofnode node; + int ret; node = dev_ofnode(dev); priv->dcfg = dcfg; - if (dcfg->method != IMX_RPROC_MMIO) + if (dcfg->method == IMX_RPROC_MMIO) { + priv->regmap = syscon_regmap_lookup_by_phandle(dev, "syscon"); + if (IS_ERR(priv->regmap)) { + dev_err(dev, "No syscon: %ld\n", PTR_ERR(priv->regmap)); + return PTR_ERR(priv->regmap); + } return 0; + } else { + if (IS_ENABLED(CONFIG_IMX_SM_LMM)) { + struct udevice *lmm_dev; + + ret = uclass_get_device_by_name(UCLASS_SCMI_BASE, "protocol@80", &lmm_dev); + if (ret) { + dev_err(dev, "Failed to get SM LMM protocol dev\n"); + return ret; + } + + priv->lmm_dev = lmm_dev; - priv->regmap = syscon_regmap_lookup_by_phandle(dev, "syscon"); - if (IS_ERR(priv->regmap)) { - dev_err(dev, "No syscon: %ld\n", PTR_ERR(priv->regmap)); - return PTR_ERR(priv->regmap); + ret = scmi_imx_lmm_info(lmm_dev, LMM_ID_DISCOVER, &info); + if (ret) { + dev_err(dev, "Failed to get lmm info\n"); + return ret; + } + + if (dcfg->lmid != info.lmid) { + ret = scmi_imx_lmm_power_boot(lmm_dev, dcfg->lmid, false); + if (ret == -EACCES) { + dev_err(dev, "Remoteproc not under U-boot control: only support detect running\n"); + } else if (ret) { + dev_err(dev, "power on lmm fail:%d\n", ret); + return ret; + } else { + priv->flags |= IMX_RPROC_FLAGS_SM_LMM_AVAIL; + } + } else { + priv->flags |= IMX_RPROC_FLAGS_SM_CPU_OP; + } + } + + if (IS_ENABLED(CONFIG_IMX_SM_CPU)) { + struct udevice *cpu_dev; + + ret = uclass_get_device_by_name(UCLASS_SCMI_BASE, "protocol@82", &cpu_dev); + if (ret) { + dev_err(dev, "Failed to get SM LMM protocol dev\n"); + return ret; + } + + priv->cpu_dev = cpu_dev; + } } return 0; @@ -351,12 +503,39 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = { .ops = &imx_rproc_ops_arm_smc, }; +static const struct imx_rproc_att imx_rproc_att_imx95_m7[] = { + /* dev addr , sys addr , size , flags */ + /* TCM CODE NON-SECURE */ + { 0x00000000, 0x203C0000, 0x00040000, ATT_OWN | ATT_IOMEM | ATT_ECC }, + + /* TCM SYS NON-SECURE*/ + { 0x20000000, 0x20400000, 0x00040000, ATT_OWN | ATT_IOMEM | ATT_ECC }, + + /* DDR */ + { 0x80000000, 0x80000000, 0x50000000, 0 }, +}; + +static const struct imx_rproc_plat_ops imx_rproc_ops_sm = { + .start = imx_rproc_sm_start, + .stop = imx_rproc_sm_stop, + .is_running = imx_rproc_sm_is_running, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx95_m7 = { + .att = imx_rproc_att_imx95_m7, + .att_size = ARRAY_SIZE(imx_rproc_att_imx95_m7), + .ops = &imx_rproc_ops_sm, + .cpuid = IMX95_M7_CPUID, + .lmid = IMX95_M7_LMID, +}; + static const struct udevice_id imx_rproc_ids[] = { { .compatible = "fsl,imx8mm-cm4", .data = (ulong)&imx_rproc_cfg_imx8mq }, { .compatible = "fsl,imx8mn-cm7", .data = (ulong)&imx_rproc_cfg_imx8mn, }, { .compatible = "fsl,imx8mp-cm7", .data = (ulong)&imx_rproc_cfg_imx8mn, }, { .compatible = "fsl,imx8mq-cm4", .data = (ulong)&imx_rproc_cfg_imx8mq }, { .compatible = "fsl,imx93-cm33", .data = (ulong)&imx_rproc_cfg_imx93 }, + { .compatible = "fsl,imx95-cm7", .data = (ulong)&imx_rproc_cfg_imx95_m7 }, {} }; diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h index 7a82dc4a195..1629bc7f6e7 100644 --- a/drivers/remoteproc/imx_rproc.h +++ b/drivers/remoteproc/imx_rproc.h @@ -51,6 +51,9 @@ struct imx_rproc_dcfg { enum imx_rproc_method method; u32 flags; const struct imx_rproc_plat_ops *ops; + /* For System Manager(SM) based SoCs, the IDs are from SM firmware */ + u32 cpuid; + u32 lmid; }; #endif /* _IMX_RPROC_H */ |
