binman: Add renesas_rcar4_sa0 etype

Add new etype which generates the Renesas R-Car Gen4 SA0 header.
This header is placed at the beginning of SPI NOR and describes
where should data from SPI NOR offset 0x40000 be loaded to, and
how much data should be loaded there. In case of U-Boot, this is
used to load SPL and possibly other payload(s) into RT-VRAM.

Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
This commit is contained in:
Marek Vasut 2025-06-17 00:45:02 +02:00
parent 48ec1fd4f4
commit 583b49a0ce
5 changed files with 93 additions and 0 deletions

1
.gitignore vendored
View File

@ -75,6 +75,7 @@ fit-dtb.blob*
/keep-syms-lto.*
/*imx8mimage*
/*imx8mcst*
/*rcar4-sa0*
/drivers/video/u_boot_logo.S
/test/overlay/test-fdt-overlay.dtbo.S
/test/overlay/test-fdt-overlay-stacked.dtbo.S

View File

@ -0,0 +1,46 @@
# SPDX-License-Identifier: GPL-2.0+
# Copyright 2025 Marek Vasut <marek.vasut+renesas@mailbox.org>
#
# Entry-type module for generating the Renesas R-Car Gen4 SA0 header.
#
import os
import struct
from binman.etype.section import Entry_section
from dtoc import fdt_util
from u_boot_pylib import tools
RCAR_GEN4_SF_HEADER_SIZE = 0x40000
RCAR_GEN4_SF_MAX_LOAD_SIZE = 0xec000
class Entry_renesas_rcar4_sa0(Entry_section):
"""Renesas R-Car Gen4 SA0 generator"""
def __init__(self, section, etype, node):
super().__init__(section, etype, node)
self.required_props = ['renesas,loader-address']
def ReadNode(self):
self.loader_address = fdt_util.GetInt(self._node, 'renesas,loader-address')
super().ReadNode()
def BuildSectionData(self, required):
data = super().BuildSectionData(required)[RCAR_GEN4_SF_HEADER_SIZE:]
# Offset 0x0000 / Value 0x00000000
header = struct.pack('<I', 0)
header += tools.get_bytes(0xff, 0x3008)
# Offset 0x300c / Value 0x00000000
header += struct.pack('<I', 0)
header += tools.get_bytes(0xff, 0x144)
# Offset 0x3154 / Value (payload load address)
header += struct.pack('<I', self.loader_address)
header += tools.get_bytes(0xff, 0x10c)
# Offset 0x3264 / Value (payload size in 4-byte words, aligned to 4k)
header += struct.pack('<I', int(tools.align(len(data), 0x1000) / 4))
header += tools.get_bytes(0xff, 0x3cd98)
if len(data) > RCAR_GEN4_SF_MAX_LOAD_SIZE:
self.Raise(f'SRAM data longer than {RCAR_GEN4_SF_MAX_LOAD_SIZE} Bytes')
return header + data

View File

@ -5586,6 +5586,17 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
data = self._DoReadFile('347_bl1.dts')
self.assertEqual(ATF_BL1_DATA, data[:len(ATF_BL1_DATA)])
def testRenesasRCarGen4SA0Image(self):
"""Test that binman can produce an Renesas R-Car Gen4 SA0 image"""
self._DoTestFile('348_renesas_rcar4_sa0.dts')
def testRenesasRCarGen4SA0ImageSize(self):
"""Test that binman can not produce large Renesas R-Car Gen4 SA0 image"""
with self.assertRaises(ValueError) as exc:
self._DoTestFile('349_renesas_rcar4_sa0_size.dts')
self.assertIn("Node '/binman/renesas-rcar4-sa0': SRAM data longer than 966656 Bytes",
str(exc.exception))
def testFitFdtOper(self):
"""Check handling of a specified FIT operation"""
entry_args = {

View File

@ -0,0 +1,15 @@
// SPDX-License-Identifier: GPL-2.0+
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
renesas-rcar4-sa0 {
filename = "sa0.bin";
renesas,loader-address = <0x10>;
};
};
};

View File

@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-2.0+
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
renesas-rcar4-sa0 {
filename = "sa0.bin";
renesas,loader-address = <0x10>;
fill { /* Oversize fill to cover size check */
size = <0x140000>;
fill-byte = [ff];
};
};
};
};