diff --git a/target/linux/ipq806x/patches-6.12/001-01-v6.19-err.h-add-INIT_ERR_PTR-macro.patch b/target/linux/ipq806x/patches-6.12/001-01-v6.19-err.h-add-INIT_ERR_PTR-macro.patch new file mode 100644 index 0000000000..a6440b73ed --- /dev/null +++ b/target/linux/ipq806x/patches-6.12/001-01-v6.19-err.h-add-INIT_ERR_PTR-macro.patch @@ -0,0 +1,42 @@ +From 652a86b24c5ac444afaf7625c9340d55aab7f105 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +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 +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20251031130835.7953-2-ansuelsmth@gmail.com +[bjorn: Added () suffix on macro references] +Signed-off-by: Bjorn Andersson +--- + 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)) + diff --git a/target/linux/ipq806x/patches-6.12/001-02-v6.19-soc-qcom-smem-better-track-SMEM-uninitialized-state.patch b/target/linux/ipq806x/patches-6.12/001-02-v6.19-soc-qcom-smem-better-track-SMEM-uninitialized-state.patch new file mode 100644 index 0000000000..e93950a972 --- /dev/null +++ b/target/linux/ipq806x/patches-6.12/001-02-v6.19-soc-qcom-smem-better-track-SMEM-uninitialized-state.patch @@ -0,0 +1,97 @@ +From 7a94d5f31b549e18f908cb669c59f066f45a21c7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +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 +Link: https://lore.kernel.org/r/20251031130835.7953-3-ansuelsmth@gmail.com +Signed-off-by: Bjorn Andersson +--- + 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); diff --git a/target/linux/ipq806x/patches-6.12/002-v6.19-cpufreq-qcom-nvmem-add-compatible-fallback-for-ipq80.patch b/target/linux/ipq806x/patches-6.12/002-v6.19-cpufreq-qcom-nvmem-add-compatible-fallback-for-ipq80.patch new file mode 100644 index 0000000000..e8ca396ca2 --- /dev/null +++ b/target/linux/ipq806x/patches-6.12/002-v6.19-cpufreq-qcom-nvmem-add-compatible-fallback-for-ipq80.patch @@ -0,0 +1,78 @@ +From a2e7c46ca61dbfac25b0c1bf566d459f609bfe64 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +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 +Signed-off-by: Christian Marangi +--- + 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: