A PBL often supports multiple SoC variants, but barebox proper has no
cheap way to find out which one it's running on before the device tree
is available.

Let's add an enum soc_type, which the upcoming entry point framework
will declare per entry point and hand off to barebox proper, where
barebox_soc_type() returns it. Images not built for a particular SoC,
like barebox-dt-2nd.img, use the SOC_TYPE_GENERIC_DT/EFI pseudo types.

A PBL that only detects the SoC at runtime can still update the type
with pbl_set_soc_type() and barebox proper complains if an entry point
forgot to set it.

Assisted-by: Claude:fable-5.1
Signed-off-by: Ahmad Fatoum <[email protected]>
---
 include/pbl/handoff-data.h |  15 ++++
 include/pbl/soc-type.h     | 170 +++++++++++++++++++++++++++++++++++++
 pbl/Makefile               |   1 +
 pbl/handoff-data.c         |   2 +
 pbl/soc-type.c             |  71 ++++++++++++++++
 5 files changed, 259 insertions(+)
 create mode 100644 include/pbl/soc-type.h
 create mode 100644 pbl/soc-type.c

diff --git a/include/pbl/handoff-data.h b/include/pbl/handoff-data.h
index 81cb0880ad4a..4b9ed31ed94b 100644
--- a/include/pbl/handoff-data.h
+++ b/include/pbl/handoff-data.h
@@ -15,6 +15,7 @@ struct handoff_data {
 #define HANDOFF_DATA_ARM_MACHINE       HANDOFF_DATA_BAREBOX(3)
 #define HANDOFF_DATA_EFI               HANDOFF_DATA_BAREBOX(4)
 #define HANDOFF_DATA_TEE_DT_OVL                HANDOFF_DATA_BAREBOX(5)
+#define HANDOFF_DATA_SOC_TYPE          HANDOFF_DATA_BAREBOX(6)
 
 #define HANDOFF_DATA_BOARD(n)          (0x951726fb + (n))
 
@@ -66,4 +67,18 @@ static inline void *handoff_data_get_entry(unsigned int 
cookie, size_t *size)
 #endif
 void handoff_data_add_dt(void *fdt);
 
+#ifdef __PBL__
+/*
+ * The stage dispatch hands off the type declared in the board info. An
+ * image running on more than one SoC may still override it later.
+ */
+void pbl_set_soc_type(unsigned int type);
+unsigned int pbl_get_soc_type(void);
+void pbl_handoff_soc_type(void);
+#elif defined(CONFIG_PBL_IMAGE)
+unsigned int barebox_soc_type(void);
+#else
+static inline unsigned int barebox_soc_type(void) { return 0; }
+#endif
+
 #endif /* __PBL_HANDOFF_DATA_H */
diff --git a/include/pbl/soc-type.h b/include/pbl/soc-type.h
new file mode 100644
index 000000000000..be71cdd4338a
--- /dev/null
+++ b/include/pbl/soc-type.h
@@ -0,0 +1,170 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#if !defined(__PBL_SOC_TYPE_H) || defined(SOC_TYPE)
+#define __PBL_SOC_TYPE_H
+
+#ifndef SOC_TYPE
+#define __PBL_SOC_TYPE_ENUM
+enum soc_type {
+#define SOC_TYPE(t)    SOC_TYPE_##t,
+#endif
+
+/*
+ * List of SoCs an image can be built for. Images not built for
+ * a particular SoC declare one of the generic pseudo types instead.
+ */
+
+SOC_TYPE(UNKNOWN)
+
+/* pseudo SoC types of the generic images */
+SOC_TYPE(GENERIC_DT)
+SOC_TYPE(GENERIC_EFI)
+
+/* Allwinner */
+SOC_TYPE(SUN20I_D1)
+SOC_TYPE(SUN50I_A64)
+
+/* Altera/Intel SoCFPGA */
+SOC_TYPE(CYCLONE5)
+SOC_TYPE(ARRIA10)
+SOC_TYPE(AGILEX5)
+
+/* Arm development platforms */
+SOC_TYPE(VERSATILEPB)
+SOC_TYPE(VEXPRESS_CA9)
+SOC_TYPE(VEXPRESS_CA15)
+
+/* Broadcom */
+SOC_TYPE(BCM2835)
+SOC_TYPE(BCM2836)
+SOC_TYPE(BCM2837)
+SOC_TYPE(BCM2711)
+SOC_TYPE(BCM2712)
+SOC_TYPE(BCM47XX)
+
+/* Cirrus Logic */
+SOC_TYPE(CLPS711X)
+
+/* Ingenic */
+SOC_TYPE(JZ4755)
+SOC_TYPE(JZ4780)
+
+/* Loongson */
+SOC_TYPE(LS1B)
+
+/* Marvell */
+SOC_TYPE(ARMADA_370)
+SOC_TYPE(ARMADA_38X)
+SOC_TYPE(ARMADA_XP)
+SOC_TYPE(DOVE)
+SOC_TYPE(KIRKWOOD)
+SOC_TYPE(PXA300)
+SOC_TYPE(PXA310)
+
+/* Microchip/Atmel */
+SOC_TYPE(AT91RM9200)
+SOC_TYPE(AT91SAM9260)
+SOC_TYPE(AT91SAM9261)
+SOC_TYPE(AT91SAM9263)
+SOC_TYPE(AT91SAM9G10)
+SOC_TYPE(AT91SAM9G20)
+SOC_TYPE(AT91SAM9G45)
+SOC_TYPE(AT91SAM9N12)
+SOC_TYPE(AT91SAM9X5)
+SOC_TYPE(SAM9X60)
+SOC_TYPE(SAMA5D2)
+SOC_TYPE(SAMA5D3)
+SOC_TYPE(SAMA5D4)
+SOC_TYPE(SAMA7G5)
+
+/* MIPS Technologies */
+SOC_TYPE(MALTA)
+
+/* NVIDIA */
+SOC_TYPE(TEGRA20)
+SOC_TYPE(TEGRA30)
+SOC_TYPE(TEGRA124)
+
+/* NXP i.MX */
+SOC_TYPE(IMX1)
+SOC_TYPE(IMX21)
+SOC_TYPE(IMX23)
+SOC_TYPE(IMX25)
+SOC_TYPE(IMX27)
+SOC_TYPE(IMX28)
+SOC_TYPE(IMX31)
+SOC_TYPE(IMX35)
+SOC_TYPE(IMX50)
+SOC_TYPE(IMX51)
+SOC_TYPE(IMX53)
+SOC_TYPE(IMX6QD)
+SOC_TYPE(IMX6SDL)
+SOC_TYPE(IMX6SL)
+SOC_TYPE(IMX6SX)
+SOC_TYPE(IMX6UL)
+SOC_TYPE(IMX6ULL)
+SOC_TYPE(IMX7)
+SOC_TYPE(IMX8MM)
+SOC_TYPE(IMX8MN)
+SOC_TYPE(IMX8MP)
+SOC_TYPE(IMX8MQ)
+SOC_TYPE(IMX93)
+SOC_TYPE(VF610)
+
+/* NXP Layerscape */
+SOC_TYPE(LS1021A)
+SOC_TYPE(LS1028A)
+SOC_TYPE(LS1046A)
+
+/* Qualcomm Atheros */
+SOC_TYPE(AR231X)
+SOC_TYPE(AR9331)
+SOC_TYPE(AR9344)
+SOC_TYPE(QCA4531)
+
+/* Rockchip */
+SOC_TYPE(RK3188)
+SOC_TYPE(RK3288)
+SOC_TYPE(RK3562)
+SOC_TYPE(RK3568)
+SOC_TYPE(RK3576)
+SOC_TYPE(RK3588)
+
+/* Samsung */
+SOC_TYPE(EXYNOS8895)
+SOC_TYPE(EXYNOS990)
+
+/* SiFive */
+SOC_TYPE(FU540)
+SOC_TYPE(FU740)
+
+/* StarFive */
+SOC_TYPE(JH7100)
+
+/* STMicroelectronics */
+SOC_TYPE(STM32MP13)
+SOC_TYPE(STM32MP15)
+
+/* Texas Instruments */
+SOC_TYPE(AM33XX)
+SOC_TYPE(AM35XX)
+SOC_TYPE(AM62X)
+SOC_TYPE(AM62LX)
+SOC_TYPE(OMAP3)
+SOC_TYPE(OMAP4)
+
+/* Xilinx/AMD */
+SOC_TYPE(ZYNQ)
+SOC_TYPE(ZYNQMP)
+
+/* FPGA soft SoCs */
+SOC_TYPE(ERIZO)
+SOC_TYPE(LITEX)
+
+
+#ifdef __PBL_SOC_TYPE_ENUM
+#undef SOC_TYPE
+};
+#undef __PBL_SOC_TYPE_ENUM
+#endif
+
+#endif /* __PBL_SOC_TYPE_H */
diff --git a/pbl/Makefile b/pbl/Makefile
index 140781bfd906..5d7c9b06015d 100644
--- a/pbl/Makefile
+++ b/pbl/Makefile
@@ -13,5 +13,6 @@ pbl-$(CONFIG_LIBFDT) += fdt.o
 pbl-$(CONFIG_PBL_CONSOLE) += console.o
 obj-pbl-y += handoff-data.o
 obj-pbl-$(CONFIG_PBL_IMAGE_ELF) += layout.o
+obj-pbl-y += soc-type.o
 obj-pbl-$(CONFIG_MMU) += mmu.o
 obj-$(CONFIG_PBL_IMAGE_ELF) += barebox-proper.o
diff --git a/pbl/handoff-data.c b/pbl/handoff-data.c
index f45f4d7a78ce..3bdd36716b4e 100644
--- a/pbl/handoff-data.c
+++ b/pbl/handoff-data.c
@@ -205,6 +205,8 @@ static const char *handoff_data_entry_name(struct 
handoff_data_entry *hde)
                return "ARM machine number";
        case HANDOFF_DATA_TEE_DT_OVL:
                return "handoff TEE FDTO";
+       case HANDOFF_DATA_SOC_TYPE:
+               return "handoff SoC type";
        default:
                sprintf(name, "handoff %08x", hde->cookie);
                return name;
diff --git a/pbl/soc-type.c b/pbl/soc-type.c
new file mode 100644
index 000000000000..4b035a3cecbd
--- /dev/null
+++ b/pbl/soc-type.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <init.h>
+#include <linux/printk.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <pbl/soc-type.h>
+#include <pbl/handoff-data.h>
+
+#ifdef __PBL__
+
+static unsigned int __pbl_soc_type __section(.data);
+
+void pbl_set_soc_type(unsigned int type)
+{
+       __pbl_soc_type = type;
+}
+
+unsigned int pbl_get_soc_type(void)
+{
+       return __pbl_soc_type;
+}
+
+/*
+ * The handoff entry references the variable itself, so pbl_set_soc_type()
+ * still takes effect until the handoff data is moved out of the PBL.
+ */
+void pbl_handoff_soc_type(void)
+{
+       size_t size;
+
+       /* Firmware returning into the PBL could add the entry twice */
+       if (handoff_data_get_entry(HANDOFF_DATA_SOC_TYPE, &size))
+               return;
+
+       handoff_data_add(HANDOFF_DATA_SOC_TYPE,
+                        &__pbl_soc_type, sizeof(__pbl_soc_type));
+}
+
+#else /* barebox proper */
+
+unsigned int barebox_soc_type(void)
+{
+       unsigned int *type;
+       size_t size;
+
+       type = handoff_data_get_entry(HANDOFF_DATA_SOC_TYPE, &size);
+       if (!type)
+               return 0;
+
+       return *type;
+}
+
+/*
+ * A missing entry means an ENTRY_FUNCTION() entry point, which declares
+ * no SoC; an entry left at SOC_TYPE_UNKNOWN is a board info that forgot.
+ */
+static int soc_type_check(void)
+{
+       unsigned int *type;
+       size_t size;
+
+       type = handoff_data_get_entry(HANDOFF_DATA_SOC_TYPE, &size);
+       if (type && *type == SOC_TYPE_UNKNOWN)
+               pr_err("PBL entry point must declare SoC type\n");
+
+       return 0;
+}
+postcore_initcall(soc_type_check);
+
+#endif
-- 
2.47.3


Reply via email to