On 9/24/26 12:24, test wrote:

i think your gitconfig might be missing something heh

From: Vandhiadevan Karunamoorthy <[email protected]>

geni_se_of_to_plat() caches need_firmware_load once at bind time by
scanning each child's FW_REVISION_RO register. qcom_geni_fw_initialise()
only ever consults that cached flag, so it cannot detect firmware that
was loaded after bind time, and a second call cannot pick up a wrapper
that still needs firmware if storage became available later in boot
(e.g. after a fastboot-triggered re-probe).

your llm context is leaking

this is barely comprehensible and I can only even guess based on your other series, which takes a specific approach to solve the specific problem where this is just a recipe for a huge mess of horrible intertwined dependencies.



Extract the scan into geni_se_needs_firmware() and re-run it inside
qcom_geni_fw_initialise() against live hardware state instead of only
trusting the cached flag, so repeated calls are safe: a call with

"live hardware state" who is this email for??

nothing left to load is a no-op that returns success.

so many wasted words


Expose qcom_geni_fw_initialise() and add the 'qcom_geni fw init'
command so a retry can be triggered manually or from other subsystems
without hardcoding SoC-specific calls into generic code.

why would we ever want this? no, if you have a specific workflow for factory flashing or something that you want to support here, then we can look at how to do that in a non-invasive way

there absolutely are issues with how this all works today, these should be fixed in DM ideally, but before that we need to drill down what the issues actually are.

NAK>
Signed-off-by: Vandhiadevan Karunamoorthy 
<[email protected]>
---
  cmd/Kconfig                    |  9 +++++++++
  cmd/Makefile                   |  1 +
  cmd/qcom_geni.c                | 26 ++++++++++++++++++++++++++
  drivers/misc/qcom_geni.c       | 24 ++++++++++++++++--------
  include/soc/qcom/qup-fw-load.h |  7 +++++++
  5 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index c71c6824a19..453ee94f6f5 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2884,6 +2884,15 @@ config CMD_SCMI
          This command provides user interfaces to several SCMI (System
          Control and Management Interface) protocols available on Arm
          platforms to manage system resources.
+
+config CMD_QCOM_GENI
+       bool "qcom_geni - Qualcomm GENI SE firmware control"
+       depends on QCOM_GENI
+       help
+         Provides the 'qcom_geni fw init' command, which (re)loads firmware
+         for Qualcomm GENI SE wrappers that still need it and probes their
+         dependent children (SPI/I2C/UART). Useful to retry firmware loading
+         once it was previously skipped.
  endmenu
menu "Filesystem commands"
diff --git a/cmd/Makefile b/cmd/Makefile
index bbbdfcc4ded..1db96718938 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -164,6 +164,7 @@ obj-$(CONFIG_CMD_KASLRSEED) += kaslrseed.o
  obj-$(CONFIG_CMD_RKMTD) += rkmtd.o
  obj-$(CONFIG_CMD_ROCKUSB) += rockusb.o
  obj-$(CONFIG_CMD_RTC) += rtc.o
+obj-$(CONFIG_CMD_QCOM_GENI) += qcom_geni.o
  obj-$(CONFIG_SANDBOX) += host.o
  obj-$(CONFIG_CMD_SATA) += sata.o
  obj-$(CONFIG_CMD_NVME) += nvme.o
diff --git a/cmd/qcom_geni.c b/cmd/qcom_geni.c
new file mode 100644
index 00000000000..31cb3f454d4
--- /dev/null
+++ b/cmd/qcom_geni.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <command.h>
+#include <linux/string.h>
+#include <soc/qcom/qup-fw-load.h>
+
+static int do_qcom_geni(struct cmd_tbl *cmdtp, int flag, int argc, char *const 
argv[])
+{
+       if (argc != 3 || strcmp(argv[1], "fw") || strcmp(argv[2], "init"))
+               return CMD_RET_USAGE;
+
+       if (qcom_geni_fw_initialise())
+               return CMD_RET_FAILURE;
+
+       return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(qcom_geni, 3, 1, do_qcom_geni,
+          "Qualcomm GENI SE firmware control",
+          "fw init\tLoad QUP firmware for GENI SE wrappers that still need it 
and\n"
+          "\t\tprobe their dependent children (SPI/I2C/UART). Safe to run 
again\n"
+          "\t\tonce firmware is already loaded.\n"
+);
diff --git a/drivers/misc/qcom_geni.c b/drivers/misc/qcom_geni.c
index 2e8f72d5c8e..41a6fd153a3 100644
--- a/drivers/misc/qcom_geni.c
+++ b/drivers/misc/qcom_geni.c
@@ -396,14 +396,11 @@ int qcom_geni_load_firmware(phys_addr_t qup_base,
   * We need to determine if firmware loading is necessary. Best way to do that 
is to check the FW
   * revision of each QUP and see if it has already been loaded.
   */
-static int geni_se_of_to_plat(struct udevice *dev)
+static bool geni_se_needs_firmware(struct udevice *dev)
  {
        ofnode child;
        struct resource res;
        u32 proto;
-       struct geni_se_plat *plat = dev_get_plat(dev);
-
-       plat->need_firmware_load = false;
dev_for_each_subnode(child, dev) {
                if (!ofnode_is_enabled(child))
@@ -417,9 +414,18 @@ static int geni_se_of_to_plat(struct udevice *dev)
                proto >>= FW_REV_PROTOCOL_SHFT;
if (proto == GENI_SE_INVALID_PROTO)
-                       plat->need_firmware_load = true;
+                       return true;
        }
+ return false;
+}
+
+static int geni_se_of_to_plat(struct udevice *dev)
+{
+       struct geni_se_plat *plat = dev_get_plat(dev);
+
+       plat->need_firmware_load = geni_se_needs_firmware(dev);
+
        return 0;
  }
@@ -496,7 +502,7 @@ static int probe_children_load_firmware(struct udevice *dev)
   * Load firmware for QCOM GENI peripherals from the dedicated partition on 
storage and bind/probe
   * all the peripheral devices that need firmware to be loaded.
   */
-static int qcom_geni_fw_initialise(void)
+int qcom_geni_fw_initialise(void)
  {
        debug("Loading firmware for QCOM GENI SE\n");
        struct udevice *geni_wrapper, *blk_dev;
@@ -506,19 +512,21 @@ static int qcom_geni_fw_initialise(void)
        size_t fw_size = MAX_FW_BUF_SIZE;
        struct geni_se_plat *plat;
- /* Find the first GENI SE wrapper that needs fw loading */
+       /* Find the first GENI SE wrapper that still needs fw loading */
        for (uclass_first_device(UCLASS_MISC, &geni_wrapper);
             geni_wrapper;
             uclass_next_device(&geni_wrapper)) {
                if (device_get_uclass_id(geni_wrapper) == UCLASS_MISC &&
                    !strcmp(geni_wrapper->driver->name, "geni-se-qup")) {
                        plat = dev_get_plat(geni_wrapper);
+                       /* Refresh against live hardware state for repeated 
calls. */
+                       plat->need_firmware_load = 
geni_se_needs_firmware(geni_wrapper);
                        if (plat->need_firmware_load)
                                break;
                }
        }
        if (!geni_wrapper) {
-               pr_err("GENI SE wrapper not found\n");
+               debug("GENI firmware is already initialized\n");
                return 0;
        }
diff --git a/include/soc/qcom/qup-fw-load.h b/include/soc/qcom/qup-fw-load.h
index a67a93c72a4..f4417fc1baf 100644
--- a/include/soc/qcom/qup-fw-load.h
+++ b/include/soc/qcom/qup-fw-load.h
@@ -175,4 +175,11 @@ struct udevice;
int qcom_geni_load_firmware(phys_addr_t qup_base, struct udevice *dev); +/*
+ * Load firmware for QCOM GENI SE wrappers that still need it and probe
+ * their dependent children. Idempotent: a call with nothing left to load
+ * is a no-op that returns success.
+ */
+int qcom_geni_fw_initialise(void);
+
  #endif /* _LINUX_QCOM_QUP_FW_LOAD */


Reply via email to