On Tue, 2026-08-18 at 08:48 -0400, Nathan Whitehorn wrote: > EXTERNAL EMAIL: Do not click links or open attachments unless you > know the content is safe > > When working with systems with multiple FPGA firmwares, it is > sometimes > useful to be able to use the same U-Boot and script conditional > behavior > based on the FPGA firmware ID and version number. This, allows, for > example, flashing new FPGA images without flashing the bootloader and > letting U-Boot and the Linux kernel adapt appropriately. > > This does two things with the information: > 1. Prints the FPGA design ID and version to the console as part of U- > Boot > startup, which is helpful to a human working with the board. > 2. Stores the same information, plus the already-acquired FPGA serial > number, in a new set of environment variables (serial_number, > design_id, design_ver [the version], and design_backlevel > [minimum-version backlevel]). These can be used in a U-Boot script > to > load different kernels, device trees, etc. depending on the > currently > installed firmware, which allows U-Boot and the kernel to adapt > cleanly to FPGA firmware updates that change accessible > peripherals > etc. > > Signed-off-by: Nathan Whitehorn <[email protected]> > --- > Changes for v2: > - Rename environment variables to remove the pf_ prefix > - Remove portions of the patch that added properties to the device > tree > - Style changes > - Rebase after a5f93037f28624c612288e2d97604d73e03af5a3 > > Thanks to Conor Dooley and Tim Ouyang for helpful suggestions. > > board/microchip/mpfs_generic/mpfs_generic.c | 26 ++++++++++ > drivers/misc/mpfs_syscontroller.c | 54 > +++++++++++++++++++++ > include/mpfs-mailbox.h | 2 + > 3 files changed, 82 insertions(+) > Hi Nathan,
Happy with the patch other than Conor's styling suggestions and one NIK of my own seen below.. Other than those: Acked-by: Jamie Gibbons <[email protected]> Thanks for the patch. > diff --git a/board/microchip/mpfs_generic/mpfs_generic.c > b/board/microchip/mpfs_generic/mpfs_generic.c > index f57f5f4046b..4423dd1e38c 100644 > --- a/board/microchip/mpfs_generic/mpfs_generic.c > +++ b/board/microchip/mpfs_generic/mpfs_generic.c > @@ -114,7 +114,10 @@ int board_late_init(void) > { > u32 ret; > int node; > + int idx; > u8 device_serial_number[16] = {0}; > + char serialstring[33], designid[33]; > + u16 designver, designbacklevel; > void *blob = (void *)gd->fdt_blob; > struct udevice *dev; > struct mpfs_sys_serv *sys_serv_priv; > @@ -144,6 +147,29 @@ int board_late_init(void) > return -EINVAL; > } > > + /* Store design info and serial number in environment */ > + memset(designid, 0, sizeof(designid)); > + memset(serialstring, 0, sizeof(serialstring)); > + > + ret = mpfs_syscontroller_read_design_info(sys_serv_priv, > designid, > + &designver, &designbacklevel); > + if (ret) { > + printf("Cannot read device design information\n"); > + return -EINVAL; > + } > + for (idx = 0; idx < 16; idx++) > + sprintf(&serialstring[2*idx], "%02x", > device_serial_number[idx]); > + > + env_set("serial_number", serialstring); > + env_set("design_id", designid); > + env_set_ulong("design_ver", designver); > + env_set_ulong("design_backlevel", designbacklevel); > + > + printf("FPGA Design name: %s\n", designid); > + printf("FPGA Serial: %s\n", serialstring); > + printf("Design version number %d (backlevel %d)\n", > designver, > + designbacklevel); > + > /* Update MAC address with device serial number */ > mac_addr[0] = 0x00; > mac_addr[1] = 0x04; > diff --git a/drivers/misc/mpfs_syscontroller.c > b/drivers/misc/mpfs_syscontroller.c > index b9aea7e1181..07a788db76e 100644 > --- a/drivers/misc/mpfs_syscontroller.c > +++ b/drivers/misc/mpfs_syscontroller.c > @@ -152,6 +152,60 @@ int mpfs_syscontroller_read_sernum(struct > mpfs_sys_serv *sys_serv_priv, u8 *devi > } > EXPORT_SYMBOL(mpfs_syscontroller_read_sernum); > > +/** > + * mpfs_syscontroller_read_design_info() - Use system service to > read FPGA design info > + * @sys_serv_priv: system service private data > + * @designid: 30-byte string name of top module in FPGA > logic design > + * NB: null termination is not guaranteed > + * @designver: version number of the FPGA design > + * @backlevel: programmed minimum allowed FPGA design > version > + * > + * Return: 0 if all went ok, else return appropriate error > + */ > +int mpfs_syscontroller_read_design_info(struct mpfs_sys_serv > *sys_serv_priv, > + u8 *designid, u16 *designver, u16 *backlevel) > +{ > + unsigned long timeoutsecs = 300; > + u8 data[36]; > + int ret; > + > + struct mpfs_mss_response response = { > + .resp_status = 0U, > + .resp_msg = (u32 *)data, > + .resp_size = sizeof(data)}; > + struct mpfs_mss_msg msg = { > + .cmd_opcode = 2, Could you put this as a define at the top of the file with the others instead of having it hardcoded here please. Thanks, Jamie. > + .cmd_data_size = CMD_DATA_SIZE, > + .response = &response, > + .cmd_data = CMD_DATA, > + .mbox_offset = MBOX_OFFSET, > + .resp_offset = RESP_OFFSET}; > + > + ret = mpfs_syscontroller_run_service(sys_serv_priv- > >sys_controller, &msg); > + if (ret) { > + dev_err(sys_serv_priv->sys_controller->chan.dev, > "Service failed: %d, abort\n", ret); > + return ret; > + } > + > + /* Receive the response */ > + ret = mpfs_syscontroller_recv_response(sys_serv_priv- > >sys_controller, &msg, timeoutsecs); > + if (ret) > + return ret; > + > + debug("%s: Read successful %s\n", > + __func__, sys_serv_priv->sys_controller->chan.dev- > >name); > + > + if (designid != NULL) > + memcpy(designid, &data[2], 30); > + if (designver != NULL) > + memcpy(designver, &data[32], 2); > + if (backlevel != NULL) > + memcpy(backlevel, &data[34], 2); > + > + return 0; > +} > +EXPORT_SYMBOL(mpfs_syscontroller_read_design_info); > + > static u16 mpfs_syscontroller_service_spi_copy(struct mpfs_sys_serv > *sys_serv_priv, u64 dst_addr, u32 src_addr, u32 length) > { > int ret; >
