* [PATCH] binman: imx8mimage: Generate FSPI header in binman instead of mkimage
@ 2026-06-10 16:17 Marek Vasut
2026-06-26 11:14 ` Quentin Schulz
2026-07-01 7:34 ` Peng Fan
0 siblings, 2 replies; 4+ messages in thread
From: Marek Vasut @ 2026-06-10 16:17 UTC (permalink / raw)
To: u-boot
Cc: Marek Vasut, NXP i.MX U-Boot Team, Fabio Estevam, Quentin Schulz,
Simon Glass, Stefano Babic, Tom Rini, Wojciech Dubowik,
Yannic Moog
Stop depending on the current mkimage method of generating the FSPI
header, instead generate the FSPI header within binman itself. This
is more flexible, as the FSPI header properties can be configured
from within the board-specific DT instead of being hard-coded in
mkimage at build time.
Signed-off-by: Marek Vasut <marex@nabladev.com>
---
Cc: "NXP i.MX U-Boot Team" <uboot-imx@nxp.com>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: Quentin Schulz <quentin.schulz@cherry.de>
Cc: Simon Glass <sjg@chromium.org>
Cc: Stefano Babic <sbabic@nabladev.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Wojciech Dubowik <Wojciech.Dubowik@mt.com>
Cc: Yannic Moog <y.moog@phytec.de>
Cc: u-boot@lists.denx.de
---
tools/binman/etype/nxp_imx8mimage.py | 93 +++++++++++++++++--
tools/binman/ftest.py | 23 ++---
tools/binman/test/vendor/nxp_imx8m_fspi.dts | 1 -
.../nxp_imx8m_fspi_fail_columnadresswidth.dts | 19 ++++
...dts => nxp_imx8m_fspi_fail_devicetype.dts} | 3 +-
.../nxp_imx8m_fspi_fail_flashpadtype.dts | 19 ++++
.../nxp_imx8m_fspi_fail_readsampleclksrc.dts | 19 ++++
.../nxp_imx8m_fspi_fail_serialclkfreq.dts | 19 ++++
.../test/vendor/nxp_imx8m_fspi_pass.dts | 1 -
9 files changed, 176 insertions(+), 21 deletions(-)
create mode 100644 tools/binman/test/vendor/nxp_imx8m_fspi_fail_columnadresswidth.dts
rename tools/binman/test/vendor/{nxp_imx8m_fspi_fail.dts => nxp_imx8m_fspi_fail_devicetype.dts} (83%)
create mode 100644 tools/binman/test/vendor/nxp_imx8m_fspi_fail_flashpadtype.dts
create mode 100644 tools/binman/test/vendor/nxp_imx8m_fspi_fail_readsampleclksrc.dts
create mode 100644 tools/binman/test/vendor/nxp_imx8m_fspi_fail_serialclkfreq.dts
diff --git a/tools/binman/etype/nxp_imx8mimage.py b/tools/binman/etype/nxp_imx8mimage.py
index 25c43438a87..47cd4481acd 100644
--- a/tools/binman/etype/nxp_imx8mimage.py
+++ b/tools/binman/etype/nxp_imx8mimage.py
@@ -8,6 +8,7 @@
#
import os
+import struct
from collections import OrderedDict
@@ -23,10 +24,25 @@ class Entry_nxp_imx8mimage(Entry_mkimage):
Properties / Entry arguments:
- nxp,boot-from - device to boot from (e.g. 'sd')
+ - nxp,fspi-columnadresswidth - FSPI column address width
+ (3 - HyperFlash, 12/13 - Serial NAND, 0 - Otherwise)
+ - nxp,fspi-controllermisc-diffclk - FSPI differential clock enable
+ - nxp,fspi-controllermisc-wordaddr - FSPI word addressable enable
+ - nxp,fspi-controllermisc-safecfg - FSPI safe configuration frequency
+ - nxp,fspi-controllermisc-padovr - FSPI pad setting override
+ - nxp,fspi-controllermisc-ddrmode - FSPI DDR mode
+ - nxp,fspi-lutcustomseq - FSPI use LUT sequence parameters
+ - nxp,fspi-devicetype - FSPI device type
+ (1 - SPI NOR, 2 - Serial NAND)
+ - nxp,fspi-flashpadtype - FSPI flash pad type
+ (1 - Single pad, 2 - Dual pads, 4 - Quad pads, 8 - Octal pads)
+ - nxp,fspi-readsampleclksrc - FSPI clock source
+ (0 - Internal loopback, 1 - loopback from DQS pad, 3 - Flash provided DQS).
+ - nxp,fspi-serialclkfreq - FSPI clock frequency
+ (1 - 30 MHz, 2 - 50 MHz, 3 - 60 MHz, 4 - 75 MHz, 5 - 80 MHz,
+ 6 - 100 MHz, 7 - 133 MHz, 8 - 166 MHz).
- nxp,loader-address - loader address (SPL text base)
- nxp,rom-version - BootROM version ('2' for i.MX8M Nano and Plus)
- - nxp,fspi-header-filename - FSPI header file name (CONFIG_FSPI_CONF_FILE).
- Used only if 'nxp,boot-from == "fspi"' .
"""
def __init__(self, section, etype, node):
@@ -37,9 +53,30 @@ class Entry_nxp_imx8mimage(Entry_mkimage):
def ReadNode(self):
super().ReadNode()
self.boot_from = fdt_util.GetString(self._node, 'nxp,boot-from')
- self.fspi_header = fdt_util.GetString(self._node, 'nxp,fspi-header-filename', 'fspi_header.bin')
+ self.fspi_columnadresswidth = fdt_util.GetInt(self._node, 'nxp,fspi-columnadresswidth', 0)
+ self.fspi_controllermisc_diffclk = fdt_util.GetBool(self._node, 'nxp,fspi-controllermisc-diffclk')
+ self.fspi_controllermisc_wordaddr = fdt_util.GetBool(self._node, 'nxp,fspi-controllermisc-wordaddr')
+ self.fspi_controllermisc_safecfg = fdt_util.GetBool(self._node, 'nxp,fspi-controllermisc-safecfg')
+ self.fspi_controllermisc_padovr = fdt_util.GetBool(self._node, 'nxp,fspi-controllermisc-padovr')
+ self.fspi_controllermisc_ddrmode = fdt_util.GetBool(self._node, 'nxp,fspi-controllermisc-ddrmode')
+ self.fspi_devicetype = fdt_util.GetInt(self._node, 'nxp,fspi-devicetype', 1)
+ self.fspi_flasha1size = fdt_util.GetInt(self._node, 'nxp,fspi-flasha1size', 0x10000000)
+ self.fspi_flashpadtype = fdt_util.GetInt(self._node, 'nxp,fspi-flashpadtype', 1)
+ self.fspi_lutcustomseq = fdt_util.GetBool(self._node, 'nxp,fspi-lutcustomseq')
+ self.fspi_readsampleclksrc = fdt_util.GetInt(self._node, 'nxp,fspi-readsampleclksrc', 0)
+ self.fspi_serialclkfreq = fdt_util.GetInt(self._node, 'nxp,fspi-serialclkfreq', 2)
self.loader_address = fdt_util.GetInt(self._node, 'nxp,loader-address')
self.rom_version = fdt_util.GetInt(self._node, 'nxp,rom-version')
+ if not self.fspi_columnadresswidth in [ 0, 3, 12, 13 ]:
+ raise ValueError('nxp,fspi-columnadresswidth can be 0, 3, 12, 13 only.')
+ if not self.fspi_devicetype in [ 1, 2 ]:
+ raise ValueError('nxp,fspi-devicetype can be 1, 2 only.')
+ if not self.fspi_flashpadtype in [ 1, 2, 4, 8 ]:
+ raise ValueError('nxp,fspi-flashpadtype can be 1, 2, 4, 8 only.')
+ if not self.fspi_readsampleclksrc in [ 0, 1, 3 ]:
+ raise ValueError('nxp,fspi-readsampleclksrc can be 0, 1, 3 only.')
+ if not self.fspi_serialclkfreq in [ 1, 2, 3, 4, 5, 6, 7, 8 ]:
+ raise ValueError('nxp,fspi-serialclkfreq can be 1..8 only.')
self.ReadEntries()
def BuildSectionData(self, required):
@@ -59,10 +96,52 @@ class Entry_nxp_imx8mimage(Entry_mkimage):
if self.mkimage.run_cmd(*args) is not None:
outdata = tools.read_file(output_fname)
if self.boot_from == 'fspi':
- spidata = tools.read_file(os.path.join(tools.get_output_dir(), self.fspi_header))
- if len(spidata) != 448:
- raise ValueError("FSPI header is not 448 Bytes long")
- spidata += tools.get_bytes(0, 0x1000 - len(spidata))
+ # 0x00 ... Tag
+ spidata = struct.pack('<I', 0x42464346)
+ # 0x04 ... Version
+ spidata += struct.pack('<I', 0x56010000)
+ # 0x08 ... Reserved
+ spidata += struct.pack('<I', 0)
+ # 0x0c ... readSampleClkSrc (LSByte at 0x0c), dataHoldTime,
+ # dataSetupTime, columnAdressWidth (MSByte at 0x0f)
+ spidata += struct.pack('<I', 0x00030300 |
+ (self.fspi_columnadresswidth << 24) |
+ self.fspi_readsampleclksrc)
+
+ # 0x10..0x3f ... Padding
+ spidata += tools.get_bytes(0, 0x30)
+
+ # 0x40 ... controllerMiscOption
+ spidata += struct.pack('<I',
+ ((1 << 0) if self.fspi_controllermisc_diffclk else 0) |
+ ((1 << 3) if self.fspi_controllermisc_wordaddr else 0) |
+ ((1 << 4) if self.fspi_controllermisc_safecfg else 0) |
+ ((1 << 5) if self.fspi_controllermisc_padovr else 0) |
+ ((1 << 6) if self.fspi_controllermisc_ddrmode else 0))
+
+ # 0x44 ... deviceType (LSByte at 0x44), sflashPadType,
+ # serialClkFreq, lutCustomSeqEnable (MSByte at 0x47)
+ spidata += struct.pack('<I',
+ ((1 << 24) if self.fspi_lutcustomseq else 0) |
+ (self.fspi_serialclkfreq << 16) |
+ (self.fspi_flashpadtype << 8) |
+ self.fspi_devicetype)
+
+ # 0x48..0x4f ... Padding
+ spidata += tools.get_bytes(0, 0x8)
+
+ # 0x50 ... flashA1Size
+ spidata += struct.pack('<I', self.fspi_flasha1size)
+
+ # 0x54..0x7f ... Padding
+ spidata += tools.get_bytes(0, 0x2c)
+
+ # 0x80 ... lookupTable
+ spidata += struct.pack('<I', 0x0818040b)
+ spidata += struct.pack('<I', 0x24043008)
+
+ # 0x88..0xfff ... Padding (end of FSPI block is 0x1bf, align to 4k)
+ spidata += tools.get_bytes(0, 0x1000 - 0xa8)
outdata = spidata + outdata
return outdata
else:
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index bf98b268ac1..03c9d42aeeb 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -8101,17 +8101,18 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
def testNxpImx8MFSPI(self):
"""Test that binman can produce an iMX8m FSPI image"""
- testdir = tempfile.mkdtemp(prefix='binman.')
-
- tools.write_file(os.path.join(testdir, 'fspi_header.bin'), tools.get_bytes(0, 448))
- with terminal.capture():
- self._DoTestFile('vendor/nxp_imx8m_fspi.dts', output_dir=testdir)
- self._DoTestFile('vendor/nxp_imx8m_fspi_pass.dts', output_dir=testdir)
-
- tools.write_file(os.path.join(testdir, 'fspi_header_fail.bin'), tools.get_bytes(0, 4097))
- with terminal.capture():
- with self.assertRaises(ValueError) as e:
- self._DoTestFile('vendor/nxp_imx8m_fspi_fail.dts', output_dir=testdir)
+ self._DoTestFile('vendor/nxp_imx8m_fspi.dts')
+ self._DoTestFile('vendor/nxp_imx8m_fspi_pass.dts')
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('vendor/nxp_imx8m_fspi_fail_columnadresswidth.dts')
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('vendor/nxp_imx8m_fspi_fail_devicetype.dts')
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('vendor/nxp_imx8m_fspi_fail_flashpadtype.dts')
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('vendor/nxp_imx8m_fspi_fail_readsampleclksrc.dts')
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('vendor/nxp_imx8m_fspi_fail_serialclkfreq.dts')
def testNxpHeaderDdrfw(self):
"""Test that binman can add a header to DDR PHY firmware images"""
diff --git a/tools/binman/test/vendor/nxp_imx8m_fspi.dts b/tools/binman/test/vendor/nxp_imx8m_fspi.dts
index ae6cc5981e6..140e9bea2e7 100644
--- a/tools/binman/test/vendor/nxp_imx8m_fspi.dts
+++ b/tools/binman/test/vendor/nxp_imx8m_fspi.dts
@@ -10,7 +10,6 @@
nxp-imx8mimage {
args; /* TODO: Needed by mkimage etype superclass */
nxp,boot-from = "fspi";
- nxp,fspi-header-filename = "fspi_header.bin";
nxp,rom-version = <1>;
nxp,loader-address = <0x10>;
};
diff --git a/tools/binman/test/vendor/nxp_imx8m_fspi_fail_columnadresswidth.dts b/tools/binman/test/vendor/nxp_imx8m_fspi_fail_columnadresswidth.dts
new file mode 100644
index 00000000000..de8bb076fc4
--- /dev/null
+++ b/tools/binman/test/vendor/nxp_imx8m_fspi_fail_columnadresswidth.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ nxp-imx8mimage {
+ args; /* TODO: Needed by mkimage etype superclass */
+ nxp,boot-from = "fspi";
+ nxp,rom-version = <2>;
+ nxp,loader-address = <0x10>;
+ /* Bogus value */
+ nxp,fspi-columnadresswidth = <1>;
+ };
+ };
+};
diff --git a/tools/binman/test/vendor/nxp_imx8m_fspi_fail.dts b/tools/binman/test/vendor/nxp_imx8m_fspi_fail_devicetype.dts
similarity index 83%
rename from tools/binman/test/vendor/nxp_imx8m_fspi_fail.dts
rename to tools/binman/test/vendor/nxp_imx8m_fspi_fail_devicetype.dts
index 5a0d758e5a3..f3b343f942f 100644
--- a/tools/binman/test/vendor/nxp_imx8m_fspi_fail.dts
+++ b/tools/binman/test/vendor/nxp_imx8m_fspi_fail_devicetype.dts
@@ -10,9 +10,10 @@
nxp-imx8mimage {
args; /* TODO: Needed by mkimage etype superclass */
nxp,boot-from = "fspi";
- nxp,fspi-header-filename = "fspi_header_fail.bin";
nxp,rom-version = <2>;
nxp,loader-address = <0x10>;
+ /* Bogus value */
+ nxp,fspi-devicetype = <3>;
};
};
};
diff --git a/tools/binman/test/vendor/nxp_imx8m_fspi_fail_flashpadtype.dts b/tools/binman/test/vendor/nxp_imx8m_fspi_fail_flashpadtype.dts
new file mode 100644
index 00000000000..515f81ba9f4
--- /dev/null
+++ b/tools/binman/test/vendor/nxp_imx8m_fspi_fail_flashpadtype.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ nxp-imx8mimage {
+ args; /* TODO: Needed by mkimage etype superclass */
+ nxp,boot-from = "fspi";
+ nxp,rom-version = <2>;
+ nxp,loader-address = <0x10>;
+ /* Bogus value */
+ nxp,fspi-flashpadtype = <9>;
+ };
+ };
+};
diff --git a/tools/binman/test/vendor/nxp_imx8m_fspi_fail_readsampleclksrc.dts b/tools/binman/test/vendor/nxp_imx8m_fspi_fail_readsampleclksrc.dts
new file mode 100644
index 00000000000..b409a6099a3
--- /dev/null
+++ b/tools/binman/test/vendor/nxp_imx8m_fspi_fail_readsampleclksrc.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ nxp-imx8mimage {
+ args; /* TODO: Needed by mkimage etype superclass */
+ nxp,boot-from = "fspi";
+ nxp,rom-version = <2>;
+ nxp,loader-address = <0x10>;
+ /* Bogus value */
+ nxp,fspi-readsampleclksrc = <2>;
+ };
+ };
+};
diff --git a/tools/binman/test/vendor/nxp_imx8m_fspi_fail_serialclkfreq.dts b/tools/binman/test/vendor/nxp_imx8m_fspi_fail_serialclkfreq.dts
new file mode 100644
index 00000000000..a71522838e8
--- /dev/null
+++ b/tools/binman/test/vendor/nxp_imx8m_fspi_fail_serialclkfreq.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ nxp-imx8mimage {
+ args; /* TODO: Needed by mkimage etype superclass */
+ nxp,boot-from = "fspi";
+ nxp,rom-version = <2>;
+ nxp,loader-address = <0x10>;
+ /* Bogus value */
+ nxp,fspi-serialclkfreq = <9>;
+ };
+ };
+};
diff --git a/tools/binman/test/vendor/nxp_imx8m_fspi_pass.dts b/tools/binman/test/vendor/nxp_imx8m_fspi_pass.dts
index 448d93d277a..1545cf6e44c 100644
--- a/tools/binman/test/vendor/nxp_imx8m_fspi_pass.dts
+++ b/tools/binman/test/vendor/nxp_imx8m_fspi_pass.dts
@@ -10,7 +10,6 @@
nxp-imx8mimage {
args; /* TODO: Needed by mkimage etype superclass */
nxp,boot-from = "fspi";
- /* Default nxp,fspi-header-filename = "fspi_header.bin"; */
nxp,rom-version = <2>;
nxp,loader-address = <0x10>;
};
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH] binman: imx8mimage: Generate FSPI header in binman instead of mkimage
2026-06-10 16:17 [PATCH] binman: imx8mimage: Generate FSPI header in binman instead of mkimage Marek Vasut
@ 2026-06-26 11:14 ` Quentin Schulz
2026-06-30 8:41 ` Marek Vasut
2026-07-01 7:34 ` Peng Fan
1 sibling, 1 reply; 4+ messages in thread
From: Quentin Schulz @ 2026-06-26 11:14 UTC (permalink / raw)
To: Marek Vasut, u-boot
Cc: NXP i.MX U-Boot Team, Fabio Estevam, Simon Glass, Stefano Babic,
Tom Rini, Wojciech Dubowik, Yannic Moog
Hi Marek,
On 6/10/26 6:17 PM, Marek Vasut wrote:
> Stop depending on the current mkimage method of generating the FSPI
> header, instead generate the FSPI header within binman itself. This
Soooooo, do we still need the mkimage version or can we remove it? I
generally would be against it since "users may make use of it" but since
you would need to rebuild (according to this commit log) it to be able
to compile what you want for your device, essentially making the host
tool dependent on the target you're building for, I guess it could be
removed? What do you think? I'm eyeing tools/imx8mimage.c and
tools/imximage.c specifically.
Which makes me ask "is this something we could do for imximage as well?"
> is more flexible, as the FSPI header properties can be configured
> from within the board-specific DT instead of being hard-coded in
> mkimage at build time.
>
> Signed-off-by: Marek Vasut <marex@nabladev.com>
> ---
> Cc: "NXP i.MX U-Boot Team" <uboot-imx@nxp.com>
> Cc: Fabio Estevam <festevam@gmail.com>
> Cc: Quentin Schulz <quentin.schulz@cherry.de>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Stefano Babic <sbabic@nabladev.com>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Wojciech Dubowik <Wojciech.Dubowik@mt.com>
> Cc: Yannic Moog <y.moog@phytec.de>
> Cc: u-boot@lists.denx.de
> ---
> tools/binman/etype/nxp_imx8mimage.py | 93 +++++++++++++++++--
> tools/binman/ftest.py | 23 ++---
> tools/binman/test/vendor/nxp_imx8m_fspi.dts | 1 -
> .../nxp_imx8m_fspi_fail_columnadresswidth.dts | 19 ++++
> ...dts => nxp_imx8m_fspi_fail_devicetype.dts} | 3 +-
> .../nxp_imx8m_fspi_fail_flashpadtype.dts | 19 ++++
> .../nxp_imx8m_fspi_fail_readsampleclksrc.dts | 19 ++++
> .../nxp_imx8m_fspi_fail_serialclkfreq.dts | 19 ++++
> .../test/vendor/nxp_imx8m_fspi_pass.dts | 1 -
> 9 files changed, 176 insertions(+), 21 deletions(-)
> create mode 100644 tools/binman/test/vendor/nxp_imx8m_fspi_fail_columnadresswidth.dts
> rename tools/binman/test/vendor/{nxp_imx8m_fspi_fail.dts => nxp_imx8m_fspi_fail_devicetype.dts} (83%)
> create mode 100644 tools/binman/test/vendor/nxp_imx8m_fspi_fail_flashpadtype.dts
> create mode 100644 tools/binman/test/vendor/nxp_imx8m_fspi_fail_readsampleclksrc.dts
> create mode 100644 tools/binman/test/vendor/nxp_imx8m_fspi_fail_serialclkfreq.dts
>
> diff --git a/tools/binman/etype/nxp_imx8mimage.py b/tools/binman/etype/nxp_imx8mimage.py
> index 25c43438a87..47cd4481acd 100644
> --- a/tools/binman/etype/nxp_imx8mimage.py
> +++ b/tools/binman/etype/nxp_imx8mimage.py
> @@ -8,6 +8,7 @@
> #
>
> import os
You remove the only user of this module later in the diff, so this can
be removed as well.
> +import struct
>
> from collections import OrderedDict
>
> @@ -23,10 +24,25 @@ class Entry_nxp_imx8mimage(Entry_mkimage):
>
> Properties / Entry arguments:
> - nxp,boot-from - device to boot from (e.g. 'sd')
> + - nxp,fspi-columnadresswidth - FSPI column address width
> + (3 - HyperFlash, 12/13 - Serial NAND, 0 - Otherwise)
> + - nxp,fspi-controllermisc-diffclk - FSPI differential clock enable
> + - nxp,fspi-controllermisc-wordaddr - FSPI word addressable enable
> + - nxp,fspi-controllermisc-safecfg - FSPI safe configuration frequency
> + - nxp,fspi-controllermisc-padovr - FSPI pad setting override
> + - nxp,fspi-controllermisc-ddrmode - FSPI DDR mode
> + - nxp,fspi-lutcustomseq - FSPI use LUT sequence parameters
> + - nxp,fspi-devicetype - FSPI device type
> + (1 - SPI NOR, 2 - Serial NAND)
> + - nxp,fspi-flashpadtype - FSPI flash pad type
> + (1 - Single pad, 2 - Dual pads, 4 - Quad pads, 8 - Octal pads)
> + - nxp,fspi-readsampleclksrc - FSPI clock source
> + (0 - Internal loopback, 1 - loopback from DQS pad, 3 - Flash provided DQS).
> + - nxp,fspi-serialclkfreq - FSPI clock frequency
> + (1 - 30 MHz, 2 - 50 MHz, 3 - 60 MHz, 4 - 75 MHz, 5 - 80 MHz,
> + 6 - 100 MHz, 7 - 133 MHz, 8 - 166 MHz).
OK, so... I have not played with i.MX8M but I would be absolutely
clueless on how to configure this. Is there some literature, readme,
docs we could point at?
Please also mention that all nxp,fspi-* arguments are only available if
nxp,boot-from == "fspi".
Please document which is the default if the argument is omitted.
Finally, I don't think it makes sense to tell the user "say 1 if you
want 30MHz, 2 for 50MHz", why can't the user specify the frequency
directly and we do the job for them of translating it to something to
put in the binary? (same remark for all arguments).
> - nxp,loader-address - loader address (SPL text base)
> - nxp,rom-version - BootROM version ('2' for i.MX8M Nano and Plus)
> - - nxp,fspi-header-filename - FSPI header file name (CONFIG_FSPI_CONF_FILE).
> - Used only if 'nxp,boot-from == "fspi"' .
> """
>
> def __init__(self, section, etype, node):
> @@ -37,9 +53,30 @@ class Entry_nxp_imx8mimage(Entry_mkimage):
> def ReadNode(self):
> super().ReadNode()
> self.boot_from = fdt_util.GetString(self._node, 'nxp,boot-from')
> - self.fspi_header = fdt_util.GetString(self._node, 'nxp,fspi-header-filename', 'fspi_header.bin')
> + self.fspi_columnadresswidth = fdt_util.GetInt(self._node, 'nxp,fspi-columnadresswidth', 0)
> + self.fspi_controllermisc_diffclk = fdt_util.GetBool(self._node, 'nxp,fspi-controllermisc-diffclk')
> + self.fspi_controllermisc_wordaddr = fdt_util.GetBool(self._node, 'nxp,fspi-controllermisc-wordaddr')
> + self.fspi_controllermisc_safecfg = fdt_util.GetBool(self._node, 'nxp,fspi-controllermisc-safecfg')
> + self.fspi_controllermisc_padovr = fdt_util.GetBool(self._node, 'nxp,fspi-controllermisc-padovr')
> + self.fspi_controllermisc_ddrmode = fdt_util.GetBool(self._node, 'nxp,fspi-controllermisc-ddrmode')
> + self.fspi_devicetype = fdt_util.GetInt(self._node, 'nxp,fspi-devicetype', 1)
> + self.fspi_flasha1size = fdt_util.GetInt(self._node, 'nxp,fspi-flasha1size', 0x10000000)
> + self.fspi_flashpadtype = fdt_util.GetInt(self._node, 'nxp,fspi-flashpadtype', 1)
> + self.fspi_lutcustomseq = fdt_util.GetBool(self._node, 'nxp,fspi-lutcustomseq')
> + self.fspi_readsampleclksrc = fdt_util.GetInt(self._node, 'nxp,fspi-readsampleclksrc', 0)
> + self.fspi_serialclkfreq = fdt_util.GetInt(self._node, 'nxp,fspi-serialclkfreq', 2)
> self.loader_address = fdt_util.GetInt(self._node, 'nxp,loader-address')
> self.rom_version = fdt_util.GetInt(self._node, 'nxp,rom-version')
> + if not self.fspi_columnadresswidth in [ 0, 3, 12, 13 ]:
> + raise ValueError('nxp,fspi-columnadresswidth can be 0, 3, 12, 13 only.')
> + if not self.fspi_devicetype in [ 1, 2 ]:
> + raise ValueError('nxp,fspi-devicetype can be 1, 2 only.')
> + if not self.fspi_flashpadtype in [ 1, 2, 4, 8 ]:
> + raise ValueError('nxp,fspi-flashpadtype can be 1, 2, 4, 8 only.')
> + if not self.fspi_readsampleclksrc in [ 0, 1, 3 ]:
> + raise ValueError('nxp,fspi-readsampleclksrc can be 0, 1, 3 only.')
> + if not self.fspi_serialclkfreq in [ 1, 2, 3, 4, 5, 6, 7, 8 ]:
> + raise ValueError('nxp,fspi-serialclkfreq can be 1..8 only.')
> self.ReadEntries()
>
> def BuildSectionData(self, required):
> @@ -59,10 +96,52 @@ class Entry_nxp_imx8mimage(Entry_mkimage):
> if self.mkimage.run_cmd(*args) is not None:
> outdata = tools.read_file(output_fname)
> if self.boot_from == 'fspi':
> - spidata = tools.read_file(os.path.join(tools.get_output_dir(), self.fspi_header))
> - if len(spidata) != 448:
> - raise ValueError("FSPI header is not 448 Bytes long")
> - spidata += tools.get_bytes(0, 0x1000 - len(spidata))
> + # 0x00 ... Tag
> + spidata = struct.pack('<I', 0x42464346)
> + # 0x04 ... Version
> + spidata += struct.pack('<I', 0x56010000)
> + # 0x08 ... Reserved
> + spidata += struct.pack('<I', 0)
> + # 0x0c ... readSampleClkSrc (LSByte at 0x0c), dataHoldTime,
> + # dataSetupTime, columnAdressWidth (MSByte at 0x0f)
> + spidata += struct.pack('<I', 0x00030300 |
> + (self.fspi_columnadresswidth << 24) |
> + self.fspi_readsampleclksrc)
> +
> + # 0x10..0x3f ... Padding
> + spidata += tools.get_bytes(0, 0x30)
> +
> + # 0x40 ... controllerMiscOption
> + spidata += struct.pack('<I',
> + ((1 << 0) if self.fspi_controllermisc_diffclk else 0) |
> + ((1 << 3) if self.fspi_controllermisc_wordaddr else 0) |
> + ((1 << 4) if self.fspi_controllermisc_safecfg else 0) |
> + ((1 << 5) if self.fspi_controllermisc_padovr else 0) |
> + ((1 << 6) if self.fspi_controllermisc_ddrmode else 0))
> +
> + # 0x44 ... deviceType (LSByte at 0x44), sflashPadType,
> + # serialClkFreq, lutCustomSeqEnable (MSByte at 0x47)
> + spidata += struct.pack('<I',
> + ((1 << 24) if self.fspi_lutcustomseq else 0) |
> + (self.fspi_serialclkfreq << 16) |
> + (self.fspi_flashpadtype << 8) |
> + self.fspi_devicetype)
> +
> + # 0x48..0x4f ... Padding
> + spidata += tools.get_bytes(0, 0x8)
> +
> + # 0x50 ... flashA1Size
> + spidata += struct.pack('<I', self.fspi_flasha1size)
> +
> + # 0x54..0x7f ... Padding
> + spidata += tools.get_bytes(0, 0x2c)
> +
> + # 0x80 ... lookupTable
> + spidata += struct.pack('<I', 0x0818040b)
> + spidata += struct.pack('<I', 0x24043008)
> +
> + # 0x88..0xfff ... Padding (end of FSPI block is 0x1bf, align to 4k)
> + spidata += tools.get_bytes(0, 0x1000 - 0xa8)
I'll let people with an i.MX8M review the implementation but I do have
some feedback to provide on the logic. This essentially removes the
ability to use an externally-provided fspi_header.bin. So you should fix
in the same commit arch/arm/dts/imx8mm-u-boot.dtsi and
arch/arm/dts/imx8mn-u-boot.dtsi to migrate them to the new mechanism...
Which likely means going through all board defconfigs and figuring out
which values they use for compiling the mkimage that is used to generate
this file and then put it in a board-specific -u-boot.dtsi. The other
issue is downstream which will now be forced to migrate to it. I guess
it could be fine but another option could be "specify the binary file to
use or all those arguments instead" and keep current logic and simply
extend it to support the new arguments. Otherwise, maybe checking the
argument exists in the DTB and fail hard and tell the user to migrate to
the new format with multiple arguments (what happens if we remove
support for nxp,fspi-header-filename but it's still present in the DTS
and the user hasn't migrated to the new arguments? does it fail the
build or silently build something that they cannot boot?).
Cheers,
Quentin
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] binman: imx8mimage: Generate FSPI header in binman instead of mkimage
2026-06-26 11:14 ` Quentin Schulz
@ 2026-06-30 8:41 ` Marek Vasut
0 siblings, 0 replies; 4+ messages in thread
From: Marek Vasut @ 2026-06-30 8:41 UTC (permalink / raw)
To: Quentin Schulz, u-boot
Cc: NXP i.MX U-Boot Team, Fabio Estevam, Simon Glass, Stefano Babic,
Tom Rini, Wojciech Dubowik, Yannic Moog
On 6/26/26 1:14 PM, Quentin Schulz wrote:
Hello Quentin,
> On 6/10/26 6:17 PM, Marek Vasut wrote:
>> Stop depending on the current mkimage method of generating the FSPI
>> header, instead generate the FSPI header within binman itself. This
>
> Soooooo, do we still need the mkimage version or can we remove it?
I believe it is part of ABI, so we cannot remove it.
> I
> generally would be against it since "users may make use of it" but since
> you would need to rebuild (according to this commit log) it to be able
> to compile what you want for your device, essentially making the host
> tool dependent on the target you're building for, I guess it could be
> removed? What do you think? I'm eyeing tools/imx8mimage.c and tools/
> imximage.c specifically.
Whatever the tool generates right now is a generic SPI NOR boot header,
for all configurations that are in the tree that use this header. I
think we should keep this, but only to retain backward compatibility and
not break users who might depend on it.
> Which makes me ask "is this something we could do for imximage as well?"
What does "this" refer to -- drop something, or, add some header
support, or something else entirely ?
[...]
>> +++ b/tools/binman/etype/nxp_imx8mimage.py
>> @@ -8,6 +8,7 @@
>> #
>> import os
>
> You remove the only user of this module later in the diff, so this can
> be removed as well.
Fixed in V2, thanks.
>> +import struct
>> from collections import OrderedDict
>> @@ -23,10 +24,25 @@ class Entry_nxp_imx8mimage(Entry_mkimage):
>> Properties / Entry arguments:
>> - nxp,boot-from - device to boot from (e.g. 'sd')
>> + - nxp,fspi-columnadresswidth - FSPI column address width
>> + (3 - HyperFlash, 12/13 - Serial NAND, 0 - Otherwise)
>> + - nxp,fspi-controllermisc-diffclk - FSPI differential clock
>> enable
>> + - nxp,fspi-controllermisc-wordaddr - FSPI word addressable
>> enable
>> + - nxp,fspi-controllermisc-safecfg - FSPI safe configuration
>> frequency
>> + - nxp,fspi-controllermisc-padovr - FSPI pad setting override
>> + - nxp,fspi-controllermisc-ddrmode - FSPI DDR mode
>> + - nxp,fspi-lutcustomseq - FSPI use LUT sequence parameters
>> + - nxp,fspi-devicetype - FSPI device type
>> + (1 - SPI NOR, 2 - Serial NAND)
>> + - nxp,fspi-flashpadtype - FSPI flash pad type
>> + (1 - Single pad, 2 - Dual pads, 4 - Quad pads, 8 - Octal
>> pads)
>> + - nxp,fspi-readsampleclksrc - FSPI clock source
>> + (0 - Internal loopback, 1 - loopback from DQS pad, 3 -
>> Flash provided DQS).
>> + - nxp,fspi-serialclkfreq - FSPI clock frequency
>> + (1 - 30 MHz, 2 - 50 MHz, 3 - 60 MHz, 4 - 75 MHz, 5 - 80 MHz,
>> + 6 - 100 MHz, 7 - 133 MHz, 8 - 166 MHz).
>
> OK, so... I have not played with i.MX8M but I would be absolutely
> clueless on how to configure this. Is there some literature, readme,
> docs we could point at?
Yes, there is the SoC datasheet if you ever need to change the defaults
(I haven't done that yet).
> Please also mention that all nxp,fspi-* arguments are only available if
> nxp,boot-from == "fspi".
Fixed in V2, thanks.
> Please document which is the default if the argument is omitted.
Fixed in V2, thanks.
> Finally, I don't think it makes sense to tell the user "say 1 if you
> want 30MHz, 2 for 50MHz", why can't the user specify the frequency
> directly and we do the job for them of translating it to something to
> put in the binary? (same remark for all arguments).
Does a big switch-case bring up any improvement in this case ?
>> + # 0x88..0xfff ... Padding (end of FSPI block is
>> 0x1bf, align to 4k)
>> + spidata += tools.get_bytes(0, 0x1000 - 0xa8)
>
> I'll let people with an i.MX8M review the implementation but I do have
> some feedback to provide on the logic. This essentially removes the
> ability to use an externally-provided fspi_header.bin. So you should fix
> in the same commit arch/arm/dts/imx8mm-u-boot.dtsi and arch/arm/dts/
> imx8mn-u-boot.dtsi to migrate them to the new mechanism...
Not in the same commit, but the fspi-header.bin references should be
dropped eventually.
> Which likely
> means going through all board defconfigs and figuring out which values
> they use for compiling the mkimage that is used to generate this file
> and then put it in a board-specific -u-boot.dtsi.
They all use the same values, the default values that are also used in
this implementation.
> The other issue is
> downstream which will now be forced to migrate to it. I guess it could
> be fine but another option could be "specify the binary file to use or
> all those arguments instead" and keep current logic and simply extend it
> to support the new arguments.
Let's not make this more complicated than it already is, and let's ditch
the old fspi-header.bin mechanism entirely. Note that the
fspi-header.bin handling was broken for some 2 years now, so I don't
think anyone depends on it.
> Otherwise, maybe checking the argument
> exists in the DTB and fail hard and tell the user to migrate to the new
> format with multiple arguments (what happens if we remove support for
> nxp,fspi-header-filename but it's still present in the DTS and the user
> hasn't migrated to the new arguments? does it fail the build or silently
> build something that they cannot boot?).
It generates the header using default values, which seems to be used by
most users anyway.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] binman: imx8mimage: Generate FSPI header in binman instead of mkimage
2026-06-10 16:17 [PATCH] binman: imx8mimage: Generate FSPI header in binman instead of mkimage Marek Vasut
2026-06-26 11:14 ` Quentin Schulz
@ 2026-07-01 7:34 ` Peng Fan
1 sibling, 0 replies; 4+ messages in thread
From: Peng Fan @ 2026-07-01 7:34 UTC (permalink / raw)
To: Marek Vasut
Cc: u-boot, NXP i.MX U-Boot Team, Fabio Estevam, Quentin Schulz,
Simon Glass, Stefano Babic, Tom Rini, Wojciech Dubowik,
Yannic Moog
On Wed, Jun 10, 2026 at 06:17:03PM +0200, Marek Vasut wrote:
>Stop depending on the current mkimage method of generating the FSPI
>header, instead generate the FSPI header within binman itself. This
>is more flexible, as the FSPI header properties can be configured
>from within the board-specific DT instead of being hard-coded in
>mkimage at build time.
>
>Signed-off-by: Marek Vasut <marex@nabladev.com>
Acked-by: Peng Fan <peng.fan@nxp.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-01 7:31 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-10 16:17 [PATCH] binman: imx8mimage: Generate FSPI header in binman instead of mkimage Marek Vasut
2026-06-26 11:14 ` Quentin Schulz
2026-06-30 8:41 ` Marek Vasut
2026-07-01 7:34 ` Peng Fan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox