[PATCH v2 00/17] imx: add i.MX95 support

CI:https://dev.azure.com/pengfan/uboot-ci/_build/results?buildId=10
Bootlog:
U-Boot SPL 2025.01-rc4-00356-g9dd9c3256131 (Dec 20 2024 - 10:37:50 +0800) DDRMIX is powered UP Normal Boot Trying to boot from MMC2 Primary set selected Load image from MMC/SD 0xdf400 NOTICE: BL31: v2.10.0 (release):android-14.0.0_2.2.0-rc1-1-g28affcae9 NOTICE: BL31: Built : 10:35:32, Aug 29 2024
U-Boot 2025.01-rc4-00356-g9dd9c3256131 (Dec 20 2024 - 10:37:50 +0800)
CPU: i.MX95 rev1.0 2000 MHz (running at 1800 MHz) CPU: Consumer temperature grade (0C to 95C) Model: NXP i.MX95 19X19 board DRAM: 15.8 GiB Core: 231 devices, 20 uclasses, devicetree: separate MMC: FSL_SDHC: 0, FSL_SDHC: 1 Loading Environment from MMC... Reading from MMC(1)... *** Warning - bad CRC, using default environment
In: serial@44380000 Out: serial@44380000 Err: serial@44380000
BuildInfo: - ELE firmware version 1.0.32-193e5781
switch to partitions #0, OK mmc1 is current device Net: No ethernet found. u-boot=>
Signed-off-by: Alice Guo alice.guo@nxp.com --- Alice Guo (3): imx: Kconfig: IMX8_ROMAPI is not configured for i.MX95 binman: add a new entry type for packing DDR PHY firmware images tools: imx8image: add i.MX95 support
Peng Fan (7): mailbox: add i.MX95 Messaging Unit (MU) driver pinctrl: nxp: add SCMI pin control protocol driver scmi_protocols: add SCMI misc protocol protocol_id and message_id for getting the ROM passover data scmi_protocols: add SCMI Performance domain management protocol message IDs clk: scmi: add the command CLOCK_PARENT_SET imx9: scmi: add i.MX95 SoC and clock related code scmi: add the macro SCMI_MSG
Teo Hall (1): imx: add V2X container support on i.MX95
Viorel Suman (1): firmware: scmi: smt: Interrupt communication enable
Ye Li (5): clk: scmi: check the clock state/parent/rate control permissions scmi_protocols: update struct scmi_base_discover_list_protocols_out imx9: add i.MX95 Kconfig and Makefile imx9: scmi: soc: Override h_spl_load_read with trampoline buffer imx95_evk: add i.MX95 19x19 EVK board basic support
MAINTAINERS | 1 + arch/arm/dts/imx95-19x19-evk-u-boot.dtsi | 224 +++++++ arch/arm/include/asm/arch-imx/cpu.h | 3 + arch/arm/include/asm/arch-imx9/clock.h | 10 +- arch/arm/include/asm/arch-imx9/imx-regs.h | 7 +- arch/arm/include/asm/arch-imx9/sys_proto.h | 3 +- arch/arm/include/asm/mach-imx/sys_proto.h | 40 ++ arch/arm/mach-imx/Kconfig | 2 +- arch/arm/mach-imx/image-container.c | 63 +- arch/arm/mach-imx/imx9/Kconfig | 12 + arch/arm/mach-imx/imx9/Makefile | 11 +- arch/arm/mach-imx/imx9/scmi/Makefile | 6 + arch/arm/mach-imx/imx9/scmi/clock.c | 328 ++++++++++ arch/arm/mach-imx/imx9/scmi/clock_scmi.c | 148 +++++ arch/arm/mach-imx/imx9/scmi/container.cfg | 10 + arch/arm/mach-imx/imx9/scmi/imximage.cfg | 15 + arch/arm/mach-imx/imx9/scmi/soc.c | 873 ++++++++++++++++++++++++++ arch/sandbox/include/asm/scmi_test.h | 2 + board/freescale/imx95_evk/Kconfig | 12 + board/freescale/imx95_evk/MAINTAINERS | 6 + board/freescale/imx95_evk/Makefile | 11 + board/freescale/imx95_evk/imx95_19x19_evk.env | 95 +++ board/freescale/imx95_evk/imx95_evk.c | 54 ++ board/freescale/imx95_evk/spl.c | 117 ++++ common/spl/spl_mmc.c | 2 +- configs/imx95_19x19_evk_defconfig | 178 ++++++ doc/board/nxp/imx95_evk.rst | 109 ++++ doc/board/nxp/index.rst | 1 + drivers/clk/clk_scmi.c | 191 +++++- drivers/firmware/scmi/sandbox-scmi_agent.c | 56 +- drivers/firmware/scmi/scmi_agent-uclass.c | 11 + drivers/firmware/scmi/smt.c | 4 + drivers/firmware/scmi/smt.h | 10 + drivers/mailbox/Kconfig | 7 + drivers/mailbox/Makefile | 1 + drivers/mailbox/imx-mailbox.c | 417 ++++++++++++ drivers/pinctrl/nxp/Kconfig | 13 + drivers/pinctrl/nxp/Makefile | 1 + drivers/pinctrl/nxp/pinctrl-imx.c | 7 +- drivers/pinctrl/nxp/pinctrl-imx.h | 11 + drivers/pinctrl/nxp/pinctrl-scmi.c | 136 ++++ include/configs/imx95_evk.h | 36 ++ include/imx8image.h | 19 +- include/scmi_agent-uclass.h | 2 + include/scmi_agent.h | 11 + include/scmi_protocols.h | 105 +++- tools/binman/entries.rst | 14 + tools/binman/etype/nxp_append_ddrfw.py | 78 +++ tools/imx8image.c | 143 ++++- tools/imx9_image.sh | 4 + 50 files changed, 3556 insertions(+), 64 deletions(-) --- base-commit: 078542c346347406cfacdec8adeac66ae6758880 change-id: 20241220-imx95-04a92b6744fe
Best regards,

From: Peng Fan peng.fan@nxp.com
i.MX95 Messaging Unit (MU) enables 2 processors on a chip to communicate and coordinate by passing messages (e.g. frame information, event notices and requests) through the MU interface. This patch provides a driver for i.MX95 MU using the common mailbox framework. Currently, SCMI exchanges on i.MX95 uses a mailbox transport with SMT format, and the hardware used is this MU.
Signed-off-by: Viorel Suman viorel.suman@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Ye Li ye.li@nxp.com --- MAINTAINERS | 1 + drivers/mailbox/Kconfig | 7 + drivers/mailbox/Makefile | 1 + drivers/mailbox/imx-mailbox.c | 417 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 426 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS index ba31f86feb6da266cddd160a041d0594ac86d274..5ab2b72d0f93afaf70c4c2dcb8fc48210683b749 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -313,6 +313,7 @@ F: board/freescale/*mx*/ F: board/freescale/common/ F: common/spl/spl_imx_container.c F: doc/imx/ +F: drivers/mailbox/imx-mailbox.c F: drivers/serial/serial_mxc.c F: include/imx_container.h
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 67d5ac1a74228ccd82b2725c0bb745354d099948..4d9f004ebad7f57034a6cdae3bff9645fa0ee67d 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -21,6 +21,13 @@ config APPLE_MBOX such as the System Management Controller (SMC) and NVMe and this driver is required to get that functionality up and running.
+config IMX_MU_MBOX + bool "Enable i.MX MU MBOX support" + depends on DM_MAILBOX + help + Enable support for i.MX Messaging Unit for communication with other + processors on the SoC using mailbox interface + config SANDBOX_MBOX bool "Enable the sandbox mailbox test driver" depends on DM_MAILBOX && SANDBOX diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 6072fa1956b793636c35aa0d1419c9dcaae27095..574add60005fe73d2beba715a12e0157fe4b0552 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -5,6 +5,7 @@
obj-$(CONFIG_$(XPL_)DM_MAILBOX) += mailbox-uclass.o obj-$(CONFIG_APPLE_MBOX) += apple-mbox.o +obj-$(CONFIG_IMX_MU_MBOX) += imx-mailbox.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox-test.o obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c new file mode 100644 index 0000000000000000000000000000000000000000..082c7740f4fc0155dce0e0ce861fec27f7a24ccc --- /dev/null +++ b/drivers/mailbox/imx-mailbox.c @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017-2023 NXP + */ + +#include <asm/io.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <mailbox-uclass.h> +#include <linux/bitfield.h> +#include <linux/bug.h> +#include <linux/iopoll.h> +#include <linux/compat.h> + +/* This driver only exposes the status bits to keep with the + * polling methodology of u-boot. + */ +DECLARE_GLOBAL_DATA_PTR; + +#define IMX_MU_CHANS 24 + +#define IMX_MU_V2_PAR_OFF 0x4 +#define IMX_MU_V2_TR_MASK GENMASK(7, 0) +#define IMX_MU_V2_RR_MASK GENMASK(15, 8) + +enum imx_mu_chan_type { + IMX_MU_TYPE_TX = 0, /* Tx */ + IMX_MU_TYPE_RX = 1, /* Rx */ + IMX_MU_TYPE_TXDB = 2, /* Tx doorbell */ + IMX_MU_TYPE_RXDB = 3, /* Rx doorbell */ + IMX_MU_TYPE_RST = 4, /* Reset */ + IMX_MU_TYPE_TXDB_V2 = 5, /* Tx doorbell with S/W ACK */ +}; + +enum imx_mu_xcr { + IMX_MU_CR, + IMX_MU_GIER, + IMX_MU_GCR, + IMX_MU_TCR, + IMX_MU_RCR, + IMX_MU_xCR_MAX, +}; + +enum imx_mu_xsr { + IMX_MU_SR, + IMX_MU_GSR, + IMX_MU_TSR, + IMX_MU_RSR, + IMX_MU_xSR_MAX, +}; + +struct imx_mu_con_priv { + unsigned int idx; + enum imx_mu_chan_type type; + struct mbox_chan *chan; +}; + +enum imx_mu_type { + IMX_MU_V1, + IMX_MU_V2 = BIT(1), + IMX_MU_V2_S4 = BIT(15), + IMX_MU_V2_IRQ = BIT(16), +}; + +struct imx_mu { + void __iomem *base; + const struct imx_mu_dcfg *dcfg; + u32 num_tr; + u32 num_rr; + /* use pointers to channel as a way to reserve channels */ + struct mbox_chan *channels[IMX_MU_CHANS]; + struct imx_mu_con_priv con_priv[IMX_MU_CHANS]; +}; + +struct imx_mu_dcfg { + int (*tx)(struct imx_mu *plat, struct imx_mu_con_priv *cp, const void *data); + int (*rx)(struct imx_mu *plat, struct imx_mu_con_priv *cp); + int (*rxdb)(struct imx_mu *plat, struct imx_mu_con_priv *cp); + int (*init)(struct imx_mu *plat); + int (*of_xlate)(struct mbox_chan *chan, struct ofnode_phandle_args *args); + enum imx_mu_type type; + u32 xTR; /* Transmit Register0 */ + u32 xRR; /* Receive Register0 */ + u32 xSR[IMX_MU_xSR_MAX]; /* Status Registers */ + u32 xCR[IMX_MU_xCR_MAX]; /* Control Registers */ +}; + +#define IMX_MU_xSR_GIPn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x)))) +#define IMX_MU_xSR_RFn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(24 + (3 - (x)))) +#define IMX_MU_xSR_TEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(20 + (3 - (x)))) + +/* General Purpose Interrupt Enable */ +#define IMX_MU_xCR_GIEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x)))) +/* Receive Interrupt Enable */ +#define IMX_MU_xCR_RIEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(24 + (3 - (x)))) +/* Transmit Interrupt Enable */ +#define IMX_MU_xCR_TIEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(20 + (3 - (x)))) +/* General Purpose Interrupt Request */ +#define IMX_MU_xCR_GIRn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(16 + (3 - (x)))) +/* MU reset */ +#define IMX_MU_xCR_RST(type) (type & IMX_MU_V2 ? BIT(0) : BIT(5)) +#define IMX_MU_xSR_RST(type) (type & IMX_MU_V2 ? BIT(0) : BIT(7)) + +static void imx_mu_write(struct imx_mu *plat, u32 val, u32 offs) +{ + iowrite32(val, plat->base + offs); +} + +static u32 imx_mu_read(struct imx_mu *plat, u32 offs) +{ + return ioread32(plat->base + offs); +} + +static u32 imx_mu_xcr_rmw(struct imx_mu *plat, enum imx_mu_xcr type, u32 set, u32 clr) +{ + u32 val; + + val = imx_mu_read(plat, plat->dcfg->xCR[type]); + val &= ~clr; + val |= set; + imx_mu_write(plat, val, plat->dcfg->xCR[type]); + + return val; +} + +/* check that the channel is open or owned by caller */ +static int imx_mu_check_channel(struct mbox_chan *chan) +{ + struct imx_mu *plat = dev_get_plat(chan->dev); + + if (plat->channels[chan->id] != NULL) { + /* if reserved check that caller owns */ + if (plat->channels[chan->id] == chan) + return 1; /* caller owns the channel */ + + return -EACCES; + } + + return 0; /* channel empty */ +} + +static int imx_mu_chan_request(struct mbox_chan *chan) +{ + struct imx_mu *plat = dev_get_plat(chan->dev); + struct imx_mu_con_priv *cp; + enum imx_mu_chan_type type; + int idx; + + type = chan->id / 4; + idx = chan->id % 4; + + if (imx_mu_check_channel(chan) < 0) /* check if channel already in use */ + return -EPERM; + + plat->channels[chan->id] = chan; + chan->con_priv = kcalloc(1, sizeof(struct imx_mu_con_priv), 0); + if (!chan->con_priv) + return -ENOMEM; + cp = chan->con_priv; + cp->idx = idx; + cp->type = type; + cp->chan = chan; + + switch (type) { + case IMX_MU_TYPE_RX: + imx_mu_xcr_rmw(plat, IMX_MU_RCR, IMX_MU_xCR_RIEn(plat->dcfg->type, idx), 0); + break; + case IMX_MU_TYPE_TXDB_V2: + case IMX_MU_TYPE_TXDB: + case IMX_MU_TYPE_RXDB: + imx_mu_xcr_rmw(plat, IMX_MU_GIER, IMX_MU_xCR_GIEn(plat->dcfg->type, idx), 0); + break; + default: + break; + } + + return 0; +} + +static int imx_mu_chan_free(struct mbox_chan *chan) +{ + struct imx_mu *plat = dev_get_plat(chan->dev); + struct imx_mu_con_priv *cp = chan->con_priv; + + if (imx_mu_check_channel(chan) <= 0) /* check that the channel is also not empty */ + return -EINVAL; + + /* if you own channel and channel is NOT empty */ + plat->channels[chan->id] = NULL; + switch (cp->type) { + case IMX_MU_TYPE_TX: + imx_mu_xcr_rmw(plat, IMX_MU_TCR, 0, IMX_MU_xCR_TIEn(plat->dcfg->type, cp->idx)); + break; + case IMX_MU_TYPE_RX: + imx_mu_xcr_rmw(plat, IMX_MU_RCR, 0, IMX_MU_xCR_RIEn(plat->dcfg->type, cp->idx)); + break; + case IMX_MU_TYPE_TXDB_V2: + case IMX_MU_TYPE_TXDB: + case IMX_MU_TYPE_RXDB: + imx_mu_xcr_rmw(plat, IMX_MU_GIER, 0, IMX_MU_xCR_GIEn(plat->dcfg->type, cp->idx)); + break; + default: + break; + } + + kfree(cp); + + return 0; +} + +static int imx_mu_send(struct mbox_chan *chan, const void *data) +{ + struct imx_mu *plat = dev_get_plat(chan->dev); + struct imx_mu_con_priv *cp = chan->con_priv; + + if (imx_mu_check_channel(chan) < 1) /* return if channel isn't owned */ + return -EPERM; + + return plat->dcfg->tx(plat, cp, data); +} + +static int imx_mu_recv(struct mbox_chan *chan, void *data) +{ + struct imx_mu *plat = dev_get_plat(chan->dev); + struct imx_mu_con_priv *cp = chan->con_priv; + u32 ctrl, val; + + if (imx_mu_check_channel(chan) < 1) /* return if channel isn't owned */ + return -EPERM; + + switch (cp->type) { + case IMX_MU_TYPE_TXDB_V2: + case IMX_MU_TYPE_RXDB: + /* check if GSR[GIRn] bit is set */ + if (readx_poll_timeout(ioread32, plat->base + plat->dcfg->xSR[IMX_MU_GSR], + val, val & BIT(cp->idx), 1000000) < 0) + return -EBUSY; + + ctrl = imx_mu_read(plat, plat->dcfg->xCR[IMX_MU_GIER]); + val = imx_mu_read(plat, plat->dcfg->xSR[IMX_MU_GSR]); + val &= IMX_MU_xSR_GIPn(plat->dcfg->type, cp->idx) & + (ctrl & IMX_MU_xCR_GIEn(plat->dcfg->type, cp->idx)); + break; + default: + dev_warn(chan->dev, "Unhandled channel type %d\n", cp->type); + return -EOPNOTSUPP; + }; + + if (val == IMX_MU_xSR_GIPn(plat->dcfg->type, cp->idx)) + plat->dcfg->rxdb(plat, cp); + + return 0; +} + +static int imx_mu_of_to_plat(struct udevice *dev) +{ + struct imx_mu *plat = dev_get_plat(dev); + fdt_addr_t addr; + + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -ENODEV; + + plat->base = (struct mu_type *)addr; + + return 0; +} + +static int imx_mu_init_generic(struct imx_mu *plat) +{ + unsigned int i; + unsigned int val; + + if (plat->num_rr > 4 || plat->num_tr > 4) { + WARN_ONCE(true, "%s not support TR/RR larger than 4\n", __func__); + return -EOPNOTSUPP; + } + + /* Set default MU configuration */ + for (i = 0; i < IMX_MU_xCR_MAX; i++) + imx_mu_write(plat, 0, plat->dcfg->xCR[i]); + + /* Clear any pending GIP */ + val = imx_mu_read(plat, plat->dcfg->xSR[IMX_MU_GSR]); + imx_mu_write(plat, val, plat->dcfg->xSR[IMX_MU_GSR]); + + /* Clear any pending RSR */ + for (i = 0; i < plat->num_rr; i++) + imx_mu_read(plat, plat->dcfg->xRR + i * 4); + + return 0; +} + +static int imx_mu_generic_of_xlate(struct mbox_chan *chan, struct ofnode_phandle_args *args) +{ + enum imx_mu_chan_type type; + int idx, cid; + + if (args->args_count != 2) { + dev_err(chan->dev, "Invalid argument count %d\n", args->args_count); + return -EINVAL; + } + + type = args->args[0]; /* channel type */ + idx = args->args[1]; /* index */ + + cid = type * 4 + idx; + if (cid >= IMX_MU_CHANS) { + dev_err(chan->dev, "Not supported channel number: %d. (type: %d, idx: %d)\n", + cid, type, idx); + return -EINVAL; + } + + chan->id = cid; + + return 0; +} + +static int imx_mu_generic_tx(struct imx_mu *plat, struct imx_mu_con_priv *cp, + const void *data) +{ + switch (cp->type) { + case IMX_MU_TYPE_TXDB_V2: + imx_mu_xcr_rmw(plat, IMX_MU_GCR, IMX_MU_xCR_GIRn(plat->dcfg->type, cp->idx), 0); + break; + default: + dev_warn(cp->chan->dev, "Send data on wrong channel type: %d\n", cp->type); + return -EINVAL; + } + + return 0; +} + +static int imx_mu_generic_rxdb(struct imx_mu *plat, struct imx_mu_con_priv *cp) +{ + imx_mu_write(plat, IMX_MU_xSR_GIPn(plat->dcfg->type, cp->idx), + plat->dcfg->xSR[IMX_MU_GSR]); + + return 0; +} + +static const struct imx_mu_dcfg imx_mu_cfg_imx95 = { + .tx = imx_mu_generic_tx, + .rxdb = imx_mu_generic_rxdb, + .init = imx_mu_init_generic, + .of_xlate = imx_mu_generic_of_xlate, + .type = IMX_MU_V2, + .xTR = 0x200, + .xRR = 0x280, + .xSR = {0xC, 0x118, 0x124, 0x12C}, + .xCR = {0x8, 0x110, 0x114, 0x120, 0x128}, +}; + +static const struct udevice_id ids[] = { + { .compatible = "fsl,imx95-mu", .data = (ulong)&imx_mu_cfg_imx95 }, + { } +}; + +int imx_mu_of_xlate(struct mbox_chan *chan, struct ofnode_phandle_args *args) +{ + struct imx_mu *plat = dev_get_plat(chan->dev); + + return plat->dcfg->of_xlate(chan, args); +} + +struct mbox_ops imx_mu_ops = { + .of_xlate = imx_mu_of_xlate, + .request = imx_mu_chan_request, + .rfree = imx_mu_chan_free, + .send = imx_mu_send, + .recv = imx_mu_recv, +}; + +static void imx_mu_get_tr_rr(struct imx_mu *plat) +{ + u32 val; + + if (plat->dcfg->type & IMX_MU_V2) { + val = imx_mu_read(plat, IMX_MU_V2_PAR_OFF); + plat->num_tr = FIELD_GET(IMX_MU_V2_TR_MASK, val); + plat->num_rr = FIELD_GET(IMX_MU_V2_RR_MASK, val); + } else { + plat->num_tr = 4; + plat->num_rr = 4; + } +} + +static int imx_mu_probe(struct udevice *dev) +{ + struct imx_mu *plat = dev_get_plat(dev); + int ret; + + debug("%s(dev=%p)\n", __func__, dev); + + plat->dcfg = (void *)dev_get_driver_data(dev); + + imx_mu_get_tr_rr(plat); + + ret = plat->dcfg->init(plat); + if (ret) { + dev_err(dev, "Failed to init MU\n"); + return ret; + } + + return 0; +} + +U_BOOT_DRIVER(imx_mu) = { + .name = "imx-mu", + .id = UCLASS_MAILBOX, + .of_match = ids, + .of_to_plat = imx_mu_of_to_plat, + .plat_auto = sizeof(struct imx_mu), + .probe = imx_mu_probe, + .ops = &imx_mu_ops, + .flags = DM_FLAG_PRE_RELOC, +};

From: Viorel Suman viorel.suman@nxp.com
When interrupt driven communication is supported, the transport allows the caller to choose between interrupt and polling driven communications. To make the choice, the channel flags are used. i.MX95 uses interrupt driven communication so that Channel flags should be set to 1.
Signed-off-by: Viorel Suman viorel.suman@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Ye Li ye.li@nxp.com --- drivers/firmware/scmi/smt.c | 4 ++++ drivers/firmware/scmi/smt.h | 10 ++++++++++ 2 files changed, 14 insertions(+)
diff --git a/drivers/firmware/scmi/smt.c b/drivers/firmware/scmi/smt.c index 67d2f45002490ab64a6bc997eda93a8f4681d99b..e5b902dcb0e641065f4c0faae6bc6660a7e2c6af 100644 --- a/drivers/firmware/scmi/smt.c +++ b/drivers/firmware/scmi/smt.c @@ -48,6 +48,10 @@ int scmi_dt_get_smt_buffer(struct udevice *dev, struct scmi_smt *smt) if (!smt->buf) return -ENOMEM;
+ /* Command should complete via an interrupt so that set Channel flags to 1. */ + if (IS_ENABLED(CONFIG_IMX95)) + scmi_smt_enable_intr(smt, true); + #ifdef CONFIG_ARM if (dcache_status()) mmu_set_region_dcache_behaviour(ALIGN_DOWN((uintptr_t)smt->buf, MMU_SECTION_SIZE), diff --git a/drivers/firmware/scmi/smt.h b/drivers/firmware/scmi/smt.h index 9d669a6c922666c48e7dce4c0affd7b47cb137e4..768b0f4c8a8d1cc7966530e724d278d72c2a167b 100644 --- a/drivers/firmware/scmi/smt.h +++ b/drivers/firmware/scmi/smt.h @@ -84,6 +84,16 @@ static inline void scmi_smt_put_channel(struct scmi_smt *smt) hdr->channel_status &= ~SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR; }
+static inline void scmi_smt_enable_intr(struct scmi_smt *smt, bool enable) +{ + struct scmi_smt_header *hdr = (void *)smt->buf; + + if (enable) + hdr->flags |= SCMI_SHMEM_FLAG_INTR_ENABLED; + else + hdr->flags &= ~SCMI_SHMEM_FLAG_INTR_ENABLED; +} + int scmi_dt_get_smt_buffer(struct udevice *dev, struct scmi_smt *smt);
/*

From: Peng Fan peng.fan@nxp.com
This patch provides a driver for the SCMI pin control protocol which is based on ARM's System Control and Management Interface (SCMI) 3.2. Currently, only the PINCTRL_CONFIG_SET command is implemented.
Signed-off-by: Ranjani Vaidyanathan Ranjani.Vaidyanathan@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Ye Li ye.li@nxp.com --- drivers/firmware/scmi/scmi_agent-uclass.c | 11 +++ drivers/pinctrl/nxp/Kconfig | 13 +++ drivers/pinctrl/nxp/Makefile | 1 + drivers/pinctrl/nxp/pinctrl-imx.c | 7 +- drivers/pinctrl/nxp/pinctrl-imx.h | 11 +++ drivers/pinctrl/nxp/pinctrl-scmi.c | 136 ++++++++++++++++++++++++++++++ include/scmi_agent-uclass.h | 2 + include/scmi_protocols.h | 34 ++++++++ 8 files changed, 213 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index 8c907c3b0328095c4b35ba089ed608fcda48b567..5f101f4ede8b585f8c562a42886ea7be4ef09953 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -97,6 +97,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev, case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: proto = priv->voltagedom_dev; break; + case SCMI_PROTOCOL_ID_PINCTRL: + proto = priv->pinctrl_dev; + break; default: dev_err(dev, "Protocol not supported\n"); proto = NULL; @@ -147,6 +150,9 @@ static int scmi_add_protocol(struct udevice *dev, case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: priv->voltagedom_dev = proto; break; + case SCMI_PROTOCOL_ID_PINCTRL: + priv->pinctrl_dev = proto; + break; default: dev_err(dev, "Protocol not supported\n"); return -EPROTO; @@ -436,6 +442,11 @@ static int scmi_bind_protocols(struct udevice *dev) drv = DM_DRIVER_GET(scmi_voltage_domain); } break; + case SCMI_PROTOCOL_ID_PINCTRL: + if (IS_ENABLED(CONFIG_PINCTRL_IMX_SCMI) && + scmi_protocol_is_supported(dev, protocol_id)) + drv = DM_DRIVER_GET(scmi_pinctrl_imx); + break; default: break; } diff --git a/drivers/pinctrl/nxp/Kconfig b/drivers/pinctrl/nxp/Kconfig index 06c26f156f6c8f63204604d6065485629cfd9b61..0086f9825837bf568bd7633a21da860e410eeeee 100644 --- a/drivers/pinctrl/nxp/Kconfig +++ b/drivers/pinctrl/nxp/Kconfig @@ -1,6 +1,19 @@ config PINCTRL_IMX bool
+config PINCTRL_IMX_SCMI + bool "IMX pinctrl SCMI driver" + depends on ARCH_IMX9 && PINCTRL_FULL + select PINCTRL_IMX + help + Say Y here to enable the imx pinctrl scmi driver + + This provides a simple pinctrl driver for i.MX SoC which supports + SCMI. This feature depends on device tree configuration. This driver + is different from the linux one, this is a simple implementation, + only parses the 'fsl,pins' property and configure related + registers. + config PINCTRL_IMX_SCU bool
diff --git a/drivers/pinctrl/nxp/Makefile b/drivers/pinctrl/nxp/Makefile index f10aa6ef188e37583b181bdf9d70ac191e506d75..3ec3e2a9c6fdb875da4ae9bf151df5666256883b 100644 --- a/drivers/pinctrl/nxp/Makefile +++ b/drivers/pinctrl/nxp/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_PINCTRL_IMX6) += pinctrl-imx6.o obj-$(CONFIG_PINCTRL_IMX7) += pinctrl-imx7.o obj-$(CONFIG_PINCTRL_IMX7ULP) += pinctrl-imx7ulp.o obj-$(CONFIG_PINCTRL_IMX8ULP) += pinctrl-imx8ulp.o +obj-$(CONFIG_PINCTRL_IMX_SCMI) += pinctrl-scmi.o obj-$(CONFIG_PINCTRL_IMX_SCU) += pinctrl-scu.o obj-$(CONFIG_PINCTRL_IMX8) += pinctrl-imx8.o obj-$(CONFIG_PINCTRL_IMX8M) += pinctrl-imx8m.o diff --git a/drivers/pinctrl/nxp/pinctrl-imx.c b/drivers/pinctrl/nxp/pinctrl-imx.c index b1960c56b512cc113a810304dc3ac3f99b237a7e..3d53d0cd4b60c0685dd4c73c23e61cb712cda0ee 100644 --- a/drivers/pinctrl/nxp/pinctrl-imx.c +++ b/drivers/pinctrl/nxp/pinctrl-imx.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2016 Peng Fan van.freenix@gmail.com + * Copyright 2024 NXP */
#include <malloc.h> @@ -65,7 +66,9 @@ static int imx_pinctrl_set_state(struct udevice *dev, struct udevice *config)
npins = size / pin_size;
- if (info->flags & IMX8_USE_SCU) { + if (info->flags & IMX_USE_SCMI) { + return imx_pinctrl_scmi_conf_pins(dev, pin_data, npins); + } else if (info->flags & IMX8_USE_SCU) { imx_pinctrl_scu_conf_pins(info, pin_data, npins); } else { /* @@ -216,7 +219,7 @@ int imx_pinctrl_probe(struct udevice *dev, priv->dev = dev; priv->info = info;
- if (info->flags & IMX8_USE_SCU) + if ((info->flags & IMX8_USE_SCU) || (info->flags & IMX_USE_SCMI)) return 0;
addr = ofnode_get_addr_size_index(dev_ofnode(dev), 0, &size); diff --git a/drivers/pinctrl/nxp/pinctrl-imx.h b/drivers/pinctrl/nxp/pinctrl-imx.h index fa4c084e2fc067fcb4e92c33312d4f430081fffd..b2f8865ded0ae380fc0156baa5eaea505c12f501 100644 --- a/drivers/pinctrl/nxp/pinctrl-imx.h +++ b/drivers/pinctrl/nxp/pinctrl-imx.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2016 Peng Fan van.freenix@gmail.com + * Copyright 2024 NXP */
#ifndef __DRIVERS_PINCTRL_IMX_H @@ -47,6 +48,7 @@ extern const struct pinctrl_ops imx_pinctrl_ops; #define ZERO_OFFSET_VALID 0x2 #define CFG_IBE_OBE 0x4 #define IMX8_USE_SCU 0x8 +#define IMX_USE_SCMI 0x10
#define IOMUXC_CONFIG_SION (0x1 << 4)
@@ -65,4 +67,13 @@ static inline int imx_pinctrl_scu_conf_pins(struct imx_pinctrl_soc_info *info, } #endif
+#ifdef CONFIG_PINCTRL_IMX_SCMI +int imx_pinctrl_scmi_conf_pins(struct udevice *dev, u32 *pin_data, int npins); +#else +static inline int imx_pinctrl_scmi_conf_pins(struct udevice *dev, u32 *pin_data, int npins) +{ + return 0; +} +#endif + #endif /* __DRIVERS_PINCTRL_IMX_H */ diff --git a/drivers/pinctrl/nxp/pinctrl-scmi.c b/drivers/pinctrl/nxp/pinctrl-scmi.c new file mode 100644 index 0000000000000000000000000000000000000000..19b1b433a5ced0bb85e52f4d19bdeab2825f275e --- /dev/null +++ b/drivers/pinctrl/nxp/pinctrl-scmi.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include <dm.h> +#include <dm/device_compat.h> +#include <errno.h> +#include <misc.h> +#include <scmi_agent.h> +#include <scmi_protocols.h> +#include <asm/io.h> +#include <asm/mach-imx/iomux-v3.h> +#include <linux/bitops.h> + +#include "pinctrl-imx.h" + +#if defined(CONFIG_IMX93) +#define DAISY_OFFSET 0x360 +#endif +#if defined(CONFIG_IMX95) +#define DAISY_OFFSET 0x408 +#endif + +/* SCMI pin control types */ +#define PINCTRL_TYPE_MUX 192 +#define PINCTRL_TYPE_CONFIG 193 +#define PINCTRL_TYPE_DAISY_ID 194 +#define PINCTRL_TYPE_DAISY_CFG 195 +#define PINCTRL_NUM_CFGS_SHIFT 2 + +static int imx_pinconf_scmi_set(struct udevice *dev, u32 mux_ofs, u32 mux, u32 config_val, + u32 input_ofs, u32 input_val) +{ + int ret, num_cfgs = 0; + + /* Call SCMI API to set the pin mux and configuration. */ + struct scmi_pinctrl_config_set_out out; + struct scmi_pinctrl_config_set_in in = { + .identifier = mux_ofs / 4, + .function_id = 0xFFFFFFFF, + .attributes = 0, + }; + if (mux_ofs != 0) { + in.configs[num_cfgs].type = PINCTRL_TYPE_MUX; + in.configs[num_cfgs].val = mux; + num_cfgs++; + } + if (config_val != 0) { + in.configs[num_cfgs].type = PINCTRL_TYPE_CONFIG; + in.configs[num_cfgs].val = config_val; + num_cfgs++; + } + if (input_ofs != 0) { + in.configs[num_cfgs].type = PINCTRL_TYPE_DAISY_ID; + in.configs[num_cfgs].val = (input_ofs - DAISY_OFFSET) / 4; + num_cfgs++; + in.configs[num_cfgs].type = PINCTRL_TYPE_DAISY_CFG; + in.configs[num_cfgs].val = input_val; + num_cfgs++; + } + /* Update the number of configs sent in this call. */ + in.attributes = num_cfgs << PINCTRL_NUM_CFGS_SHIFT; + + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_PINCTRL, + SCMI_MSG_PINCTRL_CONFIG_SET, in, out); + + ret = devm_scmi_process_msg(dev, &msg); + if (ret != 0 || out.status != 0) + dev_err(dev, "Failed to set PAD = %d, daisy = %d, scmi_err = %d, ret = %d\n", mux_ofs / 4, input_ofs / 4, out.status, ret); + + return ret; +} + +int imx_pinctrl_scmi_conf_pins(struct udevice *dev, u32 *pin_data, int npins) +{ + int mux_ofs, mux, config_val, input_reg, input_val; + int i, j = 0; + int ret; + + /* + * Refer to linux documentation for details: + * Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt + */ + for (i = 0; i < npins; i++) { + mux_ofs = pin_data[j++]; + /* Skip config_reg */ + j++; + input_reg = pin_data[j++]; + + mux = pin_data[j++]; + input_val = pin_data[j++]; + config_val = pin_data[j++]; + + if (config_val & IMX_PAD_SION) + mux |= IOMUXC_CONFIG_SION; + + config_val &= ~IMX_PAD_SION; + + ret = imx_pinconf_scmi_set(dev, mux_ofs, mux, config_val, input_reg, input_val); + if (ret && ret != -EPERM) + dev_err(dev, "Set pin %d, mux %d, val %d, error\n", + mux_ofs, mux, config_val); + } + + return ret; +} + +static struct imx_pinctrl_soc_info imx_pinctrl_scmi_soc_info __section(".data") = { + .flags = ZERO_OFFSET_VALID | IMX_USE_SCMI, +}; + +static int imx_scmi_pinctrl_probe(struct udevice *dev) +{ + struct imx_pinctrl_priv *priv = dev_get_priv(dev); + int ret; + + ret = devm_scmi_of_get_channel(dev); + if (ret) { + dev_err(dev, "get channel: %d\n", ret); + return ret; + } + + debug("%s %p %s\n", __func__, priv, dev->name); + return imx_pinctrl_probe(dev, &imx_pinctrl_scmi_soc_info); +} + +U_BOOT_DRIVER(scmi_pinctrl_imx) = { + .name = "scmi_pinctrl_imx", + .id = UCLASS_PINCTRL, + .probe = imx_scmi_pinctrl_probe, + .remove = imx_pinctrl_remove, + .priv_auto = sizeof(struct imx_pinctrl_priv), + .ops = &imx_pinctrl_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/include/scmi_agent-uclass.h b/include/scmi_agent-uclass.h index 33e0e18c30d4ae4ddaaa2cb3830c03cd7a559cc0..4beec43cb080b14a777cac1cb0f18ef53433596c 100644 --- a/include/scmi_agent-uclass.h +++ b/include/scmi_agent-uclass.h @@ -27,6 +27,7 @@ struct scmi_channel; * @clock_dev: SCMI clock protocol device * @resetdom_dev: SCMI reset domain protocol device * @voltagedom_dev: SCMI voltage domain protocol device + * @pinctrl_dev: SCMI pin control protocol device */ struct scmi_agent_priv { u32 version; @@ -43,6 +44,7 @@ struct scmi_agent_priv { struct udevice *clock_dev; struct udevice *resetdom_dev; struct udevice *voltagedom_dev; + struct udevice *pinctrl_dev; };
static inline u32 scmi_version(struct udevice *dev) diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h index 7abb2a6f36ba53223bd9103fcc02f58506fbfc8d..2367467512a6b65253317e51bea71de396aa96f9 100644 --- a/include/scmi_protocols.h +++ b/include/scmi_protocols.h @@ -24,6 +24,7 @@ enum scmi_std_protocol { SCMI_PROTOCOL_ID_SENSOR = 0x15, SCMI_PROTOCOL_ID_RESET_DOMAIN = 0x16, SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN = 0x17, + SCMI_PROTOCOL_ID_PINCTRL = 0x19, };
enum scmi_status_code { @@ -1005,4 +1006,37 @@ struct scmi_voltd_level_get_out { s32 voltage_level; };
+/* SCMI Pinctrl Protocol */ +enum scmi_pinctrl_message_id { + SCMI_MSG_PINCTRL_CONFIG_SET = 0x6 +}; + +struct scmi_pin_config { + u32 type; + u32 val; +}; + +/** + * struct scmi_pad_config_set_in - Message payload for PAD_CONFIG_SET command + * @identifier: Identifier for the pin or group. + * @function_id: Identifier for the function selected to be enabled for the + * selected pin or group. This field is set to 0xFFFFFFFF if no + * function should be enabled by the pin or group. + * @attributes: Bits[31:11] Reserved, must be zero. + * Bit[10] Function valid. + * Bits[9:2] Number of configurations to set. + * Bits[1:0] Selector: Whether the identifier field refers to a pin or a group. + * @configs: Array of configurations. + */ +struct scmi_pinctrl_config_set_in { + u32 identifier; + u32 function_id; + u32 attributes; + struct scmi_pin_config configs[4]; +}; + +struct scmi_pinctrl_config_set_out { + s32 status; +}; + #endif /* _SCMI_PROTOCOLS_H */

From: Peng Fan peng.fan@nxp.com
SCMI misc protocol is intended for miscellaneous functions which are device specific and are usually defined to access bit fields. This patch adds SCMI misc protocol protocol_id and message_id for getting the ROM passover data.
Signed-off-by: Peng Fan peng.fan@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Ye Li ye.li@nxp.com --- include/scmi_protocols.h | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h index 2367467512a6b65253317e51bea71de396aa96f9..6cda1f00df1f6baf6db65a28b4cab114f8540a4b 100644 --- a/include/scmi_protocols.h +++ b/include/scmi_protocols.h @@ -25,6 +25,7 @@ enum scmi_std_protocol { SCMI_PROTOCOL_ID_RESET_DOMAIN = 0x16, SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN = 0x17, SCMI_PROTOCOL_ID_PINCTRL = 0x19, + SCMI_PROTOCOL_ID_IMX_MISC = 0x84, };
enum scmi_status_code { @@ -50,6 +51,10 @@ enum scmi_discovery_id { SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x2, };
+enum scmi_imx_misc_message_id { + SCMI_MISC_ROM_PASSOVER_GET = 0x7 +}; + /* * SCMI Base Protocol */

From: Peng Fan peng.fan@nxp.com
SCMI Performance domain management protocol is intended for performance management of groups of devices or APs that run in the same performance domain. The functionality provided by the callee-side can be used by passing the corresponding message_id.
Signed-off-by: Peng Fan peng.fan@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Ye Li ye.li@nxp.com --- include/scmi_protocols.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h index 6cda1f00df1f6baf6db65a28b4cab114f8540a4b..08c86a642844570424dddbfcf9670d1e6757d8d1 100644 --- a/include/scmi_protocols.h +++ b/include/scmi_protocols.h @@ -1044,4 +1044,22 @@ struct scmi_pinctrl_config_set_out { s32 status; };
+/* SCMI Perf Protocol */ +enum scmi_perf_message_id { + SCMI_PERF_DOMAIN_ATTRIBUTES = 0x3, + SCMI_PERF_DESCRIBE_LEVELS = 0x4, + SCMI_PERF_LIMITS_SET = 0x5, + SCMI_PERF_LIMITS_GET = 0x6, + SCMI_PERF_LEVEL_SET = 0x7, + SCMI_PERF_LEVEL_GET = 0x8 +}; + +struct scmi_perf_in { + u32 domain_id; + u32 perf_level; +}; + +struct scmi_perf_out { + s32 status; +}; #endif /* _SCMI_PROTOCOLS_H */

From: Peng Fan peng.fan@nxp.com
This patch adds the command CLOCK_PARENT_SET that can be used to set the parent of a clock. ARM SCMI Version 3.2 supports to change the parent of a clock device.
Signed-off-by: Peng Fan peng.fan@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Ye Li ye.li@nxp.com --- drivers/clk/clk_scmi.c | 20 ++++++++++++++++++++ include/scmi_protocols.h | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+)
diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c index e42d2032d45e011b751c19b395b6f99d5c54e78e..84333cdd0ccfe566c269f776f39725c69883c25c 100644 --- a/drivers/clk/clk_scmi.c +++ b/drivers/clk/clk_scmi.c @@ -178,11 +178,31 @@ static int scmi_clk_probe(struct udevice *dev) return 0; }
+static int scmi_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct scmi_clk_parent_set_in in = { + .clock_id = clk->id, + .parent_clk = parent->id, + }; + struct scmi_clk_parent_set_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, + SCMI_CLOCK_PARENT_SET, + in, out); + int ret; + + ret = devm_scmi_process_msg(clk->dev, &msg); + if (ret < 0) + return ret; + + return scmi_to_linux_errno(out.status); +} + static const struct clk_ops scmi_clk_ops = { .enable = scmi_clk_enable, .disable = scmi_clk_disable, .get_rate = scmi_clk_get_rate, .set_rate = scmi_clk_set_rate, + .set_parent = scmi_clk_set_parent, };
U_BOOT_DRIVER(scmi_clock) = { diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h index 08c86a642844570424dddbfcf9670d1e6757d8d1..d529f8e2697472e60d0cb9c275f34ef0ecaed3ca 100644 --- a/include/scmi_protocols.h +++ b/include/scmi_protocols.h @@ -737,6 +737,7 @@ enum scmi_clock_message_id { SCMI_CLOCK_RATE_SET = 0x5, SCMI_CLOCK_RATE_GET = 0x6, SCMI_CLOCK_CONFIG_SET = 0x7, + SCMI_CLOCK_PARENT_SET = 0xD };
#define SCMI_CLK_PROTO_ATTR_COUNT_MASK GENMASK(15, 0) @@ -839,6 +840,24 @@ struct scmi_clk_rate_set_out { s32 status; };
+/** + * struct scmi_clk_parent_state_in - Message payload for CLOCK_PARENT_SET command + * @clock_id: SCMI clock ID + * @parent_clk: SCMI clock ID + */ +struct scmi_clk_parent_set_in { + u32 clock_id; + u32 parent_clk; +}; + +/** + * struct scmi_clk_parent_set_out - Response payload for CLOCK_PARENT_SET command + * @status: SCMI command status + */ +struct scmi_clk_parent_set_out { + s32 status; +}; + /* * SCMI Reset Domain Protocol */

From: Ye Li ye.li@nxp.com
SCMI clock management protocol driver in Linux checks clock state, parent and rate control permissions. To be consistent with the kernel driver, add this check here.
When using common clock framework (CCF), use the clock signal ID to get the clock registered by clk_register() in scmi_clk_probe(), and then obatin the struct clk_scmi variable with container_of().
Signed-off-by: Alice Guo alice.guo@nxp.com Signed-off-by: Ye Li ye.li@nxp.com Reviewed-by: Peng Fan peng.fan@nxp.com --- arch/sandbox/include/asm/scmi_test.h | 2 + drivers/clk/clk_scmi.c | 173 +++++++++++++++++++++++++++-- drivers/firmware/scmi/sandbox-scmi_agent.c | 56 +++++++++- include/scmi_protocols.h | 26 ++++- 4 files changed, 243 insertions(+), 14 deletions(-)
diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h index 619f8f5098cdd82ba2343897166c34c82c753422..b30e536a35771ec3e1439c1e64fd09de3728dc50 100644 --- a/arch/sandbox/include/asm/scmi_test.h +++ b/arch/sandbox/include/asm/scmi_test.h @@ -27,10 +27,12 @@ struct sandbox_scmi_pwd { * @id: Identifier of the clock used in the SCMI protocol * @enabled: Clock state: true if enabled, false if disabled * @rate: Clock rate in Hertz + * @perm: Indicating state/parent/rate permission */ struct sandbox_scmi_clk { bool enabled; ulong rate; + u32 perm; };
/** diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c index 84333cdd0ccfe566c269f776f39725c69883c25c..af15fa910480989bd21404c7cec516be737704b7 100644 --- a/drivers/clk/clk_scmi.c +++ b/drivers/clk/clk_scmi.c @@ -12,6 +12,56 @@ #include <asm/types.h> #include <linux/clk-provider.h>
+struct clk_scmi { + struct clk clk; + u32 ctrl_flags; +}; + +static int scmi_clk_get_permissions(struct udevice *dev, int clkid, u32 *perm) +{ + u32 version; + int ret; + + ret = scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_CLOCK, &version); + if (ret) { + debug("get SCMI clock management protocol version failed\n"); + return ret; + } + + if (version >= CLOCK_PROTOCOL_VERSION_3_0) { + struct scmi_clk_get_permissions_in in = { + .clock_id = clkid, + }; + struct scmi_clk_get_permissions_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_CLOCK, + .message_id = SCMI_CLOCK_GET_PERMISSIONS, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) { + debug("get SCMI clock management protocol permissions failed\n"); + return ret; + } + + ret = scmi_to_linux_errno(out.status); + if (ret < 0) { + debug("the status code of getting permissions: %d\n", ret); + return ret; + } + + *perm = out.permissions; + return 0; + } + + debug("SCMI clock management protocol version is less than 3.0.\n"); + return -1; +} + static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks) { struct scmi_clk_protocol_attr_out out; @@ -32,7 +82,8 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks) return 0; }
-static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name) +static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name, + u32 *attr) { struct scmi_clk_attribute_in in = { .clock_id = clkid, @@ -53,6 +104,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name) return ret;
*name = strdup(out.clock_name); + *attr = out.attributes;
return 0; } @@ -78,11 +130,49 @@ static int scmi_clk_gate(struct clk *clk, int enable)
static int scmi_clk_enable(struct clk *clk) { + struct clk_scmi *clkscmi; + struct clk *c; + int ret; + + if (CONFIG_IS_ENABLED(CLK_CCF)) { + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + clkscmi = container_of(c, struct clk_scmi, clk); + + if (clkscmi->ctrl_flags & SUPPORT_CLK_STAT_CONTROL) + return scmi_clk_gate(clk, 1); + + /* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */ + debug("SCMI CLOCK: the clock cannot be enabled by the agent.\n"); + return 0; + } + return scmi_clk_gate(clk, 1); }
static int scmi_clk_disable(struct clk *clk) { + struct clk_scmi *clkscmi; + struct clk *c; + int ret; + + if (CONFIG_IS_ENABLED(CLK_CCF)) { + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + clkscmi = container_of(c, struct clk_scmi, clk); + + if (clkscmi->ctrl_flags & SUPPORT_CLK_STAT_CONTROL) + return scmi_clk_gate(clk, 0); + + /* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */ + debug("SCMI CLOCK: the clock cannot be disabled by the agent.\n"); + return 0; + } + return scmi_clk_gate(clk, 0); }
@@ -108,7 +198,7 @@ static ulong scmi_clk_get_rate(struct clk *clk) return (ulong)(((u64)out.rate_msb << 32) | out.rate_lsb); }
-static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) +static ulong __scmi_clk_set_rate(struct clk *clk, ulong rate) { struct scmi_clk_rate_set_in in = { .clock_id = clk->id, @@ -133,9 +223,33 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) return scmi_clk_get_rate(clk); }
+static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) +{ + struct clk_scmi *clkscmi; + struct clk *c; + int ret; + + if (CONFIG_IS_ENABLED(CLK_CCF)) { + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + clkscmi = container_of(c, struct clk_scmi, clk); + + if (clkscmi->ctrl_flags & SUPPORT_CLK_RATE_CONTROL) + return __scmi_clk_set_rate(clk, rate); + + /* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */ + debug("SCMI CLOCK: the clock rate cannot be changed by the agent.\n"); + return 0; + } + + return __scmi_clk_set_rate(clk, rate); +} + static int scmi_clk_probe(struct udevice *dev) { - struct clk *clk; + struct clk_scmi *clk_scmi; size_t num_clocks, i; int ret;
@@ -156,29 +270,44 @@ static int scmi_clk_probe(struct udevice *dev)
for (i = 0; i < num_clocks; i++) { char *clock_name; + u32 attributes;
- if (!scmi_clk_get_attibute(dev, i, &clock_name)) { - clk = kzalloc(sizeof(*clk), GFP_KERNEL); - if (!clk || !clock_name) + if (!scmi_clk_get_attibute(dev, i, &clock_name, &attributes)) { + clk_scmi = kzalloc(sizeof(*clk_scmi), GFP_KERNEL); + if (!clk_scmi || !clock_name) ret = -ENOMEM; else - ret = clk_register(clk, dev->driver->name, + ret = clk_register(&clk_scmi->clk, dev->driver->name, clock_name, dev->name);
if (ret) { - free(clk); + free(clk_scmi); free(clock_name); + free(&attributes); return ret; }
- clk_dm(i, clk); + clk_dm(i, &clk_scmi->clk); + + if (CLK_HAS_RESTRICTIONS(attributes)) { + u32 perm; + + ret = scmi_clk_get_permissions(dev, i, &perm); + if (ret < 0) + clk_scmi->ctrl_flags = 0; + else + clk_scmi->ctrl_flags = perm; + } else { + clk_scmi->ctrl_flags = SUPPORT_CLK_STAT_CONTROL | SUPPORT_CLK_PARENT_CONTROL | + SUPPORT_CLK_RATE_CONTROL; + } } }
return 0; }
-static int scmi_clk_set_parent(struct clk *clk, struct clk *parent) +static int __scmi_clk_set_parent(struct clk *clk, struct clk *parent) { struct scmi_clk_parent_set_in in = { .clock_id = clk->id, @@ -197,6 +326,30 @@ static int scmi_clk_set_parent(struct clk *clk, struct clk *parent) return scmi_to_linux_errno(out.status); }
+static int scmi_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk_scmi *clkscmi; + struct clk *c; + int ret; + + if (CONFIG_IS_ENABLED(CLK_CCF)) { + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + clkscmi = container_of(c, struct clk_scmi, clk); + + if (clkscmi->ctrl_flags & SUPPORT_CLK_PARENT_CONTROL) + return __scmi_clk_set_parent(clk, parent); + + /* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */ + debug("SCMI CLOCK: the clock's parent cannot be changed by the agent.\n"); + return 0; + } + + return -ENOTSUPP; +} + static const struct clk_ops scmi_clk_ops = { .enable = scmi_clk_enable, .disable = scmi_clk_disable, diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c index 19be280ec44845369d1f46509978ec9b5b59c60b..74a87832dcb14d63550e450f4bea2632844199e9 100644 --- a/drivers/firmware/scmi/sandbox-scmi_agent.c +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c @@ -80,9 +80,9 @@ static struct sandbox_scmi_pwd scmi_pwdom[] = { };
static struct sandbox_scmi_clk scmi_clk[] = { - { .rate = 333 }, - { .rate = 200 }, - { .rate = 1000 }, + { .rate = 333, .perm = 0xE0000000 }, + { .rate = 200, .perm = 0xE0000000 }, + { .rate = 1000, .perm = 0xE0000000 }, };
static struct sandbox_scmi_reset scmi_reset[] = { @@ -700,6 +700,21 @@ static int sandbox_scmi_pwd_name_get(struct udevice *dev, struct scmi_msg *msg)
/* Clock Protocol */
+static int sandbox_scmi_clock_protocol_version(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_protocol_version_out *out = NULL; + + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + out = (struct scmi_protocol_version_out *)msg->out_msg; + out->version = 0x30000; + out->status = SCMI_SUCCESS; + + return 0; +} + static int sandbox_scmi_clock_protocol_attribs(struct udevice *dev, struct scmi_msg *msg) { @@ -740,6 +755,9 @@ static int sandbox_scmi_clock_attribs(struct udevice *dev, struct scmi_msg *msg) if (clk_state->enabled) out->attributes = 1;
+ /* Restricted clock */ + out->attributes |= BIT(1); + ret = snprintf(out->clock_name, sizeof(out->clock_name), "clk%u", in->clock_id); assert(ret > 0 && ret < sizeof(out->clock_name)); @@ -837,6 +855,34 @@ static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg) return 0; }
+static int sandbox_scmi_clock_permissions_get(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_clk_get_permissions_in *in = NULL; + struct scmi_clk_get_permissions_out *out = NULL; + struct sandbox_scmi_clk *clk_state = NULL; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + in = (struct scmi_clk_get_permissions_in *)msg->in_msg; + out = (struct scmi_clk_get_permissions_out *)msg->out_msg; + + clk_state = get_scmi_clk_state(in->clock_id); + if (!clk_state) { + dev_err(dev, "Unexpected clock ID %u\n", in->clock_id); + + out->status = SCMI_NOT_FOUND; + } else { + out->permissions = clk_state->perm; + + out->status = SCMI_SUCCESS; + } + + return 0; +} + static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg) { struct scmi_rd_attr_in *in = NULL; @@ -1193,6 +1239,8 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, return sandbox_proto_not_supported(msg);
switch (msg->message_id) { + case SCMI_PROTOCOL_VERSION: + return sandbox_scmi_clock_protocol_version(dev, msg); case SCMI_PROTOCOL_ATTRIBUTES: return sandbox_scmi_clock_protocol_attribs(dev, msg); case SCMI_CLOCK_ATTRIBUTES: @@ -1203,6 +1251,8 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, return sandbox_scmi_clock_rate_get(dev, msg); case SCMI_CLOCK_CONFIG_SET: return sandbox_scmi_clock_gate(dev, msg); + case SCMI_CLOCK_GET_PERMISSIONS: + return sandbox_scmi_clock_permissions_get(dev, msg); default: break; } diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h index d529f8e2697472e60d0cb9c275f34ef0ecaed3ca..9607433c3276f9aa18044c414a5bde3143726cf4 100644 --- a/include/scmi_protocols.h +++ b/include/scmi_protocols.h @@ -731,13 +731,15 @@ int scmi_pwd_name_get(struct udevice *dev, u32 domain_id, u8 **name); /* * SCMI Clock Protocol */ +#define CLOCK_PROTOCOL_VERSION_3_0 0x30000
enum scmi_clock_message_id { SCMI_CLOCK_ATTRIBUTES = 0x3, SCMI_CLOCK_RATE_SET = 0x5, SCMI_CLOCK_RATE_GET = 0x6, SCMI_CLOCK_CONFIG_SET = 0x7, - SCMI_CLOCK_PARENT_SET = 0xD + SCMI_CLOCK_PARENT_SET = 0xD, + SCMI_CLOCK_GET_PERMISSIONS = 0xF };
#define SCMI_CLK_PROTO_ATTR_COUNT_MASK GENMASK(15, 0) @@ -776,6 +778,7 @@ struct scmi_clk_attribute_in { struct scmi_clk_attribute_out { s32 status; u32 attributes; +#define CLK_HAS_RESTRICTIONS(x) ((x) & BIT(1)) char clock_name[SCMI_CLOCK_NAME_LENGTH_MAX]; };
@@ -858,6 +861,27 @@ struct scmi_clk_parent_set_out { s32 status; };
+/** + * @clock_id: Identifier for the clock device. + */ +struct scmi_clk_get_permissions_in { + u32 clock_id; +}; + +/** + * @status: Negative 32-bit integers are used to return error status codes. + * @permissions: Bit[31] Clock state control, Bit[30] Clock parent control, + * Bit[29] Clock rate control, Bits[28:0] Reserved, must be zero + */ +struct scmi_clk_get_permissions_out { + s32 status; + u32 permissions; +}; + +#define SUPPORT_CLK_STAT_CONTROL BIT(31) +#define SUPPORT_CLK_PARENT_CONTROL BIT(30) +#define SUPPORT_CLK_RATE_CONTROL BIT(29) + /* * SCMI Reset Domain Protocol */

On Thu, Dec 19, 2024 at 11:55 PM Alice Guo alice.guo@oss.nxp.com wrote:
debug("SCMI clock management protocol version is less than 3.0.\n");
return -1;
Nit: return -EINVAL would be better here.

From: Ye Li ye.li@nxp.com
@protocols is an array of protocol identifiers that are implemented, excluding the Base protocol. The number of elements of @protocols is specified by callee-side. Currently, set it to 4 is enough for i.MX95.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com --- include/scmi_protocols.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h index 9607433c3276f9aa18044c414a5bde3143726cf4..3c55d228cb641bc6c0e5ca7ac885efe84b41c66d 100644 --- a/include/scmi_protocols.h +++ b/include/scmi_protocols.h @@ -141,11 +141,14 @@ struct scmi_base_discover_impl_version_out { * @status: SCMI command status * @num_protocols: Number of SCMI protocols in @protocol * @protocols: Array of packed SCMI protocol ID's + * + * The number of elements of @protocols is specified by callee-side. Currently, + * set it to 4 is enough for i.MX95. */ struct scmi_base_discover_list_protocols_out { s32 status; u32 num_protocols; - u32 protocols[3]; + u32 protocols[4]; };
/**

From: Peng Fan peng.fan@nxp.com
This patch adds i.MX95 SoC and clock related code. Because they are based on SCMI, put them in the scmi subfolder.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Peng Fan peng.fan@nxp.com --- arch/arm/include/asm/arch-imx/cpu.h | 3 + arch/arm/include/asm/arch-imx9/clock.h | 10 +- arch/arm/include/asm/arch-imx9/imx-regs.h | 7 +- arch/arm/include/asm/arch-imx9/sys_proto.h | 3 +- arch/arm/include/asm/mach-imx/sys_proto.h | 40 ++ arch/arm/mach-imx/imx9/scmi/Makefile | 6 + arch/arm/mach-imx/imx9/scmi/clock.c | 328 ++++++++++++ arch/arm/mach-imx/imx9/scmi/clock_scmi.c | 148 +++++ arch/arm/mach-imx/imx9/scmi/soc.c | 832 +++++++++++++++++++++++++++++ 9 files changed, 1373 insertions(+), 4 deletions(-)
diff --git a/arch/arm/include/asm/arch-imx/cpu.h b/arch/arm/include/asm/arch-imx/cpu.h index 0d7a573461690046b27498c7174459110a73689c..b283c49afec83cbed670d07ad0909ad6f453853b 100644 --- a/arch/arm/include/asm/arch-imx/cpu.h +++ b/arch/arm/include/asm/arch-imx/cpu.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* * (C) Copyright 2014 Freescale Semiconductor, Inc. + * Copyright 2024 NXP */
#define MXC_CPU_MX23 0x23 @@ -76,6 +77,8 @@ #define MXC_CPU_IMX9111 0xCD /* dummy ID */ #define MXC_CPU_IMX9101 0xCE /* dummy ID */
+#define MXC_CPU_IMX95 0x1C1 /* dummy ID */ + #define MXC_SOC_MX6 0x60 #define MXC_SOC_MX7 0x70 #define MXC_SOC_IMX8M 0x80 diff --git a/arch/arm/include/asm/arch-imx9/clock.h b/arch/arm/include/asm/arch-imx9/clock.h index 60d48b13b11f274c9e4c8caf20954de0431d9d6a..a64c18b28291553d47725d83cb748031faf64488 100644 --- a/arch/arm/include/asm/arch-imx9/clock.h +++ b/arch/arm/include/asm/arch-imx9/clock.h @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright 2022 NXP + * Copyright 2024 NXP * - * Peng Fan <peng.fan at nxp.com> + * Peng Fan peng.fan@nxp.com */
#ifndef __CLOCK_IMX9__ @@ -255,5 +255,11 @@ int ccm_shared_gpr_tz_access(u32 gpr, bool non_secure, bool user_mode, bool lock void enable_usboh3_clk(unsigned char enable); int set_clk_enet(enum enet_freq type); int set_clk_eqos(enum enet_freq type); +int set_clk_netc(enum enet_freq type); void set_arm_clk(ulong freq); + +int imx_clk_scmi_enable(u32 clock_id, bool enable); +ulong imx_clk_scmi_set_rate(u32 clock_id, ulong rate); +ulong imx_clk_scmi_get_rate(u32 clock_id); +int imx_clk_scmi_set_parent(u32 clock_id, u32 parent_id); #endif diff --git a/arch/arm/include/asm/arch-imx9/imx-regs.h b/arch/arm/include/asm/arch-imx9/imx-regs.h index ef9538bd42e8b2972d7e6829a402bc4f661e3cbb..5512d66ee0a44348845d2a559bd99327115bc1d0 100644 --- a/arch/arm/include/asm/arch-imx9/imx-regs.h +++ b/arch/arm/include/asm/arch-imx9/imx-regs.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright 2022 NXP + * Copyright 2024 NXP */
#ifndef __ASM_ARCH_IMX9_REGS_H__ @@ -20,6 +20,11 @@ #define WDG4_BASE_ADDR 0x424a0000UL #define WDG5_BASE_ADDR 0x424b0000UL
+#define GPIO2_BASE_ADDR 0x43810000UL +#define GPIO3_BASE_ADDR 0x43820000UL +#define GPIO4_BASE_ADDR 0x43840000UL +#define GPIO5_BASE_ADDR 0x43850000UL + #define FSB_BASE_ADDR 0x47510000UL
#define ANATOP_BASE_ADDR 0x44480000UL diff --git a/arch/arm/include/asm/arch-imx9/sys_proto.h b/arch/arm/include/asm/arch-imx9/sys_proto.h index e4bf6a63424f7c54c1dcdf6b882a908940e5fdb1..aac43c74a44a127549c67059e70f570aae5f680c 100644 --- a/arch/arm/include/asm/arch-imx9/sys_proto.h +++ b/arch/arm/include/asm/arch-imx9/sys_proto.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright (C) 2022 NXP + * Copyright (C) 2024 NXP */
#ifndef __ARCH_IMX9_SYS_PROTO_H @@ -12,6 +12,7 @@ enum imx9_soc_voltage_mode { VOLT_LOW_DRIVE = 0, VOLT_NOMINAL_DRIVE, VOLT_OVER_DRIVE, + VOLT_SUPER_OVER_DRIVE, };
void soc_power_init(void); diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h index 109a806852ab42d018ce45a4e96af5b57adb6a9c..bcf33769ae5f45125bbf9377eb64d96473dc4996 100644 --- a/arch/arm/include/asm/mach-imx/sys_proto.h +++ b/arch/arm/include/asm/mach-imx/sys_proto.h @@ -2,6 +2,7 @@ /* * (C) Copyright 2009 * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * Copyright 2024 NXP */
#ifndef _SYS_PROTO_H_ @@ -97,6 +98,8 @@ struct bd_info; #define is_imx9302() (is_cpu_type(MXC_CPU_IMX9302)) #define is_imx9301() (is_cpu_type(MXC_CPU_IMX9301))
+#define is_imx95() (is_cpu_type(MXC_CPU_IMX95)) + #define is_imx9121() (is_cpu_type(MXC_CPU_IMX9121)) #define is_imx9111() (is_cpu_type(MXC_CPU_IMX9111)) #define is_imx9101() (is_cpu_type(MXC_CPU_IMX9101)) @@ -216,6 +219,43 @@ ulong spl_romapi_get_uboot_base(u32 image_offset, u32 rom_bt_dev); u32 rom_api_download_image(u8 *dest, u32 offset, u32 size); u32 rom_api_query_boot_infor(u32 info_type, u32 *info);
+#ifdef CONFIG_SCMI_FIRMWARE +typedef struct rom_passover { + uint16_t tag; //!< Tag + uint8_t len; //!< Fixed value of 0x80 + uint8_t ver; //!< Version + uint32_t boot_mode; //!< Boot mode + uint32_t card_addr_mode; //!< SD card address mode + uint32_t bad_blks_of_img_set0; //!< NAND bad block count skipped 1 + uint32_t ap_mu_id; //!< AP MU ID + uint32_t bad_blks_of_img_set1; //!< NAND bad block count skipped 1 + uint8_t boot_stage; //!< Boot stage + uint8_t img_set_sel; //!< Image set booted from + uint8_t rsv0[2]; //!< Reserved + uint32_t img_set_end; //!< Offset of Image End + uint32_t rom_version; //!< ROM version + uint8_t boot_dev_state; //!< Boot device state + uint8_t boot_dev_inst; //!< Boot device type + uint8_t boot_dev_type; //!< Boot device instance + uint8_t rsv1; //!< Reserved + uint32_t dev_page_size; //!< Boot device page size + uint32_t cnt_header_ofs; //!< Container header offset + uint32_t img_ofs; //!< Image offset +} __attribute__ ((packed)) rom_passover_t; + +/** + * struct scmi_rom_passover_out - Response payload for ROM_PASSOVER_GET command + * @status: SCMI clock ID + * @attributes: Attributes of the targets clock state + */ +struct scmi_rom_passover_get_out { + u32 status; + u32 numPassover; + u32 passover[(sizeof(rom_passover_t) + 8) / 4]; +}; + +#endif + /* For i.MX ULP */ #define BT0CFG_LPBOOT_MASK 0x1 #define BT0CFG_DUALBOOT_MASK 0x2 diff --git a/arch/arm/mach-imx/imx9/scmi/Makefile b/arch/arm/mach-imx/imx9/scmi/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..78f24c6e5151e2d7280b9c456c0477a3b6a958c4 --- /dev/null +++ b/arch/arm/mach-imx/imx9/scmi/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2024 NXP + +obj-y += soc.o +obj-y += clock_scmi.o clock.o diff --git a/arch/arm/mach-imx/imx9/scmi/clock.c b/arch/arm/mach-imx/imx9/scmi/clock.c new file mode 100644 index 0000000000000000000000000000000000000000..b46ff3f9944d2b08db56f7ef892fba715afd2655 --- /dev/null +++ b/arch/arm/mach-imx/imx9/scmi/clock.c @@ -0,0 +1,328 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include <asm/arch/ccm_regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <command.h> +#include <errno.h> +#ifdef CONFIG_CLK_SCMI +#include "../../../../../dts/upstream/src/arm64/freescale/imx95-clock.h" +#include <dm/uclass.h> +#include <dm/uclass-internal.h> +#include <linux/clk-provider.h> +#include <scmi_agent.h> +#include <scmi_protocols.h> +#include <dm/device.h> +#include <dm/device-internal.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +u32 get_arm_core_clk(void) +{ + u32 val; + + /* TODO: */ + val = imx_clk_scmi_get_rate(IMX95_CLK_SEL_A55C0); + if (val) + return val; + return imx_clk_scmi_get_rate(IMX95_CLK_A55); +} + +void set_arm_core_max_clk(void) +{ + int ret; + u32 arm_domain_id = 8; + + struct scmi_perf_in in = { + .domain_id = arm_domain_id, + .perf_level = 3, + }; + struct scmi_perf_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_PERF, SCMI_PERF_LEVEL_SET, in, out); + struct udevice *dev; + + ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev); + if (ret) + printf("%s: %d\n", __func__, ret); + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + printf("%s: %d\n", __func__, ret); +} + +void enable_usboh3_clk(unsigned char enable) +{ +} + +int clock_init_early(void) +{ + return 0; +} + +/* Set bus and A55 core clock per voltage mode */ +int clock_init_late(void) +{ + set_arm_core_max_clk(); + + return 0; +} + +u32 get_lpuart_clk(void) +{ + return imx_clk_scmi_get_rate(IMX95_CLK_LPUART1); +} + +void init_uart_clk(u32 index) +{ + u32 clock_id; + + switch (index) { + case 0: + clock_id = IMX95_CLK_LPUART1; + break; + case 1: + clock_id = IMX95_CLK_LPUART2; + break; + case 2: + clock_id = IMX95_CLK_LPUART3; + break; + default: + return; + } + + /* 24MHz */ + imx_clk_scmi_enable(clock_id, false); + imx_clk_scmi_set_parent(clock_id, IMX95_CLK_24M); + imx_clk_scmi_set_rate(clock_id, 24000000); + imx_clk_scmi_enable(clock_id, true); +} + +/* I2C check */ +u32 imx_get_i2cclk(u32 i2c_num) +{ + if (i2c_num > 7) + return -EINVAL; + switch (i2c_num) { + case 0: + return imx_clk_scmi_get_rate(IMX95_CLK_LPI2C1); + case 1: + return imx_clk_scmi_get_rate(IMX95_CLK_LPI2C2); + case 2: + return imx_clk_scmi_get_rate(IMX95_CLK_LPI2C3); + case 3: + return imx_clk_scmi_get_rate(IMX95_CLK_LPI2C4); + case 4: + return imx_clk_scmi_get_rate(IMX95_CLK_LPI2C5); + case 5: + return imx_clk_scmi_get_rate(IMX95_CLK_LPI2C6); + case 6: + return imx_clk_scmi_get_rate(IMX95_CLK_LPI2C7); + case 7: + return imx_clk_scmi_get_rate(IMX95_CLK_LPI2C8); + default: + return 0; + } + + return 0; +} + +int enable_i2c_clk(unsigned char enable, u32 i2c_num) +{ + u32 clock_id; + + if (i2c_num > 7) + return -EINVAL; + + switch (i2c_num) { + case 0: + clock_id = IMX95_CLK_LPI2C1; + break; + case 1: + clock_id = IMX95_CLK_LPI2C2; + break; + case 2: + clock_id = IMX95_CLK_LPI2C3; + break; + case 3: + clock_id = IMX95_CLK_LPI2C4; + break; + case 4: + clock_id = IMX95_CLK_LPI2C5; + break; + case 5: + clock_id = IMX95_CLK_LPI2C6; + break; + case 6: + clock_id = IMX95_CLK_LPI2C7; + break; + case 7: + clock_id = IMX95_CLK_LPI2C8; + break; + default: + return 0; + } + + /* 24MHz */ + imx_clk_scmi_enable(clock_id, false); + imx_clk_scmi_set_parent(clock_id, IMX95_CLK_24M); + imx_clk_scmi_set_rate(clock_id, 24000000); + imx_clk_scmi_enable(clock_id, true); + + return 0; +} + +/* dfs_clkout[1]: 800.00MHz */ +void init_clk_usdhc(u32 usdhc_id) +{ + u32 clock_id; + + switch (usdhc_id) { + case 0: + clock_id = IMX95_CLK_USDHC1; + break; + case 1: + clock_id = IMX95_CLK_USDHC2; + break; + case 2: + clock_id = IMX95_CLK_USDHC3; + break; + default: + return; + }; + + /* 400MHz */ + imx_clk_scmi_enable(clock_id, false); + imx_clk_scmi_set_parent(clock_id, IMX95_CLK_SYSPLL1_PFD1); + imx_clk_scmi_set_rate(clock_id, 400000000); + imx_clk_scmi_enable(clock_id, true); +} + +int set_clk_netc(enum enet_freq type) +{ + ulong rate; + + switch (type) { + case ENET_125MHZ: + rate = MHZ(250); /* 250Mhz */ + break; + case ENET_50MHZ: + rate = MHZ(100); /* 100Mhz */ + break; + case ENET_25MHZ: + rate = MHZ(50); /* 50Mhz */ + break; + default: + return -EINVAL; + } + + /* disable the clock first */ + imx_clk_scmi_enable(IMX95_CLK_ENETREF, false); + imx_clk_scmi_set_parent(IMX95_CLK_ENETREF, IMX95_CLK_SYSPLL1_PFD0); + imx_clk_scmi_set_rate(IMX95_CLK_ENETREF, rate); + imx_clk_scmi_enable(IMX95_CLK_ENETREF, true); + + return 0; +} + +#ifdef CONFIG_SPL_BUILD +void dram_pll_init(ulong pll_val) +{ + /* Try to configure the DDR PLL. */ + u64 ddr_rate = pll_val; + /*vco_range 2.5G - 5G */ + u64 vco_rate = ddr_rate * DIV_ROUND_UP(MHZ(3000), ddr_rate); + u64 v_rate, rate; + + v_rate = imx_clk_scmi_set_rate(IMX95_CLK_DRAMPLL_VCO, vco_rate); + rate = imx_clk_scmi_set_rate(IMX95_CLK_DRAMPLL, ddr_rate); + + debug("%s vco:%llu rate:%llu\n", __func__, v_rate, rate); +} + +void dram_enable_bypass(ulong clk_val) +{ + u64 rate; + + switch (clk_val) { + case MHZ(625): + imx_clk_scmi_set_parent(IMX95_CLK_DRAMALT, IMX95_CLK_SYSPLL1_PFD2); + rate = imx_clk_scmi_set_rate(IMX95_CLK_DRAMALT, clk_val); + break; + case MHZ(400): + imx_clk_scmi_set_parent(IMX95_CLK_DRAMALT, IMX95_CLK_SYSPLL1_PFD1); + rate = imx_clk_scmi_set_rate(IMX95_CLK_DRAMALT, clk_val); + break; + case MHZ(333): + imx_clk_scmi_set_parent(IMX95_CLK_DRAMALT, IMX95_CLK_SYSPLL1_PFD0); + rate = imx_clk_scmi_set_rate(IMX95_CLK_DRAMALT, 333333333); + break; + case MHZ(200): + imx_clk_scmi_set_parent(IMX95_CLK_DRAMALT, IMX95_CLK_SYSPLL1_PFD1); + rate = imx_clk_scmi_set_rate(IMX95_CLK_DRAMALT, clk_val); + break; + case MHZ(100): + imx_clk_scmi_set_parent(IMX95_CLK_DRAMALT, IMX95_CLK_SYSPLL1_PFD1); + rate = imx_clk_scmi_set_rate(IMX95_CLK_DRAMALT, clk_val); + break; + default: + printf("No matched freq table %lu\n", clk_val); + return; + } + + debug("%s:%llu\n", __func__, rate); + + /* Set DRAM APB to 133Mhz */ + imx_clk_scmi_set_parent(IMX95_CLK_DRAMAPB, IMX95_CLK_SYSPLL1_PFD1_DIV2); + rate = imx_clk_scmi_set_rate(IMX95_CLK_DRAMAPB, 133333333); + + /* Switch from DRAM clock root from PLL to CCM */ + imx_clk_scmi_set_parent(IMX95_CLK_SEL_DRAM, IMX95_CLK_DRAMALT); +} + +void dram_disable_bypass(void) +{ + u64 rate; + /* Set DRAM APB to 133Mhz */ + imx_clk_scmi_set_parent(IMX95_CLK_DRAMAPB, IMX95_CLK_SYSPLL1_PFD1_DIV2); + rate = imx_clk_scmi_set_rate(IMX95_CLK_DRAMAPB, 133333333); + + /*Set the DRAM_GPR_SEL to be sourced from DRAM_PLL.*/ + imx_clk_scmi_set_parent(IMX95_CLK_SEL_DRAM, IMX95_CLK_DRAMPLL); + rate = imx_clk_scmi_get_rate(IMX95_CLK_SEL_DRAM); + printf("%s:SEL_DRAM: %llu\n", __func__, rate); +} + +#endif + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return get_arm_core_clk(); + case MXC_IPG_CLK: + return imx_clk_scmi_get_rate(IMX95_CLK_BUSWAKEUP); + case MXC_CSPI_CLK: + return imx_clk_scmi_get_rate(IMX95_CLK_LPSPI1); + case MXC_ESDHC_CLK: + return imx_clk_scmi_get_rate(IMX95_CLK_USDHC1); + case MXC_ESDHC2_CLK: + return imx_clk_scmi_get_rate(IMX95_CLK_USDHC2); + case MXC_ESDHC3_CLK: + return imx_clk_scmi_get_rate(IMX95_CLK_USDHC3); + case MXC_UART_CLK: + return imx_clk_scmi_get_rate(IMX95_CLK_LPUART1); + case MXC_FLEXSPI_CLK: + return imx_clk_scmi_get_rate(IMX95_CLK_FLEXSPI1); + default: + return -1; + }; + + return -1; +}; diff --git a/arch/arm/mach-imx/imx9/scmi/clock_scmi.c b/arch/arm/mach-imx/imx9/scmi/clock_scmi.c new file mode 100644 index 0000000000000000000000000000000000000000..543abe9fed481c796602b2b2eeeec6c8f9a94862 --- /dev/null +++ b/arch/arm/mach-imx/imx9/scmi/clock_scmi.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + * + * Peng Fan peng.fan@nxp.com + */ + +#include <command.h> +#include <errno.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/ccm_regs.h> +#include <asm/mach-imx/sys_proto.h> +#include <asm/global_data.h> +#include <dm/uclass.h> +#include <dm/uclass-internal.h> +#include <dm/device.h> +#include <dm/device-internal.h> +#include "../../../../../dts/upstream/src/arm64/freescale/imx95-clock.h" +#include <linux/clk-provider.h> +#include <scmi_agent.h> +#include <scmi_protocols.h> + +DECLARE_GLOBAL_DATA_PTR; + +int imx_clk_scmi_enable(u32 clock_id, bool enable) +{ + struct scmi_clk_state_in in = { + .clock_id = clock_id, + .attributes = (enable) ? 1 : 0, + }; + struct scmi_clk_state_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, + SCMI_CLOCK_CONFIG_SET, + in, out); + int ret; + struct udevice *dev; + + ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev); + if (ret) + return ret; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + + return scmi_to_linux_errno(out.status); +} + +ulong imx_clk_scmi_set_rate(u32 clock_id, ulong rate) +{ + struct scmi_clk_rate_set_in in = { + .clock_id = clock_id, + .flags = SCMI_CLK_RATE_ROUND_CLOSEST, + .rate_lsb = (u32)rate, + .rate_msb = (u32)((u64)rate >> 32), + }; + struct scmi_clk_rate_set_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, + SCMI_CLOCK_RATE_SET, + in, out); + int ret; + struct udevice *dev; + + ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev); + if (ret) + return ret; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret < 0) + return ret; + + ret = scmi_to_linux_errno(out.status); + if (ret < 0) + return ret; + + struct scmi_clk_rate_get_in in_rate = { + .clock_id = clock_id, + }; + struct scmi_clk_rate_get_out out_rate; + + msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, SCMI_CLOCK_RATE_GET, in_rate, out_rate); + + ret = devm_scmi_process_msg(dev, &msg); + if (ret < 0) + return ret; + + ret = scmi_to_linux_errno(out_rate.status); + if (ret < 0) + return ret; + + return (ulong)(((u64)out_rate.rate_msb << 32) | out_rate.rate_lsb); +} + +ulong imx_clk_scmi_get_rate(u32 clock_id) +{ + struct scmi_clk_rate_get_in in = { + .clock_id = clock_id, + }; + struct scmi_clk_rate_get_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, + SCMI_CLOCK_RATE_GET, + in, out); + int ret; + struct udevice *dev; + + ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev); + if (ret) + return ret; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret < 0) + return ret; + + ret = scmi_to_linux_errno(out.status); + if (ret < 0) + return ret; + + return (ulong)(((u64)out.rate_msb << 32) | out.rate_lsb); +} + +int imx_clk_scmi_set_parent(u32 clock_id, u32 parent_id) +{ + struct scmi_clk_parent_set_in in = { + .clock_id = clock_id, + .parent_clk = parent_id, + }; + struct scmi_clk_parent_set_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, + SCMI_CLOCK_PARENT_SET, + in, out); + int ret; + struct udevice *dev; + + ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev); + if (ret) + return ret; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret < 0) + return ret; + + ret = scmi_to_linux_errno(out.status); + if (ret < 0 && ret != -EACCES) + printf("%s: %d, clock_id %u\n", __func__, ret, clock_id); + + return ret; +} diff --git a/arch/arm/mach-imx/imx9/scmi/soc.c b/arch/arm/mach-imx/imx9/scmi/soc.c new file mode 100644 index 0000000000000000000000000000000000000000..fefb1a6f4ca58722a5d93c39e4f6a7aaf85aa177 --- /dev/null +++ b/arch/arm/mach-imx/imx9/scmi/soc.c @@ -0,0 +1,832 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + * + * Peng Fan peng.fan@nxp.com + */ + +#include <cpu_func.h> +#include <init.h> +#include <log.h> +#include <asm/arch/imx-regs.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/ccm_regs.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/trdc.h> +#include <asm/mach-imx/boot_mode.h> +#include <asm/mach-imx/syscounter.h> +#include <asm/armv8/mmu.h> +#include <dm/uclass.h> +#include <dm/device.h> +#include <env.h> +#include <env_internal.h> +#include <errno.h> +#include <fdt_support.h> +#include <linux/bitops.h> +#include <linux/bitfield.h> +#include <asm/setup.h> +#include <asm/bootm.h> +#include <asm/arch-imx/cpu.h> +#include <asm/mach-imx/ele_api.h> +#include <linux/delay.h> +#include <fuse.h> +#include <imx_thermal.h> +#include <thermal.h> +#include <imx_sip.h> +#include <linux/arm-smccc.h> +#include <asm/arch/ddr.h> +#ifdef CONFIG_SCMI_FIRMWARE +#include <scmi_agent.h> +#include <scmi_protocols.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +rom_passover_t rom_passover_data = {0}; + +uint32_t scmi_get_rom_data(rom_passover_t *rom_data) +{ + /* Read ROM passover data */ + struct scmi_rom_passover_get_out out; + struct scmi_msg msg = SCMI_MSG(SCMI_PROTOCOL_ID_IMX_MISC, SCMI_MISC_ROM_PASSOVER_GET, out); + int ret; + struct udevice *dev; + + ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev); + if (ret) + return ret; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret == 0 && out.status == 0) { + memcpy(rom_data, (struct rom_passover_t *)out.passover, sizeof(rom_passover_t)); + } else { + printf("Failed to get ROM passover data, scmi_err = %d, size_of(out) = %ld\n", + out.status, sizeof(out)); + return -EINVAL; + } + + return 0; +} + +#ifdef CONFIG_ENV_IS_IN_MMC +__weak int board_mmc_get_env_dev(int devno) +{ + return devno; +} + +int mmc_get_env_dev(void) +{ + int ret; + u16 boot_type; + u8 boot_instance; + + volatile gd_t *pgd = gd; + rom_passover_t *rdata; +#ifdef CONFIG_SPL_BUILD + rdata = &rom_passover_data; +#else + rom_passover_t rom_data = {0}; + + if (!pgd->reloc_off) + rdata = &rom_data; + else + rdata = &rom_passover_data; +#endif + if (rdata->tag == 0) { + ret = scmi_get_rom_data(rdata); + if (ret != 0) { + puts("SCMI: failure at rom_boot_info\n"); + return CONFIG_SYS_MMC_ENV_DEV; + } + } + boot_type = rdata->boot_dev_type; + boot_instance = rdata->boot_dev_inst; + set_gd(pgd); + + debug("boot_type %d, instance %d\n", boot_type, boot_instance); + + /* If not boot from sd/mmc, use default value */ + if (boot_type != BOOT_TYPE_SD && boot_type != BOOT_TYPE_MMC) + return env_get_ulong("mmcdev", 10, CONFIG_SYS_MMC_ENV_DEV); + + return board_mmc_get_env_dev(boot_instance); +} +#endif + +u32 get_cpu_speed_grade_hz(void) +{ + u32 speed, max_speed; + int ret; + u32 val, word, offset; + + word = 17; + offset = 14; + + ret = fuse_read((word / 8), (word % 8), &val); + if (ret) + val = 0; /* If read fuse failed, return as blank fuse */ + + val >>= offset; + val &= 0xf; + + max_speed = 2300000000; + speed = max_speed - val * 100000000; + + if (is_imx95()) + max_speed = 2000000000; + + /* In case the fuse of speed grade not programmed */ + if (speed > max_speed) + speed = max_speed; + + return speed; +} + +u32 get_cpu_temp_grade(int *minc, int *maxc) +{ + int ret; + u32 val, word, offset; + + word = 17; + offset = 12; + + ret = fuse_read((word / 8), (word % 8), &val); + if (ret) + val = 0; /* If read fuse failed, return as blank fuse */ + + val >>= offset; + val &= 0x3; + + if (minc && maxc) { + if (val == TEMP_AUTOMOTIVE) { + *minc = -40; + *maxc = 125; + } else if (val == TEMP_INDUSTRIAL) { + *minc = -40; + *maxc = 105; + } else if (val == TEMP_EXTCOMMERCIAL) { + *minc = -20; + *maxc = 105; + } else { + *minc = 0; + *maxc = 95; + } + } + return val; +} + +static void set_cpu_info(struct ele_get_info_data *info) +{ + gd->arch.soc_rev = info->soc; + gd->arch.lifecycle = info->lc; + memcpy((void *)&gd->arch.uid, &info->uid, 4 * sizeof(u32)); +} + +u32 get_cpu_rev(void) +{ + u32 rev = (gd->arch.soc_rev >> 24) - 0xa0; + + return (MXC_CPU_IMX95 << 12) | (CHIP_REV_1_0 + rev); +} + +#define UNLOCK_WORD 0xD928C520 /* unlock word */ +#define REFRESH_WORD 0xB480A602 /* refresh word */ + +static void disable_wdog(void __iomem *wdog_base) +{ + u32 val_cs = readl(wdog_base + 0x00); + + if (!(val_cs & 0x80)) + return; + + /* default is 32bits cmd */ + writel(REFRESH_WORD, (wdog_base + 0x04)); /* Refresh the CNT */ + + if (!(val_cs & 0x800)) { + writel(UNLOCK_WORD, (wdog_base + 0x04)); + while (!(readl(wdog_base + 0x00) & 0x800)) + ; + } + writel(0x0, (wdog_base + 0x0C)); /* Set WIN to 0 */ + writel(0x400, (wdog_base + 0x08)); /* Set timeout to default 0x400 */ + writel(0x2120, (wdog_base + 0x00)); /* Disable it and set update */ + + while (!(readl(wdog_base + 0x00) & 0x400)) + ; +} + +static struct mm_region imx9_mem_map[] = { + { + /* ROM */ + .virt = 0x0UL, + .phys = 0x0UL, + .size = 0x100000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE + }, { + /* TCM */ + .virt = 0x201c0000UL, + .phys = 0x201c0000UL, + .size = 0x80000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* OCRAM */ + .virt = 0x20480000UL, + .phys = 0x20480000UL, + .size = 0xA0000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE + }, { + /* AIPS */ + .virt = 0x40000000UL, + .phys = 0x40000000UL, + .size = 0x40000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* Flexible Serial Peripheral Interface */ + .virt = 0x28000000UL, + .phys = 0x28000000UL, + .size = 0x8000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* DRAM1 */ + .virt = PHYS_SDRAM, + .phys = PHYS_SDRAM, + .size = PHYS_SDRAM_SIZE, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE + }, { +#ifdef PHYS_SDRAM_2_SIZE + /* DRAM2 */ + .virt = 0x100000000UL, + .phys = 0x100000000UL, + .size = PHYS_SDRAM_2_SIZE, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE + }, { +#endif + /* empty entry to split table entry 5 if needed when TEEs are used */ + 0, + }, { + /* List terminator */ + 0, + } +}; + +struct mm_region *mem_map = imx9_mem_map; + +static unsigned int imx9_find_dram_entry_in_mem_map(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(imx9_mem_map); i++) + if (imx9_mem_map[i].phys == CFG_SYS_SDRAM_BASE) + return i; + + hang(); /* Entry not found, this must never happen. */ +} + +void enable_caches(void) +{ + /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch + * If OPTEE does not run, still update the MMU table according to dram banks structure + * to set correct dram size from board_phys_sdram_size + */ + int i = 0; + /* + * please make sure that entry initial value matches + * imx9_mem_map for DRAM1 + */ + int entry = imx9_find_dram_entry_in_mem_map(); + u64 attrs = imx9_mem_map[entry].attrs; + + while (i < CONFIG_NR_DRAM_BANKS && + entry < ARRAY_SIZE(imx9_mem_map)) { + if (gd->bd->bi_dram[i].start == 0) + break; + imx9_mem_map[entry].phys = gd->bd->bi_dram[i].start; + imx9_mem_map[entry].virt = gd->bd->bi_dram[i].start; + imx9_mem_map[entry].size = gd->bd->bi_dram[i].size; + imx9_mem_map[entry].attrs = attrs; + debug("Added memory mapping (%d): %llx %llx\n", entry, + imx9_mem_map[entry].phys, imx9_mem_map[entry].size); + i++; entry++; + } + + icache_enable(); + dcache_enable(); +} + +__weak int board_phys_sdram_size(phys_size_t *size) +{ + phys_size_t start, end; + phys_size_t val; + + if (!size) + return -EINVAL; + + val = readl(REG_DDR_CS0_BNDS); + start = (val >> 16) << 24; + end = (val & 0xFFFF); + end = end ? end + 1 : 0; + end = end << 24; + *size = end - start; + + val = readl(REG_DDR_CS1_BNDS); + start = (val >> 16) << 24; + end = (val & 0xFFFF); + end = end ? end + 1 : 0; + end = end << 24; + *size += end - start; + + return 0; +} + +int dram_init(void) +{ + phys_size_t sdram_size; + int ret; + + ret = board_phys_sdram_size(&sdram_size); + if (ret) + return ret; + + /* rom_pointer[1] contains the size of TEE occupies */ + if (rom_pointer[1]) + gd->ram_size = sdram_size - rom_pointer[1]; + else + gd->ram_size = sdram_size; + + return 0; +} + +int dram_init_banksize(void) +{ + int bank = 0; + int ret; + phys_size_t sdram_size; + phys_size_t sdram_b1_size, sdram_b2_size; + + ret = board_phys_sdram_size(&sdram_size); + if (ret) + return ret; + + /* Bank 1 can't cross over 4GB space */ + if (sdram_size > 0x80000000) { + sdram_b1_size = 0x100000000UL - PHYS_SDRAM; + sdram_b2_size = sdram_size - sdram_b1_size; + } else { + sdram_b1_size = sdram_size; + sdram_b2_size = 0; + } + + gd->bd->bi_dram[bank].start = PHYS_SDRAM; + if (rom_pointer[1]) { + phys_addr_t optee_start = (phys_addr_t)rom_pointer[0]; + phys_size_t optee_size = (size_t)rom_pointer[1]; + + gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start; + if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) { + if (++bank >= CONFIG_NR_DRAM_BANKS) { + puts("CONFIG_NR_DRAM_BANKS is not enough\n"); + return -1; + } + + gd->bd->bi_dram[bank].start = optee_start + optee_size; + gd->bd->bi_dram[bank].size = PHYS_SDRAM + + sdram_b1_size - gd->bd->bi_dram[bank].start; + } + } else { + gd->bd->bi_dram[bank].size = sdram_b1_size; + } + + if (sdram_b2_size) { + if (++bank >= CONFIG_NR_DRAM_BANKS) { + puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n"); + return -1; + } + gd->bd->bi_dram[bank].start = 0x100000000UL; + gd->bd->bi_dram[bank].size = sdram_b2_size; + } + + return 0; +} + +phys_size_t get_effective_memsize(void) +{ + int ret; + phys_size_t sdram_size; + phys_size_t sdram_b1_size; + + ret = board_phys_sdram_size(&sdram_size); + if (!ret) { + /* Bank 1 can't cross over 4GB space */ + if (sdram_size > 0x80000000) { + sdram_b1_size = 0x100000000UL - PHYS_SDRAM; + } else { + sdram_b1_size = sdram_size; + } + + if (rom_pointer[1]) { + /* We will relocate u-boot to Top of dram1. Tee position has two cases: + * 1. At the top of dram1, Then return the size removed optee size. + * 2. In the middle of dram1, return the size of dram1. + */ + if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size)) + return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM); + } + + return sdram_b1_size; + } else { + return PHYS_SDRAM_SIZE; + } +} + +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + u32 val[2] = {}; + int ret; + + if (dev_id == 0) { + ret = fuse_read(39, 3, &val[0]); + if (ret) + goto err; + + ret = fuse_read(39, 4, &val[1]); + if (ret) + goto err; + + mac[0] = val[1] >> 8; + mac[1] = val[1]; + mac[2] = val[0] >> 24; + mac[3] = val[0] >> 16; + mac[4] = val[0] >> 8; + mac[5] = val[0]; + + } else { + ret = fuse_read(39, 5, &val[0]); + if (ret) + goto err; + + ret = fuse_read(39, 4, &val[1]); + if (ret) + goto err; + + if (is_soc_rev(CHIP_REV_1_0)) { + mac[0] = val[1] >> 24; + mac[1] = val[1] >> 16; + mac[2] = val[0] >> 24; + mac[3] = val[0] >> 16; + mac[4] = val[0] >> 8; + mac[5] = val[0]; + } else { + mac[0] = val[0] >> 24; + mac[1] = val[0] >> 16; + mac[2] = val[0] >> 8; + mac[3] = val[0]; + mac[4] = val[1] >> 24; + mac[5] = val[1] >> 16; + } + } + + debug("%s: MAC%d: %02x.%02x.%02x.%02x.%02x.%02x\n", + __func__, dev_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return; +err: + memset(mac, 0, 6); + printf("%s: fuse read err: %d\n", __func__, ret); +} + +const char *get_imx_type(u32 imxtype) +{ + switch (imxtype) { + case MXC_CPU_IMX95: + return "95";/* iMX95 FULL */ + default: + return "??"; + } +} + +int print_cpuinfo(void) +{ + u32 cpurev, max_freq; + int minc, maxc; + + cpurev = get_cpu_rev(); + + printf("CPU: i.MX%s rev%d.%d", + get_imx_type((cpurev & 0x1FF000) >> 12), + (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0); + + max_freq = get_cpu_speed_grade_hz(); + if (!max_freq || max_freq == mxc_get_clock(MXC_ARM_CLK)) { + printf(" at %dMHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); + } else { + printf(" %d MHz (running at %d MHz)\n", max_freq / 1000000, + mxc_get_clock(MXC_ARM_CLK) / 1000000); + } + + puts("CPU: "); + switch (get_cpu_temp_grade(&minc, &maxc)) { + case TEMP_AUTOMOTIVE: + puts("Automotive temperature grade "); + break; + case TEMP_INDUSTRIAL: + puts("Industrial temperature grade "); + break; + case TEMP_EXTCOMMERCIAL: + if (is_imx93()) + puts("Extended Industrial temperature grade "); + else + puts("Extended Consumer temperature grade "); + break; + default: + puts("Consumer temperature grade "); + break; + } + printf("(%dC to %dC)", minc, maxc); + +#if defined(CONFIG_DM_THERMAL) + struct udevice *udev; + int ret, temp; + + if (IS_ENABLED(CONFIG_IMX_TMU)) + ret = uclass_get_device_by_name(UCLASS_THERMAL, "cpu-thermal", &udev); + else + ret = uclass_get_device(UCLASS_THERMAL, 0, &udev); + if (!ret) { + ret = thermal_get_temp(udev, &temp); + + if (!ret) + printf(" at %dC", temp); + else + debug(" - invalid sensor data\n"); + } else { + debug(" - invalid sensor device\n"); + } +#endif + puts("\n"); + + return 0; +} + +void build_info(void) +{ + u32 fw_version, sha1, res, status; + int ret; + + printf("\nBuildInfo:\n"); + + ret = ele_get_fw_status(&status, &res); + if (ret) { + printf(" - ELE firmware status failed %d, 0x%x\n", ret, res); + } else if ((status & 0xff) == 1) { + ret = ele_get_fw_version(&fw_version, &sha1, &res); + if (ret) { + printf(" - ELE firmware version failed %d, 0x%x\n", ret, res); + } else { + printf(" - ELE firmware version %u.%u.%u-%x", + (fw_version & (0x00ff0000)) >> 16, + (fw_version & (0x0000ff00)) >> 8, + (fw_version & (0x000000ff)), sha1); + ((fw_version & (0x80000000)) >> 31) == 1 ? puts("-dirty\n") : puts("\n"); + } + } else { + printf(" - ELE firmware not included\n"); + } + puts("\n"); +} + +int arch_misc_init(void) +{ + build_info(); + return 0; +} + +#ifdef CONFIG_OF_BOARD_FIXUP +#ifndef CONFIG_SPL_BUILD +int board_fix_fdt(void *fdt) +{ + return 0; +} +#endif +#endif + +int ft_system_setup(void *blob, struct bd_info *bd) +{ + return 0; +} + +#if defined(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG) +void get_board_serial(struct tag_serialnr *serialnr) +{ + printf("UID: 0x%x 0x%x 0x%x 0x%x\n", + gd->arch.uid[0], gd->arch.uid[1], gd->arch.uid[2], gd->arch.uid[3]); + + serialnr->low = gd->arch.uid[0]; + serialnr->high = gd->arch.uid[3]; +} +#endif + +static void gpio_reset(ulong gpio_base) +{ + writel(0, gpio_base + 0x10); + writel(0, gpio_base + 0x14); + writel(0, gpio_base + 0x18); + writel(0, gpio_base + 0x1c); +} + +int arch_cpu_init(void) +{ + if (IS_ENABLED(CONFIG_SPL_BUILD)) { + disable_wdog((void __iomem *)WDG3_BASE_ADDR); + disable_wdog((void __iomem *)WDG4_BASE_ADDR); + + clock_init_early(); + + gpio_reset(GPIO2_BASE_ADDR); + gpio_reset(GPIO3_BASE_ADDR); + gpio_reset(GPIO4_BASE_ADDR); + gpio_reset(GPIO5_BASE_ADDR); + } + + return 0; +} + +int imx9_probe_mu(void) +{ + struct udevice *dev; + int node, ret; + u32 res; + struct ele_get_info_data info; + + ret = uclass_get_device_by_driver(UCLASS_SCMI_AGENT, DM_DRIVER_GET(scmi_mbox), &dev); + if (ret) + return ret; + + ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev); + if (ret) + return ret; + + ret = devm_scmi_of_get_channel(dev); + if (ret) + return ret; + + ret = uclass_get_device_by_name(UCLASS_PINCTRL, "protocol@19", &dev); + if (ret) + return ret; + + node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx93-mu-s4"); + + ret = uclass_get_device_by_of_offset(UCLASS_MISC, node, &dev); + if (ret) + return ret; + + if (gd->flags & GD_FLG_RELOC) + return 0; + + ret = ele_get_info(&info, &res); + if (ret) + return ret; + + set_cpu_info(&info); + + return 0; +} + +EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, imx9_probe_mu); +EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_R, imx9_probe_mu); + +int timer_init(void) +{ + gd->arch.tbl = 0; + gd->arch.tbu = 0; + +#ifdef CONFIG_SPL_BUILD + unsigned long freq = 24000000; + + asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory"); +#endif + + return 0; +} + +enum env_location env_get_location(enum env_operation op, int prio) +{ + enum boot_device dev = get_boot_device(); + enum env_location env_loc = ENVL_UNKNOWN; + + if (prio) + return env_loc; + + switch (dev) { +#if defined(CONFIG_ENV_IS_IN_SPI_FLASH) + case QSPI_BOOT: + env_loc = ENVL_SPI_FLASH; + break; +#endif +#if defined(CONFIG_ENV_IS_IN_MMC) + case SD1_BOOT: + case SD2_BOOT: + case SD3_BOOT: + case MMC1_BOOT: + case MMC2_BOOT: + case MMC3_BOOT: + env_loc = ENVL_MMC; + break; +#endif + default: +#if defined(CONFIG_ENV_IS_NOWHERE) + env_loc = ENVL_NOWHERE; +#endif + break; + } + + return env_loc; +} + +enum imx9_soc_voltage_mode soc_target_voltage_mode(void) +{ + u32 speed = get_cpu_speed_grade_hz(); + enum imx9_soc_voltage_mode voltage = VOLT_OVER_DRIVE; + + if (is_imx95()) { + if (speed == 2000000000) + voltage = VOLT_SUPER_OVER_DRIVE; + else if (speed == 1800000000) + voltage = VOLT_OVER_DRIVE; + else if (speed == 1400000000) + voltage = VOLT_NOMINAL_DRIVE; + else /* boot not support low drive mode according to AS */ + printf("Unexpected A55 freq %u, default to OD\n", speed); + } + + return voltage; +} + +#if IS_ENABLED(CONFIG_SCMI_FIRMWARE) +enum boot_device get_boot_device(void) +{ + volatile gd_t *pgd = gd; + int ret; + u16 boot_type; + u8 boot_instance; + enum boot_device boot_dev = 0; + rom_passover_t *rdata; + +#ifdef CONFIG_SPL_BUILD + rdata = &rom_passover_data; +#else + rom_passover_t rom_data = {0}; + + if (pgd->reloc_off == 0) + rdata = &rom_data; + else + rdata = &rom_passover_data; +#endif + if (rdata->tag == 0) { + ret = scmi_get_rom_data(rdata); + if (ret != 0) { + puts("SCMI: failure at rom_boot_info\n"); + return -1; + } + } + boot_type = rdata->boot_dev_type; + boot_instance = rdata->boot_dev_inst; + + set_gd(pgd); + + switch (boot_type) { + case BT_DEV_TYPE_SD: + boot_dev = boot_instance + SD1_BOOT; + break; + case BT_DEV_TYPE_MMC: + boot_dev = boot_instance + MMC1_BOOT; + break; + case BT_DEV_TYPE_NAND: + boot_dev = NAND_BOOT; + break; + case BT_DEV_TYPE_FLEXSPINOR: + boot_dev = QSPI_BOOT; + break; + case BT_DEV_TYPE_USB: + boot_dev = boot_instance + USB_BOOT; +#ifdef CONFIG_IMX95 + boot_dev -= 3; //iMX95 usb instance start at 3 +#endif + break; + default: + break; + } + + return boot_dev; +} +#endif

From: Ye Li ye.li@nxp.com
This patch adds i.MX95 Kconfig and Makefile. i.MX95 uses SCMI.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Peng Fan peng.fan@nxp.com --- arch/arm/mach-imx/imx9/Kconfig | 6 ++++++ arch/arm/mach-imx/imx9/Makefile | 11 ++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-imx/imx9/Kconfig b/arch/arm/mach-imx/imx9/Kconfig index 54c6b117fcff21be5c3800ebd1dc30f8ea12ac42..596e753f2897c11d7ca3bcc9211af786d005bfd9 100644 --- a/arch/arm/mach-imx/imx9/Kconfig +++ b/arch/arm/mach-imx/imx9/Kconfig @@ -21,6 +21,12 @@ config IMX91 select IMX9 select ARMV8_SPL_EXCEPTION_VECTORS
+config IMX95 + bool + select IMX9 + select ARMV8_SPL_EXCEPTION_VECTORS + select SCMI_FIRMWARE + select DM_MAILBOX
config SYS_SOC default "imx9" diff --git a/arch/arm/mach-imx/imx9/Makefile b/arch/arm/mach-imx/imx9/Makefile index 45a9105a75a558dada3c328ed0878050da2a41e1..8d43ea2b267e2608df2e8f140c91b626dd969842 100644 --- a/arch/arm/mach-imx/imx9/Makefile +++ b/arch/arm/mach-imx/imx9/Makefile @@ -1,10 +1,15 @@ # SPDX-License-Identifier: GPL-2.0+ # -# Copyright 2022 NXP +# Copyright 2024 NXP
obj-y += lowlevel_init.o + +ifeq ($(CONFIG_SCMI_FIRMWARE),y) +obj-y += scmi/ +else obj-y += soc.o clock.o clock_root.o trdc.o +endif
-#ifndef CONFIG_XPL_BUILD +ifneq ($(CONFIG_SPL_BUILD),y) obj-y += imx_bootaux.o -#endif +endif \ No newline at end of file

From: Ye Li ye.li@nxp.com
When SPL loading image to secure region, for example, ATF and tee to DDR secure region. Because the USDHC controller is non-secure master, it can't access this region and will cause loading issue.
So override h_spl_load_read to use a trampoline buffer in nonsecure region, then use CPU to copy the image from trampoline buffer to destination secure region.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Peng Fan peng.fan@nxp.com --- arch/arm/mach-imx/imx9/scmi/soc.c | 40 +++++++++++++++++++++++++++++++++++++++ common/spl/spl_mmc.c | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/imx9/scmi/soc.c b/arch/arm/mach-imx/imx9/scmi/soc.c index fefb1a6f4ca58722a5d93c39e4f6a7aaf85aa177..8a7df24afecc1d6d77b7162be639b56af95fd975 100644 --- a/arch/arm/mach-imx/imx9/scmi/soc.c +++ b/arch/arm/mach-imx/imx9/scmi/soc.c @@ -41,6 +41,8 @@ #include <scmi_agent.h> #include <scmi_protocols.h> #endif +#include <spl.h> +#include <mmc.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -830,3 +832,41 @@ enum boot_device get_boot_device(void) return boot_dev; } #endif + +ulong h_spl_load_read(struct spl_load_info *load, ulong off, + ulong size, void *buf) +{ + struct blk_desc *bd = load->priv; + lbaint_t sector = off >> bd->log2blksz; + lbaint_t count = size >> bd->log2blksz; + ulong trampoline_sz = SZ_16M; + void *trampoline = (void *)((ulong)CFG_SYS_SDRAM_BASE + PHYS_SDRAM_SIZE - trampoline_sz); + ulong ns_ddr_end = CFG_SYS_SDRAM_BASE + PHYS_SDRAM_SIZE; + ulong read_count, trampoline_cnt = trampoline_sz >> bd->log2blksz, actual, total; + +#ifdef PHYS_SDRAM_2_SIZE + ns_ddr_end += PHYS_SDRAM_2_SIZE; +#endif + + /* Check if the buf is in non-secure world, otherwise copy from trampoline */ + if ((ulong)buf < CFG_SYS_SDRAM_BASE || (ulong)buf + (count * sector) > ns_ddr_end) { + total = 0; + while (count) { + read_count = trampoline_cnt > count ? count : trampoline_cnt; + actual = blk_dread(bd, sector, read_count, trampoline); + if (actual != read_count) { + printf("Error in blk_dread, %lu, %lu\n", read_count, actual); + return 0; + } + memcpy(buf, trampoline, actual * 512); + buf += actual * 512; + sector += actual; + total += actual; + count -= actual; + } + + return total << bd->log2blksz; + } + + return blk_dread(bd, sector, count, buf) << bd->log2blksz; +} diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 1f69659321620739d066bd806acd1d282b66bad3..d15a6945f9c24ee427b847c036413c52475c44a8 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -17,7 +17,7 @@ #include <image.h> #include <imx_container.h>
-static ulong h_spl_load_read(struct spl_load_info *load, ulong off, +ulong __weak h_spl_load_read(struct spl_load_info *load, ulong off, ulong size, void *buf) { struct blk_desc *bd = load->priv;

From: Peng Fan peng.fan@nxp.com
This patch adds the macro SCMI_MSG for protocols that do not need _in_array.
Signed-off-by: Peng Fan peng.fan@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Ye Li ye.li@nxp.com --- include/scmi_agent.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/include/scmi_agent.h b/include/scmi_agent.h index 755986d6c424ccc881ac0943a88735cbcfacb001..5508a126a6dc504afa6d896c78c760b1af0d3deb 100644 --- a/include/scmi_agent.h +++ b/include/scmi_agent.h @@ -54,6 +54,17 @@ struct scmi_msg { .out_msg_sz = sizeof(_out_array), \ }
+/* Helper macro to match a message on output array references */ +#define SCMI_MSG(_protocol, _message, _out_array) \ + (struct scmi_msg){ \ + .protocol_id = (_protocol), \ + .message_id = (_message), \ + .in_msg = (uint8_t *)NULL, \ + .in_msg_sz = 0, \ + .out_msg = (uint8_t *)&(_out_array), \ + .out_msg_sz = sizeof(_out_array), \ + } + /** * devm_scmi_of_get_channel() - Get SCMI channel handle from SCMI agent DT node *

From: Alice Guo alice.guo@nxp.com
i.MX95 only supports low power boot, which means A55 is kicked by M33. There is no ROM runs on A55 in such case so that deselect IMX8_ROMAPI for i.MX95.
Signed-off-by: Alice Guo alice.guo@nxp.com --- arch/arm/mach-imx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 134e42028c3787d78e28af03d40c41a8b2b1981b..daf6443aa5b40b6410f2645937239a4ec785fa34 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -180,7 +180,7 @@ config DDRMC_VF610_CALIBRATION
config IMX8_ROMAPI def_bool y - depends on IMX8MN || IMX8MP || IMX8ULP || IMX9 + depends on IMX8MN || IMX8MP || IMX8ULP || (IMX9 && !IMX95)
config SPL_IMX_ROMAPI_LOADADDR hex "Default load address to load image through ROM API"

From: Alice Guo alice.guo@nxp.com
i.MX95 needs to combine DDR PHY firmware images and their byte counts together, so add a new entry type nxp-append-ddrfw for this requirement.
Signed-off-by: Alice Guo alice.guo@nxp.com --- tools/binman/entries.rst | 14 ++++++ tools/binman/etype/nxp_append_ddrfw.py | 78 ++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+)
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index 83068ba6d39d9a5b586312fd4a062b0da31eb595..061bd2f1da9812d36c90b1fb10a919667e36ceaa 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -1658,6 +1658,20 @@ Properties / Entry arguments:
+.. _etype_nxp_append_ddrfw: + +Entry: nxp-append-ddrfw: pack NXP LPDDR firmware +--------------------------------------------------- + +Properties / Entry arguments: + - oei_m33_ddr_image - M33 DDR IMAGE + - lpddr_imem - Synopsys LPDDR PHY firmware + - lpddr_dmem - Synopsys LPDDR PHY firmware + - lpddr_imem_qb - Synopsys LPDDR quick boot firmware + - lpddr_dmem_qb - Synopsys LPDDR quick boot firmware + + + .. _etype_opensbi:
Entry: opensbi: RISC-V OpenSBI fw_dynamic blob diff --git a/tools/binman/etype/nxp_append_ddrfw.py b/tools/binman/etype/nxp_append_ddrfw.py new file mode 100644 index 0000000000000000000000000000000000000000..bc23a7611eaf823651a8fcbc9898c9140c277d7f --- /dev/null +++ b/tools/binman/etype/nxp_append_ddrfw.py @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2024 NXP + +from binman.etype.section import Entry_section +from dtoc import fdt_util +import os + +class Entry_nxp_append_ddrfw(Entry_section): + """NXP M33 OEI DDRFW + + Properties / Entry arguments: + - oei_m33_ddr_image: M33 DDR IMAGE + - lpddr_imem: Synopsys LPDDR PHY firmware + - lpddr_dmem: Synopsys LPDDR PHY firmware + - lpddr_imem_qb: Synopsys LPDDR quick boot firmware + - lpddr_dmem_qb: Synopsys LPDDR quick boot firmware + """ + + def __init__(self, section, etype, node): + super().__init__(section, etype, node) + self.required_props = ['oei_m33_ddr_image', 'lpddr_imem', 'lpddr_dmem', + 'lpddr_imem_qb', 'lpddr_dmem_qb'] + + def ReadNode(self): + super().ReadNode() + self.oei_m33_ddr_image = fdt_util.GetString(self._node, 'oei_m33_ddr_image') + self.lpddr_imem = fdt_util.GetString(self._node, 'lpddr_imem') + self.lpddr_dmem = fdt_util.GetString(self._node, 'lpddr_dmem') + self.lpddr_imem_qb = fdt_util.GetString(self._node, 'lpddr_imem_qb') + self.lpddr_dmem_qb = fdt_util.GetString(self._node, 'lpddr_dmem_qb') + self.ReadEntries() + + def BuildSectionData(self, required): + u_boot_path = os.path.abspath('.') + + oei_m33_ddr_image_path = os.path.join(u_boot_path, self.oei_m33_ddr_image) + lpddr_imem_path = os.path.join(u_boot_path, self.lpddr_imem) + lpddr_dmem_path = os.path.join(u_boot_path, self.lpddr_dmem) + lpddr_imem_qb_path = os.path.join(u_boot_path, self.lpddr_imem_qb) + lpddr_dmem_qb_path = os.path.join(u_boot_path, self.lpddr_dmem_qb) + + if (not (os.path.exists(oei_m33_ddr_image_path) and + os.path.exists(lpddr_imem_path) and os.path.exists(lpddr_dmem_path) and + os.path.exists(lpddr_imem_qb_path) and os.path.exists(lpddr_dmem_qb_path))): + print("Please check if there are any external blobs that do not exist.") + return b'' + + lpddr_imem_size = os.path.getsize(lpddr_imem_path) + lpddr_dmem_size = os.path.getsize(lpddr_dmem_path) + lpddr_imem_qb_size = os.path.getsize(lpddr_imem_qb_path) + lpddr_dmem_qb_size = os.path.getsize(lpddr_dmem_qb_path) + + with open(oei_m33_ddr_image_path, 'rb') as file: + oei_m33_ddr_image = file.read() + + length = len(oei_m33_ddr_image) + if (length % 4 != 0): + oei_m33_ddr_image += bytes(4 - length % 4) + + fw_header = lpddr_imem_size.to_bytes(4, 'little') + lpddr_dmem_size.to_bytes(4, 'little') + with open(lpddr_imem_path, 'rb') as file: + lpddr_imem = file.read() + with open(lpddr_dmem_path, 'rb') as file: + lpddr_dmem = file.read() + + fw_header_qb = lpddr_imem_qb_size.to_bytes(4, 'little') + lpddr_dmem_qb_size.to_bytes(4, 'little') + with open(lpddr_imem_qb_path, 'rb') as file: + lpddr_imem_qb = file.read() + with open(lpddr_dmem_qb_path, 'rb') as file: + lpddr_dmem_qb = file.read() + + data = oei_m33_ddr_image + fw_header + lpddr_imem + lpddr_dmem + fw_header_qb + lpddr_imem_qb + lpddr_dmem_qb + length = len(data) + if (length % 8 != 0): + data += bytes(8 - length % 8) + + return data

Hi Alice,
On Thu, 19 Dec 2024 at 19:56, Alice Guo alice.guo@oss.nxp.com wrote:
From: Alice Guo alice.guo@nxp.com
i.MX95 needs to combine DDR PHY firmware images and their byte counts together, so add a new entry type nxp-append-ddrfw for this requirement.
Signed-off-by: Alice Guo alice.guo@nxp.com
tools/binman/entries.rst | 14 ++++++ tools/binman/etype/nxp_append_ddrfw.py | 78 ++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+)
Please note that you should create a test[1] for any new Binman etype.
You can see the current work on this[2], which failed apparently due to a bug in the 'cst' tool.
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index 83068ba6d39d9a5b586312fd4a062b0da31eb595..061bd2f1da9812d36c90b1fb10a919667e36ceaa 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -1658,6 +1658,20 @@ Properties / Entry arguments:
+.. _etype_nxp_append_ddrfw:
+Entry: nxp-append-ddrfw: pack NXP LPDDR firmware +---------------------------------------------------
+Properties / Entry arguments:
- oei_m33_ddr_image - M33 DDR IMAGE
- lpddr_imem - Synopsys LPDDR PHY firmware
- lpddr_dmem - Synopsys LPDDR PHY firmware
- lpddr_imem_qb - Synopsys LPDDR quick boot firmware
- lpddr_dmem_qb - Synopsys LPDDR quick boot firmware
.. _etype_opensbi:
Entry: opensbi: RISC-V OpenSBI fw_dynamic blob diff --git a/tools/binman/etype/nxp_append_ddrfw.py b/tools/binman/etype/nxp_append_ddrfw.py new file mode 100644 index 0000000000000000000000000000000000000000..bc23a7611eaf823651a8fcbc9898c9140c277d7f --- /dev/null +++ b/tools/binman/etype/nxp_append_ddrfw.py @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2024 NXP
+from binman.etype.section import Entry_section +from dtoc import fdt_util +import os
+class Entry_nxp_append_ddrfw(Entry_section):
- """NXP M33 OEI DDRFW
Here you should describe the entry type so people know what it is for. Is the word 'append' needed in the name?
- Properties / Entry arguments:
- oei_m33_ddr_image: M33 DDR IMAGE
- lpddr_imem: Synopsys LPDDR PHY firmware
- lpddr_dmem: Synopsys LPDDR PHY firmware
- lpddr_imem_qb: Synopsys LPDDR quick boot firmware
- lpddr_dmem_qb: Synopsys LPDDR quick boot firmware
It isn't clear what these things are. Please add a bit more detail about how to get these things and what they are.
From what I can tell, I think you should add each of these as a new
etype. See for example Entry_intel_fsp_m.
Then in your image description you specify how these are packed together.
- """
- def __init__(self, section, etype, node):
super().__init__(section, etype, node)
self.required_props = ['oei_m33_ddr_image', 'lpddr_imem', 'lpddr_dmem',
'lpddr_imem_qb', 'lpddr_dmem_qb']
Properties should use hyphens rather than underscores, to fit with devicetree usage.
- def ReadNode(self):
super().ReadNode()
self.oei_m33_ddr_image = fdt_util.GetString(self._node, 'oei_m33_ddr_image')
This looks like an output file. Binman handles this side of things and you should not have etypes writing out files themselves.
self.lpddr_imem = fdt_util.GetString(self._node, 'lpddr_imem')
self.lpddr_dmem = fdt_util.GetString(self._node, 'lpddr_dmem')
self.lpddr_imem_qb = fdt_util.GetString(self._node, 'lpddr_imem_qb')
self.lpddr_dmem_qb = fdt_util.GetString(self._node, 'lpddr_dmem_qb')
self.ReadEntries()
- def BuildSectionData(self, required):
u_boot_path = os.path.abspath('.')
oei_m33_ddr_image_path = os.path.join(u_boot_path, self.oei_m33_ddr_image)
lpddr_imem_path = os.path.join(u_boot_path, self.lpddr_imem)
lpddr_dmem_path = os.path.join(u_boot_path, self.lpddr_dmem)
lpddr_imem_qb_path = os.path.join(u_boot_path, self.lpddr_imem_qb)
lpddr_dmem_qb_path = os.path.join(u_boot_path, self.lpddr_dmem_qb)
if (not (os.path.exists(oei_m33_ddr_image_path) and
os.path.exists(lpddr_imem_path) and os.path.exists(lpddr_dmem_path) and
os.path.exists(lpddr_imem_qb_path) and os.path.exists(lpddr_dmem_qb_path))):
print("Please check if there are any external blobs that do not exist.")
return b''
Missing blobs are handled automatically by Binman.[3]
lpddr_imem_size = os.path.getsize(lpddr_imem_path)
lpddr_dmem_size = os.path.getsize(lpddr_dmem_path)
lpddr_imem_qb_size = os.path.getsize(lpddr_imem_qb_path)
lpddr_dmem_qb_size = os.path.getsize(lpddr_dmem_qb_path)
with open(oei_m33_ddr_image_path, 'rb') as file:
oei_m33_ddr_image = file.read()
oei_m33_ddr_image = tools.read_file(oei_m33_ddr_image_path)
length = len(oei_m33_ddr_image)
if (length % 4 != 0):
oei_m33_ddr_image += bytes(4 - length % 4)
Binman handles alignment automatically. It just needs to be in the description
It seems that this etype is putting some files together with a little header.
fw_header = lpddr_imem_size.to_bytes(4, 'little') + lpddr_dmem_size.to_bytes(4, 'little')
with open(lpddr_imem_path, 'rb') as file:
lpddr_imem = file.read()
with open(lpddr_dmem_path, 'rb') as file:
lpddr_dmem = file.read()
fw_header_qb = lpddr_imem_qb_size.to_bytes(4, 'little') + lpddr_dmem_qb_size.to_bytes(4, 'little')
with open(lpddr_imem_qb_path, 'rb') as file:
lpddr_imem_qb = file.read()
with open(lpddr_dmem_qb_path, 'rb') as file:
lpddr_dmem_qb = file.read()
data = oei_m33_ddr_image + fw_header + lpddr_imem + lpddr_dmem + fw_header_qb + lpddr_imem_qb + lpddr_dmem_qb
So ddr-image should be its own etype (probably just a one-line thing like fsp-s
The next bit is a fw_header plus two blobs, so that should be in an 'lpddr' etype
The final bit is qb (?) which should be in a 'qb' etype, or some better name.
length = len(data)
if (length % 8 != 0):
data += bytes(8 - length % 8)
In the end you will have very little code and an image description like:
oei-m33-ddr { align-size = <4>; }; imx-lpddr { align-size = <4>; imx-lpddr-imem { }; imx-lpddr-dmem { }; }; imx-lpddr-qb { align-size = <4>; imx-lpddr-imem-qb { }; imx-lpddr-dmem-qb { }; };
Please let me know if you need help with any of this.
return data
-- 2.34.1
Regards, SImon
[1] https://docs.u-boot.org/en/latest/develop/binman_tests.html [2] https://patchwork.ozlabs.org/project/uboot/list/?series=430428&state=* [3] https://docs.u-boot.org/en/latest/develop/package/binman.html#external-blobs

From: Alice Guo alice.guo@nxp.com
i.MX95 uses binman to invoke mkimage to create image container. 2 image containers are needed currently. The first one is composed of ahab-container.img, LPDDR firmware images, OEI images, System Manager image and u-boot-spl.bin. The second one is comsisted of ARM Trusted firmware and u-boot.bin.
Because DDR OEI image and LPDDR firmware images have to be packaged together and named as m33-oei-ddrfw.bin, so imx9_image.sh does not check if m33-oei-ddrfw.bin exists.
Signed-off-by: Alice Guo alice.guo@nxp.com --- include/imx8image.h | 19 +++++-- tools/imx8image.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++----- tools/imx9_image.sh | 4 ++ 3 files changed, 149 insertions(+), 17 deletions(-)
diff --git a/include/imx8image.h b/include/imx8image.h index 6b95e93fb50980f9e86099b3103142dcbe38764a..233c28aa501f1e78c4160bdf5ca69d2b474217ea 100644 --- a/include/imx8image.h +++ b/include/imx8image.h @@ -157,7 +157,9 @@ enum imx8image_cmd { CMD_SOC_TYPE, CMD_CONTAINER, CMD_IMAGE, - CMD_DATA + CMD_DATA, + CMD_DUMMY_V2X, + CMD_HOLD };
enum imx8image_core_type { @@ -169,7 +171,9 @@ enum imx8image_core_type { CFG_A35, CFG_A55, CFG_A53, - CFG_A72 + CFG_A72, + CFG_M33, + CFG_OEI };
enum imx8image_fld_types { @@ -208,7 +212,10 @@ typedef enum option_type { FILEOFF, MSG_BLOCK, SENTINEL, - UPOWER + UPOWER, + OEI, + DUMMY_V2X, + HOLD } option_type_t;
typedef struct { @@ -227,12 +234,16 @@ typedef struct { #define CORE_CA35 4 #define CORE_CA72 5 #define CORE_SECO 6 +#define CORE_M33 7
#define CORE_ULP_CM33 0x1 #define CORE_ULP_CA35 0x2 #define CORE_ULP_UPOWER 0x4 #define CORE_ULP_SENTINEL 0x6
+#define CORE_IMX95_M33P 0U +#define CORE_IMX95_A55C0 2U + #define SC_R_OTP 357U #define SC_R_DEBUG 354U #define SC_R_ROM_0 236U @@ -246,10 +257,12 @@ typedef struct { #define IMG_TYPE_EXEC 0x03 /* Executable image type */ #define IMG_TYPE_DATA 0x04 /* Data image type */ #define IMG_TYPE_DCD_DDR 0x05 /* DCD/DDR image type */ +#define IMG_TYPE_OEI 0x05 /* Optional Executable image type */ #define IMG_TYPE_SECO 0x06 /* SECO image type */ #define IMG_TYPE_SENTINEL 0x06 /* SENTINEL image type */ #define IMG_TYPE_PROV 0x07 /* Provisioning image type */ #define IMG_TYPE_DEK 0x08 /* DEK validation type */ +#define IMG_TYPE_V2X_DUMMY 0x0E /* V2X Dummy image */
#define IMG_TYPE_SHIFT 0 #define IMG_TYPE_MASK 0x1f diff --git a/tools/imx8image.c b/tools/imx8image.c index 15510d3e712495c3508e130fcb2b4df42b07136b..9c4b43174558ec669f9a196c08756bcc6522b752 100644 --- a/tools/imx8image.c +++ b/tools/imx8image.c @@ -7,6 +7,7 @@
#include "imx8image.h" #include <image.h> +#include <linux/sizes.h>
static int p_idx; static int sector_size; @@ -54,6 +55,8 @@ static table_entry_t imx8image_cmds[] = { {CMD_CONTAINER, "CONTAINER", "new container", }, {CMD_IMAGE, "IMAGE", "new image", }, {CMD_DATA, "DATA", "new data", }, + {CMD_DUMMY_V2X, "DUMMY_V2X", "v2x", }, + {CMD_HOLD, "HOLD", "hold", }, {-1, "", "", }, };
@@ -66,6 +69,8 @@ static table_entry_t imx8image_core_entries[] = { {CFG_A55, "A55", "A55 core", }, {CFG_A53, "A53", "A53 core", }, {CFG_A72, "A72", "A72 core", }, + {CFG_OEI, "OEI", "OEI", }, + {CFG_M33, "M33", "M33 core", }, {-1, "", "", }, };
@@ -144,6 +149,14 @@ static void parse_cfg_cmd(image_t *param_stack, int32_t cmd, char *token, exit(EXIT_FAILURE); } break; + case CMD_DUMMY_V2X: + param_stack[p_idx].option = DUMMY_V2X; + param_stack[p_idx++].entry = (uint32_t)strtoll(token, NULL, 0); + break; + case CMD_HOLD: + param_stack[p_idx].option = HOLD; + param_stack[p_idx].entry = (uint32_t)strtoll(token, NULL, 0); + param_stack[p_idx++].filename = NULL; default: break; } @@ -221,6 +234,16 @@ static void parse_cfg_fld(image_t *param_stack, int32_t *cmd, char *token, (*cmd == CMD_DATA) ? DATA : AP; param_stack[p_idx].filename = token; break; + case CFG_OEI: + param_stack[p_idx].option = OEI; + param_stack[p_idx].filename = token; + param_stack[p_idx].ext = CORE_CM4_0; + break; + case CFG_M33: + param_stack[p_idx].option = M40; + param_stack[p_idx].ext = 0; + param_stack[p_idx].filename = token; + break; } break; case CFG_LOAD_ADDR: @@ -238,9 +261,15 @@ static void parse_cfg_fld(image_t *param_stack, int32_t *cmd, char *token, case CFG_A53: case CFG_A55: case CFG_A72: + case CFG_M33: param_stack[p_idx++].entry = (uint32_t)strtoll(token, NULL, 0); break; + case CFG_OEI: + param_stack[p_idx].dst = (uint32_t)strtoll(token, NULL, 0); + param_stack[p_idx].entry = param_stack[p_idx].dst + 1; + p_idx++; + break; } default: break; @@ -548,6 +577,7 @@ static void set_image_array_entry(flash_header_v3_t *container, char *tmp_filename, bool dcd_skip) { uint64_t entry = image_stack->entry; + uint64_t dst = image_stack->dst; uint64_t core = image_stack->ext; uint32_t meta; char *tmp_name = ""; @@ -557,7 +587,9 @@ static void set_image_array_entry(flash_header_v3_t *container, img->offset = offset; /* Is re-adjusted later */ img->size = size;
- set_image_hash(img, tmp_filename, IMAGE_HASH_ALGO_DEFAULT); + if (type != DUMMY_V2X) { + set_image_hash(img, tmp_filename, IMAGE_HASH_ALGO_DEFAULT); + }
switch (type) { case SECO: @@ -579,6 +611,27 @@ static void set_image_array_entry(flash_header_v3_t *container, img->dst = 0xe4000000; /* S400 IRAM base */ img->entry = 0xe4000000; break; + case OEI: + if (soc != IMX9) { + fprintf(stderr, "Error: invalid core id: %" PRIi64 "\n", core); + exit(EXIT_FAILURE); + } + + img->hab_flags |= IMG_TYPE_OEI; + if (core == CORE_CM4_0) { + img->hab_flags |= CORE_ULP_CM33 << BOOT_IMG_FLAGS_CORE_SHIFT; + meta = CORE_IMX95_M33P; + + } else { + img->hab_flags |= CORE_ULP_CA35 << BOOT_IMG_FLAGS_CORE_SHIFT; + meta = CORE_IMX95_A55C0; + } + tmp_name = "OEI"; + img->dst = (dst ? dst : entry); + img->entry = entry; + img->meta = meta; + custom_partition = 0; + break; case AP: if (soc == QX && core == CORE_CA35) { meta = IMAGE_A35_DEFAULT_META(custom_partition); @@ -586,8 +639,10 @@ static void set_image_array_entry(flash_header_v3_t *container, meta = IMAGE_A53_DEFAULT_META(custom_partition); } else if (soc == QM && core == CORE_CA72) { meta = IMAGE_A72_DEFAULT_META(custom_partition); - } else if (((soc == ULP) || (soc == IMX9)) && core == CORE_CA35) { + } else if ((soc == ULP) && core == CORE_CA35) { meta = 0; + } else if ((soc == IMX9) && core == CORE_CA35) { + meta = CORE_IMX95_A55C0; } else { fprintf(stderr, "Error: invalid AP core id: %" PRIu64 "\n", @@ -686,6 +741,15 @@ static void set_image_array_entry(flash_header_v3_t *container, img->entry = 0x28300200; } break; + case DUMMY_V2X: + img->hab_flags |= IMG_TYPE_V2X_DUMMY; + img->hab_flags |= CORE_SC << BOOT_IMG_FLAGS_CORE_SHIFT; + tmp_name = "V2X Dummy"; + set_image_hash(img, "/dev/null", IMAGE_HASH_ALGO_DEFAULT); + img->dst = entry; + img->entry = entry; + img->size = 0; /* dummy image has no size */ + break; default: fprintf(stderr, "unrecognized image type (%d)\n", type); exit(EXIT_FAILURE); @@ -708,15 +772,26 @@ void set_container(flash_header_v3_t *container, uint16_t sw_version, fprintf(stdout, "container flags: 0x%x\n", container->flags); }
-static int get_container_image_start_pos(image_t *image_stack, uint32_t align) +static int get_container_image_start_pos(image_t *image_stack, uint32_t align, uint32_t *v2x) { image_t *img_sp = image_stack; /*8K total container header*/ int file_off = CONTAINER_IMAGE_ARRAY_START_OFFSET; FILE *fd = NULL; - flash_header_v3_t header; + flash_header_v3_t *header; + flash_header_v3_t *header2; + void *p; int ret;
+ p = calloc(1, SZ_4K); + if (!p) { + fprintf(stderr, "Fail to alloc 4K memory\n"); + exit(EXIT_FAILURE); + } + + header = p; + header2 = p + FIRST_CONTAINER_HEADER_LENGTH; + while (img_sp->option != NO_IMG) { if (img_sp->option == APPEND) { fd = fopen(img_sp->filename, "r"); @@ -725,7 +800,7 @@ static int get_container_image_start_pos(image_t *image_stack, uint32_t align) exit(EXIT_FAILURE); }
- ret = fread(&header, sizeof(header), 1, fd); + ret = fread(header, SZ_4K, 1, fd); if (ret != 1) { printf("Failure Read header %d\n", ret); exit(EXIT_FAILURE); @@ -733,19 +808,27 @@ static int get_container_image_start_pos(image_t *image_stack, uint32_t align)
fclose(fd);
- if (header.tag != IVT_HEADER_TAG_B0) { - fprintf(stderr, "header tag mismatched file %s\n", img_sp->filename); + if (header->tag != IVT_HEADER_TAG_B0) { + fprintf(stderr, "header tag mismatched \n"); exit(EXIT_FAILURE); } else { - file_off += - header.img[header.num_images - 1].size; - file_off = ALIGN(file_off, align); + if (header2->tag != IVT_HEADER_TAG_B0) { + file_off += header->img[header->num_images - 1].size; + file_off = ALIGN(file_off, align); + } else { + file_off = header2->img[header2->num_images - 1].offset + FIRST_CONTAINER_HEADER_LENGTH; + file_off += header2->img[header2->num_images - 1].size; + file_off = ALIGN(file_off, align); + fprintf(stderr, "Has 2nd container %x\n", file_off); + *v2x = true; + } } }
img_sp++; }
+ free(p); return file_off; }
@@ -837,6 +920,7 @@ static int build_container(soc_type_t soc, uint32_t sector_size, char *tmp_filename = NULL; uint32_t size = 0; uint32_t file_padding = 0; + uint32_t v2x = false; int ret;
int container = -1; @@ -860,7 +944,7 @@ static int build_container(soc_type_t soc, uint32_t sector_size, set_imx_hdr_v3(&imx_header, 0); set_imx_hdr_v3(&imx_header, 1);
- file_off = get_container_image_start_pos(image_stack, sector_size); + file_off = get_container_image_start_pos(image_stack, sector_size, &v2x); fprintf(stdout, "container image offset (aligned):%x\n", file_off);
/* step through image stack and generate the header */ @@ -869,6 +953,7 @@ static int build_container(soc_type_t soc, uint32_t sector_size, /* stop once we reach null terminator */ while (img_sp->option != NO_IMG) { switch (img_sp->option) { + case OEI: case AP: case M40: case M41: @@ -891,6 +976,30 @@ static int build_container(soc_type_t soc, uint32_t sector_size, file_off += ALIGN(sbuf.st_size, sector_size); break;
+ case DUMMY_V2X: + if (container < 0) { + fprintf(stderr, "No container found\n"); + exit(EXIT_FAILURE); + } + tmp_filename = "dummy"; + set_image_array_entry(&imx_header.fhdr[container], + soc, + img_sp, + file_off, + 0, + tmp_filename, + dcd_skip); + img_sp->src = file_off; + break; + + case HOLD: + if (container < 0) { + fprintf(stderr, "No container found\n"); + exit(EXIT_FAILURE); + } + file_off += ALIGN(img_sp->entry, sector_size); + break; + case SECO: case SENTINEL: if (container < 0) { @@ -962,11 +1071,15 @@ static int build_container(soc_type_t soc, uint32_t sector_size, do { if (img_sp->option == APPEND) { copy_file(ofd, img_sp->filename, 0, 0); - file_padding += FIRST_CONTAINER_HEADER_LENGTH; + if (v2x) + file_padding += FIRST_CONTAINER_HEADER_LENGTH * 2; + else + file_padding += FIRST_CONTAINER_HEADER_LENGTH; } img_sp++; } while (img_sp->option != NO_IMG);
+ fprintf(stderr, "%s: %x %d\n", __func__, file_padding, v2x); /* Add padding or skip appended container */ ret = lseek(ofd, file_padding, SEEK_SET); if (ret < 0) { @@ -979,6 +1092,7 @@ static int build_container(soc_type_t soc, uint32_t sector_size, /* Note: Image offset are not contained in the image */ tmp = flatten_container_header(&imx_header, container + 1, &size, file_padding); + fprintf(stderr, "error writing image hdr %x\n", size); /* Write image header */ if (write(ofd, tmp, size) != size) { fprintf(stderr, "error writing image hdr\n"); @@ -999,7 +1113,8 @@ static int build_container(soc_type_t soc, uint32_t sector_size, img_sp->option == AP || img_sp->option == DATA || img_sp->option == SCD || img_sp->option == SCFW || img_sp->option == SECO || img_sp->option == MSG_BLOCK || - img_sp->option == UPOWER || img_sp->option == SENTINEL) { + img_sp->option == UPOWER || img_sp->option == SENTINEL || + img_sp->option == OEI) { copy_file_aligned(ofd, img_sp->filename, img_sp->src, sector_size); } @@ -1030,7 +1145,7 @@ int imx8image_copy_image(int outfd, struct image_tool_params *mparams) fprintf(stdout, "CONTAINER SW VERSION:\t0x%04x\n", sw_version);
build_container(soc, sector_size, emmc_fastboot, - img_sp, dcd_skip, fuse_version, sw_version, outfd); + img_sp, false, fuse_version, sw_version, outfd);
return 0; } diff --git a/tools/imx9_image.sh b/tools/imx9_image.sh index ca78a57a19a06ade4792da6d2435cbc4fa07de62..76db4e8eff4018ea4eba43477c8122a08bfa92cf 100755 --- a/tools/imx9_image.sh +++ b/tools/imx9_image.sh @@ -18,6 +18,10 @@ for f in $blobs; do continue fi
+ if [ $f = "m33-oei-ddrfw.bin" ]; then + continue + fi + if [ ! -f $tmp ]; then echo "WARNING '$tmp' not found, resulting binary may be not-functional" >&2

From: Ye Li ye.li@nxp.com
This patch adds i.MX95 19x19 EVK board basic support.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Peng Fan peng.fan@nxp.com --- arch/arm/dts/imx95-19x19-evk-u-boot.dtsi | 224 ++++++++++++++++++++++++++ arch/arm/mach-imx/imx9/Kconfig | 6 + arch/arm/mach-imx/imx9/scmi/container.cfg | 10 ++ arch/arm/mach-imx/imx9/scmi/imximage.cfg | 15 ++ arch/arm/mach-imx/imx9/scmi/soc.c | 1 + board/freescale/imx95_evk/Kconfig | 12 ++ board/freescale/imx95_evk/MAINTAINERS | 6 + board/freescale/imx95_evk/Makefile | 11 ++ board/freescale/imx95_evk/imx95_19x19_evk.env | 95 +++++++++++ board/freescale/imx95_evk/imx95_evk.c | 54 +++++++ board/freescale/imx95_evk/spl.c | 117 ++++++++++++++ configs/imx95_19x19_evk_defconfig | 178 ++++++++++++++++++++ doc/board/nxp/imx95_evk.rst | 109 +++++++++++++ doc/board/nxp/index.rst | 1 + include/configs/imx95_evk.h | 36 +++++ 15 files changed, 875 insertions(+)
diff --git a/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi b/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..5c891518448d24204f5ca2a00957b47a0a24bd70 --- /dev/null +++ b/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#ifdef CONFIG_BINMAN +/ { + binman { + multiple-images; + + m33-oei-ddrfw { + filename = "m33-oei-ddrfw.bin"; + + nxp-append-ddrfw { + oei_m33_ddr_image = "oei-m33-ddr.bin"; + lpddr_imem = "lpddr5_imem_v202311.bin"; + lpddr_dmem = "lpddr5_dmem_v202311.bin"; + lpddr_imem_qb = "lpddr5_imem_qb_v202311.bin"; + lpddr_dmem_qb = "lpddr5_dmem_qb_v202311.bin"; + }; + }; + + spl { + filename = "spl.bin"; + + mkimage { + args = "-n spl/u-boot-spl.cfgout -T imx8image"; + }; + }; + + u-boot { + filename = "uboot.bin"; + + mkimage { + args = "-n u-boot-container.cfgout -T imx8image"; + }; + }; + + imx-boot { + filename = "imx-boot-imx95.bin"; + pad-byte = <0x00>; + + blob-ext@1 { + align = <0x400>; + align-size = <0x400>; + offset = <0x0>; + filename = "spl.bin"; + }; + + blob-ext@2 { + filename = "uboot.bin"; + }; + }; + }; +}; +#endif + +&{/soc} { + bootph-all; + bootph-pre-ram; +}; + +&aips1 { + bootph-all; + bootph-pre-ram; +}; + +&aips2 { + bootph-all; + bootph-pre-ram; +}; + +&aips3 { + bootph-pre-ram; +}; + +&gpio1 { + reg = <0 0x47400000 0 0x1000>, <0 0x47400040 0 0x40>; +}; + +&gpio2 { + reg = <0 0x43810000 0 0x1000>, <0 0x43810040 0 0x40>; + bootph-pre-ram; +}; + +&gpio3 { + reg = <0 0x43820000 0 0x1000>, <0 0x43820040 0 0x40>; + bootph-pre-ram; +}; + +&gpio4 { + reg = <0 0x43840000 0 0x1000>, <0 0x43840040 0 0x40>; + bootph-pre-ram; +}; + +&gpio5 { + reg = <0 0x43850000 0 0x1000>, <0 0x43850040 0 0x40>; + bootph-pre-ram; +}; + +&lpuart1 { + clocks = <&scmi_clk IMX95_CLK_LPUART1>, <&scmi_clk IMX95_CLK_LPUART1>; + clock-names = "ipg", "per"; + bootph-pre-ram; +}; + +&mu2 { + bootph-all; + bootph-pre-ram; +}; + +&osc_24m { + bootph-all; + bootph-pre-ram; +}; + +&clk_ext1 { + bootph-all; + bootph-pre-ram; +}; + +&sram0 { + bootph-all; + bootph-pre-ram; +}; + +&scmi_buf0 { + bootph-all; + bootph-pre-ram; +}; + +&scmi_buf1 { + bootph-all; + bootph-pre-ram; +}; + +&{/firmware} { + bootph-all; + bootph-pre-ram; +}; + +&{/firmware/scmi} { + bootph-all; + bootph-pre-ram; +}; + +&{/firmware/scmi/protocol@11} { + bootph-all; + bootph-pre-ram; +}; + +&{/firmware/scmi/protocol@13} { + bootph-all; + bootph-pre-ram; +}; + +&{/firmware/scmi/protocol@14} { + bootph-all; + bootph-pre-ram; +}; + +&{/firmware/scmi/protocol@19} { + bootph-all; + bootph-pre-ram; +}; + +&pinctrl_uart1 { + bootph-pre-ram; +}; + +&usdhc1 { + bootph-pre-ram; +}; + +&pinctrl_usdhc1 { + bootph-pre-ram; +}; + +&pinctrl_usdhc1_100mhz { + bootph-pre-ram; +}; + +&pinctrl_usdhc1_200mhz { + bootph-pre-ram; +}; + +&usdhc2 { + bootph-pre-ram; +}; + +&pinctrl_usdhc2 { + bootph-pre-ram; +}; + +&pinctrl_usdhc2_100mhz { + bootph-pre-ram; +}; + +&pinctrl_usdhc2_200mhz { + bootph-pre-ram; +}; + +&pinctrl_usdhc2_gpio { + bootph-pre-ram; +}; + +®_usdhc2_vmmc { + bootph-pre-ram; +}; + +&pinctrl_reg_usdhc2_vmmc { + bootph-pre-ram; +}; + +&elemu3 { + compatible = "fsl,imx93-mu-s4"; + status = "okay"; + bootph-all; + bootph-pre-ram; +}; + +&wdog3 { + status = "disabled"; +}; diff --git a/arch/arm/mach-imx/imx9/Kconfig b/arch/arm/mach-imx/imx9/Kconfig index 596e753f2897c11d7ca3bcc9211af786d005bfd9..1ba277baeb353de301a1e67a7adf70f281752ded 100644 --- a/arch/arm/mach-imx/imx9/Kconfig +++ b/arch/arm/mach-imx/imx9/Kconfig @@ -66,6 +66,11 @@ config TARGET_PHYCORE_IMX93 select OF_BOARD_FIXUP select OF_BOARD_SETUP
+config TARGET_IMX95_19X19_EVK + bool "imx95_19x19_evk" + select IMX95 + imply OF_UPSTREAM + endchoice
source "board/freescale/imx91_evk/Kconfig" @@ -73,6 +78,7 @@ source "board/freescale/imx93_evk/Kconfig" source "board/freescale/imx93_qsb/Kconfig" source "board/phytec/phycore_imx93/Kconfig" source "board/variscite/imx93_var_som/Kconfig" +source "board/freescale/imx95_evk/Kconfig"
endif
diff --git a/arch/arm/mach-imx/imx9/scmi/container.cfg b/arch/arm/mach-imx/imx9/scmi/container.cfg new file mode 100644 index 0000000000000000000000000000000000000000..29f346e59c4afd0c2689667abe36f4b776b29ba8 --- /dev/null +++ b/arch/arm/mach-imx/imx9/scmi/container.cfg @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2024 NXP + */ + +BOOT_FROM SD +SOC_TYPE IMX9 +CONTAINER +IMAGE A55 bl31.bin 0x8a200000 +IMAGE A55 u-boot.bin CONFIG_TEXT_BASE \ No newline at end of file diff --git a/arch/arm/mach-imx/imx9/scmi/imximage.cfg b/arch/arm/mach-imx/imx9/scmi/imximage.cfg new file mode 100644 index 0000000000000000000000000000000000000000..c90432f5efa78dccb2c67e237b88a96174446b96 --- /dev/null +++ b/arch/arm/mach-imx/imx9/scmi/imximage.cfg @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2024 NXP + */ + +BOOT_FROM SD +SOC_TYPE IMX9 +APPEND mx95a0-ahab-container.img +CONTAINER +IMAGE OEI m33-oei-ddrfw.bin 0x1ffc0000 +HOLD 0x10000 +IMAGE OEI oei-m33-tcm.bin 0x1ffc0000 +IMAGE M33 m33_image.bin 0x1ffc0000 +IMAGE A55 spl/u-boot-spl.bin 0x20480000 +DUMMY_V2X 0x8b000000 \ No newline at end of file diff --git a/arch/arm/mach-imx/imx9/scmi/soc.c b/arch/arm/mach-imx/imx9/scmi/soc.c index 8a7df24afecc1d6d77b7162be639b56af95fd975..38ade99964b64512ba93423efcaa0cfb58094b00 100644 --- a/arch/arm/mach-imx/imx9/scmi/soc.c +++ b/arch/arm/mach-imx/imx9/scmi/soc.c @@ -43,6 +43,7 @@ #endif #include <spl.h> #include <mmc.h> +#include <asm/arch/mu.h>
DECLARE_GLOBAL_DATA_PTR;
diff --git a/board/freescale/imx95_evk/Kconfig b/board/freescale/imx95_evk/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..f9a67353e5db6d3ec94784cf091e45d8817d541c --- /dev/null +++ b/board/freescale/imx95_evk/Kconfig @@ -0,0 +1,12 @@ +if TARGET_IMX95_19X19_EVK + +config SYS_BOARD + default "imx95_evk" + +config SYS_VENDOR + default "freescale" + +config SYS_CONFIG_NAME + default "imx95_evk" + +endif diff --git a/board/freescale/imx95_evk/MAINTAINERS b/board/freescale/imx95_evk/MAINTAINERS new file mode 100644 index 0000000000000000000000000000000000000000..5caf763e0cc390c46fc54ee627bc966b2b110958 --- /dev/null +++ b/board/freescale/imx95_evk/MAINTAINERS @@ -0,0 +1,6 @@ +i.MX95 EVK BOARD +M: Alice Guo alice.guo@nxp.com +S: Maintained +F: board/freescale/imx95_evk/ +F: include/configs/imx95_evk.h +F: configs/imx95_19x19_evk_defconfig diff --git a/board/freescale/imx95_evk/Makefile b/board/freescale/imx95_evk/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a278d58ee0085176948b812703d120aaad3a3116 --- /dev/null +++ b/board/freescale/imx95_evk/Makefile @@ -0,0 +1,11 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += imx95_evk.o + +ifdef CONFIG_SPL_BUILD +obj-y += spl.o +endif diff --git a/board/freescale/imx95_evk/imx95_19x19_evk.env b/board/freescale/imx95_evk/imx95_19x19_evk.env new file mode 100644 index 0000000000000000000000000000000000000000..27e09d3d70a068efb97d69b27089d1f213f39ee9 --- /dev/null +++ b/board/freescale/imx95_evk/imx95_19x19_evk.env @@ -0,0 +1,95 @@ +sec_boot=no +initrd_addr=0x93800000 +emmc_dev=0 +sd_dev=1 +prepare_mcore=setenv mcore_clk clk-imx95.mcore_booted +scriptaddr=0x93500000 +kernel_addr_r=" __stringify(CONFIG_SYS_LOAD_ADDR) " +image=Image +splashimage=0xA0000000 +console=ttyLP0,115200 earlycon +fdt_addr_r=0x93000000 +fdt_addr=0x93000000 +cntr_addr=0xA8000000 +cntr_file=os_cntr_signed.bin +boot_fit=no +fdtfile=" CONFIG_DEFAULT_FDT_FILE " +bootm_size=0x10000000 +mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV)" +mmcpart=1 +mmcroot=/dev/mmcblk1p2 rootwait rw +mmcautodetect=yes +mmcargs=setenv bootargs ${mcore_clk} console=${console} root=${mmcroot} +loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script}; +bootscript=echo Running bootscript from mmc ...; source +loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image} +loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} ${fdtfile} +loadcntr=fatload mmc ${mmcdev}:${mmcpart} ${cntr_addr} ${cntr_file} +auth_os=auth_cntr ${cntr_addr} +boot_os=booti ${loadaddr} - ${fdt_addr_r}; +mmcboot=echo Booting from mmc ...; + run mmcargs; + if test ${sec_boot} = yes; then + if run auth_os; then + run boot_os; + else + echo ERR: failed to authenticate; + fi; + else + if test ${boot_fit} = yes || test ${boot_fit} = try; then + bootm ${loadaddr}; + else + if run loadfdt; then + run boot_os; + else + echo WARN: Cannot load the DT; + fi; + fi; + fi; +netargs=setenv bootargs ${mcore_clk} console=${console} + root=/dev/nfs + ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp +netboot=echo Booting from net ...; + run netargs; + if test ${ip_dyn} = yes; then + setenv get_cmd dhcp; + else + setenv get_cmd tftp; + fi; + if test ${sec_boot} = yes; then + ${get_cmd} ${cntr_addr} ${cntr_file}; + if run auth_os; then + run boot_os; + else + echo ERR: failed to authenticate; + fi; + else + ${get_cmd} ${loadaddr} ${image}; + if test ${boot_fit} = yes || test ${boot_fit} = try; then + bootm ${loadaddr}; + else + if ${get_cmd} ${fdt_addr_r} ${fdtfile}; then + run boot_os; + else + echo WARN: Cannot load the DT; + fi; + fi; + fi; +bsp_bootcmd=echo Running BSP bootcmd ...; + mmc dev ${mmcdev}; if mmc rescan; then + if run loadbootscript; then + run bootscript; + else + if test ${sec_boot} = yes; then + if run loadcntr; then + run mmcboot; + else run netboot; + fi; + else + if run loadimage; then + run mmcboot; + else run netboot; + fi; + fi; + fi; + fi; \ No newline at end of file diff --git a/board/freescale/imx95_evk/imx95_evk.c b/board/freescale/imx95_evk/imx95_evk.c new file mode 100644 index 0000000000000000000000000000000000000000..c75a8f2450288a34cfc01150d3c42b07f2215491 --- /dev/null +++ b/board/freescale/imx95_evk/imx95_evk.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include <env.h> +#include <init.h> +#include <asm/global_data.h> +#include <asm/arch-imx9/ccm_regs.h> +#include <asm/arch/clock.h> +#include <fdt_support.h> +#include <asm/io.h> +#include <linux/bitfield.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <miiphy.h> +#include <netdev.h> +#include <asm/gpio.h> +#include <asm/mach-imx/sys_proto.h> +#include <scmi_agent.h> +#include <scmi_protocols.h> +#include "../../../dts/upstream/src/arm64/freescale/imx95-clock.h" +#include "../../../dts/upstream/src/arm64/freescale/imx95-power.h" + +DECLARE_GLOBAL_DATA_PTR; + +int board_early_init_f(void) +{ + /* UART1: A55, UART2: M33, UART3: M7 */ + init_uart_clk(0); + + return 0; +} + +int board_init(void) +{ + return 0; +} + +int board_late_init(void) +{ +#ifdef CONFIG_ENV_IS_IN_MMC + board_late_mmc_env_init(); +#endif + + return 0; +} + +int board_phys_sdram_size(phys_size_t *size) +{ + *size = PHYS_SDRAM_SIZE + PHYS_SDRAM_2_SIZE; + + return 0; +} diff --git a/board/freescale/imx95_evk/spl.c b/board/freescale/imx95_evk/spl.c new file mode 100644 index 0000000000000000000000000000000000000000..006239f0751f9264d44304828bc9b9a26465abd1 --- /dev/null +++ b/board/freescale/imx95_evk/spl.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include <command.h> +#include <cpu_func.h> +#include <clk.h> +#include <hang.h> +#include <image.h> +#include <init.h> +#include <log.h> +#include <spl.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#include <asm/mach-imx/boot_mode.h> +#include <asm/mach-imx/syscounter.h> +#include <asm/mach-imx/ele_api.h> +#include <asm/sections.h> +#include <dm/uclass.h> +#include <dm/device.h> +#include <dm/uclass-internal.h> +#include <dm/device-internal.h> +#include <linux/delay.h> +#include <linux/iopoll.h> +#include <asm/arch/clock.h> +#include <asm/arch/ccm_regs.h> +#ifdef CONFIG_SCMI_FIRMWARE +#include <scmi_agent.h> +#include <scmi_protocols.h> +#include "../../../dts/upstream/src/arm64/freescale/imx95-clock.h" +#include "../../../dts/upstream/src/arm64/freescale/imx95-power.h" +#endif +#include <asm/arch/mu.h> + +DECLARE_GLOBAL_DATA_PTR; + +int spl_board_boot_device(enum boot_device boot_dev_spl) +{ + switch (boot_dev_spl) { + case SD1_BOOT: + case MMC1_BOOT: + return BOOT_DEVICE_MMC1; + case SD2_BOOT: + case MMC2_BOOT: + return BOOT_DEVICE_MMC2; + case USB_BOOT: + return BOOT_DEVICE_BOARD; + default: + return BOOT_DEVICE_NONE; + } +} + +void spl_board_init(void) +{ + puts("Normal Boot\n"); +} + +void board_init_f(ulong dummy) +{ + int ret; + bool ddrmix_power = false; + + /* Clear the BSS. */ + memset(__bss_start, 0, __bss_end - __bss_start); + +#ifdef CONFIG_SPL_RECOVER_DATA_SECTION + if (IS_ENABLED(CONFIG_SPL_BUILD)) + spl_save_restore_data(); +#endif + + timer_init(); + + /* Need dm_init() to run before any SCMI calls can be made. */ + spl_early_init(); + + /* Need enable SCMI drivers and ELE driver before enabling console */ + ret = imx9_probe_mu(); + if (ret) + hang(); /* if MU not probed, nothing can output, just hang here */ + + arch_cpu_init(); + + board_early_init_f(); + + preloader_console_init(); + + debug("SOC: 0x%x\n", gd->arch.soc_rev); + debug("LC: 0x%x\n", gd->arch.lifecycle); + + /* Will set ARM freq to max rate */ + clock_init_late(); + + /* Check is DDR MIX is already powered up. */ + u32 state = 0; + struct udevice *dev; + + ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev); + if (ret) + printf("%s: %d\n", __func__, ret); + + ret = scmi_pwd_state_get(dev, IMX95_PD_DDR, &state); + if (ret) { + printf("scmi_pwd_state_get Failed %d for DDRMIX\n", ret); + } else { + if (state == BIT(30)) { + panic("DDRMIX is powered OFF, Please initialize DDR with OEI \n"); + } else { + printf("DDRMIX is powered UP \n"); + ddrmix_power = true; + } + } + + board_init_r(NULL, 0); +} diff --git a/configs/imx95_19x19_evk_defconfig b/configs/imx95_19x19_evk_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..23c7ebf4694a9d2cf2604528b142ce716e66b85a --- /dev/null +++ b/configs/imx95_19x19_evk_defconfig @@ -0,0 +1,178 @@ +CONFIG_ARM=y +CONFIG_ARCH_IMX9=y +CONFIG_TEXT_BASE=0x90200000 +CONFIG_SYS_MALLOC_LEN=0x2000000 +CONFIG_SYS_MALLOC_F_LEN=0x10000 +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_NR_DRAM_BANKS=3 +CONFIG_ENV_SIZE=0x4000 +CONFIG_ENV_OFFSET=0x700000 +CONFIG_ENV_SECT_SIZE=0x10000 +CONFIG_DM_GPIO=y +CONFIG_DEFAULT_DEVICE_TREE="freescale/imx95-19x19-evk" +CONFIG_SPL_TEXT_BASE=0x20480000 +CONFIG_TARGET_IMX95_19X19_EVK=y +CONFIG_SYS_PROMPT="u-boot=> " +CONFIG_SPL_SERIAL=y +CONFIG_SPL_DRIVERS_MISC=y +CONFIG_SPL_STACK=0x204d6000 +CONFIG_SPL=y +CONFIG_SPL_LOAD_IMX_CONTAINER=y +CONFIG_IMX_CONFIG="arch/arm/mach-imx/imx9/scmi/imximage.cfg" +CONFIG_IMX_CONTAINER_CFG="arch/arm/mach-imx/imx9/scmi/container.cfg" +CONFIG_SYS_LOAD_ADDR=0x90400000 +CONFIG_SYS_MEMTEST_START=0x90000000 +CONFIG_SYS_MEMTEST_END=0xA0000000 +CONFIG_REMAKE_ELF=y +CONFIG_SYS_MONITOR_LEN=524288 +CONFIG_DEFAULT_FDT_FILE="imx95-19x19-evk.dtb" +CONFIG_ARCH_MISC_INIT=y +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_BOARD_LATE_INIT=y +CONFIG_SPL_MAX_SIZE=0x20000 +CONFIG_SPL_HAS_BSS_LINKER_SECTION=y +CONFIG_SPL_BSS_START_ADDR=0x204d6000 +CONFIG_SPL_BSS_MAX_SIZE=0x2000 +CONFIG_SPL_BOARD_INIT=y +CONFIG_SPL_MMC=y +CONFIG_SPL_GPIO=y +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y +CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x93200000 +CONFIG_SPL_SYS_MALLOC_SIZE=0x80000 +CONFIG_SPL_SYS_MMCSD_RAW_MODE=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1040 +CONFIG_SPL_POWER=y +CONFIG_SDP_LOADADDR=0x90400000 +CONFIG_SPL_WATCHDOG=y +CONFIG_SYS_MAXARGS=64 +CONFIG_SYS_CBSIZE=2048 +CONFIG_SYS_PBSIZE=2074 +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_NVEDIT_EFI=y +CONFIG_CMD_CRC32=y +CONFIG_CRC32_VERIFY=y +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_CLK=y +CONFIG_CMD_DFU=y +CONFIG_CMD_FUSE=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_PART=y +CONFIG_CMD_POWEROFF=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_SNTP=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_EFIDEBUG=y +CONFIG_CMD_RTC=y +CONFIG_CMD_TIME=y +CONFIG_CMD_GETTIME=y +CONFIG_CMD_TIMER=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_HASH=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_OF_CONTROL=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_IS_NOWHERE=y +CONFIG_ENV_IS_IN_MMC=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SYS_MMC_ENV_DEV=1 +CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y +CONFIG_USE_ETHPRIME=y +CONFIG_ETHPRIME="eth0" +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_SPL_DM=y +CONFIG_REGMAP=y +CONFIG_SYSCON=y +CONFIG_DFU_MMC=y +CONFIG_DFU_RAM=y +CONFIG_IMX_RGPIO2P=y +CONFIG_MTD=y +CONFIG_DM_SPI_FLASH=y +CONFIG_DM_SPI=y +CONFIG_NXP_FSPI=y +CONFIG_SPI=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_MT35XU=y +CONFIG_SF_DEFAULT_BUS=0 +CONFIG_SF_DEFAULT_SPEED=40000000 +CONFIG_DM_PCA953X=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_IMX_LPI2C=y +CONFIG_SUPPORT_EMMC_BOOT=y +CONFIG_MMC_IO_VOLTAGE=y +CONFIG_MMC_UHS_SUPPORT=y +CONFIG_MMC_HS400_ES_SUPPORT=y +CONFIG_MMC_HS400_SUPPORT=y +CONFIG_FSL_USDHC=y +CONFIG_PHY=y +CONFIG_MII=y +CONFIG_PINCTRL=y +CONFIG_SPL_PINCTRL=y +CONFIG_SPL_DM_REGULATOR=y +CONFIG_SPL_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_DM_RTC=y +CONFIG_DM_SERIAL=y +CONFIG_FSL_LPUART=y +CONFIG_ULP_WATCHDOG=y +CONFIG_LZO=y +CONFIG_BZIP2=y +CONFIG_HUSH_PARSER=y +CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_OF_SYSTEM_SETUP=y +CONFIG_ADP5585_GPIO=y +CONFIG_SPL_I2C=y +CONFIG_POWER_DOMAIN=y +# SCMI options +CONFIG_DM_MAILBOX=y +CONFIG_SCMI_FIRMWARE=y +CONFIG_SCMI_AGENT_SMCCC=n +CONFIG_CLK_SCMI=y +CONFIG_CLK=y +CONFIG_SPL_CLK_SCMI=y +CONFIG_SPL_CLK=y +CONFIG_PINCTRL_IMX_SCMI=y +CONFIG_SCMI_POWER_DOMAIN=y +CONFIG_SPL_DM_MAILBOX=y +CONFIG_SPL_FIRMWARE=y +#CONFIG_SPL_POWER_DOMAIN=y +CONFIG_SPL_IMX_MU_MBOX=y +CONFIG_IMX_MU_MBOX=y +#CONFIG_REMOTEPROC_SCMI_LMM=y +#CONFIG_CMD_REMOTEPROC=y +# CONFIG_RESET_SCMI=y +# CONFIG_DM_REGULATOR_SCMI=y +CONFIG_SPL_OF_TRANSLATE=y +CONFIG_PCI=y +CONFIG_PCIE_ECAM_GENERIC=y +CONFIG_PCI_SCAN_SHOW=y +CONFIG_CMD_PCI=y +CONFIG_DM_ETH=y +CONFIG_DM_MDIO=y +CONFIG_PHYLIB=y +CONFIG_PHYLIB_10G=y +CONFIG_PHY_AQUANTIA=y +CONFIG_PHY_REALTEK=y +CONFIG_FSL_ENETC=y +CONFIG_SYS_RX_ETH_BUFFER=8 +CONFIG_IMX8_ROMAPI=n +CONFIG_CLK_CCF=y +CONFIG_SPL_CLK_CCF=y +CONFIG_SPL_RECOVER_DATA_SECTION=y +CONFIG_BINMAN_FDT is not set +CONFIG_ENV_SOURCE_FILE="imx95_19x19_evk" diff --git a/doc/board/nxp/imx95_evk.rst b/doc/board/nxp/imx95_evk.rst new file mode 100644 index 0000000000000000000000000000000000000000..c2be474aa71f0f8d934f956c8840d330fbee98df --- /dev/null +++ b/doc/board/nxp/imx95_evk.rst @@ -0,0 +1,109 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +imx95_evk +======================= + +U-Boot for the NXP i.MX95 19x19 EVK board + +Quick Start +----------- + +- Get ahab-container.img +- Get the DDR PHY Firmware Images +- Get and Build OEI Images +- Get and Build System Manager Image +- Get and Build the ARM Trusted Firmware +- Build the Bootloader Image +- Boot + +Get ahab-container.img +-------------------------------------- + +Note: srctree is U-Boot source directory + +.. code-block:: bash + + $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-ele-imx-1.3.0-17945fc.bin + $ chmod +x firmware-ele-imx-1.3.0-17945fc.bin + $ ./firmware-ele-imx-1.3.0-17945fc.bin + $ cp firmware-ele-imx-1.3.0-17945fc.bin/mx95a0-ahab-container.img $(srctree) + +Get the DDR PHY Firmware Images +-------------------------------------- + +Note: srctree is U-Boot source directory + +.. code-block:: bash + + $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.26-d4c33ab.bin + $ chmod +x firmware-imx-8.26-d4c33ab.bin + $ ./firmware-imx-8.26-d4c33ab.bin + $ cp firmware-imx-8.26-d4c33ab/firmware/ddr/synopsys/lpddr5*v202311.bin $(srctree) + +Get and Build OEI Images +-------------------------------------- + +Note: srctree is U-Boot source directory +Get OEI from: https://github.com/nxp-imx/imx-oei +branch: master + +.. code-block:: bash + + $ sudo apt -y install make gcc g++-multilib srecord + $ wget https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-g... + $ tar xvf arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi.tar.xz + $ export TOOLS=$PWD + $ make board=mx95lp5 oei=ddr DEBUG=1 + $ cp build/mx95lp5/ddr/oei-m33-ddr.bin $(srctree) + + $ make board=mx95lp5 oei=tcm DEBUG=1 + $ cp build/mx95lp5/tcm/oei-m33-tcm.bin $(srctree) + +Get and Build System Manager Image +-------------------------------------- + +Note: srctree is U-Boot source directory +Get System Manager from: https://github.com/nxp-imx/imx-sm +branch: master + +.. code-block:: bash + + $ sudo apt -y install make gcc g++-multilib srecord + $ wget https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-g... + $ tar xvf arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi.tar.xz + $ export TOOLS=$PWD + $ make config=mx95evk all + $ cp build/mx95evk/m33_image.bin $(srctree) + +Get and Build the ARM Trusted Firmware +-------------------------------------- + +Note: srctree is U-Boot source directory +Get ATF from: https://github.com/nxp-imx/imx-atf/ +branch: lf_v2.10 + +.. code-block:: bash + + $ unset LDFLAGS + $ make PLAT=imx95 bl31 + $ cp build/imx95/release/bl31.bin $(srctree) + +Build the Bootloader Image +------------ + +.. code-block:: bash + + $ export CROSS_COMPILE=aarch64-poky-linux- + $ make imx95_19x19_evk_defconfig + $ make + +Copy imx-boot-imx95.bin to the MicroSD card: + +.. code-block:: bash + + $ sudo dd if=imx-boot-imx95.bin of=/dev/sdb bs=1k seek=32 conv=fsync + +Boot +---- + +Set i.MX95 boot device to MicroSD card diff --git a/doc/board/nxp/index.rst b/doc/board/nxp/index.rst index 8ca4b5619863f616dbedc7eb0ff8a286a3fbbf48..e7ec725cc04e9755ba3dac37561c26ebc3f1c716 100644 --- a/doc/board/nxp/index.rst +++ b/doc/board/nxp/index.rst @@ -15,6 +15,7 @@ NXP Semiconductors imx91_11x11_evk imx93_9x9_qsb imx93_11x11_evk + imx95_evk imxrt1020-evk imxrt1050-evk imxrt1170-evk diff --git a/include/configs/imx95_evk.h b/include/configs/imx95_evk.h new file mode 100644 index 0000000000000000000000000000000000000000..0f37fcddebaf7c6ed45c344d8992d2aa28c798d3 --- /dev/null +++ b/include/configs/imx95_evk.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2024 NXP + */ + +#ifndef __IMX95_EVK_H +#define __IMX95_EVK_H + +#include <linux/sizes.h> +#include <linux/stringify.h> +#include <asm/arch/imx-regs.h> + +#define CFG_SYS_UBOOT_BASE \ + (QSPI0_AMBA_BASE + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512) + +#define CFG_SYS_INIT_RAM_ADDR 0x90000000 +#define CFG_SYS_INIT_RAM_SIZE 0x200000 + +#define CFG_SYS_SDRAM_BASE 0x90000000 +#define PHYS_SDRAM 0x90000000 +/* Totally 16GB */ +#define PHYS_SDRAM_SIZE 0x70000000 /* 2GB - 256MB DDR */ +#define PHYS_SDRAM_2_SIZE 0x380000000 /* 14GB */ + +#define CFG_SYS_FSL_USDHC_NUM 2 + +/* Using ULP WDOG for reset */ +#define WDOG_BASE_ADDR WDG3_BASE_ADDR + +/* USB configs */ +#if defined(CONFIG_CMD_NET) +#define PHY_ANEG_TIMEOUT 20000 +/* Number of Rx BD rings: 8 per ENETC instance */ +#endif + +#endif

Hi Alice,
On Thu, 19 Dec 2024 at 19:56, Alice Guo alice.guo@oss.nxp.com wrote:
From: Ye Li ye.li@nxp.com
This patch adds i.MX95 19x19 EVK board basic support.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Peng Fan peng.fan@nxp.com
arch/arm/dts/imx95-19x19-evk-u-boot.dtsi | 224 ++++++++++++++++++++++++++ arch/arm/mach-imx/imx9/Kconfig | 6 + arch/arm/mach-imx/imx9/scmi/container.cfg | 10 ++ arch/arm/mach-imx/imx9/scmi/imximage.cfg | 15 ++ arch/arm/mach-imx/imx9/scmi/soc.c | 1 + board/freescale/imx95_evk/Kconfig | 12 ++ board/freescale/imx95_evk/MAINTAINERS | 6 + board/freescale/imx95_evk/Makefile | 11 ++ board/freescale/imx95_evk/imx95_19x19_evk.env | 95 +++++++++++ board/freescale/imx95_evk/imx95_evk.c | 54 +++++++ board/freescale/imx95_evk/spl.c | 117 ++++++++++++++ configs/imx95_19x19_evk_defconfig | 178 ++++++++++++++++++++ doc/board/nxp/imx95_evk.rst | 109 +++++++++++++ doc/board/nxp/index.rst | 1 + include/configs/imx95_evk.h | 36 +++++ 15 files changed, 875 insertions(+)
diff --git a/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi b/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..5c891518448d24204f5ca2a00957b47a0a24bd70 --- /dev/null +++ b/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright 2024 NXP
- */
+#ifdef CONFIG_BINMAN +/ {
binman {
multiple-images;
m33-oei-ddrfw {
filename = "m33-oei-ddrfw.bin";
nxp-append-ddrfw {
oei_m33_ddr_image = "oei-m33-ddr.bin";
lpddr_imem = "lpddr5_imem_v202311.bin";
lpddr_dmem = "lpddr5_dmem_v202311.bin";
lpddr_imem_qb = "lpddr5_imem_qb_v202311.bin";
lpddr_dmem_qb = "lpddr5_dmem_qb_v202311.bin";
};
};
spl {
filename = "spl.bin";
mkimage {
args = "-n spl/u-boot-spl.cfgout -T imx8image";
};
};
u-boot {
filename = "uboot.bin";
mkimage {
args = "-n u-boot-container.cfgout -T imx8image";
};
};
imx-boot {
filename = "imx-boot-imx95.bin";
pad-byte = <0x00>;
blob-ext@1 {
align = <0x400>;
align-size = <0x400>;
offset = <0x0>;
filename = "spl.bin";
};
For this node you should just be able to do something like:
imx-boot { filename = "imx-boot-imx95.bin"; pad-byte = <0x00>; spl { type = "mkimage"; args = "-n spl/u-boot-spl.cfgout -T imx8image"; align = <0x400>; align-size = <0x400>; };
You don't need to create intermediate files for all this stuff, so drop your 'filename' properties.
blob-ext@2 {
filename = "uboot.bin";
};
similar for this one
[..]
diff --git a/board/freescale/imx95_evk/imx95_19x19_evk.env b/board/freescale/imx95_evk/imx95_19x19_evk.env new file mode 100644 index 0000000000000000000000000000000000000000..27e09d3d70a068efb97d69b27089d1f213f39ee9 --- /dev/null +++ b/board/freescale/imx95_evk/imx95_19x19_evk.env @@ -0,0 +1,95 @@ +sec_boot=no +initrd_addr=0x93800000 +emmc_dev=0 +sd_dev=1 +prepare_mcore=setenv mcore_clk clk-imx95.mcore_booted +scriptaddr=0x93500000 +kernel_addr_r=" __stringify(CONFIG_SYS_LOAD_ADDR) " +image=Image +splashimage=0xA0000000 +console=ttyLP0,115200 earlycon +fdt_addr_r=0x93000000 +fdt_addr=0x93000000 +cntr_addr=0xA8000000 +cntr_file=os_cntr_signed.bin +boot_fit=no +fdtfile=" CONFIG_DEFAULT_FDT_FILE " +bootm_size=0x10000000 +mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV)" +mmcpart=1 +mmcroot=/dev/mmcblk1p2 rootwait rw +mmcautodetect=yes +mmcargs=setenv bootargs ${mcore_clk} console=${console} root=${mmcroot} +loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script}; +bootscript=echo Running bootscript from mmc ...; source +loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image} +loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} ${fdtfile} +loadcntr=fatload mmc ${mmcdev}:${mmcpart} ${cntr_addr} ${cntr_file} +auth_os=auth_cntr ${cntr_addr} +boot_os=booti ${loadaddr} - ${fdt_addr_r}; +mmcboot=echo Booting from mmc ...;
run mmcargs;
if test ${sec_boot} = yes; then
if run auth_os; then
run boot_os;
else
echo ERR: failed to authenticate;
fi;
else
if test ${boot_fit} = yes || test ${boot_fit} = try; then
bootm ${loadaddr};
else
if run loadfdt; then
run boot_os;
else
echo WARN: Cannot load the DT;
fi;
fi;
fi;
+netargs=setenv bootargs ${mcore_clk} console=${console}
root=/dev/nfs
ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
+netboot=echo Booting from net ...;
run netargs;
if test ${ip_dyn} = yes; then
setenv get_cmd dhcp;
else
setenv get_cmd tftp;
fi;
if test ${sec_boot} = yes; then
${get_cmd} ${cntr_addr} ${cntr_file};
if run auth_os; then
run boot_os;
else
echo ERR: failed to authenticate;
fi;
else
${get_cmd} ${loadaddr} ${image};
if test ${boot_fit} = yes || test ${boot_fit} = try; then
bootm ${loadaddr};
else
if ${get_cmd} ${fdt_addr_r} ${fdtfile}; then
run boot_os;
else
echo WARN: Cannot load the DT;
fi;
fi;
fi;
+bsp_bootcmd=echo Running BSP bootcmd ...;
mmc dev ${mmcdev}; if mmc rescan; then
if run loadbootscript; then
run bootscript;
else
if test ${sec_boot} = yes; then
if run loadcntr; then
run mmcboot;
else run netboot;
fi;
else
if run loadimage; then
run mmcboot;
else run netboot;
fi;
fi;
fi;
fi;
\ No newline at end of file
Could this be moved to use standard boot?
diff --git a/board/freescale/imx95_evk/imx95_evk.c b/board/freescale/imx95_evk/imx95_evk.c new file mode 100644 index 0000000000000000000000000000000000000000..c75a8f2450288a34cfc01150d3c42b07f2215491 --- /dev/null +++ b/board/freescale/imx95_evk/imx95_evk.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright 2024 NXP
- */
+#include <env.h> +#include <init.h> +#include <asm/global_data.h> +#include <asm/arch-imx9/ccm_regs.h> +#include <asm/arch/clock.h> +#include <fdt_support.h> +#include <asm/io.h> +#include <linux/bitfield.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <miiphy.h> +#include <netdev.h> +#include <asm/gpio.h> +#include <asm/mach-imx/sys_proto.h> +#include <scmi_agent.h> +#include <scmi_protocols.h> +#include "../../../dts/upstream/src/arm64/freescale/imx95-clock.h" +#include "../../../dts/upstream/src/arm64/freescale/imx95-power.h"
+DECLARE_GLOBAL_DATA_PTR;
+int board_early_init_f(void) +{
/* UART1: A55, UART2: M33, UART3: M7 */
init_uart_clk(0);
return 0;
[..]
+void board_init_f(ulong dummy) +{
int ret;
bool ddrmix_power = false;
/* Clear the BSS. */
memset(__bss_start, 0, __bss_end - __bss_start);
+#ifdef CONFIG_SPL_RECOVER_DATA_SECTION
if (IS_ENABLED(CONFIG_SPL_BUILD))
spl_save_restore_data();
+#endif
timer_init();
/* Need dm_init() to run before any SCMI calls can be made. */
spl_early_init();
/* Need enable SCMI drivers and ELE driver before enabling console */
ret = imx9_probe_mu();
if (ret)
hang(); /* if MU not probed, nothing can output, just hang here */
arch_cpu_init();
board_early_init_f();
preloader_console_init();
debug("SOC: 0x%x\n", gd->arch.soc_rev);
debug("LC: 0x%x\n", gd->arch.lifecycle);
/* Will set ARM freq to max rate */
clock_init_late();
/* Check is DDR MIX is already powered up. */
u32 state = 0;
struct udevice *dev;
ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
if (ret)
printf("%s: %d\n", __func__, ret);
ret = scmi_pwd_state_get(dev, IMX95_PD_DDR, &state);
if (ret) {
printf("scmi_pwd_state_get Failed %d for DDRMIX\n", ret);
} else {
if (state == BIT(30)) {
panic("DDRMIX is powered OFF, Please initialize DDR with OEI \n");
} else {
printf("DDRMIX is powered UP \n");
ddrmix_power = true;
}
}
How about putting this code in a separate function (called from board_init_f()) so you can check errors consistently, and always hang or panic in that situation?
board_init_r(NULL, 0);
+}
[..]
diff --git a/doc/board/nxp/imx95_evk.rst b/doc/board/nxp/imx95_evk.rst new file mode 100644 index 0000000000000000000000000000000000000000..c2be474aa71f0f8d934f956c8840d330fbee98df --- /dev/null +++ b/doc/board/nxp/imx95_evk.rst @@ -0,0 +1,109 @@ +.. SPDX-License-Identifier: GPL-2.0+
+imx95_evk +=======================
+U-Boot for the NXP i.MX95 19x19 EVK board
+Quick Start +-----------
+- Get ahab-container.img +- Get the DDR PHY Firmware Images +- Get and Build OEI Images +- Get and Build System Manager Image +- Get and Build the ARM Trusted Firmware +- Build the Bootloader Image +- Boot
+Get ahab-container.img +--------------------------------------
+Note: srctree is U-Boot source directory
+.. code-block:: bash
- $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-ele-imx-1.3.0-17945fc.bin
- $ chmod +x firmware-ele-imx-1.3.0-17945fc.bin
- $ ./firmware-ele-imx-1.3.0-17945fc.bin
- $ cp firmware-ele-imx-1.3.0-17945fc.bin/mx95a0-ahab-container.img $(srctree)
+Get the DDR PHY Firmware Images +--------------------------------------
+Note: srctree is U-Boot source directory
+.. code-block:: bash
- $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.26-d4c33ab.bin
- $ chmod +x firmware-imx-8.26-d4c33ab.bin
- $ ./firmware-imx-8.26-d4c33ab.bin
- $ cp firmware-imx-8.26-d4c33ab/firmware/ddr/synopsys/lpddr5*v202311.bin $(srctree)
+Get and Build OEI Images +--------------------------------------
+Note: srctree is U-Boot source directory +Get OEI from: https://github.com/nxp-imx/imx-oei +branch: master
+.. code-block:: bash
- $ sudo apt -y install make gcc g++-multilib srecord
- $ wget https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-g...
- $ tar xvf arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi.tar.xz
- $ export TOOLS=$PWD
- $ make board=mx95lp5 oei=ddr DEBUG=1
- $ cp build/mx95lp5/ddr/oei-m33-ddr.bin $(srctree)
- $ make board=mx95lp5 oei=tcm DEBUG=1
- $ cp build/mx95lp5/tcm/oei-m33-tcm.bin $(srctree)
Blobs should be accessed via environment variables (like TEE, BL31) or using the binman input path. How about creating an IMX_BLOBS variable and adding to Makefile like '-a imx-blobs=$(IMX_BLOBS)' - see ti-dm-path for an example.
+Get and Build System Manager Image +--------------------------------------
+Note: srctree is U-Boot source directory +Get System Manager from: https://github.com/nxp-imx/imx-sm +branch: master
+.. code-block:: bash
- $ sudo apt -y install make gcc g++-multilib srecord
- $ wget https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-g...
- $ tar xvf arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi.tar.xz
- $ export TOOLS=$PWD
- $ make config=mx95evk all
- $ cp build/mx95evk/m33_image.bin $(srctree)
+Get and Build the ARM Trusted Firmware +--------------------------------------
+Note: srctree is U-Boot source directory +Get ATF from: https://github.com/nxp-imx/imx-atf/ +branch: lf_v2.10
+.. code-block:: bash
- $ unset LDFLAGS
- $ make PLAT=imx95 bl31
- $ cp build/imx95/release/bl31.bin $(srctree)
+Build the Bootloader Image +------------
+.. code-block:: bash
- $ export CROSS_COMPILE=aarch64-poky-linux-
- $ make imx95_19x19_evk_defconfig
- $ make
+Copy imx-boot-imx95.bin to the MicroSD card:
+.. code-block:: bash
- $ sudo dd if=imx-boot-imx95.bin of=/dev/sdb bs=1k seek=32 conv=fsync
Good instructions.
Regards, Simon

-----邮件原件----- 发件人: Simon Glass sjg@chromium.org 发送时间: 2024年12月21日 1:37 收件人: Alice Guo (OSS) alice.guo@oss.nxp.com 抄送: Tom Rini trini@konsulko.com; Stefano Babic sbabic@denx.de; Fabio Estevam festevam@gmail.com; dl-uboot-imx uboot-imx@nxp.com; Lukasz Majewski lukma@denx.de; Sean Anderson seanga2@gmail.com; Alper Nebi Yasak alpernebiyasak@gmail.com; u-boot@lists.denx.de; marex@denx.de; Alice Guo alice.guo@nxp.com; Ye Li ye.li@nxp.com; Peng Fan peng.fan@nxp.com 主题: [EXT] Re: [PATCH v2 16/17] imx95_evk: add i.MX95 19x19 EVK board basic support
Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
Hi Alice,
On Thu, 19 Dec 2024 at 19:56, Alice Guo alice.guo@oss.nxp.com wrote:
From: Ye Li ye.li@nxp.com
This patch adds i.MX95 19x19 EVK board basic support.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Peng Fan peng.fan@nxp.com
arch/arm/dts/imx95-19x19-evk-u-boot.dtsi | 224
++++++++++++++++++++++++++
arch/arm/mach-imx/imx9/Kconfig | 6 + arch/arm/mach-imx/imx9/scmi/container.cfg | 10 ++ arch/arm/mach-imx/imx9/scmi/imximage.cfg | 15 ++ arch/arm/mach-imx/imx9/scmi/soc.c | 1 + board/freescale/imx95_evk/Kconfig | 12 ++ board/freescale/imx95_evk/MAINTAINERS | 6 + board/freescale/imx95_evk/Makefile | 11 ++ board/freescale/imx95_evk/imx95_19x19_evk.env | 95 +++++++++++ board/freescale/imx95_evk/imx95_evk.c | 54 +++++++ board/freescale/imx95_evk/spl.c | 117 ++++++++++++++ configs/imx95_19x19_evk_defconfig | 178
++++++++++++++++++++
doc/board/nxp/imx95_evk.rst | 109 +++++++++++++ doc/board/nxp/index.rst | 1 + include/configs/imx95_evk.h | 36 +++++ 15 files changed, 875 insertions(+)
diff --git a/board/freescale/imx95_evk/imx95_19x19_evk.env b/board/freescale/imx95_evk/imx95_19x19_evk.env new file mode 100644 index
0000000000000000000000000000000000000000..27e09d3d70a068efb97d69b 27089
d1f213f39ee9 --- /dev/null +++ b/board/freescale/imx95_evk/imx95_19x19_evk.env @@ -0,0 +1,95 @@ +sec_boot=no +initrd_addr=0x93800000 +emmc_dev=0 +sd_dev=1 +prepare_mcore=setenv mcore_clk clk-imx95.mcore_booted +scriptaddr=0x93500000 +kernel_addr_r=" __stringify(CONFIG_SYS_LOAD_ADDR) " +image=Image +splashimage=0xA0000000 +console=ttyLP0,115200 earlycon +fdt_addr_r=0x93000000 +fdt_addr=0x93000000 +cntr_addr=0xA8000000 +cntr_file=os_cntr_signed.bin +boot_fit=no +fdtfile=" CONFIG_DEFAULT_FDT_FILE " +bootm_size=0x10000000 +mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV)" +mmcpart=1 +mmcroot=/dev/mmcblk1p2 rootwait rw +mmcautodetect=yes +mmcargs=setenv bootargs ${mcore_clk} console=${console} +root=${mmcroot} loadbootscript=fatload mmc ${mmcdev}:${mmcpart} +${loadaddr} ${script}; bootscript=echo Running bootscript from mmc +...; source loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} +${image} loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} +${fdtfile} loadcntr=fatload mmc ${mmcdev}:${mmcpart} ${cntr_addr} +${cntr_file} auth_os=auth_cntr ${cntr_addr} boot_os=booti ${loadaddr} +- ${fdt_addr_r}; mmcboot=echo Booting from mmc ...;
run mmcargs;
if test ${sec_boot} = yes; then
if run auth_os; then
run boot_os;
else
echo ERR: failed to authenticate;
fi;
else
if test ${boot_fit} = yes || test ${boot_fit} = try;
then
bootm ${loadaddr};
else
if run loadfdt; then
run boot_os;
else
echo WARN: Cannot load
the DT;
fi;
fi;
fi;
+netargs=setenv bootargs ${mcore_clk} console=${console}
root=/dev/nfs
ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
+netboot=echo Booting from net ...;
run netargs;
if test ${ip_dyn} = yes; then
setenv get_cmd dhcp;
else
setenv get_cmd tftp;
fi;
if test ${sec_boot} = yes; then
${get_cmd} ${cntr_addr} ${cntr_file};
if run auth_os; then
run boot_os;
else
echo ERR: failed to authenticate;
fi;
else
${get_cmd} ${loadaddr} ${image};
if test ${boot_fit} = yes || test ${boot_fit} = try;
then
bootm ${loadaddr};
else
if ${get_cmd} ${fdt_addr_r} ${fdtfile};
then
run boot_os;
else
echo WARN: Cannot load
the DT;
fi;
fi;
fi;
+bsp_bootcmd=echo Running BSP bootcmd ...;
mmc dev ${mmcdev}; if mmc rescan; then
if run loadbootscript; then
run bootscript;
else
if test ${sec_boot} = yes; then
if run loadcntr; then
run mmcboot;
else run netboot;
fi;
else
if run loadimage; then
run mmcboot;
else run netboot;
fi;
fi;
fi;
fi;
\ No newline at end of file
Could this be moved to use standard boot?
Hi Simon, Fabio
I am new to standard boot and trying to understand the flow, could that be a follow up patch to switch imx95 to use standard boot? Then we no need to wait longer for i.MX95 patchset for mainline.
Best Regards, Alice Guo

Hi Alice,
[Please trim your replies when replying].
On Tue, Dec 24, 2024 at 5:23 AM Alice Guo (OSS) alice.guo@oss.nxp.com wrote:
Hi Simon, Fabio
I am new to standard boot and trying to understand the flow, could that be a follow up patch to switch imx95 to use standard boot? Then we no need to wait longer for i.MX95 patchset for mainline.
That's OK.
Please send a v3 addressing the other comments.

Hi Alice
On Thu, Dec 19, 2024 at 11:56 PM Alice Guo alice.guo@oss.nxp.com wrote:
From: Ye Li ye.li@nxp.com
This patch adds i.MX95 19x19 EVK board basic support.
Do you know if this board boots without patch 17/17?
If it doesn't boot, this patch should be the last one.
+Copy imx-boot-imx95.bin to the MicroSD card:
+.. code-block:: bash
- $ sudo dd if=imx-boot-imx95.bin of=/dev/sdb bs=1k seek=32 conv=fsync
It would be better to call the final binary flash.bin to keep it consistent with imx8m/imx93.
Also, don't hardcode the device name as /dev/sdb as it can cause problem if someone has /dev/sdb mapped to something else.

On Thu, Dec 19, 2024 at 11:56 PM Alice Guo alice.guo@oss.nxp.com wrote:
+/* USB configs */ +#if defined(CONFIG_CMD_NET) +#define PHY_ANEG_TIMEOUT 20000
This should be moved to the defconfig file instead.

On Fri, Dec 20, 2024 at 10:55:14AM +0800, Alice Guo wrote:
From: Ye Li ye.li@nxp.com
This patch adds i.MX95 19x19 EVK board basic support.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Peng Fan peng.fan@nxp.com
arch/arm/dts/imx95-19x19-evk-u-boot.dtsi | 224 ++++++++++++++++++++++++++ arch/arm/mach-imx/imx9/Kconfig | 6 + arch/arm/mach-imx/imx9/scmi/container.cfg | 10 ++ arch/arm/mach-imx/imx9/scmi/imximage.cfg | 15 ++ arch/arm/mach-imx/imx9/scmi/soc.c | 1 + board/freescale/imx95_evk/Kconfig | 12 ++ board/freescale/imx95_evk/MAINTAINERS | 6 + board/freescale/imx95_evk/Makefile | 11 ++ board/freescale/imx95_evk/imx95_19x19_evk.env | 95 +++++++++++ board/freescale/imx95_evk/imx95_evk.c | 54 +++++++ board/freescale/imx95_evk/spl.c | 117 ++++++++++++++ configs/imx95_19x19_evk_defconfig | 178 ++++++++++++++++++++ doc/board/nxp/imx95_evk.rst | 109 +++++++++++++ doc/board/nxp/index.rst | 1 + include/configs/imx95_evk.h | 36 +++++ 15 files changed, 875 insertions(+)
diff --git a/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi b/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..5c891518448d24204f5ca2a00957b47a0a24bd70 --- /dev/null +++ b/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright 2024 NXP
- */
+#ifdef CONFIG_BINMAN +/ {
- binman {
multiple-images;
m33-oei-ddrfw {
filename = "m33-oei-ddrfw.bin";
nxp-append-ddrfw {
oei_m33_ddr_image = "oei-m33-ddr.bin";
lpddr_imem = "lpddr5_imem_v202311.bin";
lpddr_dmem = "lpddr5_dmem_v202311.bin";
lpddr_imem_qb = "lpddr5_imem_qb_v202311.bin";
lpddr_dmem_qb = "lpddr5_dmem_qb_v202311.bin";
};
};
spl {
filename = "spl.bin";
mkimage {
args = "-n spl/u-boot-spl.cfgout -T imx8image";
};
};
u-boot {
filename = "uboot.bin";
mkimage {
args = "-n u-boot-container.cfgout -T imx8image";
};
};
imx-boot {
filename = "imx-boot-imx95.bin";
pad-byte = <0x00>;
blob-ext@1 {
align = <0x400>;
align-size = <0x400>;
offset = <0x0>;
filename = "spl.bin";
};
blob-ext@2 {
filename = "uboot.bin";
};
};
- };
+}; +#endif
+&{/soc} {
- bootph-all;
- bootph-pre-ram;
+};
+&aips1 {
- bootph-all;
- bootph-pre-ram;
+};
+&aips2 {
- bootph-all;
- bootph-pre-ram;
+};
+&aips3 {
- bootph-pre-ram;
+};
+&gpio1 {
- reg = <0 0x47400000 0 0x1000>, <0 0x47400040 0 0x40>;
+};
+&gpio2 {
- reg = <0 0x43810000 0 0x1000>, <0 0x43810040 0 0x40>;
- bootph-pre-ram;
+};
+&gpio3 {
- reg = <0 0x43820000 0 0x1000>, <0 0x43820040 0 0x40>;
- bootph-pre-ram;
+};
+&gpio4 {
- reg = <0 0x43840000 0 0x1000>, <0 0x43840040 0 0x40>;
- bootph-pre-ram;
+};
+&gpio5 {
- reg = <0 0x43850000 0 0x1000>, <0 0x43850040 0 0x40>;
- bootph-pre-ram;
+};
+&lpuart1 {
- clocks = <&scmi_clk IMX95_CLK_LPUART1>, <&scmi_clk IMX95_CLK_LPUART1>;
- clock-names = "ipg", "per";
- bootph-pre-ram;
+};
+&mu2 {
- bootph-all;
- bootph-pre-ram;
+};
+&osc_24m {
- bootph-all;
- bootph-pre-ram;
+};
+&clk_ext1 {
- bootph-all;
- bootph-pre-ram;
+};
+&sram0 {
- bootph-all;
- bootph-pre-ram;
+};
+&scmi_buf0 {
- bootph-all;
- bootph-pre-ram;
+};
+&scmi_buf1 {
- bootph-all;
- bootph-pre-ram;
+};
+&{/firmware} {
- bootph-all;
- bootph-pre-ram;
+};
+&{/firmware/scmi} {
- bootph-all;
- bootph-pre-ram;
+};
+&{/firmware/scmi/protocol@11} {
- bootph-all;
- bootph-pre-ram;
+};
+&{/firmware/scmi/protocol@13} {
- bootph-all;
- bootph-pre-ram;
+};
+&{/firmware/scmi/protocol@14} {
- bootph-all;
- bootph-pre-ram;
+};
+&{/firmware/scmi/protocol@19} {
- bootph-all;
- bootph-pre-ram;
+};
+&pinctrl_uart1 {
- bootph-pre-ram;
+};
+&usdhc1 {
- bootph-pre-ram;
+};
+&pinctrl_usdhc1 {
- bootph-pre-ram;
+};
+&pinctrl_usdhc1_100mhz {
- bootph-pre-ram;
+};
+&pinctrl_usdhc1_200mhz {
- bootph-pre-ram;
+};
+&usdhc2 {
- bootph-pre-ram;
+};
+&pinctrl_usdhc2 {
- bootph-pre-ram;
+};
+&pinctrl_usdhc2_100mhz {
- bootph-pre-ram;
+};
+&pinctrl_usdhc2_200mhz {
- bootph-pre-ram;
+};
+&pinctrl_usdhc2_gpio {
- bootph-pre-ram;
+};
+®_usdhc2_vmmc {
- bootph-pre-ram;
+};
+&pinctrl_reg_usdhc2_vmmc {
- bootph-pre-ram;
+};
+&elemu3 {
- compatible = "fsl,imx93-mu-s4";
- status = "okay";
- bootph-all;
- bootph-pre-ram;
+};
+&wdog3 {
- status = "disabled";
+};
Hi Alice,
Would it be possible to factor out the common parts of the U-Boot SPL/Pre-relocation device tree into an imx95-u-boot.dtsi file, like U-Boot already has for imx8mp/imx8mm? From what I understand, the binman configuration and some DT nodes (e.g. soc, aips*, scmi*, elemu*, gpio2-5) are required on all boards, as they are bus parent nodes or needed by the SoC implementation.
In the downstream kernel, there are already other boards apart from the EVK (e.g., Verdin-EVK), and we’re also working on a new SoM family (Toradex SMARC iMX95). Having the common parts factored out would make things more organized and easier to upstream.
Best regards, João Paulo

-----邮件原件----- 发件人: João Paulo Gonçalves jpaulo.silvagoncalves@gmail.com 发送时间: 2024年12月24日 21:33 收件人: Alice Guo (OSS) alice.guo@oss.nxp.com 抄送: Tom Rini trini@konsulko.com; Stefano Babic sbabic@denx.de; Fabio Estevam festevam@gmail.com; dl-uboot-imx uboot-imx@nxp.com; Lukasz Majewski lukma@denx.de; Sean Anderson seanga2@gmail.com; Simon Glass sjg@chromium.org; Alper Nebi Yasak alpernebiyasak@gmail.com; u-boot@lists.denx.de; marex@denx.de; Alice Guo alice.guo@nxp.com; Ye Li ye.li@nxp.com; Peng Fan peng.fan@nxp.com; Francesco Dolcini francesco@dolcini.it; joao.goncalves@toradex.com 主题: [EXT] Re: [PATCH v2 16/17] imx95_evk: add i.MX95 19x19 EVK board basic support
Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
On Fri, Dec 20, 2024 at 10:55:14AM +0800, Alice Guo wrote:
From: Ye Li ye.li@nxp.com
This patch adds i.MX95 19x19 EVK board basic support.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Peng Fan peng.fan@nxp.com
arch/arm/dts/imx95-19x19-evk-u-boot.dtsi | 224
++++++++++++++++++++++++++
arch/arm/mach-imx/imx9/Kconfig | 6 + arch/arm/mach-imx/imx9/scmi/container.cfg | 10 ++ arch/arm/mach-imx/imx9/scmi/imximage.cfg | 15 ++ arch/arm/mach-imx/imx9/scmi/soc.c | 1 + board/freescale/imx95_evk/Kconfig | 12 ++ board/freescale/imx95_evk/MAINTAINERS | 6 + board/freescale/imx95_evk/Makefile | 11 ++ board/freescale/imx95_evk/imx95_19x19_evk.env | 95 +++++++++++ board/freescale/imx95_evk/imx95_evk.c | 54 +++++++ board/freescale/imx95_evk/spl.c | 117 ++++++++++++++ configs/imx95_19x19_evk_defconfig | 178
++++++++++++++++++++
doc/board/nxp/imx95_evk.rst | 109 +++++++++++++ doc/board/nxp/index.rst | 1 + include/configs/imx95_evk.h | 36 +++++ 15 files changed, 875 insertions(+)
diff --git a/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi b/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi new file mode 100644 index
0000000000000000000000000000000000000000..5c891518448d24204f5ca 2a00957
b47a0a24bd70 --- /dev/null +++ b/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright 2024 NXP
- */
+#ifdef CONFIG_BINMAN +/ {
binman {
multiple-images;
m33-oei-ddrfw {
filename = "m33-oei-ddrfw.bin";
nxp-append-ddrfw {
oei_m33_ddr_image = "oei-m33-ddr.bin";
lpddr_imem =
"lpddr5_imem_v202311.bin";
lpddr_dmem =
"lpddr5_dmem_v202311.bin";
lpddr_imem_qb =
"lpddr5_imem_qb_v202311.bin";
lpddr_dmem_qb =
"lpddr5_dmem_qb_v202311.bin";
};
};
spl {
filename = "spl.bin";
mkimage {
args = "-n spl/u-boot-spl.cfgout -T
imx8image";
};
};
u-boot {
filename = "uboot.bin";
mkimage {
args = "-n u-boot-container.cfgout -T
imx8image";
};
};
imx-boot {
filename = "imx-boot-imx95.bin";
pad-byte = <0x00>;
blob-ext@1 {
align = <0x400>;
align-size = <0x400>;
offset = <0x0>;
filename = "spl.bin";
};
blob-ext@2 {
filename = "uboot.bin";
};
};
};
+}; +#endif
+&{/soc} {
bootph-all;
bootph-pre-ram;
+};
+&aips1 {
bootph-all;
bootph-pre-ram;
+};
+&aips2 {
bootph-all;
bootph-pre-ram;
+};
+&aips3 {
bootph-pre-ram;
+};
+&gpio1 {
reg = <0 0x47400000 0 0x1000>, <0 0x47400040 0 0x40>; };
+&gpio2 {
reg = <0 0x43810000 0 0x1000>, <0 0x43810040 0 0x40>;
bootph-pre-ram;
+};
+&gpio3 {
reg = <0 0x43820000 0 0x1000>, <0 0x43820040 0 0x40>;
bootph-pre-ram;
+};
+&gpio4 {
reg = <0 0x43840000 0 0x1000>, <0 0x43840040 0 0x40>;
bootph-pre-ram;
+};
+&gpio5 {
reg = <0 0x43850000 0 0x1000>, <0 0x43850040 0 0x40>;
bootph-pre-ram;
+};
+&lpuart1 {
clocks = <&scmi_clk IMX95_CLK_LPUART1>, <&scmi_clk
IMX95_CLK_LPUART1>;
clock-names = "ipg", "per";
bootph-pre-ram;
+};
+&mu2 {
bootph-all;
bootph-pre-ram;
+};
+&osc_24m {
bootph-all;
bootph-pre-ram;
+};
+&clk_ext1 {
bootph-all;
bootph-pre-ram;
+};
+&sram0 {
bootph-all;
bootph-pre-ram;
+};
+&scmi_buf0 {
bootph-all;
bootph-pre-ram;
+};
+&scmi_buf1 {
bootph-all;
bootph-pre-ram;
+};
+&{/firmware} {
bootph-all;
bootph-pre-ram;
+};
+&{/firmware/scmi} {
bootph-all;
bootph-pre-ram;
+};
+&{/firmware/scmi/protocol@11} {
bootph-all;
bootph-pre-ram;
+};
+&{/firmware/scmi/protocol@13} {
bootph-all;
bootph-pre-ram;
+};
+&{/firmware/scmi/protocol@14} {
bootph-all;
bootph-pre-ram;
+};
+&{/firmware/scmi/protocol@19} {
bootph-all;
bootph-pre-ram;
+};
+&pinctrl_uart1 {
bootph-pre-ram;
+};
+&usdhc1 {
bootph-pre-ram;
+};
+&pinctrl_usdhc1 {
bootph-pre-ram;
+};
+&pinctrl_usdhc1_100mhz {
bootph-pre-ram;
+};
+&pinctrl_usdhc1_200mhz {
bootph-pre-ram;
+};
+&usdhc2 {
bootph-pre-ram;
+};
+&pinctrl_usdhc2 {
bootph-pre-ram;
+};
+&pinctrl_usdhc2_100mhz {
bootph-pre-ram;
+};
+&pinctrl_usdhc2_200mhz {
bootph-pre-ram;
+};
+&pinctrl_usdhc2_gpio {
bootph-pre-ram;
+};
+®_usdhc2_vmmc {
bootph-pre-ram;
+};
+&pinctrl_reg_usdhc2_vmmc {
bootph-pre-ram;
+};
+&elemu3 {
compatible = "fsl,imx93-mu-s4";
status = "okay";
bootph-all;
bootph-pre-ram;
+};
+&wdog3 {
status = "disabled";
+};
Hi Alice,
Would it be possible to factor out the common parts of the U-Boot SPL/Pre-relocation device tree into an imx95-u-boot.dtsi file, like U-Boot already has for imx8mp/imx8mm? From what I understand, the binman configuration and some DT nodes (e.g. soc, aips*, scmi*, elemu*, gpio2-5) are required on all boards, as they are bus parent nodes or needed by the SoC implementation.
In the downstream kernel, there are already other boards apart from the EVK (e.g., Verdin-EVK), and we’re also working on a new SoM family (Toradex SMARC iMX95). Having the common parts factored out would make things more organized and easier to upstream.
Best regards, João Paulo
Hi João Paulo,
Will move these common parts to an imx95-u-boot.dtsi file in next version.
Best Regards, Alice Guo

On Thu, Dec 19, 2024 at 6:57 PM Alice Guo alice.guo@oss.nxp.com wrote:
From: Ye Li ye.li@nxp.com
This patch adds i.MX95 19x19 EVK board basic support.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Peng Fan peng.fan@nxp.com
arch/arm/dts/imx95-19x19-evk-u-boot.dtsi | 224 ++++++++++++++++++++++++++ arch/arm/mach-imx/imx9/Kconfig | 6 + arch/arm/mach-imx/imx9/scmi/container.cfg | 10 ++ arch/arm/mach-imx/imx9/scmi/imximage.cfg | 15 ++ arch/arm/mach-imx/imx9/scmi/soc.c | 1 + board/freescale/imx95_evk/Kconfig | 12 ++ board/freescale/imx95_evk/MAINTAINERS | 6 + board/freescale/imx95_evk/Makefile | 11 ++ board/freescale/imx95_evk/imx95_19x19_evk.env | 95 +++++++++++ board/freescale/imx95_evk/imx95_evk.c | 54 +++++++ board/freescale/imx95_evk/spl.c | 117 ++++++++++++++ configs/imx95_19x19_evk_defconfig | 178 ++++++++++++++++++++ doc/board/nxp/imx95_evk.rst | 109 +++++++++++++ doc/board/nxp/index.rst | 1 + include/configs/imx95_evk.h | 36 +++++ 15 files changed, 875 insertions(+)
<snip>
diff --git a/doc/board/nxp/imx95_evk.rst b/doc/board/nxp/imx95_evk.rst new file mode 100644 index 0000000000000000000000000000000000000000..c2be474aa71f0f8d934f956c8840d330fbee98df --- /dev/null +++ b/doc/board/nxp/imx95_evk.rst @@ -0,0 +1,109 @@ +.. SPDX-License-Identifier: GPL-2.0+
+imx95_evk +=======================
+U-Boot for the NXP i.MX95 19x19 EVK board
+Quick Start +-----------
+- Get ahab-container.img +- Get the DDR PHY Firmware Images +- Get and Build OEI Images +- Get and Build System Manager Image +- Get and Build the ARM Trusted Firmware +- Build the Bootloader Image +- Boot
+Get ahab-container.img +--------------------------------------
+Note: srctree is U-Boot source directory
+.. code-block:: bash
- $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-ele-imx-1.3.0-17945fc.bin
- $ chmod +x firmware-ele-imx-1.3.0-17945fc.bin
- $ ./firmware-ele-imx-1.3.0-17945fc.bin
- $ cp firmware-ele-imx-1.3.0-17945fc.bin/mx95a0-ahab-container.img $(srctree)
Hi Alice,
typo here in the path. Should be: cp firmware-ele-imx-1.3.0-17945fc/mx95a0-ahab-container.img $(srctree)
+Get the DDR PHY Firmware Images +--------------------------------------
+Note: srctree is U-Boot source directory
+.. code-block:: bash
- $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.26-d4c33ab.bin
- $ chmod +x firmware-imx-8.26-d4c33ab.bin
- $ ./firmware-imx-8.26-d4c33ab.bin
- $ cp firmware-imx-8.26-d4c33ab/firmware/ddr/synopsys/lpddr5*v202311.bin $(srctree)
+Get and Build OEI Images +--------------------------------------
+Note: srctree is U-Boot source directory +Get OEI from: https://github.com/nxp-imx/imx-oei +branch: master
how about just adding a 'git clone https://github.com/nxp-imx/imx-oei -b master' in your instructions below and update the make/cp to use imx-oei path?
+.. code-block:: bash
- $ sudo apt -y install make gcc g++-multilib srecord
- $ wget https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-g...
- $ tar xvf arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi.tar.xz
- $ export TOOLS=$PWD
- $ make board=mx95lp5 oei=ddr DEBUG=1
- $ cp build/mx95lp5/ddr/oei-m33-ddr.bin $(srctree)
- $ make board=mx95lp5 oei=tcm DEBUG=1
- $ cp build/mx95lp5/tcm/oei-m33-tcm.bin $(srctree)
+Get and Build System Manager Image +--------------------------------------
+Note: srctree is U-Boot source directory +Get System Manager from: https://github.com/nxp-imx/imx-sm +branch: master
how about just adding a 'git clone https://github.com/nxp-imx/imx-sm -b master' in your instructions below and update make/cp to use imx-sm path?
+.. code-block:: bash
- $ sudo apt -y install make gcc g++-multilib srecord
- $ wget https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-g...
- $ tar xvf arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi.tar.xz
- $ export TOOLS=$PWD
- $ make config=mx95evk all
- $ cp build/mx95evk/m33_image.bin $(srctree)
+Get and Build the ARM Trusted Firmware +--------------------------------------
+Note: srctree is U-Boot source directory +Get ATF from: https://github.com/nxp-imx/imx-atf/ +branch: lf_v2.10
how about just adding a 'git clone https://github.com/nxp-imx/imx-atf -b lf_v2.10' in your instructions below and update make/cp to use imx-atf path?
+.. code-block:: bash
- $ unset LDFLAGS
why? where was LDFLAGS set?
- $ make PLAT=imx95 bl31
You need to export CROSS_COMPILE before building here
- $ cp build/imx95/release/bl31.bin $(srctree)
+Build the Bootloader Image +------------
+.. code-block:: bash
- $ export CROSS_COMPILE=aarch64-poky-linux-
- $ make imx95_19x19_evk_defconfig
- $ make
+Copy imx-boot-imx95.bin to the MicroSD card:
+.. code-block:: bash
- $ sudo dd if=imx-boot-imx95.bin of=/dev/sdb bs=1k seek=32 conv=fsync
+Boot +----
+Set i.MX95 boot device to MicroSD card
I gave this series a go on top of 5cfbf8c364 origin/next on an EVK I have here and I saw no u-boot proper output after the ATF.
Here is what I saw on UART2: U-Boot SPL 2025.01-rc5-00393-g9b292f7d347f (Dec 27 2024 - 16:12:20 -0800) DDRMIX is powered UP Normal Boot Trying to boot from MMC2 Primary set selected Load image from MMC/SD 0xdec00 NOTICE: BL31: v2.10.0 (release):lf-6.6.52-2.2.0 NOTICE: BL31: Built : 16:06:15, Dec 27 2024
U-Boot SPL 2025.01-rc5-00393-g9b292f7d347f (Dec 27 2024 - 16:12:20 -0800) DDRMIX is powered UP Normal Boot Trying to boot from MMC2 Primary set selected Load image from MMC/SD 0xdec00 NOTICE: BL31: v2.10.0 (release):lf-6.6.52-2.2.0 NOTICE: BL31: Built : 16:06:15, Dec 27 2024 ^^^ nothing after this
Any thoughts on what is wrong here?
Best Regards,
Tim

主题: [EXT] Re: [PATCH v2 16/17] imx95_evk: add i.MX95 19x19 EVK board basic support
I gave this series a go on top of 5cfbf8c364 origin/next on an EVK I have here and I saw no u-boot proper output after the ATF.
Here is what I saw on UART2: U-Boot SPL 2025.01-rc5-00393-g9b292f7d347f (Dec 27 2024 - 16:12:20 -0800) DDRMIX is powered UP Normal Boot Trying to boot from MMC2 Primary set selected Load image from MMC/SD 0xdec00 NOTICE: BL31: v2.10.0 (release):lf-6.6.52-2.2.0 NOTICE: BL31: Built : 16:06:15, Dec 27 2024
U-Boot SPL 2025.01-rc5-00393-g9b292f7d347f (Dec 27 2024 - 16:12:20 -0800) DDRMIX is powered UP Normal Boot Trying to boot from MMC2 Primary set selected Load image from MMC/SD 0xdec00 NOTICE: BL31: v2.10.0 (release):lf-6.6.52-2.2.0 NOTICE: BL31: Built : 16:06:15, Dec 27 2024 ^^^ nothing after this
Any thoughts on what is wrong here?
Best Regards,
Tim
Hi Tim,
I tried it on my MX95 and it works well, so I not sure what causes this issue on your EVK.
Best Regards, Alice Guo

On Mon, Dec 30, 2024 at 6:34 PM Alice Guo (OSS) alice.guo@oss.nxp.com wrote:
主题: [EXT] Re: [PATCH v2 16/17] imx95_evk: add i.MX95 19x19 EVK board basic support
I gave this series a go on top of 5cfbf8c364 origin/next on an EVK I have here and I saw no u-boot proper output after the ATF.
Here is what I saw on UART2: U-Boot SPL 2025.01-rc5-00393-g9b292f7d347f (Dec 27 2024 - 16:12:20 -0800) DDRMIX is powered UP Normal Boot Trying to boot from MMC2 Primary set selected Load image from MMC/SD 0xdec00 NOTICE: BL31: v2.10.0 (release):lf-6.6.52-2.2.0 NOTICE: BL31: Built : 16:06:15, Dec 27 2024
U-Boot SPL 2025.01-rc5-00393-g9b292f7d347f (Dec 27 2024 - 16:12:20 -0800) DDRMIX is powered UP Normal Boot Trying to boot from MMC2 Primary set selected Load image from MMC/SD 0xdec00 NOTICE: BL31: v2.10.0 (release):lf-6.6.52-2.2.0 NOTICE: BL31: Built : 16:06:15, Dec 27 2024 ^^^ nothing after this
Any thoughts on what is wrong here?
Best Regards,
Tim
Hi Tim,
I tried it on my MX95 and it works well, so I not sure what causes this issue on your EVK.
Hi Alice,
I discovered what happened. The first make for uboot resulted in a binman warning (which should be a failure but is not for some reason) and results in an image that doesn't contain uboot proper: WARNING './u-boot.bin' not found, resulting binary may be not-functional
Simon, do you know why this warning doesn't result in a make failure?
Doing a second make works, so I think there is likely a binman dependency issue going on here. You can re-create the issue with a distclean as shown here:
$ make distclean CLEAN dts/./upstream/src/arm64 CLEAN dts CLEAN lib/efi_loader CLEAN tools CLEAN tools/generated CLEAN spl/arch spl/board spl/boot spl/cmd spl/common spl/disk spl/drivers spl/dts spl/env spl/fs spl/lib spl/spl spl/u-boot-spl spl/u-boot-spl.bin spl/u-boot-spl.cfgout spl/u-boot-spl.dtb spl/u-boot-spl-dtb.bin spl/u-boot-spl.lds spl/u-boot-spl.map spl/u-boot-spl-nodtb.bin spl/u-boot-spl.sym CLEAN include/config.h u-boot u-boot.bin u-boot.cfg u-boot-container.cfgout u-boot.dtb u-boot-dtb.bin u-boot-dtb. img u-boot.dtb.out u-boot.elf u-boot-elf.lds u-boot-elf.o u-boot.img u-boot.lds u-boot.map u-boot-nodtb.bin u-boot-sp l.dtb.out u-boot.srec u-boot.sym System.map mkimage-out.spl.mkimage mkimage.spl.mkimage imx-boot.map spl.map CLEAN scripts/basic CLEAN scripts/dtc/pylibfdt CLEAN scripts/dtc CLEAN scripts/kconfig CLEAN include/config include/generated spl CLEAN .config .config.old $ make imx95_19x19_evk_defconfig HOSTCC scripts/basic/fixdep HOSTCC scripts/kconfig/conf.o YACC scripts/kconfig/zconf.tab.c LEX scripts/kconfig/zconf.lex.c HOSTCC scripts/kconfig/zconf.tab.o HOSTLD scripts/kconfig/conf # # configuration written to .config # $ make && ls -l imx-boot-imx95.bin scripts/kconfig/conf --syncconfig Kconfig UPD include/config.h CFG u-boot.cfg GEN include/autoconf.mk GEN include/autoconf.mk.dep CFG spl/u-boot.cfg GEN spl/include/autoconf.mk UPD include/config/uboot.release UPD include/generated/version_autogenerated.h UPD include/generated/timestamp_autogenerated.h UPD include/generated/dt.h ENVC include/generated/env.txt ENVP include/generated/env.in ENVT include/generated/environment.h CC lib/asm-offsets.s UPD include/generated/generic-asm-offsets.h CC arch/arm/lib/asm-offsets.s UPD include/generated/asm-offsets.h SHIPPED scripts/dtc/pylibfdt/libfdt.i PYMOD rebuild HOSTCC scripts/dtc/dtc.o HOSTCC scripts/dtc/flattree.o HOSTCC scripts/dtc/fstree.o HOSTCC scripts/dtc/data.o HOSTCC scripts/dtc/livetree.o HOSTCC scripts/dtc/treesource.o HOSTCC scripts/dtc/srcpos.o HOSTCC scripts/dtc/checks.o HOSTCC scripts/dtc/util.o LEX scripts/dtc/dtc-lexer.lex.c YACC scripts/dtc/dtc-parser.tab.h HOSTCC scripts/dtc/dtc-lexer.lex.o YACC scripts/dtc/dtc-parser.tab.c HOSTCC scripts/dtc/dtc-parser.tab.o HOSTLD scripts/dtc/dtc HOSTCC tools/gen_eth_addr HOSTCC tools/gen_ethaddr_crc.o WRAP tools/generated/lib/crc8.c HOSTCC tools/generated/lib/crc8.o HOSTLD tools/gen_ethaddr_crc HOSTCC tools/img2srec HOSTCC tools/mkenvimage.o HOSTCC tools/os_support.o WRAP tools/generated/lib/crc32.c HOSTCC tools/generated/lib/crc32.o HOSTLD tools/mkenvimage HOSTCC tools/aisimage.o HOSTCC tools/atmelimage.o HOSTCC tools/fit_common.o HOSTCC tools/fit_image.o HOSTCC tools/image-host.o WRAP tools/generated/boot/image-fit.c HOSTCC tools/generated/boot/image-fit.o HOSTCC tools/image-sig-host.o WRAP tools/generated/boot/image-fit-sig.c HOSTCC tools/generated/boot/image-fit-sig.o WRAP tools/generated/boot/image-cipher.c HOSTCC tools/generated/boot/image-cipher.o WRAP tools/generated/boot/fdt_region.c HOSTCC tools/generated/boot/fdt_region.o WRAP tools/generated/boot/bootm.c HOSTCC tools/generated/boot/bootm.o HOSTCC tools/default_image.o WRAP tools/generated/lib/fdtdec_common.c HOSTCC tools/generated/lib/fdtdec_common.o WRAP tools/generated/lib/fdtdec.c HOSTCC tools/generated/lib/fdtdec.o WRAP tools/generated/boot/image.c HOSTCC tools/generated/boot/image.o WRAP tools/generated/boot/image-host.c HOSTCC tools/generated/boot/image-host.o HOSTCC tools/imagetool.o HOSTCC tools/imximage.o HOSTCC tools/imx8image.o HOSTCC tools/imx8mimage.o HOSTCC tools/kwbimage.o WRAP tools/generated/lib/md5.c HOSTCC tools/generated/lib/md5.o HOSTCC tools/lpc32xximage.o HOSTCC tools/mxsimage.o HOSTCC tools/omapimage.o HOSTCC tools/pblimage.o HOSTCC tools/pbl_crc32.o HOSTCC tools/renesas_spkgimage.o HOSTCC tools/sfspl.o HOSTCC tools/vybridimage.o HOSTCC tools/stm32image.o WRAP tools/generated/lib/rc4.c HOSTCC tools/generated/lib/rc4.o HOSTCC tools/rkcommon.o HOSTCC tools/rkimage.o HOSTCC tools/rksd.o HOSTCC tools/rkspi.o HOSTCC tools/socfpgaimage.o HOSTCC tools/sunxi_egon.o WRAP tools/generated/lib/crc16-ccitt.c HOSTCC tools/generated/lib/crc16-ccitt.o WRAP tools/generated/lib/hash-checksum.c HOSTCC tools/generated/lib/hash-checksum.o WRAP tools/generated/lib/sha1.c HOSTCC tools/generated/lib/sha1.o WRAP tools/generated/lib/sha256.c HOSTCC tools/generated/lib/sha256.o WRAP tools/generated/lib/sha512.c HOSTCC tools/generated/lib/sha512.o WRAP tools/generated/common/hash.c HOSTCC tools/generated/common/hash.o HOSTCC tools/ublimage.o HOSTCC tools/zynqimage.o HOSTCC tools/zynqmpimage.o HOSTCC tools/zynqmpbif.o WRAP tools/generated/lib/fdt-libcrypto.c HOSTCC tools/generated/lib/fdt-libcrypto.o HOSTCC tools/sunxi_toc0.o HOSTCC tools/libfdt/fdt.o HOSTCC tools/libfdt/fdt_ro.o HOSTCC tools/libfdt/fdt_wip.o HOSTCC tools/libfdt/fdt_sw.o HOSTCC tools/libfdt/fdt_rw.o HOSTCC tools/libfdt/fdt_strerror.o HOSTCC tools/libfdt/fdt_empty_tree.o HOSTCC tools/libfdt/fdt_addresses.o HOSTCC tools/libfdt/fdt_overlay.o HOSTCC tools/gpimage.o HOSTCC tools/gpimage-common.o HOSTCC tools/mtk_image.o HOSTCC tools/mtk_nand_headers.o WRAP tools/generated/lib/ecdsa/ecdsa-libcrypto.c HOSTCC tools/generated/lib/ecdsa/ecdsa-libcrypto.o WRAP tools/generated/lib/rsa/rsa-sign.c HOSTCC tools/generated/lib/rsa/rsa-sign.o WRAP tools/generated/lib/rsa/rsa-verify.c HOSTCC tools/generated/lib/rsa/rsa-verify.o WRAP tools/generated/lib/rsa/rsa-mod-exp.c HOSTCC tools/generated/lib/rsa/rsa-mod-exp.o WRAP tools/generated/lib/aes/aes-encrypt.c HOSTCC tools/generated/lib/aes/aes-encrypt.o WRAP tools/generated/lib/aes/aes-decrypt.c HOSTCC tools/generated/lib/aes/aes-decrypt.o HOSTCC tools/dumpimage.o HOSTLD tools/dumpimage HOSTCC tools/mkimage.o HOSTLD tools/mkimage HOSTCC tools/fit_info.o HOSTLD tools/fit_info HOSTCC tools/fit_check_sign.o HOSTLD tools/fit_check_sign HOSTCC tools/fdt_add_pubkey.o HOSTLD tools/fdt_add_pubkey HOSTCC tools/proftool.o WRAP tools/generated/lib/abuf.c HOSTCC tools/generated/lib/abuf.o HOSTLD tools/proftool HOSTCC tools/relocate-rela HOSTCC tools/fdtgrep.o HOSTLD tools/fdtgrep HOSTCC tools/spl_size_limit WRAP tools/generated/lib/uuid.c HOSTCC tools/generated/lib/uuid.o HOSTCC tools/mkeficapsule.o HOSTLD tools/mkeficapsule AR arch/arm/cpu/built-in.o CC arch/arm/cpu/armv8/cpu.o CC arch/arm/cpu/armv8/generic_timer.o CC arch/arm/cpu/armv8/cache_v8.o AS arch/arm/cpu/armv8/cache.o AS arch/arm/cpu/armv8/exceptions.o CC arch/arm/cpu/armv8/exception_level.o AS arch/arm/cpu/armv8/tlb.o AS arch/arm/cpu/armv8/transition.o CC arch/arm/cpu/armv8/fwcall.o CC arch/arm/cpu/armv8/cpu-dt.o AS arch/arm/cpu/armv8/smccc-call.o AR arch/arm/cpu/armv8/built-in.o AS arch/arm/cpu/armv8/start.o AS arch/arm/lib/crt0_64.o AS arch/arm/lib/setjmp_aarch64.o AS arch/arm/lib/relocate_64.o CC arch/arm/lib/bootm-fdt.o CC arch/arm/lib/bootm.o CC arch/arm/lib/image.o CC arch/arm/lib/bdinfo.o CC arch/arm/lib/sections.o CC arch/arm/lib/stack.o CC arch/arm/lib/interrupts_64.o CC arch/arm/lib/reset.o CC arch/arm/lib/cache.o CC arch/arm/lib/psci-dt.o AR arch/arm/lib/built-in.o AR arch/arm/lib/lib.a CC arch/arm/mach-imx/imx9/scmi/soc.o CC arch/arm/mach-imx/imx9/scmi/clock_scmi.o CC arch/arm/mach-imx/imx9/scmi/clock.o AR arch/arm/mach-imx/imx9/scmi/built-in.o AS arch/arm/mach-imx/imx9/lowlevel_init.o CC arch/arm/mach-imx/imx9/imx_bootaux.o AR arch/arm/mach-imx/imx9/built-in.o CC arch/arm/mach-imx/iomux-v3.o CC arch/arm/mach-imx/fdt.o CC arch/arm/mach-imx/misc.o AR arch/arm/mach-imx/built-in.o CC board/freescale/common/mmc.o AR board/freescale/common/built-in.o CC board/freescale/imx95_evk/imx95_evk.o AR board/freescale/imx95_evk/built-in.o CC boot/bootm.o CC boot/bootm_os.o CC boot/pxe_utils.o CC boot/image.o CC boot/image-board.o CC boot/bootdev-uclass.o CC boot/bootflow.o CC boot/bootmeth-uclass.o CC boot/bootstd-uclass.o CC boot/bootmeth_extlinux.o CC boot/bootmeth_efi.o CC boot/bootmeth_efi_mgr.o CC boot/fdt_support.o CC boot/image-fdt.o AR boot/built-in.o AR cmd/arm/built-in.o CC cmd/boot.o CC cmd/bootm.o CC cmd/help.o CC cmd/panic.o CC cmd/version.o CC cmd/blk_common.o CC cmd/bootflow.o CC cmd/source.o CC cmd/bdinfo.o CC cmd/blkcache.o CC cmd/bootefi.o CC cmd/booti.o CC cmd/cache.o CC cmd/clk.o CC cmd/console.o CC cmd/date.o CC cmd/dm.o CC cmd/echo.o CC cmd/efidebug.o CC cmd/efi_common.o CC cmd/eficonfig.o CC cmd/elf.o CC cmd/exit.o CC cmd/ext4.o CC cmd/ext2.o CC cmd/fat.o CC cmd/fdt.o CC cmd/fs.o CC cmd/fuse.o CC cmd/gettime.o CC cmd/gpio.o CC cmd/i2c.o CC cmd/hash.o CC cmd/itest.o CC cmd/load.o CC cmd/mem.o CC cmd/mii.o CC cmd/mdio.o CC cmd/sleep.o CC cmd/mmc.o CC cmd/legacy-mtd-utils.o CC cmd/net.o CC cmd/net-common.o CC cmd/nvedit.o CC cmd/nvedit_efi.o CC cmd/part.o CC cmd/pci.o CC cmd/pinmux.o CC cmd/rtc.o CC cmd/sf.o CC cmd/setexpr.o CC cmd/time.o CC cmd/timer.o CC cmd/test.o CC cmd/unlz4.o CC cmd/unzip.o CC cmd/lzmadec.o CC cmd/ximg.o CC cmd/dfu.o CC cmd/gpt.o CC cmd/regulator.o AR cmd/built-in.o CC common/init/board_init.o AR common/init/built-in.o CC common/main.o CC common/memtop.o CC common/exports.o CC common/cli_getch.o CC common/cli_simple.o CC common/cli_readline.o CC common/cli_hush.o CC common/autoboot.o CC common/version.o CC common/board_f.o CC common/board_r.o CC common/board_info.o CC common/miiphyutil.o CC common/splash.o CC common/menu.o CC common/console.o CC common/dlmalloc.o CC common/malloc_simple.o CC common/event.o CC common/hash.o CC common/memsize.o CC common/stdio.o CC common/cli.o CC common/command.o CC common/s_record.o CC common/xyzModem.o AR common/built-in.o CC disk/part.o CC disk/disk-uclass.o CC disk/part_dos.o CC disk/part_efi.o AR disk/built-in.o AR drivers/ata/built-in.o AR drivers/axi/built-in.o CC drivers/block/blk-uclass.o CC drivers/block/blkcache.o AR drivers/block/built-in.o AR drivers/bus/built-in.o AR drivers/cache/built-in.o AR drivers/clk/adi/built-in.o AR drivers/clk/analogbits/built-in.o CC drivers/clk/imx/clk-gate2.o CC drivers/clk/imx/clk-pllv3.o CC drivers/clk/imx/clk-pfd.o AR drivers/clk/imx/built-in.o AR drivers/clk/tegra/built-in.o AR drivers/clk/ti/built-in.o CC drivers/clk/clk-uclass.o CC drivers/clk/clk_fixed_rate.o CC drivers/clk/clk_fixed_factor.o CC drivers/clk/clk.o CC drivers/clk/clk-divider.o CC drivers/clk/clk-mux.o CC drivers/clk/clk-gate.o CC drivers/clk/clk-fixed-factor.o CC drivers/clk/clk_scmi.o AR drivers/clk/built-in.o CC drivers/core/device.o CC drivers/core/fdtaddr.o CC drivers/core/lists.o CC drivers/core/root.o CC drivers/core/uclass.o CC drivers/core/util.o CC drivers/core/tag.o CC drivers/core/device-remove.o CC drivers/core/simple-bus.o CC drivers/core/dump.o CC drivers/core/regmap.o CC drivers/core/syscon-uclass.o CC drivers/core/of_extra.o CC drivers/core/ofnode.o CC drivers/core/read_extra.o AR drivers/core/built-in.o AR drivers/crypto/aspeed/built-in.o CC drivers/crypto/fsl/sec.o AR drivers/crypto/fsl/built-in.o AR drivers/crypto/hash/built-in.o AR drivers/crypto/nuvoton/built-in.o AR drivers/crypto/rsa_mod_exp/built-in.o AR drivers/crypto/built-in.o CC drivers/dfu/dfu.o CC drivers/dfu/dfu_mmc.o CC drivers/dfu/dfu_ram.o AR drivers/dfu/built-in.o CC drivers/firmware/scmi/scmi_agent-uclass.o CC drivers/firmware/scmi/base.o CC drivers/firmware/scmi/smt.o CC drivers/firmware/scmi/mailbox_agent.o CC drivers/firmware/scmi/pwdom.o AR drivers/firmware/scmi/built-in.o CC drivers/firmware/firmware-uclass.o CC drivers/firmware/psci.o AR drivers/firmware/built-in.o CC drivers/gpio/gpio-uclass.o CC drivers/gpio/pca953x_gpio.o CC drivers/gpio/imx_rgpio2p.o CC drivers/gpio/adp5585_gpio.o AR drivers/gpio/built-in.o CC drivers/i2c/i2c-uclass.o CC drivers/i2c/imx_lpi2c.o AR drivers/i2c/built-in.o CC drivers/input/key_matrix.o AR drivers/input/built-in.o AR drivers/iommu/built-in.o CC drivers/mailbox/mailbox-uclass.o CC drivers/mailbox/imx-mailbox.o AR drivers/mailbox/built-in.o AR drivers/memory/built-in.o AR drivers/mfd/built-in.o CC drivers/misc/imx_ele/ele_api.o CC drivers/misc/imx_ele/ele_mu.o CC drivers/misc/imx_ele/fuse.o AR drivers/misc/imx_ele/built-in.o CC drivers/misc/misc-uclass.o AR drivers/misc/built-in.o CC drivers/mmc/mmc.o CC drivers/mmc/mmc-uclass.o CC drivers/mmc/mmc_bootdev.o CC drivers/mmc/mmc_write.o CC drivers/mmc/mmc_boot.o CC drivers/mmc/fsl_esdhc_imx.o AR drivers/mmc/built-in.o AR drivers/mtd/nand/built-in.o AR drivers/mtd/onenand/built-in.o CC drivers/mtd/spi/sf-uclass.o CC drivers/mtd/spi/sf_probe.o CC drivers/mtd/spi/spi-nor-ids.o CC drivers/mtd/spi/spi-nor-core.o AR drivers/mtd/spi/spi-nor.o AR drivers/mtd/spi/built-in.o CC drivers/mtd/mtdcore.o CC drivers/mtd/mtd_uboot.o AR drivers/mtd/mtd.o AR drivers/mtd/built-in.o AR drivers/net/mscc_eswitch/built-in.o CC drivers/net/phy/phy.o CC drivers/net/phy/generic_10g.o CC drivers/net/phy/aquantia.o CC drivers/net/phy/realtek.o AR drivers/net/phy/built-in.o AR drivers/net/qe/built-in.o AR drivers/net/ti/built-in.o CC drivers/net/fsl_enetc.o CC drivers/net/fsl_enetc_mdio.o AR drivers/net/built-in.o CC drivers/pci/pci-uclass.o CC drivers/pci/pci_auto.o CC drivers/pci/pci_auto_common.o CC drivers/pci/pci_common.o CC drivers/pci/pcie_ecam_generic.o AR drivers/pci/built-in.o AR drivers/phy/allwinner/built-in.o AR drivers/phy/cadence/built-in.o AR drivers/phy/marvell/built-in.o AR drivers/phy/qcom/built-in.o AR drivers/phy/renesas/built-in.o AR drivers/phy/rockchip/built-in.o AR drivers/phy/socionext/built-in.o AR drivers/phy/ti/built-in.o CC drivers/phy/phy-uclass.o AR drivers/phy/built-in.o AR drivers/pinctrl/broadcom/built-in.o CC drivers/pinctrl/nxp/pinctrl-imx.o CC drivers/pinctrl/nxp/pinctrl-scmi.o AR drivers/pinctrl/nxp/built-in.o CC drivers/pinctrl/pinctrl-uclass.o CC drivers/pinctrl/pinctrl-generic.o AR drivers/pinctrl/built-in.o CC drivers/power/domain/power-domain-uclass.o CC drivers/power/domain/scmi-power-domain.o AR drivers/power/domain/built-in.o AR drivers/power/pmic/built-in.o CC drivers/power/regulator/regulator-uclass.o CC drivers/power/regulator/regulator_common.o CC drivers/power/regulator/fixed.o CC drivers/power/regulator/gpio-regulator.o AR drivers/power/regulator/built-in.o AR drivers/power/built-in.o AR drivers/pwm/built-in.o AR drivers/reset/built-in.o CC drivers/rtc/rtc-uclass.o AR drivers/rtc/built-in.o AR drivers/scsi/built-in.o CC drivers/serial/serial-uclass.o CC drivers/serial/serial_lpuart.o AR drivers/serial/built-in.o AR drivers/smem/built-in.o AR drivers/soc/built-in.o AR drivers/sound/built-in.o CC drivers/spi/spi-uclass.o CC drivers/spi/spi-mem.o CC drivers/spi/nxp_fspi.o AR drivers/spi/built-in.o AR drivers/spmi/built-in.o AR drivers/thermal/built-in.o AR drivers/ufs/built-in.o CC drivers/watchdog/ulp_wdog.o AR drivers/watchdog/built-in.o AR drivers/built-in.o AR drivers/usb/cdns3/built-in.o AR drivers/usb/common/built-in.o AR drivers/usb/dwc3/built-in.o AR drivers/usb/emul/built-in.o AR drivers/usb/eth/built-in.o AR drivers/usb/host/built-in.o AR drivers/usb/isp1760/built-in.o AR drivers/usb/mtu3/built-in.o AR drivers/usb/musb-new/built-in.o AR drivers/usb/musb/built-in.o AR drivers/usb/phy/built-in.o AR drivers/usb/tcpm/built-in.o AR drivers/usb/ulpi/built-in.o CC env/common.o CC env/env.o CC env/attr.o CC env/flags.o CC env/callback.o CC env/nowhere.o CC env/mmc.o AR env/built-in.o CC fs/ext4/ext4fs.o CC fs/ext4/ext4_common.o CC fs/ext4/dev.o CC fs/ext4/ext4_write.o CC fs/ext4/ext4_journal.o AR fs/ext4/built-in.o CC fs/fat/fat_write.o AR fs/fat/built-in.o CC fs/fs.o CC fs/fs_internal.o AR fs/built-in.o CC lib/bzip2/bzlib.o CC lib/bzip2/bzlib_crctable.o CC lib/bzip2/bzlib_decompress.o CC lib/bzip2/bzlib_randtable.o CC lib/bzip2/bzlib_huffman.o AR lib/bzip2/built-in.o AR lib/crypto/built-in.o CC lib/efi_driver/efi_uclass.o CC lib/efi_driver/efi_block_device.o AR lib/efi_driver/built-in.o CC lib/efi_loader/efi_bootmgr.o CC lib/efi_loader/efi_bootbin.o CC lib/efi_loader/efi_boottime.o CC lib/efi_loader/efi_helper.o CC lib/efi_loader/efi_console.o CC lib/efi_loader/efi_device_path.o CC lib/efi_loader/efi_device_path_to_text.o CC lib/efi_loader/efi_device_path_utilities.o CC lib/efi_loader/efi_dt_fixup.o CC lib/efi_loader/efi_fdt.o CC lib/efi_loader/efi_file.o CC lib/efi_loader/efi_hii.o CC lib/efi_loader/efi_image_loader.o CC lib/efi_loader/efi_load_options.o CC lib/efi_loader/efi_memory.o CC lib/efi_loader/efi_root_node.o CC lib/efi_loader/efi_runtime.o CC lib/efi_loader/efi_setup.o CC lib/efi_loader/efi_string.o CC lib/efi_loader/efi_unicode_collation.o CC lib/efi_loader/efi_var_common.o CC lib/efi_loader/efi_var_mem.o CC lib/efi_loader/efi_variable.o CC lib/efi_loader/efi_var_file.o CC lib/efi_loader/efi_watchdog.o CC lib/efi_loader/efi_disk.o CC lib/efi_loader/efi_net.o CC lib/efi_loader/efi_smbios.o CC lib/efi_loader/efi_load_initrd.o CC lib/efi_loader/efi_conformance.o AR lib/efi_loader/built-in.o CC lib/efi_loader/helloworld.o AS lib/efi_loader/efi_crt0.o CC lib/efi_loader/efi_reloc.o CC lib/efi_loader/efi_freestanding.o LD lib/efi_loader/helloworld_efi.so OBJCOPY lib/efi_loader/helloworld.efi CC lib/efi_loader/smbiosdump.o LD lib/efi_loader/smbiosdump_efi.so OBJCOPY lib/efi_loader/smbiosdump.efi CC lib/efi_loader/initrddump.o LD lib/efi_loader/initrddump_efi.so OBJCOPY lib/efi_loader/initrddump.efi CC lib/efi_loader/dtbdump.o LD lib/efi_loader/dtbdump_efi.so OBJCOPY lib/efi_loader/dtbdump.efi CC lib/efi_loader/testapp.o LD lib/efi_loader/testapp_efi.so OBJCOPY lib/efi_loader/testapp.efi CC lib/libfdt/fdt.o CC lib/libfdt/fdt_ro.o CC lib/libfdt/fdt_wip.o CC lib/libfdt/fdt_strerror.o CC lib/libfdt/fdt_sw.o CC lib/libfdt/fdt_rw.o CC lib/libfdt/fdt_empty_tree.o CC lib/libfdt/fdt_addresses.o CC lib/libfdt/fdt_overlay.o AR lib/libfdt/built-in.o CC lib/lzma/LzmaDec.o CC lib/lzma/LzmaTools.o AR lib/lzma/built-in.o CC lib/lzo/lzo1x_decompress.o AR lib/lzo/built-in.o CC lib/zlib/zlib.o AR lib/zlib/built-in.o CC lib/binman.o CC lib/charset.o CC lib/crc8.o CC lib/crc16.o CC lib/crc16-ccitt.o CC lib/smbios.o CC lib/initcall.o CC lib/ldiv.o CC lib/net_utils.o CC lib/rc4.o CC lib/list_sort.o CC lib/hash-checksum.o CC lib/sha1.o CC lib/gunzip.o CC lib/lz4_wrapper.o CC lib/fdtdec_common.o CC lib/fdtdec.o CC lib/qsort.o CC lib/hashtable.o CC lib/errno.o CC lib/display_options.o CC lib/crc32.o CC lib/ctype.o CC lib/div64.o CC lib/hang.o CC lib/linux_compat.o CC lib/linux_string.o CC lib/lmb.o CC lib/membuff.o CC lib/slre.o CC lib/string.o CC lib/tables_csum.o CC lib/time.o CC lib/hexdump.o CC lib/uuid.o CC lib/rand.o CC lib/panic.o CC lib/vsprintf.o CC lib/strto.o CC lib/abuf.o CC lib/alist.o CC lib/date.o CC lib/rtc-lib.o CC lib/elf.o AR lib/built-in.o CC net/arp.o CC net/bootp.o CC net/net.o CC net/ping.o CC net/sntp.o CC net/tftp.o CC net/udp.o CC net/eth-uclass.o CC net/eth_bootdev.o CC net/mdio-uclass.o CC net/eth_common.o CC net/net-common.o AR net/built-in.o LDS u-boot.lds LD u-boot DTC dts/upstream/src/arm64/freescale/imx95-19x19-evk.dtb SHIPPED dts/dt.dtb CC spl/./lib/asm-offsets.s UPD spl/./include/generated/generic-asm-offsets.h CC spl/./arch/arm/lib/asm-offsets.s UPD spl/./include/generated/asm-offsets.h CC spl/arch/arm/mach-imx/imx9/scmi/soc.o CC spl/arch/arm/mach-imx/imx9/scmi/clock_scmi.o CC spl/arch/arm/mach-imx/imx9/scmi/clock.o AR spl/arch/arm/mach-imx/imx9/scmi/built-in.o AS spl/arch/arm/mach-imx/imx9/lowlevel_init.o AR spl/arch/arm/mach-imx/imx9/built-in.o CC spl/arch/arm/mach-imx/iomux-v3.o CC spl/arch/arm/mach-imx/misc.o CC spl/arch/arm/mach-imx/spl.o CC spl/arch/arm/mach-imx/image-container.o AR spl/arch/arm/mach-imx/built-in.o CC spl/arch/arm/cpu/armv8/cpu.o CC spl/arch/arm/cpu/armv8/generic_timer.o CC spl/arch/arm/cpu/armv8/cache_v8.o AS spl/arch/arm/cpu/armv8/cache.o AS spl/arch/arm/cpu/armv8/exceptions.o AS spl/arch/arm/cpu/armv8/tlb.o AS spl/arch/arm/cpu/armv8/transition.o CC spl/arch/arm/cpu/armv8/fwcall.o CC spl/arch/arm/cpu/armv8/cpu-dt.o AS spl/arch/arm/cpu/armv8/smccc-call.o CC spl/arch/arm/cpu/armv8/spl_data.o AR spl/arch/arm/cpu/armv8/built-in.o AS spl/arch/arm/cpu/armv8/start.o AR spl/arch/arm/cpu/built-in.o AS spl/arch/arm/lib/crt0_64.o AS spl/arch/arm/lib/setjmp_aarch64.o CC spl/arch/arm/lib/spl.o CC spl/arch/arm/lib/image.o CC spl/arch/arm/lib/bootm-fdt.o CC spl/arch/arm/lib/bdinfo.o CC spl/arch/arm/lib/sections.o CC spl/arch/arm/lib/stack.o CC spl/arch/arm/lib/interrupts_64.o CC spl/arch/arm/lib/reset.o CC spl/arch/arm/lib/cache.o CC spl/arch/arm/lib/psci-dt.o AR spl/arch/arm/lib/built-in.o AR spl/arch/arm/lib/lib.a CC spl/board/freescale/imx95_evk/imx95_evk.o CC spl/board/freescale/imx95_evk/spl.o AR spl/board/freescale/imx95_evk/built-in.o CC spl/board/freescale/common/mmc.o AR spl/board/freescale/common/built-in.o CC spl/common/spl/spl.o CC spl/common/spl/spl_legacy.o CC spl/common/spl/spl_mmc.o CC spl/common/spl/spl_imx_container.o AR spl/common/spl/built-in.o CC spl/common/init/board_init.o AR spl/common/init/built-in.o CC spl/boot/image.o CC spl/boot/image-board.o CC spl/boot/fdt_support.o CC spl/boot/image-fdt.o AR spl/boot/built-in.o CC spl/common/console.o CC spl/common/dlmalloc.o CC spl/common/malloc_simple.o CC spl/common/memsize.o CC spl/common/stdio.o CC spl/common/cli.o CC spl/common/command.o CC spl/common/s_record.o CC spl/common/xyzModem.o AR spl/common/built-in.o AR spl/cmd/built-in.o AR spl/env/built-in.o AR spl/lib/crypto/built-in.o CC spl/lib/libfdt/fdt.o CC spl/lib/libfdt/fdt_ro.o CC spl/lib/libfdt/fdt_wip.o CC spl/lib/libfdt/fdt_strerror.o CC spl/lib/libfdt/fdt_sw.o CC spl/lib/libfdt/fdt_rw.o CC spl/lib/libfdt/fdt_empty_tree.o CC spl/lib/libfdt/fdt_addresses.o CC spl/lib/libfdt/fdt_overlay.o AR spl/lib/libfdt/built-in.o CC spl/lib/hash-checksum.o CC spl/lib/sha1.o CC spl/lib/fdtdec_common.o CC spl/lib/fdtdec.o CC spl/lib/net_utils.o CC spl/lib/qsort.o CC spl/lib/hashtable.o CC spl/lib/errno.o CC spl/lib/display_options.o CC spl/lib/crc32.o CC spl/lib/ctype.o CC spl/lib/div64.o CC spl/lib/hang.o CC spl/lib/linux_compat.o CC spl/lib/linux_string.o CC spl/lib/membuff.o CC spl/lib/slre.o CC spl/lib/string.o CC spl/lib/tables_csum.o CC spl/lib/time.o CC spl/lib/hexdump.o CC spl/lib/uuid.o CC spl/lib/rand.o CC spl/lib/panic.o CC spl/lib/tiny-printf.o CC spl/lib/strto.o CC spl/lib/abuf.o CC spl/lib/alist.o CC spl/lib/date.o CC spl/lib/rtc-lib.o CC spl/lib/elf.o AR spl/lib/built-in.o CC spl/disk/part.o CC spl/disk/disk-uclass.o CC spl/disk/part_dos.o CC spl/disk/part_efi.o AR spl/disk/built-in.o CC spl/drivers/block/blk-uclass.o AR spl/drivers/block/built-in.o AR spl/drivers/bus/built-in.o AR spl/drivers/clk/adi/built-in.o AR spl/drivers/clk/analogbits/built-in.o CC spl/drivers/clk/imx/clk-gate2.o CC spl/drivers/clk/imx/clk-pllv3.o CC spl/drivers/clk/imx/clk-pfd.o AR spl/drivers/clk/imx/built-in.o AR spl/drivers/clk/tegra/built-in.o AR spl/drivers/clk/ti/built-in.o CC spl/drivers/clk/clk-uclass.o CC spl/drivers/clk/clk_fixed_rate.o CC spl/drivers/clk/clk_fixed_factor.o CC spl/drivers/clk/clk.o CC spl/drivers/clk/clk-divider.o CC spl/drivers/clk/clk-mux.o CC spl/drivers/clk/clk-gate.o CC spl/drivers/clk/clk-fixed-factor.o CC spl/drivers/clk/clk_scmi.o AR spl/drivers/clk/built-in.o CC spl/drivers/core/device.o CC spl/drivers/core/fdtaddr.o CC spl/drivers/core/lists.o CC spl/drivers/core/root.o CC spl/drivers/core/uclass.o CC spl/drivers/core/util.o CC spl/drivers/core/tag.o CC spl/drivers/core/simple-bus.o CC spl/drivers/core/dump.o CC spl/drivers/core/of_extra.o CC spl/drivers/core/ofnode.o CC spl/drivers/core/read_extra.o AR spl/drivers/core/built-in.o AR spl/drivers/ddr/imx/imx9/../phy/built-in.o AR spl/drivers/ddr/imx/imx9/built-in.o CC spl/drivers/firmware/scmi/scmi_agent-uclass.o CC spl/drivers/firmware/scmi/base.o CC spl/drivers/firmware/scmi/smt.o CC spl/drivers/firmware/scmi/mailbox_agent.o CC spl/drivers/firmware/scmi/pwdom.o AR spl/drivers/firmware/scmi/built-in.o CC spl/drivers/firmware/firmware-uclass.o AR spl/drivers/firmware/built-in.o CC spl/drivers/gpio/gpio-uclass.o CC spl/drivers/gpio/imx_rgpio2p.o CC spl/drivers/gpio/adp5585_gpio.o AR spl/drivers/gpio/built-in.o CC spl/drivers/i2c/i2c-uclass.o CC spl/drivers/i2c/imx_lpi2c.o AR spl/drivers/i2c/built-in.o CC spl/drivers/mailbox/mailbox-uclass.o CC spl/drivers/mailbox/imx-mailbox.o AR spl/drivers/mailbox/built-in.o CC spl/drivers/misc/imx_ele/ele_api.o CC spl/drivers/misc/imx_ele/ele_mu.o CC spl/drivers/misc/imx_ele/fuse.o AR spl/drivers/misc/imx_ele/built-in.o CC spl/drivers/misc/misc-uclass.o AR spl/drivers/misc/built-in.o CC spl/drivers/mmc/mmc.o CC spl/drivers/mmc/mmc-uclass.o CC spl/drivers/mmc/mmc_boot.o CC spl/drivers/mmc/fsl_esdhc_imx.o AR spl/drivers/mmc/built-in.o AR spl/drivers/mtd/built-in.o AR spl/drivers/pinctrl/broadcom/built-in.o CC spl/drivers/pinctrl/nxp/pinctrl-imx.o CC spl/drivers/pinctrl/nxp/pinctrl-scmi.o AR spl/drivers/pinctrl/nxp/built-in.o CC spl/drivers/pinctrl/pinctrl-uclass.o CC spl/drivers/pinctrl/pinctrl-generic.o AR spl/drivers/pinctrl/built-in.o AR spl/drivers/power/pmic/built-in.o CC spl/drivers/power/regulator/regulator-uclass.o CC spl/drivers/power/regulator/regulator_common.o CC spl/drivers/power/regulator/fixed.o AR spl/drivers/power/regulator/built-in.o AR spl/drivers/power/built-in.o CC spl/drivers/serial/serial-uclass.o CC spl/drivers/serial/serial_lpuart.o AR spl/drivers/serial/built-in.o AR spl/drivers/soc/built-in.o CC spl/drivers/watchdog/ulp_wdog.o CC spl/drivers/watchdog/wdt-uclass.o AR spl/drivers/watchdog/built-in.o AR spl/drivers/built-in.o AR spl/dts/built-in.o CC spl/fs/fs_internal.o AR spl/fs/built-in.o LDS spl/u-boot-spl.lds LD spl/u-boot-spl OBJCOPY spl/u-boot-spl-nodtb.bin mkdir -p spl/dts/ FDTGREP spl/dts/dt-spl.dtb COPY spl/u-boot-spl.dtb CAT spl/u-boot-spl-dtb.bin COPY spl/u-boot-spl.bin SYM spl/u-boot-spl.sym CHECK spl/u-boot-spl.cfgout CHECK u-boot-container.cfgout WARNING './u-boot.bin' not found, resulting binary may be not-functional OBJCOPY u-boot.srec OBJCOPY u-boot-nodtb.bin RELOC u-boot-nodtb.bin CAT u-boot-dtb.bin COPY u-boot.bin SYM u-boot.sym MKIMAGE u-boot.img COPY u-boot.dtb MKIMAGE u-boot-dtb.img LDS u-boot-elf.lds LD u-boot.elf BINMAN .binman_stamp OFCHK .config -rw-r--r-- 1 tharvey Tim Harvey 922624 Dec 31 11:08 imx-boot-imx95.bin ^^^ image too small... missing u-boot.bin
$ make && ls -l imx-boot-imx95.bin UPD include/generated/timestamp_autogenerated.h CC common/version.o AR common/built-in.o LD u-boot OBJCOPY u-boot.srec OBJCOPY u-boot-nodtb.bin RELOC u-boot-nodtb.bin CAT u-boot-dtb.bin COPY u-boot.bin SYM u-boot.sym CC spl/common/spl/spl.o AR spl/common/spl/built-in.o LD spl/u-boot-spl OBJCOPY spl/u-boot-spl-nodtb.bin CAT spl/u-boot-spl-dtb.bin COPY spl/u-boot-spl.bin SYM spl/u-boot-spl.sym MKIMAGE u-boot.img MKIMAGE u-boot-dtb.img LD u-boot.elf CHECK u-boot-container.cfgout BINMAN .binman_stamp OFCHK .config -rw-r--r-- 1 tharvey Tim Harvey 1709056 Dec 31 11:10 imx-boot-imx95.bin ^^^ now we have a proper image
Best Regards,
Tim

-----邮件原件----- 发件人: Tim Harvey tharvey@gateworks.com 发送时间: 2025年1月1日 4:32 收件人: Alice Guo (OSS) alice.guo@oss.nxp.com; Simon Glass sjg@chromium.org 抄送: Tom Rini trini@konsulko.com; Stefano Babic sbabic@denx.de; Fabio Estevam festevam@gmail.com; dl-uboot-imx uboot-imx@nxp.com; Lukasz Majewski lukma@denx.de; Sean Anderson seanga2@gmail.com; Alper Nebi Yasak alpernebiyasak@gmail.com; u-boot@lists.denx.de; marex@denx.de; Alice Guo alice.guo@nxp.com; Ye Li ye.li@nxp.com; Peng Fan peng.fan@nxp.com 主题: Re: [EXT] Re: [PATCH v2 16/17] imx95_evk: add i.MX95 19x19 EVK board basic support
Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
On Mon, Dec 30, 2024 at 6:34 PM Alice Guo (OSS) alice.guo@oss.nxp.com wrote:
主题: [EXT] Re: [PATCH v2 16/17] imx95_evk: add i.MX95 19x19 EVK board basic support
I gave this series a go on top of 5cfbf8c364 origin/next on an EVK I have here and I saw no u-boot proper output after the ATF.
Here is what I saw on UART2: U-Boot SPL 2025.01-rc5-00393-g9b292f7d347f (Dec 27 2024 - 16:12:20 -0800) DDRMIX is powered UP Normal Boot Trying to boot from MMC2 Primary set selected Load image from MMC/SD 0xdec00 NOTICE: BL31: v2.10.0 (release):lf-6.6.52-2.2.0 NOTICE: BL31: Built : 16:06:15, Dec 27 2024
U-Boot SPL 2025.01-rc5-00393-g9b292f7d347f (Dec 27 2024 - 16:12:20 -0800) DDRMIX is powered UP Normal Boot Trying to boot from MMC2 Primary set selected Load image from MMC/SD 0xdec00 NOTICE: BL31: v2.10.0 (release):lf-6.6.52-2.2.0 NOTICE: BL31: Built : 16:06:15, Dec 27 2024 ^^^ nothing after this
Any thoughts on what is wrong here?
Best Regards,
Tim
Hi Tim,
I tried it on my MX95 and it works well, so I not sure what causes this issue on
your EVK.
Hi Alice,
I discovered what happened. The first make for uboot resulted in a binman warning (which should be a failure but is not for some reason) and results in an image that doesn't contain uboot proper: WARNING './u-boot.bin' not found, resulting binary may be not-functional
Simon, do you know why this warning doesn't result in a make failure?
Doing a second make works, so I think there is likely a binman dependency issue going on here. You can re-create the issue with a distclean as shown here:
I reproduced this issue with make distclean, but not every time. I need time to check it.
Best Regards, Alice Guo

-----邮件原件----- 发件人: Tim Harvey tharvey@gateworks.com 发送时间: 2025年1月1日 4:32 收件人: Alice Guo (OSS) alice.guo@oss.nxp.com; Simon Glass sjg@chromium.org 抄送: Tom Rini trini@konsulko.com; Stefano Babic sbabic@denx.de; Fabio Estevam festevam@gmail.com; dl-uboot-imx uboot-imx@nxp.com; Lukasz Majewski lukma@denx.de; Sean Anderson seanga2@gmail.com; Alper Nebi Yasak alpernebiyasak@gmail.com; u-boot@lists.denx.de; marex@denx.de; Alice Guo alice.guo@nxp.com; Ye Li ye.li@nxp.com; Peng Fan peng.fan@nxp.com 主题: Re: [EXT] Re: [PATCH v2 16/17] imx95_evk: add i.MX95 19x19 EVK board basic support
Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
On Mon, Dec 30, 2024 at 6:34 PM Alice Guo (OSS) alice.guo@oss.nxp.com wrote:
主题: [EXT] Re: [PATCH v2 16/17] imx95_evk: add i.MX95 19x19 EVK board basic support
I gave this series a go on top of 5cfbf8c364 origin/next on an EVK I have here and I saw no u-boot proper output after the ATF.
Here is what I saw on UART2: U-Boot SPL 2025.01-rc5-00393-g9b292f7d347f (Dec 27 2024 - 16:12:20 -0800) DDRMIX is powered UP Normal Boot Trying to boot from MMC2 Primary set selected Load image from MMC/SD 0xdec00 NOTICE: BL31: v2.10.0 (release):lf-6.6.52-2.2.0 NOTICE: BL31: Built : 16:06:15, Dec 27 2024
U-Boot SPL 2025.01-rc5-00393-g9b292f7d347f (Dec 27 2024 - 16:12:20 -0800) DDRMIX is powered UP Normal Boot Trying to boot from MMC2 Primary set selected Load image from MMC/SD 0xdec00 NOTICE: BL31: v2.10.0 (release):lf-6.6.52-2.2.0 NOTICE: BL31: Built : 16:06:15, Dec 27 2024 ^^^ nothing after this
Any thoughts on what is wrong here?
Best Regards,
Tim
Hi Tim,
I tried it on my MX95 and it works well, so I not sure what causes this issue on
your EVK.
Hi Alice,
I discovered what happened. The first make for uboot resulted in a binman warning (which should be a failure but is not for some reason) and results in an image that doesn't contain uboot proper: WARNING './u-boot.bin' not found, resulting binary may be not-functional
Simon, do you know why this warning doesn't result in a make failure?
Doing a second make works, so I think there is likely a binman dependency issue going on here. You can re-create the issue with a distclean as shown here:
COPY spl/u-boot-spl.bin SYM spl/u-boot-spl.sym CHECK spl/u-boot-spl.cfgout CHECK u-boot-container.cfgout WARNING './u-boot.bin' not found, resulting binary may be not-functional OBJCOPY u-boot.srec OBJCOPY u-boot-nodtb.bin RELOC u-boot-nodtb.bin CAT u-boot-dtb.bin COPY u-boot.bin SYM u-boot.sym MKIMAGE u-boot.img COPY u-boot.dtb MKIMAGE u-boot-dtb.img LDS u-boot-elf.lds LD u-boot.elf BINMAN .binman_stamp OFCHK .config -rw-r--r-- 1 tharvey Tim Harvey 922624 Dec 31 11:08 imx-boot-imx95.bin ^^^ image too small... missing u-boot.bin
$ make && ls -l imx-boot-imx95.bin UPD include/generated/timestamp_autogenerated.h CC common/version.o AR common/built-in.o LD u-boot OBJCOPY u-boot.srec OBJCOPY u-boot-nodtb.bin RELOC u-boot-nodtb.bin CAT u-boot-dtb.bin COPY u-boot.bin SYM u-boot.sym CC spl/common/spl/spl.o AR spl/common/spl/built-in.o LD spl/u-boot-spl OBJCOPY spl/u-boot-spl-nodtb.bin CAT spl/u-boot-spl-dtb.bin COPY spl/u-boot-spl.bin SYM spl/u-boot-spl.sym MKIMAGE u-boot.img MKIMAGE u-boot-dtb.img LD u-boot.elf CHECK u-boot-container.cfgout BINMAN .binman_stamp OFCHK .config -rw-r--r-- 1 tharvey Tim Harvey 1709056 Dec 31 11:10 imx-boot-imx95.bin ^^^ now we have a proper image
Best Regards,
Tim
Hi Tim,
When using "make distclean; make imx95_19x19_evk_defconfig; make", imx9_image.sh will delete the line "IMAGE A55 u-boot.bin CONFIG_TEXT_BASE" in container.cfg for i.MX95. I correct it in v3 and will send it later.
Best Regards, Alice Guo

On Thu, Dec 19, 2024 at 6:57 PM Alice Guo alice.guo@oss.nxp.com wrote:
From: Ye Li ye.li@nxp.com
This patch adds i.MX95 19x19 EVK board basic support.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Peng Fan peng.fan@nxp.com
arch/arm/dts/imx95-19x19-evk-u-boot.dtsi | 224 ++++++++++++++++++++++++++ arch/arm/mach-imx/imx9/Kconfig | 6 + arch/arm/mach-imx/imx9/scmi/container.cfg | 10 ++ arch/arm/mach-imx/imx9/scmi/imximage.cfg | 15 ++ arch/arm/mach-imx/imx9/scmi/soc.c | 1 + board/freescale/imx95_evk/Kconfig | 12 ++ board/freescale/imx95_evk/MAINTAINERS | 6 + board/freescale/imx95_evk/Makefile | 11 ++ board/freescale/imx95_evk/imx95_19x19_evk.env | 95 +++++++++++ board/freescale/imx95_evk/imx95_evk.c | 54 +++++++ board/freescale/imx95_evk/spl.c | 117 ++++++++++++++ configs/imx95_19x19_evk_defconfig | 178 ++++++++++++++++++++ doc/board/nxp/imx95_evk.rst | 109 +++++++++++++ doc/board/nxp/index.rst | 1 + include/configs/imx95_evk.h | 36 +++++ 15 files changed, 875 insertions(+)
Hi Alice,
I found some issues with imx95_19x19_evk.env (see below)
<snip>
diff --git a/board/freescale/imx95_evk/imx95_19x19_evk.env b/board/freescale/imx95_evk/imx95_19x19_evk.env new file mode 100644 index 0000000000000000000000000000000000000000..27e09d3d70a068efb97d69b27089d1f213f39ee9 --- /dev/null +++ b/board/freescale/imx95_evk/imx95_19x19_evk.env @@ -0,0 +1,95 @@ +sec_boot=no +initrd_addr=0x93800000 +emmc_dev=0 +sd_dev=1 +prepare_mcore=setenv mcore_clk clk-imx95.mcore_booted
I see where mcore_clk is used but nothing uses prepare_mcore. Also there is no upstream Linux clk-imx95 driver yet so this really doesn't do anything useful. Has a clk-imx95 driver been submitted?
+scriptaddr=0x93500000 +kernel_addr_r=" __stringify(CONFIG_SYS_LOAD_ADDR) "
for a .env file you can't use stringify. Just use the config without quotes: kernel_addr_r=CONFIG_SYS_LOAD_ADDR
+image=Image +splashimage=0xA0000000 +console=ttyLP0,115200 earlycon +fdt_addr_r=0x93000000 +fdt_addr=0x93000000 +cntr_addr=0xA8000000 +cntr_file=os_cntr_signed.bin +boot_fit=no +fdtfile=" CONFIG_DEFAULT_FDT_FILE "
fdtfile=CONFIG_DEFAULT_FDT_FILE
+bootm_size=0x10000000 +mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV)"
mmcdev=CONFIG_SYS_MMC_ENV_DEV
but you should probably just eliminate this one as its set at runtime in board_late_mmc_env_init()
+mmcpart=1 +mmcroot=/dev/mmcblk1p2 rootwait rw
This is also redundant as its set at runtime in board_late_mmc_env_init()
Best Regards,
Tim

-----邮件原件----- 发件人: Tim Harvey tharvey@gateworks.com 发送时间: 2025年1月3日 7:13 收件人: Alice Guo (OSS) alice.guo@oss.nxp.com 抄送: Tom Rini trini@konsulko.com; Stefano Babic sbabic@denx.de; Fabio Estevam festevam@gmail.com; dl-uboot-imx uboot-imx@nxp.com; Lukasz Majewski lukma@denx.de; Sean Anderson seanga2@gmail.com; Simon Glass sjg@chromium.org; Alper Nebi Yasak alpernebiyasak@gmail.com; u-boot@lists.denx.de; marex@denx.de; Alice Guo alice.guo@nxp.com; Ye Li ye.li@nxp.com; Peng Fan peng.fan@nxp.com 主题: [EXT] Re: [PATCH v2 16/17] imx95_evk: add i.MX95 19x19 EVK board basic support
Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
On Thu, Dec 19, 2024 at 6:57 PM Alice Guo alice.guo@oss.nxp.com wrote:
From: Ye Li ye.li@nxp.com
This patch adds i.MX95 19x19 EVK board basic support.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com Reviewed-by: Peng Fan peng.fan@nxp.com
arch/arm/dts/imx95-19x19-evk-u-boot.dtsi | 224
++++++++++++++++++++++++++
arch/arm/mach-imx/imx9/Kconfig | 6 + arch/arm/mach-imx/imx9/scmi/container.cfg | 10 ++ arch/arm/mach-imx/imx9/scmi/imximage.cfg | 15 ++ arch/arm/mach-imx/imx9/scmi/soc.c | 1 + board/freescale/imx95_evk/Kconfig | 12 ++ board/freescale/imx95_evk/MAINTAINERS | 6 + board/freescale/imx95_evk/Makefile | 11 ++ board/freescale/imx95_evk/imx95_19x19_evk.env | 95 +++++++++++ board/freescale/imx95_evk/imx95_evk.c | 54 +++++++ board/freescale/imx95_evk/spl.c | 117 ++++++++++++++ configs/imx95_19x19_evk_defconfig | 178
++++++++++++++++++++
doc/board/nxp/imx95_evk.rst | 109 +++++++++++++ doc/board/nxp/index.rst | 1 + include/configs/imx95_evk.h | 36 +++++ 15 files changed, 875 insertions(+)
Hi Alice,
I found some issues with imx95_19x19_evk.env (see below)
<snip> > diff --git a/board/freescale/imx95_evk/imx95_19x19_evk.env > b/board/freescale/imx95_evk/imx95_19x19_evk.env > new file mode 100644 > index > 0000000000000000000000000000000000000000..27e09d3d70a068efb97d6 9b27089 > d1f213f39ee9 > --- /dev/null > +++ b/board/freescale/imx95_evk/imx95_19x19_evk.env > @@ -0,0 +1,95 @@ > +sec_boot=no > +initrd_addr=0x93800000 > +emmc_dev=0 > +sd_dev=1 > +prepare_mcore=setenv mcore_clk clk-imx95.mcore_booted
I see where mcore_clk is used but nothing uses prepare_mcore. Also there is no upstream Linux clk-imx95 driver yet so this really doesn't do anything useful. Has a clk-imx95 driver been submitted?
Hi Tim,
i.MX95 use clk-scmi.c driver, so no clk-imx95. And there is no prepare_mcore, this env needs to be dropped.
Thanks for pointing out my errors. I will correct them.
Best Regards, Alice Guo

From: Teo Hall teo.hall@nxp.com
This patch adds V2X container support on i.MX95.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Teo Hall teo.hall@nxp.com Signed-off-by: Alice Guo alice.guo@nxp.com --- arch/arm/mach-imx/image-container.c | 63 +++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 23 deletions(-)
diff --git a/arch/arm/mach-imx/image-container.c b/arch/arm/mach-imx/image-container.c index 2afe9d38a0681862098a6566a873873f24069b88..54ae7721888dbc93fdaba8e5aedc52c4506bb1c1 100644 --- a/arch/arm/mach-imx/image-container.c +++ b/arch/arm/mach-imx/image-container.c @@ -231,45 +231,62 @@ static unsigned long get_boot_device_offset(void *dev, int dev_type) return offset; }
-static int get_imageset_end(void *dev, int dev_type) +static ulong get_imageset_end(void *dev, int dev_type) { - unsigned long offset1 = 0, offset2 = 0; - int value_container[2]; + unsigned long offset[3] = {}; + int value_container[3] = {}; u16 hdr_length;
- offset1 = get_boot_device_offset(dev, dev_type); - offset2 = CONTAINER_HDR_ALIGNMENT + offset1; + offset[0] = get_boot_device_offset(dev, dev_type);
- value_container[0] = get_dev_container_size(dev, dev_type, offset1, &hdr_length); + value_container[0] = get_dev_container_size(dev, dev_type, offset[0], &hdr_length); if (value_container[0] < 0) { printf("Parse seco container failed %d\n", value_container[0]); - return value_container[0]; + return 0; }
debug("seco container size 0x%x\n", value_container[0]);
- value_container[1] = get_dev_container_size(dev, dev_type, offset2, &hdr_length); - if (value_container[1] < 0) { - debug("Parse scu container failed %d, only seco container\n", - value_container[1]); - /* return seco container total size */ - return value_container[0] + offset1; + if (is_imx95()) { + offset[1] = ALIGN(hdr_length, CONTAINER_HDR_ALIGNMENT) + offset[0]; + + value_container[1] = get_dev_container_size(dev, dev_type, offset[1], &hdr_length); + if (value_container[1] < 0) { + printf("Parse v2x container failed %d\n", value_container[1]); + return value_container[0] + offset[0]; /* return seco container total size */ + } + + debug("v2x container size 0x%x\n", value_container[1]); + + offset[2] = ALIGN(hdr_length, CONTAINER_HDR_ALIGNMENT) + offset[1]; + } else { + /* Skip offset[1] */ + offset[2] = ALIGN(hdr_length, CONTAINER_HDR_ALIGNMENT) + offset[0]; }
- debug("scu container size 0x%x\n", value_container[1]); + value_container[2] = get_dev_container_size(dev, dev_type, offset[2], &hdr_length); + if (value_container[2] < 0) { + debug("Parse scu container image failed %d, only seco container\n", value_container[2]); + if (is_imx95()) + return value_container[1] + offset[1]; /* return seco + v2x container total size */ + else + return value_container[0] + offset[0]; /* return seco container total size */ + }
- return value_container[1] + offset2; + debug("scu container size 0x%x\n", value_container[2]); + + return value_container[2] + offset[2]; }
#ifdef CONFIG_SPL_SPI_LOAD unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash) { - int end; + ulong end;
end = get_imageset_end(flash, QSPI_DEV); end = ROUND(end, SZ_1K);
- printf("Load image from QSPI 0x%x\n", end); + printf("Load image from QSPI 0x%lx\n", end);
return end; } @@ -279,12 +296,12 @@ unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash) unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long raw_sect) { - int end; + ulong end;
end = get_imageset_end(mmc, MMC_DEV); end = ROUND(end, SZ_1K);
- printf("Load image from MMC/SD 0x%x\n", end); + printf("Load image from MMC/SD 0x%lx\n", end);
return end / mmc->read_bl_len; } @@ -312,12 +329,12 @@ int spl_mmc_emmc_boot_partition(struct mmc *mmc) #ifdef CONFIG_SPL_NAND_SUPPORT uint32_t spl_nand_get_uboot_raw_page(void) { - int end; + ulong end;
end = get_imageset_end((void *)NULL, NAND_DEV); end = ROUND(end, SZ_16K);
- printf("Load image from NAND 0x%x\n", end); + printf("Load image from NAND 0x%lx\n", end);
return end; } @@ -326,7 +343,7 @@ uint32_t spl_nand_get_uboot_raw_page(void) #ifdef CONFIG_SPL_NOR_SUPPORT unsigned long spl_nor_get_uboot_base(void) { - int end; + ulong end;
/* Calculate the image set end, * if it is less than CFG_SYS_UBOOT_BASE(0x8281000), @@ -339,7 +356,7 @@ unsigned long spl_nor_get_uboot_base(void) else end = ROUND(end, SZ_1K);
- printf("Load image from NOR 0x%x\n", end); + printf("Load image from NOR 0x%lx\n", end);
return end; }
participants (6)
-
Alice Guo
-
Alice Guo (OSS)
-
Fabio Estevam
-
João Paulo Gonçalves
-
Simon Glass
-
Tim Harvey