--- /dev/null
+From 652a86b24c5ac444afaf7625c9340d55aab7f105 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Fri, 31 Oct 2025 14:08:32 +0100
+Subject: [PATCH 1/2] err.h: add INIT_ERR_PTR() macro
+
+Add INIT_ERR_PTR() macro to initialize static variables with error
+pointers. This might be useful for specific case where there is a static
+variable initialized to an error condition and then later set to the
+real handle once probe finish/completes.
+
+This is to handle compilation problems like:
+
+error: initializer element is not constant
+
+where ERR_PTR() can't be used.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20251031130835.7953-2-ansuelsmth@gmail.com
+[bjorn: Added () suffix on macro references]
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+---
+ include/linux/err.h | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/include/linux/err.h
++++ b/include/linux/err.h
+@@ -41,6 +41,14 @@ static inline void * __must_check ERR_PT
+ return (void *) error;
+ }
+
++/**
++ * INIT_ERR_PTR - Init a const error pointer.
++ * @error: A negative error code.
++ *
++ * Like ERR_PTR(), but usable to initialize static variables.
++ */
++#define INIT_ERR_PTR(error) ((void *)(error))
++
+ /* Return the pointer in the percpu address space. */
+ #define ERR_PTR_PCPU(error) ((void __percpu *)(unsigned long)ERR_PTR(error))
+
--- /dev/null
+From 7a94d5f31b549e18f908cb669c59f066f45a21c7 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Fri, 31 Oct 2025 14:08:33 +0100
+Subject: [PATCH 2/2] soc: qcom: smem: better track SMEM uninitialized state
+
+There is currently a problem where, in the specific case of SMEM not
+initialized by SBL, any SMEM API wrongly returns PROBE_DEFER
+communicating wrong info to any user of this API.
+
+A better way to handle this would be to track the SMEM state and return
+a different kind of error than PROBE_DEFER.
+
+Rework the __smem handle to always init it to the error pointer
+-EPROBE_DEFER following what is already done by the SMEM API.
+If we detect that the SBL didn't initialized SMEM, set the __smem handle
+to the error pointer -ENODEV.
+Also rework the SMEM API to handle the __smem handle to be an error
+pointer and return it appropriately.
+
+This way user of the API can react and return a proper error or use
+fallback way for the failing API.
+
+While at it, change the return error when SMEM is not initialized by SBL
+also to -ENODEV to make it consistent with the __smem handle and use
+dev_err_probe() helper to return the message.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Link: https://lore.kernel.org/r/20251031130835.7953-3-ansuelsmth@gmail.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+---
+ drivers/soc/qcom/smem.c | 26 +++++++++++++++-----------
+ 1 file changed, 15 insertions(+), 11 deletions(-)
+
+--- a/drivers/soc/qcom/smem.c
++++ b/drivers/soc/qcom/smem.c
+@@ -353,8 +353,12 @@ static void *cached_entry_to_item(struct
+ return p - le32_to_cpu(e->size);
+ }
+
+-/* Pointer to the one and only smem handle */
+-static struct qcom_smem *__smem;
++/*
++ * Pointer to the one and only smem handle.
++ * Init to -EPROBE_DEFER to signal SMEM still has to be probed.
++ * Can be set to -ENODEV if SMEM is not initialized by SBL.
++ */
++static struct qcom_smem *__smem = INIT_ERR_PTR(-EPROBE_DEFER);
+
+ /* Timeout (ms) for the trylock of remote spinlocks */
+ #define HWSPINLOCK_TIMEOUT 1000
+@@ -506,8 +510,8 @@ int qcom_smem_alloc(unsigned host, unsig
+ unsigned long flags;
+ int ret;
+
+- if (!__smem)
+- return -EPROBE_DEFER;
++ if (IS_ERR(__smem))
++ return PTR_ERR(__smem);
+
+ if (item < SMEM_ITEM_LAST_FIXED) {
+ dev_err(__smem->dev,
+@@ -681,10 +685,10 @@ invalid_canary:
+ void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
+ {
+ struct smem_partition *part;
+- void *ptr = ERR_PTR(-EPROBE_DEFER);
++ void *ptr;
+
+- if (!__smem)
+- return ptr;
++ if (IS_ERR(__smem))
++ return __smem;
+
+ if (WARN_ON(item >= __smem->item_count))
+ return ERR_PTR(-EINVAL);
+@@ -717,8 +721,8 @@ int qcom_smem_get_free_space(unsigned ho
+ struct smem_header *header;
+ unsigned ret;
+
+- if (!__smem)
+- return -EPROBE_DEFER;
++ if (IS_ERR(__smem))
++ return PTR_ERR(__smem);
+
+ if (host < SMEM_HOST_COUNT && __smem->partitions[host].virt_base) {
+ part = &__smem->partitions[host];
+@@ -1175,8 +1179,8 @@ static int qcom_smem_probe(struct platfo
+ header = smem->regions[0].virt_base;
+ if (le32_to_cpu(header->initialized) != 1 ||
+ le32_to_cpu(header->reserved)) {
+- dev_err(&pdev->dev, "SMEM is not initialized by SBL\n");
+- return -EINVAL;
++ __smem = ERR_PTR(-ENODEV);
++ return dev_err_probe(&pdev->dev, PTR_ERR(__smem), "SMEM is not initialized by SBL\n");
+ }
+
+ hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
--- /dev/null
+From a2e7c46ca61dbfac25b0c1bf566d459f609bfe64 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Wed, 29 Oct 2025 13:38:24 +0100
+Subject: [PATCH] cpufreq: qcom-nvmem: add compatible fallback for ipq806x for
+ no SMEM
+
+On some IPQ806x SoC SMEM might be not initialized by SBL. This is the
+case for some Google devices (the OnHub family) that can't make use of
+SMEM to detect the SoC ID.
+
+To handle these specific case, check if the SMEM is not initialized (by
+checking if the qcom_smem_get_soc_id returns -ENODEV) and fallback to
+OF machine compatible checking to identify the SoC variant.
+
+Suggested-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/cpufreq/qcom-cpufreq-nvmem.c | 35 ++++++++++++++++++++++++++--
+ 1 file changed, 33 insertions(+), 2 deletions(-)
+
+--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+@@ -251,13 +251,22 @@ len_error:
+ return ret;
+ }
+
++static const struct of_device_id qcom_cpufreq_ipq806x_match_list[] = {
++ { .compatible = "qcom,ipq8062", .data = (const void *)QCOM_ID_IPQ8062 },
++ { .compatible = "qcom,ipq8064", .data = (const void *)QCOM_ID_IPQ8064 },
++ { .compatible = "qcom,ipq8065", .data = (const void *)QCOM_ID_IPQ8065 },
++ { .compatible = "qcom,ipq8066", .data = (const void *)QCOM_ID_IPQ8066 },
++ { .compatible = "qcom,ipq8068", .data = (const void *)QCOM_ID_IPQ8068 },
++ { .compatible = "qcom,ipq8069", .data = (const void *)QCOM_ID_IPQ8069 },
++};
++
+ static int qcom_cpufreq_ipq8064_name_version(struct device *cpu_dev,
+ struct nvmem_cell *speedbin_nvmem,
+ char **pvs_name,
+ struct qcom_cpufreq_drv *drv)
+ {
++ int msm_id = -1, ret = 0;
+ int speed = 0, pvs = 0;
+- int msm_id, ret = 0;
+ u8 *speedbin;
+ size_t len;
+
+@@ -274,8 +283,30 @@ static int qcom_cpufreq_ipq8064_name_ver
+ get_krait_bin_format_a(cpu_dev, &speed, &pvs, speedbin);
+
+ ret = qcom_smem_get_soc_id(&msm_id);
+- if (ret)
++ if (ret == -ENODEV) {
++ const struct of_device_id *match;
++ struct device_node *root;
++
++ root = of_find_node_by_path("/");
++ if (!root) {
++ ret = -ENODEV;
++ goto exit;
++ }
++
++ /* Fallback to compatible match with no SMEM initialized */
++ match = of_match_node(qcom_cpufreq_ipq806x_match_list, root);
++ of_node_put(root);
++ if (!match) {
++ ret = -ENODEV;
++ goto exit;
++ }
++
++ /* We found a matching device, get the msm_id from the data entry */
++ msm_id = (int)match->data;
++ ret = 0;
++ } else if (ret) {
+ goto exit;
++ }
+
+ switch (msm_id) {
+ case QCOM_ID_IPQ8062: