From 8a5d6c13cc7cf7f7f096094c5015c82b2fb36131 Mon Sep 17 00:00:00 2001 From: "Pawel Zalewski (The Capable Hub)" Date: Tue, 4 Aug 2026 12:17:45 +0100 Subject: [PATCH 001/176] cache: hisi_soc_hha: use named initializers for acpi_device_id Use a named initializer for the acpi_device_id fields which makes the code more readable and consistent with how lists are initialized in the rest of the kernel code base. Signed-off-by: Pawel Zalewski (The Capable Hub) Reviewed-by: Yushan Wang Acked-by: Jonathan Cameron Signed-off-by: Conor Dooley --- drivers/cache/hisi_soc_hha.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cache/hisi_soc_hha.c b/drivers/cache/hisi_soc_hha.c index 25ff0f5ae79b..939f42148a6f 100644 --- a/drivers/cache/hisi_soc_hha.c +++ b/drivers/cache/hisi_soc_hha.c @@ -171,7 +171,7 @@ static void hisi_soc_hha_remove(struct platform_device *pdev) } static const struct acpi_device_id hisi_soc_hha_ids[] = { - { "HISI0511", }, + { .id = "HISI0511" }, { } }; MODULE_DEVICE_TABLE(acpi, hisi_soc_hha_ids); From 8faf58aebca323d679d10876f97f0ab7fb7a48c4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 2 Jul 2026 15:27:16 +0200 Subject: [PATCH 002/176] soc: renesas: Expand MFIS acronym in RCAR_MFIS help description People not very familiar with Renesas R-Car SoCs may not know the meaning of the MFIS acronym. Hence expand it in the help text. While at it, drop "core driver", as there is only a single driver, unlike early development revisions, and replace "Gen5" by "R-Car Gen5". Signed-off-by: Geert Uytterhoeven Link: https://patch.msgid.link/b92a4b39a18aec7cdffdfdfbc75de4ecadb0395d.1782998764.git.geert+renesas@glider.be --- drivers/soc/renesas/Kconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index eb8ac0d47d9d..e334cc204ad8 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -470,9 +470,10 @@ config RCAR_MFIS depends on ARCH_RENESAS || COMPILE_TEST depends on MAILBOX help - Select this option to enable the Renesas R-Car MFIS core driver for - the MFIS device found on SoCs like R-Car. On families like Gen5, this - is needed to communicate with the SCP. + Select this option to enable support for the Renesas R-Car + Multifunctional Interface (MFIS) device found on SoCs like R-Car. + On families like R-Car Gen5, this is needed to communicate with the + SCP. config PWC_RZV2M bool "Renesas RZ/V2M PWC support" if COMPILE_TEST From b7453d3fbb017069466fcd4a0d50ffcfeadaee84 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 18 Jul 2026 20:23:54 +0200 Subject: [PATCH 003/176] soc: renesas: rcar-mfis: Convert spinlock to raw_spinlock With the upcoming hwspinlock support for this driver, mfis_write() can also be accessed from atomic contexts. Convert the spinlock guarding the unprotect register to a raw_spinlock, so we will avoid potential deadlocks with preempt_rt. Signed-off-by: Wolfram Sang Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260718182355.50045-2-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/rcar-mfis.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/soc/renesas/rcar-mfis.c b/drivers/soc/renesas/rcar-mfis.c index 3435c3e16198..c327a60789d0 100644 --- a/drivers/soc/renesas/rcar-mfis.c +++ b/drivers/soc/renesas/rcar-mfis.c @@ -50,7 +50,7 @@ struct mfis_chan_priv { }; struct mfis_priv { - spinlock_t unprotect_lock; /* guards access to the unprotection reg */ + raw_spinlock_t unprotect_lock; /* guards access to unprotection reg */ struct device *dev; struct mfis_reg common_reg; struct mfis_reg mbox_reg; @@ -80,10 +80,10 @@ static void mfis_write(struct mfis_reg *mreg, u32 reg, u32 val) unprotect_code = (MFIS_UNPROTECT_KEY & ~unprotect_mask) | ((mreg->start + reg) & unprotect_mask); - spin_lock_irqsave(&priv->unprotect_lock, flags); + raw_spin_lock_irqsave(&priv->unprotect_lock, flags); iowrite32(unprotect_code, priv->common_reg.base + MFISWACNTR); iowrite32(val, mreg->base + reg); - spin_unlock_irqrestore(&priv->unprotect_lock, flags); + raw_spin_unlock_irqrestore(&priv->unprotect_lock, flags); } /******************************************************** @@ -323,7 +323,7 @@ static int mfis_probe(struct platform_device *pdev) if (!priv->info) return -ENOENT; - spin_lock_init(&priv->unprotect_lock); + raw_spin_lock_init(&priv->unprotect_lock); ret = mfis_reg_probe(pdev, priv, &priv->common_reg, "common", true); if (ret) From dc9c9c4fcb88a5660259dcef93c1ef5acd767189 Mon Sep 17 00:00:00 2001 From: Kartik Rajput Date: Thu, 4 Jun 2026 14:28:24 +0530 Subject: [PATCH 004/176] soc/tegra: pmc: Add PMC support for Tegra410 Tegra410 uses PMC driver only to retrieve system reset reason using PMC sysfs. Tegra410 uses ACPI to probe PMC, unlike device-tree boot it does not use the early initialisation sequence. Add PMC support for Tegra410, which uses the PMC driver to retrieve the system reset reason via PMC sysfs. Signed-off-by: Kartik Rajput Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 98 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 41ed716d5857..9c26cf4c1a89 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -11,6 +11,7 @@ #define pr_fmt(fmt) "tegra-pmc: " fmt +#include #include #include #include @@ -2980,6 +2981,18 @@ static void tegra_pmc_reset_suspend_mode(void *data) pmc->suspend_mode = TEGRA_SUSPEND_NOT_READY; } +static int tegra_pmc_acpi_probe(struct platform_device *pdev, struct tegra_pmc *pmc) +{ + pmc->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pmc->base)) + return PTR_ERR(pmc->base); + + tegra_pmc_reset_sysfs_init(pmc); + platform_set_drvdata(pdev, pmc); + + return 0; +} + static int tegra_pmc_probe(struct platform_device *pdev) { struct tegra_pmc *pmc; @@ -3004,6 +3017,9 @@ static int tegra_pmc_probe(struct platform_device *pdev) mutex_init(&pmc->powergates_lock); pmc->dev = &pdev->dev; + if (is_acpi_node(dev_fwnode(&pdev->dev))) + return tegra_pmc_acpi_probe(pdev, pmc); + err = tegra_pmc_parse_dt(pmc, pdev->dev.of_node); if (err < 0) return dev_err_probe(&pdev->dev, err, "failed to parse DT\n"); @@ -4820,6 +4836,81 @@ static const struct tegra_pmc_soc tegra264_pmc_soc = { .max_wake_vectors = 4, }; +static const char * const tegra410_reset_sources[] = { + "SYS_RESET_N", /* 0x0 */ + "CSDC_RTC_XTAL", + "VREFRO_POWER_BAD", + "FMON_32K", + "FMON_OSC", + "POD_RTC", + "POD_IO", + "POD_PLUS_IO_SPLL", + "POD_PLUS_IO_VMON", /* 0x8 */ + "POD_PLUS_SOC", + "VMON_PLUS_UV", + "VMON_PLUS_OV", + "FUSECRC_FAULT", + "OSC_FAULT", + "BPMP_BOOT_FAULT", + "SCPM_BPMP_CORE_CLK", + "SCPM_PSC_SE_CLK", /* 0x10 */ + "VMON_SOC_MIN", + "VMON_SOC_MAX", + "NVJTAG_SEL_MONITOR", + "L0_RST_REQ_N", + "NV_THERM_FAULT", + "PSC_SW", + "POD_C2C_LPI_0", + "POD_C2C_LPI_1", /* 0x18 */ + "BPMP_FMON", + "FMON_SPLL_OUT", + "L1_RST_REQ_N", + "OCP_RECOVERY", + "AO_WDT_POR", + "BPMP_WDT_POR", + "RAS_WDT_POR", + "TOP_0_WDT_POR", /* 0x20 */ + "TOP_1_WDT_POR", + "TOP_2_WDT_POR", + "PSC_WDT_POR", + "OOBHUB_WDT_POR", + "MSS_SEQ_WDT_POR", + "SW_MAIN", + "L0L1_RST_OUT_N", + "HSM", /* 0x28 */ + "CSITE_SW", + "AO_WDT_DBG", + "BPMP_WDT_DBG", + "RAS_WDT_DBG", + "TOP_0_WDT_DBG", + "TOP_1_WDT_DBG", + "TOP_2_WDT_DBG", + "PSC_WDT_DBG", /* 0x30 */ + "TSC_0_WDT_DBG", + "TSC_1_WDT_DBG", + "OOBHUB_WDT_DBG", + "MSS_SEQ_WDT_DBG", + "L2_RST_REQ_N", + "L2_RST_OUT_N", + "SC7" +}; + +static const struct tegra_pmc_regs tegra410_pmc_regs = { + .rst_status = 0x8, + .rst_source_shift = 0x2, + .rst_source_mask = 0xfc, + .rst_level_shift = 0x0, + .rst_level_mask = 0x3, +}; + +static const struct tegra_pmc_soc tegra410_pmc_soc = { + .regs = &tegra410_pmc_regs, + .reset_sources = tegra410_reset_sources, + .num_reset_sources = ARRAY_SIZE(tegra410_reset_sources), + .reset_levels = tegra186_reset_levels, + .num_reset_levels = ARRAY_SIZE(tegra186_reset_levels), +}; + static const struct of_device_id tegra_pmc_match[] = { { .compatible = "nvidia,tegra264-pmc", .data = &tegra264_pmc_soc }, { .compatible = "nvidia,tegra238-pmc", .data = &tegra238_pmc_soc }, @@ -4835,6 +4926,12 @@ static const struct of_device_id tegra_pmc_match[] = { { } }; +static const struct acpi_device_id tegra_pmc_acpi_match[] = { + { .id = "NVDA2016", .driver_data = (kernel_ulong_t)&tegra410_pmc_soc }, + { } +}; +MODULE_DEVICE_TABLE(acpi, tegra_pmc_acpi_match); + static void tegra_pmc_sync_state(struct device *dev) { struct tegra_pmc *pmc = dev_get_drvdata(dev); @@ -4886,6 +4983,7 @@ static struct platform_driver tegra_pmc_driver = { .name = "tegra-pmc", .suppress_bind_attrs = true, .of_match_table = tegra_pmc_match, + .acpi_match_table = tegra_pmc_acpi_match, #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) .pm = &tegra_pmc_pm_ops, #endif From 665d237915193b06d3026da367040e4a4f3356ba Mon Sep 17 00:00:00 2001 From: Jason Pettit Date: Sat, 29 Aug 2026 12:08:10 -0700 Subject: [PATCH 005/176] firmware: qcom: scm: Allow QSEECOM on HP EliteBook X G2q 14 AI The HP EliteBook X G2q 14" Next Gen AI PC is a Snapdragon X2 Elite (Glymur) laptop whose firmware exposes EFI variables through QSEECOM. Add its board compatible to the QSEECOM allowlist so that EFI variable access (efivarfs) works on this machine. Without it the kernel reports "qseecom: untested machine, skipping" and efivarfs is empty. Reviewed-by: Dmitry Baryshkov Signed-off-by: Jason Pettit Link: https://lore.kernel.org/r/20260829-glymur-send-v5-3-a11bdf6a4b66@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 3eaa4c9ccf3c..c44c63e1c20d 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2311,6 +2311,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "ecs,liva-qc710" }, { .compatible = "honor,magicbook-art-14-snapdragon" }, { .compatible = "hp,elitebook-ultra-g1q" }, + { .compatible = "hp,elitebook-x-g2q" }, { .compatible = "hp,omnibook-x14" }, { .compatible = "huawei,gaokun3" }, { .compatible = "lenovo,flex-5g" }, From 7bb5f186784074f2a91d83e191e305238be47103 Mon Sep 17 00:00:00 2001 From: Gopikrishna Garmidi Date: Thu, 27 Aug 2026 01:13:17 -0700 Subject: [PATCH 006/176] soc: qcom: smem: fix 32-bit overflow in DDR frequency calculation The DDR frequency in SMEM is reported in kHz and converted to Hz by multiplying it by 1000. Since the SMEM frequency value is a u32, using an unsuffixed integer constant causes the multiplication to be performed with 32-bit arithmetic. This overflows for DDR frequencies above 4294967 kHz, resulting in an incorrect frequency being reported through the SMEM DRAM interface. Use an unsigned long constant for the multiplication so the calculation is performed with 64-bit arithmetic on the supported Qualcomm platforms. Apply the fix consistently to the v3, v3.1, v4, v5, and v7 SMEM parsers. Fixes: 1d234eeafc56 ("soc: qcom: smem: Expose DDR data from SMEM") Signed-off-by: Gopikrishna Garmidi Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260827-glymur_dramc-v1-1-eba358d504b8@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem_dramc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/smem_dramc.c b/drivers/soc/qcom/smem_dramc.c index 63ebe7f6db59..9612230a03be 100644 --- a/drivers/soc/qcom/smem_dramc.c +++ b/drivers/soc/qcom/smem_dramc.c @@ -219,7 +219,7 @@ static void smem_dram_parse_v3_data(struct smem_dram *dram, void *data) if (freq_entry->freq_khz && freq_entry->enabled) { u32 freq_khz = le32_to_cpu(freq_entry->freq_khz); - dram->frequencies[dram->num_frequencies++] = 1000 * freq_khz; + dram->frequencies[dram->num_frequencies++] = 1000UL * freq_khz; } } } @@ -232,7 +232,7 @@ static void smem_dram_parse_v3_14freqs_data(struct smem_dram *dram, void *data) struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; if (freq_entry->freq_khz && freq_entry->enabled) - dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz; + dram->frequencies[dram->num_frequencies++] = 1000UL * freq_entry->freq_khz; } } @@ -248,7 +248,7 @@ static void smem_dram_parse_v4_data(struct smem_dram *dram, void *data) if (freq_entry->freq_khz && freq_entry->enabled) { u32 freq_khz = le32_to_cpu(freq_entry->freq_khz); - dram->frequencies[dram->num_frequencies++] = 1000 * freq_khz; + dram->frequencies[dram->num_frequencies++] = 1000UL * freq_khz; } } } @@ -265,7 +265,7 @@ static void smem_dram_parse_v5_data(struct smem_dram *dram, void *data) if (freq_entry->freq_khz && freq_entry->enabled) { u32 freq_khz = le32_to_cpu(freq_entry->freq_khz); - dram->frequencies[dram->num_frequencies++] = 1000 * freq_khz; + dram->frequencies[dram->num_frequencies++] = 1000UL * freq_khz; } } } @@ -282,7 +282,7 @@ static void smem_dram_parse_v7_data(struct smem_dram *dram, void *data) if (freq_entry->freq_khz && freq_entry->enabled) { u32 freq_khz = le32_to_cpu(freq_entry->freq_khz); - dram->frequencies[dram->num_frequencies++] = 1000 * freq_khz; + dram->frequencies[dram->num_frequencies++] = 1000UL * freq_khz; } } } From 9f3136c0c5bcb26d5c864f8a5658c1a6f449d351 Mon Sep 17 00:00:00 2001 From: Linmao Li Date: Thu, 27 Aug 2026 10:04:47 +0800 Subject: [PATCH 007/176] soc: qcom: smem: Fix byte order in v3 14-frequency parser smem_dram_parse_v3_14freqs_data() uses the little-endian freq_khz field directly when scaling the frequency from kHz to Hz. This produces byte-swapped values on big-endian systems. Convert freq_khz to CPU byte order before using it, as the other DDR data parsers do. Fixes: 1d234eeafc56 ("soc: qcom: smem: Expose DDR data from SMEM") Signed-off-by: Linmao Li Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260827020447.2642830-1-lilinmao@kylinos.cn Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem_dramc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/smem_dramc.c b/drivers/soc/qcom/smem_dramc.c index 9612230a03be..cba5376ec80d 100644 --- a/drivers/soc/qcom/smem_dramc.c +++ b/drivers/soc/qcom/smem_dramc.c @@ -231,8 +231,11 @@ static void smem_dram_parse_v3_14freqs_data(struct smem_dram *dram, void *data) for (int i = 0; i < MAX_DDR_FREQ_NUM_V3 + 1; i++) { struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; - if (freq_entry->freq_khz && freq_entry->enabled) - dram->frequencies[dram->num_frequencies++] = 1000UL * freq_entry->freq_khz; + if (freq_entry->freq_khz && freq_entry->enabled) { + u32 freq_khz = le32_to_cpu(freq_entry->freq_khz); + + dram->frequencies[dram->num_frequencies++] = 1000UL * freq_khz; + } } } From 713f6b15f361c9218faf227e989d713632fcb2c5 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Thu, 20 Aug 2026 18:30:08 +0200 Subject: [PATCH 008/176] soc: qcom: smem: support Glymur DRAM info Glymur firmware provides a version 7 DDR-info SMEM entry whose 872-byte layout is different from the one the driver supports today. The data contains 16 channel descriptors, 14 DDR frequency slots, four 4 DDR region slots, a 10-entry SHUB frequency plan, and v6 misc information. It accounts for 616 bytes; the captured SMEM entry has a further 256 zero bytes. Add a Glymur-specific version 7 layout and recognize that complete entry. Parse the DDR frequencies and highest-bank bit from the common fields. Assisted-by: LLM Signed-off-by: Konrad Dybcio Tested-by: Gopikrishna Garmidi Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20260820-topic-glymur_dramc-v1-1-f714eef34e4d@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem_dramc.c | 66 +++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/drivers/soc/qcom/smem_dramc.c b/drivers/soc/qcom/smem_dramc.c index cba5376ec80d..24ccdfdc2b3d 100644 --- a/drivers/soc/qcom/smem_dramc.c +++ b/drivers/soc/qcom/smem_dramc.c @@ -20,12 +20,22 @@ #define MAX_DDR_FREQ_NUM_V5 14 #define MAX_CHAN_NUM 8 +#define MAX_CHAN_NUM_V7_GLYMUR 16 #define MAX_RANK_NUM 2 #define DDR_HBB_MIN 13 #define DDR_HBB_MAX 19 #define MAX_SHUB_ENTRIES 8 +#define MAX_SHUB_ENTRIES_V7_GLYMUR 10 +#define MAX_DDR_REGIONS_V7_GLYMUR 4 + +/* + * Glymur's DRAM information entry has 256 bytes of trailing zeroes + * after its DDR details, four region slots, 10-entry SHUB frequency + * plan, and v6 misc information. + */ +#define DDR_V7_GLYMUR_RESERVED_SIZE 256 static struct smem_dram *__dram; @@ -39,6 +49,7 @@ enum ddr_info_version { INFO_V6, /* INFO_V6 seems to only have shipped with 6 DDR regions, unlike V7 */ INFO_V7, INFO_V7_WITH_6_REGIONS, + INFO_V7_GLYMUR, }; struct smem_dram { @@ -188,6 +199,37 @@ struct ddr_details_v7 { struct ddr_regions_v5 ddr_regions; }; +struct ddr_regions_v7_glymur { + __le32 ddr_region_num; + __le64 ddr_rank0_size; + __le64 ddr_rank1_size; + __le64 ddr_cs0_start_addr; + __le64 ddr_cs1_start_addr; + __le32 highest_bank_addr_bit; + struct ddr_region_v5 ddr_region[MAX_DDR_REGIONS_V7_GLYMUR]; +}; + +struct ddr_details_v7_glymur { + u8 manufacturer_id; + u8 device_type; + struct ddr_part_details ddr_params[MAX_CHAN_NUM_V7_GLYMUR]; + struct ddr_freq_plan_v5 ddr_freq_tbl; + u8 num_channels; + u8 sct_config; + struct ddr_regions_v7_glymur ddr_regions; +}; + +struct shub_freq_plan_entry_v7_glymur { + u8 num_shub_freqs; + struct shub_freq_table shub_freq[MAX_SHUB_ENTRIES_V7_GLYMUR]; +}; + +struct ddr_v7_glymur_tail { + struct shub_freq_plan_entry_v7_glymur shub_freq_plan; + struct ddr_misc_info_v6 misc_info; + u8 reserved[DDR_V7_GLYMUR_RESERVED_SIZE]; +}; + /** * qcom_smem_dram_get_hbb(): Get the Highest bank address bit * @@ -290,6 +332,23 @@ static void smem_dram_parse_v7_data(struct smem_dram *dram, void *data) } } +static void smem_dram_parse_v7_glymur_data(struct smem_dram *dram, void *data) +{ + struct ddr_details_v7_glymur *details = data; + + dram->hbb = le32_to_cpu(details->ddr_regions.highest_bank_addr_bit); + + for (int i = 0; i < MAX_DDR_FREQ_NUM_V5; i++) { + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; + + if (freq_entry->freq_khz && freq_entry->enabled) { + u32 freq_khz = le32_to_cpu(freq_entry->freq_khz); + + dram->frequencies[dram->num_frequencies++] = 1000 * freq_khz; + } + } +} + /* The structure contains no version field, so we have to perform some guesswork.. */ static int smem_dram_infer_struct_version(size_t size) { @@ -344,6 +403,10 @@ static int smem_dram_infer_struct_version(size_t size) sizeof(struct shub_freq_plan_entry)) return INFO_V7_WITH_6_REGIONS; + if (size == sizeof(struct ddr_details_v7_glymur) + + sizeof(struct ddr_v7_glymur_tail)) + return INFO_V7_GLYMUR; + return INFO_UNKNOWN; } @@ -418,6 +481,9 @@ struct dentry *smem_dram_parse(struct qcom_smem *smem, struct device *dev) case INFO_V7_WITH_6_REGIONS: smem_dram_parse_v7_data(dram, data); break; + case INFO_V7_GLYMUR: + smem_dram_parse_v7_glymur_data(dram, data); + break; default: return ERR_PTR(-EINVAL); } From 57bf822e3c692e1f204d3d8674967344e7e05549 Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Wed, 19 Aug 2026 21:53:27 +0530 Subject: [PATCH 009/176] soc: qcom: llcc: Update the SCT table for IPQ5424 Update the IPQ5424 LLCC slice configuration table to give the PPE and Wi-Fi datapaths dedicated slices. Assign slice IDs 1 and 5 to the PPE RX descriptor and RX fill use cases, slice IDs 6 and 7 to the Wi-Fi radios connected over PCIe, and slice ID 2 to the CPU subsystem. Adjust the corresponding capacities, priorities, and way masks for these consumers. These slice assignments are based on recommendations from the performance team, following throughput measurements on IPQ5424. Having the dedicated slice configuration for each of these use cases helps to improve the networking throughput by more than 1 Gbps. Rename the usecase IDs for slice IDs 1 and 2 because LLCC_CPUSS and LLCC_VIDSC0 do not describe the actual users of those slices. Assisted-by: LLM Reviewed-by: Dmitry Baryshkov Signed-off-by: Kathiravan Thirumoorthy Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260819-ipq5424_llcc_updates-v3-1-42b48451481d@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 56 +++++++++++++++++++++++++----- include/linux/soc/qcom/llcc-qcom.h | 4 +++ 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 733999867bbf..d60431ace50f 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -626,11 +626,11 @@ static const struct llcc_slice_config glymur_data[] = { static const struct llcc_slice_config ipq5424_data[] = { { - .usecase_id = LLCC_CPUSS, + .usecase_id = LLCC_PPE_RXDESC, .slice_id = 1, - .max_cap = 768, - .priority = 1, - .bonus_ways = 0xFFFF, + .max_cap = 128, + .priority = 3, + .bonus_ways = 0x0FFF, .retain_on_pc = true, .activate_on_init = true, .write_scid_cacheable_en = true, @@ -642,12 +642,52 @@ static const struct llcc_slice_config ipq5424_data[] = { .vict_prio = true, }, { - .usecase_id = LLCC_VIDSC0, + .usecase_id = LLCC_CPUSS, .slice_id = 2, - .max_cap = 256, - .priority = 2, + .max_cap = 768, + .priority = 1, .fixed_size = true, - .bonus_ways = 0xF000, + .bonus_ways = 0x0FFF, + .retain_on_pc = true, + .activate_on_init = true, + .write_scid_cacheable_en = true, + .stale_en = true, + .stale_cap_en = true, + }, + { + .usecase_id = LLCC_PPE_RXFILL, + .slice_id = 5, + .max_cap = 128, + .priority = 3, + .bonus_ways = 0x0FFF, + .retain_on_pc = true, + .activate_on_init = true, + .write_scid_cacheable_en = true, + .stale_en = true, + .stale_cap_en = true, + .alloc_oneway_en = true, + .ovcap_en = true, + .ovcap_prio = true, + .vict_prio = true, + }, + { + .usecase_id = LLCC_WLAN_5G, + .slice_id = 6, + .max_cap = 128, + .priority = 3, + .bonus_ways = 0xC000, + .retain_on_pc = true, + .activate_on_init = true, + .write_scid_cacheable_en = true, + .stale_en = true, + .stale_cap_en = true, + }, + { + .usecase_id = LLCC_WLAN_6G, + .slice_id = 7, + .max_cap = 128, + .priority = 3, + .bonus_ways = 0x3000, .retain_on_pc = true, .activate_on_init = true, .write_scid_cacheable_en = true, diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h index f3ed63e475ab..1ccc429401e8 100644 --- a/include/linux/soc/qcom/llcc-qcom.h +++ b/include/linux/soc/qcom/llcc-qcom.h @@ -86,6 +86,10 @@ #define LLCC_CPUSS_HEU 94 #define LLCC_PCIE_TCU 97 #define LLCC_MDM_PNG_FIXED 100 +#define LLCC_PPE_RXDESC 101 +#define LLCC_PPE_RXFILL 102 +#define LLCC_WLAN_5G 103 +#define LLCC_WLAN_6G 104 /** * struct llcc_slice_desc - Cache slice descriptor From c84cdd308471d6ae4f8121660436a4fed8126709 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 23 Jun 2026 10:09:54 +0100 Subject: [PATCH 010/176] soc: qcom: smsm: fix __iomem annotations There are a number of points in the driver which miss out on __iomem annotations, so add these to remove the following sparse warnings: drivers/soc/qcom/smsm.c:159:32: warning: incorrect type in argument 1 (different address spaces) drivers/soc/qcom/smsm.c:159:32: expected void const volatile [noderef] __iomem *addr drivers/soc/qcom/smsm.c:159:32: got unsigned int [usertype] *local_state drivers/soc/qcom/smsm.c:171:25: warning: incorrect type in argument 2 (different address spaces) drivers/soc/qcom/smsm.c:171:25: expected void volatile [noderef] __iomem *addr drivers/soc/qcom/smsm.c:171:25: got unsigned int [usertype] *local_state drivers/soc/qcom/smsm.c:181:48: warning: incorrect type in argument 1 (different address spaces) drivers/soc/qcom/smsm.c:181:48: expected void const volatile [noderef] __iomem *addr drivers/soc/qcom/smsm.c:181:48: got unsigned int [usertype] * drivers/soc/qcom/smsm.c:219:26: warning: incorrect type in argument 1 (different address spaces) drivers/soc/qcom/smsm.c:219:26: expected void const volatile [noderef] __iomem *addr drivers/soc/qcom/smsm.c:219:26: got unsigned int [usertype] *remote_state drivers/soc/qcom/smsm.c:257:49: warning: incorrect type in argument 1 (different address spaces) drivers/soc/qcom/smsm.c:257:49: expected void const volatile [noderef] __iomem *addr drivers/soc/qcom/smsm.c:257:49: got unsigned int [usertype] * drivers/soc/qcom/smsm.c:259:49: warning: incorrect type in argument 2 (different address spaces) drivers/soc/qcom/smsm.c:259:49: expected void volatile [noderef] __iomem *addr drivers/soc/qcom/smsm.c:259:49: got unsigned int [usertype] * drivers/soc/qcom/smsm.c:280:24: warning: incorrect type in argument 1 (different address spaces) drivers/soc/qcom/smsm.c:280:24: expected void const volatile [noderef] __iomem *addr drivers/soc/qcom/smsm.c:280:24: got unsigned int [usertype] *remote_state drivers/soc/qcom/smsm.c:288:49: warning: incorrect type in argument 1 (different address spaces) drivers/soc/qcom/smsm.c:288:49: expected void const volatile [noderef] __iomem *addr drivers/soc/qcom/smsm.c:288:49: got unsigned int [usertype] * drivers/soc/qcom/smsm.c:290:49: warning: incorrect type in argument 2 (different address spaces) drivers/soc/qcom/smsm.c:290:49: expected void volatile [noderef] __iomem *addr drivers/soc/qcom/smsm.c:290:49: got unsigned int [usertype] * drivers/soc/qcom/smsm.c:330:26: warning: incorrect type in argument 1 (different address spaces) drivers/soc/qcom/smsm.c:330:26: expected void const volatile [noderef] __iomem *addr drivers/soc/qcom/smsm.c:330:26: got unsigned int [usertype] *remote_state drivers/soc/qcom/smsm.c:635:47: warning: incorrect type in argument 2 (different address spaces) drivers/soc/qcom/smsm.c:635:47: expected void volatile [noderef] __iomem *addr drivers/soc/qcom/smsm.c:635:47: got unsigned int [usertype] * Note, we don't fixup the qcom_smem_get() to return an __iomem annotated pointer. Signed-off-by: Ben Dooks Link: https://lore.kernel.org/r/20260623090954.620688-1-ben.dooks@codethink.co.uk Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smsm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c index 021e9d1f61dc..d54dfc36103e 100644 --- a/drivers/soc/qcom/smsm.c +++ b/drivers/soc/qcom/smsm.c @@ -82,8 +82,8 @@ struct qcom_smsm { u32 num_hosts; u32 num_entries; - u32 *local_state; - u32 *subscription; + u32 __iomem *local_state; + u32 __iomem *subscription; struct qcom_smem_state *state; spinlock_t lock; @@ -115,8 +115,8 @@ struct smsm_entry { DECLARE_BITMAP(irq_falling, 32); unsigned long last_value; - u32 *remote_state; - u32 *subscription; + u32 __iomem *remote_state; + u32 __iomem *subscription; }; /** @@ -513,9 +513,9 @@ static int qcom_smsm_probe(struct platform_device *pdev) struct device_node *node; struct smsm_entry *entry; struct qcom_smsm *smsm; - u32 *intr_mask; + u32 __iomem *intr_mask; size_t size; - u32 *states; + u32 __iomem *states; u32 id; int ret; @@ -579,7 +579,7 @@ static int qcom_smsm_probe(struct platform_device *pdev) goto out_put; } - states = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SHARED_STATE, NULL); + states = (u32 __iomem *)qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SHARED_STATE, NULL); if (IS_ERR(states)) { dev_err(&pdev->dev, "Unable to acquire shared state entry\n"); ret = PTR_ERR(states); @@ -594,7 +594,7 @@ static int qcom_smsm_probe(struct platform_device *pdev) goto out_put; } - intr_mask = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, NULL); + intr_mask = (u32 __iomem *)qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, NULL); if (IS_ERR(intr_mask)) { dev_err(&pdev->dev, "unable to acquire shared memory interrupt mask\n"); ret = PTR_ERR(intr_mask); From 3eda4fa73e30207eb7afedde6987f7f321f74fbc Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Thu, 2 Jul 2026 17:28:29 +0530 Subject: [PATCH 011/176] firmware: qcom_scm: Remove SCM PAS wrappers Now since all the Qcom SCM client drivers have been migrated over to generic PAS TZ service, let's drop the exported SCM PAS wrappers. Reviewed-by: Mukesh Ojha Tested-by: Mukesh Ojha # Lemans Tested-by: Vignesh Viswanathan # IPQ9650 Reviewed-by: Konrad Dybcio Signed-off-by: Sumit Garg Link: https://lore.kernel.org/r/20260702115835.167602-14-sumit.garg@kernel.org Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 143 +++++-------------------- include/linux/firmware/qcom/qcom_scm.h | 29 ----- 2 files changed, 29 insertions(+), 143 deletions(-) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 3eaa4c9ccf3c..363362a59b5a 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -576,26 +576,6 @@ static void qcom_scm_set_download_mode(struct qcom_scm *scm, u32 dload_mode) writel_relaxed(minidump_dest, scm->minidump_sram); } -struct qcom_scm_pas_context *devm_qcom_scm_pas_context_alloc(struct device *dev, - u32 pas_id, - phys_addr_t mem_phys, - size_t mem_size) -{ - struct qcom_pas_context *ctx; - - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return ERR_PTR(-ENOMEM); - - ctx->dev = dev; - ctx->pas_id = pas_id; - ctx->mem_phys = mem_phys; - ctx->mem_size = mem_size; - - return (struct qcom_scm_pas_context *)ctx; -} -EXPORT_SYMBOL_GPL(devm_qcom_scm_pas_context_alloc); - static int __qcom_scm_pas_init_image(struct device *dev, u32 pas_id, dma_addr_t mdata_phys, struct qcom_scm_res *res) @@ -653,9 +633,9 @@ static int qcom_scm_pas_prep_and_init_image(struct device *dev, return ret ? : res.result[0]; } -static int __qcom_scm_pas_init_image2(struct device *dev, u32 pas_id, - const void *metadata, size_t size, - struct qcom_pas_context *ctx) +static int qcom_scm_pas_init_image(struct device *dev, u32 pas_id, + const void *metadata, size_t size, + struct qcom_pas_context *ctx) { struct qcom_scm_res res; dma_addr_t mdata_phys; @@ -695,16 +675,8 @@ static int __qcom_scm_pas_init_image2(struct device *dev, u32 pas_id, return ret ? : res.result[0]; } -int qcom_scm_pas_init_image(u32 pas_id, const void *metadata, size_t size, - struct qcom_scm_pas_context *ctx) -{ - return __qcom_scm_pas_init_image2(__scm->dev, pas_id, metadata, size, - (struct qcom_pas_context *)ctx); -} -EXPORT_SYMBOL_GPL(qcom_scm_pas_init_image); - -static void __qcom_scm_pas_metadata_release(struct device *dev, - struct qcom_pas_context *ctx) +static void qcom_scm_pas_metadata_release(struct device *dev, + struct qcom_pas_context *ctx) { if (ctx->use_tzmem) qcom_tzmem_free(ctx->ptr); @@ -714,15 +686,8 @@ static void __qcom_scm_pas_metadata_release(struct device *dev, ctx->ptr = NULL; } -void qcom_scm_pas_metadata_release(struct qcom_scm_pas_context *ctx) -{ - __qcom_scm_pas_metadata_release(__scm->dev, - (struct qcom_pas_context *)ctx); -} -EXPORT_SYMBOL_GPL(qcom_scm_pas_metadata_release); - -static int __qcom_scm_pas_mem_setup(struct device *dev, u32 pas_id, - phys_addr_t addr, phys_addr_t size) +static int qcom_scm_pas_mem_setup(struct device *dev, u32 pas_id, + phys_addr_t addr, phys_addr_t size) { int ret; struct qcom_scm_desc desc = { @@ -753,12 +718,6 @@ static int __qcom_scm_pas_mem_setup(struct device *dev, u32 pas_id, return ret ? : res.result[0]; } -int qcom_scm_pas_mem_setup(u32 pas_id, phys_addr_t addr, phys_addr_t size) -{ - return __qcom_scm_pas_mem_setup(__scm->dev, pas_id, addr, size); -} -EXPORT_SYMBOL_GPL(qcom_scm_pas_mem_setup); - static void *__qcom_scm_pas_get_rsc_table(struct device *dev, u32 pas_id, void *input_rt_tzm, size_t input_rt_size, @@ -812,11 +771,10 @@ static void *__qcom_scm_pas_get_rsc_table(struct device *dev, u32 pas_id, return ret ? ERR_PTR(ret) : output_rt_tzm; } -static void *__qcom_scm_pas_get_rsc_table2(struct device *dev, - struct qcom_pas_context *ctx, - void *input_rt, - size_t input_rt_size, - size_t *output_rt_size) +static void *qcom_scm_pas_get_rsc_table(struct device *dev, + struct qcom_pas_context *ctx, + void *input_rt, size_t input_rt_size, + size_t *output_rt_size) { struct resource_table empty_rsc = {}; size_t size = SZ_16K; @@ -887,19 +845,7 @@ static void *__qcom_scm_pas_get_rsc_table2(struct device *dev, return ret ? ERR_PTR(ret) : tbl_ptr; } -struct resource_table *qcom_scm_pas_get_rsc_table(struct qcom_scm_pas_context *ctx, - void *input_rt, - size_t input_rt_size, - size_t *output_rt_size) -{ - return __qcom_scm_pas_get_rsc_table2(__scm->dev, - (struct qcom_pas_context *)ctx, - input_rt, input_rt_size, - output_rt_size); -} -EXPORT_SYMBOL_GPL(qcom_scm_pas_get_rsc_table); - -static int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 pas_id) +static int qcom_scm_pas_auth_and_reset(struct device *dev, u32 pas_id) { int ret; struct qcom_scm_desc desc = { @@ -928,14 +874,8 @@ static int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 pas_id) return ret ? : res.result[0]; } -int qcom_scm_pas_auth_and_reset(u32 pas_id) -{ - return __qcom_scm_pas_auth_and_reset(__scm->dev, pas_id); -} -EXPORT_SYMBOL_GPL(qcom_scm_pas_auth_and_reset); - -static int __qcom_scm_pas_prepare_and_auth_reset(struct device *dev, - struct qcom_pas_context *ctx) +static int qcom_scm_pas_prepare_and_auth_reset(struct device *dev, + struct qcom_pas_context *ctx) { u64 handle; int ret; @@ -946,7 +886,7 @@ static int __qcom_scm_pas_prepare_and_auth_reset(struct device *dev, * memory region and then invokes a call to TrustZone to authenticate. */ if (!ctx->use_tzmem) - return __qcom_scm_pas_auth_and_reset(dev, ctx->pas_id); + return qcom_scm_pas_auth_and_reset(dev, ctx->pas_id); /* * When Linux runs @ EL2 Linux must create the shmbridge itself and then @@ -956,21 +896,14 @@ static int __qcom_scm_pas_prepare_and_auth_reset(struct device *dev, if (ret) return ret; - ret = __qcom_scm_pas_auth_and_reset(dev, ctx->pas_id); + ret = qcom_scm_pas_auth_and_reset(dev, ctx->pas_id); qcom_tzmem_shm_bridge_delete(handle); return ret; } -int qcom_scm_pas_prepare_and_auth_reset(struct qcom_scm_pas_context *ctx) -{ - return __qcom_scm_pas_prepare_and_auth_reset(__scm->dev, - (struct qcom_pas_context *)ctx); -} -EXPORT_SYMBOL_GPL(qcom_scm_pas_prepare_and_auth_reset); - -static int __qcom_scm_pas_set_remote_state(struct device *dev, u32 state, - u32 pas_id) +static int qcom_scm_pas_set_remote_state(struct device *dev, u32 state, + u32 pas_id) { struct qcom_scm_desc desc = { .svc = QCOM_SCM_SVC_BOOT, @@ -988,13 +921,7 @@ static int __qcom_scm_pas_set_remote_state(struct device *dev, u32 state, return ret ? : res.result[0]; } -int qcom_scm_set_remote_state(u32 state, u32 id) -{ - return __qcom_scm_pas_set_remote_state(__scm->dev, state, id); -} -EXPORT_SYMBOL_GPL(qcom_scm_set_remote_state); - -static int __qcom_scm_pas_shutdown(struct device *dev, u32 pas_id) +static int qcom_scm_pas_shutdown(struct device *dev, u32 pas_id) { int ret; struct qcom_scm_desc desc = { @@ -1023,13 +950,7 @@ static int __qcom_scm_pas_shutdown(struct device *dev, u32 pas_id) return ret ? : res.result[0]; } -int qcom_scm_pas_shutdown(u32 pas_id) -{ - return __qcom_scm_pas_shutdown(__scm->dev, pas_id); -} -EXPORT_SYMBOL_GPL(qcom_scm_pas_shutdown); - -static bool __qcom_scm_pas_supported(struct device *dev, u32 pas_id) +static bool qcom_scm_pas_supported(struct device *dev, u32 pas_id) { int ret; struct qcom_scm_desc desc = { @@ -1050,23 +971,17 @@ static bool __qcom_scm_pas_supported(struct device *dev, u32 pas_id) return ret ? false : !!res.result[0]; } -bool qcom_scm_pas_supported(u32 pas_id) -{ - return __qcom_scm_pas_supported(__scm->dev, pas_id); -} -EXPORT_SYMBOL_GPL(qcom_scm_pas_supported); - static struct qcom_pas_ops qcom_pas_ops_scm = { .drv_name = "qcom_scm", - .supported = __qcom_scm_pas_supported, - .init_image = __qcom_scm_pas_init_image2, - .mem_setup = __qcom_scm_pas_mem_setup, - .get_rsc_table = __qcom_scm_pas_get_rsc_table2, - .auth_and_reset = __qcom_scm_pas_auth_and_reset, - .prepare_and_auth_reset = __qcom_scm_pas_prepare_and_auth_reset, - .set_remote_state = __qcom_scm_pas_set_remote_state, - .shutdown = __qcom_scm_pas_shutdown, - .metadata_release = __qcom_scm_pas_metadata_release, + .supported = qcom_scm_pas_supported, + .init_image = qcom_scm_pas_init_image, + .mem_setup = qcom_scm_pas_mem_setup, + .get_rsc_table = qcom_scm_pas_get_rsc_table, + .auth_and_reset = qcom_scm_pas_auth_and_reset, + .prepare_and_auth_reset = qcom_scm_pas_prepare_and_auth_reset, + .set_remote_state = qcom_scm_pas_set_remote_state, + .shutdown = qcom_scm_pas_shutdown, + .metadata_release = qcom_scm_pas_metadata_release, }; /** diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h index 5747bd191bf1..a0a6bc0229c4 100644 --- a/include/linux/firmware/qcom/qcom_scm.h +++ b/include/linux/firmware/qcom/qcom_scm.h @@ -64,35 +64,6 @@ bool qcom_scm_is_available(void); int qcom_scm_set_cold_boot_addr(void *entry); int qcom_scm_set_warm_boot_addr(void *entry); void qcom_scm_cpu_power_down(u32 flags); -int qcom_scm_set_remote_state(u32 state, u32 id); - -struct qcom_scm_pas_context { - struct device *dev; - u32 pas_id; - phys_addr_t mem_phys; - size_t mem_size; - void *ptr; - dma_addr_t phys; - ssize_t size; - bool use_tzmem; -}; - -struct qcom_scm_pas_context *devm_qcom_scm_pas_context_alloc(struct device *dev, - u32 pas_id, - phys_addr_t mem_phys, - size_t mem_size); -int qcom_scm_pas_init_image(u32 pas_id, const void *metadata, size_t size, - struct qcom_scm_pas_context *ctx); -void qcom_scm_pas_metadata_release(struct qcom_scm_pas_context *ctx); -int qcom_scm_pas_mem_setup(u32 pas_id, phys_addr_t addr, phys_addr_t size); -int qcom_scm_pas_auth_and_reset(u32 pas_id); -int qcom_scm_pas_shutdown(u32 pas_id); -bool qcom_scm_pas_supported(u32 pas_id); -struct resource_table *qcom_scm_pas_get_rsc_table(struct qcom_scm_pas_context *ctx, - void *input_rt, size_t input_rt_size, - size_t *output_rt_size); - -int qcom_scm_pas_prepare_and_auth_reset(struct qcom_scm_pas_context *ctx); int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val); int qcom_scm_io_writel(phys_addr_t addr, unsigned int val); From 06cb5c457dd57ad1960f7557c67976de4afa79e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Mon, 20 Jul 2026 15:33:46 +0200 Subject: [PATCH 012/176] soc: qcom: apr: Drop unused apr_device_id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit apr_device_id was introduced in commit 6adba21eb434 ("soc: qcom: Add APR bus driver") in 2018, and since then not a single driver made use of it. So drop the unused id_table pointer from struct apr_driver and move APR_NAME_SIZE to the apr header which still has a usage of it. Note that with the id_table being NULL apr_device_match() degrades to just of_driver_match_device(), so replace this callback accordingly. Reviewed-by: Srinivas Kandagatla Reviewed-by: Dmitry Baryshkov Signed-off-by: Uwe Kleine-König (The Capable Hub) Link: https://lore.kernel.org/r/e8b352f33ae38df3616dc157c1cafd13d49c5e3e.1784554037.git.u.kleine-koenig@baylibre.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/apr.c | 25 +------------------------ include/linux/device-id/apr.h | 21 --------------------- include/linux/mod_devicetable.h | 1 - include/linux/soc/qcom/apr.h | 4 ++-- 4 files changed, 3 insertions(+), 48 deletions(-) delete mode 100644 include/linux/device-id/apr.h diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c index ea7f83916d8d..2073edb416a4 100644 --- a/drivers/soc/qcom/apr.c +++ b/drivers/soc/qcom/apr.c @@ -338,29 +338,6 @@ static void apr_rxwq(struct work_struct *work) } } -static int apr_device_match(struct device *dev, const struct device_driver *drv) -{ - struct apr_device *adev = to_apr_device(dev); - const struct apr_driver *adrv = to_apr_driver(drv); - const struct apr_device_id *id = adrv->id_table; - - /* Attempt an OF style match first */ - if (of_driver_match_device(dev, drv)) - return 1; - - if (!id) - return 0; - - while (id->domain_id != 0 || id->svc_id != 0) { - if (id->domain_id == adev->domain_id && - id->svc_id == adev->svc.id) - return 1; - id++; - } - - return 0; -} - static int apr_device_probe(struct device *dev) { struct apr_device *adev = to_apr_device(dev); @@ -401,7 +378,7 @@ static int apr_uevent(const struct device *dev, struct kobj_uevent_env *env) const struct bus_type aprbus = { .name = "aprbus", - .match = apr_device_match, + .match = of_driver_match_device, .probe = apr_device_probe, .uevent = apr_uevent, .remove = apr_device_remove, diff --git a/include/linux/device-id/apr.h b/include/linux/device-id/apr.h deleted file mode 100644 index f282608ea018..000000000000 --- a/include/linux/device-id/apr.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef LINUX_DEVICE_ID_APR_H -#define LINUX_DEVICE_ID_APR_H - -#ifdef __KERNEL__ -#include -typedef unsigned long kernel_ulong_t; -#endif - -#define APR_NAME_SIZE 32 -#define APR_MODULE_PREFIX "apr:" - -struct apr_device_id { - char name[APR_NAME_SIZE]; - __u32 domain_id; - __u32 svc_id; - __u32 svc_version; - kernel_ulong_t driver_data; /* Data private to the driver */ -}; - -#endif /* ifndef LINUX_DEVICE_ID_APR_H */ diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index a397213bedac..4fe1cd64292f 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -15,7 +15,6 @@ #include "device-id/acpi.h" #include "device-id/amba.h" #include "device-id/ap.h" -#include "device-id/apr.h" #include "device-id/auxiliary.h" #include "device-id/bcma.h" #include "device-id/ccw.h" diff --git a/include/linux/soc/qcom/apr.h b/include/linux/soc/qcom/apr.h index 909e84f84e0c..2e4231092088 100644 --- a/include/linux/soc/qcom/apr.h +++ b/include/linux/soc/qcom/apr.h @@ -5,7 +5,6 @@ #include #include -#include #include #include @@ -135,6 +134,8 @@ struct pkt_router_svc { typedef struct pkt_router_svc gpr_port_t; +#define APR_NAME_SIZE 32 + struct apr_device { struct device dev; uint16_t svc_id; @@ -158,7 +159,6 @@ struct apr_driver { const struct apr_resp_pkt *d); gpr_port_cb gpr_callback; struct device_driver driver; - const struct apr_device_id *id_table; }; typedef struct apr_driver gpr_driver_t; From 63a0be9b801af9f357054226895d5a172632c7ee Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Fri, 17 Jul 2026 13:45:02 +0200 Subject: [PATCH 013/176] dt-bindings: interconnect: qcom-bwmon: Add Milos cpu-bwmon compatible Add the compatible string for the CPU-to-DDR bandwidth monitor on the Milos SoC, which is BWMONv5. Signed-off-by: Luca Weiss Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260717-milos-cpu-bwmon-v1-1-dfe0bac9898c@fairphone.com Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml index 21b4e04727de..f6969910bded 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml @@ -50,6 +50,7 @@ properties: - enum: - qcom,eliza-llcc-bwmon - qcom,hawi-llcc-bwmon + - qcom,milos-cpu-bwmon - qcom,qcs615-llcc-bwmon - qcom,qcs8300-llcc-bwmon - qcom,sa8775p-llcc-bwmon From f0c7f46249b917668851f51c7f6e9297c44d42d4 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 15 Jul 2026 09:16:14 +0800 Subject: [PATCH 014/176] dt-bindings: arm: add CTCU device for shikra The CTCU device for shikra shares the same configurations as SA8775p. Add a fallback to enable the CTCU for shikra to utilize the compatible of the SA8775p. Signed-off-by: Jie Gan Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260715-add-coresight-nodes-for-shikra-v2-1-ebd485e39a51@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml index f3f3feac4ce2..335a8e1a5a9e 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml @@ -32,6 +32,7 @@ properties: - qcom,glymur-ctcu - qcom,kaanapali-ctcu - qcom,qcs8300-ctcu + - qcom,shikra-ctcu - qcom,sm8750-ctcu - qcom,x1e80100-ctcu - const: qcom,sa8775p-ctcu From 29b96e2769def61531c19aa537f5a3cf3ef38e41 Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Thu, 23 Jul 2026 10:42:47 +0800 Subject: [PATCH 015/176] soc: qcom: Remove redundant dev_err() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() and devm_request_threaded_irq() automatically log detailed error messages on failure. Remove the now-redundant driver-specific dev_err() calls. Signed-off-by: Pan Chuang Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260723024248.17480-1-panchuang@vivo.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_aoss.c | 4 +--- drivers/soc/qcom/smp2p.c | 4 +--- drivers/soc/qcom/smsm.c | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 259c41f0c34e..a6b673cd7678 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -602,10 +602,8 @@ static int qmp_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); ret = devm_request_irq(&pdev->dev, irq, qmp_intr, 0, "aoss-qmp", qmp); - if (ret < 0) { - dev_err(&pdev->dev, "failed to request interrupt\n"); + if (ret < 0) goto err_free_mbox; - } ret = qmp_open(qmp); if (ret < 0) diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index af0ceeaf6e07..6f07fef40ce8 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -720,10 +720,8 @@ static int qcom_smp2p_probe(struct platform_device *pdev) NULL, qcom_smp2p_intr, IRQF_ONESHOT, NULL, (void *)smp2p); - if (ret) { - dev_err(&pdev->dev, "failed to request interrupt\n"); + if (ret) goto unwind_interfaces; - } /* * Treat smp2p interrupt as wakeup source, but keep it disabled diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c index d54dfc36103e..ac3c85a2597a 100644 --- a/drivers/soc/qcom/smsm.c +++ b/drivers/soc/qcom/smsm.c @@ -451,10 +451,8 @@ static int smsm_inbound_entry(struct qcom_smsm *smsm, NULL, smsm_intr, IRQF_ONESHOT, "smsm", (void *)entry); - if (ret) { - dev_err(smsm->dev, "failed to request interrupt\n"); + if (ret) return ret; - } entry->domain = irq_domain_create_linear(of_fwnode_handle(node), 32, &smsm_irq_ops, entry); if (!entry->domain) { From 595951340089dbc6e532e15242df1855bc858d45 Mon Sep 17 00:00:00 2001 From: Hardeep Sharma Date: Thu, 27 Aug 2026 23:21:16 +0530 Subject: [PATCH 016/176] dt-bindings: firmware: qcom,scm: Document SCM on Kuno SoC Document the SCM firmware interface found on the Qualcomm Kuno SoC. Reviewed-by: Bartosz Golaszewski Signed-off-by: Hardeep Sharma Link: https://lore.kernel.org/r/20260827-kuno-soc-support-v5-13-6d47636a8f09@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml index 037d4ad8f718..ecee5aef65a7 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -37,6 +37,7 @@ properties: - qcom,scm-ipq9574 - qcom,scm-ipq9650 - qcom,scm-kaanapali + - qcom,scm-kuno - qcom,scm-maili - qcom,scm-mdm9607 - qcom,scm-milos From 6ee19bbd8d14853874336294a9e9aba87f6eaea4 Mon Sep 17 00:00:00 2001 From: Hardeep Sharma Date: Thu, 27 Aug 2026 23:21:04 +0530 Subject: [PATCH 017/176] soc: qcom: geni-se: allow selection on 32-bit ARM Qualcomm SoCs Kuno, a 32-bit ARM Cortex-A7 Qualcomm SoC, uses the GENI-based QUP wrapper for its debug UART. Drop the explicit ARM64 dependency so the driver can be selected on 32-bit ARM as well; QCOM_GENI_SE already sits under the QCOM_SOC menuconfig, which is gated by ARCH_QCOM || COMPILE_TEST, so no replacement dependency is needed. Acked-by: Mukesh Savaliya Reviewed-by: Abel Vesa Signed-off-by: Hardeep Sharma Link: https://lore.kernel.org/r/20260827-kuno-soc-support-v5-1-6d47636a8f09@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 2b524154d9fb..9f703261d7ac 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -39,7 +39,6 @@ config QCOM_COMMAND_DB config QCOM_GENI_SE tristate "Qualcomm GENI Serial Engine Driver" - depends on ARM64 || COMPILE_TEST default ARCH_QCOM help This driver is used to manage Generic Interface (GENI) firmware based From 7c0b82d087908765c6c7daeb06943e21b78d523e Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Wed, 26 Aug 2026 13:14:58 -0700 Subject: [PATCH 018/176] memory: brcmstb_dpfe: Fix out-of-bounds access due to DCPU offset On API v1/v2 boards, the DCPU coprocessor can steer kernel readl_relaxed() and writel_relaxed() to any address within 256 MB of the ioremapped DPFE dmem or regs base. The DCPU firmware provides a 28-bit offset which the driver adds to the ioremap base without any bounds checking in get_msg_ptr(). This allows a compromised DCPU firmware to trick the host kernel into reading or writing arbitrary memory-mapped I/O registers in vmalloc space. When combined with a root-writable sysfs file like dpfe_refresh, it provides an arbitrary MMIO write primitive. Similarly, world-readable sysfs files can be used to leak other devices' register contents. Fix this by recording the resource_size() of the dmem and regs ioremaps at probe time, and rejecting any offset that, along with the largest field accessed (DRAM_VENDOR_ERROR + sizeof(u32)), exceeds the recorded mapping size. Fixes: fee5f1ef6cf7 ("memory: brcmstb: dpfe: support new way of passing data from the DCPU") Cc: stable@vger.kernel.org Signed-off-by: Justin Chen Assisted-by: Gemini:gemini-3.1-pro-preview cursor Signed-off-by: Danesh Petigara Reviewed-by: Florian Fainelli Link: https://patch.msgid.link/20260826201500.3000125-2-danesh.petigara@broadcom.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/brcmstb_dpfe.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c index 08d9e05b1b33..66343205f585 100644 --- a/drivers/memory/brcmstb_dpfe.c +++ b/drivers/memory/brcmstb_dpfe.c @@ -182,6 +182,8 @@ struct brcmstb_dpfe_priv { void __iomem *regs; void __iomem *dmem; void __iomem *imem; + resource_size_t regs_size; + resource_size_t dmem_size; struct device *dev; const struct dpfe_api *dpfe_api; struct mutex lock; @@ -401,9 +403,14 @@ static void __iomem *get_msg_ptr(struct brcmstb_dpfe_priv *priv, u32 response, */ switch (msg_type) { case 1: + if (DCPU_MSG_RAM_START + offset + DRAM_VENDOR_ERROR + + sizeof(u32) > priv->regs_size) + goto bad_offset; ptr = priv->regs + DCPU_MSG_RAM_START + offset; break; case 0: + if (offset + DRAM_VENDOR_ERROR + sizeof(u32) > priv->dmem_size) + goto bad_offset; ptr = priv->dmem + offset; break; default: @@ -415,6 +422,12 @@ static void __iomem *get_msg_ptr(struct brcmstb_dpfe_priv *priv, u32 response, } return ptr; + +bad_offset: + dev_err(priv->dev, "DCPU returned out-of-range offset %#x\n", offset); + if (buf && size) + *size = sprintf(buf, "ERROR: DCPU offset out of range\n"); + return NULL; } static void __finalize_command(struct brcmstb_dpfe_priv *priv) @@ -858,6 +871,7 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct brcmstb_dpfe_priv *priv; + struct resource *res; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -869,17 +883,21 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev) mutex_init(&priv->lock); platform_set_drvdata(pdev, priv); - priv->regs = devm_platform_ioremap_resource_byname(pdev, "dpfe-cpu"); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-cpu"); + priv->regs = devm_ioremap_resource(dev, res); if (IS_ERR(priv->regs)) { dev_err(dev, "couldn't map DCPU registers\n"); return -ENODEV; } + priv->regs_size = resource_size(res); - priv->dmem = devm_platform_ioremap_resource_byname(pdev, "dpfe-dmem"); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-dmem"); + priv->dmem = devm_ioremap_resource(dev, res); if (IS_ERR(priv->dmem)) { dev_err(dev, "Couldn't map DCPU data memory\n"); return -ENOENT; } + priv->dmem_size = resource_size(res); priv->imem = devm_platform_ioremap_resource_byname(pdev, "dpfe-imem"); if (IS_ERR(priv->imem)) { From 6b07f8c06caca015a0db69e3f323b5186469bc66 Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Wed, 26 Aug 2026 13:14:59 -0700 Subject: [PATCH 019/176] memory: brcmstb_dpfe: Bounds check DCPU-supplied MSG_ARG_COUNT A compromised or buggy DCPU coprocessor can make any user who reads world-readable /sys/devices/.../dpfe_info|dpfe_dram trigger a kernel stack out-of-bounds read of arbitrary extent. This bounds checks chksum_idx against MSG_FIELD_MAX after reading the response from DCPU message RAM. Fixes: 5d06f53d9509 ("memory: brcmstb: dpfe: Compute checksum at __send_command() time") Cc: stable@vger.kernel.org Signed-off-by: Justin Chen Assisted-by: Gemini:gemini-3.1-pro-preview cursor Signed-off-by: Danesh Petigara Reviewed-by: Florian Fainelli Link: https://patch.msgid.link/20260826201500.3000125-3-danesh.petigara@broadcom.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/brcmstb_dpfe.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c index 66343205f585..7b02c36c7fca 100644 --- a/drivers/memory/brcmstb_dpfe.c +++ b/drivers/memory/brcmstb_dpfe.c @@ -503,6 +503,8 @@ static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd, for (i = 0; i < MSG_FIELD_MAX; i++) result[i] = readl_relaxed(regs + DCPU_MSG_RAM(i)); chksum_idx = result[MSG_ARG_COUNT] + MSG_ARG_COUNT + 1; + if (chksum_idx >= MSG_FIELD_MAX) + ret = -EINVAL; } /* Tell DCPU we are done */ From 3db1fb5e1bb4c9eefc554f985f6f3316fa1292e5 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 27 Jul 2026 11:34:44 +0100 Subject: [PATCH 020/176] memory: renesas-rpc-if: Mark XSPI_CDD1BUF0 as volatile Add XSPI_CDD1BUF0 to the xSPI regmap volatile register table. XSPI_CDD1BUF0 is a data buffer register used during manual transfers and, like XSPI_CDD0BUF0, its contents are transient and should not be cached by regmap. Mark it as volatile so reads always access the hardware register. Fixes: 687cac9559d8 ("memory: renesas-rpc-if: Add RZ/G3E xSPI support") Cc: stable@vger.kernel.org Signed-off-by: Lad Prabhakar Link: https://patch.msgid.link/20260727103449.3188105-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/renesas-rpc-if.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index 3755956ae906..104c28532c20 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -34,6 +34,7 @@ static const struct regmap_access_table rpcif_volatile_table = { static const struct regmap_range xspi_volatile_ranges[] = { regmap_reg_range(XSPI_CDD0BUF0, XSPI_CDD0BUF0), + regmap_reg_range(XSPI_CDD1BUF0, XSPI_CDD1BUF0), }; static const struct regmap_access_table xspi_volatile_table = { From 12e44bfc2a0e97f139c37b33925cd49d1621fa91 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 27 Jul 2026 11:34:45 +0100 Subject: [PATCH 021/176] memory: renesas-rpc-if: Move static bridge configurations out of dirmap hot paths Move the initialization of the xSPI Bridge Control Register 0 (XSPI_BMCTL0) and Bridge Configuration Register (XSPI_BMCFG) from the dirmap read and write implementations into the hardware initialization function. The bridge configuration values remain unchanged across sequential dirmap transfers. Keeping these regmap_update_bits() calls inside the hot paths (xspi_dirmap_read_impl and xspi_dirmap_write) introduces significant software overhead and redundant register locking cycles. Statically setting CS0ACC to 0x3 during xspi_hw_init_impl() permanently enables the memory area for both read and write operations. Signed-off-by: Lad Prabhakar Link: https://patch.msgid.link/20260727103449.3188105-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/renesas-rpc-if.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index 104c28532c20..50294e5d2bf5 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -312,6 +312,14 @@ static int xspi_hw_init_impl(struct rpcif_priv *xspi, bool hyperflash) regmap_update_bits(xspi->regmap, XSPI_INTE, XSPI_INTE_CMDCMPE, XSPI_INTE_CMDCMPE); + regmap_update_bits(xspi->regmap, XSPI_BMCTL0, + XSPI_BMCTL0_CS0ACC(0xff), XSPI_BMCTL0_CS0ACC(0x03)); + + regmap_update_bits(xspi->regmap, XSPI_BMCFG, + XSPI_BMCFG_WRMD | XSPI_BMCFG_MWRCOMB | + XSPI_BMCFG_MWRSIZE(0xff) | XSPI_BMCFG_PREEN, + 0 | XSPI_BMCFG_MWRCOMB | XSPI_BMCFG_MWRSIZE(0x0f) | + XSPI_BMCFG_PREEN); return 0; } @@ -869,15 +877,6 @@ static size_t xspi_dirmap_read_impl(struct rpcif_priv *xspi, u64 offs, XSPI_CMCFG1_RDCMD_UPPER_BYTE(xspi->command) | XSPI_CMCFG1_RDLATE(xspi->dummy)); - regmap_update_bits(xspi->regmap, XSPI_BMCTL0, XSPI_BMCTL0_CS0ACC(0xff), - XSPI_BMCTL0_CS0ACC(0x01)); - - regmap_update_bits(xspi->regmap, XSPI_BMCFG, - XSPI_BMCFG_WRMD | XSPI_BMCFG_MWRCOMB | - XSPI_BMCFG_MWRSIZE(0xff) | XSPI_BMCFG_PREEN, - 0 | XSPI_BMCFG_MWRCOMB | XSPI_BMCFG_MWRSIZE(0x0f) | - XSPI_BMCFG_PREEN); - regmap_update_bits(xspi->regmap, XSPI_LIOCFGCS0, XSPI_LIOCFG_PRTMD(0x3ff), XSPI_LIOCFG_PRTMD(xspi->proto)); @@ -945,15 +944,6 @@ ssize_t xspi_dirmap_write(struct device *dev, u64 offs, size_t len, const void * XSPI_CMCFG2_WRCMD_UPPER(xspi->command) | XSPI_CMCFG2_WRLATE(xspi->dummy)); - regmap_update_bits(xspi->regmap, XSPI_BMCTL0, - XSPI_BMCTL0_CS0ACC(0xff), XSPI_BMCTL0_CS0ACC(0x03)); - - regmap_update_bits(xspi->regmap, XSPI_BMCFG, - XSPI_BMCFG_WRMD | XSPI_BMCFG_MWRCOMB | - XSPI_BMCFG_MWRSIZE(0xff) | XSPI_BMCFG_PREEN, - 0 | XSPI_BMCFG_MWRCOMB | XSPI_BMCFG_MWRSIZE(0x0f) | - XSPI_BMCFG_PREEN); - regmap_update_bits(xspi->regmap, XSPI_LIOCFGCS0, XSPI_LIOCFG_PRTMD(0x3ff), XSPI_LIOCFG_PRTMD(xspi->proto)); From 008a7b9631864b708ffc06d42264aeef09f09800 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 27 Jul 2026 11:34:46 +0100 Subject: [PATCH 022/176] memory: renesas-rpc-if: Consolidate XSPI_CDTBUF0 updates in write path Program the XSPI_CDTBUF0 TRTYPE, DATASIZE and ADDSIZE fields with a single regmap_update_bits() call in the RPCIF_DATA_OUT transfer path. The existing code updates these fields through three separate read-modify-write operations even though all values are known before the transfer request is issued. Combine the updates into a single register access to reduce overhead and simplify the configuration sequence. Signed-off-by: Lad Prabhakar Link: https://patch.msgid.link/20260727103449.3188105-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/renesas-rpc-if.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index 50294e5d2bf5..e406afc42616 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -660,17 +660,12 @@ static int xspi_manual_xfer_impl(struct rpcif_priv *xspi) u32 bytes_left = xspi->xferlen - pos; u32 nbytes, data[2], *p = data; - regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, - XSPI_CDTBUF_TRTYPE, XSPI_CDTBUF_TRTYPE); - nbytes = bytes_left >= max ? max : bytes_left; regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, - XSPI_CDTBUF_DATASIZE(0xf), - XSPI_CDTBUF_DATASIZE(nbytes)); - - regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, + XSPI_CDTBUF_TRTYPE | XSPI_CDTBUF_DATASIZE(0xf) | XSPI_CDTBUF_ADDSIZE(0x7), + XSPI_CDTBUF_TRTYPE | XSPI_CDTBUF_DATASIZE(nbytes) | XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes)); memcpy(data, xspi->buffer + pos, nbytes); From 26883f764dd66d0c82f258a12a2f0f769e6fc68e Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 27 Jul 2026 11:34:47 +0100 Subject: [PATCH 023/176] memory: renesas-rpc-if: Consolidate XSPI_CDTBUF0 updates in read path Program the XSPI_CDTBUF0 fields used by the RPCIF_DATA_IN transfer path through a single regmap_update_bits() call. The existing code updates TRTYPE, DATASIZE, ADDSIZE and LATE using multiple read-modify-write operations on the same register, even though all field values are known before the transfer starts. Build the register mask and value first, then perform a single register update. This reduces register accesses and simplifies the transfer setup without changing functionality. Signed-off-by: Lad Prabhakar Link: https://patch.msgid.link/20260727103449.3188105-5-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/renesas-rpc-if.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index e406afc42616..c768e9c18556 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -697,30 +697,33 @@ static int xspi_manual_xfer_impl(struct rpcif_priv *xspi) while (pos < xspi->xferlen) { u32 bytes_left = xspi->xferlen - pos; u32 nbytes, data[2], *p = data; - - regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, - XSPI_CDTBUF_TRTYPE, - ~(u32)XSPI_CDTBUF_TRTYPE); + u32 cdtbuf0_mask, cdtbuf0_val; /* nbytes can be up to 8 bytes */ nbytes = bytes_left >= max ? max : bytes_left; - regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, - XSPI_CDTBUF_DATASIZE(0xf), - XSPI_CDTBUF_DATASIZE(nbytes)); + /* clear TRTYPE */ + cdtbuf0_mask = XSPI_CDTBUF_TRTYPE; + cdtbuf0_val = 0; - regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, - XSPI_CDTBUF_ADDSIZE(0x7), - XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes)); + /* program DATASIZE */ + cdtbuf0_mask |= XSPI_CDTBUF_DATASIZE(0xf); + cdtbuf0_val |= XSPI_CDTBUF_DATASIZE(nbytes); + + /* program ADDSIZE */ + cdtbuf0_mask |= XSPI_CDTBUF_ADDSIZE(0x7); + cdtbuf0_val |= XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes); + + /* program LATE */ + cdtbuf0_mask |= XSPI_CDTBUF_LATE(0x1f); + cdtbuf0_val |= XSPI_CDTBUF_LATE(xspi->dummy); + + regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, cdtbuf0_mask, cdtbuf0_val); if (xspi->addr_nbytes) regmap_write(xspi->regmap, XSPI_CDABUF0, xspi->smadr + pos); - regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, - XSPI_CDTBUF_LATE(0x1f), - XSPI_CDTBUF_LATE(xspi->dummy)); - regmap_update_bits(xspi->regmap, XSPI_CDCTL0, XSPI_CDCTL0_TRREQ, XSPI_CDCTL0_TRREQ); From 0c49783b0ed5c3d27efb2d0d91a3272db154458d Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 27 Jul 2026 11:34:48 +0100 Subject: [PATCH 024/176] memory: renesas-rpc-if: Consolidate command setup register programming Simplify the command setup sequence in xspi_manual_xfer_impl() by combining updates to XSPI_CDCTL0 and XSPI_CDTBUF0. Clear the TRNUM and TRREQ fields in XSPI_CDCTL0 with a single regmap_update_bits() call. Likewise, program the command, command size and address size fields in XSPI_CDTBUF0 with a single regmap_write(), eliminating the subsequent ADDSIZE update. The intermediate write of zero to XSPI_CDABUF0 is also redundant, as the register is immediately programmed with the transfer address. Signed-off-by: Lad Prabhakar Link: https://patch.msgid.link/20260727103449.3188105-6-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/renesas-rpc-if.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index c768e9c18556..d98991266887 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -636,18 +636,14 @@ static int xspi_manual_xfer_impl(struct rpcif_priv *xspi) u32 pos = 0, max = 8; int ret = 0; - regmap_update_bits(xspi->regmap, XSPI_CDCTL0, XSPI_CDCTL0_TRNUM(0x3), + /* Clear transaction number and request */ + regmap_update_bits(xspi->regmap, XSPI_CDCTL0, + XSPI_CDCTL0_TRNUM(0x3) | XSPI_CDCTL0_TRREQ, XSPI_CDCTL0_TRNUM(0)); - regmap_update_bits(xspi->regmap, XSPI_CDCTL0, XSPI_CDCTL0_TRREQ, 0); - regmap_write(xspi->regmap, XSPI_CDTBUF0, - XSPI_CDTBUF_CMDSIZE(0x1) | XSPI_CDTBUF_CMD_FIELD(xspi->command)); - - regmap_write(xspi->regmap, XSPI_CDABUF0, 0); - - regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, XSPI_CDTBUF_ADDSIZE(0x7), - XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes)); + XSPI_CDTBUF_CMDSIZE(0x1) | XSPI_CDTBUF_CMD_FIELD(xspi->command) | + XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes)); regmap_write(xspi->regmap, XSPI_CDABUF0, xspi->smadr); From c8d0e87bc2413c6a3f92c7130a4cbad51f8703da Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 27 Jul 2026 11:34:49 +0100 Subject: [PATCH 025/176] memory: renesas-rpc-if: Use runtime PM autosuspend after transfers Replace pm_runtime_put() with pm_runtime_put_autosuspend() after manual transfers and direct memory-mapped read/write operations. Flash page programming may be performed as a sequence of closely spaced transfer operations. Calling pm_runtime_put() after each operation allows the runtime PM core to suspend the controller between successive transfers, introducing unnecessary suspend/resume cycles and potentially interrupting multi-step transfer sequences. Use pm_runtime_put_autosuspend() instead so the controller remains active while transfers continue, allowing it to suspend only after an idle period. Signed-off-by: Lad Prabhakar Tested-by: Wolfram Sang Link: https://patch.msgid.link/20260727103449.3188105-7-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/renesas-rpc-if.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index d98991266887..ec901a5a99aa 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -776,7 +776,7 @@ int rpcif_manual_xfer(struct device *dev) ret = rpc->info->impl->manual_xfer(rpc); - pm_runtime_put(dev); + pm_runtime_put_autosuspend(dev); return ret; } @@ -891,7 +891,7 @@ ssize_t rpcif_dirmap_read(struct device *dev, u64 offs, size_t len, void *buf) read = rpc->info->impl->dirmap_read(rpc, offs, len, buf); - pm_runtime_put(dev); + pm_runtime_put_autosuspend(dev); return read; } @@ -948,7 +948,7 @@ ssize_t xspi_dirmap_write(struct device *dev, u64 offs, size_t len, const void * regmap_update_bits(xspi->regmap, XSPI_BMCTL1, XSPI_BMCTL1_MWRPUSH, XSPI_BMCTL1_MWRPUSH); - pm_runtime_put(dev); + pm_runtime_put_autosuspend(dev); return writebytes; } From a416a347931fec0591795b4f3ab6b2df9ff37dd5 Mon Sep 17 00:00:00 2001 From: James Calligeros Date: Mon, 31 Aug 2026 21:32:39 +1000 Subject: [PATCH 026/176] arm64: Kconfig: Select HAVE_SHARED_GPIOS for Apple Silicon Apple Silicon Macs use a shared GPIO line for all speaker codec shutdown pins. Select HAVE_SHARED_GPIOS for ARCH_APPLE so that we can use the shared GPIO proxy infrastructure for this. Signed-off-by: James Calligeros Link: https://patch.msgid.link/20260831-apple-shared-gpio-v1-1-e855b12e18ce@gmail.com Signed-off-by: Sven Peter --- arch/arm64/Kconfig.platforms | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index d2acfac73003..76a6a0e6ae4f 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -37,6 +37,7 @@ config ARCH_APPLE bool "Apple Silicon SoC family" select APPLE_AIC select APPLE_PMGR_PWRSTATE if PM + select HAVE_SHARED_GPIOS help This enables support for Apple's in-house ARM SoC family, such as the Apple M1. From 8770b189131168ca56e8a3e3850210727a20fb8d Mon Sep 17 00:00:00 2001 From: Biju Das Date: Wed, 26 Aug 2026 13:27:23 +0100 Subject: [PATCH 027/176] soc: renesas: rz-sysc: Register auxiliary device for PWRRDY power sequencer Some RZ SoCs (e.g. RZ/G3L) have a PWRRDY register that is controlled through a power sequencer rather than directly by the SYSC driver. Add a pwrrdy_pwrseq flag to struct rz_sysc_soc_id_init_data to mark SoCs with this property, and set it for RZ/G3L. When set, rz_sysc_probe() registers a "pwrseq-pwrrdy" auxiliary device so a dedicated driver can handle the PWRRDY sequencing. Reviewed-by: Geert Uytterhoeven Signed-off-by: Biju Das Link: https://patch.msgid.link/20260826122742.153643-2-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 1 + drivers/soc/renesas/r9a08g046-sysc.c | 1 + drivers/soc/renesas/rz-sysc.c | 5 +++++ drivers/soc/renesas/rz-sysc.h | 2 ++ 4 files changed, 9 insertions(+) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index e334cc204ad8..3ae9e3cd3899 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -487,6 +487,7 @@ config RZN1_IRQMUX config SYSC_RZ bool "System controller for RZ SoCs" if COMPILE_TEST select MFD_SYSCON + select AUXILIARY_BUS config SYSC_R9A08G045 bool "Renesas System controller support for R9A08G045 (RZ/G3S)" if COMPILE_TEST diff --git a/drivers/soc/renesas/r9a08g046-sysc.c b/drivers/soc/renesas/r9a08g046-sysc.c index 90db9d383539..cd129c727461 100644 --- a/drivers/soc/renesas/r9a08g046-sysc.c +++ b/drivers/soc/renesas/r9a08g046-sysc.c @@ -76,6 +76,7 @@ static const struct rz_sysc_soc_id_init_data rzg3l_sysc_soc_id_init_data __initc .devid_offset = 0xa04, .revision_mask = GENMASK(31, 28), .specific_id_mask = GENMASK(27, 0), + .pwrrdy_pwrseq = true, }; const struct rz_sysc_init_data rzg3l_sysc_init_data __initconst = { diff --git a/drivers/soc/renesas/rz-sysc.c b/drivers/soc/renesas/rz-sysc.c index 161e8c38eea6..0e92c415d4be 100644 --- a/drivers/soc/renesas/rz-sysc.c +++ b/drivers/soc/renesas/rz-sysc.c @@ -5,6 +5,7 @@ * Copyright (C) 2024 Renesas Electronics Corp. */ +#include #include #include #include @@ -149,6 +150,10 @@ static int rz_sysc_probe(struct platform_device *pdev) if (IS_ERR(regmap)) return PTR_ERR(regmap); + if (data->soc_id_init_data->pwrrdy_pwrseq && + !devm_auxiliary_device_create(dev, "pwrseq-pwrrdy", regmap)) + return -ENODEV; + return of_syscon_register_regmap(dev->of_node, regmap); } diff --git a/drivers/soc/renesas/rz-sysc.h b/drivers/soc/renesas/rz-sysc.h index 921ee0d26c47..e55f3258d703 100644 --- a/drivers/soc/renesas/rz-sysc.h +++ b/drivers/soc/renesas/rz-sysc.h @@ -20,6 +20,7 @@ * @revision_mask: SYSC SoC ID revision mask * @specific_id_mask: SYSC SoC ID specific ID mask * @print_id: print SoC-specific extended device identification + * @pwrrdy_pwrseq: has pwrrdy register controlled through power sequencer */ struct rz_sysc_soc_id_init_data { const char * const family; @@ -29,6 +30,7 @@ struct rz_sysc_soc_id_init_data { u32 specific_id_mask; void (*print_id)(struct device *dev, void __iomem *sysc_base, struct soc_device_attribute *soc_dev_attr); + bool pwrrdy_pwrseq; }; /** From 529b0be30bd97dde9fe71c0cc406e252ab1362fe Mon Sep 17 00:00:00 2001 From: Biju Das Date: Wed, 26 Aug 2026 13:27:26 +0100 Subject: [PATCH 028/176] soc: renesas: Kconfig: Select POWER_SEQUENCING_RENESAS_PWRRDY for R9A08G046 The RZ/G3L SYSC driver registers a "pwrseq-pwrrdy" auxiliary device to handle the PWRRDY power sequencing, which requires the pwrseq-renesas-pwrrdy driver to bind to it. Select POWER_SEQUENCING_RENESAS_PWRRDY from SYSC_R9A08G046 so it's built whenever RZ/G3L SYSC support is enabled. Reviewed-by: Geert Uytterhoeven Signed-off-by: Biju Das Link: https://patch.msgid.link/20260826122742.153643-5-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 3ae9e3cd3899..817b2a1a7445 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -496,6 +496,8 @@ config SYSC_R9A08G045 config SYSC_R9A08G046 bool "Renesas System controller support for R9A08G046 (RZ/G3L)" if COMPILE_TEST select SYSC_RZ + select POWER_SEQUENCING + select POWER_SEQUENCING_RENESAS_PWRRDY config SYS_R9A09G047 bool "Renesas System controller support for R9A09G047 (RZ/G3E)" if COMPILE_TEST From e61c1a1103e2617e8f86288368911a8591e35c1e Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Sat, 15 Aug 2026 21:45:59 +0800 Subject: [PATCH 029/176] memory: brcmstb_dpfe: validate firmware section sizes The firmware header is read before the image has been shown to contain a complete header. In addition, the final size check adds two firmware-provided u32 section lengths before comparing the result with fw->size, so the addition can wrap. Reject images shorter than the fixed header and checksum before reading the header. Then derive the available payload length with subtraction and require the two declared sections to fill it exactly. Fixes: 2f330caff577 ("memory: brcmstb: Add driver for DPFE") Assisted-by: Codex:gpt-5 Signed-off-by: Pengpeng Hou Link: https://patch.msgid.link/20260815134559.47888-1-pengpeng@iscas.ac.cn Signed-off-by: Krzysztof Kozlowski --- drivers/memory/brcmstb_dpfe.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c index 7b02c36c7fca..04ae3cfb449e 100644 --- a/drivers/memory/brcmstb_dpfe.c +++ b/drivers/memory/brcmstb_dpfe.c @@ -533,9 +533,15 @@ static int __verify_firmware(struct init_data *init, const struct firmware *fw) { const struct dpfe_firmware_header *header = (void *)fw->data; - unsigned int dmem_size, imem_size, total_size; + unsigned int dmem_size, imem_size; bool is_big_endian = false; const u32 *chksum_ptr; + size_t payload_size; + + if (fw->size < sizeof(*header) + sizeof(*chksum_ptr)) + return ERR_INVALID_SIZE; + + payload_size = fw->size - sizeof(*header) - sizeof(*chksum_ptr); if (header->magic == DPFE_BE_MAGIC) is_big_endian = true; @@ -554,13 +560,8 @@ static int __verify_firmware(struct init_data *init, if ((dmem_size % sizeof(u32)) != 0 || (imem_size % sizeof(u32)) != 0) return ERR_INVALID_SIZE; - /* - * The header + the data section + the instruction section + the - * checksum must be equal to the total firmware size. - */ - total_size = dmem_size + imem_size + sizeof(*header) + - sizeof(*chksum_ptr); - if (total_size != fw->size) + /* The data and instruction sections must fill the payload exactly. */ + if (dmem_size > payload_size || imem_size != payload_size - dmem_size) return ERR_INVALID_SIZE; /* The checksum comes at the very end. */ From 3de7d6f8dd121d5d4b74182765be5ee8f3954d29 Mon Sep 17 00:00:00 2001 From: Aiden Isik Date: Tue, 18 Aug 2026 16:05:42 +0100 Subject: [PATCH 030/176] dt-bindings: hwinfo: samsung,exynos-chipid: Add Exynos5515 compatible Add "samsung,exynos5515-chipid" compatible string to binding document, which is fully compatible with "samsung,exynos850-chipid". Signed-off-by: Aiden Isik Link: https://patch.msgid.link/20260818-for-next-lucky7-chipid-v2-1-28ae49f5c349@member.fsf.org Signed-off-by: Krzysztof Kozlowski --- .../devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml b/Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml index b9cdfe52b62f..619faf33214b 100644 --- a/Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml +++ b/Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml @@ -25,6 +25,7 @@ properties: - items: - enum: - samsung,exynos2200-chipid + - samsung,exynos5515-chipid - samsung,exynos7885-chipid - samsung,exynos8895-chipid - samsung,exynos9610-chipid From 2f04ec82e51da9d5af5cb48c9f24c0318655b0f7 Mon Sep 17 00:00:00 2001 From: Aiden Isik Date: Tue, 18 Aug 2026 16:05:43 +0100 Subject: [PATCH 031/176] soc: samsung: exynos-chipid: Add Exynos5515 SoC support Add Exynos5515 information to the soc_ids table. The ChipID for Exynos5515 is "0xE5515000". Signed-off-by: Aiden Isik Link: https://patch.msgid.link/20260818-for-next-lucky7-chipid-v2-2-28ae49f5c349@member.fsf.org Signed-off-by: Krzysztof Kozlowski --- drivers/soc/samsung/exynos-chipid.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c index 6ef9751e2509..506a0bcdfe30 100644 --- a/drivers/soc/samsung/exynos-chipid.c +++ b/drivers/soc/samsung/exynos-chipid.c @@ -64,6 +64,7 @@ static const struct exynos_soc_id { { "EXYNOS8890", 0xE8890000 }, /* Compatible with: samsung,exynos850-chipid */ { "EXYNOS2200", 0xE9925000 }, + { "EXYNOS5515", 0xE5515000 }, { "EXYNOS7885", 0xE7885000 }, { "EXYNOS850", 0xE3830000 }, { "EXYNOS8895", 0xE8895000 }, From 8676f8e6dc8da769d5192135992a78853f9ea048 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 21 Aug 2026 09:44:12 +0200 Subject: [PATCH 032/176] memory: emif: Replace __ASSEMBLY__ with __ASSEMBLER__ in non-uapi headers While the GCC and Clang compilers already define __ASSEMBLER__ auto- matically when compiling assembly code, __ASSEMBLY__ is a macro that only gets defined by the Makefiles in the kernel. This can be very confusing when switching between userspace and kernelspace coding, or when dealing with uapi headers that rather should use __ASSEMBLER__ instead. Let's standardize now on the __ASSEMBLER__ macro to avoid this confusion. Signed-off-by: Thomas Huth Link: https://patch.msgid.link/20260821074412.144248-1-thuth@redhat.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/emif.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h index 55aeb36a5bf2..5dfb09adb096 100644 --- a/drivers/memory/emif.h +++ b/drivers/memory/emif.h @@ -558,7 +558,7 @@ #define EMIF_SRAM_AM33_REG_LAYOUT 0x00000000 #define EMIF_SRAM_AM43_REG_LAYOUT 0x00000001 -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ /* * Structure containing shadow of important registers in EMIF * The calculation function fills in this structure to be later used for @@ -603,5 +603,5 @@ void ti_emif_enter_sr(void); void ti_emif_exit_sr(void); void ti_emif_abort_sr(void); -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif /* __EMIF_H */ From 5c58f5e2d5a0088c3a8857a3d8fdea798782e1f9 Mon Sep 17 00:00:00 2001 From: Hemanth Selam Date: Fri, 4 Sep 2026 18:05:38 +0530 Subject: [PATCH 033/176] firmware: ti_sci: Fix typo "upto" in comments Correct "upto" to "up to", reported by scripts/checkpatch.pl using the misspelling list in scripts/spelling.txt. Only touches comments, no code changes. Assisted-by: Cursor:claude-opus-5 Signed-off-by: Hemanth Selam Link: https://patch.msgid.link/20260904123541.38602-2-hemanth.selam@gmail.com Signed-off-by: Nishanth Menon --- drivers/firmware/ti_sci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index cc747ab0237f..94104edba9a0 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -4050,7 +4050,7 @@ static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = { .default_host_id = 2, /* Conservative duration */ .max_rx_timeout_ms = 1000, - /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */ + /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle up to 128 messages! */ .max_msgs = 20, .max_msg_size = 64, }; @@ -4060,7 +4060,7 @@ static const struct ti_sci_desc ti_sci_pmmc_am654_desc = { .default_host_id = 12, /* Conservative duration */ .max_rx_timeout_ms = 10000, - /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */ + /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle up to 128 messages! */ .max_msgs = 20, .max_msg_size = 60, }; From 504e3ae911d1398c2941063fcbe979a2e6aa90cd Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 17 Aug 2026 11:53:34 +0200 Subject: [PATCH 034/176] soc: renesas: rcar-mfis: Add hwspinlock support Every MFIS instance has a block of hardware spinlocks. Add support for them. R-Car Gen4 has only one instance, so the base_id is always 0. R-Car Gen5 has multiple instances, so the base_id has to be encoded in the info description. Also being a provider, a hwspinlock-private header needs to be included. Work to refactor the headers is on-going, but will need many preparational steps. Until then, we need to live with the special include. Signed-off-by: Wolfram Sang Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260817095447.34693-3-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 2 +- drivers/soc/renesas/rcar-mfis.c | 54 ++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 817b2a1a7445..64f9e4be2f63 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -468,7 +468,7 @@ endif # RISCV config RCAR_MFIS tristate "Renesas R-Car MFIS driver" depends on ARCH_RENESAS || COMPILE_TEST - depends on MAILBOX + depends on MAILBOX && HWSPINLOCK help Select this option to enable support for the Renesas R-Car Multifunctional Interface (MFIS) device found on SoCs like R-Car. diff --git a/drivers/soc/renesas/rcar-mfis.c b/drivers/soc/renesas/rcar-mfis.c index c327a60789d0..d5bbc3077373 100644 --- a/drivers/soc/renesas/rcar-mfis.c +++ b/drivers/soc/renesas/rcar-mfis.c @@ -8,6 +8,7 @@ */ #include #include +#include #include #include #include @@ -19,12 +20,18 @@ #include #include +/* FIXME: hwspinlock core refactoring to not need internal header is on-going */ +#include "../../hwspinlock/hwspinlock_internal.h" + +#define MFISLCKR0 0xc0 +#define MFISLCKR8 0x0724 #define MFISWPCNTR 0x0900 #define MFISWACNTR 0x0904 #define MFIS_X5H_IICR(i) ((i) * 0x1000 + 0x00) #define MFIS_X5H_EICR(i) ((i) * 0x1000 + 0x04) +#define MFIS_NUM_LOCKS 64 #define MFIS_UNPROTECT_KEY 0xACCE0000 struct mfis_priv; @@ -42,6 +49,7 @@ struct mfis_info { unsigned int mb_tx_uses_eicr:1; unsigned int mb_channels_are_unidir:1; u32 (*mb_calc_reg)(u32 chan_num, bool tx_uses_eicr, bool is_only_rx); + int hwsp_base_id; }; struct mfis_chan_priv { @@ -59,6 +67,9 @@ struct mfis_priv { /* mailbox private data */ struct mbox_controller mbox; struct mfis_chan_priv *chan_privs; + + /* hwspinlock private data */ + struct hwspinlock_device bank; /* flex array inside, must be last! */ }; static u32 mfis_read(struct mfis_reg *mreg, unsigned int reg) @@ -86,6 +97,38 @@ static void mfis_write(struct mfis_reg *mreg, u32 reg, u32 val) raw_spin_unlock_irqrestore(&priv->unprotect_lock, flags); } +/******************************************************** + * HW Spinlocks * + ********************************************************/ + +#define MFISLCKR8_CH_OFS (MFISLCKR8 - 8 * sizeof(u32)) + +static int rcar_mfis_hwsp_trylock(struct hwspinlock *lock) +{ + struct mfis_priv *priv = lock->priv; + int id = hwlock_to_id(lock) - lock->bank->base_id; + u32 val, reg; + + reg = id * sizeof(u32) + (id < 8 ? MFISLCKR0 : MFISLCKR8_CH_OFS); + val = mfis_read(&priv->common_reg, reg); + return !val; +} + +static void rcar_mfis_hwsp_unlock(struct hwspinlock *lock) +{ + struct mfis_priv *priv = lock->priv; + int id = hwlock_to_id(lock) - lock->bank->base_id; + u32 reg; + + reg = id * sizeof(u32) + (id < 8 ? MFISLCKR0 : MFISLCKR8_CH_OFS); + mfis_write(&priv->common_reg, reg, 0); +} + +static const struct hwspinlock_ops rcar_mfis_hwsp_ops = { + .trylock = rcar_mfis_hwsp_trylock, + .unlock = rcar_mfis_hwsp_unlock, +}; + /******************************************************** * Mailbox * ********************************************************/ @@ -314,7 +357,7 @@ static int mfis_probe(struct platform_device *pdev) struct mfis_priv *priv; int ret; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(dev, struct_size(priv, bank.lock, MFIS_NUM_LOCKS), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -333,6 +376,14 @@ static int mfis_probe(struct platform_device *pdev) if (ret) return ret; + for (unsigned int ch = 0; ch < MFIS_NUM_LOCKS; ch++) + priv->bank.lock[ch].priv = priv; + + ret = devm_hwspin_lock_register(dev, &priv->bank, &rcar_mfis_hwsp_ops, + priv->info->hwsp_base_id, MFIS_NUM_LOCKS); + if (ret) + return ret; + return mfis_mb_probe(priv); } @@ -357,6 +408,7 @@ static const struct mfis_info mfis_info_r8a78000_scp = { .mb_tx_uses_eicr = true, .mb_channels_are_unidir = true, .mb_calc_reg = mfis_mb_r8a78000_calc_reg, + .hwsp_base_id = MFIS_NUM_LOCKS, }; static const struct of_device_id mfis_mfd_of_match[] = { From 4822cac9ea17399fea1ea192cf8b7d98066c0076 Mon Sep 17 00:00:00 2001 From: Ayman Chaudhry Date: Fri, 21 Aug 2026 15:03:26 +0000 Subject: [PATCH 035/176] soc: renesas: Identify RZ/G2M v3.0 SoC Add support to identify the Renesas RZ/G2M v3.0 (a.k.a. R8A774A3) SoC. The RZ/G2M v3.0 is assigned the same Product ID Number in the Product Register as the Renesas RZ/G2M v1.3 (a.k.a. R8A774A1), so use the same SoC data. Signed-off-by: Ayman Chaudhry Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260821150408.73829-2-ayman.chaudhry.kc@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 7 +++++++ drivers/soc/renesas/renesas-soc.c | 3 +++ 2 files changed, 10 insertions(+) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 64f9e4be2f63..0f6d53abd86c 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -227,6 +227,13 @@ config ARCH_R8A774A1 help This enables support for the Renesas RZ/G2M SoC. +config ARCH_R8A774A3 + bool "ARM64 Platform support for R8A774A3 (RZ/G2M v3.0)" + default y if ARCH_RENESAS + select ARCH_RCAR_GEN3 + help + This enables support for the Renesas RZ/G2M SoC (version 3.0). + config ARCH_R8A774B1 bool "ARM64 Platform support for R8A774B1 (RZ/G2N)" default y if ARCH_RENESAS diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index 18acca73064c..5a5d05013eb7 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -312,6 +312,9 @@ static const struct of_device_id renesas_socs[] __initconst __maybe_unused = { #ifdef CONFIG_ARCH_R8A774A1 { .compatible = "renesas,r8a774a1", .data = &soc_rz_g2m }, #endif +#ifdef CONFIG_ARCH_R8A774A3 + { .compatible = "renesas,r8a774a3", .data = &soc_rz_g2m }, +#endif #ifdef CONFIG_ARCH_R8A774B1 { .compatible = "renesas,r8a774b1", .data = &soc_rz_g2n }, #endif From 10eeafc3e90ebbe6627a7d471b86af889d7b07e5 Mon Sep 17 00:00:00 2001 From: Ayman Chaudhry Date: Fri, 21 Aug 2026 15:03:30 +0000 Subject: [PATCH 036/176] soc: renesas: rcar-rst: Add support for RZ/G2M v3.0 Add support for Renesas RZ/G2M v3.0 (a.k.a. R8A774A3) SoC to the R-Car RST driver. Signed-off-by: Ayman Chaudhry Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260821150408.73829-6-ayman.chaudhry.kc@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/rcar-rst.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c index 0541990901fc..26f976880d3f 100644 --- a/drivers/soc/renesas/rcar-rst.c +++ b/drivers/soc/renesas/rcar-rst.c @@ -93,6 +93,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = { { .compatible = "renesas,r8a77470-rst", .data = &rcar_rst_gen2 }, /* RZ/G2 is handled like R-Car Gen3 */ { .compatible = "renesas,r8a774a1-rst", .data = &rcar_rst_gen3 }, + { .compatible = "renesas,r8a774a3-rst", .data = &rcar_rst_gen3 }, { .compatible = "renesas,r8a774b1-rst", .data = &rcar_rst_gen3 }, { .compatible = "renesas,r8a774c0-rst", .data = &rcar_rst_gen3 }, { .compatible = "renesas,r8a774e1-rst", .data = &rcar_rst_gen3 }, From 5af2ccc8ec749d98d3d0bed4b9df25781d7f2d46 Mon Sep 17 00:00:00 2001 From: "Christophe Leroy (CS GROUP)" Date: Fri, 7 Aug 2026 07:35:52 +0200 Subject: [PATCH 037/176] soc: fsl: qe: Fix sparse warnings in GPIO A C=2 build on mpc83xx_defconfig provides following warnings: drivers/soc/fsl/qe/gpio.c:44:34: warning: incorrect type in assignment (different base types) drivers/soc/fsl/qe/gpio.c:44:34: expected restricted __be32 [usertype] cpdata drivers/soc/fsl/qe/gpio.c:44:34: got unsigned int [usertype] cpdata drivers/soc/fsl/qe/gpio.c:45:34: warning: incorrect type in assignment (different base types) drivers/soc/fsl/qe/gpio.c:45:34: expected restricted __be32 [usertype] cpdir1 drivers/soc/fsl/qe/gpio.c:45:34: got unsigned int drivers/soc/fsl/qe/gpio.c:46:34: warning: incorrect type in assignment (different base types) drivers/soc/fsl/qe/gpio.c:46:34: expected restricted __be32 [usertype] cpdir2 drivers/soc/fsl/qe/gpio.c:46:34: got unsigned int drivers/soc/fsl/qe/gpio.c:47:34: warning: incorrect type in assignment (different base types) drivers/soc/fsl/qe/gpio.c:47:34: expected restricted __be32 [usertype] cppar1 drivers/soc/fsl/qe/gpio.c:47:34: got unsigned int drivers/soc/fsl/qe/gpio.c:48:34: warning: incorrect type in assignment (different base types) drivers/soc/fsl/qe/gpio.c:48:34: expected restricted __be32 [usertype] cppar2 drivers/soc/fsl/qe/gpio.c:48:34: got unsigned int drivers/soc/fsl/qe/gpio.c:49:33: warning: incorrect type in assignment (different base types) drivers/soc/fsl/qe/gpio.c:49:33: expected restricted __be32 [usertype] cpodr drivers/soc/fsl/qe/gpio.c:49:33: got unsigned int drivers/soc/fsl/qe/gpio.c:297:17: warning: restricted __be32 degrades to integer drivers/soc/fsl/qe/gpio.c:299:17: warning: restricted __be32 degrades to integer drivers/soc/fsl/qe/gpio.c:302:17: warning: restricted __be32 degrades to integer drivers/soc/fsl/qe/gpio.c:304:17: warning: restricted __be32 degrades to integer drivers/soc/fsl/qe/gpio.c:308:18: warning: restricted __be32 degrades to integer drivers/soc/fsl/qe/gpio.c:314:9: warning: restricted __be32 degrades to integer The problem is the 'struct qe_pio_reg' embedded in 'struct qe_gpio_chip' to save register values. As the values are read with ioread32be(), they are now in CPU byte order and can't be stored as-is in a __be32 object. Replace 'struct qe_pio_reg saved_regs' by individual u32 fields. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202608051952.ADkLIB86-lkp@intel.com/ Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202608130908.gEy44F1D-lkp@intel.com/ Link: https://lore.kernel.org/r/6a84b38e766729676b375c93bf54c67ea455288d.1786080840.git.chleroy@kernel.org Signed-off-by: Christophe Leroy (CS GROUP) --- drivers/soc/fsl/qe/gpio.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index 5cd59cfbf22f..8e210f8a3b6c 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -32,8 +32,13 @@ struct qe_gpio_chip { /* shadowed data register to clear/set bits safely */ u32 cpdata; - /* saved_regs used to restore dedicated functions */ - struct qe_pio_regs saved_regs; + /* saved regs used to restore dedicated functions */ + u32 saved_cpodr; + u32 saved_cpdata; + u32 saved_cpdir1; + u32 saved_cpdir2; + u32 saved_cppar1; + u32 saved_cppar2; }; static void qe_gpio_save_regs(struct qe_gpio_chip *qe_gc) @@ -41,12 +46,12 @@ static void qe_gpio_save_regs(struct qe_gpio_chip *qe_gc) struct qe_pio_regs __iomem *regs = qe_gc->regs; qe_gc->cpdata = ioread32be(®s->cpdata); - qe_gc->saved_regs.cpdata = qe_gc->cpdata; - qe_gc->saved_regs.cpdir1 = ioread32be(®s->cpdir1); - qe_gc->saved_regs.cpdir2 = ioread32be(®s->cpdir2); - qe_gc->saved_regs.cppar1 = ioread32be(®s->cppar1); - qe_gc->saved_regs.cppar2 = ioread32be(®s->cppar2); - qe_gc->saved_regs.cpodr = ioread32be(®s->cpodr); + qe_gc->saved_cpdata = qe_gc->cpdata; + qe_gc->saved_cpdir1 = ioread32be(®s->cpdir1); + qe_gc->saved_cpdir2 = ioread32be(®s->cpdir2); + qe_gc->saved_cppar1 = ioread32be(®s->cppar1); + qe_gc->saved_cppar2 = ioread32be(®s->cppar2); + qe_gc->saved_cpodr = ioread32be(®s->cpodr); } static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio) @@ -284,7 +289,6 @@ void qe_pin_set_dedicated(struct qe_pin *qe_pin) { struct qe_gpio_chip *qe_gc = qe_pin->controller; struct qe_pio_regs __iomem *regs = qe_gc->regs; - struct qe_pio_regs *sregs = &qe_gc->saved_regs; int pin = qe_pin->num; u32 mask1 = 1 << (QE_PIO_PINS - (pin + 1)); u32 mask2 = 0x3 << (QE_PIO_PINS - (pin % (QE_PIO_PINS / 2) + 1) * 2); @@ -294,24 +298,20 @@ void qe_pin_set_dedicated(struct qe_pin *qe_pin) spin_lock_irqsave(&qe_gc->lock, flags); if (second_reg) { - qe_clrsetbits_be32(®s->cpdir2, mask2, - sregs->cpdir2 & mask2); - qe_clrsetbits_be32(®s->cppar2, mask2, - sregs->cppar2 & mask2); + qe_clrsetbits_be32(®s->cpdir2, mask2, qe_gc->saved_cpdir2 & mask2); + qe_clrsetbits_be32(®s->cppar2, mask2, qe_gc->saved_cppar2 & mask2); } else { - qe_clrsetbits_be32(®s->cpdir1, mask2, - sregs->cpdir1 & mask2); - qe_clrsetbits_be32(®s->cppar1, mask2, - sregs->cppar1 & mask2); + qe_clrsetbits_be32(®s->cpdir1, mask2, qe_gc->saved_cpdir1 & mask2); + qe_clrsetbits_be32(®s->cppar1, mask2, qe_gc->saved_cppar1 & mask2); } - if (sregs->cpdata & mask1) + if (qe_gc->saved_cpdata & mask1) qe_gc->cpdata |= mask1; else qe_gc->cpdata &= ~mask1; iowrite32be(qe_gc->cpdata, ®s->cpdata); - qe_clrsetbits_be32(®s->cpodr, mask1, sregs->cpodr & mask1); + qe_clrsetbits_be32(®s->cpodr, mask1, qe_gc->saved_cpodr & mask1); spin_unlock_irqrestore(&qe_gc->lock, flags); } EXPORT_SYMBOL(qe_pin_set_dedicated); From bada60f2d98c7cf252b1f8214e5b6ec96c429588 Mon Sep 17 00:00:00 2001 From: Hemanth Selam Date: Fri, 4 Sep 2026 18:15:36 +0530 Subject: [PATCH 038/176] bus: fsl-mc: fix repeated word 'for' in comment Drop the second 'for', reported by checkpatch.pl as a possible repeated word. Only touches a comment, no code changes. Assisted-by: Cursor:claude-opus-5 Signed-off-by: Hemanth Selam Link: https://lore.kernel.org/r/20260904124540.7652-3-hemanth.selam@gmail.com Signed-off-by: Christophe Leroy (CS GROUP) --- drivers/bus/fsl-mc/fsl-mc-msi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bus/fsl-mc/fsl-mc-msi.c b/drivers/bus/fsl-mc/fsl-mc-msi.c index be38b43803de..7d760bfa63c1 100644 --- a/drivers/bus/fsl-mc/fsl-mc-msi.c +++ b/drivers/bus/fsl-mc/fsl-mc-msi.c @@ -57,7 +57,7 @@ static void fsl_mc_write_msi_msg(struct msi_desc *msi_desc, struct msi_msg *msg) } } else { /* - * IRQ is for for a child device of mc_bus_dev + * IRQ is for a child device of mc_bus_dev */ error = dprc_set_obj_irq(mc_bus_dev->mc_io, MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, From f85e5ec18eb104574433caec67f452dd6e02d5de Mon Sep 17 00:00:00 2001 From: Vincent Jardin Date: Fri, 31 Jul 2026 22:13:49 +0200 Subject: [PATCH 039/176] bus: fsl-mc: set dma_mask for the DPRC devices On Layerscape platforms when SMMU is disabled by ATF, the root DPRC probes with its dma_mask pointer unset which leads to a notification: "DMA mask not set" so the device is left with a zero DMA mask instead of a sane default. Let's seed the masks for all cases. It was tested on LX2160A with no SMMU on the MC domain: the warning is gone and the DPAA2 children probe unchanged. Signed-off-by: Vincent Jardin Reviewed-by: Ioana Ciornei Link: https://lore.kernel.org/r/20260731-for-upstream-fsl-mc-dprc-dma-mask-v2-1-ea7058b90f06@free.fr Signed-off-by: Christophe Leroy (CS GROUP) --- drivers/bus/fsl-mc/fsl-mc-bus.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index 66a4fa73c5b8..0766ccb68629 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -797,6 +797,10 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, } dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); + mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; + mc_dev->dev.dma_mask = &mc_dev->dma_mask; + mc_dev->dev.coherent_dma_mask = mc_dev->dma_mask; + if (strcmp(obj_desc->type, "dprc") == 0) { struct fsl_mc_io *mc_io2; @@ -838,9 +842,6 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, * parent's ICID. */ mc_dev->icid = parent_mc_dev->icid; - mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; - mc_dev->dev.dma_mask = &mc_dev->dma_mask; - mc_dev->dev.coherent_dma_mask = mc_dev->dma_mask; } /* From 75effa447550c6eeb1198942e6b55dabeeb2dc64 Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Mon, 13 Jul 2026 19:29:46 +0800 Subject: [PATCH 040/176] cache: sifive_ccache: Remove redundant dev_err_probe() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err_probe() calls. Signed-off-by: Pan Chuang Signed-off-by: Conor Dooley --- drivers/cache/sifive_ccache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cache/sifive_ccache.c b/drivers/cache/sifive_ccache.c index 2acb8bdf06d5..71d3f94987fa 100644 --- a/drivers/cache/sifive_ccache.c +++ b/drivers/cache/sifive_ccache.c @@ -275,7 +275,7 @@ static int sifive_ccache_probe(struct platform_device *pdev) rc = devm_request_irq(dev, g_irq[i], ccache_int_handler, 0, "ccache_ecc", NULL); if (rc) - return dev_err_probe(dev, rc, "Could not request IRQ %d\n", g_irq[i]); + return rc; } return 0; From 525e00a1bbced112f5431448842b27fa7621725f Mon Sep 17 00:00:00 2001 From: Hrushiraj Gandhi Date: Tue, 1 Sep 2026 12:59:50 +0530 Subject: [PATCH 041/176] firmware: microchip: use kzalloc_objs() instead of kzalloc() with multiply response_msg is sized as AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg) by hand in both call sites. Use kzalloc_objs() instead, matching the kzalloc_obj() already used elsewhere in this same file for the other allocations in these functions, and getting the same overflow-checked size computation kzalloc_obj() already benefits from. No functional change. Signed-off-by: Hrushiraj Gandhi Signed-off-by: Conor Dooley --- drivers/firmware/microchip/mpfs-auto-update.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/microchip/mpfs-auto-update.c b/drivers/firmware/microchip/mpfs-auto-update.c index 1211fd8d0463..b97d34bd2354 100644 --- a/drivers/firmware/microchip/mpfs-auto-update.c +++ b/drivers/firmware/microchip/mpfs-auto-update.c @@ -156,7 +156,7 @@ static int mpfs_auto_update_verify_image(struct fw_upload *fw_uploader) { struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle; u32 *response_msg __free(kfree) = - kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL); + kzalloc_objs(*response_msg, AUTO_UPDATE_FEATURE_RESP_SIZE); struct mpfs_mss_response *response __free(kfree) = kzalloc_obj(struct mpfs_mss_response); struct mpfs_mss_msg *message __free(kfree) = @@ -358,7 +358,7 @@ static const struct fw_upload_ops mpfs_auto_update_ops = { static int mpfs_auto_update_available(struct mpfs_auto_update_priv *priv) { u32 *response_msg __free(kfree) = - kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL); + kzalloc_objs(*response_msg, AUTO_UPDATE_FEATURE_RESP_SIZE); struct mpfs_mss_response *response __free(kfree) = kzalloc_obj(struct mpfs_mss_response); struct mpfs_mss_msg *message __free(kfree) = From 6c5388154299ee0b5ab2c654d5f3631bafd524a7 Mon Sep 17 00:00:00 2001 From: Justin Yeh Date: Thu, 3 Sep 2026 14:21:24 +0800 Subject: [PATCH 042/176] soc: mediatek: mtk-regulator-coupler: Add support for MT8189 MT8189 couples its GPU supply (buck_vgpu) with the GPU SRAM supply (ldo_sram_gpu), which is exactly the GPU<->SRAM relationship this coupler already handles for MT8183, MT8186, MT8188 and MT8192. Register the coupler on MT8189 as well so that both supplies stay voltage-balanced. Signed-off-by: Justin Yeh Signed-off-by: AngeloGioacchino Del Regno --- drivers/soc/mediatek/mtk-regulator-coupler.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/mediatek/mtk-regulator-coupler.c b/drivers/soc/mediatek/mtk-regulator-coupler.c index 0b6a2884145e..1109e3d9a319 100644 --- a/drivers/soc/mediatek/mtk-regulator-coupler.c +++ b/drivers/soc/mediatek/mtk-regulator-coupler.c @@ -148,6 +148,7 @@ static int mediatek_regulator_coupler_init(void) if (!of_machine_is_compatible("mediatek,mt8183") && !of_machine_is_compatible("mediatek,mt8186") && !of_machine_is_compatible("mediatek,mt8188") && + !of_machine_is_compatible("mediatek,mt8189") && !of_machine_is_compatible("mediatek,mt8192")) return 0; From 7d5b79cd7d59dd114fb1eb5f60aaac92333edf0e Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Sat, 8 Aug 2026 20:12:34 +0100 Subject: [PATCH 043/176] include: trace: Use string helpers in msg_dump trace events Use proper available ftrace macros to handle tag strings of variable size, to avoid wasting space using statically oversized arrays while risking to expose stale stack data when such array is not properly padded when filled. Signed-off-by: Cristian Marussi Link: https://patch.msgid.link/20260808191234.402312-1-cristian.marussi@arm.com Signed-off-by: Sudeep Holla --- include/trace/events/scmi.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/include/trace/events/scmi.h b/include/trace/events/scmi.h index 703b7bb68e44..b421c253df00 100644 --- a/include/trace/events/scmi.h +++ b/include/trace/events/scmi.h @@ -7,8 +7,6 @@ #include -#define TRACE_SCMI_MAX_TAG_LEN 6 - TRACE_EVENT(scmi_fc_call, TP_PROTO(u8 protocol_id, u8 msg_id, u32 res_id, u32 val1, u32 val2), TP_ARGS(protocol_id, msg_id, res_id, val1, val2), @@ -156,7 +154,7 @@ TRACE_EVENT(scmi_msg_dump, __field(u8, channel_id) __field(u8, protocol_id) __field(u8, msg_id) - __array(char, tag, TRACE_SCMI_MAX_TAG_LEN) + __string(tag, tag) __field(u16, seq) __field(int, status) __field(size_t, len) @@ -168,7 +166,7 @@ TRACE_EVENT(scmi_msg_dump, __entry->channel_id = channel_id; __entry->protocol_id = protocol_id; __entry->msg_id = msg_id; - strscpy(__entry->tag, tag, TRACE_SCMI_MAX_TAG_LEN); + __assign_str(tag); __entry->seq = seq; __entry->status = status; __entry->len = len; @@ -177,7 +175,7 @@ TRACE_EVENT(scmi_msg_dump, TP_printk("id=%d ch=%02X pt=%02X t=%s msg_id=%02X seq=%04X s=%d pyld=%s", __entry->id, __entry->channel_id, __entry->protocol_id, - __entry->tag, __entry->msg_id, __entry->seq, __entry->status, + __get_str(tag), __entry->msg_id, __entry->seq, __entry->status, __print_hex_str(__get_dynamic_array(cmd), __entry->len)) ); #endif /* _TRACE_SCMI_H */ From 49fc5bc04eec2b7687d49ccceb7adf6ace640a3b Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 9 Sep 2026 04:32:27 +0000 Subject: [PATCH 044/176] firmware: arm_scmi: Protect xfer->async_done with xfer->lock Asynchronous SCMI commands are completed by a delayed response. The RX path signals the response with complete(xfer->async_done). Unlike xfer->done, xfer->async_done is a pointer to a completion owned by whoever is waiting for the delayed response, and it stays valid only for as long as that waiter is still waiting. In do_xfer_with_response() it is a DECLARE_COMPLETION_ONSTACK() in the caller's stack frame. Nothing serialises the RX path against a waiter that gives up on a timeout. scmi_msg_response_validate() does read xfer->async_done under xfer->lock, and documents that as a requirement, but the lock is dropped again before scmi_handle_response() dereferences the pointer, and neither the arming nor the disarming side takes it at all. So a delayed response arriving just as the wait times out can be signalled on a completion that is already gone: waiter RX path (IRQ context) ------ --------------------- do_xfer_with_response(): xfer->async_done = &async_response do_xfer(xfer) wait_for_completion_timeout(xfer->async_done, tmo) /* returns 0, gives up */ /* response receive interrupt */ scmi_handle_response(): scmi_xfer_command_acquire() lock xfer->lock validate: async_done != NULL unlock xfer->lock xfer->async_done = NULL return -ETIMEDOUT /* async_response goes out of scope */ complete(xfer->async_done) That last complete() has two possible bad outcomes: it either dereferences the NULL just stored by the waiter or - if that store is not yet visible on the RX CPU - it takes a lock and writes to a stack frame that the waiter may already have returned from. Fix this by making xfer->lock cover xfer->async_done end-to-end. Add helpers to arm and disarm it under the lock, use them on both the regular and the raw paths, and have the RX path read and signal the completion under that same lock. A waiter that is timing out then either completes its disarm before the RX path looks, in which case the delayed response is dropped, or blocks in the disarm until the RX path is done with the completion, in which case the completion is still alive. Log the dropped case, so every path where a delayed response that was matched to a pending xfer and then discarded produces an error. (This is the same treatment scmi_msg_response_validate() already gives a delayed response that arrives after the waiter has disarmed the xfer) Fixes: 58ecdf03dbb9 ("firmware: arm_scmi: Add support for asynchronous commands and delayed response") Signed-off-by: Roland Dreier Reviewed-by: Cristian Marussi Tested-by: Cristian Marussi Link: https://patch.msgid.link/20260909-scmi-async-done-race-v2-1-cc5dec25c6be@rivian.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 22 ++++++++++++++++ drivers/firmware/arm_scmi/driver.c | 37 +++++++++++++++++++++++---- drivers/firmware/arm_scmi/protocols.h | 9 ++++--- drivers/firmware/arm_scmi/raw_mode.c | 4 +-- 4 files changed, 62 insertions(+), 10 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index fe8c22cfb9f7..a5492dd90b41 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -284,6 +284,28 @@ static inline bool is_polling_enabled(struct scmi_chan_info *cinfo, is_transport_polling_capable(desc); } +/** + * scmi_xfer_async_response_arm - Arm the delayed response completion + * + * @xfer: A reference to the xfer to arm + * @async_done: The completion to signal upon reception of a delayed response, + * or NULL to disarm @xfer. + */ +static inline void scmi_xfer_async_response_arm(struct scmi_xfer *xfer, + struct completion *async_done) +{ + unsigned long flags; + + spin_lock_irqsave(&xfer->lock, flags); + xfer->async_done = async_done; + spin_unlock_irqrestore(&xfer->lock, flags); +} + +static inline void scmi_xfer_async_response_disarm(struct scmi_xfer *xfer) +{ + scmi_xfer_async_response_arm(xfer, NULL); +} + void scmi_xfer_raw_put(const struct scmi_handle *handle, struct scmi_xfer *xfer); struct scmi_xfer *scmi_xfer_raw_get(const struct scmi_handle *handle); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index fb45b8e6459d..10273e6b4fbe 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1064,6 +1064,29 @@ static inline void scmi_xfer_command_release(struct scmi_info *info, __scmi_xfer_put(&info->tx_minfo, xfer); } +/** + * scmi_xfer_async_response_complete - Signal a received delayed response + * + * @xfer: A reference to the xfer whose delayed response was received + * + * Return: True if a completion was still armed on @xfer and has been + * signalled, false if a waiter has already disarmed it due to + * timeout or other error. + */ +static bool scmi_xfer_async_response_complete(struct scmi_xfer *xfer) +{ + unsigned long flags; + struct completion *async_done; + + spin_lock_irqsave(&xfer->lock, flags); + async_done = xfer->async_done; + if (async_done) + complete(async_done); + spin_unlock_irqrestore(&xfer->lock, flags); + + return !!async_done; +} + static inline void scmi_clear_channel(struct scmi_info *info, struct scmi_chan_info *cinfo) { @@ -1167,8 +1190,12 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo, if (xfer->hdr.type == MSG_TYPE_DELAYED_RESP) { scmi_clear_channel(info, cinfo); - complete(xfer->async_done); - scmi_inc_count(info->dbg, DELAYED_RESPONSE_OK); + if (scmi_xfer_async_response_complete(xfer)) + scmi_inc_count(info->dbg, DELAYED_RESPONSE_OK); + else + dev_err(cinfo->dev, + "Delayed Response for %d (protocol 0x%X msg 0x%X) received after waiter was disarmed, dropping\n", + xfer->hdr.seq, xfer->hdr.protocol_id, xfer->hdr.id); } else { complete(&xfer->done); scmi_inc_count(info->dbg, RESPONSE_OK); @@ -1510,7 +1537,7 @@ static int do_xfer_with_response(const struct scmi_protocol_handle *ph, int ret, timeout = msecs_to_jiffies(SCMI_MAX_RESPONSE_TIMEOUT); DECLARE_COMPLETION_ONSTACK(async_response); - xfer->async_done = &async_response; + scmi_xfer_async_response_arm(xfer, &async_response); /* * Delayed responses should not be polled, so an async command should @@ -1522,7 +1549,7 @@ static int do_xfer_with_response(const struct scmi_protocol_handle *ph, ret = do_xfer(ph, xfer); if (!ret) { - if (!wait_for_completion_timeout(xfer->async_done, timeout)) { + if (!wait_for_completion_timeout(&async_response, timeout)) { dev_err(ph->dev, "timed out in delayed resp(caller: %pS)\n", (void *)_RET_IP_); @@ -1532,7 +1559,7 @@ static int do_xfer_with_response(const struct scmi_protocol_handle *ph, } } - xfer->async_done = NULL; + scmi_xfer_async_response_disarm(xfer); return ret; } diff --git a/drivers/firmware/arm_scmi/protocols.h b/drivers/firmware/arm_scmi/protocols.h index 15ad5162e37a..8583159059e6 100644 --- a/drivers/firmware/arm_scmi/protocols.h +++ b/drivers/firmware/arm_scmi/protocols.h @@ -100,7 +100,10 @@ struct scmi_msg_hdr { * message. If request-ACK protocol is used, we can reuse the same * buffer for the rx path as we use for the tx path. * @done: command message transmit completion event - * @async_done: pointer to delayed response message received event completion + * @async_done: pointer to delayed response message received event completion, + * or NULL when no delayed response is expected. Protected by + * @lock, since the completion is owned by the waiter and can + * vanish once the wait times out. * @pending: True for xfers added to @pending_xfers hashtable * @node: An hlist_node reference used to store this xfer, alternatively, on * the free list @free_xfers or in the @pending_xfers hashtable @@ -121,7 +124,7 @@ struct scmi_msg_hdr { * - SCMI_XFER_SENT_OK -> SCMI_XFER_DRESP_OK * (Missing synchronous response is assumed OK and ignored) * @flags: Optional flags associated to this xfer. - * @lock: A spinlock to protect state and busy fields. + * @lock: A spinlock to protect state, busy and async_done fields. * @priv: A pointer for transport private usage. */ struct scmi_xfer { @@ -147,7 +150,7 @@ struct scmi_xfer { #define SCMI_XFER_IS_CHAN_SET(x) \ ((x)->flags & SCMI_XFER_FLAG_CHAN_SET) int flags; - /* A lock to protect state and busy fields */ + /* A lock to protect state, busy and async_done fields */ spinlock_t lock; void *priv; }; diff --git a/drivers/firmware/arm_scmi/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c index 1f6e51670208..8751cff5fa4e 100644 --- a/drivers/firmware/arm_scmi/raw_mode.c +++ b/drivers/firmware/arm_scmi/raw_mode.c @@ -346,7 +346,7 @@ scmi_xfer_raw_waiter_get(struct scmi_raw_mode_info *raw, struct scmi_xfer *xfer, if (async) { reinit_completion(&rw->async_response); - xfer->async_done = &rw->async_response; + scmi_xfer_async_response_arm(xfer, &rw->async_response); } rw->cinfo = cinfo; @@ -361,7 +361,7 @@ static void scmi_xfer_raw_waiter_put(struct scmi_raw_mode_info *raw, struct scmi_xfer_raw_waiter *rw) { if (rw->xfer) { - rw->xfer->async_done = NULL; + scmi_xfer_async_response_disarm(rw->xfer); rw->xfer = NULL; } From 0543fc1443de1a0b04ec64684fb920d79e15de2f Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 9 Sep 2026 04:32:28 +0000 Subject: [PATCH 045/176] firmware: arm_scmi: Don't reuse raw xfers with async_done still armed In SCMI raw mode, scmi_xfer_raw_worker() releases the xfer before releasing the waiter that disarms xfer->async_done, and scmi_xfer_get() does not clear async_done when it hands out a recycled xfer. A concurrent transaction can therefore pick up the xfer while it still points at the old waiter's completion, so: - a delayed response arriving for the new transaction can be signalled on the old waiter's completion, which may already be re-armed for yet another unrelated transaction, making that transaction's wait return early; and - the old waiter's disarm, which still runs after the xfer has been released, clobbers the arming just installed by the new transaction, so the new waiter times out even if its delayed response arrives. Release the waiter first, while the worker still holds a reference on the xfer, so that an xfer can never reach the free list still armed. Track whether a delayed response is expected in the waiter itself instead of peeking at xfer->async_done outside xfer->lock, and wait on the waiter's own embedded completion. (The new async flag is not strictly needed but it makes the logic easier to reason about) Finally, harden scmi_xfer_get() to clear async_done when handing out an xfer, so that no future release-ordering change can leak a stale arming into a new transaction. Fixes: 3c3d818a9317 ("firmware: arm_scmi: Add core raw transmission support") Signed-off-by: Roland Dreier Reviewed-by: Cristian Marussi Tested-by: Cristian Marussi Link: https://patch.msgid.link/20260909-scmi-async-done-race-v2-2-cc5dec25c6be@rivian.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 1 + drivers/firmware/arm_scmi/raw_mode.c | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 10273e6b4fbe..e6e1a2508f51 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -718,6 +718,7 @@ static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle, refcount_set(&xfer->users, 1); atomic_set(&xfer->busy, SCMI_XFER_FREE); + xfer->async_done = NULL; spin_unlock_irqrestore(&minfo->xfer_lock, flags); return xfer; diff --git a/drivers/firmware/arm_scmi/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c index 8751cff5fa4e..5ee21f6b7001 100644 --- a/drivers/firmware/arm_scmi/raw_mode.c +++ b/drivers/firmware/arm_scmi/raw_mode.c @@ -198,6 +198,8 @@ struct scmi_raw_mode_info { * @async_response: A completion to be, optionally, used for async waits: it * will be setup by @scmi_do_xfer_raw_start, if needed, to be * pointed at by xfer->async_done. + * @async: True if @async_response was armed on @xfer, i.e. if a delayed + * response has to be waited for. * @node: A list node. */ struct scmi_xfer_raw_waiter { @@ -205,6 +207,7 @@ struct scmi_xfer_raw_waiter { struct scmi_chan_info *cinfo; struct scmi_xfer *xfer; struct completion async_response; + bool async; struct list_head node; }; @@ -349,6 +352,7 @@ scmi_xfer_raw_waiter_get(struct scmi_raw_mode_info *raw, struct scmi_xfer *xfer, scmi_xfer_async_response_arm(xfer, &rw->async_response); } + rw->async = async; rw->cinfo = cinfo; rw->xfer = xfer; } @@ -361,8 +365,16 @@ static void scmi_xfer_raw_waiter_put(struct scmi_raw_mode_info *raw, struct scmi_xfer_raw_waiter *rw) { if (rw->xfer) { + /* + * Disarm the delayed response before this waiter, and its + * embedded completion, can be picked up again for a new + * transaction: a delayed response received late, after the + * related wait timed out, must not signal a completion which + * has been in the meantime re-armed on a different xfer. + */ scmi_xfer_async_response_disarm(rw->xfer); rw->xfer = NULL; + rw->async = false; } mutex_lock(&raw->free_mtx); @@ -479,18 +491,23 @@ static void scmi_xfer_raw_worker(struct work_struct *work) ret, scmi_inflight_count(raw->handle)); /* Wait also for an async delayed response if needed */ - if (!ret && xfer->async_done) { + if (!ret && rw->async) { unsigned long tmo = msecs_to_jiffies(SCMI_MAX_RESPONSE_TIMEOUT); - if (!wait_for_completion_timeout(xfer->async_done, tmo)) + if (!wait_for_completion_timeout(&rw->async_response, tmo)) dev_err(dev, "timed out in RAW delayed resp - HDR:%08X\n", pack_scmi_header(&xfer->hdr)); } - /* Release waiter and xfer */ - scmi_xfer_raw_put(raw->handle, xfer); + /* + * Release the waiter first: this disarms the delayed response + * while we still hold a reference on the xfer, so that the xfer + * cannot be recycled by a new transaction while it still points + * at this waiter's completion. + */ scmi_xfer_raw_waiter_put(raw, rw); + scmi_xfer_raw_put(raw->handle, xfer); } while (1); } From 1adabdce41b93ee6f72f29daa1d3e1750e7b7bd1 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 9 Sep 2026 17:58:59 +0000 Subject: [PATCH 046/176] firmware: arm_scmi: Fix error path leak in scmi_raw_message_send() When the is_transport_polling_capable() check fails in scmi_raw_message_send(), it returns -EINVAL without doing scmi_xfer_raw_put(), which will leak a struct scmi_xfer. Reported-by: Sashiko Link: https://sashiko.dev/#/patchset/20260909-scmi-async-done-race-v2-0-cc5dec25c6be%40rivian.com Fixes: 07cb8c324b63 ("firmware: arm_scmi: Add polling support to raw mode") Signed-off-by: Roland Dreier Link: https://patch.msgid.link/20260909-scmi-raw-v1-1-de3fa75d2c6f@rivian.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/raw_mode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/arm_scmi/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c index 5ee21f6b7001..f01bf2f6ce1d 100644 --- a/drivers/firmware/arm_scmi/raw_mode.c +++ b/drivers/firmware/arm_scmi/raw_mode.c @@ -711,6 +711,7 @@ static int scmi_raw_message_send(struct scmi_raw_mode_info *raw, } else { dev_err(raw->handle->dev, "Failed to send RAW message - Polling NOT supported\n"); + scmi_xfer_raw_put(raw->handle, xfer); return -EINVAL; } } From 7e9023a18eec88b716d8d46a29c4207186fbd828 Mon Sep 17 00:00:00 2001 From: Vincent Jardin Date: Wed, 9 Sep 2026 19:04:40 +0200 Subject: [PATCH 047/176] bus: fsl-mc: register the object drivers after misc_class exists Unbinding and re-binding the root DPRC fails with: sysfs: cannot create duplicate filename '/dev/char/10:256' misc_register / fsl_mc_uapi_create_device_file / dprc_setup / dprc_probe It happens when the fsl-mc bus probe is not deferred, without SMMU: - the dprc driver is registered at postcore_initcall, - the DT node is populated at arch_initcall_sync, - the root DPRC probes right there, before misc_init() has registered misc_class at subsys_initcall. misc_register() still succeeds but the device gets no class, so misc_deregister() at unbind cannot find it: the minor is freed while the device and its /sys/dev/char/ link leak, and then the next bind collides on the same minor. Let's move the dprc and allocator drivers registration, and platform_driver_register(), to subsys_initcall_sync, after misc_init() at subsys_initcall. bus_register() and the platform-bus notifier stay at postcore_initcall so that fsl_mc_bus_notifier() still pauses the MC before the SMMU is probed. Cc: stable+noautosel@kernel.org # niche: root DPRC unbind/rebind only Fixes: 2cf1e703f066 ("bus: fsl-mc: add fsl-mc userspace support") Signed-off-by: Vincent Jardin Reviewed-by: Ioana Ciornei Link: https://lore.kernel.org/r/20260909-for-upstream-fsl-mc-initcall-order-v2-1-b7a04634fcf1@free.fr Signed-off-by: Christophe Leroy (CS GROUP) --- drivers/bus/fsl-mc/fsl-mc-bus.c | 40 ++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index 0766ccb68629..5878eafd8d44 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -1265,35 +1265,43 @@ static int __init fsl_mc_bus_driver_init(void) error = bus_register(&fsl_mc_bus_type); if (error < 0) { pr_err("bus type registration failed: %d\n", error); - goto error_cleanup_cache; + return error; } - error = platform_driver_register(&fsl_mc_bus_driver); - if (error < 0) { - pr_err("platform_driver_register() failed: %d\n", error); + error = bus_register_notifier(&platform_bus_type, &fsl_mc_nb); + if (error < 0) goto error_cleanup_bus; - } + + return 0; + +error_cleanup_bus: + bus_unregister(&fsl_mc_bus_type); + return error; +} +postcore_initcall(fsl_mc_bus_driver_init); + +static int __init fsl_mc_bus_drivers_init(void) +{ + int error; error = dprc_driver_init(); if (error < 0) - goto error_cleanup_driver; + return error; error = fsl_mc_allocator_driver_init(); if (error < 0) goto error_cleanup_dprc_driver; - return bus_register_notifier(&platform_bus_type, &fsl_mc_nb); + error = platform_driver_register(&fsl_mc_bus_driver); + if (error < 0) { + pr_err("platform_driver_register() failed: %d\n", error); + goto error_cleanup_dprc_driver; + } + + return 0; error_cleanup_dprc_driver: dprc_driver_exit(); - -error_cleanup_driver: - platform_driver_unregister(&fsl_mc_bus_driver); - -error_cleanup_bus: - bus_unregister(&fsl_mc_bus_type); - -error_cleanup_cache: return error; } -postcore_initcall(fsl_mc_bus_driver_init); +subsys_initcall_sync(fsl_mc_bus_drivers_init); From 31d42d67c6eb66efc058069f426d69abb48ec0dd Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 8 Sep 2026 11:27:46 +0200 Subject: [PATCH 048/176] soc: fsl: qe: drop GPIOD_FLAGS_BIT_NONEXCLUSIVE The GPIOD_FLAGS_BIT_NONEXCLUSIVE flag for gpiod_get() is deprecated. For actually shared GPIOs, it should be replaced by using the functionality provided by gpio-shared-proxy. The Freescale QUICC Engine GPIO driver uses it as a workaround to access the GPIO descriptor already requested by the caller of qe_pin_request() in order to access the private GPIO chip data. As the existing comment itself states, the user already requested this GPIO and the only user in tree is the FHCI USB driver which does in fact request it, we can safely modify the function to take the *exclusive* GPIO descriptor as argument and stop using the deprecated flag. Signed-off-by: Bartosz Golaszewski Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20260908-usb-fhci-drop-gpio-nonexclusive-v1-1-8e405dc67874@oss.qualcomm.com Signed-off-by: Christophe Leroy (CS GROUP) --- drivers/soc/fsl/qe/gpio.c | 29 +++++++---------------------- drivers/usb/host/fhci-hcd.c | 2 +- include/soc/fsl/qe/qe.h | 6 ++++-- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index 8e210f8a3b6c..1b5a1b134596 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -201,18 +201,17 @@ struct qe_pin { /** * qe_pin_request - Request a QE pin * @dev: device to get the pin from - * @index: index of the pin in the device tree + * @gpiod: GPIO descriptor associated with this pin * Context: non-atomic * * This function return qe_pin so that you could use it with the rest of * the QE Pin Multiplexing API. */ -struct qe_pin *qe_pin_request(struct device *dev, int index) +struct qe_pin *qe_pin_request(struct device *dev, struct gpio_desc *gpiod) { + struct gpio_device *gdev; struct qe_pin *qe_pin; struct gpio_chip *gc; - struct gpio_desc *gpiod; - int gpio_num; int err; qe_pin = kzalloc_obj(*qe_pin); @@ -221,34 +220,20 @@ struct qe_pin *qe_pin_request(struct device *dev, int index) return ERR_PTR(-ENOMEM); } - /* - * Request gpio as nonexclusive as it was likely reserved by the - * caller, and we are not planning on controlling it, we only need - * the descriptor to the to the gpio chip structure. - */ - gpiod = gpiod_get_index(dev, NULL, index, - GPIOD_ASIS | GPIOD_FLAGS_BIT_NONEXCLUSIVE); - err = PTR_ERR_OR_ZERO(gpiod); - if (err) - goto err0; - - gc = gpiod_to_chip(gpiod); - gpio_num = desc_to_gpio(gpiod); - /* We no longer need this descriptor */ - gpiod_put(gpiod); - - if (WARN_ON(!gc)) { + gdev = gpiod_to_gpio_device(gpiod); + if (WARN_ON(!gdev)) { err = -ENODEV; goto err0; } + gc = gpio_device_get_chip(gdev); qe_pin->controller = gpiochip_get_data(gc); /* * FIXME: this gets the local offset on the gpio_chip so that the driver * can manipulate pin control settings through its custom API. The real * solution is to create a real pin control driver for this. */ - qe_pin->num = gpio_num - gc->base; + qe_pin->num = desc_to_gpio(gpiod) - gc->base; if (!fwnode_device_is_compatible(gc->fwnode, "fsl,mpc8323-qe-pario-bank")) { dev_dbg(dev, "%s: tried to get a non-qe pin\n", __func__); diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index 71e785f445a3..d572f0c1dffa 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -643,7 +643,7 @@ static int of_fhci_probe(struct platform_device *ofdev) } for (j = 0; j < NUM_PINS; j++) { - fhci->pins[j] = qe_pin_request(dev, j); + fhci->pins[j] = qe_pin_request(dev, fhci->gpiods[j]); if (IS_ERR(fhci->pins[j])) { ret = PTR_ERR(fhci->pins[j]); dev_err(dev, "can't get pin %d: %d\n", j, ret); diff --git a/include/soc/fsl/qe/qe.h b/include/soc/fsl/qe/qe.h index 8f967d15e479..7f0e4165c3b0 100644 --- a/include/soc/fsl/qe/qe.h +++ b/include/soc/fsl/qe/qe.h @@ -24,6 +24,7 @@ #include struct device; +struct gpio_desc; #define QE_NUM_OF_SNUM 256 /* There are 256 serial number in QE */ #define QE_NUM_OF_BRGS 16 @@ -193,12 +194,13 @@ static inline int par_io_data_set(u8 port, u8 pin, u8 val) { return -ENOSYS; } */ struct qe_pin; #ifdef CONFIG_QE_GPIO -extern struct qe_pin *qe_pin_request(struct device *dev, int index); +extern struct qe_pin *qe_pin_request(struct device *dev, struct gpio_desc *gpiod); extern void qe_pin_free(struct qe_pin *qe_pin); extern void qe_pin_set_gpio(struct qe_pin *qe_pin); extern void qe_pin_set_dedicated(struct qe_pin *pin); #else -static inline struct qe_pin *qe_pin_request(struct device *dev, int index) +static inline struct qe_pin * +qe_pin_request(struct device *dev, struct gpio_desc *gpiod) { return ERR_PTR(-ENOSYS); } From cce46902ea9fcd585cd200fffa3166f63bc571f1 Mon Sep 17 00:00:00 2001 From: Jiawen Liu <1298662399@qq.com> Date: Fri, 4 Sep 2026 14:01:35 +0400 Subject: [PATCH 049/176] memory: exynos5422-dmc: handle clock enable failures Check the return values of clk_prepare_enable() for fout_bpll and mout_bpll. If enabling fout_bpll fails, propagate the error. If enabling mout_bpll fails, disable fout_bpll before returning. This keeps the clock enable count balanced on probe error paths. Fixes: 6e7674c3c6df ("memory: Add DMC driver for Exynos5422") Signed-off-by: Jiawen Liu <1298662399@qq.com> Reviewed-by: Lukasz Luba Link: https://patch.msgid.link/tencent_B0189529F550458590E3BA614EAB800FBF08@qq.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/samsung/exynos5422-dmc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c index 788d49c688b1..98c319552583 100644 --- a/drivers/memory/samsung/exynos5422-dmc.c +++ b/drivers/memory/samsung/exynos5422-dmc.c @@ -1297,8 +1297,15 @@ static int exynos5_dmc_init_clks(struct exynos5_dmc *dmc) if (ret) return ret; - clk_prepare_enable(dmc->fout_bpll); - clk_prepare_enable(dmc->mout_bpll); + ret = clk_prepare_enable(dmc->fout_bpll); + if (ret) + return ret; + + ret = clk_prepare_enable(dmc->mout_bpll); + if (ret) { + clk_disable_unprepare(dmc->fout_bpll); + return ret; + } /* * Some bootloaders do not set clock routes correctly. From 2911930bfbdf382aa2785f16eb960d48e8a93295 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 3 Sep 2026 11:54:25 +0200 Subject: [PATCH 050/176] firmware: arm_scmi: Merge scmi_reset_proto_ops.name_get() and .latency_get() The SCMI reset domain protocol operations structure does not provide a .info_get() method, unlike most other protocols. Instead, it provides two separate methods to get a domain's name and reset latency. Merge the .name_get() and .latency_get() methods into a single .info_get() method, to increase uniformity. Signed-off-by: Geert Uytterhoeven Link: https://patch.msgid.link/77c9651a11715013c0eaa8a56dbbc7dc3d9ddeec.1788429130.git.geert+renesas@glider.be Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/reset.c | 36 ++++++++++--------------------- include/linux/scmi_protocol.h | 13 ++++++----- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c index 4bc5c24c2d72..2cdddc28ba47 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -60,8 +60,7 @@ struct scmi_reset_issued_notify_payld { struct reset_dom_info { bool async_reset; bool reset_notify; - u32 latency_us; - char name[SCMI_MAX_STR_SIZE]; + struct scmi_reset_domain_info info; }; struct scmi_reset_info { @@ -134,10 +133,10 @@ scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph, if (pinfo->notify_reset_cmd) dom_info->reset_notify = SUPPORTS_NOTIFY_RESET(attributes); - dom_info->latency_us = le32_to_cpu(attr->latency); - if (dom_info->latency_us == U32_MAX) - dom_info->latency_us = 0; - strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE); + dom_info->info.latency_us = le32_to_cpu(attr->latency); + if (dom_info->info.latency_us == U32_MAX) + dom_info->info.latency_us = 0; + strscpy(dom_info->info.name, attr->name, SCMI_SHORT_NAME_MAX_SIZE); } ph->xops->xfer_put(ph, t); @@ -149,7 +148,7 @@ scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph, if (!ret && PROTOCOL_REV_MAJOR(ph->version) >= 0x3 && SUPPORTS_EXTENDED_NAMES(attributes)) ph->hops->extended_name_get(ph, RESET_DOMAIN_NAME_GET, domain, - NULL, dom_info->name, + NULL, dom_info->info.name, SCMI_MAX_STR_SIZE); return ret; @@ -162,28 +161,16 @@ static int scmi_reset_num_domains_get(const struct scmi_protocol_handle *ph) return pi->num_domains; } -static const char * -scmi_reset_name_get(const struct scmi_protocol_handle *ph, u32 domain) +static const struct scmi_reset_domain_info * +scmi_reset_info_get(const struct scmi_protocol_handle *ph, u32 domain) { struct reset_dom_info *dom_info; dom_info = scmi_reset_domain_lookup(ph, domain); if (IS_ERR(dom_info)) - return "unknown"; + return NULL; - return dom_info->name; -} - -static int scmi_reset_latency_get(const struct scmi_protocol_handle *ph, - u32 domain) -{ - struct reset_dom_info *dom_info; - - dom_info = scmi_reset_domain_lookup(ph, domain); - if (IS_ERR(dom_info)) - return PTR_ERR(dom_info); - - return dom_info->latency_us; + return &dom_info->info; } static int scmi_domain_reset(const struct scmi_protocol_handle *ph, u32 domain, @@ -241,8 +228,7 @@ scmi_reset_domain_deassert(const struct scmi_protocol_handle *ph, u32 domain) static const struct scmi_reset_proto_ops reset_proto_ops = { .num_domains_get = scmi_reset_num_domains_get, - .name_get = scmi_reset_name_get, - .latency_get = scmi_reset_latency_get, + .info_get = scmi_reset_info_get, .reset = scmi_reset_domain_reset, .assert = scmi_reset_domain_assert, .deassert = scmi_reset_domain_deassert, diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 5ab73b1ab9aa..ba38a26b7d50 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -528,22 +528,25 @@ struct scmi_sensor_proto_ops { u32 sensor_id, u32 sensor_config); }; +struct scmi_reset_domain_info { + char name[SCMI_MAX_STR_SIZE]; + u32 latency_us; +}; + /** * struct scmi_reset_proto_ops - represents the various operations provided * by SCMI Reset Protocol * * @num_domains_get: get the count of reset domains provided by SCMI - * @name_get: gets the name of a reset domain - * @latency_get: gets the reset latency for the specified reset domain + * @info_get: gets the information of the specified reset domain * @reset: resets the specified reset domain * @assert: explicitly assert reset signal of the specified reset domain * @deassert: explicitly deassert reset signal of the specified reset domain */ struct scmi_reset_proto_ops { int (*num_domains_get)(const struct scmi_protocol_handle *ph); - const char *(*name_get)(const struct scmi_protocol_handle *ph, - u32 domain); - int (*latency_get)(const struct scmi_protocol_handle *ph, u32 domain); + const struct scmi_reset_domain_info __must_check *(*info_get) + (const struct scmi_protocol_handle *ph, u32 domain); int (*reset)(const struct scmi_protocol_handle *ph, u32 domain); int (*assert)(const struct scmi_protocol_handle *ph, u32 domain); int (*deassert)(const struct scmi_protocol_handle *ph, u32 domain); From e3631d0242842940f9e902afaea98202e56277e8 Mon Sep 17 00:00:00 2001 From: Linkai Gong Date: Thu, 13 Aug 2026 17:58:18 +0800 Subject: [PATCH 051/176] firmware: imx: dsp: fix mailbox channel leak on kasprintf failure If kasprintf() fails while setting up mailbox channels, already requested channels from earlier iterations were never freed. Route the failure through the existing cleanup path. Fixes: ffbf23d50353 ("firmware: imx: Add DSP IPC protocol interface") Signed-off-by: Linkai Gong Reviewed-by: Frank Li Signed-off-by: Frank Li --- drivers/firmware/imx/imx-dsp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/imx/imx-dsp.c b/drivers/firmware/imx/imx-dsp.c index ed79e823157a..7e3f45ddf0c1 100644 --- a/drivers/firmware/imx/imx-dsp.c +++ b/drivers/firmware/imx/imx-dsp.c @@ -99,8 +99,10 @@ static int imx_dsp_setup_channels(struct imx_dsp_ipc *dsp_ipc) else chan_name = kasprintf(GFP_KERNEL, "rxdb%d", i - 2); - if (!chan_name) - return -ENOMEM; + if (!chan_name) { + ret = -ENOMEM; + goto out; + } dsp_chan = &dsp_ipc->chans[i]; dsp_chan->name = chan_name; From edda28d5317521c2f5172f869d3a433a2d37f7a2 Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 3 Sep 2026 18:25:18 +0000 Subject: [PATCH 052/176] memory: tegra: Use named defines for Tegra264 MC apertures The Tegra264 memory controller error interrupts are distributed across several HUB/HUBC apertures, each accessed like a broadcast channel using a fixed index. These indices were kept in a bare mc_hubc_aperture_number[] array, and handle_hub_irq() took a parameter of the same name that shadowed it. This driver is only applicable to Tegra264 devices and so this abstraction is not needed. Replace the array with named TEGRA264_MC_APERTURE_* defines to simplify the code. No functional change intended. Signed-off-by: Ketan Patil Link: https://patch.msgid.link/20260903182520.950555-2-ketanp@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra264.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/memory/tegra/tegra264.c b/drivers/memory/tegra/tegra264.c index 790349295dcc..56e55269eed7 100644 --- a/drivers/memory/tegra/tegra264.c +++ b/drivers/memory/tegra/tegra264.c @@ -717,11 +717,15 @@ static const char *const tegra264_rt_error_names[16] = { }; /* - * MC instance aperture mapping for hubc registers + * On Tegra264 the memory controller error interrupts are distributed across + * several HUB/HUBC apertures. Each aperture is accessed like a broadcast + * channel through mc_ch_readl()/mc_ch_writel() using its fixed index. */ -static const int mc_hubc_aperture_number[5] = { - 7, 8, 9, 10, 11 -}; +#define TEGRA264_MC_APERTURE_DISP 7 +#define TEGRA264_MC_APERTURE_SYSTEM 8 +#define TEGRA264_MC_APERTURE_VISION 9 +#define TEGRA264_MC_APERTURE_UPHY 10 +#define TEGRA264_MC_APERTURE_TOP 11 /* * tegra264_mc_icc_set() - Pass MC client info to the BPMP-FW @@ -1057,27 +1061,27 @@ static irqreturn_t handle_hub_irq(int irq, void *data, int mc_hubc_aperture_numb static irqreturn_t handle_disp_hub_irq(int irq, void *data) { - return handle_hub_irq(irq, data, mc_hubc_aperture_number[0]); + return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_DISP); } static irqreturn_t handle_system_hub_irq(int irq, void *data) { - return handle_hub_irq(irq, data, mc_hubc_aperture_number[1]); + return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_SYSTEM); } static irqreturn_t handle_vision_hub_irq(int irq, void *data) { - return handle_hub_irq(irq, data, mc_hubc_aperture_number[2]); + return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_VISION); } static irqreturn_t handle_uphy_hub_irq(int irq, void *data) { - return handle_hub_irq(irq, data, mc_hubc_aperture_number[3]); + return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_UPHY); } static irqreturn_t handle_top_hub_irq(int irq, void *data) { - return handle_hub_irq(irq, data, mc_hubc_aperture_number[4]); + return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_TOP); } static irqreturn_t handle_generic_irq(struct tegra_mc *mc, unsigned long intstat_reg) From fb8af372f899690646444cd0b38a88ec52568cbc Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 3 Sep 2026 18:25:19 +0000 Subject: [PATCH 053/176] memory: tegra: Parameterise Tegra264 MCF slice bound Replace the hard-coded slice bound check in handle_mcf_irq() with a TEGRA264_MC_NUM_SLICES define, so the number of MCF slices is named rather than being an unexplained literal. Note that although the existing logic is correct, the actual number of MCF slices for Tegra264 is 5 and not 4. So define TEGRA264_MC_NUM_SLICES as 5 and update the logic accordingly. No functional change intended. Signed-off-by: Ketan Patil Link: https://patch.msgid.link/20260903182520.950555-3-ketanp@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra264.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/memory/tegra/tegra264.c b/drivers/memory/tegra/tegra264.c index 56e55269eed7..b40275ae382e 100644 --- a/drivers/memory/tegra/tegra264.c +++ b/drivers/memory/tegra/tegra264.c @@ -727,6 +727,9 @@ static const char *const tegra264_rt_error_names[16] = { #define TEGRA264_MC_APERTURE_UPHY 10 #define TEGRA264_MC_APERTURE_TOP 11 +/* Tegra264 splits the MCF common interrupt status across five slices. */ +#define TEGRA264_MC_NUM_SLICES 5 + /* * tegra264_mc_icc_set() - Pass MC client info to the BPMP-FW * @src: ICC node for Memory Controller's (MC) Client @@ -941,7 +944,7 @@ static irqreturn_t handle_mcf_irq(int irq, void *data) for_each_set_bit(slice, &common_intstat, 32) { /* Find out the slice number on which interrupt occurred */ - if (slice > 4) { + if (slice >= TEGRA264_MC_NUM_SLICES) { dev_err(mc->dev, "Slice index out of bounds: %u\n", slice); return IRQ_NONE; } From f4e16143420f4021431cc652ebd71e176267ecbc Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 3 Sep 2026 18:25:20 +0000 Subject: [PATCH 054/176] memory: tegra: Refactor Tegra264 mc-err code The MC and HUB error-logging paths on Tegra264 used large switch statements that interleaved register offsets, bit positions and decoding parameters for each error type, which made them hard to read and review. Turn the error logging into a more structured implementation: - Describe each MCF error type with a tegra264_mc_fault descriptor filled in by a small per-type get_offsets() callback, and move the register access, client lookup and reporting into a common tegra264_mc_report_fault() helper. - Describe each HUB error type with a static tegra264_hub_error_handler table, since the HUB register offsets are fixed on Tegra264. No functional change intended. Signed-off-by: Ketan Patil Link: https://patch.msgid.link/20260903182520.950555-4-ketanp@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra264.c | 365 ++++++++++++++++++++------------ 1 file changed, 228 insertions(+), 137 deletions(-) diff --git a/drivers/memory/tegra/tegra264.c b/drivers/memory/tegra/tegra264.c index b40275ae382e..57e6395861ba 100644 --- a/drivers/memory/tegra/tegra264.c +++ b/drivers/memory/tegra/tegra264.c @@ -15,6 +15,47 @@ #include "mc.h" #include "tegra264-bwmgr.h" +/* + * Description of a single MCF error type: where to read the status and the + * faulting address, how to extract the high address bits, which bits encode + * the access direction and security state and the optional error-type sub-code. + */ +struct tegra264_mc_fault { + const char *const *type_names; + u32 addr_hi_mask; + u32 addr_hi_reg; + u32 addr_hi_shift; + u32 addr_reg; + u32 rw_bit; + u32 sec_bit; + u32 status1_reg; + u32 status_reg; + u32 type_mask; + u32 type_shift; +}; + +/* + * Maps an MCF interrupt to a callback that fills in the register offsets and + * decoding parameters for that error type. The register offsets live in the + * per-SoC tegra_mc_regs, so they are collected at runtime rather than being + * stored in a static table. + */ +struct tegra264_mc_error_handler { + u32 mask; + void (*get_offsets)(struct tegra_mc *mc, struct tegra264_mc_fault *fault); +}; + +/* + * Description of a single HUB error type. addr_reg is zero for error types + * that don't latch a fault address. + */ +struct tegra264_hub_error_handler { + u32 addr_hi_reg; + u32 addr_reg; + u32 mask; + u32 status_reg; +}; + /* * MC Client entries are sorted in the increasing order of the * override and security register offsets. @@ -814,115 +855,149 @@ static int tegra264_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea return 0; } +static void tegra264_mc_fault_emem(struct tegra_mc *mc, struct tegra264_mc_fault *fault) +{ + fault->status_reg = mc->soc->regs->err_status; + fault->addr_reg = mc->soc->regs->err_add; + fault->addr_hi_reg = mc->soc->regs->err_add_hi; + fault->type_mask = mc->soc->mc_err_status_type_mask; + fault->type_shift = MC_ERR_STATUS_TYPE_SHIFT; + fault->type_names = tegra264_mc_error_names; +} + +static void tegra264_mc_fault_vpr(struct tegra_mc *mc, struct tegra264_mc_fault *fault) +{ + fault->status_reg = mc->soc->regs->err_vpr_status; + fault->addr_reg = mc->soc->regs->err_vpr_add; + fault->addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT; + fault->addr_hi_mask = mc->soc->mc_addr_hi_mask; +} + +static void tegra264_mc_fault_sec(struct tegra_mc *mc, struct tegra264_mc_fault *fault) +{ + fault->status_reg = mc->soc->regs->err_sec_status; + fault->addr_reg = mc->soc->regs->err_sec_add; + fault->addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT; + fault->addr_hi_mask = mc->soc->mc_addr_hi_mask; +} + +static void tegra264_mc_fault_mts(struct tegra_mc *mc, struct tegra264_mc_fault *fault) +{ + fault->status_reg = mc->soc->regs->err_mts_status; + fault->addr_reg = mc->soc->regs->err_mts_add; + fault->addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT; + fault->addr_hi_mask = mc->soc->mc_addr_hi_mask; +} + +static void tegra264_mc_fault_gsc(struct tegra_mc *mc, struct tegra264_mc_fault *fault) +{ + fault->status_reg = mc->soc->regs->err_gen_co_status; + fault->status1_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS_1_0; + fault->addr_reg = mc->soc->regs->err_gen_co_add; + fault->addr_hi_shift = MC_ERR_STATUS_GSC_ADR_HI_SHIFT; + fault->addr_hi_mask = MC_ERR_STATUS_GSC_ADR_HI_MASK; +} + +static void tegra264_mc_fault_route(struct tegra_mc *mc, struct tegra264_mc_fault *fault) +{ + fault->status_reg = mc->soc->regs->err_route_status; + fault->addr_reg = mc->soc->regs->err_route_add; + fault->addr_hi_shift = MC_ERR_STATUS_RT_ADR_HI_SHIFT; + fault->addr_hi_mask = mc->soc->mc_addr_hi_mask; + fault->rw_bit = MC_ERR_ROUTE_SANITY_RW; + fault->sec_bit = MC_ERR_ROUTE_SANITY_SEC; + fault->type_mask = MC_ERR_STATUS_RT_TYPE_MASK; + fault->type_shift = MC_ERR_STATUS_RT_TYPE_SHIFT; + fault->type_names = tegra264_rt_error_names; +} + +static const struct tegra264_mc_error_handler tegra264_mc_error_handlers[] = { + { MC_INT_DECERR_EMEM, tegra264_mc_fault_emem }, + { MC_INT_SECURITY_VIOLATION, tegra264_mc_fault_emem }, + { MC_INT_DECERR_VPR, tegra264_mc_fault_vpr }, + { MC_INT_SECERR_SEC, tegra264_mc_fault_sec }, + { MC_INT_DECERR_MTS, tegra264_mc_fault_mts }, + { MC_INT_DECERR_GENERALIZED_CARVEOUT, tegra264_mc_fault_gsc }, + { MC_INT_DECERR_ROUTE_SANITY, tegra264_mc_fault_route }, + { MC_INT_DECERR_ROUTE_SANITY_GIC_MSI, tegra264_mc_fault_route }, +}; + +static void tegra264_mc_report_fault(struct tegra_mc *mc, u32 channel, + unsigned int interrupt, + const struct tegra264_mc_fault *fault) +{ + const char *client = "unknown", *desc = "NA"; + u32 value, client_id, status1 = 0; + phys_addr_t addr = 0; + unsigned int i; + u8 type; + + value = mc_ch_readl(mc, channel, fault->status_reg); + + if (fault->addr_hi_reg) { + addr = mc_ch_readl(mc, channel, fault->addr_hi_reg); + } else if (fault->status1_reg) { + status1 = mc_ch_readl(mc, channel, fault->status1_reg); + addr = (status1 >> fault->addr_hi_shift) & fault->addr_hi_mask; + } else { + addr = (value >> fault->addr_hi_shift) & fault->addr_hi_mask; + } + + addr <<= 32; + addr |= mc_ch_readl(mc, channel, fault->addr_reg); + + client_id = value & mc->soc->client_id_mask; + for (i = 0; i < mc->soc->num_clients; i++) { + if (mc->soc->clients[i].id == client_id) { + client = mc->soc->clients[i].name; + break; + } + } + + if (fault->type_names) { + type = (value & fault->type_mask) >> fault->type_shift; + desc = fault->type_names[type]; + } + + dev_err_ratelimited(mc->dev, "%s: %s %s @%pa: %s (%s)\n", + client, value & fault->sec_bit ? "secure" : "non-secure", + value & fault->rw_bit ? "write" : "read", &addr, + tegra_mc_status_names[interrupt] ?: "unknown", desc); + + if (fault->status1_reg) + dev_err_ratelimited(mc->dev, "gsc_apr_id=%u gsc_co_apr_id=%u\n", + (status1 >> ERR_GENERALIZED_APERTURE_ID_SHIFT) & + ERR_GENERALIZED_APERTURE_ID_MASK, + (status1 >> ERR_GENERALIZED_CARVEOUT_APERTURE_ID_SHIFT) & + ERR_GENERALIZED_CARVEOUT_APERTURE_ID_MASK); +} + static void mcf_log_fault(struct tegra_mc *mc, u32 channel, unsigned long mcf_ch_intstatus) { - unsigned int bit; + unsigned int interrupt; - for_each_set_bit(bit, &mcf_ch_intstatus, 32) { - const char *client = "unknown", *desc = "NA"; - u32 status_reg, status1_reg = 0, addr_reg, addr_hi_reg = 0, err_type_mask = 0; - u32 value, client_id, i, addr_hi_shift = 0, addr_hi_mask = 0, status1; - u32 mc_rw_bit = MC_ERR_STATUS_RW, mc_sec_bit = MC_ERR_STATUS_SECURITY; - phys_addr_t addr = 0; - u8 type; + for_each_set_bit(interrupt, &mcf_ch_intstatus, 32) { + const struct tegra264_mc_error_handler *handler = NULL; + struct tegra264_mc_fault fault = { + .rw_bit = MC_ERR_STATUS_RW, + .sec_bit = MC_ERR_STATUS_SECURITY, + }; + unsigned int i; - switch (BIT(bit)) { - case MC_INT_DECERR_EMEM: - case MC_INT_SECURITY_VIOLATION: - status_reg = mc->soc->regs->err_status; - addr_reg = mc->soc->regs->err_add; - addr_hi_reg = mc->soc->regs->err_add_hi; - err_type_mask = mc->soc->mc_err_status_type_mask; - break; - - case MC_INT_DECERR_VPR: - status_reg = mc->soc->regs->err_vpr_status; - addr_reg = mc->soc->regs->err_vpr_add; - addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT; - addr_hi_mask = mc->soc->mc_addr_hi_mask; - break; - - case MC_INT_SECERR_SEC: - status_reg = mc->soc->regs->err_sec_status; - addr_reg = mc->soc->regs->err_sec_add; - addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT; - addr_hi_mask = mc->soc->mc_addr_hi_mask; - break; - - case MC_INT_DECERR_MTS: - status_reg = mc->soc->regs->err_mts_status; - addr_reg = mc->soc->regs->err_mts_add; - addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT; - addr_hi_mask = mc->soc->mc_addr_hi_mask; - break; - - case MC_INT_DECERR_GENERALIZED_CARVEOUT: - status_reg = mc->soc->regs->err_gen_co_status; - status1_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS_1_0; - addr_reg = mc->soc->regs->err_gen_co_add; - addr_hi_shift = MC_ERR_STATUS_GSC_ADR_HI_SHIFT; - addr_hi_mask = MC_ERR_STATUS_GSC_ADR_HI_MASK; - break; - - case MC_INT_DECERR_ROUTE_SANITY: - case MC_INT_DECERR_ROUTE_SANITY_GIC_MSI: - status_reg = mc->soc->regs->err_route_status; - addr_reg = mc->soc->regs->err_route_add; - addr_hi_shift = MC_ERR_STATUS_RT_ADR_HI_SHIFT; - addr_hi_mask = mc->soc->mc_addr_hi_mask; - mc_sec_bit = MC_ERR_ROUTE_SANITY_SEC; - mc_rw_bit = MC_ERR_ROUTE_SANITY_RW; - err_type_mask = MC_ERR_STATUS_RT_TYPE_MASK; - break; - - default: - dev_err_ratelimited(mc->dev, "Incorrect MC interrupt mask\n"); - return; - } - - value = mc_ch_readl(mc, channel, status_reg); - if (addr_hi_reg) { - addr = mc_ch_readl(mc, channel, addr_hi_reg); - } else { - if (!status1_reg) { - addr = ((value >> addr_hi_shift) & addr_hi_mask); - } else { - status1 = mc_ch_readl(mc, channel, status1_reg); - addr = ((status1 >> addr_hi_shift) & addr_hi_mask); - } - } - - addr <<= 32; - addr |= mc_ch_readl(mc, channel, addr_reg); - - client_id = value & mc->soc->client_id_mask; - for (i = 0; i < mc->soc->num_clients; i++) { - if (mc->soc->clients[i].id == client_id) { - client = mc->soc->clients[i].name; + for (i = 0; i < ARRAY_SIZE(tegra264_mc_error_handlers); i++) { + if (tegra264_mc_error_handlers[i].mask == BIT(interrupt)) { + handler = &tegra264_mc_error_handlers[i]; break; } } - if (err_type_mask == MC_ERR_STATUS_RT_TYPE_MASK) { - type = (value & err_type_mask) >> - MC_ERR_STATUS_RT_TYPE_SHIFT; - desc = tegra264_rt_error_names[type]; - } else if (err_type_mask) { - type = (value & err_type_mask) >> - MC_ERR_STATUS_TYPE_SHIFT; - desc = tegra264_mc_error_names[type]; + if (!handler) { + dev_err_ratelimited(mc->dev, "Incorrect MC interrupt mask\n"); + return; } - dev_err_ratelimited(mc->dev, "%s: %s %s @%pa: %s (%s)\n", - client, value & mc_sec_bit ? "secure" : "non-secure", - value & mc_rw_bit ? "write" : "read", &addr, - tegra_mc_status_names[bit] ?: "unknown", desc); - if (status1_reg) - dev_err_ratelimited(mc->dev, "gsc_apr_id=%u gsc_co_apr_id=%u\n", - ((status1 >> ERR_GENERALIZED_APERTURE_ID_SHIFT) - & ERR_GENERALIZED_APERTURE_ID_MASK), - ((status1 >> ERR_GENERALIZED_CARVEOUT_APERTURE_ID_SHIFT) - & ERR_GENERALIZED_CARVEOUT_APERTURE_ID_MASK)); + handler->get_offsets(mc, &fault); + tegra264_mc_report_fault(mc, channel, interrupt, &fault); } /* clear interrupts */ @@ -957,53 +1032,69 @@ static irqreturn_t handle_mcf_irq(int irq, void *data) return IRQ_HANDLED; } +static const struct tegra264_hub_error_handler tegra264_hub_error_handlers[] = { + { + .mask = MSS_HUB_COALESCER_ERR_INTMASK, + .status_reg = MSS_HUB_COALESCE_ERR_STATUS_0, + .addr_reg = MSS_HUB_COALESCE_ERR_ADR_0, + .addr_hi_reg = MSS_HUB_COALESCE_ERR_ADR_HI_0, + }, + { + .mask = MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK, + .status_reg = MSS_HUB_SMMU_BYPASS_ALLOW_ERR_STATUS_0, + }, + { + .mask = MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK, + .status_reg = MSS_HUB_ILLEGAL_TBUGRP_ID_ERR_STATUS_0, + }, + { + .mask = MSS_HUB_MSI_ERR_INTMASK, + .status_reg = MSS_HUB_MSI_ERR_STATUS_0, + }, + { + .mask = MSS_HUB_POISON_RSP_INTMASK, + .status_reg = MSS_HUB_POISON_RSP_STATUS_0, + }, + { + .mask = MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK, + .status_reg = MSS_HUB_RESTRICTED_ACCESS_ERR_STATUS_0, + }, + { + .mask = MSS_HUB_RESERVED_PA_ERR_INTMASK, + .status_reg = MSS_HUB_RESERVED_PA_ERR_STATUS_0, + }, +}; + static void hub_log_fault(struct tegra_mc *mc, u32 hub, unsigned long hub_intstat) { - unsigned int bit; + unsigned int interrupt; - for_each_set_bit(bit, &hub_intstat, 32) { + for_each_set_bit(interrupt, &hub_intstat, 32) { + const struct tegra264_hub_error_handler *handler = NULL; const char *client = "unknown"; - u32 client_id, status_reg, value, i; + u32 client_id, value; phys_addr_t addr = 0; + unsigned int i; - switch (BIT(bit)) { - case MSS_HUB_COALESCER_ERR_INTMASK: - status_reg = MSS_HUB_COALESCE_ERR_STATUS_0; - addr = mc_ch_readl(mc, hub, MSS_HUB_COALESCE_ERR_ADR_HI_0); - addr <<= 32; - addr |= mc_ch_readl(mc, hub, MSS_HUB_COALESCE_ERR_ADR_0); - break; + for (i = 0; i < ARRAY_SIZE(tegra264_hub_error_handlers); i++) { + if (tegra264_hub_error_handlers[i].mask == BIT(interrupt)) { + handler = &tegra264_hub_error_handlers[i]; + break; + } + } - case MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK: - status_reg = MSS_HUB_SMMU_BYPASS_ALLOW_ERR_STATUS_0; - break; - - case MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK: - status_reg = MSS_HUB_ILLEGAL_TBUGRP_ID_ERR_STATUS_0; - break; - - case MSS_HUB_MSI_ERR_INTMASK: - status_reg = MSS_HUB_MSI_ERR_STATUS_0; - break; - - case MSS_HUB_POISON_RSP_INTMASK: - status_reg = MSS_HUB_POISON_RSP_STATUS_0; - break; - - case MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK: - status_reg = MSS_HUB_RESTRICTED_ACCESS_ERR_STATUS_0; - break; - - case MSS_HUB_RESERVED_PA_ERR_INTMASK: - status_reg = MSS_HUB_RESERVED_PA_ERR_STATUS_0; - break; - - default: + if (!handler) { dev_err_ratelimited(mc->dev, "Incorrect HUB interrupt mask\n"); return; } - value = mc_ch_readl(mc, hub, status_reg); + if (handler->addr_reg) { + addr = mc_ch_readl(mc, hub, handler->addr_hi_reg); + addr <<= 32; + addr |= mc_ch_readl(mc, hub, handler->addr_reg); + } + + value = mc_ch_readl(mc, hub, handler->status_reg); client_id = value & mc->soc->client_id_mask; for (i = 0; i < mc->soc->num_clients; i++) { @@ -1014,8 +1105,8 @@ static void hub_log_fault(struct tegra_mc *mc, u32 hub, unsigned long hub_intsta } dev_err_ratelimited(mc->dev, "%s: @%pa: %s status: 0x%x\n", - client, &addr, tegra264_hub_error_names[bit] ?: "unknown", - value); + client, &addr, + tegra264_hub_error_names[interrupt] ?: "unknown", value); } /* clear interrupts */ From 314ef67d673284d4c070455bd62d332f6d0f8634 Mon Sep 17 00:00:00 2001 From: Miles Krause Date: Wed, 9 Sep 2026 19:26:26 -0400 Subject: [PATCH 055/176] memory: emif: fix device_node reference leak on np_ddr of_get_memory_device_details() takes a reference on the DDR device node via of_parse_phandle() and stores it in emif->np_ddr for later use, but drops that reference without calling of_node_put() on two error paths: the devm_kzalloc() allocation-failure check and the is_dev_data_valid() check. Both return NULL immediately, leaking the node reference each time either failure triggers. The same reference is also never released on the success path: it is kept for the life of the bound device (compared against a later instance's np_ddr in the duplicate-DDR-geometry check) but emif_remove() never calls of_node_put() on it, leaking it every time an EMIF device unbinds. of_node_put() on a NULL pointer is a no-op, so this is also safe for the non-DT get_device_details() path, where np_ddr is left NULL by devm_kzalloc(). Fixes: e6b42eb6a66c ("memory: emif: add device tree support to emif driver") Signed-off-by: Miles Krause Link: https://patch.msgid.link/20260909-master-v1-1-8800f5647ab2@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/emif.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index 2fadad0666b1..44ccc2561835 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -922,6 +922,7 @@ static struct emif_data *of_get_memory_device_details( if (!emif || !pd || !dev_info) { dev_err(dev, "%s: Out of memory!!\n", __func__); + of_node_put(np_ddr); goto error; } @@ -946,6 +947,7 @@ static struct emif_data *of_get_memory_device_details( pd->device_info->io_width, pd->phy_type, pd->ip_rev, emif->dev)) { dev_err(dev, "%s: invalid device data!!\n", __func__); + of_node_put(np_ddr); goto error; } /* @@ -1140,6 +1142,7 @@ static void emif_remove(struct platform_device *pdev) struct emif_data *emif = platform_get_drvdata(pdev); emif_debugfs_exit(emif); + of_node_put(emif->np_ddr); } static void emif_shutdown(struct platform_device *pdev) From 605e6053de5c639abe4cba71644cd3c5fae46374 Mon Sep 17 00:00:00 2001 From: Zhengnan Chen Date: Mon, 31 Aug 2026 14:52:06 +0800 Subject: [PATCH 056/176] dt-bindings: memory-controllers: mtk-smi: Add support for mt8189 Add the SMI LARB, common and sub-common binding descriptions for MT8189. MT8189 adds an SMI sub-common block. Document this topology in mediatek,smi-common.yaml. Signed-off-by: Zhengnan Chen Signed-off-by: Congcong Yao Acked-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260831-8189-smi-support-v4-1-8ae66dd3eeed@mediatek.com Signed-off-by: Krzysztof Kozlowski --- .../mediatek,smi-common.yaml | 21 ++++++++++++++++++- .../memory-controllers/mediatek,smi-larb.yaml | 3 +++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml index 0762e0ff66ef..33c989f7fc33 100644 --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml @@ -16,7 +16,7 @@ description: | MediaTek SMI have two generations of HW architecture, here is the list which generation the SoCs use: generation 1: mt2701 and mt7623. - generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8188, mt8192 and mt8195. + generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8188, mt8189, mt8192 and mt8195. There's slight differences between the two SMI, for generation 2, the register which control the iommu port is at each larb's register base. But @@ -25,6 +25,21 @@ description: | SMI generation 1 to transform the smi clock into emi clock domain, but that is not needed for SMI generation 2. + The smi-common connects with smi-larb and IOMMU. The maximum inputs number of + a smi-common is 8. In SMI generation 2, the engines number may be over 8. + In this case, we use a smi-sub-common to merge some larbs. + The block diagram something is like: + + IOMMU + | | + smi-common + --------------------------- + | | ... + larb0 sub-common ... <-max number is 8 + ---------------- + | | ... + larb1 larbX ... <-max number is 8 + properties: compatible: oneOf: @@ -40,6 +55,8 @@ properties: - mediatek,mt8186-smi-common - mediatek,mt8188-smi-common-vdo - mediatek,mt8188-smi-common-vpp + - mediatek,mt8189-smi-common + - mediatek,mt8189-smi-sub-common - mediatek,mt8192-smi-common - mediatek,mt8195-smi-common-vdo - mediatek,mt8195-smi-common-vpp @@ -108,6 +125,7 @@ allOf: compatible: contains: enum: + - mediatek,mt8189-smi-sub-common - mediatek,mt8195-smi-sub-common then: required: @@ -157,6 +175,7 @@ allOf: - mediatek,mt6795-smi-common - mediatek,mt8167-smi-common - mediatek,mt8173-smi-common + - mediatek,mt8189-smi-common then: properties: diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml index 2e7fac4b5094..9a5dafd7c07e 100644 --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml @@ -27,6 +27,7 @@ properties: - mediatek,mt8183-smi-larb - mediatek,mt8186-smi-larb - mediatek,mt8188-smi-larb + - mediatek,mt8189-smi-larb - mediatek,mt8192-smi-larb - mediatek,mt8195-smi-larb @@ -85,6 +86,7 @@ allOf: - mediatek,mt8183-smi-larb - mediatek,mt8186-smi-larb - mediatek,mt8188-smi-larb + - mediatek,mt8189-smi-larb - mediatek,mt8195-smi-larb then: @@ -119,6 +121,7 @@ allOf: - mediatek,mt6779-smi-larb - mediatek,mt8186-smi-larb - mediatek,mt8188-smi-larb + - mediatek,mt8189-smi-larb - mediatek,mt8192-smi-larb - mediatek,mt8195-smi-larb From 771c036d72eefe36aa6c953ecf44bee4c000a368 Mon Sep 17 00:00:00 2001 From: Zhengnan Chen Date: Mon, 31 Aug 2026 14:52:07 +0800 Subject: [PATCH 057/176] memory: mtk-smi: Add MT8189 support Add the MT8189 SMI common, sub-common and LARB platform data. Enable the GALS clock for the MT8189 SMI sub-common. Signed-off-by: Zhengnan Chen Signed-off-by: Congcong Yao Reviewed-by: Yong Wu Link: https://patch.msgid.link/20260831-8189-smi-support-v4-2-8ae66dd3eeed@mediatek.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index aaeba8ab211e..8c4606cbd73d 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -401,6 +401,30 @@ static const u8 mtk_smi_larb_mt8188_ostd[][SMI_LARB_PORT_NR_MAX] = { [25] = {0x01}, }; +static const u8 mtk_smi_larb_mt8189_ostd[][SMI_LARB_PORT_NR_MAX] = { + [0] = {0x8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10,}, + [1] = {0x8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10,}, + [2] = {0x7, 0x7, 0x4, 0x4, 0x1, 0x1, 0x2, 0x2, 0x7, 0x7,}, + [4] = {0x2f, 0x1e, 0x9, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x5, 0x1, 0x17,}, + [7] = {0x20, 0x2, 0x1, 0x1, 0x1, 0x4, 0x2, 0x1, 0x1, 0x2, 0x3, 0x2, + 0xa, 0xf, 0x4, 0x6, 0x5, 0x1,}, + [9] = {0x6, 0x3, 0xc, 0x6, 0x1, 0x4, 0x3, 0x1, 0x2, 0x4, 0x5, 0x2, + 0x4, 0x2, 0x3, 0xb, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1,}, + [11] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0xb, 0x1, 0x4, 0x6, 0x5, 0x6, 0x1, 0x5, 0x2, + 0x9, 0x5,}, + [13] = {0x2, 0x8, 0x8, 0x8, 0x4, 0x4, 0x4, 0x4, 0x4, 0xe, 0x4, 0x1, + 0x6, 0x6, 0x2,}, + [14] = {0x1, 0x1, 0x1, 0x20, 0xe, 0x4, 0x8, 0x8, 0x6, 0x4,}, + [16] = {0x1e, 0xc, 0x2, 0x8, 0xe, 0x2, 0x1e, 0x10, 0x4, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x4, 0x2, 0x4,}, + [17] = {0x1e, 0xc, 0x2, 0x8, 0xe, 0x2, 0x1e, 0x10, 0x4, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x4, 0x2, 0x4,}, + [19] = {0x2, 0x1, 0x3, 0x1,}, + [20] = {0x7, 0x7, 0x3, 0x3, 0x1, 0x1,}, +}; + static const u8 mtk_smi_larb_mt8192_ostd[][SMI_LARB_PORT_NR_MAX] = { [0] = {0x2, 0x2, 0x28, 0xa, 0xc, 0x28,}, [1] = {0x2, 0x2, 0x18, 0x18, 0x18, 0xa, 0xc, 0x28,}, @@ -533,6 +557,13 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8188 = { .ostd = mtk_smi_larb_mt8188_ostd, }; +static const struct mtk_smi_larb_gen mtk_smi_larb_mt8189 = { + .config_port = mtk_smi_larb_config_port_gen2_general, + .flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG | + MTK_SMI_FLAG_SLEEP_CTL | MTK_SMI_FLAG_CFG_PORT_SEC_CTL, + .ostd = mtk_smi_larb_mt8189_ostd, +}; + static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = { .config_port = mtk_smi_larb_config_port_gen2_general, .ostd = mtk_smi_larb_mt8192_ostd, @@ -556,6 +587,7 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = { {.compatible = "mediatek,mt8183-smi-larb", .data = &mtk_smi_larb_mt8183}, {.compatible = "mediatek,mt8186-smi-larb", .data = &mtk_smi_larb_mt8186}, {.compatible = "mediatek,mt8188-smi-larb", .data = &mtk_smi_larb_mt8188}, + {.compatible = "mediatek,mt8189-smi-larb", .data = &mtk_smi_larb_mt8189}, {.compatible = "mediatek,mt8192-smi-larb", .data = &mtk_smi_larb_mt8192}, {.compatible = "mediatek,mt8195-smi-larb", .data = &mtk_smi_larb_mt8195}, {} @@ -808,6 +840,17 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vpp = { .init = mtk_smi_common_mt8195_init, }; +static const struct mtk_smi_common_plat mtk_smi_common_mt8189 = { + .type = MTK_SMI_GEN2, + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(3) | F_MMU1_LARB(5) | + F_MMU1_LARB(7), +}; + +static const struct mtk_smi_common_plat mtk_smi_sub_common_mt8189 = { + .type = MTK_SMI_GEN2_SUB_COMM, + .has_gals = true, +}; + static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = { .type = MTK_SMI_GEN2, .has_gals = true, @@ -852,6 +895,8 @@ static const struct of_device_id mtk_smi_common_of_ids[] = { {.compatible = "mediatek,mt8186-smi-common", .data = &mtk_smi_common_mt8186}, {.compatible = "mediatek,mt8188-smi-common-vdo", .data = &mtk_smi_common_mt8188_vdo}, {.compatible = "mediatek,mt8188-smi-common-vpp", .data = &mtk_smi_common_mt8188_vpp}, + {.compatible = "mediatek,mt8189-smi-common", .data = &mtk_smi_common_mt8189}, + {.compatible = "mediatek,mt8189-smi-sub-common", .data = &mtk_smi_sub_common_mt8189}, {.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192}, {.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo}, {.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp}, From 146af926951d5ce25d8c7e352f071de56aecc021 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 15 Sep 2026 18:03:35 +0100 Subject: [PATCH 058/176] firmware: arm_scmi: Set generated device fwnode with platform helpers The SCMI transport probe helper creates a platform device for the SCMI core. device_set_of_node_from_dev() propagates the supplier's OF node, but leaves generated devices for non-DT transports without a firmware node. Use platform_device_set_of_node_from_dev() for devicetree suppliers so the shared OF node is referenced and marked as reused. For all other suppliers, use platform_device_set_fwnode() so ACPI and other firmware nodes are propagated with a reference that platform_device_release() can balance. Link: https://patch.msgid.link/20260915-acpi_scmi_pcc-v5-1-298579e9f359@kernel.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index a5492dd90b41..d717d5df1463 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -671,7 +671,10 @@ static int __tag##_probe(struct platform_device *pdev) \ goto err_mem; \ } \ \ - device_set_of_node_from_dev(&spdev->dev, dev); \ + if (dev_of_node(dev)) \ + platform_device_set_of_node_from_dev(spdev, dev); \ + else \ + platform_device_set_fwnode(spdev, dev_fwnode(dev)); \ \ strans.supplier = supplier; \ memcpy(&strans.desc, &(__desc), sizeof(strans.desc)); \ From 8bac2642a97ae68f737e40823b87f015c67cd58e Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 15 Sep 2026 18:03:36 +0100 Subject: [PATCH 059/176] firmware: arm_scmi: Extend transport driver macro to support ACPI Extend the SCMI transport driver helper to support ACPI-based systems. Introduce an internal helper macro that accepts both OF and ACPI match tables, and expose two wrappers: - DEFINE_SCMI_TRANSPORT_DRIVER(...) for DT/OF transports - DEFINE_SCMI_ACPI_TRANSPORT_DRIVER(...) for ACPI transports For ACPI, set the generated platform_driver .acpi_match_table via ACPI_PTR(). The ACPI wrapper relies on the firmware-node propagation provided by the preceding change so fwnode lookups on the spawned platform device see the correct firmware description. Keep existing DT users unchanged while allowing transports to be probed using struct acpi_device_id tables on ACPI platforms. Reviewed-by: Jonathan Cameron Link: https://patch.msgid.link/20260915-acpi_scmi_pcc-v5-2-298579e9f359@kernel.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index d717d5df1463..dda34b879c39 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -9,6 +9,7 @@ #ifndef _SCMI_COMMON_H #define _SCMI_COMMON_H +#include #include #include #include @@ -637,7 +638,8 @@ struct scmi_transport_supplier __supplier = { \ .th.supplier_put = scmi_transport_supplier_put, \ } -#define DEFINE_SCMI_TRANSPORT_DRIVER(__tag, __drv, __desc, __match, __core_ops)\ +#define __DEFINE_SCMI_TRANSPORT_DRIVER(__tag, __drv, __desc, __of_match, \ + __acpi_match, __core_ops) \ static void __tag##_dev_free(void *data) \ { \ struct platform_device *spdev = data; \ @@ -703,11 +705,18 @@ err_mem: \ static struct platform_driver __drv = { \ .driver = { \ .name = #__tag "_transport", \ - .of_match_table = __match, \ + .of_match_table = __of_match, \ + .acpi_match_table = ACPI_PTR(__acpi_match), \ }, \ .probe = __tag##_probe, \ } +#define DEFINE_SCMI_TRANSPORT_DRIVER(__tag, __drv, __desc, __match, __core_ops)\ + __DEFINE_SCMI_TRANSPORT_DRIVER(__tag, __drv, __desc, __match, NULL, __core_ops) + +#define DEFINE_SCMI_ACPI_TRANSPORT_DRIVER(__tag, __drv, __desc, __match, __core_ops)\ + __DEFINE_SCMI_TRANSPORT_DRIVER(__tag, __drv, __desc, NULL, __match, __core_ops) + void scmi_notification_instance_data_set(const struct scmi_handle *handle, void *priv); void *scmi_notification_instance_data_get(const struct scmi_handle *handle); From 16276ab69678a4dd0f81d45ee0b709e036b3afa4 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 15 Sep 2026 18:03:37 +0100 Subject: [PATCH 060/176] firmware: arm_scmi: Convert OF-only paths to generic fwnode in SCMI core Switch SCMI core plumbing from struct device_node * to struct fwnode_handle * so the core can describe SCMI instances and protocols using firmware nodes rather than OF nodes directly. This change: - Replaces core OF property lookups with fwnode_property_*() helpers. - Plumbs fwnode through the SCMI device creation and channel setup paths. - Updates transport ->chan_available() callbacks to take a fwnode. - Stores per-protocol child fwnodes in info->active_protocols so the core can later locate the descriptor for a given protocol ID. - Updates mailbox/optee/smc/virtio transports to accept fwnodes and map back to OF nodes where their existing parsing remains DT-specific. DT-only transports such as mailbox, OP-TEE and SMC still parse DT properties by mapping the fwnode back to an OF node. On non-DT systems these transports report no channel available. This is a mechanical step towards firmware-node neutrality and prepares the SCMI core for non-DT transports, such as an ACPI/PCC transport. DT users continue to work unchanged; no non-DT transport is enabled by this patch. Reviewed-by: Jonathan Cameron Link: https://patch.msgid.link/20260915-acpi_scmi_pcc-v5-3-298579e9f359@kernel.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/bus.c | 37 +++--- drivers/firmware/arm_scmi/common.h | 9 +- drivers/firmware/arm_scmi/driver.c | 113 +++++++++--------- .../firmware/arm_scmi/transports/mailbox.c | 6 +- drivers/firmware/arm_scmi/transports/optee.c | 6 +- drivers/firmware/arm_scmi/transports/smc.c | 9 +- drivers/firmware/arm_scmi/transports/virtio.c | 2 +- 7 files changed, 99 insertions(+), 83 deletions(-) diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index e060edbe7e83..a86fa18fc5d2 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include @@ -429,17 +429,16 @@ static void scmi_device_release(struct device *dev) struct scmi_device *scmi_dev = to_scmi_dev(dev); scmi_device_release_resources(scmi_dev); - of_node_put(dev->of_node); + fwnode_handle_put(dev_fwnode(dev)); kfree_const(scmi_dev->name); kfree(scmi_dev); } static void __scmi_device_destroy(struct scmi_device *scmi_dev) { - pr_debug("(%pOF) Destroying SCMI device '%s' for protocol 0x%x (%s)\n", - scmi_dev->dev.parent->of_node, - dev_name(&scmi_dev->dev), scmi_dev->protocol_id, - scmi_dev->name); + pr_debug("(%pfwf) Destroying SCMI device '%s' for protocol 0x%x (%s)\n", + dev_fwnode(&scmi_dev->dev), dev_name(&scmi_dev->dev), + scmi_dev->protocol_id, scmi_dev->name); device_del(&scmi_dev->dev); scmi_device_release_resources(scmi_dev); @@ -447,7 +446,7 @@ static void __scmi_device_destroy(struct scmi_device *scmi_dev) } static struct scmi_device * -__scmi_device_create(struct device_node *np, struct device *parent, +__scmi_device_create(struct fwnode_handle *fwnode, struct device *parent, int protocol, const char *name) { int id, retval; @@ -458,7 +457,7 @@ __scmi_device_create(struct device_node *np, struct device *parent, * If the same protocol/name device already exist under the same parent * (i.e. SCMI instance) just return the existent device. * This avoids any race between the SCMI driver, creating devices for - * each DT defined protocol at probe time, and the concurrent + * each fwnode defined protocol at probe time, and the concurrent * registration of SCMI drivers. */ scmi_dev = scmi_child_dev_find_get(parent, protocol, name); @@ -495,7 +494,7 @@ __scmi_device_create(struct device_node *np, struct device *parent, scmi_dev->id = id; scmi_dev->dev.parent = parent; - device_set_node(&scmi_dev->dev, of_fwnode_handle(of_node_get(np))); + device_set_node(&scmi_dev->dev, fwnode_handle_get(fwnode)); scmi_dev->dev.bus = &scmi_bus_type; scmi_dev->dev.release = scmi_device_release; dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id); @@ -504,8 +503,8 @@ __scmi_device_create(struct device_node *np, struct device *parent, if (retval) goto put_dev; - pr_debug("(%pOF) Created SCMI device '%s' for protocol 0x%x (%s)\n", - parent->of_node, dev_name(&scmi_dev->dev), protocol, name); + pr_debug("(%pfwf) Created SCMI device '%s' - protocol 0x%x (%s)\n", + fwnode, dev_name(&scmi_dev->dev), protocol, name); return scmi_dev; put_dev: @@ -521,15 +520,15 @@ __scmi_device_create(struct device_node *np, struct device *parent, } static struct scmi_device * -_scmi_device_create(struct device_node *np, struct device *parent, +_scmi_device_create(struct fwnode_handle *fwnode, struct device *parent, int protocol, const char *name) { struct scmi_device *sdev; - sdev = __scmi_device_create(np, parent, protocol, name); + sdev = __scmi_device_create(fwnode, parent, protocol, name); if (!sdev) - pr_err("(%pOF) Failed to create device for protocol 0x%x (%s)\n", - parent->of_node, protocol, name); + pr_err("(%pfwf) Failed to create device - protocol 0x%x (%s)\n", + fwnode, protocol, name); return sdev; } @@ -537,7 +536,7 @@ _scmi_device_create(struct device_node *np, struct device *parent, /** * scmi_device_create - A method to create one or more SCMI devices * - * @np: A reference to the device node to use for the new device(s) + * @fwnode: A reference to the device node to use for the new device(s) * @parent: The parent device to use identifying a specific SCMI instance * @protocol: The SCMI protocol to be associated with this device * @name: The requested-name of the device to be created; this is optional @@ -557,7 +556,7 @@ _scmi_device_create(struct device_node *np, struct device *parent, * could have been potentially created for a whole protocol, unless no * device was found to have been requested for that specific protocol. */ -struct scmi_device *scmi_device_create(struct device_node *np, +struct scmi_device *scmi_device_create(struct fwnode_handle *fwnode, struct device *parent, int protocol, const char *name) { @@ -566,7 +565,7 @@ struct scmi_device *scmi_device_create(struct device_node *np, struct scmi_device *scmi_dev = NULL; if (name) - return _scmi_device_create(np, parent, protocol, name); + return _scmi_device_create(fwnode, parent, protocol, name); mutex_lock(&scmi_requested_devices_mtx); phead = idr_find(&scmi_requested_devices, protocol); @@ -580,7 +579,7 @@ struct scmi_device *scmi_device_create(struct device_node *np, list_for_each_entry(rdev, phead, node) { struct scmi_device *sdev; - sdev = _scmi_device_create(np, parent, + sdev = _scmi_device_create(fwnode, parent, rdev->id_table->protocol_id, rdev->id_table->name); if (sdev) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index dda34b879c39..c91b4c64a5be 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -153,7 +153,7 @@ extern const struct bus_type scmi_bus_type; #define SCMI_BUS_NOTIFY_DEVICE_UNREQUEST 1 extern struct blocking_notifier_head scmi_requested_devices_nh; -struct scmi_device *scmi_device_create(struct device_node *np, +struct scmi_device *scmi_device_create(struct fwnode_handle *fwnode, struct device *parent, int protocol, const char *name); void scmi_device_destroy(struct device *parent, int protocol, const char *name); @@ -207,7 +207,7 @@ struct scmi_chan_info { * @poll_done: Callback to poll transfer status */ struct scmi_transport_ops { - bool (*chan_available)(struct device_node *of_node, int idx); + bool (*chan_available)(struct fwnode_handle *fwnode, int idx); int (*chan_setup)(struct scmi_chan_info *cinfo, struct device *dev, bool tx); int (*chan_free)(int id, void *p, void *data); @@ -233,7 +233,7 @@ struct scmi_transport_ops { * be pending simultaneously in the system. May be overridden by the * get_max_msg op. * @max_msg_size: Maximum size of data payload per message that can be handled. - * @atomic_threshold: Optional system wide DT-configured threshold, expressed + * @atomic_threshold: Optional system wide fwnode-configured threshold, expressed * in microseconds, for atomic operations. * Only SCMI synchronous commands reported by the platform * to have an execution latency lesser-equal to the threshold @@ -241,7 +241,8 @@ struct scmi_transport_ops { * decision is finally left up to the SCMI drivers. * @no_completion_irq: Flag to indicate that this transport has no completion * interrupt and has to be polled. This is similar to the - * force_polling below, except this is set via DT property. + * force_polling below, except this is set via fwnode + * property. * @force_polling: Flag to force this whole transport to use SCMI core polling * mechanism instead of completion interrupts even if available. * @sync_cmds_completed_on_ret: Flag to indicate that the transport assures diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index e6e1a2508f51..162ba46dd965 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -102,7 +102,7 @@ struct scmi_xfers_info { * initialization code to identify this instance. * * Each protocol is initialized independently once for each SCMI platform in - * which is defined by DT and implemented by the SCMI server fw. + * which is defined by fwnode and implemented by the SCMI server fw. */ struct scmi_protocol_instance { const struct scmi_handle *handle; @@ -137,8 +137,9 @@ struct scmi_protocol_instance { * @protocols_imp: List of protocols implemented, currently maximum of * scmi_base_info.num_protocols elements allocated by the * base protocol - * @active_protocols: IDR storing device_nodes for protocols actually defined - * in the DT and confirmed as implemented by fw. + * @active_protocols: IDR storing fwnodes for protocols actually defined + * in the firmware description and confirmed as implemented + * by fw. * @notify_priv: Pointer to private data structure specific to notifications. * @node: List head * @users: Number of users of this instance @@ -416,19 +417,19 @@ EXPORT_SYMBOL_GPL(scmi_protocol_unregister); * scmi_create_protocol_devices - Create devices for all pending requests for * this SCMI instance. * - * @np: The device node describing the protocol + * @fwnode: The firmware node describing the protocol * @info: The SCMI instance descriptor * @prot_id: The protocol ID * @name: The optional name of the device to be created: if not provided this * call will lead to the creation of all the devices currently requested * for the specified protocol. */ -static void scmi_create_protocol_devices(struct device_node *np, +static void scmi_create_protocol_devices(struct fwnode_handle *fwnode, struct scmi_info *info, int prot_id, const char *name) { mutex_lock(&info->devreq_mtx); - scmi_device_create(np, info->dev, prot_id, name); + scmi_device_create(fwnode, info->dev, prot_id, name); mutex_unlock(&info->devreq_mtx); } @@ -753,9 +754,10 @@ struct scmi_xfer *scmi_xfer_raw_get(const struct scmi_handle *handle) * @protocol_id: Identifier of the protocol * * Note that in a regular SCMI stack, usually, a protocol has to be defined in - * the DT to have an associated channel and be usable; but in Raw mode any - * protocol in range is allowed, re-using the Base channel, so as to enable - * fuzzing on any protocol without the need of a fully compiled DT. + * the firmware description to have an associated channel and be usable; but in + * Raw mode any protocol in range is allowed, re-using the Base channel, so as + * to enable fuzzing on any protocol without the need of a fully compiled + * firmware description. * * Return: A reference to the channel to use, or an ERR_PTR */ @@ -769,7 +771,7 @@ scmi_xfer_raw_channel_get(const struct scmi_handle *handle, u8 protocol_id) if (!cinfo) { if (protocol_id == SCMI_PROTOCOL_BASE) return ERR_PTR(-EINVAL); - /* Use Base channel for protocols not defined for DT */ + /* Use Base channel for protocols not defined for fwnode */ cinfo = idr_find(&info->tx_idr, SCMI_PROTOCOL_BASE); if (!cinfo) return ERR_PTR(-EINVAL); @@ -2777,7 +2779,7 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo) return ret; } -static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node, +static int scmi_chan_setup(struct scmi_info *info, struct fwnode_handle *fwnode, int prot_id, bool tx) { int ret, idx; @@ -2793,7 +2795,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node, if (idr_find(idr, prot_id)) return -EEXIST; - if (!info->desc->ops->chan_available(of_node, idx)) { + if (!info->desc->ops->chan_available(fwnode, idx)) { cinfo = idr_find(idr, SCMI_PROTOCOL_BASE); if (unlikely(!cinfo)) /* Possible only if platform has no Rx */ return -EINVAL; @@ -2813,7 +2815,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node, snprintf(name, sizeof(name), SCMI_TRANSPORT_DEVNAME_PREFIX "_%s_%02X", idx ? "rx" : "tx", prot_id); /* Create a uniquely named, dedicated transport device for this chan */ - tdev = scmi_device_create(of_node, info->dev, prot_id, name); + tdev = scmi_device_create(fwnode, info->dev, prot_id, name); if (!tdev) { dev_err(info->dev, "failed to create transport device (%s)\n", name); @@ -2859,14 +2861,14 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node, } static inline int -scmi_txrx_setup(struct scmi_info *info, struct device_node *of_node, +scmi_txrx_setup(struct scmi_info *info, struct fwnode_handle *fwnode, int prot_id) { - int ret = scmi_chan_setup(info, of_node, prot_id, true); + int ret = scmi_chan_setup(info, fwnode, prot_id, true); if (!ret) { /* Rx is optional, report only memory errors */ - ret = scmi_chan_setup(info, of_node, prot_id, false); + ret = scmi_chan_setup(info, fwnode, prot_id, false); if (ret && ret != -ENOMEM) ret = 0; } @@ -2883,15 +2885,15 @@ scmi_txrx_setup(struct scmi_info *info, struct device_node *of_node, * * @info: The SCMI instance descriptor. * - * Initialize all the channels found described in the DT against the underlying - * configured transport using custom defined dedicated devices instead of - * borrowing devices from the SCMI drivers; this way channels are initialized + * Initialize all the channels found described in the fwnode against the + * underlying configured transport using custom defined dedicated devices instead + * of borrowing devices from the SCMI drivers; this way channels are initialized * upfront during core SCMI stack probing and are no more coupled with SCMI * devices used by SCMI drivers. * * Note that, even though a pair of TX/RX channels is associated to each - * protocol defined in the DT, a distinct freshly initialized channel is - * created only if the DT node for the protocol at hand describes a dedicated + * protocol defined in the fwnode, a distinct freshly initialized channel is + * created only if the fwnode for the protocol at hand describes a dedicated * channel: in all the other cases the common BASE protocol channel is reused. * * Return: 0 on Success @@ -2899,17 +2901,17 @@ scmi_txrx_setup(struct scmi_info *info, struct device_node *of_node, static int scmi_channels_setup(struct scmi_info *info) { int ret; - struct device_node *top_np = info->dev->of_node; + struct fwnode_handle *fwnode = dev_fwnode(info->dev); /* Initialize a common generic channel at first */ - ret = scmi_txrx_setup(info, top_np, SCMI_PROTOCOL_BASE); + ret = scmi_txrx_setup(info, fwnode, SCMI_PROTOCOL_BASE); if (ret) return ret; - for_each_available_child_of_node_scoped(top_np, child) { + fwnode_for_each_available_child_node_scoped(fwnode, child) { u32 prot_id; - if (of_property_read_u32(child, "reg", &prot_id)) + if (fwnode_property_read_u32(child, "reg", &prot_id)) continue; if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id)) { @@ -2997,14 +2999,14 @@ static int scmi_bus_notifier(struct notifier_block *nb, static int scmi_device_request_notifier(struct notifier_block *nb, unsigned long action, void *data) { - struct device_node *np; + struct fwnode_handle *fwnode; struct scmi_device_id *id_table = data; struct scmi_info *info = req_nb_to_scmi_info(nb); rcu_read_lock(); - np = idr_find(&info->active_protocols, id_table->protocol_id); + fwnode = idr_find(&info->active_protocols, id_table->protocol_id); rcu_read_unlock(); - if (!np) + if (!fwnode) return NOTIFY_DONE; dev_dbg(info->dev, "%sRequested device (%s) for protocol 0x%x\n", @@ -3013,7 +3015,7 @@ static int scmi_device_request_notifier(struct notifier_block *nb, switch (action) { case SCMI_BUS_NOTIFY_DEVICE_REQUEST: - scmi_create_protocol_devices(np, info, id_table->protocol_id, + scmi_create_protocol_devices(fwnode, info, id_table->protocol_id, id_table->name); break; case SCMI_BUS_NOTIFY_DEVICE_UNREQUEST: @@ -3100,13 +3102,14 @@ static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info) if (!dbg) return NULL; - dbg->name = kstrdup(of_node_full_name(info->dev->of_node), GFP_KERNEL); + dbg->name = kstrdup(fwnode_get_name(dev_fwnode(info->dev)), GFP_KERNEL); if (!dbg->name) { devm_kfree(info->dev, dbg); return NULL; } - of_property_read_string(info->dev->of_node, "compatible", &c_ptr); + fwnode_property_read_string(dev_fwnode(info->dev), "compatible", + &c_ptr); dbg->type = kstrdup(c_ptr, GFP_KERNEL); if (!dbg->type) { kfree(dbg->name); @@ -3212,23 +3215,23 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev) dev_info(dev, "Using %s\n", dev_driver_string(trans->supplier)); - ret = of_property_read_u32(dev->of_node, "arm,max-rx-timeout-ms", - &trans->desc.max_rx_timeout_ms); + ret = fwnode_property_read_u32(dev_fwnode(dev), "arm,max-rx-timeout-ms", + &trans->desc.max_rx_timeout_ms); if (ret && ret != -EINVAL) - dev_err(dev, "Malformed arm,max-rx-timeout-ms DT property.\n"); + dev_err(dev, "Malformed arm,max-rx-timeout-ms property.\n"); - ret = of_property_read_u32(dev->of_node, "arm,max-msg-size", - &trans->desc.max_msg_size); + ret = fwnode_property_read_u32(dev_fwnode(dev), "arm,max-msg-size", + &trans->desc.max_msg_size); if (ret && ret != -EINVAL) - dev_err(dev, "Malformed arm,max-msg-size DT property.\n"); + dev_err(dev, "Malformed arm,max-msg-size property.\n"); - ret = of_property_read_u32(dev->of_node, "arm,max-msg", - &trans->desc.max_msg); + ret = fwnode_property_read_u32(dev_fwnode(dev), "arm,max-msg", + &trans->desc.max_msg); if (ret && ret != -EINVAL) - dev_err(dev, "Malformed arm,max-msg DT property.\n"); + dev_err(dev, "Malformed arm,max-msg property.\n"); - trans->desc.no_completion_irq = of_property_read_bool(dev->of_node, - "arm,no-completion-irq"); + trans->desc.no_completion_irq = + fwnode_property_read_bool(dev_fwnode(dev), "arm,no-completion-irq"); dev_info(dev, "SCMI max-rx-timeout: %dms / max-msg-size: %dbytes / max-msg: %d\n", @@ -3236,8 +3239,8 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev) trans->desc.max_msg); /* System wide atomic threshold for atomic ops .. if any */ - if (!of_property_read_u32(dev->of_node, "atomic-threshold-us", - &trans->desc.atomic_threshold)) + if (!fwnode_property_read_u32(dev_fwnode(dev), "atomic-threshold-us", + &trans->desc.atomic_threshold)) dev_info(dev, "SCMI System wide atomic threshold set to %u us\n", trans->desc.atomic_threshold); @@ -3266,7 +3269,7 @@ static int scmi_probe(struct platform_device *pdev) struct scmi_info *info; bool coex = IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX); struct device *dev = &pdev->dev; - struct device_node *child, *np = dev->of_node; + struct fwnode_handle *child; desc = scmi_transport_setup(dev); if (!desc) { @@ -3305,7 +3308,7 @@ static int scmi_probe(struct platform_device *pdev) handle->devm_protocol_put = scmi_devm_protocol_put; handle->is_transport_atomic = scmi_is_transport_atomic; - /* Setup all channels described in the DT at first */ + /* Setup all channels described in the fwnode at first */ ret = scmi_channels_setup(info); if (ret) { err_str = "failed to setup channels\n"; @@ -3380,10 +3383,10 @@ static int scmi_probe(struct platform_device *pdev) scmi_enable_matching_quirks(info); - for_each_available_child_of_node(np, child) { + fwnode_for_each_available_child_node(dev_fwnode(dev), child) { u32 prot_id; - if (of_property_read_u32(child, "reg", &prot_id)) + if (fwnode_property_read_u32(child, "reg", &prot_id)) continue; if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id)) { @@ -3398,8 +3401,8 @@ static int scmi_probe(struct platform_device *pdev) } /* - * Save this valid DT protocol descriptor amongst - * @active_protocols for this SCMI instance/ + * Save this valid fwnode protocol descriptor amongst + * @active_protocols for this SCMI instance. */ ret = idr_alloc(&info->active_protocols, child, prot_id, prot_id + 1, GFP_KERNEL); @@ -3409,8 +3412,8 @@ static int scmi_probe(struct platform_device *pdev) continue; } - of_node_get(child); - scmi_create_protocol_devices(child, info, prot_id, NULL); + scmi_create_protocol_devices(fwnode_handle_get(child), info, + prot_id, NULL); } return 0; @@ -3437,7 +3440,7 @@ static void scmi_remove(struct platform_device *pdev) { int id; struct scmi_info *info = platform_get_drvdata(pdev); - struct device_node *child; + struct fwnode_handle *child; if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) scmi_raw_mode_cleanup(info->raw); @@ -3462,7 +3465,7 @@ static void scmi_remove(struct platform_device *pdev) mutex_unlock(&info->protocols_mtx); idr_for_each_entry(&info->active_protocols, child, id) - of_node_put(child); + fwnode_handle_put(child); idr_destroy(&info->active_protocols); bus_unregister_notifier(&scmi_bus_type, &info->bus_nb); diff --git a/drivers/firmware/arm_scmi/transports/mailbox.c b/drivers/firmware/arm_scmi/transports/mailbox.c index 308736c3ead9..b692cae4ff25 100644 --- a/drivers/firmware/arm_scmi/transports/mailbox.c +++ b/drivers/firmware/arm_scmi/transports/mailbox.c @@ -77,9 +77,13 @@ static void rx_callback(struct mbox_client *cl, void *m) core->shmem->read_header(smbox->shmem), NULL); } -static bool mailbox_chan_available(struct device_node *of_node, int idx) +static bool mailbox_chan_available(struct fwnode_handle *fwnode, int idx) { int num_mb; + struct device_node *of_node = to_of_node(fwnode); + + if (!of_node) + return false; /* * Just check if bidirrectional channels are involved, and check the diff --git a/drivers/firmware/arm_scmi/transports/optee.c b/drivers/firmware/arm_scmi/transports/optee.c index dbe32e141748..07d3affa0964 100644 --- a/drivers/firmware/arm_scmi/transports/optee.c +++ b/drivers/firmware/arm_scmi/transports/optee.c @@ -314,9 +314,13 @@ static int invoke_process_msg_channel(struct scmi_optee_channel *channel, size_t return 0; } -static bool scmi_optee_chan_available(struct device_node *of_node, int idx) +static bool scmi_optee_chan_available(struct fwnode_handle *fwnode, int idx) { u32 channel_id; + struct device_node *of_node = to_of_node(fwnode); + + if (!of_node) + return false; return !of_property_read_u32_index(of_node, "linaro,optee-channel-id", idx, &channel_id); diff --git a/drivers/firmware/arm_scmi/transports/smc.c b/drivers/firmware/arm_scmi/transports/smc.c index 1fce3ccdeb7f..4a4caeb4be31 100644 --- a/drivers/firmware/arm_scmi/transports/smc.c +++ b/drivers/firmware/arm_scmi/transports/smc.c @@ -84,10 +84,15 @@ static irqreturn_t smc_msg_done_isr(int irq, void *data) return IRQ_HANDLED; } -static bool smc_chan_available(struct device_node *of_node, int idx) +static bool smc_chan_available(struct fwnode_handle *fwnode, int idx) { + struct device_node *of_node = to_of_node(fwnode); + + if (!of_node) + return false; + struct device_node *np __free(device_node) = - of_parse_phandle(of_node, "shmem", 0); + of_parse_phandle(of_node, "shmem", 0); if (!np) return false; diff --git a/drivers/firmware/arm_scmi/transports/virtio.c b/drivers/firmware/arm_scmi/transports/virtio.c index 3282d8271839..6b060d61e0ca 100644 --- a/drivers/firmware/arm_scmi/transports/virtio.c +++ b/drivers/firmware/arm_scmi/transports/virtio.c @@ -375,7 +375,7 @@ static unsigned int virtio_get_max_msg(struct scmi_chan_info *base_cinfo) return vioch->max_msg; } -static bool virtio_chan_available(struct device_node *of_node, int idx) +static bool virtio_chan_available(struct fwnode_handle *fwnode, int idx) { struct scmi_vio_channel *channels, *vioch = NULL; From 17b3cdaa7ab4e9c4fc9b1b6816e80d9ade153272 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 15 Sep 2026 18:03:38 +0100 Subject: [PATCH 061/176] firmware: arm_scmi: Fall back to ACPI HID when "compatible" is absent scmi_debugfs_common_setup() uses the "compatible" property to populate the debugfs transport type string. ACPI-described SCMI devices do not provide that DT property, so the string remains NULL and debugfs setup falls through the allocation failure path. Check the property lookup result and use the ACPI HID as the fallback transport type when an ACPI companion is present. All supported DT SCMI platforms are expected to provide "compatible", so the non-ACPI fallback is not needed for normal DT operation. Keep the explicit "unknown" fallback anyway to avoid passing NULL to kstrdup() if that assumption is ever violated. Link: https://patch.msgid.link/20260915-acpi_scmi_pcc-v5-4-298579e9f359@kernel.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 162ba46dd965..d81f3fd6ea0d 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -16,6 +16,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -3091,6 +3092,15 @@ static void scmi_debugfs_common_cleanup(void *d) kfree(dbg->type); } +static const char *scmi_acpi_device_hid(struct acpi_device *adev) +{ +#ifdef CONFIG_ACPI + return adev ? acpi_device_hid(adev) : "unknown"; +#else + return "unknown"; +#endif +} + static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info) { char top_dir[16]; @@ -3108,8 +3118,10 @@ static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info) return NULL; } - fwnode_property_read_string(dev_fwnode(info->dev), "compatible", - &c_ptr); + if (fwnode_property_read_string(dev_fwnode(info->dev), "compatible", + &c_ptr)) + c_ptr = scmi_acpi_device_hid(ACPI_COMPANION(info->dev)); + dbg->type = kstrdup(c_ptr, GFP_KERNEL); if (!dbg->type) { kfree(dbg->name); From f35ee1a26795665755a6ef2475963a96c5369bb5 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 15 Sep 2026 18:03:39 +0100 Subject: [PATCH 062/176] firmware: arm_scmi: Pass protocol ID to transport chan_available() Pass the protocol ID to the transport chan_available() callback so a transport can distinguish channels associated with different protocols when they share the same firmware node. This is required by the ACPI PCC transport to resolve protocol-exclusive PCC subspaces. Update all transport implementations for the new callback signature. Existing transports ignore the protocol ID, so there is no functional change. Reviewed-by: Jonathan Cameron Link: https://patch.msgid.link/20260915-acpi_scmi_pcc-v5-5-298579e9f359@kernel.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 3 ++- drivers/firmware/arm_scmi/driver.c | 2 +- drivers/firmware/arm_scmi/transports/mailbox.c | 3 ++- drivers/firmware/arm_scmi/transports/optee.c | 3 ++- drivers/firmware/arm_scmi/transports/smc.c | 3 ++- drivers/firmware/arm_scmi/transports/virtio.c | 3 ++- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index c91b4c64a5be..5e25cbadb2fe 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -207,7 +207,8 @@ struct scmi_chan_info { * @poll_done: Callback to poll transfer status */ struct scmi_transport_ops { - bool (*chan_available)(struct fwnode_handle *fwnode, int idx); + bool (*chan_available)(struct fwnode_handle *fwnode, int prot_id, + int idx); int (*chan_setup)(struct scmi_chan_info *cinfo, struct device *dev, bool tx); int (*chan_free)(int id, void *p, void *data); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index d81f3fd6ea0d..d4ab0019bb79 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -2796,7 +2796,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct fwnode_handle *fwnode, if (idr_find(idr, prot_id)) return -EEXIST; - if (!info->desc->ops->chan_available(fwnode, idx)) { + if (!info->desc->ops->chan_available(fwnode, prot_id, idx)) { cinfo = idr_find(idr, SCMI_PROTOCOL_BASE); if (unlikely(!cinfo)) /* Possible only if platform has no Rx */ return -EINVAL; diff --git a/drivers/firmware/arm_scmi/transports/mailbox.c b/drivers/firmware/arm_scmi/transports/mailbox.c index b692cae4ff25..56af2cb0f424 100644 --- a/drivers/firmware/arm_scmi/transports/mailbox.c +++ b/drivers/firmware/arm_scmi/transports/mailbox.c @@ -77,7 +77,8 @@ static void rx_callback(struct mbox_client *cl, void *m) core->shmem->read_header(smbox->shmem), NULL); } -static bool mailbox_chan_available(struct fwnode_handle *fwnode, int idx) +static bool +mailbox_chan_available(struct fwnode_handle *fwnode, int prot_id, int idx) { int num_mb; struct device_node *of_node = to_of_node(fwnode); diff --git a/drivers/firmware/arm_scmi/transports/optee.c b/drivers/firmware/arm_scmi/transports/optee.c index 07d3affa0964..6022f74d28f3 100644 --- a/drivers/firmware/arm_scmi/transports/optee.c +++ b/drivers/firmware/arm_scmi/transports/optee.c @@ -314,7 +314,8 @@ static int invoke_process_msg_channel(struct scmi_optee_channel *channel, size_t return 0; } -static bool scmi_optee_chan_available(struct fwnode_handle *fwnode, int idx) +static bool +scmi_optee_chan_available(struct fwnode_handle *fwnode, int prot_id, int idx) { u32 channel_id; struct device_node *of_node = to_of_node(fwnode); diff --git a/drivers/firmware/arm_scmi/transports/smc.c b/drivers/firmware/arm_scmi/transports/smc.c index 4a4caeb4be31..7fb2736247a3 100644 --- a/drivers/firmware/arm_scmi/transports/smc.c +++ b/drivers/firmware/arm_scmi/transports/smc.c @@ -84,7 +84,8 @@ static irqreturn_t smc_msg_done_isr(int irq, void *data) return IRQ_HANDLED; } -static bool smc_chan_available(struct fwnode_handle *fwnode, int idx) +static bool +smc_chan_available(struct fwnode_handle *fwnode, int prot_id, int idx) { struct device_node *of_node = to_of_node(fwnode); diff --git a/drivers/firmware/arm_scmi/transports/virtio.c b/drivers/firmware/arm_scmi/transports/virtio.c index 6b060d61e0ca..3d608c8c4fe8 100644 --- a/drivers/firmware/arm_scmi/transports/virtio.c +++ b/drivers/firmware/arm_scmi/transports/virtio.c @@ -375,7 +375,8 @@ static unsigned int virtio_get_max_msg(struct scmi_chan_info *base_cinfo) return vioch->max_msg; } -static bool virtio_chan_available(struct fwnode_handle *fwnode, int idx) +static bool +virtio_chan_available(struct fwnode_handle *fwnode, int prot_id, int idx) { struct scmi_vio_channel *channels, *vioch = NULL; From 48339595cbd3e5468473c596025b4fe6096146d8 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 15 Sep 2026 18:03:40 +0100 Subject: [PATCH 063/176] firmware: arm_scmi: Refactor protocol device creation logic Move the protocol validation and device creation logic in scmi_probe() into a reusable scmi_device_check_create() helper. The helper centralizes checks for the protocol ID range, implementation availability and duplicate activation before invoking scmi_create_protocol_devices(). This preserves the existing behavior while allowing the logic to be reused by the ACPI path, where protocol child fwnodes are absent. No functional change intended. Reviewed-by: Jonathan Cameron Link: https://patch.msgid.link/20260915-acpi_scmi_pcc-v5-6-298579e9f359@kernel.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 59 +++++++++++++++++------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index d4ab0019bb79..07c3fbfea2ce 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -3272,6 +3272,39 @@ static void scmi_enable_matching_quirks(struct scmi_info *info) rev->sub_vendor_id, rev->impl_ver); } +static void scmi_device_check_create(struct fwnode_handle *fwnode, int prot_id, + struct scmi_info *info) +{ + int ret; + struct device *dev = info->dev; + struct scmi_handle *handle = &info->handle; + + if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id)) { + dev_err(dev, "Out of range protocol %d\n", prot_id); + return; + } + + if (!scmi_is_protocol_implemented(handle, prot_id)) { + dev_err(dev, "SCMI protocol %d not implemented\n", prot_id); + return; + } + + /* + * Save this valid fwnode protocol descriptor amongst + * @active_protocols for this SCMI instance. + */ + ret = idr_alloc(&info->active_protocols, fwnode, + prot_id, prot_id + 1, GFP_KERNEL); + if (ret != prot_id) { + dev_err(dev, "SCMI protocol %d already activated. Skip\n", + prot_id); + return; + } + + scmi_create_protocol_devices(fwnode_handle_get(fwnode), info, prot_id, + NULL); +} + static int scmi_probe(struct platform_device *pdev) { int ret; @@ -3401,31 +3434,7 @@ static int scmi_probe(struct platform_device *pdev) if (fwnode_property_read_u32(child, "reg", &prot_id)) continue; - if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id)) { - dev_err(dev, "Out of range protocol %d\n", prot_id); - continue; - } - - if (!scmi_is_protocol_implemented(handle, prot_id)) { - dev_err(dev, "SCMI protocol %d not implemented\n", - prot_id); - continue; - } - - /* - * Save this valid fwnode protocol descriptor amongst - * @active_protocols for this SCMI instance. - */ - ret = idr_alloc(&info->active_protocols, child, - prot_id, prot_id + 1, GFP_KERNEL); - if (ret != prot_id) { - dev_err(dev, "SCMI protocol %d already activated. Skip\n", - prot_id); - continue; - } - - scmi_create_protocol_devices(fwnode_handle_get(child), info, - prot_id, NULL); + scmi_device_check_create(child, prot_id, info); } return 0; From b42e73fa118ff455feb5174964d8b5db5aefdfb1 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 15 Sep 2026 18:03:41 +0100 Subject: [PATCH 064/176] firmware: arm_scmi: Add ACPI PCC transport Add an SCMI transport for ACPI-described systems using PCCT PCC subspaces through the Linux PCC mailbox layer. Parse the SCMI Device Properties _DSD packages defined by Arm document 111115A v1.0, sections 2.2.1.1, 2.2.2.1 and 2.2.3. Map transport UIDs to PCC subspaces for common and protocol-exclusive A2P and P2A channels, validate the mappings, and cache them for channel setup. Support the Powercap and System Telemetry protocol properties and add the System Telemetry protocol ID. Implement PCC channel management, message framing, shared-memory bounds validation, and response and notification delivery. Add the corresponding Kconfig, module and ARML0001 ACPI matching plumbing. Link: https://patch.msgid.link/20260915-acpi_scmi_pcc-v5-7-298579e9f359@kernel.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 11 + drivers/firmware/arm_scmi/transports/Kconfig | 12 + drivers/firmware/arm_scmi/transports/Makefile | 2 + drivers/firmware/arm_scmi/transports/pcc.c | 867 ++++++++++++++++++ include/linux/scmi_protocol.h | 1 + 5 files changed, 893 insertions(+) create mode 100644 drivers/firmware/arm_scmi/transports/pcc.c diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 5e25cbadb2fe..af5b025ee072 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -490,6 +490,17 @@ struct scmi_transport_core_operations { const struct scmi_message_operations *msg; }; +struct scmi_dsd_info { + u32 protocol_id; + const char *const property_name; +}; + +static const struct scmi_dsd_info scmi_dsd_info_list[] __maybe_unused = { + { SCMI_PROTOCOL_BASE, "arm-arml0001-transport-pcc" }, + { SCMI_PROTOCOL_POWERCAP, "arm-arml0001-protocol-pcap" }, + { SCMI_PROTOCOL_TELEMETRY, "arm-arml0001-protocol-telemetry" }, +}; + /** * struct scmi_transport_handle - Transport instance handle * @supplier_get: A helper to retrieve the device descriptor, identifying the diff --git a/drivers/firmware/arm_scmi/transports/Kconfig b/drivers/firmware/arm_scmi/transports/Kconfig index 57eccf316e26..0e34fbf25053 100644 --- a/drivers/firmware/arm_scmi/transports/Kconfig +++ b/drivers/firmware/arm_scmi/transports/Kconfig @@ -77,6 +77,18 @@ config ARM_SCMI_TRANSPORT_OPTEE This driver can also be built as a module. If so, the module will be called scmi_transport_optee. +config ARM_SCMI_TRANSPORT_PCC + tristate "SCMI transport based on ACPI PCC" + depends on PCC + select ARM_SCMI_HAVE_TRANSPORT + help + This enables the ACPI PCC mailbox based transport for SCMI. + + If you want the ARM SCMI PROTOCOL stack to include support for a + transport based on ACPI PCC mailboxes, answer Y. + This driver can also be built as a module. If so, the module + will be called scmi_transport_pcc. + config ARM_SCMI_TRANSPORT_VIRTIO tristate "SCMI transport based on VirtIO" depends on VIRTIO diff --git a/drivers/firmware/arm_scmi/transports/Makefile b/drivers/firmware/arm_scmi/transports/Makefile index 3ba3d3bee151..e7c4b8de6251 100644 --- a/drivers/firmware/arm_scmi/transports/Makefile +++ b/drivers/firmware/arm_scmi/transports/Makefile @@ -7,6 +7,8 @@ scmi_transport_mailbox-objs := mailbox.o obj-$(CONFIG_ARM_SCMI_TRANSPORT_MAILBOX) += scmi_transport_mailbox.o scmi_transport_optee-objs := optee.o obj-$(CONFIG_ARM_SCMI_TRANSPORT_OPTEE) += scmi_transport_optee.o +scmi_transport_pcc-objs := pcc.o +obj-$(CONFIG_ARM_SCMI_TRANSPORT_PCC) += scmi_transport_pcc.o scmi_transport_virtio-objs := virtio.o obj-$(CONFIG_ARM_SCMI_TRANSPORT_VIRTIO) += scmi_transport_virtio.o diff --git a/drivers/firmware/arm_scmi/transports/pcc.c b/drivers/firmware/arm_scmi/transports/pcc.c new file mode 100644 index 000000000000..b7501f980d0b --- /dev/null +++ b/drivers/firmware/arm_scmi/transports/pcc.c @@ -0,0 +1,867 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * System Control and Management Interface (SCMI) Message ACPI PCC + * Transport Driver + * + * This transport uses ACPI PCC (PCCT Type 3/4) subspaces via the Linux + * PCC mailbox controller to exchange SCMI messages over the standard + * SCMI Shared Memory Transport (SMT) layout. + * + * PCC subspace selection is conveyed via ACPI SCMI namespace device. + * described in ACPI for System Control and Management Interface Platform + * Design Document[1] + * + * [1] https://support.arm.com/documentation/111115/latest + * + * Copyright (C) 2026 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../common.h" + +#define SCMI_TRANSPORT_PACKAGE_MAX_VERSION (1) +#define SCMI_PROTOCOL_PACKAGE_MAX_VERSION (1) +#define SCMI_TRANSPORT_SHARED_CHANNEL BIT_ULL(0) +#define SCMI_TRANSPORT_P2A_CHANNEL BIT_ULL(1) +#define SCMI_TRANSPORT_FLAGS_MASK (SCMI_TRANSPORT_SHARED_CHANNEL | \ + SCMI_TRANSPORT_P2A_CHANNEL) + +#define SCMI_DSD_GUID_ENTRY_COUNT 2 +#define SCMI_PROTOCOL_MAX_TRANSPORTS 2 + +enum scmi_dsd_property_index { + SCMI_DSD_PROPERTY_NAME, + SCMI_DSD_PROPERTY_VALUE, + SCMI_DSD_PROPERTY_COUNT, +}; + +enum scmi_pcc_transport_index { + SCMI_PCC_TRANSPORT_REVISION, + SCMI_PCC_TRANSPORT_COUNT, + SCMI_PCC_TRANSPORT_DESCRIPTORS, +}; + +enum scmi_pcc_descriptor_index { + SCMI_PCC_DESCRIPTOR_PCCT_INDEX, + SCMI_PCC_DESCRIPTOR_TRANSPORT_UID, + SCMI_PCC_DESCRIPTOR_FLAGS, + SCMI_PCC_DESCRIPTOR_COUNT, +}; + +enum scmi_protocol_property_index { + SCMI_PROTOCOL_PROPERTY_REVISION, + SCMI_PROTOCOL_PROPERTY_TRANSPORTS, + SCMI_PROTOCOL_PROPERTY_ASSOCIATIONS, + SCMI_PROTOCOL_PROPERTY_COUNT, +}; + +enum scmi_protocol_transport_index { + SCMI_PROTOCOL_TRANSPORT_UID, + SCMI_PROTOCOL_TRANSPORT_FLAGS, + SCMI_PROTOCOL_TRANSPORT_COUNT, +}; + +/* + * SCMI specification requires all parameters, message headers, return + * arguments or any protocol data to be expressed in little endian + * format only. + */ +struct pcc_shared_mem { + struct acpi_pcct_ext_pcc_shared_memory header; + u8 msg_payload[]; +}; + +#define SCMI_PCC_MSG_HEADER_SIZE sizeof(u32) +#define SCMI_PCC_STATUS_SIZE sizeof(u32) +#define SCMI_PCC_RESPONSE_OVERHEAD (SCMI_PCC_MSG_HEADER_SIZE + \ + SCMI_PCC_STATUS_SIZE) +#define SCMI_PCC_SHMEM_OVERHEAD (sizeof(struct pcc_shared_mem) + \ + SCMI_PCC_STATUS_SIZE) + +/** + * struct scmi_pcc - Structure representing a SCMI mailbox transport + * + * @cl: Mailbox Client + * @pchan: Transmit/Receive PCC/mailbox channel + * @cinfo: SCMI channel info + */ +struct scmi_pcc { + struct mbox_client cl; + struct pcc_mbox_chan *pchan; + struct scmi_chan_info *cinfo; +}; + +struct pcc_transport { + u64 uid; + u64 flags; + u32 pcc_ss_id; + u32 protocol_id; + struct hlist_node hnode; +}; + +struct pcc_transport_map { + struct fwnode_handle *fwnode; + struct device *dev; + struct list_head node; + DECLARE_HASHTABLE(table, ilog2(MAX_PCC_SUBSPACES / 8)); +}; + +#define client_to_scmi_pcc(c) container_of(c, struct scmi_pcc, cl) + +static struct scmi_transport_core_operations *core; +static LIST_HEAD(pcc_transport_maps); +static DEFINE_MUTEX(pcc_transport_maps_lock); + +static void acpi_scmi_clear_transport_map(struct pcc_transport_map *map) +{ + struct pcc_transport *p; + struct hlist_node *tmp; + int idx; + + hash_for_each_safe(map->table, idx, tmp, p, hnode) { + hash_del(&p->hnode); + kfree(p); + } +} + +static void acpi_scmi_destroy_transport_map(struct pcc_transport_map *map) +{ + acpi_scmi_clear_transport_map(map); + if (map->fwnode) + fwnode_handle_put(map->fwnode); + kfree(map); +} + +static void pcc_transport_map_release(void *data) +{ + struct pcc_transport_map *map = data; + + guard(mutex)(&pcc_transport_maps_lock); + list_del(&map->node); + acpi_scmi_destroy_transport_map(map); +} + +static void acpi_scmi_clear_transport_maps(void) +{ + struct pcc_transport_map *map, *tmp; + + guard(mutex)(&pcc_transport_maps_lock); + list_for_each_entry_safe(map, tmp, &pcc_transport_maps, node) { + list_del(&map->node); + acpi_scmi_destroy_transport_map(map); + } +} + +static const union acpi_object * +acpi_scmi_pkg_elements(const union acpi_object *obj, unsigned int count) +{ + if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != count) + return NULL; + + return obj->package.elements; +} + +static int +acpi_scmi_pkg_u64(const union acpi_object *pkg, unsigned int idx, u64 *val) +{ + const union acpi_object *elem = &pkg->package.elements[idx]; + + if (elem->type != ACPI_TYPE_INTEGER) + return -EINVAL; + + *val = elem->integer.value; + + return 0; +} + +static int acpi_scmi_property(const union acpi_object *properties, + unsigned int idx, const char **name, + const union acpi_object **value) +{ + const union acpi_object *property; + const union acpi_object *elems; + + property = &properties->package.elements[idx]; + elems = acpi_scmi_pkg_elements(property, SCMI_DSD_PROPERTY_COUNT); + if (!elems) + return -EINVAL; + if (elems[SCMI_DSD_PROPERTY_NAME].type != ACPI_TYPE_STRING || + !elems[SCMI_DSD_PROPERTY_NAME].string.pointer) + return -EINVAL; + + *name = elems[SCMI_DSD_PROPERTY_NAME].string.pointer; + *value = &elems[SCMI_DSD_PROPERTY_VALUE]; + + return 0; +} + +static int +acpi_scmi_dsd_parse_transport_package(struct pcc_transport_map *map, + const union acpi_object *obj) +{ + u64 revision, pkg_cnt; + bool common_a2p = false, common_p2a = false; + + if (obj->type != ACPI_TYPE_PACKAGE || + obj->package.count < SCMI_PCC_TRANSPORT_DESCRIPTORS || + acpi_scmi_pkg_u64(obj, SCMI_PCC_TRANSPORT_REVISION, &revision) || + acpi_scmi_pkg_u64(obj, SCMI_PCC_TRANSPORT_COUNT, &pkg_cnt)) + return -EINVAL; + if (revision != SCMI_TRANSPORT_PACKAGE_MAX_VERSION) + return -EINVAL; + if (pkg_cnt != obj->package.count - SCMI_PCC_TRANSPORT_DESCRIPTORS) + return -EINVAL; + + for (u32 idx = 0; idx < pkg_cnt; idx++) { + struct pcc_transport *p, *tmp; + union acpi_object *pack; + u64 pcc_ss_id, uid, flags; + + pack = &obj->package.elements[idx + + SCMI_PCC_TRANSPORT_DESCRIPTORS]; + if (!acpi_scmi_pkg_elements(pack, SCMI_PCC_DESCRIPTOR_COUNT)) { + pr_info("Invalid transport properties pkg %u\n", idx); + return -EINVAL; + } + if (acpi_scmi_pkg_u64(pack, SCMI_PCC_DESCRIPTOR_PCCT_INDEX, + &pcc_ss_id) || + acpi_scmi_pkg_u64(pack, SCMI_PCC_DESCRIPTOR_TRANSPORT_UID, + &uid) || + acpi_scmi_pkg_u64(pack, SCMI_PCC_DESCRIPTOR_FLAGS, &flags)) + return -EINVAL; + if (pcc_ss_id > INT_MAX || + flags & ~SCMI_TRANSPORT_FLAGS_MASK) + return -EINVAL; + + hash_for_each_possible(map->table, tmp, hnode, uid) { + if (tmp->uid == uid) { + pr_info("Duplicate UID %llu\n", uid); + return -EEXIST; + } + } + + if (flags & SCMI_TRANSPORT_SHARED_CHANNEL) { + if (flags & SCMI_TRANSPORT_P2A_CHANNEL) { + if (common_p2a) + return -EINVAL; + common_p2a = true; + } else { + if (common_a2p) + return -EINVAL; + common_a2p = true; + } + } + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + p->uid = uid; + p->pcc_ss_id = pcc_ss_id; + p->flags = flags; + if (p->flags & SCMI_TRANSPORT_SHARED_CHANNEL) + p->protocol_id = SCMI_PROTOCOL_BASE; + + hash_add(map->table, &p->hnode, uid); + } + + if (!common_a2p) + return -EINVAL; + + return 0; +} + +static int +acpi_scmi_dsd_parse_protocol_subpackage(struct pcc_transport_map *map, + const union acpi_object *obj, + int prot_id) +{ + struct pcc_transport *p; + unsigned int pkg_cnt = obj->package.count; + bool found, tx_found = false, rx_found = false; + u64 uid; + + if (pkg_cnt > SCMI_PROTOCOL_MAX_TRANSPORTS) { + pr_warn("Found %u protocol channels, at most %u allowed\n", + pkg_cnt, SCMI_PROTOCOL_MAX_TRANSPORTS); + return -EINVAL; + } + + for (u32 idx = 0; idx < pkg_cnt; idx++) { + union acpi_object *pack = &obj->package.elements[idx]; + u64 flags; + + if (!acpi_scmi_pkg_elements(pack, SCMI_PROTOCOL_TRANSPORT_COUNT) || + acpi_scmi_pkg_u64(pack, SCMI_PROTOCOL_TRANSPORT_UID, &uid) || + acpi_scmi_pkg_u64(pack, SCMI_PROTOCOL_TRANSPORT_FLAGS, + &flags)) + return -EINVAL; + if (flags) + return -EINVAL; + + found = false; + hash_for_each_possible(map->table, p, hnode, uid) { + if (p->uid != uid) + continue; + + found = true; + if (p->flags & SCMI_TRANSPORT_SHARED_CHANNEL) { + pr_info("Protocol package references common PCC subspace %u\n", + p->pcc_ss_id); + return -EINVAL; + } + if (p->protocol_id && p->protocol_id != prot_id) + return -EINVAL; + + if (p->flags & SCMI_TRANSPORT_P2A_CHANNEL) { + if (rx_found) + return -EINVAL; + rx_found = true; + } else { + if (tx_found) + return -EINVAL; + tx_found = true; + } + p->protocol_id = prot_id; + break; + } + + if (!found) + return -ENOENT; + } + + return 0; +} + +static int +acpi_scmi_dsd_parse_protocol_package(struct pcc_transport_map *map, + const union acpi_object *obj, int prot_id) +{ + const union acpi_object *elems; + const union acpi_object *pack; + u64 revision; + int ret; + + elems = acpi_scmi_pkg_elements(obj, SCMI_PROTOCOL_PROPERTY_COUNT); + if (!elems || + acpi_scmi_pkg_u64(obj, SCMI_PROTOCOL_PROPERTY_REVISION, &revision)) + return -EINVAL; + + pack = &elems[SCMI_PROTOCOL_PROPERTY_TRANSPORTS]; + + if (revision != SCMI_PROTOCOL_PACKAGE_MAX_VERSION) + return -EINVAL; + + if (pack->type != ACPI_TYPE_PACKAGE) { + pr_info("Invalid protocol transport package\n"); + return -EINVAL; + } + + /* + * Document 111115A v1.0, Sections 2.2.2.1 and 2.2.3 permit an empty + * protocol transport package when common transport channels exist. + */ + if (pack->package.count != 0) { + ret = acpi_scmi_dsd_parse_protocol_subpackage(map, pack, prot_id); + if (ret) + return ret; + } + + pack = &elems[SCMI_PROTOCOL_PROPERTY_ASSOCIATIONS]; + if (pack->type != ACPI_TYPE_PACKAGE) { + pr_info("Invalid protocol transport association package\n"); + return -EINVAL; + } + + if (pack->package.count != 0) { + pr_info("Non-empty association package not supported\n"); + return -EINVAL; + } + + return 0; +} + +/* ACPI SCMI _DSD UUID: "84a2d1c6-86b6-4199-8dac-9c17449d5e03" */ +static const guid_t acpi_scmi_uuid = GUID_INIT(0x84a2d1c6, 0x86b6, 0x4199, + 0x8d, 0xac, 0x9c, 0x17, + 0x44, 0x9d, 0x5e, 0x03); + +static int acpi_scmi_lookup_protocol_id(const char *name) +{ + for (size_t i = 0; i < ARRAY_SIZE(scmi_dsd_info_list); i++) { + if (!strcmp(name, scmi_dsd_info_list[i].property_name)) + return scmi_dsd_info_list[i].protocol_id; + } + return -ENOENT; +} + +static int acpi_scmi_parse_properties(struct pcc_transport_map *map, + const union acpi_object *properties) +{ + bool transport_found = false; + + if (properties->type != ACPI_TYPE_PACKAGE) + return -EINVAL; + + /* + * Protocol properties reference TransportUIDs declared by the transport + * property. Parse the transport first because _DSD property ordering is + * not defined. + */ + for (u32 i = 0; i < properties->package.count; i++) { + const union acpi_object *v; + const char *name; + int prot_id, ret; + + ret = acpi_scmi_property(properties, i, &name, &v); + if (ret) + return ret; + + prot_id = acpi_scmi_lookup_protocol_id(name); + if (prot_id < 0) + continue; + if (prot_id != SCMI_PROTOCOL_BASE) + continue; + if (v->type != ACPI_TYPE_PACKAGE) + return -EINVAL; + if (transport_found) + return -EEXIST; + + ret = acpi_scmi_dsd_parse_transport_package(map, v); + if (ret) + return ret; + transport_found = true; + } + + if (!transport_found) + return -ENOENT; + + for (u32 i = 0; i < properties->package.count; i++) { + const union acpi_object *v; + const char *name; + int prot_id, ret; + + ret = acpi_scmi_property(properties, i, &name, &v); + if (ret) + return ret; + + prot_id = acpi_scmi_lookup_protocol_id(name); + if (prot_id < 0 || prot_id == SCMI_PROTOCOL_BASE) + continue; + if (v->type != ACPI_TYPE_PACKAGE) + return -EINVAL; + + ret = acpi_scmi_dsd_parse_protocol_package(map, v, prot_id); + if (ret) + return ret; + } + + return 0; +} + +static int acpi_scmi_namespace_fwnode_parse(struct fwnode_handle *fwnode, + struct pcc_transport_map *map) +{ + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_device *adev = to_acpi_device_node(fwnode); + union acpi_object *desc; + acpi_status status; + int ret = -ENOENT; + + if (!adev || !adev->handle) + return -EINVAL; + + status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf, + ACPI_TYPE_PACKAGE); + if (ACPI_FAILURE(status)) + return -EINVAL; + + desc = buf.pointer; + if (desc->package.count % SCMI_DSD_GUID_ENTRY_COUNT) { + ret = -EINVAL; + goto out_free; + } + + /* Look for the device properties GUID. */ + for (u32 i = 0; i < desc->package.count; + i += SCMI_DSD_GUID_ENTRY_COUNT) { + const union acpi_object *guid; + const union acpi_object *properties; + + guid = &desc->package.elements[i]; + properties = &desc->package.elements[i + 1]; + + /* + * The first element must be a GUID and the second one must be + * a package. + */ + if (guid->type != ACPI_TYPE_BUFFER || + guid->buffer.length != UUID_SIZE || + properties->type != ACPI_TYPE_PACKAGE) + continue; + + if (!guid_equal((guid_t *)guid->buffer.pointer, + &acpi_scmi_uuid)) + continue; + + ret = acpi_scmi_parse_properties(map, properties); + break; + } + +out_free: + ACPI_FREE(buf.pointer); + return ret; +} + +static bool +pcc_transport_map_has_ss_id(struct pcc_transport_map *map, u32 pcc_ss_id) +{ + struct pcc_transport *p; + int idx; + + hash_for_each(map->table, idx, p, hnode) { + if (p->pcc_ss_id == pcc_ss_id) + return true; + } + + return false; +} + +static int pcc_transport_map_validate(struct pcc_transport_map *map) +{ + struct pcc_transport_map *iter; + struct pcc_transport *p; + int idx; + + list_for_each_entry(iter, &pcc_transport_maps, node) { + hash_for_each(map->table, idx, p, hnode) { + if (pcc_transport_map_has_ss_id(iter, p->pcc_ss_id)) + return -EEXIST; + } + } + + return 0; +} + +static +struct pcc_transport_map *pcc_transport_map_find(struct fwnode_handle *fwnode) +{ + struct pcc_transport_map *map; + + list_for_each_entry(map, &pcc_transport_maps, node) { + if (map->fwnode == fwnode) + return map; + } + + return NULL; +} + +static +struct pcc_transport_map *pcc_transport_map_get(struct fwnode_handle *fwnode) +{ + struct pcc_transport_map *map; + int ret; + + map = pcc_transport_map_find(fwnode); + if (map) + return map; + + map = kzalloc_obj(*map, GFP_KERNEL); + if (!map) + return ERR_PTR(-ENOMEM); + + hash_init(map->table); + ret = acpi_scmi_namespace_fwnode_parse(fwnode, map); + if (ret) + goto err_free_map; + + ret = pcc_transport_map_validate(map); + if (ret) + goto err_free_map; + + map->fwnode = fwnode_handle_get(fwnode); + list_add_tail(&map->node, &pcc_transport_maps); + + return map; + +err_free_map: + acpi_scmi_clear_transport_map(map); + kfree(map); + return ERR_PTR(ret); +} + +static int pcc_transport_map_manage(struct pcc_transport_map *map, + struct device *dev) +{ + int ret; + + if (!dev || map->dev == dev) + return 0; + if (map->dev) + return -EBUSY; + + /* + * Release the cached map after the SCMI remove path tears down channels. + */ + ret = devm_add_action(dev, pcc_transport_map_release, map); + if (ret) + return ret; + + map->dev = dev; + + return 0; +} + +static int pcc_lookup_ss_id(struct pcc_transport_map *map, u32 prot_id, bool tx) +{ + struct pcc_transport *p; + int idx; + + hash_for_each(map->table, idx, p, hnode) { + if (p->protocol_id != prot_id) + continue; + + if ((!tx && (p->flags & SCMI_TRANSPORT_P2A_CHANNEL)) || + (tx && !(p->flags & SCMI_TRANSPORT_P2A_CHANNEL))) + return p->pcc_ss_id; + } + + return -ENOENT; +} + +static int pcc_get_ss_id(struct fwnode_handle *fwnode, u32 prot_id, bool tx, + struct device *dev) +{ + struct pcc_transport_map *map; + int ret; + + if (!fwnode) + return -EINVAL; + + guard(mutex)(&pcc_transport_maps_lock); + map = pcc_transport_map_get(fwnode); + if (IS_ERR(map)) + return PTR_ERR(map); + + ret = pcc_transport_map_manage(map, dev); + if (ret) + return ret; + + return pcc_lookup_ss_id(map, prot_id, tx); +} + +static bool +pcc_chan_available(struct fwnode_handle *fwnode, int prot_id, int idx) +{ + return pcc_get_ss_id(fwnode, prot_id, !idx, NULL) >= 0; +} + +static void tx_prepare(struct mbox_client *cl, void *m) +{ + struct scmi_pcc *smbox = client_to_scmi_pcc(cl); + struct pcc_shared_mem __iomem *shmem = smbox->pchan->shmem; + struct scmi_xfer *xfer = m; + + /* + * PCC take cares not to call tx_prepare until last transmit is done. + * Request platform interrupt notification if available. + */ + if (xfer->tx.buf) + memcpy_toio(shmem->msg_payload, xfer->tx.buf, xfer->tx.len); + iowrite32(SCMI_PCC_MSG_HEADER_SIZE + xfer->tx.len, + &shmem->header.length); + iowrite32(pack_scmi_header(&xfer->hdr), &shmem->header.command); + iowrite32(smbox->pchan->mchan->mbox->txdone_irq ? + PCC_CMD_COMPLETION_NOTIFY : 0, &shmem->header.flags); +} + +static void rx_callback(struct mbox_client *cl, void *m) +{ + struct scmi_pcc *smbox = client_to_scmi_pcc(cl); + struct pcc_shared_mem __iomem *shmem = smbox->pchan->shmem; + + core->rx_callback(smbox->cinfo, ioread32(&shmem->header.command), NULL); +} + +static int pcc_chan_validate_shmem(struct scmi_chan_info *cinfo, + struct scmi_pcc *smbox) +{ + if (smbox->pchan->shmem_size < SCMI_PCC_SHMEM_OVERHEAD || + smbox->pchan->shmem_size - SCMI_PCC_SHMEM_OVERHEAD < + cinfo->max_msg_size) { + dev_err(cinfo->dev, "misconfigured SCMI PCC shared memory\n"); + return -ENOSPC; + } + + return 0; +} + +static int pcc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, + bool tx) +{ + const char *desc = tx ? "Tx" : "Rx"; + struct device *cdev = cinfo->dev; + struct scmi_pcc *smbox; + struct mbox_client *cl; + int ret, ss_id; + + smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL); + if (!smbox) + return -ENOMEM; + + cl = &smbox->cl; + cl->dev = cdev; + cl->tx_prepare = tx ? tx_prepare : NULL; + cl->rx_callback = rx_callback; + cl->tx_block = false; + + ss_id = pcc_get_ss_id(dev_fwnode(cinfo->dev), cinfo->id, tx, dev); + if (ss_id < 0) + return ss_id; + + smbox->pchan = pcc_mbox_request_channel(cl, ss_id); + if (IS_ERR(smbox->pchan)) { + ret = PTR_ERR(smbox->pchan); + if (ret != -EPROBE_DEFER) + dev_err(cdev, + "failed to request SCMI %s mailbox\n", desc); + return ret; + } + + ret = pcc_chan_validate_shmem(cinfo, smbox); + if (ret) { + pcc_mbox_free_channel(smbox->pchan); + return ret; + } + + cinfo->transport_info = smbox; + smbox->cinfo = cinfo; + + return 0; +} + +static int pcc_chan_free(int id, void *p, void *data) +{ + struct scmi_chan_info *cinfo = p; + struct scmi_pcc *smbox = cinfo->transport_info; + + if (!smbox || IS_ERR_OR_NULL(smbox->pchan)) + return 0; + + pcc_mbox_free_channel(smbox->pchan); + cinfo->transport_info = NULL; + smbox->pchan = NULL; + smbox->cinfo = NULL; + + return 0; +} + +static int +pcc_send_message(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) +{ + struct scmi_pcc *smbox = cinfo->transport_info; + int ret; + + /* + * The mailbox layer has its own queue. However the mailbox queue + * confuses the per message SCMI timeouts since the clock starts when + * the message is submitted into the mailbox queue. So when multiple + * messages are queued up the clock starts on all messages instead of + * only the one inflight. + */ + ret = mbox_send_message(smbox->pchan->mchan, xfer); + /* mbox_send_message returns non-negative value on success */ + if (ret < 0) + return ret; + + return 0; +} + +static void pcc_fetch_response(struct scmi_chan_info *cinfo, + struct scmi_xfer *xfer) +{ + struct scmi_pcc *smbox = cinfo->transport_info; + struct pcc_shared_mem __iomem *shmem = smbox->pchan->shmem; + size_t len = ioread32(&shmem->header.length); + size_t payload_len; + + xfer->hdr.status = ioread32(shmem->msg_payload); + payload_len = len > SCMI_PCC_RESPONSE_OVERHEAD ? + len - SCMI_PCC_RESPONSE_OVERHEAD : 0; + xfer->rx.len = min(xfer->rx.len, payload_len); + + /* msg_payload starts after the header, so skip only the status here. */ + memcpy_fromio(xfer->rx.buf, shmem->msg_payload + SCMI_PCC_STATUS_SIZE, + xfer->rx.len); +} + +static void pcc_fetch_notification(struct scmi_chan_info *cinfo, size_t max_len, + struct scmi_xfer *xfer) +{ + struct scmi_pcc *smbox = cinfo->transport_info; + struct pcc_shared_mem __iomem *shmem = smbox->pchan->shmem; + size_t len = ioread32(&shmem->header.length); + size_t payload_len; + + payload_len = len > SCMI_PCC_MSG_HEADER_SIZE ? + len - SCMI_PCC_MSG_HEADER_SIZE : 0; + xfer->rx.len = min(max_len, payload_len); + memcpy_fromio(xfer->rx.buf, shmem->msg_payload, xfer->rx.len); +} + +static const struct scmi_transport_ops scmi_pcc_ops = { + .chan_available = pcc_chan_available, + .chan_setup = pcc_chan_setup, + .chan_free = pcc_chan_free, + .send_message = pcc_send_message, + .fetch_response = pcc_fetch_response, + .fetch_notification = pcc_fetch_notification, +}; + +static struct scmi_desc scmi_pcc_desc = { + .ops = &scmi_pcc_ops, + .max_rx_timeout_ms = 30, + .max_msg = MBOX_TX_QUEUE_LEN, + .max_msg_size = SCMI_SHMEM_MAX_PAYLOAD_SIZE, +}; + +static const struct acpi_device_id scmi_acpi_ids[] = { + { .id = "ARML0001" }, + { } +}; + +MODULE_DEVICE_TABLE(acpi, scmi_acpi_ids); + +DEFINE_SCMI_ACPI_TRANSPORT_DRIVER(scmi_pcc, scmi_pcc_driver, + scmi_pcc_desc, scmi_acpi_ids, core); + +static int __init scmi_pcc_init(void) +{ + return platform_driver_register(&scmi_pcc_driver); +} + +static void __exit scmi_pcc_exit(void) +{ + platform_driver_unregister(&scmi_pcc_driver); + acpi_scmi_clear_transport_maps(); +} +module_init(scmi_pcc_init); +module_exit(scmi_pcc_exit); + +MODULE_AUTHOR("Sudeep Holla "); +MODULE_DESCRIPTION("SCMI ACPI PCC Transport driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index ba38a26b7d50..0c05925d8595 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -933,6 +933,7 @@ enum scmi_std_protocol { SCMI_PROTOCOL_VOLTAGE = 0x17, SCMI_PROTOCOL_POWERCAP = 0x18, SCMI_PROTOCOL_PINCTRL = 0x19, + SCMI_PROTOCOL_TELEMETRY = 0x1B, }; enum scmi_system_events { From 4f5f291a5704457394c356331bc01cfe7f915a78 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 15 Sep 2026 18:03:42 +0100 Subject: [PATCH 065/176] firmware: arm_scmi: Initialise known ACPI protocol devices and channels Unlike Device Tree, the ACPI SCMI namespace device does not provide child fwnodes to represent each protocol. Iterate over the non-BASE entries in scmi_dsd_info_list to initialize their protocol devices and transport channels. The BASE channel and device are handled by the common setup path. Let the transport channel-availability and SCMI protocol implementation checks decide which of the known protocols are usable on the platform. Reviewed-by: Jonathan Cameron Link: https://patch.msgid.link/20260915-acpi_scmi_pcc-v5-8-298579e9f359@kernel.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 66 +++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 07c3fbfea2ce..599d77abc4a9 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -2901,7 +2901,7 @@ scmi_txrx_setup(struct scmi_info *info, struct fwnode_handle *fwnode, */ static int scmi_channels_setup(struct scmi_info *info) { - int ret; + int ret, idx; struct fwnode_handle *fwnode = dev_fwnode(info->dev); /* Initialize a common generic channel at first */ @@ -2909,21 +2909,34 @@ static int scmi_channels_setup(struct scmi_info *info) if (ret) return ret; - fwnode_for_each_available_child_node_scoped(fwnode, child) { - u32 prot_id; + if (!is_acpi_node(fwnode)) { + fwnode_for_each_available_child_node_scoped(fwnode, child) { + u32 prot_id; - if (fwnode_property_read_u32(child, "reg", &prot_id)) - continue; + if (fwnode_property_read_u32(child, "reg", &prot_id)) + continue; - if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id)) { - dev_err(info->dev, - "Out of range protocol %d\n", prot_id); - continue; + if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id)) { + dev_err(info->dev, + "Out of range protocol %d\n", prot_id); + continue; + } + + ret = scmi_txrx_setup(info, child, prot_id); + if (ret) + return ret; } + } else { + for (idx = 0; idx < ARRAY_SIZE(scmi_dsd_info_list); idx++) { + int prot_id = scmi_dsd_info_list[idx].protocol_id; - ret = scmi_txrx_setup(info, child, prot_id); - if (ret) - return ret; + if (prot_id == SCMI_PROTOCOL_BASE) + continue; + + ret = scmi_txrx_setup(info, fwnode, prot_id); + if (ret) + return ret; + } } return 0; @@ -3273,7 +3286,7 @@ static void scmi_enable_matching_quirks(struct scmi_info *info) } static void scmi_device_check_create(struct fwnode_handle *fwnode, int prot_id, - struct scmi_info *info) + struct scmi_info *info, bool report_missing) { int ret; struct device *dev = info->dev; @@ -3285,6 +3298,9 @@ static void scmi_device_check_create(struct fwnode_handle *fwnode, int prot_id, } if (!scmi_is_protocol_implemented(handle, prot_id)) { + if (!report_missing) + return; + dev_err(dev, "SCMI protocol %d not implemented\n", prot_id); return; } @@ -3307,7 +3323,7 @@ static void scmi_device_check_create(struct fwnode_handle *fwnode, int prot_id, static int scmi_probe(struct platform_device *pdev) { - int ret; + int ret, idx; char *err_str = "probe failure\n"; struct scmi_handle *handle; const struct scmi_desc *desc; @@ -3428,13 +3444,25 @@ static int scmi_probe(struct platform_device *pdev) scmi_enable_matching_quirks(info); - fwnode_for_each_available_child_node(dev_fwnode(dev), child) { - u32 prot_id; + if (!is_acpi_node(dev_fwnode(dev))) { + fwnode_for_each_available_child_node(dev_fwnode(dev), child) { + u32 prot_id; - if (fwnode_property_read_u32(child, "reg", &prot_id)) - continue; + if (fwnode_property_read_u32(child, "reg", &prot_id)) + continue; - scmi_device_check_create(child, prot_id, info); + scmi_device_check_create(child, prot_id, info, true); + } + } else { + for (idx = 0; idx < ARRAY_SIZE(scmi_dsd_info_list); idx++) { + int prot_id = scmi_dsd_info_list[idx].protocol_id; + + if (prot_id == SCMI_PROTOCOL_BASE) + continue; + + scmi_device_check_create(dev_fwnode(dev), prot_id, + info, false); + } } return 0; From 60a89ec8d8f56dcd99611cb054fbf7d0e864cf4e Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 15 Sep 2026 18:03:43 +0100 Subject: [PATCH 066/176] firmware: arm_scmi: Validate PCC shared memory signature Validate the PCC shared memory signature when setting up an SCMI PCC channel. Reject channels whose shared memory signature does not encode PCC_SIGNATURE combined with the PCC subspace ID, so misconfigured firmware is caught before the transport starts using the shared memory region. Reviewed-by: Jonathan Cameron Link: https://patch.msgid.link/20260915-acpi_scmi_pcc-v5-9-298579e9f359@kernel.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/transports/pcc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/arm_scmi/transports/pcc.c b/drivers/firmware/arm_scmi/transports/pcc.c index b7501f980d0b..86d4a097d8ec 100644 --- a/drivers/firmware/arm_scmi/transports/pcc.c +++ b/drivers/firmware/arm_scmi/transports/pcc.c @@ -698,8 +698,11 @@ static void rx_callback(struct mbox_client *cl, void *m) } static int pcc_chan_validate_shmem(struct scmi_chan_info *cinfo, - struct scmi_pcc *smbox) + struct scmi_pcc *smbox, int ss_id) { + struct pcc_shared_mem __iomem *shmem = smbox->pchan->shmem; + u32 valid_signature = ss_id + PCC_SIGNATURE; + if (smbox->pchan->shmem_size < SCMI_PCC_SHMEM_OVERHEAD || smbox->pchan->shmem_size - SCMI_PCC_SHMEM_OVERHEAD < cinfo->max_msg_size) { @@ -707,6 +710,11 @@ static int pcc_chan_validate_shmem(struct scmi_chan_info *cinfo, return -ENOSPC; } + if (ioread32(&shmem->header.signature) != valid_signature) { + dev_err(cinfo->dev, "invalid PCC shared memory signature\n"); + return -EINVAL; + } + return 0; } @@ -742,7 +750,7 @@ static int pcc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, return ret; } - ret = pcc_chan_validate_shmem(cinfo, smbox); + ret = pcc_chan_validate_shmem(cinfo, smbox, ss_id); if (ret) { pcc_mbox_free_channel(smbox->pchan); return ret; From 6229fda9a88656ea7c727c3e2401080c5d3efbc6 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Thu, 3 Sep 2026 12:57:30 -0500 Subject: [PATCH 067/176] tee: move tee_ioctl_shm_register_data to above IOCTL definition Most of the struct definitions for a given IOCTL definition immediately preceded that definition. The struct tee_ioctl_shm_register_data is an exception as it is placed above the TEE_IOC_SHM_REGISTER_FD definition, not the TEE_IOC_SHM_REGISTER one it is to be used with. Move it down to match the others. This is a non-functional change for consistency and to help prevent someone from accidentally using the wrong struct with the wrong IOCTL based on the struct's location. Fix a couple small spelling issues while here. Signed-off-by: Andrew Davis Reviewed-by: Sumit Garg Signed-off-by: Jens Wiklander --- include/uapi/linux/tee.h | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h index 5203977ed35d..76815b0f4b66 100644 --- a/include/uapi/linux/tee.h +++ b/include/uapi/linux/tee.h @@ -384,24 +384,6 @@ struct tee_iocl_supp_send_arg { #define TEE_IOC_SUPPL_SEND _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 7, \ struct tee_ioctl_buf_data) -/** - * struct tee_ioctl_shm_register_data - Shared memory register argument - * @addr: [in] Start address of shared memory to register - * @length: [in/out] Length of shared memory to register - * @flags: [in/out] Flags to/from registration. - * @id: [out] Identifier of the shared memory - * - * The flags field should currently be zero as input. Updated by the call - * with actual flags as defined by TEE_IOCTL_SHM_* above. - * This structure is used as argument for TEE_IOC_SHM_REGISTER below. - */ -struct tee_ioctl_shm_register_data { - __u64 addr; - __u64 length; - __u32 flags; - __s32 id; -}; - /** * struct tee_ioctl_shm_register_fd_data - Shared memory registering argument * @fd: [in] File descriptor identifying dmabuf reference @@ -426,13 +408,31 @@ struct tee_ioctl_shm_register_fd_data { * Returns a file descriptor on success or < 0 on failure * * The returned file descriptor refers to the shared memory object in the - * kernel. The supplied file deccriptor can be closed if it's not needed + * kernel. The supplied file descriptor can be closed if it's not needed * for other purposes. The shared memory is freed when the descriptor is * closed. */ #define TEE_IOC_SHM_REGISTER_FD _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \ struct tee_ioctl_shm_register_fd_data) +/** + * struct tee_ioctl_shm_register_data - Shared memory register argument + * @addr: [in] Start address of shared memory to register + * @length: [in/out] Length of shared memory to register + * @flags: [in/out] Flags to/from registration. + * @id: [out] Identifier of the shared memory + * + * The flags field should currently be zero as input. Updated by the call + * with actual flags as defined by TEE_IOCTL_SHM_* above. + * This structure is used as argument for TEE_IOC_SHM_REGISTER below. + */ +struct tee_ioctl_shm_register_data { + __u64 addr; + __u64 length; + __u32 flags; + __s32 id; +}; + /** * TEE_IOC_SHM_REGISTER - Register shared memory argument * @@ -440,7 +440,7 @@ struct tee_ioctl_shm_register_fd_data { * * Returns a file descriptor on success or < 0 on failure * - * The shared memory is unregisterred when the descriptor is closed. + * The shared memory is unregistered when the descriptor is closed. */ #define TEE_IOC_SHM_REGISTER _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 9, \ struct tee_ioctl_shm_register_data) From 615970476444bdf853c7c3ecdbe809dbdca06c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Tue, 16 Jun 2026 16:38:29 +0200 Subject: [PATCH 068/176] tee: qcomtee: Drop unused assignment of platform_device_id driver data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver explicitly sets the .driver_data member of struct platform_device_id to zero without relying on that value. Drop this unused assignment. While touching this array unify spacing and usage of commas and use a named initializer for .name for improved readability. Signed-off-by: Uwe Kleine-König (The Capable Hub) Reviewed-by: Amirreza Zarrabi Signed-off-by: Jens Wiklander --- drivers/tee/qcomtee/call.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/tee/qcomtee/call.c b/drivers/tee/qcomtee/call.c index 0efc5646242a..4a597eeaf174 100644 --- a/drivers/tee/qcomtee/call.c +++ b/drivers/tee/qcomtee/call.c @@ -798,7 +798,12 @@ static void qcomtee_remove(struct platform_device *pdev) kfree(qcomtee); } -static const struct platform_device_id qcomtee_ids[] = { { "qcomtee", 0 }, {} }; +static const struct platform_device_id qcomtee_ids[] = { + { + .name = "qcomtee", + }, + { } +}; MODULE_DEVICE_TABLE(platform, qcomtee_ids); static struct platform_driver qcomtee_platform_driver = { From b098cb3c3c9b98ba36241efd177ee572a856e37c Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 21 Aug 2026 10:36:45 +0200 Subject: [PATCH 069/176] ARM: at91: Replace __ASSEMBLY__ with __ASSEMBLER__ While the GCC and Clang compilers already define __ASSEMBLER__ auto- matically when compiling assembly code, __ASSEMBLY__ is a macro that only gets defined by the Makefiles in the kernel. This can be very confusing when switching between userspace and kernelspace coding, or when dealing with uapi headers that rather should use __ASSEMBLER__ instead. Let's standardize now on the __ASSEMBLER__ macro to avoid this confusion. Signed-off-by: Thomas Huth Reviewed-by: Claudiu Beznea Acked-by: Alexandre Belloni Link: https://lore.kernel.org/r/20260821083645.200344-1-thuth@redhat.com Signed-off-by: Claudiu Beznea --- arch/arm/mach-at91/pm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index 50c3a425d140..2193e1ab9847 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -25,7 +25,7 @@ #define AT91_PM_ULP1 0x03 #define AT91_PM_BACKUP 0x04 -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct at91_pm_data { void __iomem *pmc; void __iomem *ramc[2]; From b847099fdcc855b04b017a67bd6d3097ce277175 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 3 Sep 2026 11:59:06 +0200 Subject: [PATCH 070/176] soc: atmel: Convert to of_machine_device_match() Use the of_machine_device_match() helper instead of open-coding the same operation. Signed-off-by: Geert Uytterhoeven Reviewed-by: Claudiu Beznea Link: https://lore.kernel.org/r/c3b4f8aceb5f0bc95fa10e6fa469574cfdaa8ee6.1788429505.git.geert+renesas@glider.be Signed-off-by: Claudiu Beznea --- drivers/soc/atmel/soc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c index d89f9dcade7d..7e60c5681ad0 100644 --- a/drivers/soc/atmel/soc.c +++ b/drivers/soc/atmel/soc.c @@ -404,9 +404,7 @@ static const struct of_device_id at91_soc_allowed_list[] __initconst = { static int __init atmel_soc_device_init(void) { - struct device_node *np __free(device_node) = of_find_node_by_path("/"); - - if (!of_match_node(at91_soc_allowed_list, np)) + if (!of_machine_device_match(at91_soc_allowed_list)) return 0; at91_soc_init(socs); From e3049c9edd4181e5ce4f83bbac4b611d921f45ff Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 17 Sep 2026 14:12:54 -0700 Subject: [PATCH 071/176] memory: emif: Remove const from min_tck allocation type In preparation for making the devm_kmalloc family of allocators type aware, we need to make sure that the returned type from the allocation matches the type of the variable being assigned. (Before, the allocator would always return "void *", which can be implicitly cast to any pointer type.) The size was taken from "*pd->min_tck", so the converted allocation type would be "const struct lpddr2_min_tck *", as "pd->min_tck" points to const. The allocation is a writable copy assigned to a "void *" and then memcpy()ed into, so name the unqualified type directly, for a converted allocation type of "struct lpddr2_min_tck *". As there is no general way to remove const qualifiers, this keeps the allocation type matching how the memory is used. No change in allocation size results. Build tested ARCH=x86_64 allmodconfig with GCC 16.2.0: drivers/memory/emif.o Assisted-by: LLM coccinelle Signed-off-by: Kees Cook Link: https://patch.msgid.link/20260917211253.i.532-kees@kernel.org Signed-off-by: Krzysztof Kozlowski --- drivers/memory/emif.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index 44ccc2561835..886c2ca0dc19 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -1064,7 +1064,8 @@ static struct emif_data *get_device_details( } if (pd->min_tck) { - temp = devm_kzalloc(dev, sizeof(*pd->min_tck), GFP_KERNEL); + temp = devm_kzalloc(dev, sizeof(struct lpddr2_min_tck), + GFP_KERNEL); if (temp) { memcpy(temp, pd->min_tck, sizeof(*pd->min_tck)); pd->min_tck = temp; From ca4fb89e677527e32d16c5eb779eb34bccd2b967 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Mon, 14 Sep 2026 17:58:44 +0100 Subject: [PATCH 072/176] dt-bindings: sram: Document samsung,exynos850-acpm-sram Document "samsung,exynos850-acpm-sram" which represents an SRAM region used for ACPM communication on Samsung-based SoCs. The SRAM is consumed as a whole, is not split up using child nodes and properties related to this are not required, that is why "mmio-sram" compatible can't be used for ACPM purposes because it requires child nodes to be declared, which are not needed and make no sense in case of ACPM. Reviewed-by: Krzysztof Kozlowski Reviewed-by: Sam Protsenko Signed-off-by: Alexey Klimov Reviewed-by: Peter Griffin Link: https://patch.msgid.link/20260914-exynos850_sram-v4-1-253871de0f61@linaro.org Signed-off-by: Krzysztof Kozlowski --- Documentation/devicetree/bindings/sram/sram.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/sram/sram.yaml b/Documentation/devicetree/bindings/sram/sram.yaml index b83fc6831947..b9c4d4f3199b 100644 --- a/Documentation/devicetree/bindings/sram/sram.yaml +++ b/Documentation/devicetree/bindings/sram/sram.yaml @@ -43,6 +43,7 @@ properties: - qcom,rpm-msg-ram - qcom,shikra-imem - rockchip,rk3288-pmu-sram + - samsung,exynos850-acpm-sram reg: maxItems: 1 @@ -159,6 +160,7 @@ if: enum: - qcom,rpm-msg-ram - rockchip,rk3288-pmu-sram + - samsung,exynos850-acpm-sram then: required: - "#address-cells" From be615311c48f9ce69fffa88d66fba430a3f800b0 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 17 Sep 2026 10:16:03 +0100 Subject: [PATCH 073/176] soc/tegra: fuse: Add Tegra264 support Add the fuse SoC data for the Tegra264 device which defines the address range and keepouts for the fuse registers. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/fuse-tegra.c | 11 +- drivers/soc/tegra/fuse/fuse-tegra30.c | 168 +++++++++++++++++++++++++- drivers/soc/tegra/fuse/fuse.h | 7 +- 3 files changed, 183 insertions(+), 3 deletions(-) diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index 39654964c35c..b8c8ccf80056 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -65,6 +65,9 @@ static struct tegra_fuse *fuse = &(struct tegra_fuse) { }; static const struct of_device_id tegra_fuse_match[] = { +#ifdef CONFIG_ARCH_TEGRA_264_SOC + { .compatible = "nvidia,tegra264-efuse", .data = &tegra264_fuse_soc }, +#endif #ifdef CONFIG_ARCH_TEGRA_234_SOC { .compatible = "nvidia,tegra234-efuse", .data = &tegra234_fuse_soc }, #endif @@ -175,6 +178,11 @@ static int tegra_fuse_probe(struct platform_device *pdev) case TEGRA241: fuse->soc = &tegra241_fuse_soc; break; +#endif +#if defined(CONFIG_ARCH_TEGRA_264_SOC) + case TEGRA264: + fuse->soc = &tegra264_fuse_soc; + break; #endif default: return dev_err_probe(&pdev->dev, -EINVAL, "Unsupported SoC: %02x\n", chip); @@ -413,7 +421,8 @@ const struct attribute_group tegra_soc_attr_group = { #if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \ IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC) || \ - IS_ENABLED(CONFIG_ARCH_TEGRA_241_SOC) + IS_ENABLED(CONFIG_ARCH_TEGRA_241_SOC) || \ + IS_ENABLED(CONFIG_ARCH_TEGRA_264_SOC) static ssize_t platform_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index 2fad8b13a3b9..623848116b69 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c @@ -39,7 +39,8 @@ defined(CONFIG_ARCH_TEGRA_186_SOC) || \ defined(CONFIG_ARCH_TEGRA_194_SOC) || \ defined(CONFIG_ARCH_TEGRA_234_SOC) || \ - defined(CONFIG_ARCH_TEGRA_241_SOC) + defined(CONFIG_ARCH_TEGRA_241_SOC) || \ + defined(CONFIG_ARCH_TEGRA_264_SOC) static u32 tegra30_fuse_read_early(struct tegra_fuse *fuse, unsigned int offset) { if (WARN_ON(!fuse->base)) @@ -802,3 +803,168 @@ const struct tegra_fuse_soc tegra241_fuse_soc = { .soc_attr_group = &tegra194_soc_attr_group, }; #endif + +#ifdef CONFIG_ARCH_TEGRA_264_SOC +static const struct nvmem_keepout tegra264_fuse_keepouts[] = { + { .start = 0x0019c, .end = 0x001a0 }, + { .start = 0x00308, .end = 0x00310 }, + { .start = 0x0032c, .end = 0x00334 }, + { .start = 0x00350, .end = 0x00354 }, + { .start = 0x00494, .end = 0x0049c }, + { .start = 0x0078c, .end = 0x00790 }, + { .start = 0x007a0, .end = 0x007a8 }, + { .start = 0x007dc, .end = 0x007e4 }, + { .start = 0x008d8, .end = 0x008dc }, + { .start = 0x0096c, .end = 0x00970 }, + { .start = 0x00974, .end = 0x0097c }, + { .start = 0x009f4, .end = 0x009f8 }, + { .start = 0x00a14, .end = 0x00a20 }, + { .start = 0x00a44, .end = 0x00a4c }, + { .start = 0x00a50, .end = 0x00a58 }, + { .start = 0x00a5c, .end = 0x00a64 }, + { .start = 0x00a68, .end = 0x00a70 }, + { .start = 0x00acc, .end = 0x00ad0 }, + { .start = 0x00b0c, .end = 0x00b18 }, + { .start = 0x00c80, .end = 0x00c8c }, + { .start = 0x00dac, .end = 0x00db4 }, + { .start = 0x00db8, .end = 0x00dbc }, + { .start = 0x00e0c, .end = 0x00e10 }, + { .start = 0x00fd0, .end = 0x01f00 }, + { .start = 0x01f1c, .end = 0x10064 }, + { .start = 0x10084, .end = 0x100a0 }, + { .start = 0x100a4, .end = 0x1019c }, + { .start = 0x101a0, .end = 0x101cc }, + { .start = 0x101d0, .end = 0x10308 }, + { .start = 0x10310, .end = 0x1055c }, + { .start = 0x1057c, .end = 0x106b0 }, + { .start = 0x106b4, .end = 0x11008 }, + { .start = 0x1100c, .end = 0x11018 }, + { .start = 0x11020, .end = 0x110b8 }, + { .start = 0x110c4, .end = 0x110c8 }, + { .start = 0x110e8, .end = 0x110ec }, + { .start = 0x110f0, .end = 0x11124 }, + { .start = 0x11128, .end = 0x11168 }, + { .start = 0x1116c, .end = 0x111b8 }, + { .start = 0x111bc, .end = 0x111e4 }, + { .start = 0x111e8, .end = 0x111ec }, + { .start = 0x111f0, .end = 0x1121c }, + { .start = 0x11250, .end = 0x1133c }, + { .start = 0x11340, .end = 0x113c8 }, + { .start = 0x113d0, .end = 0x11420 }, + { .start = 0x11430, .end = 0x11440 }, + { .start = 0x11444, .end = 0x11468 }, + { .start = 0x1146c, .end = 0x114a8 }, + { .start = 0x114ac, .end = 0x115cc }, + { .start = 0x115d0, .end = 0x115dc }, + { .start = 0x115e0, .end = 0x116b4 }, + { .start = 0x116bc, .end = 0x11740 }, + { .start = 0x11744, .end = 0x117b8 }, + { .start = 0x117bc, .end = 0x11810 }, + { .start = 0x11814, .end = 0x11850 }, + { .start = 0x11858, .end = 0x118a0 }, + { .start = 0x118ac, .end = 0x11b48 }, + { .start = 0x11b50, .end = 0x11b5c }, + { .start = 0x11b60, .end = 0x11bf8 }, + { .start = 0x11bfc, .end = 0x11c18 }, + { .start = 0x11c40, .end = 0x12000 }, + { .start = 0x12004, .end = 0x12010 }, + { .start = 0x12014, .end = 0x120fc }, + { .start = 0x1211c, .end = 0x12120 }, + { .start = 0x12124, .end = 0x12144 }, + { .start = 0x1214c, .end = 0x12300 }, + { .start = 0x12308, .end = 0x1236c }, + { .start = 0x12370, .end = 0x126ac }, + { .start = 0x126b0, .end = 0x12c60 }, + { .start = 0x12c64, .end = 0x12d94 }, + { .start = 0x12da4, .end = 0x13004 }, + { .start = 0x13008, .end = 0x1300c }, + { .start = 0x13010, .end = 0x13014 }, + { .start = 0x13018, .end = 0x13020 }, + { .start = 0x13064, .end = 0x13084 }, + { .start = 0x130a0, .end = 0x130a4 }, + { .start = 0x130b8, .end = 0x130c4 }, + { .start = 0x130c8, .end = 0x130e8 }, + { .start = 0x130ec, .end = 0x130f0 }, + { .start = 0x130fc, .end = 0x1311c }, + { .start = 0x13120, .end = 0x13128 }, + { .start = 0x13144, .end = 0x1314c }, + { .start = 0x13168, .end = 0x1316c }, + { .start = 0x1319c, .end = 0x131a0 }, + { .start = 0x131ac, .end = 0x131c0 }, + { .start = 0x131cc, .end = 0x131d0 }, + { .start = 0x131e4, .end = 0x131e8 }, + { .start = 0x131ec, .end = 0x131f0 }, + { .start = 0x1321c, .end = 0x13250 }, + { .start = 0x132f0, .end = 0x13310 }, + { .start = 0x1332c, .end = 0x13334 }, + { .start = 0x1333c, .end = 0x13344 }, + { .start = 0x13350, .end = 0x13354 }, + { .start = 0x1336c, .end = 0x13370 }, + { .start = 0x133ac, .end = 0x133b0 }, + { .start = 0x133c8, .end = 0x133d0 }, + { .start = 0x13420, .end = 0x13430 }, + { .start = 0x13440, .end = 0x13444 }, + { .start = 0x13468, .end = 0x13470 }, + { .start = 0x13494, .end = 0x1349c }, + { .start = 0x134a8, .end = 0x134ac }, + { .start = 0x13544, .end = 0x1354c }, + { .start = 0x1355c, .end = 0x1357c }, + { .start = 0x135cc, .end = 0x135e0 }, + { .start = 0x135e4, .end = 0x13608 }, + { .start = 0x1360c, .end = 0x13620 }, + { .start = 0x136ac, .end = 0x136bc }, + { .start = 0x136c0, .end = 0x136c8 }, + { .start = 0x13714, .end = 0x13718 }, + { .start = 0x13724, .end = 0x13728 }, + { .start = 0x1372c, .end = 0x13730 }, + { .start = 0x13734, .end = 0x1373c }, + { .start = 0x13740, .end = 0x13744 }, + { .start = 0x13754, .end = 0x13758 }, + { .start = 0x13760, .end = 0x13784 }, + { .start = 0x1378c, .end = 0x13790 }, + { .start = 0x137a0, .end = 0x137a8 }, + { .start = 0x137b8, .end = 0x137bc }, + { .start = 0x137dc, .end = 0x137e4 }, + { .start = 0x137ec, .end = 0x137f0 }, + { .start = 0x13800, .end = 0x13818 }, + { .start = 0x13820, .end = 0x13828 }, + { .start = 0x13830, .end = 0x13858 }, + { .start = 0x138a0, .end = 0x138b0 }, + { .start = 0x138d0, .end = 0x138dc }, + { .start = 0x1396c, .end = 0x13970 }, + { .start = 0x13974, .end = 0x1397c }, + { .start = 0x139f4, .end = 0x139f8 }, + { .start = 0x13a14, .end = 0x13a20 }, + { .start = 0x13a44, .end = 0x13a4c }, + { .start = 0x13a50, .end = 0x13a58 }, + { .start = 0x13a5c, .end = 0x13a64 }, + { .start = 0x13a68, .end = 0x13a70 }, + { .start = 0x13acc, .end = 0x13ad8 }, + { .start = 0x13b0c, .end = 0x13b18 }, + { .start = 0x13b48, .end = 0x13b50 }, + { .start = 0x13b5c, .end = 0x13b60 }, + { .start = 0x13bf8, .end = 0x13bfc }, + { .start = 0x13c18, .end = 0x13c40 }, + { .start = 0x13c60, .end = 0x13c64 }, + { .start = 0x13c74, .end = 0x13c8c }, + { .start = 0x13d94, .end = 0x13da4 }, + { .start = 0x13dac, .end = 0x13db4 }, + { .start = 0x13db8, .end = 0x13dbc }, + { .start = 0x13df4, .end = 0x13e04 }, + { .start = 0x13e0c, .end = 0x13e10 }, +}; + +static const struct tegra_fuse_info tegra264_fuse_info = { + .read = tegra30_fuse_read, + .size = 0x13eb8, +}; + +const struct tegra_fuse_soc tegra264_fuse_soc = { + .init = tegra30_fuse_init, + .info = &tegra264_fuse_info, + .keepouts = tegra264_fuse_keepouts, + .num_keepouts = ARRAY_SIZE(tegra264_fuse_keepouts), + .soc_attr_group = &tegra194_soc_attr_group, + .clk_suspend_on = false, +}; +#endif diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h index 9fee6ad6ad9e..0fb97508db0a 100644 --- a/drivers/soc/tegra/fuse/fuse.h +++ b/drivers/soc/tegra/fuse/fuse.h @@ -125,7 +125,8 @@ extern const struct tegra_fuse_soc tegra186_fuse_soc; #if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \ IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC) || \ - IS_ENABLED(CONFIG_ARCH_TEGRA_241_SOC) + IS_ENABLED(CONFIG_ARCH_TEGRA_241_SOC) || \ + IS_ENABLED(CONFIG_ARCH_TEGRA_264_SOC) extern const struct attribute_group tegra194_soc_attr_group; #endif @@ -141,4 +142,8 @@ extern const struct tegra_fuse_soc tegra234_fuse_soc; extern const struct tegra_fuse_soc tegra241_fuse_soc; #endif +#ifdef CONFIG_ARCH_TEGRA_264_SOC +extern const struct tegra_fuse_soc tegra264_fuse_soc; +#endif + #endif From 96c2b43b1fb305e91700f64e9f758fc140c66b83 Mon Sep 17 00:00:00 2001 From: Luca Leonardo Scorcia Date: Fri, 18 Sep 2026 19:55:27 +0200 Subject: [PATCH 074/176] soc: mediatek: mt8167-mmsys: add routes for all display paths mt8167 display output pipeline can be configured in many different ways. Add support for additional routes according to the SoC data sheet and Android sources. There's a few inconsistencies between those two, but assume the Android sources are correct since they are required to drive HDMI output via DPI1. Signed-off-by: Luca Leonardo Scorcia Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: AngeloGioacchino Del Regno --- drivers/soc/mediatek/mt8167-mmsys.h | 183 ++++++++++++++++++++++++++-- 1 file changed, 174 insertions(+), 9 deletions(-) diff --git a/drivers/soc/mediatek/mt8167-mmsys.h b/drivers/soc/mediatek/mt8167-mmsys.h index 001379373507..858779ace895 100644 --- a/drivers/soc/mediatek/mt8167-mmsys.h +++ b/drivers/soc/mediatek/mt8167-mmsys.h @@ -5,35 +5,200 @@ #define MT8167_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN 0x030 #define MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN 0x038 +#define MT8167_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN 0x03c #define MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN 0x058 +#define MT8167_DISP_REG_CONFIG_DISP_WDMA0_SEL_IN 0x05c +#define MT8167_DISP_REG_CONFIG_DISP_UFOE_SEL_IN 0x060 #define MT8167_DISP_REG_CONFIG_DISP_DSI0_SEL_IN 0x064 +#define MT8167_DISP_REG_CONFIG_DISP_DPI0_SEL_IN 0x068 #define MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN 0x06c +#define MT8167_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL_IN 0x070 +#define MT8167_DISP_REG_CONFIG_DISP_DPI1_SEL_IN 0x074 + +#define MT8167_OVL0_MOUT_EN_COLOR0 0x1 +#define MT8167_OVL0_MOUT_EN_WDMA0 0x2 +#define MT8167_OVL0_MOUT_EN_MASK 0x3 #define MT8167_DITHER_MOUT_EN_RDMA0 0x1 +#define MT8167_DITHER_MOUT_EN_UFOE 0x2 +#define MT8167_DITHER_MOUT_EN_WDMA0 0x4 #define MT8167_DITHER_MOUT_EN_MASK 0x7 -#define MT8167_RDMA0_SOUT_DSI0 0x2 -#define MT8167_RDMA0_SOUT_MASK 0x3 +#define MT8167_UFOE_MOUT_EN_DSI0 0x1 +#define MT8167_UFOE_MOUT_EN_DPI0 0x2 +/* + * For some reason Android sources and the data sheet don't agree here, + * the data sheet has UFOE_MOUT_EN_WDMA0 as 0x4 and does not mention DPI1. + */ +#define MT8167_UFOE_MOUT_EN_DPI1 0x4 +#define MT8167_UFOE_MOUT_EN_WDMA0 0x8 +#define MT8167_UFOE_MOUT_EN_MASK 0xF +#define MT8167_COLOR0_SEL_IN_RDMA0 0x0 +#define MT8167_COLOR0_SEL_IN_OVL0 0x1 +#define MT8167_COLOR0_SEL_IN_MASK 0x1 + +#define MT8167_WDMA0_SEL_IN_OVL0 0x0 +#define MT8167_WDMA0_SEL_IN_DITHER 0x1 +#define MT8167_WDMA0_SEL_IN_UFOE 0x2 +#define MT8167_WDMA0_SEL_IN_MASK 0x3 + +#define MT8167_UFOE_SEL_IN_RDMA0 0x0 +#define MT8167_UFOE_SEL_IN_DITHER 0x1 +#define MT8167_UFOE_SEL_IN_MASK 0x1 + +#define MT8167_DSI0_SEL_IN_UFOE 0x0 #define MT8167_DSI0_SEL_IN_RDMA0 0x1 +#define MT8167_DSI0_SEL_IN_RDMA1 0x2 #define MT8167_DSI0_SEL_IN_MASK 0x3 +#define MT8167_DPI0_SEL_IN_UFOE 0x0 +#define MT8167_DPI0_SEL_IN_RDMA0 0x1 +#define MT8167_DPI0_SEL_IN_RDMA1 0x2 +#define MT8167_DPI0_SEL_IN_MASK 0x3 + +#define MT8167_DPI1_SEL_IN_UFOE 0x0 +#define MT8167_DPI1_SEL_IN_RDMA0 0x1 +#define MT8167_DPI1_SEL_IN_RDMA1 0x2 +#define MT8167_DPI1_SEL_IN_MASK 0x3 + +#define MT8167_RDMA0_SOUT_UFOE 0x0 +#define MT8167_RDMA0_SOUT_COLOR0 0x1 +#define MT8167_RDMA0_SOUT_DSI0 0x2 +#define MT8167_RDMA0_SOUT_DPI0 0x3 +/* DPI1 is only defined in Android sources, not in the data sheet */ +#define MT8167_RDMA0_SOUT_DPI1 0x4 +#define MT8167_RDMA0_SOUT_MASK 0x7 + +#define MT8167_RDMA1_SOUT_DSI0 0x0 +#define MT8167_RDMA1_SOUT_DPI0 0x1 +/* DPI1 is only defined in Android sources, not in the data sheet */ +#define MT8167_RDMA1_SOUT_DPI1 0x2 +#define MT8167_RDMA1_SOUT_MASK 0x3 + static const struct mtk_mmsys_routes mt8167_mmsys_routing_table[] = { + /* OVL0<->COLOR0 */ MMSYS_ROUTE(OVL, 0, COLOR, 0, - MT8167_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, OVL0_MOUT_EN_COLOR0, - OVL0_MOUT_EN_COLOR0), + MT8167_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, MT8167_OVL0_MOUT_EN_MASK, + MT8167_OVL0_MOUT_EN_COLOR0), + MMSYS_ROUTE(OVL, 0, COLOR, 0, + MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, MT8167_COLOR0_SEL_IN_MASK, + MT8167_COLOR0_SEL_IN_OVL0), + + /* OVL0<->WDMA0 */ + MMSYS_ROUTE(OVL, 0, WDMA, 0, + MT8167_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, MT8167_OVL0_MOUT_EN_MASK, + MT8167_OVL0_MOUT_EN_WDMA0), + MMSYS_ROUTE(OVL, 0, WDMA, 0, + MT8167_DISP_REG_CONFIG_DISP_WDMA0_SEL_IN, MT8167_COLOR0_SEL_IN_MASK, + MT8167_WDMA0_SEL_IN_OVL0), + + /* DITHER0 outputs */ MMSYS_ROUTE(DITHER, 0, RDMA, 0, MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN, MT8167_DITHER_MOUT_EN_MASK, MT8167_DITHER_MOUT_EN_RDMA0), - MMSYS_ROUTE(OVL, 0, COLOR, 0, - MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, COLOR0_SEL_IN_OVL0, - COLOR0_SEL_IN_OVL0), - MMSYS_ROUTE(RDMA, 0, DSI, 0, + MMSYS_ROUTE(DITHER, 0, UFOE, 0, + MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN, MT8167_DITHER_MOUT_EN_MASK, + MT8167_DITHER_MOUT_EN_UFOE), + MMSYS_ROUTE(DITHER, 0, WDMA, 0, + MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN, MT8167_DITHER_MOUT_EN_MASK, + MT8167_DITHER_MOUT_EN_WDMA0), + + /* UFOE<->DSI0 */ + MMSYS_ROUTE(UFOE, 0, DSI, 0, + MT8167_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN, MT8167_UFOE_MOUT_EN_MASK, + MT8167_UFOE_MOUT_EN_DSI0), + MMSYS_ROUTE(UFOE, 0, DSI, 0, MT8167_DISP_REG_CONFIG_DISP_DSI0_SEL_IN, MT8167_DSI0_SEL_IN_MASK, - MT8167_DSI0_SEL_IN_RDMA0), + MT8167_DSI0_SEL_IN_UFOE), + + /* UFOE<->DPI0 */ + MMSYS_ROUTE(UFOE, 0, DPI, 0, + MT8167_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN, MT8167_UFOE_MOUT_EN_MASK, + MT8167_UFOE_MOUT_EN_DPI0), + MMSYS_ROUTE(UFOE, 0, DPI, 0, + MT8167_DISP_REG_CONFIG_DISP_DPI0_SEL_IN, MT8167_DPI0_SEL_IN_MASK, + MT8167_DPI0_SEL_IN_UFOE), + + /* UFOE<->DPI1 */ + MMSYS_ROUTE(UFOE, 0, DPI, 1, + MT8167_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN, MT8167_UFOE_MOUT_EN_MASK, + MT8167_UFOE_MOUT_EN_DPI1), + MMSYS_ROUTE(UFOE, 0, DPI, 1, + MT8167_DISP_REG_CONFIG_DISP_DPI1_SEL_IN, MT8167_DPI1_SEL_IN_MASK, + MT8167_DPI1_SEL_IN_UFOE), + + /* UFOE<->WDMA0 */ + MMSYS_ROUTE(UFOE, 0, WDMA, 0, + MT8167_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN, MT8167_UFOE_MOUT_EN_MASK, + MT8167_UFOE_MOUT_EN_WDMA0), + MMSYS_ROUTE(UFOE, 0, WDMA, 0, + MT8167_DISP_REG_CONFIG_DISP_WDMA0_SEL_IN, MT8167_WDMA0_SEL_IN_MASK, + MT8167_WDMA0_SEL_IN_UFOE), + + /* RDMA0<->UFOE */ + MMSYS_ROUTE(RDMA, 0, UFOE, 0, + MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_MASK, + MT8167_RDMA0_SOUT_UFOE), + MMSYS_ROUTE(RDMA, 0, UFOE, 0, + MT8167_DISP_REG_CONFIG_DISP_UFOE_SEL_IN, MT8167_UFOE_SEL_IN_MASK, + MT8167_UFOE_SEL_IN_RDMA0), + + /* RDMA0->COLOR0 */ + MMSYS_ROUTE(RDMA, 0, COLOR, 0, + MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_MASK, + MT8167_RDMA0_SOUT_COLOR0), + MMSYS_ROUTE(RDMA, 0, COLOR, 0, + MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, MT8167_COLOR0_SEL_IN_MASK, + MT8167_COLOR0_SEL_IN_RDMA0), + + /* RDMA0<->DSI0 */ MMSYS_ROUTE(RDMA, 0, DSI, 0, MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_MASK, MT8167_RDMA0_SOUT_DSI0), + MMSYS_ROUTE(RDMA, 0, DSI, 0, + MT8167_DISP_REG_CONFIG_DISP_DSI0_SEL_IN, MT8167_DSI0_SEL_IN_MASK, + MT8167_DSI0_SEL_IN_RDMA0), + + /* RDMA0<->DPI0 */ + MMSYS_ROUTE(RDMA, 0, DPI, 0, + MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_MASK, + MT8167_RDMA0_SOUT_DPI0), + MMSYS_ROUTE(RDMA, 0, DPI, 0, + MT8167_DISP_REG_CONFIG_DISP_DPI0_SEL_IN, MT8167_DPI0_SEL_IN_MASK, + MT8167_DPI0_SEL_IN_RDMA0), + + /* RDMA0<->DPI1 */ + MMSYS_ROUTE(RDMA, 0, DPI, 1, + MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_MASK, + MT8167_RDMA0_SOUT_DPI1), + MMSYS_ROUTE(RDMA, 0, DPI, 1, + MT8167_DISP_REG_CONFIG_DISP_DPI1_SEL_IN, MT8167_DPI1_SEL_IN_MASK, + MT8167_DPI1_SEL_IN_RDMA0), + + /* RDMA1<->DSI0 */ + MMSYS_ROUTE(RDMA, 1, DSI, 0, + MT8167_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL_IN, MT8167_RDMA1_SOUT_MASK, + MT8167_RDMA1_SOUT_DSI0), + MMSYS_ROUTE(RDMA, 1, DSI, 0, + MT8167_DISP_REG_CONFIG_DISP_DSI0_SEL_IN, MT8167_DSI0_SEL_IN_MASK, + MT8167_DSI0_SEL_IN_RDMA1), + + /* RDMA1<->DPI0 */ + MMSYS_ROUTE(RDMA, 1, DPI, 0, + MT8167_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL_IN, MT8167_RDMA1_SOUT_MASK, + MT8167_RDMA1_SOUT_DPI0), + MMSYS_ROUTE(RDMA, 1, DPI, 0, + MT8167_DISP_REG_CONFIG_DISP_DPI0_SEL_IN, MT8167_DPI0_SEL_IN_MASK, + MT8167_DPI0_SEL_IN_RDMA1), + + /* RDMA1<->DPI1 */ + MMSYS_ROUTE(RDMA, 1, DPI, 1, + MT8167_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL_IN, MT8167_RDMA1_SOUT_MASK, + MT8167_RDMA1_SOUT_DPI1), + MMSYS_ROUTE(RDMA, 1, DPI, 1, + MT8167_DISP_REG_CONFIG_DISP_DPI1_SEL_IN, MT8167_DPI1_SEL_IN_MASK, + MT8167_DPI1_SEL_IN_RDMA1), }; #endif /* __SOC_MEDIATEK_MT8167_MMSYS_H */ From e0d291986738791444dd0426c85f5e7d747fa44f Mon Sep 17 00:00:00 2001 From: Hemanth Selam Date: Fri, 11 Sep 2026 14:20:55 +0530 Subject: [PATCH 075/176] soc: ti: knav_qmss: Fix typos in comments Correct "specifes" to "specifies" in the knav_queue_open() kernel-doc and "accomodate" to "accommodate" in knav_pool_create(). No code changes. Signed-off-by: Hemanth Selam Acked-by: Udit Kumar Link: https://patch.msgid.link/20260911085055.715191-1-hemanth.selam@gmail.com Signed-off-by: Nishanth Menon --- drivers/soc/ti/knav_qmss_queue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index 3e4041454f69..6186454dff51 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c @@ -509,7 +509,7 @@ static int knav_queue_flush(struct knav_queue *qh) /** * knav_queue_open() - open a hardware queue * @name: - name to give the queue handle - * @id: - desired queue number if any or specifes the type + * @id: - desired queue number if any or specifies the type * of queue * @flags: - the following flags are applicable to queues: * KNAV_QUEUE_SHARED - allow the queue to be shared. Queues are @@ -805,7 +805,7 @@ void *knav_pool_create(const char *name, } /* Region maintains a sorted (by region offset) list of pools - * use the first free slot which is large enough to accomodate + * use the first free slot which is large enough to accommodate * the request */ last_offset = 0; From a22355280361d2a376a2020059a2bae11e6cea10 Mon Sep 17 00:00:00 2001 From: Diego Fernando Mancera Gomez Date: Thu, 17 Sep 2026 17:59:25 -0600 Subject: [PATCH 076/176] memory: stm32_omm: fix child clock leak on set_amcr() error path When the mux is enabled, stm32_omm_configure() enables the two OSPI child clocks via stm32_omm_toggle_child_clock(dev, true); they are meant to stay enabled for the device's lifetime and are disabled again in stm32_omm_remove() and on the devm_of_platform_populate() error path. However, if the subsequent stm32_omm_set_amcr() call fails, the function jumps to the "error:" label which only calls pm_runtime_put_sync_suspend() before returning, leaving the two child clocks enabled. As this happens during probe, the error is propagated and .remove() is never called, so the clock enable references are leaked. devm_clk_bulk_get() only releases the clock handles on unwind, it does not undo clk_prepare_enable(). Disable the child clocks on the set_amcr() error path, mirroring the cleanup already done on the devm_of_platform_populate() failure path. Fixes: 8181d061dcff ("memory: Add STM32 Octo Memory Manager driver") Cc: stable@vger.kernel.org Signed-off-by: Diego Fernando Mancera Gomez Link: https://patch.msgid.link/20260917235925.44185-1-diegomancera.dev@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/stm32_omm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/memory/stm32_omm.c b/drivers/memory/stm32_omm.c index 84eb23c824f5..3599683ab04a 100644 --- a/drivers/memory/stm32_omm.c +++ b/drivers/memory/stm32_omm.c @@ -274,6 +274,8 @@ static int stm32_omm_configure(struct device *dev) writel_relaxed(omm->cr, omm->io_base + OMM_CR); ret = stm32_omm_set_amcr(dev, true); + if (ret && (mux & CR_MUXEN)) + stm32_omm_toggle_child_clock(dev, false); error: pm_runtime_put_sync_suspend(dev); From d59717cfbe1e7c03e4ce1a6ab35c16661b1a55c0 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 18 Sep 2026 11:29:50 +0200 Subject: [PATCH 077/176] firmware: arm_scmi: Add SCMI device table alias support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SCMI client drivers already describe their bus match data with MODULE_DEVICE_TABLE(scmi, ...), but modpost does not know how to consume SCMI device tables. As a result, SCMI modules do not get generated module aliases from their id tables. Move struct scmi_device_id to mod_devicetable.h so it has a fixed layout visible to modpost, add the corresponding generated offsets and teach file2alias to emit scmi:: aliases. Use the same stable alias format for SCMI device uevents and sysfs modaliases. The previous string included the instance-specific device name, which is not useful for matching modules. Assisted-by: Codex:GPT-5.5 Tested-by: Hans de Goede Tested-by: Rob Clark Tested-by: Daniel Lezcano # Lenovo Acked-by: Uwe Kleine-König Reviewed-by: Hans de Goede Link: https://patch.msgid.link/20260918092951.5656-2-johannes.goede@oss.qualcomm.com Signed-off-by: Bjorn Andersson Signed-off-by: Hans de Goede (sudeep.holla: updated the title to use standard format for SCMI) Signed-off-by: Sudeep Holla --- MAINTAINERS | 1 + drivers/firmware/arm_scmi/bus.c | 21 ++++++++++----------- include/linux/device-id/scmi.h | 17 +++++++++++++++++ include/linux/scmi_protocol.h | 6 +----- scripts/mod/devicetable-offsets.c | 5 +++++ scripts/mod/file2alias.c | 12 ++++++++++++ 6 files changed, 46 insertions(+), 16 deletions(-) create mode 100644 include/linux/device-id/scmi.h diff --git a/MAINTAINERS b/MAINTAINERS index 3a19da74d00c..5b722dba5395 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -26610,6 +26610,7 @@ F: drivers/pmdomain/arm/ F: drivers/powercap/arm_scmi_powercap.c F: drivers/regulator/scmi-regulator.c F: drivers/reset/reset-scmi.c +F: include/linux/device-id/scmi.h F: include/linux/sc[mp]i_protocol.h F: include/trace/events/scmi.h F: include/uapi/linux/virtio_scmi.h diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index a86fa18fc5d2..1961a4dd6a54 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -12,11 +12,12 @@ #include #include #include +#include #include #include "common.h" -#define SCMI_UEVENT_MODALIAS_FMT "%s:%02x:%s" +#define SCMI_UEVENT_MODALIAS_FMT SCMI_MODULE_PREFIX "%02x:%s" BLOCKING_NOTIFIER_HEAD(scmi_requested_devices_nh); EXPORT_SYMBOL_GPL(scmi_requested_devices_nh); @@ -185,7 +186,7 @@ static int scmi_protocol_table_register(const struct scmi_device_id *id_table) const struct scmi_device_id *entry; int ret; - for (entry = id_table; entry->name; entry++) { + for (entry = id_table; entry->name[0]; entry++) { ret = scmi_protocol_device_request(entry); if (ret) goto err_unrequest; @@ -205,7 +206,7 @@ scmi_protocol_table_unregister(const struct scmi_device_id *id_table) { const struct scmi_device_id *entry; - for (entry = id_table; entry->name; entry++) + for (entry = id_table; entry->name[0]; entry++) scmi_protocol_device_unrequest(entry); } @@ -219,10 +220,10 @@ static int __scmi_dev_match_by_id_table(struct scmi_device *scmi_dev, const struct scmi_device_id *id_table, bool skip_transport) { - if (!id_table || !id_table->name) + if (!id_table || !id_table->name[0]) return 0; - for (; id_table->protocol_id && id_table->name; id_table++) + for (; id_table->protocol_id && id_table->name[0]; id_table++) if (id_table->protocol_id == scmi_dev->protocol_id && !(skip_transport && scmi_device_is_transport(scmi_dev)) && !strcmp(id_table->name, scmi_dev->name)) @@ -266,7 +267,7 @@ scmi_child_dev_find_get(struct device *parent, int prot_id, const char *name) struct device *dev; id_table[0].protocol_id = prot_id; - id_table[0].name = name; + strscpy(id_table[0].name, name, sizeof(id_table[0].name)); dev = device_find_child(parent, &id_table, scmi_match_by_id_table); if (!dev) @@ -300,8 +301,7 @@ static int scmi_device_uevent(const struct device *dev, struct kobj_uevent_env * const struct scmi_device *scmi_dev = to_scmi_dev(dev); return add_uevent_var(env, "MODALIAS=" SCMI_UEVENT_MODALIAS_FMT, - dev_name(&scmi_dev->dev), scmi_dev->protocol_id, - scmi_dev->name); + scmi_dev->protocol_id, scmi_dev->name); } static ssize_t modalias_show(struct device *dev, @@ -309,9 +309,8 @@ static ssize_t modalias_show(struct device *dev, { struct scmi_device *scmi_dev = to_scmi_dev(dev); - return sysfs_emit(buf, SCMI_UEVENT_MODALIAS_FMT, - dev_name(&scmi_dev->dev), scmi_dev->protocol_id, - scmi_dev->name); + return sysfs_emit(buf, SCMI_UEVENT_MODALIAS_FMT "\n", + scmi_dev->protocol_id, scmi_dev->name); } static DEVICE_ATTR_RO(modalias); diff --git a/include/linux/device-id/scmi.h b/include/linux/device-id/scmi.h new file mode 100644 index 000000000000..1b4ccfa9dcc5 --- /dev/null +++ b/include/linux/device-id/scmi.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef LINUX_DEVICE_ID_SCMI_H +#define LINUX_DEVICE_ID_SCMI_H + +#ifdef __KERNEL__ +#include +#endif + +#define SCMI_NAME_SIZE 32 +#define SCMI_MODULE_PREFIX "scmi:" + +struct scmi_device_id { + __u8 protocol_id; + char name[SCMI_NAME_SIZE]; +}; + +#endif /* ifndef LINUX_DEVICE_ID_SCMI_H */ diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 0c05925d8595..3f7cc35eb861 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -9,6 +9,7 @@ #define _LINUX_SCMI_PROTOCOL_H #include +#include #include #include #include @@ -955,11 +956,6 @@ struct scmi_device { #define to_scmi_dev(d) container_of_const(d, struct scmi_device, dev) -struct scmi_device_id { - u8 protocol_id; - const char *name; -}; - struct scmi_driver { const char *name; int (*probe)(struct scmi_device *sdev); diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c index b4178c42d08f..91ec3704ee2b 100644 --- a/scripts/mod/devicetable-offsets.c +++ b/scripts/mod/devicetable-offsets.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #define COMPILE_OFFSETS +#include #include #include @@ -144,6 +145,10 @@ int main(void) DEVID(rpmsg_device_id); DEVID_FIELD(rpmsg_device_id, name); + DEVID(scmi_device_id); + DEVID_FIELD(scmi_device_id, protocol_id); + DEVID_FIELD(scmi_device_id, name); + DEVID(i2c_device_id); DEVID_FIELD(i2c_device_id, name); diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 8d36c74dec2d..5379b1def07b 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -121,6 +121,7 @@ typedef struct { /* Big exception to the "don't include kernel headers into userspace, which * even potentially has different endianness and word sizes, since * we handle those differences explicitly below */ +#include "../../include/linux/device-id/scmi.h" #include "../../include/linux/mod_devicetable.h" struct devtable { @@ -852,6 +853,16 @@ static void do_rpmsg_entry(struct module *mod, void *symval) module_alias_printf(mod, false, RPMSG_DEVICE_MODALIAS_FMT, *name); } +/* Looks like: scmi:NN:S */ +static void do_scmi_entry(struct module *mod, void *symval) +{ + DEF_FIELD(symval, scmi_device_id, protocol_id); + DEF_FIELD_ADDR(symval, scmi_device_id, name); + + module_alias_printf(mod, false, SCMI_MODULE_PREFIX "%02x:%s", + protocol_id, *name); +} + /* Looks like: i2c:S */ static void do_i2c_entry(struct module *mod, void *symval) { @@ -1491,6 +1502,7 @@ static const struct devtable devtable[] = { {"virtio", SIZE_virtio_device_id, do_virtio_entry}, {"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry}, {"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry}, + {"scmi", SIZE_scmi_device_id, do_scmi_entry}, {"i2c", SIZE_i2c_device_id, do_i2c_entry}, {"i3c", SIZE_i3c_device_id, do_i3c_entry}, {"slim", SIZE_slim_device_id, do_slim_entry}, From aac4e67d6eb93118cfa70c6562b5f9c81a7042ef Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 18 Sep 2026 11:29:51 +0200 Subject: [PATCH 078/176] firmware: arm_scmi: Always create devices for standard protocols Protocol driver module auto-loading requires the devices to already be created for udev to get the necessary uevents based on which udev loads modules. But SCMI devices are only created after their { protocol, name } device-id has been added to the requested-devices list which is done from scmi_driver_register(). This creates a circular dependency where device creation is waiting for the driver to register and loading the module with the driver is waiting for the device to be created. Add a list of standard protocol device-ids and always create devices for these without relying on these being added to the requested-devices list. This removes the circular dependency, fixing module auto-loading. Signed-off-by: Hans de Goede Link: https://patch.msgid.link/20260918092951.5656-3-johannes.goede@oss.qualcomm.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/bus.c | 51 +++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index 1961a4dd6a54..25197197db8e 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -532,6 +532,34 @@ _scmi_device_create(struct fwnode_handle *fwnode, struct device *parent, return sdev; } +/* Standard protocols table */ +static const struct scmi_device_id scmi_std_id_table[] = { + { SCMI_PROTOCOL_POWER, "genpd" }, + { SCMI_PROTOCOL_SYSTEM, "syspower" }, + { SCMI_PROTOCOL_PERF, "perf" }, + { SCMI_PROTOCOL_PERF, "cpufreq" }, + { SCMI_PROTOCOL_CLOCK, "clocks" }, + { SCMI_PROTOCOL_SENSOR, "hwmon" }, + { SCMI_PROTOCOL_SENSOR, "iiodev" }, + { SCMI_PROTOCOL_RESET, "reset" }, + { SCMI_PROTOCOL_VOLTAGE, "regulator" }, + { SCMI_PROTOCOL_POWERCAP, "powercap" }, + { SCMI_PROTOCOL_PINCTRL, "pinctrl" }, + { SCMI_PROTOCOL_PINCTRL, "pinctrl-imx" }, + { }, +}; + +static bool scmi_device_id_in_std_id_table(const struct scmi_device_id *id) +{ + for (int i = 0; scmi_std_id_table[i].name[0]; i++) { + if (scmi_std_id_table[i].protocol_id == id->protocol_id && + !strcmp(scmi_std_id_table[i].name, id->name)) + return true; + } + + return false; +} + /** * scmi_device_create - A method to create one or more SCMI devices * @@ -561,22 +589,39 @@ struct scmi_device *scmi_device_create(struct fwnode_handle *fwnode, { struct list_head *phead; struct scmi_requested_dev *rdev; - struct scmi_device *scmi_dev = NULL; + struct scmi_device *sdev, *scmi_dev = NULL; if (name) return _scmi_device_create(fwnode, parent, protocol, name); + /* + * Always create devices for standard protocols, even if the device-ids + * have not been registered into scmi_requested_devices yet. This allows + * auto-loading of SCMI protocol driver modules for standard protocols. + */ + for (int i = 0; scmi_std_id_table[i].name[0]; i++) { + if (scmi_std_id_table[i].protocol_id != protocol) + continue; + + sdev = _scmi_device_create(fwnode, parent, protocol, + scmi_std_id_table[i].name); + if (sdev) + scmi_dev = sdev; + } + mutex_lock(&scmi_requested_devices_mtx); phead = idr_find(&scmi_requested_devices, protocol); /* Nothing to do. */ if (!phead) { mutex_unlock(&scmi_requested_devices_mtx); - return NULL; + return scmi_dev; } /* Walk the list of requested devices for protocol and create them */ list_for_each_entry(rdev, phead, node) { - struct scmi_device *sdev; + /* Standard proto matches already have their dev created above */ + if (scmi_device_id_in_std_id_table(rdev->id_table)) + continue; sdev = _scmi_device_create(fwnode, parent, rdev->id_table->protocol_id, From 1401205dedd5b266c751302fd9c2a073bdf0d3f5 Mon Sep 17 00:00:00 2001 From: Ayman Chaudhry Date: Mon, 21 Sep 2026 13:44:24 +0000 Subject: [PATCH 079/176] soc: renesas: Enable SYSC driver for r8a774a3 Select SYSC_R8A774A3 config option if ARCH_R8A774A3 is enabled so that System Controller driver is enabled on Renesas RZ/G2M v3.0 SoC. Signed-off-by: Ayman Chaudhry Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260921134432.50338-5-ayman.chaudhry.kc@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 0f6d53abd86c..5445fba0879d 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -231,6 +231,7 @@ config ARCH_R8A774A3 bool "ARM64 Platform support for R8A774A3 (RZ/G2M v3.0)" default y if ARCH_RENESAS select ARCH_RCAR_GEN3 + select SYSC_R8A774A3 help This enables support for the Renesas RZ/G2M SoC (version 3.0). From e93e5ac0719cd31e7e78e590e76b7be88519716a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 4 Aug 2026 17:02:31 +0200 Subject: [PATCH 080/176] firmware: xilinx: ufs: move PHY/SRAM ready polling into the firmware backend The Versal Gen 2 UFS driver polls the firmware for M-PHY TX/RX configuration readiness and SRAM initialisation completion with two open-coded do/while loops. Each iteration is a full firmware round-trip (PM_IOCTL/IOCTL_READ_REG of a protected PMC_IOU_SLCR register), so the loop can issue up to a million EEMI calls, and it hard-codes the wait policy inside the controller driver. Introduce coarse blocking helpers, zynqmp_pm_wait_mphy_tx_rx_config_ready() and zynqmp_pm_wait_sram_init_done(), that take a caller-supplied timeout budget and contain the poll loop. The loop is EEMI-specific (legacy firmware only exposes the per-read status primitive) so it lives in the firmware driver, keeping the UFS driver backend-agnostic: a future backend can offload the wait to the platform in a single call without touching the controller driver again. The existing per-read primitives stay exported, so the current EEMI interface is unchanged. The timeout budget remains owned by the UFS driver (the consumer that knows the hardware) and is passed down, so EEMI and any future backend stay consistent. Reviewed-by: Sai Krishna Potthuri Link: https://patch.msgid.link/eaeaaea8ed76069943e0706a0917139ff6569929.1785855749.git.michal.simek@amd.com Signed-off-by: Michal Simek --- drivers/firmware/xilinx/zynqmp-ufs.c | 70 ++++++++++++++++++++++-- drivers/ufs/host/ufs-amd-versal2.c | 46 ++++------------ include/linux/firmware/xlnx-zynqmp-ufs.h | 8 +-- 3 files changed, 82 insertions(+), 42 deletions(-) diff --git a/drivers/firmware/xilinx/zynqmp-ufs.c b/drivers/firmware/xilinx/zynqmp-ufs.c index 85da8a822f3a..81ccf61a037c 100644 --- a/drivers/firmware/xilinx/zynqmp-ufs.c +++ b/drivers/firmware/xilinx/zynqmp-ufs.c @@ -5,6 +5,7 @@ * Copyright (C) 2025 Advanced Micro Devices, Inc. */ +#include #include #include @@ -33,7 +34,7 @@ * * Return: Returns 0 on success or error value on failure. */ -int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready) +static int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready) { u32 regval; int ret; @@ -53,7 +54,6 @@ int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready) return ret; } -EXPORT_SYMBOL_GPL(zynqmp_pm_is_mphy_tx_rx_config_ready); /** * zynqmp_pm_is_sram_init_done - check SRAM initialization @@ -61,7 +61,7 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_is_mphy_tx_rx_config_ready); * * Return: Returns 0 on success or error value on failure. */ -int zynqmp_pm_is_sram_init_done(bool *is_done) +static int zynqmp_pm_is_sram_init_done(bool *is_done) { u32 regval; int ret; @@ -81,7 +81,69 @@ int zynqmp_pm_is_sram_init_done(bool *is_done) return ret; } -EXPORT_SYMBOL_GPL(zynqmp_pm_is_sram_init_done); + +/** + * zynqmp_pm_wait_mphy_tx_rx_config_ready - wait for M-PHY TX-RX config ready + * @timeout_us: Caller-supplied timeout budget in microseconds + * + * Poll the M-PHY TX-RX configuration-ready status until it settles or the + * timeout elapses. The poll loop is EEMI-specific (legacy firmware only offers + * the per-read status primitive), so it lives here in the firmware driver + * rather than in the UFS controller driver; an SCMI-based backend can instead + * offload the wait to the platform in a single call. The timeout budget is + * owned by the caller (UFS driver), keeping the policy with the consumer. + * + * Return: Returns 0 once ready, -ETIMEDOUT on timeout, or error value. + */ +int zynqmp_pm_wait_mphy_tx_rx_config_ready(u32 timeout_us) +{ + bool is_ready; + int ret; + + while (timeout_us--) { + ret = zynqmp_pm_is_mphy_tx_rx_config_ready(&is_ready); + if (ret) + return ret; + + if (!is_ready) + return 0; + + usleep_range(1, 5); + } + + return -ETIMEDOUT; +} +EXPORT_SYMBOL_GPL(zynqmp_pm_wait_mphy_tx_rx_config_ready); + +/** + * zynqmp_pm_wait_sram_init_done - wait for SRAM initialization to complete + * @timeout_us: Caller-supplied timeout budget in microseconds + * + * Poll the SRAM initialization-done status until it is set or the timeout + * elapses. As with the M-PHY wait, the poll loop is EEMI-specific and kept in + * the firmware driver so the UFS controller driver stays backend-agnostic. + * + * Return: Returns 0 once done, -ETIMEDOUT on timeout, or error value. + */ +int zynqmp_pm_wait_sram_init_done(u32 timeout_us) +{ + bool is_done; + int ret; + + while (timeout_us--) { + ret = zynqmp_pm_is_sram_init_done(&is_done); + if (ret) + return ret; + + if (is_done) + return 0; + + usleep_range(1, 5); + } + + return -ETIMEDOUT; +} +EXPORT_SYMBOL_GPL(zynqmp_pm_wait_sram_init_done); /** * zynqmp_pm_set_sram_bypass - Set SRAM bypass Control diff --git a/drivers/ufs/host/ufs-amd-versal2.c b/drivers/ufs/host/ufs-amd-versal2.c index 2154d6286817..dff0c2c95486 100644 --- a/drivers/ufs/host/ufs-amd-versal2.c +++ b/drivers/ufs/host/ufs-amd-versal2.c @@ -225,8 +225,6 @@ static int ufs_versal2_setup_phy(struct ufs_hba *hba) static int ufs_versal2_phy_init(struct ufs_hba *hba) { struct ufs_versal2_host *host = ufshcd_get_variant(hba); - u32 time_left; - bool is_ready; int ret; static const struct ufshcd_dme_attr_val rmmi_attrs[] = { { UIC_ARG_MIB(CBREFCLKCTRL2), CBREFREFCLK_GATE_OVR_EN, DME_LOCAL }, @@ -235,23 +233,15 @@ static int ufs_versal2_phy_init(struct ufs_hba *hba) { UIC_ARG_MIB(VS_MPHYCFGUPDT), 1, DME_LOCAL } }; - /* Wait for Tx/Rx config_rdy */ - time_left = TIMEOUT_MICROSEC; - do { - time_left--; - ret = zynqmp_pm_is_mphy_tx_rx_config_ready(&is_ready); - if (ret) - return ret; - - if (!is_ready) - break; - - usleep_range(1, 5); - } while (time_left); - - if (!time_left) { + /* + * Wait for Tx/Rx config_rdy. The poll loop lives in the firmware + * backend (EEMI today, SCMI in future) so this driver stays + * backend-agnostic; the timeout budget stays here with the consumer. + */ + ret = zynqmp_pm_wait_mphy_tx_rx_config_ready(TIMEOUT_MICROSEC); + if (ret) { dev_err(hba->dev, "Tx/Rx configuration signal busy.\n"); - return -ETIMEDOUT; + return ret; } ret = ufshcd_dwc_dme_set_attrs(hba, rmmi_attrs, ARRAY_SIZE(rmmi_attrs)); @@ -264,23 +254,11 @@ static int ufs_versal2_phy_init(struct ufs_hba *hba) return ret; } - /* Wait for SRAM init done */ - time_left = TIMEOUT_MICROSEC; - do { - time_left--; - ret = zynqmp_pm_is_sram_init_done(&is_ready); - if (ret) - return ret; - - if (is_ready) - break; - - usleep_range(1, 5); - } while (time_left); - - if (!time_left) { + /* Wait for SRAM init done (poll handled by the firmware backend). */ + ret = zynqmp_pm_wait_sram_init_done(TIMEOUT_MICROSEC); + if (ret) { dev_err(hba->dev, "SRAM initialization failed.\n"); - return -ETIMEDOUT; + return ret; } ret = ufs_versal2_setup_phy(hba); diff --git a/include/linux/firmware/xlnx-zynqmp-ufs.h b/include/linux/firmware/xlnx-zynqmp-ufs.h index d3538dd5822a..00383dd835f2 100644 --- a/include/linux/firmware/xlnx-zynqmp-ufs.h +++ b/include/linux/firmware/xlnx-zynqmp-ufs.h @@ -9,17 +9,17 @@ #define __FIRMWARE_XLNX_ZYNQMP_UFS_H__ #if IS_REACHABLE(CONFIG_ZYNQMP_FIRMWARE) -int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready); -int zynqmp_pm_is_sram_init_done(bool *is_done); +int zynqmp_pm_wait_mphy_tx_rx_config_ready(u32 timeout_us); +int zynqmp_pm_wait_sram_init_done(u32 timeout_us); int zynqmp_pm_set_sram_bypass(void); int zynqmp_pm_get_ufs_calibration_values(u32 *val); #else -static inline int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready) +static inline int zynqmp_pm_wait_mphy_tx_rx_config_ready(u32 timeout_us) { return -ENODEV; } -static inline int zynqmp_pm_is_sram_init_done(bool *is_done) +static inline int zynqmp_pm_wait_sram_init_done(u32 timeout_us) { return -ENODEV; } From 118be086595e8f98b19e8fa8e24276466a8e9483 Mon Sep 17 00:00:00 2001 From: Tanmay Shah Date: Mon, 3 Aug 2026 13:05:02 -0700 Subject: [PATCH 081/176] firmware: xilinx: support RPU boot from DDR Cortex-R52 cores can boot from DDR. In such case, elf's boot address will be in the ddr, and it should be passed to the PLM via EEMI call. Add ddr boot config EEMI call before starting RPU to configure the boot address. Also make sure TCM-Boot is support for old platforms as well. Remove HIVEC & LOVEC enum, as now PLM supports boot address directly. Signed-off-by: Tanmay Shah Link: https://patch.msgid.link/20260803200502.209361-1-tanmay.shah@amd.com Signed-off-by: Michal Simek --- drivers/firmware/xilinx/zynqmp.c | 44 ++++++++++++++++++++++++---- include/linux/firmware/xlnx-zynqmp.h | 5 ---- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index fe650747ac91..d76660c55354 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -1527,7 +1527,6 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_request_wake); */ int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr) { - enum rpu_boot_mem bootmem; int ret; /* @@ -1536,22 +1535,55 @@ int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr) * starts at the base-address and subsequent vectors are on 4-byte * boundaries. * + * The Cortex-R5 cores can boot from TCM and OCM memories. * Exception vectors can start either from 0x0000_0000 (LOVEC) or * from 0xFFFF_0000 (HIVEC) which is mapped in the OCM (On-Chip Memory) * * Usually firmware will put Exception vectors at LOVEC. * + * The Cortex-R52 cores can boot from DDR and TCM. + * That means vector table can be at address 0x0 or at any DDR address + * that is in the 32-bit address range. Note that booting from DDR + * address 0x0 is not supported and the user must always assume that if + * 0x0 address is passed, then it will be TCM boot. + * * It is not recommend that you change the exception vector. * Changing the EVP to HIVEC will result in increased interrupt latency * and jitter. Also, if the OCM is secured and the Cortex-R5F processor * is non-secured, then the Cortex-R5F processor cannot access the * HIVEC exception vectors in the OCM. */ - bootmem = (bootaddr >= 0xFFFC0000) ? - PM_RPU_BOOTMEM_HIVEC : PM_RPU_BOOTMEM_LOVEC; + if (upper_32_bits(bootaddr)) { + pr_err("invalid bootaddr = 0x%llx\n", bootaddr); + return -EINVAL; + } - pr_debug("RPU boot addr 0x%llx from %s.", bootaddr, - bootmem == PM_RPU_BOOTMEM_HIVEC ? "OCM" : "TCM"); + /* + * New platforms can boot from DDR and require the DDR address + * to be configured explicitly. If the correct version of the + * IOCTL_RPU_BOOT_ADDR_CONFIG ioctl is not supported, do not + * treat it as a failure. If a DDR address is passed on other + * platforms, the PM request wake EEMI call will still fail and + * the RPU won't boot. + */ + ret = zynqmp_pm_is_function_supported(PM_IOCTL, + IOCTL_RPU_BOOT_ADDR_CONFIG); + if (!ret) { + /* config ddr boot address */ + ret = zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, + node, + IOCTL_RPU_BOOT_ADDR_CONFIG, + bootaddr); + if (ret < 0) { + pr_err("failed to set RPU Boot address 0x%llx\n", + bootaddr); + return ret; + } + } else if (ret != -EOPNOTSUPP && ret != -ENODATA) { + pr_err("ioctl rpu boot addr config ver check failed %d\n", + ret); + return ret; + } /* Request node before starting RPU core if new version of API is supported */ if (zynqmp_pm_feature(PM_REQUEST_NODE) > PM_API_VERSION_1) { @@ -1565,7 +1597,7 @@ int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr) } ret = zynqmp_pm_request_wake(node, true, - bootmem, ZYNQMP_PM_REQUEST_ACK_NO); + bootaddr, ZYNQMP_PM_REQUEST_ACK_NO); if (ret) pr_err("failed to start RPU = 0x%x\n", node); return ret; diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index f4b3df614c77..41a1cd810bda 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -277,11 +277,6 @@ enum rpu_oper_mode { PM_RPU_MODE_SPLIT = 1, }; -enum rpu_boot_mem { - PM_RPU_BOOTMEM_LOVEC = 0, - PM_RPU_BOOTMEM_HIVEC = 1, -}; - enum rpu_tcm_comb { PM_RPU_TCM_SPLIT = 0, PM_RPU_TCM_COMB = 1, From 1a2ae085282a99332dc8f46fe29e0cf820f19ba5 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sat, 19 Sep 2026 00:47:03 +0800 Subject: [PATCH 082/176] soc: apple: rtkit-crashlog: rename 'Crg8' section from regs to aarch64 This section contains AArch64 CPU state of the IOP when the exception occurred, including register information. Rename this section to be clear about the CPU architecture as support for crashlog section with AArch32 CPU state will be added. Signed-off-by: Nick Chan Link: https://patch.msgid.link/20260919-rtkit-armv7-crashlog-v1-1-f4a671ea453c@gmail.com Signed-off-by: Sven Peter --- drivers/soc/apple/rtkit-crashlog.c | 43 +++++++++++++++--------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/soc/apple/rtkit-crashlog.c b/drivers/soc/apple/rtkit-crashlog.c index 8319e365110b..6a8273e81e61 100644 --- a/drivers/soc/apple/rtkit-crashlog.c +++ b/drivers/soc/apple/rtkit-crashlog.c @@ -13,7 +13,7 @@ #define APPLE_RTKIT_CRASHLOG_VERSION FOURCC('C', 'v', 'e', 'r') #define APPLE_RTKIT_CRASHLOG_MBOX FOURCC('C', 'm', 'b', 'x') #define APPLE_RTKIT_CRASHLOG_TIME FOURCC('C', 't', 'i', 'm') -#define APPLE_RTKIT_CRASHLOG_REGS FOURCC('C', 'r', 'g', '8') +#define APPLE_RTKIT_CRASHLOG_AARCH64 FOURCC('C', 'r', 'g', '8') /* For COMPILE_TEST on non-ARM64 architectures */ #ifndef PSR_MODE_EL0t @@ -42,7 +42,7 @@ struct apple_rtkit_crashlog_mbox_entry { }; static_assert(sizeof(struct apple_rtkit_crashlog_mbox_entry) == 0x18); -struct apple_rtkit_crashlog_regs { +struct apple_rtkit_crashlog_aarch64 { u32 unk_0; u32 unk_4; u64 regs[31]; @@ -58,7 +58,7 @@ struct apple_rtkit_crashlog_regs { u64 esr; u64 unk_Z; } __packed; -static_assert(sizeof(struct apple_rtkit_crashlog_regs) == 0x350); +static_assert(sizeof(struct apple_rtkit_crashlog_aarch64) == 0x350); static void apple_rtkit_crashlog_dump_str(struct apple_rtkit *rtk, u8 *bfr, size_t size) @@ -123,21 +123,22 @@ static void apple_rtkit_crashlog_dump_mailbox(struct apple_rtkit *rtk, u8 *bfr, } } -static void apple_rtkit_crashlog_dump_regs(struct apple_rtkit *rtk, u8 *bfr, - size_t size) +static void apple_rtkit_crashlog_dump_aarch64(struct apple_rtkit *rtk, u8 *bfr, + size_t size) { - struct apple_rtkit_crashlog_regs *regs; + struct apple_rtkit_crashlog_aarch64 *state; const char *el; int i; - if (size < sizeof(*regs)) { - dev_warn(rtk->dev, "RTKit: Regs section too small: 0x%zx", size); + if (size < sizeof(*state)) { + dev_warn(rtk->dev, "RTKit: AArch64 section too small: 0x%zx", + size); return; } - regs = (struct apple_rtkit_crashlog_regs *)bfr; + state = (struct apple_rtkit_crashlog_aarch64 *)bfr; - switch (regs->psr & PSR_MODE_MASK) { + switch (state->psr & PSR_MODE_MASK) { case PSR_MODE_EL0t: el = "EL0t"; break; @@ -160,11 +161,11 @@ static void apple_rtkit_crashlog_dump_regs(struct apple_rtkit *rtk, u8 *bfr, dev_warn(rtk->dev, "RTKit: Exception dump:"); dev_warn(rtk->dev, " == Exception taken from %s ==", el); - dev_warn(rtk->dev, " PSR = 0x%llx", regs->psr); - dev_warn(rtk->dev, " PC = 0x%llx\n", regs->pc); - dev_warn(rtk->dev, " ESR = 0x%llx\n", regs->esr); - dev_warn(rtk->dev, " FAR = 0x%llx\n", regs->far); - dev_warn(rtk->dev, " SP = 0x%llx\n", regs->sp); + dev_warn(rtk->dev, " PSR = 0x%llx", state->psr); + dev_warn(rtk->dev, " PC = 0x%llx\n", state->pc); + dev_warn(rtk->dev, " ESR = 0x%llx\n", state->esr); + dev_warn(rtk->dev, " FAR = 0x%llx\n", state->far); + dev_warn(rtk->dev, " SP = 0x%llx\n", state->sp); dev_warn(rtk->dev, "\n"); for (i = 0; i < 31; i += 4) { @@ -172,12 +173,12 @@ static void apple_rtkit_crashlog_dump_regs(struct apple_rtkit *rtk, u8 *bfr, dev_warn(rtk->dev, " x%02d-x%02d = %016llx %016llx %016llx %016llx\n", i, i + 3, - regs->regs[i], regs->regs[i + 1], - regs->regs[i + 2], regs->regs[i + 3]); + state->regs[i], state->regs[i + 1], + state->regs[i + 2], state->regs[i + 3]); else dev_warn(rtk->dev, " x%02d-x%02d = %016llx %016llx %016llx\n", i, i + 3, - regs->regs[i], regs->regs[i + 1], regs->regs[i + 2]); + state->regs[i], state->regs[i + 1], state->regs[i + 2]); } dev_warn(rtk->dev, "\n"); @@ -229,9 +230,9 @@ void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size) apple_rtkit_crashlog_dump_time(rtk, bfr + offset + 16, section_size); break; - case APPLE_RTKIT_CRASHLOG_REGS: - apple_rtkit_crashlog_dump_regs(rtk, bfr + offset + 16, - section_size); + case APPLE_RTKIT_CRASHLOG_AARCH64: + apple_rtkit_crashlog_dump_aarch64(rtk, bfr + offset + 16, + section_size); break; default: dev_warn(rtk->dev, From 4edbfa916dbfba44af3ef2378cae2b2653c96058 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sat, 19 Sep 2026 00:47:04 +0800 Subject: [PATCH 083/176] soc: apple: rtkit-crashlog: Add support for AArch32 state 'CrgA' section Add support for CrgA section containing the AArch32 IOP CPU state, which may appear when an AArch32 RTKit IOP crashes. Signed-off-by: Nick Chan Link: https://patch.msgid.link/20260919-rtkit-armv7-crashlog-v1-2-f4a671ea453c@gmail.com Signed-off-by: Sven Peter --- drivers/soc/apple/rtkit-crashlog.c | 96 ++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/drivers/soc/apple/rtkit-crashlog.c b/drivers/soc/apple/rtkit-crashlog.c index 6a8273e81e61..195b7869ce58 100644 --- a/drivers/soc/apple/rtkit-crashlog.c +++ b/drivers/soc/apple/rtkit-crashlog.c @@ -13,6 +13,7 @@ #define APPLE_RTKIT_CRASHLOG_VERSION FOURCC('C', 'v', 'e', 'r') #define APPLE_RTKIT_CRASHLOG_MBOX FOURCC('C', 'm', 'b', 'x') #define APPLE_RTKIT_CRASHLOG_TIME FOURCC('C', 't', 'i', 'm') +#define APPLE_RTKIT_CRASHLOG_AARCH32 FOURCC('C', 'r', 'g', 'A') #define APPLE_RTKIT_CRASHLOG_AARCH64 FOURCC('C', 'r', 'g', '8') /* For COMPILE_TEST on non-ARM64 architectures */ @@ -25,6 +26,21 @@ #define PSR_MODE_MASK 0x0000000f #endif +/* + * AArch32 mode definitions: APPLE_RTKIT depends on APPLE_MAILBOX, which + * depends on 64BIT, so there is no need to care about COMPILE_TEST on ARM. + */ +#define USR_MODE 0x00000010 +#define FIQ_MODE 0x00000011 +#define IRQ_MODE 0x00000012 +#define SVC_MODE 0x00000013 +#define MON_MODE 0x00000016 +#define ABT_MODE 0x00000017 +#define HYP_MODE 0x0000001a +#define UND_MODE 0x0000001b +#define SYSTEM_MODE 0x0000001f +#define MODE_MASK_32 0x0000001f + struct apple_rtkit_crashlog_header { u32 fourcc; u32 version; @@ -60,6 +76,20 @@ struct apple_rtkit_crashlog_aarch64 { } __packed; static_assert(sizeof(struct apple_rtkit_crashlog_aarch64) == 0x350); +struct apple_rtkit_crashlog_aarch32 { + u32 unk_0; + u32 unk_4; + u32 regs[16]; + u32 psr; + u32 unk_x1; + u8 stack[0x100]; + u32 unk_x2; + u32 unk_x3; + u32 unk_x4; + u32 unk_x5; +} __packed; +static_assert(sizeof(struct apple_rtkit_crashlog_aarch32) == 0x160); + static void apple_rtkit_crashlog_dump_str(struct apple_rtkit *rtk, u8 *bfr, size_t size) { @@ -123,6 +153,68 @@ static void apple_rtkit_crashlog_dump_mailbox(struct apple_rtkit *rtk, u8 *bfr, } } +static void apple_rtkit_crashlog_dump_aarch32(struct apple_rtkit *rtk, u8 *bfr, + size_t size) +{ + struct apple_rtkit_crashlog_aarch32 *state; + const char *mode; + int i; + + if (size < sizeof(*state)) { + dev_warn(rtk->dev, "RTKit: AArch32 section too small: 0x%zx", size); + return; + } + + state = (struct apple_rtkit_crashlog_aarch32 *)bfr; + + switch (state->psr & MODE_MASK_32) { + case USR_MODE: + mode = "User"; + break; + case FIQ_MODE: + mode = "FIQ"; + break; + case IRQ_MODE: + mode = "IRQ"; + break; + case SVC_MODE: + mode = "Supervisor"; + break; + case MON_MODE: + mode = "Monitor"; + break; + case ABT_MODE: + mode = "Abort"; + break; + case HYP_MODE: + mode = "Hypervisor"; + break; + case UND_MODE: + mode = "Undefined"; + break; + case SYSTEM_MODE: + mode = "System"; + break; + default: + mode = "Unknown"; + break; + } + + dev_warn(rtk->dev, "RTKit: Exception dump:"); + dev_warn(rtk->dev, " == Exception taken from %s mode ==", mode); + dev_warn(rtk->dev, " PSR = 0x%x", state->psr); + dev_warn(rtk->dev, "\n"); + + for (i = 0; i < 16; i += 4) + dev_warn(rtk->dev, + " r%02d-r%02d = %08x %08x %08x %08x\n", + i, i + 3, + state->regs[i], state->regs[i + 1], + state->regs[i + 2], state->regs[i + 3]); + + dev_warn(rtk->dev, "\n"); +} + static void apple_rtkit_crashlog_dump_aarch64(struct apple_rtkit *rtk, u8 *bfr, size_t size) { @@ -230,6 +322,10 @@ void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size) apple_rtkit_crashlog_dump_time(rtk, bfr + offset + 16, section_size); break; + case APPLE_RTKIT_CRASHLOG_AARCH32: + apple_rtkit_crashlog_dump_aarch32(rtk, bfr + offset + 16, + section_size); + break; case APPLE_RTKIT_CRASHLOG_AARCH64: apple_rtkit_crashlog_dump_aarch64(rtk, bfr + offset + 16, section_size); From 6ace5611ac85887a593b7eae2b7edec8dfeb2ffa Mon Sep 17 00:00:00 2001 From: Siddharth Karanam Date: Fri, 18 Sep 2026 17:38:39 +0530 Subject: [PATCH 084/176] firmware: ti_sci: replace kcalloc with kzalloc for buffer pointer allocation Previously, the buffer pointer was being allocated via devm_kcalloc that would check for a mul overflow before allocating n * size bytes (size being desc->max_msg_size), but since n is 1 here, we can instead use devm_kzalloc that allocates the size directly. Signed-off-by: Siddharth Karanam Link: https://patch.msgid.link/20260918120839.207459-1-sid9.karanam@gmail.com Signed-off-by: Nishanth Menon --- drivers/firmware/ti_sci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 94104edba9a0..8025a4cdd35c 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -4132,7 +4132,7 @@ static int ti_sci_probe(struct platform_device *pdev) /* Pre-initialize the buffer pointer to pre-allocated buffers */ for (i = 0, xfer = minfo->xfer_block; i < desc->max_msgs; i++, xfer++) { - xfer->xfer_buf = devm_kcalloc(dev, 1, desc->max_msg_size, + xfer->xfer_buf = devm_kzalloc(dev, desc->max_msg_size, GFP_KERNEL); if (!xfer->xfer_buf) return -ENOMEM; From 45ea6911ad16859d4ce4f25780b0ebcf5660e43a Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Wed, 23 Sep 2026 08:16:57 +0200 Subject: [PATCH 085/176] soc: ti: k3-ringacc: Correct ring API kernel-doc The ring accelerator header labels k3_ring_cfg as an enum, uses propname instead of property, and gives the DMA reset helper the ordinary reset helper's name. The DMA reset comment also omits occ, including the convention that zero requests a hardware occupancy read. The proxy flag is parsed as a separate parameter, and the pop helpers describe pushing elements. Proxy access is supported in Message mode; the listed Credentials and Queue modes are not implemented. The phandle lookup returns encoded error pointers rather than integer error values. Match the declarations and document these argument and operation roles. Fixes: 3277e8aa2504 ("soc: ti: k3: add navss ringacc driver") Assisted-by: LLM Signed-off-by: Karl Mehltretter Link: https://patch.msgid.link/20260923061658.20140-1-kmehltretter@gmail.com Signed-off-by: Nishanth Menon --- include/linux/soc/ti/k3-ringacc.h | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/include/linux/soc/ti/k3-ringacc.h b/include/linux/soc/ti/k3-ringacc.h index 39b022b92598..2de6031b9424 100644 --- a/include/linux/soc/ti/k3-ringacc.h +++ b/include/linux/soc/ti/k3-ringacc.h @@ -57,13 +57,13 @@ struct k3_ringacc; struct k3_ring; /** - * enum k3_ring_cfg - RA ring configuration structure + * struct k3_ring_cfg - RA ring configuration structure * * @size: Ring size, number of elements * @elm_size: Ring element size * @mode: Ring operational mode * @flags: Ring configuration flags. Possible values: - * @K3_RINGACC_RING_SHARED: when set allows to request the same ring + * %K3_RINGACC_RING_SHARED: when set allows to request the same ring * few times. It's usable when the same ring is used as Free Host PD ring * for different flows, for example. * Note: Locking should be done by consumer if required @@ -88,11 +88,10 @@ struct k3_ring_cfg { /** * of_k3_ringacc_get_by_phandle - find a RA by phandle property * @np: device node - * @propname: property name containing phandle on RA node + * @property: property name containing phandle on RA node * - * Returns pointer on the RA - struct k3_ringacc - * or -ENODEV if not found, - * or -EPROBE_DEFER if not yet registered + * Return: Pointer to the RA, or ERR_PTR(-ENODEV) if the phandle cannot + * be resolved, or ERR_PTR(-EPROBE_DEFER) if the RA is not yet registered. */ struct k3_ringacc *of_k3_ringacc_get_by_phandle(struct device_node *np, const char *property); @@ -103,10 +102,8 @@ struct k3_ringacc *of_k3_ringacc_get_by_phandle(struct device_node *np, * k3_ringacc_request_ring - request ring from ringacc * @ringacc: pointer on ringacc * @id: ring id or K3_RINGACC_RING_ID_ANY for any general purpose ring - * @flags: - * @K3_RINGACC_RING_USE_PROXY: if set - proxy will be allocated and - * used to access ring memory. Sopported only for rings in - * Message/Credentials/Queue mode. + * @flags: Set %K3_RINGACC_RING_USE_PROXY to allocate a proxy for + * accessing ring memory in Message mode. * * Returns pointer on the Ring - struct k3_ring * or NULL in case of failure. @@ -126,8 +123,9 @@ int k3_ringacc_request_rings_pair(struct k3_ringacc *ringacc, */ void k3_ringacc_ring_reset(struct k3_ring *ring); /** - * k3_ringacc_ring_reset - ring reset for DMA rings + * k3_ringacc_ring_reset_dma - ring reset for DMA rings * @ring: pointer on Ring + * @occ: occupancy used by the DMA reset quirk, or zero to read it from hardware * * Resets ring internal state ((hw)occ, (hw)idx). Should be used for rings * which are read by K3 UDMA, like TX or Free Host PD rings. @@ -217,8 +215,8 @@ int k3_ringacc_ring_push(struct k3_ring *ring, void *elem); * @ring: pointer on ring * @elem: pointer on ring element buffer * - * Push one ring element from the ring head. Size of the ring element is - * determined by ring configuration &struct k3_ring_cfg elm_size.. + * Pop one ring element from the ring head. Size of the ring element is + * determined by ring configuration &struct k3_ring_cfg elm_size. * * Returns 0 on success, errno otherwise. */ @@ -242,7 +240,7 @@ int k3_ringacc_ring_push_head(struct k3_ring *ring, void *elem); * @ring: pointer on ring * @elem: pointer on ring element buffer * - * Push one ring element from the ring tail. Size of the ring element is + * Pop one ring element from the ring tail. Size of the ring element is * determined by ring configuration &struct k3_ring_cfg elm_size. * * Returns 0 on success, errno otherwise. From 6c4e6e8f5cf95f7e0d4f04928a9ae70e20c73d4b Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Wed, 23 Sep 2026 08:16:58 +0200 Subject: [PATCH 086/176] soc: ti: k3-ringacc: Fix DMA ring initialization kernel-doc The heading for k3_ringacc_init_data repeats struct, so kernel-doc cannot match it to the declaration. Its three fields are also missing descriptions. Use the structure name and describe the firmware handle, device ID, and total number of available rings used during DMA ring initialization. Fixes: d782298c6f6b ("soc: ti: k3-ringacc: add AM64 DMA rings support.") Assisted-by: LLM Signed-off-by: Karl Mehltretter Reviewed-by: Udit Kumar Link: https://patch.msgid.link/20260923061658.20140-2-kmehltretter@gmail.com Signed-off-by: Nishanth Menon --- include/linux/soc/ti/k3-ringacc.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/linux/soc/ti/k3-ringacc.h b/include/linux/soc/ti/k3-ringacc.h index 2de6031b9424..7b7fc237c08f 100644 --- a/include/linux/soc/ti/k3-ringacc.h +++ b/include/linux/soc/ti/k3-ringacc.h @@ -254,7 +254,10 @@ u32 k3_ringacc_get_tisci_dev_id(struct k3_ring *ring); struct ti_sci_handle; /** - * struct struct k3_ringacc_init_data - Initialization data for DMA rings + * struct k3_ringacc_init_data - Initialization data for DMA rings + * @tisci: TI SCI firmware handle + * @tisci_dev_id: TI SCI device ID of the DMA controller + * @num_rings: Total number of available rings */ struct k3_ringacc_init_data { const struct ti_sci_handle *tisci; From a251a759b52082627f2e78068560e29765de1ae7 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 25 Sep 2026 23:49:27 +0100 Subject: [PATCH 087/176] soc: renesas: Kconfig: Enable ICU support for RZ/G3E and RZ/V2N Explicitly select the RZ/V2H ICU driver for RZ/G3E and RZ/V2N, as GPIO and IRQ interrupts are routed through the ICU block on these SoCs. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260925224927.14951-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 5445fba0879d..a63df28df3b5 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -418,6 +418,7 @@ config ARCH_R9A09G011 config ARCH_R9A09G047 bool "ARM64 Platform support for R9A09G047 (RZ/G3E)" default y if ARCH_RENESAS + select RENESAS_RZV2H_ICU select SYS_R9A09G047 help This enables support for the Renesas RZ/G3E SoC variants. @@ -425,6 +426,7 @@ config ARCH_R9A09G047 config ARCH_R9A09G056 bool "ARM64 Platform support for R9A09G056 (RZ/V2N)" default y if ARCH_RENESAS + select RENESAS_RZV2H_ICU select SYS_R9A09G056 help This enables support for the Renesas RZ/V2N SoC variants. From 59797443846bc2451c35816026bbb79d281c9f23 Mon Sep 17 00:00:00 2001 From: Ridham Khurana Date: Mon, 21 Sep 2026 20:41:47 +0000 Subject: [PATCH 088/176] platform: cznic: turris-omnia-mcu: Add missing MODULE_DEVICE_TABLE() The driver wires of_omnia_mcu_match into the i2c_driver's .of_match_table but never exports it with MODULE_DEVICE_TABLE(), so no module alias is generated and the module is not autoloaded when the MCU is probed from the device tree. Found by code inspection. Not tested on the hardware itself; with the module built, the alias lookup $ modprobe -R 'of:Nsystem-controllerT(null)Ccznic,turris-omnia-mcu' reports no match before this change and resolves to turris_omnia_mcu after it. Fixes: 992f1a3d4e88 ("platform: cznic: Add preliminary support for Turris Omnia MCU") Signed-off-by: Ridham Khurana Link: https://patch.msgid.link/20260921204204.797294-1-khurana.ridham222@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/platform/cznic/turris-omnia-mcu-base.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/cznic/turris-omnia-mcu-base.c b/drivers/platform/cznic/turris-omnia-mcu-base.c index e8fc0d7b3343..f0416302a1f3 100644 --- a/drivers/platform/cznic/turris-omnia-mcu-base.c +++ b/drivers/platform/cznic/turris-omnia-mcu-base.c @@ -403,6 +403,7 @@ static const struct of_device_id of_omnia_mcu_match[] = { { .compatible = "cznic,turris-omnia-mcu" }, {} }; +MODULE_DEVICE_TABLE(of, of_omnia_mcu_match); static struct i2c_driver omnia_mcu_driver = { .probe = omnia_mcu_probe, From 60d42c6cde87da7bc065ad6c1f088964ae2d8b2d Mon Sep 17 00:00:00 2001 From: Manikanta Maddireddy Date: Mon, 7 Sep 2026 17:01:33 +0530 Subject: [PATCH 089/176] soc/tegra: pmc: Add PCIe wake event for Tegra234 GPIO L.2 is used as the PCIe WAKE# signal on Tegra234 platforms. Add the PMC wake event mapping so the GPIO interrupt can be armed as a system wake source. Signed-off-by: Manikanta Maddireddy Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 9c26cf4c1a89..512cca3c7509 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -4437,6 +4437,7 @@ static const char * const tegra234_reset_sources[] = { }; static const struct tegra_wake_event tegra234_wake_events[] = { + TEGRA_WAKE_GPIO("pcie-wake", 1, 0, TEGRA234_MAIN_GPIO(L, 2)), TEGRA_WAKE_GPIO("sd-wake", 8, 0, TEGRA234_MAIN_GPIO(G, 7)), TEGRA_WAKE_GPIO("eqos", 20, 0, TEGRA234_MAIN_GPIO(G, 4)), TEGRA_WAKE_IRQ("pmu", 24, 209), From b6dd5a5465bb1c24279c1b18d9ee738c996f9ec6 Mon Sep 17 00:00:00 2001 From: Chuan Liu Date: Sun, 20 Sep 2026 18:25:03 +0800 Subject: [PATCH 090/176] dt-bindings: soc: amlogic: Reordering compatible of clk-measure Sort the compatible properties defined by clk-measure in alphabetical order. Signed-off-by: Chuan Liu Acked-by: Krzysztof Kozlowski Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20260920-more-socs-to-support-clk_measure-v2-1-224382a429e8@amlogic.com Signed-off-by: Neil Armstrong --- .../soc/amlogic/amlogic,meson-gx-clk-measure.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml b/Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml index b1200e6940ac..ad37eca48103 100644 --- a/Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml +++ b/Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml @@ -16,15 +16,15 @@ maintainers: properties: compatible: enum: - - amlogic,meson-gx-clk-measure - - amlogic,meson8-clk-measure - - amlogic,meson8b-clk-measure + - amlogic,a1-clk-measure + - amlogic,c3-clk-measure - amlogic,meson-axg-clk-measure - amlogic,meson-g12a-clk-measure + - amlogic,meson-gx-clk-measure - amlogic,meson-sm1-clk-measure - - amlogic,c3-clk-measure + - amlogic,meson8-clk-measure + - amlogic,meson8b-clk-measure - amlogic,s4-clk-measure - - amlogic,a1-clk-measure - amlogic,t7-clk-measure reg: From 668232197683898b1dbab05d6f1e7f93084160c1 Mon Sep 17 00:00:00 2001 From: Chuan Liu Date: Sun, 20 Sep 2026 18:25:04 +0800 Subject: [PATCH 091/176] dt-bindings: soc: amlogic: Add clk-measure compatible to support more SoCs Add clk-measure compatible for amlogic A5, A4, S7, S7D, S6 and A9 SoCs. Although the clk-measure IP itself has little hardware difference across SoCs, the clock inputs connected to the clk-measure block vary between SoCs. Therefore, it is difficult to fall back to the configuration used by previous SoCs. Signed-off-by: Chuan Liu Acked-by: Krzysztof Kozlowski Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20260920-more-socs-to-support-clk_measure-v2-2-224382a429e8@amlogic.com Signed-off-by: Neil Armstrong --- .../bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml b/Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml index ad37eca48103..16893f427532 100644 --- a/Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml +++ b/Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml @@ -17,6 +17,9 @@ properties: compatible: enum: - amlogic,a1-clk-measure + - amlogic,a4-clk-measure + - amlogic,a5-clk-measure + - amlogic,a9-clk-measure - amlogic,c3-clk-measure - amlogic,meson-axg-clk-measure - amlogic,meson-g12a-clk-measure @@ -25,6 +28,9 @@ properties: - amlogic,meson8-clk-measure - amlogic,meson8b-clk-measure - amlogic,s4-clk-measure + - amlogic,s6-clk-measure + - amlogic,s7-clk-measure + - amlogic,s7d-clk-measure - amlogic,t7-clk-measure reg: From abb63af22300c59e0e8dca322c21ed186ba7e51f Mon Sep 17 00:00:00 2001 From: Chuan Liu Date: Sun, 20 Sep 2026 18:25:05 +0800 Subject: [PATCH 092/176] soc: amlogic: clk-measure: Support more measurement channels On S4 and C3, as well as later SoCs, the clk-measure IP expands the number of supported measurement channels from 128 to 256. Accordingly, the MSR_CLK_SRC field in the register is extended from 7 bits to 8 bits. To support both the old and new implementations, the driver now uniformly defines the valid MSR_CLK_SRC field as bits[27:20]. For SoCs where MSR_CLK_SRC is only 7 bits wide, the driver never sets bit27, and on those SoCs bit27 is read-only. Therefore, using bits[27:20] as the unified field definition does not introduce any behavioral change or compatibility issue for existing SoCs. Signed-off-by: Chuan Liu Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20260920-more-socs-to-support-clk_measure-v2-3-224382a429e8@amlogic.com Signed-off-by: Neil Armstrong --- drivers/soc/amlogic/meson-clk-measure.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c index 8a1a9fed0e74..0d4ba2555d17 100644 --- a/drivers/soc/amlogic/meson-clk-measure.c +++ b/drivers/soc/amlogic/meson-clk-measure.c @@ -20,7 +20,7 @@ static DEFINE_MUTEX(measure_lock); #define MSR_CONT BIT(17) /* continuous measurement */ #define MSR_INTR BIT(18) /* interrupts */ #define MSR_RUN BIT(19) -#define MSR_CLK_SRC GENMASK(26, 20) +#define MSR_CLK_SRC GENMASK(27, 20) #define MSR_BUSY BIT(31) #define MSR_VAL_MASK GENMASK(15, 0) From 8c6e2215b7ce72901e6aa2fecc4166d75e60c7e8 Mon Sep 17 00:00:00 2001 From: Chuan Liu Date: Sun, 20 Sep 2026 18:25:06 +0800 Subject: [PATCH 093/176] soc: amlogic: clk-measure: Align compatible entries with DT bindings Reorder the meson_msr_match_table entries to match the order of the compatible strings in the DT binding. Move the newly added clk_msr_a1_data entry accordingly, while keeping the existing SoC-specific data order unchanged. Signed-off-by: Chuan Liu Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20260920-more-socs-to-support-clk_measure-v2-4-224382a429e8@amlogic.com Signed-off-by: Neil Armstrong --- drivers/soc/amlogic/meson-clk-measure.c | 40 ++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c index 0d4ba2555d17..d58c8d9629ea 100644 --- a/drivers/soc/amlogic/meson-clk-measure.c +++ b/drivers/soc/amlogic/meson-clk-measure.c @@ -1279,6 +1279,12 @@ static const struct msr_reg_offset msr_reg_offset_v2 = { .duty_val = 0x18, }; +static const struct meson_msr_data clk_msr_a1_data = { + .msr_table = (void *)clk_msr_a1, + .msr_count = ARRAY_SIZE(clk_msr_a1), + .reg = &msr_reg_offset_v2, +}; + static const struct meson_msr_data clk_msr_c3_data = { .msr_table = (void *)clk_msr_c3, .msr_count = ARRAY_SIZE(clk_msr_c3), @@ -1291,12 +1297,6 @@ static const struct meson_msr_data clk_msr_s4_data = { .reg = &msr_reg_offset_v2, }; -static const struct meson_msr_data clk_msr_a1_data = { - .msr_table = (void *)clk_msr_a1, - .msr_count = ARRAY_SIZE(clk_msr_a1), - .reg = &msr_reg_offset_v2, -}; - static const struct meson_msr_data clk_msr_t7_data = { .msr_table = (void *)clk_msr_t7, .msr_count = ARRAY_SIZE(clk_msr_t7), @@ -1305,16 +1305,12 @@ static const struct meson_msr_data clk_msr_t7_data = { static const struct of_device_id meson_msr_match_table[] = { { - .compatible = "amlogic,meson-gx-clk-measure", - .data = &clk_msr_gx_data, + .compatible = "amlogic,a1-clk-measure", + .data = &clk_msr_a1_data, }, { - .compatible = "amlogic,meson8-clk-measure", - .data = &clk_msr_m8_data, - }, - { - .compatible = "amlogic,meson8b-clk-measure", - .data = &clk_msr_m8_data, + .compatible = "amlogic,c3-clk-measure", + .data = &clk_msr_c3_data, }, { .compatible = "amlogic,meson-axg-clk-measure", @@ -1324,22 +1320,26 @@ static const struct of_device_id meson_msr_match_table[] = { .compatible = "amlogic,meson-g12a-clk-measure", .data = &clk_msr_g12a_data, }, + { + .compatible = "amlogic,meson-gx-clk-measure", + .data = &clk_msr_gx_data, + }, { .compatible = "amlogic,meson-sm1-clk-measure", .data = &clk_msr_sm1_data, }, { - .compatible = "amlogic,c3-clk-measure", - .data = &clk_msr_c3_data, + .compatible = "amlogic,meson8-clk-measure", + .data = &clk_msr_m8_data, + }, + { + .compatible = "amlogic,meson8b-clk-measure", + .data = &clk_msr_m8_data, }, { .compatible = "amlogic,s4-clk-measure", .data = &clk_msr_s4_data, }, - { - .compatible = "amlogic,a1-clk-measure", - .data = &clk_msr_a1_data, - }, { .compatible = "amlogic,t7-clk-measure", .data = &clk_msr_t7_data, From 5508eab53e4b79a1b45f78713cab6e7154131800 Mon Sep 17 00:00:00 2001 From: Chuan Liu Date: Sun, 20 Sep 2026 18:25:07 +0800 Subject: [PATCH 094/176] soc: amlogic: clk-measure: Add support for more SoCs Add clk-measure driver support for Amlogic A5, A4, S7, S7D, S6 and A9 SoCs. Signed-off-by: Chuan Liu Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20260920-more-socs-to-support-clk_measure-v2-5-224382a429e8@amlogic.com Signed-off-by: Neil Armstrong --- drivers/soc/amlogic/meson-clk-measure.c | 897 ++++++++++++++++++++++++ 1 file changed, 897 insertions(+) diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c index d58c8d9629ea..50928ac14f86 100644 --- a/drivers/soc/amlogic/meson-clk-measure.c +++ b/drivers/soc/amlogic/meson-clk-measure.c @@ -1041,6 +1041,843 @@ static const struct meson_msr_id clk_msr_t7[] = { CLK_MSR_ID(222, "enc0") }; +static const struct meson_msr_id clk_msr_a4[] = { + CLK_MSR_ID(0, "sys_clk"), + CLK_MSR_ID(1, "axi_clk"), + CLK_MSR_ID(2, "rtc_clk"), + CLK_MSR_ID(3, "p22_usb2_ckout"), + CLK_MSR_ID(4, "p21_usb2_ckout"), + CLK_MSR_ID(5, "p20_usb2_ckout"), + CLK_MSR_ID(6, "cpu_clk_div16"), + CLK_MSR_ID(8, "eth_mpll_test"), + CLK_MSR_ID(10, "fclk_div5"), + CLK_MSR_ID(15, "fclk_50m"), + CLK_MSR_ID(16, "sys_oscin32k_i"), + CLK_MSR_ID(17, "rtc_pll"), + CLK_MSR_ID(19, "hifi_pll"), + CLK_MSR_ID(20, "gp0_pll"), + CLK_MSR_ID(21, "gp1_pll"), + CLK_MSR_ID(22, "eth_mppll_50m_ckout"), + CLK_MSR_ID(23, "sys_pll_div16"), + CLK_MSR_ID(24, "ddr_dpll_pt_clk"), + CLK_MSR_ID(27, "rtc_sec_pulse_out"), + CLK_MSR_ID(28, "rtc_osc_clk_out"), + CLK_MSR_ID(30, "mod_eth_phy_ref_clk"), + CLK_MSR_ID(31, "mod_eth_tx_clk"), + CLK_MSR_ID(32, "eth_125m"), + CLK_MSR_ID(33, "eth_rmii"), + CLK_MSR_ID(34, "co_clkin_to_mac"), + CLK_MSR_ID(35, "mod_eth_rx_clk_rmii"), + CLK_MSR_ID(36, "co_rx_clk"), + CLK_MSR_ID(37, "co_tx_clk"), + CLK_MSR_ID(38, "eth_phy_rxclk"), + CLK_MSR_ID(39, "eth_phy_plltxclk"), + CLK_MSR_ID(40, "ephy_test_clk"), + CLK_MSR_ID(41, "audio_core"), + CLK_MSR_ID(51, "cts_vout_venc_clk_ph"), + CLK_MSR_ID(52, "cts_vout_venc_clk"), + CLK_MSR_ID(106, "deskew_pll_test_clk"), + CLK_MSR_ID(111, "sar_adc"), + CLK_MSR_ID(112, "ts"), + CLK_MSR_ID(113, "sd_emmc_c"), + CLK_MSR_ID(115, "sd_emmc_a"), + CLK_MSR_ID(116, "gpio_msr_clk"), + CLK_MSR_ID(117, "spicc1"), + CLK_MSR_ID(118, "spicc0"), + CLK_MSR_ID(119, "o_mst_sclk_vad"), + CLK_MSR_ID(120, "o_mst_mclk_vad"), + CLK_MSR_ID(121, "o_pdm_sysclk"), + CLK_MSR_ID(122, "mod_audio_pdm_dclk_o"), + CLK_MSR_ID(123, "o_vad_clk"), + CLK_MSR_ID(124, "earcrx_dmac_clk"), + CLK_MSR_ID(125, "earcrx_cmdc_clk"), + CLK_MSR_ID(126, "earctx_dmac_clk"), + CLK_MSR_ID(127, "earctx_cmdc_clk"), + CLK_MSR_ID(128, "tohdmitx_bclk"), + CLK_MSR_ID(129, "tohdmitx_mclk"), + CLK_MSR_ID(130, "tohdmitx_spdif_clk"), + CLK_MSR_ID(131, "toacodec_bclk"), + CLK_MSR_ID(132, "toacodec_mclk"), + CLK_MSR_ID(133, "spdifout_b_mst_clk"), + CLK_MSR_ID(134, "spdifout_mst_clk"), + CLK_MSR_ID(135, "spdifin_mst_clk"), + CLK_MSR_ID(136, "audio_mclk"), + CLK_MSR_ID(137, "vad_clk"), + CLK_MSR_ID(138, "tdmout_d_sclk"), + CLK_MSR_ID(139, "tdmout_c_sclk"), + CLK_MSR_ID(140, "tdmout_b_sclk"), + CLK_MSR_ID(141, "tdmout_a_sclk"), + CLK_MSR_ID(142, "tdminb_lb_sclk"), + CLK_MSR_ID(143, "tdmin_lb_sclk"), + CLK_MSR_ID(144, "tdmin_d_sclk"), + CLK_MSR_ID(145, "tdmin_c_sclk"), + CLK_MSR_ID(146, "tdmin_b_sclk"), + CLK_MSR_ID(147, "tdmin_a_sclk"), + CLK_MSR_ID(148, "resampleb_clk"), + CLK_MSR_ID(149, "resamplea_clk"), + CLK_MSR_ID(150, "pdmb_sysclk"), + CLK_MSR_ID(151, "pdmb_dclk"), + CLK_MSR_ID(152, "pdm_sysclk"), + CLK_MSR_ID(153, "pdm_dclk"), + CLK_MSR_ID(154, "alockerb_out_clk"), + CLK_MSR_ID(155, "alockerb_in_clk"), + CLK_MSR_ID(156, "alocker_out_clk"), + CLK_MSR_ID(157, "alocker_in_clk"), + CLK_MSR_ID(158, "audio_mst_clk[34]"), + CLK_MSR_ID(159, "audio_mst_clk[35]"), + CLK_MSR_ID(162, "pwm_h"), + CLK_MSR_ID(163, "pwm_g"), + CLK_MSR_ID(164, "pwm_f"), + CLK_MSR_ID(165, "pwm_e"), + CLK_MSR_ID(166, "pwm_d"), + CLK_MSR_ID(167, "pwm_c"), + CLK_MSR_ID(168, "pwm_b"), + CLK_MSR_ID(169, "pwm_a"), + CLK_MSR_ID(170, "AU_ADC_CLK_G128X"), + CLK_MSR_ID(171, "AU_ADC_CLK_TO_GPIO"), + CLK_MSR_ID(172, "AU_DAC1_CLK_G128X"), + CLK_MSR_ID(173, "AU_DAC1_CLK_TO_GPIO"), + CLK_MSR_ID(176, "rng_ring_osc_clk[0]"), + CLK_MSR_ID(177, "rng_ring_osc_clk[1]"), + CLK_MSR_ID(178, "rng_ring_osc_clk[2]"), + CLK_MSR_ID(179, "rng_ring_osc_clk[3]"), + CLK_MSR_ID(180, "sys_cpu_osc_ring[0](ULVT16)"), + CLK_MSR_ID(181, "sys_cpu_osc_ring[1](ULVT20)"), + CLK_MSR_ID(182, "sys_cpu_osc_ring[2](ULVT16)"), + CLK_MSR_ID(183, "sys_cpu_osc_ring[3](ULVT16)"), + CLK_MSR_ID(184, "sys_cpu_osc_ring[4](ULVT16)"), + CLK_MSR_ID(185, "am_ring_osc_clk_out_top[0](SVT16)"), + CLK_MSR_ID(186, "am_ring_osc_clk_out_top[1](LVT20)"), +}; + +static const struct meson_msr_id clk_msr_a5[] = { + CLK_MSR_ID(0, "sys_clk"), + CLK_MSR_ID(1, "axi_clk"), + CLK_MSR_ID(2, "rtc_clk"), + CLK_MSR_ID(3, "dspa"), + CLK_MSR_ID(6, "cpu_clk_div16"), + CLK_MSR_ID(10, "fclk_div5"), + CLK_MSR_ID(11, "mpll0"), + CLK_MSR_ID(12, "mpll1"), + CLK_MSR_ID(13, "mpll2"), + CLK_MSR_ID(14, "mpll3"), + CLK_MSR_ID(15, "fclk_50m"), + CLK_MSR_ID(16, "sys_oscin32k_i"), + CLK_MSR_ID(17, "rtc_pll"), + CLK_MSR_ID(18, "mpll_clk_test_out"), + CLK_MSR_ID(19, "hifi_pll"), + CLK_MSR_ID(20, "gp0_pll"), + CLK_MSR_ID(21, "gp1_pll"), + CLK_MSR_ID(23, "sys_pll_div16"), + CLK_MSR_ID(24, "ddr_dpll_pt_clk"), + CLK_MSR_ID(25, "nna_axi"), + CLK_MSR_ID(26, "nna_core"), + CLK_MSR_ID(27, "rtc_sec_pulse_out"), + CLK_MSR_ID(28, "rtc_osc_clk_out"), + CLK_MSR_ID(30, "mod_eth_phy_ref_clk"), + CLK_MSR_ID(31, "mod_eth_tx_clk"), + CLK_MSR_ID(35, "mod_eth_rx_clk_rmii"), + CLK_MSR_ID(79, "rama_clk"), + CLK_MSR_ID(106, "deskew_pll_clk_div32_out"), + CLK_MSR_ID(111, "sar_adc"), + CLK_MSR_ID(112, "ts"), + CLK_MSR_ID(113, "sd_emmc_c"), + CLK_MSR_ID(115, "sd_emmc_a"), + CLK_MSR_ID(116, "gpio_msr_clk"), + CLK_MSR_ID(117, "spicc1"), + CLK_MSR_ID(118, "spicc0"), + CLK_MSR_ID(119, "o_mst_sclk_vad"), + CLK_MSR_ID(120, "o_mst_mclk_vad"), + CLK_MSR_ID(121, "o_pdm_sysclk"), + CLK_MSR_ID(122, "mod_audio_pdm_dclk_o"), + CLK_MSR_ID(123, "o_vad_clk"), + CLK_MSR_ID(124, "earcrx_dmac_clk"), + CLK_MSR_ID(125, "earcrx_cmdc_clk"), + CLK_MSR_ID(126, "earctx_dmac_clk"), + CLK_MSR_ID(127, "earctx_cmdc_clk"), + CLK_MSR_ID(128, "tohdmitx_bclk"), + CLK_MSR_ID(129, "tohdmitx_mclk"), + CLK_MSR_ID(130, "tohdmitx_spdif_clk"), + CLK_MSR_ID(131, "toacodec_bclk"), + CLK_MSR_ID(132, "toacodec_mclk"), + CLK_MSR_ID(133, "spdifout_b_mst_clk"), + CLK_MSR_ID(134, "spdifout_mst_clk"), + CLK_MSR_ID(135, "spdifin_mst_clk"), + CLK_MSR_ID(136, "audio_mclk"), + CLK_MSR_ID(137, "vad_clk"), + CLK_MSR_ID(138, "tdmout_d_sclk"), + CLK_MSR_ID(139, "tdmout_c_sclk"), + CLK_MSR_ID(140, "tdmout_b_sclk"), + CLK_MSR_ID(141, "tdmout_a_sclk"), + CLK_MSR_ID(142, "tdminb_lb_sclk"), + CLK_MSR_ID(143, "tdmin_lb_sclk"), + CLK_MSR_ID(144, "tdmin_d_sclk"), + CLK_MSR_ID(145, "tdmin_c_sclk"), + CLK_MSR_ID(146, "tdmin_b_sclk"), + CLK_MSR_ID(147, "tdmin_a_sclk"), + CLK_MSR_ID(148, "resampleb_clk"), + CLK_MSR_ID(149, "resamplea_clk"), + CLK_MSR_ID(150, "pdmb_sysclk"), + CLK_MSR_ID(151, "pdmb_dclk"), + CLK_MSR_ID(152, "pdm_sysclk"), + CLK_MSR_ID(153, "pdm_dclk"), + CLK_MSR_ID(154, "alockerb_out_clk"), + CLK_MSR_ID(155, "alockerb_in_clk"), + CLK_MSR_ID(156, "alocker_out_clk"), + CLK_MSR_ID(157, "alocker_in_clk"), + CLK_MSR_ID(158, "audio_mst_clk[34]"), + CLK_MSR_ID(159, "audio_mst_clk[35]"), + CLK_MSR_ID(162, "pwm_h"), + CLK_MSR_ID(163, "pwm_g"), + CLK_MSR_ID(164, "pwm_f"), + CLK_MSR_ID(165, "pwm_e"), + CLK_MSR_ID(166, "pwm_d"), + CLK_MSR_ID(167, "pwm_c"), + CLK_MSR_ID(168, "pwm_b"), + CLK_MSR_ID(169, "pwm_a"), + CLK_MSR_ID(176, "rng_ring_osc_clk[0]"), + CLK_MSR_ID(177, "rng_ring_osc_clk[1]"), + CLK_MSR_ID(178, "rng_ring_osc_clk[2]"), + CLK_MSR_ID(179, "rng_ring_osc_clk[3]"), + CLK_MSR_ID(180, "dmc_osc_ring(LVT16)"), + CLK_MSR_ID(181, "dsp_osc_ring(SVT16)"), + CLK_MSR_ID(182, "axi_srama_osc_ring(SVT16)"), + CLK_MSR_ID(183, "nna_osc_ring[0](ULVT20)"), + CLK_MSR_ID(184, "nna_osc_ring[1](LVT16)"), + CLK_MSR_ID(185, "sys_cpu_osc_ring[0](ULVT16)"), + CLK_MSR_ID(186, "sys_cpu_osc_ring[1](ULVT20)"), + CLK_MSR_ID(187, "sys_cpu_osc_ring[2](ULVT16)"), + CLK_MSR_ID(188, "sys_cpu_osc_ring[3](LVT16)"), + CLK_MSR_ID(189, "axi_sramb_osc_ring(SVT16)"), +}; + +static const struct meson_msr_id clk_msr_a9[] = { + CLK_MSR_ID(0, "sys_clk"), + CLK_MSR_ID(1, "axi_clk"), + CLK_MSR_ID(2, "rtc_clk"), + CLK_MSR_ID(3, "dspa"), + CLK_MSR_ID(4, "mali_stack"), + CLK_MSR_ID(5, "mali"), + CLK_MSR_ID(6, "cpu_clk_div16"), + CLK_MSR_ID(7, "a78_clk_div16"), + CLK_MSR_ID(8, "dsu_clk_div16"), + CLK_MSR_ID(9, "isp"), + CLK_MSR_ID(10, "gp2_pll"), + CLK_MSR_ID(11, "fclk_div5"), + CLK_MSR_ID(12, "u2drd_usb2_ckout"), + CLK_MSR_ID(13, "pre0_hdmirx_aud_pll_clk"), + CLK_MSR_ID(14, "hrx20_pll_clk_test"), + CLK_MSR_ID(15, "u2h_usb2_ckout"), + CLK_MSR_ID(16, "fclk_50m"), + CLK_MSR_ID(17, "u3drd_b_usb2_ckout"), + CLK_MSR_ID(18, "gp1_pll"), + CLK_MSR_ID(19, "hifi_pll"), + CLK_MSR_ID(20, "gp0_pll"), + CLK_MSR_ID(21, "hifi1_pll"), + CLK_MSR_ID(22, "csi_phy"), + CLK_MSR_ID(23, "sys_pll_div16"), + CLK_MSR_ID(24, "ddr_dpll_pt_clk"), + CLK_MSR_ID(25, "mod_Tsin_A_CLK_IN"), + CLK_MSR_ID(26, "ext_Tsin_B_CLK_IN"), + CLK_MSR_ID(27, "u3p2pll1_0_clk_div16"), + CLK_MSR_ID(28, "u3p2pll1_1_clk_div16"), + CLK_MSR_ID(29, "upcrx0_cdrclk"), + CLK_MSR_ID(30, "upcrx1_cdrclk"), + CLK_MSR_ID(31, "hdmirx_aud_sck"), + CLK_MSR_ID(32, "uptx0_clk_sync_b20"), + CLK_MSR_ID(33, "uptx1_clk_sync_b20"), + CLK_MSR_ID(34, "lp_pll_clk0"), + CLK_MSR_ID(35, "lp_pll_clk1"), + CLK_MSR_ID(36, "u3hsg_PCIE_PIPE_PCLK"), + CLK_MSR_ID(37, "u3hsg_upcrx_cdrclk"), + CLK_MSR_ID(38, "u3hsg_upctx_clk_sync_b20"), + CLK_MSR_ID(39, "u3hsg_upcrxpll_clk_test"), + CLK_MSR_ID(40, "hdmirx_acr_lclk"), + CLK_MSR_ID(41, "i3c"), + CLK_MSR_ID(42, "hdmirx_aud_pll"), + CLK_MSR_ID(43, "hdmirx_acr_ref"), + CLK_MSR_ID(44, "hdmirx_meter"), + CLK_MSR_ID(45, "hdmirx_hdcp2x"), + CLK_MSR_ID(46, "hdmirx_5m"), + CLK_MSR_ID(47, "hdmirx_2m"), + CLK_MSR_ID(48, "hdmirx_cfg"), + CLK_MSR_ID(49, "hdmi_vx1_pix_clk"), + CLK_MSR_ID(50, "vid_pll"), + CLK_MSR_ID(51, "encoder0_if_clk"), + CLK_MSR_ID(52, "encoder1"), + CLK_MSR_ID(53, "encoder0"), + CLK_MSR_ID(54, "vdac"), + CLK_MSR_ID(55, "mali_aclkm"), + CLK_MSR_ID(56, "vid1_pll"), + CLK_MSR_ID(57, "lcd_an_ph2"), + CLK_MSR_ID(58, "lcd_an_ph3"), + CLK_MSR_ID(59, "hdmitx_pixel"), + CLK_MSR_ID(60, "vdin_meas"), + CLK_MSR_ID(61, "vpu"), + CLK_MSR_ID(62, "vpu_clkb"), + CLK_MSR_ID(63, "vpu_clkb_tmp"), + CLK_MSR_ID(64, "u3p2_upcrxpll_fst_pll_clk"), + CLK_MSR_ID(65, "vid_lock"), + CLK_MSR_ID(66, "vapb"), + CLK_MSR_ID(67, "ge2d"), + CLK_MSR_ID(68, "cve"), + CLK_MSR_ID(69, "vge"), + CLK_MSR_ID(70, "dsi0_meas"), + CLK_MSR_ID(71, "dsi1_meas"), + CLK_MSR_ID(72, "mipi_csi_phy_clk_out[0]"), + CLK_MSR_ID(73, "mipi_csi_phy_clk_out[1]"), + CLK_MSR_ID(74, "mipi_csi_phy_clk_out[2]"), + CLK_MSR_ID(75, "mipi_csi_phy_clk_out[3]"), + CLK_MSR_ID(76, "hdmitx_tmds"), + CLK_MSR_ID(77, "hdmitx_sys"), + CLK_MSR_ID(78, "hdmitx_fe"), + CLK_MSR_ID(80, "hdmitx_prif"), + CLK_MSR_ID(81, "hdmitx_200m"), + CLK_MSR_ID(82, "hdmitx_aud"), + CLK_MSR_ID(83, "hdmitx1_pixel"), + CLK_MSR_ID(84, "hdmitx1_fe"), + CLK_MSR_ID(85, "gic"), + CLK_MSR_ID(86, "lvds0_fifo_clk"), + CLK_MSR_ID(87, "lvds1_fifo_clk"), + CLK_MSR_ID(88, "htx_aes_clk"), + CLK_MSR_ID(89, "amfc"), + CLK_MSR_ID(90, "a_clk_sync_dig"), + CLK_MSR_ID(91, "b_clk_sync_dig"), + CLK_MSR_ID(92, "u3dp_upcrx_cdrclk"), + CLK_MSR_ID(93, "u3dp_upctx_clk_sync_b20"), + CLK_MSR_ID(94, "u3dp_upcrxpll_clk_test"), + CLK_MSR_ID(95, "u3dp_upcrpll_fst_pll_clk"), + CLK_MSR_ID(96, "u3dp_usb2_ckout"), + CLK_MSR_ID(97, "hcodec"), + CLK_MSR_ID(99, "hevcf"), + CLK_MSR_ID(104, "spisg2"), + CLK_MSR_ID(105, "spisg1"), + CLK_MSR_ID(106, "deskew_pll_clk_div32_out"), + CLK_MSR_ID(108, "cmpr"), + CLK_MSR_ID(109, "dewarpa"), + CLK_MSR_ID(110, "sc"), + CLK_MSR_ID(111, "sar_adc"), + CLK_MSR_ID(112, "glb"), + CLK_MSR_ID(113, "sd_emmc_c"), + CLK_MSR_ID(114, "sd_emmc_b"), + CLK_MSR_ID(115, "sd_emmc_a"), + CLK_MSR_ID(116, "gpio_msr_clk"), + CLK_MSR_ID(117, "aux_clk_o"), + CLK_MSR_ID(118, "spisg0"), + CLK_MSR_ID(121, "ts"), + CLK_MSR_ID(122, "usb_48m"), + CLK_MSR_ID(123, "usb_250m"), + CLK_MSR_ID(124, "eth_125m"), + CLK_MSR_ID(125, "eth_rmii"), + CLK_MSR_ID(126, "hrx20_tmds20_clk"), + CLK_MSR_ID(127, "hrx20_cable_clk"), + CLK_MSR_ID(128, "hdmirx_vid_clk"), + CLK_MSR_ID(129, "hdmirx_aud_clk"), + CLK_MSR_ID(130, "dptx_apb2"), + CLK_MSR_ID(131, "dptx_aud"), + CLK_MSR_ID(132, "audio_todptx_bclk"), + CLK_MSR_ID(133, "audio_txhdmitx_bclk"), + CLK_MSR_ID(134, "audio_txhdmitx_mclk"), + CLK_MSR_ID(135, "audio_txhdmitx_spdif_clk"), + CLK_MSR_ID(136, "mclk_0_pre"), + CLK_MSR_ID(137, "mclk1_0_pre"), + CLK_MSR_ID(138, "pixel0_pll_clkout"), + CLK_MSR_ID(139, "pixel1_pll_clkout"), + CLK_MSR_ID(140, "tcon_clk_out0"), + CLK_MSR_ID(141, "tcon_clk_out1"), + CLK_MSR_ID(142, "audio_todptx_spdif_clk"), + CLK_MSR_ID(143, "audio_todptx_mclk"), + CLK_MSR_ID(144, "dptx_lnk_clk"), + CLK_MSR_ID(145, "edptx_lnk_clk_tx"), + CLK_MSR_ID(146, "mod_audio_pdm_dclk_o_ao"), + CLK_MSR_ID(147, "vid2_pll"), + CLK_MSR_ID(151, "can1_filter"), + CLK_MSR_ID(152, "can0_filter"), + CLK_MSR_ID(153, "can1_pe"), + CLK_MSR_ID(154, "can0_pe"), + CLK_MSR_ID(155, "o_sed_clk"), + CLK_MSR_ID(156, "pwm_n"), + CLK_MSR_ID(157, "pwm_m"), + CLK_MSR_ID(158, "pwm_l"), + CLK_MSR_ID(159, "pwm_k"), + CLK_MSR_ID(160, "pwm_j"), + CLK_MSR_ID(161, "pwm_i"), + CLK_MSR_ID(162, "pwm_h"), + CLK_MSR_ID(170, "rng_ring_osc_clk[0]"), + CLK_MSR_ID(171, "rng_ring_osc_clk[1]"), + CLK_MSR_ID(172, "rng_ring_osc_clk[2]"), + CLK_MSR_ID(173, "rng_ring_osc_clk[3]"), + CLK_MSR_ID(174, "rng_ring_osc_clk[4]"), + CLK_MSR_ID(175, "sys_cpu_osc_ring_clk[0]"), + CLK_MSR_ID(176, "sys_cpu_osc_ring_clk[1]"), + CLK_MSR_ID(177, "sys_cpu_osc_ring_clk[2]"), + CLK_MSR_ID(178, "sys_cpu_osc_ring_clk[3]"), + CLK_MSR_ID(179, "sys_cpu_osc_ring_clk[4]"), + CLK_MSR_ID(180, "sys_cpu_osc_ring_clk[5]"), + CLK_MSR_ID(181, "sys_cpu_osc_ring_clk[6]"), + CLK_MSR_ID(182, "sys_cpu_osc_ring_clk[7]"), + CLK_MSR_ID(183, "sys_cpu_osc_ring_clk[8]"), + CLK_MSR_ID(184, "sys_cpu_osc_ring_clk[9]"), + CLK_MSR_ID(185, "osc_ring_clk_gpu[0]"), + CLK_MSR_ID(186, "osc_ring_clk_gpu[1]"), + CLK_MSR_ID(187, "osc_ring_clk_vpu"), + CLK_MSR_ID(188, "osc_ring_clk_dos[0]"), + CLK_MSR_ID(189, "osc_ring_clk_dos[1]"), + CLK_MSR_ID(190, "osc_ring_clk_vge"), + CLK_MSR_ID(191, "osc_ring_clk_nna[0]"), + CLK_MSR_ID(192, "osc_ring_clk_nna[1]"), + CLK_MSR_ID(193, "osc_ring_clk_top[0]"), + CLK_MSR_ID(194, "osc_ring_clk_top[1]"), + CLK_MSR_ID(195, "nna"), + CLK_MSR_ID(200, "pcie1_tl"), + CLK_MSR_ID(201, "pcie0_tl"), + CLK_MSR_ID(202, "pp"), + CLK_MSR_ID(203, "pwm_a(ao)"), + CLK_MSR_ID(204, "pwm_b(ao)"), + CLK_MSR_ID(205, "pwm_c(ao)"), + CLK_MSR_ID(206, "pwm_d(ao)"), + CLK_MSR_ID(207, "pwm_e(ao)"), + CLK_MSR_ID(208, "pwm_f(ao)"), + CLK_MSR_ID(209, "pwm_g(ao)"), + CLK_MSR_ID(210, "ao_cec"), + CLK_MSR_ID(211, "sec_pulse_out"), + CLK_MSR_ID(212, "osc_clk_out"), + CLK_MSR_ID(213, "earcrx_pll_clk_out"), + CLK_MSR_ID(215, "o_pd_sysclk"), + CLK_MSR_ID(216, "o_earcrx_dmac_clk"), + CLK_MSR_ID(217, "o_earcrx_cmdc_clk"), + CLK_MSR_ID(218, "o_earctx_dmac_clk"), + CLK_MSR_ID(219, "o_earctx_cmdc_clk"), + CLK_MSR_ID(220, "o_earctx_ana_dmac_clk_a2d"), + CLK_MSR_ID(221, "o_tohdmi_dp_tx_a_bclk"), + CLK_MSR_ID(222, "o_tohdmi_dp_tx_a_mclk"), + CLK_MSR_ID(223, "o_tohdmi_dp_tx_a_spdif_clk"), + CLK_MSR_ID(224, "o_tohdmi_dp_tx_b_bclk"), + CLK_MSR_ID(225, "o_tohdmi_dp_tx_b_mclk"), + CLK_MSR_ID(226, "o_tohdmi_dp_tx_b_spdif_clk"), + CLK_MSR_ID(227, "o_toacodec_dac_bclk"), + CLK_MSR_ID(228, "o_toacodec_dac_mclk"), + CLK_MSR_ID(229, "o_spdifout_b_mst_clk"), + CLK_MSR_ID(230, "o_spdifout_mst_clk"), + CLK_MSR_ID(231, "o_spdifin_mst_clk"), + CLK_MSR_ID(232, "o_audio_mclk"), + CLK_MSR_ID(233, "o_vad_clk"), + CLK_MSR_ID(234, "o_tdmout_d_sclk"), + CLK_MSR_ID(235, "o_tdmout_c_sclk"), + CLK_MSR_ID(236, "o_tdmout_b_sclk"), + CLK_MSR_ID(237, "o_tdmout_a_sclk"), + CLK_MSR_ID(238, "o_tdminb_lb_sclk"), + CLK_MSR_ID(239, "o_tdmin_lb_sclk"), + CLK_MSR_ID(240, "o_tdmin_d_sclk"), + CLK_MSR_ID(241, "o_tdmin_c_sclk"), + CLK_MSR_ID(242, "o_tdmin_b_sclk"), + CLK_MSR_ID(243, "o_tdmin_a_sclk"), + CLK_MSR_ID(244, "o_resampleb_clk"), + CLK_MSR_ID(245, "o_resamplea_clk"), + CLK_MSR_ID(246, "o_pdmb_sysclk"), + CLK_MSR_ID(247, "o_pdmb_dclk"), + CLK_MSR_ID(248, "o_pdm_sysclk"), + CLK_MSR_ID(249, "o_pdm_dclk"), + CLK_MSR_ID(250, "c_alockerb_out_clk"), + CLK_MSR_ID(251, "c_alockerb_in_clk"), + CLK_MSR_ID(252, "c_alocker_out_clk"), + CLK_MSR_ID(253, "c_alocker_in_clk"), + CLK_MSR_ID(254, "o_resample_c_clk") +}; + +static const struct meson_msr_id clk_msr_s6[] = { + CLK_MSR_ID(0, "sys_clk"), + CLK_MSR_ID(1, "axi_clk"), + CLK_MSR_ID(2, "rtc_clk"), + CLK_MSR_ID(3, "dspa"), + CLK_MSR_ID(4, "mali_stack"), + CLK_MSR_ID(5, "mali"), + CLK_MSR_ID(6, "cpu_clk_div16"), + CLK_MSR_ID(7, "mali_aclkm"), + CLK_MSR_ID(8, "cecb"), + CLK_MSR_ID(9, "gp2_pll"), + CLK_MSR_ID(10, "fclk_div5"), + CLK_MSR_ID(11, "p21_usb2_ckout"), + CLK_MSR_ID(12, "p20_usb2_ckout"), + CLK_MSR_ID(13, "eth_mpll_test"), + CLK_MSR_ID(15, "fclk_50m"), + CLK_MSR_ID(18, "gp1_pll"), + CLK_MSR_ID(19, "hifi_pll"), + CLK_MSR_ID(20, "gp0_pll"), + CLK_MSR_ID(21, "hifi1_pll"), + CLK_MSR_ID(22, "eth_mppll_50m_ckout"), + CLK_MSR_ID(23, "sys_pll_div16"), + CLK_MSR_ID(24, "ddr_dpll_pt_clk"), + CLK_MSR_ID(25, "mod_Tsin_A_CLK_IN"), + CLK_MSR_ID(26, "ext_Tsin_B_CLK_IN"), + CLK_MSR_ID(27, "mod_Tsin_C_CLK_IN"), + CLK_MSR_ID(28, "mod_Tsin_D_CLK_IN"), + CLK_MSR_ID(29, "dsi_pll_div_clk_out"), + CLK_MSR_ID(30, "dsi_pll_clk"), + CLK_MSR_ID(32, "eth_125m"), + CLK_MSR_ID(33, "eth_rmii"), + CLK_MSR_ID(34, "co_clkin_to_mac"), + CLK_MSR_ID(36, "co_rx_clk"), + CLK_MSR_ID(37, "co_tx_clk"), + CLK_MSR_ID(38, "eth_phy_rxclk"), + CLK_MSR_ID(39, "eth_phy_plltxclk"), + CLK_MSR_ID(40, "ephy_test_clk"), + CLK_MSR_ID(49, "hdmi_vx1_pix_clk"), + CLK_MSR_ID(50, "vid_pll"), + CLK_MSR_ID(51, "enci"), + CLK_MSR_ID(52, "encp"), + CLK_MSR_ID(53, "encl"), + CLK_MSR_ID(54, "vdac"), + CLK_MSR_ID(55, "cdac"), + CLK_MSR_ID(57, "lcd_an_clk_ph2"), + CLK_MSR_ID(58, "lcd_an_clk_ph3"), + CLK_MSR_ID(59, "hdmitx_pixel"), + CLK_MSR_ID(60, "vdin_meas"), + CLK_MSR_ID(61, "vpu"), + CLK_MSR_ID(62, "vpu_clkb"), + CLK_MSR_ID(63, "vpu_clkb_tmp"), + CLK_MSR_ID(64, "vpu_clkc"), + CLK_MSR_ID(65, "vid_lock"), + CLK_MSR_ID(66, "vapb"), + CLK_MSR_ID(67, "ge2d"), + CLK_MSR_ID(70, "mipi_dsi_meas"), + CLK_MSR_ID(71, "mipi_dsi_phy"), + CLK_MSR_ID(72, "mipi_csi_phy"), + CLK_MSR_ID(73, "csi2_adapt"), + CLK_MSR_ID(74, "cts_csi2_data"), + CLK_MSR_ID(75, "mipi_csi_phy_out"), + CLK_MSR_ID(76, "hdmitx_tmds"), + CLK_MSR_ID(77, "hdmitx_sys"), + CLK_MSR_ID(78, "hdmitx_fe"), + CLK_MSR_ID(79, "rama_clk"), + CLK_MSR_ID(80, "hdmitx_prif"), + CLK_MSR_ID(81, "hdmitx_200m"), + CLK_MSR_ID(82, "hdmitx_aud"), + CLK_MSR_ID(84, "audio_tohdmitx_mclk"), + CLK_MSR_ID(85, "audio_tohdmitx_bclk"), + CLK_MSR_ID(86, "audio_tohdmitx_lrclk"), + CLK_MSR_ID(87, "audio_tohdmitx_spdif_clk"), + CLK_MSR_ID(88, "htx_aes_clk"), + CLK_MSR_ID(89, "amfc"), + CLK_MSR_ID(93, "vdec"), + CLK_MSR_ID(99, "hevcf"), + CLK_MSR_ID(106, "deskew_pll_clk_div32_out"), + CLK_MSR_ID(108, "cmpr"), + CLK_MSR_ID(109, "dewarpa"), + CLK_MSR_ID(110, "sc"), + CLK_MSR_ID(111, "sar_adc"), + CLK_MSR_ID(113, "sd_emmc_c"), + CLK_MSR_ID(114, "sd_emmc_b"), + CLK_MSR_ID(115, "sd_emmc_a"), + CLK_MSR_ID(116, "gpio_msr_clk"), + CLK_MSR_ID(117, "aux_clk_o"), + CLK_MSR_ID(118, "spicc"), + CLK_MSR_ID(121, "ts"), + CLK_MSR_ID(130, "o_vad_clk"), + CLK_MSR_ID(132, "audio_locker_in_clk"), + CLK_MSR_ID(133, "audio_locker_out_clk"), + CLK_MSR_ID(134, "audio_tdmout_c_sclk"), + CLK_MSR_ID(135, "audio_tdmout_b_sclk"), + CLK_MSR_ID(136, "audio_tdmout_a_sclk"), + CLK_MSR_ID(137, "audio_tdmin_lb_sclk"), + CLK_MSR_ID(138, "audio_tdmin_c_sclk"), + CLK_MSR_ID(139, "audio_tdmin_b_sclk"), + CLK_MSR_ID(140, "audio_tdmin_a_sclk"), + CLK_MSR_ID(141, "audio_resamplea_clk"), + CLK_MSR_ID(142, "audio_pdm_sysclk"), + CLK_MSR_ID(143, "audio_spdifout_b_mst_clk"), + CLK_MSR_ID(144, "audio_spdifout_mst_clk"), + CLK_MSR_ID(145, "audio_spdifin_mst_clk"), + CLK_MSR_ID(147, "audio_resampleb_clk"), + CLK_MSR_ID(148, "pcie_pipe_clk"), + CLK_MSR_ID(149, "pcie_ref_clk"), + CLK_MSR_ID(150, "pcie_upcrx_cdrclk"), + CLK_MSR_ID(151, "pcie_upcrx_clk_sync_b20"), + CLK_MSR_ID(152, "pcie_u3p2pll1_clk_div16"), + CLK_MSR_ID(153, "pcie_u3p2pll0_clkout"), + CLK_MSR_ID(154, "pcie_ref_clk_p"), + CLK_MSR_ID(160, "pwm_j"), + CLK_MSR_ID(161, "pwm_i"), + CLK_MSR_ID(162, "pwm_h"), + CLK_MSR_ID(163, "pwm_g"), + CLK_MSR_ID(164, "pwm_f"), + CLK_MSR_ID(165, "pwm_e"), + CLK_MSR_ID(166, "pwm_d"), + CLK_MSR_ID(167, "pwm_c"), + CLK_MSR_ID(168, "pwm_b"), + CLK_MSR_ID(169, "pwm_a"), + CLK_MSR_ID(175, "rng_ring_clk[0]"), + CLK_MSR_ID(176, "rng_ring_clk[1]"), + CLK_MSR_ID(177, "rng_ring_clk[2]"), + CLK_MSR_ID(178, "rng_ring_clk[3]"), + CLK_MSR_ID(179, "rng_ring_clk[4]"), + CLK_MSR_ID(180, "am_ring_osc_clk_out[0]"), + CLK_MSR_ID(181, "am_ring_osc_clk_out[1]"), + CLK_MSR_ID(182, "am_ring_osc_clk_out[2]"), + CLK_MSR_ID(183, "am_ring_osc_clk_out[3]"), + CLK_MSR_ID(184, "am_ring_osc_clk_out[4]"), + CLK_MSR_ID(185, "am_ring_osc_clk_out[5]"), + CLK_MSR_ID(186, "am_ring_osc_clk_out[6]"), + CLK_MSR_ID(187, "am_ring_osc_clk_out[7]"), + CLK_MSR_ID(188, "am_ring_osc_clk_out[8]"), + CLK_MSR_ID(189, "am_ring_osc_clk_out[9]"), + CLK_MSR_ID(190, "am_ring_osc_clk_out[10]"), + CLK_MSR_ID(191, "am_ring_osc_clk_out[11]"), + CLK_MSR_ID(192, "am_ring_osc_clk_out[12]"), + CLK_MSR_ID(193, "am_ring_osc_clk_out[13]"), + CLK_MSR_ID(194, "am_ring_osc_clk_out[14]"), + CLK_MSR_ID(195, "am_ring_osc_clk_out[15]"), + CLK_MSR_ID(196, "am_ring_osc_clk_out[16]"), + CLK_MSR_ID(197, "nna"), + CLK_MSR_ID(198, "vc9000e_axi"), + CLK_MSR_ID(199, "vc9000e_core"), + CLK_MSR_ID(201, "pcie_tl"), + CLK_MSR_ID(204, "u3p2pll1_clk_div16"), + CLK_MSR_ID(205, "u3p2pll0_clkout"), + CLK_MSR_ID(206, "upctx_clk_sync_b20"), + CLK_MSR_ID(207, "upcrx_carclk"), + CLK_MSR_ID(208, "usb_pipe_clk"), + CLK_MSR_ID(209, "earcrx_pll_out"), + CLK_MSR_ID(210, "mclk_pll_clk") +}; + +static const struct meson_msr_id clk_msr_s7[] = { + CLK_MSR_ID(0, "sys_clk"), + CLK_MSR_ID(1, "axi_clk"), + CLK_MSR_ID(2, "rtc_clk"), + CLK_MSR_ID(5, "mali"), + CLK_MSR_ID(6, "cpu_clk_div16"), + CLK_MSR_ID(8, "cecb"), + CLK_MSR_ID(10, "fclk_div5"), + CLK_MSR_ID(11, "p21_usb2_ckout"), + CLK_MSR_ID(12, "p20_usb2_ckout"), + CLK_MSR_ID(13, "eth_mpll_test"), + CLK_MSR_ID(15, "fclk_50m"), + CLK_MSR_ID(18, "gp1_pll"), + CLK_MSR_ID(19, "hifi_pll"), + CLK_MSR_ID(20, "gp0_pll"), + CLK_MSR_ID(21, "hifi1_pll"), + CLK_MSR_ID(22, "eth_mppll_50m_ckout"), + CLK_MSR_ID(23, "sys_pll_div16"), + CLK_MSR_ID(24, "ddr_dpll_pt_clk"), + CLK_MSR_ID(25, "mod_Tsin_A_CLK_IN"), + CLK_MSR_ID(32, "eth_125m"), + CLK_MSR_ID(33, "eth_rmii"), + CLK_MSR_ID(34, "co_clkin_to_mac"), + CLK_MSR_ID(36, "co_rx_clk"), + CLK_MSR_ID(37, "co_tx_clk"), + CLK_MSR_ID(38, "eth_phy_rxclk"), + CLK_MSR_ID(39, "eth_phy_plltxclk"), + CLK_MSR_ID(40, "ephy_test_clk"), + CLK_MSR_ID(49, "hdmi_vx1_pix_clk"), + CLK_MSR_ID(50, "vid_pll"), + CLK_MSR_ID(51, "enci"), + CLK_MSR_ID(52, "encp"), + CLK_MSR_ID(53, "encl"), + CLK_MSR_ID(54, "vdac"), + CLK_MSR_ID(55, "cdac"), + CLK_MSR_ID(57, "lcd_an_clk_ph2"), + CLK_MSR_ID(58, "lcd_an_clk_ph3"), + CLK_MSR_ID(59, "hdmitx_pixel"), + CLK_MSR_ID(60, "vdin_meas"), + CLK_MSR_ID(61, "vpu"), + CLK_MSR_ID(62, "vpu_clkb"), + CLK_MSR_ID(63, "vpu_clkb_tmp"), + CLK_MSR_ID(64, "vpu_clkc"), + CLK_MSR_ID(65, "vid_lock"), + CLK_MSR_ID(66, "vapb"), + CLK_MSR_ID(67, "ge2d"), + CLK_MSR_ID(76, "hdmitx_tmds"), + CLK_MSR_ID(77, "hdmitx_sys"), + CLK_MSR_ID(78, "hdmitx_fe"), + CLK_MSR_ID(80, "hdmitx_prif"), + CLK_MSR_ID(81, "hdmitx_200m"), + CLK_MSR_ID(82, "hdmitx_aud"), + CLK_MSR_ID(84, "audio_tohdmitx_mclk"), + CLK_MSR_ID(85, "audio_tohdmitx_bclk"), + CLK_MSR_ID(86, "audio_tohdmitx_lrclk"), + CLK_MSR_ID(87, "audio_tohdmitx_spdif_clk"), + CLK_MSR_ID(88, "htx_aes_clk"), + CLK_MSR_ID(93, "vdec"), + CLK_MSR_ID(99, "hevcf"), + CLK_MSR_ID(106, "deskew_pll_clk_div32_out"), + CLK_MSR_ID(110, "sc"), + CLK_MSR_ID(111, "sar_adc"), + CLK_MSR_ID(113, "sd_emmc_c"), + CLK_MSR_ID(114, "sd_emmc_b"), + CLK_MSR_ID(115, "sd_emmc_a"), + CLK_MSR_ID(116, "gpio_msr_clk"), + CLK_MSR_ID(118, "spicc"), + CLK_MSR_ID(121, "ts"), + CLK_MSR_ID(130, "o_vad_clk"), + CLK_MSR_ID(131, "au_dac_clk_x128"), + CLK_MSR_ID(132, "audio_locker_in_clk"), + CLK_MSR_ID(133, "audio_locker_out_clk"), + CLK_MSR_ID(134, "audio_tdmout_c_sclk"), + CLK_MSR_ID(135, "audio_tdmout_b_sclk"), + CLK_MSR_ID(136, "audio_tdmout_a_sclk"), + CLK_MSR_ID(137, "audio_tdmin_lb_sclk"), + CLK_MSR_ID(138, "audio_tdmin_c_sclk"), + CLK_MSR_ID(139, "audio_tdmin_b_sclk"), + CLK_MSR_ID(140, "audio_tdmin_a_sclk"), + CLK_MSR_ID(141, "audio_resamplea_clk"), + CLK_MSR_ID(142, "audio_pdm_sysclk"), + CLK_MSR_ID(143, "audio_spdifout_b_mst_clk"), + CLK_MSR_ID(144, "audio_spdifout_mst_clk"), + CLK_MSR_ID(145, "audio_spdifin_mst_clk"), + CLK_MSR_ID(147, "audio_resampleb_clk"), + CLK_MSR_ID(160, "pwm_j"), + CLK_MSR_ID(161, "pwm_i"), + CLK_MSR_ID(162, "pwm_h"), + CLK_MSR_ID(163, "pwm_g"), + CLK_MSR_ID(164, "pwm_f"), + CLK_MSR_ID(165, "pwm_e"), + CLK_MSR_ID(166, "pwm_d"), + CLK_MSR_ID(167, "pwm_c"), + CLK_MSR_ID(168, "pwm_b"), + CLK_MSR_ID(169, "pwm_a"), + CLK_MSR_ID(176, "rng_ring_clk[0]"), + CLK_MSR_ID(177, "rng_ring_clk[1]"), + CLK_MSR_ID(178, "rng_ring_clk[2]"), + CLK_MSR_ID(179, "rng_ring_clk[3]"), + CLK_MSR_ID(180, "osc_ring_clk[0](a55 core0 14_slvt)"), + CLK_MSR_ID(181, "osc_ring_clk[1](a55 core1 14_slvt)"), + CLK_MSR_ID(182, "osc_ring_clk[2](a55 core2 14_slvt)"), + CLK_MSR_ID(183, "osc_ring_clk[3](a55 core3 14_slvt)"), + CLK_MSR_ID(184, "osc_ring_clk[4](a55_pwr[0] 16_slvt)"), + CLK_MSR_ID(185, "osc_ring_clk[5](a55_pwr[1] 14_lvt)"), + CLK_MSR_ID(186, "osc_ring_clk[6](a55_pwr[2] 14_rvt)"), + CLK_MSR_ID(187, "osc_ring_clk[7](mali[1] 14_lvt)"), + CLK_MSR_ID(188, "osc_ring_clk[8](mali[1] 14_rvt)"), + CLK_MSR_ID(189, "osc_ring_clk[9](dos[0] 16_lvt)"), + CLK_MSR_ID(190, "osc_ring_clk[10](dos[1] 14_rvt)"), + CLK_MSR_ID(191, "osc_ring_clk[11](ddr[0] 9t_14_lvt)"), + CLK_MSR_ID(192, "osc_ring_clk[12](top[0] 16_rvt)"), +}; + +static const struct meson_msr_id clk_msr_s7d[] = { + CLK_MSR_ID(0, "sys_clk"), + CLK_MSR_ID(1, "axi_clk"), + CLK_MSR_ID(2, "rtc_clk"), + CLK_MSR_ID(4, "mali_stack"), + CLK_MSR_ID(5, "mali"), + CLK_MSR_ID(6, "cpu_clk_div16"), + CLK_MSR_ID(8, "cecb"), + CLK_MSR_ID(9, "mali_aclkm"), + CLK_MSR_ID(10, "fclk_div5"), + CLK_MSR_ID(11, "p21_usb2_ckout"), + CLK_MSR_ID(12, "p20_usb2_ckout"), + CLK_MSR_ID(13, "eth_mpll_test"), + CLK_MSR_ID(15, "fclk_50m"), + CLK_MSR_ID(18, "gp1_pll"), + CLK_MSR_ID(19, "hifi_pll"), + CLK_MSR_ID(20, "gp0_pll"), + CLK_MSR_ID(21, "hifi1_pll"), + CLK_MSR_ID(22, "eth_mppll_50m_ckout"), + CLK_MSR_ID(23, "sys_pll_div16"), + CLK_MSR_ID(24, "ddr_dpll_pt_clk"), + CLK_MSR_ID(25, "mod_Tsin_A_CLK_IN"), + CLK_MSR_ID(26, "mod_Tsin_B_CLK_IN"), + CLK_MSR_ID(31, "earcrx_pll_clk_out"), + CLK_MSR_ID(32, "eth_125m"), + CLK_MSR_ID(33, "eth_rmii"), + CLK_MSR_ID(34, "co_clkin_to_mac"), + CLK_MSR_ID(36, "co_rx_clk"), + CLK_MSR_ID(37, "co_tx_clk"), + CLK_MSR_ID(38, "eth_phy_rxclk"), + CLK_MSR_ID(39, "eth_phy_plltxclk"), + CLK_MSR_ID(40, "ephy_test_clk"), + CLK_MSR_ID(49, "hdmi_vx1_pix_clk"), + CLK_MSR_ID(50, "vid_pll"), + CLK_MSR_ID(51, "enci"), + CLK_MSR_ID(52, "encp"), + CLK_MSR_ID(53, "encl"), + CLK_MSR_ID(54, "vdac"), + CLK_MSR_ID(55, "cdac"), + CLK_MSR_ID(57, "lcd_an_clk_ph2"), + CLK_MSR_ID(58, "lcd_an_clk_ph3"), + CLK_MSR_ID(59, "hdmitx_pixel"), + CLK_MSR_ID(60, "vdin_meas"), + CLK_MSR_ID(61, "vpu"), + CLK_MSR_ID(62, "vpu_clkb"), + CLK_MSR_ID(63, "vpu_clkb_tmp"), + CLK_MSR_ID(64, "vpu_clkc"), + CLK_MSR_ID(65, "vid_lock"), + CLK_MSR_ID(66, "vapb"), + CLK_MSR_ID(67, "ge2d"), + CLK_MSR_ID(76, "hdmitx_tmds"), + CLK_MSR_ID(77, "hdmitx_sys"), + CLK_MSR_ID(78, "hdmitx_fe"), + CLK_MSR_ID(80, "hdmitx_prif"), + CLK_MSR_ID(81, "hdmitx_200m"), + CLK_MSR_ID(82, "hdmitx_aud"), + CLK_MSR_ID(84, "audio_tohdmitx_mclk"), + CLK_MSR_ID(85, "audio_tohdmitx_bclk"), + CLK_MSR_ID(86, "audio_tohdmitx_lrclk"), + CLK_MSR_ID(87, "audio_tohdmitx_spdif_clk"), + CLK_MSR_ID(88, "htx_aes_clk"), + CLK_MSR_ID(89, "amfc"), + CLK_MSR_ID(93, "vdec"), + CLK_MSR_ID(97, "hcodec"), + CLK_MSR_ID(99, "hevcf"), + CLK_MSR_ID(106, "deskew_pll_clk_div32_out"), + CLK_MSR_ID(110, "sc"), + CLK_MSR_ID(111, "sar_adc"), + CLK_MSR_ID(112, "aux_adc_clk_to_gpio"), + CLK_MSR_ID(113, "sd_emmc_c"), + CLK_MSR_ID(114, "sd_emmc_b"), + CLK_MSR_ID(115, "sd_emmc_a"), + CLK_MSR_ID(116, "gpio_msr_clk"), + CLK_MSR_ID(117, "aux_clk_o"), + CLK_MSR_ID(118, "spicc"), + CLK_MSR_ID(121, "ts"), + CLK_MSR_ID(130, "o_vad_clk"), + CLK_MSR_ID(131, "au_dac_clk_x128"), + CLK_MSR_ID(132, "audio_locker_in_clk"), + CLK_MSR_ID(133, "audio_locker_out_clk"), + CLK_MSR_ID(134, "audio_tdmout_c_sclk"), + CLK_MSR_ID(135, "audio_tdmout_b_sclk"), + CLK_MSR_ID(136, "audio_tdmout_a_sclk"), + CLK_MSR_ID(137, "audio_tdmin_lb_sclk"), + CLK_MSR_ID(138, "audio_tdmin_c_sclk"), + CLK_MSR_ID(139, "audio_tdmin_b_sclk"), + CLK_MSR_ID(140, "audio_tdmin_a_sclk"), + CLK_MSR_ID(141, "audio_resamplea_clk"), + CLK_MSR_ID(142, "audio_pdm_sysclk"), + CLK_MSR_ID(143, "audio_spdifout_b_mst_clk"), + CLK_MSR_ID(144, "audio_spdifout_mst_clk"), + CLK_MSR_ID(145, "audio_spdifin_mst_clk"), + CLK_MSR_ID(146, "mod_audio_pdm_dclk_o"), + CLK_MSR_ID(147, "audio_resampleb_clk"), + CLK_MSR_ID(160, "pwm_j"), + CLK_MSR_ID(161, "pwm_i"), + CLK_MSR_ID(162, "pwm_h"), + CLK_MSR_ID(163, "pwm_g"), + CLK_MSR_ID(164, "pwm_f"), + CLK_MSR_ID(165, "pwm_e"), + CLK_MSR_ID(166, "pwm_d"), + CLK_MSR_ID(167, "pwm_c"), + CLK_MSR_ID(168, "pwm_b"), + CLK_MSR_ID(169, "pwm_a"), + CLK_MSR_ID(176, "rng_ring_clk[0]"), + CLK_MSR_ID(177, "rng_ring_clk[1]"), + CLK_MSR_ID(178, "rng_ring_clk[2]"), + CLK_MSR_ID(179, "rng_ring_clk[3]"), + CLK_MSR_ID(180, "osc_ring_clk[0](a55 core0 14_slvt)"), + CLK_MSR_ID(181, "osc_ring_clk[1](a55 core1 14_slvt)"), + CLK_MSR_ID(182, "osc_ring_clk[2](a55 core2 14_slvt)"), + CLK_MSR_ID(183, "osc_ring_clk[3](a55 core3 14_slvt)"), + CLK_MSR_ID(184, "osc_ring_clk[4](a55_pwr[0] 16_slvt)"), + CLK_MSR_ID(185, "osc_ring_clk[5](a55_pwr[1] 14_lvt)"), + CLK_MSR_ID(186, "osc_ring_clk[6](a55_pwr[2] 14_rvt)"), + CLK_MSR_ID(187, "osc_ring_clk[7](mali[1] 14_lvt)"), + CLK_MSR_ID(188, "osc_ring_clk[8](mali[1] 14_rvt)"), + CLK_MSR_ID(189, "osc_ring_clk[9](dos[0] 16_lvt)"), + CLK_MSR_ID(190, "osc_ring_clk[10](dos[1] 14_rvt)"), + CLK_MSR_ID(191, "osc_ring_clk[11](ddr[0] 9t_14_lvt)"), + CLK_MSR_ID(192, "osc_ring_clk[12](top[0] 16_rvt)"), +}; + static int meson_measure_id(struct meson_msr_id *clk_msr_id, unsigned int duration) { @@ -1285,6 +2122,24 @@ static const struct meson_msr_data clk_msr_a1_data = { .reg = &msr_reg_offset_v2, }; +static const struct meson_msr_data clk_msr_a4_data = { + .msr_table = (void *)clk_msr_a4, + .msr_count = ARRAY_SIZE(clk_msr_a4), + .reg = &msr_reg_offset_v2, +}; + +static const struct meson_msr_data clk_msr_a5_data = { + .msr_table = (void *)clk_msr_a5, + .msr_count = ARRAY_SIZE(clk_msr_a5), + .reg = &msr_reg_offset_v2, +}; + +static const struct meson_msr_data clk_msr_a9_data = { + .msr_table = (void *)clk_msr_a9, + .msr_count = ARRAY_SIZE(clk_msr_a9), + .reg = &msr_reg_offset_v2, +}; + static const struct meson_msr_data clk_msr_c3_data = { .msr_table = (void *)clk_msr_c3, .msr_count = ARRAY_SIZE(clk_msr_c3), @@ -1297,6 +2152,24 @@ static const struct meson_msr_data clk_msr_s4_data = { .reg = &msr_reg_offset_v2, }; +static const struct meson_msr_data clk_msr_s6_data = { + .msr_table = (void *)clk_msr_s6, + .msr_count = ARRAY_SIZE(clk_msr_s6), + .reg = &msr_reg_offset_v2, +}; + +static const struct meson_msr_data clk_msr_s7_data = { + .msr_table = (void *)clk_msr_s7, + .msr_count = ARRAY_SIZE(clk_msr_s7), + .reg = &msr_reg_offset_v2, +}; + +static const struct meson_msr_data clk_msr_s7d_data = { + .msr_table = (void *)clk_msr_s7d, + .msr_count = ARRAY_SIZE(clk_msr_s7d), + .reg = &msr_reg_offset_v2, +}; + static const struct meson_msr_data clk_msr_t7_data = { .msr_table = (void *)clk_msr_t7, .msr_count = ARRAY_SIZE(clk_msr_t7), @@ -1308,6 +2181,18 @@ static const struct of_device_id meson_msr_match_table[] = { .compatible = "amlogic,a1-clk-measure", .data = &clk_msr_a1_data, }, + { + .compatible = "amlogic,a4-clk-measure", + .data = &clk_msr_a4_data, + }, + { + .compatible = "amlogic,a5-clk-measure", + .data = &clk_msr_a5_data, + }, + { + .compatible = "amlogic,a9-clk-measure", + .data = &clk_msr_a9_data, + }, { .compatible = "amlogic,c3-clk-measure", .data = &clk_msr_c3_data, @@ -1340,6 +2225,18 @@ static const struct of_device_id meson_msr_match_table[] = { .compatible = "amlogic,s4-clk-measure", .data = &clk_msr_s4_data, }, + { + .compatible = "amlogic,s6-clk-measure", + .data = &clk_msr_s6_data, + }, + { + .compatible = "amlogic,s7-clk-measure", + .data = &clk_msr_s7_data, + }, + { + .compatible = "amlogic,s7d-clk-measure", + .data = &clk_msr_s7d_data, + }, { .compatible = "amlogic,t7-clk-measure", .data = &clk_msr_t7_data, From a848d72aab71e19ea78180f2502ad7d12818723f Mon Sep 17 00:00:00 2001 From: Chuan Liu Date: Sun, 20 Sep 2026 18:25:08 +0800 Subject: [PATCH 095/176] soc: amlogic: clk-measure: Optimize CLK_MSR_ID to reduce memory usage The original CLK_MSR_ID macro uses __id as the designated array index. This can waste memory when defining struct meson_msr_id arrays. For example: static const struct meson_msr_id clk_msr_foo[] = { CLK_MSR_ID(255, NULL), }; Although the array contains only one valid entry, it occupies space for 256 elements because the designated initializer forces the array size to match the highest index. The driver does not rely on the array index when accessing measurement IDs. Instead, the measurement ID is obtained from the id field of struct meson_msr_id. Therefore, removing the designated array index from CLK_MSR_ID does not affect the current driver behavior while significantly reducing unnecessary memory usage. Compared with before and after modification, the memory size is reduced by 24.76%: $ scripts/bloat-o-meter pre_meson-clk-measure.o meson-clk-measure.o add/remove: 0/0 grow/shrink: 0/15 up/down: 0/-16224 (-16224) Function old new delta clk_msr_sm1 3072 3048 -24 clk_msr_a1 1488 1272 -216 clk_msr_g12a 2952 2712 -240 clk_msr_gx 1992 1608 -384 clk_msr_m8 1536 1104 -432 clk_msr_a9 6120 5544 -576 clk_msr_t7 5352 4632 -720 clk_msr_axg 2640 1704 -936 clk_msr_s6 5064 3672 -1392 clk_msr_c3 4896 3264 -1632 clk_msr_s7d 4632 2880 -1752 clk_msr_s4 5376 3576 -1800 clk_msr_a4 4488 2544 -1944 clk_msr_s7 4632 2664 -1968 clk_msr_a5 4560 2352 -2208 Total: Before=65527, After=49303, chg -24.76% Signed-off-by: Chuan Liu Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20260920-more-socs-to-support-clk_measure-v2-6-224382a429e8@amlogic.com Signed-off-by: Neil Armstrong --- drivers/soc/amlogic/meson-clk-measure.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c index 50928ac14f86..33767f0bc67c 100644 --- a/drivers/soc/amlogic/meson-clk-measure.c +++ b/drivers/soc/amlogic/meson-clk-measure.c @@ -55,7 +55,7 @@ struct meson_msr { }; #define CLK_MSR_ID(__id, __name) \ - [__id] = {.id = __id, .name = __name,} + {.id = __id, .name = __name,} static const struct meson_msr_id clk_msr_m8[] = { CLK_MSR_ID(0, "ring_osc_out_ee0"), From 8d1bd7882127465b56f1157bbe48ef3375d8f2d9 Mon Sep 17 00:00:00 2001 From: Changhuang Liang Date: Wed, 30 Sep 2026 05:42:59 -0700 Subject: [PATCH 096/176] dt-bindings: clock: Add StarFive JHB100 System-0 clock and reset generator Add bindings for the System-0 clocks and reset generator (SYS0CRG) on JHB100 SoC. Signed-off-by: Changhuang Liang Reviewed-by: Rob Herring (Arm) Signed-off-by: Conor Dooley --- .../clock/starfive,jhb100-sys0crg.yaml | 63 +++++++++++++++++++ .../dt-bindings/clock/starfive,jhb100-crg.h | 56 +++++++++++++++++ .../dt-bindings/reset/starfive,jhb100-crg.h | 28 +++++++++ 3 files changed, 147 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/starfive,jhb100-sys0crg.yaml create mode 100644 include/dt-bindings/clock/starfive,jhb100-crg.h create mode 100644 include/dt-bindings/reset/starfive,jhb100-crg.h diff --git a/Documentation/devicetree/bindings/clock/starfive,jhb100-sys0crg.yaml b/Documentation/devicetree/bindings/clock/starfive,jhb100-sys0crg.yaml new file mode 100644 index 000000000000..cf1b0175b158 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/starfive,jhb100-sys0crg.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/starfive,jhb100-sys0crg.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JHB100 System-0 Clock and Reset Generator + +maintainers: + - Changhuang Liang + +properties: + compatible: + const: starfive,jhb100-sys0crg + + reg: + maxItems: 1 + + clocks: + items: + - description: Main Oscillator (25 MHz) + - description: PLL0 + - description: PLL1 + - description: PLL2 + + clock-names: + items: + - const: osc + - const: pll0 + - const: pll1 + - const: pll2 + + '#clock-cells': + const: 1 + description: + See for valid indices. + + '#reset-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + clock-controller@13000000 { + compatible = "starfive,jhb100-sys0crg"; + reg = <0x13000000 0x4000>; + clocks = <&osc>, <&pll0>, <&pll1>, + <&syspll 0>; + clock-names = "osc", "pll0", "pll1", "pll2"; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/include/dt-bindings/clock/starfive,jhb100-crg.h b/include/dt-bindings/clock/starfive,jhb100-crg.h new file mode 100644 index 000000000000..24ef2663f05a --- /dev/null +++ b/include/dt-bindings/clock/starfive,jhb100-crg.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/* + * Copyright (C) 2024 StarFive Technology Co., Ltd. + * Author: Changhuang Liang + * + */ + +#ifndef __DT_BINDINGS_CLOCK_STARFIVE_JHB100_H__ +#define __DT_BINDINGS_CLOCK_STARFIVE_JHB100_H__ + +/* SYS0CRG clocks */ +#define JHB100_SYS0CLK_BMCPCIERP_NCNOC_MAIN 17 +#define JHB100_SYS0CLK_BMCPCIERP_NCNOC_CFG 18 + +#define JHB100_SYS0CLK_PCIE_REF_CML 20 +#define JHB100_SYS0CLK_BMCPCIERP_NCNOC_DATA_INIT 21 +#define JHB100_SYS0CLK_BMCPCIERP_NCNOC_CFG_INIT 22 +#define JHB100_SYS0CLK_BMCPCIERP_NCNOC_TARG 23 + +#define JHB100_SYS0CLK_BMCPCIERP_PCU 26 +#define JHB100_SYS0CLK_HOSTSS0_NCNOC_CFG 27 +#define JHB100_SYS0CLK_HOSTSS0_NCNOC_DATA 28 +#define JHB100_SYS0CLK_HOSTSS0_PHY_SCAN_400 29 +#define JHB100_SYS0CLK_GPIO_ESPI0_EXT 30 + +#define JHB100_SYS0CLK_BMCUSB_NCNOC_INIT 34 +#define JHB100_SYS0CLK_BMCUSB_NCNOC_TARG 35 +#define JHB100_SYS0CLK_BMCUSB_SCANCLK 36 +#define JHB100_SYS0CLK_BMCUSB_480M_SCANCLK 37 + +#define JHB100_SYS0CLK_VCE_NCNOC_INIT 50 +#define JHB100_SYS0CLK_VCE_NCNOC_TARG 51 +#define JHB100_SYS0CLK_BMCPER2_NCNOC_INIT 52 +#define JHB100_SYS0CLK_BMCPER2_NCNOC_TARG 53 +#define JHB100_SYS0CLK_BMCPER2_CFG_400 54 +#define JHB100_SYS0CLK_BMCPER2_CFG_125 55 + +#define JHB100_SYS0CLK_HOSTSS1_NCNOC_DATA 58 +#define JHB100_SYS0CLK_HOSTSS1_PHY_SCAN_400 59 +#define JHB100_SYS0CLK_HOSTSS1_PHY_SCAN_400_ICG_BUF 60 +#define JHB100_SYS0CLK_NPU_NCNOC_INIT 61 +#define JHB100_SYS0CLK_VOUT_NCNOC_INIT 62 +#define JHB100_SYS0CLK_VOUT_AUX 63 + +#define JHB100_SYS0CLK_BMCPER3_NCNOC_INIT 65 +#define JHB100_SYS0CLK_HOSTUSB_NCNOC_INIT 66 +#define JHB100_SYS0CLK_HOSTUSBCMN_CFG_480 67 +#define JHB100_SYS0CLK_BMCPER1_NCNOC_INIT 68 +#define JHB100_SYS0CLK_BMCPER1_CFG_800 69 +#define JHB100_SYS0CLK_BMCPER0_NCNOC_INIT 70 +#define JHB100_SYS0CLK_BMCPER0_CFG_400 71 +#define JHB100_SYS0CLK_BMCPER0_CFG_800 72 +#define JHB100_SYS0CLK_GPU0_NCNOC_INIT 73 +#define JHB100_SYS0CLK_GPU1_NCNOC_INIT 74 + +#endif /* __DT_BINDINGS_CLOCK_STARFIVE_JHB100_H__ */ diff --git a/include/dt-bindings/reset/starfive,jhb100-crg.h b/include/dt-bindings/reset/starfive,jhb100-crg.h new file mode 100644 index 000000000000..5c7b00afda73 --- /dev/null +++ b/include/dt-bindings/reset/starfive,jhb100-crg.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/* + * Copyright (C) 2024 StarFive Technology Co., Ltd. + * Author: Changhuang Liang + * + */ + +#ifndef __DT_BINDINGS_RESET_STARFIVE_JHB100_CRG_H__ +#define __DT_BINDINGS_RESET_STARFIVE_JHB100_CRG_H__ + +/* SYS0CRG resets */ +#define JHB100_SYS0RST_RESOURCE_ARB 0 +#define JHB100_SYS0RST_SYS0_IOMUX_PRESETN 1 +#define JHB100_SYS0RST_SYS0H_IOMUX_PRESETN 2 +#define JHB100_SYS0RST_RST_ADAPTOR_TIMEOUT_RSTN 3 +#define JHB100_SYS0RST_BMCPCIERP_RSTN_BUS 4 +#define JHB100_SYS0RST_BMCPCIERP_RSTN_CRG 5 +#define JHB100_SYS0RST_HOSTSS0_RSTN_BUS_ESPI 6 +#define JHB100_SYS0RST_HOSTSS0_RSTN_BUS_PCIE 7 +#define JHB100_SYS0RST_HOSTSS0_RSTN_CRG 8 +#define JHB100_SYS0RST_BMCPERIPH2_RSTN_CRG 9 +#define JHB100_SYS0RST_BMCPERIPH2_RSTN_BUS 10 +#define JHB100_SYS0RST_VCE_RSTN_CRG 11 +#define JHB100_SYS0RST_VCE_RSTN_BUS 12 +#define JHB100_SYS0RST_BMCUSB_RSTN_BUS 13 +#define JHB100_SYS0RST_BMCUSB_RSTN_CRG 14 + +#endif /* __DT_BINDINGS_RESET_STARFIVE_JHB100_CRG_H__ */ From 2bb7b7f56c5b679c3c31aca4f7de6d62fa3dd263 Mon Sep 17 00:00:00 2001 From: Changhuang Liang Date: Wed, 30 Sep 2026 05:43:01 -0700 Subject: [PATCH 097/176] dt-bindings: clock: Add StarFive JHB100 System-1 clock and reset generator Add bindings for the System-1 clocks and reset generator (SYS1CRG) on JHB100 SoC. Signed-off-by: Changhuang Liang Reviewed-by: Rob Herring (Arm) Signed-off-by: Conor Dooley --- .../clock/starfive,jhb100-sys1crg.yaml | 71 +++++++++++++++++++ .../dt-bindings/clock/starfive,jhb100-crg.h | 20 ++++++ .../dt-bindings/reset/starfive,jhb100-crg.h | 11 +++ 3 files changed, 102 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/starfive,jhb100-sys1crg.yaml diff --git a/Documentation/devicetree/bindings/clock/starfive,jhb100-sys1crg.yaml b/Documentation/devicetree/bindings/clock/starfive,jhb100-sys1crg.yaml new file mode 100644 index 000000000000..70cbfa38c100 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/starfive,jhb100-sys1crg.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/starfive,jhb100-sys1crg.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JHB100 System-1 Clock and Reset Generator + +maintainers: + - Changhuang Liang + +properties: + compatible: + const: starfive,jhb100-sys1crg + + reg: + maxItems: 1 + + clocks: + items: + - description: Main Oscillator (25 MHz) + - description: PLL0 + - description: PLL1 + - description: PLL2 + - description: PLL4 + - description: PLL5 + - description: NPU Non Coherent NOC Initiator + + clock-names: + items: + - const: osc + - const: pll0 + - const: pll1 + - const: pll2 + - const: pll4 + - const: pll5 + - const: npu_ncnoc_init + + '#clock-cells': + const: 1 + description: + See for valid indices. + + '#reset-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + clock-controller@13004000 { + compatible = "starfive,jhb100-sys1crg"; + reg = <0x13004000 0x4000>; + clocks = <&osc>, <&pll0>, <&pll1>, + <&syspll 0>, <&syspll 2>, + <&syspll 3>, <&sys0crg 61>; + clock-names = "osc", "pll0", "pll1", "pll2", + "pll4", "pll5", "npu_ncnoc_init"; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/include/dt-bindings/clock/starfive,jhb100-crg.h b/include/dt-bindings/clock/starfive,jhb100-crg.h index 24ef2663f05a..d7904b32bd51 100644 --- a/include/dt-bindings/clock/starfive,jhb100-crg.h +++ b/include/dt-bindings/clock/starfive,jhb100-crg.h @@ -53,4 +53,24 @@ #define JHB100_SYS0CLK_GPU0_NCNOC_INIT 73 #define JHB100_SYS0CLK_GPU1_NCNOC_INIT 74 +/* SYS1CRG clocks */ +#define JHB100_SYS1CLK_APB_MAIN_SYS1 0 +#define JHB100_SYS1CLK_APB_SENSOR_ICG_BUF 1 + +#define JHB100_SYS1CLK_GPIO_ESPI1_EXT 5 + +#define JHB100_SYS1CLK_HOSTSS1_NCNOC_CFG 7 +#define JHB100_SYS1CLK_HOSTSS1_PHY_SCAN_1000_ICG_BUF 8 +#define JHB100_SYS1CLK_NPU_NCNOC_CFG 9 +#define JHB100_SYS1CLK_NPU_CORE_DIV 10 +#define JHB100_SYS1CLK_DOM_NPU_CORE_CLK 11 +#define JHB100_SYS1CLK_DOM_NPU_BUS_CLK 12 +#define JHB100_SYS1CLK_DOM_NPU_INIT_CLK 13 +#define JHB100_SYS1CLK_DOM_NPU_OSC_CLK 14 +#define JHB100_SYS1CLK_VOUT_NCNOC_TARG 15 +#define JHB100_SYS1CLK_VOUT_PIX0 16 +#define JHB100_SYS1CLK_VOUT_PIX1 17 +#define JHB100_SYS1CLK_BMCPER3_NCNOC_TARG 18 +#define JHB100_SYS1CLK_BMCPER3_CFG_125 19 + #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JHB100_H__ */ diff --git a/include/dt-bindings/reset/starfive,jhb100-crg.h b/include/dt-bindings/reset/starfive,jhb100-crg.h index 5c7b00afda73..da1b51621172 100644 --- a/include/dt-bindings/reset/starfive,jhb100-crg.h +++ b/include/dt-bindings/reset/starfive,jhb100-crg.h @@ -25,4 +25,15 @@ #define JHB100_SYS0RST_BMCUSB_RSTN_BUS 13 #define JHB100_SYS0RST_BMCUSB_RSTN_CRG 14 +/* SYS1CRG resets */ +#define JHB100_SYS1RST_SYS1_IOMUX_PRESETN 0 +#define JHB100_SYS1RST_MAIN_RSTN_CHIPTOP_SENSOR 1 +#define JHB100_SYS1RST_VOUT_RSTN_HOST0 2 +#define JHB100_SYS1RST_VOUT_RSTN_HOST1 3 +#define JHB100_SYS1RST_HOSTSS1_RSTN_BUS_ESPI 4 +#define JHB100_SYS1RST_HOSTSS1_RSTN_BUS_PCIE 5 +#define JHB100_SYS1RST_HOSTSS1_RSTN_CRG 6 +#define JHB100_SYS1RST_BMCPERIPH3_RSTN_CRG 7 +#define JHB100_SYS1RST_BMCPERIPH3_RSTN_BUS 8 + #endif /* __DT_BINDINGS_RESET_STARFIVE_JHB100_CRG_H__ */ From 59e04d1e99361ceeb2dd474a6a66f8cd9937d3d2 Mon Sep 17 00:00:00 2001 From: Changhuang Liang Date: Wed, 30 Sep 2026 05:43:03 -0700 Subject: [PATCH 098/176] dt-bindings: clock: Add StarFive JHB100 System-2 clock and reset generator Add bindings for the System-2 clocks and reset generator (SYS2CRG) on JHB100 SoC. Signed-off-by: Changhuang Liang Reviewed-by: Rob Herring (Arm) Signed-off-by: Conor Dooley --- .../clock/starfive,jhb100-sys2crg.yaml | 64 +++++++++++++++++++ .../dt-bindings/clock/starfive,jhb100-crg.h | 33 ++++++++++ .../dt-bindings/reset/starfive,jhb100-crg.h | 25 ++++++++ 3 files changed, 122 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/starfive,jhb100-sys2crg.yaml diff --git a/Documentation/devicetree/bindings/clock/starfive,jhb100-sys2crg.yaml b/Documentation/devicetree/bindings/clock/starfive,jhb100-sys2crg.yaml new file mode 100644 index 000000000000..a63809c72e2a --- /dev/null +++ b/Documentation/devicetree/bindings/clock/starfive,jhb100-sys2crg.yaml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/starfive,jhb100-sys2crg.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JHB100 System-2 Clock and Reset Generator + +maintainers: + - Changhuang Liang + +properties: + compatible: + const: starfive,jhb100-sys2crg + + reg: + maxItems: 1 + + clocks: + items: + - description: Main Oscillator (25 MHz) + - description: PLL1 + - description: GPU0 Non Coherent NOC Initiator + - description: GPU1 Non Coherent NOC Initiator + + clock-names: + items: + - const: osc + - const: pll1 + - const: gpu0_ncnoc_init + - const: gpu1_ncnoc_init + + '#clock-cells': + const: 1 + description: + See for valid indices. + + '#reset-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + clock-controller@13008000 { + compatible = "starfive,jhb100-sys2crg"; + reg = <0x13008000 0x4000>; + clocks = <&osc>, <&pll1>, <&sys0crg 73>, + <&sys0crg 74>; + clock-names = "osc", "pll1", "gpu0_ncnoc_init", + "gpu1_ncnoc_init"; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/include/dt-bindings/clock/starfive,jhb100-crg.h b/include/dt-bindings/clock/starfive,jhb100-crg.h index d7904b32bd51..d19618e2a846 100644 --- a/include/dt-bindings/clock/starfive,jhb100-crg.h +++ b/include/dt-bindings/clock/starfive,jhb100-crg.h @@ -73,4 +73,37 @@ #define JHB100_SYS1CLK_BMCPER3_NCNOC_TARG 18 #define JHB100_SYS1CLK_BMCPER3_CFG_125 19 +/* SYS2CRG clocks */ +#define JHB100_SYS2CLK_JTAGM0_HCLK 3 +#define JHB100_SYS2CLK_JTAGM1_HCLK 4 +#define JHB100_SYS2CLK_JTAGM0_ATPG 5 +#define JHB100_SYS2CLK_JTAGM1_ATPG 6 +#define JHB100_SYS2CLK_JTAGM0_ATPG_TCLOCK 7 +#define JHB100_SYS2CLK_JTAGM1_ATPG_TCLOCK 8 +#define JHB100_SYS2CLK_JTAG0_MST_WRAP_HCLK 9 +#define JHB100_SYS2CLK_JTAG0_MST_WRAP_CLK_JTAG 10 +#define JHB100_SYS2CLK_JTAG0_MST_WRAP_APB_PCLK 11 +#define JHB100_SYS2CLK_JTAG0_MST_WRAP_ATPG_TCLOCK 12 +#define JHB100_SYS2CLK_JTAG1_MST_WRAP_HCLK 13 +#define JHB100_SYS2CLK_JTAG1_MST_WRAP_CLK_JTAG 14 +#define JHB100_SYS2CLK_JTAG1_MST_WRAP_APB_PCLK 15 +#define JHB100_SYS2CLK_JTAG1_MST_WRAP_ATPG_TCLOCK 16 +#define JHB100_SYS2CLK_HOSTUSB_NCNOC_TARG 17 +#define JHB100_SYS2CLK_HOSTUSBCMN_CFG_500 18 +#define JHB100_SYS2CLK_BMCPER1_NCNOC_TARG 19 +#define JHB100_SYS2CLK_BMCPER1_CFG_250 20 +#define JHB100_SYS2CLK_BMCPER1_CFG_143_DFT 21 +#define JHB100_SYS2CLK_BMCPER1_CFG_143 22 +#define JHB100_SYS2CLK_BMCPER0_NCNOC_TARG 23 +#define JHB100_SYS2CLK_GPU0_NCNOC_TARG 24 +#define JHB100_SYS2CLK_GPU0_BUS_CLK 25 +#define JHB100_SYS2CLK_GPU0_APB_CLK 26 +#define JHB100_SYS2CLK_GPU0_OSC_CLK 27 +#define JHB100_SYS2CLK_GPU1_NCNOC_TARG 28 +#define JHB100_SYS2CLK_GPU1_BUS_CLK 29 +#define JHB100_SYS2CLK_GPU1_APB_CLK 30 +#define JHB100_SYS2CLK_GPU1_OSC_CLK 31 +#define JHB100_SYS2CLK_MAIN_ICG_EN_JTAG0 32 +#define JHB100_SYS2CLK_MAIN_ICG_EN_JTAG1 33 + #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JHB100_H__ */ diff --git a/include/dt-bindings/reset/starfive,jhb100-crg.h b/include/dt-bindings/reset/starfive,jhb100-crg.h index da1b51621172..fbc55f95e76c 100644 --- a/include/dt-bindings/reset/starfive,jhb100-crg.h +++ b/include/dt-bindings/reset/starfive,jhb100-crg.h @@ -36,4 +36,29 @@ #define JHB100_SYS1RST_BMCPERIPH3_RSTN_CRG 7 #define JHB100_SYS1RST_BMCPERIPH3_RSTN_BUS 8 +/* SYS2CRG resets */ +#define JHB100_SYS2RST_JTAG0_MST_WRAP_HRESETN 0 +#define JHB100_SYS2RST_JTAG0_MST_WRAP_APB_PRESETN 1 +#define JHB100_SYS2RST_JTAG1_MST_WRAP_HRESETN 2 +#define JHB100_SYS2RST_JTAG1_MST_WRAP_APB_PRESETN 3 +#define JHB100_SYS2RST_HUSBCMN_HOSTCMN_RSTN_BUS_NCNOC_INIT 4 +#define JHB100_SYS2RST_HUSBCMN_RSTN_HOSTCMN_CRG 5 +#define JHB100_SYS2RST_HUSBCMN_HOSTUSB0_RSTN_BUS_NCNOC_BMC_TARG 6 +#define JHB100_SYS2RST_HUSBCMN_HOSTUSB0_RSTN_BUS_NCNOC_HOST_TARG 7 +#define JHB100_SYS2RST_HUSBCMN_RSTN_BMC_CRG 8 +#define JHB100_SYS2RST_HUSBCMN_RSTN_HOSTUSB0_CRG 9 +#define JHB100_SYS2RST_HUSBCMN_HOSTUSB1_RSTN_BUS_NCNOC_BMC_TARG 10 +#define JHB100_SYS2RST_HUSBCMN_HOSTUSB1_RSTN_BUS_NCNOC_HOST_TARG 11 +#define JHB100_SYS2RST_HUSBCMN_RSTN_HOSTUSB1_CRG 12 +#define JHB100_SYS2RST_BMCPERIPH1_RSTN_CRG 13 +#define JHB100_SYS2RST_BMCPERIPH1_RSTN_BUS 14 +#define JHB100_SYS2RST_BMCPERIPH0_RSTN_CRG 15 +#define JHB100_SYS2RST_BMCPERIPH0_RSTN_BUS 16 +#define JHB100_SYS2RST_GPU0_RSTN_CRG 17 +#define JHB100_SYS2RST_GPU0_RSTN_BUS 18 +#define JHB100_SYS2RST_GPU0_HOST_PCIE_RST_N 19 +#define JHB100_SYS2RST_GPU1_RSTN_CRG 20 +#define JHB100_SYS2RST_GPU1_RSTN_BUS 21 +#define JHB100_SYS2RST_GPU1_HOST_PCIE_RST_N 22 + #endif /* __DT_BINDINGS_RESET_STARFIVE_JHB100_CRG_H__ */ From 412d6e358eec72bd5227e4fd4a5af9461e695fbf Mon Sep 17 00:00:00 2001 From: Changhuang Liang Date: Wed, 30 Sep 2026 05:43:05 -0700 Subject: [PATCH 099/176] dt-bindings: clock: Add StarFive JHB100 Peripheral-0 clock and reset generator Add bindings for the Peripheral-0 clock and reset generator (PER0CRG) on the JHB100 RISC-V SoC by StarFive Ltd. Signed-off-by: Changhuang Liang Reviewed-by: Rob Herring (Arm) Signed-off-by: Conor Dooley --- .../clock/starfive,jhb100-per0crg.yaml | 70 +++++ .../dt-bindings/clock/starfive,jhb100-crg.h | 281 ++++++++++++++++++ .../dt-bindings/reset/starfive,jhb100-crg.h | 77 +++++ 3 files changed, 428 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/starfive,jhb100-per0crg.yaml diff --git a/Documentation/devicetree/bindings/clock/starfive,jhb100-per0crg.yaml b/Documentation/devicetree/bindings/clock/starfive,jhb100-per0crg.yaml new file mode 100644 index 000000000000..db43e03fd60c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/starfive,jhb100-per0crg.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/starfive,jhb100-per0crg.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JHB100 Peripheral-0 Clock and Reset Generator + +maintainers: + - Changhuang Liang + +properties: + compatible: + const: starfive,jhb100-per0crg + + reg: + maxItems: 1 + + clocks: + items: + - description: Main Oscillator (25 MHz) + - description: PLL6 + - description: Configure 400MHz + - description: Configure 800MHZ + - description: Non Coherent NOC Initiator + - description: Non Coherent NOC Target + + clock-names: + items: + - const: osc + - const: pll6 + - const: cfg_400 + - const: cfg_800 + - const: ncnoc_init + - const: ncnoc_targ + + '#clock-cells': + const: 1 + description: + See for valid indices. + + '#reset-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + clock-controller@11a08000 { + compatible = "starfive,jhb100-per0crg"; + reg = <0x11a08000 0x1000>; + clocks = <&osc>, <&pll6>, <&sys0crg 71>, + <&sys0crg 72>, <&sys0crg 70>, + <&sys2crg 23>; + clock-names = "osc", "pll6", "cfg_400", + "cfg_800", "ncnoc_init", + "ncnoc_targ"; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/include/dt-bindings/clock/starfive,jhb100-crg.h b/include/dt-bindings/clock/starfive,jhb100-crg.h index d19618e2a846..add2cd093dbd 100644 --- a/include/dt-bindings/clock/starfive,jhb100-crg.h +++ b/include/dt-bindings/clock/starfive,jhb100-crg.h @@ -106,4 +106,285 @@ #define JHB100_SYS2CLK_MAIN_ICG_EN_JTAG0 32 #define JHB100_SYS2CLK_MAIN_ICG_EN_JTAG1 33 +/* PER0CRG clocks */ +#define JHB100_PER0CLK_CDR_I3C0 0 +#define JHB100_PER0CLK_CDR_I3C1 1 +#define JHB100_PER0CLK_CDR_I3C2 2 +#define JHB100_PER0CLK_CDR_I3C3 3 +#define JHB100_PER0CLK_CDR_I3C4 4 +#define JHB100_PER0CLK_CDR_I3C5 5 +#define JHB100_PER0CLK_CDR_I3C6 6 +#define JHB100_PER0CLK_CDR_I3C7 7 +#define JHB100_PER0CLK_CDR_I3C8 8 +#define JHB100_PER0CLK_CDR_I3C9 9 +#define JHB100_PER0CLK_CDR_I3C10 10 +#define JHB100_PER0CLK_CDR_I3C11 11 +#define JHB100_PER0CLK_CDR_I3C12 12 +#define JHB100_PER0CLK_CDR_I3C13 13 +#define JHB100_PER0CLK_CDR_I3C14 14 +#define JHB100_PER0CLK_CDR_I3C15 15 +#define JHB100_PER0CLK_200 16 +#define JHB100_PER0CLK_600_DIV6 17 +#define JHB100_PER0CLK_600_DIV6_DIV5 18 +#define JHB100_PER0CLK_TIMER0_DUALTIMER0 19 +#define JHB100_PER0CLK_TIMER1_DUALTIMER0 20 +#define JHB100_PER0CLK_TIMER0_DUALTIMER1 21 +#define JHB100_PER0CLK_TIMER1_DUALTIMER1 22 +#define JHB100_PER0CLK_TIMER0_DUALTIMER2 23 +#define JHB100_PER0CLK_TIMER1_DUALTIMER2 24 +#define JHB100_PER0CLK_1200_PH0_LVDS0 25 +#define JHB100_PER0CLK_1200_PH0_LVDS1 26 +#define JHB100_PER0CLK_1200_CORE0 27 +#define JHB100_PER0CLK_1200_CORE1 28 +#define JHB100_PER0CLK_1200_SHIFT90_LVDS0 29 +#define JHB100_PER0CLK_1200_SHIFT90_LVDS1 30 +#define JHB100_PER0CLK_1200_DIV5_CORE0 31 +#define JHB100_PER0CLK_1200_DIV5_CORE1 32 +#define JHB100_PER0CLK_PH0_LTPI0 33 + +#define JHB100_PER0CLK_PH0_LTPI1 35 + +#define JHB100_PER0CLK_PH90_LTPI0 37 + +#define JHB100_PER0CLK_PH90_LTPI1 39 + +#define JHB100_PER0CLK_240_CORE_LTPI0 41 + +#define JHB100_PER0CLK_240_CORE_LTPI1 43 + +#define JHB100_PER0CLK_AXI_DMA_I2C_INIT 45 +#define JHB100_PER0CLK_AXI_DMA_I3C_INIT 46 +#define JHB100_PER0CLK_AXI_DMA_UART_INIT 47 +#define JHB100_PER0CLK_CORE_DMAC0 48 +#define JHB100_PER0CLK_CORE_DMAC1 49 +#define JHB100_PER0CLK_CORE_DMAC2 50 + +#define JHB100_PER0CLK_HDR_TX_I3C0 78 +#define JHB100_PER0CLK_HDR_TX_I3C1 79 +#define JHB100_PER0CLK_HDR_TX_I3C2 80 +#define JHB100_PER0CLK_HDR_TX_I3C3 81 +#define JHB100_PER0CLK_HDR_TX_I3C4 82 +#define JHB100_PER0CLK_HDR_TX_I3C5 83 +#define JHB100_PER0CLK_HDR_TX_I3C6 84 +#define JHB100_PER0CLK_HDR_TX_I3C7 85 +#define JHB100_PER0CLK_HDR_TX_I3C8 86 +#define JHB100_PER0CLK_HDR_TX_I3C9 87 +#define JHB100_PER0CLK_HDR_TX_I3C10 88 +#define JHB100_PER0CLK_HDR_TX_I3C11 89 +#define JHB100_PER0CLK_HDR_TX_I3C12 90 +#define JHB100_PER0CLK_HDR_TX_I3C13 91 +#define JHB100_PER0CLK_HDR_TX_I3C14 92 +#define JHB100_PER0CLK_HDR_TX_I3C15 93 +#define JHB100_PER0CLK_CORE_I2C0 94 +#define JHB100_PER0CLK_CORE_I2C1 95 +#define JHB100_PER0CLK_CORE_I2C2 96 +#define JHB100_PER0CLK_CORE_I2C3 97 +#define JHB100_PER0CLK_CORE_I2C4 98 +#define JHB100_PER0CLK_CORE_I2C5 99 +#define JHB100_PER0CLK_CORE_I2C6 100 +#define JHB100_PER0CLK_CORE_I2C7 101 +#define JHB100_PER0CLK_CORE_I2C8 102 +#define JHB100_PER0CLK_CORE_I2C9 103 +#define JHB100_PER0CLK_CORE_I2C10 104 +#define JHB100_PER0CLK_CORE_I2C11 105 +#define JHB100_PER0CLK_CORE_I2C12 106 +#define JHB100_PER0CLK_CORE_I2C13 107 +#define JHB100_PER0CLK_CORE_I2C14 108 +#define JHB100_PER0CLK_CORE_I2C15 109 + +#define JHB100_PER0CLK_WDOGCLK_WDT0 126 +#define JHB100_PER0CLK_WDOGCLK_WDT1 127 +#define JHB100_PER0CLK_WDOGCLK_WDT2 128 +#define JHB100_PER0CLK_WDOGCLK_WDT3 129 +#define JHB100_PER0CLK_WDOGCLK_WDT_EXTERNAL 130 +#define JHB100_PER0CLK_SCLK_UART4 131 +#define JHB100_PER0CLK_SCLK_UART5 132 +#define JHB100_PER0CLK_SCLK_UART6 133 +#define JHB100_PER0CLK_SCLK_UART7 134 +#define JHB100_PER0CLK_SCLK_UART8 135 +#define JHB100_PER0CLK_SCLK_UART9 136 +#define JHB100_PER0CLK_SCLK_UART10 137 +#define JHB100_PER0CLK_SCLK_UART11 138 +#define JHB100_PER0CLK_SCLK_UART12 139 +#define JHB100_PER0CLK_SCLK_UART13 140 +#define JHB100_PER0CLK_SCLK_UART14 141 + +#define JHB100_PER0CLK_PCLK_DMA_UART_CFG 148 +#define JHB100_PER0CLK_PCLK_DMA_I2C_CFG 149 +#define JHB100_PER0CLK_PCLK_DMA_I3C_CFG 150 +#define JHB100_PER0CLK_PCLK_DUALTIMER0 151 +#define JHB100_PER0CLK_PCLK_DUALTIMER1 152 +#define JHB100_PER0CLK_PCLK_DUALTIMER2 153 + +#define JHB100_PER0CLK_HCLK_TRNG 156 +#define JHB100_PER0CLK_APB_I2C0 157 +#define JHB100_PER0CLK_APB_I2C1 158 +#define JHB100_PER0CLK_APB_I2C2 159 +#define JHB100_PER0CLK_APB_I2C3 160 +#define JHB100_PER0CLK_APB_I2C4 161 +#define JHB100_PER0CLK_APB_I2C5 162 +#define JHB100_PER0CLK_APB_I2C6 163 +#define JHB100_PER0CLK_APB_I2C7 164 +#define JHB100_PER0CLK_APB_I2C8 165 +#define JHB100_PER0CLK_APB_I2C9 166 +#define JHB100_PER0CLK_APB_I2C10 167 +#define JHB100_PER0CLK_APB_I2C11 168 +#define JHB100_PER0CLK_APB_I2C12 169 +#define JHB100_PER0CLK_APB_I2C13 170 +#define JHB100_PER0CLK_APB_I2C14 171 +#define JHB100_PER0CLK_APB_I2C15 172 +#define JHB100_PER0CLK_APB_I2CF0 173 +#define JHB100_PER0CLK_APB_I2CF1 174 +#define JHB100_PER0CLK_APB_I2CF2 175 +#define JHB100_PER0CLK_APB_I2CF3 176 +#define JHB100_PER0CLK_APB_I2CF4 177 +#define JHB100_PER0CLK_APB_I2CF5 178 +#define JHB100_PER0CLK_APB_I2CF6 179 +#define JHB100_PER0CLK_APB_I2CF7 180 +#define JHB100_PER0CLK_APB_I2CF8 181 +#define JHB100_PER0CLK_APB_I2CF9 182 +#define JHB100_PER0CLK_APB_I2CF10 183 +#define JHB100_PER0CLK_APB_I2CF11 184 +#define JHB100_PER0CLK_APB_I2CF12 185 +#define JHB100_PER0CLK_APB_I2CF13 186 +#define JHB100_PER0CLK_APB_I2CF14 187 +#define JHB100_PER0CLK_APB_I2CF15 188 +#define JHB100_PER0CLK_APB_I3C0 189 +#define JHB100_PER0CLK_APB_I3C1 190 +#define JHB100_PER0CLK_APB_I3C2 191 +#define JHB100_PER0CLK_APB_I3C3 192 +#define JHB100_PER0CLK_APB_I3C4 193 +#define JHB100_PER0CLK_APB_I3C5 194 +#define JHB100_PER0CLK_APB_I3C6 195 +#define JHB100_PER0CLK_APB_I3C7 196 +#define JHB100_PER0CLK_APB_I3C8 197 +#define JHB100_PER0CLK_APB_I3C9 198 +#define JHB100_PER0CLK_APB_I3C10 199 +#define JHB100_PER0CLK_APB_I3C11 200 +#define JHB100_PER0CLK_APB_I3C12 201 +#define JHB100_PER0CLK_APB_I3C13 202 +#define JHB100_PER0CLK_APB_I3C14 203 +#define JHB100_PER0CLK_APB_I3C15 204 +#define JHB100_PER0CLK_APB_UART0 205 +#define JHB100_PER0CLK_APB_UART1 206 +#define JHB100_PER0CLK_APB_UART2 207 +#define JHB100_PER0CLK_APB_UART3 208 +#define JHB100_PER0CLK_APB_UART4 209 +#define JHB100_PER0CLK_APB_UART5 210 +#define JHB100_PER0CLK_APB_UART6 211 +#define JHB100_PER0CLK_APB_UART7 212 +#define JHB100_PER0CLK_APB_UART8 213 +#define JHB100_PER0CLK_APB_UART9 214 +#define JHB100_PER0CLK_APB_UART10 215 +#define JHB100_PER0CLK_APB_UART11 216 +#define JHB100_PER0CLK_APB_UART12 217 +#define JHB100_PER0CLK_APB_UART13 218 +#define JHB100_PER0CLK_APB_UART14 219 +#define JHB100_PER0CLK_DMA_I3C0 220 +#define JHB100_PER0CLK_DMA_I3C1 221 +#define JHB100_PER0CLK_DMA_I3C2 222 +#define JHB100_PER0CLK_DMA_I3C3 223 +#define JHB100_PER0CLK_DMA_I3C4 224 +#define JHB100_PER0CLK_DMA_I3C5 225 +#define JHB100_PER0CLK_DMA_I3C6 226 +#define JHB100_PER0CLK_DMA_I3C7 227 +#define JHB100_PER0CLK_DMA_I3C8 228 +#define JHB100_PER0CLK_DMA_I3C9 229 +#define JHB100_PER0CLK_DMA_I3C10 230 +#define JHB100_PER0CLK_DMA_I3C11 231 +#define JHB100_PER0CLK_DMA_I3C12 232 +#define JHB100_PER0CLK_DMA_I3C13 233 +#define JHB100_PER0CLK_DMA_I3C14 234 +#define JHB100_PER0CLK_DMA_I3C15 235 +#define JHB100_PER0CLK_CORE_I3C0 236 +#define JHB100_PER0CLK_CORE_I3C1 237 +#define JHB100_PER0CLK_CORE_I3C2 238 +#define JHB100_PER0CLK_CORE_I3C3 239 +#define JHB100_PER0CLK_CORE_I3C4 240 +#define JHB100_PER0CLK_CORE_I3C5 241 +#define JHB100_PER0CLK_CORE_I3C6 242 +#define JHB100_PER0CLK_CORE_I3C7 243 +#define JHB100_PER0CLK_CORE_I3C8 244 +#define JHB100_PER0CLK_CORE_I3C9 245 +#define JHB100_PER0CLK_CORE_I3C10 246 +#define JHB100_PER0CLK_CORE_I3C11 247 +#define JHB100_PER0CLK_CORE_I3C12 248 +#define JHB100_PER0CLK_CORE_I3C13 249 +#define JHB100_PER0CLK_CORE_I3C14 250 +#define JHB100_PER0CLK_CORE_I3C15 251 +#define JHB100_PER0CLK_DMAC_AXI_PERIPH0_HS_CLK_I2C 252 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C0 253 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C1 254 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C2 255 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C3 256 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C4 257 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C5 258 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C6 259 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C7 260 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C8 261 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C9 262 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C10 263 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C11 264 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C12 265 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C13 266 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C14 267 +#define JHB100_PER0CLK_MAIN_ICG_EN_I3C15 268 +#define JHB100_PER0CLK_MAIN_ICG_EN_DUALTIMER0 269 +#define JHB100_PER0CLK_MAIN_ICG_EN_DUALTIMER1 270 +#define JHB100_PER0CLK_MAIN_ICG_EN_DUALTIMER2 271 +#define JHB100_PER0CLK_MAIN_ICG_EN_LTPI0 272 +#define JHB100_PER0CLK_MAIN_ICG_EN_LTPI1 273 +#define JHB100_PER0CLK_MAIN_ICG_EN_DMAC_I2C 274 +#define JHB100_PER0CLK_MAIN_ICG_EN_DMAC_I3C 275 +#define JHB100_PER0CLK_MAIN_ICG_EN_DMAC_UART 276 +#define JHB100_PER0CLK_MAIN_ICG_EN_SOL4 277 +#define JHB100_PER0CLK_MAIN_ICG_EN_SOL5 278 +#define JHB100_PER0CLK_MAIN_ICG_EN_SOL6 279 +#define JHB100_PER0CLK_MAIN_ICG_EN_SOL7 280 +#define JHB100_PER0CLK_MAIN_ICG_EN_SOL8 281 +#define JHB100_PER0CLK_MAIN_ICG_EN_SOL9 282 +#define JHB100_PER0CLK_MAIN_ICG_EN_SOL10 283 +#define JHB100_PER0CLK_MAIN_ICG_EN_SOL11 284 +#define JHB100_PER0CLK_MAIN_ICG_EN_SOL12 285 +#define JHB100_PER0CLK_MAIN_ICG_EN_SOL13 286 +#define JHB100_PER0CLK_MAIN_ICG_EN_SOL14 287 + +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C0 304 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C1 305 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C2 306 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C3 307 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C4 308 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C5 309 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C6 310 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C7 311 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C8 312 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C9 313 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C10 314 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C11 315 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C12 316 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C13 317 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C14 318 +#define JHB100_PER0CLK_MAIN_ICG_EN_I2C15 319 +#define JHB100_PER0CLK_MAIN_ICG_EN_WDT0 320 +#define JHB100_PER0CLK_MAIN_ICG_EN_WDT1 321 +#define JHB100_PER0CLK_MAIN_ICG_EN_WDT2 322 +#define JHB100_PER0CLK_MAIN_ICG_EN_WDT3 323 +#define JHB100_PER0CLK_MAIN_ICG_EN_WDT_EXTERNAL 324 +#define JHB100_PER0CLK_MAIN_ICG_EN_UART4 325 +#define JHB100_PER0CLK_MAIN_ICG_EN_UART5 326 +#define JHB100_PER0CLK_MAIN_ICG_EN_UART6 327 +#define JHB100_PER0CLK_MAIN_ICG_EN_UART7 328 +#define JHB100_PER0CLK_MAIN_ICG_EN_UART8 329 +#define JHB100_PER0CLK_MAIN_ICG_EN_UART9 330 +#define JHB100_PER0CLK_MAIN_ICG_EN_UART10 331 +#define JHB100_PER0CLK_MAIN_ICG_EN_UART11 332 +#define JHB100_PER0CLK_MAIN_ICG_EN_UART12 333 +#define JHB100_PER0CLK_MAIN_ICG_EN_UART13 334 +#define JHB100_PER0CLK_MAIN_ICG_EN_UART14 335 +#define JHB100_PER0CLK_MAIN_ICG_EN_LDO0 336 +#define JHB100_PER0CLK_MAIN_ICG_EN_LDO1 337 +#define JHB100_PER0CLK_MAIN_ICG_EN_SENSORS_PERIPH0 338 +#define JHB100_PER0CLK_MAIN_ICG_EN_SENSORS_DMAC 339 +#define JHB100_PER0CLK_MAIN_ICG_EN_TRNG 340 + #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JHB100_H__ */ diff --git a/include/dt-bindings/reset/starfive,jhb100-crg.h b/include/dt-bindings/reset/starfive,jhb100-crg.h index fbc55f95e76c..ccfb7616e1a7 100644 --- a/include/dt-bindings/reset/starfive,jhb100-crg.h +++ b/include/dt-bindings/reset/starfive,jhb100-crg.h @@ -61,4 +61,81 @@ #define JHB100_SYS2RST_GPU1_RSTN_BUS 21 #define JHB100_SYS2RST_GPU1_HOST_PCIE_RST_N 22 +/* PER0CRG resets */ +#define JHB100_PER0RST_MAIN_RSTN_UART4 0 +#define JHB100_PER0RST_MAIN_RSTN_UART5 1 +#define JHB100_PER0RST_MAIN_RSTN_UART6 2 +#define JHB100_PER0RST_MAIN_RSTN_UART7 3 +#define JHB100_PER0RST_MAIN_RSTN_UART8 4 +#define JHB100_PER0RST_MAIN_RSTN_UART9 5 +#define JHB100_PER0RST_MAIN_RSTN_UART10 6 +#define JHB100_PER0RST_MAIN_RSTN_UART11 7 +#define JHB100_PER0RST_MAIN_RSTN_UART12 8 +#define JHB100_PER0RST_MAIN_RSTN_UART13 9 +#define JHB100_PER0RST_MAIN_RSTN_UART14 10 +#define JHB100_PER0RST_MAIN_RSTN_I2C0 11 +#define JHB100_PER0RST_MAIN_RSTN_I2C1 12 +#define JHB100_PER0RST_MAIN_RSTN_I2C2 13 +#define JHB100_PER0RST_MAIN_RSTN_I2C3 14 +#define JHB100_PER0RST_MAIN_RSTN_I2C4 15 +#define JHB100_PER0RST_MAIN_RSTN_I2C5 16 +#define JHB100_PER0RST_MAIN_RSTN_I2C6 17 +#define JHB100_PER0RST_MAIN_RSTN_I2C7 18 +#define JHB100_PER0RST_MAIN_RSTN_I2C8 19 +#define JHB100_PER0RST_MAIN_RSTN_I2C9 20 +#define JHB100_PER0RST_MAIN_RSTN_I2C10 21 +#define JHB100_PER0RST_MAIN_RSTN_I2C11 22 +#define JHB100_PER0RST_MAIN_RSTN_I2C12 23 +#define JHB100_PER0RST_MAIN_RSTN_I2C13 24 +#define JHB100_PER0RST_MAIN_RSTN_I2C14 25 +#define JHB100_PER0RST_MAIN_RSTN_I2C15 26 +#define JHB100_PER0RST_MAIN_RSTN_I3C0 27 +#define JHB100_PER0RST_MAIN_RSTN_I3C1 28 +#define JHB100_PER0RST_MAIN_RSTN_I3C2 29 +#define JHB100_PER0RST_MAIN_RSTN_I3C3 30 +#define JHB100_PER0RST_MAIN_RSTN_I3C4 31 +#define JHB100_PER0RST_MAIN_RSTN_I3C5 32 +#define JHB100_PER0RST_MAIN_RSTN_I3C6 33 +#define JHB100_PER0RST_MAIN_RSTN_I3C7 34 +#define JHB100_PER0RST_MAIN_RSTN_I3C8 35 +#define JHB100_PER0RST_MAIN_RSTN_I3C9 36 +#define JHB100_PER0RST_MAIN_RSTN_I3C10 37 +#define JHB100_PER0RST_MAIN_RSTN_I3C11 38 +#define JHB100_PER0RST_MAIN_RSTN_I3C12 39 +#define JHB100_PER0RST_MAIN_RSTN_I3C13 40 +#define JHB100_PER0RST_MAIN_RSTN_I3C14 41 +#define JHB100_PER0RST_MAIN_RSTN_I3C15 42 +#define JHB100_PER0RST_MAIN_RSTN_WDT0 43 +#define JHB100_PER0RST_MAIN_RSTN_WDT1 44 +#define JHB100_PER0RST_MAIN_RSTN_WDT2 45 +#define JHB100_PER0RST_MAIN_RSTN_WDT3 46 +#define JHB100_PER0RST_MAIN_RSTN_WDT4 47 +#define JHB100_PER0RST_MAIN_RSTN_DUALTIMER0 48 +#define JHB100_PER0RST_MAIN_RSTN_DUALTIMER1 49 +#define JHB100_PER0RST_MAIN_RSTN_DUALTIMER2 50 +#define JHB100_PER0RST_MAIN_RSTN_TRNG 51 +#define JHB100_PER0RST_MAIN_RSTN_DMAC0 52 +#define JHB100_PER0RST_MAIN_RSTN_DMAC1 53 +#define JHB100_PER0RST_MAIN_RSTN_DMAC2 54 +#define JHB100_PER0RST_MAIN_RSTN_LTPI0 55 +#define JHB100_PER0RST_MAIN_RSTN_LTPI1 56 +#define JHB100_PER0RST_MAIN_RSTN_SOL4 57 +#define JHB100_PER0RST_MAIN_RSTN_SOL5 58 +#define JHB100_PER0RST_MAIN_RSTN_SOL6 59 +#define JHB100_PER0RST_MAIN_RSTN_SOL7 60 +#define JHB100_PER0RST_MAIN_RSTN_SOL8 61 +#define JHB100_PER0RST_MAIN_RSTN_SOL9 62 +#define JHB100_PER0RST_MAIN_RSTN_SOL10 63 +#define JHB100_PER0RST_MAIN_RSTN_SOL11 64 +#define JHB100_PER0RST_MAIN_RSTN_SOL12 65 +#define JHB100_PER0RST_MAIN_RSTN_SOL13 66 +#define JHB100_PER0RST_MAIN_RSTN_SOL14 67 +#define JHB100_PER0RST_MAIN_RSTN_LDO0 68 +#define JHB100_PER0RST_MAIN_RSTN_LDO1 69 +#define JHB100_PER0RST_MAIN_RSTN_PERIPH0_SENSORS 70 +#define JHB100_PER0RST_MAIN_RSTN_DMAC0_SENSORS 71 +#define JHB100_PER0RST_SYSCON_PRESETN 72 +#define JHB100_PER0RST_GPIO_IOMUX_PRESETN 73 +#define JHB100_PER0RST_UART_MUX_REG_WRAP 74 + #endif /* __DT_BINDINGS_RESET_STARFIVE_JHB100_CRG_H__ */ From d20c33354c2234f52f426d283eaf85b1e4f375dd Mon Sep 17 00:00:00 2001 From: Changhuang Liang Date: Wed, 30 Sep 2026 05:43:09 -0700 Subject: [PATCH 100/176] dt-bindings: clock: Add StarFive JHB100 Peripheral-1 clock and reset generator Add bindings for the Peripheral-1 clock and reset generator (PER1CRG) on the JHB100 RISC-V SoC by StarFive Ltd. Signed-off-by: Changhuang Liang Reviewed-by: Rob Herring (Arm) Signed-off-by: Conor Dooley --- .../clock/starfive,jhb100-per1crg.yaml | 70 +++++++++++++++++++ .../dt-bindings/clock/starfive,jhb100-crg.h | 60 ++++++++++++++++ .../dt-bindings/reset/starfive,jhb100-crg.h | 19 +++++ 3 files changed, 149 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/starfive,jhb100-per1crg.yaml diff --git a/Documentation/devicetree/bindings/clock/starfive,jhb100-per1crg.yaml b/Documentation/devicetree/bindings/clock/starfive,jhb100-per1crg.yaml new file mode 100644 index 000000000000..c72a355ceb34 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/starfive,jhb100-per1crg.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/starfive,jhb100-per1crg.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JHB100 Peripheral-1 Clock and Reset Generator + +maintainers: + - Changhuang Liang + +properties: + compatible: + const: starfive,jhb100-per1crg + + reg: + maxItems: 1 + + clocks: + items: + - description: PLL7 + - description: Non Coherent NOC Initiator + - description: Configure 800MHz + - description: Non Coherent NOC Target + - description: Configure 143MHz + + clock-names: + items: + - const: pll7 + - const: ncnoc_init + - const: cfg_800 + - const: ncnoc_targ + - const: cfg_143 + + '#clock-cells': + const: 1 + description: + See for valid indices. + + '#reset-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + clock-controller@11b40000 { + compatible = "starfive,jhb100-per1crg"; + reg = <0x11b40000 0x1000>; + clocks = <&pll7>, + <&sys0crg 68>, + <&sys0crg 69>, + <&sys2crg 19>, + <&sys2crg 22>; + clock-names = "pll7", "ncnoc_init", + "cfg_800", "ncnoc_targ", + "cfg_143"; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/include/dt-bindings/clock/starfive,jhb100-crg.h b/include/dt-bindings/clock/starfive,jhb100-crg.h index add2cd093dbd..7f508574177c 100644 --- a/include/dt-bindings/clock/starfive,jhb100-crg.h +++ b/include/dt-bindings/clock/starfive,jhb100-crg.h @@ -387,4 +387,64 @@ #define JHB100_PER0CLK_MAIN_ICG_EN_SENSORS_DMAC 339 #define JHB100_PER0CLK_MAIN_ICG_EN_TRNG 340 +/* PER1CRG clocks */ +#define JHB100_PER1CLK_100 0 +#define JHB100_PER1CLK_1 1 +#define JHB100_PER1CLK_200_DIVN0 2 +#define JHB100_PER1CLK_200_DIVN1 3 +#define JHB100_PER1CLK_200_DIVN2 4 +#define JHB100_PER1CLK_200_DIVN3 5 +#define JHB100_PER1CLK_200_CCLK_DIV 6 + +#define JHB100_PER1CLK_SGPIO0_PCLK 15 +#define JHB100_PER1CLK_SGPIO0_DCLK 16 +#define JHB100_PER1CLK_SGPIO1_PCLK 17 +#define JHB100_PER1CLK_SGPIO1_DCLK 18 + +#define JHB100_PER1CLK_EMMC0_BCLK 22 + +#define JHB100_PER1CLK_EMMC0_CCLK 25 + +#define JHB100_PER1CLK_DMAC1_1CH_CORE 29 + +#define JHB100_PER1CLK_DMAC1_1CH_ACLK 31 + +#define JHB100_PER1CLK_DMAC2_1CH_CORE 33 + +#define JHB100_PER1CLK_DMAC2_1CH_ACLK 35 + +#define JHB100_PER1CLK_DMAC3_1CH_CORE 37 + +#define JHB100_PER1CLK_DMAC3_1CH_ACLK 39 + +#define JHB100_PER1CLK_DMAC0_2CH_CORE 41 + +#define JHB100_PER1CLK_DMAC0_2CH_ACLK 43 + +#define JHB100_PER1CLK_UFS_REF 45 +#define JHB100_PER1CLK_UFS_300 46 +#define JHB100_PER1CLK_UFS_150 47 +#define JHB100_PER1CLK_UFS_400 48 +#define JHB100_PER1CLK_UFS_75 49 +#define JHB100_PER1CLK_UFS_37_5 50 +#define JHB100_PER1CLK_UFS_7_5 51 +#define JHB100_PER1CLK_UFS_1_875 52 +#define JHB100_PER1CLK_UFS_7_143 53 +#define JHB100_PER1CLK_UFS_3_5715 54 + +#define JHB100_PER1CLK_MAIN_ICG_EN_SFC0 63 +#define JHB100_PER1CLK_MAIN_ICG_EN_SFC1 64 +#define JHB100_PER1CLK_MAIN_ICG_EN_SFC2 65 +#define JHB100_PER1CLK_MAIN_ICG_EN_SPI0 66 +#define JHB100_PER1CLK_MAIN_ICG_EN_SGPIO0 67 +#define JHB100_PER1CLK_MAIN_ICG_EN_SGPIO1 68 +#define JHB100_PER1CLK_MAIN_ICG_EN_SENSORS_PERIPH1 69 +#define JHB100_PER1CLK_MAIN_ICG_EN_EMMC0 70 +#define JHB100_PER1CLK_MAIN_ICG_EN_DMAC_SFC0 71 +#define JHB100_PER1CLK_MAIN_ICG_EN_DMAC_SFC1 72 +#define JHB100_PER1CLK_MAIN_ICG_EN_DMAC_SFC2 73 +#define JHB100_PER1CLK_MAIN_ICG_EN_DMAC_SPI0 74 +#define JHB100_PER1CLK_MAIN_ICG_EN_RAS 75 +#define JHB100_PER1CLK_MAIN_ICG_EN_UFS 76 + #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JHB100_H__ */ diff --git a/include/dt-bindings/reset/starfive,jhb100-crg.h b/include/dt-bindings/reset/starfive,jhb100-crg.h index ccfb7616e1a7..cf933a1befbb 100644 --- a/include/dt-bindings/reset/starfive,jhb100-crg.h +++ b/include/dt-bindings/reset/starfive,jhb100-crg.h @@ -138,4 +138,23 @@ #define JHB100_PER0RST_GPIO_IOMUX_PRESETN 73 #define JHB100_PER0RST_UART_MUX_REG_WRAP 74 +/* PER1CRG resets */ +#define JHB100_PER1RST_IOMUX_PRESETN 0 +#define JHB100_PER1RST_SYSCON_PRESETN 1 +#define JHB100_PER1RST_MAIN_RSTN_SFC0 2 +#define JHB100_PER1RST_MAIN_RSTN_SFC1 3 +#define JHB100_PER1RST_MAIN_RSTN_SFC2 4 +#define JHB100_PER1RST_MAIN_RSTN_SPI0 5 +#define JHB100_PER1RST_MAIN_RSTN_PERIPH1_SENSORS 6 +#define JHB100_PER1RST_MAIN_RSTN_SGPIO0 7 +#define JHB100_PER1RST_MAIN_RSTN_SGPIO1 8 +#define JHB100_PER1RST_MAIN_RSTN_EMMC0 9 +#define JHB100_PER1RST_MAIN_RSTN_UFS 10 +#define JHB100_PER1RST_MAIN_RSTN_UFS_PHY 11 +#define JHB100_PER1RST_MAIN_RSTN_DMAC_SFC0 12 +#define JHB100_PER1RST_MAIN_RSTN_DMAC_SFC1 13 +#define JHB100_PER1RST_MAIN_RSTN_DMAC_SFC2 14 +#define JHB100_PER1RST_MAIN_RSTN_DMAC_SPI0 15 +#define JHB100_PER1RST_MAIN_RSTN_PERIPH1_RAS 16 + #endif /* __DT_BINDINGS_RESET_STARFIVE_JHB100_CRG_H__ */ From 5b86a2f9415fdf4ef1188fdfe0dafb1727328cfd Mon Sep 17 00:00:00 2001 From: Changhuang Liang Date: Wed, 30 Sep 2026 05:43:11 -0700 Subject: [PATCH 101/176] dt-bindings: clock: Add StarFive JHB100 Peripheral-2 clock and reset generator Add bindings for the Peripheral-2 clock and reset generator (PER2CRG) on the JHB100 RISC-V SoC by StarFive Ltd. Signed-off-by: Changhuang Liang Reviewed-by: Krzysztof Kozlowski Signed-off-by: Conor Dooley --- .../clock/starfive,jhb100-per2crg.yaml | 76 +++++++++++++++++++ .../dt-bindings/clock/starfive,jhb100-crg.h | 57 ++++++++++++++ .../dt-bindings/reset/starfive,jhb100-crg.h | 17 +++++ 3 files changed, 150 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/starfive,jhb100-per2crg.yaml diff --git a/Documentation/devicetree/bindings/clock/starfive,jhb100-per2crg.yaml b/Documentation/devicetree/bindings/clock/starfive,jhb100-per2crg.yaml new file mode 100644 index 000000000000..175654645221 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/starfive,jhb100-per2crg.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/starfive,jhb100-per2crg.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JHB100 Peripheral-2 Clock and Reset Generator + +maintainers: + - Changhuang Liang + +properties: + compatible: + const: starfive,jhb100-per2crg + + reg: + maxItems: 1 + + clocks: + items: + - description: Non Coherent NOC Initiator + - description: Configure 400MHz + - description: Configure 125MHz + - description: GMAC2 RGMII RX + - description: GMAC2 RMII Reference + - description: GMAC3 SGMII TX + - description: GMAC3 SGMII RX + - description: Main Oscillator (25 MHz) + + clock-names: + items: + - const: ncnoc_init + - const: cfg_400 + - const: cfg_125 + - const: gmac2_rgmii_rx + - const: gmac2_rmii_ref + - const: gmac3_sgmii_tx + - const: gmac3_sgmii_rx + - const: osc + + '#clock-cells': + const: 1 + description: + See for valid indices. + + '#reset-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + clock-controller@11bc0000 { + compatible = "starfive,jhb100-per2crg"; + reg = <0x11bc0000 0x1000>; + clocks = <&sys0crg 52>, <&sys0crg 54>, <&sys0crg 55>, + <&per2_gmac2_rgmii_rx>, <&per2_gmac2_rmii_ref>, + <&per2_gmac3_sgmii_tx>, <&per2_gmac3_sgmii_rx>, + <&osc>; + clock-names = "ncnoc_init", "cfg_400", "cfg_125", + "gmac2_rgmii_rx", "gmac2_rmii_ref", + "gmac3_sgmii_tx", "gmac3_sgmii_rx", + "osc"; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/include/dt-bindings/clock/starfive,jhb100-crg.h b/include/dt-bindings/clock/starfive,jhb100-crg.h index 7f508574177c..2b2e148ce5ce 100644 --- a/include/dt-bindings/clock/starfive,jhb100-crg.h +++ b/include/dt-bindings/clock/starfive,jhb100-crg.h @@ -447,4 +447,61 @@ #define JHB100_PER1CLK_MAIN_ICG_EN_RAS 75 #define JHB100_PER1CLK_MAIN_ICG_EN_UFS 76 +/* PER2CRG clocks */ +#define JHB100_PER2CLK_300 0 +#define JHB100_PER2CLK_100 1 +#define JHB100_PER2CLK_50 2 +#define JHB100_PER2CLK_GMAC2_RMII_50 3 +#define JHB100_PER2CLK_CAN0_CORE_DIV 4 +#define JHB100_PER2CLK_CAN1_CORE_DIV 5 +#define JHB100_PER2CLK_CAN0_TIMER 6 +#define JHB100_PER2CLK_CAN1_TIMER 7 + +#define JHB100_PER2CLK_RTC_CORE_DIV 11 +#define JHB100_PER2CLK_GMAC2_RMII_MUX_DLY 12 +#define JHB100_PER2CLK_GMAC2_RMII_DIV 13 + +#define JHB100_PER2CLK_GMAC2_RGMII_125_MUX 15 +#define JHB100_PER2CLK_GMAC2_RGMII_DIV 16 +#define JHB100_PER2CLK_GMAC2_TX_MUX 17 +#define JHB100_PER2CLK_GMAC2_TX_180_BUF 18 +#define JHB100_PER2CLK_GMAC2_RX_MUX_DLY 19 +#define JHB100_PER2CLK_GMAC2_RX_180_BUF 20 +#define JHB100_PER2CLK_GMAC2_TXCK_MUX_DLY 21 +#define JHB100_PER2CLK_GMAC3_TX_125_MUX 22 +#define JHB100_PER2CLK_GMAC3_RX_125_MUX 23 +#define JHB100_PER2CLK_GMAC3_TX_DIV 24 +#define JHB100_PER2CLK_GMAC3_RX_DIV 25 +#define JHB100_PER2CLK_SENSORS_PERIPH2 26 + +#define JHB100_PER2CLK_FAN_TACH_PCLK 33 + +#define JHB100_PER2CLK_ETHER0_RMIIANDRGMII_TX_I 44 +#define JHB100_PER2CLK_ETHER0_RMIIANDRGMII_RX_I 45 +#define JHB100_PER2CLK_ETHER0_RMIIANDRGMII_TX_180_I 46 +#define JHB100_PER2CLK_ETHER0_RMIIANDRGMII_RX_180_I 47 +#define JHB100_PER2CLK_ETHER0_RMIIANDRGMII_PTP_REF_I 48 +#define JHB100_PER2CLK_ETHER0_RMIIANDRGMII_RMII_I 49 +#define JHB100_PER2CLK_ETHER0_RMIIANDRGMII_CSR_I 50 +#define JHB100_PER2CLK_ETHER0_RMIIANDRGMII_ACLK_I 51 +#define JHB100_PER2CLK_RMIIANDRGMII_IOMUX_GMAC2_TXCK 52 +#define JHB100_PER2CLK_ETHER1_SGMII_TX_I 53 +#define JHB100_PER2CLK_ETHER1_SGMII_RX_I 54 +#define JHB100_PER2CLK_ETHER1_SGMII_TX_125_I 55 +#define JHB100_PER2CLK_ETHER1_SGMII_RX_125_I 56 +#define JHB100_PER2CLK_ETHER1_SGMII_PTP_REF_I 57 +#define JHB100_PER2CLK_ETHER1_SGMII_CSR_I 58 +#define JHB100_PER2CLK_ETHER1_SGMII_ACLK_I 59 +#define JHB100_PER2CLK_ETHER1_SGMII_PHY_PCLK_I 60 +#define JHB100_PER2CLK_ETHER1_SGMII_REF_25_I 61 +#define JHB100_PER2CLK_MAIN_ICG_EN_CAN0 62 +#define JHB100_PER2CLK_MAIN_ICG_EN_CAN1 63 + +#define JHB100_PER2CLK_MAIN_ICG_EN_DMAC_8CH 65 +#define JHB100_PER2CLK_MAIN_ICG_EN_RTC_SCAN 66 +#define JHB100_PER2CLK_MAIN_ICG_EN_ADC0 67 +#define JHB100_PER2CLK_MAIN_ICG_EN_ADC1 68 +#define JHB100_PER2CLK_MAIN_ICG_EN_GMAC2 69 +#define JHB100_PER2CLK_MAIN_ICG_EN_GMAC3 70 + #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JHB100_H__ */ diff --git a/include/dt-bindings/reset/starfive,jhb100-crg.h b/include/dt-bindings/reset/starfive,jhb100-crg.h index cf933a1befbb..0965f3798397 100644 --- a/include/dt-bindings/reset/starfive,jhb100-crg.h +++ b/include/dt-bindings/reset/starfive,jhb100-crg.h @@ -157,4 +157,21 @@ #define JHB100_PER1RST_MAIN_RSTN_DMAC_SPI0 15 #define JHB100_PER1RST_MAIN_RSTN_PERIPH1_RAS 16 +/* PER2CRG resets */ +#define JHB100_PER2RST_IOMUX_PRESETN 0 +#define JHB100_PER2RST_POK_IOMUX_PRESETN 1 +#define JHB100_PER2RST_SYSREG_RSTN 2 +#define JHB100_PER2RST_MAIN_RSTN_CAN0 3 +#define JHB100_PER2RST_MAIN_RSTN_CAN1 4 +#define JHB100_PER2RST_FAN_TACH_PRESETN 5 +#define JHB100_PER2RST_MAIN_RSTN_GMAC2 6 +#define JHB100_PER2RST_MAIN_RSTN_GMAC3 7 +#define JHB100_PER2RST_MAIN_RSTN_DMAC_8CH 8 +#define JHB100_PER2RST_MAIN_RSTN_RTC 9 +#define JHB100_PER2RST_ADC0_PRESETN 10 +#define JHB100_PER2RST_ADC0_IOMUX_PRESETN 11 +#define JHB100_PER2RST_ADC1_PRESETN 12 +#define JHB100_PER2RST_ADC1_IOMUX_PRESETN 13 +#define JHB100_PER2RST_MAIN_RSTN_PERIPH2_SENSORS 14 + #endif /* __DT_BINDINGS_RESET_STARFIVE_JHB100_CRG_H__ */ From 17986e31f3b6142c302c8f9af16540422787daf9 Mon Sep 17 00:00:00 2001 From: Changhuang Liang Date: Wed, 30 Sep 2026 05:43:13 -0700 Subject: [PATCH 102/176] dt-bindings: clock: Add StarFive JHB100 Peripheral-3 clock and reset generator Add bindings for the Peripheral-3 clock and reset generator (PER3CRG) on the JHB100 RISC-V SoC by StarFive Ltd. Signed-off-by: Changhuang Liang Reviewed-by: Rob Herring (Arm) Signed-off-by: Conor Dooley --- .../clock/starfive,jhb100-per3crg.yaml | 76 +++++++++++++++++++ .../dt-bindings/clock/starfive,jhb100-crg.h | 35 +++++++++ .../dt-bindings/reset/starfive,jhb100-crg.h | 9 +++ 3 files changed, 120 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/starfive,jhb100-per3crg.yaml diff --git a/Documentation/devicetree/bindings/clock/starfive,jhb100-per3crg.yaml b/Documentation/devicetree/bindings/clock/starfive,jhb100-per3crg.yaml new file mode 100644 index 000000000000..2c3b9f4146b5 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/starfive,jhb100-per3crg.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/starfive,jhb100-per3crg.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JHB100 Peripheral-3 Clock and Reset Generator + +maintainers: + - Changhuang Liang + +properties: + compatible: + const: starfive,jhb100-per3crg + + reg: + maxItems: 1 + + clocks: + items: + - description: Non Coherent NOC Initiator + - description: Non Coherent NOC Target + - description: Configure 125MHz + - description: GMAC0 RMII Reference clock + - description: GMAC1 SGMII TX + - description: GMAC1 SGMII RX + - description: Main Oscillator (25 MHz) + + clock-names: + items: + - const: ncnoc_init + - const: ncnoc_targ + - const: cfg_125 + - const: gmac0_rmii_rclki + - const: gmac1_sgmii_tx + - const: gmac1_sgmii_rx + - const: osc + + '#clock-cells': + const: 1 + description: + See for valid indices. + + '#reset-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + clock-controller@11c40000 { + compatible = "starfive,jhb100-per3crg"; + reg = <0x11c40000 0x1000>; + clocks = <&sys0crg 65>, + <&sys1crg 18>, + <&sys1crg 19>, + <&per3_gmac0_rmii_rclki>, + <&per3_gmac1_sgmii_tx>, + <&per3_gmac1_sgmii_rx>, + <&osc>; + clock-names = "ncnoc_init", "ncnoc_targ", "cfg_125", + "gmac0_rmii_rclki", "gmac1_sgmii_tx", + "gmac1_sgmii_rx", "osc"; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/include/dt-bindings/clock/starfive,jhb100-crg.h b/include/dt-bindings/clock/starfive,jhb100-crg.h index 2b2e148ce5ce..bdf7d628b381 100644 --- a/include/dt-bindings/clock/starfive,jhb100-crg.h +++ b/include/dt-bindings/clock/starfive,jhb100-crg.h @@ -504,4 +504,39 @@ #define JHB100_PER2CLK_MAIN_ICG_EN_GMAC2 69 #define JHB100_PER2CLK_MAIN_ICG_EN_GMAC3 70 +/* PER3CRG clocks */ +#define JHB100_PER3CLK_300 0 +#define JHB100_PER3CLK_200 1 +#define JHB100_PER3CLK_GMAC1_PTP_REF 2 +#define JHB100_PER3CLK_GMAC1_TX_125_MUX 3 +#define JHB100_PER3CLK_GMAC1_TX 4 +#define JHB100_PER3CLK_GMAC1_RX_125_MUX 5 +#define JHB100_PER3CLK_GMAC1_RX 6 +#define JHB100_PER3CLK_GMAC0_PTP_REF 7 +#define JHB100_PER3CLK_GMAC0_RMII_PLL 8 +#define JHB100_PER3CLK_GMAC0_RMII_MUX 9 +#define JHB100_PER3CLK_GMAC0_RMII_MUX_DIV2 10 + +#define JHB100_PER3CLK_ETHER0_RMII_CLK_TX_I 17 +#define JHB100_PER3CLK_ETHER0_RMII_CLK_RX_I 18 +#define JHB100_PER3CLK_ETHER0_RMII_CLK_PTP_REF_I 19 +#define JHB100_PER3CLK_ETHER0_RMII_CLK_RMII_I 20 +#define JHB100_PER3CLK_ETHER0_RMII_CLK_CSR_I 21 +#define JHB100_PER3CLK_ETHER0_RMII_ACLK_I 22 +#define JHB100_PER3CLK_GMAC0_RMII_RCLKO 23 +#define JHB100_PER3CLK_ETHER0_SGMII_CLK_TX_I 24 +#define JHB100_PER3CLK_ETHER0_SGMII_CLK_RX_I 25 +#define JHB100_PER3CLK_ETHER0_SGMII_CLK_TX_125_I 26 +#define JHB100_PER3CLK_ETHER0_SGMII_CLK_RX_125_I 27 +#define JHB100_PER3CLK_ETHER0_SGMII_CLK_PTP_REF_I 28 +#define JHB100_PER3CLK_ETHER0_SGMII_CLK_REF_25_I 29 +#define JHB100_PER3CLK_ETHER0_SGMII_CLK_CSR_I 30 +#define JHB100_PER3CLK_ETHER0_SGMII_ACLK_I 31 +#define JHB100_PER3CLK_ETHER0_SGMII_PHY_PCLK_I 32 +#define JHB100_PER3CLK_MAIN_ICG_EN_SENSORS_PERIPH3 33 +#define JHB100_PER3CLK_MAIN_ICG_EN_PECI0 34 +#define JHB100_PER3CLK_MAIN_ICG_EN_PECI1 35 +#define JHB100_PER3CLK_MAIN_ICG_EN_GMAC0 36 +#define JHB100_PER3CLK_MAIN_ICG_EN_GMAC1 37 + #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JHB100_H__ */ diff --git a/include/dt-bindings/reset/starfive,jhb100-crg.h b/include/dt-bindings/reset/starfive,jhb100-crg.h index 0965f3798397..872a4dd25beb 100644 --- a/include/dt-bindings/reset/starfive,jhb100-crg.h +++ b/include/dt-bindings/reset/starfive,jhb100-crg.h @@ -174,4 +174,13 @@ #define JHB100_PER2RST_ADC1_IOMUX_PRESETN 13 #define JHB100_PER2RST_MAIN_RSTN_PERIPH2_SENSORS 14 +/* PER3CRG resets */ +#define JHB100_PER3RST_SYSREG_RSTN 0 +#define JHB100_PER3RST_MAIN_RSTN_GMAC0 1 +#define JHB100_PER3RST_MAIN_RSTN_GMAC1 2 +#define JHB100_PER3RST_MAIN_RSTN_PECI0 3 +#define JHB100_PER3RST_MAIN_RSTN_PECI1 4 +#define JHB100_PER3RST_MAIN_RSTN_PERIPH3_SENSORS 5 +#define JHB100_PER3RST_IOMUX_PRESETN 6 + #endif /* __DT_BINDINGS_RESET_STARFIVE_JHB100_CRG_H__ */ From c4a545d3e428e9600d670fa8a08098b7bc82d5ec Mon Sep 17 00:00:00 2001 From: Changhuang Liang Date: Fri, 28 Aug 2026 02:56:01 -0700 Subject: [PATCH 103/176] dt-bindings: soc: starfive: Add StarFive JHB100 syscon modules Add documentation to describe StarFive JHB100 SoC System Controller Registers. Add the PLL clocks for the sys0, per0, and per1 domains under syscon, as well as the PCIe RP reset. Signed-off-by: Changhuang Liang Reviewed-by: Krzysztof Kozlowski Signed-off-by: Conor Dooley --- .../soc/starfive/starfive,jhb100-syscon.yaml | 115 ++++++++++++++++++ .../dt-bindings/clock/starfive,jhb100-crg.h | 12 ++ .../dt-bindings/reset/starfive,jhb100-crg.h | 3 + 3 files changed, 130 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/starfive/starfive,jhb100-syscon.yaml diff --git a/Documentation/devicetree/bindings/soc/starfive/starfive,jhb100-syscon.yaml b/Documentation/devicetree/bindings/soc/starfive/starfive,jhb100-syscon.yaml new file mode 100644 index 000000000000..000f53acab34 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/starfive/starfive,jhb100-syscon.yaml @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/starfive/starfive,jhb100-syscon.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JHB100 SoC system controller + +maintainers: + - Kevin Xie + - Changhuang Liang + +description: + The StarFive JHB100 SoC system controller contains MMIO registers used by + other hardware modules (e.g., PLL, eMMC, PCIe). These modules access + specific register offsets, bit masks, and shifts within the system + controller region for configuration and status. + +properties: + compatible: + items: + - enum: + - starfive,jhb100-b2h-syscon + - starfive,jhb100-gpu-syscon + - starfive,jhb100-h2b-syscon + - starfive,jhb100-host-syscon + - starfive,jhb100-husb-syscon + - starfive,jhb100-husbcmn-syscon + - starfive,jhb100-husbd-syscon + - starfive,jhb100-npu-syscon + - starfive,jhb100-pcieep-ecsr-syscon + - starfive,jhb100-pcierp-ecsr-syscon + - starfive,jhb100-pcierp-syscon + - starfive,jhb100-per0-syscon + - starfive,jhb100-per1-syscon + - starfive,jhb100-per2-syscon + - starfive,jhb100-per3-syscon + - starfive,jhb100-sfc-filter-syscon + - starfive,jhb100-strap-syscon + - starfive,jhb100-sys0-syscon + - starfive,jhb100-sys1-syscon + - starfive,jhb100-sys2-syscon + - starfive,jhb100-usb-syscon + - starfive,jhb100-vout-syscon + - const: syscon + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + +required: + - compatible + - reg + +allOf: + - if: + properties: + compatible: + contains: + enum: + - starfive,jhb100-per0-syscon + - starfive,jhb100-per1-syscon + - starfive,jhb100-sys0-syscon + then: + required: + - clocks + - '#clock-cells' + else: + properties: + clocks: false + '#clock-cells': false + + - if: + properties: + compatible: + contains: + const: starfive,jhb100-pcierp-syscon + then: + required: + - '#reset-cells' + else: + properties: + '#reset-cells': false + +additionalProperties: false + +examples: + - | + syscon@13010000 { + compatible = "starfive,jhb100-sys0-syscon", "syscon"; + reg = <0x13010000 0x2000>; + clocks = <&osc>; + #clock-cells = <1>; + }; + + syscon@13014000 { + compatible = "starfive,jhb100-sys1-syscon", "syscon"; + reg = <0x13014000 0x4000>; + }; + + syscon@11719000 { + compatible = "starfive,jhb100-pcierp-syscon", "syscon"; + reg = <0x11719000 0x1000>; + #reset-cells = <1>; + }; + +... diff --git a/include/dt-bindings/clock/starfive,jhb100-crg.h b/include/dt-bindings/clock/starfive,jhb100-crg.h index bdf7d628b381..4270bfa532e8 100644 --- a/include/dt-bindings/clock/starfive,jhb100-crg.h +++ b/include/dt-bindings/clock/starfive,jhb100-crg.h @@ -8,6 +8,18 @@ #ifndef __DT_BINDINGS_CLOCK_STARFIVE_JHB100_H__ #define __DT_BINDINGS_CLOCK_STARFIVE_JHB100_H__ +/* SYS0PLL clocks */ +#define JHB100_SYS0PLL_PLL2_OUT 0 +#define JHB100_SYS0PLL_PLL3_OUT 1 +#define JHB100_SYS0PLL_PLL4_OUT 2 +#define JHB100_SYS0PLL_PLL5_OUT 3 + +/* PER0PLL clocks */ +#define JHB100_PER0PLL_PLL6_OUT 0 + +/* PER1PLL clocks */ +#define JHB100_PER1PLL_PLL7_OUT 0 + /* SYS0CRG clocks */ #define JHB100_SYS0CLK_BMCPCIERP_NCNOC_MAIN 17 #define JHB100_SYS0CLK_BMCPCIERP_NCNOC_CFG 18 diff --git a/include/dt-bindings/reset/starfive,jhb100-crg.h b/include/dt-bindings/reset/starfive,jhb100-crg.h index 872a4dd25beb..1489bb01c2bd 100644 --- a/include/dt-bindings/reset/starfive,jhb100-crg.h +++ b/include/dt-bindings/reset/starfive,jhb100-crg.h @@ -183,4 +183,7 @@ #define JHB100_PER3RST_MAIN_RSTN_PERIPH3_SENSORS 5 #define JHB100_PER3RST_IOMUX_PRESETN 6 +/* PCIERP SYSCON resets */ +#define JHB100_PCIERP_SYSCONRST_PE2RST_OUT 0 + #endif /* __DT_BINDINGS_RESET_STARFIVE_JHB100_CRG_H__ */ From 96b35a1251dc9977967286623fd15fcef34feeb1 Mon Sep 17 00:00:00 2001 From: Changhuang Liang Date: Fri, 28 Aug 2026 02:56:07 -0700 Subject: [PATCH 104/176] soc: starfive: Add socinfo driver for JHB100 SoC Add a socinfo driver for the JHB100 SoC, exposing the SoC family, ID and revision through the SoC bus. It is currently used to distinguish the two revisions, A0 and A1. The driver binds to the sys0 system controller node. That region only contains the PLL controls, this revision ID register and a few debug registers, so rather than describing an extra child node in the devicetree, the sys0 PLL device is instantiated from here as an MFD cell. The PLL driver then picks up the regmap from its parent's DT node. Note that CONFIG_STARFIVE_JHB100_SOCINFO is therefore a build-time prerequisite for the sys0 PLL clocks; see CLK_STARFIVE_JHB100_PLL. Signed-off-by: Changhuang Liang Signed-off-by: Conor Dooley --- drivers/soc/Kconfig | 1 + drivers/soc/Makefile | 1 + drivers/soc/starfive/Kconfig | 6 + drivers/soc/starfive/Makefile | 2 + drivers/soc/starfive/socinfo/Kconfig | 13 +++ drivers/soc/starfive/socinfo/Makefile | 2 + drivers/soc/starfive/socinfo/jhb100-socinfo.c | 105 ++++++++++++++++++ 7 files changed, 130 insertions(+) create mode 100644 drivers/soc/starfive/Kconfig create mode 100644 drivers/soc/starfive/Makefile create mode 100644 drivers/soc/starfive/socinfo/Kconfig create mode 100644 drivers/soc/starfive/socinfo/Makefile create mode 100644 drivers/soc/starfive/socinfo/jhb100-socinfo.c diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index a2d65adffb80..b3b01fc38139 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -24,6 +24,7 @@ source "drivers/soc/renesas/Kconfig" source "drivers/soc/rockchip/Kconfig" source "drivers/soc/samsung/Kconfig" source "drivers/soc/sophgo/Kconfig" +source "drivers/soc/starfive/Kconfig" source "drivers/soc/sunxi/Kconfig" source "drivers/soc/tegra/Kconfig" source "drivers/soc/ti/Kconfig" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index c9e689080ceb..009f85ff891a 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -30,6 +30,7 @@ obj-y += renesas/ obj-y += rockchip/ obj-$(CONFIG_SOC_SAMSUNG) += samsung/ obj-y += sophgo/ +obj-y += starfive/ obj-y += sunxi/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-y += ti/ diff --git a/drivers/soc/starfive/Kconfig b/drivers/soc/starfive/Kconfig new file mode 100644 index 000000000000..04b020083d3e --- /dev/null +++ b/drivers/soc/starfive/Kconfig @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +menu "StarFive SoC (System On Chip) specific Drivers" + +source "drivers/soc/starfive/socinfo/Kconfig" + +endmenu diff --git a/drivers/soc/starfive/Makefile b/drivers/soc/starfive/Makefile new file mode 100644 index 000000000000..ca1e609b8104 --- /dev/null +++ b/drivers/soc/starfive/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-y += socinfo/ diff --git a/drivers/soc/starfive/socinfo/Kconfig b/drivers/soc/starfive/socinfo/Kconfig new file mode 100644 index 000000000000..64f1b1e04d01 --- /dev/null +++ b/drivers/soc/starfive/socinfo/Kconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config STARFIVE_JHB100_SOCINFO + bool "StarFive JHB100 SoC Information" + depends on ARCH_STARFIVE || COMPILE_TEST + select SOC_BUS + select MFD_CORE + select MFD_SYSCON + default y + help + Include support for the SoC bus socinfo for the StarFive JHB100 SoC + platforms to provide information about the SoC family and variant + to user space. diff --git a/drivers/soc/starfive/socinfo/Makefile b/drivers/soc/starfive/socinfo/Makefile new file mode 100644 index 000000000000..26c2bdf1de3b --- /dev/null +++ b/drivers/soc/starfive/socinfo/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_STARFIVE_JHB100_SOCINFO) += jhb100-socinfo.o diff --git a/drivers/soc/starfive/socinfo/jhb100-socinfo.c b/drivers/soc/starfive/socinfo/jhb100-socinfo.c new file mode 100644 index 000000000000..0a31cae9b4f5 --- /dev/null +++ b/drivers/soc/starfive/socinfo/jhb100-socinfo.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025 StarFive Technology Co., Ltd. + * + * Author: Changhuang Liang + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define JHB100_REV_ID 0x38 +#define JHB100_REV_ID_CHAR GENMASK(3, 2) +#define JHB100_REV_ID_NUM GENMASK(1, 0) + +/* + * The sys0 system controller region only contains the PLL controls, this + * revision ID register and a few debug registers, so instead of describing + * a child node in the devicetree the PLL device is instantiated from here. + */ +static const struct mfd_cell jhb100_sys0_syscon_cells[] = { + { .name = "jhb100-sys0-pll", }, +}; + +static void jhb100_socinfo_unregister(void *data) +{ + soc_device_unregister(data); +} + +static int jhb100_socinfo_probe(struct platform_device *pdev) +{ + struct soc_device_attribute *attrs; + struct device *dev = &pdev->dev; + struct soc_device *soc_dev; + struct regmap *regmap; + char rev_char; + u32 rev_id; + int ret; + + regmap = syscon_node_to_regmap(dev->of_node); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "failed to get syscon regmap\n"); + + ret = regmap_read(regmap, JHB100_REV_ID, &rev_id); + if (ret) + return dev_err_probe(dev, ret, "failed to read revision ID\n"); + + attrs = devm_kzalloc(dev, sizeof(*attrs), GFP_KERNEL); + if (!attrs) + return -ENOMEM; + + rev_char = FIELD_GET(JHB100_REV_ID_CHAR, rev_id) + 'A'; + + attrs->family = "JH"; + attrs->soc_id = "JHB100"; + attrs->revision = devm_kasprintf(dev, GFP_KERNEL, "%c%lu", rev_char, + FIELD_GET(JHB100_REV_ID_NUM, rev_id)); + if (!attrs->revision) + return -ENOMEM; + + soc_dev = soc_device_register(attrs); + if (IS_ERR(soc_dev)) + return dev_err_probe(dev, PTR_ERR(soc_dev), + "failed to register SoC device\n"); + + ret = devm_add_action_or_reset(dev, jhb100_socinfo_unregister, soc_dev); + if (ret) + return ret; + + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, + jhb100_sys0_syscon_cells, + ARRAY_SIZE(jhb100_sys0_syscon_cells), + NULL, 0, NULL); + if (ret) + return dev_err_probe(dev, ret, "failed to add mfd cells\n"); + + dev_info(dev, "StarFive %s SoC rev(%s)\n", attrs->soc_id, attrs->revision); + + return 0; +} + +static const struct of_device_id jhb100_socinfo_of_match[] = { + { .compatible = "starfive,jhb100-sys0-syscon" }, + { /* sentinel */ } +}; + +static struct platform_driver jhb100_socinfo_driver = { + .probe = jhb100_socinfo_probe, + .driver = { + .name = "jhb100-socinfo", + .of_match_table = jhb100_socinfo_of_match, + }, +}; + +static int __init jhb100_socinfo_init(void) +{ + return platform_driver_register(&jhb100_socinfo_driver); +} +subsys_initcall(jhb100_socinfo_init); From 72497e9692aae048166dd86e7b79c5a08b353b60 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 2 Oct 2026 11:16:42 +0200 Subject: [PATCH 105/176] soc/tegra: cbb: Fix loggger -> logger typo Found using codespell. Signed-off-by: Thierry Reding --- drivers/soc/tegra/cbb/tegra194-cbb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/tegra/cbb/tegra194-cbb.c b/drivers/soc/tegra/cbb/tegra194-cbb.c index 69ef929e04f8..be35ec0f39de 100644 --- a/drivers/soc/tegra/cbb/tegra194-cbb.c +++ b/drivers/soc/tegra/cbb/tegra194-cbb.c @@ -1912,7 +1912,7 @@ static bool print_errlog0(struct seq_file *file, struct tegra194_cbb *cbb) /* * Print debug information about failed transaction using - * ErrLog registers of error loggger having ErrVld set + * ErrLog registers of error logger having ErrVld set */ static bool print_errloggerX_info(struct seq_file *file, struct tegra194_cbb *cbb, int errloggerX) From 4ccb980125b68964e90c05d7c6dbf3e804b93b32 Mon Sep 17 00:00:00 2001 From: Alexandre Hamamdjian Date: Mon, 27 Jul 2026 21:00:11 -0500 Subject: [PATCH 106/176] soc/tegra: pmc: Add Tegra210B01 support The PMC in Tegra210B01 is very similar to the one in the original Tegra210, but has a few powergate differences. Specifically sata and ve2 are removed. Signed-off-by: Alexandre Hamamdjian Co-developed-by: Thomas Makin Signed-off-by: Thomas Makin Co-developed-by: Aaron Kling Signed-off-by: Aaron Kling Reviewed-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 512cca3c7509..92704d39dc5f 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -3916,6 +3916,67 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = { .has_single_mmio_aperture = true, }; +static const char * const tegra210b01_powergates[] = { + [TEGRA_POWERGATE_CPU] = "crail", + [TEGRA_POWERGATE_3D] = "3d", + [TEGRA_POWERGATE_VENC] = "venc", + [TEGRA_POWERGATE_PCIE] = "pcie", + [TEGRA_POWERGATE_MPE] = "mpe", + [TEGRA_POWERGATE_CPU1] = "cpu1", + [TEGRA_POWERGATE_CPU2] = "cpu2", + [TEGRA_POWERGATE_CPU3] = "cpu3", + [TEGRA_POWERGATE_CPU0] = "cpu0", + [TEGRA_POWERGATE_C0NC] = "c0nc", + [TEGRA_POWERGATE_SOR] = "sor", + [TEGRA_POWERGATE_DIS] = "dis", + [TEGRA_POWERGATE_DISB] = "disb", + [TEGRA_POWERGATE_XUSBA] = "xusba", + [TEGRA_POWERGATE_XUSBB] = "xusbb", + [TEGRA_POWERGATE_XUSBC] = "xusbc", + [TEGRA_POWERGATE_VIC] = "vic", + [TEGRA_POWERGATE_IRAM] = "iram", + [TEGRA_POWERGATE_NVDEC] = "nvdec", + [TEGRA_POWERGATE_NVJPG] = "nvjpg", + [TEGRA_POWERGATE_AUD] = "aud", + [TEGRA_POWERGATE_DFD] = "dfd", +}; + +static const struct tegra_pmc_soc tegra210b01_pmc_soc = { + .supports_core_domain = false, + .num_powergates = ARRAY_SIZE(tegra210b01_powergates), + .powergates = tegra210b01_powergates, + .num_cpu_powergates = ARRAY_SIZE(tegra210_cpu_powergates), + .cpu_powergates = tegra210_cpu_powergates, + .has_tsense_reset = true, + .has_gpu_clamps = true, + .needs_mbist_war = false, + .has_io_pad_wren = true, + .maybe_tz_only = true, + .num_io_pads = ARRAY_SIZE(tegra210_io_pads), + .io_pads = tegra210_io_pads, + .num_io_pad_vctrls = ARRAY_SIZE(tegra210_io_pad_vctrls), + .io_pad_vctrls = tegra210_io_pad_vctrls, + .num_pin_descs = ARRAY_SIZE(tegra210_pin_descs), + .pin_descs = tegra210_pin_descs, + .regs = &tegra20_pmc_regs, + .init = tegra20_pmc_init, + .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, + .powergate_set = tegra114_powergate_set, + .irq_set_wake = tegra210_pmc_irq_set_wake, + .irq_set_type = tegra210_pmc_irq_set_type, + .reset_sources = tegra210_reset_sources, + .num_reset_sources = ARRAY_SIZE(tegra210_reset_sources), + .reset_levels = NULL, + .num_reset_levels = 0, + .num_wake_events = ARRAY_SIZE(tegra210_wake_events), + .wake_events = tegra210_wake_events, + .pmc_clks_data = tegra_pmc_clks_data, + .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data), + .has_blink_output = true, + .has_usb_sleepwalk = true, + .has_single_mmio_aperture = true, +}; + static const struct tegra_io_pad_soc tegra186_io_pads[] = { TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x74, 0x78, "csia"), TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x74, 0x78, "csib"), @@ -4919,6 +4980,7 @@ static const struct of_device_id tegra_pmc_match[] = { { .compatible = "nvidia,tegra194-pmc", .data = &tegra194_pmc_soc }, { .compatible = "nvidia,tegra186-pmc", .data = &tegra186_pmc_soc }, { .compatible = "nvidia,tegra210-pmc", .data = &tegra210_pmc_soc }, + { .compatible = "nvidia,tegra210b01-pmc", .data = &tegra210b01_pmc_soc }, { .compatible = "nvidia,tegra132-pmc", .data = &tegra124_pmc_soc }, { .compatible = "nvidia,tegra124-pmc", .data = &tegra124_pmc_soc }, { .compatible = "nvidia,tegra114-pmc", .data = &tegra114_pmc_soc }, From 98442683d8584feab37b1ae26c8ce31318790c44 Mon Sep 17 00:00:00 2001 From: Aaron Kling Date: Mon, 27 Jul 2026 20:57:35 -0500 Subject: [PATCH 107/176] soc/tegra: fuse: Support revision B01 Previously, all supported SoCs only used the A major revision. The Tegra210B01 SoC incremented the major revision. Add support for this. Signed-off-by: Aaron Kling Reviewed-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/fuse-tegra.c | 1 + drivers/soc/tegra/fuse/tegra-apbmisc.c | 51 ++++++++++++++++---------- include/soc/tegra/fuse.h | 1 + 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index b8c8ccf80056..04075e2b6434 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -34,6 +34,7 @@ static const char *tegra_revision_name[TEGRA_REVISION_MAX] = { [TEGRA_REVISION_A03] = "A03", [TEGRA_REVISION_A03p] = "A03 prime", [TEGRA_REVISION_A04] = "A04", + [TEGRA_REVISION_B01] = "B01", }; static const char *tegra_platform_name[TEGRA_PLATFORM_MAX] = { diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 6af69ccaa295..a4fb0ecd15cf 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -167,30 +167,41 @@ static const struct of_device_id apbmisc_match[] __initconst = { void __init tegra_init_revision(void) { - u8 chip_id, minor_rev; + u8 chip_id, major_rev, minor_rev; chip_id = tegra_get_chip_id(); + major_rev = tegra_get_major_rev(); minor_rev = tegra_get_minor_rev(); - switch (minor_rev) { - case 1: - tegra_sku_info.revision = TEGRA_REVISION_A01; - break; - case 2: - tegra_sku_info.revision = TEGRA_REVISION_A02; - break; - case 3: - if (chip_id == TEGRA20 && (tegra_fuse_read_spare(18) || - tegra_fuse_read_spare(19))) - tegra_sku_info.revision = TEGRA_REVISION_A03p; - else - tegra_sku_info.revision = TEGRA_REVISION_A03; - break; - case 4: - tegra_sku_info.revision = TEGRA_REVISION_A04; - break; - default: - tegra_sku_info.revision = TEGRA_REVISION_UNKNOWN; + if (major_rev > 1) { + switch (minor_rev) { + case 1: + tegra_sku_info.revision = TEGRA_REVISION_B01; + break; + default: + tegra_sku_info.revision = TEGRA_REVISION_UNKNOWN; + } + } else { + switch (minor_rev) { + case 1: + tegra_sku_info.revision = TEGRA_REVISION_A01; + break; + case 2: + tegra_sku_info.revision = TEGRA_REVISION_A02; + break; + case 3: + if (chip_id == TEGRA20 && (tegra_fuse_read_spare(18) || + tegra_fuse_read_spare(19))) + tegra_sku_info.revision = TEGRA_REVISION_A03p; + else + tegra_sku_info.revision = TEGRA_REVISION_A03; + break; + case 4: + tegra_sku_info.revision = TEGRA_REVISION_A04; + break; + default: + tegra_sku_info.revision = TEGRA_REVISION_UNKNOWN; + } } tegra_sku_info.sku_id = tegra_fuse_read_early(FUSE_SKU_INFO); diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h index c4f7a1b97c54..14822f981fec 100644 --- a/include/soc/tegra/fuse.h +++ b/include/soc/tegra/fuse.h @@ -33,6 +33,7 @@ enum tegra_revision { TEGRA_REVISION_A03, TEGRA_REVISION_A03p, TEGRA_REVISION_A04, + TEGRA_REVISION_B01, TEGRA_REVISION_MAX, }; From 968c438e7d28a2905571502ef103d06bd6c2c4ab Mon Sep 17 00:00:00 2001 From: Aaron Kling Date: Mon, 27 Jul 2026 20:57:36 -0500 Subject: [PATCH 108/176] soc/tegra: fuse: speedo-tegra210: Support revision B01 Tegra210B01 has a separate set of skus and speedo tables Based-on: https://gitlab.com/nvidia/nv-tegra/linux-5.10/-/commit/8555ef4988d3b39d91791794825c354b3c9377ba Based-on-patch-by: Alex Frid Signed-off-by: Aaron Kling Reviewed-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/speedo-tegra210.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/soc/tegra/fuse/speedo-tegra210.c b/drivers/soc/tegra/fuse/speedo-tegra210.c index 06c2bcbee573..699751f4bd0c 100644 --- a/drivers/soc/tegra/fuse/speedo-tegra210.c +++ b/drivers/soc/tegra/fuse/speedo-tegra210.c @@ -65,7 +65,25 @@ static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info, sku_info->gpu_speedo_id = 0; *threshold = THRESHOLD_INDEX_0; - if (sku_info->revision >= TEGRA_REVISION_A02) { + if (sku_info->revision >= TEGRA_REVISION_B01) { + sku_info->gpu_speedo_id = 1; + + switch (sku) { + case 0x00: /* Engineering SKU */ + case 0x01: /* Engineering SKU */ + case 0x83: + break; + + case 0x87: + sku_info->cpu_speedo_id = 3; + break; + + default: + pr_err("Tegra210B01: unknown SKU %#04x\n", sku); + /* Using the default for the error case */ + break; + } + } else if (sku_info->revision >= TEGRA_REVISION_A02) { switch (sku) { case 0x00: /* Engineering SKU */ case 0x01: /* Engineering SKU */ @@ -154,7 +172,7 @@ void __init tegra210_init_speedo_data(struct tegra_sku_info *sku_info) speedo_revision = get_speedo_revision(); pr_info("Speedo Revision %u\n", speedo_revision); - if (speedo_revision >= 3) { + if (sku_info->revision == TEGRA_REVISION_B01 || speedo_revision >= 3) { sku_info->cpu_speedo_value = cpu_speedo[0]; sku_info->gpu_speedo_value = cpu_speedo[2]; sku_info->soc_speedo_value = soc_speedo[0]; From c842922f5ff229c9df2a2be56327c36aced7a3a7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 21 Aug 2026 10:52:25 +0200 Subject: [PATCH 109/176] soc/tegra: pmc: Make sure clk_init_data is fully initialized The clk_init_data structure contains several mutually-exclusive members for different methods to specify the possible parents of a clock, prompting drivers to initialize only the members they need. However, not initializing all members may cause subtle issues, which are only exposed when CONFIG_INIT_STACK_ALL_PATTERN or CONFIG_INIT_STACK_NONE is enabled. Make sure all members are fully initialized, to avoid such bugs, and to prevent future breakage when converting drivers to a different method for specifying the parents. Signed-off-by: Geert Uytterhoeven Reviewed-by: Brian Masney Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 92704d39dc5f..0f4e46020084 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -2695,7 +2695,7 @@ tegra_pmc_clk_out_register(struct tegra_pmc *pmc, const struct pmc_clk_init_data *data, unsigned long offset) { - struct clk_init_data init; + struct clk_init_data init = {}; struct pmc_clk *pmc_clk; pmc_clk = devm_kzalloc(pmc->dev, sizeof(*pmc_clk), GFP_KERNEL); @@ -2753,7 +2753,7 @@ tegra_pmc_clk_gate_register(struct tegra_pmc *pmc, const char *name, const char *parent_name, unsigned long offset, u32 shift) { - struct clk_init_data init; + struct clk_init_data init = {}; struct pmc_clk_gate *gate; gate = devm_kzalloc(pmc->dev, sizeof(*gate), GFP_KERNEL); From 4eaed7ea6ab36e1160d660b05551702c36dfed6c Mon Sep 17 00:00:00 2001 From: Yuho Choi Date: Sat, 1 Aug 2026 19:50:08 -0400 Subject: [PATCH 110/176] soc/tegra: flowctrl: Release OF node reference on error tegra_flowctrl_init() obtains a reference from of_find_matching_node() and currently releases it only after of_address_to_resource() succeeds. Release the reference before checking the resource conversion result so the error path is balanced as well. Fixes: 1fd09e5d884a ("soc/tegra: Add initial flowctrl support for Tegra132/210") Signed-off-by: Yuho Choi Signed-off-by: Thierry Reding --- drivers/soc/tegra/flowctrl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/soc/tegra/flowctrl.c b/drivers/soc/tegra/flowctrl.c index 221202db3313..d5c3af586d31 100644 --- a/drivers/soc/tegra/flowctrl.c +++ b/drivers/soc/tegra/flowctrl.c @@ -195,11 +195,14 @@ static int __init tegra_flowctrl_init(void) np = of_find_matching_node(NULL, tegra_flowctrl_match); if (np) { - if (of_address_to_resource(np, 0, &res) < 0) { + int err = of_address_to_resource(np, 0, &res); + + of_node_put(np); + + if (err < 0) { pr_err("failed to get flowctrl register\n"); return -ENXIO; } - of_node_put(np); } else if (IS_ENABLED(CONFIG_ARM)) { /* * Hardcoded fallback for 32-bit Tegra From f7b2b6acf658be412b0c4746d07d210a9e18f13b Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Wed, 30 Sep 2026 00:50:31 +0100 Subject: [PATCH 111/176] soc: samsung: exynos-pmu: fix error paths in cpuhotplug/idle states setup The setup_cpuhp_and_cpuidle() initialisation sequence currently ignores the return values of cpuhp_setup_state(), cpu_pm_register_notifier(), and register_reboot_notifier(). If any of these registrations fail during probe() routine, the driver returns 0, leaving the driver partially configured. Furthermore, if anything after setup_cpuhp_and_cpuidle() fails in probe() routine, for instance devm_mfd_add_devices(), the probe() lacks an error path and leaves notifiers and cpu hotplug states registered. Introduce variables for the cpu hotplug state IDs in exynos_pmu_context struct, that should be initialised to CPUHP_INVALID by default. Check all return codes in setup_cpuhp_and_cpuidle(), and add an error path to remove registered states on failure. Finally, add destroy_cpuhp_and_cpuidle() helper to safely tear down notifiers and cpu hotplug states. Reported-by: Sashiko Closes: https://sashiko.dev/#/patchset/20260513-exynos850-cpuhotplug-v4-0-54fec5f65362@linaro.org?part=3 Fixes: 78b72897a5c8 ("soc: samsung: exynos-pmu: Enable CPU Idle for gs101") Cc: stable@vger.kernel.org Signed-off-by: Alexey Klimov Link: https://patch.msgid.link/20260930-exynos-pmu-cpuhp-idle-fixes-v3-1-4269d8425978@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/soc/samsung/exynos-pmu.c | 61 +++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c index f5fcdde9750e..759b246eccf9 100644 --- a/drivers/soc/samsung/exynos-pmu.c +++ b/drivers/soc/samsung/exynos-pmu.c @@ -38,6 +38,8 @@ struct exynos_pmu_context { unsigned long *in_cpuhp; bool sys_insuspend; bool sys_inreboot; + int cpuhp_prepare_state; + int cpuhp_online_state; }; void __iomem *pmu_base_addr; @@ -461,16 +463,55 @@ static int setup_cpuhp_and_cpuidle(struct device *dev) gs101_cpuhp_pmu_online(cpu); /* register CPU hotplug callbacks */ - cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "soc/exynos-pmu:prepare", - gs101_cpuhp_pmu_online, NULL); + pmu_context->cpuhp_prepare_state = CPUHP_INVALID; + pmu_context->cpuhp_online_state = CPUHP_INVALID; - cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "soc/exynos-pmu:online", - NULL, gs101_cpuhp_pmu_offline); + ret = cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "soc/exynos-pmu:prepare", + gs101_cpuhp_pmu_online, NULL); + if (ret < 0) + return ret; + + pmu_context->cpuhp_prepare_state = ret; + + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "soc/exynos-pmu:online", + NULL, gs101_cpuhp_pmu_offline); + if (ret < 0) + goto clean_cpuhp_state_prepare; + + pmu_context->cpuhp_online_state = ret; /* register CPU PM notifiers for cpuidle */ - cpu_pm_register_notifier(&gs101_cpu_pm_notifier); - register_reboot_notifier(&exynos_cpupm_reboot_nb); - return 0; + ret = cpu_pm_register_notifier(&gs101_cpu_pm_notifier); + if (ret) + goto clean_cpuhp_states; + + ret = register_reboot_notifier(&exynos_cpupm_reboot_nb); + if (!ret) + /* Success */ + return ret; + + cpu_pm_unregister_notifier(&gs101_cpu_pm_notifier); + +clean_cpuhp_states: + cpuhp_remove_state(pmu_context->cpuhp_online_state); + pmu_context->cpuhp_online_state = CPUHP_INVALID; + +clean_cpuhp_state_prepare: + cpuhp_remove_state(pmu_context->cpuhp_prepare_state); + pmu_context->cpuhp_prepare_state = CPUHP_INVALID; + + return ret; +} + +static void destroy_cpuhp_and_cpuidle(void) +{ + cpu_pm_unregister_notifier(&gs101_cpu_pm_notifier); + unregister_reboot_notifier(&exynos_cpupm_reboot_nb); + + if (pmu_context->cpuhp_prepare_state != CPUHP_INVALID) + cpuhp_remove_state(pmu_context->cpuhp_prepare_state); + if (pmu_context->cpuhp_online_state != CPUHP_INVALID) + cpuhp_remove_state(pmu_context->cpuhp_online_state); } static int exynos_pmu_probe(struct platform_device *pdev) @@ -544,8 +585,12 @@ static int exynos_pmu_probe(struct platform_device *pdev) ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, exynos_pmu_devs, ARRAY_SIZE(exynos_pmu_devs), NULL, 0, NULL); - if (ret) + if (ret) { + if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_cpuhp) + destroy_cpuhp_and_cpuidle(); + return ret; + } if (devm_of_platform_populate(dev)) dev_err(dev, "Error populating children, reboot and poweroff might not work properly\n"); From 682df6e2330123019fcdb9f6122f34a395082356 Mon Sep 17 00:00:00 2001 From: Jaidev Shastri Date: Mon, 21 Sep 2026 21:07:23 -0400 Subject: [PATCH 112/176] soc: samsung: exynos-pmu: order pmu_base_addr before the pmu_context gate exynos_sys_powerdown_conf() returns early while pmu_context is NULL and otherwise programs the PMU through pmu_raw_writel(), which uses the separate global pmu_base_addr. exynos_pmu_probe() maps pmu_base_addr and stores pmu_context afterwards, both with plain stores, and the reader loads both plainly. Neither the two stores nor the two loads are ordered. The callers are the Exynos cpuidle AFTR path and the suspend path on 32-bit Exynos, which run on other CPUs, so a caller that sees pmu_context before pmu_base_addr writes the power-down configuration through a NULL base. Publish pmu_context with smp_store_release() and read it with smp_load_acquire(). Found with MBCheck, a static herd7-based memory consistency checker. Signed-off-by: Jaidev Shastri Link: https://patch.msgid.link/20260921-mb-exynos-pmu-v1-1-4babb522ce0d@vt.edu Signed-off-by: Krzysztof Kozlowski --- drivers/soc/samsung/exynos-pmu.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c index 759b246eccf9..c78fbd16c4ad 100644 --- a/drivers/soc/samsung/exynos-pmu.c +++ b/drivers/soc/samsung/exynos-pmu.c @@ -61,11 +61,14 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode) { unsigned int i; const struct exynos_pmu_data *pmu_data; + struct exynos_pmu_context *ctx; - if (!pmu_context || !pmu_context->pmu_data) + /* Pairs with the smp_store_release() in exynos_pmu_probe(). */ + ctx = smp_load_acquire(&pmu_context); + if (!ctx || !ctx->pmu_data) return; - pmu_data = pmu_context->pmu_data; + pmu_data = ctx->pmu_data; if (pmu_data->powerdown_conf) pmu_data->powerdown_conf(mode); @@ -518,6 +521,7 @@ static int exynos_pmu_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct regmap_config pmu_regmcfg; + struct exynos_pmu_context *ctx; struct regmap *regmap; struct resource *res; int ret; @@ -526,12 +530,19 @@ static int exynos_pmu_probe(struct platform_device *pdev) if (IS_ERR(pmu_base_addr)) return PTR_ERR(pmu_base_addr); - pmu_context = devm_kzalloc(&pdev->dev, - sizeof(struct exynos_pmu_context), - GFP_KERNEL); - if (!pmu_context) + ctx = devm_kzalloc(&pdev->dev, sizeof(struct exynos_pmu_context), + GFP_KERNEL); + if (!ctx) return -ENOMEM; + /* + * exynos_sys_powerdown_conf() gates on pmu_context and then writes + * through pmu_base_addr, which is a separate global. Publish the + * context with release semantics so that the mapping is visible to + * a CPU that passes the gate. + */ + smp_store_release(&pmu_context, ctx); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; From b6fe0b2ca99c29d211cacffd17bcd0e2f69049c2 Mon Sep 17 00:00:00 2001 From: Sreeshankar K Date: Mon, 24 Aug 2026 15:01:44 +0000 Subject: [PATCH 113/176] dt-bindings: arm: qcom,ids: Add SoC ID for SM7250 Add the ID for the Qualcomm SM7250 SoC. Signed-off-by: Sreeshankar K Acked-by: Krzysztof Kozlowski Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260824150156.1310-2-sreeshankar0910@gmail.com Signed-off-by: Bjorn Andersson --- include/dt-bindings/arm/qcom,ids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index 2cf433f61d5e..b63e4a0b8e54 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -209,6 +209,7 @@ #define QCOM_ID_IPQ8172 397 #define QCOM_ID_IPQ8173 398 #define QCOM_ID_IPQ8174 399 +#define QCOM_ID_SM7250 400 #define QCOM_ID_IPQ6018 402 #define QCOM_ID_IPQ6028 403 #define QCOM_ID_SDM429W 416 From 4f7b5ac0c4d841d9356af9f9d2698ab6caecf529 Mon Sep 17 00:00:00 2001 From: Sreeshankar K Date: Mon, 24 Aug 2026 15:01:45 +0000 Subject: [PATCH 114/176] soc: qcom: socinfo: Add SM7250 SoC ID Add SoC ID for Qualcomm SM7250 SoC. Signed-off-by: Sreeshankar K Reviewed-by: Dmitry Baryshkov Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20260824150156.1310-3-sreeshankar0910@gmail.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 1836e226a294..63ee5cd561a2 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -450,6 +450,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(IPQ8172) }, { qcom_board_id(IPQ8173) }, { qcom_board_id(IPQ8174) }, + { qcom_board_id(SM7250) }, { qcom_board_id(IPQ6018) }, { qcom_board_id(IPQ6028) }, { qcom_board_id(SDM429W) }, From 34da43344c042bf276abace745d7cf6af27699df Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Fri, 21 Aug 2026 12:06:17 +0530 Subject: [PATCH 115/176] soc: qcom: geni-se: Fix endian conversion for serial_protocol comparison serial_protocol is declared as __le16 in struct se_fw_hdr, but was decoded with le32_to_cpu(). On big-endian systems the extra byte swap causes the field to always compare unequal to the protocol argument, so no firmware segment is ever selected. Use le16_to_cpu() to match the field width. Fixes: d4bf06592ad6 ("soc: qcom: geni-se: Add support to load QUP SE Firmware via Linux subsystem") Cc: stable@vger.kernel.org Reviewed-by: Konrad Dybcio Signed-off-by: Viken Dadhaniya Link: https://lore.kernel.org/r/20260821-fix-write-to-read-only-firmware-buffer-v3-1-43e6a3abd651@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 873bfbd6b2b7..1d6e6611441d 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -1298,7 +1298,7 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct if (le32_to_cpu(sefw->magic) != SE_MAGIC_NUM || le32_to_cpu(sefw->version) != 1) continue; - if (le32_to_cpu(sefw->serial_protocol) != protocol) + if (le16_to_cpu(sefw->serial_protocol) != protocol) continue; if (fw_size % 2 != 0) { From 570b3d23794bff9ba8dd99dbd5293dc158a7dbce Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Fri, 21 Aug 2026 12:06:18 +0530 Subject: [PATCH 116/176] soc: qcom: geni-se: Widen fw_size to u32 to prevent wrap-around fw_size is read from the 16-bit fw_size_in_items field and incremented when the count is odd. If fw_size_in_items == 0xffff the increment wraps to 0 as a u16, making the bounds check below pass for a firmware segment whose actual size was not validated. Widen fw_size to u32 so the increment never wraps. Fixes: d4bf06592ad6 ("soc: qcom: geni-se: Add support to load QUP SE Firmware via Linux subsystem") Cc: stable@vger.kernel.org Reviewed-by: Konrad Dybcio Signed-off-by: Viken Dadhaniya Link: https://lore.kernel.org/r/20260821-fix-write-to-read-only-firmware-buffer-v3-2-43e6a3abd651@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 1d6e6611441d..54c0a66d6dd6 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -1248,7 +1248,7 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct struct se_fw_hdr *sefw; u32 fw_end, cfg_idx_end, cfg_val_end; u32 prog_ram_depth; - u16 fw_size; + u32 fw_size; int i; if (!fw || fw->size < sizeof(struct elf32_hdr)) From 091269da39eb0a52cca2549e9ba522ab7b841ff2 Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Fri, 21 Aug 2026 12:06:19 +0530 Subject: [PATCH 117/176] soc: qcom: geni-se: Fix fw_end computed before round-up; propagate size to caller fw_end was computed from the raw fw_size_in_items, before the odd-word round-up. A segment with an odd word count could pass the bounds check at the unrounded value but then be copied one word past the validated limit. Move fw_end (and the cfg_{idx,val}_end) calculations to after the round-up so they always reflect the true copy extent. The caller geni_load_se_fw() re-read hdr->fw_size_in_items for the memcpy_toio() length, bypassing the validated and rounded value established by geni_find_protocol_fw(). Add a fw_size_out output parameter and use it in the caller. Fixes: d4bf06592ad6 ("soc: qcom: geni-se: Add support to load QUP SE Firmware via Linux subsystem") Cc: stable@vger.kernel.org Reviewed-by: Konrad Dybcio Signed-off-by: Viken Dadhaniya Link: https://lore.kernel.org/r/20260821-fix-write-to-read-only-firmware-buffer-v3-3-43e6a3abd651@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 54c0a66d6dd6..11ca8223fbcd 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -1230,6 +1230,8 @@ EXPORT_SYMBOL_GPL(geni_se_resources_init); * @se: Pointer to the serial engine structure. * @fw: Pointer to the firmware image. * @protocol: Expected serial engine protocol type. + * @fw_size_out: Non-NULL output parameter; receives the rounded, validated + * firmware word count on success. * * Identifies the appropriate firmware image or configuration required for a * specific communication protocol instance running on a Qualcomm GENI @@ -1239,7 +1241,8 @@ EXPORT_SYMBOL_GPL(geni_se_resources_init); * Return: pointer to a valid 'struct se_fw_hdr' if found, or NULL otherwise. */ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct firmware *fw, - enum geni_se_protocol_type protocol) + enum geni_se_protocol_type protocol, + u32 *fw_size_out) { struct device *dev = se->dev; const struct elf32_hdr *ehdr; @@ -1289,11 +1292,6 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct sefw = (struct se_fw_hdr *)(fw->data + phdr->p_offset); fw_size = le16_to_cpu(sefw->fw_size_in_items); - fw_end = le16_to_cpu(sefw->fw_offset) + fw_size * sizeof(u32); - cfg_idx_end = le16_to_cpu(sefw->cfg_idx_offset) + - le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u8); - cfg_val_end = le16_to_cpu(sefw->cfg_val_offset) + - le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u32); if (le32_to_cpu(sefw->magic) != SE_MAGIC_NUM || le32_to_cpu(sefw->version) != 1) continue; @@ -1306,6 +1304,12 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct sefw->fw_size_in_items = cpu_to_le16(fw_size); } + fw_end = le16_to_cpu(sefw->fw_offset) + fw_size * sizeof(u32); + cfg_idx_end = le16_to_cpu(sefw->cfg_idx_offset) + + le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u8); + cfg_val_end = le16_to_cpu(sefw->cfg_val_offset) + + le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u32); + prog_ram_depth = FIELD_GET(PROG_RAM_DEPTH_MSK, readl_relaxed(se->base + SE_HW_PARAM_2)); if (fw_size >= prog_ram_depth) { @@ -1320,6 +1324,7 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct continue; } + *fw_size_out = fw_size; return sefw; } @@ -1430,11 +1435,11 @@ static int geni_load_se_fw(struct geni_se *se, const struct firmware *fw, { const u32 *fw_data, *cfg_val_arr; const u8 *cfg_idx_arr; - u32 i, reg_value; + u32 i, reg_value, fw_size_in_items; int ret; struct se_fw_hdr *hdr; - hdr = geni_find_protocol_fw(se, fw, protocol); + hdr = geni_find_protocol_fw(se, fw, protocol, &fw_size_in_items); if (!hdr) return -EINVAL; @@ -1511,7 +1516,7 @@ static int geni_load_se_fw(struct geni_se *se, const struct firmware *fw, /* Program RAM address space. */ memcpy_toio(se->base + SE_GENI_CFG_RAMN, fw_data, - le16_to_cpu(hdr->fw_size_in_items) * sizeof(u32)); + fw_size_in_items * sizeof(u32)); /* Put default values on GENI's output pads. */ writel_relaxed(0x1, se->base + GENI_FORCE_DEFAULT_REG); From f38399670d0701ede4f8da397807aa64d7dc98be Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Fri, 21 Aug 2026 12:06:20 +0530 Subject: [PATCH 118/176] soc: qcom: geni-se: Fix write to read-only firmware buffer geni_find_protocol_fw() casts fw->data to a non-const struct se_fw_hdr pointer and writes back the rounded-up fw_size value: sefw->fw_size_in_items = cpu_to_le16(fw_size); The firmware subsystem maps the firmware blob read-only. Writing through the cast pointer causes a level-3 permission fault on AArch64 and crashes the kernel during driver probe. The write-back is no longer necessary: geni_find_protocol_fw() now propagates the rounded size to the caller via fw_size_out. Remove the write-back and make sefw (and the hdr pointer in the caller) const-correct. Fixes: d4bf06592ad6 ("soc: qcom: geni-se: Add support to load QUP SE Firmware via Linux subsystem") Cc: stable@vger.kernel.org Reviewed-by: Konrad Dybcio Signed-off-by: Viken Dadhaniya Link: https://lore.kernel.org/r/20260821-fix-write-to-read-only-firmware-buffer-v3-4-43e6a3abd651@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 11ca8223fbcd..6ac2bdc16984 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -1238,17 +1238,17 @@ EXPORT_SYMBOL_GPL(geni_se_resources_init); * controller. Validates the firmware size against the hardware PROG_RAM_DEPTH * read from SE_HW_PARAM_2. * - * Return: pointer to a valid 'struct se_fw_hdr' if found, or NULL otherwise. + * Return: pointer to a valid 'const struct se_fw_hdr' if found, or NULL otherwise. */ -static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct firmware *fw, - enum geni_se_protocol_type protocol, - u32 *fw_size_out) +static const struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct firmware *fw, + enum geni_se_protocol_type protocol, + u32 *fw_size_out) { struct device *dev = se->dev; const struct elf32_hdr *ehdr; const struct elf32_phdr *phdrs; const struct elf32_phdr *phdr; - struct se_fw_hdr *sefw; + const struct se_fw_hdr *sefw; u32 fw_end, cfg_idx_end, cfg_val_end; u32 prog_ram_depth; u32 fw_size; @@ -1290,7 +1290,7 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct if (phdr->p_filesz < sizeof(struct se_fw_hdr)) continue; - sefw = (struct se_fw_hdr *)(fw->data + phdr->p_offset); + sefw = (const struct se_fw_hdr *)(fw->data + phdr->p_offset); fw_size = le16_to_cpu(sefw->fw_size_in_items); if (le32_to_cpu(sefw->magic) != SE_MAGIC_NUM || le32_to_cpu(sefw->version) != 1) @@ -1299,10 +1299,8 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct if (le16_to_cpu(sefw->serial_protocol) != protocol) continue; - if (fw_size % 2 != 0) { + if (fw_size % 2 != 0) fw_size++; - sefw->fw_size_in_items = cpu_to_le16(fw_size); - } fw_end = le16_to_cpu(sefw->fw_offset) + fw_size * sizeof(u32); cfg_idx_end = le16_to_cpu(sefw->cfg_idx_offset) + @@ -1437,15 +1435,15 @@ static int geni_load_se_fw(struct geni_se *se, const struct firmware *fw, const u8 *cfg_idx_arr; u32 i, reg_value, fw_size_in_items; int ret; - struct se_fw_hdr *hdr; + const struct se_fw_hdr *hdr; hdr = geni_find_protocol_fw(se, fw, protocol, &fw_size_in_items); if (!hdr) return -EINVAL; - fw_data = (const u32 *)((u8 *)hdr + le16_to_cpu(hdr->fw_offset)); + fw_data = (const u32 *)((const u8 *)hdr + le16_to_cpu(hdr->fw_offset)); cfg_idx_arr = (const u8 *)hdr + le16_to_cpu(hdr->cfg_idx_offset); - cfg_val_arr = (const u32 *)((u8 *)hdr + le16_to_cpu(hdr->cfg_val_offset)); + cfg_val_arr = (const u32 *)((const u8 *)hdr + le16_to_cpu(hdr->cfg_val_offset)); ret = geni_icc_set_bw(se); if (ret) From c708b7141c6a9fd9d20b827a4fefc24ed65327ce Mon Sep 17 00:00:00 2001 From: bui duc phuc Date: Wed, 19 Aug 2026 17:26:30 +0700 Subject: [PATCH 119/176] soc: qcom: llcc-qcom: Handle errors from optional IRQ lookup platform_get_irq_optional() returns a positive IRQ number on success or a negative error code on failure. For an optional IRQ, -ENXIO indicates that no optional IRQ is available. Other errors, such as -EPROBE_DEFER and -EINVAL, should be propagated so that the caller can handle them appropriately. Propagate negative errors other than -ENXIO. Signed-off-by: bui duc phuc Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260819102630.68991-1-phucduc.bui@gmail.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index d60431ace50f..5e45a10663c4 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -5657,6 +5657,10 @@ static int qcom_llcc_probe(struct platform_device *pdev) } drv_data->ecc_irq = platform_get_irq_optional(pdev, 0); + if (drv_data->ecc_irq < 0 && drv_data->ecc_irq != -ENXIO) + return dev_err_probe(&pdev->dev, drv_data->ecc_irq, + "failed to get IRQ resource\n"); + drv_data->edac_reg_offset = cfg->edac_reg_offset; drv_data->ecc_irq_configured = cfg->irq_configured; drv_data->dev = dev; From c7c56b6ec077cb96657494b8c18c2c78625035b1 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 19 Aug 2026 10:23:28 +0300 Subject: [PATCH 120/176] soc: qcom: pmic_glink: Fix device access from worker during suspend For historical reasons, the GLINK smem interrupt is registered with IRRQF_NO_SUSPEND flag set, which is the underlying problem here, since the incoming messages can be delivered during late suspend and early resume. In this specific case, the pmic_glink_altmode_worker() currently gets scheduled on the system_wq which can be scheduled to run while devices are still suspended. This proves to be a problem when a Type-C retimer, switch or mux that is controlled over a bus like I2C, because the I2C controller is suspended. This has been proven to be the case on the X Elite boards where such retimers (ParadeTech PS8830) are used in order to handle Type-C orientation and altmode configuration. The following warning is thrown: [ 35.134876] i2c i2c-4: Transfer while suspended [ 35.143865] WARNING: CPU: 0 PID: 99 at drivers/i2c/i2c-core.h:56 __i2c_transfer+0xb4/0x57c [i2c_core] [ 35.352879] Workqueue: events pmic_glink_altmode_worker [pmic_glink_altmode] [ 35.360179] pstate: 61400005 (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--) [ 35.455242] Call trace: [ 35.457826] __i2c_transfer+0xb4/0x57c [i2c_core] (P) [ 35.463086] i2c_transfer+0x98/0xf0 [i2c_core] [ 35.467713] i2c_transfer_buffer_flags+0x54/0x88 [i2c_core] [ 35.473502] regmap_i2c_write+0x20/0x48 [regmap_i2c] [ 35.478659] _regmap_raw_write_impl+0x780/0x944 [ 35.483401] _regmap_bus_raw_write+0x60/0x7c [ 35.487848] _regmap_write+0x134/0x184 [ 35.491773] regmap_write+0x54/0x78 [ 35.495418] ps883x_set+0x58/0xec [ps883x] [ 35.499688] ps883x_sw_set+0x60/0x84 [ps883x] [ 35.504223] typec_switch_set+0x48/0x74 [typec] [ 35.508952] pmic_glink_altmode_worker+0x44/0x1fc [pmic_glink_altmode] [ 35.515712] process_scheduled_works+0x1a0/0x2d0 [ 35.520525] worker_thread+0x2a8/0x3c8 [ 35.524449] kthread+0xfc/0x184 [ 35.527749] ret_from_fork+0x10/0x20 The proper solution here should be to not deliver these kind of messages during system suspend at all, or at least make it configurable per glink client. But simply dropping the IRQF_NO_SUSPEND flag entirely will break other clients. The final shape of the rework of the pmic glink driver in order to fulfill both the filtering of the messages that need to be able to wake-up the system and the queueing of these messages until the system has properly resumed is still being discussed and it is planned as a future effort. Meanwhile, the stop-gap fix here is to schedule the pmic glink altmode worker on the system_freezable_wq instead of the system_wq. This will result in the altmode worker not being scheduled to run until the devices are resumed first, which will give the controllers like I2C a chance to resume before the transfer is requested. Reported-by: Johan Hovold Closes: https://lore.kernel.org/lkml/Z1CCVjEZMQ6hJ-wK@hovoldconsulting.com/ Fixes: 080b4e24852b ("soc: qcom: pmic_glink: Introduce altmode support") Cc: stable@vger.kernel.org # 6.3 Reviewed-by: Caleb Connolly Reviewed-by: Bjorn Andersson Signed-off-by: Abel Vesa Signed-off-by: Abel Vesa Link: https://lore.kernel.org/r/20260819-b4-soc-qcom-pmic-glink-fix-device-access-on-worker-while-suspended-v3-1-169b00e0d9d4@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pmic_glink_altmode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index 13c434f8d03a..465e5d2316a0 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -451,7 +451,7 @@ static void pmic_glink_altmode_sc8180xp_notify(struct pmic_glink_altmode *altmod alt_port->mode = mode; alt_port->hpd_state = hpd_state; alt_port->hpd_irq = hpd_irq; - schedule_work(&alt_port->work); + queue_work(system_freezable_wq, &alt_port->work); } #define SC8280XP_DPAM_MASK 0x3f @@ -502,7 +502,7 @@ static void pmic_glink_altmode_sc8280xp_notify(struct pmic_glink_altmode *altmod alt_port->tbt_data = *tbt; } - schedule_work(&alt_port->work); + queue_work(system_freezable_wq, &alt_port->work); } static void pmic_glink_altmode_callback(const void *data, size_t len, void *priv) From b2370c0f8960dbe9bc0b5169944c58239964a738 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Sun, 2 Aug 2026 18:58:53 +0530 Subject: [PATCH 121/176] soc: qcom: rpmh-internal: fix kernel-doc issues in rpmh-internal.h kernel-doc emits two warnings for rpmh-internal.h: Warning: drivers/soc/qcom/rpmh-internal.h:136 struct member 'ver' not described in 'rsc_drv' Warning: drivers/soc/qcom/rpmh-internal.h:136 struct member 'regs' not described in 'rsc_drv' Fix them by adding @ver and @regs entries to the struct rsc_drv documentation. While at it, add a missing kernel-doc block for struct rsc_ver, and update the remaining struct kernel-doc comments (struct tcs_group, struct rpmh_request, struct rpmh_ctrlr, struct rsc_drv) to use the 'struct name -' format documented in Documentation/doc-guide/kernel-doc.rst. No functional impact. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Maulik Shah Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260802-b4b4-rpmh-kdoc-v1-1-0f5026293d9a@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmh-internal.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h index e3cf1beff803..39441a25af9b 100644 --- a/drivers/soc/qcom/rpmh-internal.h +++ b/drivers/soc/qcom/rpmh-internal.h @@ -20,7 +20,7 @@ struct rsc_drv; /** - * struct tcs_group: group of Trigger Command Sets (TCS) to send state requests + * struct tcs_group - group of Trigger Command Sets (TCS) to send state requests * to the controller * * @drv: The controller. @@ -53,7 +53,7 @@ struct tcs_group { }; /** - * struct rpmh_request: the message to be sent to rpmh-rsc + * struct rpmh_request - the message to be sent to rpmh-rsc * * @msg: the request * @cmd: the payload that will be part of the @msg @@ -70,7 +70,7 @@ struct rpmh_request { }; /** - * struct rpmh_ctrlr: our representation of the controller + * struct rpmh_ctrlr - our representation of the controller * * @cache: the list of cached requests * @cache_lock: synchronize access to the cache data @@ -84,13 +84,19 @@ struct rpmh_ctrlr { struct list_head batch_cache; }; +/** + * struct rsc_ver - Hardware version of the RSC controller. + * + * @major: Major version number. + * @minor: Minor version number. + */ struct rsc_ver { u32 major; u32 minor; }; /** - * struct rsc_drv: the Direct Resource Voter (DRV) of the + * struct rsc_drv - the Direct Resource Voter (DRV) of the * Resource State Coordinator controller (RSC) * * @name: Controller identifier. @@ -116,6 +122,8 @@ struct rsc_ver { * slot * @client: Handle to the DRV's client. * @dev: RSC device. + * @ver: HW version of the RSC controller. + * @regs: Pointer to the register offset table for this version. */ struct rsc_drv { const char *name; From 5e1fccb482a9b92e465fe1fd689f4e8cefd15a08 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Sun, 2 Aug 2026 18:58:54 +0530 Subject: [PATCH 122/176] soc: qcom: rpmh: fix kernel-doc issues in rpmh.c Six documentation issues in rpmh.c: - struct batch_cache_req has a typo in its title: 'batch catch' should be 'batch cache'. Fix it. - __rpmh_write(), rpmh_write_async(), rpmh_write(), rpmh_write_batch() and rpmh_invalidate() use 'name: title' format instead of the 'name() - title' format documented in Documentation/doc-guide/kernel-doc.rst. Fix all of them. - rpmh_tx_done() has no kernel-doc comment. Add one describing its purpose as the RSC driver callback for active-only transfer completion. - __rpmh_write(), rpmh_write_async(), rpmh_write() and rpmh_write_batch() are missing Return: tags. Add them. - struct cache_req uses 'struct name:' format instead of the 'struct name -' format documented in Documentation/doc-guide/kernel-doc.rst. Fix it. - rpmh_write_batch() has an inaccurate description: it says requests are sent 'without caching' and that SLEEP/WAKE_ONLY requests are sent as fire-and-forget. In reality, SLEEP/WAKE_ONLY requests are cached in batch_cache and returned immediately; they are only sent to the controller later by rpmh_flush(). Fix the description. No functional impact. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Maulik Shah Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260802-b4b4-rpmh-kdoc-v1-2-0f5026293d9a@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmh.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index f881c4c757ec..360242a315e3 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -41,7 +41,7 @@ #define ctrlr_to_drv(ctrlr) container_of(ctrlr, struct rsc_drv, client) /** - * struct cache_req: the request object for caching + * struct cache_req - the request object for caching * * @addr: the address of the resource * @sleep_val: the sleep vote @@ -56,7 +56,7 @@ struct cache_req { }; /** - * struct batch_cache_req - An entry in our batch catch + * struct batch_cache_req - An entry in our batch cache * * @list: linked list obj * @count: number of messages @@ -76,6 +76,14 @@ static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev) return &drv->client; } +/** + * rpmh_tx_done() - Signal the completion of a RPMH transfer. + * @msg: The request that was previously sent. + * + * Called by the RSC driver when an active-only transfer is complete. + * Signals any blocking waiter and frees the message if it was dynamically + * allocated. + */ void rpmh_tx_done(const struct tcs_request *msg) { struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request, @@ -157,7 +165,7 @@ static struct cache_req *cache_rpm_request(struct rpmh_ctrlr *ctrlr, } /** - * __rpmh_write: Cache and send the RPMH request + * __rpmh_write() - Cache and send the RPMH request. * * @dev: The device making the request * @state: Active/Sleep request type @@ -166,6 +174,8 @@ static struct cache_req *cache_rpm_request(struct rpmh_ctrlr *ctrlr, * Cache the RPMH request and send if the state is ACTIVE_ONLY. * SLEEP/WAKE_ONLY requests are not sent to the controller at * this time. Use rpmh_flush() to send them to the controller. + * + * Return: 0 on success, negative error code on failure. */ static int __rpmh_write(const struct device *dev, enum rpmh_state state, struct rpmh_request *rpm_msg) @@ -248,7 +258,7 @@ int rpmh_read(const struct device *dev, struct tcs_cmd *cmd) EXPORT_SYMBOL_GPL(rpmh_read); /** - * rpmh_write_async: Write a set of RPMH commands + * rpmh_write_async() - Write a set of RPMH commands. * * @dev: The device making the request * @state: Active/sleep set @@ -257,6 +267,8 @@ EXPORT_SYMBOL_GPL(rpmh_read); * * Write a set of RPMH commands, the order of commands is maintained * and will be sent as a single shot. + * + * Return: 0 on success, negative error code on failure. */ int rpmh_write_async(const struct device *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 n) @@ -280,7 +292,7 @@ int rpmh_write_async(const struct device *dev, enum rpmh_state state, EXPORT_SYMBOL_GPL(rpmh_write_async); /** - * rpmh_write: Write a set of RPMH commands and block until response + * rpmh_write() - Write a set of RPMH commands and block until response * * @dev: The device making the request * @state: Active/sleep set @@ -288,6 +300,8 @@ EXPORT_SYMBOL_GPL(rpmh_write_async); * @n: The number of elements in @cmd * * May sleep. Do not call from atomic contexts. + * + * Return: 0 on success, negative error code on failure. */ int rpmh_write(const struct device *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 n) @@ -342,7 +356,7 @@ static int flush_batch(struct rpmh_ctrlr *ctrlr) } /** - * rpmh_write_batch: Write multiple sets of RPMH commands and wait for the + * rpmh_write_batch() - Write multiple sets of RPMH commands and wait for the * batch to finish. * * @dev: the device making the request @@ -350,13 +364,15 @@ static int flush_batch(struct rpmh_ctrlr *ctrlr) * @cmd: The payload data * @n: The array of count of elements in each batch, 0 terminated. * - * Write a request to the RSC controller without caching. If the request - * state is ACTIVE, then the requests are treated as completion request - * and sent to the controller immediately. The function waits until all the - * commands are complete. If the request was to SLEEP or WAKE_ONLY, then the - * request is sent as fire-n-forget and no ack is expected. + * If the request state is ACTIVE_ONLY, the requests are sent to the + * controller immediately and the function waits until all commands are + * complete. If the state is SLEEP or WAKE_ONLY, the requests are cached + * and the function returns immediately; they are sent to the controller + * later by rpmh_flush(). * * May sleep. Do not call from atomic contexts for ACTIVE_ONLY requests. + * + * Return: 0 on success, negative error code on failure. */ int rpmh_write_batch(const struct device *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 *n) @@ -519,7 +535,7 @@ int rpmh_flush(struct rpmh_ctrlr *ctrlr) } /** - * rpmh_invalidate: Invalidate sleep and wake sets in batch_cache + * rpmh_invalidate() - Invalidate sleep and wake sets in batch_cache * * @dev: The device making the request * From 8f206c85f3c383605a5bc3640f9e5aa1d9d8a51a Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Sun, 2 Aug 2026 18:58:55 +0530 Subject: [PATCH 123/176] soc: qcom: rpmh-rsc: fix kernel-doc issues in rpmh-rsc.c Two documentation issues in rpmh-rsc.c: - rpmh_rsc_pd_callback() has a copy-paste title 'Check if any of the AMCs are busy' which describes rpmh_rsc_ctrlr_is_busy() not this function. Fix the title to accurately describe what this callback does: flush sleep/wake TCS data on PM domain power-off. - rpmh_rsc_cpu_pm_callback() has the same copy-paste title 'Check if any of the AMCs are busy'. Fix the title to accurately describe what this callback does: flush sleep/wake TCS data when all CPUs enter power down. No functional impact. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Maulik Shah Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260802-b4b4-rpmh-kdoc-v1-3-0f5026293d9a@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmh-rsc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index f881af35ecfc..c4542318eac4 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -842,7 +842,7 @@ void rpmh_rsc_write_next_wakeup(struct rsc_drv *drv) } /** - * rpmh_rsc_cpu_pm_callback() - Check if any of the AMCs are busy. + * rpmh_rsc_cpu_pm_callback() - CPU PM notifier to flush sleep/wake TCS data. * @nfb: Pointer to the notifier block in struct rsc_drv. * @action: CPU_PM_ENTER, CPU_PM_ENTER_FAILED, or CPU_PM_EXIT. * @v: Unused @@ -923,7 +923,7 @@ static int rpmh_rsc_cpu_pm_callback(struct notifier_block *nfb, } /** - * rpmh_rsc_pd_callback() - Check if any of the AMCs are busy. + * rpmh_rsc_pd_callback() - PM domain callback to flush sleep/wake TCS data. * @nfb: Pointer to the genpd notifier block in struct rsc_drv. * @action: GENPD_NOTIFY_PRE_OFF, GENPD_NOTIFY_OFF, GENPD_NOTIFY_PRE_ON or GENPD_NOTIFY_ON. * @v: Unused From 5909d98ef551f13efcd4e2a366eebffaf3c29d3b Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 12 Aug 2026 14:29:00 +0800 Subject: [PATCH 124/176] soc: qcom: ubwc: Add configuration for Hawi Add UBWC configuration data for the Hawi platform, which uses UBWC 7.0 and enables the required flags and highest bank bit settings. This allows drivers to query the correct UBWC capabilities on Hawi. Also add UBWC 7.0 support to the version tag helper so that qcom_ubwc_version_tag() returns the correct tag for UBWC 7.0. Signed-off-by: Wangao Wang Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260812-ubwc_for_hawi_maili-v1-1-c29edecb3bd8@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ubwc_config.c | 8 ++++++++ include/linux/soc/qcom/ubwc.h | 3 +++ 2 files changed, 11 insertions(+) diff --git a/drivers/soc/qcom/ubwc_config.c b/drivers/soc/qcom/ubwc_config.c index 23901a4c51f7..428a3d1038c8 100644 --- a/drivers/soc/qcom/ubwc_config.c +++ b/drivers/soc/qcom/ubwc_config.c @@ -105,6 +105,13 @@ static const struct qcom_ubwc_cfg_data milos_data = { .highest_bank_bit = 15, }; +static const struct qcom_ubwc_cfg_data ubwc_7_0_hbb16 = { + .ubwc_enc_version = UBWC_7_0, + .flags = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .highest_bank_bit = 16, +}; + static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = { { .compatible = "qcom,apq8016", .data = &no_ubwc_data }, { .compatible = "qcom,apq8026", .data = &no_ubwc_data }, @@ -112,6 +119,7 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = { { .compatible = "qcom,apq8096", .data = &ubwc_1_0_hbb15 }, { .compatible = "qcom,eliza", .data = &ubwc_5_0_hbb15 }, { .compatible = "qcom,glymur", .data = &glymur_data}, + { .compatible = "qcom,hawi", .data = &ubwc_7_0_hbb16 }, { .compatible = "qcom,kaanapali", .data = &ubwc_6_0_hbb16 }, { .compatible = "qcom,mahua", .data = &glymur_data }, { .compatible = "qcom,milos", .data = &milos_data }, diff --git a/include/linux/soc/qcom/ubwc.h b/include/linux/soc/qcom/ubwc.h index f3a70360b177..b09ae05cbeae 100644 --- a/include/linux/soc/qcom/ubwc.h +++ b/include/linux/soc/qcom/ubwc.h @@ -36,6 +36,7 @@ struct qcom_ubwc_cfg_data { #define UBWC_4_3 0x40030000 #define UBWC_5_0 0x50000000 #define UBWC_6_0 0x60000000 +#define UBWC_7_0 0x70000000 #if IS_ENABLED(CONFIG_QCOM_UBWC_CONFIG) const struct qcom_ubwc_cfg_data *qcom_ubwc_config_get_data(void); @@ -108,6 +109,8 @@ static inline u32 qcom_ubwc_swizzle(const struct qcom_ubwc_cfg_data *cfg) static inline u32 qcom_ubwc_version_tag(const struct qcom_ubwc_cfg_data *cfg) { + if (cfg->ubwc_enc_version >= UBWC_7_0) + return 6; if (cfg->ubwc_enc_version >= UBWC_6_0) return 5; if (cfg->ubwc_enc_version >= UBWC_5_0) From 77a717ae0e07303d4ece8382cbf203e0c0c5c25f Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 12 Aug 2026 14:29:01 +0800 Subject: [PATCH 125/176] soc: qcom: ubwc: Add configuration for Maili Describe the Universal Bandwidth Compression (UBWC) configuration for the Maili platform. Maili reuses the hawi UBWC configuration. Signed-off-by: Wangao Wang Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260812-ubwc_for_hawi_maili-v1-2-c29edecb3bd8@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ubwc_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/ubwc_config.c b/drivers/soc/qcom/ubwc_config.c index 428a3d1038c8..e593386920ed 100644 --- a/drivers/soc/qcom/ubwc_config.c +++ b/drivers/soc/qcom/ubwc_config.c @@ -122,6 +122,7 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = { { .compatible = "qcom,hawi", .data = &ubwc_7_0_hbb16 }, { .compatible = "qcom,kaanapali", .data = &ubwc_6_0_hbb16 }, { .compatible = "qcom,mahua", .data = &glymur_data }, + { .compatible = "qcom,maili", .data = &ubwc_7_0_hbb16, }, { .compatible = "qcom,milos", .data = &milos_data }, { .compatible = "qcom,msm8226", .data = &no_ubwc_data }, { .compatible = "qcom,msm8916", .data = &no_ubwc_data }, From f3c95a76d2ee9c17034e9d96917b37d194dd9f91 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 13 Aug 2026 10:09:21 +0300 Subject: [PATCH 126/176] soc: qcom: smem: Fix signedness bug in smem_dram_parse() The "ver" variable is type "enum ddr_info_version". Enum types are dependent on the compiler but in practical terms here, "ver" is basically an unsigned int. It needs to be signed for the -EINVAL to be handled correctly. Fixes: 1d234eeafc56 ("soc: qcom: smem: Expose DDR data from SMEM") Signed-off-by: Dan Carpenter Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/an1toQ-acGR0kOWj@stanley.mountain Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem_dramc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/smem_dramc.c b/drivers/soc/qcom/smem_dramc.c index 24ccdfdc2b3d..497513c95308 100644 --- a/drivers/soc/qcom/smem_dramc.c +++ b/drivers/soc/qcom/smem_dramc.c @@ -448,7 +448,7 @@ struct dentry *smem_dram_parse(struct qcom_smem *smem, struct device *dev) return ERR_PTR(-ENODATA); ver = smem_dram_infer_struct_version(actual_size); - if (ver < 0) { + if ((int)ver < 0) { /* Some SoCs don't provide data that's useful for us */ return ERR_PTR(-ENODATA); } else if (ver == INFO_UNKNOWN) { From bb5c846a74ca119679fdc3241888a3de179d02c2 Mon Sep 17 00:00:00 2001 From: Hongyan Xu Date: Thu, 6 Aug 2026 14:05:40 +0800 Subject: [PATCH 127/176] soc: qcom: apr: clean up failed service registrations apr_add_device() publishes a service in svcs_idr before parsing the optional protection domain and registering the device. If device registration fails, put_device() frees the apr_device while its service remains in the IDR. A received packet can then dereference that stale entry. The property error path also leaves the service and allocation behind. Split device_register() into device_initialize() and device_add() so every pre-registration error can safely drop the device reference. Remove the service from the IDR on all failures after publication, then drain the RX workqueue before dropping the device reference. This prevents an in-flight lookup from outliving the device. Fixes: 6adba21eb434 ("soc: qcom: Add APR bus driver") Signed-off-by: Hongyan Xu Link: https://lore.kernel.org/r/20260806060541.820-1-getshell@seu.edu.cn Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/apr.c | 50 ++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c index 2073edb416a4..2d5645ff9919 100644 --- a/drivers/soc/qcom/apr.c +++ b/drivers/soc/qcom/apr.c @@ -411,31 +411,35 @@ static int apr_add_device(struct device *dev, struct device_node *np, if (np) snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np); - switch (apr->type) { - case PR_TYPE_APR: - dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, - domain_id, svc_id); - break; - case PR_TYPE_GPR: - dev_set_name(&adev->dev, "gprsvc:%s:%x:%x", adev->name, - domain_id, svc_id); - break; - default: - break; - } - adev->dev.bus = &aprbus; adev->dev.parent = dev; adev->dev.of_node = np; adev->dev.release = apr_dev_release; adev->dev.driver = NULL; + device_initialize(&adev->dev); + + switch (apr->type) { + case PR_TYPE_APR: + ret = dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, + domain_id, svc_id); + break; + case PR_TYPE_GPR: + ret = dev_set_name(&adev->dev, "gprsvc:%s:%x:%x", adev->name, + domain_id, svc_id); + break; + default: + ret = -EINVAL; + break; + } + if (ret) + goto out_put_device; spin_lock(&apr->svcs_lock); ret = idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); spin_unlock(&apr->svcs_lock); if (ret < 0) { dev_err(dev, "idr_alloc failed: %d\n", ret); - goto out; + goto out_put_device; } /* Protection domain is optional, it does not exist on older platforms */ @@ -443,18 +447,26 @@ static int apr_add_device(struct device *dev, struct device_node *np, 1, &adev->service_path); if (ret < 0 && ret != -EINVAL) { dev_err(dev, "Failed to read second value of qcom,protection-domain\n"); - goto out; + goto out_remove_idr; } dev_info(dev, "Adding APR/GPR dev: %s\n", dev_name(&adev->dev)); - ret = device_register(&adev->dev); + ret = device_add(&adev->dev); if (ret) { - dev_err(dev, "device_register failed: %d\n", ret); - put_device(&adev->dev); + dev_err(dev, "device_add failed: %d\n", ret); + goto out_remove_idr; } -out: + return 0; + +out_remove_idr: + spin_lock(&apr->svcs_lock); + idr_remove(&apr->svcs_idr, svc_id); + spin_unlock(&apr->svcs_lock); + flush_workqueue(apr->rxwq); +out_put_device: + put_device(&adev->dev); return ret; } From 7cabc842d0f2540f1d7734e7bb41d740560a036f Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 23 Jun 2026 09:59:31 +0100 Subject: [PATCH 128/176] soc: qcom: smp2p: fix __iomem annotation on entry->value pointer The entry->value is passed to readl() so should be marked __iomem so remove these sparse warnings by marking it __iomem and do the relevant casting to ensure no further warnings: drivers/soc/qcom/smp2p.c:280:64: warning: incorrect type in argument 1 (different address spaces) drivers/soc/qcom/smp2p.c:280:64: expected void const volatile [noderef] __iomem *addr drivers/soc/qcom/smp2p.c:280:64: got unsigned int [usertype] *value drivers/soc/qcom/smp2p.c:318:34: warning: incorrect type in argument 1 (different address spaces) drivers/soc/qcom/smp2p.c:318:34: expected void const volatile [noderef] __iomem *addr drivers/soc/qcom/smp2p.c:318:34: got unsigned int [usertype] *value drivers/soc/qcom/smp2p.c:446:26: warning: incorrect type in argument 1 (different address spaces) drivers/soc/qcom/smp2p.c:446:26: expected void const volatile [noderef] __iomem *addr drivers/soc/qcom/smp2p.c:446:26: got unsigned int [usertype] *value drivers/soc/qcom/smp2p.c:501:33: warning: incorrect type in argument 1 (different address spaces) drivers/soc/qcom/smp2p.c:501:33: expected void const volatile [noderef] __iomem *addr drivers/soc/qcom/smp2p.c:501:33: got unsigned int [usertype] *value drivers/soc/qcom/smp2p.c:504:26: warning: incorrect type in argument 2 (different address spaces) drivers/soc/qcom/smp2p.c:504:26: expected void volatile [noderef] __iomem *addr drivers/soc/qcom/smp2p.c:504:26: got unsigned int [usertype] *value Signed-off-by: Ben Dooks Link: https://lore.kernel.org/r/20260623085931.589735-1-ben.dooks@codethink.co.uk Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smp2p.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index 6f07fef40ce8..3104e31f91c9 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -102,7 +102,7 @@ struct smp2p_entry { struct qcom_smp2p *smp2p; const char *name; - u32 *value; + u32 __iomem *value; u32 last_value; struct irq_domain *domain; @@ -276,7 +276,7 @@ static void qcom_smp2p_start_in(struct qcom_smp2p *smp2p) list_for_each_entry(entry, &smp2p->inbound, node) { memcpy(buf, in->entries[i].name, sizeof(buf)); if (!strcmp(buf, entry->name)) { - entry->value = &in->entries[i].value; + entry->value = (u32 __iomem *)&in->entries[i].value; entry->last_value = readl(entry->value); break; } @@ -302,7 +302,7 @@ static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p) list_for_each_entry(entry, &smp2p->inbound, node) { memcpy(buf, in->entries[i].name, sizeof(buf)); if (!strcmp(buf, entry->name)) { - entry->value = &in->entries[i].value; + entry->value = (u32 __iomem *)&in->entries[i].value; break; } } @@ -528,7 +528,7 @@ static int qcom_smp2p_outbound_entry(struct qcom_smp2p *smp2p, memcpy(out->entries[out->valid_entries].name, buf, SMP2P_MAX_ENTRY_NAME); /* Make the logical entry reference the physical value */ - entry->value = &out->entries[out->valid_entries].value; + entry->value = (u32 __iomem *)&out->entries[out->valid_entries].value; out->valid_entries++; From c373463f8c08d46dd6a0d3b385037da790e186e7 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Thu, 3 Sep 2026 01:09:48 +0530 Subject: [PATCH 129/176] firmware: qcom: scm: Use devm_of_reserved_mem_device_init() Switch from of_reserved_mem_device_init() to the new resource managed devm_of_reserved_mem_device_init() so that the reserved memory region is released automatically on probe failure or device unbind. This eliminates the err_rmem cleanup label and the need to call of_reserved_mem_device_release() explicitly on error paths. Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Mukesh Ojha Link: https://lore.kernel.org/r/20260902193948.1999595-1-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index c44c63e1c20d..7085595582e8 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2845,17 +2845,15 @@ static int qcom_scm_probe(struct platform_device *pdev) if (ret) return ret; - ret = of_reserved_mem_device_init(scm->dev); + ret = devm_of_reserved_mem_device_init(scm->dev); if (ret && ret != -ENODEV) return dev_err_probe(scm->dev, ret, "Failed to setup the reserved memory region for TZ mem\n"); ret = qcom_tzmem_enable(scm->dev); - if (ret) { - ret = dev_err_probe(scm->dev, ret, - "Failed to enable the TrustZone memory allocator\n"); - goto err_rmem; - } + if (ret) + return dev_err_probe(scm->dev, ret, + "Failed to enable the TrustZone memory allocator\n"); memset(&pool_config, 0, sizeof(pool_config)); pool_config.initial_size = 0; @@ -2863,11 +2861,9 @@ static int qcom_scm_probe(struct platform_device *pdev) pool_config.max_size = SZ_256K; scm->mempool = devm_qcom_tzmem_pool_new(scm->dev, &pool_config); - if (IS_ERR(scm->mempool)) { - ret = dev_err_probe(scm->dev, PTR_ERR(scm->mempool), - "Failed to create the SCM memory pool\n"); - goto err_rmem; - } + if (IS_ERR(scm->mempool)) + return dev_err_probe(scm->dev, PTR_ERR(scm->mempool), + "Failed to create the SCM memory pool\n"); ret = qcom_scm_query_waitq_count(scm); scm->wq_cnt = ret < 0 ? QCOM_SCM_DEFAULT_WAITQ_COUNT : ret; @@ -2943,10 +2939,6 @@ static int qcom_scm_probe(struct platform_device *pdev) qcom_scm_gunyah_wdt_init(scm); return 0; - -err_rmem: - of_reserved_mem_device_release(scm->dev); - return ret; } static void qcom_scm_shutdown(struct platform_device *pdev) From 618aedff70fbecb502a3f312a8b292e8478a93c7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 6 Aug 2026 12:35:15 +0200 Subject: [PATCH 130/176] firmware: QCOM interfaces should depend on ARCH_QCOM The various Qualcomm firmware interfaces are only present on Qualcomm systems. Hence add dependencies on ARCH_QCOM, to prevent asking the user about them when configuring a kernel without Qualcomm SoC support. Make QCOM_PAS invisible instead, as it is already selected by its users when needed. Signed-off-by: Geert Uytterhoeven Reviewed-by: Sumit Garg Acked-by: Konrad Dybcio Link: https://lore.kernel.org/r/888efe8e63b6a18fae4acd5a90a1e0e69dcdf2ca.1786012495.git.geert+renesas@glider.be Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig index c7f8413ab996..691db0ded8e8 100644 --- a/drivers/firmware/qcom/Kconfig +++ b/drivers/firmware/qcom/Kconfig @@ -7,7 +7,7 @@ menu "Qualcomm firmware drivers" config QCOM_PAS - tristate "Qualcomm generic PAS interface driver" + tristate "Qualcomm generic PAS interface driver" if COMPILE_TEST help Enable the generic Peripheral Authentication Service (PAS) provided by the firmware. It acts as the common layer with different TZ @@ -16,6 +16,7 @@ config QCOM_PAS config QCOM_PAS_TEE tristate "Qualcomm PAS TEE interface driver" + depends on ARCH_QCOM || COMPILE_TEST select QCOM_PAS depends on TEE depends on !CPU_BIG_ENDIAN @@ -26,6 +27,7 @@ config QCOM_PAS_TEE config QCOM_SCM tristate "Qualcomm PAS SCM interface driver" + depends on ARCH_QCOM || COMPILE_TEST select QCOM_PAS select QCOM_TZMEM default y if ARCH_QCOM From 3ae4bd9cdcd25bb8ac9b9951934bedd404935545 Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Thu, 3 Sep 2026 09:43:09 +0800 Subject: [PATCH 131/176] soc: qcom: ubwcg: Add Nord UBWC config Map qcom,nord to glymur_data in qcom_ubwc_configs[], since Nord shares Glymur's UBWC capabilities. Signed-off-by: Gourav Kumar Signed-off-by: Shawn Guo Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260903014309.314962-1-shengchao.guo@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ubwc_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/ubwc_config.c b/drivers/soc/qcom/ubwc_config.c index e593386920ed..36c90f72943f 100644 --- a/drivers/soc/qcom/ubwc_config.c +++ b/drivers/soc/qcom/ubwc_config.c @@ -136,6 +136,7 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = { { .compatible = "qcom,msm8976", .data = &no_ubwc_data }, { .compatible = "qcom,msm8996", .data = &ubwc_1_0_hbb15 }, { .compatible = "qcom,msm8998", .data = &ubwc_1_0_hbb15 }, + { .compatible = "qcom,nord", .data = &glymur_data }, { .compatible = "qcom,qcm2290", .data = &ubwc_0_0_hbb15, }, { .compatible = "qcom,qcm6490", .data = &ubwc_3_1_hbb14, }, { .compatible = "qcom,qcs8300", .data = &ubwc_4_0_hbb16, }, From a5c8d6d13a0417e19bb0c771f28474d997c21d11 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 2 Sep 2026 14:57:06 +0300 Subject: [PATCH 132/176] MAINTAINERS: add Abel as reviewer for linux-arm-msm As agreed with Bjorn and Konrad off-list, I'm stepping up as reviewer for Qualcomm SoCs support. Signed-off-by: Abel Vesa Acked-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260902-maintainers-qcom-add-reviewer-v1-1-82d6126df520@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3a19da74d00c..e51a130e33f0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3432,6 +3432,7 @@ F: include/linux/soc/qcom/ ARM/QUALCOMM SUPPORT M: Bjorn Andersson M: Konrad Dybcio +R: Abel Vesa L: linux-arm-msm@vger.kernel.org S: Maintained C: irc://irc.oftc.net/linux-msm From 72961dcd01a295caf6fbf9d1cc5bd3482dd91b07 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 31 Jul 2026 19:59:46 +0200 Subject: [PATCH 133/176] firmware: qcom: scm: Allow QSEECOM on Yoga Slim 7x Gen11 Allow the use of QSEECOM on the Glymur-based Lenovo Yoga Slim 7x Gen11, as there seem to be no issues with the firmware that would mandate disabling it. Reviewed-by: Abel Vesa Reviewed-by: Dmitry Baryshkov Signed-off-by: Konrad Dybcio Tested-by: Oleg Keri Link: https://lore.kernel.org/r/20260731-topic-yoga_submission-v2-3-f1887031da4f@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 7085595582e8..40d3cb847f8d 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2320,6 +2320,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "lenovo,thinkpad-t14s" }, { .compatible = "lenovo,thinkpad-x13s", }, { .compatible = "lenovo,yoga-slim7x" }, + { .compatible = "lenovo,yoga-slim7x-gen11" }, { .compatible = "medion,sprchrgd14s1" }, { .compatible = "microsoft,arcata", }, { .compatible = "microsoft,surface-pro-12in", }, From 50c98ff64feb77bebd995719afe84421db12b553 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Wed, 23 Sep 2026 02:37:32 +0530 Subject: [PATCH 134/176] dt-bindings: arm: qcom,ids: Add SoC ID for SM8975 Add the ID for the Qualcomm SM8975 SoC which represents the Hawi platform. Signed-off-by: Mukesh Ojha Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20260923-hawi-socinfo-v1-1-f0d1aaee9323@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- include/dt-bindings/arm/qcom,ids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index b63e4a0b8e54..4259f8960447 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -301,6 +301,7 @@ #define QCOM_ID_QCS9075 676 #define QCOM_ID_QCS615 680 #define QCOM_ID_SA8797P 690 +#define QCOM_ID_SM8975 707 #define QCOM_ID_CQ7790M 731 #define QCOM_ID_CQ7790S 732 #define QCOM_ID_CQ2390M 756 From 87802d4dc4850bf27b3955ee9162b1e52c99da1a Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 15 Sep 2026 20:54:24 -0500 Subject: [PATCH 135/176] firmware: qcom: scm: Allow QSEECOM on Asus Zenbook A14 (UX3407NA) In line with other Glymur-based machines, the Asus Zenbook A14 (UX3407NA) exposes EFI variables through the "uefisecapp". Add it to the QSEECOM allowlist to enable this access. Reviewed-by: Dmitry Baryshkov Signed-off-by: Bjorn Andersson Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20260915-zenbook-dts-v2-3-41de8669a7a8@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 40d3cb847f8d..162444f8bc8b 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2302,6 +2302,7 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_send); static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "asus,vivobook-s15" }, { .compatible = "asus,vivobook-s15-x1p4" }, + { .compatible = "asus,zenbook-a14-ux3407na" }, { .compatible = "asus,zenbook-a14-ux3407qa" }, { .compatible = "asus,zenbook-a14-ux3407ra" }, { .compatible = "asus,zenbook-a16-ux3607oa" }, From 06bf7462ed7ffe823e595b6de939023bedaa1c61 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Wed, 23 Sep 2026 02:37:33 +0530 Subject: [PATCH 136/176] soc: qcom: socinfo: Add SM8975 SoC ID Add SoC ID for Qualcomm SM8975 which represents the Hawi platform. Signed-off-by: Mukesh Ojha Link: https://patch.msgid.link/20260923-hawi-socinfo-v1-2-f0d1aaee9323@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 63ee5cd561a2..ddc717382797 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -542,6 +542,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QCS9075) }, { qcom_board_id(QCS615) }, { qcom_board_id(SA8797P) }, + { qcom_board_id(SM8975) }, { qcom_board_id(CQ7790M) }, { qcom_board_id(CQ7790S) }, { qcom_board_id(CQ2390M) }, From 60d4a6edea9ec617725db6dd1e66d96a13bc8d0a Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Tue, 22 Sep 2026 01:26:34 +0530 Subject: [PATCH 137/176] firmware: qcom: tzmem: Use DO_ONCE_SLEEPABLE() in qcom_tzmem_enable() qcom_tzmem_enable() is called from qcom_scm_probe() in a sleepable process context. The helper it wraps, qcom_tzmem_init(), calls qcom_scm_shm_bridge_enable() -> qcom_scm_call(), which invokes might_sleep() and later acquires the qcom_scm_lock mutex via __scm_smc_do(). DO_ONCE() takes the once_lock spinlock with IRQs disabled, so invoking qcom_tzmem_init() from inside DO_ONCE() runs a sleepable call chain in atomic context. CONFIG_DEBUG_ATOMIC_SLEEP=y catches this on boot: BUG: sleeping function called from invalid context at drivers/firmware/qcom/qcom_scm.c:334 in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 49, name: kworker/u16:2 ... __might_resched+0x148/0x24c __might_sleep+0x48/0x7c qcom_scm_call+0x30/0xc0 __qcom_scm_is_call_available+0x98/0x100 qcom_scm_shm_bridge_enable+0x60/0xbc qcom_tzmem_enable+0xf8/0x118 qcom_scm_probe+0x2d0/0x680 [ BUG: Invalid wait context ] ... kworker/u16:2/49 is trying to lock: ffffa83e8a485e38 (qcom_scm_lock){....}-{4:4}, at: __scm_smc_do+0x70/0x488 Switch to DO_ONCE_SLEEPABLE(), which guards the one-shot init with a mutex-style path (__do_once_sleepable_start/done) that is safe to hold across sleeping callees. All callers of qcom_tzmem_enable() are in process context (driver probe), so this is safe. Fixes: 9941fe8a04f3 ("firmware: qcom: scm: Fix tzmem state on probe retry") Reported-by: Marek Szyprowski Closes: https://lore.kernel.org/lkml/5ea74dd3-7471-4c7c-9242-c2005312b1ab@samsung.com/ Reviewed-by: Bartosz Golaszewski Signed-off-by: Mukesh Ojha Link: https://patch.msgid.link/20260921195636.1925869-1-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_tzmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/qcom_tzmem.c b/drivers/firmware/qcom/qcom_tzmem.c index 0fd9581275f1..ebcdee3c5975 100644 --- a/drivers/firmware/qcom/qcom_tzmem.c +++ b/drivers/firmware/qcom/qcom_tzmem.c @@ -518,7 +518,7 @@ int qcom_tzmem_enable(struct device *dev) static int result; qcom_tzmem_dev = dev; - DO_ONCE(qcom_tzmem_do_init, &result); + DO_ONCE_SLEEPABLE(qcom_tzmem_do_init, &result); return result; } EXPORT_SYMBOL_GPL(qcom_tzmem_enable); From 324103eb65ba26704c2293d9daaa15c0dc022930 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Tue, 22 Sep 2026 01:26:35 +0530 Subject: [PATCH 138/176] firmware: qcom_scm: handle empty PAS resource table The PAS resource-table query may successfully return a zero-sized table. kmemdup() with a zero length returns ZERO_SIZE_PTR, which is stored in rproc->table_ptr. The remoteproc core then dereferences this invalid pointer while processing resources. Treat a zero-sized result as an absent resource table and return NULL after releasing the TrustZone memory buffer. This allows the remoteproc core to skip resource-table processing. Fixes: 8b9d2050cfa0 ("firmware: qcom_scm: Add qcom_scm_pas_get_rsc_table() to get resource table") Signed-off-by: Mukesh Ojha Reviewed-by: Bartosz Golaszewski Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20260921195636.1925869-2-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 162444f8bc8b..7bc97096d63b 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -865,6 +865,14 @@ static void *__qcom_scm_pas_get_rsc_table2(struct device *dev, goto free_input_rt; } + *output_rt_size = size; + + /* A zero-sized table means that TrustZone has no resource table. */ + if (!size) { + tbl_ptr = NULL; + goto free_output_rt; + } + tbl_ptr = kmemdup(output_rt_tzm, size, GFP_KERNEL); if (!tbl_ptr) { qcom_tzmem_free(output_rt_tzm); @@ -872,7 +880,7 @@ static void *__qcom_scm_pas_get_rsc_table2(struct device *dev, goto free_input_rt; } - *output_rt_size = size; +free_output_rt: qcom_tzmem_free(output_rt_tzm); free_input_rt: From 57e43df2e426ac5561ee3832d425e1071772e963 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Tue, 22 Sep 2026 01:26:36 +0530 Subject: [PATCH 139/176] firmware: qcom_scm: align PAS resource table retry The initial PAS resource-table buffer can be too small. TrustZone returns the required size and the wrapper retries the SCM call. Although qcom_tzmem_alloc() aligns the allocated buffer, the size passed to TrustZone remained unaligned. Align the retry size to a page boundary so that both the buffer and its advertised size satisfy the PAS/TrustZone contract. Fixes: 8b9d2050cfa0 ("firmware: qcom_scm: Add qcom_scm_pas_get_rsc_table() to get resource table") Signed-off-by: Mukesh Ojha Reviewed-by: Bartosz Golaszewski Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20260921195636.1925869-3-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 7bc97096d63b..d309689de266 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -854,12 +854,14 @@ static void *__qcom_scm_pas_get_rsc_table2(struct device *dev, output_rt_tzm = __qcom_scm_pas_get_rsc_table(dev, ctx->pas_id, input_rt_tzm, input_rt_size, &size); - if (PTR_ERR(output_rt_tzm) == -EOVERFLOW) - /* Try again with the size requested by the TZ */ + if (PTR_ERR(output_rt_tzm) == -EOVERFLOW) { + /* Try again with a page-aligned size requested by the TZ. */ + size = PAGE_ALIGN(size); output_rt_tzm = __qcom_scm_pas_get_rsc_table(dev, ctx->pas_id, input_rt_tzm, input_rt_size, &size); + } if (IS_ERR(output_rt_tzm)) { ret = PTR_ERR(output_rt_tzm); goto free_input_rt; From 9b79d37cfacbd8b525c728bb6e0b00777e37293a Mon Sep 17 00:00:00 2001 From: Muzaffer Kadir Date: Mon, 21 Sep 2026 21:19:02 +0300 Subject: [PATCH 140/176] dt-bindings: firmware: qcom,scm: Document MSM8952 SCM Document the scm compatible for msm8952 SoC. Signed-off-by: Muzaffer Kadir Link: https://patch.msgid.link/20260921-msm8952-initial-support-v3-11-b96fd3fe298b@mainlining.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml index ecee5aef65a7..40a267c54b00 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -45,6 +45,7 @@ properties: - qcom,scm-msm8660 - qcom,scm-msm8916 - qcom,scm-msm8937 + - qcom,scm-msm8952 - qcom,scm-msm8953 - qcom,scm-msm8960 - qcom,scm-msm8974 @@ -153,6 +154,7 @@ allOf: - qcom,scm-msm8660 - qcom,scm-msm8916 - qcom,scm-msm8937 + - qcom,scm-msm8952 - qcom,scm-msm8953 - qcom,scm-msm8960 - qcom,scm-msm8974 @@ -199,6 +201,7 @@ allOf: - qcom,scm-msm8226 - qcom,scm-msm8916 - qcom,scm-msm8937 + - qcom,scm-msm8952 - qcom,scm-msm8953 - qcom,scm-msm8974 - qcom,scm-msm8976 From 012cfa80370d199bb1c946524594b982bf2a5c01 Mon Sep 17 00:00:00 2001 From: Muzaffer Kadir Date: Mon, 21 Sep 2026 21:19:05 +0300 Subject: [PATCH 141/176] soc: qcom: ubwc: Add UBWC config for MSM8952 MSM8952 uses Adreno 405 and predates ubwc just like MSM8939. Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Signed-off-by: Muzaffer Kadir Link: https://patch.msgid.link/20260921-msm8952-initial-support-v3-14-b96fd3fe298b@mainlining.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ubwc_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/ubwc_config.c b/drivers/soc/qcom/ubwc_config.c index 36c90f72943f..53c1df3ca641 100644 --- a/drivers/soc/qcom/ubwc_config.c +++ b/drivers/soc/qcom/ubwc_config.c @@ -130,6 +130,7 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = { { .compatible = "qcom,msm8937", .data = &ubwc_1_0_hbb14 }, { .compatible = "qcom,msm8929", .data = &no_ubwc_data }, { .compatible = "qcom,msm8939", .data = &no_ubwc_data }, + { .compatible = "qcom,msm8952", .data = &no_ubwc_data }, { .compatible = "qcom,msm8953", .data = &ubwc_1_0_hbb14 }, { .compatible = "qcom,msm8956", .data = &no_ubwc_data }, { .compatible = "qcom,msm8974", .data = &no_ubwc_data }, From 1cd31ba4f9bc87fe851b5894cb76da379709c95c Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 18 Sep 2026 22:18:32 +0800 Subject: [PATCH 142/176] soc: qcom: use assign_bit() where applicable Convert open-coded if/else with set_bit/clear_bit and their non-atomic __set_bit/__clear_bit variants to the assign_bit/__assign_bit API. Done with Coccinelle semantic patch: // set_bit -> clear_bit => assign_bit @@ expression cond, bit, addr; @@ -if (cond) - set_bit(bit, addr); -else - clear_bit(bit, addr); +assign_bit(bit, addr, cond); // clear_bit -> set_bit => assign_bit @@ expression cond, bit, addr; @@ -if (cond) - clear_bit(bit, addr); -else - set_bit(bit, addr); +assign_bit(bit, addr, !cond); Signed-off-by: Peng Fan Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Link: https://patch.msgid.link/20260918141833.3023124-1-peng.fan@oss.nxp.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smp2p.c | 10 ++-------- drivers/soc/qcom/smsm.c | 16 ++++------------ 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index 3104e31f91c9..01b8580c9f27 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -411,15 +411,9 @@ static int smp2p_set_irq_type(struct irq_data *irqd, unsigned int type) if (!(type & IRQ_TYPE_EDGE_BOTH)) return -EINVAL; - if (type & IRQ_TYPE_EDGE_RISING) - set_bit(irq, entry->irq_rising); - else - clear_bit(irq, entry->irq_rising); + assign_bit(irq, entry->irq_rising, type & IRQ_TYPE_EDGE_RISING); - if (type & IRQ_TYPE_EDGE_FALLING) - set_bit(irq, entry->irq_falling); - else - clear_bit(irq, entry->irq_falling); + assign_bit(irq, entry->irq_falling, type & IRQ_TYPE_EDGE_FALLING); return 0; } diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c index ac3c85a2597a..bb487bf6bf03 100644 --- a/drivers/soc/qcom/smsm.c +++ b/drivers/soc/qcom/smsm.c @@ -277,10 +277,8 @@ static void smsm_unmask_irq(struct irq_data *irqd) u32 val; /* Make sure our last cached state is up-to-date */ - if (readl(entry->remote_state) & BIT(irq)) - set_bit(irq, &entry->last_value); - else - clear_bit(irq, &entry->last_value); + assign_bit(irq, &entry->last_value, + readl(entry->remote_state) & BIT(irq)); set_bit(irq, entry->irq_enabled); @@ -304,15 +302,9 @@ static int smsm_set_irq_type(struct irq_data *irqd, unsigned int type) if (!(type & IRQ_TYPE_EDGE_BOTH)) return -EINVAL; - if (type & IRQ_TYPE_EDGE_RISING) - set_bit(irq, entry->irq_rising); - else - clear_bit(irq, entry->irq_rising); + assign_bit(irq, entry->irq_rising, type & IRQ_TYPE_EDGE_RISING); - if (type & IRQ_TYPE_EDGE_FALLING) - set_bit(irq, entry->irq_falling); - else - clear_bit(irq, entry->irq_falling); + assign_bit(irq, entry->irq_falling, type & IRQ_TYPE_EDGE_FALLING); return 0; } From 0c79a829af36a94143c747a0ab8f0a8563b17cfa Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 20 Jul 2026 16:39:02 +0200 Subject: [PATCH 143/176] soc: qcom: pmic_glink: Avoid losing early rpmsg probe The PMIC GLINK rpmsg device can appear before the platform device has finished probing. In that case pmic_glink_rpmsg_probe() sees __pmic_glink as NULL and returns -ENODEV, which is treated as a fatal probe failure for the rpmsg endpoint. If this race is hit, pg->ept is never installed and PMIC GLINK clients never receive the service-up notification. This may leave the system with no Type-C functionality and without battery/power supply management. Return -EPROBE_DEFER when the rpmsg endpoint arrives before the platform device is ready. Fixes: 58ef4ece1e41 ("soc: qcom: pmic_glink: Introduce base PMIC GLINK driver") Assisted-by: Codex:GPT-5.5 Signed-off-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Link: https://patch.msgid.link/20260720-topic-pmic_glink_defer-v1-1-94c0f233f2f7@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pmic_glink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index 3042261578aa..84fd0c82c0c4 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -250,7 +250,8 @@ static int pmic_glink_rpmsg_probe(struct rpmsg_device *rpdev) guard(mutex)(&__pmic_glink_lock); pg = __pmic_glink; if (!pg) - return dev_err_probe(&rpdev->dev, -ENODEV, "no pmic_glink device to attach to\n"); + return dev_err_probe(&rpdev->dev, -EPROBE_DEFER, + "no pmic_glink device to attach to\n"); dev_set_drvdata(&rpdev->dev, pg); pg->pdr_available = rpdev->id.driver_data; From 33cd898a0f06b6fed0b9f46af000e4e915432120 Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Mon, 27 Jul 2026 21:17:35 +0530 Subject: [PATCH 144/176] dt-bindings: sram: describe the IPQ5424 IMEM as mmio-sram MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IMEM shouldn’t be treated as a syscon or simple-mfd because it’s really just on‑chip SRAM, not a block of control registers or a device with multiple hardware functions. Describing it as generic mmio‑sram keeps the model simple and closer to what the hardware actually is. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kathiravan Thirumoorthy Link: https://patch.msgid.link/20260727-wdt_reset_reason-v11-1-eeedb22beefe@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/sram/qcom,imem.yaml | 1 - Documentation/devicetree/bindings/sram/sram.yaml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sram/qcom,imem.yaml b/Documentation/devicetree/bindings/sram/qcom,imem.yaml index b4f082f2af3a..2f120376a8f4 100644 --- a/Documentation/devicetree/bindings/sram/qcom,imem.yaml +++ b/Documentation/devicetree/bindings/sram/qcom,imem.yaml @@ -18,7 +18,6 @@ properties: items: - enum: - qcom,apq8064-imem - - qcom,ipq5424-imem - qcom,msm8226-imem - qcom,msm8974-imem - qcom,msm8976-imem diff --git a/Documentation/devicetree/bindings/sram/sram.yaml b/Documentation/devicetree/bindings/sram/sram.yaml index b83fc6831947..0acb7593045c 100644 --- a/Documentation/devicetree/bindings/sram/sram.yaml +++ b/Documentation/devicetree/bindings/sram/sram.yaml @@ -37,6 +37,7 @@ properties: - qcom,eliza-imem - qcom,glymur-imem - qcom,hawi-imem + - qcom,ipq5424-imem - qcom,kaanapali-imem - qcom,maili-imem - qcom,milos-imem From 02171d1103d3489dd7920534df4f96b6d101db01 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Thu, 10 Sep 2026 18:30:43 +0530 Subject: [PATCH 145/176] dt-bindings: cache: qcom,llcc: Add Nord compatible Nord has four DDR slices with four MACH9 LLCC banks each, so it exposes sixteen bank regions plus the shared broadcast OR/AND pair. Add its compatible with a matching reg/reg-names group and raise the top level maxItems to eighteen. Signed-off-by: Anurag Pateriya Reviewed-by: Shawn Guo Reviewed-by: Komal Bajaj Link: https://patch.msgid.link/20260910-nord_llcc-v1-1-30fd1cca65fe@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/cache/qcom,llcc.yaml | 55 ++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml index a1340226a0d0..2141e5d4de63 100644 --- a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml +++ b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml @@ -26,6 +26,7 @@ properties: - qcom,hawi-llcc - qcom,ipq5424-llcc - qcom,kaanapali-llcc + - qcom,nord-llcc - qcom,qcs615-llcc - qcom,qcs8300-llcc - qcom,qdu1000-llcc @@ -56,11 +57,11 @@ properties: reg: minItems: 1 - maxItems: 14 + maxItems: 18 reg-names: minItems: 1 - maxItems: 14 + maxItems: 18 interrupts: maxItems: 1 @@ -355,6 +356,56 @@ allOf: - const: llcc3_base - const: llcc_broadcast_base - const: llcc_broadcast_and_base + + - if: + properties: + compatible: + contains: + enum: + - qcom,nord-llcc + then: + properties: + reg: + items: + - description: LLCC0 base register region + - description: LLCC1 base register region + - description: LLCC2 base register region + - description: LLCC3 base register region + - description: LLCC4 base register region + - description: LLCC5 base register region + - description: LLCC6 base register region + - description: LLCC7 base register region + - description: LLCC8 base register region + - description: LLCC9 base register region + - description: LLCC10 base register region + - description: LLCC11 base register region + - description: LLCC12 base register region + - description: LLCC13 base register region + - description: LLCC14 base register region + - description: LLCC15 base register region + - description: LLCC broadcast OR register region + - description: LLCC broadcast AND register region + reg-names: + items: + - const: llcc0_base + - const: llcc1_base + - const: llcc2_base + - const: llcc3_base + - const: llcc4_base + - const: llcc5_base + - const: llcc6_base + - const: llcc7_base + - const: llcc8_base + - const: llcc9_base + - const: llcc10_base + - const: llcc11_base + - const: llcc12_base + - const: llcc13_base + - const: llcc14_base + - const: llcc15_base + - const: llcc_broadcast_base + - const: llcc_broadcast_and_base + - if: properties: compatible: From c3a652c41a8778b9e114fb16ad7998c4c6f65895 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Thu, 10 Sep 2026 18:30:44 +0530 Subject: [PATCH 146/176] soc: qcom: llcc: Add LLCC configuration for Nord Add the sub-cache table for Nord, derived from the Nord AU (Safe IVI) SCT table and limited to the POR use cases that have a unique SCID and a usecase ID in llcc-qcom.h. Nord has the CFG0/CFG1 pairs and the full ALGO_ALLOC0..3 set, so it uses the v6 register offsets. num_banks is set explicitly because LLCC_LB_CNT in LLCC_COMMON_STATUS0 is four bits wide and cannot report sixteen banks; a wrong count makes the driver map a bank aperture in place of the broadcast region and abort on the first broadcast read. no_edac is set because the bootloader leaves the LLCC EDAC registers locked, as on Glymur. Signed-off-by: Anurag Pateriya Tested-by: Zhangfei Gao Reviewed-by: Shawn Guo Reviewed-by: Abel Vesa Reviewed-by: Komal Bajaj Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20260910-nord_llcc-v1-2-30fd1cca65fe@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 139 +++++++++++++++++++++++++++++ include/linux/soc/qcom/llcc-qcom.h | 2 + 2 files changed, 141 insertions(+) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 5e45a10663c4..d7a42a8040a1 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -1054,6 +1054,128 @@ static const struct llcc_slice_config kaanapali_data[] = { }, }; +static const struct llcc_slice_config nord_data[] = { + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 3072, + .priority = 0, + .bonus_ways = 0xff, + .activate_on_init = true, + .write_scid_en = true, + .write_scid_cacheable_en = true, + .vict_prio = true, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 34, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .vict_prio = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .vict_prio = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 2048, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .write_scid_en = true, + .write_scid_cacheable_en = true, + .vict_prio = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .activate_on_init = true, + .vict_prio = true, + }, { + .usecase_id = LLCC_CAMFW, + .slice_id = 20, + .max_cap = 512, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xff, + .vict_prio = true, + }, { + .usecase_id = LLCC_ECC, + .slice_id = 26, + .max_cap = 1536, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xff, + .activate_on_init = true, + .write_scid_en = true, + .write_scid_cacheable_en = true, + .vict_prio = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 2048, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .activate_on_init = true, + .vict_prio = true, + }, { + .usecase_id = LLCC_LCPDARE, + .slice_id = 30, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xff, + .activate_on_init = true, + .alloc_oneway_en = true, + .vict_prio = true, + }, { + .usecase_id = LLCC_COMPUTE1, + .slice_id = 22, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .vict_prio = true, + }, { + .usecase_id = LLCC_PCIE_TCU, + .slice_id = 15, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .activate_on_init = true, + .vict_prio = true, + }, { + .usecase_id = LLCC_GPU_LITTLE, + .slice_id = 9, + .max_cap = 2048, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .write_scid_en = true, + .write_scid_cacheable_en = true, + .vict_prio = true, + }, { + .usecase_id = LLCC_GPUHTW_LITTLE, + .slice_id = 14, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .vict_prio = true, + }, +}; + static const struct llcc_slice_config sa8775p_data[] = { { .usecase_id = LLCC_CPUSS, @@ -4484,6 +4606,17 @@ static const struct qcom_llcc_config glymur_cfg[] = { }, }; +static const struct qcom_llcc_config nord_cfg[] = { + { + .sct_data = nord_data, + .size = ARRAY_SIZE(nord_data), + .reg_offset = llcc_v6_reg_offset, + .edac_reg_offset = &llcc_v6_edac_reg_offset, + .num_banks = 16, + .no_edac = true, + }, +}; + static const struct qcom_llcc_config qcs615_cfg[] = { { .sct_data = qcs615_data, @@ -4751,6 +4884,11 @@ static const struct qcom_sct_config glymur_cfgs = { .num_config = ARRAY_SIZE(glymur_cfg), }; +static const struct qcom_sct_config nord_cfgs = { + .llcc_config = nord_cfg, + .num_config = ARRAY_SIZE(nord_cfg), +}; + static const struct qcom_sct_config qcs615_cfgs = { .llcc_config = qcs615_cfg, .num_config = ARRAY_SIZE(qcs615_cfg), @@ -5693,6 +5831,7 @@ static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,hawi-llcc", .data = &hawi_sct_cfgs }, { .compatible = "qcom,ipq5424-llcc", .data = &ipq5424_cfgs}, { .compatible = "qcom,kaanapali-llcc", .data = &kaanapali_cfgs}, + { .compatible = "qcom,nord-llcc", .data = &nord_cfgs}, { .compatible = "qcom,qcs615-llcc", .data = &qcs615_cfgs}, { .compatible = "qcom,qcs8300-llcc", .data = &qcs8300_cfgs}, { .compatible = "qcom,qdu1000-llcc", .data = &qdu1000_cfgs}, diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h index 1ccc429401e8..713cb0221b14 100644 --- a/include/linux/soc/qcom/llcc-qcom.h +++ b/include/linux/soc/qcom/llcc-qcom.h @@ -74,6 +74,7 @@ #define LLCC_CAMSRTIP 73 #define LLCC_CAMRTRF 74 #define LLCC_CAMSRTRF 75 +#define LLCC_GPU_LITTLE 80 #define LLCC_OOBM_NS 81 #define LLCC_OOBM_S 82 #define LLCC_VIDEO_APV 83 @@ -85,6 +86,7 @@ #define LLCC_CAM_OFE_STROV 93 #define LLCC_CPUSS_HEU 94 #define LLCC_PCIE_TCU 97 +#define LLCC_GPUHTW_LITTLE 98 #define LLCC_MDM_PNG_FIXED 100 #define LLCC_PPE_RXDESC 101 #define LLCC_PPE_RXFILL 102 From 50508d3e0abd83bf0ff82f53cc89a987728853a9 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 13 Sep 2026 13:30:49 -0400 Subject: [PATCH 147/176] firmware: qcom: scm: Hide QCOM_SCM instead of depending on ARCH_QCOM imx_v6_v7_defconfig fails to link: arm-linux-gnueabihf-ld: drivers/firmware/qcom/qcom_scm.o: in function `qcom_scm_pas_init_image': qcom_scm.c:(.text+0xecc): undefined reference to `qcom_tzmem_alloc' qcom_scm.c:(.text+0x2b0): undefined reference to `qcom_tzmem_free' qcom_scm.c:(.text+0x1514): undefined reference to `qcom_tzmem_to_phys' QCOM_SCM gained a "depends on ARCH_QCOM || COMPILE_TEST", but it is selected from 20 places in the tree and several of those are reachable without ARCH_QCOM. DRM_MSM is one of them, via SOC_IMX5, which is how imx_v6_v7_defconfig ends up here: WARNING: unmet direct dependencies detected for QCOM_SCM Depends on [n]: ARCH_QCOM [=n] || COMPILE_TEST [=n] Selected by [y]: - DRM_MSM [=y] && ... && (ARCH_QCOM [=n] || SOC_IMX5 [=y] || COMPILE_TEST [=n]) && ... kconfig still honours the select and sets QCOM_SCM=y, but it does not propagate the selects of a symbol whose own dependencies are unmet, so QCOM_TZMEM is left unset, qcom_tzmem.c is not built, and the unconditional qcom_tzmem_*() calls in qcom_scm.c and qcom_scm-smc.c have nothing to bind to. The point of the dependency was only to stop asking the user about Qualcomm firmware interfaces when configuring a non-Qualcomm kernel. Express that as a prompt condition, which is what the same commit already did for QCOM_PAS: the symbol stays invisible, but it no longer carries a dependency that silently drops its selects. Found by KernelCI builds of the linux-next tree. Fixes: 8fecd3194de3 ("firmware: QCOM interfaces should depend on ARCH_QCOM") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202609120634.g0HMAp3g-lkp@intel.com/ Assisted-by: LLM Signed-off-by: Sasha Levin Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260913173049.1168963-1-sashal@kernel.org Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig index 691db0ded8e8..b50e1309ced5 100644 --- a/drivers/firmware/qcom/Kconfig +++ b/drivers/firmware/qcom/Kconfig @@ -26,8 +26,7 @@ config QCOM_PAS_TEE by the firmware TEE implementation as the backend. config QCOM_SCM - tristate "Qualcomm PAS SCM interface driver" - depends on ARCH_QCOM || COMPILE_TEST + tristate "Qualcomm PAS SCM interface driver" if ARCH_QCOM || COMPILE_TEST select QCOM_PAS select QCOM_TZMEM default y if ARCH_QCOM From 17a46b6ffa2f7227e166a0b4b82f159c983b2d84 Mon Sep 17 00:00:00 2001 From: Antony Kurniawan Soemardi Date: Mon, 3 Aug 2026 02:03:45 +0700 Subject: [PATCH 148/176] dt-bindings: mfd: syscon: add qcom,msm8960-sps-sic Add compat for Smart Peripheral System (SPS) Interrupt Controller (SIC) present on Qualcomm MSM8960 SoC. Acked-by: Krzysztof Kozlowski Signed-off-by: Antony Kurniawan Soemardi Link: https://patch.msgid.link/20260803-msm8960-wifi-v4-1-5ffa27aea39d@smankusors.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/mfd/syscon.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml index 945a168b613d..33e0b1bad5ab 100644 --- a/Documentation/devicetree/bindings/mfd/syscon.yaml +++ b/Documentation/devicetree/bindings/mfd/syscon.yaml @@ -107,6 +107,7 @@ properties: - nxp,s32g3-gpr - qcom,apq8064-mmss-sfpb - qcom,apq8064-sps-sic + - qcom,msm8960-sps-sic - rockchip,px30-qos - rockchip,rk3036-qos - rockchip,rk3066-qos From 803f9950a6c6e0b37ed7f24925feed823703467e Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 23 Sep 2026 10:51:45 +0200 Subject: [PATCH 149/176] soc: qcom: geni-se: provide PROG_RAM_DEPTH for I2C HUB Serial Engines The I2C Hub serial elements lacks DMA, so the SE_HW_PARAM_2 register which is in the DMA register space doesn't exist for those instances. Provide the ram depth in the compatible data to be used instead of the reading the missing SE_HW_PARAM_2 register. Fixes: 522bfb4f33c0 ("soc: qcom: geni-se: Use HW PROG_RAM_DEPTH to validate firmware size") Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20260923-topic-sm8x50-i2c-hub-fw-ram-v3-1-44287b4e814b@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 6ac2bdc16984..08e05ba70f73 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -101,22 +101,26 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(geni_se_regs); * @base: Base address of this instance of QUP wrapper core * @clks: Handle to the primary & optional secondary AHB clocks * @num_clks: Count of clocks + * @prog_ram_depth: Available CFG RAM depth for instance without SE_HW_PARAM_2 */ struct geni_wrapper { struct device *dev; void __iomem *base; struct clk_bulk_data clks[MAX_CLKS]; unsigned int num_clks; + unsigned int prog_ram_depth; }; /** * struct geni_se_desc - Data structure to represent the QUP Wrapper resources * @clks: Name of the primary & optional secondary AHB clocks * @num_clks: Count of clock names + * @prog_ram_depth: Available CFG RAM depth for instance without SE_HW_PARAM_2 */ struct geni_se_desc { unsigned int num_clks; const char * const *clks; + unsigned int prog_ram_depth; }; static const char * const icc_path_names[] = {"qup-core", "qup-config", @@ -1244,6 +1248,7 @@ static const struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const s enum geni_se_protocol_type protocol, u32 *fw_size_out) { + struct geni_wrapper *wrapper = se->wrapper; struct device *dev = se->dev; const struct elf32_hdr *ehdr; const struct elf32_phdr *phdrs; @@ -1308,8 +1313,11 @@ static const struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const s cfg_val_end = le16_to_cpu(sefw->cfg_val_offset) + le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u32); - prog_ram_depth = FIELD_GET(PROG_RAM_DEPTH_MSK, - readl_relaxed(se->base + SE_HW_PARAM_2)); + if (wrapper->prog_ram_depth) + prog_ram_depth = wrapper->prog_ram_depth; + else + prog_ram_depth = FIELD_GET(PROG_RAM_DEPTH_MSK, + readl_relaxed(se->base + SE_HW_PARAM_2)); if (fw_size >= prog_ram_depth) { dev_err(dev, "Firmware size (%u) exceeds RAM size (%u)\n", fw_size, prog_ram_depth); @@ -1620,6 +1628,7 @@ static int geni_se_probe(struct platform_device *pdev) return PTR_ERR(wrapper->base); desc = device_get_match_data(&pdev->dev); + wrapper->prog_ram_depth = desc->prog_ram_depth; if (!has_acpi_companion(&pdev->dev) && desc->num_clks) { int i; @@ -1672,6 +1681,7 @@ static const char * const i2c_master_hub_clks[] = { static const struct geni_se_desc i2c_master_hub_desc = { .clks = i2c_master_hub_clks, .num_clks = ARRAY_SIZE(i2c_master_hub_clks), + .prog_ram_depth = 1020, }; static const struct of_device_id geni_se_dt_match[] = { From c8f9c5192c39db9b88550d7392e3f656b6560d75 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Tue, 22 Sep 2026 16:06:19 -0700 Subject: [PATCH 150/176] dt-bindings: arm: qcom,ids: Add SoC ID for SM8950 Add the ID for the Qualcomm SM8950 SoC which represents the Maili platform. Signed-off-by: Jingyi Wang Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20260922-maili-socinfo-v1-1-a82bd7d4ca77@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- include/dt-bindings/arm/qcom,ids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index 4259f8960447..135297027580 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -304,6 +304,7 @@ #define QCOM_ID_SM8975 707 #define QCOM_ID_CQ7790M 731 #define QCOM_ID_CQ7790S 732 +#define QCOM_ID_SM8950 735 #define QCOM_ID_CQ2390M 756 #define QCOM_ID_CQ2390S 758 #define QCOM_ID_IQ2390S 759 From 5ce6f7de57c0efa4075eaf76245e622f962d0cfe Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Tue, 22 Sep 2026 16:06:20 -0700 Subject: [PATCH 151/176] soc: qcom: socinfo: Add SM8950 SoC ID Add SoC ID for Qualcomm SM8950 which represents the Maili platform. Signed-off-by: Jingyi Wang Link: https://patch.msgid.link/20260922-maili-socinfo-v1-2-a82bd7d4ca77@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index ddc717382797..38efc5db7fa8 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -545,6 +545,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(SM8975) }, { qcom_board_id(CQ7790M) }, { qcom_board_id(CQ7790S) }, + { qcom_board_id(SM8950) }, { qcom_board_id(CQ2390M) }, { qcom_board_id(CQ2390S) }, { qcom_board_id(IQ2390S) }, From af0730a79096af88a8801740bf92795beb172ce4 Mon Sep 17 00:00:00 2001 From: Hemanth Selam Date: Mon, 7 Sep 2026 11:47:41 +0530 Subject: [PATCH 152/176] firmware: qcom: fix typo "uninterruptable" in comment Correct "uninterruptable" to "uninterruptible", reported by scripts/checkpatch.pl using the misspelling list in scripts/spelling.txt. Only touches comments, no code changes. Assisted-by: Cursor:claude-opus-5 Signed-off-by: Hemanth Selam Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20260907061742.10954-2-hemanth.selam@gmail.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm-legacy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/qcom_scm-legacy.c b/drivers/firmware/qcom/qcom_scm-legacy.c index 029e6d117cb8..fe751ee512da 100644 --- a/drivers/firmware/qcom/qcom_scm-legacy.c +++ b/drivers/firmware/qcom/qcom_scm-legacy.c @@ -219,7 +219,7 @@ int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, * @res: SCM call return values * * This shall only be used with commands that are guaranteed to be - * uninterruptable, atomic and SMP safe. + * uninterruptible, atomic and SMP safe. */ int scm_legacy_call_atomic(struct device *unused, const struct qcom_scm_desc *desc, From d2bcd688b74857d4c12315a7426302c192671ec8 Mon Sep 17 00:00:00 2001 From: Hemanth Selam Date: Mon, 7 Sep 2026 11:47:42 +0530 Subject: [PATCH 153/176] soc: qcom: fix typo "upto" in comment Correct "upto" to "up to", reported by scripts/checkpatch.pl using the misspelling list in scripts/spelling.txt. Only touches comments, no code changes. Assisted-by: Cursor:claude-opus-5 Signed-off-by: Hemanth Selam Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20260907061742.10954-3-hemanth.selam@gmail.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 08e05ba70f73..7ad002b111c8 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -42,7 +42,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(geni_se_regs); * * GENI based QUP is a highly-flexible and programmable module for supporting * a wide range of serial interfaces like UART, SPI, I2C, I3C, etc. A single - * QUP module can provide upto 8 serial interfaces, using its internal + * QUP module can provide up to 8 serial interfaces, using its internal * serial engines. The actual configuration is determined by the target * platform configuration. The protocol supported by each interface is * determined by the firmware loaded to the serial engine. Each SE consists From ed0c12e25cce898db1a42eb2b9e1d5e87c56d315 Mon Sep 17 00:00:00 2001 From: Sneh Mankad Date: Mon, 7 Sep 2026 19:17:53 +0530 Subject: [PATCH 154/176] dt-bindings: soc: qcom: stats: Add compatible for Shikra SoC LPM stats are present in RPM MSGRAM and subsystem LPM stats are present in SMEM for Shikra. A generic "qcom,rpm-stats" compatible only reads SoC LPM stats like vmin and vlow. Document shikra rpm compatible to read subsystem LPM stats too along with SoC LPM stats. Keep "qcom,rpm-stats" as a fallback for RPM targets, so that SoC level stats are still shown even without subsystem level stats support. A plain enum can't express that, since it caps compatible at one item. Add a oneOf branch with items for this pattern. Signed-off-by: Sneh Mankad Reviewed-by: Komal Bajaj Link: https://patch.msgid.link/20260907-shikra_stats-v4-1-3825351f9740@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../bindings/soc/qcom/qcom-stats.yaml | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom-stats.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom-stats.yaml index 686a7ef2f48a..b384a5983d43 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom-stats.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom-stats.yaml @@ -18,15 +18,22 @@ description: properties: compatible: - enum: - - qcom,rpmh-stats - - qcom,sdm845-rpmh-stats - - qcom,rpm-stats - # For older RPM firmware versions with fixed offset for the sleep stats - - qcom,apq8084-rpm-stats - - qcom,msm8226-rpm-stats - - qcom,msm8916-rpm-stats - - qcom,msm8974-rpm-stats + oneOf: + - enum: + - qcom,rpmh-stats + - qcom,sdm845-rpmh-stats + - qcom,rpm-stats + # For older RPM firmware versions with fixed offset for the sleep stats + - qcom,apq8084-rpm-stats + - qcom,msm8226-rpm-stats + - qcom,msm8916-rpm-stats + - qcom,msm8974-rpm-stats + # SoC-specific compatibles that also read subsystem-level stats, + # falling back to "qcom,rpm-stats" for SoC-level stats only + - items: + - enum: + - qcom,shikra-rpm-stats + - const: qcom,rpm-stats reg: maxItems: 1 From c98d40a52c9e13578521f4a7ea91427117ec806e Mon Sep 17 00:00:00 2001 From: Sneh Mankad Date: Mon, 7 Sep 2026 19:17:54 +0530 Subject: [PATCH 155/176] soc: qcom: stats: Add stats compatible and config for Shikra SoC LPM stats are present in RPM MSGRAM and subsystem LPM stats are present in SMEM for Shikra. For earlier targets using RPM processor like msm8974, rpm_master_stat.c was used for subsystem LPM stats since those stats were populated in RPM MSGRAM. Here is a brief summary of previous targets and their stats configuration, along with the drivers used to display them. +---------------|----------------------------|---------------------------+ | SoC | subsystem LPM stats | SoC LPM stats | |---------------|----------------------------|---------------------------| | msm8974, | RPM processor MSGRAM | RPM processor MSGRAM | | msm8226 | (rpm_master_stat.c) | (qcom_stats.c) | |---------------|----------------------------|---------------------------| | sm6350, | SMEM (DDR) | AOP processor MSGRAM | | sdm845, etc. | (qcom_stats.c) | (qcom_stats.c) | |---------------|----------------------------|---------------------------| | Shikra | SMEM (DDR) | RPM processor MSGRAM | | | (qcom_stats.c) | (qcom_stats.c) | +---------------|----------------------------|---------------------------+ qcom_stats.c supports both the configurations for shikra, reading subsystem LPM stats from SMEM and reading SoC LPM stats from RPM MSGRAM. A generic "qcom,rpm-stats" compatible only reads SoC LPM stats like vmin and vlow. Add shikra rpm compatible and config to read subsystem LPM stats too along with SoC LPM stats. Below is an example showing LPM stats for "apss" subsystem with this change: cat /sys/kernel/debug/qcom_stats/apss Count: 2192 Last Entered At: 5498618336 Last Exited At: 5498708046 Accumulated Duration: 2046572620. Reviewed-by: Konrad Dybcio Reviewed-by: Maulik Shah Signed-off-by: Sneh Mankad Reviewed-by: Komal Bajaj Reviewed-by: Abel Vesa Link: https://patch.msgid.link/20260907-shikra_stats-v4-2-3825351f9740@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_stats.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/soc/qcom/qcom_stats.c b/drivers/soc/qcom/qcom_stats.c index 06923408bfce..3422d6df7b51 100644 --- a/drivers/soc/qcom/qcom_stats.c +++ b/drivers/soc/qcom/qcom_stats.c @@ -371,6 +371,14 @@ static const struct stats_config rpm_data_dba0 = { .subsystem_stats_in_smem = false, }; +static const struct stats_config rpm_data_shikra = { + .stats_offset = 0, + .num_records = 2, + .appended_stats_avail = true, + .dynamic_offset = true, + .subsystem_stats_in_smem = true, +}; + static const struct stats_config rpmh_data_sdm845 = { .stats_offset = 0x48, .num_records = 2, @@ -396,6 +404,7 @@ static const struct of_device_id qcom_stats_table[] = { { .compatible = "qcom,rpm-stats", .data = &rpm_data }, { .compatible = "qcom,rpmh-stats", .data = &rpmh_data }, { .compatible = "qcom,sdm845-rpmh-stats", .data = &rpmh_data_sdm845 }, + { .compatible = "qcom,shikra-rpm-stats", .data = &rpm_data_shikra }, { } }; MODULE_DEVICE_TABLE(of, qcom_stats_table); From d745bbeb0f780d7e2dbe9a5ba08db3ee89eec8c0 Mon Sep 17 00:00:00 2001 From: Gopikrishna Garmidi Date: Tue, 8 Sep 2026 23:40:54 -0700 Subject: [PATCH 156/176] firmware: qcom: scm: Allow QSEECOM on the Glymur QCB Add Glymur QCB board to the QSEECOM allowlist for enabling access to efivars and uefi bootloader. Reviewed-by: Mukesh Ojha Reviewed-by: Dmitry Baryshkov Signed-off-by: Gopikrishna Garmidi Link: https://patch.msgid.link/20260908-glymur-qcb-v3-3-c194c0219218@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index d309689de266..56d54c4f09e2 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2340,6 +2340,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "microsoft,romulus13", }, { .compatible = "microsoft,romulus15", }, { .compatible = "qcom,glymur-crd" }, + { .compatible = "qcom,glymur-qcb" }, { .compatible = "qcom,hamoa-iot-evk" }, { .compatible = "qcom,mahua-crd" }, { .compatible = "qcom,purwa-iot-evk" }, From cbab6ecf312831a2fc55ec21c168ef895514d8c5 Mon Sep 17 00:00:00 2001 From: Gopikrishna Garmidi Date: Wed, 9 Sep 2026 00:18:17 -0700 Subject: [PATCH 157/176] firmware: qcom: scm: Allow QSEECOM on Kalambo CRD Add Kalambo CRD board to the QSEECOM allowlist for enabling access to efivars. Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Gopikrishna Garmidi Link: https://patch.msgid.link/20260909-b4-kalambo-crd-v7-4-f5685804478a@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 56d54c4f09e2..1ac77eb6ac65 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2342,6 +2342,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "qcom,glymur-crd" }, { .compatible = "qcom,glymur-qcb" }, { .compatible = "qcom,hamoa-iot-evk" }, + { .compatible = "qcom,kalambo-crd" }, { .compatible = "qcom,mahua-crd" }, { .compatible = "qcom,purwa-iot-evk" }, { .compatible = "qcom,sc8180x-primus" }, From 1337776a5388a0641c4ad12c30c8da7381971f37 Mon Sep 17 00:00:00 2001 From: Gopikrishna Garmidi Date: Wed, 9 Sep 2026 00:18:18 -0700 Subject: [PATCH 158/176] soc: qcom: ubwc: Add Kalambo UBWC config Qualcomm Kalambo is a derivative of the Mahua SoC and shares the same Universal Bandwidth Compression (UBWC) configuration. Add the Kalambo compatible to the UBWC configuration table to enable support. Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Gopikrishna Garmidi Link: https://patch.msgid.link/20260909-b4-kalambo-crd-v7-5-f5685804478a@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ubwc_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/ubwc_config.c b/drivers/soc/qcom/ubwc_config.c index 53c1df3ca641..a4d8769f8550 100644 --- a/drivers/soc/qcom/ubwc_config.c +++ b/drivers/soc/qcom/ubwc_config.c @@ -121,6 +121,7 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = { { .compatible = "qcom,glymur", .data = &glymur_data}, { .compatible = "qcom,hawi", .data = &ubwc_7_0_hbb16 }, { .compatible = "qcom,kaanapali", .data = &ubwc_6_0_hbb16 }, + { .compatible = "qcom,kalambo", .data = &glymur_data }, { .compatible = "qcom,mahua", .data = &glymur_data }, { .compatible = "qcom,maili", .data = &ubwc_7_0_hbb16, }, { .compatible = "qcom,milos", .data = &milos_data }, From e2467151dcab02a7b134eac32b74fb8267bc2a24 Mon Sep 17 00:00:00 2001 From: Vitalii Skorkin Date: Thu, 10 Sep 2026 15:27:22 +0300 Subject: [PATCH 159/176] firmware: qcom: tzmem: disable SHM bridge for SM7125 platform Currently SHM bridge causes RCU stalls when booting. Disable it for SM7125 until a fix is available. Signed-off-by: Vitalii Skorkin Reviewed-by: Dmitry Baryshkov Acked-by: Bartosz Golaszewski Signed-off-by: Erikas Bitovtas Link: https://patch.msgid.link/20260910-sm7125-samsung-v3-2-c467bea0fb9c@gmail.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_tzmem.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/qcom/qcom_tzmem.c b/drivers/firmware/qcom/qcom_tzmem.c index ebcdee3c5975..44cf80c84d7f 100644 --- a/drivers/firmware/qcom/qcom_tzmem.c +++ b/drivers/firmware/qcom/qcom_tzmem.c @@ -82,6 +82,7 @@ static const char *const qcom_tzmem_blacklist[] = { "qcom,sc8180x", "qcom,sdm670", /* failure in GPU firmware loading */ "qcom,sdm845", /* reset in rmtfs memory assignment */ + "qcom,sm7125", /* hang in rmtfs memory assignment */ "qcom,sm7150", /* reset in rmtfs memory assignment */ "qcom,sm8150", /* reset in rmtfs memory assignment */ NULL From ceab390aeefaa28e4c91ccdc60f53d18f8b76c79 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 17 Sep 2026 10:07:30 +0530 Subject: [PATCH 160/176] ASoC: dt-bindings: qcom,apr: Add modem_apps GLINK channel for shikra Add support for the modem_apps GLINK channel on Shikra, as audio processing is handled through the modem DSP. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Mohammad Rafi Shaik Link: https://patch.msgid.link/20260917-shikra_audio_dts-v3-1-9a49e1ca6370@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml index e51acdcaafaf..01250b556985 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml @@ -120,7 +120,9 @@ allOf: properties: qcom,glink-channels: items: - - const: adsp_apps + - enum: + - adsp_apps + - modem_apps power-domains: false else: properties: From 66894a1c51366cc2d5c498178105dfe3bcccc1e4 Mon Sep 17 00:00:00 2001 From: Yibo Tan Date: Sun, 13 Sep 2026 00:12:10 +0800 Subject: [PATCH 161/176] soc: qcom: pmic_pdcharger_ulog: prevent work requeue during remove pmic_pdcharger_ulog_rpmsg_remove() cancels the delayed worker while the RPMsg endpoint can still deliver callbacks. The RPMsg core invokes the driver remove callback before destroying the endpoint, so a response callback can run after cancel_delayed_work_sync() returns and queue the worker again. Device cleanup then frees the devm-allocated pmic_pdcharger_ulog while the requeued delayed work still embeds and dereferences that object. KASAN reports a slab-use-after-free in pmic_pdcharger_ulog_work(). Use disable_delayed_work_sync() to drain the worker and reject queue attempts that race with removal. The issue was reproduced in four of four runs with the real target driver, RPMsg bus removal, endpoint teardown, workqueue code and devres cleanup. The test provider delivered a valid response in the window between the driver remove callback and endpoint destruction. With this change, the same late callback occurred in four of four runs without a KASAN report, warning, Oops or panic. The reproducer uses a test RPMsg provider to control the teardown timing. No unprivileged trigger or physical Qualcomm-device result is claimed. Fixes: 086fdb48bc65 ("soc: qcom: add ADSP PDCharger ULOG driver") Assisted-by: Codex:GPT-5 Signed-off-by: Yibo Tan Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Link: https://patch.msgid.link/20260912161210.1683266-1-lhfff@tju.edu.cn Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pmic_pdcharger_ulog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/pmic_pdcharger_ulog.c b/drivers/soc/qcom/pmic_pdcharger_ulog.c index 39f412bbf2c1..06cd9c4411c2 100644 --- a/drivers/soc/qcom/pmic_pdcharger_ulog.c +++ b/drivers/soc/qcom/pmic_pdcharger_ulog.c @@ -143,7 +143,7 @@ static void pmic_pdcharger_ulog_rpmsg_remove(struct rpmsg_device *rpdev) { struct pmic_pdcharger_ulog *pg = dev_get_drvdata(&rpdev->dev); - cancel_delayed_work_sync(&pg->ulog_work); + disable_delayed_work_sync(&pg->ulog_work); } static const struct rpmsg_device_id pmic_pdcharger_ulog_rpmsg_id_match[] = { From a46b914f6aa4056673727e72747874aa8b7a4975 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Mon, 31 Aug 2026 20:53:44 -0700 Subject: [PATCH 162/176] dt-bindings: spmi: glymur-spmi-pmic-arb: Add compatible for Qualcomm Maili SoC The PMIC arbiter in the Qualcomm Maili SoC is version v8.5, which is the same with Hawi and compatible with Glymur. Hence, add a string for "qcom,maili-spmi-pmic-arb" as a compatible entry for "qcom,glymur-spmi-pmic-arb". Reviewed-by: Yijie Yang Reviewed-by: Krzysztof Kozlowski Signed-off-by: Fenglin Wu Reviewed-by: Abel Vesa Link: https://patch.msgid.link/20260831-maili-spmi-binding-v2-1-37a25ef3921c@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/spmi/qcom,glymur-spmi-pmic-arb.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spmi/qcom,glymur-spmi-pmic-arb.yaml b/Documentation/devicetree/bindings/spmi/qcom,glymur-spmi-pmic-arb.yaml index 1593a1183a36..44c864fd5fc7 100644 --- a/Documentation/devicetree/bindings/spmi/qcom,glymur-spmi-pmic-arb.yaml +++ b/Documentation/devicetree/bindings/spmi/qcom,glymur-spmi-pmic-arb.yaml @@ -27,6 +27,7 @@ properties: - enum: - qcom,hawi-spmi-pmic-arb - qcom,kaanapali-spmi-pmic-arb + - qcom,maili-spmi-pmic-arb - const: qcom,glymur-spmi-pmic-arb - enum: - qcom,glymur-spmi-pmic-arb From ccd9552a96f3b0e2f55c397368f575446c0e6acd Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 7 Sep 2026 14:07:18 +0530 Subject: [PATCH 163/176] dt-bindings: mailbox: qcom: Document Maili CPUCP mailbox controller Document the CPU Control Processor (CPUCP) mailbox controller for the Qualcomm Maili SoC. It is software compatible with the X1E80100 CPUCP mailbox controller and uses it as a fallback compatible string. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Taniya Das Reviewed-by: Maria Yu Link: https://patch.msgid.link/20260907-maili_initial_clock-v5-1-e79bb6b93a49@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/mailbox/qcom,cpucp-mbox.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mailbox/qcom,cpucp-mbox.yaml b/Documentation/devicetree/bindings/mailbox/qcom,cpucp-mbox.yaml index 03359479d926..2185920e1b5d 100644 --- a/Documentation/devicetree/bindings/mailbox/qcom,cpucp-mbox.yaml +++ b/Documentation/devicetree/bindings/mailbox/qcom,cpucp-mbox.yaml @@ -21,6 +21,7 @@ properties: - qcom,glymur-cpucp-mbox - qcom,hawi-cpucp-mbox - qcom,kaanapali-cpucp-mbox + - qcom,maili-cpucp-mbox - qcom,nord-cpucp-mbox - qcom,sm8750-cpucp-mbox - const: qcom,x1e80100-cpucp-mbox From 73fa037209f9c2e50681a1cd04a4ef5f76f87873 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 28 Sep 2026 15:51:22 +0100 Subject: [PATCH 164/176] firmware: qcom: scm: Allow QSEECOM on ThinkPad T14s Gen 7 Allow the use of QSEECOM on the Mahua-based Lenovo ThinkPad T14s Gen 7, matching the pattern established for the Yoga Slim 7x Gen 11. Assisted-by: Claude:claude-opus-4-7 Signed-off-by: Srinivas Kandagatla Link: https://patch.msgid.link/20260928145122.1337186-4-srinivas.kandagatla@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 1ac77eb6ac65..ca5d7bd4af8e 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2329,6 +2329,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "lenovo,ideacentre-mini-01q8x10" }, { .compatible = "lenovo,thinkbook-16" }, { .compatible = "lenovo,thinkpad-t14s" }, + { .compatible = "lenovo,thinkpad-t14s-gen7" }, { .compatible = "lenovo,thinkpad-x13s", }, { .compatible = "lenovo,yoga-slim7x" }, { .compatible = "lenovo,yoga-slim7x-gen11" }, From f44ee24f4a96ad97c2f0191e503c91477d9b530b Mon Sep 17 00:00:00 2001 From: Somesh Dey Date: Wed, 30 Sep 2026 13:31:54 +0530 Subject: [PATCH 165/176] soc: qcom: geni-se: Drop unused icc_ddr parameter from geni_icc_get() geni_icc_get() takes an icc_ddr string argument but never uses it: the DDR interconnect path is looked up with the "qup-memory" string literal directly, and the sole caller passes that same literal. The parameter carries no information. Drop the icc_ddr parameter and update the prototype and call site accordingly. Signed-off-by: Somesh Dey Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20260930-icc-ddr-param-remove-v1-1-61223714c9bc@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 4 ++-- include/linux/soc/qcom/geni-se.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 7ad002b111c8..074087c592cc 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -924,7 +924,7 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len) } EXPORT_SYMBOL_GPL(geni_se_rx_dma_unprep); -int geni_icc_get(struct geni_se *se, const char *icc_ddr) +int geni_icc_get(struct geni_se *se) { struct geni_icc_path *icc_paths = se->icc_paths; @@ -1221,7 +1221,7 @@ int geni_se_resources_init(struct geni_se *se) se->has_opp = (ret == 0); - ret = geni_icc_get(se, "qup-memory"); + ret = geni_icc_get(se); if (ret) return ret; diff --git a/include/linux/soc/qcom/geni-se.h b/include/linux/soc/qcom/geni-se.h index 29a53bbc0dd4..95c0cc4d4ea1 100644 --- a/include/linux/soc/qcom/geni-se.h +++ b/include/linux/soc/qcom/geni-se.h @@ -573,7 +573,7 @@ void geni_se_tx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len); void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len); -int geni_icc_get(struct geni_se *se, const char *icc_ddr); +int geni_icc_get(struct geni_se *se); int geni_icc_set_bw(struct geni_se *se); int geni_icc_set_bw_ab(struct geni_se *se, u32 core_ab, u32 cfg_ab, u32 ddr_ab); From 46201d760c48e771fa2febfcb0787f22c3b71387 Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Thu, 17 Sep 2026 15:27:19 +0000 Subject: [PATCH 166/176] soc: fsl: cpm1: tsa: Fix clock leak in tsa_of_parse_tdms() The error cleanup loop puts l1rsync_clk and l1rclk_clk a second time and never puts l1tsync_clk or l1tclk_clk, because the branches that guard the transmit clocks use the receive clock field names. Use the matching field in each branch so every clock acquired by tsa_of_parse_tdms() is released exactly once. Fixes: 1d4ba0b81c1c ("soc: fsl: cpm1: Add support for TSA") Cc: stable@vger.kernel.org Signed-off-by: Wentao Liang Reviewed-by: Herve Codina Link: https://lore.kernel.org/r/20260917152719.2160395-1-vulab@iscas.ac.cn [chleroy: Fixed the same in tsa_remove()] Signed-off-by: Christophe Leroy (CS GROUP) --- drivers/soc/fsl/qe/tsa.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/soc/fsl/qe/tsa.c b/drivers/soc/fsl/qe/tsa.c index 4a88e54d25b9..502e2ffe8689 100644 --- a/drivers/soc/fsl/qe/tsa.c +++ b/drivers/soc/fsl/qe/tsa.c @@ -865,12 +865,12 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) clk_put(tsa->tdm[i].l1rclk_clk); } if (tsa->tdm[i].l1tsync_clk) { - clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); - clk_put(tsa->tdm[i].l1rsync_clk); + clk_disable_unprepare(tsa->tdm[i].l1tsync_clk); + clk_put(tsa->tdm[i].l1tsync_clk); } if (tsa->tdm[i].l1tclk_clk) { - clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); - clk_put(tsa->tdm[i].l1rclk_clk); + clk_disable_unprepare(tsa->tdm[i].l1tclk_clk); + clk_put(tsa->tdm[i].l1tclk_clk); } } return ret; @@ -1039,12 +1039,12 @@ static void tsa_remove(struct platform_device *pdev) clk_put(tsa->tdm[i].l1rclk_clk); } if (tsa->tdm[i].l1tsync_clk) { - clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); - clk_put(tsa->tdm[i].l1rsync_clk); + clk_disable_unprepare(tsa->tdm[i].l1tsync_clk); + clk_put(tsa->tdm[i].l1tsync_clk); } if (tsa->tdm[i].l1tclk_clk) { - clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); - clk_put(tsa->tdm[i].l1rclk_clk); + clk_disable_unprepare(tsa->tdm[i].l1tclk_clk); + clk_put(tsa->tdm[i].l1tclk_clk); } } } From 4258e8f44462463d618f6b4f24a46b35f36cfd0f Mon Sep 17 00:00:00 2001 From: Vincent Jardin Date: Wed, 30 Sep 2026 22:15:48 +0200 Subject: [PATCH 167/176] bus: fsl-mc: drop the fwnode links of the dpmacs nodes A DPMAC node under dpmacs/ is never the fwnode of any device: the fsl-mc bus creates dpmac.N objects without one, then dpaa2-mac finds its node in dpmacs/ at connect time. fw_devlink therefore attaches the supplier links of those nodes (phys, ...) to the nearest ancestor device, the fsl-mc bus, as SYNC_STATE_ONLY proxies. device_link_add() refuses such a link once the consumer has probed, and fw_devlink logs the refusal as an error. On an LX2160A board with 4x25G DPMACs for which phys = <&serdes_1 N>, the Serdes PHY binds after the bus and then at every boot it shows: fsl_mc_bus 80c000000.fsl-mc: Failed to create device link (0x180) with supplier 1ea0000.phy for /soc/fsl-mc@80c000000/dpmacs/ethernet@3 once per port! To fix it, when the root MC bus probes, purge the fwnode links of every child of its dpmacs node, so fw_devlink has no supplier link left to proxy to the bus and no longer tries to create those device links. Signed-off-by: Vincent Jardin Reviewed-by: Ioana Ciornei Tested-by: Ioana Ciornei # LX2160ARDB Link: https://lore.kernel.org/r/20260930-for-upstream-fsl-mc-dpmac-fwnode-links-v2-1-13f7b6ef000f@free.fr Signed-off-by: Christophe Leroy (CS GROUP) --- drivers/bus/fsl-mc/fsl-mc-bus.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index 5878eafd8d44..0c37b6780c84 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -11,6 +11,7 @@ #define pr_fmt(fmt) "fsl-mc: " fmt #include +#include #include #include #include @@ -1033,6 +1034,20 @@ static int fsl_mc_firmware_check(struct platform_device *pdev) return 0; } +static void fsl_mc_purge_dpmac_fwnode_links(struct device *dev) +{ + struct device_node *dpmacs, *child; + + dpmacs = of_get_child_by_name(dev->of_node, "dpmacs"); + if (!dpmacs) + return; + + for_each_child_of_node(dpmacs, child) + fwnode_links_purge(of_fwnode_handle(child)); + + of_node_put(dpmacs); +} + /* * fsl_mc_bus_probe - callback invoked when the root MC bus is being * added @@ -1134,6 +1149,8 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) &mc->num_translation_ranges); if (error < 0) goto error_cleanup_mc_io; + + fsl_mc_purge_dpmac_fwnode_links(&pdev->dev); } error = dprc_get_container_id(mc_io, 0, &container_id); From 7aed976c4207bda126f41475eebaf8162b6a0ce4 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Tue, 22 Sep 2026 22:35:38 +0000 Subject: [PATCH 168/176] bus: fsl-mc: Annotate fsl_mc_io.portal_virt_addr with __counted_by_ptr The GCC and Clang compilers provide the __counted_by_ptr attribute, which is used by KASAN and compiler bounds-checking to detect out-of-bounds accesses to pointer fields. In "struct fsl_mc_io", the "portal_virt_addr" pointer points to the MC command portal virtual address. The size of this allocated portal in bytes is tracked by the "portal_size" field within the same structure. Annotate the "portal_virt_addr" pointer field with "__counted_by_ptr(portal_size)" to enable compiler bounds-checking and harden against potential out-of-bounds accesses. Cc: codemender-patching+linux@google.com Assisted-by: LLM Signed-off-by: Bill Wendling Reviewed-by: Ioana Ciornei Reviewed-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20260922223538.2287676-1-morbo@google.com Signed-off-by: Christophe Leroy (CS GROUP) --- include/linux/fsl/mc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h index c25f0f7e6dd4..0b2c0eb9b605 100644 --- a/include/linux/fsl/mc.h +++ b/include/linux/fsl/mc.h @@ -336,7 +336,7 @@ struct fsl_mc_io { u16 flags; u32 portal_size; phys_addr_t portal_phys_addr; - void __iomem *portal_virt_addr; + void __iomem *portal_virt_addr __counted_by_ptr(portal_size); struct fsl_mc_device *dpmcp_dev; union { /* From 45ecea8c55521d424513178fb612cefffb09a9f5 Mon Sep 17 00:00:00 2001 From: Myeonghun Pak Date: Fri, 2 Oct 2026 15:48:01 -0400 Subject: [PATCH 169/176] soc: fsl: dpio: Fix cleanup on IRQ registration failure IRQ registration happens after dpaa2_io_create(), but its failure path only releases the IRQ resources and the MC portal. The I/O object stays allocated and published in the service list and per-CPU lookup table, while devres unmaps its portal registers after probe fails. Call dpaa2_io_down() on IRQ registration failure to remove the object from those lookup structures and free it. Reorder the error labels so that a failed dpaa2_io_create() still skips this cleanup. Remove unregister_dpio_irq_handlers() from the probe error path, since no IRQ handler or affinity hint has been installed when registration fails. This issue was identified during our ongoing static-analysis research while reviewing kernel code. Fixes: fe8fe7723a3a ("soc: fsl: dpio: register dpio irq handlers after dpio create") Cc: stable@vger.kernel.org Assisted-by: LLM Co-developed-by: Ijae Kim Signed-off-by: Ijae Kim Signed-off-by: Myeonghun Pak Reviewed-by: Ioana Ciornei Link: https://lore.kernel.org/r/20261002194802.375497-2-mhun512@gmail.com Signed-off-by: Christophe Leroy (CS GROUP) --- drivers/soc/fsl/dpio/dpio-driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/fsl/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c index d5198ffc4455..8d3134622a28 100644 --- a/drivers/soc/fsl/dpio/dpio-driver.c +++ b/drivers/soc/fsl/dpio/dpio-driver.c @@ -244,9 +244,9 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) return 0; -err_dpaa2_io_create: - unregister_dpio_irq_handlers(dpio_dev); err_register_dpio_irq: + dpaa2_io_down(priv->io); +err_dpaa2_io_create: fsl_mc_free_irqs(dpio_dev); err_allocate_irqs: dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); From a7831c657c90e8f9165f6bbe0cc56262fee075e8 Mon Sep 17 00:00:00 2001 From: Myeonghun Pak Date: Fri, 2 Oct 2026 15:48:02 -0400 Subject: [PATCH 170/176] soc: fsl: dpio: Free the IRQ before releasing the I/O object The DPIO interrupt handler accesses priv->io, but dpaa2_dpio_remove() releases that object before tearing down the interrupts. The IRQ was requested with devm_request_irq(), and unregister_dpio_irq_handlers() only clears its affinity hint. fsl_mc_free_irqs() returns IRQ resources to the MC resource pool without freeing the handler. An interrupt can therefore access the freed I/O object before devres releases the IRQ. Explicitly free the managed IRQ in unregister_dpio_irq_handlers() before returning its resource to the pool, and perform IRQ teardown before releasing the I/O object. This also waits for an in-flight handler while the object is still valid. This issue was identified during our ongoing static-analysis research while reviewing kernel code. Fixes: 993fec7e11ca ("bus: fsl-mc: dpio: add the DPAA2 DPIO object driver") Cc: stable@vger.kernel.org Assisted-by: LLM Co-developed-by: Ijae Kim Signed-off-by: Ijae Kim Signed-off-by: Myeonghun Pak Reviewed-by: Ioana Ciornei Link: https://lore.kernel.org/r/20261002194802.375497-3-mhun512@gmail.com Signed-off-by: Christophe Leroy (CS GROUP) --- drivers/soc/fsl/dpio/dpio-driver.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/soc/fsl/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c index 8d3134622a28..d8f28fb7c37a 100644 --- a/drivers/soc/fsl/dpio/dpio-driver.c +++ b/drivers/soc/fsl/dpio/dpio-driver.c @@ -88,6 +88,7 @@ static void unregister_dpio_irq_handlers(struct fsl_mc_device *dpio_dev) /* clear the affinity hint */ irq_set_affinity_hint(irq->virq, NULL); + devm_free_irq(&dpio_dev->dev, irq->virq, &dpio_dev->dev); } static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu) @@ -276,10 +277,10 @@ static void dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) priv = dev_get_drvdata(dev); cpu = dpaa2_io_get_cpu(priv->io); - dpaa2_io_down(priv->io); - dpio_teardown_irqs(dpio_dev); + dpaa2_io_down(priv->io); + cpumask_set_cpu(cpu, cpus_unused_mask); err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, From 41d6c0fcd4d75bf78c304c6660d60fcf757885ce Mon Sep 17 00:00:00 2001 From: Yuho Choi Date: Wed, 23 Sep 2026 12:35:15 -0400 Subject: [PATCH 171/176] bus: arm-cci: Drop CPU node reference in cci_ace_init_ports() cci_ace_init_ports() looks up each possible CPU's node with of_get_cpu_node(), which returns the node with its reference count raised, but never releases it: neither when the CPU has no ACE port nor after the port has been recorded. Before the commit below the loop used for_each_child_of_node(), which manages the references itself. The node is only needed for the port lookup, so drop the reference right after __cci_ace_get_port(). Fixes: 78b4d6e0fd26 ("drivers/bus: arm-cci: avoid parsing DT for cpu device nodes") Signed-off-by: Yuho Choi Link: https://lore.kernel.org/r/20260923163536.596107-1-oss.patchbox@gmail.com Signed-off-by: Arnd Bergmann --- drivers/bus/arm-cci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c index 7f2baf057128..076ac8e06bd0 100644 --- a/drivers/bus/arm-cci.c +++ b/drivers/bus/arm-cci.c @@ -199,6 +199,7 @@ static void cci_ace_init_ports(void) continue; port = __cci_ace_get_port(cpun, ACE_PORT); + of_node_put(cpun); if (port < 0) continue; From 810ccc792193909ba9bbb4246e0eb0de14dad724 Mon Sep 17 00:00:00 2001 From: Yuho Choi Date: Wed, 23 Sep 2026 12:40:55 -0400 Subject: [PATCH 172/176] bus: arm-cci: Drop cci-control-port node reference in __cci_ace_get_port() __cci_ace_get_port() looks up the device's "cci-control-port" node with of_parse_phandle(), which returns the node with its reference count raised, and only compares the pointer against the probed ports. Neither the match nor the no-match return releases it. Drop the reference on both paths once the comparison is done. Fixes: ed69bdd8fd9b ("drivers: bus: add ARM CCI support") Signed-off-by: Yuho Choi Link: https://lore.kernel.org/r/20260923164122.596910-1-oss.patchbox@gmail.com Signed-off-by: Arnd Bergmann --- drivers/bus/arm-cci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c index 076ac8e06bd0..435952602d06 100644 --- a/drivers/bus/arm-cci.c +++ b/drivers/bus/arm-cci.c @@ -167,9 +167,12 @@ static int __cci_ace_get_port(struct device_node *dn, int type) cci_portn = of_parse_phandle(dn, "cci-control-port", 0); for (i = 0; i < nb_cci_ports; i++) { ace_match = ports[i].type == type; - if (ace_match && cci_portn == ports[i].dn) + if (ace_match && cci_portn == ports[i].dn) { + of_node_put(cci_portn); return i; + } } + of_node_put(cci_portn); return -ENODEV; } From f918e380449880824c415a39214b553aa7f64d5d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 25 Sep 2026 09:43:17 +0200 Subject: [PATCH 173/176] arm64: enable HAVE_SHARED_GPIOS for all ARM64 platforms Shared GPIO management provided by the GPIO shared proxy module has been enabled for Qualcomm platforms for some time. By extension of the defconfig, it's been effectively enabled for all ARM64 platforms when using the default configuration. Bugs discovered initially after the feature was first enabled, were fixed and I haven't seen any new reports for several months. Make the feature enabled by default for all ARM64 platforms officially, which will allow us to continue the removal of the deprecated GPIOD_FLAGS_BIT_NONEXCLUSIVE flag from the kernel. Acked-by: Catalin Marinas Reviewed-by: Linus Walleij Reviewed-by: Frank Li Signed-off-by: Bartosz Golaszewski Signed-off-by: Arnd Bergmann --- arch/arm64/Kconfig | 1 + arch/arm64/Kconfig.platforms | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b5a51b0ef944..4c8948e87859 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -196,6 +196,7 @@ config ARM64 if DYNAMIC_FTRACE_WITH_ARGS select HAVE_SAMPLE_FTRACE_DIRECT select HAVE_SAMPLE_FTRACE_DIRECT_MULTI + select HAVE_SHARED_GPIOS select HAVE_BUILDTIME_MCOUNT_SORT select HAVE_EFFICIENT_UNALIGNED_ACCESS select HAVE_GUP_FAST diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 76a6a0e6ae4f..74c03cb2f9bc 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -37,7 +37,6 @@ config ARCH_APPLE bool "Apple Silicon SoC family" select APPLE_AIC select APPLE_PMGR_PWRSTATE if PM - select HAVE_SHARED_GPIOS help This enables support for Apple's in-house ARM SoC family, such as the Apple M1. @@ -329,7 +328,6 @@ config ARCH_QCOM select GPIOLIB select PINCTRL select HAVE_PWRCTRL if PCI - select HAVE_SHARED_GPIOS help This enables support for the ARMv8 based Qualcomm chipsets. From 6f77194e1147d85c10b4964edee7091c701a25c2 Mon Sep 17 00:00:00 2001 From: Guangshuo Li Date: Wed, 7 Oct 2026 20:17:43 +0800 Subject: [PATCH 174/176] soc: mpfs: use kref cleanup on probe failure After kref_init(), the device_get_match_data() failure path frees the mailbox channel and sys_controller directly, bypassing the matching kref_put() for the initial reference. Use mpfs_sys_controller_put() on this path so that the initial reference established by kref_init() is released through the existing kref release callback. Rename the error label to reflect that cleanup is now performed through the kref helper. This issue was found by manual code inspection. Fixes: 75ef23397558 ("soc: microchip: mpfs-sys-controller: fix resource leak on probe error") Signed-off-by: Guangshuo Li Signed-off-by: Conor Dooley --- drivers/soc/microchip/mpfs-sys-controller.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/soc/microchip/mpfs-sys-controller.c b/drivers/soc/microchip/mpfs-sys-controller.c index 0400a01b2338..ef27e1083f0f 100644 --- a/drivers/soc/microchip/mpfs-sys-controller.c +++ b/drivers/soc/microchip/mpfs-sys-controller.c @@ -159,7 +159,7 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev) of_data = (struct mpfs_syscon_config *) device_get_match_data(dev); if (!of_data) { ret = dev_err_probe(dev, -EINVAL, "Error getting match data\n"); - goto out_free_channel; + goto out_put; } for (i = 0; i < of_data->nb_subdevs; i++) { @@ -173,8 +173,9 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev) return 0; -out_free_channel: - mbox_free_channel(sys_controller->chan); +out_put: + mpfs_sys_controller_put(sys_controller); + return ret; out_free: kfree(sys_controller); return ret; From b2f3a170ae968fac6270e89ce5738685bd2e530c Mon Sep 17 00:00:00 2001 From: Bence Csokas Date: Thu, 1 Oct 2026 13:00:07 +0200 Subject: [PATCH 175/176] cache: Make cpu_cache_invalidate_memregion() error out if there are no handlers Currently, if there are no registered handlers, cpu_cache_invalidate_memregion() returns 0. Callers are expected to check cpu_cache_has_invalidate_memregion() and return -ENXIO themselves, instead of calling this function. If a caller forgets to do this, they may erroneously think the operation succeeded. This is in contrast to x86, where cpu_cache_invalidate_memregion() itself checks if the operation is supported, and returns -ENXIO if it is not. Reviewed-by: Jonathan Cameron Signed-off-by: Bence Csokas Signed-off-by: Conor Dooley --- lib/cache_maint.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cache_maint.c b/lib/cache_maint.c index 9256a9ffc34c..132d2816d6b1 100644 --- a/lib/cache_maint.c +++ b/lib/cache_maint.c @@ -59,12 +59,12 @@ static int cache_inval_done_one(struct cache_coherency_ops_inst *cci) static int cache_invalidate_memregion(phys_addr_t addr, size_t size) { - int ret; struct cache_coherency_ops_inst *cci; struct cc_inval_params params = { .addr = addr, .size = size, }; + int ret = -ENXIO; guard(rwsem_read)(&cache_ops_instance_list_lock); list_for_each_entry(cci, &cache_ops_instance_list, node) { @@ -78,7 +78,7 @@ static int cache_invalidate_memregion(phys_addr_t addr, size_t size) return ret; } - return 0; + return ret; } struct cache_coherency_ops_inst * From 0045cd6b8ab2319e9d8de46e5e329cdc35ce6d05 Mon Sep 17 00:00:00 2001 From: Myeonghun Pak Date: Thu, 15 Oct 2026 21:39:18 -0400 Subject: [PATCH 176/176] platform: cznic: turris-omnia-mcu: stop button emulation producers The legacy MCU IRQ thread can requeue button-release emulation work after its managed cleanup has canceled it. Since the IRQ is still active at that point, the newly queued work can outlive device teardown and access freed MCU state. Use disable_delayed_work_sync() to prevent further queueing and drain the worker before the IRQ action is released. Keep the parent IRQ active while the worker completes. devm_add_action_or_reset() also drains the work if action registration fails. This issue was identified as part of our ongoing research while reviewing kernel code. Fixes: dfa556e45ae9 ("platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs") Assisted-by: LLM Co-developed-by: Ijae Kim Signed-off-by: Ijae Kim Signed-off-by: Myeonghun Pak Link: https://lore.kernel.org/r/20261016013918.3492835-1-mhun512@gmail.com Signed-off-by: Arnd Bergmann --- .../platform/cznic/turris-omnia-mcu-gpio.c | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/platform/cznic/turris-omnia-mcu-gpio.c b/drivers/platform/cznic/turris-omnia-mcu-gpio.c index 4e430d6c3fc4..8f43bfa92373 100644 --- a/drivers/platform/cznic/turris-omnia-mcu-gpio.c +++ b/drivers/platform/cznic/turris-omnia-mcu-gpio.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -841,6 +840,18 @@ static void button_release_emul_fn(struct work_struct *work) generic_handle_irq_safe(mcu->client->irq); } +static void omnia_disable_button_release_work(void *data) +{ + struct delayed_work *work = data; + + /* + * The IRQ thread may requeue this work while the IRQ remains active. + * Disable and drain it before releasing the IRQ action and the MCU + * state used by the worker. + */ + disable_delayed_work_sync(work); +} + static void fill_int_from_sts(unsigned long *rising, unsigned long *falling, unsigned long rising_sts, unsigned long falling_sts, @@ -1082,21 +1093,9 @@ int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu) return dev_err_probe(dev, err, "Cannot request IRQ\n"); if (!new_api) { - /* - * The button_release_emul_work has to be initialized before the - * thread is requested, and on driver remove it needs to be - * canceled before the thread is freed. Therefore we can't use - * devm_delayed_work_autocancel() directly, because the order - * devm_delayed_work_autocancel(); - * devm_request_threaded_irq(); - * would cause improper release order: - * free_irq(); - * cancel_delayed_work_sync(); - * Instead we first initialize the work above, and only now - * after IRQ is requested we add the work devm action. - */ - err = devm_add_action(dev, devm_delayed_work_drop, - &mcu->button_release_emul_work); + err = devm_add_action_or_reset(dev, + omnia_disable_button_release_work, + &mcu->button_release_emul_work); if (err) return err; }