arm64: renesas: Add R-Car S4 Starter Kit support
Add support for the R-Car S4 Starter Kit with R8A779F4 SoC support.
This implementation natively uses OF_UPSTREAM to pull in most recent
DT. The defconfig is derived from S4 Spider, with reduced UART baud
rate to 921600 Bdps. The DT alias to rswitch is removed as the alias
should point to rswitch ports, not to rswitch itself, see [1].
[1] https://lore.kernel.org/linux-arm-kernel/20250118111344.361617-5-marek.vasut+renesas@mailbox.org/
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
diff --git a/board/renesas/s4sk/s4sk.c b/board/renesas/s4sk/s4sk.c
new file mode 100644
index 0000000..d2beb71
--- /dev/null
+++ b/board/renesas/s4sk/s4sk.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2025 Marek Vasut <marek.vasut+renesas@mailbox.org>
+ */
+
+#include <dm.h>
+#include <i2c.h>
+#include <malloc.h>
+#include <net-common.h>
+
+#define S4SK_FPGA_I2C_BUS "i2c5"
+#define S4SK_FPGA_I2C_DEV_ADDR 0x70
+#define S4SK_FPGA_I2C_DEV_WIDTH 2
+#define S4SK_FPGA_I2C_MAC_COUNT 4
+#define S4SK_FPGA_I2C_MAC_OFFSET 0x58
+#define S4SK_FPGA_I2C_MAC_WIDTH 8
+
+int board_late_init(void)
+{
+ /*
+ * Extract AVB and TSN0,1,2 MAC addresses from FPGA via I2C.
+ *
+ * In case a matching ethaddr/ethNaddr environment variable
+ * is not set, set it, otherwise do not override it. This
+ * allows users to set their own MAC addresses via ethaddr
+ * and ethNaddr environment variables.
+ *
+ * The ethaddr/ethNaddr mapping follows Linux kernel DT aliases
+ * ethernetN property assignment:
+ * - ethaddr ..... TSN0 (IC104 connector)
+ * - eth1addr .... TSN1 (IC101 connector)
+ * - eth2addr .... TSN2 (Expansion connector)
+ * - eth3addr .... AVB (CN1 connector)
+ */
+ ofnode i2c_node = ofnode_path(S4SK_FPGA_I2C_BUS);
+ struct udevice *bus, *dev;
+ unsigned char enetaddr[6];
+ unsigned char macs[32]; /* Four MAC addresses in FPGA in total. */
+ int i, idx, j, ret;
+
+ ret = uclass_get_device_by_ofnode(UCLASS_I2C, i2c_node, &bus);
+ if (ret < 0) {
+ printf("s4sk: cannot find i2c bus (%d)\n", ret);
+ return 0;
+ }
+
+ ret = i2c_get_chip(bus, S4SK_FPGA_I2C_DEV_ADDR,
+ S4SK_FPGA_I2C_DEV_WIDTH, &dev);
+ if (ret < 0) {
+ printf("s4sk: cannot find i2c chip (%d)\n", ret);
+ return 0;
+ }
+
+ ret = dm_i2c_read(dev, S4SK_FPGA_I2C_MAC_OFFSET, macs, sizeof(macs));
+ if (ret < 0) {
+ printf("s4sk: failed to read MAC addresses via i2c (%d)\n", ret);
+ return 0;
+ }
+
+ for (i = 0; i < S4SK_FPGA_I2C_MAC_COUNT; i++) {
+ /*
+ * Remap TSN0,1,2 to ethaddr,eth1addr,eth2addr and
+ * AVB to eth3addr to match Linux /aliases ethernetN
+ * assignment, which starts with ethernet0 for TSN.
+ */
+ idx = (i + 3) % 4;
+ ret = eth_env_get_enetaddr_by_index("eth", idx, enetaddr);
+ if (ret) /* ethaddr is already set */
+ continue;
+
+ /* Byte-wise reverse the MAC address */
+ for (j = 0; j < sizeof(enetaddr); j++)
+ enetaddr[j] = macs[i * S4SK_FPGA_I2C_MAC_WIDTH + (5 - j)];
+
+ if (!is_valid_ethaddr(enetaddr)) {
+ printf("s4sk: MAC address %d in FPGA not valid (%pM)\n",
+ i, enetaddr);
+ continue;
+ }
+
+ eth_env_set_enetaddr_by_index("eth", idx, enetaddr);
+ }
+
+ return 0;
+}