From aed7440146548cbbcb36780ccc6f9db4cf18f832 Mon Sep 17 00:00:00 2001 From: Anjelique Melendez Date: Mon, 9 Feb 2026 12:49:11 -0800 Subject: [PATCH 001/193] dt-bindings: soc: qcom: qcom,pmic-glink: Add Glymur and Kaanapali compatibles Glymur (a recent compute platform) and Kaanapali (a recent mobile platform) have the charger FW running on a new subsystem SOCCP (SOC Control Processor) instead of on ADSP like in previous platforms. Because of this, pmic_glink interface on Glymur and Kaanapali platforms are not compatible with previous platforms. Hence, add new compatible strings for Glymur and Kaanapali. Signed-off-by: Anjelique Melendez Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260209204915.1983997-2-anjelique.melendez@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml index 7085bf88afab..ff01d2f3ee5b 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml @@ -23,6 +23,8 @@ properties: oneOf: - items: - enum: + - qcom,glymur-pmic-glink + - qcom,kaanapali-pmic-glink - qcom,qcm6490-pmic-glink - qcom,sc8180x-pmic-glink - qcom,sc8280xp-pmic-glink From 540262793df13d90274aae90aa70584ef6fb3aa4 Mon Sep 17 00:00:00 2001 From: Anjelique Melendez Date: Mon, 9 Feb 2026 12:49:12 -0800 Subject: [PATCH 002/193] soc: qcom: pmic_glink: Add charger PDR service information to client data Currently, the charger PD service path and service name are hard coded however these paths are not guaranteed to be the same between SOCs. Define charger PDR service path and service name as client data so that each PMIC generation can properly define these paths. Signed-off-by: Anjelique Melendez Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260209204915.1983997-3-anjelique.melendez@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pmic_glink.c | 58 ++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index 627f96ca322e..df2fd03d3b33 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -23,13 +23,19 @@ enum { PMIC_GLINK_CLIENT_UCSI, }; +struct pmic_glink_data { + unsigned long client_mask; + const char *charger_pdr_service_name; + const char *charger_pdr_service_path; +}; + struct pmic_glink { struct device *dev; struct pdr_handle *pdr; struct rpmsg_endpoint *ept; - unsigned long client_mask; + const struct pmic_glink_data *data; struct auxiliary_device altmode_aux; struct auxiliary_device ps_aux; @@ -292,7 +298,6 @@ static struct rpmsg_driver pmic_glink_rpmsg_driver = { static int pmic_glink_probe(struct platform_device *pdev) { - const unsigned long *match_data; struct pdr_service *service; struct pmic_glink *pg; int ret; @@ -309,12 +314,10 @@ static int pmic_glink_probe(struct platform_device *pdev) spin_lock_init(&pg->client_lock); mutex_init(&pg->state_lock); - match_data = (unsigned long *)of_device_get_match_data(&pdev->dev); - if (!match_data) + pg->data = of_device_get_match_data(&pdev->dev); + if (!pg->data) return -EINVAL; - pg->client_mask = *match_data; - pg->pdr = pdr_handle_alloc(pmic_glink_pdr_callback, pg); if (IS_ERR(pg->pdr)) { ret = dev_err_probe(&pdev->dev, PTR_ERR(pg->pdr), @@ -322,27 +325,30 @@ static int pmic_glink_probe(struct platform_device *pdev) return ret; } - if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) { + if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) { ret = pmic_glink_add_aux_device(pg, &pg->ucsi_aux, "ucsi"); if (ret) goto out_release_pdr_handle; } - if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) { + if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) { ret = pmic_glink_add_aux_device(pg, &pg->altmode_aux, "altmode"); if (ret) goto out_release_ucsi_aux; } - if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) { + if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) { ret = pmic_glink_add_aux_device(pg, &pg->ps_aux, "power-supply"); if (ret) goto out_release_altmode_aux; } - service = pdr_add_lookup(pg->pdr, "tms/servreg", "msm/adsp/charger_pd"); - if (IS_ERR(service)) { - ret = dev_err_probe(&pdev->dev, PTR_ERR(service), - "failed adding pdr lookup for charger_pd\n"); - goto out_release_aux_devices; + if (pg->data->charger_pdr_service_name && pg->data->charger_pdr_service_path) { + service = pdr_add_lookup(pg->pdr, pg->data->charger_pdr_service_name, + pg->data->charger_pdr_service_path); + if (IS_ERR(service)) { + ret = dev_err_probe(&pdev->dev, PTR_ERR(service), + "failed adding pdr lookup for charger_pd\n"); + goto out_release_aux_devices; + } } mutex_lock(&__pmic_glink_lock); @@ -352,13 +358,13 @@ static int pmic_glink_probe(struct platform_device *pdev) return 0; out_release_aux_devices: - if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) + if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) pmic_glink_del_aux_device(pg, &pg->ps_aux); out_release_altmode_aux: - if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) + if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) pmic_glink_del_aux_device(pg, &pg->altmode_aux); out_release_ucsi_aux: - if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) + if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) pmic_glink_del_aux_device(pg, &pg->ucsi_aux); out_release_pdr_handle: pdr_handle_release(pg->pdr); @@ -372,23 +378,27 @@ static void pmic_glink_remove(struct platform_device *pdev) pdr_handle_release(pg->pdr); - if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) + if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) pmic_glink_del_aux_device(pg, &pg->ps_aux); - if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) + if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) pmic_glink_del_aux_device(pg, &pg->altmode_aux); - if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) + if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) pmic_glink_del_aux_device(pg, &pg->ucsi_aux); guard(mutex)(&__pmic_glink_lock); __pmic_glink = NULL; } -static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | - BIT(PMIC_GLINK_CLIENT_ALTMODE) | - BIT(PMIC_GLINK_CLIENT_UCSI); +static const struct pmic_glink_data pmic_glink_adsp_data = { + .client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | + BIT(PMIC_GLINK_CLIENT_ALTMODE) | + BIT(PMIC_GLINK_CLIENT_UCSI), + .charger_pdr_service_name = "tms/servreg", + .charger_pdr_service_path = "msm/adsp/charger_pd", +}; static const struct of_device_id pmic_glink_of_match[] = { - { .compatible = "qcom,pmic-glink", .data = &pmic_glink_sm8450_client_mask }, + { .compatible = "qcom,pmic-glink", .data = &pmic_glink_adsp_data }, {} }; MODULE_DEVICE_TABLE(of, pmic_glink_of_match); From 9386d9e8cc72edc1a55ee1337c442b3ceff1d1ba Mon Sep 17 00:00:00 2001 From: Anjelique Melendez Date: Mon, 9 Feb 2026 12:49:13 -0800 Subject: [PATCH 003/193] soc: qcom: pmic_glink: Add support for Glymur and Kaanapali On Glymur, a compute platform, and Kaanapali, a mobile platform, charger FW runs on SOCCP (another subsystem). SOCCP does not have any specific charger PDs defined. So, add support for Glymur and Kaanapali compatible strings. Signed-off-by: Anjelique Melendez Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260209204915.1983997-4-anjelique.melendez@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pmic_glink.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index df2fd03d3b33..3042261578aa 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -397,7 +397,15 @@ static const struct pmic_glink_data pmic_glink_adsp_data = { .charger_pdr_service_path = "msm/adsp/charger_pd", }; +static const struct pmic_glink_data pmic_glink_soccp_data = { + .client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | + BIT(PMIC_GLINK_CLIENT_ALTMODE) | + BIT(PMIC_GLINK_CLIENT_UCSI), +}; + static const struct of_device_id pmic_glink_of_match[] = { + { .compatible = "qcom,glymur-pmic-glink", .data = &pmic_glink_soccp_data }, + { .compatible = "qcom,kaanapali-pmic-glink", .data = &pmic_glink_soccp_data }, { .compatible = "qcom,pmic-glink", .data = &pmic_glink_adsp_data }, {} }; From ef4d7b9975d6d87a21574f98473945c8e499a0d2 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 16 Jan 2026 13:37:32 +0100 Subject: [PATCH 004/193] memory: tegra: Add support for DBB clock on Tegra264 The DBB clock is needed by many IP blocks in order to access system memory via the data backbone. The memory controller and external memory controllers are the central place where these accesses are managed, so make sure that the clock can be controlled from the corresponding driver. Note that not all drivers fully register bandwidth requests, and hence the EMC driver doesn't have enough information to know when it's safe to switch the clock off, so for now it will be kept on permanently. Signed-off-by: Thierry Reding Reviewed-by: Jon Hunter Link: https://patch.msgid.link/20260116123732.140813-1-thierry.reding@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra186-emc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/memory/tegra/tegra186-emc.c b/drivers/memory/tegra/tegra186-emc.c index dfddceecdd1a..03ebab6fbe68 100644 --- a/drivers/memory/tegra/tegra186-emc.c +++ b/drivers/memory/tegra/tegra186-emc.c @@ -22,6 +22,7 @@ struct tegra186_emc { struct tegra_bpmp *bpmp; struct device *dev; struct clk *clk; + struct clk *clk_dbb; struct tegra186_emc_dvfs *dvfs; unsigned int num_dvfs; @@ -328,6 +329,13 @@ static int tegra186_emc_probe(struct platform_device *pdev) goto put_bpmp; } + emc->clk_dbb = devm_clk_get_optional_enabled(&pdev->dev, "dbb"); + if (IS_ERR(emc->clk_dbb)) { + err = dev_err_probe(&pdev->dev, PTR_ERR(emc->clk_dbb), + "failed to get DBB clock\n"); + goto put_bpmp; + } + platform_set_drvdata(pdev, emc); emc->dev = &pdev->dev; From 9597ab9a8296ab337e6820f8a717ff621078b632 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Mon, 26 Jan 2026 15:50:42 +0900 Subject: [PATCH 005/193] memory: tegra124-emc: Fix dll_change check The code checking whether the specified memory timing enables DLL in the EMRS register was reversed. DLL is enabled if bit A0 is low. Fix the check. Fixes: 73a7f0a90641 ("memory: tegra: Add EMC (external memory controller) driver") Signed-off-by: Mikko Perttunen Link: https://patch.msgid.link/20260126-fix-emc-dllchange-v1-1-47ad3bb63262@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra124-emc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c index ff26815e51f1..5cfbc169c5f9 100644 --- a/drivers/memory/tegra/tegra124-emc.c +++ b/drivers/memory/tegra/tegra124-emc.c @@ -608,7 +608,7 @@ static int tegra124_emc_prepare_timing_change(struct tegra_emc *emc, if ((last->emc_mode_1 & 0x1) == (timing->emc_mode_1 & 0x1)) dll_change = DLL_CHANGE_NONE; - else if (timing->emc_mode_1 & 0x1) + else if (!(timing->emc_mode_1 & 0x1)) dll_change = DLL_CHANGE_ON; else dll_change = DLL_CHANGE_OFF; From 0a93f2355cf4922ad2399dbef5ea1049fef116d4 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Mon, 26 Jan 2026 15:50:43 +0900 Subject: [PATCH 006/193] memory: tegra30-emc: Fix dll_change check The code checking whether the specified memory timing enables DLL in the EMRS register was reversed. DLL is enabled if bit A0 is low. Fix the check. Fixes: e34212c75a68 ("memory: tegra: Introduce Tegra30 EMC driver") Signed-off-by: Mikko Perttunen Link: https://patch.msgid.link/20260126-fix-emc-dllchange-v1-2-47ad3bb63262@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra30-emc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/memory/tegra/tegra30-emc.c b/drivers/memory/tegra/tegra30-emc.c index 606106dd2b32..5812c8cd6ce4 100644 --- a/drivers/memory/tegra/tegra30-emc.c +++ b/drivers/memory/tegra/tegra30-emc.c @@ -554,14 +554,14 @@ static int emc_prepare_timing_change(struct tegra_emc *emc, unsigned long rate) emc->emc_cfg = readl_relaxed(emc->regs + EMC_CFG); emc_dbg = readl_relaxed(emc->regs + EMC_DBG); - if (emc->dll_on == !!(timing->emc_mode_1 & 0x1)) + if (emc->dll_on == !(timing->emc_mode_1 & 0x1)) dll_change = DLL_CHANGE_NONE; - else if (timing->emc_mode_1 & 0x1) + else if (!(timing->emc_mode_1 & 0x1)) dll_change = DLL_CHANGE_ON; else dll_change = DLL_CHANGE_OFF; - emc->dll_on = !!(timing->emc_mode_1 & 0x1); + emc->dll_on = !(timing->emc_mode_1 & 0x1); if (timing->data[80] && !readl_relaxed(emc->regs + EMC_ZCAL_INTERVAL)) emc->zcal_long = true; From 910e91a6496f7e0af80e945a6b850b589b90669e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 19 Feb 2026 12:27:10 +0100 Subject: [PATCH 007/193] firmware: exynos-acpm: Use unsigned int for acpm_pmic_linux_errmap index acpm_pmic_to_linux_err() uses an unsigned integer obtained from messages as index of array to map them to error codes. Array index cannot be negative, so make that explicit. Reviewed-by: Tudor Ambarus Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260219-firmare-acpm-counted-v2-1-e1f7389237d3@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski --- drivers/firmware/samsung/exynos-acpm-pmic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/samsung/exynos-acpm-pmic.c b/drivers/firmware/samsung/exynos-acpm-pmic.c index 961d7599e422..44265db34ae6 100644 --- a/drivers/firmware/samsung/exynos-acpm-pmic.c +++ b/drivers/firmware/samsung/exynos-acpm-pmic.c @@ -41,7 +41,7 @@ static const int acpm_pmic_linux_errmap[] = { [2] = -EACCES, /* Write register can't be accessed or issues to access it. */ }; -static int acpm_pmic_to_linux_err(int err) +static int acpm_pmic_to_linux_err(unsigned int err) { if (err >= 0 && err < ARRAY_SIZE(acpm_pmic_linux_errmap)) return acpm_pmic_linux_errmap[err]; From 00808ae2e679a97dccc5cf0ee4474ba1e2e8a21a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 19 Feb 2026 12:27:11 +0100 Subject: [PATCH 008/193] firmware: exynos-acpm: Count number of commands in acpm_xfer Struct acpm_xfer holds two buffers with u32 commands - rxd and txd - and counts their size by rxlen and txlen. "len" suffix is here ambiguous, so could mean length of the buffer or length of commands, and these are not the same since each command is u32. Rename these to rxcnt and txcnt, and change their usage to count the number of commands in each buffer. This will have a benefit of allowing to use __counted_by_ptr later. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Tudor Ambarus Link: https://patch.msgid.link/20260219-firmare-acpm-counted-v2-2-e1f7389237d3@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski --- drivers/firmware/samsung/exynos-acpm-dvfs.c | 9 +++++---- drivers/firmware/samsung/exynos-acpm-pmic.c | 14 +++++++------- drivers/firmware/samsung/exynos-acpm.c | 14 +++++++------- drivers/firmware/samsung/exynos-acpm.h | 4 ++-- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/firmware/samsung/exynos-acpm-dvfs.c b/drivers/firmware/samsung/exynos-acpm-dvfs.c index 1c5b2b143bcc..485fc77ad4b1 100644 --- a/drivers/firmware/samsung/exynos-acpm-dvfs.c +++ b/drivers/firmware/samsung/exynos-acpm-dvfs.c @@ -5,6 +5,7 @@ * Copyright 2025 Linaro Ltd. */ +#include #include #include #include @@ -25,11 +26,11 @@ static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen, { xfer->acpm_chan_id = acpm_chan_id; xfer->txd = cmd; - xfer->txlen = cmdlen; + xfer->txcnt = cmdlen; if (response) { xfer->rxd = cmd; - xfer->rxlen = cmdlen; + xfer->rxcnt = cmdlen; } } @@ -50,7 +51,7 @@ int acpm_dvfs_set_rate(const struct acpm_handle *handle, u32 cmd[4]; acpm_dvfs_init_set_rate_cmd(cmd, clk_id, rate); - acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, false); + acpm_dvfs_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id, false); return acpm_do_xfer(handle, &xfer); } @@ -70,7 +71,7 @@ unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle, int ret; acpm_dvfs_init_get_rate_cmd(cmd, clk_id); - acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, true); + acpm_dvfs_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id, true); ret = acpm_do_xfer(handle, &xfer); if (ret) diff --git a/drivers/firmware/samsung/exynos-acpm-pmic.c b/drivers/firmware/samsung/exynos-acpm-pmic.c index 44265db34ae6..26a9024d8ed8 100644 --- a/drivers/firmware/samsung/exynos-acpm-pmic.c +++ b/drivers/firmware/samsung/exynos-acpm-pmic.c @@ -63,8 +63,8 @@ static void acpm_pmic_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen, { xfer->txd = cmd; xfer->rxd = cmd; - xfer->txlen = cmdlen; - xfer->rxlen = cmdlen; + xfer->txcnt = cmdlen; + xfer->rxcnt = cmdlen; xfer->acpm_chan_id = acpm_chan_id; } @@ -86,7 +86,7 @@ int acpm_pmic_read_reg(const struct acpm_handle *handle, int ret; acpm_pmic_init_read_cmd(cmd, type, reg, chan); - acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id); + acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id); ret = acpm_do_xfer(handle, &xfer); if (ret) @@ -119,7 +119,7 @@ int acpm_pmic_bulk_read(const struct acpm_handle *handle, return -EINVAL; acpm_pmic_init_bulk_read_cmd(cmd, type, reg, chan, count); - acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id); + acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id); ret = acpm_do_xfer(handle, &xfer); if (ret) @@ -159,7 +159,7 @@ int acpm_pmic_write_reg(const struct acpm_handle *handle, int ret; acpm_pmic_init_write_cmd(cmd, type, reg, chan, value); - acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id); + acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id); ret = acpm_do_xfer(handle, &xfer); if (ret) @@ -199,7 +199,7 @@ int acpm_pmic_bulk_write(const struct acpm_handle *handle, return -EINVAL; acpm_pmic_init_bulk_write_cmd(cmd, type, reg, chan, count, buf); - acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id); + acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id); ret = acpm_do_xfer(handle, &xfer); if (ret) @@ -229,7 +229,7 @@ int acpm_pmic_update_reg(const struct acpm_handle *handle, int ret; acpm_pmic_init_update_cmd(cmd, type, reg, chan, value, mask); - acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id); + acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id); ret = acpm_do_xfer(handle, &xfer); if (ret) diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c index 0cb269c70460..c616ac951a0d 100644 --- a/drivers/firmware/samsung/exynos-acpm.c +++ b/drivers/firmware/samsung/exynos-acpm.c @@ -205,7 +205,7 @@ static void acpm_get_saved_rx(struct acpm_chan *achan, rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]); if (rx_seqnum == tx_seqnum) { - memcpy(xfer->rxd, rx_data->cmd, xfer->rxlen); + memcpy(xfer->rxd, rx_data->cmd, xfer->rxcnt * sizeof(*xfer->rxd)); clear_bit(rx_seqnum - 1, achan->bitmap_seqnum); } } @@ -258,8 +258,7 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer) if (rx_data->response) { if (rx_seqnum == tx_seqnum) { - __ioread32_copy(xfer->rxd, addr, - xfer->rxlen / 4); + __ioread32_copy(xfer->rxd, addr, xfer->rxcnt); rx_set = true; clear_bit(seqnum, achan->bitmap_seqnum); } else { @@ -269,8 +268,7 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer) * clear yet the bitmap. It will be cleared * after the response is copied to the request. */ - __ioread32_copy(rx_data->cmd, addr, - xfer->rxlen / 4); + __ioread32_copy(rx_data->cmd, addr, xfer->rxcnt); } } else { clear_bit(seqnum, achan->bitmap_seqnum); @@ -425,7 +423,9 @@ int acpm_do_xfer(const struct acpm_handle *handle, const struct acpm_xfer *xfer) achan = &acpm->chans[xfer->acpm_chan_id]; - if (!xfer->txd || xfer->txlen > achan->mlen || xfer->rxlen > achan->mlen) + if (!xfer->txd || + (xfer->txcnt * sizeof(*xfer->txd) > achan->mlen) || + (xfer->rxcnt * sizeof(*xfer->rxd) > achan->mlen)) return -EINVAL; if (!achan->poll_completion) { @@ -448,7 +448,7 @@ int acpm_do_xfer(const struct acpm_handle *handle, const struct acpm_xfer *xfer) /* Write TX command. */ __iowrite32_copy(achan->tx.base + achan->mlen * tx_front, - xfer->txd, xfer->txlen / 4); + xfer->txd, xfer->txcnt); /* Advance TX front. */ writel(idx, achan->tx.front); diff --git a/drivers/firmware/samsung/exynos-acpm.h b/drivers/firmware/samsung/exynos-acpm.h index 2d14cb58f98c..422fbcac7284 100644 --- a/drivers/firmware/samsung/exynos-acpm.h +++ b/drivers/firmware/samsung/exynos-acpm.h @@ -10,8 +10,8 @@ struct acpm_xfer { const u32 *txd; u32 *rxd; - size_t txlen; - size_t rxlen; + size_t txcnt; + size_t rxcnt; unsigned int acpm_chan_id; }; From 951b8eee0581bbf39e7b0464d679eee8cb9da3e0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 19 Feb 2026 12:27:12 +0100 Subject: [PATCH 009/193] firmware: exynos-acpm: Count acpm_xfer buffers with __counted_by_ptr Use __counted_by_ptr() attribute on the acpm_xfer buffers so UBSAN will validate runtime that we do not pass over the buffer size, thus making code safer. Usage of __counted_by_ptr() (or actually __counted_by()) requires that counter is initialized before counted array. Tested-by: Tudor Ambarus Reviewed-by: Tudor Ambarus Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260219-firmare-acpm-counted-v2-3-e1f7389237d3@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski --- drivers/firmware/samsung/exynos-acpm-dvfs.c | 4 ++-- drivers/firmware/samsung/exynos-acpm.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/samsung/exynos-acpm-dvfs.c b/drivers/firmware/samsung/exynos-acpm-dvfs.c index 485fc77ad4b1..17e7be7757b3 100644 --- a/drivers/firmware/samsung/exynos-acpm-dvfs.c +++ b/drivers/firmware/samsung/exynos-acpm-dvfs.c @@ -25,12 +25,12 @@ static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen, unsigned int acpm_chan_id, bool response) { xfer->acpm_chan_id = acpm_chan_id; - xfer->txd = cmd; xfer->txcnt = cmdlen; + xfer->txd = cmd; if (response) { - xfer->rxd = cmd; xfer->rxcnt = cmdlen; + xfer->rxd = cmd; } } diff --git a/drivers/firmware/samsung/exynos-acpm.h b/drivers/firmware/samsung/exynos-acpm.h index 422fbcac7284..8392fcb91f45 100644 --- a/drivers/firmware/samsung/exynos-acpm.h +++ b/drivers/firmware/samsung/exynos-acpm.h @@ -8,8 +8,8 @@ #define __EXYNOS_ACPM_H__ struct acpm_xfer { - const u32 *txd; - u32 *rxd; + const u32 *txd __counted_by_ptr(txcnt); + u32 *rxd __counted_by_ptr(rxcnt); size_t txcnt; size_t rxcnt; unsigned int acpm_chan_id; From 3feaa4342637eef673243dd38ccb32e8dc8efd5a Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Thu, 15 Jan 2026 16:24:51 +0100 Subject: [PATCH 010/193] dt-bindings: soc: imx93-media-blk-ctrl: Add PDFC subnode to schema and example i.MX93 SoC mediamix blk-ctrl contains one DISPLAY_MUX register which configures parallel display format by using the "PARALLEL_DISP_FORMAT" field. Document the Parallel Display Format Configuration(PDFC) subnode and add the subnode to example. [m.felsch@pengutronix.de: add bus-width] Signed-off-by: Liu Ying [m.felsch@pengutronix.de: port to v6.18-rc1] Signed-off-by: Marco Felsch Reviewed-by: Rob Herring (Arm) Signed-off-by: Frank Li --- .../soc/imx/fsl,imx93-media-blk-ctrl.yaml | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml index 34aea58094e5..d828c2e82965 100644 --- a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml +++ b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml @@ -40,6 +40,58 @@ properties: minItems: 8 maxItems: 10 + dpi-bridge: + type: object + additionalProperties: false + + properties: + compatible: + enum: + - nxp,imx91-pdfc + - nxp,imx93-pdfc + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: Input port node to receive pixel data. + + port@1: + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: Output port node to downstream pixel data receivers. + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + properties: + bus-width: + enum: [ 16, 18, 24 ] + description: + Specify the physical parallel bus width. + + This property is optional if the display bus-width + matches the SoC bus-width, e.g. a 18-bit RGB666 (display) + is connected and all 18-bit data lines are muxed to the + parallel-output pads. + + This property must be set to 18 to cut only the LSBs + instead of the MSBs in case a 24-bit RGB888 display is + connected and only the lower 18-bit data lanes are muxed + to the parallel-output pads. + + required: + - port@0 + - port@1 + + required: + - compatible + - ports + allOf: - if: properties: @@ -112,4 +164,30 @@ examples: clock-names = "apb", "axi", "nic", "disp", "cam", "pxp", "lcdif", "isi", "csi", "dsi"; #power-domain-cells = <1>; + + dpi-bridge { + compatible = "nxp,imx93-pdfc"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + pdfc_from_lcdif: endpoint { + remote-endpoint = <&lcdif_to_pdfc>; + }; + }; + + port@1 { + reg = <1>; + + pdfc_to_panel: endpoint { + remote-endpoint = <&panel_from_pdfc>; + bus-width = <18>; + }; + }; + }; + }; }; From 28e99f8bc651636e74c1dab259e92c3264f9dc51 Mon Sep 17 00:00:00 2001 From: Stefano Radaelli Date: Mon, 19 Jan 2026 19:35:53 +0100 Subject: [PATCH 011/193] dt-bindings: arm: fsl: add Variscite DART-MX95 Boards Add DT compatible strings for Variscite DART-MX95 SoM and Variscite development carrier Board. Link: https://variscite.com/system-on-module-som/i-mx-9/dart-mx95/ Link: https://variscite.com/carrier-boards/sonata-board/ Acked-by: Krzysztof Kozlowski Signed-off-by: Stefano Radaelli Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 5716d701292c..39245f066ce0 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1477,6 +1477,12 @@ properties: - const: toradex,smarc-imx95 # Toradex SMARC iMX95 Module - const: fsl,imx95 + - description: Variscite DART-MX95 based Boards + items: + - const: variscite,var-dart-mx95-sonata # Variscite DART-MX95 SOM on Sonata Development Board + - const: variscite,var-dart-mx95 # Variscite DART-MX95 SOM + - const: fsl,imx95 + - description: i.MXRT1050 based Boards items: - enum: From 26279c8d5ede072e8fad9b2f14b03fc27888f471 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 26 Jan 2026 17:11:56 +0800 Subject: [PATCH 012/193] bus: imx-aipstz: set default value for opacr registers The sdma script app_2_mcu needs the permission to access the peripheral devices: 1) SDMA2 transactions are set to user-mode in this particular case. 2) This type of script doesn't use the peripheral interface (connected directly to SPBA), but it uses the peripheral DMA interface, then the SDMA2-issued transactions are subjected to AIPSTZ5's security-related checks. So need to clear the Supervisor Protect bit of SPBA2, otherwise the sdma script can't work. As the imx-aipstz is a common driver for all aips bus, so set default value (zero) for all opacr registers. Signed-off-by: Shengjiu Wang Reviewed-by: Laurentiu Mihalcea Reviewed-by: Daniel Baluta Reviewed-by: Frank Li Signed-off-by: Frank Li --- drivers/bus/imx-aipstz.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/bus/imx-aipstz.c b/drivers/bus/imx-aipstz.c index 5fdf377f5d06..83371e5b35a2 100644 --- a/drivers/bus/imx-aipstz.c +++ b/drivers/bus/imx-aipstz.c @@ -11,9 +11,19 @@ #include #define IMX_AIPSTZ_MPR0 0x0 +#define IMX_AIPSTZ_OPACR0 0x40 +#define IMX_AIPSTZ_OPACR1 0x44 +#define IMX_AIPSTZ_OPACR2 0x48 +#define IMX_AIPSTZ_OPACR3 0x4c +#define IMX_AIPSTZ_OPACR4 0x50 struct imx_aipstz_config { u32 mpr0; + u32 opacr0; + u32 opacr1; + u32 opacr2; + u32 opacr3; + u32 opacr4; }; struct imx_aipstz_data { @@ -24,6 +34,11 @@ struct imx_aipstz_data { static void imx_aipstz_apply_default(struct imx_aipstz_data *data) { writel(data->default_cfg->mpr0, data->base + IMX_AIPSTZ_MPR0); + writel(data->default_cfg->opacr0, data->base + IMX_AIPSTZ_OPACR0); + writel(data->default_cfg->opacr1, data->base + IMX_AIPSTZ_OPACR1); + writel(data->default_cfg->opacr2, data->base + IMX_AIPSTZ_OPACR2); + writel(data->default_cfg->opacr3, data->base + IMX_AIPSTZ_OPACR3); + writel(data->default_cfg->opacr4, data->base + IMX_AIPSTZ_OPACR4); } static const struct of_device_id imx_aipstz_match_table[] = { From 4048cdc0655b9d79d8d7475859de186e3f592027 Mon Sep 17 00:00:00 2001 From: Sherry Sun Date: Wed, 4 Feb 2026 16:35:47 +0800 Subject: [PATCH 013/193] dt-bindings: arm: fsl: Add i.MX93 Wireless EVK board Add DT compatible string for NXP i.MX93 Wireless EVK board. i.MX93 Wireless SiP is created by integrating i.MX93 and IW610 WLCSP (Wi-Fi + BLE + 802.15.4). And i.MX93 Wireless EVK board with the i.MX93 Wireless SiP basically reuse the i.MX93 11x11 EVK board, with some minor functional and pin connection differences. Signed-off-by: Sherry Sun Acked-by: Krzysztof Kozlowski Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 39245f066ce0..910c20bf07a4 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1441,6 +1441,7 @@ properties: - fsl,imx93-11x11-evk # i.MX93 11x11 EVK Board - fsl,imx93-11x11-frdm # i.MX93 11x11 FRDM Board - fsl,imx93-14x14-evk # i.MX93 14x14 EVK Board + - fsl,imx93-wireless-evk # i.MX93 and IW610G WLCSP (Wi-Fi + BLE + 802.15.4) SiP EVK Board - const: fsl,imx93 - description: i.MX94 based Boards From 26b86610650eaac17bf6574f34d9119151b95483 Mon Sep 17 00:00:00 2001 From: Jens Glathe Date: Sat, 14 Feb 2026 09:32:54 +0100 Subject: [PATCH 014/193] firmware: qcom: scm: allow QSEECOM on ASUS Vivobook X1P42100 variant Enables access to EFI variables on this machine. Reviewed-by: Dmitry Baryshkov Tested-by: Colin K. Williams Signed-off-by: Jens Glathe Link: https://lore.kernel.org/r/20260214-b4-vivobook-v3-2-3c88065bbf77@oldschoolsolutions.biz 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 8fbc96693a55..2fe1632f06e9 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2290,6 +2290,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-ux3407qa" }, { .compatible = "asus,zenbook-a14-ux3407ra" }, { .compatible = "dell,inspiron-14-plus-7441" }, From d455e0f602d7e4d4ba709418009c39be48fc2149 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 25 Feb 2026 18:37:20 +0100 Subject: [PATCH 015/193] memory: bt1-l2-ctl: Remove not-going-to-be-supported code for Baikal SoC As noticed in the discussion [1] the Baikal SoC and platforms are not going to be finalized, hence remove stale code. Link: https://lore.kernel.org/lkml/22b92ddf-6321-41b5-8073-f9c7064d3432@infradead.org/ [1] Reviewed-by: Randy Dunlap Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20260225173930.3819351-2-andriy.shevchenko@linux.intel.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/Kconfig | 11 -- drivers/memory/Makefile | 1 - drivers/memory/bt1-l2-ctl.c | 323 ------------------------------------ 3 files changed, 335 deletions(-) delete mode 100644 drivers/memory/bt1-l2-ctl.c diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 79df0d22e218..e5527020ff33 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -64,17 +64,6 @@ config BRCMSTB_MEMC controller and specifically control the Self Refresh Power Down (SRPD) inactivity timeout. -config BT1_L2_CTL - bool "Baikal-T1 CM2 L2-RAM Cache Control Block" - depends on MIPS_BAIKAL_T1 || COMPILE_TEST - select MFD_SYSCON - help - Baikal-T1 CPU is based on the MIPS P5600 Warrior IP-core. The CPU - resides Coherency Manager v2 with embedded 1MB L2-cache. It's - possible to tune the L2 cache performance up by setting the data, - tags and way-select latencies of RAM access. This driver provides a - dt properties-based and sysfs interface for it. - config TI_AEMIF tristate "Texas Instruments AEMIF driver" depends on ARCH_DAVINCI || ARCH_KEYSTONE || COMPILE_TEST diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index c1959661bf63..3ee883c8759a 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o obj-$(CONFIG_BRCMSTB_MEMC) += brcmstb_memc.o -obj-$(CONFIG_BT1_L2_CTL) += bt1-l2-ctl.o obj-$(CONFIG_TI_AEMIF) += ti-aemif.o obj-$(CONFIG_TI_EMIF) += emif.o obj-$(CONFIG_OMAP_GPMC) += omap-gpmc.o diff --git a/drivers/memory/bt1-l2-ctl.c b/drivers/memory/bt1-l2-ctl.c deleted file mode 100644 index 0fd96abc172a..000000000000 --- a/drivers/memory/bt1-l2-ctl.c +++ /dev/null @@ -1,323 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC - * - * Authors: - * Serge Semin - * - * Baikal-T1 CM2 L2-cache Control Block driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define L2_CTL_REG 0x028 -#define L2_CTL_DATA_STALL_FLD 0 -#define L2_CTL_DATA_STALL_MASK GENMASK(1, L2_CTL_DATA_STALL_FLD) -#define L2_CTL_TAG_STALL_FLD 2 -#define L2_CTL_TAG_STALL_MASK GENMASK(3, L2_CTL_TAG_STALL_FLD) -#define L2_CTL_WS_STALL_FLD 4 -#define L2_CTL_WS_STALL_MASK GENMASK(5, L2_CTL_WS_STALL_FLD) -#define L2_CTL_SET_CLKRATIO BIT(13) -#define L2_CTL_CLKRATIO_LOCK BIT(31) - -#define L2_CTL_STALL_MIN 0 -#define L2_CTL_STALL_MAX 3 -#define L2_CTL_STALL_SET_DELAY_US 1 -#define L2_CTL_STALL_SET_TOUT_US 1000 - -/* - * struct l2_ctl - Baikal-T1 L2 Control block private data. - * @dev: Pointer to the device structure. - * @sys_regs: Baikal-T1 System Controller registers map. - */ -struct l2_ctl { - struct device *dev; - - struct regmap *sys_regs; -}; - -/* - * enum l2_ctl_stall - Baikal-T1 L2-cache-RAM stall identifier. - * @L2_WSSTALL: Way-select latency. - * @L2_TAGSTALL: Tag latency. - * @L2_DATASTALL: Data latency. - */ -enum l2_ctl_stall { - L2_WS_STALL, - L2_TAG_STALL, - L2_DATA_STALL -}; - -/* - * struct l2_ctl_device_attribute - Baikal-T1 L2-cache device attribute. - * @dev_attr: Actual sysfs device attribute. - * @id: L2-cache stall field identifier. - */ -struct l2_ctl_device_attribute { - struct device_attribute dev_attr; - enum l2_ctl_stall id; -}; - -#define to_l2_ctl_dev_attr(_dev_attr) \ - container_of(_dev_attr, struct l2_ctl_device_attribute, dev_attr) - -#define L2_CTL_ATTR_RW(_name, _prefix, _id) \ - struct l2_ctl_device_attribute l2_ctl_attr_##_name = \ - { __ATTR(_name, 0644, _prefix##_show, _prefix##_store), _id } - -static int l2_ctl_get_latency(struct l2_ctl *l2, enum l2_ctl_stall id, u32 *val) -{ - u32 data = 0; - int ret; - - ret = regmap_read(l2->sys_regs, L2_CTL_REG, &data); - if (ret) - return ret; - - switch (id) { - case L2_WS_STALL: - *val = FIELD_GET(L2_CTL_WS_STALL_MASK, data); - break; - case L2_TAG_STALL: - *val = FIELD_GET(L2_CTL_TAG_STALL_MASK, data); - break; - case L2_DATA_STALL: - *val = FIELD_GET(L2_CTL_DATA_STALL_MASK, data); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int l2_ctl_set_latency(struct l2_ctl *l2, enum l2_ctl_stall id, u32 val) -{ - u32 mask = 0, data = 0; - int ret; - - val = clamp_val(val, L2_CTL_STALL_MIN, L2_CTL_STALL_MAX); - - switch (id) { - case L2_WS_STALL: - data = FIELD_PREP(L2_CTL_WS_STALL_MASK, val); - mask = L2_CTL_WS_STALL_MASK; - break; - case L2_TAG_STALL: - data = FIELD_PREP(L2_CTL_TAG_STALL_MASK, val); - mask = L2_CTL_TAG_STALL_MASK; - break; - case L2_DATA_STALL: - data = FIELD_PREP(L2_CTL_DATA_STALL_MASK, val); - mask = L2_CTL_DATA_STALL_MASK; - break; - default: - return -EINVAL; - } - - data |= L2_CTL_SET_CLKRATIO; - mask |= L2_CTL_SET_CLKRATIO; - - ret = regmap_update_bits(l2->sys_regs, L2_CTL_REG, mask, data); - if (ret) - return ret; - - return regmap_read_poll_timeout(l2->sys_regs, L2_CTL_REG, data, - data & L2_CTL_CLKRATIO_LOCK, - L2_CTL_STALL_SET_DELAY_US, - L2_CTL_STALL_SET_TOUT_US); -} - -static void l2_ctl_clear_data(void *data) -{ - struct l2_ctl *l2 = data; - struct platform_device *pdev = to_platform_device(l2->dev); - - platform_set_drvdata(pdev, NULL); -} - -static struct l2_ctl *l2_ctl_create_data(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct l2_ctl *l2; - int ret; - - l2 = devm_kzalloc(dev, sizeof(*l2), GFP_KERNEL); - if (!l2) - return ERR_PTR(-ENOMEM); - - ret = devm_add_action(dev, l2_ctl_clear_data, l2); - if (ret) { - dev_err(dev, "Can't add L2 CTL data clear action\n"); - return ERR_PTR(ret); - } - - l2->dev = dev; - platform_set_drvdata(pdev, l2); - - return l2; -} - -static int l2_ctl_find_sys_regs(struct l2_ctl *l2) -{ - l2->sys_regs = syscon_node_to_regmap(l2->dev->of_node->parent); - if (IS_ERR(l2->sys_regs)) { - dev_err(l2->dev, "Couldn't get L2 CTL register map\n"); - return PTR_ERR(l2->sys_regs); - } - - return 0; -} - -static int l2_ctl_of_parse_property(struct l2_ctl *l2, enum l2_ctl_stall id, - const char *propname) -{ - int ret = 0; - u32 data; - - if (!of_property_read_u32(l2->dev->of_node, propname, &data)) { - ret = l2_ctl_set_latency(l2, id, data); - if (ret) - dev_err(l2->dev, "Invalid value of '%s'\n", propname); - } - - return ret; -} - -static int l2_ctl_of_parse(struct l2_ctl *l2) -{ - int ret; - - ret = l2_ctl_of_parse_property(l2, L2_WS_STALL, "baikal,l2-ws-latency"); - if (ret) - return ret; - - ret = l2_ctl_of_parse_property(l2, L2_TAG_STALL, "baikal,l2-tag-latency"); - if (ret) - return ret; - - return l2_ctl_of_parse_property(l2, L2_DATA_STALL, - "baikal,l2-data-latency"); -} - -static ssize_t l2_ctl_latency_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct l2_ctl_device_attribute *devattr = to_l2_ctl_dev_attr(attr); - struct l2_ctl *l2 = dev_get_drvdata(dev); - u32 data; - int ret; - - ret = l2_ctl_get_latency(l2, devattr->id, &data); - if (ret) - return ret; - - return sysfs_emit(buf, "%u\n", data); -} - -static ssize_t l2_ctl_latency_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct l2_ctl_device_attribute *devattr = to_l2_ctl_dev_attr(attr); - struct l2_ctl *l2 = dev_get_drvdata(dev); - u32 data; - int ret; - - if (kstrtouint(buf, 0, &data) < 0) - return -EINVAL; - - ret = l2_ctl_set_latency(l2, devattr->id, data); - if (ret) - return ret; - - return count; -} - -static L2_CTL_ATTR_RW(l2_ws_latency, l2_ctl_latency, L2_WS_STALL); -static L2_CTL_ATTR_RW(l2_tag_latency, l2_ctl_latency, L2_TAG_STALL); -static L2_CTL_ATTR_RW(l2_data_latency, l2_ctl_latency, L2_DATA_STALL); - -static struct attribute *l2_ctl_sysfs_attrs[] = { - &l2_ctl_attr_l2_ws_latency.dev_attr.attr, - &l2_ctl_attr_l2_tag_latency.dev_attr.attr, - &l2_ctl_attr_l2_data_latency.dev_attr.attr, - NULL -}; -ATTRIBUTE_GROUPS(l2_ctl_sysfs); - -static void l2_ctl_remove_sysfs(void *data) -{ - struct l2_ctl *l2 = data; - - device_remove_groups(l2->dev, l2_ctl_sysfs_groups); -} - -static int l2_ctl_init_sysfs(struct l2_ctl *l2) -{ - int ret; - - ret = device_add_groups(l2->dev, l2_ctl_sysfs_groups); - if (ret) { - dev_err(l2->dev, "Failed to create L2 CTL sysfs nodes\n"); - return ret; - } - - ret = devm_add_action_or_reset(l2->dev, l2_ctl_remove_sysfs, l2); - if (ret) - dev_err(l2->dev, "Can't add L2 CTL sysfs remove action\n"); - - return ret; -} - -static int l2_ctl_probe(struct platform_device *pdev) -{ - struct l2_ctl *l2; - int ret; - - l2 = l2_ctl_create_data(pdev); - if (IS_ERR(l2)) - return PTR_ERR(l2); - - ret = l2_ctl_find_sys_regs(l2); - if (ret) - return ret; - - ret = l2_ctl_of_parse(l2); - if (ret) - return ret; - - ret = l2_ctl_init_sysfs(l2); - if (ret) - return ret; - - return 0; -} - -static const struct of_device_id l2_ctl_of_match[] = { - { .compatible = "baikal,bt1-l2-ctl" }, - { } -}; -MODULE_DEVICE_TABLE(of, l2_ctl_of_match); - -static struct platform_driver l2_ctl_driver = { - .probe = l2_ctl_probe, - .driver = { - .name = "bt1-l2-ctl", - .of_match_table = l2_ctl_of_match - } -}; -module_platform_driver(l2_ctl_driver); - -MODULE_AUTHOR("Serge Semin "); -MODULE_DESCRIPTION("Baikal-T1 L2-cache driver"); From 9983d51d1a68520ce74663920929e27b191cf43a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 25 Feb 2026 18:37:21 +0100 Subject: [PATCH 016/193] dt-bindings: cache: bt1-l2-ctl: Remove unused bindings As stated in [1] the Baikal platforms are not supported and the respective driver code has just been removed. Remove unused bindings. Link: https://lore.kernel.org/lkml/22b92ddf-6321-41b5-8073-f9c7064d3432@infradead.org/ [1] Acked-by: Conor Dooley Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20260225173930.3819351-3-andriy.shevchenko@linux.intel.com Signed-off-by: Krzysztof Kozlowski --- .../bindings/cache/baikal,bt1-l2-ctl.yaml | 63 ------------------- 1 file changed, 63 deletions(-) delete mode 100644 Documentation/devicetree/bindings/cache/baikal,bt1-l2-ctl.yaml diff --git a/Documentation/devicetree/bindings/cache/baikal,bt1-l2-ctl.yaml b/Documentation/devicetree/bindings/cache/baikal,bt1-l2-ctl.yaml deleted file mode 100644 index ec4f367bc0b4..000000000000 --- a/Documentation/devicetree/bindings/cache/baikal,bt1-l2-ctl.yaml +++ /dev/null @@ -1,63 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -# Copyright (C) 2020 BAIKAL ELECTRONICS, JSC -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/cache/baikal,bt1-l2-ctl.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Baikal-T1 L2-cache Control Block - -maintainers: - - Serge Semin - -description: | - By means of the System Controller Baikal-T1 SoC exposes a few settings to - tune the MIPS P5600 CM2 L2 cache performance up. In particular it's possible - to change the Tag, Data and Way-select RAM access latencies. Baikal-T1 - L2-cache controller block is responsible for the tuning. Its DT node is - supposed to be a child of the system controller. - -properties: - compatible: - const: baikal,bt1-l2-ctl - - reg: - maxItems: 1 - - baikal,l2-ws-latency: - $ref: /schemas/types.yaml#/definitions/uint32 - description: Cycles of latency for Way-select RAM accesses - default: 0 - minimum: 0 - maximum: 3 - - baikal,l2-tag-latency: - $ref: /schemas/types.yaml#/definitions/uint32 - description: Cycles of latency for Tag RAM accesses - default: 0 - minimum: 0 - maximum: 3 - - baikal,l2-data-latency: - $ref: /schemas/types.yaml#/definitions/uint32 - description: Cycles of latency for Data RAM accesses - default: 1 - minimum: 0 - maximum: 3 - -additionalProperties: false - -required: - - compatible - -examples: - - | - l2@1f04d028 { - compatible = "baikal,bt1-l2-ctl"; - reg = <0x1f04d028 0x004>; - - baikal,l2-ws-latency = <1>; - baikal,l2-tag-latency = <1>; - baikal,l2-data-latency = <2>; - }; -... From f2e83070febf61fc72765cdc28d2a45c89b77ce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Tue, 10 Feb 2026 12:42:32 +0000 Subject: [PATCH 017/193] dt-bindings: firmware: google,gs101-acpm-ipc: add S2MPG11 secondary PMIC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In a typical system using the Samsung S2MPG10 PMIC, an S2MPG11 is used as a sub-PMIC. The interface for both is the ACPM firmware protocol, so update the binding to allow the relevant node and update the example here to describe the connection for both PMICs. Since we have two PMICs here, but can not use the 'reg' property (as the addressing is based on software, i.e. the ACPM firmware), the node names reflect that with their respective suffix. The existing 'pmic' therefore becomes deprecated in favour of 'pmic-1'. While at it, update the example. Reviewed-by: Krzysztof Kozlowski Signed-off-by: André Draszik Link: https://patch.msgid.link/20260210-s2mpg1x-regulators-v8-1-c429d709c0e0@linaro.org Signed-off-by: Krzysztof Kozlowski --- .../firmware/google,gs101-acpm-ipc.yaml | 50 ++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml index 4a1e3e3c0505..e68f9c3ca5e2 100644 --- a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml +++ b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml @@ -37,6 +37,7 @@ properties: maxItems: 1 pmic: + deprecated: true description: Child node describing the main PMIC. type: object additionalProperties: true @@ -45,6 +46,24 @@ properties: compatible: const: samsung,s2mpg10-pmic + pmic-1: + description: Child node describing the main PMIC. + type: object + additionalProperties: true + + properties: + compatible: + const: samsung,s2mpg10-pmic + + pmic-2: + description: Child node describing the sub PMIC. + type: object + additionalProperties: true + + properties: + compatible: + const: samsung,s2mpg11-pmic + shmem: description: List of phandle pointing to the shared memory (SHM) area. The memory @@ -62,7 +81,9 @@ additionalProperties: false examples: - | + #include #include + #include power-management { compatible = "google,gs101-acpm-ipc"; @@ -70,10 +91,12 @@ examples: mboxes = <&ap2apm_mailbox>; shmem = <&apm_sram>; - pmic { + pmic-1 { compatible = "samsung,s2mpg10-pmic"; interrupts-extended = <&gpa0 6 IRQ_TYPE_LEVEL_LOW>; + vinl3m-supply = <&buck8m>; + regulators { ldo1m { regulator-name = "vdd_ldo1"; @@ -82,7 +105,13 @@ examples: regulator-always-on; }; - // ... + ldo20m { + regulator-name = "vdd_dmics"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + samsung,ext-control = ; + }; buck8m { regulator-name = "vdd_mif"; @@ -93,4 +122,21 @@ examples: }; }; }; + + pmic-2 { + compatible = "samsung,s2mpg11-pmic"; + interrupts-extended = <&gpa0 7 IRQ_TYPE_LEVEL_LOW>; + + vinl1s-supply = <&buck8m>; + vinl2s-supply = <&buck6s>; + + regulators { + buckd { + regulator-name = "vcc_ufs"; + regulator-ramp-delay = <6250>; + enable-gpios = <&gpp0 1 GPIO_ACTIVE_HIGH>; + samsung,ext-control = ; + }; + }; + }; }; From a969a0835152984a0f556434eafdee0b84213670 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 21 Jan 2026 16:35:00 -0800 Subject: [PATCH 018/193] memory: brcmstb_memc: Expand LPDDR4 check to cover for LPDDR5 The same limitations that apply to LPDDR4 also apply to LPDDR5. Expand the check and rename accordingly. Signed-off-by: Florian Fainelli Link: https://patch.msgid.link/20260122003501.1191059-1-florian.fainelli@broadcom.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/brcmstb_memc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/memory/brcmstb_memc.c b/drivers/memory/brcmstb_memc.c index ba73470b1b13..c28fe9093616 100644 --- a/drivers/memory/brcmstb_memc.c +++ b/drivers/memory/brcmstb_memc.c @@ -14,6 +14,7 @@ #define REG_MEMC_CNTRLR_CONFIG 0x00 #define CNTRLR_CONFIG_LPDDR4_SHIFT 5 +#define CNTRLR_CONFIG_LPDDR5_SHIFT 6 #define CNTRLR_CONFIG_MASK 0xf #define REG_MEMC_SRPD_CFG_21 0x20 #define REG_MEMC_SRPD_CFG_20 0x34 @@ -34,14 +35,15 @@ struct brcmstb_memc { u32 srpd_offset; }; -static int brcmstb_memc_uses_lpddr4(struct brcmstb_memc *memc) +static int brcmstb_memc_uses_lpddr45(struct brcmstb_memc *memc) { void __iomem *config = memc->ddr_ctrl + REG_MEMC_CNTRLR_CONFIG; u32 reg; reg = readl_relaxed(config) & CNTRLR_CONFIG_MASK; - return reg == CNTRLR_CONFIG_LPDDR4_SHIFT; + return reg == CNTRLR_CONFIG_LPDDR4_SHIFT || + reg == CNTRLR_CONFIG_LPDDR5_SHIFT; } static int brcmstb_memc_srpd_config(struct brcmstb_memc *memc, @@ -95,7 +97,7 @@ static ssize_t srpd_store(struct device *dev, struct device_attribute *attr, * dynamic tuning process will also get affected by the inactivity * timeout, thus making it non functional. */ - if (brcmstb_memc_uses_lpddr4(memc)) + if (brcmstb_memc_uses_lpddr45(memc)) return -EOPNOTSUPP; ret = kstrtouint(buf, 10, &val); From a2be37eedb52ea26938fa4cc9de1ff84963c57ad Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 24 Feb 2026 11:42:04 +0100 Subject: [PATCH 019/193] firmware: exynos-acpm: Drop fake 'const' on handle pointer All the functions operating on the 'handle' pointer are claiming it is a pointer to const thus they should not modify the handle. In fact that's a false statement, because first thing these functions do is drop the cast to const with container_of: struct acpm_info *acpm = handle_to_acpm_info(handle); And with such cast the handle is easily writable with simple: acpm->handle.ops.pmic_ops.read_reg = NULL; The code is not correct logically, either, because functions like acpm_get_by_node() and acpm_handle_put() are meant to modify the handle reference counting, thus they must modify the handle. Modification here happens anyway, even if the reference counting is stored in the container which the handle is part of. The code does not have actual visible bug, but incorrect 'const' annotations could lead to incorrect compiler decisions. Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver") Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260224104203.42950-2-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-acpm.c | 4 +- drivers/firmware/samsung/exynos-acpm-dvfs.c | 4 +- drivers/firmware/samsung/exynos-acpm-dvfs.h | 4 +- drivers/firmware/samsung/exynos-acpm-pmic.c | 10 ++--- drivers/firmware/samsung/exynos-acpm-pmic.h | 10 ++--- drivers/firmware/samsung/exynos-acpm.c | 16 ++++---- drivers/firmware/samsung/exynos-acpm.h | 2 +- drivers/mfd/sec-acpm.c | 10 ++--- .../firmware/samsung/exynos-acpm-protocol.h | 40 ++++++++----------- 9 files changed, 48 insertions(+), 52 deletions(-) diff --git a/drivers/clk/samsung/clk-acpm.c b/drivers/clk/samsung/clk-acpm.c index b90809ce3f88..d8944160793a 100644 --- a/drivers/clk/samsung/clk-acpm.c +++ b/drivers/clk/samsung/clk-acpm.c @@ -20,7 +20,7 @@ struct acpm_clk { u32 id; struct clk_hw hw; unsigned int mbox_chan_id; - const struct acpm_handle *handle; + struct acpm_handle *handle; }; struct acpm_clk_variant { @@ -113,7 +113,7 @@ static int acpm_clk_register(struct device *dev, struct acpm_clk *aclk, static int acpm_clk_probe(struct platform_device *pdev) { - const struct acpm_handle *acpm_handle; + struct acpm_handle *acpm_handle; struct clk_hw_onecell_data *clk_data; struct clk_hw **hws; struct device *dev = &pdev->dev; diff --git a/drivers/firmware/samsung/exynos-acpm-dvfs.c b/drivers/firmware/samsung/exynos-acpm-dvfs.c index 17e7be7757b3..06bdf62dea1f 100644 --- a/drivers/firmware/samsung/exynos-acpm-dvfs.c +++ b/drivers/firmware/samsung/exynos-acpm-dvfs.c @@ -43,7 +43,7 @@ static void acpm_dvfs_init_set_rate_cmd(u32 cmd[4], unsigned int clk_id, cmd[3] = ktime_to_ms(ktime_get()); } -int acpm_dvfs_set_rate(const struct acpm_handle *handle, +int acpm_dvfs_set_rate(struct acpm_handle *handle, unsigned int acpm_chan_id, unsigned int clk_id, unsigned long rate) { @@ -63,7 +63,7 @@ static void acpm_dvfs_init_get_rate_cmd(u32 cmd[4], unsigned int clk_id) cmd[3] = ktime_to_ms(ktime_get()); } -unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle, +unsigned long acpm_dvfs_get_rate(struct acpm_handle *handle, unsigned int acpm_chan_id, unsigned int clk_id) { struct acpm_xfer xfer; diff --git a/drivers/firmware/samsung/exynos-acpm-dvfs.h b/drivers/firmware/samsung/exynos-acpm-dvfs.h index 9f2778e649c9..b37b15426102 100644 --- a/drivers/firmware/samsung/exynos-acpm-dvfs.h +++ b/drivers/firmware/samsung/exynos-acpm-dvfs.h @@ -11,10 +11,10 @@ struct acpm_handle; -int acpm_dvfs_set_rate(const struct acpm_handle *handle, +int acpm_dvfs_set_rate(struct acpm_handle *handle, unsigned int acpm_chan_id, unsigned int id, unsigned long rate); -unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle, +unsigned long acpm_dvfs_get_rate(struct acpm_handle *handle, unsigned int acpm_chan_id, unsigned int clk_id); diff --git a/drivers/firmware/samsung/exynos-acpm-pmic.c b/drivers/firmware/samsung/exynos-acpm-pmic.c index 26a9024d8ed8..0c50993cc9a8 100644 --- a/drivers/firmware/samsung/exynos-acpm-pmic.c +++ b/drivers/firmware/samsung/exynos-acpm-pmic.c @@ -77,7 +77,7 @@ static void acpm_pmic_init_read_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan) cmd[3] = ktime_to_ms(ktime_get()); } -int acpm_pmic_read_reg(const struct acpm_handle *handle, +int acpm_pmic_read_reg(struct acpm_handle *handle, unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, u8 *buf) { @@ -107,7 +107,7 @@ static void acpm_pmic_init_bulk_read_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan, FIELD_PREP(ACPM_PMIC_VALUE, count); } -int acpm_pmic_bulk_read(const struct acpm_handle *handle, +int acpm_pmic_bulk_read(struct acpm_handle *handle, unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, u8 count, u8 *buf) { @@ -150,7 +150,7 @@ static void acpm_pmic_init_write_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan, cmd[3] = ktime_to_ms(ktime_get()); } -int acpm_pmic_write_reg(const struct acpm_handle *handle, +int acpm_pmic_write_reg(struct acpm_handle *handle, unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, u8 value) { @@ -187,7 +187,7 @@ static void acpm_pmic_init_bulk_write_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan, } } -int acpm_pmic_bulk_write(const struct acpm_handle *handle, +int acpm_pmic_bulk_write(struct acpm_handle *handle, unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, u8 count, const u8 *buf) { @@ -220,7 +220,7 @@ static void acpm_pmic_init_update_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan, cmd[3] = ktime_to_ms(ktime_get()); } -int acpm_pmic_update_reg(const struct acpm_handle *handle, +int acpm_pmic_update_reg(struct acpm_handle *handle, unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, u8 value, u8 mask) { diff --git a/drivers/firmware/samsung/exynos-acpm-pmic.h b/drivers/firmware/samsung/exynos-acpm-pmic.h index 078421888a14..88ae9aada2ae 100644 --- a/drivers/firmware/samsung/exynos-acpm-pmic.h +++ b/drivers/firmware/samsung/exynos-acpm-pmic.h @@ -11,19 +11,19 @@ struct acpm_handle; -int acpm_pmic_read_reg(const struct acpm_handle *handle, +int acpm_pmic_read_reg(struct acpm_handle *handle, unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, u8 *buf); -int acpm_pmic_bulk_read(const struct acpm_handle *handle, +int acpm_pmic_bulk_read(struct acpm_handle *handle, unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, u8 count, u8 *buf); -int acpm_pmic_write_reg(const struct acpm_handle *handle, +int acpm_pmic_write_reg(struct acpm_handle *handle, unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, u8 value); -int acpm_pmic_bulk_write(const struct acpm_handle *handle, +int acpm_pmic_bulk_write(struct acpm_handle *handle, unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, u8 count, const u8 *buf); -int acpm_pmic_update_reg(const struct acpm_handle *handle, +int acpm_pmic_update_reg(struct acpm_handle *handle, unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, u8 value, u8 mask); #endif /* __EXYNOS_ACPM_PMIC_H__ */ diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c index c616ac951a0d..16c46ed60837 100644 --- a/drivers/firmware/samsung/exynos-acpm.c +++ b/drivers/firmware/samsung/exynos-acpm.c @@ -410,7 +410,7 @@ static int acpm_wait_for_message_response(struct acpm_chan *achan, * * Return: 0 on success, -errno otherwise. */ -int acpm_do_xfer(const struct acpm_handle *handle, const struct acpm_xfer *xfer) +int acpm_do_xfer(struct acpm_handle *handle, const struct acpm_xfer *xfer) { struct acpm_info *acpm = handle_to_acpm_info(handle); struct exynos_mbox_msg msg; @@ -674,7 +674,7 @@ static int acpm_probe(struct platform_device *pdev) * acpm_handle_put() - release the handle acquired by acpm_get_by_phandle. * @handle: Handle acquired by acpm_get_by_phandle. */ -static void acpm_handle_put(const struct acpm_handle *handle) +static void acpm_handle_put(struct acpm_handle *handle) { struct acpm_info *acpm = handle_to_acpm_info(handle); struct device *dev = acpm->dev; @@ -700,9 +700,11 @@ static void devm_acpm_release(struct device *dev, void *res) * @np: ACPM device tree node. * * Return: pointer to handle on success, ERR_PTR(-errno) otherwise. + * + * Note: handle CANNOT be pointer to const */ -static const struct acpm_handle *acpm_get_by_node(struct device *dev, - struct device_node *np) +static struct acpm_handle *acpm_get_by_node(struct device *dev, + struct device_node *np) { struct platform_device *pdev; struct device_link *link; @@ -743,10 +745,10 @@ static const struct acpm_handle *acpm_get_by_node(struct device *dev, * * Return: pointer to handle on success, ERR_PTR(-errno) otherwise. */ -const struct acpm_handle *devm_acpm_get_by_node(struct device *dev, - struct device_node *np) +struct acpm_handle *devm_acpm_get_by_node(struct device *dev, + struct device_node *np) { - const struct acpm_handle **ptr, *handle; + struct acpm_handle **ptr, *handle; ptr = devres_alloc(devm_acpm_release, sizeof(*ptr), GFP_KERNEL); if (!ptr) diff --git a/drivers/firmware/samsung/exynos-acpm.h b/drivers/firmware/samsung/exynos-acpm.h index 8392fcb91f45..5df8354dc96c 100644 --- a/drivers/firmware/samsung/exynos-acpm.h +++ b/drivers/firmware/samsung/exynos-acpm.h @@ -17,7 +17,7 @@ struct acpm_xfer { struct acpm_handle; -int acpm_do_xfer(const struct acpm_handle *handle, +int acpm_do_xfer(struct acpm_handle *handle, const struct acpm_xfer *xfer); #endif /* __EXYNOS_ACPM_H__ */ diff --git a/drivers/mfd/sec-acpm.c b/drivers/mfd/sec-acpm.c index 537ea65685bf..0e23b9d9f7ee 100644 --- a/drivers/mfd/sec-acpm.c +++ b/drivers/mfd/sec-acpm.c @@ -367,7 +367,7 @@ static const struct regmap_config s2mpg11_regmap_config_meter = { }; struct sec_pmic_acpm_shared_bus_context { - const struct acpm_handle *acpm; + struct acpm_handle *acpm; unsigned int acpm_chan_id; u8 speedy_channel; }; @@ -390,7 +390,7 @@ static int sec_pmic_acpm_bus_write(void *context, const void *data, size_t count) { struct sec_pmic_acpm_bus_context *ctx = context; - const struct acpm_handle *acpm = ctx->shared->acpm; + struct acpm_handle *acpm = ctx->shared->acpm; const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops; size_t val_count = count - BITS_TO_BYTES(ACPM_ADDR_BITS); const u8 *d = data; @@ -410,7 +410,7 @@ static int sec_pmic_acpm_bus_read(void *context, const void *reg_buf, size_t reg void *val_buf, size_t val_size) { struct sec_pmic_acpm_bus_context *ctx = context; - const struct acpm_handle *acpm = ctx->shared->acpm; + struct acpm_handle *acpm = ctx->shared->acpm; const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops; const u8 *r = reg_buf; u8 reg; @@ -429,7 +429,7 @@ static int sec_pmic_acpm_bus_reg_update_bits(void *context, unsigned int reg, un unsigned int val) { struct sec_pmic_acpm_bus_context *ctx = context; - const struct acpm_handle *acpm = ctx->shared->acpm; + struct acpm_handle *acpm = ctx->shared->acpm; const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops; return pmic_ops->update_reg(acpm, ctx->shared->acpm_chan_id, ctx->type, reg & 0xff, @@ -480,7 +480,7 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev) struct regmap *regmap_common, *regmap_pmic, *regmap; const struct sec_pmic_acpm_platform_data *pdata; struct sec_pmic_acpm_shared_bus_context *shared_ctx; - const struct acpm_handle *acpm; + struct acpm_handle *acpm; struct device *dev = &pdev->dev; int ret, irq; diff --git a/include/linux/firmware/samsung/exynos-acpm-protocol.h b/include/linux/firmware/samsung/exynos-acpm-protocol.h index 2091da965a5a..13f17dc4443b 100644 --- a/include/linux/firmware/samsung/exynos-acpm-protocol.h +++ b/include/linux/firmware/samsung/exynos-acpm-protocol.h @@ -14,30 +14,24 @@ struct acpm_handle; struct device_node; struct acpm_dvfs_ops { - int (*set_rate)(const struct acpm_handle *handle, - unsigned int acpm_chan_id, unsigned int clk_id, - unsigned long rate); - unsigned long (*get_rate)(const struct acpm_handle *handle, + int (*set_rate)(struct acpm_handle *handle, unsigned int acpm_chan_id, + unsigned int clk_id, unsigned long rate); + unsigned long (*get_rate)(struct acpm_handle *handle, unsigned int acpm_chan_id, unsigned int clk_id); }; struct acpm_pmic_ops { - int (*read_reg)(const struct acpm_handle *handle, - unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, - u8 *buf); - int (*bulk_read)(const struct acpm_handle *handle, - unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, - u8 count, u8 *buf); - int (*write_reg)(const struct acpm_handle *handle, - unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, - u8 value); - int (*bulk_write)(const struct acpm_handle *handle, - unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, - u8 count, const u8 *buf); - int (*update_reg)(const struct acpm_handle *handle, - unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, - u8 value, u8 mask); + int (*read_reg)(struct acpm_handle *handle, unsigned int acpm_chan_id, + u8 type, u8 reg, u8 chan, u8 *buf); + int (*bulk_read)(struct acpm_handle *handle, unsigned int acpm_chan_id, + u8 type, u8 reg, u8 chan, u8 count, u8 *buf); + int (*write_reg)(struct acpm_handle *handle, unsigned int acpm_chan_id, + u8 type, u8 reg, u8 chan, u8 value); + int (*bulk_write)(struct acpm_handle *handle, unsigned int acpm_chan_id, + u8 type, u8 reg, u8 chan, u8 count, const u8 *buf); + int (*update_reg)(struct acpm_handle *handle, unsigned int acpm_chan_id, + u8 type, u8 reg, u8 chan, u8 value, u8 mask); }; struct acpm_ops { @@ -56,12 +50,12 @@ struct acpm_handle { struct device; #if IS_ENABLED(CONFIG_EXYNOS_ACPM_PROTOCOL) -const struct acpm_handle *devm_acpm_get_by_node(struct device *dev, - struct device_node *np); +struct acpm_handle *devm_acpm_get_by_node(struct device *dev, + struct device_node *np); #else -static inline const struct acpm_handle *devm_acpm_get_by_node(struct device *dev, - struct device_node *np) +static inline struct acpm_handle *devm_acpm_get_by_node(struct device *dev, + struct device_node *np) { return NULL; } From af08f9628bb6a2eb7bf42463eee1a41de848abb4 Mon Sep 17 00:00:00 2001 From: Stefano Radaelli Date: Thu, 5 Feb 2026 11:01:23 +0100 Subject: [PATCH 020/193] dt-bindings: arm: fsl: add Variscite DART-MX91 Boards Add DT compatible strings for Variscite DART-MX91 SoM and Variscite development carrier Board. Acked-by: Conor Dooley Signed-off-by: Stefano Radaelli Reviewed-by: Daniel Baluta Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 910c20bf07a4..285d5c2dd0f7 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1552,6 +1552,12 @@ properties: - const: phytec,imx93-phycore-som # phyCORE-i.MX93 SoM - const: fsl,imx93 + - description: Variscite DART-MX91 based boards + items: + - const: variscite,var-dart-mx91-sonata # Variscite DART-MX91 on Sonata Development Board + - const: variscite,var-dart-mx91 # Variscite DART-MX91 SOM + - const: fsl,imx91 + - description: Variscite VAR-SOM-MX93 based boards items: - const: variscite,var-som-mx93-symphony From 48d8ef9209f488f4661d4daa0700d149b8cad54d Mon Sep 17 00:00:00 2001 From: Yanan Yang Date: Tue, 10 Feb 2026 19:47:54 +0900 Subject: [PATCH 021/193] dt-bindings: arm: fsl: Add FRDM-IMX91S board Add DT compatible string for NXP FRDM-IMX91S board The FRDM-IMX91S is a low-cost, compact development board based on the i.MX91 applications processor. It is a cost-optimized variant of the FRDM-IMX91 board, with notable hardware differences requiring a separate DTS: - 512MB LPDDR4 (FRDM-IMX91 uses 1GB) - 256MB FlexSPI-NAND (FRDM-IMX91 uses 8GB eMMC) - Single GbE port (FRDM-IMX91 has dual GbE) - PMIC PF9453 (FRDM-IMX91 uses PCA9451A) Acked-by: Krzysztof Kozlowski Reviewed-by: Daniel Baluta Signed-off-by: Yanan Yang Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 285d5c2dd0f7..b76a2b8ac527 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1432,6 +1432,7 @@ properties: - enum: - fsl,imx91-11x11-evk # i.MX91 11x11 EVK Board - fsl,imx91-11x11-frdm # FRDM i.MX91 Development Board + - fsl,imx91-11x11-frdm-s # FRDM i.MX91S Development Board - const: fsl,imx91 - description: i.MX93 based Boards From ebe69512733ad5e50c110df903722b0f5b54cb69 Mon Sep 17 00:00:00 2001 From: Maud Spierings Date: Mon, 16 Feb 2026 14:07:08 +0100 Subject: [PATCH 022/193] dt-bindings: arm: fsl: Add GOcontroll Moduline IV/Mini Document the compatible strings for the Moduline IV and Mini. Also add a compatible for the Ka-Ro Electronics TX8M-1610 SoM that they are based on. Acked-by: Conor Dooley Signed-off-by: Maud Spierings Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index b76a2b8ac527..92abff6f534e 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -996,6 +996,14 @@ properties: - const: engicam,icore-mx8mm # i.MX8MM Engicam i.Core MX8M Mini SoM - const: fsl,imx8mm + - description: Ka-Ro Electronics TX8M-1610 based boards + items: + - enum: + - gocontroll,moduline-iv-306-d + - gocontroll,moduline-mini-111 + - const: karo,tx8m-1610 + - const: fsl,imx8mm + - description: Kontron BL i.MX8MM (N801X S) Board items: - const: kontron,imx8mm-bl From 7a58baed883a08d5cffa906d325be70942c13f03 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Mon, 17 Nov 2025 14:21:20 +0000 Subject: [PATCH 023/193] dt-bindings: soc: microchip: add compatible for the mss-top-sysreg on pic64gx pic64gx has an identical sysreg syscon to mpfs, add it using a fallback. Acked-by: Rob Herring (Arm) Signed-off-by: Conor Dooley --- .../microchip/microchip,mpfs-mss-top-sysreg.yaml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml b/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml index 44e4a50c3155..2c1efcdf59b7 100644 --- a/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml +++ b/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml @@ -15,10 +15,16 @@ description: properties: compatible: - items: - - const: microchip,mpfs-mss-top-sysreg - - const: syscon - - const: simple-mfd + oneOf: + - items: + - const: microchip,mpfs-mss-top-sysreg + - const: syscon + - const: simple-mfd + - items: + - const: microchip,pic64gx-mss-top-sysreg + - const: microchip,mpfs-mss-top-sysreg + - const: syscon + - const: simple-mfd reg: maxItems: 1 From ecc09da7ba34b249022897b2c0cafcbd8e2280ac Mon Sep 17 00:00:00 2001 From: Pierre-Henry Moussay Date: Mon, 17 Nov 2025 14:21:21 +0000 Subject: [PATCH 024/193] dt-bindings: soc: microchip: mpfs-sys-controller: Add pic64gx compatibility pic64gx is not compatible with mpfs because due to the lack of FPGA functionality some features are disabled. Notably, anything to do with FPGA fabric contents is not supported. Signed-off-by: Pierre-Henry Moussay Acked-by: Rob Herring (Arm) Signed-off-by: Conor Dooley --- .../bindings/soc/microchip/microchip,mpfs-sys-controller.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-sys-controller.yaml b/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-sys-controller.yaml index a3fa04f3a1bd..6cebc19db4f5 100644 --- a/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-sys-controller.yaml +++ b/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-sys-controller.yaml @@ -24,7 +24,9 @@ properties: maxItems: 1 compatible: - const: microchip,mpfs-sys-controller + enum: + - microchip,mpfs-sys-controller + - microchip,pic64gx-sys-controller microchip,bitstream-flash: $ref: /schemas/types.yaml#/definitions/phandle From 63b5305ad84d72ff60a7cfcdd70fd97dd45e0b7a Mon Sep 17 00:00:00 2001 From: Pierre-Henry Moussay Date: Mon, 17 Nov 2025 14:21:22 +0000 Subject: [PATCH 025/193] soc: microchip: mpfs-sys-controller: add support for pic64gx pic64gx is not compatible with mpfs because due to the lack of FPGA functionality some features are disabled. Notably, anything to do with FPGA fabric contents is not supported. Signed-off-by: Pierre-Henry Moussay Signed-off-by: Conor Dooley --- drivers/soc/microchip/mpfs-sys-controller.c | 74 +++++++++++++++------ 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/drivers/soc/microchip/mpfs-sys-controller.c b/drivers/soc/microchip/mpfs-sys-controller.c index 8e7ae3cb92ff..0be7b109df05 100644 --- a/drivers/soc/microchip/mpfs-sys-controller.c +++ b/drivers/soc/microchip/mpfs-sys-controller.c @@ -36,6 +36,11 @@ struct mpfs_sys_controller { struct kref consumers; }; +struct mpfs_syscon_config { + unsigned int nb_subdevs; + struct platform_device *subdevs; +}; + int mpfs_blocking_transaction(struct mpfs_sys_controller *sys_controller, struct mpfs_mss_msg *msg) { unsigned long timeout = msecs_to_jiffies(MPFS_SYS_CTRL_TIMEOUT_MS); @@ -110,25 +115,11 @@ struct mtd_info *mpfs_sys_controller_get_flash(struct mpfs_sys_controller *mpfs_ } EXPORT_SYMBOL(mpfs_sys_controller_get_flash); -static struct platform_device subdevs[] = { - { - .name = "mpfs-rng", - .id = -1, - }, - { - .name = "mpfs-generic-service", - .id = -1, - }, - { - .name = "mpfs-auto-update", - .id = -1, - }, -}; - static int mpfs_sys_controller_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mpfs_sys_controller *sys_controller; + struct mpfs_syscon_config *of_data; struct device_node *np; int i, ret; @@ -164,11 +155,17 @@ no_flash: platform_set_drvdata(pdev, sys_controller); + of_data = (struct mpfs_syscon_config *) device_get_match_data(dev); + if (!of_data) { + dev_err(dev, "Error getting match data\n"); + return -EINVAL; + } - for (i = 0; i < ARRAY_SIZE(subdevs); i++) { - subdevs[i].dev.parent = dev; - if (platform_device_register(&subdevs[i])) - dev_warn(dev, "Error registering sub device %s\n", subdevs[i].name); + for (i = 0; i < of_data->nb_subdevs; i++) { + of_data->subdevs[i].dev.parent = dev; + if (platform_device_register(&of_data->subdevs[i])) + dev_warn(dev, "Error registering sub device %s\n", + of_data->subdevs[i].name); } dev_info(&pdev->dev, "Registered MPFS system controller\n"); @@ -183,8 +180,45 @@ static void mpfs_sys_controller_remove(struct platform_device *pdev) mpfs_sys_controller_put(sys_controller); } +static struct platform_device mpfs_subdevs[] = { + { + .name = "mpfs-rng", + .id = -1, + }, + { + .name = "mpfs-generic-service", + .id = -1, + }, + { + .name = "mpfs-auto-update", + .id = -1, + }, +}; + +static struct platform_device pic64gx_subdevs[] = { + { + .name = "mpfs-rng", + .id = -1, + }, + { + .name = "mpfs-generic-service", + .id = -1, + }, +}; + +static const struct mpfs_syscon_config mpfs_config = { + .nb_subdevs = ARRAY_SIZE(mpfs_subdevs), + .subdevs = mpfs_subdevs, +}; + +static const struct mpfs_syscon_config pic64gx_config = { + .nb_subdevs = ARRAY_SIZE(pic64gx_subdevs), + .subdevs = pic64gx_subdevs, +}; + static const struct of_device_id mpfs_sys_controller_of_match[] = { - {.compatible = "microchip,mpfs-sys-controller", }, + {.compatible = "microchip,mpfs-sys-controller", .data = &mpfs_config}, + {.compatible = "microchip,pic64gx-sys-controller", .data = &pic64gx_config}, {}, }; MODULE_DEVICE_TABLE(of, mpfs_sys_controller_of_match); From 8c6e843f1c26a0b12720cab02f785c46450b6adc Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Mon, 26 Jan 2026 11:11:24 +0100 Subject: [PATCH 026/193] optee: simplify OP-TEE context match Simplify the TEE implementor ID match by returning the boolean expression directly instead of going through an if/else. Signed-off-by: Rouven Czerwinski Reviewed-by: Sumit Garg Signed-off-by: Jens Wiklander --- drivers/tee/optee/device.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/tee/optee/device.c b/drivers/tee/optee/device.c index bae954e79fdc..f751d743a120 100644 --- a/drivers/tee/optee/device.c +++ b/drivers/tee/optee/device.c @@ -13,10 +13,7 @@ static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data) { - if (ver->impl_id == TEE_IMPL_ID_OPTEE) - return 1; - else - return 0; + return (ver->impl_id == TEE_IMPL_ID_OPTEE); } static int get_devices(struct tee_context *ctx, u32 session, From 0924a6fba19c8f4bbbe2e228a4fb5ae4bdb6d8ab Mon Sep 17 00:00:00 2001 From: Yijie Yang Date: Mon, 2 Feb 2026 15:35:46 +0800 Subject: [PATCH 027/193] firmware: qcom: scm: Allow QSEECOM on PURWA-IOT-EVK Add the Purwa-IoT-EVK board to the list to enable access to EFI variables. Guarantee that subsystems relying on SCM services can access secure-world features. This change improves reliability and prevents missing functionality or boot-time issues by making service availability explicit. Reviewed-by: Dmitry Baryshkov Signed-off-by: Yijie Yang Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20260202073555.1345260-2-yijie.yang@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 2fe1632f06e9..8c1bee400dfa 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 = "microsoft,romulus13", }, { .compatible = "microsoft,romulus15", }, { .compatible = "qcom,hamoa-iot-evk" }, + { .compatible = "qcom,purwa-iot-evk" }, { .compatible = "qcom,sc8180x-primus" }, { .compatible = "qcom,x1e001de-devkit" }, { .compatible = "qcom,x1e80100-crd" }, From c3d1892569afad7cdd5fbe94b4698e3b87fbde9f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 20 Jan 2026 17:47:07 +0100 Subject: [PATCH 028/193] dt-bindings: arm: qcom,ids: Add SoC ID for CQ7790 Document the IDs used by Eliza SoC IoT variant: CQ7790S (without modem) and CQ7790M, present for example on MTP7790 IoT and evalkit boards. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260120164706.501119-3-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- include/dt-bindings/arm/qcom,ids.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index 8776844e0eeb..febb69b0438f 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -294,6 +294,8 @@ #define QCOM_ID_QCS8275 675 #define QCOM_ID_QCS9075 676 #define QCOM_ID_QCS615 680 +#define QCOM_ID_CQ7790M 731 +#define QCOM_ID_CQ7790S 732 /* * The board type and revision information, used by Qualcomm bootloaders and From 2ad034b05154bb61d1296896ce11129e97e838f0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 20 Jan 2026 17:47:08 +0100 Subject: [PATCH 029/193] soc: qcom: socinfo: Add SoC ID for CQ7790 Recognize the CQ7790S and CQ7790M SoCs (Eliza SoC IoT variants). Signed-off-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260120164706.501119-4-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 003a2304d535..41867601d250 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -522,6 +522,8 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QCS8275) }, { qcom_board_id(QCS9075) }, { qcom_board_id(QCS615) }, + { qcom_board_id(CQ7790M) }, + { qcom_board_id(CQ7790S) }, }; static const char *socinfo_machine(struct device *dev, unsigned int id) From 34a49e8508b5d00816d25fe3758b474471e7e051 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Tue, 20 Jan 2026 20:30:13 -0300 Subject: [PATCH 030/193] firmware: qcom: scm: Allow QSEECOM on ECS LIVA QC710 Allow this machine to access efivars through qseecom/uefisecapp. Reviewed-by: Dmitry Baryshkov Signed-off-by: Val Packett Link: https://lore.kernel.org/r/20260120234029.419825-11-val@packett.cool 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 8c1bee400dfa..5c4375a7fa1f 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2296,6 +2296,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "dell,inspiron-14-plus-7441" }, { .compatible = "dell,latitude-7455" }, { .compatible = "dell,xps13-9345" }, + { .compatible = "ecs,liva-qc710" }, { .compatible = "hp,elitebook-ultra-g1q" }, { .compatible = "hp,omnibook-x14" }, { .compatible = "huawei,gaokun3" }, From 8a39b1d4b358f8ccae29166e239f4dd2594b2e7c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 26 Feb 2026 21:35:24 +0100 Subject: [PATCH 031/193] memory: renesas-rpc-if: Simplify printing PTR_ERR with dev_err_probe Use dev_err_probe() to simplify the code and fix Coccinelle warning: renesas-rpc-if.c:1010:3-10: WARNING: Consider using %pe to print PTR_ERR() Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260226-memory-simplify-v1-1-ccb94f378628@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/renesas-rpc-if.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index 58ccc1c02e90..0fb568456164 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -1005,11 +1005,9 @@ static int rpcif_probe(struct platform_device *pdev) return PTR_ERR(rpc->base); rpc->info = of_device_get_match_data(dev); rpc->regmap = devm_regmap_init(dev, NULL, rpc, rpc->info->regmap_config); - if (IS_ERR(rpc->regmap)) { - dev_err(dev, "failed to init regmap for rpcif, error %ld\n", - PTR_ERR(rpc->regmap)); - return PTR_ERR(rpc->regmap); - } + if (IS_ERR(rpc->regmap)) + return dev_err_probe(dev, PTR_ERR(rpc->regmap), + "failed to init regmap for rpcif\n"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap"); rpc->dirmap = devm_ioremap_resource(dev, res); From 2ac5ba4c50be535497dc01089e4113185e4ccad1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 26 Feb 2026 21:35:25 +0100 Subject: [PATCH 032/193] memory: tegra-mc: Drop tegra_mc_setup_latency_allowance() return value tegra_mc_setup_latency_allowance() only succeeds, thus its return value can be dropped making code a bit simpler. Signed-off-by: Krzysztof Kozlowski Acked-by: Thierry Reding Link: https://patch.msgid.link/20260226-memory-simplify-v1-2-ccb94f378628@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 6edb210287dc..c33f514fc804 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -386,7 +386,7 @@ EXPORT_SYMBOL_GPL(tegra_mc_get_emem_device_count); defined(CONFIG_ARCH_TEGRA_124_SOC) || \ defined(CONFIG_ARCH_TEGRA_132_SOC) || \ defined(CONFIG_ARCH_TEGRA_210_SOC) -static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc) +static void tegra_mc_setup_latency_allowance(struct tegra_mc *mc) { unsigned long long tick; unsigned int i; @@ -414,8 +414,6 @@ static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc) /* latch new values */ mc_writel(mc, MC_TIMING_UPDATE, MC_TIMING_CONTROL); - - return 0; } static int load_one_timing(struct tegra_mc *mc, @@ -517,11 +515,7 @@ int tegra30_mc_probe(struct tegra_mc *mc) /* ensure that debug features are disabled */ mc_writel(mc, 0x00000000, MC_TIMING_CONTROL_DBG); - err = tegra_mc_setup_latency_allowance(mc); - if (err < 0) { - dev_err(mc->dev, "failed to setup latency allowance: %d\n", err); - return err; - } + tegra_mc_setup_latency_allowance(mc); err = tegra_mc_setup_timings(mc); if (err < 0) { From f7bd985ad907ed85999f4bac4870abe35dcd2745 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 26 Feb 2026 21:35:26 +0100 Subject: [PATCH 033/193] memory: tegra-mc: Simplify printing PTR_ERR with dev_err_probe Use dev_err_probe() to simplify the code and fix Coccinelle warning: tegra/mc.c:513:52-59: WARNING: Consider using %pe to print PTR_ERR() Signed-off-by: Krzysztof Kozlowski Acked-by: Thierry Reding Link: https://patch.msgid.link/20260226-memory-simplify-v1-3-ccb94f378628@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index c33f514fc804..1dc516a5be14 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -507,10 +507,9 @@ int tegra30_mc_probe(struct tegra_mc *mc) int err; mc->clk = devm_clk_get_optional(mc->dev, "mc"); - if (IS_ERR(mc->clk)) { - dev_err(mc->dev, "failed to get MC clock: %ld\n", PTR_ERR(mc->clk)); - return PTR_ERR(mc->clk); - } + if (IS_ERR(mc->clk)) + return dev_err_probe(mc->dev, PTR_ERR(mc->clk), + "failed to get MC clock\n"); /* ensure that debug features are disabled */ mc_writel(mc, 0x00000000, MC_TIMING_CONTROL_DBG); @@ -518,10 +517,8 @@ int tegra30_mc_probe(struct tegra_mc *mc) tegra_mc_setup_latency_allowance(mc); err = tegra_mc_setup_timings(mc); - if (err < 0) { - dev_err(mc->dev, "failed to setup timings: %d\n", err); - return err; - } + if (err < 0) + return dev_err_probe(mc->dev, err, "failed to setup timings\n"); return 0; } From 2413283fac5b2975f5ead6a1dcac7d5c6f7366d8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 26 Feb 2026 21:35:27 +0100 Subject: [PATCH 034/193] memory: tegra-mc: Use %pe format Make code printing pointer error value a bit simpler and fix coccinelle suggestion: tegra/mc.c:975:4-11: WARNING: Consider using %pe to print PTR_ERR() Signed-off-by: Krzysztof Kozlowski Acked-by: Thierry Reding Link: https://patch.msgid.link/20260226-memory-simplify-v1-4-ccb94f378628@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 1dc516a5be14..67a0b0c07712 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -962,8 +962,7 @@ static int tegra_mc_probe(struct platform_device *pdev) if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU) && mc->soc->smmu) { mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc); if (IS_ERR(mc->smmu)) { - dev_err(&pdev->dev, "failed to probe SMMU: %ld\n", - PTR_ERR(mc->smmu)); + dev_err(&pdev->dev, "failed to probe SMMU: %pe\n", mc->smmu); mc->smmu = NULL; } } From 59ad2fb0be75d984e78c9e9ceb6c371f656ac74d Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Wed, 13 Aug 2025 16:41:33 -0500 Subject: [PATCH 035/193] reset: ath79: Use devm_register_restart_handler() Function register_restart_handler() is deprecated. Using this new API removes our need to keep and manage a struct notifier_block and to later unregister the handler. Signed-off-by: Andrew Davis Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/reset-ath79.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/reset/reset-ath79.c b/drivers/reset/reset-ath79.c index b5d620132052..4c4e69eb32bb 100644 --- a/drivers/reset/reset-ath79.c +++ b/drivers/reset/reset-ath79.c @@ -15,7 +15,6 @@ struct ath79_reset { struct reset_controller_dev rcdev; - struct notifier_block restart_nb; void __iomem *base; spinlock_t lock; }; @@ -72,11 +71,9 @@ static const struct reset_control_ops ath79_reset_ops = { .status = ath79_reset_status, }; -static int ath79_reset_restart_handler(struct notifier_block *nb, - unsigned long action, void *data) +static int ath79_reset_restart_handler(struct sys_off_data *data) { - struct ath79_reset *ath79_reset = - container_of(nb, struct ath79_reset, restart_nb); + struct ath79_reset *ath79_reset = data->cb_data; ath79_reset_assert(&ath79_reset->rcdev, FULL_CHIP_RESET); @@ -108,10 +105,7 @@ static int ath79_reset_probe(struct platform_device *pdev) if (err) return err; - ath79_reset->restart_nb.notifier_call = ath79_reset_restart_handler; - ath79_reset->restart_nb.priority = 128; - - err = register_restart_handler(&ath79_reset->restart_nb); + err = devm_register_restart_handler(&pdev->dev, ath79_reset_restart_handler, ath79_reset); if (err) dev_warn(&pdev->dev, "Failed to register restart handler\n"); From 8bfef0c2438978d4e246f239b3e5dcd0ab9df07d Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Wed, 13 Aug 2025 16:41:34 -0500 Subject: [PATCH 036/193] reset: intel: Use devm_register_restart_handler() Function register_restart_handler() is deprecated. Using this new API removes our need to keep and manage a struct notifier_block and to later unregister the handler. Signed-off-by: Andrew Davis Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/reset-intel-gw.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/reset/reset-intel-gw.c b/drivers/reset/reset-intel-gw.c index a5ce3350cb5e..0db64cc8a282 100644 --- a/drivers/reset/reset-intel-gw.c +++ b/drivers/reset/reset-intel-gw.c @@ -28,7 +28,6 @@ struct intel_reset_soc { struct intel_reset_data { struct reset_controller_dev rcdev; - struct notifier_block restart_nb; const struct intel_reset_soc *soc_data; struct regmap *regmap; struct device *dev; @@ -153,12 +152,10 @@ static int intel_reset_xlate(struct reset_controller_dev *rcdev, return id; } -static int intel_reset_restart_handler(struct notifier_block *nb, - unsigned long action, void *data) +static int intel_reset_restart_handler(struct sys_off_data *data) { - struct intel_reset_data *reset_data; + struct intel_reset_data *reset_data = data->cb_data; - reset_data = container_of(nb, struct intel_reset_data, restart_nb); intel_assert_device(&reset_data->rcdev, reset_data->reboot_id); return NOTIFY_DONE; @@ -215,9 +212,7 @@ static int intel_reset_probe(struct platform_device *pdev) if (data->soc_data->legacy) data->reboot_id |= FIELD_PREP(STAT_BIT_OFFSET_MASK, rb_id[2]); - data->restart_nb.notifier_call = intel_reset_restart_handler; - data->restart_nb.priority = 128; - register_restart_handler(&data->restart_nb); + devm_register_restart_handler(&pdev->dev, intel_reset_restart_handler, data); return 0; } From 09f166128aeae20706611d009e3c3d39e285e368 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Wed, 13 Aug 2025 16:41:35 -0500 Subject: [PATCH 037/193] reset: lpc18xx: Use devm_register_sys_off_handler() Function register_restart_handler() is deprecated. Using this new API removes our need to keep and manage a struct notifier_block and to later unregister the handler. Signed-off-by: Andrew Davis Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/reset-lpc18xx.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c index e42b2f24a93d..8ac9f237e1ce 100644 --- a/drivers/reset/reset-lpc18xx.c +++ b/drivers/reset/reset-lpc18xx.c @@ -31,7 +31,6 @@ struct lpc18xx_rgu_data { struct reset_controller_dev rcdev; - struct notifier_block restart_nb; struct clk *clk_delay; struct clk *clk_reg; void __iomem *base; @@ -41,11 +40,9 @@ struct lpc18xx_rgu_data { #define to_rgu_data(p) container_of(p, struct lpc18xx_rgu_data, rcdev) -static int lpc18xx_rgu_restart(struct notifier_block *nb, unsigned long mode, - void *cmd) +static int lpc18xx_rgu_restart(struct sys_off_data *data) { - struct lpc18xx_rgu_data *rc = container_of(nb, struct lpc18xx_rgu_data, - restart_nb); + struct lpc18xx_rgu_data *rc = data->cb_data; writel(BIT(LPC18XX_RGU_CORE_RST), rc->base + LPC18XX_RGU_CTRL0); mdelay(2000); @@ -178,9 +175,8 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev) if (ret) return dev_err_probe(&pdev->dev, ret, "unable to register device\n"); - rc->restart_nb.priority = 192, - rc->restart_nb.notifier_call = lpc18xx_rgu_restart, - ret = register_restart_handler(&rc->restart_nb); + ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART, 192, + lpc18xx_rgu_restart, rc); if (ret) dev_warn(&pdev->dev, "failed to register restart handler\n"); From 42d03696a05de8a79383d9ed29ca286846133c40 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Wed, 13 Aug 2025 16:41:36 -0500 Subject: [PATCH 038/193] reset: ma35d1: Use devm_register_sys_off_handler() Function register_restart_handler() is deprecated. Using this new API removes our need to keep and manage a struct notifier_block and to later unregister the handler. Signed-off-by: Andrew Davis Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/reset-ma35d1.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/reset/reset-ma35d1.c b/drivers/reset/reset-ma35d1.c index 54e53863c98a..4ee901f00132 100644 --- a/drivers/reset/reset-ma35d1.c +++ b/drivers/reset/reset-ma35d1.c @@ -19,7 +19,6 @@ struct ma35d1_reset_data { struct reset_controller_dev rcdev; - struct notifier_block restart_handler; void __iomem *base; /* protect registers against concurrent read-modify-write */ spinlock_t lock; @@ -125,10 +124,9 @@ static const struct { [MA35D1_RESET_SSPCC] = {0x2C, 31} }; -static int ma35d1_restart_handler(struct notifier_block *this, unsigned long mode, void *cmd) +static int ma35d1_restart_handler(struct sys_off_data *sys_off_data) { - struct ma35d1_reset_data *data = - container_of(this, struct ma35d1_reset_data, restart_handler); + struct ma35d1_reset_data *data = sys_off_data->cb_data; u32 id = MA35D1_RESET_CHIP; writel_relaxed(BIT(ma35d1_reset_map[id].bit), @@ -213,11 +211,10 @@ static int ma35d1_reset_probe(struct platform_device *pdev) reset_data->rcdev.nr_resets = MA35D1_RESET_COUNT; reset_data->rcdev.ops = &ma35d1_reset_ops; reset_data->rcdev.of_node = dev->of_node; - reset_data->restart_handler.notifier_call = ma35d1_restart_handler; - reset_data->restart_handler.priority = 192; spin_lock_init(&reset_data->lock); - err = register_restart_handler(&reset_data->restart_handler); + err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, 192, + ma35d1_restart_handler, reset_data); if (err) dev_warn(&pdev->dev, "failed to register restart handler\n"); From 71c021cd8875ad96c01fa9263b8a4868d2635a0d Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Wed, 13 Aug 2025 16:41:37 -0500 Subject: [PATCH 039/193] reset: npcm: Use devm_register_sys_off_handler() Function register_restart_handler() is deprecated. Using this new API removes our need to keep and manage a struct notifier_block and to later unregister the handler. Signed-off-by: Andrew Davis Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/reset-npcm.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/reset/reset-npcm.c b/drivers/reset/reset-npcm.c index 4070a4b6663f..a762d0215e76 100644 --- a/drivers/reset/reset-npcm.c +++ b/drivers/reset/reset-npcm.c @@ -89,7 +89,6 @@ static const struct npcm_reset_info npxm8xx_reset_info[] = { struct npcm_rc_data { struct reset_controller_dev rcdev; - struct notifier_block restart_nb; const struct npcm_reset_info *info; struct regmap *gcr_regmap; u32 sw_reset_number; @@ -100,11 +99,9 @@ struct npcm_rc_data { #define to_rc_data(p) container_of(p, struct npcm_rc_data, rcdev) -static int npcm_rc_restart(struct notifier_block *nb, unsigned long mode, - void *cmd) +static int npcm_rc_restart(struct sys_off_data *data) { - struct npcm_rc_data *rc = container_of(nb, struct npcm_rc_data, - restart_nb); + struct npcm_rc_data *rc = data->cb_data; writel(NPCM_SWRST << rc->sw_reset_number, rc->base + NPCM_SWRSTR); mdelay(1000); @@ -472,9 +469,8 @@ static int npcm_rc_probe(struct platform_device *pdev) if (!of_property_read_u32(pdev->dev.of_node, "nuvoton,sw-reset-number", &rc->sw_reset_number)) { if (rc->sw_reset_number && rc->sw_reset_number < 5) { - rc->restart_nb.priority = 192; - rc->restart_nb.notifier_call = npcm_rc_restart; - ret = register_restart_handler(&rc->restart_nb); + ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART, 192, + npcm_rc_restart, rc); if (ret) { dev_warn(&pdev->dev, "failed to register restart handler\n"); return ret; From 9d93e13bf5c4d7800a6168a145984adda9bf3c0e Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Wed, 13 Aug 2025 16:41:38 -0500 Subject: [PATCH 040/193] reset: sunplus: Use devm_register_sys_off_handler() Function register_restart_handler() is deprecated. Using this new API removes our need to keep and manage a struct notifier_block and to later unregister the handler. Signed-off-by: Andrew Davis Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/reset-sunplus.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/reset/reset-sunplus.c b/drivers/reset/reset-sunplus.c index df58decab64d..58b087433759 100644 --- a/drivers/reset/reset-sunplus.c +++ b/drivers/reset/reset-sunplus.c @@ -100,7 +100,6 @@ static const u32 sp_resets[] = { struct sp_reset { struct reset_controller_dev rcdev; - struct notifier_block notifier; void __iomem *base; }; @@ -154,10 +153,9 @@ static const struct reset_control_ops sp_reset_ops = { .status = sp_reset_status, }; -static int sp_restart(struct notifier_block *nb, unsigned long mode, - void *cmd) +static int sp_restart(struct sys_off_data *data) { - struct sp_reset *reset = container_of(nb, struct sp_reset, notifier); + struct sp_reset *reset = data->cb_data; sp_reset_assert(&reset->rcdev, 0); sp_reset_deassert(&reset->rcdev, 0); @@ -189,10 +187,8 @@ static int sp_reset_probe(struct platform_device *pdev) if (ret) return ret; - reset->notifier.notifier_call = sp_restart; - reset->notifier.priority = 192; - - return register_restart_handler(&reset->notifier); + return devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART, + 192, sp_restart, reset); } static const struct of_device_id sp_reset_dt_ids[] = { From 56c828dff9ff5e787e74d901e8b530a36b8941da Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 3 Feb 2026 10:30:10 +0000 Subject: [PATCH 041/193] dt-bindings: soc: renesas: Document RZ/G3L SoC variants, SMARC SoM and Carrier-II EVK Document Renesas RZ/G3L (R9A08G046) SoC variants and the Renesas RZ/G3L SMARC Carrier-II EVK board which is based on the Renesas RZ/G3L SMARC SoM. The RZ/G3L SMARC Carrier-II EVK consists of an RZ/G3L SoM module and a SMARC Carrier-II carrier board. The SoM module sits on top of the carrier board. Reviewed-by: Fabrizio Castro Signed-off-by: Biju Das Acked-by: Conor Dooley Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260203103031.247435-3-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- .../devicetree/bindings/soc/renesas/renesas.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/renesas/renesas.yaml b/Documentation/devicetree/bindings/soc/renesas/renesas.yaml index f4947ac65460..5c22c51b1533 100644 --- a/Documentation/devicetree/bindings/soc/renesas/renesas.yaml +++ b/Documentation/devicetree/bindings/soc/renesas/renesas.yaml @@ -548,6 +548,19 @@ properties: - const: renesas,r9a08g045s33 # PCIe support - const: renesas,r9a08g045 + - description: RZ/G3L (R9A08G046) + items: + - enum: + - renesas,smarc2-evk # RZ SMARC Carrier-II EVK + - enum: + - renesas,rzg3l-smarcm # RZ/G3L SMARC Module (SoM) + - enum: + - renesas,r9a08g046l26 # Dual Cortex-A55 + Cortex-M33 + GE3D/VCP (14mm LFBGA) + - renesas,r9a08g046l28 # Dual Cortex-A55 + Cortex-M33 + GE3D/VCP (17mm LFBGA) + - renesas,r9a08g046l46 # Quad Cortex-A55 + Cortex-M33 + GE3D/VCP (14mm LFBGA) + - renesas,r9a08g046l48 # Quad Cortex-A55 + Cortex-M33 + GE3D/VCP (17mm LFBGA) + - const: renesas,r9a08g046 + - description: RZ/V2M (R9A09G011) items: - enum: From 3ac4e6b92fc200e047d13aae06224b2a72539b9e Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 3 Feb 2026 10:30:11 +0000 Subject: [PATCH 042/193] dt-bindings: soc: renesas: renesas,rzg2l-sysc: Document RZ/G3L SoC Document RZ/G3L (R9A08G046) SYSC bindings. The SYSC block found on the RZ/G3L SoC is similar to the one found on RZ/G3S. Acked-by: Conor Dooley Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260203103031.247435-4-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- .../devicetree/bindings/soc/renesas/renesas,rzg2l-sysc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/renesas/renesas,rzg2l-sysc.yaml b/Documentation/devicetree/bindings/soc/renesas/renesas,rzg2l-sysc.yaml index 4386b2c3fa4d..94ae72eb8fb6 100644 --- a/Documentation/devicetree/bindings/soc/renesas/renesas,rzg2l-sysc.yaml +++ b/Documentation/devicetree/bindings/soc/renesas/renesas,rzg2l-sysc.yaml @@ -24,6 +24,7 @@ properties: - renesas,r9a07g044-sysc # RZ/G2{L,LC} - renesas,r9a07g054-sysc # RZ/V2L - renesas,r9a08g045-sysc # RZ/G3S + - renesas,r9a08g046-sysc # RZ/G3L reg: maxItems: 1 From b1de9823fdc67a8e9cd0dcf1f6f0e9780d425d4e Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 3 Feb 2026 10:30:12 +0000 Subject: [PATCH 043/193] soc: renesas: rz-sysc: Add SoC identification for RZ/G3L SoC Add SoC identification for the RZ/G3L SoC using the System Controller (SYSC) block. Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260203103031.247435-5-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 12 ++++ drivers/soc/renesas/Makefile | 1 + drivers/soc/renesas/r9a08g046-sysc.c | 91 ++++++++++++++++++++++++++++ drivers/soc/renesas/rz-sysc.c | 3 + drivers/soc/renesas/rz-sysc.h | 1 + 5 files changed, 108 insertions(+) create mode 100644 drivers/soc/renesas/r9a08g046-sysc.c diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 1e50dc7c31cd..26bed0fdceb0 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -390,6 +390,14 @@ config ARCH_R9A08G045 help This enables support for the Renesas RZ/G3S SoC variants. +config ARCH_R9A08G046 + bool "ARM64 Platform support for R9A08G046 (RZ/G3L)" + default y if ARCH_RENESAS + select ARCH_RZG2L + select SYSC_R9A08G046 + help + This enables support for the Renesas RZ/G3L SoC variants. + config ARCH_R9A09G011 bool "ARM64 Platform support for R9A09G011 (RZ/V2M)" default y if ARCH_RENESAS @@ -474,6 +482,10 @@ config SYSC_R9A08G045 bool "Renesas System controller support for R9A08G045 (RZ/G3S)" if COMPILE_TEST select SYSC_RZ +config SYSC_R9A08G046 + bool "Renesas System controller support for R9A08G046 (RZ/G3L)" if COMPILE_TEST + select SYSC_RZ + config SYS_R9A09G047 bool "Renesas System controller support for R9A09G047 (RZ/G3E)" if COMPILE_TEST select SYSC_RZ diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 33d44d964d61..655dbcb08747 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -7,6 +7,7 @@ ifdef CONFIG_SMP obj-$(CONFIG_ARCH_R9A06G032) += r9a06g032-smp.o endif obj-$(CONFIG_SYSC_R9A08G045) += r9a08g045-sysc.o +obj-$(CONFIG_SYSC_R9A08G046) += r9a08g046-sysc.o obj-$(CONFIG_SYS_R9A09G047) += r9a09g047-sys.o obj-$(CONFIG_SYS_R9A09G056) += r9a09g056-sys.o obj-$(CONFIG_SYS_R9A09G057) += r9a09g057-sys.o diff --git a/drivers/soc/renesas/r9a08g046-sysc.c b/drivers/soc/renesas/r9a08g046-sysc.c new file mode 100644 index 000000000000..fd98df196d0a --- /dev/null +++ b/drivers/soc/renesas/r9a08g046-sysc.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/G3L System controller (SYSC) driver + * + * Copyright (C) 2026 Renesas Electronics Corp. + */ + +#include +#include +#include + +#include "rz-sysc.h" + +#define SYS_XSPI_MAP_STAADD_CS0 0x348 +#define SYS_XSPI_MAP_ENDADD_CS0 0x34c +#define SYS_XSPI_MAP_STAADD_CS1 0x350 +#define SYS_XSPI_MAP_ENDADD_CS1 0x354 +#define SYS_GETH0_CFG 0x380 +#define SYS_GETH1_CFG 0x390 +#define SYS_PCIE_CFG 0x3a0 +#define SYS_PCIE_MON 0x3a4 +#define SYS_PCIE_PHY 0x3b4 +#define SYS_I2C0_CFG 0x400 +#define SYS_I2C1_CFG 0x410 +#define SYS_I2C2_CFG 0x420 +#define SYS_I2C3_CFG 0x430 +#define SYS_I3C_CFG 0x440 +#define SYS_PWRRDY_N 0xd70 +#define SYS_IPCONT_SEL_CLONECH 0xe2c + +static bool rzg3l_regmap_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case SYS_XSPI_MAP_STAADD_CS0: + case SYS_XSPI_MAP_ENDADD_CS0: + case SYS_XSPI_MAP_STAADD_CS1: + case SYS_XSPI_MAP_ENDADD_CS1: + case SYS_GETH0_CFG: + case SYS_GETH1_CFG: + case SYS_PCIE_CFG: + case SYS_PCIE_MON: + case SYS_PCIE_PHY: + case SYS_I2C0_CFG: + case SYS_I2C1_CFG: + case SYS_I2C2_CFG: + case SYS_I2C3_CFG: + case SYS_I3C_CFG: + case SYS_PWRRDY_N: + case SYS_IPCONT_SEL_CLONECH: + return true; + default: + return false; + } +} + +static bool rzg3l_regmap_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case SYS_XSPI_MAP_STAADD_CS0: + case SYS_XSPI_MAP_ENDADD_CS0: + case SYS_XSPI_MAP_STAADD_CS1: + case SYS_XSPI_MAP_ENDADD_CS1: + case SYS_PCIE_CFG: + case SYS_PCIE_PHY: + case SYS_I2C0_CFG: + case SYS_I2C1_CFG: + case SYS_I2C2_CFG: + case SYS_I2C3_CFG: + case SYS_I3C_CFG: + case SYS_PWRRDY_N: + case SYS_IPCONT_SEL_CLONECH: + return true; + default: + return false; + } +} + +static const struct rz_sysc_soc_id_init_data rzg3l_sysc_soc_id_init_data __initconst = { + .family = "RZ/G3L", + .id = 0x87d9447, + .devid_offset = 0xa04, + .revision_mask = GENMASK(31, 28), + .specific_id_mask = GENMASK(27, 0), +}; + +const struct rz_sysc_init_data rzg3l_sysc_init_data __initconst = { + .soc_id_init_data = &rzg3l_sysc_soc_id_init_data, + .readable_reg = rzg3l_regmap_readable_reg, + .writeable_reg = rzg3l_regmap_writeable_reg, + .max_register = 0xe2c, +}; diff --git a/drivers/soc/renesas/rz-sysc.c b/drivers/soc/renesas/rz-sysc.c index 7471dc8736e6..161e8c38eea6 100644 --- a/drivers/soc/renesas/rz-sysc.c +++ b/drivers/soc/renesas/rz-sysc.c @@ -88,6 +88,9 @@ static const struct of_device_id rz_sysc_match[] = { #ifdef CONFIG_SYSC_R9A08G045 { .compatible = "renesas,r9a08g045-sysc", .data = &rzg3s_sysc_init_data }, #endif +#ifdef CONFIG_SYSC_R9A08G046 + { .compatible = "renesas,r9a08g046-sysc", .data = &rzg3l_sysc_init_data }, +#endif #ifdef CONFIG_SYS_R9A09G047 { .compatible = "renesas,r9a09g047-sys", .data = &rzg3e_sys_init_data }, #endif diff --git a/drivers/soc/renesas/rz-sysc.h b/drivers/soc/renesas/rz-sysc.h index 88929bf21cb1..921ee0d26c47 100644 --- a/drivers/soc/renesas/rz-sysc.h +++ b/drivers/soc/renesas/rz-sysc.h @@ -46,6 +46,7 @@ struct rz_sysc_init_data { }; extern const struct rz_sysc_init_data rzg3e_sys_init_data; +extern const struct rz_sysc_init_data rzg3l_sysc_init_data; extern const struct rz_sysc_init_data rzg3s_sysc_init_data; extern const struct rz_sysc_init_data rzv2h_sys_init_data; extern const struct rz_sysc_init_data rzv2n_sys_init_data; From 0b7b7d1abec33d568086165916510c0415fcabcf Mon Sep 17 00:00:00 2001 From: Akhila YS Date: Fri, 27 Feb 2026 15:14:31 +0000 Subject: [PATCH 044/193] dt-bindings: arm: microchip,sama7g5-chipid : convert to DT schema Convert Atmel system registers binding to YAML format. Acked-by: Conor Dooley Signed-off-by: Akhila YS Link: https://lore.kernel.org/r/20260227-arm-microchip-v4-1-7e2ae1c5b5d6@gmail.com [claudiu.beznea: alphanumerically sort the enum entries] Signed-off-by: Claudiu Beznea --- .../devicetree/bindings/arm/atmel-sysregs.txt | 5 --- .../arm/microchip,sama7g5-chipid.yaml | 41 +++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/microchip,sama7g5-chipid.yaml diff --git a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt index 5ce54f9befe6..4ee18112586d 100644 --- a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt +++ b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt @@ -1,10 +1,5 @@ Atmel system registers -Chipid required properties: -- compatible: Should be "atmel,sama5d2-chipid" or "microchip,sama7g5-chipid" - "microchip,sama7d65-chipid" -- reg : Should contain registers location and length - PIT Timer required properties: - compatible: Should be "atmel,at91sam9260-pit" - reg: Should contain registers location and length diff --git a/Documentation/devicetree/bindings/arm/microchip,sama7g5-chipid.yaml b/Documentation/devicetree/bindings/arm/microchip,sama7g5-chipid.yaml new file mode 100644 index 000000000000..4d6442ba5ac9 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/microchip,sama7g5-chipid.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/microchip,sama7g5-chipid.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Atmel/Microchip RAMC SDRAM/DDR Controller + +maintainers: + - Nicolas Ferre + - Claudiu Beznea + +description: + This binding describes the Atmel/Microchip Chip ID register block used + for SoC identification and revision information. It requires compatible + strings matching specific SoC families and a reg property defining the + register address and size. + +properties: + compatible: + enum: + - atmel,sama5d2-chipid + - microchip,sama7d65-chipid + - microchip,sama7g5-chipid + + reg: + maxItems: 1 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + chipid@fc069000 { + compatible = "atmel,sama5d2-chipid"; + reg = <0xfc069000 0x8>; + }; +... From 5f3acf8c03d666377fbe68a8562d89b2e737875d Mon Sep 17 00:00:00 2001 From: Akhila YS Date: Fri, 27 Feb 2026 15:14:32 +0000 Subject: [PATCH 045/193] dt-bindings: arm: atmel,at91sam9260-pit: convert to DT schema Convert Atmel Periodic interval timer (PIT) binding to YAML format. Acked-by: Conor Dooley Signed-off-by: Akhila YS Link: https://lore.kernel.org/r/20260227-arm-microchip-v4-2-7e2ae1c5b5d6@gmail.com Signed-off-by: Claudiu Beznea --- .../bindings/arm/atmel,at91sam9260-pit.yaml | 49 +++++++++++++++++++ .../devicetree/bindings/arm/atmel-sysregs.txt | 6 --- 2 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/atmel,at91sam9260-pit.yaml diff --git a/Documentation/devicetree/bindings/arm/atmel,at91sam9260-pit.yaml b/Documentation/devicetree/bindings/arm/atmel,at91sam9260-pit.yaml new file mode 100644 index 000000000000..d1bdc4a4f9e0 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/atmel,at91sam9260-pit.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/atmel,at91sam9260-pit.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Atmel AT91SAM9260 Periodic Interval Timer (PIT) + +maintainers: + - Nicolas Ferre + - Claudiu Beznea + +description: + The Periodic Interval Timer (PIT) is part of the System Controller of + various Microchip 32-bit ARM-based SoCs (formerly Atmel AT91 series). + It is a simple down-counter timer used mainly as the kernel tick source. + The PIT is clocked from the slow clock and shares a single IRQ line with + other System Controller peripherals. + +properties: + compatible: + const: atmel,at91sam9260-pit + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +unevaluatedProperties: false + +examples: + - | + #include + timer@fffffd30 { + compatible = "atmel,at91sam9260-pit"; + reg = <0xfffffd30 0x10>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk32k>; + }; +... diff --git a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt index 4ee18112586d..70059f66f2b4 100644 --- a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt +++ b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt @@ -1,11 +1,5 @@ Atmel system registers -PIT Timer required properties: -- compatible: Should be "atmel,at91sam9260-pit" -- reg: Should contain registers location and length -- interrupts: Should contain interrupt for the PIT which is the IRQ line - shared across all System Controller members. - PIT64B Timer required properties: - compatible: Should be "microchip,sam9x60-pit64b" or "microchip,sam9x7-pit64b", "microchip,sam9x60-pit64b" From 67f386b2c623aa07b73a3f6882472d439c5b3ceb Mon Sep 17 00:00:00 2001 From: Akhila YS Date: Fri, 27 Feb 2026 15:14:33 +0000 Subject: [PATCH 046/193] dt-bindings: arm: microchip,sam9x60-pit64b : convert to DT schema Convert Atmel Periodic interval timer of 64bit (PIT64b) binding to YAML format. Changes during conversion: - Add missing compatible "microchip,sama7g5-pit64b" along with a fallback compatible "microchip,sam9x60-pit64b". Acked-by: Conor Dooley Signed-off-by: Akhila YS Link: https://lore.kernel.org/r/20260227-arm-microchip-v4-3-7e2ae1c5b5d6@gmail.com [claudiu.beznea: alphanumerically sort the enum entries] Signed-off-by: Claudiu Beznea --- .../devicetree/bindings/arm/atmel-sysregs.txt | 8 --- .../arm/microchip,sam9x60-pit64b.yaml | 68 +++++++++++++++++++ 2 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/microchip,sam9x60-pit64b.yaml diff --git a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt index 70059f66f2b4..d0561f7f465c 100644 --- a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt +++ b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt @@ -1,13 +1,5 @@ Atmel system registers -PIT64B Timer required properties: -- compatible: Should be "microchip,sam9x60-pit64b" or - "microchip,sam9x7-pit64b", "microchip,sam9x60-pit64b" - "microchip,sama7d65-pit64b", "microchip,sam9x60-pit64b" -- reg: Should contain registers location and length -- interrupts: Should contain interrupt for PIT64B timer -- clocks: Should contain the available clock sources for PIT64B timer. - System Timer (ST) required properties: - compatible: Should be "atmel,at91rm9200-st", "syscon", "simple-mfd" - reg: Should contain registers location and length diff --git a/Documentation/devicetree/bindings/arm/microchip,sam9x60-pit64b.yaml b/Documentation/devicetree/bindings/arm/microchip,sam9x60-pit64b.yaml new file mode 100644 index 000000000000..802cf2424c42 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/microchip,sam9x60-pit64b.yaml @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/microchip,sam9x60-pit64b.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip PIT64B 64-bit Periodic Interval Timer + +maintainers: + - Nicolas Ferre + - Claudiu Beznea + +description: + The Microchip PIT64B is a 64-bit periodic interval timer used in + several modern Microchip ARM SoCs including SAM9X60, SAM9X7 and + SAMA7D65 families. It provides extended timing range, flexible + clock selection and supports both periodic and one-shot interrupt + generation modes. + +properties: + compatible: + oneOf: + - const: microchip,sam9x60-pit64b + - items: + - enum: + - microchip,sam9x7-pit64b + - microchip,sama7d65-pit64b + - microchip,sama7g5-pit64b + - const: microchip,sam9x60-pit64b + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 2 + + clock-names: + minItems: 1 + maxItems: 2 + items: + enum: + - pclk + - gclk + +required: + - compatible + - reg + - interrupts + - clocks + +unevaluatedProperties: false + +examples: + - | + #include + #include + timer@f0028000 { + compatible = "microchip,sama7g5-pit64b", "microchip,sam9x60-pit64b"; + reg = <0xf0028000 0x100>; + interrupts = <37 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 37>, <&pmc PMC_TYPE_GCK 37>; + clock-names = "pclk", "gclk"; + }; +... From ae18e2543c4a07317a03c7cf042d8a0596cd5bd0 Mon Sep 17 00:00:00 2001 From: Akhila YS Date: Fri, 27 Feb 2026 15:14:34 +0000 Subject: [PATCH 047/193] dt-bindings: arm: atmel,at91rm9200-st: convert to DT schema Convert System Timer binding to YAML format. Changes during conversion: - Add "#address-cells" and "#size-cells" to the properties and required as watchdog is defined as a child node to the timer parent node. - Define watchdog as a pattern property along with unit address in examples. Acked-by: Conor Dooley Signed-off-by: Akhila YS Link: https://lore.kernel.org/r/20260227-arm-microchip-v4-4-7e2ae1c5b5d6@gmail.com Signed-off-by: Claudiu Beznea --- .../bindings/arm/atmel,at91rm9200-st.yaml | 69 +++++++++++++++++++ .../devicetree/bindings/arm/atmel-sysregs.txt | 9 --- 2 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/atmel,at91rm9200-st.yaml diff --git a/Documentation/devicetree/bindings/arm/atmel,at91rm9200-st.yaml b/Documentation/devicetree/bindings/arm/atmel,at91rm9200-st.yaml new file mode 100644 index 000000000000..3f6a934a2a69 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/atmel,at91rm9200-st.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/atmel,at91rm9200-st.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Atmel System Timer + +maintainers: + - Nicolas Ferre + - Claudiu Beznea + +description: + The System Timer (ST) module in AT91RM9200 provides periodic tick and + alarm capabilities. It is exposed as a simple multi-function device + (simple-mfd + syscon) because it shares its register space and interrupt + with other System Controller blocks. + +properties: + compatible: + items: + - const: atmel,at91rm9200-st + - const: syscon + - const: simple-mfd + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + +patternProperties: + "^watchdog@[0-9a-f]+$": + $ref: /schemas/watchdog/atmel,at91rm9200-wdt.yaml# + +required: + - compatible + - reg + - interrupts + - clocks + +unevaluatedProperties: false + +examples: + - | + #include + timer@fffffd00 { + compatible = "atmel,at91rm9200-st", "syscon", "simple-mfd"; + reg = <0xfffffd00 0x100>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&slow_xtal>; + #address-cells = <1>; + #size-cells = <1>; + + watchdog@fffffd40 { + compatible = "atmel,at91rm9200-wdt"; + reg = <0xfffffd40 0x40>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt index d0561f7f465c..14642384bc87 100644 --- a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt +++ b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt @@ -1,14 +1,5 @@ Atmel system registers -System Timer (ST) required properties: -- compatible: Should be "atmel,at91rm9200-st", "syscon", "simple-mfd" -- reg: Should contain registers location and length -- interrupts: Should contain interrupt for the ST which is the IRQ line - shared across all System Controller members. -- clocks: phandle to input clock. -Its subnodes can be: -- watchdog: compatible should be "atmel,at91rm9200-wdt" - RAMC SDRAM/DDR Controller required properties: - compatible: Should be "atmel,at91rm9200-sdramc", "syscon" or "atmel,at91sam9260-sdramc" or From f3ae0049ff8a3d2cbd8c05857705744435629d0c Mon Sep 17 00:00:00 2001 From: Akhila YS Date: Fri, 27 Feb 2026 15:14:35 +0000 Subject: [PATCH 048/193] dt-bindings: arm: atmel,at91rm9200-sdramc: convert to DT schema Convert RAMC SDRAM/DDR controller binding to YAML format. Signed-off-by: Akhila YS Acked-by: Conor Dooley Link: https://lore.kernel.org/r/20260227-arm-microchip-v4-5-7e2ae1c5b5d6@gmail.com Signed-off-by: Claudiu Beznea --- .../bindings/arm/atmel,at91rm9200-sdramc.yaml | 66 +++++++++++++++++++ .../devicetree/bindings/arm/atmel-sysregs.txt | 20 ------ 2 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/atmel,at91rm9200-sdramc.yaml delete mode 100644 Documentation/devicetree/bindings/arm/atmel-sysregs.txt diff --git a/Documentation/devicetree/bindings/arm/atmel,at91rm9200-sdramc.yaml b/Documentation/devicetree/bindings/arm/atmel,at91rm9200-sdramc.yaml new file mode 100644 index 000000000000..ac7e0f454a34 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/atmel,at91rm9200-sdramc.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/atmel,at91rm9200-sdramc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip (Atmel) SDRAM / DDR Controller (RAMC / DDRAMC / UDDRC) + +maintainers: + - Nicolas Ferre + - Claudiu Beznea + +description: + The SDRAM/DDR Controller (often called RAMC or DDRAMC) in various + Atmel/Microchip ARM9 and Cortex-A5/A7 SoCs manages external + SDRAM / DDR memory. It is typically exposed as a syscon node for + register access from other drivers (e.g. for initialization or mode + configuration). No interrupts or clocks are usually required in the + binding. + +properties: + compatible: + oneOf: + - items: + - const: atmel,at91rm9200-sdramc + - const: syscon + - items: + - const: microchip,sama7d65-uddrc + - const: microchip,sama7g5-uddrc + - enum: + - atmel,at91sam9260-sdramc + - atmel,at91sam9g45-ddramc + - atmel,sama5d3-ddramc + - microchip,sam9x60-ddramc + - microchip,sam9x7-ddramc + - microchip,sama7g5-uddrc + + reg: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 2 + + clock-names: + minItems: 1 + items: + - const: ddrck + - const: mpddr + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include + ramc@ffffe400 { + compatible = "atmel,at91sam9g45-ddramc"; + reg = <0xffffe400 0x200>; + clocks = <&pmc PMC_TYPE_SYSTEM 2>; + clock-names = "ddrck"; + }; +... diff --git a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt deleted file mode 100644 index 14642384bc87..000000000000 --- a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt +++ /dev/null @@ -1,20 +0,0 @@ -Atmel system registers - -RAMC SDRAM/DDR Controller required properties: -- compatible: Should be "atmel,at91rm9200-sdramc", "syscon" or - "atmel,at91sam9260-sdramc" or - "atmel,at91sam9g45-ddramc" or - "atmel,sama5d3-ddramc" or - "microchip,sam9x60-ddramc" or - "microchip,sama7g5-uddrc" or - "microchip,sama7d65-uddrc", "microchip,sama7g5-uddrc" or - "microchip,sam9x7-ddramc", "atmel,sama5d3-ddramc". -- reg: Should contain registers location and length - -Examples: - - ramc0: ramc@ffffe800 { - compatible = "atmel,at91sam9g45-ddramc"; - reg = <0xffffe800 0x200>; - }; - From b8a177f18df1b439aac708da2d8bd9fcd68bb1eb Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 26 Feb 2026 16:31:10 +0000 Subject: [PATCH 049/193] memory: tegra: Group error handling related registers Group MC error related registers into a struct as they could have SoC specific values. Tegra264 has different register offsets than the existing devices and so in order to add support for Tegra264 we need to first make this change. Signed-off-by: Ketan Patil Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20260226163115.1152181-2-ketanp@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 47 ++++++++++++++++++++++----------- drivers/memory/tegra/mc.h | 16 +---------- drivers/memory/tegra/tegra114.c | 3 ++- drivers/memory/tegra/tegra124.c | 4 ++- drivers/memory/tegra/tegra186.c | 3 ++- drivers/memory/tegra/tegra194.c | 3 ++- drivers/memory/tegra/tegra20.c | 3 ++- drivers/memory/tegra/tegra210.c | 3 ++- drivers/memory/tegra/tegra234.c | 3 ++- drivers/memory/tegra/tegra30.c | 3 ++- include/soc/tegra/mc.h | 22 ++++++++++++++- 11 files changed, 71 insertions(+), 39 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 67a0b0c07712..63f402aa1976 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2014-2025 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -56,6 +56,23 @@ static const struct of_device_id tegra_mc_of_match[] = { }; MODULE_DEVICE_TABLE(of, tegra_mc_of_match); +const struct tegra_mc_regs tegra20_mc_regs = { + .cfg_channel_enable = 0xdf8, + .err_status = 0x08, + .err_add = 0x0c, + .err_add_hi = 0x11fc, + .err_vpr_status = 0x654, + .err_vpr_add = 0x658, + .err_sec_status = 0x67c, + .err_sec_add = 0x680, + .err_mts_status = 0x9b0, + .err_mts_add = 0x9b4, + .err_gen_co_status = 0xc00, + .err_gen_co_add = 0xc04, + .err_route_status = 0x9c0, + .err_route_add = 0x9c4, +}; + static void tegra_mc_devm_action_put_device(void *data) { struct tegra_mc *mc = data; @@ -591,37 +608,37 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data) switch (intmask) { case MC_INT_DECERR_VPR: - status_reg = MC_ERR_VPR_STATUS; - addr_reg = MC_ERR_VPR_ADR; + status_reg = mc->soc->regs->err_vpr_status; + addr_reg = mc->soc->regs->err_vpr_add; break; case MC_INT_SECERR_SEC: - status_reg = MC_ERR_SEC_STATUS; - addr_reg = MC_ERR_SEC_ADR; + status_reg = mc->soc->regs->err_sec_status; + addr_reg = mc->soc->regs->err_sec_add; break; case MC_INT_DECERR_MTS: - status_reg = MC_ERR_MTS_STATUS; - addr_reg = MC_ERR_MTS_ADR; + status_reg = mc->soc->regs->err_mts_status; + addr_reg = mc->soc->regs->err_mts_add; break; case MC_INT_DECERR_GENERALIZED_CARVEOUT: - status_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS; - addr_reg = MC_ERR_GENERALIZED_CARVEOUT_ADR; + status_reg = mc->soc->regs->err_gen_co_status; + addr_reg = mc->soc->regs->err_gen_co_add; break; case MC_INT_DECERR_ROUTE_SANITY: - status_reg = MC_ERR_ROUTE_SANITY_STATUS; - addr_reg = MC_ERR_ROUTE_SANITY_ADR; + status_reg = mc->soc->regs->err_route_status; + addr_reg = mc->soc->regs->err_route_add; break; default: - status_reg = MC_ERR_STATUS; - addr_reg = MC_ERR_ADR; + status_reg = mc->soc->regs->err_status; + addr_reg = mc->soc->regs->err_add; #ifdef CONFIG_PHYS_ADDR_T_64BIT if (mc->soc->has_addr_hi_reg) - addr_hi_reg = MC_ERR_ADR_HI; + addr_hi_reg = mc->soc->regs->err_add_hi; #endif break; } @@ -874,7 +891,7 @@ static void tegra_mc_num_channel_enabled(struct tegra_mc *mc) unsigned int i; u32 value; - value = mc_ch_readl(mc, 0, MC_EMEM_ADR_CFG_CHANNEL_ENABLE); + value = mc_ch_readl(mc, 0, mc->soc->regs->cfg_channel_enable); if (value <= 0) { mc->num_channels = mc->soc->num_channels; return; diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index 1d97cf4d3a94..bbe3e2690c64 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2014-2025 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved. */ #ifndef MEMORY_TEGRA_MC_H @@ -14,8 +14,6 @@ #define MC_INTSTATUS 0x00 #define MC_INTMASK 0x04 -#define MC_ERR_STATUS 0x08 -#define MC_ERR_ADR 0x0c #define MC_GART_ERROR_REQ 0x30 #define MC_EMEM_ADR_CFG 0x54 #define MC_DECERR_EMEM_OTHERS_STATUS 0x58 @@ -43,19 +41,7 @@ #define MC_EMEM_ARB_OVERRIDE 0xe8 #define MC_TIMING_CONTROL_DBG 0xf8 #define MC_TIMING_CONTROL 0xfc -#define MC_ERR_VPR_STATUS 0x654 -#define MC_ERR_VPR_ADR 0x658 -#define MC_ERR_SEC_STATUS 0x67c -#define MC_ERR_SEC_ADR 0x680 -#define MC_ERR_MTS_STATUS 0x9b0 -#define MC_ERR_MTS_ADR 0x9b4 -#define MC_ERR_ROUTE_SANITY_STATUS 0x9c0 -#define MC_ERR_ROUTE_SANITY_ADR 0x9c4 -#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00 -#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04 -#define MC_EMEM_ADR_CFG_CHANNEL_ENABLE 0xdf8 #define MC_GLOBAL_INTSTATUS 0xf24 -#define MC_ERR_ADR_HI 0x11fc #define MC_INT_DECERR_ROUTE_SANITY BIT(20) #define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17) diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c index 41350570c815..ea7e4c7bb5f8 100644 --- a/drivers/memory/tegra/tegra114.c +++ b/drivers/memory/tegra/tegra114.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -1114,4 +1114,5 @@ const struct tegra_mc_soc tegra114_mc_soc = { .resets = tegra114_mc_resets, .num_resets = ARRAY_SIZE(tegra114_mc_resets), .ops = &tegra30_mc_ops, + .regs = &tegra20_mc_regs, }; diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index 991d4f7bc070..f0cfe14bb475 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -1275,6 +1275,7 @@ const struct tegra_mc_soc tegra124_mc_soc = { .num_resets = ARRAY_SIZE(tegra124_mc_resets), .icc_ops = &tegra124_mc_icc_ops, .ops = &tegra30_mc_ops, + .regs = &tegra20_mc_regs, }; #endif /* CONFIG_ARCH_TEGRA_124_SOC */ @@ -1307,5 +1308,6 @@ const struct tegra_mc_soc tegra132_mc_soc = { .num_resets = ARRAY_SIZE(tegra124_mc_resets), .icc_ops = &tegra124_mc_icc_ops, .ops = &tegra30_mc_ops, + .regs = &tegra20_mc_regs, }; #endif /* CONFIG_ARCH_TEGRA_132_SOC */ diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c index aee11457bf8e..51e2dd628fb4 100644 --- a/drivers/memory/tegra/tegra186.c +++ b/drivers/memory/tegra/tegra186.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2017-2025 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2017-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -914,5 +914,6 @@ const struct tegra_mc_soc tegra186_mc_soc = { .ops = &tegra186_mc_ops, .ch_intmask = 0x0000000f, .global_intstatus_channel_shift = 0, + .regs = &tegra20_mc_regs, }; #endif diff --git a/drivers/memory/tegra/tegra194.c b/drivers/memory/tegra/tegra194.c index 26035ac3a1eb..5b7ff2dd6812 100644 --- a/drivers/memory/tegra/tegra194.c +++ b/drivers/memory/tegra/tegra194.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2017-2021 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2017-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -1358,4 +1358,5 @@ const struct tegra_mc_soc tegra194_mc_soc = { .icc_ops = &tegra_mc_icc_ops, .ch_intmask = 0x00000f00, .global_intstatus_channel_shift = 8, + .regs = &tegra20_mc_regs, }; diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c index 4748113bfe9d..1b2b598ab564 100644 --- a/drivers/memory/tegra/tegra20.c +++ b/drivers/memory/tegra/tegra20.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2012-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -778,4 +778,5 @@ const struct tegra_mc_soc tegra20_mc_soc = { .num_resets = ARRAY_SIZE(tegra20_mc_resets), .icc_ops = &tegra20_mc_icc_ops, .ops = &tegra20_mc_ops, + .regs = &tegra20_mc_regs, }; diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c index 3c2949c16fde..e166b33848e9 100644 --- a/drivers/memory/tegra/tegra210.c +++ b/drivers/memory/tegra/tegra210.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2015 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2015-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -1287,4 +1287,5 @@ const struct tegra_mc_soc tegra210_mc_soc = { .resets = tegra210_mc_resets, .num_resets = ARRAY_SIZE(tegra210_mc_resets), .ops = &tegra30_mc_ops, + .regs = &tegra20_mc_regs, }; diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index 5f57cea48b62..512d054d7592 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2022-2023, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2022-2026, NVIDIA CORPORATION. All rights reserved. */ #include @@ -1152,4 +1152,5 @@ const struct tegra_mc_soc tegra234_mc_soc = { * supported. */ .num_carveouts = 32, + .regs = &tegra20_mc_regs, }; diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c index a6bcde4b92c0..337501a30a73 100644 --- a/drivers/memory/tegra/tegra30.c +++ b/drivers/memory/tegra/tegra30.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -1400,4 +1400,5 @@ const struct tegra_mc_soc tegra30_mc_soc = { .num_resets = ARRAY_SIZE(tegra30_mc_resets), .icc_ops = &tegra30_mc_icc_ops, .ops = &tegra30_mc_ops, + .regs = &tegra20_mc_regs, }; diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index 6ee4c59db620..372f47e824d5 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2014 NVIDIA Corporation + * Copyright (C) 2014-2026 NVIDIA Corporation */ #ifndef __SOC_TEGRA_MC_H__ @@ -168,6 +168,23 @@ struct tegra_mc_ops { int (*probe_device)(struct tegra_mc *mc, struct device *dev); }; +struct tegra_mc_regs { + unsigned int cfg_channel_enable; + unsigned int err_status; + unsigned int err_add; + unsigned int err_add_hi; + unsigned int err_vpr_status; + unsigned int err_vpr_add; + unsigned int err_sec_status; + unsigned int err_sec_add; + unsigned int err_mts_status; + unsigned int err_mts_add; + unsigned int err_gen_co_status; + unsigned int err_gen_co_add; + unsigned int err_route_status; + unsigned int err_route_add; +}; + struct tegra_mc_soc { const struct tegra_mc_client *clients; unsigned int num_clients; @@ -196,6 +213,7 @@ struct tegra_mc_soc { const struct tegra_mc_icc_ops *icc_ops; const struct tegra_mc_ops *ops; + const struct tegra_mc_regs *regs; }; struct tegra_mc { @@ -256,4 +274,6 @@ tegra_mc_get_carveout_info(struct tegra_mc *mc, unsigned int id, } #endif +extern const struct tegra_mc_regs tegra20_mc_regs; + #endif /* __SOC_TEGRA_MC_H__ */ From 95b714bd8c39d65b241aa1c346625b9c942af403 Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 26 Feb 2026 16:31:11 +0000 Subject: [PATCH 050/193] memory: tegra: Group register and fields The current register definitions are not in sorted order. Sort these registers according to their address. Put bit fields and masks of the corresponding registers below the register definitions to clearly identify which fields belongs to which registers. Signed-off-by: Ketan Patil Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20260226163115.1152181-3-ketanp@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.h | 62 +++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index bbe3e2690c64..5f816d703d81 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -13,13 +13,35 @@ #include #define MC_INTSTATUS 0x00 +/* Bit field of MC_INTSTATUS register */ +#define MC_INT_DECERR_EMEM BIT(6) +#define MC_INT_INVALID_GART_PAGE BIT(7) +#define MC_INT_SECURITY_VIOLATION BIT(8) +#define MC_INT_ARBITRATION_EMEM BIT(9) +#define MC_INT_INVALID_SMMU_PAGE BIT(10) +#define MC_INT_INVALID_APB_ASID_UPDATE BIT(11) +#define MC_INT_DECERR_VPR BIT(12) +#define MC_INT_SECERR_SEC BIT(13) +#define MC_INT_DECERR_MTS BIT(16) +#define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17) +#define MC_INT_DECERR_ROUTE_SANITY BIT(20) + #define MC_INTMASK 0x04 #define MC_GART_ERROR_REQ 0x30 #define MC_EMEM_ADR_CFG 0x54 +#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0) + #define MC_DECERR_EMEM_OTHERS_STATUS 0x58 #define MC_SECURITY_VIOLATION_STATUS 0x74 #define MC_EMEM_ARB_CFG 0x90 +#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) ((x) & 0x1ff) +#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff + #define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 +#define MC_EMEM_ARB_OUTSTANDING_REQ_HOLDOFF_OVERRIDE BIT(30) +#define MC_EMEM_ARB_OUTSTANDING_REQ_LIMIT_ENABLE BIT(31) +#define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_MASK 0x1ff + #define MC_EMEM_ARB_TIMING_RCD 0x98 #define MC_EMEM_ARB_TIMING_RP 0x9c #define MC_EMEM_ARB_TIMING_RC 0xa0 @@ -39,45 +61,27 @@ #define MC_EMEM_ARB_MISC1 0xdc #define MC_EMEM_ARB_RING1_THROTTLE 0xe0 #define MC_EMEM_ARB_OVERRIDE 0xe8 +#define MC_EMEM_ARB_OVERRIDE_EACK_MASK 0x3 + #define MC_TIMING_CONTROL_DBG 0xf8 #define MC_TIMING_CONTROL 0xfc +#define MC_TIMING_UPDATE BIT(0) + #define MC_GLOBAL_INTSTATUS 0xf24 -#define MC_INT_DECERR_ROUTE_SANITY BIT(20) -#define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17) -#define MC_INT_DECERR_MTS BIT(16) -#define MC_INT_SECERR_SEC BIT(13) -#define MC_INT_DECERR_VPR BIT(12) -#define MC_INT_INVALID_APB_ASID_UPDATE BIT(11) -#define MC_INT_INVALID_SMMU_PAGE BIT(10) -#define MC_INT_ARBITRATION_EMEM BIT(9) -#define MC_INT_SECURITY_VIOLATION BIT(8) -#define MC_INT_INVALID_GART_PAGE BIT(7) -#define MC_INT_DECERR_EMEM BIT(6) +/* Bit field of MC_ERR_STATUS_0 register */ +#define MC_ERR_STATUS_RW BIT(16) +#define MC_ERR_STATUS_SECURITY BIT(17) +#define MC_ERR_STATUS_NONSECURE BIT(25) +#define MC_ERR_STATUS_WRITABLE BIT(26) +#define MC_ERR_STATUS_READABLE BIT(27) #define MC_ERR_STATUS_TYPE_SHIFT 28 #define MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE (0x6 << 28) #define MC_ERR_STATUS_TYPE_MASK (0x7 << 28) -#define MC_ERR_STATUS_READABLE BIT(27) -#define MC_ERR_STATUS_WRITABLE BIT(26) -#define MC_ERR_STATUS_NONSECURE BIT(25) + #define MC_ERR_STATUS_ADR_HI_SHIFT 20 #define MC_ERR_STATUS_ADR_HI_MASK 0x3 -#define MC_ERR_STATUS_SECURITY BIT(17) -#define MC_ERR_STATUS_RW BIT(16) - -#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0) - -#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) ((x) & 0x1ff) -#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff - -#define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_MASK 0x1ff -#define MC_EMEM_ARB_OUTSTANDING_REQ_HOLDOFF_OVERRIDE BIT(30) -#define MC_EMEM_ARB_OUTSTANDING_REQ_LIMIT_ENABLE BIT(31) - -#define MC_EMEM_ARB_OVERRIDE_EACK_MASK 0x3 - -#define MC_TIMING_UPDATE BIT(0) #define MC_BROADCAST_CHANNEL ~0 From 4d865a2374037d2d0842f88822fd753f0918b370 Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 26 Feb 2026 16:31:12 +0000 Subject: [PATCH 051/193] memory: tegra: Add support for multiple IRQs Add support to handle multiple MC interrupts lines, as supported by Tegra264. Turn the single IRQ handler callback into a counted array to allow specifying a separate handler for each interrupt. Move IRQ handlers into tegra_mc_soc struct, so as to specify SoC specific values. Signed-off-by: Ketan Patil Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20260226163115.1152181-4-ketanp@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 34 ++++++++++++++++++++------------- drivers/memory/tegra/mc.h | 1 + drivers/memory/tegra/tegra114.c | 2 ++ drivers/memory/tegra/tegra124.c | 4 ++++ drivers/memory/tegra/tegra186.c | 3 ++- drivers/memory/tegra/tegra194.c | 2 ++ drivers/memory/tegra/tegra20.c | 7 ++++++- drivers/memory/tegra/tegra210.c | 2 ++ drivers/memory/tegra/tegra234.c | 2 ++ drivers/memory/tegra/tegra30.c | 2 ++ include/soc/tegra/mc.h | 8 +++++--- 11 files changed, 49 insertions(+), 18 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 63f402aa1976..8114574374d5 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -398,6 +398,10 @@ unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc) } EXPORT_SYMBOL_GPL(tegra_mc_get_emem_device_count); +const irq_handler_t tegra30_mc_irq_handlers[] = { + tegra30_mc_handle_irq +}; + #if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \ defined(CONFIG_ARCH_TEGRA_114_SOC) || \ defined(CONFIG_ARCH_TEGRA_124_SOC) || \ @@ -542,7 +546,6 @@ int tegra30_mc_probe(struct tegra_mc *mc) const struct tegra_mc_ops tegra30_mc_ops = { .probe = tegra30_mc_probe, - .handle_irq = tegra30_mc_handle_irq, }; #endif @@ -943,26 +946,31 @@ static int tegra_mc_probe(struct platform_device *pdev) tegra_mc_num_channel_enabled(mc); - if (mc->soc->ops && mc->soc->ops->handle_irq) { - mc->irq = platform_get_irq(pdev, 0); - if (mc->irq < 0) - return mc->irq; + if (mc->soc->handle_irq) { + unsigned int i; WARN(!mc->soc->client_id_mask, "missing client ID mask for this SoC\n"); + for (i = 0; i < mc->soc->num_interrupts; i++) { + int irq; + + irq = platform_get_irq(pdev, i); + if (irq < 0) + return irq; + + err = devm_request_irq(&pdev->dev, irq, mc->soc->handle_irq[i], 0, + dev_name(&pdev->dev), mc); + if (err < 0) { + dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", irq, err); + return err; + } + } + if (mc->soc->num_channels) mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmask, MC_INTMASK); else mc_writel(mc, mc->soc->intmask, MC_INTMASK); - - err = devm_request_irq(&pdev->dev, mc->irq, mc->soc->ops->handle_irq, 0, - dev_name(&pdev->dev), mc); - if (err < 0) { - dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq, - err); - return err; - } } if (mc->soc->reset_ops) { diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index 5f816d703d81..34ce03ebc51c 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -193,6 +193,7 @@ extern const struct tegra_mc_ops tegra186_mc_ops; #endif irqreturn_t tegra30_mc_handle_irq(int irq, void *data); +extern const irq_handler_t tegra30_mc_irq_handlers[1]; extern const char * const tegra_mc_status_names[32]; extern const char * const tegra_mc_error_names[8]; diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c index ea7e4c7bb5f8..fffb28eea57f 100644 --- a/drivers/memory/tegra/tegra114.c +++ b/drivers/memory/tegra/tegra114.c @@ -1115,4 +1115,6 @@ const struct tegra_mc_soc tegra114_mc_soc = { .num_resets = ARRAY_SIZE(tegra114_mc_resets), .ops = &tegra30_mc_ops, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index f0cfe14bb475..2cf733198782 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -1276,6 +1276,8 @@ const struct tegra_mc_soc tegra124_mc_soc = { .icc_ops = &tegra124_mc_icc_ops, .ops = &tegra30_mc_ops, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; #endif /* CONFIG_ARCH_TEGRA_124_SOC */ @@ -1309,5 +1311,7 @@ const struct tegra_mc_soc tegra132_mc_soc = { .icc_ops = &tegra124_mc_icc_ops, .ops = &tegra30_mc_ops, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; #endif /* CONFIG_ARCH_TEGRA_132_SOC */ diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c index 51e2dd628fb4..eb1eaaffc79a 100644 --- a/drivers/memory/tegra/tegra186.c +++ b/drivers/memory/tegra/tegra186.c @@ -174,7 +174,6 @@ const struct tegra_mc_ops tegra186_mc_ops = { .remove = tegra186_mc_remove, .resume = tegra186_mc_resume, .probe_device = tegra186_mc_probe_device, - .handle_irq = tegra30_mc_handle_irq, }; #if defined(CONFIG_ARCH_TEGRA_186_SOC) @@ -915,5 +914,7 @@ const struct tegra_mc_soc tegra186_mc_soc = { .ch_intmask = 0x0000000f, .global_intstatus_channel_shift = 0, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; #endif diff --git a/drivers/memory/tegra/tegra194.c b/drivers/memory/tegra/tegra194.c index 5b7ff2dd6812..cb0e7886857d 100644 --- a/drivers/memory/tegra/tegra194.c +++ b/drivers/memory/tegra/tegra194.c @@ -1359,4 +1359,6 @@ const struct tegra_mc_soc tegra194_mc_soc = { .ch_intmask = 0x00000f00, .global_intstatus_channel_shift = 8, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c index 1b2b598ab564..6750b08d875f 100644 --- a/drivers/memory/tegra/tegra20.c +++ b/drivers/memory/tegra/tegra20.c @@ -761,9 +761,12 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data) return IRQ_HANDLED; } +static const irq_handler_t tegra20_mc_irq_handlers[] = { + tegra20_mc_handle_irq +}; + static const struct tegra_mc_ops tegra20_mc_ops = { .probe = tegra20_mc_probe, - .handle_irq = tegra20_mc_handle_irq, }; const struct tegra_mc_soc tegra20_mc_soc = { @@ -779,4 +782,6 @@ const struct tegra_mc_soc tegra20_mc_soc = { .icc_ops = &tegra20_mc_icc_ops, .ops = &tegra20_mc_ops, .regs = &tegra20_mc_regs, + .handle_irq = tegra20_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra20_mc_irq_handlers), }; diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c index e166b33848e9..8283601ab52c 100644 --- a/drivers/memory/tegra/tegra210.c +++ b/drivers/memory/tegra/tegra210.c @@ -1288,4 +1288,6 @@ const struct tegra_mc_soc tegra210_mc_soc = { .num_resets = ARRAY_SIZE(tegra210_mc_resets), .ops = &tegra30_mc_ops, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index 512d054d7592..9586d7528fb7 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -1153,4 +1153,6 @@ const struct tegra_mc_soc tegra234_mc_soc = { */ .num_carveouts = 32, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c index 337501a30a73..ff89b9078772 100644 --- a/drivers/memory/tegra/tegra30.c +++ b/drivers/memory/tegra/tegra30.c @@ -1401,4 +1401,6 @@ const struct tegra_mc_soc tegra30_mc_soc = { .icc_ops = &tegra30_mc_icc_ops, .ops = &tegra30_mc_ops, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index 372f47e824d5..d07de04c0f33 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -10,10 +10,11 @@ #include #include #include +#include #include #include -#include #include +#include struct clk; struct device; @@ -164,7 +165,6 @@ struct tegra_mc_ops { int (*probe)(struct tegra_mc *mc); void (*remove)(struct tegra_mc *mc); int (*resume)(struct tegra_mc *mc); - irqreturn_t (*handle_irq)(int irq, void *data); int (*probe_device)(struct tegra_mc *mc, struct device *dev); }; @@ -214,6 +214,9 @@ struct tegra_mc_soc { const struct tegra_mc_icc_ops *icc_ops; const struct tegra_mc_ops *ops; const struct tegra_mc_regs *regs; + + const irq_handler_t *handle_irq; + unsigned int num_interrupts; }; struct tegra_mc { @@ -224,7 +227,6 @@ struct tegra_mc { void __iomem *bcast_ch_regs; void __iomem **ch_regs; struct clk *clk; - int irq; const struct tegra_mc_soc *soc; unsigned long tick; From 2e4cfaa78eb98d2623367818c859225c6b6bf701 Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 26 Feb 2026 16:31:13 +0000 Subject: [PATCH 052/193] memory: tegra: Group SoC specific fields Introduce new SoC specific fields in tegra_mc_soc struct for high address mask and error status type mask because Tegra264 has different values for these than the existing devices. Error status registers e.g. MC_ERR_STATUS_0 has few bits which indicate the type of the error. In order to obtain such type of error from error status register, we use error status type mask. Similarly, these error status registers have bits which indicate the higher address bits of the address responsible for mc error. In order to obtain such higher address, we use high address mask. Make this change to prepare for adding MC interrupt support for Tegra264. Signed-off-by: Ketan Patil Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20260226163115.1152181-5-ketanp@nvidia.com [krzk: Fix checkpatch warning] Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 11 +++++++---- drivers/memory/tegra/mc.h | 2 -- drivers/memory/tegra/tegra114.c | 1 + drivers/memory/tegra/tegra124.c | 4 ++++ drivers/memory/tegra/tegra186.c | 2 ++ drivers/memory/tegra/tegra194.c | 2 ++ drivers/memory/tegra/tegra20.c | 1 + drivers/memory/tegra/tegra210.c | 2 ++ drivers/memory/tegra/tegra234.c | 2 ++ drivers/memory/tegra/tegra30.c | 1 + include/soc/tegra/mc.h | 2 ++ 11 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 8114574374d5..5d0d9b7fc534 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -658,9 +658,12 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data) addr = mc_ch_readl(mc, channel, addr_hi_reg); else addr = mc_readl(mc, addr_hi_reg); - } else { + } else if (mc->soc->mc_addr_hi_mask) { addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT) & - MC_ERR_STATUS_ADR_HI_MASK); + mc->soc->mc_addr_hi_mask); + } else { + dev_err_ratelimited(mc->dev, "Unable to determine high address!"); + return IRQ_NONE; } addr <<= 32; } @@ -685,11 +688,11 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data) } } - type = (value & MC_ERR_STATUS_TYPE_MASK) >> + type = (value & mc->soc->mc_err_status_type_mask) >> MC_ERR_STATUS_TYPE_SHIFT; desc = tegra_mc_error_names[type]; - switch (value & MC_ERR_STATUS_TYPE_MASK) { + switch (value & mc->soc->mc_err_status_type_mask) { case MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE: perm[0] = ' '; perm[1] = '['; diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index 34ce03ebc51c..b286c2558fd5 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -78,10 +78,8 @@ #define MC_ERR_STATUS_TYPE_SHIFT 28 #define MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE (0x6 << 28) -#define MC_ERR_STATUS_TYPE_MASK (0x7 << 28) #define MC_ERR_STATUS_ADR_HI_SHIFT 20 -#define MC_ERR_STATUS_ADR_HI_MASK 0x3 #define MC_BROADCAST_CHANNEL ~0 diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c index fffb28eea57f..3a061a2d881e 100644 --- a/drivers/memory/tegra/tegra114.c +++ b/drivers/memory/tegra/tegra114.c @@ -1117,4 +1117,5 @@ const struct tegra_mc_soc tegra114_mc_soc = { .regs = &tegra20_mc_regs, .handle_irq = tegra30_mc_irq_handlers, .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), + .mc_err_status_type_mask = (0x7 << 28), }; diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index 2cf733198782..4d394889c1e9 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -1278,6 +1278,8 @@ const struct tegra_mc_soc tegra124_mc_soc = { .regs = &tegra20_mc_regs, .handle_irq = tegra30_mc_irq_handlers, .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), + .mc_addr_hi_mask = 0x3, + .mc_err_status_type_mask = (0x7 << 28), }; #endif /* CONFIG_ARCH_TEGRA_124_SOC */ @@ -1313,5 +1315,7 @@ const struct tegra_mc_soc tegra132_mc_soc = { .regs = &tegra20_mc_regs, .handle_irq = tegra30_mc_irq_handlers, .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), + .mc_addr_hi_mask = 0x3, + .mc_err_status_type_mask = (0x7 << 28), }; #endif /* CONFIG_ARCH_TEGRA_132_SOC */ diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c index eb1eaaffc79a..94cad76c52ac 100644 --- a/drivers/memory/tegra/tegra186.c +++ b/drivers/memory/tegra/tegra186.c @@ -916,5 +916,7 @@ const struct tegra_mc_soc tegra186_mc_soc = { .regs = &tegra20_mc_regs, .handle_irq = tegra30_mc_irq_handlers, .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), + .mc_addr_hi_mask = 0x3, + .mc_err_status_type_mask = (0x7 << 28), }; #endif diff --git a/drivers/memory/tegra/tegra194.c b/drivers/memory/tegra/tegra194.c index cb0e7886857d..38852b2a0f44 100644 --- a/drivers/memory/tegra/tegra194.c +++ b/drivers/memory/tegra/tegra194.c @@ -1361,4 +1361,6 @@ const struct tegra_mc_soc tegra194_mc_soc = { .regs = &tegra20_mc_regs, .handle_irq = tegra30_mc_irq_handlers, .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), + .mc_addr_hi_mask = 0x3, + .mc_err_status_type_mask = (0x7 << 28), }; diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c index 6750b08d875f..a5cc770437ae 100644 --- a/drivers/memory/tegra/tegra20.c +++ b/drivers/memory/tegra/tegra20.c @@ -784,4 +784,5 @@ const struct tegra_mc_soc tegra20_mc_soc = { .regs = &tegra20_mc_regs, .handle_irq = tegra20_mc_irq_handlers, .num_interrupts = ARRAY_SIZE(tegra20_mc_irq_handlers), + .mc_err_status_type_mask = (0x7 << 28), }; diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c index 8283601ab52c..aa606df8a679 100644 --- a/drivers/memory/tegra/tegra210.c +++ b/drivers/memory/tegra/tegra210.c @@ -1290,4 +1290,6 @@ const struct tegra_mc_soc tegra210_mc_soc = { .regs = &tegra20_mc_regs, .handle_irq = tegra30_mc_irq_handlers, .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), + .mc_addr_hi_mask = 0x3, + .mc_err_status_type_mask = (0x7 << 28), }; diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index 9586d7528fb7..67d5d4e01a65 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -1155,4 +1155,6 @@ const struct tegra_mc_soc tegra234_mc_soc = { .regs = &tegra20_mc_regs, .handle_irq = tegra30_mc_irq_handlers, .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), + .mc_addr_hi_mask = 0x3, + .mc_err_status_type_mask = (0x7 << 28), }; diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c index ff89b9078772..8a26a2f204e9 100644 --- a/drivers/memory/tegra/tegra30.c +++ b/drivers/memory/tegra/tegra30.c @@ -1403,4 +1403,5 @@ const struct tegra_mc_soc tegra30_mc_soc = { .regs = &tegra20_mc_regs, .handle_irq = tegra30_mc_irq_handlers, .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), + .mc_err_status_type_mask = (0x7 << 28), }; diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index d07de04c0f33..b9b1763b10b5 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -217,6 +217,8 @@ struct tegra_mc_soc { const irq_handler_t *handle_irq; unsigned int num_interrupts; + unsigned int mc_addr_hi_mask; + unsigned int mc_err_status_type_mask; }; struct tegra_mc { From 9f2614510960f0761144d14e1b4c4d82e0c098e9 Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 26 Feb 2026 16:31:14 +0000 Subject: [PATCH 053/193] memory: tegra: Prepare for supporting multiple intmask registers Add a new structure for the intmask register e.g. MC_INTMASK_0 and it's mask value. Add an array of these new structures to prepare for supporting multiple intmask registers. This is done in preparation for adding support for Tegra264 which supports multiple intmask registers. Signed-off-by: Ketan Patil Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20260226163115.1152181-6-ketanp@nvidia.com [krzk: Fix checkpatch warning] Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 16 +++++++++------- drivers/memory/tegra/tegra114.c | 12 ++++++++++-- drivers/memory/tegra/tegra124.c | 28 ++++++++++++++++++++++------ drivers/memory/tegra/tegra186.c | 14 +++++++++++--- drivers/memory/tegra/tegra194.c | 15 +++++++++++---- drivers/memory/tegra/tegra20.c | 14 +++++++++++--- drivers/memory/tegra/tegra210.c | 14 +++++++++++--- drivers/memory/tegra/tegra234.c | 15 +++++++++++---- drivers/memory/tegra/tegra264.c | 17 ++++++++++++----- drivers/memory/tegra/tegra30.c | 12 ++++++++++-- include/soc/tegra/mc.h | 8 +++++++- 11 files changed, 125 insertions(+), 40 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 5d0d9b7fc534..dccebbed7833 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -586,9 +586,9 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data) } /* mask all interrupts to avoid flooding */ - status = mc_ch_readl(mc, channel, MC_INTSTATUS) & mc->soc->intmask; + status = mc_ch_readl(mc, channel, MC_INTSTATUS) & mc->soc->intmasks[0].mask; } else { - status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask; + status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmasks[0].mask; } if (!status) @@ -969,11 +969,13 @@ static int tegra_mc_probe(struct platform_device *pdev) } } - if (mc->soc->num_channels) - mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmask, - MC_INTMASK); - else - mc_writel(mc, mc->soc->intmask, MC_INTMASK); + for (i = 0; i < mc->soc->num_intmasks; i++) { + if (mc->soc->num_channels) + mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmasks[i].mask, + mc->soc->intmasks[i].reg); + else + mc_writel(mc, mc->soc->intmasks[i].mask, mc->soc->intmasks[i].reg); + } } if (mc->soc->reset_ops) { diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c index 3a061a2d881e..02dd4e26288a 100644 --- a/drivers/memory/tegra/tegra114.c +++ b/drivers/memory/tegra/tegra114.c @@ -1101,6 +1101,14 @@ static const struct tegra_mc_reset tegra114_mc_resets[] = { TEGRA114_MC_RESET(VI, 0x200, 0x204, 17), }; +static const struct tegra_mc_intmask tegra114_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | + MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra114_mc_soc = { .clients = tegra114_mc_clients, .num_clients = ARRAY_SIZE(tegra114_mc_clients), @@ -1108,8 +1116,8 @@ const struct tegra_mc_soc tegra114_mc_soc = { .atom_size = 32, .client_id_mask = 0x7f, .smmu = &tegra114_smmu_soc, - .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | - MC_INT_DECERR_EMEM, + .intmasks = tegra114_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra114_mc_intmasks), .reset_ops = &tegra_mc_reset_ops_common, .resets = tegra114_mc_resets, .num_resets = ARRAY_SIZE(tegra114_mc_resets), diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index 4d394889c1e9..df87c5038625 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -1258,6 +1258,15 @@ static const struct tegra_smmu_soc tegra124_smmu_soc = { .num_asids = 128, }; +static const struct tegra_mc_intmask tegra124_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | + MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE | + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra124_mc_soc = { .clients = tegra124_mc_clients, .num_clients = ARRAY_SIZE(tegra124_mc_clients), @@ -1267,9 +1276,8 @@ const struct tegra_mc_soc tegra124_mc_soc = { .smmu = &tegra124_smmu_soc, .emem_regs = tegra124_mc_emem_regs, .num_emem_regs = ARRAY_SIZE(tegra124_mc_emem_regs), - .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | - MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE | - MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .intmasks = tegra124_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra124_mc_intmasks), .reset_ops = &tegra_mc_reset_ops_common, .resets = tegra124_mc_resets, .num_resets = ARRAY_SIZE(tegra124_mc_resets), @@ -1297,6 +1305,15 @@ static const struct tegra_smmu_soc tegra132_smmu_soc = { .num_asids = 128, }; +static const struct tegra_mc_intmask tegra132_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | + MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE | + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra132_mc_soc = { .clients = tegra124_mc_clients, .num_clients = ARRAY_SIZE(tegra124_mc_clients), @@ -1304,9 +1321,8 @@ const struct tegra_mc_soc tegra132_mc_soc = { .atom_size = 32, .client_id_mask = 0x7f, .smmu = &tegra132_smmu_soc, - .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | - MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE | - MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .intmasks = tegra132_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra132_mc_intmasks), .reset_ops = &tegra_mc_reset_ops_common, .resets = tegra124_mc_resets, .num_resets = ARRAY_SIZE(tegra124_mc_resets), diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c index 94cad76c52ac..91d56165605f 100644 --- a/drivers/memory/tegra/tegra186.c +++ b/drivers/memory/tegra/tegra186.c @@ -901,15 +901,23 @@ static const struct tegra_mc_client tegra186_mc_clients[] = { }, }; +static const struct tegra_mc_intmask tegra186_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS | + MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra186_mc_soc = { .num_clients = ARRAY_SIZE(tegra186_mc_clients), .clients = tegra186_mc_clients, .num_address_bits = 40, .num_channels = 4, .client_id_mask = 0xff, - .intmask = MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS | - MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | - MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .intmasks = tegra186_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra186_mc_intmasks), .ops = &tegra186_mc_ops, .ch_intmask = 0x0000000f, .global_intstatus_channel_shift = 0, diff --git a/drivers/memory/tegra/tegra194.c b/drivers/memory/tegra/tegra194.c index 38852b2a0f44..a8cc57690696 100644 --- a/drivers/memory/tegra/tegra194.c +++ b/drivers/memory/tegra/tegra194.c @@ -1343,16 +1343,23 @@ static const struct tegra_mc_client tegra194_mc_clients[] = { }, }; +static const struct tegra_mc_intmask tegra194_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_DECERR_ROUTE_SANITY | MC_INT_DECERR_GENERALIZED_CARVEOUT | + MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra194_mc_soc = { .num_clients = ARRAY_SIZE(tegra194_mc_clients), .clients = tegra194_mc_clients, .num_address_bits = 40, .num_channels = 16, .client_id_mask = 0xff, - .intmask = MC_INT_DECERR_ROUTE_SANITY | - MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS | - MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | - MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .intmasks = tegra194_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra194_mc_intmasks), .has_addr_hi_reg = true, .ops = &tegra186_mc_ops, .icc_ops = &tegra_mc_icc_ops, diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c index a5cc770437ae..ff9e151b5a4c 100644 --- a/drivers/memory/tegra/tegra20.c +++ b/drivers/memory/tegra/tegra20.c @@ -695,7 +695,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data) unsigned int bit; /* mask all interrupts to avoid flooding */ - status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask; + status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmasks[0].mask; if (!status) return IRQ_NONE; @@ -769,13 +769,21 @@ static const struct tegra_mc_ops tegra20_mc_ops = { .probe = tegra20_mc_probe, }; +static const struct tegra_mc_intmask tegra20_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE | + MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra20_mc_soc = { .clients = tegra20_mc_clients, .num_clients = ARRAY_SIZE(tegra20_mc_clients), .num_address_bits = 32, .client_id_mask = 0x3f, - .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE | - MC_INT_DECERR_EMEM, + .intmasks = tegra20_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra20_mc_intmasks), .reset_ops = &tegra20_mc_reset_ops, .resets = tegra20_mc_resets, .num_resets = ARRAY_SIZE(tegra20_mc_resets), diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c index aa606df8a679..f58f3ef6f681 100644 --- a/drivers/memory/tegra/tegra210.c +++ b/drivers/memory/tegra/tegra210.c @@ -1273,6 +1273,15 @@ static const struct tegra_mc_reset tegra210_mc_resets[] = { TEGRA210_MC_RESET(TSECB, 0x970, 0x974, 13), }; +static const struct tegra_mc_intmask tegra210_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | + MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE | + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra210_mc_soc = { .clients = tegra210_mc_clients, .num_clients = ARRAY_SIZE(tegra210_mc_clients), @@ -1280,9 +1289,8 @@ const struct tegra_mc_soc tegra210_mc_soc = { .atom_size = 64, .client_id_mask = 0xff, .smmu = &tegra210_smmu_soc, - .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | - MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE | - MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .intmasks = tegra210_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra210_mc_intmasks), .reset_ops = &tegra_mc_reset_ops_common, .resets = tegra210_mc_resets, .num_resets = ARRAY_SIZE(tegra210_mc_resets), diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index 67d5d4e01a65..87b22038a5fb 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -1132,16 +1132,23 @@ static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = { .set = tegra234_mc_icc_set, }; +static const struct tegra_mc_intmask tegra234_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_DECERR_ROUTE_SANITY | MC_INT_DECERR_GENERALIZED_CARVEOUT | + MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra234_mc_soc = { .num_clients = ARRAY_SIZE(tegra234_mc_clients), .clients = tegra234_mc_clients, .num_address_bits = 40, .num_channels = 16, .client_id_mask = 0x1ff, - .intmask = MC_INT_DECERR_ROUTE_SANITY | - MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS | - MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | - MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .intmasks = tegra234_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra234_mc_intmasks), .has_addr_hi_reg = true, .ops = &tegra186_mc_ops, .icc_ops = &tegra234_mc_icc_ops, diff --git a/drivers/memory/tegra/tegra264.c b/drivers/memory/tegra/tegra264.c index 5203e6c11372..172a48b56484 100644 --- a/drivers/memory/tegra/tegra264.c +++ b/drivers/memory/tegra/tegra264.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2025, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2025-2026, NVIDIA CORPORATION. All rights reserved. */ #include @@ -290,16 +290,23 @@ static const struct tegra_mc_icc_ops tegra264_mc_icc_ops = { .set = tegra264_mc_icc_set, }; +static const struct tegra_mc_intmask tegra264_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_DECERR_ROUTE_SANITY | MC_INT_DECERR_GENERALIZED_CARVEOUT | + MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra264_mc_soc = { .num_clients = ARRAY_SIZE(tegra264_mc_clients), .clients = tegra264_mc_clients, .num_address_bits = 40, .num_channels = 16, .client_id_mask = 0x1ff, - .intmask = MC_INT_DECERR_ROUTE_SANITY | - MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS | - MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | - MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .intmasks = tegra264_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra264_mc_intmasks), .has_addr_hi_reg = true, .ops = &tegra186_mc_ops, .icc_ops = &tegra264_mc_icc_ops, diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c index 8a26a2f204e9..8389e3af0121 100644 --- a/drivers/memory/tegra/tegra30.c +++ b/drivers/memory/tegra/tegra30.c @@ -1384,6 +1384,14 @@ static const struct tegra_mc_icc_ops tegra30_mc_icc_ops = { .set = tegra30_mc_icc_set, }; +static const struct tegra_mc_intmask tegra30_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | + MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra30_mc_soc = { .clients = tegra30_mc_clients, .num_clients = ARRAY_SIZE(tegra30_mc_clients), @@ -1393,8 +1401,8 @@ const struct tegra_mc_soc tegra30_mc_soc = { .smmu = &tegra30_smmu_soc, .emem_regs = tegra30_mc_emem_regs, .num_emem_regs = ARRAY_SIZE(tegra30_mc_emem_regs), - .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | - MC_INT_DECERR_EMEM, + .intmasks = tegra30_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra30_mc_intmasks), .reset_ops = &tegra_mc_reset_ops_common, .resets = tegra30_mc_resets, .num_resets = ARRAY_SIZE(tegra30_mc_resets), diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index b9b1763b10b5..e6da035d1306 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -185,6 +185,11 @@ struct tegra_mc_regs { unsigned int err_route_add; }; +struct tegra_mc_intmask { + u32 reg; + u32 mask; +}; + struct tegra_mc_soc { const struct tegra_mc_client *clients; unsigned int num_clients; @@ -202,7 +207,6 @@ struct tegra_mc_soc { const struct tegra_smmu_soc *smmu; - u32 intmask; u32 ch_intmask; u32 global_intstatus_channel_shift; bool has_addr_hi_reg; @@ -219,6 +223,8 @@ struct tegra_mc_soc { unsigned int num_interrupts; unsigned int mc_addr_hi_mask; unsigned int mc_err_status_type_mask; + const struct tegra_mc_intmask *intmasks; + unsigned int num_intmasks; }; struct tegra_mc { From 82169065ffb07577075a5088b313d78673ded331 Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 26 Feb 2026 16:31:15 +0000 Subject: [PATCH 054/193] memory: tegra: Add MC error logging support for Tegra264 In Tegra264, different components from memory subsystems like Memory Controller Fabric (MCF), HUB, HUB Common (HUBC), Side Band Shim (SBS) and channels have different interrupt lines for receiving memory controller error interrupts. Add support for logging memory controller errors reported by these memory subsystems on Tegra264 by: - Renaming tegra_mc_error_names array to tegra20_mc_error_names because it has a different bit index for error names compared to Tegra264. - Defining the intmask registers and mask values supported for Tegra264. - Registering interrupt handlers for interrupts associated with these different MC components which read the interrupt status registers to determine the type of violation that occurred. Signed-off-by: Ketan Patil Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20260226163115.1152181-7-ketanp@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 5 +- drivers/memory/tegra/mc.h | 72 +++++- drivers/memory/tegra/tegra20.c | 6 +- drivers/memory/tegra/tegra264.c | 411 +++++++++++++++++++++++++++++++- 4 files changed, 484 insertions(+), 10 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index dccebbed7833..d620660da331 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -690,7 +690,7 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data) type = (value & mc->soc->mc_err_status_type_mask) >> MC_ERR_STATUS_TYPE_SHIFT; - desc = tegra_mc_error_names[type]; + desc = tegra20_mc_error_names[type]; switch (value & mc->soc->mc_err_status_type_mask) { case MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE: @@ -758,9 +758,10 @@ const char *const tegra_mc_status_names[32] = { [16] = "MTS carveout violation", [17] = "Generalized carveout violation", [20] = "Route Sanity error", + [21] = "GIC_MSI error", }; -const char *const tegra_mc_error_names[8] = { +const char *const tegra20_mc_error_names[8] = { [2] = "EMEM decode error", [3] = "TrustZone violation", [4] = "Carveout violation", diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index b286c2558fd5..649b54369263 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -25,6 +25,7 @@ #define MC_INT_DECERR_MTS BIT(16) #define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17) #define MC_INT_DECERR_ROUTE_SANITY BIT(20) +#define MC_INT_DECERR_ROUTE_SANITY_GIC_MSI BIT(21) #define MC_INTMASK 0x04 #define MC_GART_ERROR_REQ 0x30 @@ -76,13 +77,82 @@ #define MC_ERR_STATUS_WRITABLE BIT(26) #define MC_ERR_STATUS_READABLE BIT(27) +#define MC_ERR_STATUS_GSC_ADR_HI_MASK 0xffff +#define MC_ERR_STATUS_GSC_ADR_HI_SHIFT 16 +#define MC_ERR_STATUS_RT_ADR_HI_SHIFT 15 + #define MC_ERR_STATUS_TYPE_SHIFT 28 #define MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE (0x6 << 28) +#define MC_ERR_STATUS_RT_TYPE_MASK (0xf << 28) +#define MC_ERR_STATUS_RT_TYPE_SHIFT 28 #define MC_ERR_STATUS_ADR_HI_SHIFT 20 #define MC_BROADCAST_CHANNEL ~0 +/* Tegra264 specific registers */ + +/* Registers for MSS HUB */ +#define MSS_HUB_GLOBAL_INTSTATUS_0 0x6000 +#define MSS_HUBC_INTR BIT(0) +#define MSS_HUB_GLOBAL_MASK 0x7F00 +#define MSS_HUB_GLOBAL_SHIFT 8 + +#define MSS_HUB_HUBC_INTSTATUS_0 0x6008 +#define MSS_HUB_INTRSTATUS_0 0x600c +#define MSS_HUB_HUBC_INTMASK_0 0x6010 +#define MSS_HUB_HUBC_SCRUB_DONE_INTMASK BIT(0) + +#define MSS_HUB_HUBC_INTPRIORITY_0 0x6014 +#define MSS_HUB_INTRMASK_0 0x6018 +#define MSS_HUB_COALESCER_ERR_INTMASK BIT(0) +#define MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK BIT(1) +#define MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK BIT(2) +#define MSS_HUB_MSI_ERR_INTMASK BIT(3) +#define MSS_HUB_POISON_RSP_INTMASK BIT(4) +#define MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK BIT(5) +#define MSS_HUB_RESERVED_PA_ERR_INTMASK BIT(6) + +#define MSS_HUB_INTRPRIORITY_0 0x601c +#define MSS_HUB_SMMU_BYPASS_ALLOW_ERR_STATUS_0 0x6020 +#define MSS_HUB_MSI_ERR_STATUS_0 0x6024 +#define MSS_HUB_POISON_RSP_STATUS_0 0x6028 +#define MSS_HUB_COALESCE_ERR_STATUS_0 0x60e0 +#define MSS_HUB_COALESCE_ERR_ADR_HI_0 0x60e4 +#define MSS_HUB_COALESCE_ERR_ADR_0 0x60e8 +#define MSS_HUB_RESTRICTED_ACCESS_ERR_STATUS_0 0x638c +#define MSS_HUB_RESERVED_PA_ERR_STATUS_0 0x6390 +#define MSS_HUB_ILLEGAL_TBUGRP_ID_ERR_STATUS_0 0x63b0 + +/* Registers for channels */ +#define MC_CH_INTSTATUS_0 0x82d4 +#define MC_CH_INTMASK_0 0x82d8 +#define WCAM_ERR_INTMASK BIT(19) + +#define MC_ERR_GENERALIZED_CARVEOUT_STATUS_1_0 0xbc74 + +/* Registers for MCF */ +#define MCF_COMMON_INTSTATUS0_0_0 0xce04 +#define MCF_INTSTATUS_0 0xce2c +#define MCF_INTMASK_0 0xce30 +#define MCF_INTPRIORITY_0 0xce34 + +/* Registers for SBS */ +#define MSS_SBS_INTSTATUS_0 0xec08 +#define MSS_SBS_INTMASK_0 0xec0c +#define MSS_SBS_FILL_FIFO_ISO_OVERFLOW_INTMASK BIT(0) +#define MSS_SBS_FILL_FIFO_SISO_OVERFLOW_INTMASK BIT(1) +#define MSS_SBS_FILL_FIFO_NISO_OVERFLOW_INTMASK BIT(2) + +/* Bit field of MC_ERR_ROUTE_SANITY_STATUS_0 register */ +#define MC_ERR_ROUTE_SANITY_RW BIT(12) +#define MC_ERR_ROUTE_SANITY_SEC BIT(13) + +#define ERR_GENERALIZED_APERTURE_ID_SHIFT 0 +#define ERR_GENERALIZED_APERTURE_ID_MASK 0x1F +#define ERR_GENERALIZED_CARVEOUT_APERTURE_ID_SHIFT 5 +#define ERR_GENERALIZED_CARVEOUT_APERTURE_ID_MASK 0x1F + static inline u32 tegra_mc_scale_percents(u64 val, unsigned int percents) { val = val * percents; @@ -193,7 +263,7 @@ extern const struct tegra_mc_ops tegra186_mc_ops; irqreturn_t tegra30_mc_handle_irq(int irq, void *data); extern const irq_handler_t tegra30_mc_irq_handlers[1]; extern const char * const tegra_mc_status_names[32]; -extern const char * const tegra_mc_error_names[8]; +extern const char * const tegra20_mc_error_names[8]; /* * These IDs are for internal use of Tegra ICC drivers. The ID numbers are diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c index ff9e151b5a4c..27dd6886f86e 100644 --- a/drivers/memory/tegra/tegra20.c +++ b/drivers/memory/tegra/tegra20.c @@ -713,7 +713,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data) value = mc_readl(mc, reg); id = value & mc->soc->client_id_mask; - desc = tegra_mc_error_names[2]; + desc = tegra20_mc_error_names[2]; if (value & BIT(31)) direction = "write"; @@ -724,7 +724,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data) value = mc_readl(mc, reg); id = (value >> 1) & mc->soc->client_id_mask; - desc = tegra_mc_error_names[2]; + desc = tegra20_mc_error_names[2]; if (value & BIT(0)) direction = "write"; @@ -736,7 +736,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data) id = value & mc->soc->client_id_mask; type = (value & BIT(30)) ? 4 : 3; - desc = tegra_mc_error_names[type]; + desc = tegra20_mc_error_names[type]; secure = "secure "; if (value & BIT(31)) diff --git a/drivers/memory/tegra/tegra264.c b/drivers/memory/tegra/tegra264.c index 172a48b56484..e43ef14da1ee 100644 --- a/drivers/memory/tegra/tegra264.c +++ b/drivers/memory/tegra/tegra264.c @@ -188,6 +188,41 @@ static const struct tegra_mc_client tegra264_mc_clients[] = { }, }; +static const char *const tegra264_hub_error_names[32] = { + [0] = "coalescer error", + [1] = "SMMU BYPASS ALLOW error", + [2] = "Illegal tbugrp_id error", + [3] = "Malformed MSI request error", + [4] = "Read response with poison bit error", + [5] = "Restricted access violation error", + [6] = "Reserved PA error", +}; + +static const char *const tegra264_mc_error_names[4] = { + [1] = "EMEM decode error", + [2] = "TrustZone violation", + [3] = "Carveout violation", +}; + +static const char *const tegra264_rt_error_names[16] = { + [1] = "DECERR_PARTIAL_POPULATED", + [2] = "DECERR_SMMU_BYPASS", + [3] = "DECERR_INVALID_MMIO", + [4] = "DECERR_INVALID_GIC_MSI", + [5] = "DECERR_ATOMIC_SYSRAM", + [9] = "DECERR_REMOTE_REQ_PRE_BOOT", + [10] = "DECERR_ISO_OVER_C2C", + [11] = "DECERR_UNSUPPORTED_SBS_OPCODE", + [12] = "DECERR_SBS_REQ_OVER_SISO_LL", +}; + +/* + * MC instance aperture mapping for hubc registers + */ +static const int mc_hubc_aperture_number[5] = { + 7, 8, 9, 10, 11 +}; + /* * tegra264_mc_icc_set() - Pass MC client info to the BPMP-FW * @src: ICC node for Memory Controller's (MC) Client @@ -283,6 +318,312 @@ static int tegra264_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea return 0; } +static void mcf_log_fault(struct tegra_mc *mc, u32 channel, unsigned long mcf_ch_intstatus) +{ + unsigned int bit; + + 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; + + 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; + 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]; + } + + 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)); + } + + /* clear interrupts */ + mc_ch_writel(mc, channel, mcf_ch_intstatus, MCF_INTSTATUS_0); +} + +static irqreturn_t handle_mcf_irq(int irq, void *data) +{ + struct tegra_mc *mc = data; + unsigned long common_intstat, intstatus; + u32 slice; + + /* Read MCF_COMMON_INTSTATUS0_0_0 from MCB block */ + common_intstat = mc_ch_readl(mc, MC_BROADCAST_CHANNEL, MCF_COMMON_INTSTATUS0_0_0); + if (common_intstat == 0) { + dev_warn(mc->dev, "No interrupt in MCF\n"); + return IRQ_NONE; + } + + for_each_set_bit(slice, &common_intstat, 32) { + /* Find out the slice number on which interrupt occurred */ + if (slice > 4) { + dev_err(mc->dev, "Slice index out of bounds: %u\n", slice); + return IRQ_NONE; + } + + intstatus = mc_ch_readl(mc, slice, MCF_INTSTATUS_0); + if (intstatus != 0) + mcf_log_fault(mc, slice, intstatus); + } + + return IRQ_HANDLED; +} + +static void hub_log_fault(struct tegra_mc *mc, u32 hub, unsigned long hub_intstat) +{ + unsigned int bit; + + for_each_set_bit(bit, &hub_intstat, 32) { + const char *client = "unknown"; + u32 client_id, status_reg, value, i; + phys_addr_t addr = 0; + + 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; + + 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: + dev_err_ratelimited(mc->dev, "Incorrect HUB interrupt mask\n"); + return; + } + + value = mc_ch_readl(mc, hub, status_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; + } + } + + dev_err_ratelimited(mc->dev, "%s: @%pa: %s status: 0x%x\n", + client, &addr, tegra264_hub_error_names[bit] ?: "unknown", + value); + } + + /* clear interrupts */ + mc_ch_writel(mc, hub, hub_intstat, MSS_HUB_INTRSTATUS_0); +} + +static irqreturn_t handle_hub_irq(int irq, void *data, int mc_hubc_aperture_number) +{ + struct tegra_mc *mc = data; + u32 global_intstat; + unsigned long hub_interrupt, intstat, hub; + + /* Read MSS_HUB_GLOBAL_INTSTATUS_0 from mc_hubc_aperture_number block */ + global_intstat = mc_ch_readl(mc, mc_hubc_aperture_number, MSS_HUB_GLOBAL_INTSTATUS_0); + if (global_intstat == 0) { + dev_warn(mc->dev, "No interrupt in HUB/HUBC\n"); + return IRQ_NONE; + } + + /* Handle interrupt from hubc */ + if (global_intstat & MSS_HUBC_INTR) { + /* Read MSS_HUB_HUBC_INTSTATUS_0 from block mc_hubc_aperture_number */ + intstat = mc_ch_readl(mc, mc_hubc_aperture_number, MSS_HUB_HUBC_INTSTATUS_0); + if (intstat != 0) { + dev_err_ratelimited(mc->dev, "Scrubber operation status: 0x%lx\n", + intstat); + /* Clear hubc interrupt */ + mc_ch_writel(mc, mc_hubc_aperture_number, intstat, + MSS_HUB_HUBC_INTSTATUS_0); + } + } + + hub_interrupt = (global_intstat & MSS_HUB_GLOBAL_MASK) >> MSS_HUB_GLOBAL_SHIFT; + /* Handle interrupt from hub */ + for_each_set_bit(hub, &hub_interrupt, 32) { + /* Read MSS_HUB_INTRSTATUS_0 from block MCi */ + intstat = mc_ch_readl(mc, hub, MSS_HUB_INTRSTATUS_0); + if (intstat != 0) + hub_log_fault(mc, hub, intstat); + } + + /* Clear global interrupt status register */ + mc_ch_writel(mc, mc_hubc_aperture_number, global_intstat, MSS_HUB_GLOBAL_INTSTATUS_0); + return IRQ_HANDLED; +} + +static irqreturn_t handle_disp_hub_irq(int irq, void *data) +{ + return handle_hub_irq(irq, data, mc_hubc_aperture_number[0]); +} + +static irqreturn_t handle_system_hub_irq(int irq, void *data) +{ + return handle_hub_irq(irq, data, mc_hubc_aperture_number[1]); +} + +static irqreturn_t handle_vision_hub_irq(int irq, void *data) +{ + return handle_hub_irq(irq, data, mc_hubc_aperture_number[2]); +} + +static irqreturn_t handle_uphy_hub_irq(int irq, void *data) +{ + return handle_hub_irq(irq, data, mc_hubc_aperture_number[3]); +} + +static irqreturn_t handle_top_hub_irq(int irq, void *data) +{ + return handle_hub_irq(irq, data, mc_hubc_aperture_number[4]); +} + +static irqreturn_t handle_generic_irq(struct tegra_mc *mc, unsigned long intstat_reg) +{ + u32 intstat, i; + + /* Iterate over all MC blocks to read INTSTATUS */ + for (i = 0; i < mc->num_channels; i++) { + intstat = mc_ch_readl(mc, i, intstat_reg); + if (intstat) { + dev_err_ratelimited(mc->dev, "channel: %i status: 0x%x\n", i, intstat); + /* Clear interrupt */ + mc_ch_writel(mc, i, intstat, intstat_reg); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t handle_sbs_irq(int irq, void *data) +{ + return handle_generic_irq((struct tegra_mc *)data, MSS_SBS_INTSTATUS_0); +} + +static irqreturn_t handle_channel_irq(int irq, void *data) +{ + return handle_generic_irq((struct tegra_mc *)data, MC_CH_INTSTATUS_0); +} + +static const irq_handler_t tegra264_mc_irq_handlers[8] = { + handle_mcf_irq, handle_disp_hub_irq, handle_vision_hub_irq, + handle_system_hub_irq, handle_uphy_hub_irq, handle_top_hub_irq, + handle_sbs_irq, handle_channel_irq +}; + static const struct tegra_mc_icc_ops tegra264_mc_icc_ops = { .xlate = tegra_mc_icc_xlate, .aggregate = tegra264_mc_icc_aggregate, @@ -290,13 +631,70 @@ static const struct tegra_mc_icc_ops tegra264_mc_icc_ops = { .set = tegra264_mc_icc_set, }; +static const struct tegra_mc_regs tegra264_mc_regs = { + .cfg_channel_enable = 0x8870, + .err_status = 0xbc00, + .err_add = 0xbc04, + .err_add_hi = 0xbc08, + .err_vpr_status = 0xbc20, + .err_vpr_add = 0xbc24, + .err_sec_status = 0xbc3c, + .err_sec_add = 0xbc40, + .err_mts_status = 0xbc5c, + .err_mts_add = 0xbc60, + .err_gen_co_status = 0xbc78, + .err_gen_co_add = 0xbc7c, + .err_route_status = 0xbc64, + .err_route_add = 0xbc68, +}; + static const struct tegra_mc_intmask tegra264_mc_intmasks[] = { { - .reg = MC_INTMASK, - .mask = MC_INT_DECERR_ROUTE_SANITY | MC_INT_DECERR_GENERALIZED_CARVEOUT | - MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | - MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .reg = MCF_INTMASK_0, + .mask = MC_INT_DECERR_ROUTE_SANITY_GIC_MSI | MC_INT_DECERR_ROUTE_SANITY | + MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS | + MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | MC_INT_SECURITY_VIOLATION | + MC_INT_DECERR_EMEM, }, + { + .reg = MCF_INTPRIORITY_0, + .mask = MC_INT_DECERR_ROUTE_SANITY_GIC_MSI | MC_INT_DECERR_ROUTE_SANITY | + MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS | + MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | MC_INT_SECURITY_VIOLATION | + MC_INT_DECERR_EMEM, + }, + { + .reg = MSS_HUB_INTRMASK_0, + .mask = MSS_HUB_COALESCER_ERR_INTMASK | MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK | + MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK | MSS_HUB_MSI_ERR_INTMASK | + MSS_HUB_POISON_RSP_INTMASK | MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK | + MSS_HUB_RESERVED_PA_ERR_INTMASK, + }, + { + .reg = MSS_HUB_INTRPRIORITY_0, + .mask = MSS_HUB_COALESCER_ERR_INTMASK | MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK | + MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK | MSS_HUB_MSI_ERR_INTMASK | + MSS_HUB_POISON_RSP_INTMASK | MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK | + MSS_HUB_RESERVED_PA_ERR_INTMASK, + }, + { + .reg = MSS_HUB_HUBC_INTMASK_0, + .mask = MSS_HUB_HUBC_SCRUB_DONE_INTMASK, + }, + { + .reg = MSS_HUB_HUBC_INTPRIORITY_0, + .mask = MSS_HUB_HUBC_SCRUB_DONE_INTMASK, + }, + { + .reg = MSS_SBS_INTMASK_0, + .mask = MSS_SBS_FILL_FIFO_ISO_OVERFLOW_INTMASK | + MSS_SBS_FILL_FIFO_SISO_OVERFLOW_INTMASK | + MSS_SBS_FILL_FIFO_NISO_OVERFLOW_INTMASK, + }, + { + .reg = MC_CH_INTMASK_0, + .mask = WCAM_ERR_INTMASK, + } }; const struct tegra_mc_soc tegra264_mc_soc = { @@ -317,4 +715,9 @@ const struct tegra_mc_soc tegra264_mc_soc = { * supported. */ .num_carveouts = 32, + .mc_addr_hi_mask = 0xff, + .mc_err_status_type_mask = (0x3 << 28), + .regs = &tegra264_mc_regs, + .handle_irq = tegra264_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra264_mc_irq_handlers), }; From 0c5453bf8437e558d3b3bc5a8e8c45d31126c254 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 17 Jan 2026 02:02:28 +0100 Subject: [PATCH 055/193] dt-bindings: firmware: arm,scmi: Document arm,no-completion-irq property Document new property arm,no-completion-irq . This optional property is intended for hardware that does not generate completion interrupts and can be used to unconditionally enable forced polling mode of operation. With this property set, such implementations which do not generate interrupts can be interacted with, until they are fixed to generate interrupts properly. Note that, because the original base protocol exchange also requires some sort of completion mechanism, it is not possible to query SCMI itself for this property and it must be described in DT. While this does look a bit like policy, the SCMI provider is part of the hardware, hence DT. Reviewed-by: Rob Herring (Arm) Signed-off-by: Marek Vasut Reviewed-by: Cristian Marussi Message-Id: <20260117010241.186685-1-marek.vasut+renesas@mailbox.org> Signed-off-by: Sudeep Holla --- .../devicetree/bindings/firmware/arm,scmi.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml index be817fd9cc34..d06cca9273c4 100644 --- a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml +++ b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml @@ -146,6 +146,13 @@ properties: this platform. If set, the value should be non-zero. minimum: 1 + arm,no-completion-irq: + type: boolean + description: + This optional property is intended for hardware that does not generate + completion interrupts and can be used to unconditionally enable forced + polling mode of operation. + arm,smc-id: $ref: /schemas/types.yaml#/definitions/uint32 description: @@ -379,6 +386,9 @@ then: - shmem else: + properties: + arm,no-completion-irq: false + if: properties: compatible: From d8283ac2c8fbf2b459672064ebff718fbefae226 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 17 Jan 2026 02:02:29 +0100 Subject: [PATCH 056/193] firmware: arm_scmi: Implement arm,no-completion-irq property Implement new property arm,no-completion-irq, which sets all SCMI operation into poll mode. This is meant to work around uncooperative SCP implementations, which do not generate completion interrupts. This applies to mbox/shmem based implementations. With this property set, such implementations which do not generate interrupts can be interacted with, until they are fixed to generate interrupts properly. Signed-off-by: Marek Vasut Reviewed-by: Cristian Marussi Message-Id: <20260117010241.186685-2-marek.vasut+renesas@mailbox.org> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 4 ++++ drivers/firmware/arm_scmi/driver.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 7c35c95fddba..7c9617d080a0 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -235,6 +235,9 @@ struct scmi_transport_ops { * to have an execution latency lesser-equal to the threshold * should be considered for atomic mode operation: such * 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: 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 @@ -254,6 +257,7 @@ struct scmi_desc { int max_msg; int max_msg_size; unsigned int atomic_threshold; + bool no_completion_irq; const bool force_polling; const bool sync_cmds_completed_on_ret; const bool atomic_enabled; diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 3e76a3204ba4..f167194f7cf6 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -2735,6 +2735,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node, cinfo->is_p2a = !tx; cinfo->rx_timeout_ms = info->desc->max_rx_timeout_ms; cinfo->max_msg_size = info->desc->max_msg_size; + cinfo->no_completion_irq = info->desc->no_completion_irq; /* Create a unique name for this transport device */ snprintf(name, 32, "__scmi_transport_device_%s_%02X", @@ -3150,6 +3151,9 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev) if (ret && ret != -EINVAL) dev_err(dev, "Malformed arm,max-msg DT property.\n"); + trans->desc.no_completion_irq = of_property_read_bool(dev->of_node, + "arm,no-completion-irq"); + dev_info(dev, "SCMI max-rx-timeout: %dms / max-msg-size: %dbytes / max-msg: %d\n", trans->desc.max_rx_timeout_ms, trans->desc.max_msg_size, From 09bb95d63adeaab7b07127cfce4ecbeff9ab6488 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Sat, 28 Feb 2026 11:37:33 +0800 Subject: [PATCH 057/193] firmware: arm_scmi: Use round_up() for base protocol list size calculation Replace the open-coded size rounding logic with the kernel's round_up() helper to improve readability and align with common kernel practices. The original expression: (1 + (loop_num_ret - 1) / sizeof(u32)) * sizeof(u32) is equivalent to rounding up loop_num_ret to the nearest multiple of sizeof(u32), which is exactly what round_up() does. No functional change. Signed-off-by: Peng Fan Reviewed-by: Cristian Marussi Message-Id: <20260228-scmi-check-v1-1-4935b58bb2db@nxp.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c index 22267bbd0f4d..cd1331c2fc40 100644 --- a/drivers/firmware/arm_scmi/base.c +++ b/drivers/firmware/arm_scmi/base.c @@ -7,6 +7,7 @@ #define pr_fmt(fmt) "SCMI Notifications BASE - " fmt +#include #include #include @@ -219,8 +220,7 @@ scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph, } real_list_sz = t->rx.len - sizeof(u32); - calc_list_sz = (1 + (loop_num_ret - 1) / sizeof(u32)) * - sizeof(u32); + calc_list_sz = round_up(loop_num_ret, sizeof(u32)); if (calc_list_sz != real_list_sz) { dev_warn(dev, "Malformed reply - real_sz:%zd calc_sz:%u (loop_num_ret:%d)\n", From fe3da77f2f946e84d13e5183ae0fa223b968766b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:45 +0100 Subject: [PATCH 058/193] reset: gpio: remove unneeded OF-node put priv->rc.of_node is never set in reset core. Even if it were: tasking the reset-gpio driver with controlling the reference count of an OF node set up in reset core is a weird inversion of responsability. But it's also wrong in that the underlying device never actually gets removed so the node should not be put at all and especially not at driver detach. Remove the devres action. Reviewed-by: Philipp Zabel Signed-off-by: Bartosz Golaszewski Signed-off-by: Philipp Zabel --- drivers/reset/reset-gpio.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/reset/reset-gpio.c b/drivers/reset/reset-gpio.c index 0a1610d9e78a..ad5bfe27aaef 100644 --- a/drivers/reset/reset-gpio.c +++ b/drivers/reset/reset-gpio.c @@ -52,18 +52,12 @@ static int reset_gpio_of_xlate(struct reset_controller_dev *rcdev, return reset_spec->args[0]; } -static void reset_gpio_of_node_put(void *data) -{ - of_node_put(data); -} - static int reset_gpio_probe(struct auxiliary_device *adev, const struct auxiliary_device_id *id) { struct device *dev = &adev->dev; struct of_phandle_args *platdata = dev_get_platdata(dev); struct reset_gpio_priv *priv; - int ret; if (!platdata) return -EINVAL; @@ -83,10 +77,6 @@ static int reset_gpio_probe(struct auxiliary_device *adev, priv->rc.owner = THIS_MODULE; priv->rc.dev = dev; priv->rc.of_args = platdata; - ret = devm_add_action_or_reset(dev, reset_gpio_of_node_put, - priv->rc.of_node); - if (ret) - return ret; /* Cells to match GPIO specifier, but it's not really used */ priv->rc.of_reset_n_cells = 2; From a9b95ce36de4422761dc2a2afc01e1781801800c Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:46 +0100 Subject: [PATCH 059/193] reset: gpio: add a devlink between reset-gpio and its consumer The device that requests the reset control managed by the reset-gpio device is effectively its consumer but the devlink is only established between it and the GPIO controller exposing the reset pin. Add a devlink between the consumer of the reset control and its supplier. This will allow us to simplify the GPIOLIB code managing shared GPIOs when handling the corner case of reset-gpio and gpiolib-shared interacting. While at it and since we need to store the address of the auxiliary device: don't allocate memory for the device separately but fold it into struct reset_gpio_lookup instead. Reviewed-by: Philipp Zabel Signed-off-by: Bartosz Golaszewski Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 79 ++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 24 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index fceec45c8afc..3845e77a8d32 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -77,11 +77,13 @@ struct reset_control_array { * @of_args: phandle to the reset controller with all the args like GPIO number * @swnode: Software node containing the reference to the GPIO provider * @list: list entry for the reset_gpio_lookup_list + * @adev: Auxiliary device representing the reset controller */ struct reset_gpio_lookup { struct of_phandle_args of_args; struct fwnode_handle *swnode; struct list_head list; + struct auxiliary_device adev; }; static const char *rcdev_name(struct reset_controller_dev *rcdev) @@ -824,49 +826,72 @@ static void __reset_control_put_internal(struct reset_control *rstc) static void reset_gpio_aux_device_release(struct device *dev) { - struct auxiliary_device *adev = to_auxiliary_dev(dev); - kfree(adev); } -static int reset_add_gpio_aux_device(struct device *parent, - struct fwnode_handle *swnode, - int id, void *pdata) +static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev, + struct device *parent, int id) { - struct auxiliary_device *adev; + struct auxiliary_device *adev = &rgpio_dev->adev; int ret; - adev = kzalloc_obj(*adev); - if (!adev) - return -ENOMEM; - adev->id = id; adev->name = "gpio"; adev->dev.parent = parent; - adev->dev.platform_data = pdata; + adev->dev.platform_data = &rgpio_dev->of_args; adev->dev.release = reset_gpio_aux_device_release; - device_set_node(&adev->dev, swnode); + device_set_node(&adev->dev, rgpio_dev->swnode); ret = auxiliary_device_init(adev); - if (ret) { - kfree(adev); + if (ret) return ret; - } ret = __auxiliary_device_add(adev, "reset"); if (ret) { auxiliary_device_uninit(adev); - kfree(adev); return ret; } - return ret; + return 0; +} + +static void reset_gpio_add_devlink(struct device_node *np, + struct reset_gpio_lookup *rgpio_dev) +{ + struct device *consumer; + + /* + * We must use get_dev_from_fwnode() and not of_find_device_by_node() + * because the latter only considers the platform bus while we want to + * get consumers of any kind that can be associated with firmware + * nodes: auxiliary, soundwire, etc. + */ + consumer = get_dev_from_fwnode(of_fwnode_handle(np)); + if (consumer) { + if (!device_link_add(consumer, &rgpio_dev->adev.dev, + DL_FLAG_AUTOREMOVE_CONSUMER)) + pr_warn("Failed to create a device link between reset-gpio and its consumer"); + + put_device(consumer); + } + /* + * else { } + * + * TODO: If ever there's a case where we need to support shared + * reset-gpios retrieved from a device node for which there's no + * device present yet, this is where we'd set up a notifier waiting + * for the device to appear in the system. This would be a lot of code + * that would go unused for now so let's cross that bridge when and if + * we get there. + */ } /* - * @args: phandle to the GPIO provider with all the args like GPIO number + * @np: OF-node associated with the consumer + * @args: phandle to the GPIO provider with all the args like GPIO number */ -static int __reset_add_reset_gpio_device(const struct of_phandle_args *args) +static int __reset_add_reset_gpio_device(struct device_node *np, + const struct of_phandle_args *args) { struct property_entry properties[3] = { }; unsigned int offset, of_flags, lflags; @@ -916,8 +941,14 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args) list_for_each_entry(rgpio_dev, &reset_gpio_lookup_list, list) { if (args->np == rgpio_dev->of_args.np) { - if (of_phandle_args_equal(args, &rgpio_dev->of_args)) - return 0; /* Already on the list, done */ + if (of_phandle_args_equal(args, &rgpio_dev->of_args)) { + /* + * Already on the list, create the device link + * and stop here. + */ + reset_gpio_add_devlink(np, rgpio_dev); + return 0; + } } } @@ -951,11 +982,11 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args) goto err_put_of_node; } - ret = reset_add_gpio_aux_device(parent, rgpio_dev->swnode, id, - &rgpio_dev->of_args); + ret = reset_create_gpio_aux_device(rgpio_dev, parent, id); if (ret) goto err_del_swnode; + reset_gpio_add_devlink(np, rgpio_dev); list_add(&rgpio_dev->list, &reset_gpio_lookup_list); return 0; @@ -1035,7 +1066,7 @@ __of_reset_control_get(struct device_node *node, const char *id, int index, gpio_fallback = true; - ret = __reset_add_reset_gpio_device(&args); + ret = __reset_add_reset_gpio_device(node, &args); if (ret) { rstc = ERR_PTR(ret); goto out_put; From ad9d28e68f4f9d15b9bde15e1ab79a4f85eff60e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:47 +0100 Subject: [PATCH 060/193] reset: gpio: simplify fallback device matching The of_args field of struct reset_controller_dev was introduced to allow the reset-gpio driver to pass the phandle arguments back to reset core. The thing is: it doesn't even have to do it. The core sets the platform data of the auxiliary device *AND* has access to it later on during the lookup. This means the field is unneeded and all can happen entirely in reset core. Remove the field from the public header and don't set it in reset-gpio.c. Retrieve the platform data in reset core when needed instead. Reviewed-by: Philipp Zabel Signed-off-by: Bartosz Golaszewski Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 15 ++++++--------- drivers/reset/reset-gpio.c | 5 ----- include/linux/reset-controller.h | 4 ---- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 3845e77a8d32..954df36a242e 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -94,9 +94,6 @@ static const char *rcdev_name(struct reset_controller_dev *rcdev) if (rcdev->of_node) return rcdev->of_node->full_name; - if (rcdev->of_args) - return rcdev->of_args->np->full_name; - return NULL; } @@ -125,9 +122,6 @@ static int of_reset_simple_xlate(struct reset_controller_dev *rcdev, */ int reset_controller_register(struct reset_controller_dev *rcdev) { - if (rcdev->of_node && rcdev->of_args) - return -EINVAL; - if (!rcdev->of_xlate) { rcdev->of_reset_n_cells = 1; rcdev->of_xlate = of_reset_simple_xlate; @@ -1006,13 +1000,16 @@ static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_a bool gpio_fallback) { struct reset_controller_dev *rcdev; + struct of_phandle_args *rc_args; lockdep_assert_held(&reset_list_mutex); list_for_each_entry(rcdev, &reset_controller_list, list) { - if (gpio_fallback) { - if (rcdev->of_args && of_phandle_args_equal(args, - rcdev->of_args)) + if (gpio_fallback && rcdev->dev && + device_is_compatible(rcdev->dev, "reset-gpio")) { + rc_args = dev_get_platdata(rcdev->dev); + + if (of_phandle_args_equal(args, rc_args)) return rcdev; } else { if (args->np == rcdev->of_node) diff --git a/drivers/reset/reset-gpio.c b/drivers/reset/reset-gpio.c index ad5bfe27aaef..6e1c4f990bc0 100644 --- a/drivers/reset/reset-gpio.c +++ b/drivers/reset/reset-gpio.c @@ -56,12 +56,8 @@ static int reset_gpio_probe(struct auxiliary_device *adev, const struct auxiliary_device_id *id) { struct device *dev = &adev->dev; - struct of_phandle_args *platdata = dev_get_platdata(dev); struct reset_gpio_priv *priv; - if (!platdata) - return -EINVAL; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -76,7 +72,6 @@ static int reset_gpio_probe(struct auxiliary_device *adev, priv->rc.ops = &reset_gpio_ops; priv->rc.owner = THIS_MODULE; priv->rc.dev = dev; - priv->rc.of_args = platdata; /* Cells to match GPIO specifier, but it's not really used */ priv->rc.of_reset_n_cells = 2; diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h index 46514cb1b9e0..aa95b460fdf8 100644 --- a/include/linux/reset-controller.h +++ b/include/linux/reset-controller.h @@ -35,9 +35,6 @@ struct of_phandle_args; * @reset_control_head: head of internal list of requested reset controls * @dev: corresponding driver model device struct * @of_node: corresponding device tree node as phandle target - * @of_args: for reset-gpios controllers: corresponding phandle args with - * of_node and GPIO number complementing of_node; either this or - * of_node should be present * @of_reset_n_cells: number of cells in reset line specifiers * @of_xlate: translation function to translate from specifier as found in the * device tree to id as given to the reset control ops, defaults @@ -51,7 +48,6 @@ struct reset_controller_dev { struct list_head reset_control_head; struct device *dev; struct device_node *of_node; - const struct of_phandle_args *of_args; int of_reset_n_cells; int (*of_xlate)(struct reset_controller_dev *rcdev, const struct of_phandle_args *reset_spec); From 1acd4663840849d3371ab8734b55cd184a2a5c5b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:48 +0100 Subject: [PATCH 061/193] reset: gpio: remove unneeded auxiliary_set_drvdata() There's no user of the driver data so don't needlessly assign it. Reviewed-by: Philipp Zabel Signed-off-by: Bartosz Golaszewski Signed-off-by: Philipp Zabel --- drivers/reset/reset-gpio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/reset/reset-gpio.c b/drivers/reset/reset-gpio.c index 6e1c4f990bc0..5044f809d0e5 100644 --- a/drivers/reset/reset-gpio.c +++ b/drivers/reset/reset-gpio.c @@ -62,8 +62,6 @@ static int reset_gpio_probe(struct auxiliary_device *adev, if (!priv) return -ENOMEM; - auxiliary_set_drvdata(adev, &priv->rc); - priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(priv->reset)) return dev_err_probe(dev, PTR_ERR(priv->reset), From 20adbf3b8f5c5787da29f8cdd7cfc4fa87854bd5 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:49 +0100 Subject: [PATCH 062/193] reset: warn on reset-gpio release While we implement an empty .release() callback for reset-gpio (driver core requires it), this function will never actually be called as nobody ever removes the device and the last reference is not dropped anywhere. This is by design - once created, the reset-gpio device stays in memory. Make the .release() callback emit a warning, should it ever be called due to a programming bug. Reviewed-by: Philipp Zabel Signed-off-by: Bartosz Golaszewski Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 954df36a242e..3fa0d49eb494 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -820,7 +820,7 @@ static void __reset_control_put_internal(struct reset_control *rstc) static void reset_gpio_aux_device_release(struct device *dev) { - + WARN(1, "reset-gpio device %s should never have been removed", dev_name(dev)); } static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev, From 6703784ab9a8039bd3f476db2643414c45690c68 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:50 +0100 Subject: [PATCH 063/193] reset: fold ida_alloc() into reset_create_gpio_aux_device() We don't need to know the IDA value outside of the function that creates the auxiliary reset-gpio device. Simplify error handling by folding it into reset_create_gpio_aux_device(). Signed-off-by: Bartosz Golaszewski Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 3fa0d49eb494..3b67e727c84e 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -824,10 +824,14 @@ static void reset_gpio_aux_device_release(struct device *dev) } static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev, - struct device *parent, int id) + struct device *parent) { struct auxiliary_device *adev = &rgpio_dev->adev; - int ret; + int ret, id; + + id = ida_alloc(&reset_gpio_ida, GFP_KERNEL); + if (id < 0) + return -ENOMEM; adev->id = id; adev->name = "gpio"; @@ -837,12 +841,15 @@ static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev, device_set_node(&adev->dev, rgpio_dev->swnode); ret = auxiliary_device_init(adev); - if (ret) + if (ret) { + ida_free(&reset_gpio_ida, id); return ret; + } ret = __auxiliary_device_add(adev, "reset"); if (ret) { auxiliary_device_uninit(adev); + ida_free(&reset_gpio_ida, id); return ret; } @@ -891,7 +898,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np, unsigned int offset, of_flags, lflags; struct reset_gpio_lookup *rgpio_dev; struct device *parent; - int id, ret, prop = 0; + int ret, prop = 0; /* * Currently only #gpio-cells=2 is supported with the meaning of: @@ -951,16 +958,10 @@ static int __reset_add_reset_gpio_device(struct device_node *np, properties[prop++] = PROPERTY_ENTRY_STRING("compatible", "reset-gpio"); properties[prop++] = PROPERTY_ENTRY_GPIO("reset-gpios", parent->fwnode, offset, lflags); - id = ida_alloc(&reset_gpio_ida, GFP_KERNEL); - if (id < 0) - return id; - /* Not freed on success, because it is persisent subsystem data. */ rgpio_dev = kzalloc_obj(*rgpio_dev); - if (!rgpio_dev) { - ret = -ENOMEM; - goto err_ida_free; - } + if (!rgpio_dev) + return -ENOMEM; rgpio_dev->of_args = *args; /* @@ -976,7 +977,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np, goto err_put_of_node; } - ret = reset_create_gpio_aux_device(rgpio_dev, parent, id); + ret = reset_create_gpio_aux_device(rgpio_dev, parent); if (ret) goto err_del_swnode; @@ -990,8 +991,6 @@ err_del_swnode: err_put_of_node: of_node_put(rgpio_dev->of_args.np); kfree(rgpio_dev); -err_ida_free: - ida_free(&reset_gpio_ida, id); return ret; } From 1f10008aff7190e300e93ed33a0eb2d236c0b87d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:51 +0100 Subject: [PATCH 064/193] reset: use lock guards in reset core Simplify the locking code in reset core by using lock guard from linux/cleanup.h. Reviewed-by: Philipp Zabel Signed-off-by: Bartosz Golaszewski Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 55 ++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 3b67e727c84e..2102093624aa 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -129,9 +129,9 @@ int reset_controller_register(struct reset_controller_dev *rcdev) INIT_LIST_HEAD(&rcdev->reset_control_head); - mutex_lock(&reset_list_mutex); + guard(mutex)(&reset_list_mutex); + list_add(&rcdev->list, &reset_controller_list); - mutex_unlock(&reset_list_mutex); return 0; } @@ -143,9 +143,9 @@ EXPORT_SYMBOL_GPL(reset_controller_register); */ void reset_controller_unregister(struct reset_controller_dev *rcdev) { - mutex_lock(&reset_list_mutex); + guard(mutex)(&reset_list_mutex); + list_del(&rcdev->list); - mutex_unlock(&reset_list_mutex); } EXPORT_SYMBOL_GPL(reset_controller_unregister); @@ -646,25 +646,20 @@ int reset_control_acquire(struct reset_control *rstc) if (reset_control_is_array(rstc)) return reset_control_array_acquire(rstc_to_array(rstc)); - mutex_lock(&reset_list_mutex); + guard(mutex)(&reset_list_mutex); - if (rstc->acquired) { - mutex_unlock(&reset_list_mutex); + if (rstc->acquired) return 0; - } list_for_each_entry(rc, &rstc->rcdev->reset_control_head, list) { if (rstc != rc && rstc->id == rc->id) { - if (rc->acquired) { - mutex_unlock(&reset_list_mutex); + if (rc->acquired) return -EBUSY; - } } } rstc->acquired = true; - mutex_unlock(&reset_list_mutex); return 0; } EXPORT_SYMBOL_GPL(reset_control_acquire); @@ -1064,27 +1059,28 @@ __of_reset_control_get(struct device_node *node, const char *id, int index, ret = __reset_add_reset_gpio_device(node, &args); if (ret) { - rstc = ERR_PTR(ret); - goto out_put; + of_node_put(args.np); + return ERR_PTR(ret); } } - mutex_lock(&reset_list_mutex); + guard(mutex)(&reset_list_mutex); + rcdev = __reset_find_rcdev(&args, gpio_fallback); if (!rcdev) { rstc = ERR_PTR(-EPROBE_DEFER); - goto out_unlock; + goto out_put; } if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) { rstc = ERR_PTR(-EINVAL); - goto out_unlock; + goto out_put; } rstc_id = rcdev->of_xlate(rcdev, &args); if (rstc_id < 0) { rstc = ERR_PTR(rstc_id); - goto out_unlock; + goto out_put; } flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL; @@ -1092,8 +1088,6 @@ __of_reset_control_get(struct device_node *node, const char *id, int index, /* reset_list_mutex also protects the rcdev's reset_control list */ rstc = __reset_control_get_internal(rcdev, rstc_id, flags); -out_unlock: - mutex_unlock(&reset_list_mutex); out_put: of_node_put(args.np); @@ -1135,10 +1129,11 @@ int __reset_control_bulk_get(struct device *dev, int num_rstcs, return 0; err: - mutex_lock(&reset_list_mutex); + guard(mutex)(&reset_list_mutex); + while (i--) __reset_control_put_internal(rstcs[i].rstc); - mutex_unlock(&reset_list_mutex); + return ret; } EXPORT_SYMBOL_GPL(__reset_control_bulk_get); @@ -1147,10 +1142,10 @@ static void reset_control_array_put(struct reset_control_array *resets) { int i; - mutex_lock(&reset_list_mutex); + guard(mutex)(&reset_list_mutex); + for (i = 0; i < resets->num_rstcs; i++) __reset_control_put_internal(resets->rstc[i]); - mutex_unlock(&reset_list_mutex); kfree(resets); } @@ -1168,9 +1163,9 @@ void reset_control_put(struct reset_control *rstc) return; } - mutex_lock(&reset_list_mutex); + guard(mutex)(&reset_list_mutex); + __reset_control_put_internal(rstc); - mutex_unlock(&reset_list_mutex); } EXPORT_SYMBOL_GPL(reset_control_put); @@ -1181,10 +1176,10 @@ EXPORT_SYMBOL_GPL(reset_control_put); */ void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs) { - mutex_lock(&reset_list_mutex); + guard(mutex)(&reset_list_mutex); + while (num_rstcs--) __reset_control_put_internal(rstcs[num_rstcs].rstc); - mutex_unlock(&reset_list_mutex); } EXPORT_SYMBOL_GPL(reset_control_bulk_put); @@ -1403,10 +1398,10 @@ of_reset_control_array_get(struct device_node *np, enum reset_control_flags flag return &resets->base; err_rst: - mutex_lock(&reset_list_mutex); + guard(mutex)(&reset_list_mutex); + while (--i >= 0) __reset_control_put_internal(resets->rstc[i]); - mutex_unlock(&reset_list_mutex); kfree(resets); From 78ebbff6d1a05ffc2062d90231b4720618a57147 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:52 +0100 Subject: [PATCH 065/193] reset: handle removing supplier before consumers Except for the reset-gpio, all reset drivers use device tree - and as such - benefit from the device links set up by driver core. This means, that no reset supplier will be unbound before all its consumers have been. For this reason, nobody bothered making the reset core resiliant to the object life-time issues that are plagueing the kernel. In this case: reset control handles referencing the reset provider device with no serialization or NULL-pointer checking. We now want to make the reset core fwnode-agnostic but before we do, we must make sure it can survive unbinding of suppliers with consumers still holding reset control handles. To that end: use SRCU to protect the rcdev pointer inside struct reset_control. We protect all sections using the pointer with SRCU read-only critical sections and synchronize SRCU after every modification of the pointer. This is in line with what the GPIO subsystem does and what the proposed revocable API tries to generalize. When and if the latter makes its way into the kernel, reset core could potentially also be generalized to use it. Signed-off-by: Bartosz Golaszewski Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 108 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 17 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 2102093624aa..e6c12fbebca9 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -23,6 +23,7 @@ #include #include #include +#include static DEFINE_MUTEX(reset_list_mutex); static LIST_HEAD(reset_controller_list); @@ -36,6 +37,7 @@ static DEFINE_IDA(reset_gpio_ida); * struct reset_control - a reset control * @rcdev: a pointer to the reset controller device * this reset control belongs to + * @srcu: protects the rcdev pointer from removal during consumer access * @list: list entry for the rcdev's reset controller list * @id: ID of the reset controller in the reset * controller device @@ -49,7 +51,8 @@ static DEFINE_IDA(reset_gpio_ida); * will be either 0 or 1. */ struct reset_control { - struct reset_controller_dev *rcdev; + struct reset_controller_dev __rcu *rcdev; + struct srcu_struct srcu; struct list_head list; unsigned int id; struct kref refcnt; @@ -137,15 +140,35 @@ int reset_controller_register(struct reset_controller_dev *rcdev) } EXPORT_SYMBOL_GPL(reset_controller_register); +static void reset_controller_remove(struct reset_controller_dev *rcdev, + struct reset_control *rstc) +{ + list_del(&rstc->list); + module_put(rcdev->owner); + put_device(rcdev->dev); +} + /** * reset_controller_unregister - unregister a reset controller device * @rcdev: a pointer to the reset controller device */ void reset_controller_unregister(struct reset_controller_dev *rcdev) { + struct reset_control *rstc, *pos; + guard(mutex)(&reset_list_mutex); list_del(&rcdev->list); + + /* + * Numb but don't free the remaining reset control handles that are + * still held by consumers. + */ + list_for_each_entry_safe(rstc, pos, &rcdev->reset_control_head, list) { + rcu_assign_pointer(rstc->rcdev, NULL); + synchronize_srcu(&rstc->srcu); + reset_controller_remove(rcdev, rstc); + } } EXPORT_SYMBOL_GPL(reset_controller_unregister); @@ -322,6 +345,7 @@ static inline bool reset_control_is_array(struct reset_control *rstc) */ int reset_control_reset(struct reset_control *rstc) { + struct reset_controller_dev *rcdev; int ret; if (!rstc) @@ -333,7 +357,13 @@ int reset_control_reset(struct reset_control *rstc) if (reset_control_is_array(rstc)) return reset_control_array_reset(rstc_to_array(rstc)); - if (!rstc->rcdev->ops->reset) + guard(srcu)(&rstc->srcu); + + rcdev = srcu_dereference(rstc->rcdev, &rstc->srcu); + if (!rcdev) + return -ENODEV; + + if (!rcdev->ops->reset) return -ENOTSUPP; if (rstc->shared) { @@ -347,7 +377,7 @@ int reset_control_reset(struct reset_control *rstc) return -EPERM; } - ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id); + ret = rcdev->ops->reset(rcdev, rstc->id); if (rstc->shared && ret) atomic_dec(&rstc->triggered_count); @@ -437,6 +467,8 @@ EXPORT_SYMBOL_GPL(reset_control_rearm); */ int reset_control_assert(struct reset_control *rstc) { + struct reset_controller_dev *rcdev; + if (!rstc) return 0; @@ -446,6 +478,12 @@ int reset_control_assert(struct reset_control *rstc) if (reset_control_is_array(rstc)) return reset_control_array_assert(rstc_to_array(rstc)); + guard(srcu)(&rstc->srcu); + + rcdev = srcu_dereference(rstc->rcdev, &rstc->srcu); + if (!rcdev) + return -ENODEV; + if (rstc->shared) { if (WARN_ON(atomic_read(&rstc->triggered_count) != 0)) return -EINVAL; @@ -460,7 +498,7 @@ int reset_control_assert(struct reset_control *rstc) * Shared reset controls allow the reset line to be in any state * after this call, so doing nothing is a valid option. */ - if (!rstc->rcdev->ops->assert) + if (!rcdev->ops->assert) return 0; } else { /* @@ -468,17 +506,17 @@ int reset_control_assert(struct reset_control *rstc) * is no way to guarantee that the reset line is asserted after * this call. */ - if (!rstc->rcdev->ops->assert) + if (!rcdev->ops->assert) return -ENOTSUPP; if (!rstc->acquired) { WARN(1, "reset %s (ID: %u) is not acquired\n", - rcdev_name(rstc->rcdev), rstc->id); + rcdev_name(rcdev), rstc->id); return -EPERM; } } - return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); + return rcdev->ops->assert(rcdev, rstc->id); } EXPORT_SYMBOL_GPL(reset_control_assert); @@ -525,6 +563,8 @@ EXPORT_SYMBOL_GPL(reset_control_bulk_assert); */ int reset_control_deassert(struct reset_control *rstc) { + struct reset_controller_dev *rcdev; + if (!rstc) return 0; @@ -534,6 +574,12 @@ int reset_control_deassert(struct reset_control *rstc) if (reset_control_is_array(rstc)) return reset_control_array_deassert(rstc_to_array(rstc)); + guard(srcu)(&rstc->srcu); + + rcdev = srcu_dereference(rstc->rcdev, &rstc->srcu); + if (!rcdev) + return -ENODEV; + if (rstc->shared) { if (WARN_ON(atomic_read(&rstc->triggered_count) != 0)) return -EINVAL; @@ -543,7 +589,7 @@ int reset_control_deassert(struct reset_control *rstc) } else { if (!rstc->acquired) { WARN(1, "reset %s (ID: %u) is not acquired\n", - rcdev_name(rstc->rcdev), rstc->id); + rcdev_name(rcdev), rstc->id); return -EPERM; } } @@ -555,10 +601,10 @@ int reset_control_deassert(struct reset_control *rstc) * case, the reset controller driver should implement .deassert() and * return -ENOTSUPP. */ - if (!rstc->rcdev->ops->deassert) + if (!rcdev->ops->deassert) return 0; - return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id); + return rcdev->ops->deassert(rcdev, rstc->id); } EXPORT_SYMBOL_GPL(reset_control_deassert); @@ -600,14 +646,22 @@ EXPORT_SYMBOL_GPL(reset_control_bulk_deassert); */ int reset_control_status(struct reset_control *rstc) { + struct reset_controller_dev *rcdev; + if (!rstc) return 0; if (WARN_ON(IS_ERR(rstc)) || reset_control_is_array(rstc)) return -EINVAL; - if (rstc->rcdev->ops->status) - return rstc->rcdev->ops->status(rstc->rcdev, rstc->id); + guard(srcu)(&rstc->srcu); + + rcdev = srcu_dereference(rstc->rcdev, &rstc->srcu); + if (!rcdev) + return -ENODEV; + + if (rcdev->ops->status) + return rcdev->ops->status(rcdev, rstc->id); return -ENOTSUPP; } @@ -635,6 +689,7 @@ EXPORT_SYMBOL_GPL(reset_control_status); */ int reset_control_acquire(struct reset_control *rstc) { + struct reset_controller_dev *rcdev; struct reset_control *rc; if (!rstc) @@ -651,7 +706,13 @@ int reset_control_acquire(struct reset_control *rstc) if (rstc->acquired) return 0; - list_for_each_entry(rc, &rstc->rcdev->reset_control_head, list) { + guard(srcu)(&rstc->srcu); + + rcdev = srcu_dereference(rstc->rcdev, &rstc->srcu); + if (!rcdev) + return -ENODEV; + + list_for_each_entry(rc, &rcdev->reset_control_head, list) { if (rstc != rc && rstc->id == rc->id) { if (rc->acquired) return -EBUSY; @@ -743,6 +804,7 @@ __reset_control_get_internal(struct reset_controller_dev *rcdev, bool shared = flags & RESET_CONTROL_FLAGS_BIT_SHARED; bool acquired = flags & RESET_CONTROL_FLAGS_BIT_ACQUIRED; struct reset_control *rstc; + int ret; lockdep_assert_held(&reset_list_mutex); @@ -773,12 +835,19 @@ __reset_control_get_internal(struct reset_controller_dev *rcdev, if (!rstc) return ERR_PTR(-ENOMEM); + ret = init_srcu_struct(&rstc->srcu); + if (ret) { + kfree(rstc); + return ERR_PTR(ret); + } + if (!try_module_get(rcdev->owner)) { + cleanup_srcu_struct(&rstc->srcu); kfree(rstc); return ERR_PTR(-ENODEV); } - rstc->rcdev = rcdev; + rcu_assign_pointer(rstc->rcdev, rcdev); list_add(&rstc->list, &rcdev->reset_control_head); rstc->id = index; kref_init(&rstc->refcnt); @@ -793,13 +862,18 @@ static void __reset_control_release(struct kref *kref) { struct reset_control *rstc = container_of(kref, struct reset_control, refcnt); + struct reset_controller_dev *rcdev; lockdep_assert_held(&reset_list_mutex); - module_put(rstc->rcdev->owner); + scoped_guard(srcu, &rstc->srcu) { + rcdev = rcu_replace_pointer(rstc->rcdev, NULL, true); + if (rcdev) + reset_controller_remove(rcdev, rstc); + } - list_del(&rstc->list); - put_device(rstc->rcdev->dev); + synchronize_srcu(&rstc->srcu); + cleanup_srcu_struct(&rstc->srcu); kfree(rstc); } From 44a0acb2caca3bfd0ca459fbf0b19be75f1819c0 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:53 +0100 Subject: [PATCH 066/193] reset: protect struct reset_controller_dev with its own mutex Currently we use a single, global mutex - misleadingly names reset_list_mutex - to protect the global list of reset devices, per-controller list of reset control handles and also internal fields of struct reset_control. Locking can be made a lot more fine-grained if we use a separate mutex for serializing operations on the list AND accessing the reset controller device. Signed-off-by: Bartosz Golaszewski Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 44 ++++++++++++++++++++------------ include/linux/reset-controller.h | 3 +++ 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index e6c12fbebca9..acd9d10b1ceb 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -131,6 +131,7 @@ int reset_controller_register(struct reset_controller_dev *rcdev) } INIT_LIST_HEAD(&rcdev->reset_control_head); + mutex_init(&rcdev->lock); guard(mutex)(&reset_list_mutex); @@ -143,6 +144,8 @@ EXPORT_SYMBOL_GPL(reset_controller_register); static void reset_controller_remove(struct reset_controller_dev *rcdev, struct reset_control *rstc) { + lockdep_assert_held(&rcdev->lock); + list_del(&rstc->list); module_put(rcdev->owner); put_device(rcdev->dev); @@ -156,19 +159,22 @@ void reset_controller_unregister(struct reset_controller_dev *rcdev) { struct reset_control *rstc, *pos; - guard(mutex)(&reset_list_mutex); + scoped_guard(mutex, &reset_list_mutex) + list_del(&rcdev->list); - list_del(&rcdev->list); - - /* - * Numb but don't free the remaining reset control handles that are - * still held by consumers. - */ - list_for_each_entry_safe(rstc, pos, &rcdev->reset_control_head, list) { - rcu_assign_pointer(rstc->rcdev, NULL); - synchronize_srcu(&rstc->srcu); - reset_controller_remove(rcdev, rstc); + scoped_guard(mutex, &rcdev->lock) { + /* + * Numb but don't free the remaining reset control handles that are + * still held by consumers. + */ + list_for_each_entry_safe(rstc, pos, &rcdev->reset_control_head, list) { + rcu_assign_pointer(rstc->rcdev, NULL); + synchronize_srcu(&rstc->srcu); + reset_controller_remove(rcdev, rstc); + } } + + mutex_destroy(&rcdev->lock); } EXPORT_SYMBOL_GPL(reset_controller_unregister); @@ -712,10 +718,12 @@ int reset_control_acquire(struct reset_control *rstc) if (!rcdev) return -ENODEV; - list_for_each_entry(rc, &rcdev->reset_control_head, list) { - if (rstc != rc && rstc->id == rc->id) { - if (rc->acquired) - return -EBUSY; + scoped_guard(mutex, &rcdev->lock) { + list_for_each_entry(rc, &rcdev->reset_control_head, list) { + if (rstc != rc && rstc->id == rc->id) { + if (rc->acquired) + return -EBUSY; + } } } @@ -806,7 +814,7 @@ __reset_control_get_internal(struct reset_controller_dev *rcdev, struct reset_control *rstc; int ret; - lockdep_assert_held(&reset_list_mutex); + lockdep_assert_held(&rcdev->lock); /* Expect callers to filter out OPTIONAL and DEASSERTED bits */ if (WARN_ON(flags & ~(RESET_CONTROL_FLAGS_BIT_SHARED | @@ -868,8 +876,10 @@ static void __reset_control_release(struct kref *kref) scoped_guard(srcu, &rstc->srcu) { rcdev = rcu_replace_pointer(rstc->rcdev, NULL, true); - if (rcdev) + if (rcdev) { + guard(mutex)(&rcdev->lock); reset_controller_remove(rcdev, rstc); + } } synchronize_srcu(&rstc->srcu); diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h index aa95b460fdf8..185d2a9bd7cd 100644 --- a/include/linux/reset-controller.h +++ b/include/linux/reset-controller.h @@ -3,6 +3,7 @@ #define _LINUX_RESET_CONTROLLER_H_ #include +#include struct reset_controller_dev; @@ -40,6 +41,7 @@ struct of_phandle_args; * device tree to id as given to the reset control ops, defaults * to :c:func:`of_reset_simple_xlate`. * @nr_resets: number of reset controls in this reset controller device + * @lock: protects the reset control list from concurrent access */ struct reset_controller_dev { const struct reset_control_ops *ops; @@ -52,6 +54,7 @@ struct reset_controller_dev { int (*of_xlate)(struct reset_controller_dev *rcdev, const struct of_phandle_args *reset_spec); unsigned int nr_resets; + struct mutex lock; }; #if IS_ENABLED(CONFIG_RESET_CONTROLLER) From 8c91302a29bc1b710c7a164d4b81b5bb432f4eb5 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:54 +0100 Subject: [PATCH 067/193] reset: protect struct reset_control with its own mutex Currently we use a single, global mutex - misleadingly names reset_list_mutex - to protect the global list of reset devices, per-controller list of reset control handles and also internal fields of struct reset_control. Locking can be made a lot more fine-grained if we use a separate mutex for serializing operations on the list AND accessing the reset control handle. Signed-off-by: Bartosz Golaszewski Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 68 +++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index acd9d10b1ceb..edb672ad7e40 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -49,6 +49,7 @@ static DEFINE_IDA(reset_gpio_ida); * @triggered_count: Number of times this reset line has been reset. Currently * only used for shared resets, which means that the value * will be either 0 or 1. + * @lock: serializes the internals of reset_control_acquire() */ struct reset_control { struct reset_controller_dev __rcu *rcdev; @@ -61,6 +62,7 @@ struct reset_control { bool array; atomic_t deassert_count; atomic_t triggered_count; + struct mutex lock; }; /** @@ -707,7 +709,7 @@ int reset_control_acquire(struct reset_control *rstc) if (reset_control_is_array(rstc)) return reset_control_array_acquire(rstc_to_array(rstc)); - guard(mutex)(&reset_list_mutex); + guard(mutex)(&rstc->lock); if (rstc->acquired) return 0; @@ -859,6 +861,7 @@ __reset_control_get_internal(struct reset_controller_dev *rcdev, list_add(&rstc->list, &rcdev->reset_control_head); rstc->id = index; kref_init(&rstc->refcnt); + mutex_init(&rstc->lock); rstc->acquired = acquired; rstc->shared = shared; get_device(rcdev->dev); @@ -872,29 +875,40 @@ static void __reset_control_release(struct kref *kref) refcnt); struct reset_controller_dev *rcdev; - lockdep_assert_held(&reset_list_mutex); + lockdep_assert_held(&rstc->srcu); - scoped_guard(srcu, &rstc->srcu) { - rcdev = rcu_replace_pointer(rstc->rcdev, NULL, true); - if (rcdev) { - guard(mutex)(&rcdev->lock); - reset_controller_remove(rcdev, rstc); - } + rcdev = rcu_replace_pointer(rstc->rcdev, NULL, true); + if (rcdev) { + lockdep_assert_held(&rcdev->lock); + reset_controller_remove(rcdev, rstc); } - synchronize_srcu(&rstc->srcu); - cleanup_srcu_struct(&rstc->srcu); - kfree(rstc); + mutex_destroy(&rstc->lock); } -static void __reset_control_put_internal(struct reset_control *rstc) +static void reset_control_put_internal(struct reset_control *rstc) { - lockdep_assert_held(&reset_list_mutex); + struct reset_controller_dev *rcdev; + int ret = 0; if (IS_ERR_OR_NULL(rstc)) return; - kref_put(&rstc->refcnt, __reset_control_release); + scoped_guard(srcu, &rstc->srcu) { + rcdev = srcu_dereference(rstc->rcdev, &rstc->srcu); + if (!rcdev) + /* Already released. */ + return; + + guard(mutex)(&rcdev->lock); + ret = kref_put(&rstc->refcnt, __reset_control_release); + } + + if (ret) { + synchronize_srcu(&rstc->srcu); + cleanup_srcu_struct(&rstc->srcu); + kfree(rstc); + } } static void reset_gpio_aux_device_release(struct device *dev) @@ -1104,7 +1118,7 @@ __of_reset_control_get(struct device_node *node, const char *id, int index, { bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; bool gpio_fallback = false; - struct reset_control *rstc; + struct reset_control *rstc = ERR_PTR(-EINVAL); struct reset_controller_dev *rcdev; struct of_phandle_args args; int rstc_id; @@ -1169,8 +1183,8 @@ __of_reset_control_get(struct device_node *node, const char *id, int index, flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL; - /* reset_list_mutex also protects the rcdev's reset_control list */ - rstc = __reset_control_get_internal(rcdev, rstc_id, flags); + scoped_guard(mutex, &rcdev->lock) + rstc = __reset_control_get_internal(rcdev, rstc_id, flags); out_put: of_node_put(args.np); @@ -1213,10 +1227,8 @@ int __reset_control_bulk_get(struct device *dev, int num_rstcs, return 0; err: - guard(mutex)(&reset_list_mutex); - while (i--) - __reset_control_put_internal(rstcs[i].rstc); + reset_control_put_internal(rstcs[i].rstc); return ret; } @@ -1226,10 +1238,8 @@ static void reset_control_array_put(struct reset_control_array *resets) { int i; - guard(mutex)(&reset_list_mutex); - for (i = 0; i < resets->num_rstcs; i++) - __reset_control_put_internal(resets->rstc[i]); + reset_control_put_internal(resets->rstc[i]); kfree(resets); } @@ -1247,9 +1257,7 @@ void reset_control_put(struct reset_control *rstc) return; } - guard(mutex)(&reset_list_mutex); - - __reset_control_put_internal(rstc); + reset_control_put_internal(rstc); } EXPORT_SYMBOL_GPL(reset_control_put); @@ -1260,10 +1268,8 @@ EXPORT_SYMBOL_GPL(reset_control_put); */ void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs) { - guard(mutex)(&reset_list_mutex); - while (num_rstcs--) - __reset_control_put_internal(rstcs[num_rstcs].rstc); + reset_control_put_internal(rstcs[num_rstcs].rstc); } EXPORT_SYMBOL_GPL(reset_control_bulk_put); @@ -1482,10 +1488,8 @@ of_reset_control_array_get(struct device_node *np, enum reset_control_flags flag return &resets->base; err_rst: - guard(mutex)(&reset_list_mutex); - while (--i >= 0) - __reset_control_put_internal(resets->rstc[i]); + reset_control_put_internal(resets->rstc[i]); kfree(resets); From 9d52054a4fc3d6f95f4aa81d5355505c98a3e4ee Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:55 +0100 Subject: [PATCH 068/193] reset: convert of_reset_control_get_count() to using firmware nodes Start the conversion of reset core to using firmware nodes by reworking of_reset_control_get_count(). Unfortunately there is no fwnode-based alternative to of_count_phandle_with_args() so we have to hand-code it. Reviewed-by: Philipp Zabel Signed-off-by: Bartosz Golaszewski Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index edb672ad7e40..f1b644a86ad0 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -1430,21 +1432,35 @@ EXPORT_SYMBOL_GPL(__device_reset); */ /** - * of_reset_control_get_count - Count number of resets available with a device + * fwnode_reset_control_get_count - Count number of resets available with a device * - * @node: device node that contains 'resets'. + * @fwnode: firmware node that contains 'resets'. * * Returns positive reset count on success, or error number on failure and * on count being zero. */ -static int of_reset_control_get_count(struct device_node *node) +static int fwnode_reset_control_get_count(struct fwnode_handle *fwnode) { - int count; + struct fwnode_reference_args args; + int count = 0, ret; - if (!node) + if (!fwnode) return -EINVAL; - count = of_count_phandle_with_args(node, "resets", "#reset-cells"); + for (;;) { + ret = fwnode_property_get_reference_args(fwnode, "resets", "#reset-cells", + 0, count, &args); + if (ret) { + if (ret == -ENOENT) + break; + + return ret; + } + + fwnode_handle_put(args.fwnode); + count++; + } + if (count == 0) count = -ENOENT; @@ -1468,7 +1484,7 @@ of_reset_control_array_get(struct device_node *np, enum reset_control_flags flag struct reset_control *rstc; int num, i; - num = of_reset_control_get_count(np); + num = fwnode_reset_control_get_count(of_fwnode_handle(np)); if (num < 0) return optional ? NULL : ERR_PTR(num); @@ -1542,8 +1558,10 @@ EXPORT_SYMBOL_GPL(devm_reset_control_array_get); */ int reset_control_get_count(struct device *dev) { - if (dev->of_node) - return of_reset_control_get_count(dev->of_node); + struct fwnode_handle *fwnode = dev_fwnode(dev); + + if (fwnode) + return fwnode_reset_control_get_count(fwnode); return -ENOENT; } From ba8dbbb14b7e6734afbb5ba37d0679831aa3d590 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:56 +0100 Subject: [PATCH 069/193] reset: convert the core API to using firmware nodes In order to simplify the commit converting the internals of reset core to using firmware nodes, first convert the user-facing API. Modify the signature of the core consumer functions but leave the specialized wrappers as is to avoid modifying users for now. No functional change intended. Reviewed-by: Philipp Zabel Signed-off-by: Bartosz Golaszewski Signed-off-by: Philipp Zabel --- Documentation/driver-api/reset.rst | 1 - drivers/reset/core.c | 33 ++++++++++++----------- include/linux/reset.h | 43 +++++++++++++++++++----------- 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/Documentation/driver-api/reset.rst b/Documentation/driver-api/reset.rst index f773100daaa4..7a6571849664 100644 --- a/Documentation/driver-api/reset.rst +++ b/Documentation/driver-api/reset.rst @@ -198,7 +198,6 @@ query the reset line status using reset_control_status(). reset_control_rearm reset_control_put of_reset_control_get_count - of_reset_control_array_get devm_reset_control_array_get reset_control_get_count diff --git a/drivers/reset/core.c b/drivers/reset/core.c index f1b644a86ad0..0da5079ea9db 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -1061,7 +1061,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np, rgpio_dev->of_args = *args; /* * We keep the device_node reference, but of_args.np is put at the end - * of __of_reset_control_get(), so get it one more time. + * of __fwnode_reset_control_get(), so get it one more time. * Hold reference as long as rgpio_dev memory is valid. */ of_node_get(rgpio_dev->of_args.np); @@ -1115,18 +1115,19 @@ static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_a } struct reset_control * -__of_reset_control_get(struct device_node *node, const char *id, int index, - enum reset_control_flags flags) +__fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int index, + enum reset_control_flags flags) { bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; bool gpio_fallback = false; + struct device_node *node = to_of_node(fwnode); struct reset_control *rstc = ERR_PTR(-EINVAL); struct reset_controller_dev *rcdev; struct of_phandle_args args; int rstc_id; int ret; - if (!node) + if (!fwnode) return ERR_PTR(-EINVAL); if (id) { @@ -1193,7 +1194,7 @@ out_put: return rstc; } -EXPORT_SYMBOL_GPL(__of_reset_control_get); +EXPORT_SYMBOL_GPL(__fwnode_reset_control_get); struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, enum reset_control_flags flags) @@ -1201,12 +1202,13 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id, bool shared = flags & RESET_CONTROL_FLAGS_BIT_SHARED; bool acquired = flags & RESET_CONTROL_FLAGS_BIT_ACQUIRED; bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; + struct fwnode_handle *fwnode = dev_fwnode(dev); if (WARN_ON(shared && acquired)) return ERR_PTR(-EINVAL); - if (dev->of_node) - return __of_reset_control_get(dev->of_node, id, index, flags); + if (fwnode) + return __fwnode_reset_control_get(fwnode, id, index, flags); return optional ? NULL : ERR_PTR(-ENOENT); } @@ -1468,23 +1470,24 @@ static int fwnode_reset_control_get_count(struct fwnode_handle *fwnode) } /** - * of_reset_control_array_get - Get a list of reset controls using - * device node. + * fwnode_reset_control_array_get - Get a list of reset controls using + * a firmware node. * - * @np: device node for the device that requests the reset controls array + * @fwnode: firmware node for the device that requests the reset controls array * @flags: whether reset controls are shared, optional, acquired * * Returns pointer to allocated reset_control on success or error on failure */ struct reset_control * -of_reset_control_array_get(struct device_node *np, enum reset_control_flags flags) +fwnode_reset_control_array_get(struct fwnode_handle *fwnode, + enum reset_control_flags flags) { bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; struct reset_control_array *resets; struct reset_control *rstc; int num, i; - num = fwnode_reset_control_get_count(of_fwnode_handle(np)); + num = fwnode_reset_control_get_count(fwnode); if (num < 0) return optional ? NULL : ERR_PTR(num); @@ -1494,7 +1497,7 @@ of_reset_control_array_get(struct device_node *np, enum reset_control_flags flag resets->num_rstcs = num; for (i = 0; i < num; i++) { - rstc = __of_reset_control_get(np, NULL, i, flags); + rstc = __fwnode_reset_control_get(fwnode, NULL, i, flags); if (IS_ERR(rstc)) goto err_rst; resets->rstc[i] = rstc; @@ -1511,7 +1514,7 @@ err_rst: return rstc; } -EXPORT_SYMBOL_GPL(of_reset_control_array_get); +EXPORT_SYMBOL_GPL(fwnode_reset_control_array_get); /** * devm_reset_control_array_get - Resource managed reset control array get @@ -1535,7 +1538,7 @@ devm_reset_control_array_get(struct device *dev, enum reset_control_flags flags) if (!ptr) return ERR_PTR(-ENOMEM); - rstc = of_reset_control_array_get(dev->of_node, flags); + rstc = fwnode_reset_control_array_get(dev_fwnode(dev), flags); if (IS_ERR_OR_NULL(rstc)) { devres_free(ptr); return rstc; diff --git a/include/linux/reset.h b/include/linux/reset.h index 44f9e3415f92..9c391cf0c822 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -5,10 +5,12 @@ #include #include #include +#include #include struct device; struct device_node; +struct fwnode_handle; struct reset_control; /** @@ -84,7 +86,7 @@ int reset_control_bulk_deassert(int num_rstcs, struct reset_control_bulk_data *r int reset_control_bulk_acquire(int num_rstcs, struct reset_control_bulk_data *rstcs); void reset_control_bulk_release(int num_rstcs, struct reset_control_bulk_data *rstcs); -struct reset_control *__of_reset_control_get(struct device_node *node, +struct reset_control *__fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int index, enum reset_control_flags flags); struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, enum reset_control_flags flags); @@ -103,7 +105,8 @@ int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs, struct reset_control *devm_reset_control_array_get(struct device *dev, enum reset_control_flags flags); -struct reset_control *of_reset_control_array_get(struct device_node *np, enum reset_control_flags); +struct reset_control *fwnode_reset_control_array_get(struct fwnode_handle *fwnode, + enum reset_control_flags); int reset_control_get_count(struct device *dev); @@ -152,8 +155,8 @@ static inline int __device_reset(struct device *dev, bool optional) return optional ? 0 : -ENOTSUPP; } -static inline struct reset_control *__of_reset_control_get( - struct device_node *node, +static inline struct reset_control *__fwnode_reset_control_get( + struct fwnode_handle *fwnode, const char *id, int index, enum reset_control_flags flags) { bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; @@ -242,7 +245,7 @@ devm_reset_control_array_get(struct device *dev, enum reset_control_flags flags) } static inline struct reset_control * -of_reset_control_array_get(struct device_node *np, enum reset_control_flags flags) +fwnode_reset_control_array_get(struct fwnode_handle *fwnode, enum reset_control_flags flags) { bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; @@ -500,7 +503,8 @@ reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs, static inline struct reset_control *of_reset_control_get_exclusive( struct device_node *node, const char *id) { - return __of_reset_control_get(node, id, 0, RESET_CONTROL_EXCLUSIVE); + return __fwnode_reset_control_get(of_fwnode_handle(node), id, 0, + RESET_CONTROL_EXCLUSIVE); } /** @@ -520,7 +524,8 @@ static inline struct reset_control *of_reset_control_get_exclusive( static inline struct reset_control *of_reset_control_get_optional_exclusive( struct device_node *node, const char *id) { - return __of_reset_control_get(node, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE); + return __fwnode_reset_control_get(of_fwnode_handle(node), id, 0, + RESET_CONTROL_OPTIONAL_EXCLUSIVE); } /** @@ -545,7 +550,8 @@ static inline struct reset_control *of_reset_control_get_optional_exclusive( static inline struct reset_control *of_reset_control_get_shared( struct device_node *node, const char *id) { - return __of_reset_control_get(node, id, 0, RESET_CONTROL_SHARED); + return __fwnode_reset_control_get(of_fwnode_handle(node), id, 0, + RESET_CONTROL_SHARED); } /** @@ -562,7 +568,8 @@ static inline struct reset_control *of_reset_control_get_shared( static inline struct reset_control *of_reset_control_get_exclusive_by_index( struct device_node *node, int index) { - return __of_reset_control_get(node, NULL, index, RESET_CONTROL_EXCLUSIVE); + return __fwnode_reset_control_get(of_fwnode_handle(node), NULL, index, + RESET_CONTROL_EXCLUSIVE); } /** @@ -590,7 +597,8 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index( static inline struct reset_control *of_reset_control_get_shared_by_index( struct device_node *node, int index) { - return __of_reset_control_get(node, NULL, index, RESET_CONTROL_SHARED); + return __fwnode_reset_control_get(of_fwnode_handle(node), NULL, index, + RESET_CONTROL_SHARED); } /** @@ -1032,30 +1040,35 @@ devm_reset_control_array_get_optional_shared(struct device *dev) static inline struct reset_control * of_reset_control_array_get_exclusive(struct device_node *node) { - return of_reset_control_array_get(node, RESET_CONTROL_EXCLUSIVE); + return fwnode_reset_control_array_get(of_fwnode_handle(node), + RESET_CONTROL_EXCLUSIVE); } static inline struct reset_control * of_reset_control_array_get_exclusive_released(struct device_node *node) { - return of_reset_control_array_get(node, RESET_CONTROL_EXCLUSIVE_RELEASED); + return fwnode_reset_control_array_get(of_fwnode_handle(node), + RESET_CONTROL_EXCLUSIVE_RELEASED); } static inline struct reset_control * of_reset_control_array_get_shared(struct device_node *node) { - return of_reset_control_array_get(node, RESET_CONTROL_SHARED); + return fwnode_reset_control_array_get(of_fwnode_handle(node), + RESET_CONTROL_SHARED); } static inline struct reset_control * of_reset_control_array_get_optional_exclusive(struct device_node *node) { - return of_reset_control_array_get(node, RESET_CONTROL_OPTIONAL_EXCLUSIVE); + return fwnode_reset_control_array_get(of_fwnode_handle(node), + RESET_CONTROL_OPTIONAL_EXCLUSIVE); } static inline struct reset_control * of_reset_control_array_get_optional_shared(struct device_node *node) { - return of_reset_control_array_get(node, RESET_CONTROL_OPTIONAL_SHARED); + return fwnode_reset_control_array_get(of_fwnode_handle(node), + RESET_CONTROL_OPTIONAL_SHARED); } #endif From 9035073d0ef1de813c6335239250248bfe0a64aa Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:57 +0100 Subject: [PATCH 070/193] reset: convert reset core to using firmware nodes With everything else now in place, we can convert the remaining parts of the reset subsystem to becoming fwnode-agnostic - meaning it will work with all kinds of firmware nodes, not only devicetree. To that end: extend struct reset_controller_dev with fields taking information relevant for using firmware nodes (which mirrors what we already do for OF-nodes) and limit using of_ APIs only to where it's absolutely necessary (mostly around the of_xlate callback). For backward compatibility of existing drivers we still support OF-nodes but firmware nodes become the preferred method. Signed-off-by: Bartosz Golaszewski Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 166 +++++++++++++++++++------------ include/linux/reset-controller.h | 14 ++- 2 files changed, 112 insertions(+), 68 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 0da5079ea9db..e625cf59cfb0 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -81,13 +81,13 @@ struct reset_control_array { /** * struct reset_gpio_lookup - lookup key for ad-hoc created reset-gpio devices - * @of_args: phandle to the reset controller with all the args like GPIO number + * @ref_args: Reference to the reset controller with all the args like GPIO number * @swnode: Software node containing the reference to the GPIO provider * @list: list entry for the reset_gpio_lookup_list * @adev: Auxiliary device representing the reset controller */ struct reset_gpio_lookup { - struct of_phandle_args of_args; + struct fwnode_reference_args ref_args; struct fwnode_handle *swnode; struct list_head list; struct auxiliary_device adev; @@ -98,24 +98,24 @@ static const char *rcdev_name(struct reset_controller_dev *rcdev) if (rcdev->dev) return dev_name(rcdev->dev); - if (rcdev->of_node) - return rcdev->of_node->full_name; + if (rcdev->fwnode) + return fwnode_get_name(rcdev->fwnode); return NULL; } /** - * of_reset_simple_xlate - translate reset_spec to the reset line number + * fwnode_reset_simple_xlate - translate reset_spec to the reset line number * @rcdev: a pointer to the reset controller device - * @reset_spec: reset line specifier as found in the device tree + * @reset_spec: reset line specifier as found in firmware * - * This static translation function is used by default if of_xlate in - * :c:type:`reset_controller_dev` is not set. It is useful for all reset - * controllers with 1:1 mapping, where reset lines can be indexed by number - * without gaps. + * This static translation function is used by default if neither fwnode_xlate + * not of_xlate in :c:type:`reset_controller_dev` is not set. It is useful for + * all reset controllers with 1:1 mapping, where reset lines can be indexed by + * number without gaps. */ -static int of_reset_simple_xlate(struct reset_controller_dev *rcdev, - const struct of_phandle_args *reset_spec) +static int fwnode_reset_simple_xlate(struct reset_controller_dev *rcdev, + const struct fwnode_reference_args *reset_spec) { if (reset_spec->args[0] >= rcdev->nr_resets) return -EINVAL; @@ -129,9 +129,23 @@ static int of_reset_simple_xlate(struct reset_controller_dev *rcdev, */ int reset_controller_register(struct reset_controller_dev *rcdev) { - if (!rcdev->of_xlate) { - rcdev->of_reset_n_cells = 1; - rcdev->of_xlate = of_reset_simple_xlate; + if ((rcdev->of_node && rcdev->fwnode) || (rcdev->of_xlate && rcdev->fwnode_xlate)) + return -EINVAL; + + if (!rcdev->of_node && !rcdev->fwnode) { + rcdev->fwnode = dev_fwnode(rcdev->dev); + if (!rcdev->fwnode) + return -EINVAL; + } + + if (rcdev->of_node) { + rcdev->fwnode = of_fwnode_handle(rcdev->of_node); + rcdev->fwnode_reset_n_cells = rcdev->of_reset_n_cells; + } + + if (rcdev->fwnode && !rcdev->fwnode_xlate) { + rcdev->fwnode_reset_n_cells = 1; + rcdev->fwnode_xlate = fwnode_reset_simple_xlate; } INIT_LIST_HEAD(&rcdev->reset_control_head); @@ -931,7 +945,7 @@ static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev, adev->id = id; adev->name = "gpio"; adev->dev.parent = parent; - adev->dev.platform_data = &rgpio_dev->of_args; + adev->dev.platform_data = &rgpio_dev->ref_args; adev->dev.release = reset_gpio_aux_device_release; device_set_node(&adev->dev, rgpio_dev->swnode); @@ -951,18 +965,18 @@ static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev, return 0; } -static void reset_gpio_add_devlink(struct device_node *np, +static void reset_gpio_add_devlink(struct fwnode_handle *fwnode, struct reset_gpio_lookup *rgpio_dev) { struct device *consumer; /* - * We must use get_dev_from_fwnode() and not of_find_device_by_node() + * We must use get_dev_from_fwnode() and not ref_find_device_by_node() * because the latter only considers the platform bus while we want to * get consumers of any kind that can be associated with firmware * nodes: auxiliary, soundwire, etc. */ - consumer = get_dev_from_fwnode(of_fwnode_handle(np)); + consumer = get_dev_from_fwnode(fwnode); if (consumer) { if (!device_link_add(consumer, &rgpio_dev->adev.dev, DL_FLAG_AUTOREMOVE_CONSUMER)) @@ -982,15 +996,23 @@ static void reset_gpio_add_devlink(struct device_node *np, */ } +/* TODO: move it out into drivers/base/ */ +static bool fwnode_reference_args_equal(const struct fwnode_reference_args *left, + const struct fwnode_reference_args *right) +{ + return left->fwnode == right->fwnode && left->nargs == right->nargs && + !memcmp(left->args, right->args, sizeof(left->args[0]) * left->nargs); +} + /* * @np: OF-node associated with the consumer - * @args: phandle to the GPIO provider with all the args like GPIO number + * @args: Reference to the GPIO provider with all the args like GPIO number */ -static int __reset_add_reset_gpio_device(struct device_node *np, - const struct of_phandle_args *args) +static int __reset_add_reset_gpio_device(struct fwnode_handle *fwnode, + const struct fwnode_reference_args *args) { struct property_entry properties[3] = { }; - unsigned int offset, of_flags, lflags; + unsigned int offset, flags, lflags; struct reset_gpio_lookup *rgpio_dev; struct device *parent; int ret, prop = 0; @@ -1001,7 +1023,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np, * args[1]: GPIO flags * TODO: Handle other cases. */ - if (args->args_count != 2) + if (args->nargs != 2) return -ENOENT; /* @@ -1012,7 +1034,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np, lockdep_assert_not_held(&reset_list_mutex); offset = args->args[0]; - of_flags = args->args[1]; + flags = args->args[1]; /* * Later we map GPIO flags between OF and Linux, however not all @@ -1022,33 +1044,31 @@ static int __reset_add_reset_gpio_device(struct device_node *np, * FIXME: Find a better way of translating OF flags to GPIO lookup * flags. */ - if (of_flags > GPIO_ACTIVE_LOW) { + if (flags > GPIO_ACTIVE_LOW) { pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n", - of_flags, offset); + flags, offset); return -EINVAL; } struct gpio_device *gdev __free(gpio_device_put) = - gpio_device_find_by_fwnode(of_fwnode_handle(args->np)); + gpio_device_find_by_fwnode(args->fwnode); if (!gdev) return -EPROBE_DEFER; guard(mutex)(&reset_gpio_lookup_mutex); list_for_each_entry(rgpio_dev, &reset_gpio_lookup_list, list) { - if (args->np == rgpio_dev->of_args.np) { - if (of_phandle_args_equal(args, &rgpio_dev->of_args)) { - /* - * Already on the list, create the device link - * and stop here. - */ - reset_gpio_add_devlink(np, rgpio_dev); - return 0; - } + if (fwnode_reference_args_equal(args, &rgpio_dev->ref_args)) { + /* + * Already on the list, create the device link + * and stop here. + */ + reset_gpio_add_devlink(fwnode, rgpio_dev); + return 0; } } - lflags = GPIO_PERSISTENT | (of_flags & GPIO_ACTIVE_LOW); + lflags = GPIO_PERSISTENT | (flags & GPIO_ACTIVE_LOW); parent = gpio_device_to_device(gdev); properties[prop++] = PROPERTY_ENTRY_STRING("compatible", "reset-gpio"); properties[prop++] = PROPERTY_ENTRY_GPIO("reset-gpios", parent->fwnode, offset, lflags); @@ -1058,43 +1078,43 @@ static int __reset_add_reset_gpio_device(struct device_node *np, if (!rgpio_dev) return -ENOMEM; - rgpio_dev->of_args = *args; + rgpio_dev->ref_args = *args; /* - * We keep the device_node reference, but of_args.np is put at the end - * of __fwnode_reset_control_get(), so get it one more time. + * We keep the fwnode_handle reference, but ref_args.fwnode is put at + * the end of __fwnode_reset_control_get(), so get it one more time. * Hold reference as long as rgpio_dev memory is valid. */ - of_node_get(rgpio_dev->of_args.np); + fwnode_handle_get(rgpio_dev->ref_args.fwnode); rgpio_dev->swnode = fwnode_create_software_node(properties, NULL); if (IS_ERR(rgpio_dev->swnode)) { ret = PTR_ERR(rgpio_dev->swnode); - goto err_put_of_node; + goto err_put_fwnode; } ret = reset_create_gpio_aux_device(rgpio_dev, parent); if (ret) goto err_del_swnode; - reset_gpio_add_devlink(np, rgpio_dev); + reset_gpio_add_devlink(fwnode, rgpio_dev); list_add(&rgpio_dev->list, &reset_gpio_lookup_list); return 0; err_del_swnode: fwnode_remove_software_node(rgpio_dev->swnode); -err_put_of_node: - of_node_put(rgpio_dev->of_args.np); +err_put_fwnode: + fwnode_handle_put(rgpio_dev->ref_args.fwnode); kfree(rgpio_dev); return ret; } -static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_args *args, - bool gpio_fallback) +static struct reset_controller_dev * +__reset_find_rcdev(const struct fwnode_reference_args *args, bool gpio_fallback) { + struct fwnode_reference_args *rc_args; struct reset_controller_dev *rcdev; - struct of_phandle_args *rc_args; lockdep_assert_held(&reset_list_mutex); @@ -1103,10 +1123,10 @@ static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_a device_is_compatible(rcdev->dev, "reset-gpio")) { rc_args = dev_get_platdata(rcdev->dev); - if (of_phandle_args_equal(args, rc_args)) + if (fwnode_reference_args_equal(args, rc_args)) return rcdev; } else { - if (args->np == rcdev->of_node) + if (args->fwnode == rcdev->fwnode) return rcdev; } } @@ -1120,27 +1140,26 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind { bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; bool gpio_fallback = false; - struct device_node *node = to_of_node(fwnode); struct reset_control *rstc = ERR_PTR(-EINVAL); struct reset_controller_dev *rcdev; - struct of_phandle_args args; - int rstc_id; + struct fwnode_reference_args args; + struct of_phandle_args of_args; + int rstc_id = -EINVAL; int ret; if (!fwnode) return ERR_PTR(-EINVAL); if (id) { - index = of_property_match_string(node, - "reset-names", id); + index = fwnode_property_match_string(fwnode, "reset-names", id); if (index == -EILSEQ) return ERR_PTR(index); if (index < 0) return optional ? NULL : ERR_PTR(-ENOENT); } - ret = of_parse_phandle_with_args(node, "resets", "#reset-cells", - index, &args); + ret = fwnode_property_get_reference_args(fwnode, "resets", "#reset-cells", + 0, index, &args); if (ret == -EINVAL) return ERR_PTR(ret); if (ret) { @@ -1151,16 +1170,16 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind * There can be only one reset-gpio for regular devices, so * don't bother with the "reset-gpios" phandle index. */ - ret = of_parse_phandle_with_args(node, "reset-gpios", "#gpio-cells", - 0, &args); + ret = fwnode_property_get_reference_args(fwnode, "reset-gpios", + "#gpio-cells", 0, 0, &args); if (ret) return optional ? NULL : ERR_PTR(ret); gpio_fallback = true; - ret = __reset_add_reset_gpio_device(node, &args); + ret = __reset_add_reset_gpio_device(fwnode, &args); if (ret) { - of_node_put(args.np); + fwnode_handle_put(args.fwnode); return ERR_PTR(ret); } } @@ -1173,15 +1192,30 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind goto out_put; } - if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) { + if (WARN_ON(args.nargs != rcdev->fwnode_reset_n_cells)) { rstc = ERR_PTR(-EINVAL); goto out_put; } - rstc_id = rcdev->of_xlate(rcdev, &args); + if (rcdev->of_xlate && is_of_node(fwnode)) { + ret = of_parse_phandle_with_args(to_of_node(fwnode), + gpio_fallback ? "reset-gpios" : "resets", + gpio_fallback ? "#gpio-cells" : "#reset-cells", + gpio_fallback ? 0 : index, + &of_args); + if (ret) { + rstc = ERR_PTR(ret); + goto out_put; + } + + rstc_id = rcdev->of_xlate(rcdev, &of_args); + of_node_put(of_args.np); + } else if (rcdev->fwnode_xlate) { + rstc_id = rcdev->fwnode_xlate(rcdev, &args); + } if (rstc_id < 0) { rstc = ERR_PTR(rstc_id); - goto out_put; + goto out_put; } flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL; @@ -1190,7 +1224,7 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind rstc = __reset_control_get_internal(rcdev, rstc_id, flags); out_put: - of_node_put(args.np); + fwnode_handle_put(args.fwnode); return rstc; } diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h index 185d2a9bd7cd..52a5a4e81f18 100644 --- a/include/linux/reset-controller.h +++ b/include/linux/reset-controller.h @@ -5,6 +5,8 @@ #include #include +struct fwnode_handle; +struct fwnode_reference_args; struct reset_controller_dev; /** @@ -38,8 +40,12 @@ struct of_phandle_args; * @of_node: corresponding device tree node as phandle target * @of_reset_n_cells: number of cells in reset line specifiers * @of_xlate: translation function to translate from specifier as found in the - * device tree to id as given to the reset control ops, defaults - * to :c:func:`of_reset_simple_xlate`. + * device tree to id as given to the reset control ops + * @fwnode: firmware node associated with this device + * @fwnode_reset_n_cells: number of cells in reset line specifiers + * @fwnode_xlate: translation function to translate from firmware specifier to + * id as given to the reset control ops, defaults to + * :c:func:`fwnode_reset_simple_xlate` * @nr_resets: number of reset controls in this reset controller device * @lock: protects the reset control list from concurrent access */ @@ -53,6 +59,10 @@ struct reset_controller_dev { int of_reset_n_cells; int (*of_xlate)(struct reset_controller_dev *rcdev, const struct of_phandle_args *reset_spec); + struct fwnode_handle *fwnode; + int fwnode_reset_n_cells; + int (*fwnode_xlate)(struct reset_controller_dev *rcdev, + const struct fwnode_reference_args *reset_spec); unsigned int nr_resets; struct mutex lock; }; From faaad5006e5835c3b9228906232fc6b17b01512b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Mar 2026 18:22:58 +0100 Subject: [PATCH 071/193] reset: gpio: make the driver fwnode-agnostic With reset core now being able to work with firmware nodes, we can make reset-gpio node-agnostic and drop any OF dependencies. Reviewed-by: Philipp Zabel Signed-off-by: Bartosz Golaszewski Signed-off-by: Philipp Zabel --- drivers/reset/reset-gpio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/reset/reset-gpio.c b/drivers/reset/reset-gpio.c index 5044f809d0e5..26aa2c3a2e68 100644 --- a/drivers/reset/reset-gpio.c +++ b/drivers/reset/reset-gpio.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include struct reset_gpio_priv { @@ -46,8 +46,8 @@ static const struct reset_control_ops reset_gpio_ops = { .status = reset_gpio_status, }; -static int reset_gpio_of_xlate(struct reset_controller_dev *rcdev, - const struct of_phandle_args *reset_spec) +static int reset_gpio_fwnode_xlate(struct reset_controller_dev *rcdev, + const struct fwnode_reference_args *reset_spec) { return reset_spec->args[0]; } @@ -72,8 +72,8 @@ static int reset_gpio_probe(struct auxiliary_device *adev, priv->rc.dev = dev; /* Cells to match GPIO specifier, but it's not really used */ - priv->rc.of_reset_n_cells = 2; - priv->rc.of_xlate = reset_gpio_of_xlate; + priv->rc.fwnode_reset_n_cells = 2; + priv->rc.fwnode_xlate = reset_gpio_fwnode_xlate; priv->rc.nr_resets = 1; return devm_reset_controller_register(dev, &priv->rc); From c76350e7add86344beae4cd69fffdf63284a4bf5 Mon Sep 17 00:00:00 2001 From: Gary Yang Date: Mon, 2 Mar 2026 14:44:05 +0800 Subject: [PATCH 072/193] dt-bindings: soc: cix: document the syscon on Sky1 SoC There are two system control on Cix sky1 Soc. One is located in S0 domain, and the other is located in S5 domain. The system control contains resets, usb typeC and more. At this point, only the reset controller is embedded as usb typeC uses it by phandle. Signed-off-by: Gary Yang Reviewed-by: Krzysztof Kozlowski Signed-off-by: Philipp Zabel --- .../soc/cix/cix,sky1-system-control.yaml | 42 +++++ .../reset/cix,sky1-s5-system-control.h | 163 ++++++++++++++++++ .../reset/cix,sky1-system-control.h | 41 +++++ 3 files changed, 246 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/cix/cix,sky1-system-control.yaml create mode 100644 include/dt-bindings/reset/cix,sky1-s5-system-control.h create mode 100644 include/dt-bindings/reset/cix,sky1-system-control.h diff --git a/Documentation/devicetree/bindings/soc/cix/cix,sky1-system-control.yaml b/Documentation/devicetree/bindings/soc/cix/cix,sky1-system-control.yaml new file mode 100644 index 000000000000..a01a515222c6 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/cix/cix,sky1-system-control.yaml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/cix/cix,sky1-system-control.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cix Sky1 SoC system control register region + +maintainers: + - Gary Yang + +description: + An wide assortment of registers of the system controller on Sky1 SoC, + including resets, usb, wakeup sources and so on. + +properties: + compatible: + items: + - enum: + - cix,sky1-system-control + - cix,sky1-s5-system-control + - const: syscon + + reg: + maxItems: 1 + + '#reset-cells': + const: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + syscon@4160000 { + compatible = "cix,sky1-system-control", "syscon"; + reg = <0x4160000 0x100>; + #reset-cells = <1>; + }; diff --git a/include/dt-bindings/reset/cix,sky1-s5-system-control.h b/include/dt-bindings/reset/cix,sky1-s5-system-control.h new file mode 100644 index 000000000000..808bbcbe0c98 --- /dev/null +++ b/include/dt-bindings/reset/cix,sky1-s5-system-control.h @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* Author: Jerry Zhu */ +#ifndef DT_BINDING_RESET_CIX_SKY1_S5_SYSTEM_CONTROL_H +#define DT_BINDING_RESET_CIX_SKY1_S5_SYSTEM_CONTROL_H + +/* reset for csu_pm */ +#define SKY1_CSU_PM_RESET_N 0 +#define SKY1_SENSORFUSION_RESET_N 1 +#define SKY1_SENSORFUSION_NOC_RESET_N 2 + +/* reset group0 for s0 domain modules */ +#define SKY1_DDRC_RESET_N 3 +#define SKY1_GIC_RESET_N 4 +#define SKY1_CI700_RESET_N 5 +#define SKY1_SYS_NI700_RESET_N 6 +#define SKY1_MM_NI700_RESET_N 7 +#define SKY1_PCIE_NI700_RESET_N 8 +#define SKY1_GPU_RESET_N 9 +#define SKY1_NPUTOP_RESET_N 10 +#define SKY1_NPUCORE0_RESET_N 11 +#define SKY1_NPUCORE1_RESET_N 12 +#define SKY1_NPUCORE2_RESET_N 13 +#define SKY1_VPU_RESET_N 14 +#define SKY1_ISP_SRESET_N 15 +#define SKY1_ISP_ARESET_N 16 +#define SKY1_ISP_HRESET_N 17 +#define SKY1_ISP_GDCRESET_N 18 +#define SKY1_DPU_RESET0_N 19 +#define SKY1_DPU_RESET1_N 20 +#define SKY1_DPU_RESET2_N 21 +#define SKY1_DPU_RESET3_N 22 +#define SKY1_DPU_RESET4_N 23 +#define SKY1_DP_RESET0_N 24 +#define SKY1_DP_RESET1_N 25 +#define SKY1_DP_RESET2_N 26 +#define SKY1_DP_RESET3_N 27 +#define SKY1_DP_RESET4_N 28 +#define SKY1_DP_PHY_RST_N 29 + +/* reset group1 for s0 domain modules */ +#define SKY1_AUDIO_HIFI5_RESET_N 30 +#define SKY1_AUDIO_HIFI5_NOC_RESET_N 31 +#define SKY1_CSIDPHY_PRST0_N 32 +#define SKY1_CSIDPHY_CMNRST0_N 33 +#define SKY1_CSI0_RST_N 34 +#define SKY1_CSIDPHY_PRST1_N 35 +#define SKY1_CSIDPHY_CMNRST1_N 36 +#define SKY1_CSI1_RST_N 37 +#define SKY1_CSI2_RST_N 38 +#define SKY1_CSI3_RST_N 39 +#define SKY1_CSIBRDGE0_RST_N 40 +#define SKY1_CSIBRDGE1_RST_N 41 +#define SKY1_CSIBRDGE2_RST_N 42 +#define SKY1_CSIBRDGE3_RST_N 43 +#define SKY1_GMAC0_RST_N 44 +#define SKY1_GMAC1_RST_N 45 +#define SKY1_PCIE0_RESET_N 46 +#define SKY1_PCIE1_RESET_N 47 +#define SKY1_PCIE2_RESET_N 48 +#define SKY1_PCIE3_RESET_N 49 +#define SKY1_PCIE4_RESET_N 50 + +/* reset group1 for usb phys */ +#define SKY1_USB_DP_PHY0_PRST_N 51 +#define SKY1_USB_DP_PHY1_PRST_N 52 +#define SKY1_USB_DP_PHY2_PRST_N 53 +#define SKY1_USB_DP_PHY3_PRST_N 54 +#define SKY1_USB_DP_PHY0_RST_N 55 +#define SKY1_USB_DP_PHY1_RST_N 56 +#define SKY1_USB_DP_PHY2_RST_N 57 +#define SKY1_USB_DP_PHY3_RST_N 58 +#define SKY1_USBPHY_SS_PST_N 59 +#define SKY1_USBPHY_SS_RST_N 60 +#define SKY1_USBPHY_HS0_PRST_N 61 +#define SKY1_USBPHY_HS1_PRST_N 62 +#define SKY1_USBPHY_HS2_PRST_N 63 +#define SKY1_USBPHY_HS3_PRST_N 64 +#define SKY1_USBPHY_HS4_PRST_N 65 +#define SKY1_USBPHY_HS5_PRST_N 66 +#define SKY1_USBPHY_HS6_PRST_N 67 +#define SKY1_USBPHY_HS7_PRST_N 68 +#define SKY1_USBPHY_HS8_PRST_N 69 +#define SKY1_USBPHY_HS9_PRST_N 70 + +/* reset group1 for usb controllers */ +#define SKY1_USBC_SS0_PRST_N 71 +#define SKY1_USBC_SS1_PRST_N 72 +#define SKY1_USBC_SS2_PRST_N 73 +#define SKY1_USBC_SS3_PRST_N 74 +#define SKY1_USBC_SS4_PRST_N 75 +#define SKY1_USBC_SS5_PRST_N 76 +#define SKY1_USBC_SS0_RST_N 77 +#define SKY1_USBC_SS1_RST_N 78 +#define SKY1_USBC_SS2_RST_N 79 +#define SKY1_USBC_SS3_RST_N 80 +#define SKY1_USBC_SS4_RST_N 81 +#define SKY1_USBC_SS5_RST_N 82 +#define SKY1_USBC_HS0_PRST_N 83 +#define SKY1_USBC_HS1_PRST_N 84 +#define SKY1_USBC_HS2_PRST_N 85 +#define SKY1_USBC_HS3_PRST_N 86 +#define SKY1_USBC_HS0_RST_N 87 +#define SKY1_USBC_HS1_RST_N 88 +#define SKY1_USBC_HS2_RST_N 89 +#define SKY1_USBC_HS3_RST_N 90 + +/* reset group0 for rcsu */ +#define SKY1_AUDIO_RCSU_RESET_N 91 +#define SKY1_CI700_RCSU_RESET_N 92 +#define SKY1_CSI_RCSU0_RESET_N 93 +#define SKY1_CSI_RCSU1_RESET_N 94 +#define SKY1_CSU_PM_RCSU_RESET_N 95 +#define SKY1_DDR_BROADCAST_RCSU_RESET_N 96 +#define SKY1_DDR_CTRL_RCSU_0_RESET_N 97 +#define SKY1_DDR_CTRL_RCSU_1_RESET_N 98 +#define SKY1_DDR_CTRL_RCSU_2_RESET_N 99 +#define SKY1_DDR_CTRL_RCSU_3_RESET_N 100 +#define SKY1_DDR_TZC400_RCSU_0_RESET_N 101 +#define SKY1_DDR_TZC400_RCSU_1_RESET_N 102 +#define SKY1_DDR_TZC400_RCSU_2_RESET_N 103 +#define SKY1_DDR_TZC400_RCSU_3_RESET_N 104 +#define SKY1_DP0_RCSU_RESET_N 105 +#define SKY1_DP1_RCSU_RESET_N 106 +#define SKY1_DP2_RCSU_RESET_N 107 +#define SKY1_DP3_RCSU_RESET_N 108 +#define SKY1_DP4_RCSU_RESET_N 109 +#define SKY1_DPU0_RCSU_RESET_N 110 +#define SKY1_DPU1_RCSU_RESET_N 111 +#define SKY1_DPU2_RCSU_RESET_N 112 +#define SKY1_DPU3_RCSU_RESET_N 113 +#define SKY1_DPU4_RCSU_RESET_N 114 +#define SKY1_DSU_RCSU_RESET_N 115 +#define SKY1_FCH_RCSU_RESET_N 116 +#define SKY1_GICD_RCSU_RESET_N 117 +#define SKY1_GMAC_RCSU_RESET_N 118 +#define SKY1_GPU_RCSU_RESET_N 119 +#define SKY1_ISP_RCSU0_RESET_N 120 +#define SKY1_ISP_RCSU1_RESET_N 121 +#define SKY1_NI700_MMHUB_RCSU_RESET_N 122 + +/* reset group1 for rcsu */ +#define SKY1_NPU_RCSU_RESET_N 123 +#define SKY1_NI700_PCIE_RCSU_RESET_N 124 +#define SKY1_PCIE_X421_RCSU_RESET_N 125 +#define SKY1_PCIE_X8_RCSU_RESET_N 126 +#define SKY1_SF_RCSU_RESET_N 127 +#define SKY1_RCSU_SMMU_MMHUB_RESET_N 128 +#define SKY1_RCSU_SMMU_PCIEHUB_RESET_N 129 +#define SKY1_RCSU_SYSHUB_RESET_N 130 +#define SKY1_NI700_SMN_RCSU_RESET_N 131 +#define SKY1_NI700_SYSHUB_RCSU_RESET_N 132 +#define SKY1_RCSU_USB2_HOST0_RESET_N 133 +#define SKY1_RCSU_USB2_HOST1_RESET_N 134 +#define SKY1_RCSU_USB2_HOST2_RESET_N 135 +#define SKY1_RCSU_USB2_HOST3_RESET_N 136 +#define SKY1_RCSU_USB3_TYPEA_DRD_RESET_N 137 +#define SKY1_RCSU_USB3_TYPEC_DRD_RESET_N 138 +#define SKY1_RCSU_USB3_TYPEC_HOST0_RESET_N 139 +#define SKY1_RCSU_USB3_TYPEC_HOST1_RESET_N 140 +#define SKY1_RCSU_USB3_TYPEC_HOST2_RESET_N 141 +#define SKY1_VPU_RCSU_RESET_N 142 + +#endif diff --git a/include/dt-bindings/reset/cix,sky1-system-control.h b/include/dt-bindings/reset/cix,sky1-system-control.h new file mode 100644 index 000000000000..7a16fc4ef3b5 --- /dev/null +++ b/include/dt-bindings/reset/cix,sky1-system-control.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* Author: Jerry Zhu */ +#ifndef DT_BINDING_RESET_CIX_SKY1_SYSTEM_CONTROL_H +#define DT_BINDING_RESET_CIX_SKY1_SYSTEM_CONTROL_H + +/* func reset for sky1 fch */ +#define SW_I3C0_RST_FUNC_G_N 0 +#define SW_I3C0_RST_FUNC_I_N 1 +#define SW_I3C1_RST_FUNC_G_N 2 +#define SW_I3C1_RST_FUNC_I_N 3 +#define SW_UART0_RST_FUNC_N 4 +#define SW_UART1_RST_FUNC_N 5 +#define SW_UART2_RST_FUNC_N 6 +#define SW_UART3_RST_FUNC_N 7 +#define SW_TIMER_RST_FUNC_N 8 + +/* apb reset for sky1 fch */ +#define SW_I3C0_RST_APB_N 9 +#define SW_I3C1_RST_APB_N 10 +#define SW_DMA_RST_AXI_N 11 +#define SW_UART0_RST_APB_N 12 +#define SW_UART1_RST_APB_N 13 +#define SW_UART2_RST_APB_N 14 +#define SW_UART3_RST_APB_N 15 +#define SW_SPI0_RST_APB_N 16 +#define SW_SPI1_RST_APB_N 17 +#define SW_I2C0_RST_APB_N 18 +#define SW_I2C1_RST_APB_N 19 +#define SW_I2C2_RST_APB_N 20 +#define SW_I2C3_RST_APB_N 21 +#define SW_I2C4_RST_APB_N 22 +#define SW_I2C5_RST_APB_N 23 +#define SW_I2C6_RST_APB_N 24 +#define SW_I2C7_RST_APB_N 25 +#define SW_GPIO_RST_APB_N 26 + +/* fch rst for xspi */ +#define SW_XSPI_REG_RST_N 27 +#define SW_XSPI_SYS_RST_N 28 + +#endif From 7cd3ca90d92110cb6a57fcc286c193cf7fd048d2 Mon Sep 17 00:00:00 2001 From: Gary Yang Date: Mon, 2 Mar 2026 14:44:06 +0800 Subject: [PATCH 073/193] reset: add Sky1 soc reset support Add support for the resets on Cix's Sky1 SoC. There are two reset controllers on Cix Sky1 Soc. One is located in S0 domain, and the other is located in S5 domain. Signed-off-by: Gary Yang Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/Kconfig | 7 + drivers/reset/Makefile | 1 + drivers/reset/reset-sky1.c | 367 +++++++++++++++++++++++++++++++++++++ 3 files changed, 375 insertions(+) create mode 100644 drivers/reset/reset-sky1.c diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 7ce151f6a7e4..c73145749455 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -291,6 +291,13 @@ config RESET_SIMPLE - SiFive FU740 SoCs - Sophgo SoCs +config RESET_SKY1 + bool "Cix Sky1 reset controller" + depends on ARCH_CIX || COMPILE_TEST + select REGMAP_MMIO + help + This enables the reset controller for Cix Sky1. + config RESET_SOCFPGA bool "SoCFPGA Reset Driver" if COMPILE_TEST && (!ARM || !ARCH_INTEL_SOCFPGA) default ARM && ARCH_INTEL_SOCFPGA diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index fc0cc99f8514..d1b8c66e5086 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o obj-$(CONFIG_RESET_RZV2H_USB2PHY) += reset-rzv2h-usb2phy.o obj-$(CONFIG_RESET_SCMI) += reset-scmi.o obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o +obj-$(CONFIG_RESET_SKY1) += reset-sky1.o obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o diff --git a/drivers/reset/reset-sky1.c b/drivers/reset/reset-sky1.c new file mode 100644 index 000000000000..78e80a533c39 --- /dev/null +++ b/drivers/reset/reset-sky1.c @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * + * CIX System Reset Controller (SRC) driver + * + * Author: Jerry Zhu + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define SKY1_RESET_SLEEP_MIN_US 50 +#define SKY1_RESET_SLEEP_MAX_US 100 + +struct sky1_src_signal { + unsigned int offset; + unsigned int bit; +}; + +struct sky1_src_variant { + const struct sky1_src_signal *signals; + unsigned int signals_num; +}; + +struct sky1_src { + struct reset_controller_dev rcdev; + const struct sky1_src_signal *signals; + struct regmap *regmap; +}; + +enum { + CSU_PM_RESET = 0x304, + SENSORFUSION_RESET = 0x308, + SENSORFUSION_NOC_RESET = 0x30c, + RESET_GROUP0_S0_DOMAIN_0 = 0x400, + RESET_GROUP0_S0_DOMAIN_1 = 0x404, + RESET_GROUP1_USB_PHYS = 0x408, + RESET_GROUP1_USB_CONTROLLERS = 0x40c, + RESET_GROUP0_RCSU = 0x800, + RESET_GROUP1_RCSU = 0x804, +}; + +static const struct sky1_src_signal sky1_src_signals[] = { + /* reset group1 for s0 domain modules */ + [SKY1_CSU_PM_RESET_N] = { CSU_PM_RESET, BIT(0) }, + [SKY1_SENSORFUSION_RESET_N] = { SENSORFUSION_RESET, BIT(0) }, + [SKY1_SENSORFUSION_NOC_RESET_N] = { SENSORFUSION_NOC_RESET, BIT(0) }, + [SKY1_DDRC_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(0) }, + [SKY1_GIC_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(1) }, + [SKY1_CI700_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(2) }, + [SKY1_SYS_NI700_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(3) }, + [SKY1_MM_NI700_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(4) }, + [SKY1_PCIE_NI700_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(5) }, + [SKY1_GPU_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(6) }, + [SKY1_NPUTOP_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(7) }, + [SKY1_NPUCORE0_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(8) }, + [SKY1_NPUCORE1_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(9) }, + [SKY1_NPUCORE2_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(10) }, + [SKY1_VPU_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(11) }, + [SKY1_ISP_SRESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(12) }, + [SKY1_ISP_ARESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(13) }, + [SKY1_ISP_HRESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(14) }, + [SKY1_ISP_GDCRESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(15) }, + [SKY1_DPU_RESET0_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(16) }, + [SKY1_DPU_RESET1_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(17) }, + [SKY1_DPU_RESET2_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(18) }, + [SKY1_DPU_RESET3_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(19) }, + [SKY1_DPU_RESET4_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(20) }, + [SKY1_DP_RESET0_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(21) }, + [SKY1_DP_RESET1_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(22) }, + [SKY1_DP_RESET2_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(23) }, + [SKY1_DP_RESET3_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(24) }, + [SKY1_DP_RESET4_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(25) }, + [SKY1_DP_PHY_RST_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(26) }, + + /* reset group1 for s0 domain modules */ + [SKY1_AUDIO_HIFI5_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(0) }, + [SKY1_AUDIO_HIFI5_NOC_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(1) }, + [SKY1_CSIDPHY_PRST0_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(2) }, + [SKY1_CSIDPHY_CMNRST0_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(3) }, + [SKY1_CSI0_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(4) }, + [SKY1_CSIDPHY_PRST1_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(5) }, + [SKY1_CSIDPHY_CMNRST1_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(6) }, + [SKY1_CSI1_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(7) }, + [SKY1_CSI2_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(8) }, + [SKY1_CSI3_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(9) }, + [SKY1_CSIBRDGE0_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(10) }, + [SKY1_CSIBRDGE1_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(11) }, + [SKY1_CSIBRDGE2_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(12) }, + [SKY1_CSIBRDGE3_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(13) }, + [SKY1_GMAC0_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(14) }, + [SKY1_GMAC1_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(15) }, + [SKY1_PCIE0_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(16) }, + [SKY1_PCIE1_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(17) }, + [SKY1_PCIE2_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(18) }, + [SKY1_PCIE3_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(19) }, + [SKY1_PCIE4_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(20) }, + + /* reset group1 for usb phys */ + [SKY1_USB_DP_PHY0_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(0) }, + [SKY1_USB_DP_PHY1_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(1) }, + [SKY1_USB_DP_PHY2_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(2) }, + [SKY1_USB_DP_PHY3_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(3) }, + [SKY1_USB_DP_PHY0_RST_N] = { RESET_GROUP1_USB_PHYS, BIT(4) }, + [SKY1_USB_DP_PHY1_RST_N] = { RESET_GROUP1_USB_PHYS, BIT(5) }, + [SKY1_USB_DP_PHY2_RST_N] = { RESET_GROUP1_USB_PHYS, BIT(6) }, + [SKY1_USB_DP_PHY3_RST_N] = { RESET_GROUP1_USB_PHYS, BIT(7) }, + [SKY1_USBPHY_SS_PST_N] = { RESET_GROUP1_USB_PHYS, BIT(8) }, + [SKY1_USBPHY_SS_RST_N] = { RESET_GROUP1_USB_PHYS, BIT(9) }, + [SKY1_USBPHY_HS0_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(10) }, + [SKY1_USBPHY_HS1_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(11) }, + [SKY1_USBPHY_HS2_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(12) }, + [SKY1_USBPHY_HS3_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(13) }, + [SKY1_USBPHY_HS4_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(14) }, + [SKY1_USBPHY_HS5_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(15) }, + [SKY1_USBPHY_HS6_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(16) }, + [SKY1_USBPHY_HS7_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(17) }, + [SKY1_USBPHY_HS8_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(18) }, + [SKY1_USBPHY_HS9_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(19) }, + + /* reset group1 for usb controllers */ + [SKY1_USBC_SS0_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(0) }, + [SKY1_USBC_SS1_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(1) }, + [SKY1_USBC_SS2_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(2) }, + [SKY1_USBC_SS3_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(3) }, + [SKY1_USBC_SS4_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(4) }, + [SKY1_USBC_SS5_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(5) }, + [SKY1_USBC_SS0_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(6) }, + [SKY1_USBC_SS1_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(7) }, + [SKY1_USBC_SS2_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(8) }, + [SKY1_USBC_SS3_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(9) }, + [SKY1_USBC_SS4_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(10) }, + [SKY1_USBC_SS5_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(11) }, + [SKY1_USBC_HS0_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(12) }, + [SKY1_USBC_HS1_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(13) }, + [SKY1_USBC_HS2_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(14) }, + [SKY1_USBC_HS3_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(15) }, + [SKY1_USBC_HS0_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(16) }, + [SKY1_USBC_HS1_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(17) }, + [SKY1_USBC_HS2_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(18) }, + [SKY1_USBC_HS3_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(19) }, + + /* reset group0 for rcsu */ + [SKY1_AUDIO_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(0) }, + [SKY1_CI700_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(1) }, + [SKY1_CSI_RCSU0_RESET_N] = { RESET_GROUP0_RCSU, BIT(2) }, + [SKY1_CSI_RCSU1_RESET_N] = { RESET_GROUP0_RCSU, BIT(3) }, + [SKY1_CSU_PM_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(4) }, + [SKY1_DDR_BROADCAST_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(5) }, + [SKY1_DDR_CTRL_RCSU_0_RESET_N] = { RESET_GROUP0_RCSU, BIT(6) }, + [SKY1_DDR_CTRL_RCSU_1_RESET_N] = { RESET_GROUP0_RCSU, BIT(7) }, + [SKY1_DDR_CTRL_RCSU_2_RESET_N] = { RESET_GROUP0_RCSU, BIT(8) }, + [SKY1_DDR_CTRL_RCSU_3_RESET_N] = { RESET_GROUP0_RCSU, BIT(9) }, + [SKY1_DDR_TZC400_RCSU_0_RESET_N] = { RESET_GROUP0_RCSU, BIT(10) }, + [SKY1_DDR_TZC400_RCSU_1_RESET_N] = { RESET_GROUP0_RCSU, BIT(11) }, + [SKY1_DDR_TZC400_RCSU_2_RESET_N] = { RESET_GROUP0_RCSU, BIT(12) }, + [SKY1_DDR_TZC400_RCSU_3_RESET_N] = { RESET_GROUP0_RCSU, BIT(13) }, + [SKY1_DP0_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(14) }, + [SKY1_DP1_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(15) }, + [SKY1_DP2_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(16) }, + [SKY1_DP3_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(17) }, + [SKY1_DP4_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(18) }, + [SKY1_DPU0_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(19) }, + [SKY1_DPU1_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(20) }, + [SKY1_DPU2_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(21) }, + [SKY1_DPU3_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(22) }, + [SKY1_DPU4_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(23) }, + [SKY1_DSU_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(24) }, + [SKY1_FCH_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(25) }, + [SKY1_GICD_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(26) }, + [SKY1_GMAC_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(27) }, + [SKY1_GPU_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(28) }, + [SKY1_ISP_RCSU0_RESET_N] = { RESET_GROUP0_RCSU, BIT(29) }, + [SKY1_ISP_RCSU1_RESET_N] = { RESET_GROUP0_RCSU, BIT(30) }, + [SKY1_NI700_MMHUB_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(31) }, + + /* reset group1 for rcsu */ + [SKY1_NPU_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(0) }, + [SKY1_NI700_PCIE_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(1) }, + [SKY1_PCIE_X421_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(2) }, + [SKY1_PCIE_X8_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(3) }, + [SKY1_SF_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(4) }, + [SKY1_RCSU_SMMU_MMHUB_RESET_N] = { RESET_GROUP1_RCSU, BIT(5) }, + [SKY1_RCSU_SMMU_PCIEHUB_RESET_N] = { RESET_GROUP1_RCSU, BIT(6) }, + [SKY1_RCSU_SYSHUB_RESET_N] = { RESET_GROUP1_RCSU, BIT(7) }, + [SKY1_NI700_SMN_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(8) }, + [SKY1_NI700_SYSHUB_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(9) }, + [SKY1_RCSU_USB2_HOST0_RESET_N] = { RESET_GROUP1_RCSU, BIT(10) }, + [SKY1_RCSU_USB2_HOST1_RESET_N] = { RESET_GROUP1_RCSU, BIT(11) }, + [SKY1_RCSU_USB2_HOST2_RESET_N] = { RESET_GROUP1_RCSU, BIT(12) }, + [SKY1_RCSU_USB2_HOST3_RESET_N] = { RESET_GROUP1_RCSU, BIT(13) }, + [SKY1_RCSU_USB3_TYPEA_DRD_RESET_N] = { RESET_GROUP1_RCSU, BIT(14) }, + [SKY1_RCSU_USB3_TYPEC_DRD_RESET_N] = { RESET_GROUP1_RCSU, BIT(15) }, + [SKY1_RCSU_USB3_TYPEC_HOST0_RESET_N] = { RESET_GROUP1_RCSU, BIT(16) }, + [SKY1_RCSU_USB3_TYPEC_HOST1_RESET_N] = { RESET_GROUP1_RCSU, BIT(17) }, + [SKY1_RCSU_USB3_TYPEC_HOST2_RESET_N] = { RESET_GROUP1_RCSU, BIT(18) }, + [SKY1_VPU_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(19) }, +}; + +static const struct sky1_src_variant variant_sky1 = { + .signals = sky1_src_signals, + .signals_num = ARRAY_SIZE(sky1_src_signals), +}; + +enum { + FCH_SW_RST_FUNC = 0x8, + FCH_SW_RST_BUS = 0xc, + FCH_SW_XSPI = 0x10, +}; + +static const struct sky1_src_signal sky1_src_fch_signals[] = { + /* resets for fch_sw_rst_func */ + [SW_I3C0_RST_FUNC_G_N] = { FCH_SW_RST_FUNC, BIT(0) }, + [SW_I3C0_RST_FUNC_I_N] = { FCH_SW_RST_FUNC, BIT(1) }, + [SW_I3C1_RST_FUNC_G_N] = { FCH_SW_RST_FUNC, BIT(2) }, + [SW_I3C1_RST_FUNC_I_N] = { FCH_SW_RST_FUNC, BIT(3) }, + [SW_UART0_RST_FUNC_N] = { FCH_SW_RST_FUNC, BIT(4) }, + [SW_UART1_RST_FUNC_N] = { FCH_SW_RST_FUNC, BIT(5) }, + [SW_UART2_RST_FUNC_N] = { FCH_SW_RST_FUNC, BIT(6) }, + [SW_UART3_RST_FUNC_N] = { FCH_SW_RST_FUNC, BIT(7) }, + [SW_TIMER_RST_FUNC_N] = { FCH_SW_RST_FUNC, BIT(20) }, + + /* resets for fch_sw_rst_bus */ + [SW_I3C0_RST_APB_N] = { FCH_SW_RST_BUS, BIT(0) }, + [SW_I3C1_RST_APB_N] = { FCH_SW_RST_BUS, BIT(1) }, + [SW_DMA_RST_AXI_N] = { FCH_SW_RST_BUS, BIT(2) }, + [SW_UART0_RST_APB_N] = { FCH_SW_RST_BUS, BIT(4) }, + [SW_UART1_RST_APB_N] = { FCH_SW_RST_BUS, BIT(5) }, + [SW_UART2_RST_APB_N] = { FCH_SW_RST_BUS, BIT(6) }, + [SW_UART3_RST_APB_N] = { FCH_SW_RST_BUS, BIT(7) }, + [SW_SPI0_RST_APB_N] = { FCH_SW_RST_BUS, BIT(8) }, + [SW_SPI1_RST_APB_N] = { FCH_SW_RST_BUS, BIT(9) }, + [SW_I2C0_RST_APB_N] = { FCH_SW_RST_BUS, BIT(12) }, + [SW_I2C1_RST_APB_N] = { FCH_SW_RST_BUS, BIT(13) }, + [SW_I2C2_RST_APB_N] = { FCH_SW_RST_BUS, BIT(14) }, + [SW_I2C3_RST_APB_N] = { FCH_SW_RST_BUS, BIT(15) }, + [SW_I2C4_RST_APB_N] = { FCH_SW_RST_BUS, BIT(16) }, + [SW_I2C5_RST_APB_N] = { FCH_SW_RST_BUS, BIT(17) }, + [SW_I2C6_RST_APB_N] = { FCH_SW_RST_BUS, BIT(18) }, + [SW_I2C7_RST_APB_N] = { FCH_SW_RST_BUS, BIT(19) }, + [SW_GPIO_RST_APB_N] = { FCH_SW_RST_BUS, BIT(21) }, + + /* resets for fch_sw_xspi */ + [SW_XSPI_REG_RST_N] = { FCH_SW_XSPI, BIT(0) }, + [SW_XSPI_SYS_RST_N] = { FCH_SW_XSPI, BIT(1) }, +}; + +static const struct sky1_src_variant variant_sky1_fch = { + .signals = sky1_src_fch_signals, + .signals_num = ARRAY_SIZE(sky1_src_fch_signals), +}; + +static struct sky1_src *to_sky1_src(struct reset_controller_dev *rcdev) +{ + return container_of(rcdev, struct sky1_src, rcdev); +} + +static int sky1_reset_set(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) +{ + struct sky1_src *sky1src = to_sky1_src(rcdev); + const struct sky1_src_signal *signal = &sky1src->signals[id]; + unsigned int value = assert ? 0 : signal->bit; + + return regmap_update_bits(sky1src->regmap, + signal->offset, signal->bit, value); +} + +static int sky1_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + sky1_reset_set(rcdev, id, true); + usleep_range(SKY1_RESET_SLEEP_MIN_US, + SKY1_RESET_SLEEP_MAX_US); + return 0; +} + +static int sky1_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + sky1_reset_set(rcdev, id, false); + usleep_range(SKY1_RESET_SLEEP_MIN_US, + SKY1_RESET_SLEEP_MAX_US); + return 0; +} + +static int sky1_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + sky1_reset_assert(rcdev, id); + sky1_reset_deassert(rcdev, id); + return 0; +} + +static int sky1_reset_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + unsigned int value = 0; + struct sky1_src *sky1src = to_sky1_src(rcdev); + const struct sky1_src_signal *signal = &sky1src->signals[id]; + + regmap_read(sky1src->regmap, signal->offset, &value); + return !(value & signal->bit); +} + +static const struct reset_control_ops sky1_src_ops = { + .reset = sky1_reset, + .assert = sky1_reset_assert, + .deassert = sky1_reset_deassert, + .status = sky1_reset_status +}; + +static int sky1_reset_probe(struct platform_device *pdev) +{ + struct sky1_src *sky1src; + struct device *dev = &pdev->dev; + const struct sky1_src_variant *variant; + + sky1src = devm_kzalloc(dev, sizeof(*sky1src), GFP_KERNEL); + if (!sky1src) + return -ENOMEM; + + variant = of_device_get_match_data(dev); + + sky1src->regmap = device_node_to_regmap(dev->of_node); + if (IS_ERR(sky1src->regmap)) { + return dev_err_probe(dev, PTR_ERR(sky1src->regmap), + "Unable to get sky1-src regmap"); + } + + sky1src->signals = variant->signals; + sky1src->rcdev.owner = THIS_MODULE; + sky1src->rcdev.nr_resets = variant->signals_num; + sky1src->rcdev.ops = &sky1_src_ops; + sky1src->rcdev.of_node = dev->of_node; + sky1src->rcdev.dev = dev; + + return devm_reset_controller_register(dev, &sky1src->rcdev); +} + +static const struct of_device_id sky1_sysreg_of_match[] = { + { .compatible = "cix,sky1-system-control", .data = &variant_sky1_fch}, + { .compatible = "cix,sky1-s5-system-control", .data = &variant_sky1}, + {}, +}; +MODULE_DEVICE_TABLE(of, sky1_sysreg_of_match); + +static struct platform_driver sky1_reset_driver = { + .probe = sky1_reset_probe, + .driver = { + .name = "cix,sky1-rst", + .of_match_table = sky1_sysreg_of_match, + }, +}; +module_platform_driver(sky1_reset_driver) + +MODULE_AUTHOR("Jerry Zhu "); +MODULE_DESCRIPTION("Cix Sky1 reset driver"); +MODULE_LICENSE("GPL"); From cb794619c2d29b882f6eec3b6ad4a1ca5afab312 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 2 Mar 2026 23:07:41 +0800 Subject: [PATCH 074/193] dt-bindings: fsl: imx7ulp-smc1: Add #clock-cells property The SMC1 block on i.MX7ULP is already used as a clock provider in imx7ulp.dtsi, but the corresponding dt-binding schema does not define the required '#clock-cells' property. This results in CHECK_DTBS schema validation errors. Functionally, SMC1 controls the CPU run mode configuration: - 00b: Normal Run (RUN) - 10b: Very-Low-Power Run (VLPR) - 11b: High-Speed Run (HSRUN) These run modes determine the effective CPU operating point, and their programming is tied to the OPP table. Add the missing `#clock-cells` definition so the dt-binding schema is consistent with the DTS and validates correctly. Fixes: 8ba41d6bd9893 ("dt-bindings: fsl: Convert i.MX7ULP PM to json-schema") Reviewed-by: Krzysztof Kozlowski Signed-off-by: Peng Fan Signed-off-by: Frank Li --- .../devicetree/bindings/arm/freescale/fsl,imx7ulp-pm.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,imx7ulp-pm.yaml b/Documentation/devicetree/bindings/arm/freescale/fsl,imx7ulp-pm.yaml index 9d377e193c12..7ad470260c0d 100644 --- a/Documentation/devicetree/bindings/arm/freescale/fsl,imx7ulp-pm.yaml +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,imx7ulp-pm.yaml @@ -28,6 +28,9 @@ properties: reg: maxItems: 1 + '#clock-cells': + const: 1 + clocks: maxItems: 2 @@ -39,6 +42,7 @@ properties: required: - compatible - reg + - '#clock-cells' additionalProperties: false @@ -47,4 +51,5 @@ examples: smc1@40410000 { compatible = "fsl,imx7ulp-smc1"; reg = <0x40410000 0x1000>; + #clock-cells = <1>; }; From 826f32e8ff437b4b88ba0b5c7978699710572ceb Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 26 Feb 2026 16:38:52 +0100 Subject: [PATCH 075/193] dt-bindings: arm: fsl: add bindings for TQMa8x TQMa8x is a SOM family using NXP i.MX8QM CPU family MBa8x is an evaluation mainboard for this SOM. Signed-off-by: Markus Niebel Signed-off-by: Alexander Stein Reviewed-by: Rob Herring (Arm) Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 92abff6f534e..fe31a9476889 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1428,6 +1428,16 @@ properties: - const: tq,imx8dxp-tqma8xdps # TQ-Systems GmbH TQMa8XDPS SOM - const: fsl,imx8dxp + - description: + TQMa8x is a series of SOM featuring NXP i.MX8 system-on-chip + variants. It is designed to be clicked on different carrier boards + MBa8x is the starterkit + items: + - enum: + - tq,imx8qm-tqma8qm-mba8x # TQ-Systems GmbH TQMa8QM SOM on MBa8x + - const: tq,imx8qm-tqma8qm # TQ-Systems GmbH TQMa8QM SOM + - const: fsl,imx8qm + - description: i.MX8ULP based Boards items: - enum: From 7a7d24a14a009691a1af6bfe45b210521635db5b Mon Sep 17 00:00:00 2001 From: Le Qi Date: Fri, 30 Jan 2026 14:12:31 +0800 Subject: [PATCH 076/193] soc: qcom: pd-mapper: Add QCS615 power domain mappings Add the QCS615 domain table to the in-kernel pd-mapper so that audio subsystems no longer rely on the userspace pd-mapper daemon. This enables proper initialization of ADSP and CDSP domains directly from the kernel. Reviewed-by: Dmitry Baryshkov Signed-off-by: Le Qi Link: https://lore.kernel.org/r/20260130061231.310113-1-le.qi@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_pd_mapper.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index dc10bc859ff4..0bccc23c0a58 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -401,6 +401,16 @@ static const struct qcom_pdm_domain_data *qcs404_domains[] = { NULL, }; +static const struct qcom_pdm_domain_data *qcs615_domains[] = { + &adsp_audio_pd, + &adsp_root_pd, + &adsp_sensor_pd, + &cdsp_root_pd, + &mpss_root_pd, + &mpss_wlan_pd, + NULL, +}; + static const struct qcom_pdm_domain_data *sc7180_domains[] = { &adsp_audio_pd, &adsp_root_pd_pdr, @@ -572,6 +582,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,qcm2290", .data = qcm2290_domains, }, { .compatible = "qcom,qcm6490", .data = sc7280_domains, }, { .compatible = "qcom,qcs404", .data = qcs404_domains, }, + { .compatible = "qcom,qcs615", .data = qcs615_domains, }, { .compatible = "qcom,sc7180", .data = sc7180_domains, }, { .compatible = "qcom,sc7280", .data = sc7280_domains, }, { .compatible = "qcom,sc8180x", .data = sc8180x_domains, }, From 2737dcb3c467824cd55921fba3fbd1375fc01695 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 10 Mar 2026 10:00:05 +0100 Subject: [PATCH 077/193] reset: core: Fix indentation Correct an accidental whitespace change. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202603100730.J3pi4xqi-lkp@intel.com/ Fixes: 9035073d0ef1 ("reset: convert reset core to using firmware nodes") Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index e625cf59cfb0..726b7346b148 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -1215,7 +1215,7 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind } if (rstc_id < 0) { rstc = ERR_PTR(rstc_id); - goto out_put; + goto out_put; } flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL; From 62d11b80ea5d118ba4a1b24e55ca13d77a4cf161 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 10 Mar 2026 16:15:15 +0100 Subject: [PATCH 078/193] reset: don't overwrite fwnode_reset_n_cells Fix a logic bug in reset_controller_register() where we set fwnode_reset_n_cells to 1 if fwnode is set and fwnode_xlate is not but we do it after assigning of_fwnode_handle(of_node) to fwnode. Modify the logic to: assign fwnode from of_node if applicable, if fwnode is still not set, try to get it from the device and only then check of_xlate and fwnode_xlate and either assign fwnode_reset_n_cells from OF or default to fwnode_reset_simple_xlate and fwnode_reset_n_cells = 1. Fixes: ba8dbbb14b7e ("reset: convert the core API to using firmware nodes") Reported-by: Mark Brown Closes: https://lore.kernel.org/all/0b72286b-33dd-4bc9-8c0e-161c2f4baed8@sirena.org.uk/ Signed-off-by: Bartosz Golaszewski Tested-by: Mark Brown Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 726b7346b148..a0d8c68f2afc 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -132,20 +132,21 @@ int reset_controller_register(struct reset_controller_dev *rcdev) if ((rcdev->of_node && rcdev->fwnode) || (rcdev->of_xlate && rcdev->fwnode_xlate)) return -EINVAL; - if (!rcdev->of_node && !rcdev->fwnode) { + if (rcdev->of_node && !rcdev->fwnode) + rcdev->fwnode = of_fwnode_handle(rcdev->of_node); + + if (!rcdev->fwnode) { rcdev->fwnode = dev_fwnode(rcdev->dev); if (!rcdev->fwnode) return -EINVAL; } - if (rcdev->of_node) { - rcdev->fwnode = of_fwnode_handle(rcdev->of_node); + if (rcdev->of_xlate) rcdev->fwnode_reset_n_cells = rcdev->of_reset_n_cells; - } - if (rcdev->fwnode && !rcdev->fwnode_xlate) { - rcdev->fwnode_reset_n_cells = 1; + if (!rcdev->fwnode_xlate && !rcdev->of_xlate) { rcdev->fwnode_xlate = fwnode_reset_simple_xlate; + rcdev->fwnode_reset_n_cells = 1; } INIT_LIST_HEAD(&rcdev->reset_control_head); From e416e7fa417b2d2604c1526a2f9cc38da7ced166 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 10 Mar 2026 22:29:53 -0700 Subject: [PATCH 079/193] tee: clean up tee_core.h kernel-doc Use the correct struct member name and function parameter name in kernel-doc comments. Move a macro that was between a struct's documentation and its declaration. These eliminate the following kernel-doc warnings: Warning: include/linux/tee_core.h:73 struct member 'c_no_users' not described in 'tee_device' Warning: include/linux/tee_core.h:132 #define TEE_DESC_PRIVILEGED 0x1; error: Cannot parse struct or union! Warning: include/linux/tee_core.h:257 function parameter 'connection_data' not described in 'tee_session_calc_client_uuid' Warning: include/linux/tee_core.h:320 function parameter 'teedev' not described in 'tee_get_drvdata' Signed-off-by: Randy Dunlap Reviewed-by: Sumit Garg Signed-off-by: Jens Wiklander --- include/linux/tee_core.h | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h index ee5f0bd41f43..f993d5118edd 100644 --- a/include/linux/tee_core.h +++ b/include/linux/tee_core.h @@ -50,7 +50,7 @@ enum tee_dma_heap_id { * @dev: embedded basic device structure * @cdev: embedded cdev * @num_users: number of active users of this device - * @c_no_user: completion used when unregistering the device + * @c_no_users: completion used when unregistering the device * @mutex: mutex protecting @num_users and @idr * @idr: register of user space shared memory objects allocated or * registered on this device @@ -132,6 +132,7 @@ struct tee_driver_ops { /* Size for TEE revision string buffer used by get_tee_revision(). */ #define TEE_REVISION_STR_SIZE 128 +#define TEE_DESC_PRIVILEGED 0x1 /** * struct tee_desc - Describes the TEE driver to the subsystem * @name: name of driver @@ -139,7 +140,6 @@ struct tee_driver_ops { * @owner: module providing the driver * @flags: Extra properties of driver, defined by TEE_DESC_* below */ -#define TEE_DESC_PRIVILEGED 0x1 struct tee_desc { const char *name; const struct tee_driver_ops *ops; @@ -187,7 +187,7 @@ struct tee_protmem_pool_ops { * Allocates a new struct tee_device instance. The device is * removed by tee_device_unregister(). * - * @returns a pointer to a 'struct tee_device' or an ERR_PTR on failure + * @returns: a pointer to a 'struct tee_device' or an ERR_PTR on failure */ struct tee_device *tee_device_alloc(const struct tee_desc *teedesc, struct device *dev, @@ -201,7 +201,7 @@ struct tee_device *tee_device_alloc(const struct tee_desc *teedesc, * tee_device_unregister() need to be called to remove the @teedev if * this function fails. * - * @returns < 0 on failure + * @returns: < 0 on failure */ int tee_device_register(struct tee_device *teedev); @@ -254,14 +254,14 @@ void tee_device_set_dev_groups(struct tee_device *teedev, * tee_session_calc_client_uuid() - Calculates client UUID for session * @uuid: Resulting UUID * @connection_method: Connection method for session (TEE_IOCTL_LOGIN_*) - * @connectuon_data: Connection data for opening session + * @connection_data: Connection data for opening session * * Based on connection method calculates UUIDv5 based client UUID. * * For group based logins verifies that calling process has specified * credentials. * - * @return < 0 on failure + * @returns: < 0 on failure */ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method, const u8 connection_data[TEE_IOCTL_UUID_LEN]); @@ -295,7 +295,7 @@ struct tee_shm_pool_ops { * @paddr: Physical address of start of pool * @size: Size in bytes of the pool * - * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. + * @returns: pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. */ struct tee_shm_pool *tee_shm_pool_alloc_res_mem(unsigned long vaddr, phys_addr_t paddr, size_t size, @@ -318,14 +318,16 @@ static inline void tee_shm_pool_free(struct tee_shm_pool *pool) * @paddr: Physical address of start of pool * @size: Size in bytes of the pool * - * @returns pointer to a 'struct tee_protmem_pool' or an ERR_PTR on failure. + * @returns: pointer to a 'struct tee_protmem_pool' or an ERR_PTR on failure. */ struct tee_protmem_pool *tee_protmem_static_pool_alloc(phys_addr_t paddr, size_t size); /** * tee_get_drvdata() - Return driver_data pointer - * @returns the driver_data pointer supplied to tee_register(). + * @teedev: Pointer to the tee_device + * + * @returns: the driver_data pointer supplied to tee_register(). */ void *tee_get_drvdata(struct tee_device *teedev); @@ -334,7 +336,7 @@ void *tee_get_drvdata(struct tee_device *teedev); * TEE driver * @ctx: The TEE context for shared memory allocation * @size: Shared memory allocation size - * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure + * @returns: a pointer to 'struct tee_shm' on success or an ERR_PTR on failure */ struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size); @@ -354,7 +356,7 @@ void tee_dyn_shm_free_helper(struct tee_shm *shm, /** * tee_shm_is_dynamic() - Check if shared memory object is of the dynamic kind * @shm: Shared memory handle - * @returns true if object is dynamic shared memory + * @returns: true if object is dynamic shared memory */ static inline bool tee_shm_is_dynamic(struct tee_shm *shm) { @@ -370,7 +372,7 @@ void tee_shm_put(struct tee_shm *shm); /** * tee_shm_get_id() - Get id of a shared memory object * @shm: Shared memory handle - * @returns id + * @returns: id */ static inline int tee_shm_get_id(struct tee_shm *shm) { @@ -382,7 +384,7 @@ static inline int tee_shm_get_id(struct tee_shm *shm) * count * @ctx: Context owning the shared memory * @id: Id of shared memory object - * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure + * @returns: a pointer to 'struct tee_shm' on success or an ERR_PTR on failure */ struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id); @@ -402,7 +404,7 @@ static inline bool tee_param_is_memref(struct tee_param *param) * teedev_open() - Open a struct tee_device * @teedev: Device to open * - * @return a pointer to struct tee_context on success or an ERR_PTR on failure. + * @returns: pointer to struct tee_context on success or an ERR_PTR on failure. */ struct tee_context *teedev_open(struct tee_device *teedev); From 1b7c834dedf9933447c424bfa01348f9dc3db4d1 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 4 Mar 2026 15:44:22 +0100 Subject: [PATCH 080/193] MAINTAINERS: Add i.MX team to all arm NXP platforms i.MX team maintains layerscape as well, so add the whole arch/arm/boot/dts/nxp directory as requested in [1]. [1] https://lore.kernel.org/all/Z+Vs+pHZs2fMP%2Fp3@lizhi-Precision-Tower-5810/ Signed-off-by: Alexander Stein Reviewed-by: Frank Li Acked-by: Daniel Baluta Signed-off-by: Frank Li --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 55af015174a5..057de78edd77 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2806,8 +2806,7 @@ S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/frank.li/linux.git F: Documentation/devicetree/bindings/firmware/fsl* F: Documentation/devicetree/bindings/firmware/nxp* -F: arch/arm/boot/dts/nxp/imx/ -F: arch/arm/boot/dts/nxp/mxs/ +F: arch/arm/boot/dts/nxp/ F: arch/arm64/boot/dts/freescale/ X: Documentation/devicetree/bindings/media/i2c/ X: arch/arm64/boot/dts/freescale/fsl-* From 8a9a7b9d14c21d060301a8dd4a676ccb4ade5870 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Tue, 27 Jan 2026 16:08:45 +0530 Subject: [PATCH 081/193] soc: qcom: smp2p: Add irqchip state support A remoteproc booted during earlier boot stages such as UEFI or the bootloader, may need to be attached to without restarting the remoteproc hardware. To do this the remoteproc will need to check the ready and handover states in smp2p without an interrupt notification. Create qcom_smp2p_start_in() to initialize the shadow state without notifying clients because these early events happened in the past. Add support for the .irq_get_irqchip_state callback so remoteproc can read the current state of the fatal, ready and handover bits. Signed-off-by: Chris Lew Signed-off-by: Deepak Kumar Singh Link: https://lore.kernel.org/r/20260127-smp2pv2-v3-1-4060b859b1e2@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smp2p.c | 55 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index cb515c2340c1..c27ffb44b825 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -222,6 +222,39 @@ static void qcom_smp2p_negotiate(struct qcom_smp2p *smp2p) } } +static void qcom_smp2p_start_in(struct qcom_smp2p *smp2p) +{ + unsigned int smem_id = smp2p->smem_items[SMP2P_INBOUND]; + unsigned int pid = smp2p->remote_pid; + char buf[SMP2P_MAX_ENTRY_NAME]; + struct smp2p_smem_item *in; + struct smp2p_entry *entry; + size_t size; + int i; + + in = qcom_smem_get(pid, smem_id, &size); + if (IS_ERR(in)) + return; + + smp2p->in = in; + + /* Check if version is initialized by the remote. */ + if (in->version == 0) + return; + + for (i = smp2p->valid_entries; i < in->valid_entries; i++) { + 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->last_value = readl(entry->value); + break; + } + } + } + smp2p->valid_entries = i; +} + static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p) { struct smp2p_smem_item *in; @@ -368,12 +401,31 @@ static void smp2p_irq_print_chip(struct irq_data *irqd, struct seq_file *p) seq_printf(p, "%8s", dev_name(entry->smp2p->dev)); } +static int smp2p_irq_get_irqchip_state(struct irq_data *irqd, enum irqchip_irq_state which, + bool *state) +{ + struct smp2p_entry *entry = irq_data_get_irq_chip_data(irqd); + u32 val; + + if (which != IRQCHIP_STATE_LINE_LEVEL) + return -EINVAL; + + if (!entry->value) + return -ENODEV; + + val = readl(entry->value); + *state = !!(val & BIT(irqd_to_hwirq(irqd))); + + return 0; +} + static struct irq_chip smp2p_irq_chip = { .name = "smp2p", .irq_mask = smp2p_mask_irq, .irq_unmask = smp2p_unmask_irq, .irq_set_type = smp2p_set_irq_type, .irq_print_chip = smp2p_irq_print_chip, + .irq_get_irqchip_state = smp2p_irq_get_irqchip_state, }; static int smp2p_irq_map(struct irq_domain *d, @@ -618,6 +670,9 @@ static int qcom_smp2p_probe(struct platform_device *pdev) } } + /* Check inbound entries in the case of early boot processor */ + qcom_smp2p_start_in(smp2p); + /* Kick the outgoing edge after allocating entries */ qcom_smp2p_kick(smp2p); From 42c4cf5d482813067789dd5ea2e33f3b7805e7e1 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Tue, 27 Jan 2026 16:08:46 +0530 Subject: [PATCH 082/193] soc: qcom: smp2p: Add support for smp2p v2 smp2p v2 adds support for allowing remote processors to write outbound smp2p items without completing the feature negotiation. This is required for processors that start before linux to write out signals like error and clock ready and unblock their bootup. If a remote processor only supports v1, smp2p can version down by mirroring the peer version during the negotiation stage. When using smp2p version 2, the remote does not wait for the ssr ack before setting the items. To accommodate this, set the last_value of all the entries to 0 when SSR is detected. This forces smp2p to detect the new values written by the remote. Because the SSR ack is skipped, the down transition of bits is missed in smp2p version 2. Signed-off-by: Chris Lew Signed-off-by: Deepak Kumar Singh Link: https://lore.kernel.org/r/20260127-smp2pv2-v3-2-4060b859b1e2@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smp2p.c | 48 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index c27ffb44b825..af0ceeaf6e07 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -36,6 +36,10 @@ * The driver uses the Linux GPIO and interrupt framework to expose a virtual * GPIO for each outbound entry and a virtual interrupt controller for each * inbound entry. + * + * V2 of SMP2P allows remote processors to write to outbound smp2p items before + * the full smp2p connection is negotiated. This is important for processors + * started before linux runs. */ #define SMP2P_MAX_ENTRY 16 @@ -47,11 +51,12 @@ #define SMP2P_MAGIC 0x504d5324 #define SMP2P_ALL_FEATURES SMP2P_FEATURE_SSR_ACK +#define MAX_VERSION 2 /** * struct smp2p_smem_item - in memory communication structure * @magic: magic number - * @version: version - must be 1 + * @version: version * @features: features flag - currently unused * @local_pid: processor id of sending end * @remote_pid: processor id of receiving end @@ -180,14 +185,22 @@ static void qcom_smp2p_kick(struct qcom_smp2p *smp2p) static bool qcom_smp2p_check_ssr(struct qcom_smp2p *smp2p) { struct smp2p_smem_item *in = smp2p->in; + struct smp2p_entry *entry; + bool restart_done; bool restart; if (!smp2p->ssr_ack_enabled) return false; - restart = in->flags & BIT(SMP2P_FLAGS_RESTART_DONE_BIT); + restart_done = in->flags & BIT(SMP2P_FLAGS_RESTART_DONE_BIT); + restart = restart_done != smp2p->ssr_ack; + list_for_each_entry(entry, &smp2p->inbound, node) { + if (!entry->value) + continue; + entry->last_value = 0; + } - return restart != smp2p->ssr_ack; + return restart; } static void qcom_smp2p_do_ssr_ack(struct qcom_smp2p *smp2p) @@ -219,9 +232,26 @@ static void qcom_smp2p_negotiate(struct qcom_smp2p *smp2p) smp2p->negotiation_done = true; trace_smp2p_negotiate(smp2p->dev, out->features); + } else if (in->version && in->version < out->version) { + out->version = in->version; + qcom_smp2p_kick(smp2p); } } +static int qcom_smp2p_in_version(struct qcom_smp2p *smp2p) +{ + unsigned int smem_id = smp2p->smem_items[SMP2P_INBOUND]; + unsigned int pid = smp2p->remote_pid; + struct smp2p_smem_item *in; + size_t size; + + in = qcom_smem_get(pid, smem_id, &size); + if (IS_ERR(in)) + return 0; + + return in->version; +} + static void qcom_smp2p_start_in(struct qcom_smp2p *smp2p) { unsigned int smem_id = smp2p->smem_items[SMP2P_INBOUND]; @@ -516,6 +546,7 @@ static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p) struct smp2p_smem_item *out; unsigned smem_id = smp2p->smem_items[SMP2P_OUTBOUND]; unsigned pid = smp2p->remote_pid; + u8 in_version; int ret; ret = qcom_smem_alloc(pid, smem_id, sizeof(*out)); @@ -537,12 +568,21 @@ static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p) out->valid_entries = 0; out->features = SMP2P_ALL_FEATURES; + in_version = qcom_smp2p_in_version(smp2p); + if (in_version > MAX_VERSION) { + dev_err(smp2p->dev, "Unsupported smp2p version %d\n", in_version); + return -EINVAL; + } + /* * Make sure the rest of the header is written before we validate the * item by writing a valid version number. */ wmb(); - out->version = 1; + if (in_version && in_version <= 2) + out->version = in_version; + else + out->version = 2; qcom_smp2p_kick(smp2p); From 12cf1b5de820bc302f92221d87ae13ec1c760c84 Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Mon, 9 Feb 2026 21:19:55 -0500 Subject: [PATCH 083/193] dt-bindings: cache: qcom,llcc: Add SDM670 compatible Document the Last Level Cache Controller on SDM670. Signed-off-by: Richard Acayan Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260210021957.13357-2-mailingradian@gmail.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/cache/qcom,llcc.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml index 6671e461e34a..995d57815781 100644 --- a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml +++ b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml @@ -33,6 +33,7 @@ properties: - qcom,sc7280-llcc - qcom,sc8180x-llcc - qcom,sc8280xp-llcc + - qcom,sdm670-llcc - qcom,sdm845-llcc - qcom,sm6350-llcc - qcom,sm7150-llcc @@ -204,6 +205,7 @@ allOf: contains: enum: - qcom,sc7280-llcc + - qcom,sdm670-llcc then: properties: reg: From 11080cc4af8f0ee4b88d0e51384765bb78f05bf5 Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Mon, 9 Feb 2026 21:19:56 -0500 Subject: [PATCH 084/193] soc: qcom: llcc: Add configuration data for SDM670 Add system cache table and configs for the SDM670 SoC. Signed-off-by: Richard Acayan Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260210021957.13357-3-mailingradian@gmail.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 105 +++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index ad5899d083f3..e221e3c4982b 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -1782,6 +1782,94 @@ static const struct llcc_slice_config sc8280xp_data[] = { }, }; +static const struct llcc_slice_config sdm670_data[] = { + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 512, + .priority = 1, + .bonus_ways = 0xf, + .res_ways = 0x0, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_ROTATOR, + .slice_id = 4, + .max_cap = 384, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0xe, + .cache_mode = 2, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_VOICE, + .slice_id = 5, + .max_cap = 512, + .priority = 1, + .bonus_ways = 0xf, + .res_ways = 0x0, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 512, + .priority = 1, + .bonus_ways = 0xf, + .res_ways = 0x0, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDM, + .slice_id = 8, + .max_cap = 512, + .priority = 1, + .bonus_ways = 0xf, + .res_ways = 0x0, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 384, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0x0, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 512, + .priority = 1, + .bonus_ways = 0xf, + .res_ways = 0x0, + .cache_mode = 0, + .dis_cap_alloc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf, + .res_ways = 0x0, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, +}; + static const struct llcc_slice_config sdm845_data[] = {{ .usecase_id = LLCC_CPUSS, .slice_id = 1, @@ -4196,6 +4284,17 @@ static const struct qcom_llcc_config sc8280xp_cfg[] = { }, }; +static const struct qcom_llcc_config sdm670_cfg[] = { + { + .sct_data = sdm670_data, + .size = ARRAY_SIZE(sdm670_data), + .skip_llcc_cfg = true, + .reg_offset = llcc_v1_reg_offset, + .edac_reg_offset = &llcc_v1_edac_reg_offset, + .no_edac = true, + }, +}; + static const struct qcom_llcc_config sdm845_cfg[] = { { .sct_data = sdm845_data, @@ -4364,6 +4463,11 @@ static const struct qcom_sct_config sc8280xp_cfgs = { .num_config = ARRAY_SIZE(sc8280xp_cfg), }; +static const struct qcom_sct_config sdm670_cfgs = { + .llcc_config = sdm670_cfg, + .num_config = ARRAY_SIZE(sdm670_cfg), +}; + static const struct qcom_sct_config sdm845_cfgs = { .llcc_config = sdm845_cfg, .num_config = ARRAY_SIZE(sdm845_cfg), @@ -5160,6 +5264,7 @@ static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,sc7280-llcc", .data = &sc7280_cfgs }, { .compatible = "qcom,sc8180x-llcc", .data = &sc8180x_cfgs }, { .compatible = "qcom,sc8280xp-llcc", .data = &sc8280xp_cfgs }, + { .compatible = "qcom,sdm670-llcc", .data = &sdm670_cfgs }, { .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfgs }, { .compatible = "qcom,sm6350-llcc", .data = &sm6350_cfgs }, { .compatible = "qcom,sm7150-llcc", .data = &sm7150_cfgs }, From cdf0e445ee21119187f5551e68ff4e466f8aa950 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Tue, 24 Feb 2026 13:02:13 +0200 Subject: [PATCH 085/193] soc: qcom: pd-mapper: Simplify code using of_root to get root device tree node A few lines of code are removed by using the global non-NULL of_root pointer to access the root device tree node instead of its recalculation. Signed-off-by: Vladimir Zapolskiy Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260224110213.3929063-1-vladimir.zapolskiy@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_pd_mapper.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index 0bccc23c0a58..c54b3cec508d 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -626,15 +626,9 @@ static struct qcom_pdm_data *qcom_pdm_start(void) const struct qcom_pdm_domain_data * const *domains; const struct of_device_id *match; struct qcom_pdm_data *data; - struct device_node *root; int ret, i; - root = of_find_node_by_path("/"); - if (!root) - return ERR_PTR(-ENODEV); - - match = of_match_node(qcom_pdm_domains, root); - of_node_put(root); + match = of_match_node(qcom_pdm_domains, of_root); if (!match) { pr_notice("PDM: no support for the platform, userspace daemon might be required.\n"); return ERR_PTR(-ENODEV); From 583157bee545e5c2da6ae094bcac7f68dbc5d265 Mon Sep 17 00:00:00 2001 From: Aelin Reidel Date: Mon, 2 Mar 2026 14:10:14 +0100 Subject: [PATCH 086/193] dt-bindings: arm: qcom,ids: Add SoC IDs for SM7450 and SM7450P SM7450 and SM7450P are two SoCs of the 'fillmore' family. Signed-off-by: Aelin Reidel Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260302-fillmore-socids-v2-1-e6c5ad167ec4@mainlining.org Signed-off-by: Bjorn Andersson --- include/dt-bindings/arm/qcom,ids.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index febb69b0438f..4985f6afa204 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -245,6 +245,7 @@ #define QCOM_ID_IPQ5000 503 #define QCOM_ID_IPQ0509 504 #define QCOM_ID_IPQ0518 505 +#define QCOM_ID_SM7450 506 #define QCOM_ID_SM6375 507 #define QCOM_ID_IPQ9514 510 #define QCOM_ID_IPQ9550 511 @@ -264,6 +265,7 @@ #define QCOM_ID_QRU1000 539 #define QCOM_ID_SM8475_2 540 #define QCOM_ID_QDU1000 545 +#define QCOM_ID_SM7450P 547 #define QCOM_ID_X1E80100 555 #define QCOM_ID_SM8650 557 #define QCOM_ID_SM4450 568 From 3fa036c08938d37c4bc79d125974bb87b4122ac4 Mon Sep 17 00:00:00 2001 From: Aelin Reidel Date: Mon, 2 Mar 2026 14:10:15 +0100 Subject: [PATCH 087/193] soc: qcom: socinfo: Add SoC IDs for SM7450 and SM7450P SM7450 and SM7450P are two SoCs in the 'fillmore' family. Signed-off-by: Aelin Reidel Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260302-fillmore-socids-v2-2-e6c5ad167ec4@mainlining.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 41867601d250..f21c6d5c4905 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -473,6 +473,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(IPQ5000) }, { qcom_board_id(IPQ0509) }, { qcom_board_id(IPQ0518) }, + { qcom_board_id(SM7450) }, { qcom_board_id(SM6375) }, { qcom_board_id(IPQ9514) }, { qcom_board_id(IPQ9550) }, @@ -492,6 +493,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QRU1000) }, { qcom_board_id(SM8475_2) }, { qcom_board_id(QDU1000) }, + { qcom_board_id(SM7450P) }, { qcom_board_id(X1E80100) }, { qcom_board_id(SM8650) }, { qcom_board_id(SM4450) }, From 45c2a55d13c698ba6a281315676934c44225b034 Mon Sep 17 00:00:00 2001 From: Unnathi Chalicheemala Date: Thu, 5 Mar 2026 19:12:05 -0800 Subject: [PATCH 088/193] soc: qcom: llcc: Add per-slice counter and common llcc slice descriptor Fix incorrect slice activation/deactivation accounting by replacing the bitmap-based activation tracking with per-slice atomic reference counters. This resolves mismatches that occur when multiple client drivers vote for the same slice or when llcc_slice_getd() is called multiple times. As part of this fix, simplify slice descriptor handling by eliminating dynamic allocation. llcc_slice_getd() now returns a pointer to a preallocated descriptor, removing the need for repeated allocation/free cycles and ensuring consistent reference tracking across all users. Signed-off-by: Unnathi Chalicheemala Signed-off-by: Francisco Munoz Ruiz Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260305-external_llcc_changes1set-v1-1-6347e52e648e@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 57 +++++++++++++++--------------- include/linux/soc/qcom/llcc-qcom.h | 8 ++--- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index e221e3c4982b..8fdca7658393 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -5,7 +5,6 @@ */ #include -#include #include #include #include @@ -4535,8 +4534,7 @@ static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER; struct llcc_slice_desc *llcc_slice_getd(u32 uid) { const struct llcc_slice_config *cfg; - struct llcc_slice_desc *desc; - u32 sz, count; + u32 sz, i; if (IS_ERR(drv_data)) return ERR_CAST(drv_data); @@ -4544,21 +4542,14 @@ struct llcc_slice_desc *llcc_slice_getd(u32 uid) cfg = drv_data->cfg; sz = drv_data->cfg_size; - for (count = 0; cfg && count < sz; count++, cfg++) + for (i = 0; cfg && i < sz; i++, cfg++) if (cfg->usecase_id == uid) break; - if (count == sz || !cfg) + if (i == sz) return ERR_PTR(-ENODEV); - desc = kzalloc_obj(*desc); - if (!desc) - return ERR_PTR(-ENOMEM); - - desc->slice_id = cfg->slice_id; - desc->slice_size = cfg->max_cap; - - return desc; + return &drv_data->desc[i]; } EXPORT_SYMBOL_GPL(llcc_slice_getd); @@ -4569,7 +4560,7 @@ EXPORT_SYMBOL_GPL(llcc_slice_getd); void llcc_slice_putd(struct llcc_slice_desc *desc) { if (!IS_ERR_OR_NULL(desc)) - kfree(desc); + return; } EXPORT_SYMBOL_GPL(llcc_slice_putd); @@ -4645,7 +4636,8 @@ int llcc_slice_activate(struct llcc_slice_desc *desc) return -EINVAL; mutex_lock(&drv_data->lock); - if (test_bit(desc->slice_id, drv_data->bitmap)) { + /* Already active; try to take another reference. */ + if (refcount_inc_not_zero(&desc->refcount)) { mutex_unlock(&drv_data->lock); return 0; } @@ -4659,7 +4651,8 @@ int llcc_slice_activate(struct llcc_slice_desc *desc) return ret; } - __set_bit(desc->slice_id, drv_data->bitmap); + /* Set first reference */ + refcount_set(&desc->refcount, 1); mutex_unlock(&drv_data->lock); return ret; @@ -4685,10 +4678,12 @@ int llcc_slice_deactivate(struct llcc_slice_desc *desc) return -EINVAL; mutex_lock(&drv_data->lock); - if (!test_bit(desc->slice_id, drv_data->bitmap)) { + /* refcount > 1, drop one ref and we’re done. */ + if (refcount_dec_not_one(&desc->refcount)) { mutex_unlock(&drv_data->lock); return 0; } + act_ctrl_val = ACT_CTRL_OPCODE_DEACTIVATE << ACT_CTRL_OPCODE_SHIFT; ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val, @@ -4698,7 +4693,8 @@ int llcc_slice_deactivate(struct llcc_slice_desc *desc) return ret; } - __clear_bit(desc->slice_id, drv_data->bitmap); + /* Finalize: atomically transition 1 -> 0 */ + WARN_ON_ONCE(!refcount_dec_if_one(&desc->refcount)); mutex_unlock(&drv_data->lock); return ret; @@ -4742,7 +4738,7 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, u32 attr1_val; u32 attr0_val; u32 max_cap_cacheline; - struct llcc_slice_desc desc; + struct llcc_slice_desc *desc; attr1_val = config->cache_mode; attr1_val |= config->probe_target_ways << ATTR1_PROBE_TARGET_WAYS_SHIFT; @@ -4891,8 +4887,11 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, } if (config->activate_on_init) { - desc.slice_id = config->slice_id; - ret = llcc_slice_activate(&desc); + desc = llcc_slice_getd(config->usecase_id); + if (IS_ERR(desc)) + return PTR_ERR(desc); + + ret = llcc_slice_activate(desc); } return ret; @@ -5205,18 +5204,18 @@ static int qcom_llcc_probe(struct platform_device *pdev) llcc_cfg = cfg->sct_data; sz = cfg->size; - - for (i = 0; i < sz; i++) - if (llcc_cfg[i].slice_id > drv_data->max_slices) - drv_data->max_slices = llcc_cfg[i].slice_id; - - drv_data->bitmap = devm_bitmap_zalloc(dev, drv_data->max_slices, - GFP_KERNEL); - if (!drv_data->bitmap) { + drv_data->desc = devm_kcalloc(dev, sz, sizeof(struct llcc_slice_desc), GFP_KERNEL); + if (!drv_data->desc) { ret = -ENOMEM; goto err; } + for (i = 0; i < sz; i++) { + drv_data->desc[i].slice_id = llcc_cfg[i].slice_id; + drv_data->desc[i].slice_size = llcc_cfg[i].max_cap; + refcount_set(&drv_data->desc[i].refcount, 0); + } + drv_data->cfg = llcc_cfg; drv_data->cfg_size = sz; drv_data->edac_reg_offset = cfg->edac_reg_offset; diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h index 8243ab3a12a8..227125d84318 100644 --- a/include/linux/soc/qcom/llcc-qcom.h +++ b/include/linux/soc/qcom/llcc-qcom.h @@ -91,10 +91,12 @@ * struct llcc_slice_desc - Cache slice descriptor * @slice_id: llcc slice id * @slice_size: Size allocated for the llcc slice + * @refcount: Atomic counter to track activate/deactivate calls */ struct llcc_slice_desc { u32 slice_id; size_t slice_size; + refcount_t refcount; }; /** @@ -152,11 +154,10 @@ struct llcc_edac_reg_offset { * @edac_reg_offset: Offset of the LLCC EDAC registers * @lock: mutex associated with each slice * @cfg_size: size of the config data table - * @max_slices: max slices as read from device tree * @num_banks: Number of llcc banks - * @bitmap: Bit map to track the active slice ids * @ecc_irq: interrupt for llcc cache error detection and reporting * @ecc_irq_configured: 'True' if firmware has already configured the irq propagation + * @desc: Array pointer of pre-allocated LLCC slice descriptors * @version: Indicates the LLCC version */ struct llcc_drv_data { @@ -167,12 +168,11 @@ struct llcc_drv_data { const struct llcc_edac_reg_offset *edac_reg_offset; struct mutex lock; u32 cfg_size; - u32 max_slices; u32 num_banks; - unsigned long *bitmap; int ecc_irq; bool ecc_irq_configured; u32 version; + struct llcc_slice_desc *desc; }; #if IS_ENABLED(CONFIG_QCOM_LLCC) From eda32f68ce7a3d16071870c7af0803fdfae40401 Mon Sep 17 00:00:00 2001 From: Unnathi Chalicheemala Date: Thu, 5 Mar 2026 19:12:06 -0800 Subject: [PATCH 089/193] soc: qcom: llcc: Use guards for mutex handling Replacing manual lock/unlock pairs with guard() removes the need to think about unlocking entirely and keeps the function trivially structured. Signed-off-by: Unnathi Chalicheemala Signed-off-by: Francisco Munoz Ruiz Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260305-external_llcc_changes1set-v1-2-6347e52e648e@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 8fdca7658393..68a3416692e0 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -4635,27 +4635,21 @@ int llcc_slice_activate(struct llcc_slice_desc *desc) if (IS_ERR_OR_NULL(desc)) return -EINVAL; - mutex_lock(&drv_data->lock); + guard(mutex)(&drv_data->lock); /* Already active; try to take another reference. */ - if (refcount_inc_not_zero(&desc->refcount)) { - mutex_unlock(&drv_data->lock); + if (refcount_inc_not_zero(&desc->refcount)) return 0; - } act_ctrl_val = ACT_CTRL_OPCODE_ACTIVATE << ACT_CTRL_OPCODE_SHIFT; - ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val, DEACTIVATE); - if (ret) { - mutex_unlock(&drv_data->lock); + if (ret) return ret; - } /* Set first reference */ refcount_set(&desc->refcount, 1); - mutex_unlock(&drv_data->lock); - return ret; + return 0; } EXPORT_SYMBOL_GPL(llcc_slice_activate); @@ -4677,27 +4671,21 @@ int llcc_slice_deactivate(struct llcc_slice_desc *desc) if (IS_ERR_OR_NULL(desc)) return -EINVAL; - mutex_lock(&drv_data->lock); + guard(mutex)(&drv_data->lock); /* refcount > 1, drop one ref and we’re done. */ - if (refcount_dec_not_one(&desc->refcount)) { - mutex_unlock(&drv_data->lock); + if (refcount_dec_not_one(&desc->refcount)) return 0; - } act_ctrl_val = ACT_CTRL_OPCODE_DEACTIVATE << ACT_CTRL_OPCODE_SHIFT; - ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val, ACTIVATE); - if (ret) { - mutex_unlock(&drv_data->lock); + if (ret) return ret; - } /* Finalize: atomically transition 1 -> 0 */ WARN_ON_ONCE(!refcount_dec_if_one(&desc->refcount)); - mutex_unlock(&drv_data->lock); - return ret; + return 0; } EXPORT_SYMBOL_GPL(llcc_slice_deactivate); From e4ee7621d732162ea2ec714ae76dac2f70519417 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Tue, 10 Mar 2026 00:03:30 +0100 Subject: [PATCH 090/193] soc: qcom: qmi: Enumerate the service IDs of QMI The QMI framework proposes a set of services which are defined by an integer identifier. The different QMI client lookup for the services via this identifier. Moreover, the function qmi_add_lookup() and qmi_add_server() must match the service ID but the code in different places set the same value but with a different macro name. These macros are spreaded across the different subsystems implementing the protocols associated with a service. It would make more sense to define them in the QMI header for the sake of consistency and clarity. This change use an unified naming for the services and enumerate the ones implemented in the Linux kernel. More services can come later and put the service ID in this same header. Signed-off-by: Daniel Lezcano Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260309230346.3584252-2-daniel.lezcano@oss.qualcomm.com [bjorn: Lower case hex constants] Signed-off-by: Bjorn Andersson --- include/linux/soc/qcom/qmi.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/linux/soc/qcom/qmi.h b/include/linux/soc/qcom/qmi.h index 291cdc7ef49c..b9dcb437a0be 100644 --- a/include/linux/soc/qcom/qmi.h +++ b/include/linux/soc/qcom/qmi.h @@ -92,6 +92,18 @@ struct qmi_elem_info { #define QMI_ERR_INCOMPATIBLE_STATE_V01 90 #define QMI_ERR_NOT_SUPPORTED_V01 94 +/* + * Enumerate the IDs of the QMI services + */ +#define QMI_SERVICE_ID_TEST 0x0f /* 15 */ +#define QMI_SERVICE_ID_SSCTL 0x2b /* 43 */ +#define QMI_SERVICE_ID_IPA 0x31 /* 49 */ +#define QMI_SERVICE_ID_SERVREG_LOC 0x40 /* 64 */ +#define QMI_SERVICE_ID_SERVREG_NOTIF 0x42 /* 66 */ +#define QMI_SERVICE_ID_WLFW 0x45 /* 69 */ +#define QMI_SERVICE_ID_SLIMBUS 0x301 /* 769 */ +#define QMI_SERVICE_ID_USB_AUDIO_STREAM 0x41d /* 1053 */ + /** * struct qmi_response_type_v01 - common response header (decoded) * @result: result of the transaction From 24f80cbe0b8f4c6b27d03c7a7ad707d76c1c4885 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Tue, 10 Mar 2026 00:03:35 +0100 Subject: [PATCH 091/193] soc: qcom: pdr: Use the unified QMI service ID instead of defining it locally Instead of defining a local macro with a custom name for the QMI service identifier, use the one provided in qmi.h and remove the locally defined macro. Signed-off-by: Daniel Lezcano Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260309230346.3584252-7-daniel.lezcano@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pdr_interface.c | 4 ++-- drivers/soc/qcom/pdr_internal.h | 3 --- drivers/soc/qcom/qcom_pd_mapper.c | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c index 72259f489075..6d879e1540b0 100644 --- a/drivers/soc/qcom/pdr_interface.c +++ b/drivers/soc/qcom/pdr_interface.c @@ -523,7 +523,7 @@ struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr, if (!pds) return ERR_PTR(-ENOMEM); - pds->service = SERVREG_NOTIFIER_SERVICE; + pds->service = QMI_SERVICE_ID_SERVREG_NOTIF; strscpy(pds->service_name, service_name, sizeof(pds->service_name)); strscpy(pds->service_path, service_path, sizeof(pds->service_path)); pds->need_locator_lookup = true; @@ -678,7 +678,7 @@ struct pdr_handle *pdr_handle_alloc(void (*status)(int state, if (ret < 0) goto destroy_indack; - ret = qmi_add_lookup(&pdr->locator_hdl, SERVREG_LOCATOR_SERVICE, 1, 1); + ret = qmi_add_lookup(&pdr->locator_hdl, QMI_SERVICE_ID_SERVREG_LOC, 1, 1); if (ret < 0) goto release_qmi_handle; diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h index 039508c1bbf7..6cd8cbe26822 100644 --- a/drivers/soc/qcom/pdr_internal.h +++ b/drivers/soc/qcom/pdr_internal.h @@ -4,9 +4,6 @@ #include -#define SERVREG_LOCATOR_SERVICE 0x40 -#define SERVREG_NOTIFIER_SERVICE 0x42 - #define SERVREG_REGISTER_LISTENER_REQ 0x20 #define SERVREG_GET_DOMAIN_LIST_REQ 0x21 #define SERVREG_STATE_UPDATED_IND_ID 0x22 diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index c54b3cec508d..21e4dd594295 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -661,7 +661,7 @@ static struct qcom_pdm_data *qcom_pdm_start(void) goto err_stop; } - ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE, + ret = qmi_add_server(&data->handle, QMI_SERVICE_ID_SERVREG_LOC, SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE); if (ret) { pr_err("PDM: error adding server %d\n", ret); From 8baf6b3b7695849581a91bdaf66af2be68ef32ed Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Tue, 10 Mar 2026 00:03:37 +0100 Subject: [PATCH 092/193] samples: qmi: Use the unified QMI service ID instead of defining it locally Instead of defining a local macro with a custom name for the QMI service identifier, use the one provided in qmi.h and remove the locally defined macro. Signed-off-by: Daniel Lezcano Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260309230346.3584252-9-daniel.lezcano@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- samples/qmi/qmi_sample_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/qmi/qmi_sample_client.c b/samples/qmi/qmi_sample_client.c index d1814582319b..247ec5e54c4f 100644 --- a/samples/qmi/qmi_sample_client.c +++ b/samples/qmi/qmi_sample_client.c @@ -592,7 +592,7 @@ static int qmi_sample_init(void) if (ret < 0) goto err_unregister_driver; - qmi_add_lookup(&lookup_client, 15, 0, 0); + qmi_add_lookup(&lookup_client, QMI_SERVICE_ID_TEST, 0, 0); return 0; From 508e58ac65eec4e272f89e39d9b64588f7fe21cc Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Fri, 13 Mar 2026 21:32:56 +0530 Subject: [PATCH 093/193] dt-bindings: arm: qcom,ids: add SOC IDs for IPQ5210 family SoCs based on IPQ5210 is shipped under two different naming schemes namely IPQ52xx and QCF2xxx/QCF3xxx. In the later variants Passive Optical Network (PON) interface acts as the backhaul where as in the former it is ethernet backhaul. Document the same. Signed-off-by: Kathiravan Thirumoorthy Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260313-b4-ipq5210_soc_ids-v1-1-97faae3fef95@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- include/dt-bindings/arm/qcom,ids.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index 4985f6afa204..0316b85747d9 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -298,6 +298,11 @@ #define QCOM_ID_QCS615 680 #define QCOM_ID_CQ7790M 731 #define QCOM_ID_CQ7790S 732 +#define QCOM_ID_IPQ5200 765 +#define QCOM_ID_IPQ5210 766 +#define QCOM_ID_QCF2200 767 +#define QCOM_ID_QCF3200 768 +#define QCOM_ID_QCF3210 769 /* * The board type and revision information, used by Qualcomm bootloaders and From 5a679430cf1def009b5c5cb821cad46be450c149 Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Fri, 13 Mar 2026 21:32:57 +0530 Subject: [PATCH 094/193] soc: qcom: socinfo: add SoC ID for IPQ5210 family SoCs based on IPQ5210 is shipped under two different naming schemes namely IPQ52xx and QCF2xxx/QCF3xxx. In the later variants Passive Optical Network (PON) interface acts as the backhaul where as in the former it is ethernet backhaul. Add the SoC IDs for the same. Signed-off-by: Kathiravan Thirumoorthy Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260313-b4-ipq5210_soc_ids-v1-2-97faae3fef95@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index f21c6d5c4905..c7298e8f716e 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -526,6 +526,11 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QCS615) }, { qcom_board_id(CQ7790M) }, { qcom_board_id(CQ7790S) }, + { qcom_board_id(IPQ5200) }, + { qcom_board_id(IPQ5210) }, + { qcom_board_id(QCF2200) }, + { qcom_board_id(QCF3200) }, + { qcom_board_id(QCF3210) }, }; static const char *socinfo_machine(struct device *dev, unsigned int id) From a01c4cd7e2f7812bb5c87a73d0fb9cb501e7cabd Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 9 Mar 2026 16:59:44 +0000 Subject: [PATCH 095/193] soc: renesas: r9a09g057-sys: Mark rzv2h_sys_init_data as __initconst Annotate rzv2h_sys_init_data with __initconst as it is only used during initialization. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Reviewed-by: Claudiu Beznea Link: https://patch.msgid.link/20260309165946.3003731-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/r9a09g057-sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/renesas/r9a09g057-sys.c b/drivers/soc/renesas/r9a09g057-sys.c index 827c718ac7c5..f3e054206acb 100644 --- a/drivers/soc/renesas/r9a09g057-sys.c +++ b/drivers/soc/renesas/r9a09g057-sys.c @@ -161,7 +161,7 @@ static bool rzv2h_regmap_writeable_reg(struct device *dev, unsigned int reg) } } -const struct rz_sysc_init_data rzv2h_sys_init_data = { +const struct rz_sysc_init_data rzv2h_sys_init_data __initconst = { .soc_id_init_data = &rzv2h_sys_soc_id_init_data, .readable_reg = rzv2h_regmap_readable_reg, .writeable_reg = rzv2h_regmap_writeable_reg, From 71e94c79606c5e6ca0c3ae41b6a9ce8b13c721b4 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 9 Mar 2026 16:59:45 +0000 Subject: [PATCH 096/193] soc: renesas: r9a09g047-sys: Mark rzg3e_sys_init_data as __initconst Annotate rzg3e_sys_init_data with __initconst as it is only used during initialization. Signed-off-by: Lad Prabhakar Reviewed-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260309165946.3003731-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/r9a09g047-sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/renesas/r9a09g047-sys.c b/drivers/soc/renesas/r9a09g047-sys.c index e413b0eff9bf..ea3ca10fcc33 100644 --- a/drivers/soc/renesas/r9a09g047-sys.c +++ b/drivers/soc/renesas/r9a09g047-sys.c @@ -139,7 +139,7 @@ static bool rzg3e_regmap_writeable_reg(struct device *dev, unsigned int reg) } } -const struct rz_sysc_init_data rzg3e_sys_init_data = { +const struct rz_sysc_init_data rzg3e_sys_init_data __initconst = { .soc_id_init_data = &rzg3e_sys_soc_id_init_data, .readable_reg = rzg3e_regmap_readable_reg, .writeable_reg = rzg3e_regmap_writeable_reg, From abf3502033cfc2797126f054eb081857f8e7e939 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 9 Mar 2026 16:59:46 +0000 Subject: [PATCH 097/193] soc: renesas: r9a09g056-sys: Mark rzv2n_sys_init_data as __initconst Annotate rzv2n_sys_init_data with __initconst as it is only used during initialization. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Reviewed-by: Claudiu Beznea Link: https://patch.msgid.link/20260309165946.3003731-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/r9a09g056-sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/renesas/r9a09g056-sys.c b/drivers/soc/renesas/r9a09g056-sys.c index 42f5eff291fd..2a8ebc209961 100644 --- a/drivers/soc/renesas/r9a09g056-sys.c +++ b/drivers/soc/renesas/r9a09g056-sys.c @@ -136,7 +136,7 @@ static bool rzv2n_regmap_writeable_reg(struct device *dev, unsigned int reg) } } -const struct rz_sysc_init_data rzv2n_sys_init_data = { +const struct rz_sysc_init_data rzv2n_sys_init_data __initconst = { .soc_id_init_data = &rzv2n_sys_soc_id_init_data, .readable_reg = rzv2n_regmap_readable_reg, .writeable_reg = rzv2n_regmap_writeable_reg, From 0a7ec808abecaf0d5c3ecc0d1b87d58f29c85604 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 16 Mar 2026 16:34:40 +0100 Subject: [PATCH 098/193] firmware: arm_scmi: Support loop control in quirk code snippets Each SCMI firmware quirk contains a code snippet, which handles the quirk, and has full access to the surrounding context. When this context is (part of) a loop body, the code snippet may want to use loop control statements like "break" and "continue". Unfortunately the SCMI_QUIRK() macro implementation contains a dummy loop, taking precedence over any outer loops. Hence quirk code cannot use loop control statements, but has to resort to polluting the surrounding context with a label, and use goto. Fix this by replacing the "do { ... } while (0)" construct in the SCMI_QUIRK() implementation by "({ ... })". Signed-off-by: Geert Uytterhoeven Reviewed-by: Cristian Marussi Reviewed-by: Peng Fan Message-Id: <51de914cddef8fa86c2e7dd5397e5df759c45464.1773675224.git.geert+renesas@glider.be> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/quirks.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/arm_scmi/quirks.h b/drivers/firmware/arm_scmi/quirks.h index a71fde85a527..d8ba60b95652 100644 --- a/drivers/firmware/arm_scmi/quirks.h +++ b/drivers/firmware/arm_scmi/quirks.h @@ -20,10 +20,10 @@ * named as _qn. */ #define SCMI_QUIRK(_qn, _blk) \ - do { \ + ({ \ if (static_branch_unlikely(&(scmi_quirk_ ## _qn))) \ (_blk); \ - } while (0) + }) void scmi_quirks_initialize(void); void scmi_quirks_enable(struct device *dev, const char *vend, @@ -34,10 +34,10 @@ void scmi_quirks_enable(struct device *dev, const char *vend, #define DECLARE_SCMI_QUIRK(_qn) /* Force quirks compilation even when SCMI Quirks are disabled */ #define SCMI_QUIRK(_qn, _blk) \ - do { \ + ({ \ if (0) \ (_blk); \ - } while (0) + }) static inline void scmi_quirks_initialize(void) { } static inline void scmi_quirks_enable(struct device *dev, const char *vend, From 055d79affa436d83a6e0d3ca6d054f11a7e3d4c1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 16 Feb 2026 10:15:26 +0100 Subject: [PATCH 099/193] firmware: qcom: uefisecapp: Simplify mutex with guard Simplify error path unlocking mutex with the guard. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260216091525.107935-4-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_qseecom_uefisecapp.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c index 98a463e9774b..21be447374aa 100644 --- a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c +++ b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c @@ -699,16 +699,13 @@ static DEFINE_MUTEX(__qcuefi_lock); static int qcuefi_set_reference(struct qcuefi_client *qcuefi) { - mutex_lock(&__qcuefi_lock); + guard(mutex)(&__qcuefi_lock); - if (qcuefi && __qcuefi) { - mutex_unlock(&__qcuefi_lock); + if (qcuefi && __qcuefi) return -EEXIST; - } __qcuefi = qcuefi; - mutex_unlock(&__qcuefi_lock); return 0; } From 4bfb0ec11e20b9354beabf1b9f3e70e926c407bd Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 16 Feb 2026 10:15:27 +0100 Subject: [PATCH 100/193] firmware: qcom: uefisecapp: Annotate acquiring locks for context tracking qcuefi_acquire() and qcuefi_release() end with mutex locked or unlocked respectively, so annotate them so the lock usage will be tracked by context tracking tools. Note that mutex is tracked since commit 370f0a345a70 ("locking/mutex: Support Clang's context analysis"). Signed-off-by: Krzysztof Kozlowski Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260216091525.107935-5-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_qseecom_uefisecapp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c index 21be447374aa..befa68d1dcaf 100644 --- a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c +++ b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c @@ -710,6 +710,7 @@ static int qcuefi_set_reference(struct qcuefi_client *qcuefi) } static struct qcuefi_client *qcuefi_acquire(void) + __acquires(__qcuefi_lock) { mutex_lock(&__qcuefi_lock); if (!__qcuefi) { @@ -720,6 +721,7 @@ static struct qcuefi_client *qcuefi_acquire(void) } static void qcuefi_release(void) + __releases(__qcuefi_lock) { mutex_unlock(&__qcuefi_lock); } From d98b978446d249df1a662b4fef4c0bbfa1d650b8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 16 Feb 2026 10:15:28 +0100 Subject: [PATCH 101/193] firmware: qcom: scom: Simplify mutex with guard Simplify error path unlocking mutex with the guard. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260216091525.107935-6-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 5c4375a7fa1f..ca6cedf25677 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -199,19 +199,18 @@ static int qcom_scm_bw_enable(void) if (!__scm->path) return 0; - mutex_lock(&__scm->scm_bw_lock); + guard(mutex)(&__scm->scm_bw_lock); + if (!__scm->scm_vote_count) { ret = icc_set_bw(__scm->path, 0, UINT_MAX); if (ret < 0) { dev_err(__scm->dev, "failed to set bandwidth request\n"); - goto err_bw; + return ret; } } __scm->scm_vote_count++; -err_bw: - mutex_unlock(&__scm->scm_bw_lock); - return ret; + return 0; } static void qcom_scm_bw_disable(void) From 87a1698cb80650e47b41ca78a78ce06870cba631 Mon Sep 17 00:00:00 2001 From: Pankaj Patil Date: Wed, 25 Feb 2026 17:37:24 +0530 Subject: [PATCH 102/193] firmware: qcom: scm: Allow QSEECOM on Glymur CRD Add glymur-crd to QSEECOM allowlist for enabling access to efivars and uefi bootloader Signed-off-by: Pankaj Patil Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260225-qseecom_glymur-v1-1-0cafc709e2ef@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 ca6cedf25677..33333384ac81 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2310,6 +2310,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "microsoft,denali", }, { .compatible = "microsoft,romulus13", }, { .compatible = "microsoft,romulus15", }, + { .compatible = "qcom,glymur-crd" }, { .compatible = "qcom,hamoa-iot-evk" }, { .compatible = "qcom,purwa-iot-evk" }, { .compatible = "qcom,sc8180x-primus" }, From 47b8c61eab8f25b16b5aae90f3991abc6d56d712 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 18 Mar 2026 19:25:06 +0200 Subject: [PATCH 103/193] soc: qcom: socinfo: Add PM7550BA PMIC Add the PM7550BA to the pmic_models array. It is one of the PMICs used by the Eliza MTP platform. Reviewed-by: Konrad Dybcio Signed-off-by: Abel Vesa Link: https://lore.kernel.org/r/20260318-qcom-socinfo-add-pm8550ba-v2-1-2f9171af0465@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 c7298e8f716e..802bf289626f 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -182,6 +182,7 @@ static const char *const pmic_models[] = { [72] = "PMR735D", [73] = "PM8550", [74] = "PMK8550", + [76] = "PM7550BA", [78] = "PMM8650AU", [79] = "PMM8650AU_PSAIL", [80] = "PM7550", From e3f45d32664edd2b25746e22add3a20c088edbec Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Wed, 18 Mar 2026 14:09:46 +0530 Subject: [PATCH 104/193] dt-bindings: firmware: qcom,scm: Document ipq5210 SCM Document the scm compatible for ipq5210 SoC. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kathiravan Thirumoorthy Link: https://lore.kernel.org/r/20260318-ipq5210_boot_to_shell-v2-4-a87e27c37070@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 d66459f1d84e..6d9b71a9b9b3 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -26,6 +26,7 @@ properties: - qcom,scm-glymur - qcom,scm-ipq4019 - qcom,scm-ipq5018 + - qcom,scm-ipq5210 - qcom,scm-ipq5332 - qcom,scm-ipq5424 - qcom,scm-ipq6018 From 678647c26e317d8d1de4d630ee9ffa7ecad637fe Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Fri, 16 Jan 2026 15:50:47 +0100 Subject: [PATCH 105/193] soc: qcom: pd-mapper: Add Milos compatible Add support for the Qualcomm Milos SoC to the protection domain mapper. Milos shares the same protection domain configuration as SM8550, so reuse the existing SM8550 domain data. Signed-off-by: Luca Weiss Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260116-milos-fp6-bt-wifi-v1-1-27b4fbb77e9c@fairphone.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_pd_mapper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index 21e4dd594295..72698772838e 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -572,6 +572,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,apq8084", .data = NULL, }, { .compatible = "qcom,apq8096", .data = msm8996_domains, }, { .compatible = "qcom,kaanapali", .data = kaanapali_domains, }, + { .compatible = "qcom,milos", .data = sm8550_domains, }, { .compatible = "qcom,msm8226", .data = NULL, }, { .compatible = "qcom,msm8909", .data = NULL, }, { .compatible = "qcom,msm8916", .data = NULL, }, From d921f8d3b955ba09d321c612fc485b9e9ac438c0 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 26 Feb 2026 16:09:33 +0100 Subject: [PATCH 106/193] firmware: tegra: bpmp: Rename Tegra239 to Tegra238 This chip identifies as Tegra238, so update the BPMP ABI header to refer to it by the correct name. Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- include/soc/tegra/bpmp-abi.h | 48 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/include/soc/tegra/bpmp-abi.h b/include/soc/tegra/bpmp-abi.h index dc0789c20333..39bb3f87e28d 100644 --- a/include/soc/tegra/bpmp-abi.h +++ b/include/soc/tegra/bpmp-abi.h @@ -1020,9 +1020,9 @@ struct cmd_i2c_xfer_request { /** * @brief Tegra PWR_I2C bus identifier * - * @cond (bpmp_t234 || bpmp_t239 || bpmp_t194) + * @cond (bpmp_t234 || bpmp_t238 || bpmp_t194) * Must be set to 5. - * @endcond (bpmp_t234 || bpmp_t239 || bpmp_t194) + * @endcond (bpmp_t234 || bpmp_t238 || bpmp_t194) * @cond bpmp_th500 * Must be set to 1. * @endcond bpmp_th500 @@ -2108,7 +2108,7 @@ struct mrq_emc_dvfs_latency_response { * @brief Query EMC HUB frequencies * * * Platforms: T234 onwards - * @cond (bpmp_t234 || bpmp_t239 || bpmp_th500) + * @cond (bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: N/A @@ -2139,7 +2139,7 @@ struct mrq_emc_dvfs_emchub_response { } BPMP_ABI_PACKED; /** @} EMC */ -/** @endcond (bpmp_t234 || bpmp_t239 || bpmp_th500) */ +/** @endcond (bpmp_t234 || bpmp_t238 || bpmp_th500) */ /** * @ingroup MRQ_Codes @@ -2147,7 +2147,7 @@ struct mrq_emc_dvfs_emchub_response { * @brief Set EMC display RFL handshake mode of operations * * * Platforms: T234 onwards - * @cond (bpmp_t234 || bpmp_t239 || bpmp_th500) + * @cond (bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_emc_disp_rfl_request @@ -2184,7 +2184,7 @@ struct mrq_emc_disp_rfl_request { } BPMP_ABI_PACKED; /** @} EMC */ -/** @endcond (bpmp_t234 || bpmp_t239 || bpmp_th500) */ +/** @endcond (bpmp_t234 || bpmp_t238 || bpmp_th500) */ /** * @ingroup MRQ_Codes @@ -2192,7 +2192,7 @@ struct mrq_emc_disp_rfl_request { * @brief bwmgr requests * * * Platforms: T234 onwards - * @cond (bpmp_t234 || bpmp_t239 || bpmp_th500) + * @cond (bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_bwmgr_request @@ -2299,7 +2299,7 @@ struct mrq_bwmgr_response { } BPMP_ABI_PACKED; /** @} BWMGR */ -/** @endcond (bpmp_t234 || bpmp_t239 || bpmp_th500) */ +/** @endcond (bpmp_t234 || bpmp_t238 || bpmp_th500) */ /** * @ingroup MRQ_Codes @@ -2307,7 +2307,7 @@ struct mrq_bwmgr_response { * @brief bpmp-integrated bwmgr requests * * * Platforms: T234 onwards - * @cond (bpmp_t234 || bpmp_t239 || bpmp_th500) + * @cond (bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_bwmgr_int_request @@ -2445,7 +2445,7 @@ struct mrq_bwmgr_int_response { } BPMP_ABI_PACKED; /** @} BWMGR_INT */ -/** @endcond (bpmp_t234 || bpmp_t239 || bpmp_th500) */ +/** @endcond (bpmp_t234 || bpmp_t238 || bpmp_th500) */ /** * @ingroup MRQ_Codes @@ -2453,7 +2453,7 @@ struct mrq_bwmgr_int_response { * @brief ISO client requests * * * Platforms: T234 onwards - * @cond (bpmp_t234 || bpmp_t239 || bpmp_th500) + * @cond (bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_iso_client_request @@ -2636,7 +2636,7 @@ struct mrq_iso_client_response { } BPMP_ABI_PACKED; /** @} ISO_CLIENT */ -/** @endcond (bpmp_t234 || bpmp_t239 || bpmp_th500) */ +/** @endcond (bpmp_t234 || bpmp_t238 || bpmp_th500) */ /** * @ingroup MRQ_Codes @@ -2644,7 +2644,7 @@ struct mrq_iso_client_response { * @brief CPU freq. limits in ndiv * * * Platforms: T194 onwards - * @cond (bpmp_t194 || bpmp_t234 || bpmp_t239 || bpmp_th500) + * @cond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_cpu_ndiv_limits_request @@ -2678,7 +2678,7 @@ struct mrq_cpu_ndiv_limits_response { } BPMP_ABI_PACKED; /** @} CPU */ -/** @endcond (bpmp_t194 || bpmp_t234 || bpmp_t239 || bpmp_th500) */ +/** @endcond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) */ /** * @ingroup MRQ_Codes @@ -2911,7 +2911,7 @@ union mrq_ringbuf_console_bpmp_to_host_response { * @brief Set a strap value controlled by BPMP * * * Platforms: T194 onwards - * @cond (bpmp_t194 || bpmp_t234 || bpmp_t239 || bpmp_th500) + * @cond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_strap_request @@ -2949,7 +2949,7 @@ struct mrq_strap_request { } BPMP_ABI_PACKED; /** @} Strap */ -/** @endcond (bpmp_t194 || bpmp_t234 || bpmp_t239 || bpmp_th500) */ +/** @endcond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) */ /** * @ingroup MRQ_Codes @@ -2957,7 +2957,7 @@ struct mrq_strap_request { * @brief Perform a UPHY operation * * * Platforms: T194 onwards - * @cond (bpmp_t194 || bpmp_t234 || bpmp_t239 || bpmp_th500) + * @cond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_uphy_request @@ -2997,23 +2997,23 @@ struct cmd_uphy_margin_status_response { } BPMP_ABI_PACKED; struct cmd_uphy_ep_controller_pll_init_request { - /** @brief EP controller number, T194 valid: 0, 4, 5; T234 valid: 5, 6, 7, 10; T239 valid: 0 */ + /** @brief EP controller number, T194 valid: 0, 4, 5; T234 valid: 5, 6, 7, 10; T238 valid: 0 */ uint8_t ep_controller; } BPMP_ABI_PACKED; struct cmd_uphy_pcie_controller_state_request { - /** @brief PCIE controller number, T194 valid: 0-4; T234 valid: 0-10; T239 valid: 0-3 */ + /** @brief PCIE controller number, T194 valid: 0-4; T234 valid: 0-10; T238 valid: 0-3 */ uint8_t pcie_controller; uint8_t enable; } BPMP_ABI_PACKED; struct cmd_uphy_ep_controller_pll_off_request { - /** @brief EP controller number, T194 valid: 0, 4, 5; T234 valid: 5, 6, 7, 10; T239 valid: 0 */ + /** @brief EP controller number, T194 valid: 0, 4, 5; T234 valid: 5, 6, 7, 10; T238 valid: 0 */ uint8_t ep_controller; } BPMP_ABI_PACKED; struct cmd_uphy_display_port_init_request { - /** @brief DisplayPort link rate, T239 valid: 1620, 2700, 5400, 8100, 2160, 2430, 3240, 4320, 6750 */ + /** @brief DisplayPort link rate, T238 valid: 1620, 2700, 5400, 8100, 2160, 2430, 3240, 4320, 6750 */ uint16_t link_rate; /** @brief 1: lane 0; 2: lane 1; 3: lane 0 and 1 */ uint16_t lanes_bitmap; @@ -3084,7 +3084,7 @@ struct mrq_uphy_response { } BPMP_ABI_PACKED; /** @} UPHY */ -/** @endcond (bpmp_t194 || bpmp_t234 || bpmp_t239 || bpmp_th500) */ +/** @endcond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) */ /** * @ingroup MRQ_Codes @@ -3092,12 +3092,12 @@ struct mrq_uphy_response { * @brief Perform a frequency monitor configuration operations * * * Platforms: T194 onwards - * @cond (bpmp_t194 || bpmp_t234 || bpmp_t239 || bpmp_th500) + * @cond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_fmon_request * * Response Payload: @ref mrq_fmon_response - * @endcond (bpmp_t194 || bpmp_t234 || bpmp_t239 || bpmp_th500) + * @endcond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) * * @addtogroup FMON * @{ From 223af4a569d1f491e55d4de8ed40333c938622d0 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 19 Mar 2026 18:05:17 -0700 Subject: [PATCH 107/193] reset: sti: kzalloc + kcalloc to kzalloc Simplify allocation. Signed-off-by: Rosen Penev Reviewed-by: Patrice Chotard Signed-off-by: Philipp Zabel --- drivers/reset/sti/reset-syscfg.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/reset/sti/reset-syscfg.c b/drivers/reset/sti/reset-syscfg.c index 2324060b747c..38f78d78fa4f 100644 --- a/drivers/reset/sti/reset-syscfg.c +++ b/drivers/reset/sti/reset-syscfg.c @@ -41,7 +41,7 @@ struct syscfg_reset_channel { struct syscfg_reset_controller { struct reset_controller_dev rst; bool active_low; - struct syscfg_reset_channel *channels; + struct syscfg_reset_channel channels[]; }; #define to_syscfg_reset_controller(_rst) \ @@ -135,15 +135,10 @@ static int syscfg_reset_controller_register(struct device *dev, struct syscfg_reset_controller *rc; int i, err; - rc = devm_kzalloc(dev, sizeof(*rc), GFP_KERNEL); + rc = devm_kzalloc(dev, struct_size(rc, channels, data->nr_channels), GFP_KERNEL); if (!rc) return -ENOMEM; - rc->channels = devm_kcalloc(dev, data->nr_channels, - sizeof(*rc->channels), GFP_KERNEL); - if (!rc->channels) - return -ENOMEM; - rc->rst.ops = &syscfg_reset_ops; rc->rst.of_node = dev->of_node; rc->rst.nr_resets = data->nr_channels; From 3caf4aa0d515080533373f4b75786d295f64e806 Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Tue, 17 Mar 2026 11:57:45 +0800 Subject: [PATCH 108/193] =?UTF-8?q?soc:=20hisilicon:=20kunpeng=5Fhccs:=20F?= =?UTF-8?q?ix=20discard=20=E2=80=98const=E2=80=99=20qualifier=20compiling?= =?UTF-8?q?=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The link_fsm_map has ‘const’ qualifier, but the 'str' pointer in link_fsm_map is discarded. So add 'const' for this pointer to fix the compiling warning. Signed-off-by: Huisong Li Signed-off-by: Wei Xu --- drivers/soc/hisilicon/kunpeng_hccs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index 2af3bfda313e..d6ff7de63836 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -961,7 +961,7 @@ static ssize_t link_fsm_show(struct kobject *kobj, struct hccs_link_status link_status = {0}; const struct { u8 link_fsm; - char *str; + const char *str; } link_fsm_map[] = { {HCCS_PORT_RESET, "reset"}, {HCCS_PORT_SETUP, "setup"}, From a8f5c98517c7c89947024f79e5854e6b09766b79 Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Tue, 17 Mar 2026 11:57:46 +0800 Subject: [PATCH 109/193] soc: hisilicon: kunpeng_hccs: Remove unused input parameter The 'hdev' parameter of hccs_create_hccs_dir() is unused. Remove it to fix the compiler warning. Signed-off-by: Huisong Li Signed-off-by: Wei Xu --- drivers/soc/hisilicon/kunpeng_hccs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index d6ff7de63836..0cc2953d59a5 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -1621,8 +1621,7 @@ static void hccs_remove_topo_dirs(struct hccs_dev *hdev) hccs_remove_misc_sysfs(hdev); } -static int hccs_create_hccs_dir(struct hccs_dev *hdev, - struct hccs_die_info *die, +static int hccs_create_hccs_dir(struct hccs_die_info *die, struct hccs_port_info *port) { int ret; @@ -1654,7 +1653,7 @@ static int hccs_create_die_dir(struct hccs_dev *hdev, for (i = 0; i < die->port_num; i++) { port = &die->ports[i]; - ret = hccs_create_hccs_dir(hdev, die, port); + ret = hccs_create_hccs_dir(die, port); if (ret) { dev_err(hdev->dev, "create hccs%u dir failed.\n", port->port_id); From e32701726c0e6312aabd83aa1c00f59b0d7df276 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Tue, 10 Mar 2026 19:32:55 +0530 Subject: [PATCH 110/193] firmware: qcom_scm: don't opencode kmemdup Lets not opencode kmemdup which is reported by coccinelle tool. Fix it using kmemdup. cocci warnings: (new ones prefixed by >>) >> drivers/firmware/qcom/qcom_scm.c:916:11-18: WARNING opportunity for kmemdup Fixes: 8b9d2050cfa0 ("firmware: qcom_scm: Add qcom_scm_pas_get_rsc_table() to get resource table") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202601142144.HvSlBSI9-lkp@intel.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Mukesh Ojha Link: https://lore.kernel.org/r/20260310140255.2520230-1-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 33333384ac81..d1082695ec38 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -922,14 +922,13 @@ struct resource_table *qcom_scm_pas_get_rsc_table(struct qcom_scm_pas_context *c goto free_input_rt; } - tbl_ptr = kzalloc(size, GFP_KERNEL); + tbl_ptr = kmemdup(output_rt_tzm, size, GFP_KERNEL); if (!tbl_ptr) { qcom_tzmem_free(output_rt_tzm); ret = -ENOMEM; goto free_input_rt; } - memcpy(tbl_ptr, output_rt_tzm, size); *output_rt_size = size; qcom_tzmem_free(output_rt_tzm); From e031e7ceac4ee04973bd77362c363734e79dd08c Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 28 Feb 2026 20:34:27 +0200 Subject: [PATCH 111/193] soc: qcom: ubwc: disable bank swizzling for Glymur platform Due to the way the DDR controller is organized on Glymur, hardware engineers strongly recommended disabling UBWC bank swizzling on Glymur. Follow that recommendation. Fixes: 9b21c3bd2480 ("soc: qcom: ubwc: Add configuration Glymur platform") Signed-off-by: Dmitry Baryshkov Acked-by: Rob Clark Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Reviewed-by: Akhil P Oommen Reviewed-by: Akhil P Oommen Link: https://lore.kernel.org/r/20260228-fix-glymur-ubwc-v2-1-70819bd6a6b4@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ubwc_config.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/soc/qcom/ubwc_config.c b/drivers/soc/qcom/ubwc_config.c index 1c25aaf55e52..8304463f238a 100644 --- a/drivers/soc/qcom/ubwc_config.c +++ b/drivers/soc/qcom/ubwc_config.c @@ -231,8 +231,7 @@ static const struct qcom_ubwc_cfg_data x1e80100_data = { static const struct qcom_ubwc_cfg_data glymur_data = { .ubwc_enc_version = UBWC_5_0, .ubwc_dec_version = UBWC_5_0, - .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | - UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_swizzle = 0, .ubwc_bank_spread = true, /* TODO: highest_bank_bit = 15 for LP_DDR4 */ .highest_bank_bit = 16, From e8a61c51417c679d1a599fb36695e9d3b8d95514 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 23 Mar 2026 03:20:57 +0200 Subject: [PATCH 112/193] soc: qcom: ocmem: make the core clock optional OCMEM's core clock (aka RPM bus 2 clock) is being handled internally by the interconnect driver. Corresponding clock has been dropped from the SMD RPM clock driver. The users of the ocmem will vote on the ocmemnoc interconnect paths, making sure that ocmem is on. Make the clock optional, keeping it for compatibility with older DT. Fixes: d6edc31f3a68 ("clk: qcom: smd-rpm: Separate out interconnect bus clocks") Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260323-ocmem-v1-1-ad9bcae44763@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ocmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index 6a23f18b0281..dd46bb14b7be 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -308,7 +308,7 @@ static int ocmem_dev_probe(struct platform_device *pdev) ocmem->dev = dev; ocmem->config = device_get_match_data(dev); - ocmem->core_clk = devm_clk_get(dev, "core"); + ocmem->core_clk = devm_clk_get_optional(dev, "core"); if (IS_ERR(ocmem->core_clk)) return dev_err_probe(dev, PTR_ERR(ocmem->core_clk), "Unable to get core clock\n"); From 9dfd69cd89cd6afa4723be9098979abeef3bb8c6 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 23 Mar 2026 03:20:58 +0200 Subject: [PATCH 113/193] soc: qcom: ocmem: register reasons for probe deferrals Instead of printing messages to the dmesg, let the message be recorded as a reason for the OCMEM client deferral. Fixes: 88c1e9404f1d ("soc: qcom: add OCMEM driver") Signed-off-by: Dmitry Baryshkov Reviewed-by: Brian Masney Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260323-ocmem-v1-2-ad9bcae44763@oss.qualcomm.com [bjorn: s/ERR_PTR(dev_err_probe)/dev_err_ptr_probe/ Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ocmem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index dd46bb14b7be..d47ce5707fd8 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -196,10 +196,10 @@ struct ocmem *of_get_ocmem(struct device *dev) } pdev = of_find_device_by_node(devnode->parent); - if (!pdev) { - dev_err(dev, "Cannot find device node %s\n", devnode->name); - return ERR_PTR(-EPROBE_DEFER); - } + if (!pdev) + return dev_err_ptr_probe(dev, -EPROBE_DEFER, + "Cannot find device node %s\n", + devnode->name); ocmem = platform_get_drvdata(pdev); put_device(&pdev->dev); From 91b59009c7d48b58dbc50fecb27f2ad20749a05a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 23 Mar 2026 03:20:59 +0200 Subject: [PATCH 114/193] soc: qcom: ocmem: return -EPROBE_DEFER is ocmem is not available If OCMEM is declared in DT, it is expected that it is present and handled by the driver. The GPU driver will ignore -ENODEV error, which typically means that OCMEM isn't defined in DT. Let ocmem return -EPROBE_DEFER if it supposed to be used, but it is not probed (yet). Fixes: 88c1e9404f1d ("soc: qcom: add OCMEM driver") Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260323-ocmem-v1-3-ad9bcae44763@oss.qualcomm.com [bjorn: s/ERR_PTR(dev_err_probe)/dev_err_ptr_probe/ Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ocmem.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index d47ce5707fd8..96ca0b87bfc4 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -203,10 +203,9 @@ struct ocmem *of_get_ocmem(struct device *dev) ocmem = platform_get_drvdata(pdev); put_device(&pdev->dev); - if (!ocmem) { - dev_err(dev, "Cannot get ocmem\n"); - return ERR_PTR(-ENODEV); - } + if (!ocmem) + return dev_err_ptr_probe(dev, -EPROBE_DEFER, "Cannot get ocmem\n"); + return ocmem; } EXPORT_SYMBOL_GPL(of_get_ocmem); From b4d4a4f6e2ca171c5f1ef6b9e387943542eded09 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 11 Mar 2026 10:43:02 +0200 Subject: [PATCH 115/193] dt-bindings: firmware: qcom,scm: document Eliza SCM Firmware Interface Document the SCM Firmware Interface on the Eliza SoC. Signed-off-by: Abel Vesa Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260311-eliza-bindings-scm-v2-1-b2d2e69068e3@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml index 6d9b71a9b9b3..f628b1d70fa1 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -23,6 +23,7 @@ properties: - enum: - qcom,scm-apq8064 - qcom,scm-apq8084 + - qcom,scm-eliza - qcom,scm-glymur - qcom,scm-ipq4019 - qcom,scm-ipq5018 @@ -205,6 +206,7 @@ allOf: compatible: contains: enum: + - qcom,scm-eliza - qcom,scm-kaanapali - qcom,scm-milos - qcom,scm-sm8450 From ece67f475887f77a889ce2ad27a49d12e69aa6be Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 17 Feb 2026 10:16:36 +0100 Subject: [PATCH 116/193] soc/tegra: Make ARCH_TEGRA_SOC_FOO defaults for NVIDIA Tegra By convention, only one globally selectable ARCH_PLATFORM is expected for given SoC platform, defined in arch/arm64/Kconfig.platforms or arch/arm/mach-*/Kconfig, because we target a single multi-platform kernel image. Platforms wanting different granularity, e.g. due to size constraints on their devices, should be sure that globally only one ARCH_PLATFORM is selected in defconfig. Change Tegra per-SoC Kconfig entries to default to ARCH_TEGRA allowing removal of these per-SoC parts from defconfigs. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij [treding@nvidia.com: Fix ARCH_PLATFORM typo, correct spelling] Signed-off-by: Thierry Reding --- drivers/soc/tegra/Kconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index c0fc54c3cd35..a1cadfdb356c 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -6,6 +6,7 @@ if ARM config ARCH_TEGRA_2x_SOC bool "Enable support for Tegra20 family" + default ARCH_TEGRA select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP select ARM_ERRATA_720789 select ARM_ERRATA_754327 if SMP @@ -23,6 +24,7 @@ config ARCH_TEGRA_2x_SOC config ARCH_TEGRA_3x_SOC bool "Enable support for Tegra30 family" + default ARCH_TEGRA select ARM_ERRATA_754322 select ARM_ERRATA_764369 if SMP select PINCTRL_TEGRA30 @@ -37,6 +39,7 @@ config ARCH_TEGRA_3x_SOC config ARCH_TEGRA_114_SOC bool "Enable support for Tegra114 family" + default ARCH_TEGRA select ARM_ERRATA_798181 if SMP select HAVE_ARM_ARCH_TIMER select PINCTRL_TEGRA114 @@ -49,6 +52,7 @@ config ARCH_TEGRA_114_SOC config ARCH_TEGRA_124_SOC bool "Enable support for Tegra124 family" + default ARCH_TEGRA select HAVE_ARM_ARCH_TIMER select PINCTRL_TEGRA124 select SOC_TEGRA_FLOWCTRL @@ -65,6 +69,7 @@ if ARM64 config ARCH_TEGRA_132_SOC bool "NVIDIA Tegra132 SoC" + default ARCH_TEGRA select PINCTRL_TEGRA124 select SOC_TEGRA_FLOWCTRL select SOC_TEGRA_PMC @@ -76,6 +81,7 @@ config ARCH_TEGRA_132_SOC config ARCH_TEGRA_210_SOC bool "NVIDIA Tegra210 SoC" + default ARCH_TEGRA select PINCTRL_TEGRA210 select SOC_TEGRA_FLOWCTRL select SOC_TEGRA_PMC @@ -95,6 +101,7 @@ config ARCH_TEGRA_210_SOC config ARCH_TEGRA_186_SOC bool "NVIDIA Tegra186 SoC" + default ARCH_TEGRA depends on !CPU_BIG_ENDIAN select PINCTRL_TEGRA186 select MAILBOX @@ -109,6 +116,7 @@ config ARCH_TEGRA_186_SOC config ARCH_TEGRA_194_SOC bool "NVIDIA Tegra194 SoC" + default ARCH_TEGRA depends on !CPU_BIG_ENDIAN select MAILBOX select PINCTRL_TEGRA194 @@ -118,6 +126,7 @@ config ARCH_TEGRA_194_SOC config ARCH_TEGRA_234_SOC bool "NVIDIA Tegra234 SoC" + default ARCH_TEGRA depends on !CPU_BIG_ENDIAN select MAILBOX select PINCTRL_TEGRA234 @@ -127,11 +136,13 @@ config ARCH_TEGRA_234_SOC config ARCH_TEGRA_241_SOC bool "NVIDIA Tegra241 SoC" + default ARCH_TEGRA help Enable support for the NVIDIA Tegra241 SoC. config ARCH_TEGRA_264_SOC bool "NVIDIA Tegra264 SoC" + default ARCH_TEGRA depends on !CPU_BIG_ENDIAN select MAILBOX select SOC_TEGRA_PMC From 9514d3f2dd4b8df4505c9104da8ac12fefb0d871 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 26 Feb 2026 16:09:32 +0100 Subject: [PATCH 117/193] soc/tegra: Add Tegra238 Kconfig symbol The NVIDIA Tegra238 SoC is an upcoming new chip. Add a Kconfig symbol to allow fine-grained selection of support code for this chip. Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index a1cadfdb356c..073346c1542b 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -134,6 +134,15 @@ config ARCH_TEGRA_234_SOC help Enable support for the NVIDIA Tegra234 SoC. +config ARCH_TEGRA_238_SOC + bool "NVIDIA Tegra238 SoC" + default ARCH_TEGRA + depends on !CPU_BIG_ENDIAN + select MAILBOX + select SOC_TEGRA_PMC + help + Enable support for the NVIDIA Tegra238 SoC. + config ARCH_TEGRA_241_SOC bool "NVIDIA Tegra241 SoC" default ARCH_TEGRA From 698753e4a51a5a6670d527a3db084c3616253abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Goffic?= Date: Tue, 10 Feb 2026 20:05:45 +0100 Subject: [PATCH 118/193] bus: firewall: move stm32_firewall header file in include folder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Other driver than RIFSC and ETZPC can implement firewall ops, such as RCC. In order for them to have access to the ops and type of this framework, we need to get the `stm32_firewall.h` file in the include/ folder. Signed-off-by: Clément Le Goffic Signed-off-by: Clément Le Goffic Acked-by: Gatien Chevallier Link: https://lore.kernel.org/r/20260210-b4-firewall-upstream-v8-1-097c1e47af82@gmail.com Signed-off-by: Alexandre Torgue --- drivers/bus/stm32_etzpc.c | 3 +-- drivers/bus/stm32_firewall.c | 3 +-- drivers/bus/stm32_rifsc.c | 3 +-- {drivers => include/linux}/bus/stm32_firewall.h | 0 4 files changed, 3 insertions(+), 6 deletions(-) rename {drivers => include/linux}/bus/stm32_firewall.h (100%) diff --git a/drivers/bus/stm32_etzpc.c b/drivers/bus/stm32_etzpc.c index 7fc0f16960be..4918a14e507e 100644 --- a/drivers/bus/stm32_etzpc.c +++ b/drivers/bus/stm32_etzpc.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -16,8 +17,6 @@ #include #include -#include "stm32_firewall.h" - /* * ETZPC registers */ diff --git a/drivers/bus/stm32_firewall.c b/drivers/bus/stm32_firewall.c index 7e7afe8007db..bbcf42ad668a 100644 --- a/drivers/bus/stm32_firewall.c +++ b/drivers/bus/stm32_firewall.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -18,8 +19,6 @@ #include #include -#include "stm32_firewall.h" - /* Corresponds to STM32_FIREWALL_MAX_EXTRA_ARGS + firewall ID */ #define STM32_FIREWALL_MAX_ARGS (STM32_FIREWALL_MAX_EXTRA_ARGS + 1) diff --git a/drivers/bus/stm32_rifsc.c b/drivers/bus/stm32_rifsc.c index debeaf8ea1bd..65990ae8dd08 100644 --- a/drivers/bus/stm32_rifsc.c +++ b/drivers/bus/stm32_rifsc.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -17,8 +18,6 @@ #include #include -#include "stm32_firewall.h" - /* * RIFSC offset register */ diff --git a/drivers/bus/stm32_firewall.h b/include/linux/bus/stm32_firewall.h similarity index 100% rename from drivers/bus/stm32_firewall.h rename to include/linux/bus/stm32_firewall.h From 256b4efd98b1dcbe80e817a67b17c07becb80969 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 5 Jan 2026 15:36:59 +0100 Subject: [PATCH 119/193] bus: stm32_firewall: Simplify with scoped for each OF child loop Use scoped for-each loop when iterating over device nodes to make code a bit simpler. Signed-off-by: Krzysztof Kozlowski Tested-by: Gatien Chevallier Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260105143657.383621-5-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Alexandre Torgue --- drivers/bus/stm32_firewall.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/bus/stm32_firewall.c b/drivers/bus/stm32_firewall.c index bbcf42ad668a..b023d1f4fcf7 100644 --- a/drivers/bus/stm32_firewall.c +++ b/drivers/bus/stm32_firewall.c @@ -240,7 +240,6 @@ EXPORT_SYMBOL_GPL(stm32_firewall_controller_unregister); int stm32_firewall_populate_bus(struct stm32_firewall_controller *firewall_controller) { struct stm32_firewall *firewalls; - struct device_node *child; struct device *parent; unsigned int i; int len; @@ -250,25 +249,20 @@ int stm32_firewall_populate_bus(struct stm32_firewall_controller *firewall_contr dev_dbg(parent, "Populating %s system bus\n", dev_name(firewall_controller->dev)); - for_each_available_child_of_node(dev_of_node(parent), child) { + for_each_available_child_of_node_scoped(dev_of_node(parent), child) { /* The access-controllers property is mandatory for firewall bus devices */ len = of_count_phandle_with_args(child, "access-controllers", "#access-controller-cells"); - if (len <= 0) { - of_node_put(child); + if (len <= 0) return -EINVAL; - } firewalls = kzalloc_objs(*firewalls, len); - if (!firewalls) { - of_node_put(child); + if (!firewalls) return -ENOMEM; - } err = stm32_firewall_get_firewall(child, firewalls, (unsigned int)len); if (err) { kfree(firewalls); - of_node_put(child); return err; } From a6e1842be2e4fd590136da5c100fbad6c3129d96 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 23 Feb 2026 22:12:11 +0100 Subject: [PATCH 120/193] bus: rifsc: Replace snprintf("%s") with strscpy Replace snprintf("%s", ...) with the faster and more direct strscpy(). Signed-off-by: Thorsten Blum Acked-by: Gatien Chevallier Link: https://lore.kernel.org/r/20260223211212.344855-1-thorsten.blum@linux.dev Signed-off-by: Alexandre Torgue --- drivers/bus/stm32_rifsc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/bus/stm32_rifsc.c b/drivers/bus/stm32_rifsc.c index 65990ae8dd08..ab8d4e3128c3 100644 --- a/drivers/bus/stm32_rifsc.c +++ b/drivers/bus/stm32_rifsc.c @@ -16,6 +16,7 @@ #include #include #include +#include #include /* @@ -449,7 +450,7 @@ static void stm32_rifsc_fill_rimu_dbg_entry(struct rifsc_dbg_private *rifsc, const struct stm32_rifsc_resources_names *dbg_names = rifsc->res_names; u32 rimc_attr = readl_relaxed(rifsc->mmio + RIFSC_RIMC_ATTR0 + 0x4 * i); - snprintf(dbg_entry->m_name, sizeof(dbg_entry->m_name), "%s", dbg_names->initiator_names[i]); + strscpy(dbg_entry->m_name, dbg_names->initiator_names[i]); dbg_entry->m_cid = FIELD_GET(RIFSC_RIMC_MCID_MASK, rimc_attr); dbg_entry->cidsel = rimc_attr & RIFSC_RIMC_CIDSEL; dbg_entry->m_sec = rimc_attr & RIFSC_RIMC_MSEC; @@ -468,8 +469,7 @@ static void stm32_rifsc_fill_dev_dbg_entry(struct rifsc_dbg_private *rifsc, sec_cfgr = readl_relaxed(rifsc->mmio + RIFSC_RISC_SECCFGR0 + 0x4 * reg_id); priv_cfgr = readl_relaxed(rifsc->mmio + RIFSC_RISC_PRIVCFGR0 + 0x4 * reg_id); - snprintf(dbg_entry->dev_name, sizeof(dbg_entry->dev_name), "%s", - dbg_names->device_names[i]); + strscpy(dbg_entry->dev_name, dbg_names->device_names[i]); dbg_entry->dev_id = i; dbg_entry->dev_cid_filt_en = cid_cfgr & CIDCFGR_CFEN; dbg_entry->dev_sem_en = cid_cfgr & CIDCFGR_SEMEN; From d5ce3b4e951bc41a6ce877c8500bb4fe42146669 Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Thu, 29 Jan 2026 13:56:17 +0100 Subject: [PATCH 121/193] bus: rifsc: fix RIF configuration check for peripherals Peripheral holding CID0 cannot be accessed, remove this completely incorrect check. While there, fix and simplify the semaphore checking that should be performed when the CID filtering is enabled. Fixes: a18208457253 ("bus: rifsc: introduce RIFSC firewall controller driver") Signed-off-by: Gatien Chevallier Link: https://lore.kernel.org/r/20260129-fix_cid_check_rifsc-v1-1-ef280ccf764d@foss.st.com Signed-off-by: Alexandre Torgue --- drivers/bus/stm32_rifsc.c | 52 ++++++++++++++------------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/drivers/bus/stm32_rifsc.c b/drivers/bus/stm32_rifsc.c index ab8d4e3128c3..19d10379dcef 100644 --- a/drivers/bus/stm32_rifsc.c +++ b/drivers/bus/stm32_rifsc.c @@ -687,34 +687,6 @@ static int stm32_rifsc_grant_access(struct stm32_firewall_controller *ctrl, u32 sec_reg_value = readl(rifsc_controller->mmio + RIFSC_RISC_SECCFGR0 + 0x4 * reg_id); cid_reg_value = readl(rifsc_controller->mmio + RIFSC_RISC_PER0_CIDCFGR + 0x8 * firewall_id); - /* First check conditions for semaphore mode, which doesn't take into account static CID. */ - if ((cid_reg_value & CIDCFGR_SEMEN) && (cid_reg_value & CIDCFGR_CFEN)) { - if (cid_reg_value & BIT(RIF_CID1 + SEMWL_SHIFT)) { - /* Static CID is irrelevant if semaphore mode */ - goto skip_cid_check; - } else { - dev_dbg(rifsc_controller->dev, - "Invalid bus semaphore configuration: index %d\n", firewall_id); - return -EACCES; - } - } - - /* - * Skip CID check if CID filtering isn't enabled or filtering is enabled on CID0, which - * corresponds to whatever CID. - */ - if (!(cid_reg_value & CIDCFGR_CFEN) || - FIELD_GET(RIFSC_RISC_SCID_MASK, cid_reg_value) == RIF_CID0) - goto skip_cid_check; - - /* Coherency check with the CID configuration */ - if (FIELD_GET(RIFSC_RISC_SCID_MASK, cid_reg_value) != RIF_CID1) { - dev_dbg(rifsc_controller->dev, "Invalid CID configuration for peripheral: %d\n", - firewall_id); - return -EACCES; - } - -skip_cid_check: /* Check security configuration */ if (sec_reg_value & BIT(reg_offset)) { dev_dbg(rifsc_controller->dev, @@ -722,19 +694,31 @@ skip_cid_check: return -EACCES; } - /* - * If the peripheral is in semaphore mode, take the semaphore so that - * the CID1 has the ownership. - */ - if ((cid_reg_value & CIDCFGR_SEMEN) && (cid_reg_value & CIDCFGR_CFEN)) { + /* Skip CID check if CID filtering isn't enabled */ + if (!(cid_reg_value & CIDCFGR_CFEN)) + goto skip_cid_check; + + /* First check conditions for semaphore mode, which doesn't take into account static CID. */ + if (cid_reg_value & CIDCFGR_SEMEN) { + if (!(cid_reg_value & BIT(RIF_CID1 + SEMWL_SHIFT))) { + dev_dbg(rifsc_controller->dev, + "Invalid bus semaphore configuration: index %d\n", firewall_id); + return -EACCES; + } + rc = stm32_rif_acquire_semaphore(rifsc_controller, firewall_id); if (rc) { - dev_err(rifsc_controller->dev, + dev_dbg(rifsc_controller->dev, "Couldn't acquire semaphore for peripheral: %d\n", firewall_id); return rc; } + } else if (FIELD_GET(RIFSC_RISC_SCID_MASK, cid_reg_value) != RIF_CID1) { + dev_dbg(rifsc_controller->dev, "Invalid CID configuration for peripheral: %d\n", + firewall_id); + return -EACCES; } +skip_cid_check: return 0; } From c75617dd949b343ade70f35ecd2d4546738b57bf Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Thu, 26 Feb 2026 11:30:16 +0100 Subject: [PATCH 122/193] dt-bindings: document access-controllers property for coresight peripherals Document the access-controllers for coresight peripherals in case some access checks need to be performed to use them. Signed-off-by: Gatien Chevallier Reviewed-by: Rob Herring (Arm) Acked-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20260226-debug_bus-v6-1-5d794697798d@foss.st.com Signed-off-by: Alexandre Torgue --- Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml | 3 +++ .../devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml | 3 +++ Documentation/devicetree/bindings/arm/arm,coresight-etm.yaml | 3 +++ Documentation/devicetree/bindings/arm/arm,coresight-stm.yaml | 3 +++ Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml | 3 +++ Documentation/devicetree/bindings/arm/arm,coresight-tpiu.yaml | 3 +++ 6 files changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml index 2a91670ccb8c..949444aba1f8 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml @@ -128,6 +128,9 @@ properties: "#address-cells": const: 1 + access-controllers: + maxItems: 1 + patternProperties: '^trig-conns@([0-9]+)$': type: object diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml index b74db15e5f8a..b0693cd46d27 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml @@ -78,6 +78,9 @@ properties: description: Output connection to CoreSight Trace bus $ref: /schemas/graph.yaml#/properties/port + access-controllers: + maxItems: 1 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-etm.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-etm.yaml index 71f2e1ed27e5..10ebbbeadf93 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-etm.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-etm.yaml @@ -118,6 +118,9 @@ properties: description: Output connection from the ETM to CoreSight Trace bus. $ref: /schemas/graph.yaml#/properties/port + access-controllers: + maxItems: 1 + required: - compatible - clocks diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-stm.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-stm.yaml index 378380c3f5aa..f243e76f597f 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-stm.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-stm.yaml @@ -73,6 +73,9 @@ properties: description: Output connection to the CoreSight Trace bus. $ref: /schemas/graph.yaml#/properties/port + access-controllers: + maxItems: 1 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml index 96dd5b5f771a..9dc096698c65 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml @@ -128,6 +128,9 @@ properties: - const: tracedata - const: metadata + access-controllers: + maxItems: 1 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-tpiu.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-tpiu.yaml index a207f6899e67..29bbc3961fdf 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-tpiu.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-tpiu.yaml @@ -70,6 +70,9 @@ properties: description: Input connection from the CoreSight Trace bus. $ref: /schemas/graph.yaml#/properties/port + access-controllers: + maxItems: 1 + required: - compatible - reg From f7cfd2b29127893982b4f73908df1036cfc0b9ff Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Thu, 26 Feb 2026 11:30:17 +0100 Subject: [PATCH 123/193] dt-bindings: pinctrl: document access-controllers property for stm32 HDP HDP being functional depends on the debug configuration on the platform that can be checked using the access-controllers property, document it. Signed-off-by: Gatien Chevallier Acked-by: Rob Herring (Arm) Acked-by: Linus Walleij Link: https://lore.kernel.org/r/20260226-debug_bus-v6-2-5d794697798d@foss.st.com Signed-off-by: Alexandre Torgue --- Documentation/devicetree/bindings/pinctrl/st,stm32-hdp.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-hdp.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-hdp.yaml index 845b6b7b7552..8f8b4b68aaa3 100644 --- a/Documentation/devicetree/bindings/pinctrl/st,stm32-hdp.yaml +++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-hdp.yaml @@ -27,6 +27,12 @@ properties: clocks: maxItems: 1 + access-controllers: + minItems: 1 + items: + - description: debug configuration access controller + - description: access controller that manages the HDP as a peripheral + patternProperties: "^hdp[0-7]-pins$": type: object From 2b690a435643bde649a088bfc59be5282acf018f Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Thu, 26 Feb 2026 11:30:18 +0100 Subject: [PATCH 124/193] dt-bindings: bus: document the stm32 debug bus Document the stm32 debug bus. The debug bus is responsible for checking the debug sub-system accessibility before probing any related drivers. Signed-off-by: Gatien Chevallier Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20260226-debug_bus-v6-3-5d794697798d@foss.st.com Signed-off-by: Alexandre Torgue --- .../bindings/bus/st,stm32mp131-dbg-bus.yaml | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 Documentation/devicetree/bindings/bus/st,stm32mp131-dbg-bus.yaml diff --git a/Documentation/devicetree/bindings/bus/st,stm32mp131-dbg-bus.yaml b/Documentation/devicetree/bindings/bus/st,stm32mp131-dbg-bus.yaml new file mode 100644 index 000000000000..6c74433efbe3 --- /dev/null +++ b/Documentation/devicetree/bindings/bus/st,stm32mp131-dbg-bus.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bus/st,stm32mp131-dbg-bus.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STM32 Coresight bus + +maintainers: + - Gatien Chevallier + +description: + The STM32 debug bus is in charge of checking the debug configuration + of the platform before probing the peripheral drivers that rely on the debug + domain. + +properties: + compatible: + items: + - enum: + - st,stm32mp131-dbg-bus + - st,stm32mp151-dbg-bus + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + ranges: + minItems: 1 + maxItems: 2 + + "#access-controller-cells": + const: 1 + description: + Contains the debug profile necessary to access the peripheral. + +patternProperties: + "@[0-9a-f]+$": + description: Debug related peripherals + type: object + + additionalProperties: true + + required: + - access-controllers + +required: + - "#access-controller-cells" + - "#address-cells" + - "#size-cells" + - compatible + - ranges + +additionalProperties: false + +examples: + - | + #include + + dbg_bus: bus@50080000 { + compatible = "st,stm32mp131-dbg-bus"; + #address-cells = <1>; + #size-cells = <1>; + #access-controller-cells = <1>; + ranges = <0x50080000 0x50080000 0x3f80000>; + + cti@50094000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x50094000 0x1000>; + clocks = <&rcc CK_DBG>; + clock-names = "apb_pclk"; + access-controllers = <&dbg_bus 0>; + }; + }; From 892320d20362b7d567b759aec2bbe9c26b404e00 Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Thu, 26 Feb 2026 11:30:19 +0100 Subject: [PATCH 125/193] bus: stm32_firewall: allow check on different firewall controllers Current implementation restricts the check on the firewall controller being the bus parent. Change this by using the controller referenced in each firewall queries. Signed-off-by: Gatien Chevallier Link: https://lore.kernel.org/r/20260226-debug_bus-v6-4-5d794697798d@foss.st.com Signed-off-by: Alexandre Torgue --- drivers/bus/stm32_firewall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bus/stm32_firewall.c b/drivers/bus/stm32_firewall.c index b023d1f4fcf7..e69bc8c1a4e7 100644 --- a/drivers/bus/stm32_firewall.c +++ b/drivers/bus/stm32_firewall.c @@ -267,7 +267,7 @@ int stm32_firewall_populate_bus(struct stm32_firewall_controller *firewall_contr } for (i = 0; i < len; i++) { - if (firewall_controller->grant_access(firewall_controller, + if (firewall_controller->grant_access(firewalls[i].firewall_ctrl, firewalls[i].firewall_id)) { /* * Peripheral access not allowed or not defined. From 4ea96cfc728bbc7c1c3051cce9209bf9a6eeb23e Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Thu, 26 Feb 2026 11:30:20 +0100 Subject: [PATCH 126/193] bus: stm32_firewall: add stm32_firewall_get_grant_all_access() API Add the stm32_firewall_get_grant_all_access() API to be able to fetch all firewall references in an access-controllers property and try to grant access to all of them. Signed-off-by: Gatien Chevallier Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20260226-debug_bus-v6-5-5d794697798d@foss.st.com Signed-off-by: Alexandre Torgue --- drivers/bus/stm32_firewall.c | 42 +++++++++++++++++++++++ include/linux/bus/stm32_firewall_device.h | 26 ++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/drivers/bus/stm32_firewall.c b/drivers/bus/stm32_firewall.c index e69bc8c1a4e7..e3619dba8b06 100644 --- a/drivers/bus/stm32_firewall.c +++ b/drivers/bus/stm32_firewall.c @@ -184,6 +184,48 @@ void stm32_firewall_release_access_by_id(struct stm32_firewall *firewall, u32 su } EXPORT_SYMBOL_GPL(stm32_firewall_release_access_by_id); +int stm32_firewall_get_grant_all_access(struct device *dev, struct stm32_firewall **firewall, + int *nb_firewall) +{ + struct stm32_firewall *loc_firewall; + int err; + int i; + + *nb_firewall = of_count_phandle_with_args(dev->of_node, "access-controllers", + "#access-controller-cells"); + if (*nb_firewall < 0) + return *nb_firewall; + + if (!*nb_firewall) { + *firewall = NULL; + return 0; + } + + loc_firewall = devm_kcalloc(dev, *nb_firewall, sizeof(*loc_firewall), GFP_KERNEL); + if (!loc_firewall) + return -ENOMEM; + + /* Get stm32 firewall information */ + err = stm32_firewall_get_firewall(dev->of_node, loc_firewall, *nb_firewall); + if (err) + return err; + + for (i = 0; i < *nb_firewall; i++) { + err = stm32_firewall_grant_access(&loc_firewall[i]); + if (err) { + while (i--) + stm32_firewall_release_access(&loc_firewall[i]); + + return err; + } + } + + *firewall = loc_firewall; + + return 0; +} +EXPORT_SYMBOL_GPL(stm32_firewall_get_grant_all_access); + /* Firewall controller API */ int stm32_firewall_controller_register(struct stm32_firewall_controller *firewall_controller) diff --git a/include/linux/bus/stm32_firewall_device.h b/include/linux/bus/stm32_firewall_device.h index eaa7a3f54450..6c878f3ca86f 100644 --- a/include/linux/bus/stm32_firewall_device.h +++ b/include/linux/bus/stm32_firewall_device.h @@ -112,6 +112,25 @@ int stm32_firewall_grant_access_by_id(struct stm32_firewall *firewall, u32 subsy */ void stm32_firewall_release_access_by_id(struct stm32_firewall *firewall, u32 subsystem_id); +/** + * stm32_firewall_get_grant_all_access - Allocate and get all the firewall(s) associated to given + * device. Then, try to grant access rights for each element. + * This function is basically a helper function that wraps + * both stm32_firewall_get_firewall() and + * stm32_firewall_grant_access() on all firewall references of + * a device along with the allocation of the array. + * Realease access using stm32_firewall_release_access* APIs + * when done. + * + * @dev: Device performing the checks + * @firewall: Pointer to the array of firewall references to be allocated + * @nb_firewall: Number of allocated elements in @firewall + * + * Returns 0 on success, or appropriate errno code if error occurred. + */ +int stm32_firewall_get_grant_all_access(struct device *dev, struct stm32_firewall **firewall, + int *nb_firewall); + #else /* CONFIG_STM32_FIREWALL */ static inline int stm32_firewall_get_firewall(struct device_node *np, @@ -141,5 +160,12 @@ static inline void stm32_firewall_release_access_by_id(struct stm32_firewall *fi { } +static inline int stm32_firewall_get_grant_all_access(struct device *dev, + struct stm32_firewall **firewall, + int *nb_firewall) +{ + return -ENODEV; +} + #endif /* CONFIG_STM32_FIREWALL */ #endif /* STM32_FIREWALL_DEVICE_H */ From f1939c6a0bed6a4af8339fd0aeb28a17b7a0d4c7 Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Thu, 26 Feb 2026 11:30:21 +0100 Subject: [PATCH 127/193] drivers: bus: add the stm32 debug bus driver Add the stm32 debug bus driver that is responsible of checking the debug subsystem accessibility before probing the related peripheral drivers. This driver is OP-TEE dependent and relies on the STM32 debug access PTA. Signed-off-by: Gatien Chevallier Link: https://lore.kernel.org/r/20260226-debug_bus-v6-6-5d794697798d@foss.st.com Signed-off-by: Alexandre Torgue --- MAINTAINERS | 1 + drivers/bus/Kconfig | 10 ++ drivers/bus/Makefile | 1 + drivers/bus/stm32_dbg_bus.c | 250 ++++++++++++++++++++++++++++++++++++ 4 files changed, 262 insertions(+) create mode 100644 drivers/bus/stm32_dbg_bus.c diff --git a/MAINTAINERS b/MAINTAINERS index 55af015174a5..63f59748d661 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -25009,6 +25009,7 @@ F: drivers/hwmon/pmbus/stef48h28.c ST STM32 FIREWALL M: Gatien Chevallier S: Maintained +F: drivers/bus/stm32_dbg_bus.c F: drivers/bus/stm32_etzpc.c F: drivers/bus/stm32_firewall.c F: drivers/bus/stm32_rifsc.c diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 2a1b46f07080..7a1b04007efb 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -169,6 +169,16 @@ config QCOM_SSC_BLOCK_BUS i2c/spi/uart controllers, a hexagon core, and a clock controller which provides clocks for the above. +config STM32_DBG_BUS + tristate "OP-TEE based debug access bus" + depends on OPTEE && STM32_FIREWALL + depends on ARCH_STM32 || COMPILE_TEST + help + Select this to get the support for the OP-TEE based STM32 debug bus + driver that is used to handle debug-related peripherals on STM32 + platforms when the debug configuration is not accessible by the + normal world. + config STM32_FIREWALL bool "STM32 Firewall framework" depends on (ARCH_STM32 || COMPILE_TEST) && OF diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index 8e693fe8a03a..799724cfc2df 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o obj-$(CONFIG_QCOM_SSC_BLOCK_BUS) += qcom-ssc-block-bus.o +obj-$(CONFIG_STM32_DBG_BUS) += stm32_dbg_bus.o obj-$(CONFIG_STM32_FIREWALL) += stm32_firewall.o stm32_rifsc.o stm32_etzpc.o obj-$(CONFIG_SUN50I_DE2_BUS) += sun50i-de2.o obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o diff --git a/drivers/bus/stm32_dbg_bus.c b/drivers/bus/stm32_dbg_bus.c new file mode 100644 index 000000000000..e30ef3465609 --- /dev/null +++ b/drivers/bus/stm32_dbg_bus.c @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum stm32_dbg_profile { + PERIPHERAL_DBG_PROFILE = 0, + HDP_DBG_PROFILE = 1, +}; + +enum stm32_dbg_pta_command { + /* + * PTA_CMD_GRANT_DBG_ACCESS - Verify the debug configuration against the given debug profile + * and grant access or not + * + * [in] value[0].a Debug profile to grant access to. + */ + PTA_CMD_GRANT_DBG_ACCESS, +}; + +/** + * struct stm32_dbg_bus - OP-TEE based STM32 debug bus private data + * @dev: STM32 debug bus device. + * @ctx: OP-TEE context handler. + */ +struct stm32_dbg_bus { + struct device *dev; + struct tee_context *ctx; +}; + +/* Expect at most 1 instance of this driver */ +static struct stm32_dbg_bus *stm32_dbg_bus_priv; + +static int stm32_dbg_pta_open_session(u32 *id) +{ + struct tee_client_device *dbg_bus_dev = to_tee_client_device(stm32_dbg_bus_priv->dev); + struct tee_ioctl_open_session_arg sess_arg; + int ret; + + memset(&sess_arg, 0, sizeof(sess_arg)); + export_uuid(sess_arg.uuid, &dbg_bus_dev->id.uuid); + sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL; + + ret = tee_client_open_session(stm32_dbg_bus_priv->ctx, &sess_arg, NULL); + if (ret < 0 || sess_arg.ret) { + dev_err(stm32_dbg_bus_priv->dev, "Failed opening tee session, err: %#x\n", + sess_arg.ret); + return -EOPNOTSUPP; + } + + *id = sess_arg.session; + + return 0; +} + +static void stm32_dbg_pta_close_session(u32 id) +{ + tee_client_close_session(stm32_dbg_bus_priv->ctx, id); +} + +static int stm32_dbg_bus_grant_access(struct stm32_firewall_controller *ctrl, u32 dbg_profile) +{ + struct tee_ioctl_invoke_arg inv_arg = {0}; + struct tee_param param[1] = {0}; + u32 session_id; + int ret; + + if (dbg_profile != PERIPHERAL_DBG_PROFILE && dbg_profile != HDP_DBG_PROFILE) + return -EOPNOTSUPP; + + ret = stm32_dbg_pta_open_session(&session_id); + if (ret) + return ret; + + inv_arg.func = PTA_CMD_GRANT_DBG_ACCESS; + inv_arg.session = session_id; + inv_arg.num_params = 1; + param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; + param[0].u.value.a = dbg_profile; + + ret = tee_client_invoke_func(stm32_dbg_bus_priv->ctx, &inv_arg, param); + if (ret < 0 || inv_arg.ret != 0) { + dev_dbg(stm32_dbg_bus_priv->dev, + "When invoking function, err %x, TEE returns: %x\n", ret, inv_arg.ret); + if (!ret) + ret = -EACCES; + } + + stm32_dbg_pta_close_session(session_id); + + return ret; +} + +/* Implement mandatory release_access ops even if it does nothing*/ +static void stm32_dbg_bus_release_access(struct stm32_firewall_controller *ctrl, u32 dbg_profile) +{ +} + +static int stm32_dbg_bus_plat_probe(struct platform_device *pdev) +{ + struct stm32_firewall_controller *dbg_controller; + int ret; + + /* Defer if OP-TEE service is not yet available */ + if (!stm32_dbg_bus_priv) + return -EPROBE_DEFER; + + dbg_controller = devm_kzalloc(&pdev->dev, sizeof(*dbg_controller), GFP_KERNEL); + if (!dbg_controller) + return dev_err_probe(&pdev->dev, -ENOMEM, "Couldn't allocate debug controller\n"); + + dbg_controller->dev = &pdev->dev; + dbg_controller->mmio = NULL; + dbg_controller->name = dev_driver_string(dbg_controller->dev); + dbg_controller->type = STM32_PERIPHERAL_FIREWALL; + dbg_controller->grant_access = stm32_dbg_bus_grant_access; + dbg_controller->release_access = stm32_dbg_bus_release_access; + + ret = stm32_firewall_controller_register(dbg_controller); + if (ret) { + dev_err(dbg_controller->dev, "Couldn't register as a firewall controller: %d", ret); + return ret; + } + + ret = stm32_firewall_populate_bus(dbg_controller); + if (ret) { + dev_err(dbg_controller->dev, "Couldn't populate debug bus: %d", ret); + stm32_firewall_controller_unregister(dbg_controller); + return ret; + } + + pm_runtime_enable(&pdev->dev); + + ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); + if (ret) { + dev_err(dbg_controller->dev, "Couldn't populate the node: %d", ret); + stm32_firewall_controller_unregister(dbg_controller); + return ret; + } + + return 0; +} + +static const struct of_device_id stm32_dbg_bus_of_match[] = { + { .compatible = "st,stm32mp131-dbg-bus", }, + { .compatible = "st,stm32mp151-dbg-bus", }, + { }, +}; +MODULE_DEVICE_TABLE(of, stm32_dbg_bus_of_match); + +static struct platform_driver stm32_dbg_bus_driver = { + .probe = stm32_dbg_bus_plat_probe, + .driver = { + .name = "stm32-dbg-bus", + .of_match_table = stm32_dbg_bus_of_match, + }, +}; + +static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data) +{ + return (ver->impl_id == TEE_IMPL_ID_OPTEE); +} + +static void stm32_dbg_bus_remove(struct tee_client_device *tee_dev) +{ + tee_client_close_context(stm32_dbg_bus_priv->ctx); + stm32_dbg_bus_priv = NULL; + + of_platform_depopulate(&tee_dev->dev); +} + +static int stm32_dbg_bus_probe(struct tee_client_device *tee_dev) +{ + struct device *dev = &tee_dev->dev; + struct stm32_dbg_bus *priv; + int ret = 0; + + if (stm32_dbg_bus_priv) + return dev_err_probe(dev, -EBUSY, + "A STM32 debug bus device is already initialized\n"); + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* Open context with TEE driver */ + priv->ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL); + if (IS_ERR_OR_NULL(priv->ctx)) + return dev_err_probe(dev, PTR_ERR_OR_ZERO(priv->ctx), "Cannot open TEE context\n"); + + stm32_dbg_bus_priv = priv; + stm32_dbg_bus_priv->dev = dev; + + return ret; +} + +static const struct tee_client_device_id optee_dbg_bus_id_table[] = { + {UUID_INIT(0xdd05bc8b, 0x9f3b, 0x49f0, + 0xb6, 0x49, 0x01, 0xaa, 0x10, 0xc1, 0xc2, 0x10)}, + {} +}; + +static struct tee_client_driver stm32_optee_dbg_bus_driver = { + .id_table = optee_dbg_bus_id_table, + .probe = stm32_dbg_bus_probe, + .remove = stm32_dbg_bus_remove, + .driver = { + .name = "optee_dbg_bus", + }, +}; + +static void __exit stm32_optee_dbg_bus_driver_exit(void) +{ + platform_driver_unregister(&stm32_dbg_bus_driver); + tee_client_driver_unregister(&stm32_optee_dbg_bus_driver); +} +module_exit(stm32_optee_dbg_bus_driver_exit); + +static int __init stm32_optee_dbg_bus_driver_init(void) +{ + int err; + + err = tee_client_driver_register(&stm32_optee_dbg_bus_driver); + if (err) + return err; + + err = platform_driver_register(&stm32_dbg_bus_driver); + if (err) + tee_client_driver_unregister(&stm32_optee_dbg_bus_driver); + + return err; +} +module_init(stm32_optee_dbg_bus_driver_init); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gatien Chevallier "); +MODULE_DESCRIPTION("OP-TEE based STM32 debug access bus driver"); From 348741a97c28d7679fb1e204aeec0d6305fc6817 Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Thu, 26 Feb 2026 11:30:27 +0100 Subject: [PATCH 128/193] pinctrl: stm32: add firewall checks before probing the HDP driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because the HDP peripheral both depends on debug and firewall configuration, when CONFIG_STM32_FIREWALL is present, use the stm32 firewall framework to be able to check these configuration against the relevant controllers. Signed-off-by: Gatien Chevallier Reviewed-by: Clément Le Goffic Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20260226-debug_bus-v6-12-5d794697798d@foss.st.com Signed-off-by: Alexandre Torgue --- drivers/pinctrl/stm32/pinctrl-stm32-hdp.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32-hdp.c b/drivers/pinctrl/stm32/pinctrl-stm32-hdp.c index 0b1dff01e04c..cce477e86ef9 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32-hdp.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32-hdp.c @@ -4,6 +4,7 @@ * Author: Clément Le Goffic for STMicroelectronics. */ #include +#include #include #include #include @@ -46,9 +47,11 @@ struct stm32_hdp { void __iomem *base; struct clk *clk; struct pinctrl_dev *pctl_dev; + struct stm32_firewall *firewall; struct gpio_generic_chip gpio_chip; u32 mux_conf; u32 gposet_conf; + int nb_firewall_entries; const char * const *func_name; }; @@ -615,6 +618,13 @@ static int stm32_hdp_probe(struct platform_device *pdev) return -ENOMEM; hdp->dev = dev; + if (IS_ENABLED(CONFIG_STM32_FIREWALL)) { + err = stm32_firewall_get_grant_all_access(dev, &hdp->firewall, + &hdp->nb_firewall_entries); + if (err) + return err; + } + platform_set_drvdata(pdev, hdp); hdp->base = devm_platform_ioremap_resource(pdev, 0); @@ -670,8 +680,12 @@ static int stm32_hdp_probe(struct platform_device *pdev) static void stm32_hdp_remove(struct platform_device *pdev) { struct stm32_hdp *hdp = platform_get_drvdata(pdev); + int i; writel_relaxed(HDP_CTRL_DISABLE, hdp->base + HDP_CTRL); + + for (i = 0; i < hdp->nb_firewall_entries; i++) + stm32_firewall_release_access(&hdp->firewall[i]); } static int stm32_hdp_suspend(struct device *dev) From 624a97208904ed50288f32e8b1ecc9ff9aeddf1b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 25 Mar 2026 13:08:47 +0100 Subject: [PATCH 129/193] soc: qcom: ubwc: Remove redundant x1e80100_data UBWC data for X1E80100 is exactly the same as one for SM8550, so reduce code duplication by reusing older entry. Reviewed-by: Konrad Dybcio Cc: Dmitry Baryshkov Signed-off-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260325120846.139836-2-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ubwc_config.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/soc/qcom/ubwc_config.c b/drivers/soc/qcom/ubwc_config.c index 8304463f238a..e63daf748e30 100644 --- a/drivers/soc/qcom/ubwc_config.c +++ b/drivers/soc/qcom/ubwc_config.c @@ -217,17 +217,6 @@ static const struct qcom_ubwc_cfg_data sm8750_data = { .macrotile_mode = true, }; -static const struct qcom_ubwc_cfg_data x1e80100_data = { - .ubwc_enc_version = UBWC_4_0, - .ubwc_dec_version = UBWC_4_3, - .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | - UBWC_SWIZZLE_ENABLE_LVL3, - .ubwc_bank_spread = true, - /* TODO: highest_bank_bit = 15 for LP_DDR4 */ - .highest_bank_bit = 16, - .macrotile_mode = true, -}; - static const struct qcom_ubwc_cfg_data glymur_data = { .ubwc_enc_version = UBWC_5_0, .ubwc_dec_version = UBWC_5_0, @@ -293,8 +282,8 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = { { .compatible = "qcom,sm8550", .data = &sm8550_data, }, { .compatible = "qcom,sm8650", .data = &sm8550_data, }, { .compatible = "qcom,sm8750", .data = &sm8750_data, }, - { .compatible = "qcom,x1e80100", .data = &x1e80100_data, }, - { .compatible = "qcom,x1p42100", .data = &x1e80100_data, }, + { .compatible = "qcom,x1e80100", .data = &sm8550_data, }, + { .compatible = "qcom,x1p42100", .data = &sm8550_data, }, { } }; From 9a116af73a3c90cbfc78d6b007325539056f83be Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 25 Mar 2026 13:16:49 +0100 Subject: [PATCH 130/193] soc: qcom: ubwc: Add configuration Eliza SoC Add configuration data and an entry to OF table for matching the Eliza SoC. Reviewed-by: Konrad Dybcio Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260325-drm-display-eliza-v3-8-dc2b2f0c74a2@oss.qualcomm.com [bjorn: Reordered device_id list] Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ubwc_config.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/soc/qcom/ubwc_config.c b/drivers/soc/qcom/ubwc_config.c index e63daf748e30..355d9ea1f7d9 100644 --- a/drivers/soc/qcom/ubwc_config.c +++ b/drivers/soc/qcom/ubwc_config.c @@ -16,6 +16,17 @@ static const struct qcom_ubwc_cfg_data no_ubwc_data = { /* no UBWC, no HBB */ }; +static const struct qcom_ubwc_cfg_data eliza_data = { + .ubwc_enc_version = UBWC_5_0, + .ubwc_dec_version = UBWC_5_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_bank_spread = true, + /* TODO: highest_bank_bit = 14 for LP_DDR4 */ + .highest_bank_bit = 15, + .macrotile_mode = true, +}; + static const struct qcom_ubwc_cfg_data kaanapali_data = { .ubwc_enc_version = UBWC_6_0, .ubwc_dec_version = UBWC_6_0, @@ -232,6 +243,7 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = { { .compatible = "qcom,apq8026", .data = &no_ubwc_data }, { .compatible = "qcom,apq8074", .data = &no_ubwc_data }, { .compatible = "qcom,apq8096", .data = &msm8998_data }, + { .compatible = "qcom,eliza", .data = &eliza_data, }, { .compatible = "qcom,kaanapali", .data = &kaanapali_data, }, { .compatible = "qcom,glymur", .data = &glymur_data}, { .compatible = "qcom,msm8226", .data = &no_ubwc_data }, From 2725be96755b6f9c5a1fa41a1a675a86d9e8a019 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 24 Mar 2026 12:53:49 +0000 Subject: [PATCH 131/193] soc: qcom: pd-mapper: Add support for Glymur and Mahua Add Protection Domains for Qualcomm Glymur and Mahua SoC which have both ADSP and CDSP. Adding this entry to the kernel will avoid the need for userspace to provide this service. Signed-off-by: Srinivas Kandagatla Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260324125349.2380904-1-srinivas.kandagatla@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_pd_mapper.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index 72698772838e..003aa88fc372 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -360,6 +360,14 @@ static const struct qcom_pdm_domain_data mpss_wlan_pd = { }, }; +static const struct qcom_pdm_domain_data *glymur_domains[] = { + &adsp_audio_pd, + &adsp_root_pd, + &adsp_sensor_pd, + &cdsp_root_pd, + NULL, +}; + static const struct qcom_pdm_domain_data *kaanapali_domains[] = { &adsp_audio_pd, &adsp_root_pd, @@ -571,7 +579,9 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,apq8074", .data = NULL, }, { .compatible = "qcom,apq8084", .data = NULL, }, { .compatible = "qcom,apq8096", .data = msm8996_domains, }, + { .compatible = "qcom,glymur", .data = glymur_domains, }, { .compatible = "qcom,kaanapali", .data = kaanapali_domains, }, + { .compatible = "qcom,mahua", .data = glymur_domains, }, { .compatible = "qcom,milos", .data = sm8550_domains, }, { .compatible = "qcom,msm8226", .data = NULL, }, { .compatible = "qcom,msm8909", .data = NULL, }, From 85adc680c60bcd3b3ff83296410f13eee49f5df0 Mon Sep 17 00:00:00 2001 From: Gopikrishna Garmidi Date: Tue, 24 Mar 2026 10:14:57 -0700 Subject: [PATCH 132/193] soc: qcom: ubwc: Add support for Mahua Mahua is a derivative of the Glymur SoC. Add the Mahua compatible to the UBWC configuration table to enable support. Signed-off-by: Gopikrishna Garmidi Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260324-mahua_ubwc_config_support-v1-1-037d35ff2317@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 355d9ea1f7d9..3fe47d8f0f63 100644 --- a/drivers/soc/qcom/ubwc_config.c +++ b/drivers/soc/qcom/ubwc_config.c @@ -246,6 +246,7 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = { { .compatible = "qcom,eliza", .data = &eliza_data, }, { .compatible = "qcom,kaanapali", .data = &kaanapali_data, }, { .compatible = "qcom,glymur", .data = &glymur_data}, + { .compatible = "qcom,mahua", .data = &glymur_data }, { .compatible = "qcom,msm8226", .data = &no_ubwc_data }, { .compatible = "qcom,msm8916", .data = &no_ubwc_data }, { .compatible = "qcom,msm8917", .data = &no_ubwc_data }, From dc67808832d3a1d337c314a2c950f9bf774a21b2 Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Wed, 25 Mar 2026 17:09:43 +0530 Subject: [PATCH 133/193] dt-bindings: firmware: qcom,scm: Document ipq9650 SCM Document the scm compatible for ipq9650 SoC. Signed-off-by: Kathiravan Thirumoorthy Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260325-ipq9650_scm-v1-1-ad6a3fe53f38@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 f628b1d70fa1..7918d31f58b4 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -34,6 +34,7 @@ properties: - qcom,scm-ipq806x - qcom,scm-ipq8074 - qcom,scm-ipq9574 + - qcom,scm-ipq9650 - qcom,scm-kaanapali - qcom,scm-mdm9607 - qcom,scm-milos From 05452c58ef4f308f67b9bc7b37e8dcb7e5aa988d Mon Sep 17 00:00:00 2001 From: Josua Mayer Date: Thu, 26 Feb 2026 18:36:30 +0200 Subject: [PATCH 134/193] dt-bindings: arm: fsl: Add various solidrun i.MX8M boards Add bindings for various SolidRun boards: - i.MX8MP HummingBoard IIoT - based on the SolidRun i.MX8M Plus SoM - SolidSense N8 - single-board design with i.MX8M Nano - i.MX8M Mini System on Module - i.MX8M Mini HummingBoard Ripple Acked-by: Krzysztof Kozlowski Signed-off-by: Josua Mayer Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index fe31a9476889..6994c57afa1b 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1049,6 +1049,13 @@ properties: - const: phytec,imx8mm-phycore-som # phyCORE-i.MX8MM SoM - const: fsl,imx8mm + - description: SolidRun i.MX8MM SoM based boards + items: + - enum: + - solidrun,imx8mm-hummingboard-ripple # SolidRun i.MX8MM SoM on HummingBoard Ripple + - const: solidrun,imx8mm-sr-som + - const: fsl,imx8mm + - description: Variscite VAR-SOM-MX8MM based boards items: - const: variscite,var-som-mx8mm-symphony @@ -1077,6 +1084,7 @@ properties: - fsl,imx8mn-ddr4-evk # i.MX8MN DDR4 EVK Board - fsl,imx8mn-evk # i.MX8MN LPDDR4 EVK Board - gw,imx8mn-gw7902 # i.MX8MM Gateworks Board + - solidrun,solidsense-n8-compact # SolidRun SolidSense N8 Compact - const: fsl,imx8mn - description: ifm i.MX8MN VHIP4 based boards @@ -1233,6 +1241,7 @@ properties: items: - enum: - solidrun,imx8mp-cubox-m # SolidRun i.MX8MP SoM on CuBox-M + - solidrun,imx8mp-hummingboard-iiot # SolidRun i.MX8MP SoM on HummingBoard IIoT - solidrun,imx8mp-hummingboard-mate # SolidRun i.MX8MP SoM on HummingBoard Mate - solidrun,imx8mp-hummingboard-pro # SolidRun i.MX8MP SoM on HummingBoard Pro - solidrun,imx8mp-hummingboard-pulse # SolidRun i.MX8MP SoM on HummingBoard Pulse From f2c05ff2fe69ebbd63038160b063b0bc88dbe4e9 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 27 Feb 2026 09:58:36 +0800 Subject: [PATCH 135/193] dt-bindings: arm: fsl: Add compatible for i.MX8MP audio board (version 2) Introduce a new DT compatible string for the NXP i.MX8MP audio board (version 2). i.MX Audio Board is a configurable and functional audio processing platform. Integrating a variety of audio input and output interfaces into the system, the i.MX Audio Board supports HDMI input, HDMI eARC, S/PDIF I/O, 2-ch ADC line-in, 24-ch DAC line-out and more. Based on these features, rich audio application cases can be realized. Signed-off-by: Shengjiu Wang Acked-by: Conor Dooley Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 6994c57afa1b..f5d3c08369b9 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1122,6 +1122,7 @@ properties: - beacon,imx8mp-beacon-kit # i.MX8MP Beacon Development Kit - dmo,imx8mp-data-modul-edm-sbc # i.MX8MP eDM SBC - emcraft,imx8mp-navqp # i.MX8MP Emcraft Systems NavQ+ Kit + - fsl,imx8mp-ab2 # i.MX8MP Audio Board V2 - fsl,imx8mp-evk # i.MX8MP EVK Board - fsl,imx8mp-evk-revb4 # i.MX8MP EVK Rev B4 Board - fsl,imx8mp-frdm # i.MX8MP Freedom Board From 0b7973dfb7467f69843fb56bf62c7cb440a0bc3c Mon Sep 17 00:00:00 2001 From: Ciprian Marian Costea Date: Wed, 11 Mar 2026 09:11:50 +0100 Subject: [PATCH 136/193] dt-bindings: interrupt-controller: fsl,irqsteer: add S32N79 support Add compatible string for the interrupt steering controller used in NXP S32N79 SoC. The S32N79 SoC differs from the i.MX version by not implementing the CHANCTRL register, but otherwise maintains the same programming model and register layout. Co-developed-by: Larisa Grigore Signed-off-by: Larisa Grigore Signed-off-by: Ciprian Marian Costea Reviewed-by: Krzysztof Kozlowski Signed-off-by: Frank Li --- .../bindings/interrupt-controller/fsl,irqsteer.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,irqsteer.yaml b/Documentation/devicetree/bindings/interrupt-controller/fsl,irqsteer.yaml index 5c768c1e159c..13cd37bf48e4 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/fsl,irqsteer.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,irqsteer.yaml @@ -12,7 +12,9 @@ maintainers: properties: compatible: oneOf: - - const: fsl,imx-irqsteer + - enum: + - fsl,imx-irqsteer + - nxp,s32n79-irqsteer - items: - enum: - fsl,imx8m-irqsteer From bda4af7c7811382ab477421a83c29b5ef187fee9 Mon Sep 17 00:00:00 2001 From: Ciprian Marian Costea Date: Wed, 11 Mar 2026 09:11:51 +0100 Subject: [PATCH 137/193] dt-bindings: arm: fsl: Add NXP S32N79 SoC and RDB board Add device tree binding documentation for the NXP S32N79 automotive SoC and the S32N79 Reference Design Board (S32N79-RDB). The S32N79 is an automotive-grade SoC featuring eight ARM Cortex-A78AE cores organized for high-performance networking and gateway applications in vehicles. Co-developed-by: Larisa Grigore Signed-off-by: Larisa Grigore Signed-off-by: Ciprian Marian Costea Acked-by: Krzysztof Kozlowski Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index f5d3c08369b9..da2be7114f64 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1869,6 +1869,12 @@ properties: - fsl,s32v234-evb # S32V234-EVB2 Customer Evaluation Board - const: fsl,s32v234 + - description: S32N79 based Boards + items: + - enum: + - nxp,s32n79-rdb + - const: nxp,s32n79 + - description: Traverse LS1088A based Boards items: - enum: From 43dcd2c99ff4f4370eb22b61968204890d7e94be Mon Sep 17 00:00:00 2001 From: Frank Li Date: Wed, 15 Oct 2025 14:48:45 -0400 Subject: [PATCH 138/193] dt-bindings: arm: lpc: add missed lpc43xx board Add missed legancy lpc43xx board compatible string to fix below CHECK_DTB warnings: arch/arm/boot/dts/nxp/lpc/lpc4337-ciaa.dtb: /: failed to match any schema with compatible: ['ciaa,lpc4337', 'nxp,lpc4337', 'nxp,lpc4350'] Reviewed-by: Vladimir Zapolskiy Reviewed-by: Krzysztof Kozlowski Signed-off-by: Frank Li --- .../devicetree/bindings/arm/nxp/lpc32xx.yaml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/nxp/lpc32xx.yaml b/Documentation/devicetree/bindings/arm/nxp/lpc32xx.yaml index 6b7f5e6f99cf..1e290f16a7a5 100644 --- a/Documentation/devicetree/bindings/arm/nxp/lpc32xx.yaml +++ b/Documentation/devicetree/bindings/arm/nxp/lpc32xx.yaml @@ -22,5 +22,27 @@ properties: - phytec,phy3250 - const: nxp,lpc3250 + - items: + - enum: + - ea,lpc4357-developers-kit + - const: nxp,lpc4357 + - const: nxp,lpc4350 + + - items: + - enum: + - ciaa,lpc4337 + - const: nxp,lpc4337 + - const: nxp,lpc4350 + + - items: + - enum: + - hitex,lpc4350-eval-board + - const: nxp,lpc4350 + + - items: + - enum: + - myir,myd-lpc4357 + - const: nxp,lpc4357 + additionalProperties: true ... From d44627c13049ea347d59ef5c75b1ceef27725bde Mon Sep 17 00:00:00 2001 From: Markus Niebel Date: Mon, 16 Mar 2026 16:04:51 +0100 Subject: [PATCH 139/193] dt-bindings: arm: add bindings for TQMa95xxLA TQMa95xxLA is a SOM using NXP i.MX95 CPU. MBa95xxCA is a carrier reference design / starter kit board. [1] https://www.tq-group.com/en/products/tq-embedded/arm-architecture/tqma95xxla/ Signed-off-by: Markus Niebel Signed-off-by: Alexander Stein Acked-by: Krzysztof Kozlowski Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index da2be7114f64..bea66d3830f6 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1599,6 +1599,17 @@ properties: - const: kontron,imx93-osm-s # Kontron OSM-S i.MX93 SoM - const: fsl,imx93 + - description: + TQMa95xxLA is a series of SOM featuring NXP i.MX95 SoC variants, + designed to be soldered on different carrier boards. + MBa95xxCA is a carrier reference design / starter kit that allows + to use TQMa95xxLA via an adaper board. + items: + - enum: + - tq,imx95-tqma9596la-mba95xxca # TQ-Systems GmbH i.MX95 TQMa95xxLA SOM on MBa95xxCA + - const: tq,imx95-tqma9596la # TQ-Systems GmbH i.MX95 TQMa95xxLA SOM + - const: fsl,imx95 + - description: TQMa95xxSA is a series of SOM featuring NXP i.MX95 SoC variants. It has the SMARC form factor and is designed to be placed on From 53210b46cd11260334f4025769c3c74886015fef Mon Sep 17 00:00:00 2001 From: Martin Schmiedel Date: Thu, 19 Mar 2026 13:50:08 +0100 Subject: [PATCH 140/193] dt-bindings: arm: fsl: add MBa93xxLA-MINI Adds support for the MBa93xxLA-MINI SBC. https://www.tq-group.com/en/products/tq-embedded/arm-architecture/mba93xxla-mini/ Signed-off-by: Martin Schmiedel Signed-off-by: Alexander Stein Reviewed-by: Daniel Baluta Acked-by: Conor Dooley Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index bea66d3830f6..3d4f3cd517c8 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1558,11 +1558,14 @@ properties: soldered on an adapter board or for the connector variant MBa93xxLA mainboard is a single board computer using the solderable SOM variant + MBa93xxLA-MINI mainboard is a single board computer using the solderable + SOM variant items: - enum: - tq,imx93-tqma9352-mba91xxca # TQ-Systems GmbH i.MX93 TQMa93xxCA/LA SOM on MBa91xxCA - tq,imx93-tqma9352-mba93xxca # TQ-Systems GmbH i.MX93 TQMa93xxCA/LA SOM on MBa93xxCA - tq,imx93-tqma9352-mba93xxla # TQ-Systems GmbH i.MX93 TQMa93xxLA SOM on MBa93xxLA SBC + - tq,imx93-tqma9352-mba93xxla-mini # TQ-Systems GmbH i.MX93 TQMa93xxLA SOM on MBa93xxLA-MINI SBC - const: tq,imx93-tqma9352 # TQ-Systems GmbH i.MX93 TQMa93xxCA/LA SOM - const: fsl,imx93 From e54390aae6887151ff67526af45382beb889f99a Mon Sep 17 00:00:00 2001 From: Ernest Van Hoecke Date: Wed, 25 Mar 2026 15:46:02 +0100 Subject: [PATCH 141/193] dt-bindings: arm: fsl: add Verdin iMX95 Add DT compatible strings for the Verdin i.MX95 SoM and its supported carrier boards: the Verdin Development Board, and the Dahlia, Ivy, Mallow and Yavia carrier boards. Link: https://www.toradex.com/computer-on-modules/verdin-arm-family/nxp-imx95 Link: https://www.toradex.com/products/carrier-board/verdin-development-board-kit Link: https://www.toradex.com/products/carrier-board/dahlia-carrier-board-kit Link: https://www.toradex.com/products/carrier-board/ivy-carrier-board Link: https://www.toradex.com/products/carrier-board/mallow-carrier-board Link: https://www.toradex.com/products/carrier-board/yavia Reviewed-by: Krzysztof Kozlowski Signed-off-by: Ernest Van Hoecke Signed-off-by: Frank Li --- .../devicetree/bindings/arm/fsl.yaml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 3d4f3cd517c8..0023cd126807 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1507,6 +1507,30 @@ properties: - const: toradex,smarc-imx95 # Toradex SMARC iMX95 Module - const: fsl,imx95 + - description: Toradex Boards with Verdin iMX95 Modules + items: + - enum: + - toradex,verdin-imx95-nonwifi-dahlia # Verdin iMX95 Module on Dahlia + - toradex,verdin-imx95-nonwifi-dev # Verdin iMX95 Module on Verdin Development Board + - toradex,verdin-imx95-nonwifi-ivy # Verdin iMX95 Module on Ivy + - toradex,verdin-imx95-nonwifi-mallow # Verdin iMX95 Module on Mallow + - toradex,verdin-imx95-nonwifi-yavia # Verdin iMX95 Module on Yavia + - const: toradex,verdin-imx95-nonwifi # Verdin iMX95 Module without Wi-Fi / BT + - const: toradex,verdin-imx95 # Verdin iMX95 Module + - const: fsl,imx95 + + - description: Toradex Boards with Verdin iMX95 Wi-Fi / BT Modules + items: + - enum: + - toradex,verdin-imx95-wifi-dahlia # Verdin iMX95 Wi-Fi / BT Module on Dahlia + - toradex,verdin-imx95-wifi-dev # Verdin iMX95 Wi-Fi / BT Module on Verdin Development B. + - toradex,verdin-imx95-wifi-ivy # Verdin iMX95 Wi-Fi / BT Module on Ivy + - toradex,verdin-imx95-wifi-mallow # Verdin iMX95 Wi-Fi / BT Module on Mallow + - toradex,verdin-imx95-wifi-yavia # Verdin iMX95 Wi-Fi / BT Module on Yavia + - const: toradex,verdin-imx95-wifi # Verdin iMX95 Wi-Fi / BT Module + - const: toradex,verdin-imx95 # Verdin iMX95 Module + - const: fsl,imx95 + - description: Variscite DART-MX95 based Boards items: - const: variscite,var-dart-mx95-sonata # Variscite DART-MX95 SOM on Sonata Development Board From 8889b289ce1bd11a5102b9617742a1b93bb4843e Mon Sep 17 00:00:00 2001 From: Tommaso Merciai Date: Thu, 12 Mar 2026 15:50:38 +0100 Subject: [PATCH 142/193] reset: rzv2h-usb2phy: Keep PHY clock enabled for entire device lifetime The driver was disabling the USB2 PHY clock immediately after register initialization in probe() and after each reset operation. This left the PHY unclocked even though it must remain active for USB functionality. The behavior appeared to work only when another driver (e.g., USB controller) had already enabled the clock, making operation unreliable and hardware-dependent. In configurations where this driver is the sole clock user, USB functionality would fail. Fix this by: - Enabling the clock once in probe() via pm_runtime_resume_and_get() - Removing all pm_runtime_put() calls from assert/deassert/status - Registering a devm cleanup action to release the clock at removal - Removed rzv2h_usbphy_assert_helper() and its call in rzv2h_usb2phy_reset_probe() This ensures the PHY clock remains enabled for the entire device lifetime, preventing instability and aligning with hardware requirements. Cc: stable@vger.kernel.org Fixes: e3911d7f865b ("reset: Add USB2PHY port reset driver for Renesas RZ/V2H(P)") Signed-off-by: Tommaso Merciai Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/reset-rzv2h-usb2phy.c | 64 ++++++++--------------------- 1 file changed, 18 insertions(+), 46 deletions(-) diff --git a/drivers/reset/reset-rzv2h-usb2phy.c b/drivers/reset/reset-rzv2h-usb2phy.c index ae643575b067..5bdd39274612 100644 --- a/drivers/reset/reset-rzv2h-usb2phy.c +++ b/drivers/reset/reset-rzv2h-usb2phy.c @@ -49,9 +49,10 @@ static inline struct rzv2h_usb2phy_reset_priv return container_of(rcdev, struct rzv2h_usb2phy_reset_priv, rcdev); } -/* This function must be called only after pm_runtime_resume_and_get() has been called */ -static void rzv2h_usbphy_assert_helper(struct rzv2h_usb2phy_reset_priv *priv) +static int rzv2h_usbphy_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) { + struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev); const struct rzv2h_usb2phy_reset_of_data *data = priv->data; scoped_guard(spinlock, &priv->lock) { @@ -60,24 +61,6 @@ static void rzv2h_usbphy_assert_helper(struct rzv2h_usb2phy_reset_priv *priv) } usleep_range(11, 20); -} - -static int rzv2h_usbphy_reset_assert(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev); - struct device *dev = priv->dev; - int ret; - - ret = pm_runtime_resume_and_get(dev); - if (ret) { - dev_err(dev, "pm_runtime_resume_and_get failed\n"); - return ret; - } - - rzv2h_usbphy_assert_helper(priv); - - pm_runtime_put(dev); return 0; } @@ -87,14 +70,6 @@ static int rzv2h_usbphy_reset_deassert(struct reset_controller_dev *rcdev, { struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev); const struct rzv2h_usb2phy_reset_of_data *data = priv->data; - struct device *dev = priv->dev; - int ret; - - ret = pm_runtime_resume_and_get(dev); - if (ret) { - dev_err(dev, "pm_runtime_resume_and_get failed\n"); - return ret; - } scoped_guard(spinlock, &priv->lock) { writel(data->reset_deassert_val, priv->base + data->reset_reg); @@ -102,8 +77,6 @@ static int rzv2h_usbphy_reset_deassert(struct reset_controller_dev *rcdev, writel(data->reset_release_val, priv->base + data->reset_reg); } - pm_runtime_put(dev); - return 0; } @@ -111,20 +84,10 @@ static int rzv2h_usbphy_reset_status(struct reset_controller_dev *rcdev, unsigned long id) { struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev); - struct device *dev = priv->dev; - int ret; u32 reg; - ret = pm_runtime_resume_and_get(dev); - if (ret) { - dev_err(dev, "pm_runtime_resume_and_get failed\n"); - return ret; - } - reg = readl(priv->base + priv->data->reset_reg); - pm_runtime_put(dev); - return (reg & priv->data->reset_status_bits) == priv->data->reset_status_bits; } @@ -141,6 +104,11 @@ static int rzv2h_usb2phy_reset_of_xlate(struct reset_controller_dev *rcdev, return 0; } +static void rzv2h_usb2phy_reset_pm_runtime_put(void *data) +{ + pm_runtime_put(data); +} + static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev) { const struct rzv2h_usb2phy_reset_of_data *data; @@ -175,14 +143,14 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev) if (error) return dev_err_probe(dev, error, "pm_runtime_resume_and_get failed\n"); + error = devm_add_action_or_reset(dev, rzv2h_usb2phy_reset_pm_runtime_put, + dev); + if (error) + return dev_err_probe(dev, error, "unable to register cleanup action\n"); + for (unsigned int i = 0; i < data->init_val_count; i++) writel(data->init_vals[i].val, priv->base + data->init_vals[i].reg); - /* keep usb2phy in asserted state */ - rzv2h_usbphy_assert_helper(priv); - - pm_runtime_put(dev); - priv->rcdev.ops = &rzv2h_usbphy_reset_ops; priv->rcdev.of_reset_n_cells = 0; priv->rcdev.nr_resets = 1; @@ -190,7 +158,11 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev) priv->rcdev.of_node = dev->of_node; priv->rcdev.dev = dev; - return devm_reset_controller_register(dev, &priv->rcdev); + error = devm_reset_controller_register(dev, &priv->rcdev); + if (error) + return dev_err_probe(dev, error, "could not register reset controller\n"); + + return 0; } /* From ccef9ef0aa2b9a7814e4def6f18b25211b8ae530 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 26 Mar 2026 21:29:24 +0200 Subject: [PATCH 143/193] reset: core: Drop unnecessary double quote Drop unnecessary double quote. Reported-by: Pavel Machek Closes: https://lore.kernel.org/all/acJbYxKGAB4lxGQr@duo.ucw.cz Signed-off-by: Claudiu Beznea Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index a0d8c68f2afc..38e189d04d09 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -435,7 +435,7 @@ int reset_control_bulk_reset(int num_rstcs, EXPORT_SYMBOL_GPL(reset_control_bulk_reset); /** - * reset_control_rearm - allow shared reset line to be re-triggered" + * reset_control_rearm - allow shared reset line to be re-triggered * @rstc: reset controller * * On a shared reset line the actual reset pulse is only triggered once for the From ad7ffe102a52141a0da19ca766c5103bec28ddb6 Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Wed, 25 Mar 2026 18:27:26 +0530 Subject: [PATCH 144/193] soc/tegra: cbb: Add support for CBB fabrics in Tegra238 Add support for CBB 2.0 based fabrics in Tegra238 SoC using DT. Fabrics reporting errors are: CBB, AON, BPMP, APE. Signed-off-by: Sumit Gupta Signed-off-by: Thierry Reding --- drivers/soc/tegra/cbb/tegra234-cbb.c | 134 +++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c index a9adbcecd47c..30f421c8e90c 100644 --- a/drivers/soc/tegra/cbb/tegra234-cbb.c +++ b/drivers/soc/tegra/cbb/tegra234-cbb.c @@ -89,6 +89,15 @@ enum tegra234_cbb_fabric_ids { T234_MAX_FABRIC_ID, }; +enum tegra238_cbb_fabric_ids { + T238_CBB_FABRIC_ID = 0, + T238_AON_FABRIC_ID = 4, + T238_PSC_FABRIC_ID = 5, + T238_BPMP_FABRIC_ID = 6, + T238_APE_FABRIC_ID = 7, + T238_MAX_FABRIC_ID, +}; + enum tegra264_cbb_fabric_ids { T264_SYSTEM_CBB_FABRIC_ID, T264_TOP_0_CBB_FABRIC_ID, @@ -974,6 +983,127 @@ static const struct tegra234_cbb_fabric tegra234_sce_fabric = { .firewall_wr_ctl = 0x288, }; +static const struct tegra234_target_lookup tegra238_ape_target_map[] = { + { "AXI2APB", 0x00000 }, + { "AGIC", 0x15000 }, + { "AMC", 0x16000 }, + { "AST0", 0x17000 }, + { "AST1", 0x18000 }, + { "AST2", 0x19000 }, + { "CBB", 0x1A000 }, +}; + +static const struct tegra234_target_lookup tegra238_cbb_target_map[] = { + { "AON", 0x40000 }, + { "APE", 0x50000 }, + { "BPMP", 0x41000 }, + { "HOST1X", 0x43000 }, + { "STM", 0x44000 }, + { "CBB_CENTRAL", 0x00000 }, + { "PCIE_C0", 0x51000 }, + { "PCIE_C1", 0x47000 }, + { "PCIE_C2", 0x48000 }, + { "PCIE_C3", 0x49000 }, + { "GPU", 0x4C000 }, + { "SMMU0", 0x4D000 }, + { "SMMU1", 0x4E000 }, + { "SMMU2", 0x4F000 }, + { "PSC", 0x52000 }, + { "AXI2APB_1", 0x70000 }, + { "AXI2APB_12", 0x73000 }, + { "AXI2APB_13", 0x74000 }, + { "AXI2APB_15", 0x76000 }, + { "AXI2APB_16", 0x77000 }, + { "AXI2APB_18", 0x79000 }, + { "AXI2APB_19", 0x7A000 }, + { "AXI2APB_2", 0x7B000 }, + { "AXI2APB_23", 0x7F000 }, + { "AXI2APB_25", 0x80000 }, + { "AXI2APB_26", 0x81000 }, + { "AXI2APB_27", 0x82000 }, + { "AXI2APB_28", 0x83000 }, + { "AXI2APB_32", 0x87000 }, + { "AXI2APB_33", 0x88000 }, + { "AXI2APB_4", 0x8B000 }, + { "AXI2APB_5", 0x8C000 }, + { "AXI2APB_6", 0x93000 }, + { "AXI2APB_9", 0x90000 }, + { "AXI2APB_3", 0x91000 }, +}; + +static const struct tegra234_fabric_lookup tegra238_cbb_fab_list[] = { + [T238_CBB_FABRIC_ID] = { "cbb-fabric", true, + tegra238_cbb_target_map, + ARRAY_SIZE(tegra238_cbb_target_map) }, + [T238_AON_FABRIC_ID] = { "aon-fabric", true, + tegra234_aon_target_map, + ARRAY_SIZE(tegra234_aon_target_map) }, + [T238_PSC_FABRIC_ID] = { "psc-fabric" }, + [T238_BPMP_FABRIC_ID] = { "bpmp-fabric", true, + tegra234_bpmp_target_map, + ARRAY_SIZE(tegra234_bpmp_target_map) }, + [T238_APE_FABRIC_ID] = { "ape-fabric", true, + tegra238_ape_target_map, + ARRAY_SIZE(tegra238_ape_target_map) }, +}; + +static const struct tegra234_cbb_fabric tegra238_aon_fabric = { + .fab_id = T238_AON_FABRIC_ID, + .fab_list = tegra238_cbb_fab_list, + .initiator_id = tegra234_initiator_id, + .errors = tegra234_cbb_errors, + .max_errors = ARRAY_SIZE(tegra234_cbb_errors), + .err_intr_enbl = 0x7, + .err_status_clr = 0x3f, + .notifier_offset = 0x17000, + .firewall_base = 0x30000, + .firewall_ctl = 0x8f0, + .firewall_wr_ctl = 0x8e8, +}; + +static const struct tegra234_cbb_fabric tegra238_ape_fabric = { + .fab_id = T238_APE_FABRIC_ID, + .fab_list = tegra238_cbb_fab_list, + .initiator_id = tegra234_initiator_id, + .errors = tegra234_cbb_errors, + .max_errors = ARRAY_SIZE(tegra234_cbb_errors), + .err_intr_enbl = 0xf, + .err_status_clr = 0x3f, + .notifier_offset = 0x1E000, + .firewall_base = 0x30000, + .firewall_ctl = 0xad0, + .firewall_wr_ctl = 0xac8, +}; + +static const struct tegra234_cbb_fabric tegra238_bpmp_fabric = { + .fab_id = T238_BPMP_FABRIC_ID, + .fab_list = tegra238_cbb_fab_list, + .initiator_id = tegra234_initiator_id, + .errors = tegra234_cbb_errors, + .max_errors = ARRAY_SIZE(tegra234_cbb_errors), + .err_intr_enbl = 0xf, + .err_status_clr = 0x3f, + .notifier_offset = 0x19000, + .firewall_base = 0x30000, + .firewall_ctl = 0x8f0, + .firewall_wr_ctl = 0x8e8, +}; + +static const struct tegra234_cbb_fabric tegra238_cbb_fabric = { + .fab_id = T238_CBB_FABRIC_ID, + .fab_list = tegra238_cbb_fab_list, + .initiator_id = tegra234_initiator_id, + .errors = tegra234_cbb_errors, + .max_errors = ARRAY_SIZE(tegra234_cbb_errors), + .err_intr_enbl = 0x3f, + .err_status_clr = 0x3f, + .notifier_offset = 0x60000, + .off_mask_erd = 0x3d004, + .firewall_base = 0x10000, + .firewall_ctl = 0x2230, + .firewall_wr_ctl = 0x2228, +}; + static const char * const tegra241_initiator_id[] = { [0x0] = "TZ", [0x1] = "CCPLEX", @@ -1480,6 +1610,10 @@ static const struct of_device_id tegra234_cbb_dt_ids[] = { { .compatible = "nvidia,tegra234-dce-fabric", .data = &tegra234_dce_fabric }, { .compatible = "nvidia,tegra234-rce-fabric", .data = &tegra234_rce_fabric }, { .compatible = "nvidia,tegra234-sce-fabric", .data = &tegra234_sce_fabric }, + { .compatible = "nvidia,tegra238-aon-fabric", .data = &tegra238_aon_fabric }, + { .compatible = "nvidia,tegra238-ape-fabric", .data = &tegra238_ape_fabric }, + { .compatible = "nvidia,tegra238-bpmp-fabric", .data = &tegra238_bpmp_fabric }, + { .compatible = "nvidia,tegra238-cbb-fabric", .data = &tegra238_cbb_fabric }, { .compatible = "nvidia,tegra264-sys-cbb-fabric", .data = &tegra264_sys_cbb_fabric }, { .compatible = "nvidia,tegra264-top0-cbb-fabric", .data = &tegra264_top0_cbb_fabric }, { .compatible = "nvidia,tegra264-uphy0-cbb-fabric", .data = &tegra264_uphy0_cbb_fabric }, From b6ff71c5d1d4ad858ddf6f39394d169c96689596 Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Wed, 21 Jan 2026 15:42:03 +0530 Subject: [PATCH 145/193] soc/tegra: cbb: Set ERD on resume for err interrupt Set the Error Response Disable (ERD) bit to mask SError responses and use interrupt-based error reporting. When the ERD bit is set, inband error responses to the initiator via SError are suppressed, and fabric errors are reported via an interrupt instead. The register is set during boot but the info is lost during system suspend and needs to be set again on resume. Fixes: fc2f151d2314 ("soc/tegra: cbb: Add driver for Tegra234 CBB 2.0") Signed-off-by: Sumit Gupta Signed-off-by: Thierry Reding --- drivers/soc/tegra/cbb/tegra234-cbb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c index 30f421c8e90c..6276a9603e5f 100644 --- a/drivers/soc/tegra/cbb/tegra234-cbb.c +++ b/drivers/soc/tegra/cbb/tegra234-cbb.c @@ -1720,6 +1720,10 @@ static int __maybe_unused tegra234_cbb_resume_noirq(struct device *dev) { struct tegra234_cbb *cbb = dev_get_drvdata(dev); + /* set ERD bit to mask SError and generate interrupt to report error */ + if (cbb->fabric->off_mask_erd) + tegra234_cbb_mask_serror(cbb); + tegra234_cbb_error_enable(&cbb->base); dev_dbg(dev, "%s resumed\n", cbb->fabric->fab_list[cbb->fabric->fab_id].name); From 499f7e5ebbdd9ff0c4d532b1c432f8a61ff585b3 Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Wed, 21 Jan 2026 15:42:04 +0530 Subject: [PATCH 146/193] soc/tegra: cbb: Fix incorrect ARRAY_SIZE in fabric lookup tables Fix incorrect ARRAY_SIZE usage in fabric lookup tables which could cause out-of-bounds access during target timeout lookup. Fixes: 25de5c8fe0801 ("soc/tegra: cbb: Improve handling for per SoC fabric data") Signed-off-by: Sumit Gupta Signed-off-by: Thierry Reding --- drivers/soc/tegra/cbb/tegra234-cbb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c index 6276a9603e5f..e67ac058846a 100644 --- a/drivers/soc/tegra/cbb/tegra234-cbb.c +++ b/drivers/soc/tegra/cbb/tegra234-cbb.c @@ -890,7 +890,7 @@ static const struct tegra234_fabric_lookup tegra234_cbb_fab_list[] = { ARRAY_SIZE(tegra234_common_target_map) }, [T234_AON_FABRIC_ID] = { "aon-fabric", true, tegra234_aon_target_map, - ARRAY_SIZE(tegra234_bpmp_target_map) }, + ARRAY_SIZE(tegra234_aon_target_map) }, [T234_PSC_FABRIC_ID] = { "psc-fabric" }, [T234_BPMP_FABRIC_ID] = { "bpmp-fabric", true, tegra234_bpmp_target_map, @@ -1290,7 +1290,7 @@ static const struct tegra234_fabric_lookup tegra241_cbb_fab_list[] = { [T234_CBB_FABRIC_ID] = { "cbb-fabric", true, tegra241_cbb_target_map, ARRAY_SIZE(tegra241_cbb_target_map) }, [T234_BPMP_FABRIC_ID] = { "bpmp-fabric", true, - tegra241_bpmp_target_map, ARRAY_SIZE(tegra241_cbb_target_map) }, + tegra241_bpmp_target_map, ARRAY_SIZE(tegra241_bpmp_target_map) }, }; static const struct tegra234_cbb_fabric tegra241_cbb_fabric = { .fab_id = T234_CBB_FABRIC_ID, From a5f51b04cbb3ae0f9cb2c4488952b775ebb0ccbf Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Wed, 21 Jan 2026 15:42:05 +0530 Subject: [PATCH 147/193] soc/tegra: cbb: Fix cross-fabric target timeout lookup When a fabric receives an error interrupt, the error may have occurred on a different fabric. The target timeout lookup was using the wrong base address (cbb->regs) with offsets from a different fabric's target map, causing a kernel page fault. Unable to handle kernel paging request at virtual address ffff80000954cc00 pc : tegra234_cbb_get_tmo_slv+0xc/0x28 Call trace: tegra234_cbb_get_tmo_slv+0xc/0x28 print_err_notifier+0x6c0/0x7d0 tegra234_cbb_isr+0xe4/0x1b4 Add tegra234_cbb_get_fabric() to look up the correct fabric device using fab_id, and use its base address for accessing target timeout registers. Fixes: 25de5c8fe0801 ("soc/tegra: cbb: Improve handling for per SoC fabric data") Signed-off-by: Sumit Gupta Signed-off-by: Thierry Reding --- drivers/soc/tegra/cbb/tegra234-cbb.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c index e67ac058846a..fb26f085f691 100644 --- a/drivers/soc/tegra/cbb/tegra234-cbb.c +++ b/drivers/soc/tegra/cbb/tegra234-cbb.c @@ -322,12 +322,37 @@ static void tegra234_cbb_lookup_apbslv(struct seq_file *file, const char *target } } +static struct tegra234_cbb *tegra234_cbb_get_fabric(u8 fab_id) +{ + struct tegra_cbb *entry; + + list_for_each_entry(entry, &cbb_list, node) { + struct tegra234_cbb *priv = to_tegra234_cbb(entry); + + if (priv->fabric->fab_id == fab_id) + return priv; + } + + return NULL; +} + static void tegra234_sw_lookup_target_timeout(struct seq_file *file, struct tegra234_cbb *cbb, u8 target_id, u8 fab_id) { const struct tegra234_target_lookup *map = cbb->fabric->fab_list[fab_id].target_map; + struct tegra234_cbb *target_cbb = NULL; void __iomem *addr; + if (fab_id == cbb->fabric->fab_id) + target_cbb = cbb; + else + target_cbb = tegra234_cbb_get_fabric(fab_id); + + if (!target_cbb) { + dev_err(cbb->base.dev, "could not find fabric for fab_id:%d\n", fab_id); + return; + } + if (target_id >= cbb->fabric->fab_list[fab_id].max_targets) { tegra_cbb_print_err(file, "\t Invalid target_id:%d\n", target_id); return; @@ -350,7 +375,7 @@ static void tegra234_sw_lookup_target_timeout(struct seq_file *file, struct tegr * e) Goto step-a till all bits are set. */ - addr = cbb->regs + map[target_id].offset; + addr = target_cbb->regs + map[target_id].offset; if (strstr(map[target_id].name, "AXI2APB")) { addr += APB_BLOCK_TMO_STATUS_0; From 83c18a324570193140cafc12c88eb1e370564078 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 26 Mar 2026 14:58:48 +0100 Subject: [PATCH 148/193] soc/tegra: Update BPMP ABI header This update primarily adds various new commands and MRQs for Tegra264, but also contains a few new annotations and fixes. Signed-off-by: Thierry Reding --- include/soc/tegra/bpmp-abi.h | 4569 +++++++++++++++++++++++++++------- 1 file changed, 3673 insertions(+), 896 deletions(-) diff --git a/include/soc/tegra/bpmp-abi.h b/include/soc/tegra/bpmp-abi.h index 39bb3f87e28d..5c64b3e02211 100644 --- a/include/soc/tegra/bpmp-abi.h +++ b/include/soc/tegra/bpmp-abi.h @@ -1,6 +1,6 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ /* - * Copyright (c) 2014-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2025, NVIDIA CORPORATION. All rights reserved. */ #ifndef ABI_BPMP_ABI_H @@ -74,6 +74,7 @@ /** * @ingroup MRQ_Format + * * Request an answer from the peer. * This should be set in mrq_request::flags for all requests targetted * at BPMP. For requests originating in BPMP, this flag is optional except @@ -85,6 +86,7 @@ /** * @ingroup MRQ_Format + * * Ring the sender's doorbell when responding. This should be set unless * the sender wants to poll the underlying communications layer directly. * @@ -94,7 +96,9 @@ /** * @ingroup MRQ_Format - * CRC present + * + * This is set in mrq_request::flags for requests that have CRC present and + * correspondingly in mrq_response::flags for responses that have CRC present. */ #define BPMP_MAIL_CRC_PRESENT (1U << 2U) @@ -127,91 +131,319 @@ struct mrq_request { * crc16, xid and length fields are present when set. * Some platform configurations, especially when targeted to applications requiring * functional safety, mandate this option being set or otherwise will respond with - * -BPMP_EBADMSG and ignore the request. + * -#BPMP_EBADMSG and ignore the request. * * **xid** is a transaction ID. * * Only used when #BPMP_MAIL_CRC_PRESENT is set. * * **payload_length** of the message expressed in bytes without the size of this header. - * See table below for minimum accepted payload lengths for each MRQ. - * Note: For DMCE communication, this field expresses the length as a multiple of 4 bytes - * rather than bytes. + * See tables below for minimum accepted payload lengths for each MRQ. * * Only used when #BPMP_MAIL_CRC_PRESENT is set. * - * | MRQ | CMD | minimum payload length - * | -------------------- | ------------------------------------ | ------------------------------------------ | - * | MRQ_PING | | 4 | - * | MRQ_THREADED_PING | | 4 | - * | MRQ_RESET | any | 8 | - * | MRQ_I2C | | 12 + cmd_i2c_xfer_request.data_size | - * | MRQ_CLK | CMD_CLK_GET_RATE | 4 | - * | MRQ_CLK | CMD_CLK_SET_RATE | 16 | - * | MRQ_CLK | CMD_CLK_ROUND_RATE | 16 | - * | MRQ_CLK | CMD_CLK_GET_PARENT | 4 | - * | MRQ_CLK | CMD_CLK_SET_PARENT | 8 | - * | MRQ_CLK | CMD_CLK_ENABLE | 4 | - * | MRQ_CLK | CMD_CLK_DISABLE | 4 | - * | MRQ_CLK | CMD_CLK_IS_ENABLED | 4 | - * | MRQ_CLK | CMD_CLK_GET_ALL_INFO | 4 | - * | MRQ_CLK | CMD_CLK_GET_MAX_CLK_ID | 4 | - * | MRQ_CLK | CMD_CLK_GET_FMAX_AT_VMIN | 4 | - * | MRQ_QUERY_ABI | | 4 | - * | MRQ_PG | CMD_PG_QUERY_ABI | 12 | - * | MRQ_PG | CMD_PG_SET_STATE | 12 | - * | MRQ_PG | CMD_PG_GET_STATE | 8 | - * | MRQ_PG | CMD_PG_GET_NAME | 8 | - * | MRQ_PG | CMD_PG_GET_MAX_ID | 8 | - * | MRQ_THERMAL | CMD_THERMAL_QUERY_ABI | 8 | - * | MRQ_THERMAL | CMD_THERMAL_GET_TEMP | 8 | - * | MRQ_THERMAL | CMD_THERMAL_SET_TRIP | 20 | - * | MRQ_THERMAL | CMD_THERMAL_GET_NUM_ZONES | 4 | - * | MRQ_THERMAL | CMD_THERMAL_GET_THERMTRIP | 8 | - * | MRQ_CPU_VHINT | | 8 | - * | MRQ_ABI_RATCHET | | 2 | - * | MRQ_EMC_DVFS_LATENCY | | 8 | - * | MRQ_EMC_DVFS_EMCHUB | | 8 | - * | MRQ_EMC_DISP_RFL | | 4 | - * | MRQ_BWMGR | CMD_BWMGR_QUERY_ABI | 8 | - * | MRQ_BWMGR | CMD_BWMGR_CALC_RATE | 8 + 8 * bwmgr_rate_req.num_iso_clients | - * | MRQ_ISO_CLIENT | CMD_ISO_CLIENT_QUERY_ABI | 8 | - * | MRQ_ISO_CLIENT | CMD_ISO_CLIENT_CALCULATE_LA | 16 | - * | MRQ_ISO_CLIENT | CMD_ISO_CLIENT_SET_LA | 16 | - * | MRQ_ISO_CLIENT | CMD_ISO_CLIENT_GET_MAX_BW | 8 | - * | MRQ_CPU_NDIV_LIMITS | | 4 | - * | MRQ_CPU_AUTO_CC3 | | 4 | - * | MRQ_RINGBUF_CONSOLE | CMD_RINGBUF_CONSOLE_QUERY_ABI | 8 | - * | MRQ_RINGBUF_CONSOLE | CMD_RINGBUF_CONSOLE_READ | 5 | - * | MRQ_RINGBUF_CONSOLE | CMD_RINGBUF_CONSOLE_WRITE | 5 + cmd_ringbuf_console_write_req.len | - * | MRQ_RINGBUF_CONSOLE | CMD_RINGBUF_CONSOLE_GET_FIFO | 4 | - * | MRQ_STRAP | STRAP_SET | 12 | - * | MRQ_UPHY | CMD_UPHY_PCIE_LANE_MARGIN_CONTROL | 24 | - * | MRQ_UPHY | CMD_UPHY_PCIE_LANE_MARGIN_STATUS | 4 | - * | MRQ_UPHY | CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT | 5 | - * | MRQ_UPHY | CMD_UPHY_PCIE_CONTROLLER_STATE | 6 | - * | MRQ_UPHY | CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF | 5 | - * | MRQ_FMON | CMD_FMON_GEAR_CLAMP | 16 | - * | MRQ_FMON | CMD_FMON_GEAR_FREE | 4 | - * | MRQ_FMON | CMD_FMON_GEAR_GET | 4 | - * | MRQ_FMON | CMD_FMON_FAULT_STS_GET | 8 | - * | MRQ_EC | CMD_EC_STATUS_EX_GET | 12 | - * | MRQ_QUERY_FW_TAG | | 0 | - * | MRQ_DEBUG | CMD_DEBUG_OPEN_RO | 4 + length of cmd_debug_fopen_request.name | - * | MRQ_DEBUG | CMD_DEBUG_OPEN_WO | 4 + length of cmd_debug_fopen_request.name | - * | MRQ_DEBUG | CMD_DEBUG_READ | 8 | - * | MRQ_DEBUG | CMD_DEBUG_WRITE | 12 + cmd_debug_fwrite_request.datalen | - * | MRQ_DEBUG | CMD_DEBUG_CLOSE | 8 | - * | MRQ_TELEMETRY | | 8 | - * | MRQ_PWR_LIMIT | CMD_PWR_LIMIT_QUERY_ABI | 8 | - * | MRQ_PWR_LIMIT | CMD_PWR_LIMIT_SET | 20 | - * | MRQ_PWR_LIMIT | CMD_PWR_LIMIT_GET | 16 | - * | MRQ_PWR_LIMIT | CMD_PWR_LIMIT_CURR_CAP | 8 | - * | MRQ_GEARS | | 0 | - * | MRQ_BWMGR_INT | CMD_BWMGR_INT_QUERY_ABI | 8 | - * | MRQ_BWMGR_INT | CMD_BWMGR_INT_CALC_AND_SET | 16 | - * | MRQ_BWMGR_INT | CMD_BWMGR_INT_CAP_SET | 8 | - * | MRQ_OC_STATUS | | 0 | + * | MRQ | Sub-command | Minimum payload length + * | --------------------- | ------------------------------------ | ------------------------------------------------------- | + * | #MRQ_PING | - | 4 | + * | #MRQ_THREADED_PING | - | 4 | + * | #MRQ_RESET | any | 8 | + * | #MRQ_I2C | - | 12 + cmd_i2c_xfer_request.data_size | + * | #MRQ_CLK | #CMD_CLK_GET_RATE | 4 | + * | #MRQ_CLK | #CMD_CLK_SET_RATE | 16 | + * | #MRQ_CLK | #CMD_CLK_ROUND_RATE | 16 | + * | #MRQ_CLK | #CMD_CLK_GET_PARENT | 4 | + * | #MRQ_CLK | #CMD_CLK_SET_PARENT | 8 | + * | #MRQ_CLK | #CMD_CLK_ENABLE | 4 | + * | #MRQ_CLK | #CMD_CLK_DISABLE | 4 | + * | #MRQ_CLK | #CMD_CLK_IS_ENABLED | 4 | + * | #MRQ_CLK | #CMD_CLK_GET_ALL_INFO | 4 | + * | #MRQ_CLK | #CMD_CLK_GET_MAX_CLK_ID | 4 | + * | #MRQ_CLK | #CMD_CLK_GET_FMAX_AT_VMIN | 4 | + * | #MRQ_QUERY_ABI | - | 4 | + * | #MRQ_PG | #CMD_PG_QUERY_ABI | 12 | + * | #MRQ_PG | #CMD_PG_SET_STATE | 12 | + * | #MRQ_PG | #CMD_PG_GET_STATE | 8 | + * | #MRQ_PG | #CMD_PG_GET_NAME | 8 | + * | #MRQ_PG | #CMD_PG_GET_MAX_ID | 8 | + * | #MRQ_THERMAL | #CMD_THERMAL_QUERY_ABI | 8 | + * | #MRQ_THERMAL | #CMD_THERMAL_GET_TEMP | 8 | + * | #MRQ_THERMAL | #CMD_THERMAL_GET_NUM_ZONES | 4 | + * | #MRQ_THERMAL | #CMD_THERMAL_GET_THERMTRIP | 8 | + * | #MRQ_ABI_RATCHET | - | 2 | + * | #MRQ_EMC_DVFS_LATENCY | - | 8 | + * | #MRQ_QUERY_FW_TAG | - | 0 | + * | #MRQ_DEBUG | #CMD_DEBUG_OPEN_RO | 4 + length of cmd_debug_fopen_request.name | + * | #MRQ_DEBUG | #CMD_DEBUG_OPEN_WO | 4 + length of cmd_debug_fopen_request.name | + * | #MRQ_DEBUG | #CMD_DEBUG_READ | 8 | + * | #MRQ_DEBUG | #CMD_DEBUG_WRITE | 12 + cmd_debug_fwrite_request.datalen | + * | #MRQ_DEBUG | #CMD_DEBUG_CLOSE | 8 | + * + * @cond (bpmp_t186) + * The following additional MRQ is supported on T186 -platform: + * + * | MRQ | Sub-command | Minimum payload length | + * | --------------------- | ------------------------------------- | ------------------------------------- | + * | #MRQ_CPU_VHINT | - | 8 | + * | #MRQ_THERMAL | #CMD_THERMAL_SET_TRIP | 20 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_QUERY_ABI | 8 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_READ | 5 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_WRITE | 5 + cmd_ringbuf_console_write_req.len | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_GET_FIFO | 4 | + * @endcond + * + * @cond (bpmp_t194) + * The following additional MRQs are supported on T194 -platform: + * + * | MRQ | Sub-command | Minimum payload length | + * | --------------------- | ------------------------------------- | ------------------------------------- | + * | #MRQ_CPU_NDIV_LIMITS | - | 4 | + * | #MRQ_STRAP | #STRAP_SET | 12 | + * | #MRQ_CPU_AUTO_CC3 | - | 4 | + * | #MRQ_EC | #CMD_EC_STATUS_EX_GET | 12 | + * | #MRQ_FMON | #CMD_FMON_GEAR_CLAMP | 16 | + * | #MRQ_FMON | #CMD_FMON_GEAR_FREE | 4 | + * | #MRQ_FMON | #CMD_FMON_GEAR_GET | 4 | + * | #MRQ_FMON | #CMD_FMON_FAULT_STS_GET | 8 | + * | #MRQ_THERMAL | #CMD_THERMAL_SET_TRIP | 20 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_QUERY_ABI | 8 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_READ | 5 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_WRITE | 5 + cmd_ringbuf_console_write_req.len | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_GET_FIFO | 4 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_LANE_MARGIN_CONTROL | 24 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_LANE_MARGIN_STATUS | 4 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT | 5 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_CONTROLLER_STATE | 6 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF | 5 | + * @endcond + * + * @cond (bpmp_safe && bpmp_t234) + * The following additional MRQ is supported on functional-safety + * builds for the T234 platform: + * + * | MRQ | Sub-command | Minimum payload length | + * | --------------------- | ------------------------------------- | ------------------------------------- | + * | #MRQ_CPU_NDIV_LIMITS | - | 4 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_QUERY_ABI | 8 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_READ | 5 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_WRITE | 5 + cmd_ringbuf_console_write_req.len | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_GET_FIFO | 4 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_LANE_MARGIN_CONTROL | 24 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_LANE_MARGIN_STATUS | 4 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT | 5 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_CONTROLLER_STATE | 6 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF | 5 | + * | #MRQ_FMON | #CMD_FMON_GEAR_CLAMP | 16 | + * | #MRQ_FMON | #CMD_FMON_GEAR_FREE | 4 | + * | #MRQ_FMON | #CMD_FMON_GEAR_GET | 4 | + * | #MRQ_FMON | #CMD_FMON_FAULT_STS_GET | 8 | + * | #MRQ_EMC_DVFS_EMCHUB | - | 8 | + * | #MRQ_EMC_DISP_RFL | - | 4 | + * + * @endcond + * + * @cond (!bpmp_safe && bpmp_t234) + * + * The following additional MRQs are supported on non-functional-safety + * builds for the T234 and T238 -platforms: + * + * | MRQ | Sub-command | Minimum payload length | + * | --------------------- | ------------------------------------- | --------------------------------------------------- | + * | #MRQ_CPU_NDIV_LIMITS | - | 4 | + * | #MRQ_STRAP | #STRAP_SET | 12 | + * | #MRQ_THERMAL | #CMD_THERMAL_SET_TRIP | 20 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_QUERY_ABI | 8 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_READ | 5 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_WRITE | 5 + cmd_ringbuf_console_write_req.len | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_GET_FIFO | 4 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_LANE_MARGIN_CONTROL | 24 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_LANE_MARGIN_STATUS | 4 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT | 5 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_CONTROLLER_STATE | 6 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF | 5 | + * | #MRQ_FMON | #CMD_FMON_GEAR_CLAMP | 16 | + * | #MRQ_FMON | #CMD_FMON_GEAR_FREE | 4 | + * | #MRQ_FMON | #CMD_FMON_GEAR_GET | 4 | + * | #MRQ_FMON | #CMD_FMON_FAULT_STS_GET | 8 | + * | #MRQ_EMC_DVFS_EMCHUB | - | 8 | + * | #MRQ_EMC_DISP_RFL | - | 4 | + * | #MRQ_BWMGR | #CMD_BWMGR_QUERY_ABI | 8 | + * | #MRQ_BWMGR | #CMD_BWMGR_CALC_RATE | 8 + 8 * cmd_bwmgr_calc_rate_request.num_iso_clients | + * | #MRQ_ISO_CLIENT | #CMD_ISO_CLIENT_QUERY_ABI | 8 | + * | #MRQ_ISO_CLIENT | #CMD_ISO_CLIENT_CALCULATE_LA | 16 | + * | #MRQ_ISO_CLIENT | #CMD_ISO_CLIENT_SET_LA | 16 | + * | #MRQ_ISO_CLIENT | #CMD_ISO_CLIENT_GET_MAX_BW | 8 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_QUERY_ABI | 8 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_CALC_AND_SET | 16 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_CAP_SET | 8 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_GET_LAST_REQUEST | 9 | + * | #MRQ_OC_STATUS | - | 0 | + * @endcond + * + * @cond bpmp_t238 + * The following additional MRQs are supported on T238 platform: + * + * | MRQ | Sub-command | Minimum payload length | + * | --------------------- | ------------------------------------- | --------------------------------------------------- | + * | #MRQ_CPU_NDIV_LIMITS | - | 4 | + * | #MRQ_STRAP | #STRAP_SET | 12 | + * | #MRQ_THERMAL | #CMD_THERMAL_SET_TRIP | 20 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_QUERY_ABI | 8 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_READ | 5 | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_WRITE | 5 + cmd_ringbuf_console_write_req.len | + * | #MRQ_RINGBUF_CONSOLE | #CMD_RINGBUF_CONSOLE_GET_FIFO | 4 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_LANE_MARGIN_CONTROL | 24 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_LANE_MARGIN_STATUS | 4 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT | 5 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_CONTROLLER_STATE | 6 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF | 5 | + * | #MRQ_FMON | #CMD_FMON_GEAR_CLAMP | 16 | + * | #MRQ_FMON | #CMD_FMON_GEAR_FREE | 4 | + * | #MRQ_FMON | #CMD_FMON_GEAR_GET | 4 | + * | #MRQ_FMON | #CMD_FMON_FAULT_STS_GET | 8 | + * | #MRQ_EMC_DVFS_EMCHUB | - | 8 | + * | #MRQ_EMC_DISP_RFL | - | 4 | + * | #MRQ_BWMGR | #CMD_BWMGR_QUERY_ABI | 8 | + * | #MRQ_BWMGR | #CMD_BWMGR_CALC_RATE | 8 + 8 * cmd_bwmgr_calc_rate_request.num_iso_clients | + * | #MRQ_ISO_CLIENT | #CMD_ISO_CLIENT_QUERY_ABI | 8 | + * | #MRQ_ISO_CLIENT | #CMD_ISO_CLIENT_CALCULATE_LA | 16 | + * | #MRQ_ISO_CLIENT | #CMD_ISO_CLIENT_SET_LA | 16 | + * | #MRQ_ISO_CLIENT | #CMD_ISO_CLIENT_GET_MAX_BW | 8 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_QUERY_ABI | 8 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_CALC_AND_SET | 16 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_CAP_SET | 8 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_GET_LAST_REQUEST | 9 | + * | #MRQ_OC_STATUS | - | 0 | + * | #MRQ_THROTTLE | #CMD_THROTTLE_SET_OC_CONFIG | 5 | + * @endcond + * + * @cond (bpmp_th500) + * The following additional MRQs are supported on TH500 -platform: + * + * | MRQ | Sub-command | Minimum payload length | + * | -------------------- | ------------------------------------- | ---------------------- | + * | #MRQ_CPU_NDIV_LIMITS | - | 4 | + * | #MRQ_THERMAL | #CMD_THERMAL_SET_TRIP | 20 | + * | #MRQ_STRAP | #STRAP_SET | 12 | + * | #MRQ_SHUTDOWN | - | 4 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_LANE_MARGIN_CONTROL | 24 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_LANE_MARGIN_STATUS | 4 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT | 5 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_CONTROLLER_STATE | 6 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF | 5 | + * | #MRQ_UPHY | #CMD_UPHY_PCIE_CONFIG_VDM | 3 | + * | #MRQ_TELEMETRY | - | 8 | + * | #MRQ_PWR_LIMIT | #CMD_PWR_LIMIT_QUERY_ABI | 8 | + * | #MRQ_PWR_LIMIT | #CMD_PWR_LIMIT_SET | 20 | + * | #MRQ_PWR_LIMIT | #CMD_PWR_LIMIT_GET | 16 | + * | #MRQ_PWR_LIMIT | #CMD_PWR_LIMIT_CURR_CAP | 8 | + * | #MRQ_GEARS | - | 0 | + * | #MRQ_C2C | #CMD_C2C_QUERY_ABI | 8 | + * | #MRQ_C2C | #CMD_C2C_START_INITIALIZATION | 5 | + * | #MRQ_C2C | #CMD_C2C_GET_STATUS | 4 | + * | #MRQ_C2C | #CMD_C2C_HOTRESET_PREP | 5 | + * | #MRQ_C2C | #CMD_C2C_START_HOTRESET | 5 | + * | #MRQ_THROTTLE | #CMD_THROTTLE_QUERY_ABI | 4 | + * | #MRQ_THROTTLE | #CMD_THROTTLE_GET_CHIPTHROT_STATUS | 4 | + * | #MRQ_PWRMODEL | #CMD_PWRMODEL_QUERY_ABI | 8 | + * | #MRQ_PWRMODEL | #CMD_PWRMODEL_PWR_GET | 16 | + * | #MRQ_PWR_CNTRL | #CMD_PWR_CNTRL_QUERY_ABI | 8 | + * | #MRQ_PWR_CNTRL | #CMD_PWR_CNTRL_BYPASS_SET | 12 | + * | #MRQ_PWR_CNTRL | #CMD_PWR_CNTRL_BYPASS_GET | 8 | + * @endcond + * + * @cond (bpmp_tb500) + * The following additional MRQs are supported on TB500 -platform: + * + * | MRQ | Sub-command | Minimum payload length | + * | -------------------- | ---------------------------------------- | ---------------------- | + * | #MRQ_PWR_LIMIT | #CMD_PWR_LIMIT_QUERY_ABI | 8 | + * | #MRQ_PWR_LIMIT | #CMD_PWR_LIMIT_SET | 20 | + * | #MRQ_PWR_LIMIT | #CMD_PWR_LIMIT_GET | 16 | + * | #MRQ_PWR_LIMIT | #CMD_PWR_LIMIT_CURR_CAP | 8 | + * | #MRQ_TELEMETRY_EX | #CMD_TELEMETRY_EX_QUERY_ABI | 8 | + * | #MRQ_TELEMETRY_EX | #CMD_TELEMETRY_EX_BASE_SZ_GET | 12 | + * | #MRQ_THROTTLE | #CMD_THROTTLE_GET_CHIPTHROT_STATUS | 4 | + * | #MRQ_C2C | #CMD_C2C_QUERY_ABI | 8 | + * | #MRQ_C2C | #CMD_C2C_START_INITIALIZATION | 5 | + * | #MRQ_C2C | #CMD_C2C_GET_STATUS | 4 | + * | #MRQ_C2C | #CMD_C2C_HOTRESET_PREP | 5 | + * | #MRQ_C2C | #CMD_C2C_START_HOTRESET | 5 | + * | MRQ_HWPM | CMD_HWPM_QUERY_ABI | 4 | + * | MRQ_HWPM | CMD_HWPM_IPMU_SET_TRIGGERS | 120 | + * | MRQ_HWPM | CMD_HWPM_IPMU_SET_PAYLOADS_SHIFTS | 120 | + * | MRQ_HWPM | CMD_HWPM_IPMU_GET_MAX_PAYLOADS | 0 | + * | MRQ_HWPM | CMD_HWPM_NVTHERM_SET_SAMPLE_RATE | 4 | + * | MRQ_HWPM | CMD_HWPM_NVTHERM_SET_BUBBLE_INTERVAL | 4 | + * | MRQ_HWPM | CMD_HWPM_NVTHERM_SET_FLEX_CHANNELS | 120 | + * | MRQ_HWPM | CMD_HWPM_ISENSE_GET_SENSOR_NAME | 4 | + * | MRQ_HWPM | CMD_HWPM_ISENSE_GET_SENSOR_CHANNEL | 4 | + * | MRQ_HWPM | CMD_HWPM_ISENSE_GET_SENSOR_SCALE_FACTOR | 4 | + * | MRQ_HWPM | CMD_HWPM_ISENSE_GET_SENSOR_OFFSET | 4 | + * | MRQ_HWPM | CMD_HWPM_ISENSE_GET_SUM_BLOCK_NAME | 4 | + * | MRQ_HWPM | CMD_HWPM_ISENSE_GET_SUM_BLOCK_INPUTS | 4 | + * | MRQ_DVFS | CMD_DVFS_QUERY_ABI | 4 | + * | MRQ_DVFS | CMD_DVFS_SET_CTRL_STATE | 8 | + * | MRQ_DVFS | CMD_DVFS_SET_MGR_STATE | 8 | + * | MRQ_PPP_PROFILE | CMD_PPP_PROFILE_QUERY_ABI | 8 | + * | MRQ_PPP_PROFILE | CMD_PPP_PROFILE_QUERY_MASKS | 8 | + * | MRQ_PPP_PROFILE | CMD_PPP_CORE_QUERY_CPU_MASK | 8 | + * | MRQ_PPP_PROFILE | CMD_PPP_AVAILABLE_QUERY | 4 | + * @endcond + * + * @cond (bpmp_safe && bpmp_t264) + * The following additional MRQ is supported on functional-safety + * builds for the T264 platform: + * + * | MRQ | Sub-command | Minimum payload length | + * | -------------------- | --------------------------------- | ---------------------- | + * | #MRQ_CPU_NDIV_LIMITS | - | 4 | + * | #MRQ_STRAP | #STRAP_SET | 12 | + * | #MRQ_SHUTDOWN | - | 4 | + * | #MRQ_FMON | #CMD_FMON_GEAR_CLAMP | 16 | + * | #MRQ_FMON | #CMD_FMON_GEAR_FREE | 4 | + * | #MRQ_FMON | #CMD_FMON_GEAR_GET | 4 | + * | #MRQ_FMON | #CMD_FMON_FAULT_STS_GET | 8 | + * | #MRQ_PCIE | #CMD_PCIE_EP_CONTROLLER_INIT | 5 | + * | #MRQ_PCIE | #CMD_PCIE_EP_CONTROLLER_OFF | 5 | + * | #MRQ_CR7 | #CMD_CR7_ENTRY | 12 | + * | #MRQ_CR7 | #CMD_CR7_EXIT | 12 | + * | #MRQ_SLC | #CMD_SLC_QUERY_ABI | 8 | + * | #MRQ_SLC | #CMD_SLC_BYPASS_SET | 8 | + * | #MRQ_SLC | #CMD_SLC_BYPASS_GET | 4 | + * @endcond + * + * @cond (!bpmp_safe && bpmp_t264) + * The following additional MRQs are supported on non-functional-safety + * builds for the T264 -platform: + * + * | MRQ | Sub-command | Minimum payload length | + * | -------------------- | --------------------------------- | ---------------------- | + * | #MRQ_CPU_NDIV_LIMITS | - | 4 | + * | #MRQ_STRAP | #STRAP_SET | 12 | + * | #MRQ_SHUTDOWN | - | 4 | + * | #MRQ_FMON | #CMD_FMON_GEAR_CLAMP | 16 | + * | #MRQ_FMON | #CMD_FMON_GEAR_FREE | 4 | + * | #MRQ_FMON | #CMD_FMON_GEAR_GET | 4 | + * | #MRQ_FMON | #CMD_FMON_FAULT_STS_GET | 8 | + * | #MRQ_OC_STATUS | - | 0 | + * | #MRQ_PCIE | #CMD_PCIE_EP_CONTROLLER_INIT | 5 | + * | #MRQ_PCIE | #CMD_PCIE_EP_CONTROLLER_OFF | 5 | + * | #MRQ_PCIE | #CMD_PCIE_RP_CONTROLLER_OFF | 5 | + * | #MRQ_CR7 | #CMD_CR7_ENTRY | 12 | + * | #MRQ_CR7 | #CMD_CR7_EXIT | 12 | + * | #MRQ_SLC | #CMD_SLC_QUERY_ABI | 8 | + * | #MRQ_SLC | #CMD_SLC_BYPASS_SET | 8 | + * | #MRQ_SLC | #CMD_SLC_BYPASS_GET | 4 | + * | #MRQ_ISO_CLIENT | #CMD_ISO_CLIENT_QUERY_ABI | 8 | + * | #MRQ_ISO_CLIENT | #CMD_ISO_CLIENT_CALCULATE_LA | 16 | + * | #MRQ_ISO_CLIENT | #CMD_ISO_CLIENT_SET_LA | 16 | + * | #MRQ_ISO_CLIENT | #CMD_ISO_CLIENT_GET_MAX_BW | 8 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_QUERY_ABI | 8 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_CALC_AND_SET | 16 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_CAP_SET | 8 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_CURR_AVAILABLE_BW | 8 | + * | #MRQ_BWMGR_INT | #CMD_BWMGR_INT_GET_LAST_REQUEST | 9 | + * @endcond * * **crc16** * @@ -220,7 +452,7 @@ struct mrq_request { * including this header. However the crc16 field is considered to be set to 0 when * calculating the CRC. Only used when #BPMP_MAIL_CRC_PRESENT is set. If * #BPMP_MAIL_CRC_PRESENT is set and this field does not match the CRC as - * calculated by BPMP, -BPMP_EBADMSG will be returned and the request will + * calculated by BPMP, -#BPMP_EBADMSG will be returned and the request will * be ignored. See code snippet below on how to calculate the CRC. * * @code @@ -322,6 +554,9 @@ struct mrq_response { #define MRQ_CPU_VHINT 28U #define MRQ_ABI_RATCHET 29U #define MRQ_EMC_DVFS_LATENCY 31U +//adoc: tag::bpmp_dmce_mrq_shutdown[] +#define MRQ_SHUTDOWN 49U +//adoc: end::bpmp_dmce_mrq_shutdown[] #define MRQ_RINGBUF_CONSOLE 65U #define MRQ_PG 66U #define MRQ_CPU_NDIV_LIMITS 67U @@ -341,48 +576,31 @@ struct mrq_response { #define MRQ_GEARS 82U #define MRQ_BWMGR_INT 83U #define MRQ_OC_STATUS 84U - -/** @cond DEPRECATED */ -#define MRQ_RESERVED_2 2U -#define MRQ_RESERVED_3 3U -#define MRQ_RESERVED_4 4U -#define MRQ_RESERVED_5 5U -#define MRQ_RESERVED_6 6U -#define MRQ_RESERVED_7 7U -#define MRQ_RESERVED_8 8U -#define MRQ_RESERVED_10 10U -#define MRQ_RESERVED_11 11U -#define MRQ_RESERVED_12 12U -#define MRQ_RESERVED_13 13U -#define MRQ_RESERVED_14 14U -#define MRQ_RESERVED_15 15U -#define MRQ_RESERVED_16 16U -#define MRQ_RESERVED_17 17U -#define MRQ_RESERVED_18 18U -#define MRQ_RESERVED_24 24U -#define MRQ_RESERVED_25 25U -#define MRQ_RESERVED_26 26U -#define MRQ_RESERVED_30 30U -#define MRQ_RESERVED_64 64U -#define MRQ_RESERVED_74 74U -/** @endcond DEPRECATED */ - -/** @} */ +#define MRQ_C2C 85U +#define MRQ_THROTTLE 86U +#define MRQ_PWRMODEL 87U +#define MRQ_PCIE 88U +#define MRQ_PWR_CNTRL 89U +#define MRQ_CR7 90U +#define MRQ_SLC 91U +#define MRQ_TELEMETRY_EX 92U +#define MRQ_HWPM 93U +#define MRQ_DVFS 94U +#define MRQ_PPP_PROFILE 95U /** - * @ingroup MRQ_Codes * @brief Maximum MRQ code to be sent by CPU software to * BPMP. Subject to change in future */ -#define MAX_CPU_MRQ_ID 84U +#define MAX_CPU_MRQ_ID 95U + +/** @} */ /** * @addtogroup MRQ_Payloads * @{ * @defgroup Ping Ping * @defgroup Query_Tag Query Tag - * @defgroup Module Loadable Modules - * @defgroup Trace Trace * @defgroup Debugfs Debug File System * @defgroup Reset Reset * @defgroup I2C I2C @@ -390,6 +608,7 @@ struct mrq_response { * @defgroup ABI_info ABI Info * @defgroup Powergating Power Gating * @defgroup Thermal Thermal + * @defgroup Throttle Throttle * @defgroup OC_status OC status * @defgroup Vhint CPU Voltage hint * @defgroup EMC EMC @@ -405,7 +624,22 @@ struct mrq_response { * @defgroup Telemetry Telemetry * @defgroup Pwrlimit PWR_LIMIT * @defgroup Gears Gears + * @defgroup Shutdown Shutdown * @defgroup BWMGR_INT Bandwidth Manager Integrated + * @defgroup C2C C2C + * @defgroup Pwrmodel Power Model + * @defgroup Pwrcntrl Power Controllers + * @cond bpmp_t264 + * * @defgroup PCIE PCIE + * * @defgroup CR7 CR7 + * * @defgroup Slc Slc + * @endcond + * @cond bpmp_tb500 + * * @defgroup Telemetry_ex Telemetry Expanded + * * @defgroup HWPM Hardware Performance Monitoring + * * @defgroup DVFS Dynamic Voltage and Frequency Scaling + * * @defgroup PPP power/performance profiles + * @endcond * @} MRQ_Payloads */ @@ -414,7 +648,6 @@ struct mrq_response { * @def MRQ_PING * @brief A simple ping * - * * Platforms: All * * Initiators: Any * * Targets: Any * * Request Payload: @ref mrq_ping_request @@ -424,7 +657,6 @@ struct mrq_response { * @def MRQ_THREADED_PING * @brief A deeper ping * - * * Platforms: All * * Initiators: Any * * Targets: BPMP * * Request Payload: @ref mrq_ping_request @@ -441,8 +673,8 @@ struct mrq_response { * @brief Request with #MRQ_PING * * Used by the sender of an #MRQ_PING message to request a pong from - * recipient. The response from the recipient is computed based on - * #challenge. + * recipient. The response from the recipient is computed based on the + * mrq_ping_request::challenge -value. */ struct mrq_ping_request { /** @brief Arbitrarily chosen value */ @@ -470,7 +702,7 @@ struct mrq_ping_response { * * @deprecated Use #MRQ_QUERY_FW_TAG instead. * - * * Platforms: All + * @details * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_query_tag_request @@ -483,7 +715,7 @@ struct mrq_ping_response { * @brief Request with #MRQ_QUERY_TAG * * @deprecated This structure will be removed in future version. - * Use MRQ_QUERY_FW_TAG instead. + * Use #MRQ_QUERY_FW_TAG instead. */ struct mrq_query_tag_request { /** @brief Base address to store the firmware tag */ @@ -496,7 +728,6 @@ struct mrq_query_tag_request { * @def MRQ_QUERY_FW_TAG * @brief Query BPMP firmware's tag (i.e. unique identifier) * - * * Platforms: All * * Initiators: Any * * Targets: BPMP * * Request Payload: N/A @@ -510,10 +741,9 @@ struct mrq_query_tag_request { * * Sent in response to #MRQ_QUERY_FW_TAG message. #tag contains the unique * identifier for the version of firmware issuing the reply. - * */ struct mrq_query_fw_tag_response { - /** @brief Array to store tag information */ + /** @brief Array to store tag information */ uint8_t tag[32]; } BPMP_ABI_PACKED; @@ -532,9 +762,8 @@ struct mrq_threaded_ping_response { * @def MRQ_DEBUGFS * @brief Interact with BPMP's debugfs file nodes * - * @deprecated use MRQ_DEBUG instead. + * @deprecated Use #MRQ_DEBUG instead. * - * * Platforms: T186, T194 * * Initiators: Any * * Targets: BPMP * * Request Payload: @ref mrq_debugfs_request @@ -626,9 +855,9 @@ struct cmd_debugfs_dumpdir_response { /** * @ingroup Debugfs - * @brief Request with #MRQ_DEBUGFS. + * @brief Request with #MRQ_DEBUG. * - * The sender of an MRQ_DEBUGFS message uses #cmd to specify a debugfs + * The sender of an MRQ_DEBUG message uses #cmd to specify a debugfs * command to execute. Legal commands are the values of @ref * mrq_debugfs_commands. Each command requires a specific additional * payload of data. @@ -676,16 +905,15 @@ struct mrq_debugfs_response { /** * @ingroup MRQ_Codes * @def MRQ_DEBUG - * @brief Interact with BPMP's debugfs file nodes. Use message payload + * @brief Interact with BPMP-FW debugfs file nodes. Use message payload * for exchanging data. This is functionally equivalent to - * @ref MRQ_DEBUGFS. But the way in which data is exchanged is different. - * When software running on CPU tries to read a debugfs file, + * the deprecated MRQ_DEBUGFS but the way in which data is exchanged is + * different. When software running on CPU tries to read a debugfs file, * the file path and read data will be stored in message payload. * Since the message payload size is limited, a debugfs file * transaction might require multiple frames of data exchanged * between BPMP and CPU until the transaction completes. * - * * Platforms: T194 * * Initiators: Any * * Targets: BPMP * * Request Payload: @ref mrq_debug_request @@ -694,17 +922,34 @@ struct mrq_debugfs_response { /** @ingroup Debugfs */ enum mrq_debug_commands { - /** @brief Open required file for read operation */ + /** + * @brief Open file represented by the path in + * cmd_debug_fopen_request::name for read operation + */ CMD_DEBUG_OPEN_RO = 0, - /** @brief Open required file for write operation */ + /** + * @brief Open file represented by the path in + * cmd_debug_fopen_request::name for write operation + */ CMD_DEBUG_OPEN_WO = 1, - /** @brief Perform read */ + /** + * @brief Perform read on a previously opened file handle represented + * by the cmd_debug_fread_request::fd -value. + */ CMD_DEBUG_READ = 2, - /** @brief Perform write */ + /** + * @brief Perform write on a previously opened file handle represented + * by the cmd_debug_fwrite_request::fd -value. + */ CMD_DEBUG_WRITE = 3, - /** @brief Close file */ + /** + * @brief Close previously opened file handle. + */ CMD_DEBUG_CLOSE = 4, - /** @brief Not a command */ + /** + * @brief Not a command, represents maximum number of supported + * sub-commands + */ CMD_DEBUG_MAX }; @@ -727,35 +972,38 @@ enum mrq_debug_commands { /** * @ingroup Debugfs - * @brief Parameters for CMD_DEBUG_OPEN command + * @brief Parameters for #CMD_DEBUG_OPEN_RO and #CMD_DEBUG_OPEN_WO -commands */ struct cmd_debug_fopen_request { - /** @brief File name - Null-terminated string with maximum - * length @ref DEBUG_FNAME_MAX_SZ + /** + * @brief File name - Null-terminated string with maximum + * length including the terminator defined by the + * #DEBUG_FNAME_MAX_SZ -preprocessor constant. */ char name[DEBUG_FNAME_MAX_SZ]; } BPMP_ABI_PACKED; /** * @ingroup Debugfs - * @brief Response data for CMD_DEBUG_OPEN_RO/WO command + * @brief Response data for #CMD_DEBUG_OPEN_RO and #CMD_DEBUG_OPEN_WO commands */ struct cmd_debug_fopen_response { /** @brief Identifier for file access */ uint32_t fd; /** @brief Data length. File data size for READ command. - * Maximum allowed length for WRITE command + * Maximum allowed length for WRITE command */ uint32_t datalen; } BPMP_ABI_PACKED; /** * @ingroup Debugfs - * @brief Parameters for CMD_DEBUG_READ command + * @brief Parameters for #CMD_DEBUG_READ command */ struct cmd_debug_fread_request { - /** @brief File access identifier received in response - * to CMD_DEBUG_OPEN_RO request + /** + * @brief File access identifier received in response + * to #CMD_DEBUG_OPEN_RO request */ uint32_t fd; } BPMP_ABI_PACKED; @@ -770,7 +1018,7 @@ struct cmd_debug_fread_request { /** * @ingroup Debugfs - * @brief Response data for CMD_DEBUG_READ command + * @brief Response data for #CMD_DEBUG_READ command */ struct cmd_debug_fread_response { /** @brief Size of data provided in this response in bytes */ @@ -789,11 +1037,11 @@ struct cmd_debug_fread_response { /** * @ingroup Debugfs - * @brief Parameters for CMD_DEBUG_WRITE command + * @brief Parameters for #CMD_DEBUG_WRITE command */ struct cmd_debug_fwrite_request { /** @brief File access identifier received in response - * to CMD_DEBUG_OPEN_RO request + * to prior #CMD_DEBUG_OPEN_RO -request */ uint32_t fd; /** @brief Size of write data in bytes */ @@ -804,11 +1052,12 @@ struct cmd_debug_fwrite_request { /** * @ingroup Debugfs - * @brief Parameters for CMD_DEBUG_CLOSE command + * @brief Parameters for #CMD_DEBUG_CLOSE command */ struct cmd_debug_fclose_request { - /** @brief File access identifier received in response - * to CMD_DEBUG_OPEN_RO request + /** + * @brief File access identifier received in prior response + * to #CMD_DEBUG_OPEN_RO or #CMD_DEBUG_OPEN_WO -request. */ uint32_t fd; } BPMP_ABI_PACKED; @@ -817,30 +1066,34 @@ struct cmd_debug_fclose_request { * @ingroup Debugfs * @brief Request with #MRQ_DEBUG. * - * The sender of an MRQ_DEBUG message uses #cmd to specify a debugfs - * command to execute. Legal commands are the values of @ref - * mrq_debug_commands. Each command requires a specific additional - * payload of data. + * The sender of an #MRQ_DEBUG message uses mrq_debug_request::cmd to specify + * which debugfs sub-command to execute. Legal sub-commands are the values + * specified in the @ref mrq_debug_commands -enumeration. Each sub-command + * requires a specific additional payload of data according to the following + * table: * - * |command |payload| - * |-------------------|-------| - * |CMD_DEBUG_OPEN_RO |fop | - * |CMD_DEBUG_OPEN_WO |fop | - * |CMD_DEBUG_READ |frd | - * |CMD_DEBUG_WRITE |fwr | - * |CMD_DEBUG_CLOSE |fcl | + * |Sub-command |Payload structure | + * |--------------------|---------------------------| + * |#CMD_DEBUG_OPEN_RO |cmd_debug_fopen_request | + * |#CMD_DEBUG_OPEN_WO |cmd_debug_fopen_request | + * |#CMD_DEBUG_READ |cmd_debug_fread_request | + * |#CMD_DEBUG_WRITE |cmd_debug_fwrite_request | + * |#CMD_DEBUG_CLOSE |cmd_debug_fclose_request | */ struct mrq_debug_request { - /** @brief Sub-command (@ref mrq_debug_commands) */ + /** @brief Sub-command identifier from @ref mrq_debug_commands */ uint32_t cmd; union { - /** @brief Request payload for CMD_DEBUG_OPEN_RO/WO command */ + /** + * @brief Request payload for #CMD_DEBUG_OPEN_RO and + * #CMD_DEBUG_OPEN_WO sub-commands + */ struct cmd_debug_fopen_request fop; - /** @brief Request payload for CMD_DEBUG_READ command */ + /** @brief Request payload for #CMD_DEBUG_READ sub-command */ struct cmd_debug_fread_request frd; - /** @brief Request payload for CMD_DEBUG_WRITE command */ + /** @brief Request payload for #CMD_DEBUG_WRITE sub-command */ struct cmd_debug_fwrite_request fwr; - /** @brief Request payload for CMD_DEBUG_CLOSE command */ + /** @brief Request payload for #CMD_DEBUG_CLOSE sub-command */ struct cmd_debug_fclose_request fcl; } BPMP_UNION_ANON; } BPMP_ABI_PACKED; @@ -850,9 +1103,12 @@ struct mrq_debug_request { */ struct mrq_debug_response { union { - /** @brief Response data for CMD_DEBUG_OPEN_RO/WO command */ + /** + * @brief Response data for the #CMD_DEBUG_OPEN_RO and + * #CMD_DEBUG_OPEN_WO sub-commands + */ struct cmd_debug_fopen_response fop; - /** @brief Response data for CMD_DEBUG_READ command */ + /** @brief Response data for the #CMD_DEBUG_READ sub-command */ struct cmd_debug_fread_response frd; } BPMP_UNION_ANON; } BPMP_ABI_PACKED; @@ -862,7 +1118,6 @@ struct mrq_debug_response { * @def MRQ_RESET * @brief Reset an IP block * - * * Platforms: T186, T194 * * Initiators: Any * * Targets: BPMP * * Request Payload: @ref mrq_reset_request @@ -872,39 +1127,46 @@ struct mrq_debug_response { * @{ */ +/** + * @brief Sub-command identifiers for #MRQ_RESET + */ enum mrq_reset_commands { /** * @brief Assert module reset * - * mrq_response::err is 0 if the operation was successful, or @n - * -#BPMP_EINVAL if mrq_reset_request::reset_id is invalid @n - * -#BPMP_EACCES if mrq master is not an owner of target domain reset @n - * -#BPMP_ENOTSUP if target domain h/w state does not allow reset + * mrq_response::err is + * * 0 if the operation was successful + * * -#BPMP_EINVAL if mrq_reset_request::reset_id is invalid + * * -#BPMP_EACCES if mrq master is not an owner of target domain reset + * * -#BPMP_ENOTSUP if target domain h/w state does not allow reset */ CMD_RESET_ASSERT = 1, /** * @brief Deassert module reset * - * mrq_response::err is 0 if the operation was successful, or @n - * -#BPMP_EINVAL if mrq_reset_request::reset_id is invalid @n - * -#BPMP_EACCES if mrq master is not an owner of target domain reset @n - * -#BPMP_ENOTSUP if target domain h/w state does not allow reset + * mrq_response::err is + * * 0 if the operation was successful + * * -#BPMP_EINVAL if mrq_reset_request::reset_id is invalid + * * -#BPMP_EACCES if mrq master is not an owner of target domain reset + * * -#BPMP_ENOTSUP if target domain h/w state does not allow reset */ CMD_RESET_DEASSERT = 2, /** * @brief Assert and deassert the module reset * - * mrq_response::err is 0 if the operation was successful, or @n - * -#BPMP_EINVAL if mrq_reset_request::reset_id is invalid @n - * -#BPMP_EACCES if mrq master is not an owner of target domain reset @n - * -#BPMP_ENOTSUP if target domain h/w state does not allow reset + * mrq_response::err is + * * 0 if the operation was successful + * * -#BPMP_EINVAL if mrq_reset_request::reset_id is invalid + * * -#BPMP_EACCES if mrq master is not an owner of target domain reset + * * -#BPMP_ENOTSUP if target domain h/w state does not allow reset */ CMD_RESET_MODULE = 3, /** * @brief Get the highest reset ID * - * mrq_response::err is 0 if the operation was successful, or @n - * -#BPMP_ENODEV if no reset domains are supported (number of IDs is 0) + * mrq_response::err is + * * 0 if the operation was successful + * * -#BPMP_ENODEV if no reset domains are supported (number of IDs is 0) */ CMD_RESET_GET_MAX_ID = 4, @@ -913,15 +1175,15 @@ enum mrq_reset_commands { }; /** - * @brief Request with MRQ_RESET + * @brief Request with #MRQ_RESET * * Used by the sender of an #MRQ_RESET message to request BPMP to - * assert or or deassert a given reset line. + * assert or deassert a given reset line. */ struct mrq_reset_request { - /** @brief Reset action to perform (@ref mrq_reset_commands) */ + /** @brief Reset action to perform, from @ref mrq_reset_commands */ uint32_t cmd; - /** @brief Id of the reset to affected */ + /** @brief ID of the reset to affected, from @ref bpmp_reset_ids */ uint32_t reset_id; } BPMP_ABI_PACKED; @@ -940,7 +1202,7 @@ struct cmd_reset_get_max_id_response { * * Each sub-command supported by @ref mrq_reset_request may return * sub-command-specific data. Some do and some do not as indicated - * in the following table + * in the following table: * * | sub-command | payload | * |----------------------|------------------| @@ -962,7 +1224,6 @@ struct mrq_reset_response { * @def MRQ_I2C * @brief Issue an i2c transaction * - * * Platforms: T186, T194 * * Initiators: Any * * Targets: BPMP * * Request Payload: @ref mrq_i2c_request @@ -971,19 +1232,60 @@ struct mrq_reset_response { * @addtogroup I2C * @{ */ + +/** + * @brief Size of the cmd_i2c_xfer_request::data_buf -member array in bytes. + */ #define TEGRA_I2C_IPC_MAX_IN_BUF_SIZE (MSG_DATA_MIN_SZ - 12U) + +/** + * @brief Size of the cmd_i2c_xfer_response::data_buf -member array in bytes. + */ #define TEGRA_I2C_IPC_MAX_OUT_BUF_SIZE (MSG_DATA_MIN_SZ - 4U) +/** + * @defgroup seriali2c_flags I2C flags + * + * @brief I2C transaction modifier flags for each transaction segment + * in #MRQ_I2C subcommand CMD_I2C_XFER + */ + +/** + * @addtogroup seriali2c_flags + * @{ + */ + +/** @brief when set, use 10-bit I2C slave address */ #define SERIALI2C_TEN 0x0010U +/** @brief when set, perform a Read transaction */ #define SERIALI2C_RD 0x0001U -#define SERIALI2C_STOP 0x8000U +/** + * @brief when set, no repeated START is issued between the segments + * of transaction. This flag is ignored for the first segment as any + * transaction always starts with a START condition + */ #define SERIALI2C_NOSTART 0x4000U -#define SERIALI2C_REV_DIR_ADDR 0x2000U +/** + * @brief when set, a no-ACK from slave device is ignored and treated + * always as success + */ #define SERIALI2C_IGNORE_NAK 0x1000U +/** @} seriali2c_flags */ + +/** brief Unused flag. Retained for backwards compatibility. */ +#define SERIALI2C_STOP 0x8000U +/** brief Unused flag. Retained for backwards compatibility. */ +#define SERIALI2C_REV_DIR_ADDR 0x2000U +/** brief Unused flag. Retained for backwards compatibility. */ #define SERIALI2C_NO_RD_ACK 0x0800U +/** brief Unused flag. Retained for backwards compatibility. */ #define SERIALI2C_RECV_LEN 0x0400U -enum { +/** + * @brief Supported I2C sub-command identifiers + */ +enum mrq_i2c_commands { + /** @brief Perform an I2C transaction */ CMD_I2C_XFER = 1 }; @@ -1005,7 +1307,7 @@ enum { struct serial_i2c_request { /** @brief I2C slave address */ uint16_t addr; - /** @brief Bitmask of SERIALI2C_ flags */ + /** @brief Bitmask of @ref seriali2c_flags */ uint16_t flags; /** @brief Length of I2C transaction in bytes */ uint16_t len; @@ -1020,13 +1322,13 @@ struct cmd_i2c_xfer_request { /** * @brief Tegra PWR_I2C bus identifier * - * @cond (bpmp_t234 || bpmp_t238 || bpmp_t194) + * @cond (bpmp_t186 || bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_t264) * Must be set to 5. - * @endcond (bpmp_t234 || bpmp_t238 || bpmp_t194) - * @cond bpmp_th500 - * Must be set to 1. - * @endcond bpmp_th500 + * @endcond * + * @cond (bpmp_th500) + * Must be set to 1. + * @endcond */ uint32_t bus_id; @@ -1047,7 +1349,7 @@ struct cmd_i2c_xfer_request { struct cmd_i2c_xfer_response { /** @brief Count of valid bytes in #data_buf*/ uint32_t data_size; - /** @brief I2c read data */ + /** @brief I2C read data */ uint8_t data_buf[TEGRA_I2C_IPC_MAX_OUT_BUF_SIZE]; } BPMP_ABI_PACKED; @@ -1064,16 +1366,19 @@ struct mrq_i2c_request { /** * @brief Response to #MRQ_I2C * - * mrq_response:err is - * 0: Success - * -#BPMP_EBADCMD: if mrq_i2c_request::cmd is other than 1 - * -#BPMP_EINVAL: if cmd_i2c_xfer_request does not contain correctly formatted request - * -#BPMP_ENODEV: if cmd_i2c_xfer_request::bus_id is not supported by BPMP - * -#BPMP_EACCES: if i2c transaction is not allowed due to firewall rules - * -#BPMP_ETIMEDOUT: if i2c transaction times out - * -#BPMP_ENXIO: if i2c slave device does not reply with ACK to the transaction - * -#BPMP_EAGAIN: if ARB_LOST condition is detected by the i2c controller - * -#BPMP_EIO: any other i2c controller error code than NO_ACK or ARB_LOST + * mrq_response::err value for this response is defined as: + * + * | Value | Description | + * |--------------------|---------------------------------------------------------------------| + * | 0 | Success | + * | -#BPMP_EBADCMD | mrq_i2c_request::cmd is other than 1 | + * | -#BPMP_EINVAL | cmd_i2c_xfer_request does not contain correctly formatted request | + * | -#BPMP_ENODEV | cmd_i2c_xfer_request::bus_id is not supported by BPMP | + * | -#BPMP_EACCES | I2C transaction is not allowed due to firewall rules | + * | -#BPMP_ETIMEDOUT | I2C transaction times out | + * | -#BPMP_ENXIO | I2C slave device does not reply with ACK to the transaction | + * | -#BPMP_EAGAIN | ARB_LOST condition is detected by the I2C controller | + * | -#BPMP_EIO | Any other I2C controller error code than NO_ACK or ARB_LOST | */ struct mrq_i2c_response { struct cmd_i2c_xfer_response xfer; @@ -1086,7 +1391,6 @@ struct mrq_i2c_response { * @def MRQ_CLK * @brief Perform a clock operation * - * * Platforms: T186, T194 * * Initiators: Any * * Targets: BPMP * * Request Payload: @ref mrq_clk_request @@ -1095,205 +1399,354 @@ struct mrq_i2c_response { * @addtogroup Clocks * @{ */ -enum { + +/** + * @brief Sub-command identifiers for #MRQ_CLK + */ +enum mrq_clk_commands { + /** Get clock rate */ CMD_CLK_GET_RATE = 1, + + /** Set clock rate */ CMD_CLK_SET_RATE = 2, + + /** Get attainable clock rate closer to a given rate */ CMD_CLK_ROUND_RATE = 3, + + /** Get parent clock identifier for a given clock */ CMD_CLK_GET_PARENT = 4, + + /** Change clock parent */ CMD_CLK_SET_PARENT = 5, + + /** Get clock enable status */ CMD_CLK_IS_ENABLED = 6, + + /** Enable a clock */ CMD_CLK_ENABLE = 7, + + /** Disable a clock */ CMD_CLK_DISABLE = 8, -/** @cond DEPRECATED */ - CMD_CLK_PROPERTIES = 9, - CMD_CLK_POSSIBLE_PARENTS = 10, - CMD_CLK_NUM_POSSIBLE_PARENTS = 11, - CMD_CLK_GET_POSSIBLE_PARENT = 12, - CMD_CLK_RESET_REFCOUNTS = 13, -/** @endcond DEPRECATED */ + + /** Get all information about a clock */ CMD_CLK_GET_ALL_INFO = 14, + + /** Get largest supported clock identifier */ CMD_CLK_GET_MAX_CLK_ID = 15, + + /** Get clock maximum rate at VMIN */ CMD_CLK_GET_FMAX_AT_VMIN = 16, + + /** Largest supported #MRQ_CLK sub-command identifier + 1 */ CMD_CLK_MAX, }; +/** + * Flag bit set in cmd_clk_get_all_info_response::flags -field when clock + * supports changing of the parent clock at runtime. + */ #define BPMP_CLK_HAS_MUX (1U << 0U) + +/** + * Flag bit set in cmd_clk_get_all_info_response::flags -field when clock + * supports changing the clock rate at runtime. + */ #define BPMP_CLK_HAS_SET_RATE (1U << 1U) + +/** + * Flag bit set in cmd_clk_get_all_info_response::flags -field when clock is a + * root clock without visible parents. + */ #define BPMP_CLK_IS_ROOT (1U << 2U) + #define BPMP_CLK_IS_VAR_ROOT (1U << 3U) + /** * @brief Protection against rate and parent changes * - * #MRQ_CLK command #CMD_CLK_SET_RATE or #MRQ_CLK command #CMD_CLK_SET_PARENT will return - * -#BPMP_EACCES. + * #MRQ_CLK command #CMD_CLK_SET_RATE or #MRQ_CLK command #CMD_CLK_SET_PARENT + * will return -#BPMP_EACCES. */ #define BPMP_CLK_RATE_PARENT_CHANGE_DENIED (1U << 30) /** * @brief Protection against state changes * - * #MRQ_CLK command #CMD_CLK_ENABLE or #MRQ_CLK command #CMD_CLK_DISABLE will return - * -#BPMP_EACCES. + * #MRQ_CLK command #CMD_CLK_ENABLE or #MRQ_CLK command #CMD_CLK_DISABLE + * will return -#BPMP_EACCES. */ #define BPMP_CLK_STATE_CHANGE_DENIED (1U << 31) +/** + * Size of the cmd_clk_get_all_info_response::name -array in number + * of elements. + */ #define MRQ_CLK_NAME_MAXLEN 40U + +/** + * @brief Maximum number of elements in parent_id arrays of clock info responses. + */ #define MRQ_CLK_MAX_PARENTS 16U -/** @private */ +/** + * @brief Request payload for #MRQ_CLK sub-command #CMD_CLK_GET_RATE + * + * This structure is an empty placeholder for future expansion of this + * sub-command. + */ struct cmd_clk_get_rate_request { BPMP_ABI_EMPTY } BPMP_ABI_PACKED; +/** + * @brief Response payload for #MRQ_CLK sub-command #CMD_CLK_GET_RATE + */ struct cmd_clk_get_rate_response { + /** + * Current rate of the given clock in Hz if mrq_response::err is 0 to + * indicate successful #CMD_CLK_GET_RATE -request. + */ int64_t rate; } BPMP_ABI_PACKED; +/** + * @brief Request payload for #MRQ_CLK sub-command #CMD_CLK_SET_RATE + */ struct cmd_clk_set_rate_request { + /** Unused / reserved field. */ int32_t unused; + + /** Requested rate of the clock in Hz. */ int64_t rate; } BPMP_ABI_PACKED; +/** + * @brief Response payload for #MRQ_CLK sub-command #CMD_CLK_SET_RATE + */ struct cmd_clk_set_rate_response { + /** + * If request was successful (mrq_response::err is 0), set to the new + * rate of the given clock in Hz. + */ int64_t rate; } BPMP_ABI_PACKED; +/** + * @brief Request payload for #MRQ_CLK sub-command #CMD_CLK_ROUND_RATE + */ struct cmd_clk_round_rate_request { + /** Unused / reserved field. */ int32_t unused; + + /** Target rate for the clock */ int64_t rate; } BPMP_ABI_PACKED; +/** + * @brief Response payload for #MRQ_CLK sub-command #CMD_CLK_ROUND_RATE + */ struct cmd_clk_round_rate_response { + /** + * The attainable rate if request was successful + * (mrq_response::err is 0). + */ int64_t rate; } BPMP_ABI_PACKED; -/** @private */ +/** + * @brief Request payload for #MRQ_CLK sub-command #CMD_CLK_GET_PARENT + * + * This structure is an empty placeholder for future expansion of this + * sub-command. + */ struct cmd_clk_get_parent_request { BPMP_ABI_EMPTY } BPMP_ABI_PACKED; +/** + * @brief Response payload for #MRQ_CLK sub-command #CMD_CLK_GET_PARENT + */ struct cmd_clk_get_parent_response { + /** + * The clock identifier of the parent clock if request was successful + * (mrq_response::err is 0). + */ uint32_t parent_id; } BPMP_ABI_PACKED; +/** + * @brief Request payload for #MRQ_CLK sub-command #CMD_CLK_SET_PARENT + */ struct cmd_clk_set_parent_request { + /** + * The clock identifier of the new parent clock. + */ uint32_t parent_id; } BPMP_ABI_PACKED; +/** + * @brief Response payload for #MRQ_CLK sub-command #CMD_CLK_SET_PARENT + */ struct cmd_clk_set_parent_response { + /** + * The clock identifier of the new parent clock if request was + * successful (mrq_response::err is 0). + */ uint32_t parent_id; } BPMP_ABI_PACKED; -/** @private */ +/** + * @brief Request payload for #CMD_CLK_IS_ENABLED -sub-command + * + * This structure is an empty placeholder for future expansion of this + * sub-command. + */ struct cmd_clk_is_enabled_request { BPMP_ABI_EMPTY } BPMP_ABI_PACKED; /** - * @brief Response data to #MRQ_CLK sub-command CMD_CLK_IS_ENABLED + * @brief Response payload for #MRQ_CLK sub-command #CMD_CLK_IS_ENABLED */ struct cmd_clk_is_enabled_response { /** * @brief The state of the clock that has been successfully - * requested with CMD_CLK_ENABLE or CMD_CLK_DISABLE by the + * requested with #CMD_CLK_ENABLE or #CMD_CLK_DISABLE by the * master invoking the command earlier. * * The state may not reflect the physical state of the clock * if there are some other masters requesting it to be - * enabled. + * enabled. Valid values: * - * Value 0 is disabled, all other values indicate enabled. + * * Value 0: The clock is disabled, + * * Value 1: The clock is enabled. */ int32_t state; } BPMP_ABI_PACKED; -/** @private */ +/** + * @brief Request payload for #MRQ_CLK sub-command #CMD_CLK_ENABLE + * + * This structure is an empty placeholder for future expansion of this + * sub-command. + */ struct cmd_clk_enable_request { BPMP_ABI_EMPTY } BPMP_ABI_PACKED; -/** @private */ +/** + * @brief Response payload for #MRQ_CLK sub-command #CMD_CLK_ENABLE + * + * This structure is an empty placeholder for future expansion of this + * sub-command. + */ struct cmd_clk_enable_response { BPMP_ABI_EMPTY } BPMP_ABI_PACKED; -/** @private */ +/** + * @brief Request payload for #MRQ_CLK sub-command #CMD_CLK_DISABLE + * + * This structure is an empty placeholder for future expansion of this + * sub-command. + */ struct cmd_clk_disable_request { BPMP_ABI_EMPTY } BPMP_ABI_PACKED; -/** @private */ +/** + * @brief Response payload for #MRQ_CLK sub-command #CMD_CLK_DISABLE + * + * This structure is an empty placeholder for future expansion of this + * sub-command. + */ struct cmd_clk_disable_response { BPMP_ABI_EMPTY } BPMP_ABI_PACKED; -/** @cond DEPRECATED */ -/** @private */ -struct cmd_clk_properties_request { - BPMP_ABI_EMPTY -} BPMP_ABI_PACKED; - -/** @todo flags need to be spelled out here */ -struct cmd_clk_properties_response { - uint32_t flags; -} BPMP_ABI_PACKED; - -/** @private */ -struct cmd_clk_possible_parents_request { - BPMP_ABI_EMPTY -} BPMP_ABI_PACKED; - -struct cmd_clk_possible_parents_response { - uint8_t num_parents; - uint8_t reserved[3]; - uint32_t parent_id[MRQ_CLK_MAX_PARENTS]; -} BPMP_ABI_PACKED; - -/** @private */ -struct cmd_clk_num_possible_parents_request { - BPMP_ABI_EMPTY -} BPMP_ABI_PACKED; - -struct cmd_clk_num_possible_parents_response { - uint8_t num_parents; -} BPMP_ABI_PACKED; - -struct cmd_clk_get_possible_parent_request { - uint8_t parent_idx; -} BPMP_ABI_PACKED; - -struct cmd_clk_get_possible_parent_response { - uint32_t parent_id; -} BPMP_ABI_PACKED; -/** @endcond DEPRECATED */ - -/** @private */ +/** + * @brief Request payload for #MRQ_CLK sub-command #CMD_CLK_GET_ALL_INFO + * + * This structure is an empty placeholder for future expansion of this + * sub-command. + */ struct cmd_clk_get_all_info_request { BPMP_ABI_EMPTY } BPMP_ABI_PACKED; + +/** + * @brief Response payload for #MRQ_CLK sub-command #CMD_CLK_GET_ALL_INFO + * + * The values in the response are only set and valid if request status in + * mrq_response::err is 0. + */ struct cmd_clk_get_all_info_response { + /** + * State / informational flags for the clock: + * + * | Flag bit | Description | + * |------------------------|------------------------------------------| + * | #BPMP_CLK_IS_ROOT | Clock is a root clock. | + * | #BPMP_CLK_HAS_MUX | Clock supports changing of parent clock. | + * | #BPMP_CLK_HAS_SET_RATE | Clock supports changing clock rate. | + */ uint32_t flags; + + /** + * Current parent clock identifier. + */ uint32_t parent; + + /** + * Array of possible parent clock identifiers. + */ uint32_t parents[MRQ_CLK_MAX_PARENTS]; + + /** + * Number of identifiers in the #parents -array. + */ uint8_t num_parents; + + /** + * Friendly name of the clock, truncated to fit the array + * and null-terminated. + */ uint8_t name[MRQ_CLK_NAME_MAXLEN]; } BPMP_ABI_PACKED; -/** @private */ + +/** + * @brief Request payload for #MRQ_CLK sub-command #CMD_CLK_GET_MAX_CLK_ID + * + * This structure is an empty placeholder for future expansion of this + * sub-command. + */ struct cmd_clk_get_max_clk_id_request { BPMP_ABI_EMPTY } BPMP_ABI_PACKED; +/** + * @brief Response payload for #MRQ_CLK sub-command #CMD_CLK_GET_MAX_CLK_ID + */ struct cmd_clk_get_max_clk_id_response { + /** @brief Largest supported clock identifier. */ uint32_t max_id; } BPMP_ABI_PACKED; -/** @private */ +/** + * @brief Request payload for #MRQ_CLK sub-command #CMD_CLK_GET_FMAX_AT_VMIN + * + * This structure is an empty placeholder for future expansion of this + * sub-command. + */ struct cmd_clk_get_fmax_at_vmin_request { BPMP_ABI_EMPTY } BPMP_ABI_PACKED; +/** + * @brief Response payload for #MRQ_CLK sub-command #CMD_CLK_GET_FMAX_AT_VMIN + */ struct cmd_clk_get_fmax_at_vmin_response { int64_t rate; } BPMP_ABI_PACKED; @@ -1308,38 +1761,26 @@ struct cmd_clk_get_fmax_at_vmin_response { * require no additional data. Others have a sub-command specific * payload * - * |sub-command |payload | - * |----------------------------|-----------------------| - * |CMD_CLK_GET_RATE |- | - * |CMD_CLK_SET_RATE |clk_set_rate | - * |CMD_CLK_ROUND_RATE |clk_round_rate | - * |CMD_CLK_GET_PARENT |- | - * |CMD_CLK_SET_PARENT |clk_set_parent | - * |CMD_CLK_IS_ENABLED |- | - * |CMD_CLK_ENABLE |- | - * |CMD_CLK_DISABLE |- | - * |CMD_CLK_GET_ALL_INFO |- | - * |CMD_CLK_GET_MAX_CLK_ID |- | - * |CMD_CLK_GET_FMAX_AT_VMIN |- - * | - * + * |Sub-command |Payload | + * |----------------------------|-----------------------------| + * |#CMD_CLK_GET_RATE |- | + * |#CMD_CLK_SET_RATE |#cmd_clk_set_rate_request | + * |#CMD_CLK_ROUND_RATE |#cmd_clk_round_rate_request | + * |#CMD_CLK_GET_PARENT |- | + * |#CMD_CLK_SET_PARENT |#cmd_clk_set_parent_request | + * |#CMD_CLK_IS_ENABLED |- | + * |#CMD_CLK_ENABLE |- | + * |#CMD_CLK_DISABLE |- | + * |#CMD_CLK_GET_ALL_INFO |- | + * |#CMD_CLK_GET_MAX_CLK_ID |- | + * |#CMD_CLK_GET_FMAX_AT_VMIN |- | */ -/** @cond DEPRECATED - * - * Older versions of firmware also supported following sub-commands: - * |CMD_CLK_PROPERTIES |- | - * |CMD_CLK_POSSIBLE_PARENTS |- | - * |CMD_CLK_NUM_POSSIBLE_PARENTS|- | - * |CMD_CLK_GET_POSSIBLE_PARENT |clk_get_possible_parent| - * |CMD_CLK_RESET_REFCOUNTS |- | - * - * @endcond DEPRECATED */ - struct mrq_clk_request { /** @brief Sub-command and clock id concatenated to 32-bit word. - * - bits[31..24] is the sub-cmd. - * - bits[23..0] is the clock id + * + * - bits[31..24] is the sub-command ID from @ref mrq_clk_commands. + * - bits[23..0] is the clock identifier from @ref bpmp_clock_ids. */ uint32_t cmd_and_id; @@ -1357,15 +1798,6 @@ struct mrq_clk_request { struct cmd_clk_disable_request clk_disable; /** @private */ struct cmd_clk_is_enabled_request clk_is_enabled; - /** @cond DEPRECATED */ - /** @private */ - struct cmd_clk_properties_request clk_properties; - /** @private */ - struct cmd_clk_possible_parents_request clk_possible_parents; - /** @private */ - struct cmd_clk_num_possible_parents_request clk_num_possible_parents; - struct cmd_clk_get_possible_parent_request clk_get_possible_parent; - /** @endcond DEPRECATED */ /** @private */ struct cmd_clk_get_all_info_request clk_get_all_info; /** @private */ @@ -1381,35 +1813,24 @@ struct mrq_clk_request { * * Each sub-command supported by @ref mrq_clk_request may return * sub-command-specific data. Some do and some do not as indicated in - * the following table + * the following table: * - * |sub-command |payload | - * |----------------------------|------------------------| - * |CMD_CLK_GET_RATE |clk_get_rate | - * |CMD_CLK_SET_RATE |clk_set_rate | - * |CMD_CLK_ROUND_RATE |clk_round_rate | - * |CMD_CLK_GET_PARENT |clk_get_parent | - * |CMD_CLK_SET_PARENT |clk_set_parent | - * |CMD_CLK_IS_ENABLED |clk_is_enabled | - * |CMD_CLK_ENABLE |- | - * |CMD_CLK_DISABLE |- | - * |CMD_CLK_GET_ALL_INFO |clk_get_all_info | - * |CMD_CLK_GET_MAX_CLK_ID |clk_get_max_id | - * |CMD_CLK_GET_FMAX_AT_VMIN |clk_get_fmax_at_vmin | + * |Sub-command |Payload | + * |----------------------------|-----------------------------------| + * |#CMD_CLK_GET_RATE |#cmd_clk_get_rate_response | + * |#CMD_CLK_SET_RATE |#cmd_clk_set_rate_response | + * |#CMD_CLK_ROUND_RATE |#cmd_clk_round_rate_response | + * |#CMD_CLK_GET_PARENT |#cmd_clk_get_parent_response | + * |#CMD_CLK_SET_PARENT |#cmd_clk_set_parent_response | + * |#CMD_CLK_IS_ENABLED |#cmd_clk_is_enabled_response | + * |#CMD_CLK_ENABLE |- | + * |#CMD_CLK_DISABLE |- | + * |#CMD_CLK_GET_ALL_INFO |#cmd_clk_get_all_info_response | + * |#CMD_CLK_GET_MAX_CLK_ID |#cmd_clk_get_max_clk_id_response | + * |#CMD_CLK_GET_FMAX_AT_VMIN |#cmd_clk_get_fmax_at_vmin_response | * */ -/** @cond DEPRECATED - * - * Older versions of firmware also supported following sub-commands: - * |CMD_CLK_PROPERTIES |clk_properties | - * |CMD_CLK_POSSIBLE_PARENTS |clk_possible_parents | - * |CMD_CLK_NUM_POSSIBLE_PARENTS|clk_num_possible_parents| - * |CMD_CLK_GET_POSSIBLE_PARENT |clk_get_possible_parents| - * |CMD_CLK_RESET_REFCOUNTS |- | - * - * @endcond DEPRECATED */ - struct mrq_clk_response { union { struct cmd_clk_get_rate_response clk_get_rate; @@ -1422,12 +1843,6 @@ struct mrq_clk_response { /** @private */ struct cmd_clk_disable_response clk_disable; struct cmd_clk_is_enabled_response clk_is_enabled; - /** @cond DEPRECATED */ - struct cmd_clk_properties_response clk_properties; - struct cmd_clk_possible_parents_response clk_possible_parents; - struct cmd_clk_num_possible_parents_response clk_num_possible_parents; - struct cmd_clk_get_possible_parent_response clk_get_possible_parent; - /** @endcond DEPRECATED */ struct cmd_clk_get_all_info_response clk_get_all_info; struct cmd_clk_get_max_clk_id_response clk_get_max_clk_id; struct cmd_clk_get_fmax_at_vmin_response clk_get_fmax_at_vmin; @@ -1441,7 +1856,6 @@ struct mrq_clk_response { * @def MRQ_QUERY_ABI * @brief Check if an MRQ is implemented * - * * Platforms: All * * Initiators: Any * * Targets: Any except DMCE * * Request Payload: @ref mrq_query_abi_request @@ -1450,7 +1864,7 @@ struct mrq_clk_response { /** * @ingroup ABI_info - * @brief Request with MRQ_QUERY_ABI + * @brief Request with #MRQ_QUERY_ABI * * Used by #MRQ_QUERY_ABI call to check if MRQ code #mrq is supported * by the recipient. @@ -1468,7 +1882,11 @@ struct mrq_query_abi_request { * successful, not that the MRQ itself is supported! */ struct mrq_query_abi_response { - /** @brief 0 if queried MRQ is supported. Else, -#BPMP_ENODEV */ + /** + * This response field is set to: + * - 0 if queried MRQ is supported, or + * - -#BPMP_ENODEV if queried MRQ is not supported + */ int32_t status; } BPMP_ABI_PACKED; @@ -1476,9 +1894,7 @@ struct mrq_query_abi_response { * * @ingroup MRQ_Codes * @def MRQ_PG - * @brief Control power-gating state of a partition. In contrast to - * MRQ_PG_UPDATE_STATE, operations that change the power partition - * state are NOT reference counted + * @brief Control power-gating state of a partition. * * @cond (bpmp_t194 || bpmp_t186) * @note On T194 and earlier BPMP-FW forcefully turns off some partitions as @@ -1486,9 +1902,8 @@ struct mrq_query_abi_response { * Therefore, it is recommended to power off all domains via MRQ_PG prior to SC7 * entry. * See @ref bpmp_pdomain_ids for further detail. - * @endcond (bpmp_t194 || bpmp_t186) + * @endcond * - * * Platforms: T186, T194 * * Initiators: Any * * Targets: BPMP * * Request Payload: @ref mrq_pg_request @@ -1497,6 +1912,10 @@ struct mrq_query_abi_response { * @addtogroup Powergating * @{ */ + +/** + * @brief Sub-command identifiers for #MRQ_PG -command. + */ enum mrq_pg_cmd { /** * @brief Check whether the BPMP driver supports the specified @@ -1512,9 +1931,14 @@ enum mrq_pg_cmd { * possible values for power domains are defined in enum * pg_states * - * mrq_response:err is - * 0: Success - * -#BPMP_EINVAL: Invalid request parameters + * mrq_response:err for this sub-command is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------------------------------------ | + * | 0 | Request was successful. | + * | -#BPMP_EINVAL | Invalid request parameters were provided. | + * | -#BPMP_EACCES | Permission denied or always-off partition was attempted to be turned on. | + * | Any other <0 | Internal error while performing the operation. | */ CMD_PG_SET_STATE = 1, @@ -1523,18 +1947,26 @@ enum mrq_pg_cmd { * possible values for power domains are defined in enum * pg_states * - * mrq_response:err is - * 0: Success - * -#BPMP_EINVAL: Invalid request parameters + * mrq_response:err for this sub-command is defined as: + * + * | Value | Description | + * | -------------- | ---------------------------------------------- | + * | 0 | Request was successful. | + * | -#BPMP_EINVAL | Invalid request parameters were provided. | + * | Any other <0 | Internal error while performing the operation. | */ CMD_PG_GET_STATE = 2, /** * @brief Get the name string of specified power domain id. * - * mrq_response:err is - * 0: Success - * -#BPMP_EINVAL: Invalid request parameters + * mrq_response:err for this sub-command is defined as: + * + * | Value | Description | + * | -------------- | ---------------------------------------------- | + * | 0 | Request was successful. | + * | -#BPMP_EINVAL | Invalid request parameters were provided. | + * | Any other <0 | Internal error while performing the operation. | */ CMD_PG_GET_NAME = 3, @@ -1543,20 +1975,29 @@ enum mrq_pg_cmd { * @brief Get the highest power domain id in the system. Not * all IDs between 0 and max_id are valid IDs. * - * mrq_response:err is - * 0: Success - * -#BPMP_EINVAL: Invalid request parameters + * mrq_response:err for this sub-command is defined as: + * + * | Value | Description | + * | -------------- | ---------------------------------------------- | + * | 0 | Request was successful. | + * | -#BPMP_EINVAL | Invalid request parameters were provided. | + * | Any other <0 | Internal error while performing the operation. | */ CMD_PG_GET_MAX_ID = 4, }; #define MRQ_PG_NAME_MAXLEN 40 +/** + * @brief State value for the cmd_pg_set_state_request::state -field. + */ enum pg_states { /** @brief Power domain is OFF */ PG_STATE_OFF = 0, /** @brief Power domain is ON */ PG_STATE_ON = 1, + + /** @cond bpmp_t186 */ /** * @brief a legacy state where power domain and the clock * associated to the domain are ON. @@ -1564,40 +2005,51 @@ enum pg_states { * deprecated. */ PG_STATE_RUNNING = 2, + /** @endcond */ }; struct cmd_pg_query_abi_request { - /** @ref mrq_pg_cmd */ + /** #MRQ_PG sub-command identifier from @ref mrq_pg_cmd */ uint32_t type; } BPMP_ABI_PACKED; struct cmd_pg_set_state_request { - /** @ref pg_states */ + /** One of the state values from @ref pg_states */ uint32_t state; } BPMP_ABI_PACKED; /** - * @brief Response data to #MRQ_PG sub command #CMD_PG_GET_STATE + * @brief Response payload for the #MRQ_PG sub-command #CMD_PG_GET_STATE */ struct cmd_pg_get_state_response { /** * @brief The state of the power partition that has been - * succesfuly requested by the master earlier using #MRQ_PG + * successfully requested by the master earlier using #MRQ_PG * command #CMD_PG_SET_STATE. * * The state may not reflect the physical state of the power * partition if there are some other masters requesting it to * be enabled. * - * See @ref pg_states for possible values + * See @ref pg_states for possible values. */ uint32_t state; } BPMP_ABI_PACKED; +/** + * @brief Response payload for the #MRQ_PG sub-command #CMD_PG_GET_NAME + */ struct cmd_pg_get_name_response { + /** + * @brief On successful response contains the null-terminated + * friendly name of the requested power-domain. + */ uint8_t name[MRQ_PG_NAME_MAXLEN]; } BPMP_ABI_PACKED; +/** + * @brief Response payload for the #MRQ_PG sub-command #CMD_PG_GET_MAX_ID + */ struct cmd_pg_get_max_id_response { uint32_t max_id; } BPMP_ABI_PACKED; @@ -1606,22 +2058,28 @@ struct cmd_pg_get_max_id_response { * @brief Request with #MRQ_PG * * Used by the sender of an #MRQ_PG message to control power - * partitions. The pg_request is split into several sub-commands. Some - * sub-commands require no additional data. Others have a sub-command - * specific payload + * partitions. The expected payload depends on the sub-command identifier. + * Some sub-commands require no additional data while others have a sub-command + * specific payload: * - * |sub-command |payload | - * |----------------------------|-----------------------| - * |CMD_PG_QUERY_ABI | query_abi | - * |CMD_PG_SET_STATE | set_state | - * |CMD_PG_GET_STATE | - | - * |CMD_PG_GET_NAME | - | - * |CMD_PG_GET_MAX_ID | - | + * |Sub-command |Payload | + * |----------------------------|---------------------------| + * |#CMD_PG_QUERY_ABI | #cmd_pg_query_abi_request | + * |#CMD_PG_SET_STATE | #cmd_pg_set_state_request | + * |#CMD_PG_GET_STATE | - | + * |#CMD_PG_GET_NAME | - | + * |#CMD_PG_GET_MAX_ID | - | * */ struct mrq_pg_request { + /** @brief Sub-command identifier from @ref mrq_pg_cmd. */ uint32_t cmd; + + /** + * @brief Power-domain identifier + */ uint32_t id; + union { struct cmd_pg_query_abi_request query_abi; struct cmd_pg_set_state_request set_state; @@ -1629,19 +2087,18 @@ struct mrq_pg_request { } BPMP_ABI_PACKED; /** - * @brief Response to MRQ_PG + * @brief Response to #MRQ_PG * - * Each sub-command supported by @ref mrq_pg_request may return - * sub-command-specific data. Some do and some do not as indicated in - * the following table + * Some of the #MRQ_PG sub-commands return a sub-command -specific payload + * as specified in the following table: * - * |sub-command |payload | - * |----------------------------|-----------------------| - * |CMD_PG_QUERY_ABI | - | - * |CMD_PG_SET_STATE | - | - * |CMD_PG_GET_STATE | get_state | - * |CMD_PG_GET_NAME | get_name | - * |CMD_PG_GET_MAX_ID | get_max_id | + * |Sub-command |Payload | + * |--------------------|------------------------------| + * |#CMD_PG_QUERY_ABI | - | + * |#CMD_PG_SET_STATE | - | + * |#CMD_PG_GET_STATE | #cmd_pg_get_state_response | + * |#CMD_PG_GET_NAME | #cmd_pg_get_name_response | + * |#CMD_PG_GET_MAX_ID | #cmd_pg_get_max_id_response | */ struct mrq_pg_response { union { @@ -1658,11 +2115,10 @@ struct mrq_pg_response { * @def MRQ_THERMAL * @brief Interact with BPMP thermal framework * - * * Platforms: T186, T194 * * Initiators: Any * * Targets: Any - * * Request Payload: TODO - * * Response Payload: TODO + * * Request Payload: #mrq_thermal_host_to_bpmp_request + * * Response Payload: #mrq_thermal_bpmp_to_host_response * * @addtogroup Thermal * @@ -1686,10 +2142,14 @@ struct mrq_pg_response { * payload of @ref mrq_thermal_bpmp_to_host_request. * @{ */ + +/** + * @brief Sub-command identifiers for Host->BPMP #MRQ_THERMAL -command. + */ enum mrq_thermal_host_to_bpmp_cmd { /** - * @brief Check whether the BPMP driver supports the specified - * request type. + * @brief Check whether BPMP-FW supports the specified + * #MRQ_THERMAL sub-command. * * Host needs to supply request parameters. * @@ -1703,31 +2163,44 @@ enum mrq_thermal_host_to_bpmp_cmd { * * Host needs to supply request parameters. * - * mrq_response::err is - * * 0: Temperature query succeeded. - * * -#BPMP_EINVAL: Invalid request parameters. - * * -#BPMP_ENOENT: No driver registered for thermal zone.. - * * -#BPMP_EFAULT: Problem reading temperature measurement. + * mrq_response::err value for this sub-command is: + * + * | Value | Description | + * | -------------- | ----------------------------------------- | + * | 0 | Temperature query succeeded. | + * | -#BPMP_EINVAL | Invalid request parameters. | + * | -#BPMP_ENOENT | No driver registered for thermal zone. | + * | -#BPMP_EFAULT | Problem reading temperature measurement. | */ CMD_THERMAL_GET_TEMP = 1, /** + * @cond (!bpmp_safe && !bpmp_t264) * @brief Enable or disable and set the lower and upper * thermal limits for a thermal trip point. Each zone has * one trip point. * * Host needs to supply request parameters. Once the * temperature hits a trip point, the BPMP will send a message - * to the CPU having MRQ=MRQ_THERMAL and - * type=CMD_THERMAL_HOST_TRIP_REACHED + * to the CPU having MRQ command identifier equal to #MRQ_THERMAL and + * sub-command identifier equal to #CMD_THERMAL_HOST_TRIP_REACHED. * - * mrq_response::err is - * * 0: Trip successfully set. - * * -#BPMP_EINVAL: Invalid request parameters. - * * -#BPMP_ENOENT: No driver registered for thermal zone. - * * -#BPMP_EFAULT: Problem setting trip point. + * If #CMD_THERMAL_SET_TRIP -sub-command is issued for a + * thermal zone that is currently power gated and unable to + * report temperature, a temperature of -256C is used as + * temperature for evaluation of the trip. + * + * mrq_response::err for this sub-command is defined as: + * + * | Value | Description | + * | --------------- | -------------------------------------- | + * | 0 | Trip successfully set. | + * | -#BPMP_EINVAL | Invalid request parameters. | + * | -#BPMP_ENOENT | No driver registered for thermal zone. | + * | -#BPMP_EFAULT | Problem setting trip point. | */ CMD_THERMAL_SET_TRIP = 2, + /** @endcond */ /** * @brief Get the number of supported thermal zones. @@ -1739,135 +2212,153 @@ enum mrq_thermal_host_to_bpmp_cmd { CMD_THERMAL_GET_NUM_ZONES = 3, /** - * @brief Get the thermtrip of the specified zone. + * @brief Get the thermal trip value of the specified zone. * * Host needs to supply request parameters. * - * mrq_response::err is - * * 0: Valid zone information returned. - * * -#BPMP_EINVAL: Invalid request parameters. - * * -#BPMP_ENOENT: No driver registered for thermal zone. - * * -#BPMP_ERANGE if thermtrip is invalid or disabled. - * * -#BPMP_EFAULT: Problem reading zone information. + * mrq_response::err for this sub-command is defined as: + * + * | Value | Description | + * | --------------- | -------------------------------------- | + * | 0 | Valid zone information returned. | + * | -#BPMP_EINVAL | Invalid request parameters. | + * | -#BPMP_ENOENT | No driver registered for thermal zone. | + * | -#BPMP_ERANGE | Thermal trip is invalid or disabled. | + * | -#BPMP_EFAULT | Problem reading zone information. | */ CMD_THERMAL_GET_THERMTRIP = 4, - /** @brief: number of supported host-to-bpmp commands. May - * increase in future + /** + * @brief Number of supported host-to-bpmp commands. */ CMD_THERMAL_HOST_TO_BPMP_NUM }; +/** + * @brief Sub-command identifiers for BPMP->host #MRQ_THERMAL -command + */ enum mrq_thermal_bpmp_to_host_cmd { /** * @brief Indication that the temperature for a zone has - * exceeded the range indicated in the thermal trip point - * for the zone. + * exceeded the range indicated in the thermal trip point + * for the zone. * - * BPMP needs to supply request parameters. Host only needs to + * BPMP-FW needs to supply request parameters. Host only needs to * acknowledge. */ CMD_THERMAL_HOST_TRIP_REACHED = 100, - /** @brief: number of supported bpmp-to-host commands. May - * increase in future + /** + * @brief: Number of supported bpmp-to-host commands. May + * increase in future. */ CMD_THERMAL_BPMP_TO_HOST_NUM }; -/* - * Host->BPMP request data for request type CMD_THERMAL_QUERY_ABI - * - * zone: Request type for which to check existence. +/** + * Host->BPMP request payload for the #CMD_THERMAL_QUERY_ABI sub-command */ struct cmd_thermal_query_abi_request { + /** + * Request type for which to check whether supported by BPMP-FW. + * + * Valid identifiers are available at #mrq_thermal_host_to_bpmp_cmd + */ uint32_t type; } BPMP_ABI_PACKED; -/* - * Host->BPMP request data for request type CMD_THERMAL_GET_TEMP - * - * zone: Number of thermal zone. +/** + * Host->BPMP request payload for the #CMD_THERMAL_GET_TEMP sub-command */ struct cmd_thermal_get_temp_request { + /** Thermal zone identifier from @ref bpmp_thermal_ids. */ uint32_t zone; } BPMP_ABI_PACKED; -/* - * BPMP->Host reply data for request CMD_THERMAL_GET_TEMP +/** + * BPMP->Host response payload for the #CMD_THERMAL_GET_TEMP sub-command. * - * error: 0 if request succeeded. - * -BPMP_EINVAL if request parameters were invalid. - * -BPMP_ENOENT if no driver was registered for the specified thermal zone. - * -BPMP_EFAULT for other thermal zone driver errors. - * temp: Current temperature in millicelsius. + * mrq_response::err is defined as: + * + * | Value | Description | + * | ------------- | -------------------------------------------------------- | + * | 0 | Request succeeded. | + * | -#BPMP_EINVAL | Request parameters were invalid. | + * | -#BPMP_ENOENT | No driver was registered for the specified thermal zone. | + * | -#BPMP_EFAULT | For other BPMP-FW internal thermal zone driver errors. | */ struct cmd_thermal_get_temp_response { + /** @brief Current temperature in millicelsius. */ int32_t temp; } BPMP_ABI_PACKED; -/* - * Host->BPMP request data for request type CMD_THERMAL_SET_TRIP +/** + * @cond (!bpmp_safe && !bpmp_t264) * - * zone: Number of thermal zone. - * low: Temperature of lower trip point in millicelsius - * high: Temperature of upper trip point in millicelsius - * enabled: 1 to enable trip point, 0 to disable trip point + * Host->BPMP request payload for the #CMD_THERMAL_SET_TRIP sub-command. */ struct cmd_thermal_set_trip_request { + /** @brief Thermal zone identifier from @ref bpmp_thermal_ids. */ uint32_t zone; + /** @brief Temperature of lower trip point in millicelsius */ int32_t low; + /** @brief Temperature of upper trip point in millicelsius */ int32_t high; + /** 1 to enable trip point, 0 to disable trip point */ uint32_t enabled; } BPMP_ABI_PACKED; -/* - * BPMP->Host request data for request type CMD_THERMAL_HOST_TRIP_REACHED - * - * zone: Number of thermal zone where trip point was reached. +/** + * BPMP->Host request payload for the #CMD_THERMAL_HOST_TRIP_REACHED sub-command. */ struct cmd_thermal_host_trip_reached_request { + /** + * @brief ID of the thermal zone where trip point was reached, + * from @ref bpmp_thermal_ids. + */ uint32_t zone; } BPMP_ABI_PACKED; +/** @endcond */ -/* - * BPMP->Host reply data for request type CMD_THERMAL_GET_NUM_ZONES - * - * num: Number of supported thermal zones. The thermal zones are indexed - * starting from zero. +/** + * BPMP->Host response payload for the #CMD_THERMAL_GET_NUM_ZONES sub-command. */ struct cmd_thermal_get_num_zones_response { + /** + * @brief Number of supported thermal zones. + * + * The thermal zones are indexed starting from zero. + */ uint32_t num; } BPMP_ABI_PACKED; -/* - * Host->BPMP request data for request type CMD_THERMAL_GET_THERMTRIP - * - * zone: Number of thermal zone. +/** + * Host->BPMP request payload for the #CMD_THERMAL_GET_THERMTRIP sub-command. */ struct cmd_thermal_get_thermtrip_request { + /** @brief Thermal zone identifier from @ref bpmp_thermal_ids. */ uint32_t zone; } BPMP_ABI_PACKED; -/* - * BPMP->Host reply data for request CMD_THERMAL_GET_THERMTRIP - * - * thermtrip: HW shutdown temperature in millicelsius. +/** + * BPMP->Host response payload for the #CMD_THERMAL_GET_THERMTRIP sub-command. */ struct cmd_thermal_get_thermtrip_response { + /** @brief HW shutdown temperature in millicelsius. */ int32_t thermtrip; } BPMP_ABI_PACKED; -/* - * Host->BPMP request data. +/** + * Host->BPMP #MRQ_THERMAL request payload. * - * Reply type is union mrq_thermal_bpmp_to_host_response. - * - * type: Type of request. Values listed in enum mrq_thermal_type. - * data: Request type specific parameters. + * Response payload type is #mrq_thermal_bpmp_to_host_response. */ struct mrq_thermal_host_to_bpmp_request { + /** + * Request sub-command identifier from @ref mrq_thermal_host_to_bpmp_cmd. + */ uint32_t type; + union { struct cmd_thermal_query_abi_request query_abi; struct cmd_thermal_get_temp_request get_temp; @@ -1876,21 +2367,22 @@ struct mrq_thermal_host_to_bpmp_request { } BPMP_UNION_ANON; } BPMP_ABI_PACKED; -/* - * BPMP->Host request data. - * - * type: Type of request. Values listed in enum mrq_thermal_type. - * data: Request type specific parameters. +/** + * @brief Request payload for the BPMP->Host #MRQ_THERMAL command. */ struct mrq_thermal_bpmp_to_host_request { + /** + * Request sub-command identifier from @ref mrq_thermal_bpmp_to_host_cmd. + */ uint32_t type; + union { struct cmd_thermal_host_trip_reached_request host_trip_reached; } BPMP_UNION_ANON; } BPMP_ABI_PACKED; -/* - * Data in reply to a Host->BPMP request. +/** + * @brief Response payload for the Host->BPMP #MRQ_THERMAL command. */ union mrq_thermal_bpmp_to_host_response { struct cmd_thermal_get_temp_response get_temp; @@ -1900,13 +2392,11 @@ union mrq_thermal_bpmp_to_host_response { /** @} Thermal */ -/** +/** @cond (!bpmp_safe && (bpmp_t234 || bpmp_t238 || bpmp_t264)) * @ingroup MRQ_Codes * @def MRQ_OC_STATUS - * @brief Query over current status + * @brief Query overcurrent status * - * * Platforms: T234 - * @cond bpmp_t234 * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: N/A @@ -1916,33 +2406,224 @@ union mrq_thermal_bpmp_to_host_response { * @{ */ +/** + * @brief Size of the mrq_oc_status_response::throt_en and + * mrq_oc_status_response::event_cnt -arrays. + */ #define OC_STATUS_MAX_SIZE 24U -/* - * @brief Response to #MRQ_OC_STATUS - * - * throt_en: Value for each OC alarm where zero signifies throttle is - * disabled, and non-zero throttle is enabled. - * event_cnt: Total number of OC events for each OC alarm. +/** + * @brief Response payload for the #MRQ_OC_STATUS -command. * * mrq_response::err is 0 if the operation was successful and * -#BPMP_ENODEV otherwise. */ struct mrq_oc_status_response { + /** + * @brief Value for each overcurrent alarm where zero signifies + * throttle is disabled, and non-zero throttle is enabled. + */ uint8_t throt_en[OC_STATUS_MAX_SIZE]; + + /** + * @brief Total number of overcurrent events for each overcurrent alarm. + */ uint32_t event_cnt[OC_STATUS_MAX_SIZE]; } BPMP_ABI_PACKED; /** @} OC_status */ -/** @endcond bpmp_t234 */ +/** @endcond */ + +/** @cond (bpmp_th500 || bpmp_tb500 || bpmp_t238) + * @ingroup MRQ_Codes + * @def MRQ_THROTTLE + * @brief Overcurrent throttling + * + * * Initiators: CCPLEX + * * Targets: BPMP + * * Request Payload: @ref mrq_throttle_request + * * Response Payload: @ref mrq_throttle_response + * @addtogroup Throttle + * @{ + */ +enum mrq_throttle_cmd { + /** + * @brief Check whether the BPMP-FW supports the specified + * #MRQ_THROTTLE sub-command. + * + * mrq_response::err is 0 if the specified request is + * supported and -#BPMP_ENODEV otherwise. + */ + CMD_THROTTLE_QUERY_ABI = 0, + + /** + * @cond (bpmp_th500 || bpmp_tb500) + * @brief query chipthrot status + * + * mrq_response:err is defined as: + * + * | Value | Description | + * |----------------|--------------------------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENODEV | CMD_THROTTLE_GET_CHIPTHROT_STATUS is not supported by BPMP-FW| + */ + CMD_THROTTLE_GET_CHIPTHROT_STATUS = 1, + /** @endcond */ + + /** + * @cond bpmp_t238 + * @brief program OC throttle configuration + * + * mrq_response:err is defined as: + * + * | Value | Description | + * |----------------|--------------------------------------------------------------| + * | 0 | Success | + * | -#BPMP_EINVAL | ID out of range or alarm for this ID not enabled at boot | + * | -#BPMP_ENODEV | CMD_THROTTLE_SET_OC_CONFIG is not supported by BPMP-FW | + */ + CMD_THROTTLE_SET_OC_CONFIG = 2, + /** @endcond */ +}; /** + * @brief Request payload for #MRQ_THROTTLE sub-command #CMD_THROTTLE_QUERY_ABI + */ +struct cmd_throttle_query_abi_request { + uint32_t cmd; /**< @ref mrq_throttle_cmd */ +} BPMP_ABI_PACKED; + +/** + * @cond bpmp_th500 + * @brief Response payload for #MRQ_THROTTLE sub-command + * #CMD_THROTTLE_GET_CHIPTHROT_STATUS + * + * Bit-mask of all h/w throttling actions that have been engaged since + * last invocation of this command + * Bit 0...11 : HW throttling status of the thermal zones. + * Bit 12...23 : Reserved for future thermal zone events. + * Bit 24...25 : HW throttling status of the Over current Alarms OC1 & OC2. + * Bit 26...31 : Reserved for future Over current alarm events. + * Bit 32...63 : Reserved for future use. + * @endcond + * @cond bpmp_tb500 + * @brief Response payload for #MRQ_THROTTLE sub-command + * #CMD_THROTTLE_GET_CHIPTHROT_STATUS + * + * Bit-mask of all h/w throttling actions that have been engaged since + * last invocation of this command + * Bit 0 : HW throttling status of the TB500C_TJ_MAX thermal zone. + * Bit 1...63 : Reserved for future use. + * @endcond + * @cond (bpmp_th500 || bpmp_tb500) + */ +struct cmd_throttle_get_chipthrot_status_response { + uint64_t status; +} BPMP_ABI_PACKED; +/** @endcond */ + +/** + * @cond bpmp_t238 + * @brief Request payload for #MRQ_THROTTLE sub-command + * #CMD_THROTTLE_SET_OC_CONFIG + * + * Only alarms that have been configured as enabled in BPMP-DTB at boot can + * be reconfigured with this MRQ. + */ +struct cmd_throttle_set_oc_config_request { + /** @brief valid OC alarm ID from @ref bpmp_soctherm_edp_oc_ids */ + uint32_t id; + /** @brief Throttling enable/disable + * + * Set to 1 to enable throttling, or 0 to disable. Other values are + * disallowed. + */ + uint8_t en_throttle; +} BPMP_ABI_PACKED; +/** @endcond */ + +/** + * @brief Request payload for the #MRQ_THROTTLE -command + * + * | Sub-command | Request payload | + * |------------------------------------|----------------------------------| + * | #CMD_THROTTLE_QUERY_ABI | #cmd_throttle_query_abi_request | + * + * @cond bpmp_th500 + * The following additional sub-commands are supported on TH500 platforms: + * | Sub-command | Request payload | + * |------------------------------------|----------------------------------| + * | #CMD_THROTTLE_GET_CHIPTHROT_STATUS | - | + * @endcond + * + * @cond bpmp_tb500 + * The following additional sub-commands are supported on TB500 platforms: + * | Sub-command | Request payload | + * |------------------------------------|----------------------------------| + * | #CMD_THROTTLE_GET_CHIPTHROT_STATUS | - | + * @endcond + * + * @cond bpmp_t238 + * The following additional sub-commands are supported on T238 platforms: + * | Sub-command | Request payload | + * |------------------------------------|-------------------------------------| + * | #CMD_THROTTLE_SET_OC_CONFIG | #cmd_throttle_set_oc_config_request | + * @endcond + */ +struct mrq_throttle_request { + uint32_t cmd; + union { + struct cmd_throttle_query_abi_request throttle_query_abi_req; + /** @cond bpmp_t238 */ + struct cmd_throttle_set_oc_config_request throttle_set_oc_config_req; + /** @endcond */ + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** + * @brief Response payload for the #MRQ_THROTTLE -command. + * + * | Sub-command | Response payload | + * |------------------------------------|--------------------------------------------| + * | #CMD_THROTTLE_QUERY_ABI | - | + * + * @cond bpmp_th500 + * The following additional sub-commands are supported on TH500 platforms: + * | Sub-command | Response payload | + * |------------------------------------|--------------------------------------------| + * | #CMD_THROTTLE_GET_CHIPTHROT_STATUS | #cmd_throttle_get_chipthrot_status_response| + * @endcond + * + * @cond bpmp_tb500 + * The following additional sub-commands are supported on TB500 platforms: + * | Sub-command | Response payload | + * |------------------------------------|--------------------------------------------| + * | #CMD_THROTTLE_GET_CHIPTHROT_STATUS | #cmd_throttle_get_chipthrot_status_response| + * @endcond + * + * @cond bpmp_t238 + * The following additional sub-commands are supported on T238 platforms: + * | Sub-command | Response payload | + * |------------------------------------|--------------------------------------------| + * | #CMD_THROTTLE_SET_OC_CONFIG | - | + * @endcond + */ +struct mrq_throttle_response { + union { + /** @cond (bpmp_th500 || bpmp_tb500) */ + struct cmd_throttle_get_chipthrot_status_response throttle_get_chipthrot_status_resp; + /** @endcond */ + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; +/** @} Throttle */ +/** @endcond */ + + +/** @cond bpmp_t186 * @ingroup MRQ_Codes * @def MRQ_CPU_VHINT * @brief Query CPU voltage hint data * - * * Platforms: T186 - * @cond bpmp_t186 * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_cpu_vhint_request @@ -1995,14 +2676,13 @@ struct cpu_vhint_data { } BPMP_ABI_PACKED; /** @} Vhint */ -/** @endcond bpmp_t186 */ +/** @endcond */ /** * @ingroup MRQ_Codes * @def MRQ_ABI_RATCHET * @brief ABI ratchet value query * - * * Platforms: T186, T194 * * Initiators: Any * * Targets: BPMP * * Request Payload: @ref mrq_abi_ratchet_request @@ -2014,7 +2694,7 @@ struct cpu_vhint_data { /** * @brief An ABI compatibility mechanism * - * BPMP_ABI_RATCHET_VALUE may increase for various reasons in a future + * #BPMP_ABI_RATCHET_VALUE may increase for various reasons in a future * revision of this header file. * 1. That future revision deprecates some MRQ * 2. That future revision introduces a breaking change to an existing @@ -2051,11 +2731,11 @@ struct mrq_abi_ratchet_request { * * If #ratchet is less than the requester's #BPMP_ABI_RATCHET_VALUE, * the requster must either interoperate with BPMP according to an ABI - * header version with BPMP_ABI_RATCHET_VALUE = ratchet or cease + * header version with #BPMP_ABI_RATCHET_VALUE = ratchet or cease * communication with BPMP. * * If mrq_response::err is 0 and ratchet is greater than or equal to the - * requester's BPMP_ABI_RATCHET_VALUE, the requester should continue + * requester's #BPMP_ABI_RATCHET_VALUE, the requester should continue * normal operation. */ struct mrq_abi_ratchet_response { @@ -2070,7 +2750,9 @@ struct mrq_abi_ratchet_response { * @def MRQ_EMC_DVFS_LATENCY * @brief Query frequency dependent EMC DVFS latency * - * * Platforms: T186, T194, T234 + * On T264 and onwards, this MRQ service is available only when + * BPMP-FW has valid DRAM timing table passed by earlier boot stages. + * * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: N/A @@ -2094,7 +2776,11 @@ struct emc_dvfs_latency { * @brief Response to #MRQ_EMC_DVFS_LATENCY */ struct mrq_emc_dvfs_latency_response { - /** @brief The number valid entries in #pairs */ + /** + * @brief The number valid entries in #pairs + * + * Valid range is [0, #EMC_DVFS_LATENCY_MAX_SIZE] + */ uint32_t num_pairs; /** @brief EMC DVFS node information */ struct emc_dvfs_latency pairs[EMC_DVFS_LATENCY_MAX_SIZE]; @@ -2102,13 +2788,11 @@ struct mrq_emc_dvfs_latency_response { /** @} EMC */ -/** +/** @cond (bpmp_t234) * @ingroup MRQ_Codes * @def MRQ_EMC_DVFS_EMCHUB * @brief Query EMC HUB frequencies * - * * Platforms: T234 onwards - * @cond (bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: N/A @@ -2139,15 +2823,13 @@ struct mrq_emc_dvfs_emchub_response { } BPMP_ABI_PACKED; /** @} EMC */ -/** @endcond (bpmp_t234 || bpmp_t238 || bpmp_th500) */ +/** @endcond */ -/** +/** @cond (bpmp_t234) * @ingroup MRQ_Codes * @def MRQ_EMC_DISP_RFL * @brief Set EMC display RFL handshake mode of operations * - * * Platforms: T234 onwards - * @cond (bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_emc_disp_rfl_request @@ -2157,6 +2839,9 @@ struct mrq_emc_dvfs_emchub_response { * @{ */ +/** + * @brief Allowed mode values for the mrq_emc_disp_rfl_request::mode -field. + */ enum mrq_emc_disp_rfl_mode { /** @brief EMC display RFL handshake disabled */ EMC_DISP_RFL_MODE_DISABLED = 0, @@ -2171,65 +2856,75 @@ enum mrq_emc_disp_rfl_mode { * Used by the sender of an #MRQ_EMC_DISP_RFL message to * request the mode of EMC display RFL handshake. * - * mrq_response::err is - * * 0: RFL mode is set successfully - * * -#BPMP_EINVAL: invalid mode requested - * * -#BPMP_ENOSYS: RFL handshake is not supported - * * -#BPMP_EACCES: Permission denied - * * -#BPMP_ENODEV: if disp rfl mrq is not supported by BPMP-FW + * mrq_response::err for this request is defined as: + * + * | Value | Description | + * | -------------- | --------------------------------------------- | + * | 0 | RFL mode is set successfully. | + * | -#BPMP_EINVAL | Invalid mode requested. | + * | -#BPMP_ENOSYS | RFL handshake is not supported. | + * | -#BPMP_EACCES | Permission denied. | + * | -#BPMP_ENODEV | if disp rfl mrq is not supported by BPMP-FW. | */ struct mrq_emc_disp_rfl_request { - /** @brief EMC display RFL mode (@ref mrq_emc_disp_rfl_mode) */ + /** @brief EMC display RFL mode from @ref mrq_emc_disp_rfl_mode */ uint32_t mode; } BPMP_ABI_PACKED; /** @} EMC */ -/** @endcond (bpmp_t234 || bpmp_t238 || bpmp_th500) */ +/** @endcond */ -/** +/** @cond (!bpmp_safe && (bpmp_t234 || bpmp_t238)) * @ingroup MRQ_Codes * @def MRQ_BWMGR - * @brief bwmgr requests + * @brief Bandwidth manager (BWMGR) commands * - * * Platforms: T234 onwards - * @cond (bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_bwmgr_request * * Response Payload: @ref mrq_bwmgr_response * * @addtogroup BWMGR - * * @{ */ +/** + * @brief Sub-command identifiers for #MRQ_BWMGR + */ enum mrq_bwmgr_cmd { /** - * @brief Check whether the BPMP driver supports the specified - * request type + * @brief Check whether BPMP-FW supports the specified + * #MRQ_BWMGR sub-command. * - * mrq_response::err is 0 if the specified request is - * supported and -#BPMP_ENODEV otherwise. + * mrq_response::err is defined to be: + * + * | Value | Description + * |----------------|---------------------------- + * | 0 | Specified sub-command is supported. + * | -#BPMP_ENODEV | Specified sub-command is not supported. */ CMD_BWMGR_QUERY_ABI = 0, /** - * @brief Determine dram rate to satisfy iso/niso bw requests + * @brief Determine DRAM rate to satisfy ISO/NISO bandwidth requests * - * mrq_response::err is - * * 0: calc_rate succeeded. - * * -#BPMP_EINVAL: Invalid request parameters. - * * -#BPMP_ENOTSUP: Requested bw is not available. + * mrq_response::err is defined to be: + * + * | Value | Description + * |----------------|---------------------------- + * | 0 | Rate calculation succeeded. + * | -#BPMP_EINVAL | Invalid request parameters. + * | -#BPMP_ENOTSUP | Requested bandwidth is not available. + * | <0 | Any other internal error. */ CMD_BWMGR_CALC_RATE = 1 }; -/* - * request data for request type CMD_BWMGR_QUERY_ABI - * - * type: Request type for which to check existence. +/** + * @brief Request payload for #MRQ_BWMGR sub-command #CMD_BWMGR_QUERY_ABI */ struct cmd_bwmgr_query_abi_request { + /** @brief Sub-command identifier from @ref mrq_bwmgr_cmd. */ uint32_t type; } BPMP_ABI_PACKED; @@ -2237,47 +2932,56 @@ struct cmd_bwmgr_query_abi_request { * @brief Used by @ref cmd_bwmgr_calc_rate_request */ struct iso_req { - /* @brief bwmgr client ID @ref bpmp_bwmgr_ids */ + /** @brief BWMGR client ID from @ref bpmp_bwmgr_ids */ uint32_t id; - /* @brief bw in kBps requested by client */ + /** @brief Bandwidth in kBps requested by client */ uint32_t iso_bw; } BPMP_ABI_PACKED; +/** + * @brief Size of the cmd_bwmgr_calc_rate_request::isobw_reqs -array. + */ #define MAX_ISO_CLIENTS 13U -/* - * request data for request type CMD_BWMGR_CALC_RATE + +/** + * @brief Request payload for #MRQ_BWMGR sub-command #CMD_BWMGR_CALC_RATE */ struct cmd_bwmgr_calc_rate_request { - /* @brief total bw in kBps requested by all niso clients */ + /** @brief Total bandwidth in kBps requested by all NISO clients. */ uint32_t sum_niso_bw; - /* @brief The number of iso clients */ + /** @brief The number of ISO client requests in #isobw_reqs -array */ uint32_t num_iso_clients; - /* @brief iso_req information */ + /** @brief iso_req information */ struct iso_req isobw_reqs[MAX_ISO_CLIENTS]; } BPMP_ABI_PACKED; -/* - * response data for request type CMD_BWMGR_CALC_RATE - * - * iso_rate_min: min dram data clk rate in kHz to satisfy all iso bw reqs - * total_rate_min: min dram data clk rate in kHz to satisfy all bw reqs +/** + * @brief Response payload for #MRQ_BWMGR sub-command #CMD_BWMGR_CALC_RATE */ struct cmd_bwmgr_calc_rate_response { + /** + * @brief Minimum DRAM data clock rate in kHz to satisfy all ISO client + * bandwidth requests. + */ uint32_t iso_rate_min; + + /** + * @brief Minimum DRAM data clock rate in kHz to satisfy all + * bandwidth requests. + */ uint32_t total_rate_min; } BPMP_ABI_PACKED; -/* - * @brief Request with #MRQ_BWMGR - * - * - * |sub-command |payload | - * |----------------------------|------------------------------| - * |CMD_BWMGR_QUERY_ABI | cmd_bwmgr_query_abi_request | - * |CMD_BWMGR_CALC_RATE | cmd_bwmgr_calc_rate_request | +/** + * @brief Request payload for the #MRQ_BWMGR -command. * + * |Sub-command |Payload | + * |----------------------|-----------------------------| + * |#CMD_BWMGR_QUERY_ABI |#cmd_bwmgr_query_abi_request | + * |#CMD_BWMGR_CALC_RATE |#cmd_bwmgr_calc_rate_request | */ struct mrq_bwmgr_request { + /** @brief Sub-command identifier from @ref mrq_bwmgr_cmd. */ uint32_t cmd; union { struct cmd_bwmgr_query_abi_request query_abi; @@ -2285,12 +2989,12 @@ struct mrq_bwmgr_request { } BPMP_UNION_ANON; } BPMP_ABI_PACKED; -/* - * @brief Response to MRQ_BWMGR +/** + * @brief Response payload for the #MRQ_BWMGR -command. * - * |sub-command |payload | - * |----------------------------|------------------------------| - * |CMD_BWMGR_CALC_RATE | cmd_bwmgr_calc_rate_response | + * |Sub-command |Payload | + * |----------------------|------------------------------| + * |#CMD_BWMGR_CALC_RATE |#cmd_bwmgr_calc_rate_response | */ struct mrq_bwmgr_response { union { @@ -2299,15 +3003,13 @@ struct mrq_bwmgr_response { } BPMP_ABI_PACKED; /** @} BWMGR */ -/** @endcond (bpmp_t234 || bpmp_t238 || bpmp_th500) */ +/** @endcond */ -/** +/** @cond (!bpmp_safe && (bpmp_t234 || bpmp_t238 || bpmp_t264)) * @ingroup MRQ_Codes * @def MRQ_BWMGR_INT - * @brief bpmp-integrated bwmgr requests + * @brief BPMP-FW integrated BWMGR requests * - * * Platforms: T234 onwards - * @cond (bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_bwmgr_int_request @@ -2317,10 +3019,13 @@ struct mrq_bwmgr_response { * @{ */ +/** + * @brief Sub-command identifiers for #MRQ_BWMGR_INT + */ enum mrq_bwmgr_int_cmd { /** * @brief Check whether the BPMP-FW supports the specified - * request type + * sub-command. * * mrq_response::err is 0 if the specified request is * supported and -#BPMP_ENODEV otherwise. @@ -2328,36 +3033,64 @@ enum mrq_bwmgr_int_cmd { CMD_BWMGR_INT_QUERY_ABI = 1, /** - * @brief Determine and set dram rate to satisfy iso/niso bw request + * @brief Determine and set DRAM rate to satisfy ISO/NISO bandwidth requests. * - * mrq_response::err is - * * 0: request succeeded. - * * -#BPMP_EINVAL: Invalid request parameters. - * set_frequency in @ref cmd_bwmgr_int_calc_and_set_response - * will not be set. - * * -#BPMP_ENOTSUP: Requested bw is not available. - * set_frequency in @ref cmd_bwmgr_int_calc_and_set_response - * will be current dram-clk rate. + * mrq_response::err is defined as: + * + * |Value |Description | + * |-----------------|----------------------------------------------------------------------------------------------------------------| + * |0 |Request succeeded. | + * |-#BPMP_EINVAL |Invalid request parameters, cmd_bwmgr_int_calc_and_set_response::rate is not set. | + * |-#BPMP_ENOTSUP |Requested bandwidth is not available, cmd_bwmgr_int_calc_and_set_response::rate is the current DRAM clock rate. | + * |<0 |Any other internal error. | */ CMD_BWMGR_INT_CALC_AND_SET = 2, /** - * @brief Set a max DRAM frequency for the bandwidth-manager + * @brief Set a max DRAM frequency for the bandwidth manager. * - * mrq_response::err is - * * 0: request succeeded. - * * -#BPMP_ENOTSUP: Requested cap frequency is not possible. + * mrq_response::err is defined as: + * + * |Value |Description | + * |-----------------|------------------------------------------| + * |0 |Request succeeded. | + * |-#BPMP_ENOTSUP |Requested cap frequency is not possible. | + * |<0 |Any other internal error. | */ - CMD_BWMGR_INT_CAP_SET = 3 + CMD_BWMGR_INT_CAP_SET = 3, + + /** + * @brief Obtain the maximum amount of bandwidth currently allocatable + * to the requesting client. + * + * mrq_response::err is defined as: + * + * |Value |Description | + * |-----------------|------------------------------------------| + * |0 |Request succeeded. | + * |-#BPMP_EINVAL |Invalid request parameters. | + * |<0 |Any other internal error. | + */ + CMD_BWMGR_INT_CURR_AVAILABLE_BW = 4, + /** + * @brief Get the last request made by the client. + * + * mrq_response::err is defined as: + * + * |Value |Description | + * |-----------------|------------------------------------------| + * |0 |Request succeeded. | + * |-#BPMP_EINVAL |Invalid request parameters. | + * |<0 |Any other internal error. | + */ + CMD_BWMGR_INT_GET_LAST_REQUEST = 5, }; -/* - * request structure for request type CMD_BWMGR_QUERY_ABI - * - * type: Request type for which to check existence. +/** + * @brief Request payload for #MRQ_BWMGR_INT sub-command #CMD_BWMGR_INT_QUERY_ABI */ struct cmd_bwmgr_int_query_abi_request { - /* @brief request type determined by @ref mrq_bwmgr_int_cmd */ + /** @brief Sub-command identifier from @ref mrq_bwmgr_int_cmd. */ uint32_t type; } BPMP_ABI_PACKED; @@ -2373,87 +3106,168 @@ struct cmd_bwmgr_int_query_abi_request { /** @} bwmgr_int_unit_type */ -/* - * request data for request type CMD_BWMGR_INT_CALC_AND_SET +/** + * @brief Request payload for #MRQ_BWMGR_INT sub-command #CMD_BWMGR_INT_CALC_AND_SET */ struct cmd_bwmgr_int_calc_and_set_request { - /* @brief bwmgr client ID @ref bpmp_bwmgr_ids */ + /** @brief BWGMR client ID from @ref bpmp_bwmgr_ids */ uint32_t client_id; - /* @brief average niso bw usage in kBps requested by client. */ + /** @brief Average NISO bandwidth usage in kBps requested by client. */ uint32_t niso_bw; - /* - * @brief average iso bw usage in kBps requested by client. - * Value is ignored if client is niso. Determined by client_id. + /** + * @brief Average ISO bandwidth usage in kBps requested by client. + * + * Value is ignored if client is NISO as determined by #client_id. */ uint32_t iso_bw; - /* - * @brief memory clock floor requested by client. - * Unit determined by floor_unit. + /** + * @brief Memory clock floor requested by client, unit of the value + * is determined by #floor_unit -field. */ uint32_t mc_floor; - /* - * @brief toggle to determine the unit-type of floor value. - * See @ref bwmgr_int_unit_type definitions for unit-type mappings. + /** + * @brief Value set to determine the unit of the #mc_floor value: + * + * | Value | Unit | + * |-----------------------|----------------------| + * | #BWMGR_INT_UNIT_KBPS | Kilobytes per second | + * | #BWMGR_INT_UNIT_KHZ | Kilohertz | */ uint8_t floor_unit; } BPMP_ABI_PACKED; -struct cmd_bwmgr_int_cap_set_request { - /* @brief requested cap frequency in Hz. */ - uint64_t rate; -} BPMP_ABI_PACKED; - -/* - * response data for request type CMD_BWMGR_CALC_AND_SET +/** + * @brief Response payload for #MRQ_BWMGR_INT sub-command #CMD_BWMGR_INT_CALC_AND_SET */ struct cmd_bwmgr_int_calc_and_set_response { - /* @brief current set memory clock frequency in Hz */ + /** @brief Currently set memory clock frequency in Hz */ uint64_t rate; } BPMP_ABI_PACKED; -/* - * @brief Request with #MRQ_BWMGR_INT +/** + * @brief Request payload for #MRQ_BWMGR_INT sub-command #CMD_BWMGR_INT_CAP_SET + */ +struct cmd_bwmgr_int_cap_set_request { + /** @brief Requested cap frequency in Hz. */ + uint64_t rate; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for #MRQ_BWMGR_INT sub-command #CMD_BWMGR_INT_CURR_AVAILABLE_BW + */ +struct cmd_bwmgr_int_curr_available_bw_request { + /** @brief BWMGR client ID from @ref bpmp_bwmgr_ids */ + uint32_t id; +} BPMP_ABI_PACKED; + +/** + * @brief Response payload for #MRQ_BWMGR_INT sub-command #CMD_BWMGR_INT_CURR_AVAILABLE_BW + */ +struct cmd_bwmgr_int_curr_available_bw_response { + /** @brief Current cap frequency in KHz. */ + uint64_t cap_rate; + /** @brief Currently available bandwidth for the requesting client + * to allocate in KBps. + */ + uint64_t available_bw; +} BPMP_ABI_PACKED; + +struct cmd_bwmgr_int_get_last_request_request { + /** @brief BWMGR client ID from @ref bpmp_bwmgr_ids */ + uint32_t id; + /** + * @brief Value set to determine the unit of the returned mc_floor value: + * + * | Value | Unit | + * |-----------------------|----------------------| + * | #BWMGR_INT_UNIT_KBPS | Kilobytes per second | + * | #BWMGR_INT_UNIT_KHZ | Kilohertz | + */ + uint8_t floor_unit; +} BPMP_ABI_PACKED; + +struct cmd_bwmgr_int_get_last_request_response { + /** @brief BWGMR client ID from @ref bpmp_bwmgr_ids */ + uint32_t client_id; + /** @brief Average NISO bandwidth usage in kBps requested by client. */ + uint32_t niso_bw; + /** + * @brief Average ISO bandwidth usage in kBps requested by client. + */ + uint32_t iso_bw; + /** + * @brief Memory clock floor requested by client, unit of the value + * is determined by #floor_unit -field. + */ + uint32_t mc_floor; + /** + * @brief Value set to determine the unit of the #mc_floor value: + * + * | Value | Unit | + * |-----------------------|----------------------| + * | #BWMGR_INT_UNIT_KBPS | Kilobytes per second | + * | #BWMGR_INT_UNIT_KHZ | Kilohertz | + */ + uint8_t floor_unit; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for the #MRQ_BWMGR_INT -command. * + * |Sub-command |Payload | + * |---------------------------------|-----------------------------------------| + * |#CMD_BWMGR_INT_QUERY_ABI |#cmd_bwmgr_int_query_abi_request | + * |#CMD_BWMGR_INT_CALC_AND_SET |#cmd_bwmgr_int_calc_and_set_request | + * |#CMD_BWMGR_INT_CAP_SET |#cmd_bwmgr_int_cap_set_request | + * |#CMD_BWMGR_INT_GET_LAST_REQUEST |#cmd_bwmgr_int_get_last_request_request | * - * |sub-command |payload | - * |----------------------------|-----------------------------------| - * |CMD_BWMGR_INT_QUERY_ABI | cmd_bwmgr_int_query_abi_request | - * |CMD_BWMGR_INT_CALC_AND_SET | cmd_bwmgr_int_calc_and_set_request| - * |CMD_BWMGR_INT_CAP_SET | cmd_bwmgr_int_cap_set_request | + * The following additional sub-commands are supported on T264 platforms: * + * |Sub-command |Payload | + * |---------------------------------|-----------------------------------------| + * |#CMD_BWMGR_INT_CURR_AVAILABLE_BW |#cmd_bwmgr_int_curr_available_bw_request | */ struct mrq_bwmgr_int_request { + /** @brief Sub-command identifier from @ref mrq_bwmgr_int_cmd. */ uint32_t cmd; union { struct cmd_bwmgr_int_query_abi_request query_abi; struct cmd_bwmgr_int_calc_and_set_request bwmgr_calc_set_req; struct cmd_bwmgr_int_cap_set_request bwmgr_cap_set_req; + struct cmd_bwmgr_int_curr_available_bw_request bwmgr_curr_available_bw_req; + struct cmd_bwmgr_int_get_last_request_request bwmgr_get_last_request_req; } BPMP_UNION_ANON; } BPMP_ABI_PACKED; -/* - * @brief Response to MRQ_BWMGR_INT +/** + * @brief Response payload for the #MRQ_BWMGR_INT -command. * - * |sub-command |payload | - * |----------------------------|---------------------------------------| - * |CMD_BWMGR_INT_CALC_AND_SET | cmd_bwmgr_int_calc_and_set_response | + * |Sub-command |Payload | + * |---------------------------------|------------------------------------------| + * |#CMD_BWMGR_INT_CALC_AND_SET |#cmd_bwmgr_int_calc_and_set_response | + * |#CMD_BWMGR_INT_GET_LAST_REQUEST |#cmd_bwmgr_int_get_last_request_response | + * + * The following additional sub-commands are supported on T264 platforms: + * |Sub-command |Payload | + * |---------------------------------|------------------------------------------| + * |#CMD_BWMGR_INT_CURR_AVAILABLE_BW |#cmd_bwmgr_int_curr_available_bw_response | */ struct mrq_bwmgr_int_response { union { struct cmd_bwmgr_int_calc_and_set_response bwmgr_calc_set_resp; + struct cmd_bwmgr_int_curr_available_bw_response bwmgr_curr_available_bw_resp; + struct cmd_bwmgr_int_get_last_request_response bwmgr_get_last_request_resp; } BPMP_UNION_ANON; } BPMP_ABI_PACKED; /** @} BWMGR_INT */ -/** @endcond (bpmp_t234 || bpmp_t238 || bpmp_th500) */ +/** @endcond */ -/** +/** @cond (!bpmp_safe && (bpmp_t234 || bpmp_t238 || bpmp_t264)) * @ingroup MRQ_Codes * @def MRQ_ISO_CLIENT * @brief ISO client requests * - * * Platforms: T234 onwards - * @cond (bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_iso_client_request @@ -2463,148 +3277,178 @@ struct mrq_bwmgr_int_response { * @{ */ +/** + * @brief Sub-command identifiers for #MRQ_ISO_CLIENT. + */ enum mrq_iso_client_cmd { /** - * @brief Check whether the BPMP driver supports the specified - * request type + * @brief Check whether BPMP-FW supports a specified + * #MRQ_ISO_CLIENT sub-command. * * mrq_response::err is 0 if the specified request is * supported and -#BPMP_ENODEV otherwise. */ CMD_ISO_CLIENT_QUERY_ABI = 0, - /* - * @brief check for legal LA for the iso client. Without programming - * LA MC registers, calculate and ensure that legal LA is possible for - * iso bw requested by the ISO client. + /** + * @brief Determine legal LA for ISO client. * - * mrq_response::err is - * * 0: check la succeeded. - * * -#BPMP_EINVAL: Invalid request parameters. - * * -#BPMP_EFAULT: Legal LA is not possible for client requested iso_bw + * Without programming LA MC registers, calculate and ensure that + * a legal LA is possible for the ISO bandwidth requested by the + * ISO client. + * + * mrq_response::err for this sub-command is defined as: + * + * | Value | Description | + * |---------------|--------------------------------------------------------------| + * | 0 | Request successful and legal LA is possible. | + * | -#BPMP_EINVAL | Invalid request parameters. | + * | -#BPMP_EFAULT | Legal LA is not possible for client requested ISO bandwidth. | + * | <0 | Any other internal error. | */ CMD_ISO_CLIENT_CALCULATE_LA = 1, - /* - * @brief set LA for the iso client. Calculate and program the LA/PTSA - * MC registers corresponding to the client making bw request + /** + * @brief Set LA for ISO client. * - * mrq_response::err is - * * 0: set la succeeded. - * * -#BPMP_EINVAL: Invalid request parameters. - * * -#BPMP_EFAULT: Failed to calculate or program MC registers. + * Calculate and program the LA/PTSA MC registers corresponding to the + * ISO client making the bandwidth request. + * + * mrq_response::err for this sub-command is defined as: + * + * | Value | Description | + * |---------------|----------------------------------------------| + * | 0 | Setting LA succeeded. | + * | -#BPMP_EINVAL | Invalid request parameters. | + * | -#BPMP_EFAULT | Failed to calculate or program MC registers. | + * | <0 | Any other internal error. | */ CMD_ISO_CLIENT_SET_LA = 2, - /* - * @brief Get max possible bw for iso client + /** + * @brief Get maximum possible bandwidth for ISO client. * - * mrq_response::err is - * * 0: get_max_bw succeeded. - * * -#BPMP_EINVAL: Invalid request parameters. + * mrq_response::err for this sub-command is defined as: + * + * | Value | Description | + * |---------------|----------------------------------------------| + * | 0 | Operation successful. | + * | -#BPMP_EINVAL | Invalid request parameters. | + * | <0 | Any other internal error. | */ CMD_ISO_CLIENT_GET_MAX_BW = 3 }; -/* - * request data for request type CMD_ISO_CLIENT_QUERY_ABI - * - * type: Request type for which to check existence. +/** + * @brief Request payload for #MRQ_ISO_CLIENT sub-command #CMD_ISO_CLIENT_QUERY_ABI */ struct cmd_iso_client_query_abi_request { + /** + * @brief Sub-command identifier from @ref mrq_iso_client_cmd + * for which to check existence. + */ uint32_t type; } BPMP_ABI_PACKED; -/* - * request data for request type CMD_ISO_CLIENT_CALCULATE_LA - * - * id: client ID in @ref bpmp_bwmgr_ids - * bw: bw requested in kBps by client ID. - * init_bw_floor: initial dram_bw_floor in kBps passed by client ID. - * ISO client will perform mempool allocation and DVFS buffering based - * on this dram_bw_floor. +/** + * @brief Request payload #MRQ_ISO_CLIENT sub-command #CMD_ISO_CLIENT_CALCULATE_LA */ struct cmd_iso_client_calculate_la_request { + /** @brief BWMGR client ID from @ref bpmp_bwmgr_ids */ uint32_t id; + /** @brief Bandwidth requested in kBps for the client specified in #id. */ uint32_t bw; + /** + * @brief Initial DRAM bandwidth floor in kBps for the ISO client specified in #id. + * + * ISO client will perform mempool allocation and DVFS buffering based + * on this value. + */ uint32_t init_bw_floor; } BPMP_ABI_PACKED; -/* - * request data for request type CMD_ISO_CLIENT_SET_LA - * - * id: client ID in @ref bpmp_bwmgr_ids - * bw: bw requested in kBps by client ID. - * final_bw_floor: final dram_bw_floor in kBps. - * Sometimes the initial dram_bw_floor passed by ISO client may need to be - * updated by considering higher dram freq's. This is the final dram_bw_floor - * used to calculate and program MC registers. +/** + * @brief Response payload for #MRQ_ISO_CLIENT sub-command #CMD_ISO_CLIENT_CALCULATE_LA + */ +struct cmd_iso_client_calculate_la_response { + /** @brief Minimum DRAM rate in kHz at which a legal LA is possible */ + uint32_t la_rate_floor; + /** + * Minimum DRAM frequency in kHz required to satisfy this clients + * ISO bandwidth request, assuming all other ISO clients are inactive. + */ + uint32_t iso_client_only_rate; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for #MRQ_ISO_CLIENT sub-command #CMD_ISO_CLIENT_SET_LA */ struct cmd_iso_client_set_la_request { + /** @brief BMWGR client ID from @ref bpmp_bwmgr_ids */ uint32_t id; + /** @brief Bandwidth requested in kBps for the client specified in #id. */ uint32_t bw; + /** + * @brief Final DRAM bandwidth floor in kBps. + * + * Sometimes the initial cmd_iso_client_calculate_la_request::dram_bw_floor + * passed by ISO client may need to be updated by considering higher + * DRAM frequencies. This is the final DRAM bandwidth floor value used + * to calculate and program MC registers. + */ uint32_t final_bw_floor; } BPMP_ABI_PACKED; -/* - * request data for request type CMD_ISO_CLIENT_GET_MAX_BW - * - * id: client ID in @ref bpmp_bwmgr_ids +/** + * @brief Request payload for #MRQ_ISO_CLIENT sub-command #CMD_ISO_CLIENT_GET_MAX_BW */ struct cmd_iso_client_get_max_bw_request { + /** @brief BWMGR client ID from @ref bpmp_bwmgr_ids */ uint32_t id; } BPMP_ABI_PACKED; -/* - * response data for request type CMD_ISO_CLIENT_CALCULATE_LA - * - * la_rate_floor: minimum dram_rate_floor in kHz at which a legal la is possible - * iso_client_only_rate: Minimum dram freq in kHz required to satisfy this clients - * iso bw request, assuming all other iso clients are inactive - */ -struct cmd_iso_client_calculate_la_response { - uint32_t la_rate_floor; - uint32_t iso_client_only_rate; -} BPMP_ABI_PACKED; - /** * @brief Used by @ref cmd_iso_client_get_max_bw_response */ struct iso_max_bw { - /* @brief dram frequency in kHz */ + /** @brief dram frequency in kHz */ uint32_t freq; - /* @brief max possible iso-bw in kBps */ + /** @brief max possible iso-bw in kBps */ uint32_t iso_bw; } BPMP_ABI_PACKED; +/** + * @brief Size of the cmd_iso_client_get_max_bw_response::pairs -array. + */ #define ISO_MAX_BW_MAX_SIZE 14U -/* - * response data for request type CMD_ISO_CLIENT_GET_MAX_BW + +/** + * @brief Response payload for #MRQ_ISO_CLIENT sub-command #CMD_ISO_CLIENT_GET_MAX_BW */ struct cmd_iso_client_get_max_bw_response { - /* @brief The number valid entries in iso_max_bw pairs */ + /** @brief The number valid entries in iso_max_bw pairs */ uint32_t num_pairs; - /* @brief max ISOBW information */ + /** @brief max ISOBW information */ struct iso_max_bw pairs[ISO_MAX_BW_MAX_SIZE]; } BPMP_ABI_PACKED; /** - * @brief Request with #MRQ_ISO_CLIENT + * @brief Request payload for #MRQ_ISO_CLIENT command. * - * Used by the sender of an #MRQ_ISO_CLIENT message. - * - * |sub-command |payload | - * |------------------------------------ |----------------------------------------| - * |CMD_ISO_CLIENT_QUERY_ABI |cmd_iso_client_query_abi_request | - * |CMD_ISO_CLIENT_CALCULATE_LA |cmd_iso_client_calculate_la_request | - * |CMD_ISO_CLIENT_SET_LA |cmd_iso_client_set_la_request | - * |CMD_ISO_CLIENT_GET_MAX_BW |cmd_iso_client_get_max_bw_request | + * Each #MRQ_ISO_CLIENT -command is expected to include a sub-command specific + * payload as defined in table below: * + * |Sub-command |Request payload | + * |-----------------------------|--------------------------------------| + * |#CMD_ISO_CLIENT_QUERY_ABI |#cmd_iso_client_query_abi_request | + * |#CMD_ISO_CLIENT_CALCULATE_LA |#cmd_iso_client_calculate_la_request | + * |#CMD_ISO_CLIENT_SET_LA |#cmd_iso_client_set_la_request | + * |#CMD_ISO_CLIENT_GET_MAX_BW |#cmd_iso_client_get_max_bw_request | */ - struct mrq_iso_client_request { - /* Type of request. Values listed in enum mrq_iso_client_cmd */ + /** @brief Sub-command identifier from @ref mrq_iso_client_cmd. */ uint32_t cmd; + union { struct cmd_iso_client_query_abi_request query_abi; struct cmd_iso_client_calculate_la_request calculate_la_req; @@ -2614,20 +3458,20 @@ struct mrq_iso_client_request { } BPMP_ABI_PACKED; /** - * @brief Response to MRQ_ISO_CLIENT + * @brief Response payload for #MRQ_ISO_CLIENT command. * - * Each sub-command supported by @ref mrq_iso_client_request may return - * sub-command-specific data. Some do and some do not as indicated in - * the following table + * Some of the sub-commands supported by #MRQ_ISO_CLIENT may return + * a sub-command -specific payload in the MRQ response as defined in table + * below: * - * |sub-command |payload | - * |---------------------------- |------------------------------------| - * |CMD_ISO_CLIENT_CALCULATE_LA |cmd_iso_client_calculate_la_response| - * |CMD_ISO_CLIENT_SET_LA |N/A | - * |CMD_ISO_CLIENT_GET_MAX_BW |cmd_iso_client_get_max_bw_response | + * |Sub-command |Response payload | + * |---------------------------- |--------------------------------------| + * |#CMD_ISO_CLIENT_QUERY_ABI |- | + * |#CMD_ISO_CLIENT_CALCULATE_LA |#cmd_iso_client_calculate_la_response | + * |#CMD_ISO_CLIENT_SET_LA |- | + * |#CMD_ISO_CLIENT_GET_MAX_BW |#cmd_iso_client_get_max_bw_response | * */ - struct mrq_iso_client_response { union { struct cmd_iso_client_calculate_la_response calculate_la_resp; @@ -2636,15 +3480,13 @@ struct mrq_iso_client_response { } BPMP_ABI_PACKED; /** @} ISO_CLIENT */ -/** @endcond (bpmp_t234 || bpmp_t238 || bpmp_th500) */ +/** @endcond */ -/** +/** @cond (!bpmp_t186) * @ingroup MRQ_Codes * @def MRQ_CPU_NDIV_LIMITS - * @brief CPU freq. limits in ndiv + * @brief Return CPU cluster NDIV limits * - * * Platforms: T194 onwards - * @cond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_cpu_ndiv_limits_request @@ -2654,10 +3496,10 @@ struct mrq_iso_client_response { */ /** - * @brief Request for ndiv limits of a cluster + * @brief Request payload for the #MRQ_CPU_NDIV_LIMITS -command */ struct mrq_cpu_ndiv_limits_request { - /** @brief Enum cluster_id */ + /** @brief Logical CPU cluster identifier */ uint32_t cluster_id; } BPMP_ABI_PACKED; @@ -2678,15 +3520,14 @@ struct mrq_cpu_ndiv_limits_response { } BPMP_ABI_PACKED; /** @} CPU */ -/** @endcond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) */ +/** @endcond */ -/** + +/** @cond (bpmp_t194) * @ingroup MRQ_Codes * @def MRQ_CPU_AUTO_CC3 * @brief Query CPU cluster auto-CC3 configuration * - * * Platforms: T194 - * @cond bpmp_t194 * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_cpu_auto_cc3_request @@ -2702,15 +3543,15 @@ struct mrq_cpu_ndiv_limits_response { */ /** - * @brief Request for auto-CC3 configuration of a cluster + * @brief Request payload for the #MRQ_CPU_AUTO_CC3 -command */ struct mrq_cpu_auto_cc3_request { - /** @brief Enum cluster_id (logical cluster id, known to CCPLEX s/w) */ + /** @brief Logical CPU cluster ID */ uint32_t cluster_id; } BPMP_ABI_PACKED; /** - * @brief Response to #MRQ_CPU_AUTO_CC3 + * @brief Response payload for the #MRQ_CPU_AUTO_CC3 -command */ struct mrq_cpu_auto_cc3_response { /** @@ -2724,9 +3565,9 @@ struct mrq_cpu_auto_cc3_response { } BPMP_ABI_PACKED; /** @} CC3 */ -/** @endcond bpmp_t194 */ +/** @endcond */ -/** +/** @cond (bpmp_t186 || bpmp_t194 || bpmp_t234) * @ingroup MRQ_Codes * @def MRQ_RINGBUF_CONSOLE * @brief A ring buffer debug console for BPMP @@ -2811,7 +3652,9 @@ struct cmd_ringbuf_console_query_abi_resp { */ struct cmd_ringbuf_console_read_req { /** - * @brief Number of bytes requested to be read from the BPMP TX buffer + * @brief Number of bytes requested to be read from the BPMP TX buffer. + * + * Valid range is [0, #MRQ_RINGBUF_CONSOLE_MAX_READ_LEN] */ uint8_t len; } BPMP_ABI_PACKED; @@ -2823,7 +3666,11 @@ struct cmd_ringbuf_console_read_req { struct cmd_ringbuf_console_read_resp { /** @brief The actual data read from the BPMP TX buffer */ uint8_t data[MRQ_RINGBUF_CONSOLE_MAX_READ_LEN]; - /** @brief Number of bytes in cmd_ringbuf_console_read_resp::data */ + /** + * @brief Number of bytes in cmd_ringbuf_console_read_resp::data + * + * Valid range is [0, #MRQ_RINGBUF_CONSOLE_MAX_WRITE_LEN] + */ uint8_t len; } BPMP_ABI_PACKED; @@ -2904,14 +3751,13 @@ union mrq_ringbuf_console_bpmp_to_host_response { } BPMP_ABI_PACKED; /** @} RingbufConsole */ +/** @endcond */ -/** +/** @cond (!bpmp_t186 && !(bpmp_safe && bpmp_t234)) * @ingroup MRQ_Codes * @def MRQ_STRAP * @brief Set a strap value controlled by BPMP * - * * Platforms: T194 onwards - * @cond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_strap_request @@ -2925,10 +3771,14 @@ union mrq_ringbuf_console_bpmp_to_host_response { * deasserted. * * BPMP owns registers which act as straps to various units. It - * exposes limited control of those straps via #MRQ_STRAP. + * exposes limited control of those registers via #MRQ_STRAP. * * @{ */ + +/** + * @brief Sub-command identifiers for the #MRQ_STRAP -command. + */ enum mrq_strap_cmd { /** @private */ STRAP_RESERVED = 0, @@ -2937,27 +3787,31 @@ enum mrq_strap_cmd { }; /** - * @brief Request with #MRQ_STRAP + * @brief Request payload for the #MRQ_STRAP -command. */ struct mrq_strap_request { - /** @brief @ref mrq_strap_cmd */ + /** @brief Sub-command identifier from @ref mrq_strap_cmd */ uint32_t cmd; - /** @brief Strap ID from @ref Strap_Identifiers */ + /** + * @if (bpmp_t234 || bpmp_th500 || bpmp_t264) + * @brief Strap ID from @ref bpmp_strap_ids + * @else + * @brief Strap ID (undefined) + * @endif + */ uint32_t id; - /** @brief Desired value for strap (if cmd is #STRAP_SET) */ + /** @brief Desired value for strap (if #cmd is #STRAP_SET) */ uint32_t value; } BPMP_ABI_PACKED; /** @} Strap */ -/** @endcond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) */ +/** @endcond */ -/** +/** @cond (bpmp_t194 || bpmp_t234 || bpmp_th500) * @ingroup MRQ_Codes * @def MRQ_UPHY * @brief Perform a UPHY operation * - * * Platforms: T194 onwards - * @cond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_uphy_request @@ -2966,52 +3820,124 @@ struct mrq_strap_request { * @addtogroup UPHY * @{ */ -enum { + +/** + * @brief Sub-command identifiers for #MRQ_UPHY. + */ +enum mrq_uphy_cmd { + /** @brief Trigger PCIE lane margining procedure. */ CMD_UPHY_PCIE_LANE_MARGIN_CONTROL = 1, + /** @brief Return PCIE lane margining status. */ CMD_UPHY_PCIE_LANE_MARGIN_STATUS = 2, + /** @brief Initialize PCIE EP PLL controller. */ CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT = 3, + /** @brief Set state of the PCIE RP/EP controller. */ CMD_UPHY_PCIE_CONTROLLER_STATE = 4, + /** @brief Disable PCIE EP PLL controller. */ CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF = 5, + + /** + * @cond bpmp_t238 + * @brief Initialize and enable UPHY display port. + */ CMD_UPHY_DISPLAY_PORT_INIT = 6, + /** @brief Disable UPHY display port. */ CMD_UPHY_DISPLAY_PORT_OFF = 7, + /** @brief Trigger sequence to restore XUSB DYN lanes during SC7 exit. */ CMD_UPHY_XUSB_DYN_LANES_RESTORE = 8, + /** @endcond */ + + /** + * @cond bpmp_th500 + * @brief Perform UPHY Lane EOM scan. + */ + CMD_UPHY_LANE_EOM_SCAN = 9, + /** @brief Config PCIe VDM with a given BDF ID. */ + CMD_UPHY_PCIE_CONFIG_VDM = 10, + /** @endcond */ + CMD_UPHY_MAX, }; +/** + * @brief Request payload for #MRQ_UPHY sub-command #CMD_UPHY_PCIE_LANE_MARGIN_CONTROL. + */ struct cmd_uphy_margin_control_request { - /** @brief Enable margin */ + /** + * @brief Enable margin. + * + * Valid values: + * * Value 0 disables margin, + * * Value 1 enables margin. + */ int32_t en; - /** @brief Clear the number of error and sections */ + /** + * @brief Clear the number of error and sections. + * + * Valid values: + * + * * Value 0: Skip clear, + * * Value 1: Perform clear. + */ int32_t clr; - /** @brief Set x offset (1's complement) for left/right margin type (y should be 0) */ + /** + * @brief Set x offset (1's complement) for left/right margin type (y should be 0). + * + * Valid range is [0, 127] + */ uint32_t x; - /** @brief Set y offset (1's complement) for left/right margin type (x should be 0) */ + /** + * @brief Set y offset (1's complement) for left/right margin type (x should be 0) + * + * Valid range is [0, 63] + */ uint32_t y; - /** @brief Set number of bit blocks for each margin section */ + /** + * @brief Set number of bit blocks for each margin section. + * + * Valid range is [0, 15] + */ uint32_t nblks; } BPMP_ABI_PACKED; +/** + * @brief Response payload for #MRQ_UPHY sub-command #CMD_UPHY_PCIE_LANE_MARGIN_STATUS. + */ struct cmd_uphy_margin_status_response { /** @brief Number of errors observed */ uint32_t status; } BPMP_ABI_PACKED; +/** + * @brief Request payload for #MRQ_UPHY sub-command #CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT. + */ struct cmd_uphy_ep_controller_pll_init_request { /** @brief EP controller number, T194 valid: 0, 4, 5; T234 valid: 5, 6, 7, 10; T238 valid: 0 */ uint8_t ep_controller; } BPMP_ABI_PACKED; +/** + * @brief Request payload for #MRQ_UPHY sub-command #CMD_UPHY_PCIE_CONTROLLER_STATE. + */ struct cmd_uphy_pcie_controller_state_request { /** @brief PCIE controller number, T194 valid: 0-4; T234 valid: 0-10; T238 valid: 0-3 */ uint8_t pcie_controller; + /** @brief Nonzero value to enable controller, zero value to disable */ uint8_t enable; } BPMP_ABI_PACKED; +/** + * @brief Request payload for #MRQ_UPHY sub-command #CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF. + */ struct cmd_uphy_ep_controller_pll_off_request { /** @brief EP controller number, T194 valid: 0, 4, 5; T234 valid: 5, 6, 7, 10; T238 valid: 0 */ uint8_t ep_controller; } BPMP_ABI_PACKED; +/** + * @cond bpmp_t238 + * @brief Request payload for #MRQ_UPHY sub-command #CMD_UPHY_DISPLAY_PORT_INIT. + */ struct cmd_uphy_display_port_init_request { /** @brief DisplayPort link rate, T238 valid: 1620, 2700, 5400, 8100, 2160, 2430, 3240, 4320, 6750 */ uint16_t link_rate; @@ -3019,37 +3945,90 @@ struct cmd_uphy_display_port_init_request { uint16_t lanes_bitmap; } BPMP_ABI_PACKED; +/** + * @brief Request payload for #MRQ_UPHY sub-command #CMD_UPHY_XUSB_DYN_LANES_RESTORE. + */ struct cmd_uphy_xusb_dyn_lanes_restore_request { /** @brief 1: lane 0; 2: lane 1; 3: lane 0 and 1 */ uint16_t lanes_bitmap; } BPMP_ABI_PACKED; +/** @endcond */ + +/** + * @cond bpmp_th500 + * @brief Request payload for #MRQ_UPHY sub-command #CMD_UPHY_LANE_EOM_SCAN + */ +struct cmd_uphy_lane_eom_scan_request { + /** @brief UPHY brick number, valid: 0-5 */ + uint32_t brick; + /** @brief UPHY lane number, valid: 0-15 for UPHY0-UPHY3, 0-1 for UPHY4-UPHY5 */ + uint32_t lane; + /** @brief Perform EOM for PCIE GEN5 link: 1 for yes, 0 for no. */ + uint32_t pcie_gen5; +} BPMP_ABI_PACKED; + +/** + * @brief Response payload for #MRQ_UPHY sub-command #CMD_UPHY_LANE_EOM_SCAN + */ +struct cmd_uphy_lane_eom_scan_response { + uint32_t data; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for #MRQ_UPHY sub-command #CMD_UPHY_PCIE_CONFIG_VDM + */ +struct cmd_uphy_pcie_config_vdm_request { + uint8_t pcie_controller; + /** + * @brief Bus/Dev/Func ID to be programmed for VDM. + * + * - bits[15..8] Bus + * - bits[7..3] Dev + * - bit [2..0] Func + */ + uint16_t bdf; +} BPMP_ABI_PACKED; +/** @endcond */ /** * @ingroup UPHY - * @brief Request with #MRQ_UPHY + * @brief Request payload for the #MRQ_UPHY -command. * * Used by the sender of an #MRQ_UPHY message to control UPHY. * The uphy_request is split into several sub-commands. CMD_UPHY_PCIE_LANE_MARGIN_STATUS * requires no additional data. Others have a sub-command specific payload. Below table * shows sub-commands with their corresponding payload data. * - * |sub-command |payload | - * |------------------------------------ |----------------------------------------| - * |CMD_UPHY_PCIE_LANE_MARGIN_CONTROL |uphy_set_margin_control | - * |CMD_UPHY_PCIE_LANE_MARGIN_STATUS | | - * |CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT |cmd_uphy_ep_controller_pll_init_request | - * |CMD_UPHY_PCIE_CONTROLLER_STATE |cmd_uphy_pcie_controller_state_request | - * |CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF |cmd_uphy_ep_controller_pll_off_request | - * |CMD_UPHY_PCIE_DISPLAY_PORT_INIT |cmd_uphy_display_port_init_request | - * |CMD_UPHY_PCIE_DISPLAY_PORT_OFF | | - * |CMD_UPHY_XUSB_DYN_LANES_RESTORE |cmd_uphy_xusb_dyn_lanes_restore_request | + * |sub-command |payload | + * |--------------------------------------|-----------------------------------------| + * |#CMD_UPHY_PCIE_LANE_MARGIN_CONTROL |#cmd_uphy_margin_control_request | + * |#CMD_UPHY_PCIE_LANE_MARGIN_STATUS |- | + * |#CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT |#cmd_uphy_ep_controller_pll_init_request | + * |#CMD_UPHY_PCIE_CONTROLLER_STATE |#cmd_uphy_pcie_controller_state_request | + * |#CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF |#cmd_uphy_ep_controller_pll_off_request | * + * @cond bpmp_t238 + * The following additional sub-commands are supported on T238 platforms: + * + * |sub-command |payload | + * |--------------------------------------|-----------------------------------------| + * |#CMD_UPHY_DISPLAY_PORT_INIT |#cmd_uphy_display_port_init_request | + * |#CMD_UPHY_DISPLAY_PORT_OFF |- | + * |#CMD_UPHY_XUSB_DYN_LANES_RESTORE |#cmd_uphy_xusb_dyn_lanes_restore_request | + * @endcond + * + * @cond bpmp_th500 + * The following additional sub-commands are supported on TH500 platforms: + * |sub-command |payload | + * |--------------------------------------|-----------------------------------------| + * |#CMD_UPHY_LANE_EOM_SCAN |#cmd_uphy_lane_eom_scan_request | + * |#CMD_UPHY_PCIE_CONFIG_VDM |#cmd_uphy_pcie_config_vdm_request | + * @endcond */ - struct mrq_uphy_request { /** @brief Lane number. */ uint16_t lane; - /** @brief Sub-command id. */ + /** @brief Sub-command ID from @ref mrq_uphy_cmd. */ uint16_t cmd; union { @@ -3057,53 +4036,68 @@ struct mrq_uphy_request { struct cmd_uphy_ep_controller_pll_init_request ep_ctrlr_pll_init; struct cmd_uphy_pcie_controller_state_request controller_state; struct cmd_uphy_ep_controller_pll_off_request ep_ctrlr_pll_off; + /** @cond bpmp_t238 */ struct cmd_uphy_display_port_init_request display_port_init; struct cmd_uphy_xusb_dyn_lanes_restore_request xusb_dyn_lanes_restore; + /** @endcond */ + /** @cond bpmp_th500 */ + struct cmd_uphy_lane_eom_scan_request lane_eom_scan; + struct cmd_uphy_pcie_config_vdm_request pcie_vdm; + /** @endcond */ } BPMP_UNION_ANON; } BPMP_ABI_PACKED; /** * @ingroup UPHY - * @brief Response to MRQ_UPHY + * @brief Response payload for the #MRQ_UPHY -command. * * Each sub-command supported by @ref mrq_uphy_request may return * sub-command-specific data. Some do and some do not as indicated in * the following table * - * |sub-command |payload | - * |---------------------------- |------------------------| - * |CMD_UPHY_PCIE_LANE_MARGIN_CONTROL | | - * |CMD_UPHY_PCIE_LANE_MARGIN_STATUS |uphy_get_margin_status | + * |sub-command |payload | + * |-----------------------------------|---------------------------------| + * |#CMD_UPHY_PCIE_LANE_MARGIN_CONTROL |- | + * |#CMD_UPHY_PCIE_LANE_MARGIN_STATUS |#cmd_uphy_margin_status_response | * + * @cond bpmp_th500 + * The following additional sub-commands are supported on TH500 platforms: + * |sub-command |payload | + * |-----------------------------------|---------------------------------| + * |#CMD_UPHY_LANE_EOM_SCAN |#cmd_uphy_lane_eom_scan_response | + * |#CMD_UPHY_PCIE_CONFIG_VDM |- | + * @endcond */ - struct mrq_uphy_response { union { struct cmd_uphy_margin_status_response uphy_get_margin_status; + /** @cond bpmp_th500 */ + struct cmd_uphy_lane_eom_scan_response eom_status; + /** @endcond */ } BPMP_UNION_ANON; } BPMP_ABI_PACKED; /** @} UPHY */ -/** @endcond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) */ +/** @endcond */ -/** +/** @cond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_t264) * @ingroup MRQ_Codes * @def MRQ_FMON - * @brief Perform a frequency monitor configuration operations + * @brief Perform a frequency monitor configuration operation * - * * Platforms: T194 onwards - * @cond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_fmon_request * * Response Payload: @ref mrq_fmon_response - * @endcond (bpmp_t194 || bpmp_t234 || bpmp_t238 || bpmp_th500) * * @addtogroup FMON * @{ - * @cond (bpmp_t194 || bpmp_t234) */ -enum { + +/** + * @brief Sub-command identifiers for #MRQ_FMON + */ +enum mrq_fmon_cmd { /** * @brief Clamp FMON configuration to specified rate. * @@ -3111,62 +4105,80 @@ enum { * clamped, FMON configuration is preserved when clock rate * and/or state is changed. * - * mrq_response::err is 0 if the operation was successful, or @n - * -#BPMP_EACCES: FMON access error @n - * -#BPMP_EBADCMD if subcommand is not supported @n - * -#BPMP_EBADSLT: clamp FMON on cluster with auto-CC3 enabled @n - * -#BPMP_EBUSY: fmon is already clamped at different rate @n - * -#BPMP_EFAULT: self-diagnostic error @n - * -#BPMP_EINVAL: invalid FMON configuration @n - * -#BPMP_EOPNOTSUPP: not in production mode @n - * -#BPMP_ENODEV: invalid clk_id @n - * -#BPMP_ENOENT: no calibration data, uninitialized @n - * -#BPMP_ENOTSUP: avfs config not set @n - * -#BPMP_ENOSYS: clamp FMON on cluster clock w/ no NAFLL @n - * -#BPMP_ETIMEDOUT: operation timed out @n + * mrq_response::err for this sub-command is defined to be: + * + * | Value | Description | + * |-------------------|---------------------------------------------------| + * | 0 | Operation was successful. | + * | -#BPMP_EBADCMD | Subcommand is not supported. | + * | -#BPMP_EACCES | FMON access error. | + * | -#BPMP_EBADSLT | Clamp FMON on cluster with auto-CC3 enabled. | + * | -#BPMP_EBUSY | FMON is already clamped at different rate. | + * | -#BPMP_EFAULT | Self-diagnostic error detected. | + * | -#BPMP_EINVAL | Invalid FMON configuration. | + * | -#BPMP_EOPNOTSUPP | Not in production mode. | + * | -#BPMP_ENODEV | Invalid clock ID in mrq_fmon_request::cmd_and_id. | + * | -#BPMP_ENOENT | No calibration data, uninitialized. | + * | -#BPMP_ENOTSUP | AVFS config not set. | + * | -#BPMP_ENOSYS | Clamp FMON on cluster clock w/ no NAFLL. | + * | -#BPMP_ETIMEDOUT | Operation timed out. | */ CMD_FMON_GEAR_CLAMP = 1, + /** * @brief Release clamped FMON configuration. * * Allow FMON configuration to follow monitored clock rate * and/or state changes. * - * mrq_response::err is 0 if the operation was successful, or @n - * -#BPMP_EBADCMD if subcommand is not supported @n - * -#BPMP_ENODEV: invalid clk_id @n - * -#BPMP_ENOENT: no calibration data, uninitialized @n - * -#BPMP_ENOTSUP: avfs config not set @n - * -#BPMP_EOPNOTSUPP: not in production mode @n + * mrq_response::err for this sub-command is defined to be: + * + * | Value | Description | + * |-------------------|---------------------------------------------------| + * | 0 | Operation was successful. | + * | -#BPMP_EBADCMD | Subcommand is not supported. | + * | -#BPMP_ENODEV | Invalid clock ID in mrq_fmon_request::cmd_and_id. | + * | -#BPMP_ENOENT | No calibration data, uninitialized. | + * | -#BPMP_ENOTSUP | AVFS config not set. | + * | -#BPMP_EOPNOTSUPP | Not in production mode. | */ CMD_FMON_GEAR_FREE = 2, + /** - * @brief Return rate FMON is clamped at, or 0 if FMON is not - * clamped. + * @brief Return rate FMON is clamped at, or 0 if FMON is not clamped. * - * Inherently racy, since clamp state can be changed - * concurrently. Useful for testing. + * Inherently racy, since clamp state can be changed concurrently, + * only provided and useful for testing purposes. * - * mrq_response::err is 0 if the operation was successful, or @n - * -#BPMP_EBADCMD if subcommand is not supported @n - * -#BPMP_ENODEV: invalid clk_id @n - * -#BPMP_ENOENT: no calibration data, uninitialized @n - * -#BPMP_ENOTSUP: avfs config not set @n - * -#BPMP_EOPNOTSUPP: not in production mode @n + * mrq_response::err for this sub-command is defined to be: + * + * | Value | Description | + * |-------------------|---------------------------------------------------| + * | 0 | Operation was successful. | + * | -#BPMP_EBADCMD | Subcommand is not supported. | + * | -#BPMP_ENODEV | Invalid clock ID in mrq_fmon_request::cmd_and_id. | + * | -#BPMP_ENOENT | No calibration data, uninitialized. | + * | -#BPMP_ENOTSUP | AVFS config not set. | + * | -#BPMP_EOPNOTSUPP | Not in production mode. | */ CMD_FMON_GEAR_GET = 3, + /** * @brief Return current status of FMON faults detected by FMON - * h/w or s/w since last invocation of this command. - * Clears fault status. + * HW or SW since last invocation of this sub-command. + * Clears fault status. * - * mrq_response::err is 0 if the operation was successful, or @n - * -#BPMP_EBADCMD if subcommand is not supported @n - * -#BPMP_EINVAL: invalid fault type @n - * -#BPMP_ENODEV: invalid clk_id @n - * -#BPMP_ENOENT: no calibration data, uninitialized @n - * -#BPMP_ENOTSUP: avfs config not set @n - * -#BPMP_EOPNOTSUPP: not in production mode @n + * mrq_response::err for this sub-command is defined to be: + * + * | Value | Description | + * |-------------------|---------------------------------------------------| + * | 0 | Operation was successful. | + * | -#BPMP_EBADCMD | Subcommand is not supported. | + * | -#BPMP_ENODEV | Invalid clock ID in mrq_fmon_request::cmd_and_id. | + * | -#BPMP_ENOENT | No calibration data, uninitialized. | + * | -#BPMP_ENOTSUP | AVFS config not set. | + * | -#BPMP_EOPNOTSUPP | Not in production mode. | + * | -#BPMP_EINVAL | Invalid fault type. | */ CMD_FMON_FAULT_STS_GET = 4, }; @@ -3177,25 +4189,30 @@ enum { */ #define CMD_FMON_NUM 4 -/** @endcond DEPRECATED */ +/** @endcond */ /** - * @defgroup fmon_fault_type FMON fault type + * @defgroup fmon_fault_type FMON fault types * @addtogroup fmon_fault_type * @{ */ -/** @brief All detected FMON faults (h/w or s/w) */ +/** @brief All detected FMON faults (HW or SW) */ #define FMON_FAULT_TYPE_ALL 0U -/** @brief FMON faults detected by h/w */ +/** @brief FMON faults detected by HW */ #define FMON_FAULT_TYPE_HW 1U -/** @brief FMON faults detected by s/w */ +/** @brief FMON faults detected by SW */ #define FMON_FAULT_TYPE_SW 2U /** @} fmon_fault_type */ - +/** + * @brief Request payload for #MRQ_FMON sub-command #CMD_FMON_GEAR_CLAMP. + */ struct cmd_fmon_gear_clamp_request { + /** @brief Unused / reserved */ int32_t unused; + + /** @brief Target rate in Hz. Valid range for the rate is [1, INT64_MAX] */ int64_t rate; } BPMP_ABI_PACKED; @@ -3219,40 +4236,63 @@ struct cmd_fmon_gear_get_request { BPMP_ABI_EMPTY } BPMP_ABI_PACKED; +/** + * @brief Response payload for #MRQ_FMON sub-command #CMD_FMON_GEAR_GET. + */ struct cmd_fmon_gear_get_response { int64_t rate; } BPMP_ABI_PACKED; +/** + * @brief Request payload for #MRQ_FMON sub-command #CMD_FMON_FAULT_STS_GET + */ struct cmd_fmon_fault_sts_get_request { - uint32_t fault_type; /**< @ref fmon_fault_type */ + /** + * @brief Which fault types to return in response: + * + * | Value | Description | + * |----------------------|-----------------------------------------| + * | #FMON_FAULT_TYPE_ALL | Return all detected faults (HW and SW). | + * | #FMON_FAULT_TYPE_HW | Return only HW detected faults. | + * | #FMON_FAULT_TYPE_SW | Return only SW detected faults. | + */ + uint32_t fault_type; } BPMP_ABI_PACKED; +/** + * @brief Response payload for #MRQ_FMON sub-command #CMD_FMON_FAULT_STS_GET + */ struct cmd_fmon_fault_sts_get_response { + /** + * Bitmask of detected HW / SW specific faults, or 0 if no faults have + * been detected since last invocation of #CMD_FMON_FAULT_STS_GET. + */ uint32_t fault_sts; } BPMP_ABI_PACKED; /** * @ingroup FMON - * @brief Request with #MRQ_FMON + * @brief Request payload for the #MRQ_FMON -command. * * Used by the sender of an #MRQ_FMON message to configure clock * frequency monitors. The FMON request is split into several - * sub-commands. Some sub-commands require no additional data. - * Others have a sub-command specific payload + * sub-commands. Sub-command specific payloads are defined in + * the following table: * - * |sub-command |payload | - * |----------------------------|-----------------------| - * |CMD_FMON_GEAR_CLAMP |fmon_gear_clamp | - * |CMD_FMON_GEAR_FREE |- | - * |CMD_FMON_GEAR_GET |- | - * |CMD_FMON_FAULT_STS_GET |fmon_fault_sts_get | + * |Sub-command |Payload | + * |------------------------|--------------------------------| + * |#CMD_FMON_GEAR_CLAMP |#cmd_fmon_gear_clamp_request | + * |#CMD_FMON_GEAR_FREE |- | + * |#CMD_FMON_GEAR_GET |- | + * |#CMD_FMON_FAULT_STS_GET |#cmd_fmon_fault_sts_get_request | * */ struct mrq_fmon_request { - /** @brief Sub-command and clock id concatenated to 32-bit word. - * - bits[31..24] is the sub-cmd. - * - bits[23..0] is monitored clock id used to select target - * FMON + /** + * @brief Sub-command and clock id concatenated to 32-bit word. + * + * - bits[31..24] -> Sub-command identifier from @ref mrq_fmon_cmd. + * - bits[23..0] -> Monitored clock identifier used to select target FMON. */ uint32_t cmd_and_id; @@ -3268,20 +4308,19 @@ struct mrq_fmon_request { /** * @ingroup FMON - * @brief Response to MRQ_FMON + * @brief Response payload for the #MRQ_FMON -command. * * Each sub-command supported by @ref mrq_fmon_request may * return sub-command-specific data as indicated below. * - * |sub-command |payload | - * |----------------------------|------------------------| - * |CMD_FMON_GEAR_CLAMP |- | - * |CMD_FMON_GEAR_FREE |- | - * |CMD_FMON_GEAR_GET |fmon_gear_get | - * |CMD_FMON_FAULT_STS_GET |fmon_fault_sts_get | + * |Sub-command |Payload | + * |------------------------|---------------------------------| + * |#CMD_FMON_GEAR_CLAMP |- | + * |#CMD_FMON_GEAR_FREE |- | + * |#CMD_FMON_GEAR_GET |#cmd_fmon_gear_get_response | + * |#CMD_FMON_FAULT_STS_GET |#cmd_fmon_fault_sts_get_response | * */ - struct mrq_fmon_response { union { /** @private */ @@ -3293,17 +4332,15 @@ struct mrq_fmon_response { } BPMP_UNION_ANON; } BPMP_ABI_PACKED; -/** @endcond (bpmp_t194 || bpmp_t234) */ /** @} FMON */ +/** @endcond */ -/** +/** @cond (bpmp_t194) * @ingroup MRQ_Codes * @def MRQ_EC * @brief Provide status information on faults reported by Error * Collator (EC) to HSM. * - * * Platforms: T194 - * @cond bpmp_t194 * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: @ref mrq_ec_request @@ -3311,10 +4348,8 @@ struct mrq_fmon_response { * * @note This MRQ ABI is under construction, and subject to change * - * @endcond bpmp_t194 * @addtogroup EC * @{ - * @cond bpmp_t194 */ enum { /** @@ -3325,7 +4360,7 @@ enum { * -#BPMP_ENODEV if target EC is not owned by BPMP @n * -#BPMP_EACCES if target EC power domain is turned off @n * -#BPMP_EBADCMD if subcommand is not supported - * @endcond DEPRECATED + * @endcond */ CMD_EC_STATUS_GET = 1, /* deprecated */ @@ -3572,7 +4607,7 @@ struct cmd_ec_status_get_response { /** @brief EC error descriptors */ union ec_err_desc error_descs[EC_ERR_STATUS_DESC_MAX_NUM]; } BPMP_ABI_PACKED; -/** @endcond DEPRECATED */ +/** @endcond */ struct cmd_ec_status_ex_get_response { /** @brief Target EC id (the same id received with request). */ @@ -3610,7 +4645,7 @@ struct cmd_ec_status_ex_get_response { * |sub-command |payload | * |----------------------------|-----------------------| * |@ref CMD_EC_STATUS_GET |ec_status_get | - * @endcond DEPRECATED + * @endcond * * |sub-command |payload | * |----------------------------|-----------------------| @@ -3638,7 +4673,7 @@ struct mrq_ec_request { * |sub-command |payload | * |----------------------------|------------------------| * |@ref CMD_EC_STATUS_GET |ec_status_get | - * @endcond DEPRECATED + * @endcond * * |sub-command |payload | * |----------------------------|------------------------| @@ -3652,22 +4687,20 @@ struct mrq_ec_response { * @cond DEPRECATED */ struct cmd_ec_status_get_response ec_status_get; - /** @endcond DEPRECATED */ + /** @endcond */ struct cmd_ec_status_ex_get_response ec_status_ex_get; } BPMP_UNION_ANON; } BPMP_ABI_PACKED; -/** @endcond bpmp_t194 */ /** @} EC */ +/** @endcond */ -/** +/** @cond (bpmp_th500) * @ingroup MRQ_Codes * @def MRQ_TELEMETRY * @brief Get address of memory buffer refreshed with recently sampled * telemetry data * - * * Platforms: TH500 onwards - * @cond bpmp_th500 * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: N/A @@ -3677,14 +4710,17 @@ struct mrq_ec_response { */ /** - * @brief Response to #MRQ_TELEMETRY + * @brief Response payload for the #MRQ_TELEMETRY -command * - * mrq_response::err is - * * 0: Telemetry data is available at returned address - * * -#BPMP_EACCES: MRQ master is not allowed to request buffer refresh - * * -#BPMP_ENAVAIL: Telemetry buffer cannot be refreshed via this MRQ channel - * * -#BPMP_ENOTSUP: Telemetry buffer is not supported by BPMP-FW - * * -#BPMP_ENODEV: Telemetry mrq is not supported by BPMP-FW + * mrq_response::err is defined as: + * + * | Value | Description | + * |-----------------|------------------------------------------------------------| + * | 0 | Telemetry data is available at returned address. | + * | -#BPMP_EACCES | MRQ master is not allowed to request buffer refresh. | + * | -#BPMP_ENAVAIL | Telemetry buffer cannot be refreshed via this MRQ channel. | + * | -#BPMP_ENOTSUP | Telemetry buffer is not supported by BPMP-FW. | + * | -#BPMP_ENODEV | Telemetry MRQ is not supported by BPMP-FW. | */ struct mrq_telemetry_response { /** @brief Physical address of telemetry data buffer */ @@ -3692,15 +4728,112 @@ struct mrq_telemetry_response { } BPMP_ABI_PACKED; /** @} Telemetry */ -/** @endcond bpmp_th500 */ +/** @endcond */ + +/** @cond (bpmp_tb500) + * @ingroup MRQ_Codes + * @def MRQ_TELEMETRY_EX + * @brief Get telemetry configuration settings. + * + * * Initiators: Any + * * Targets: BPMP + * * Request Payload: @ref mrq_telemetry_ex_request + * * Response Payload: @ref mrq_telemetry_ex_response + * + * @addtogroup Telemetry_ex + * @{ + */ /** + * @brief Sub-command identifiers for #MRQ_TELEMETRY_EX. + */ +enum mrq_telemetry_ex_cmd { + /** + * @brief Check whether the BPMP-FW supports the specified + * #MRQ_TELEMETRY_EX sub-command. + * + * mrq_response::err is 0 if the specified request is + * supported and -#BPMP_ENODEV otherwise. + */ + CMD_TELEMETRY_EX_QUERY_ABI = 0, + + /** + * @brief Get telemetry buffer base address and data size + * + * mrq_response:err is defined as: + * + * | Value | Description | + * |----------------|------------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_TELEMETRY_EX is not supported by BPMP-FW. | + */ + CMD_TELEMETRY_EX_BASE_SZ_GET = 1, +}; + +/** + * @brief Request data for #MRQ_TELEMETRY_EX sub-command + * #CMD_TELEMETRY_EX_QUERY_ABI + */ +struct cmd_telemetry_ex_query_abi_request { + /** @brief Sub-command identifier from @ref mrq_telemetry_ex_cmd */ + uint32_t cmd_code; +} BPMP_ABI_PACKED; + +/** + * @brief Response payload for #MRQ_TELEMETRY_EX sub-command + * #CMD_TELEMETRY_EX_BASE_SZ_GET + */ +struct cmd_telemetry_ex_base_sz_get_response { + /** + * @brief Physical address of telemetry data buffer + * + * 0 if no buffer is allocated for the initiator sending MRQ. + */ + uint64_t buf_base_addr; + /** @brief Telemetry data size in bytes */ + uint32_t buf_size; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for the #MRQ_TELEMETRY_EX -command + * + * | Sub-command | Request payload | + * |-------------------------------|----------------------------------------| + * | #CMD_TELEMETRY_EX_QUERY_ABI | #cmd_telemetry_ex_query_abi_request | + * | #CMD_TELEMETRY_EX_BASE_SZ_GET | - | + */ +struct mrq_telemetry_ex_request { + /** @brief Sub-command ID from @ref mrq_telemetry_ex_cmd. */ + uint32_t cmd; + union { + struct cmd_telemetry_ex_query_abi_request + telemetry_ex_query_abi_req; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** + * @brief Response payload for the #MRQ_TELEMETRY_EX -command. + * + * | Sub-command | Response payload | + * |-------------------------------|----------------------------------------| + * | #CMD_TELEMETRY_EX_QUERY_ABI | - | + * | #CMD_TELEMETRY_EX_BASE_SZ_GET | #cmd_telemetry_ex_base_sz_get_response | + */ +struct mrq_telemetry_ex_response { + union { + struct cmd_telemetry_ex_base_sz_get_response + telemetry_ex_base_sz_get_rsp; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** @} Telemetry_ex */ +/** @endcond */ + +/** @cond (bpmp_th500 || bpmp_tb500) * @ingroup MRQ_Codes * @def MRQ_PWR_LIMIT * @brief Control power limits. * - * * Platforms: TH500 onwards - * @cond bpmp_th500 * * Initiators: Any * * Targets: BPMP * * Request Payload: @ref mrq_pwr_limit_request @@ -3709,10 +4842,14 @@ struct mrq_telemetry_response { * @addtogroup Pwrlimit * @{ */ + +/** + * @brief Sub-command identifiers for #MRQ_PWR_LIMIT. + */ enum mrq_pwr_limit_cmd { /** * @brief Check whether the BPMP-FW supports the specified - * command + * #MRQ_PWR_LIMIT sub-command. * * mrq_response::err is 0 if the specified request is * supported and -#BPMP_ENODEV otherwise. @@ -3722,31 +4859,43 @@ enum mrq_pwr_limit_cmd { /** * @brief Set power limit * - * mrq_response:err is - * * 0: Success - * * -#BPMP_ENODEV: Pwr limit mrq is not supported by BPMP-FW - * * -#BPMP_ENAVAIL: Invalid request parameters - * * -#BPMP_EACCES: Request is not accepted + * mrq_response:err is defined as: + * + * | Value | Description | + * |----------------|---------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_PWR_LIMIT is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + * | -#BPMP_EACCES | Request is not accepted. | */ CMD_PWR_LIMIT_SET = 1, /** * @brief Get power limit setting * - * mrq_response:err is - * * 0: Success - * * -#BPMP_ENODEV: Pwr limit mrq is not supported by BPMP-FW - * * -#BPMP_ENAVAIL: Invalid request parameters + * mrq_response:err is defined as: + * + * | Value | Description | + * |----------------|---------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_PWR_LIMIT is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | */ CMD_PWR_LIMIT_GET = 2, /** - * @brief Get current power cap + * @brief Get current aggregated power cap * - * mrq_response:err is - * * 0: Success - * * -#BPMP_ENODEV: Pwr limit mrq is not supported by BPMP-FW - * * -#BPMP_ENAVAIL: Invalid request parameters + * Get currently applied power cap for the specified limit id + * aggregated across all limit sources and types. + * + * mrq_response:err is defined as: + * + * | Value | Description | + * |----------------|---------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_PWR_LIMIT is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | */ CMD_PWR_LIMIT_CURR_CAP = 3, }; @@ -3761,7 +4910,7 @@ enum mrq_pwr_limit_cmd { #define PWR_LIMIT_TYPE_BOUND_MAX 1U /** @brief Limit value specifies minimum possible target cap */ #define PWR_LIMIT_TYPE_BOUND_MIN 2U -/** @brief Number of limit types supported by mrq interface */ +/** @brief Number of limit types supported by #MRQ_PWR_LIMIT command */ #define PWR_LIMIT_TYPE_NUM 3U /** @} bpmp_pwr_limit_type */ @@ -3770,7 +4919,8 @@ enum mrq_pwr_limit_cmd { * @brief Request data for #MRQ_PWR_LIMIT command CMD_PWR_LIMIT_QUERY_ABI */ struct cmd_pwr_limit_query_abi_request { - uint32_t cmd_code; /**< @ref mrq_pwr_limit_cmd */ + /** @brief Sub-command identifier from @ref mrq_pwr_limit_cmd */ + uint32_t cmd_code; } BPMP_ABI_PACKED; /** @@ -3782,56 +4932,66 @@ struct cmd_pwr_limit_query_abi_request { * is ignored by the arbitration (i.e., indicates "no limit set"). */ struct cmd_pwr_limit_set_request { - uint32_t limit_id; /**< @ref bpmp_pwr_limit_id */ + /** @brief Power limit identifier from @ref bpmp_pwr_limit_id */ + uint32_t limit_id; + /** @brief Power limit source identifier from @ref bpmp_pwr_limit_src */ uint32_t limit_src; /**< @ref bpmp_pwr_limit_src */ - uint32_t limit_type; /**< @ref bpmp_pwr_limit_type */ + /** @brief Power limit type from @ref bpmp_pwr_limit_type */ + uint32_t limit_type; + /** @brief New power limit value */ uint32_t limit_setting; } BPMP_ABI_PACKED; /** - * @brief Request data for #MRQ_PWR_LIMIT command CMD_PWR_LIMIT_GET + * @brief Request payload for #MRQ_PWR_LIMIT sub-command #CMD_PWR_LIMIT_GET * * Get previously set from specified source specified limit value of specified * type. */ struct cmd_pwr_limit_get_request { - uint32_t limit_id; /**< @ref bpmp_pwr_limit_id */ + /** @brief Power limit identifier from @ref bpmp_pwr_limit_id */ + uint32_t limit_id; + /** @brief Power limit source identifier from @ref bpmp_pwr_limit_src */ uint32_t limit_src; /**< @ref bpmp_pwr_limit_src */ - uint32_t limit_type; /**< @ref bpmp_pwr_limit_type */ + /** @brief Power limit type from @ref bpmp_pwr_limit_type */ + uint32_t limit_type; } BPMP_ABI_PACKED; /** - * @brief Response data for #MRQ_PWR_LIMIT command CMD_PWR_LIMIT_GET + * @brief Response payload for #MRQ_PWR_LIMIT sub-command #CMD_PWR_LIMIT_GET */ struct cmd_pwr_limit_get_response { + /** @brief Power limit value */ uint32_t limit_setting; } BPMP_ABI_PACKED; /** - * @brief Request data for #MRQ_PWR_LIMIT command CMD_PWR_LIMIT_CURR_CAP + * @brief Request payload for #MRQ_PWR_LIMIT sub-command #CMD_PWR_LIMIT_CURR_CAP * * For specified limit get current power cap aggregated from all sources. */ struct cmd_pwr_limit_curr_cap_request { - uint32_t limit_id; /**< @ref bpmp_pwr_limit_id */ + /** @brief Power limit identifier from @ref bpmp_pwr_limit_id */ + uint32_t limit_id; } BPMP_ABI_PACKED; /** - * @brief Response data for #MRQ_PWR_LIMIT command CMD_PWR_LIMIT_CURR_CAP + * @brief Response payload for #MRQ_PWR_LIMIT sub-command #CMD_PWR_LIMIT_CURR_CAP */ struct cmd_pwr_limit_curr_cap_response { + /** @brief Current power cap value */ uint32_t curr_cap; } BPMP_ABI_PACKED; /** - * @brief Request with #MRQ_PWR_LIMIT + * @brief Request payload for the #MRQ_PWR_LIMIT -command * - * |sub-command |payload | - * |----------------------------|---------------------------------| - * |CMD_PWR_LIMIT_QUERY_ABI | cmd_pwr_limit_query_abi_request | - * |CMD_PWR_LIMIT_SET | cmd_pwr_limit_set_request | - * |CMD_PWR_LIMIT_GET | cmd_pwr_limit_get_request | - * |CMD_PWR_LIMIT_CURR_CAP | cmd_pwr_limit_curr_cap_request | + * | Sub-command | Request payload | + * |--------------------------|----------------------------------| + * | #CMD_PWR_LIMIT_QUERY_ABI | #cmd_pwr_limit_query_abi_request | + * | #CMD_PWR_LIMIT_SET | #cmd_pwr_limit_set_request | + * | #CMD_PWR_LIMIT_GET | #cmd_pwr_limit_get_request | + * | #CMD_PWR_LIMIT_CURR_CAP | #cmd_pwr_limit_curr_cap_request | */ struct mrq_pwr_limit_request { uint32_t cmd; @@ -3844,14 +5004,14 @@ struct mrq_pwr_limit_request { } BPMP_ABI_PACKED; /** - * @brief Response to MRQ_PWR_LIMIT + * @brief Response payload for the #MRQ_PWR_LIMIT -command. * - * |sub-command |payload | - * |----------------------------|---------------------------------| - * |CMD_PWR_LIMIT_QUERY_ABI | - | - * |CMD_PWR_LIMIT_SET | - | - * |CMD_PWR_LIMIT_GET | cmd_pwr_limit_get_response | - * |CMD_PWR_LIMIT_CURR_CAP | cmd_pwr_limit_curr_cap_response | + * | Sub-command | Response payload | + * |--------------------------|----------------------------------| + * | #CMD_PWR_LIMIT_QUERY_ABI | - | + * | #CMD_PWR_LIMIT_SET | - | + * | #CMD_PWR_LIMIT_GET | #cmd_pwr_limit_get_response | + * | #CMD_PWR_LIMIT_CURR_CAP | #cmd_pwr_limit_curr_cap_response | */ struct mrq_pwr_limit_response { union { @@ -3860,17 +5020,395 @@ struct mrq_pwr_limit_response { } BPMP_UNION_ANON; } BPMP_ABI_PACKED; -/** @} PwrLimit */ -/** @endcond bpmp_th500 */ +/** @} Pwrlimit */ +/** @endcond */ + +/** @cond (bpmp_th500) + * @ingroup MRQ_Codes + * @def MRQ_PWRMODEL + * @brief Retrieve power evaluted by SoC power model. + * + * * Initiators: Any + * * Targets: BPMP + * * Request Payload: @ref mrq_pwrmodel_request + * * Response Payload: @ref mrq_pwrmodel_response + * + * @addtogroup Pwrmodel + * @{ + */ + /** + * @brief Sub-command identifiers for #MRQ_PWRMODEL. + */ +enum mrq_pwrmodel_cmd { + /** + * @brief Check whether the BPMP-FW supports the specified + * #MRQ_PWRMODEL sub-command. + * + * mrq_response::err is 0 if the specified request is + * supported and -#BPMP_ENODEV otherwise. + */ + CMD_PWRMODEL_QUERY_ABI = 0, + + /** + * @brief Get power model output power + * + * mrq_response:err is defined as: + * + * | Value | Description | + * |----------------|---------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_PWRMODEL is not supported by BPMP-FW. | + * | -#BPMP_ERANGE | Power model calculation overflow. | + */ + CMD_PWRMODEL_PWR_GET = 1, +}; + +/** + * @brief Request data for #MRQ_PWRMODEL sub-command #CMD_PWRMODEL_QUERY_ABI + */ +struct cmd_pwrmodel_query_abi_request { + /** @brief Sub-command identifier from @ref mrq_pwrmodel_cmd */ + uint32_t cmd_code; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for #MRQ_PWRMODEL sub-command #CMD_PWRMODEL_PWR_GET + * + * Rerieve power evaluated by power model for specified work-load factor, + * temperature, and cpu iso frequency for all cores. + */ +struct cmd_pwrmodel_pwr_get_request { + /** @brief Unitless work load factor to evaluate power model at */ + uint32_t work_load_factor; + /** @brief CPU frequency in kHz to evaluate power model at */ + uint32_t cpu_frequency; + /** @brief Temperature in mC to evaluate power model at */ + int32_t temperature; +} BPMP_ABI_PACKED; + +/** + * @brief Response payload for #MRQ_PWRMODEL sub-command #CMD_PWRMODEL_PWR_GET + */ +struct cmd_pwrmodel_pwr_get_response { + /** @brief Power model output in mW */ + uint32_t power; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for the #MRQ_PWRMODEL -command + * + * | Sub-command | Request payload | + * |--------------------------|----------------------------------| + * | #CMD_PWRMODEL_QUERY_ABI | #cmd_pwrmodel_query_abi_request | + * | #CMD_PWRMODEL_PWR_GET | #cmd_pwrmodel_pwr_get_request | + */ +struct mrq_pwrmodel_request { + uint32_t cmd; + union { + struct cmd_pwrmodel_query_abi_request pwrmodel_query_abi_req; + struct cmd_pwrmodel_pwr_get_request pwrmodel_pwr_get_req; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** + * @brief Response payload for the #MRQ_PWRMODEL -command. + * + * | Sub-command | Response payload | + * |--------------------------|----------------------------------| + * | #CMD_PWRMODEL_QUERY_ABI | - | + * | #CMD_PWRMODEL_PWR_GET | #cmd_pwrmodel_pwr_get_response | + */ +struct mrq_pwrmodel_response { + union { + struct cmd_pwrmodel_pwr_get_response pwrmodel_pwr_get_rsp; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** @} Pwrmodel */ +/** @endcond */ + + +/** @cond (bpmp_th500) + * @ingroup MRQ_Codes + * @def MRQ_PWR_CNTRL + * @brief Configure power controllers. + * + * * Initiators: Any + * * Targets: BPMP + * * Request Payload: @ref mrq_pwr_cntrl_request + * * Response Payload: @ref mrq_pwr_cntrl_response + * + * @addtogroup Pwrcntrl + * @{ + */ + +/** + * @brief Sub-command identifiers for #MRQ_PWR_CNTRL. + */ +enum mrq_pwr_cntrl_cmd { + /** + * @brief Check whether the BPMP-FW supports the specified + * #MRQ_PWR_CNTRL sub-command. + * + * mrq_response::err is 0 if the specified request is + * supported and -#BPMP_ENODEV otherwise. + */ + CMD_PWR_CNTRL_QUERY_ABI = 0, + + /** + * @brief Switch power controller to/out of bypass mode + * + * mrq_response:err is defined as: + * + * | Value | Description | + * |----------------|---------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_PWR_CNTRL is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + * | -#BPMP_ENOTSUP | Bypass mode is not supported. | + */ + CMD_PWR_CNTRL_BYPASS_SET = 1, + + /** + * @brief Get power controller bypass mode status + * + * mrq_response:err is defined as: + * + * | Value | Description | + * |----------------|---------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_PWR_CNTRL is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_PWR_CNTRL_BYPASS_GET = 2, +}; + +/** + * @brief Request data for #MRQ_PWR_CNTRL sub-command #CMD_PWR_CNTRL_QUERY_ABI + */ +struct cmd_pwr_cntrl_query_abi_request { + /** @brief Sub-command identifier from @ref mrq_pwr_cntrl_cmd */ + uint32_t cmd_code; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_PWR_CNTRL sub-command #CMD_PWR_CNTRL_BYPASS_SET + * + * Switch specified power controller to / out of bypass mode provided such + * mode is supported by the controller. + */ +struct cmd_pwr_cntrl_bypass_set_request { + /** @brief Power controller identifier from @ref bpmp_pwr_cntrl_id */ + uint32_t cntrl_id; + /** + * @brief Bypass setting. + * + * Valid values: + * + * * 1 to enter bypass mode, + * * 0 to exit bypass mode. + */ + uint32_t bypass_setting; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_PWR_CNTRL sub-command #CMD_PWR_CNTRL_BYPASS_GET + * + * Get bypass mode status of the specified power controller. + */ +struct cmd_pwr_cntrl_bypass_get_request { + /** @brief Power controller identifier from @ref bpmp_pwr_cntrl_id */ + uint32_t cntrl_id; +} BPMP_ABI_PACKED; + +/** + * @brief Response data for #MRQ_PWR_CNTRL sub-command #CMD_PWR_CNTRL_BYPASS_GET + * + * Get current bypass mode status if such mode is supported by the controller. + * Otherwise, return "out of bypass" . + */ +struct cmd_pwr_cntrl_bypass_get_response { + /** + * @brief Bypass mode status: 1 controller is in bypass, + * 0 controller is out of bypass. + */ + uint32_t bypass_status; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for the #MRQ_PWR_CNTRL -command + * + * | Sub-command | Request payload | + * |---------------------------|-----------------------------------| + * | #CMD_PWR_CNTRL_QUERY_ABI | #cmd_pwr_cntrl_query_abi_request | + * | #CMD_PWR_CNTRL_BYPASS_SET | #cmd_pwr_cntrl_bypass_set_request | + * | #CMD_PWR_CNTRL_BYPASS_GET | #cmd_pwr_cntrl_bypass_get_request | + */ +struct mrq_pwr_cntrl_request { + uint32_t cmd; + union { + struct cmd_pwr_cntrl_query_abi_request pwr_cntrl_query_abi_req; + struct cmd_pwr_cntrl_bypass_set_request pwr_cntrl_bypass_set_req; + struct cmd_pwr_cntrl_bypass_get_request pwr_cntrl_bypass_get_req; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** + * @brief Response payload for the #MRQ_PWR_CNTRL -command. + * + * | Sub-command | Response payload | + * |---------------------------|-----------------------------------| + * | #CMD_PWR_CNTRL_QUERY_ABI | - | + * | #CMD_PWR_CNTRL_BYPASS_SET | - | + * | #CMD_PWR_CNTRL_BYPASS_GET | #cmd_pwr_cntrl_bypass_get_response| + */ +struct mrq_pwr_cntrl_response { + union { + struct cmd_pwr_cntrl_bypass_get_response pwr_cntrl_bypass_get_rsp; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** @} Pwrcntrl */ +/** @endcond */ + + +/** @cond (bpmp_t264) + * @ingroup MRQ_Codes + * @def MRQ_SLC + * @brief Configure SLC state. + * + * * Initiators: Any + * * Targets: BPMP + * * Request Payload: @ref mrq_slc_request + * * Response Payload: @ref mrq_slc_response + * + * @addtogroup Slc + * @{ + */ + +/** + * @brief Sub-command identifiers for #MRQ_SLC. + */ +enum mrq_slc_cmd { + /** + * @brief Check whether the BPMP-FW supports the specified + * #MRQ_SLC sub-command. + * + * mrq_response::err is 0 if the specified request is + * supported and -#BPMP_ENODEV otherwise. + */ + CMD_SLC_QUERY_ABI = 0, + + /** + * @brief Switch SLC to/out of bypass mode + * + * mrq_response:err is defined as: + * + * | Value | Description | + * |----------------|---------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_SLC is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + * | -#BPMP_ENOTSUP | Bypass mode is not supported. | + */ + CMD_SLC_BYPASS_SET = 1, + + /** + * @brief Get SLC bypass mode status + * + * mrq_response:err is defined as: + * + * | Value | Description | + * |----------------|---------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_SLC is not supported by BPMP-FW. | + */ + CMD_SLC_BYPASS_GET = 2, +}; + +/** + * @brief Request data for #MRQ_SLC sub-command #CMD_SLC_QUERY_ABI + */ +struct cmd_slc_query_abi_request { + /** @brief Sub-command identifier from @ref mrq_slc_cmd */ + uint32_t cmd_code; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_SLC sub-command #CMD_SLC_BYPASS_SET + * + * Switch SLC to / out of bypass mode provided such + * mode is supported by the SLC. + */ +struct cmd_slc_bypass_set_request { + /** + * @brief Bypass setting. + * + * Valid values: + * + * * 1 to enter bypass mode, + * * 0 to exit bypass mode. + */ + uint32_t bypass_setting; +} BPMP_ABI_PACKED; + +/** + * @brief Response data for #MRQ_SLC sub-command #CMD_SLC_BYPASS_GET + * + * Get current bypass mode status if such mode is supported by the SLC. + * Otherwise, return "out of bypass" . + */ +struct cmd_slc_bypass_get_response { + /** + * @brief Bypass mode status: 1 SLC is in bypass, + * 0 SLC is out of bypass. + */ + uint32_t bypass_status; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for the #MRQ_SLC -command + * + * | Sub-command | Request payload | + * |---------------------------|-----------------------------------| + * | #CMD_SLC_QUERY_ABI | #cmd_slc_query_abi_request | + * | #CMD_SLC_BYPASS_SET | #cmd_slc_bypass_set_request | + * | #CMD_SLC_BYPASS_GET | - | + */ +struct mrq_slc_request { + uint32_t cmd; + union { + struct cmd_slc_query_abi_request slc_query_abi_req; + struct cmd_slc_bypass_set_request slc_bypass_set_req; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** + * @brief Response payload for the #MRQ_SLC -command. + * + * | Sub-command | Response payload | + * |---------------------------|-----------------------------------| + * | #CMD_SLC_QUERY_ABI | - | + * | #CMD_SLC_BYPASS_SET | - | + * | #CMD_SLC_BYPASS_GET | #cmd_slc_bypass_get_response | + */ +struct mrq_slc_response { + union { + struct cmd_slc_bypass_get_response slc_bypass_get_rsp; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** @} Slc */ +/** @endcond */ + +/** @cond (bpmp_th500) * @ingroup MRQ_Codes * @def MRQ_GEARS * @brief Get thresholds for NDIV offset switching * - * * Platforms: TH500 onwards - * @cond bpmp_th500 * * Initiators: CCPLEX * * Targets: BPMP * * Request Payload: N/A @@ -3905,11 +5443,1248 @@ struct mrq_pwr_limit_response { */ struct mrq_gears_response { /** @brief number of online CPUs for each gear */ - uint32_t ncpu[16]; + uint32_t ncpu[8]; + /** @brief ndiv offset for each gear */ + uint32_t ndiv_offset[8]; + /** @brief voltage below which gears are disabled */ + uint32_t uv_threshold; } BPMP_ABI_PACKED; /** @} Gears */ -/** @endcond bpmp_th500 */ +/** @endcond */ + + +/** + * @ingroup MRQ_Codes + * @def MRQ_SHUTDOWN + * @brief System shutdown + * + * This message indicates system shutdown or reboot request. BPMP will + * initiate system shutdown/reboot after receiving this message, it + * may include turning off some rails in sequence and programming + * PMIC. + * + * * Initiators: CPU_S, MCE + * * Targets: BPMP + * * Request Payload: @ref mrq_shutdown_request + * * Response Payload: N/A + * @addtogroup Shutdown + * @{ + */ + +/** + * @brief Request with #MRQ_SHUTDOWN + */ +struct mrq_shutdown_request { + /** + * @brief Shutdown state ID + * + * Legal values: + * * 0 - Power off + * * 1 - Reboot + * @cond bpmp_t264 + * * 2 - Suspend + * @endcond + */ + uint32_t state; +} BPMP_ABI_PACKED; + +/** @} Shutdown */ + +/** @cond (bpmp_th500 || bpmp_tb500) + * @defgroup bpmp_c2c_status C2C link status + * @addtogroup bpmp_c2c_status + * @{ + */ +/** @brief initial status code */ +#define BPMP_C2C_STATUS_INIT_NOT_STARTED 0 +/** @brief Invalid speedo code */ +#define BPMP_C2C_STATUS_C2C_INVALID_SPEEDO_CODE 7 +/** @brief Invalid frequency */ +#define BPMP_C2C_STATUS_C2C_INVALID_FREQ 8 +/** @brief Invalid link */ +#define BPMP_C2C_STATUS_C2C_INVALID_LINK 9 +/** @brief refpll lock polling times out - partition 0 */ +#define BPMP_C2C_STATUS_C2C0_REFPLL_FAIL 10 +/** @brief refpll lock polling times out - partition 1 */ +#define BPMP_C2C_STATUS_C2C1_REFPLL_FAIL 11 +/** @brief PLL cal times out - partition 0 */ +#define BPMP_C2C_STATUS_C2C0_PLLCAL_FAIL 12 +/** @brief PLL cal times out - partition 1 */ +#define BPMP_C2C_STATUS_C2C1_PLLCAL_FAIL 13 +/** @brief clock detection times out - partition 0 */ +#define BPMP_C2C_STATUS_C2C0_CLKDET_FAIL 14 +/** @brief clock detection times out - partition 1 */ +#define BPMP_C2C_STATUS_C2C1_CLKDET_FAIL 15 +/** @brief Final trainings fail partition 0 */ +#define BPMP_C2C_STATUS_C2C0_TR_FAIL 16 +/** @brief Final trainings fail partition 1 */ +#define BPMP_C2C_STATUS_C2C1_TR_FAIL 17 +/** @brief C2C FW init done */ +#define NV_GFW_GLOBAL_DEVINIT_C2C_STATUS_C2C_FW_INIT_DONE 20 +/** @brief C2C FW init failed partition 0 */ +#define NV_GFW_GLOBAL_DEVINIT_C2C_STATUS_C2C0_FW_INIT_FAIL 21 +/** @brief C2C FW init failed partition 1 */ +#define NV_GFW_GLOBAL_DEVINIT_C2C_STATUS_C2C1_FW_INIT_FAIL 22 +/** @brief no failure seen, c2c init was successful */ +#define BPMP_C2C_STATUS_C2C_LINK_TRAIN_PASS 255 +/** @} bpmp_c2c_status */ + +/** + * @ingroup MRQ_Codes + * @def MRQ_C2C + * @brief Control C2C partitions initialization. + * + * * Initiators: Any + * * Targets: BPMP + * * Request Payload: @ref mrq_c2c_request + * * Response Payload: @ref mrq_c2c_response + * + * @addtogroup C2C + * @{ + */ +enum mrq_c2c_cmd { + /** + * @brief Check whether the BPMP driver supports the specified request + * type + * + * mrq_response:: err is 0 if the specified request is supported and + * -#BPMP_ENODEV otherwise + */ + CMD_C2C_QUERY_ABI = 0, + + /** + * @brief Start C2C initialization + * + * mrq_response:err is + * * 0: Success + * * -#BPMP_ENODEV: MRQ_C2C is not supported by BPMP-FW + * * -#BPMP_ENAVAIL: Invalid request parameters + * * -#BPMP_EACCES: Request is not accepted + */ + CMD_C2C_START_INITIALIZATION = 1, + + /** + * @brief Command to query current C2C training status + * + * This command will return the result of the latest C2C re-training that is initiated with + * MRQ_C2C.CMD_C2C_START_INITIALIZATION or MRQ_C2C.CMD_C2C_START_HOTRESET calls. + * If no training has been initiated yet, the command will return code BPMP_C2C_STATUS_INIT_NOT_STARTED. + * + * mrq_response:err is + * * 0: Success + * * -#BPMP_ENODEV: MRQ_C2C is not supported by BPMP-FW + * * -#BPMP_EACCES: Request is not accepted + */ + CMD_C2C_GET_STATUS = 2, + /** + * @brief C2C hot-reset precondition + * + * mrq_response:err is + * * 0: Success + * * -#BPMP_ENODEV: MRQ_C2C is not supported by BPMP-FW + * * -#BPMP_ENAVAIL: Invalid request parameters + * * -#BPMP_EACCES: Request is not accepted + */ + CMD_C2C_HOTRESET_PREP = 3, + /** + * @brief Start C2C hot-reset + * + * mrq_response:err is + * * 0: Success + * * -#BPMP_ENODEV: MRQ_C2C is not supported by BPMP-FW + * * -#BPMP_ENAVAIL: Invalid request parameters + * * -#BPMP_EACCES: Request is not accepted + */ + CMD_C2C_START_HOTRESET = 4, + + CMD_C2C_MAX +}; + +/** + * @brief Request data for #MRQ_C2C command CMD_C2C_QUERY_ABI + */ +struct cmd_c2c_query_abi_request { + /** @brief Command identifier to be queried */ + uint32_t cmd; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_C2C command CMD_C2C_START_INITIALIZATION + */ +struct cmd_c2c_start_init_request { + /** @brief 1: partition 0; 2: partition 1; 3: partition 0 and 1; */ + uint8_t partitions; +} BPMP_ABI_PACKED; + +/** + * @brief Response data for #MRQ_C2C command CMD_C2C_START_INITIALIZATION + */ +struct cmd_c2c_start_init_response { + /** @brief Refer to @ref bpmp_c2c_status */ + uint8_t status; +} BPMP_ABI_PACKED; + +/** + * @brief Response data for #MRQ_C2C command CMD_C2C_GET_STATUS + */ +struct cmd_c2c_get_status_response { + /** @brief Refer to @ref bpmp_c2c_status */ + uint8_t status; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_C2C command CMD_C2C_HOTRESET_PREP + */ +struct cmd_c2c_hotreset_prep_request { + /** @brief 1: partition 0; 2: partition 1; 3: partition 0 and 1; */ + uint8_t partitions; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_C2C command CMD_C2C_START_HOTRESET + */ +struct cmd_c2c_start_hotreset_request { + /** @brief 1: partition 0; 2: partition 1; 3: partition 0 and 1; */ + uint8_t partitions; +} BPMP_ABI_PACKED; + +/** + * @brief Response data for #MRQ_C2C command CMD_C2C_START_HOTRESET + */ +struct cmd_c2c_start_hotreset_response { + /** @brief Refer to @ref bpmp_c2c_status */ + uint8_t status; +} BPMP_ABI_PACKED; + +/** + * @brief Request with #MRQ_C2C + * + * |sub-command |payload | + * |-----------------------------|-------------------------------| + * |CMD_C2C_QUERY_ABI |cmd_c2c_query_abi_request | + * |CMD_C2C_START_INITIALIZATION |cmd_c2c_start_init_request | + * |CMD_C2C_GET_STATUS | | + * |CMD_C2C_HOTRESET_PREP |cmd_c2c_hotreset_prep_request | + * |CMD_C2C_START_HOTRESET |cmd_c2c_start_hotreset_request | + + */ +struct mrq_c2c_request { + uint32_t cmd; + union { + struct cmd_c2c_query_abi_request c2c_query_abi_req; + struct cmd_c2c_start_init_request c2c_start_init_req; + struct cmd_c2c_hotreset_prep_request c2c_hotreset_prep_req; + struct cmd_c2c_start_hotreset_request c2c_start_hotreset_req; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** + * @brief Response to MRQ_C2C + * + * |sub-command |payload | + * |-----------------------------|--------------------------------| + * |CMD_C2C_QUERY_ABI | | + * |CMD_C2C_START_INITIALIZATION |cmd_c2c_start_init_response | + * |CMD_C2C_GET_STATUS |cmd_c2c_get_status_response | + * |CMD_C2C_HOTRESET_PREP | | + * |CMD_C2C_START_HOTRESET |cmd_c2c_start_hotreset_response | + */ +struct mrq_c2c_response { + union { + struct cmd_c2c_start_init_response c2c_start_init_resp; + struct cmd_c2c_get_status_response c2c_get_status_resp; + struct cmd_c2c_start_hotreset_response c2c_start_hotreset_resp; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; +/** @} */ +/** @endcond */ + + +/** @cond (bpmp_t264) + * @ingroup MRQ_Codes + * @def MRQ_PCIE + * @brief Perform a PCIE operation + * + * * Initiators: CCPLEX + * * Targets: BPMP + * * Request Payload: @ref mrq_pcie_request + * + * @addtogroup PCIE + * @{ + */ + +/** + * @brief Sub-command identifiers for #MRQ_PCIE. + */ +enum mrq_pcie_cmd { + /** @brief Initialize PCIE EP controller. */ + CMD_PCIE_EP_CONTROLLER_INIT = 0, + /** @brief Disable PCIE EP controller. */ + CMD_PCIE_EP_CONTROLLER_OFF = 1, + + /** @brief Disable PCIE RP controller. */ + CMD_PCIE_RP_CONTROLLER_OFF = 100, + + CMD_PCIE_MAX, +}; + +/** + * @brief Request payload for #MRQ_PCIE sub-command #CMD_PCIE_EP_CONTROLLER_INIT. + */ +struct cmd_pcie_ep_controller_init_request { + /** + * @brief PCIe EP controller number. + * Valid entries for T264 are 2, 4 and 5. + */ + uint8_t ep_controller; + /** + * @brief PCIe EP function programming interface code. + * Valid range in HW is [0, 0xFFU], BPMP-FW programs the input value without any check. + * It is up to the requester to send valid input as documented in "PCI CODE AND ID + * ASSIGNMENT SPECIFICATION". + */ + uint8_t progif_code; + /** + * @brief PCIe EP function sub-class code. + * Valid range in HW is [0, 0xFFU], BPMP-FW programs the input value without any check. + * It is up to the requester to send valid input as documented in "PCI CODE AND ID + * ASSIGNMENT SPECIFICATION". + */ + uint8_t subclass_code; + /** + * @brief PCIe EP function base class code. + * Valid range in HW is [0, 0xFFU], BPMP-FW programs the input value without any check. + * It is up to the requester to send valid input as documented in "PCI CODE AND ID + * ASSIGNMENT SPECIFICATION". + */ + uint8_t baseclass_code; + /** + * @brief PCIe EP function device id. + * Valid range is [0, 0x7FU], only LSB 7 bits are writable in 16-bit PCI device id. + * Valid range check is done on input value and returns -BPMP_EINVAL on failure. + */ + uint8_t deviceid; + /** + * @brief PCIe EP EP BAR1 size. + * Valid range is [6U, 16U], which translate to [64MB, 64GB] size. + * Valid range check is done on input value and returns -BPMP_EINVAL on failure. + */ + uint8_t bar1_size; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for #MRQ_PCIE sub-command #CMD_PCIE_EP_CONTROLLER_OFF. + */ +struct cmd_pcie_ep_controller_off_request { + /** @brief EP controller number, T264 valid: 2, 4, 5. */ + uint8_t ep_controller; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for #MRQ_PCIE sub-command #CMD_PCIE_RP_CONTROLLER_OFF. + */ +struct cmd_pcie_rp_controller_off_request { + /** @brief RP controller number, T264 valid: 1-5 */ + uint8_t rp_controller; +} BPMP_ABI_PACKED; + +/** + * @ingroup PCIE + * @brief Request payload for the #MRQ_PCIE command. + * + * Used by the sender of an #MRQ_PCIE message to control PCIE. + * Below table shows sub-commands with their corresponding payload data. + * + * |sub-command |payload | + * |--------------------------------------|-----------------------------------------| + * |#CMD_PCIE_EP_CONTROLLER_INIT |#cmd_pcie_ep_controller_init_request | + * |#CMD_PCIE_EP_CONTROLLER_OFF |#cmd_pcie_ep_controller_off_request | + * + * @cond (!bpmp_safe) + * + * The following additional MRQs are supported on non-functional-safety + * builds: + * |sub-command |payload | + * |--------------------------------------|-----------------------------------------| + * |#CMD_PCIE_RP_CONTROLLER_OFF |#cmd_pcie_rp_controller_off_request | + * + * @endcond + * + */ +struct mrq_pcie_request { + /** @brief Sub-command ID from @ref mrq_pcie_cmd. */ + uint32_t cmd; + + union { + struct cmd_pcie_ep_controller_init_request ep_ctrlr_init; + struct cmd_pcie_ep_controller_off_request ep_ctrlr_off; + /** @cond (!bpmp_safe) */ + struct cmd_pcie_rp_controller_off_request rp_ctrlr_off; + /** @endcond */ + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** @} PCIE */ +/** @endcond */ + +/** @cond (bpmp_t264) + * @ingroup MRQ_Codes + * @def MRQ_CR7 + * @brief Perform a CR7 operation + * + * * Initiators: CPU_S + * * Targets: BPMP + * * Request Payload: @ref mrq_cr7_request + * + * @addtogroup CR7 + * @{ + */ + +/** + * @brief Payload for #MRQ_CR7 + * 2 fields for future parameters are provided. These must be 0 currently. + */ +struct cmd_cr7_request { + uint32_t fld0; + uint32_t fld1; +} BPMP_ABI_PACKED; + +struct cmd_cr7_query_abi_request { + /** #MRQ_CR7 sub-command identifier from @ref mrq_cr7_cmd */ + uint32_t type; +} BPMP_ABI_PACKED; + +/** + * @brief Sub-command identifiers for #MRQ_CR7. + */ +enum mrq_cr7_cmd { + /** + * @brief Check whether the BPMP driver supports the specified request + * type + * + * mrq_response:: err is 0 if the specified request is supported and + * -#BPMP_ENODEV otherwise + */ + CMD_CR7_QUERY_ABI = 0, + + /** @brief Enter CR7 state on the package BPMP-FW is running on. */ + CMD_CR7_ENTRY = 1, + /** @brief Exit CR7 state on the package BPMP-FW is running on. */ + CMD_CR7_EXIT = 2, + + CMD_CR7_MAX, +}; + +/** + * @ingroup CR7 + * @brief #MRQ_CR7 structure + * + * |Sub-command |Payload | + * |----------------------------|---------------------------| + * |#CMD_CR7_QUERY_ABI | #cmd_cr7_query_abi_request| + * |#CMD_CR7_ENTRY | #cmd_cr7_request | + * |#CMD_CR7_EXIT | #cmd_cr7_request | + + */ +struct mrq_cr7_request { + /** @brief Sub-command ID from @ref mrq_cr7_cmd. */ + uint32_t cmd; + union { + struct cmd_cr7_query_abi_request query_abi; + struct cmd_cr7_request cr7_request; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** @} CR7 */ +/** @endcond */ + +/** @cond (bpmp_tb500) + * @ingroup MRQ_Codes + * @def MRQ_HWPM + * @brief Configure and query HWPM functionality + * + * * Initiators: CCPLEX + * * Targets: BPMP + * * Request Payload: @ref mrq_hwpm_request + * * Response Payload: @ref mrq_hwpm_response + * + * @addtogroup HWPM + * @{ + */ + +/** + * @brief Sub-command identifiers for #MRQ_HWPM. + */ +enum mrq_hwpm_cmd { + /** + * @brief Check whether the BPMP-FW supports the specified + * #MRQ_HWPM sub-command. + * + * mrq_response:err is 0 if the specified request is + * supported and -#BPMP_ENODEV otherwise. + */ + CMD_HWPM_QUERY_ABI = 1, + + /** + * @brief Configure IPMU triggers + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_HWPM is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_HWPM_IPMU_SET_TRIGGERS = 2, + + /** + * @brief Configure IPMU payloads and shifts + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_HWPM is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_HWPM_IPMU_SET_PAYLOADS_SHIFTS = 3, + + /** + * @brief Get maximum number of payloads + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_HWPM is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + */ + CMD_HWPM_IPMU_GET_MAX_PAYLOADS = 4, + + /** + * @brief Configure NVTHERM sample rate + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_HWPM is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_HWPM_NVTHERM_SET_SAMPLE_RATE = 5, + + /** + * @brief Set NVTHERM bubble interval + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_HWPM is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_HWPM_NVTHERM_SET_BUBBLE_INTERVAL = 6, + + /** + * @brief Configure NVTHERM DG flexible channels + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_HWPM is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_HWPM_NVTHERM_SET_FLEX_CHANNELS = 7, + + /** + * @brief Get ISENSE sensor name + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_HWPM is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_HWPM_ISENSE_GET_SENSOR_NAME = 8, + + /** + * @brief Get ISENSE sensor channel + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_HWPM is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_HWPM_ISENSE_GET_SENSOR_CHANNEL = 9, + + /** + * @brief Get ISENSE sensor scale factor + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_HWPM is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_HWPM_ISENSE_GET_SENSOR_SCALE_FACTOR = 10, + + /** + * @brief Get ISENSE sensor offset + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_HWPM is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + * | -#BPMP_ENODATA | No sensor offset. | + */ + CMD_HWPM_ISENSE_GET_SENSOR_OFFSET = 11, + + /** + * @brief Get ISENSE sum block name + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_HWPM is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_HWPM_ISENSE_GET_SUM_BLOCK_NAME = 12, + + /** + * @brief Get ISENSE sum input sensor IDs + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_HWPM is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_HWPM_ISENSE_GET_SUM_BLOCK_INPUTS = 13, + + /** + * @brief Largest supported #MRQ_HWPM sub-command identifier + 1 + */ + CMD_HWPM_MAX, +}; + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_QUERY_ABI + */ +struct cmd_hwpm_query_abi_req { + /** @brief Sub-command identifier from @ref mrq_hwpm_cmd */ + uint32_t cmd_code; +} BPMP_ABI_PACKED; + +/** + * @brief Maximum array length for IPMU trigger bitmask + */ +#define HWPM_IPMU_TRIGGER_ARR_LEN 28U + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_IPMU_SET_TRIGGERS + */ +struct cmd_hwpm_ipmu_set_triggers_req { + /** @brief IPMU physical ID + * + * @note Valid range from [0, MAX_CPU_CORES), see @ref bpmp_hwpm_core_config + */ + uint32_t ipmu_phys_id; + /** @brief Trigger bitmask, see @ref bpmp_ipmu_trigger_ids + * + * @note Setting a trigger bit will cause the associated trigger to + * generate an output packet from IPMU to the HWPM perfmux. + * @note Up to a maximum possible 896 triggers + */ + uint32_t triggers[HWPM_IPMU_TRIGGER_ARR_LEN]; +} BPMP_ABI_PACKED; + +/** + * @brief Array length for IPMU payload bitmask + */ +#define HWPM_IPMU_PAYLOAD_ARR_LEN 26U + +/** + * @brief Array length for IPMU payload shift bitmask + */ +#define HWPM_IPMU_SHIFT_ARR_LEN 2U + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_IPMU_SET_PAYLOADS_SHIFTS + */ +struct cmd_hwpm_ipmu_set_payloads_shifts_req { + /** @brief IPMU physical ID + * + * @note Valid range from [0, MAX_CPU_CORES), see @ref bpmp_hwpm_core_config + */ + uint32_t ipmu_phys_id; + /** @brief Payload bitmask, see @ref bpmp_ipmu_payload_ids + * + * @note Setting a payload bit will add the associated payload to the + * IPMU output packet. + * @note The maximum number of payloads is platform dependent, + * @see #CMD_HWPM_IPMU_GET_MAX_PAYLOADS + * @note To disable IPMU streaming on this instance, set all payload bits to 0. + * @note Up to a maximum of 832 available payloads + */ + uint32_t payloads[HWPM_IPMU_PAYLOAD_ARR_LEN]; + /** + * @brief Payload shift mask + * + * @note Setting the i-th shift bit will right-shift the + * i-th enabled payload by 1 bit. + * @note Up to a maximum of 64 simultaneous emitted payloads + */ + uint32_t shifts[HWPM_IPMU_SHIFT_ARR_LEN]; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_IPMU_GET_MAX_PAYLOADS + */ +struct cmd_hwpm_ipmu_get_max_payloads_req { + BPMP_ABI_EMPTY +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_NVTHERM_SET_SAMPLE_RATE + */ +struct cmd_hwpm_nvtherm_set_sample_rate_req { + /** @brief Sample rate in microseconds + * + * @note Requesting a sample rate of 0 will disable NVTHERM streaming. + */ + uint32_t sample_rate; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_NVTHERM_SET_BUBBLE_INTERVAL + */ +struct cmd_hwpm_nvtherm_set_bubble_interval_req { + /** @brief Bubble interval in microseconds */ + uint32_t bubble_interval; +} BPMP_ABI_PACKED; + +/** + * @brief Maximum array length for NVTHERM flexible channel bitmask + */ +#define HWPM_NVTHERM_FLEX_CHANNEL_ARR_LEN 29U + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_NVTHERM_SET_FLEX_CHANNELS + */ +struct cmd_hwpm_nvtherm_set_flex_channels_req { + /** @brief NVTHERM flexible channel bitmask + * + * @see #bpmp_nvtherm_flex_channel_ids + * + * @note Up to a maximum of 928 flexible channels + */ + uint32_t channels[HWPM_NVTHERM_FLEX_CHANNEL_ARR_LEN]; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_ISENSE_GET_SENSOR_NAME + */ +struct cmd_hwpm_isense_get_sensor_name_req { + /** @brief Sensor ID from @ref bpmp_isense_sensor_ids */ + uint32_t sensor_id; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_ISENSE_GET_SENSOR_CHANNEL + */ +struct cmd_hwpm_isense_get_sensor_channel_req { + /** @brief Sensor ID from @ref bpmp_isense_sensor_ids */ + uint32_t sensor_id; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_ISENSE_GET_SENSOR_SCALE_FACTOR + */ +struct cmd_hwpm_isense_get_sensor_scale_factor_req { + /** @brief Sensor ID from @ref bpmp_isense_sensor_ids */ + uint32_t sensor_id; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_ISENSE_GET_SENSOR_OFFSET + */ +struct cmd_hwpm_isense_get_sensor_offset_req { + /** @brief Sensor ID from @ref bpmp_isense_sensor_ids */ + uint32_t sensor_id; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_ISENSE_GET_SUM_BLOCK_NAME + */ +struct cmd_hwpm_isense_get_sum_block_name_req { + /** @brief Sum block index */ + uint32_t sum_block_index; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_HWPM sub-command #CMD_HWPM_ISENSE_GET_SUM_BLOCK_INPUTS + */ +struct cmd_hwpm_isense_get_sum_block_inputs_req { + /** @brief Sum block index */ + uint32_t sum_block_index; +} BPMP_ABI_PACKED; + +/** + * @brief Response data for #MRQ_HWPM sub-command #CMD_HWPM_IPMU_GET_MAX_PAYLOADS + */ +struct cmd_hwpm_ipmu_get_max_payloads_resp { + /** @brief Maximum number of payloads */ + uint32_t max_payloads; +} BPMP_ABI_PACKED; + +/** + * @brief Maximum array length for ISENSE sensor name + */ +#define HWPM_ISENSE_SENSOR_MAX_NAME_LEN 64U + +/** + * @brief Response data for #MRQ_HWPM sub-command #CMD_HWPM_ISENSE_GET_SENSOR_NAME + */ +struct cmd_hwpm_isense_get_sensor_name_resp { + /** @brief Sensor name */ + char sensor_name[HWPM_ISENSE_SENSOR_MAX_NAME_LEN]; +} BPMP_ABI_PACKED; + +/** + * @brief Response data for #MRQ_HWPM sub-command #CMD_HWPM_ISENSE_GET_SENSOR_CHANNEL + */ +struct cmd_hwpm_isense_get_sensor_channel_resp { + /** @brief Physical channel index */ + uint32_t channel_index; +} BPMP_ABI_PACKED; + +/** + * @brief Response data for #MRQ_HWPM sub-command #CMD_HWPM_ISENSE_GET_SENSOR_SCALE_FACTOR + */ +struct cmd_hwpm_isense_get_sensor_scale_factor_resp { + /** @brief Scale factor */ + float scale_factor; +} BPMP_ABI_PACKED; + +/** + * @brief Response data for #MRQ_HWPM sub-command #CMD_HWPM_ISENSE_GET_SENSOR_OFFSET + */ +struct cmd_hwpm_isense_get_sensor_offset_resp { + /** @brief Offset sensor ID */ + uint32_t offset_sensor_id; +} BPMP_ABI_PACKED; + +/** + * @brief Maximum array length for ISENSE sum name + */ +#define HWPM_ISENSE_SUM_BLOCK_MAX_NAME_LEN 64U + +/** + * @brief Response data for #MRQ_HWPM sub-command #CMD_HWPM_ISENSE_GET_SUM_BLOCK_NAME + */ +struct cmd_hwpm_isense_get_sum_block_name_resp { + /** @brief Sum block name */ + char sum_block_name[HWPM_ISENSE_SUM_BLOCK_MAX_NAME_LEN]; +} BPMP_ABI_PACKED; + +/** + * @brief Maximum array length for ISENSE sum block input sensor IDs + */ +#define HWPM_ISENSE_SUM_BLOCK_INPUTS_MAX 16U + +/** + * @brief Response data for #MRQ_HWPM sub-command #CMD_HWPM_ISENSE_GET_SUM_BLOCK_INPUTS + */ +struct cmd_hwpm_isense_get_sum_block_inputs_resp { + /** @brief Input channel indices; negative if no input is applied */ + int32_t input_channel_idx[HWPM_ISENSE_SUM_BLOCK_INPUTS_MAX]; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for the #MRQ_HWPM -command + * + * | Sub-command | Request payload | + * | ---------------------------------------- | -------------------------------------------- | + * | #CMD_HWPM_QUERY_ABI | #cmd_hwpm_query_abi_req | + * | #CMD_HWPM_IPMU_SET_TRIGGERS | #cmd_hwpm_ipmu_set_triggers_req | + * | #CMD_HWPM_IPMU_SET_PAYLOADS_SHIFTS | #cmd_hwpm_ipmu_set_payloads_shifts_req | + * | #CMD_HWPM_IPMU_GET_MAX_PAYLOADS | #cmd_hwpm_ipmu_get_max_payloads_req | + * | #CMD_HWPM_NVTHERM_SET_SAMPLE_RATE | #cmd_hwpm_nvtherm_set_sample_rate_req | + * | #CMD_HWPM_NVTHERM_SET_BUBBLE_INTERVAL | #cmd_hwpm_nvtherm_set_bubble_interval_req | + * | #CMD_HWPM_NVTHERM_SET_FLEX_CHANNELS | #cmd_hwpm_nvtherm_set_flex_channels_req | + * | #CMD_HWPM_ISENSE_GET_SENSOR_CHANNEL | #cmd_hwpm_isense_get_sensor_channel_req | + * | #CMD_HWPM_ISENSE_GET_SENSOR_SCALE_FACTOR | #cmd_hwpm_isense_get_sensor_scale_factor_req | + * | #CMD_HWPM_ISENSE_GET_SENSOR_OFFSET | #cmd_hwpm_isense_get_sensor_offset_req | + * | #CMD_HWPM_ISENSE_GET_SUM_BLOCK_NAME | #cmd_hwpm_isense_get_sum_block_name_req | + * | #CMD_HWPM_ISENSE_GET_SUM_BLOCK_INPUTS | #cmd_hwpm_isense_get_sum_block_inputs_req | + */ +struct mrq_hwpm_request { + uint32_t cmd; + union { + struct cmd_hwpm_query_abi_req query_abi; + struct cmd_hwpm_ipmu_set_triggers_req ipmu_set_triggers; + struct cmd_hwpm_ipmu_set_payloads_shifts_req ipmu_set_payloads_shifts; + struct cmd_hwpm_ipmu_get_max_payloads_req ipmu_get_max_payloads; + struct cmd_hwpm_nvtherm_set_sample_rate_req nvtherm_set_sample_rate; + struct cmd_hwpm_nvtherm_set_bubble_interval_req nvtherm_set_bubble_interval; + struct cmd_hwpm_nvtherm_set_flex_channels_req nvtherm_set_flex_channels; + struct cmd_hwpm_isense_get_sensor_name_req isense_get_sensor_name; + struct cmd_hwpm_isense_get_sensor_channel_req isense_get_sensor_channel; + struct cmd_hwpm_isense_get_sensor_scale_factor_req isense_get_sensor_scale_factor; + struct cmd_hwpm_isense_get_sensor_offset_req isense_get_sensor_offset; + struct cmd_hwpm_isense_get_sum_block_name_req isense_get_sum_block_name; + struct cmd_hwpm_isense_get_sum_block_inputs_req isense_get_sum_block_inputs; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** + * @brief Response payload for the #MRQ_HWPM -command + * + * | Sub-command | Response payload | + * | ---------------------------------------- | --------------------------------------------- | + * | #CMD_HWPM_QUERY_ABI | - | + * | #CMD_HWPM_IPMU_SET_TRIGGERS | - | + * | #CMD_HWPM_IPMU_SET_PAYLOADS_SHIFTS | - | + * | #CMD_HWPM_IPMU_GET_MAX_PAYLOADS | #cmd_hwpm_ipmu_get_max_payloads_resp | + * | #CMD_HWPM_NVTHERM_SET_SAMPLE_RATE | - | + * | #CMD_HWPM_NVTHERM_SET_BUBBLE_INTERVAL | - | + * | #CMD_HWPM_NVTHERM_SET_FLEX_CHANNELS | - | + * | #CMD_HWPM_ISENSE_GET_SENSOR_NAME | #cmd_hwpm_isense_get_sensor_name_resp | + * | #CMD_HWPM_ISENSE_GET_SENSOR_CHANNEL | #cmd_hwpm_isense_get_sensor_channel_resp | + * | #CMD_HWPM_ISENSE_GET_SENSOR_SCALE_FACTOR | #cmd_hwpm_isense_get_sensor_scale_factor_resp | + * | #CMD_HWPM_ISENSE_GET_SENSOR_OFFSET | #cmd_hwpm_isense_get_sensor_offset_resp | + * | #CMD_HWPM_ISENSE_GET_SUM_BLOCK_NAME | #cmd_hwpm_isense_get_sum_block_name_resp | + * | #CMD_HWPM_ISENSE_GET_SUM_BLOCK_INPUTS | #cmd_hwpm_isense_get_sum_block_inputs_resp | + */ +struct mrq_hwpm_response { + uint32_t err; + union { + struct cmd_hwpm_ipmu_get_max_payloads_resp ipmu_get_max_payloads; + struct cmd_hwpm_isense_get_sensor_name_resp isense_get_sensor_name; + struct cmd_hwpm_isense_get_sensor_channel_resp isense_get_sensor_channel; + struct cmd_hwpm_isense_get_sensor_scale_factor_resp isense_get_sensor_scale_factor; + struct cmd_hwpm_isense_get_sensor_offset_resp isense_get_sensor_offset; + struct cmd_hwpm_isense_get_sum_block_name_resp isense_get_sum_block_name; + struct cmd_hwpm_isense_get_sum_block_inputs_resp isense_get_sum_block_inputs; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** @} HWPM */ +/** @endcond */ + +/** @cond (bpmp_tb500) + * @ingroup MRQ_Codes + * @def MRQ_DVFS + * @brief Configure DVFS functionality + * + * * Initiators: CCPLEX + * * Targets: BPMP + * * Request Payload: @ref mrq_dvfs_request + * + * @addtogroup DVFS + * @{ + */ + +/** + * @brief Sub-command identifiers for #MRQ_DVFS. + */ +enum mrq_dvfs_cmd { + /** + * @brief Check whether the BPMP-FW supports the specified + * #MRQ_DVFS sub-command. + * + * mrq_response:err is 0 if the specified request is + * supported and -#BPMP_ENODEV otherwise. + */ + CMD_DVFS_QUERY_ABI = 1, + + /** + * @brief Configure DVFS controller + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_DVFS is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_DVFS_SET_CTRL_STATE = 2, + + /** + * @brief Configure DVFS manager + * + * mrq_response:err is defined as: + * + * | Value | Description | + * | -------------- | ------------------------------------------- | + * | 0 | Success | + * | -#BPMP_ENODEV | #MRQ_DVFS is not supported by BPMP-FW. | + * | -#BPMP_ENOTSUP | Subcommand is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_DVFS_SET_MGR_STATE = 3, + + /** + * @brief Largest supported #MRQ_DVFS sub-command identifier + 1 + */ + CMD_DVFS_MAX, +}; + +/** + * @brief Request data for #MRQ_DVFS sub-command #CMD_DVFS_QUERY_ABI + */ +struct cmd_dvfs_query_abi_req { + /** @brief Sub-command identifier from @ref mrq_dvfs_cmd */ + uint32_t cmd_code; +} BPMP_ABI_PACKED; + +struct cmd_dvfs_set_ctrl_state_req { + /** @brief Controller ID from @ref bpmp_dvfs_ctrl_ids */ + uint32_t ctrl_id; + /** @brief Controller enable state */ + uint32_t enable; +} BPMP_ABI_PACKED; + +struct cmd_dvfs_set_mgr_state_req { + /** @brief Manager ID from @ref bpmp_dvfs_mgr_ids */ + uint32_t mgr_id; + /** @brief Manager enable state */ + uint32_t enable; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for the #MRQ_DVFS -command + * + * | Sub-command | Request payload | + * | ---------------------------------------- | -------------------------------------------- | + * | #CMD_DVFS_QUERY_ABI | #cmd_dvfs_query_abi_req | + * | #CMD_DVFS_SET_CTRL_STATE | #cmd_dvfs_set_ctrl_state_req | + * | #CMD_DVFS_SET_MGR_STATE | #cmd_dvfs_set_mgr_state_req | + */ +struct mrq_dvfs_request { + uint32_t cmd; + union { + struct cmd_dvfs_query_abi_req query_abi; + struct cmd_dvfs_set_ctrl_state_req set_ctrl_state; + struct cmd_dvfs_set_mgr_state_req set_mgr_state; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** @} DVFS */ +/** @endcond */ + +/** @cond (bpmp_tb500) + * @ingroup MRQ_Codes + * @def MRQ_PPP_PROFILE + * @brief Get power/performance profile configuration settings. + * + * * Initiators: Any + * * Targets: BPMP + * * Request Payload: @ref mrq_ppp_profile_request + * * Response Payload: @ref mrq_ppp_profile_response + * + * @addtogroup PPP + * @{ + */ + +/** + * @brief Sub-command identifiers for #MRQ_PPP_PROFILE. + */ +enum mrq_ppp_profile_cmd { + /** + * @brief Check whether the BPMP-FW supports the specified + * #MRQ_PPP_PROFILE sub-command. + * + * mrq_ppp_profile_response:err is 0 if the specified request is + * supported and -#BPMP_ENOTSUP otherwise. + */ + + CMD_PPP_PROFILE_QUERY_ABI = 0, + /** + * @brief Query the BPMP for the CPU core and SLC slice configuration associated + * with a given Power/Performance Profile (PPP). + * + * mrq_ppp_profile_response:err is defined as: + * + * | Value | Description | + * |----------------|------------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENOTSUP | #MRQ_PPP_PROFILE is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_PPP_PROFILE_QUERY_MASKS = 1, + /** + * @brief Query BPMP for the CPU mask corresponding to a requested + * number of active CPU cores. + * + * mrq_ppp_profile_response:err is defined as: + * + * | Value | Description | + * |----------------|------------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENOTSUP | #MRQ_PPP_PROFILE is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_PPP_CORE_QUERY_CPU_MASK = 2, + /** + * @brief Query BPMP-FW for the currently available Power/Performance Profiles. + * + * mrq_ppp_profile_response:err is defined as: + * + * | Value | Description | + * |----------------|------------------------------------------------| + * | 0 | Success | + * | -#BPMP_ENOTSUP | #MRQ_PPP_PROFILE is not supported by BPMP-FW. | + * | -#BPMP_EINVAL | Invalid request parameters. | + */ + CMD_PPP_AVAILABLE_QUERY = 3, +}; + +/** + * @brief Request data for #MRQ_PPP_PROFILE sub-command + * #CMD_PPP_PROFILE_QUERY_ABI + */ +struct cmd_ppp_profile_query_abi_req { + /** @brief Sub-command identifier from @ref mrq_ppp_profile_cmd */ + uint32_t cmd_code; +} BPMP_ABI_PACKED; + +/** + * @brief Response data for #MRQ_PPP_PROFILE sub-command + * #CMD_PPP_AVAILABLE_QUERY + */ +struct cmd_ppp_available_query_resp { + /** + * @brief Bitmask of available profiles. + * Bit N = 1 ⇒ profile N is available + */ + uint32_t avail_ppp_mask; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_PPP_PROFILE sub-command + * #CMD_PPP_PROFILE_QUERY_MASKS + */ +struct cmd_ppp_profile_query_masks_req { + /** @brief power/perf profile identifier */ + uint32_t profile_id; +} BPMP_ABI_PACKED; + +/** + * @brief Response payload for #MRQ_PPP_PROFILE sub-command + * #CMD_PPP_PROFILE_QUERY_MASKS + */ +struct cmd_ppp_profile_query_masks_resp { + /** @brief Enabled cores in this profile */ + uint32_t num_active_cores; + /** @brief Enabled SLC slices in this profile */ + uint32_t num_active_slcs; + /** @brief Number of valid words in active_core_masks array */ + uint32_t max_num_core_words; + /** @brief Number of valid words in active_slc_masks array */ + uint32_t max_num_slc_words; + /** @brief Enabled cores bit mask (bit N = 1 => core N enabled) */ + uint32_t active_core_masks[8]; + /** @brief Enabled SLC slices bit mask (bit N = 1 => SLC slice N enabled) */ + uint32_t active_slc_masks[8]; +} BPMP_ABI_PACKED; + +/** + * @brief Request data for #MRQ_PPP_PROFILE sub-command + * #CMD_PPP_CORE_QUERY_CPU_MASK + */ +struct cmd_ppp_core_query_cpu_mask_req { + /** @brief Requested number of active cores */ + uint32_t num_cores; +} BPMP_ABI_PACKED; + +/** + * @brief Response data for #MRQ_PPP_PROFILE sub-command + * #CMD_PPP_CORE_QUERY_CPU_MASK + */ +struct cmd_ppp_core_query_cpu_mask_resp { + /** @brief Number of valid words in active_core_masks array */ + uint32_t max_num_words; + /** @brief Enabled CPU core bitmask (bit N = 1 ⇒ core N enabled) */ + uint32_t active_core_masks[8]; +} BPMP_ABI_PACKED; + +/** + * @brief Request payload for the #MRQ_PPP_PROFILE -command + * + * | Sub-command | Request payload | + * |-------------------------------|----------------------------------------| + * | #CMD_PPP_PROFILE_QUERY_ABI | #cmd_ppp_profile_query_abi_req | + * | #CMD_PPP_PROFILE_QUERY_MASKS | #cmd_ppp_profile_query_masks_req | + * | #CMD_PPP_CORE_QUERY_CPU_MASK | #cmd_ppp_core_query_cpu_mask_req | + * | #CMD_PPP_AVAILABLE_QUERY | - | + */ +struct mrq_ppp_profile_request { + /** @brief Sub-command ID from @ref mrq_ppp_profile_cmd. */ + uint32_t cmd; + union { + struct cmd_ppp_profile_query_abi_req query_abi; + struct cmd_ppp_profile_query_masks_req ppp_profile_masks_req; + struct cmd_ppp_core_query_cpu_mask_req ppp_core_mask_req; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** + * @brief Response payload for the #MRQ_PPP_PROFILE -command. + * + * | Sub-command | Response payload | + * |-------------------------------|----------------------------------------| + * | #CMD_PPP_PROFILE_QUERY_ABI | - | + * | #CMD_PPP_PROFILE_QUERY_MASKS | #cmd_ppp_profile_query_masks_resp | + * | #CMD_PPP_CORE_QUERY_CPU_MASK | #cmd_ppp_core_query_cpu_mask_resp | + * | #CMD_PPP_AVAILABLE_QUERY | #cmd_ppp_available_query_resp | + */ +struct mrq_ppp_profile_response { + uint32_t err; + union { + struct cmd_ppp_profile_query_masks_resp ppp_profile_masks_resp; + struct cmd_ppp_core_query_cpu_mask_resp ppp_core_mask_resp; + struct cmd_ppp_available_query_resp ppp_avail_query_resp; + } BPMP_UNION_ANON; +} BPMP_ABI_PACKED; + +/** @} PPP */ +/** @endcond */ /** * @addtogroup Error_Codes @@ -3953,6 +6728,8 @@ struct mrq_gears_response { #define BPMP_ENOSYS 38 /** @brief Invalid slot */ #define BPMP_EBADSLT 57 +/** @brief No data */ +#define BPMP_ENODATA 61 /** @brief Invalid message */ #define BPMP_EBADMSG 77 /** @brief Operation not supported */ From 77344118720e31dcbac47d13c35da3b1de663529 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 26 Mar 2026 14:58:49 +0100 Subject: [PATCH 149/193] firmware: tegra: bpmp: Add tegra_bpmp_get_with_id() function Some device tree bindings need to specify a parameter along with a BPMP phandle reference to designate the ID associated with a given controller that needs to interoperate with BPMP. Typically this is specified as an extra cell in the nvidia,bpmp property, so add a helper to parse this ID while resolving the phandle reference. Signed-off-by: Thierry Reding --- drivers/firmware/tegra/bpmp.c | 34 ++++++++++++++++++++++++++++++++++ include/soc/tegra/bpmp.h | 8 ++++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c index e74bba7ccc44..753472b53bd8 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c @@ -32,6 +32,40 @@ channel_to_ops(struct tegra_bpmp_channel *channel) return bpmp->soc->ops; } +struct tegra_bpmp *tegra_bpmp_get_with_id(struct device *dev, unsigned int *id) +{ + struct platform_device *pdev; + struct of_phandle_args args; + struct tegra_bpmp *bpmp; + int err; + + err = __of_parse_phandle_with_args(dev->of_node, "nvidia,bpmp", NULL, + 1, 0, &args); + if (err < 0) + return ERR_PTR(err); + + pdev = of_find_device_by_node(args.np); + if (!pdev) { + bpmp = ERR_PTR(-ENODEV); + goto put; + } + + bpmp = platform_get_drvdata(pdev); + if (!bpmp) { + bpmp = ERR_PTR(-EPROBE_DEFER); + put_device(&pdev->dev); + goto put; + } + + if (id) + *id = args.args[0]; + +put: + of_node_put(args.np); + return bpmp; +} +EXPORT_SYMBOL_GPL(tegra_bpmp_get_with_id); + struct tegra_bpmp *tegra_bpmp_get(struct device *dev) { struct platform_device *pdev; diff --git a/include/soc/tegra/bpmp.h b/include/soc/tegra/bpmp.h index f5e4ac5b8cce..822851ef4bf8 100644 --- a/include/soc/tegra/bpmp.h +++ b/include/soc/tegra/bpmp.h @@ -127,6 +127,7 @@ struct tegra_bpmp_message { #if IS_ENABLED(CONFIG_TEGRA_BPMP) struct tegra_bpmp *tegra_bpmp_get(struct device *dev); +struct tegra_bpmp *tegra_bpmp_get_with_id(struct device *dev, unsigned int *id); void tegra_bpmp_put(struct tegra_bpmp *bpmp); int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp, struct tegra_bpmp_message *msg); @@ -145,6 +146,13 @@ static inline struct tegra_bpmp *tegra_bpmp_get(struct device *dev) { return ERR_PTR(-ENOTSUPP); } + +static inline struct tegra_bpmp *tegra_bpmp_get_with_id(struct device *dev, + unsigned int *id) +{ + return ERR_PTR(-ENODEV); +} + static inline void tegra_bpmp_put(struct tegra_bpmp *bpmp) { } From d4e0199bb5545acdfe5ce9d8046f4f35c95d6b8a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 23 Feb 2026 15:32:56 +0100 Subject: [PATCH 150/193] dt-bindings: phy: tegra-xusb: Document Type C support Each XUSB PHY can be hooked up to a Type C controller via a port property, so document this in the bindings accordingly. Reviewed-by: Rob Herring (Arm) Signed-off-by: Thierry Reding --- .../phy/nvidia,tegra194-xusb-padctl.yaml | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/phy/nvidia,tegra194-xusb-padctl.yaml b/Documentation/devicetree/bindings/phy/nvidia,tegra194-xusb-padctl.yaml index 6e3398399628..d8de900a4fce 100644 --- a/Documentation/devicetree/bindings/phy/nvidia,tegra194-xusb-padctl.yaml +++ b/Documentation/devicetree/bindings/phy/nvidia,tegra194-xusb-padctl.yaml @@ -230,6 +230,10 @@ properties: connector: type: object + port: + description: connection to a USB Type C controller + $ref: /schemas/graph.yaml#/properties/port + mode: description: A string that determines the mode in which to run the port. @@ -256,7 +260,12 @@ properties: voltage. dependencies: - usb-role-switch: [ connector ] + usb-role-switch: + oneOf: + - required: + - connector + - required: + - port usb2-1: type: object @@ -268,6 +277,10 @@ properties: connector: type: object + port: + description: connection to a USB Type C controller + $ref: /schemas/graph.yaml#/properties/port + mode: description: A string that determines the mode in which to run the port. @@ -306,6 +319,10 @@ properties: connector: type: object + port: + description: connection to a USB Type C controller + $ref: /schemas/graph.yaml#/properties/port + mode: description: A string that determines the mode in which to run the port. @@ -344,6 +361,10 @@ properties: connector: type: object + port: + description: connection to a USB Type C controller + $ref: /schemas/graph.yaml#/properties/port + mode: description: A string that determines the mode in which to run the port. @@ -405,6 +426,10 @@ properties: description: A phandle to the regulator supplying the VBUS voltage. + port: + description: connection to a USB Type C controller + $ref: /schemas/graph.yaml#/properties/port + usb3-1: type: object additionalProperties: false @@ -438,6 +463,10 @@ properties: description: A phandle to the regulator supplying the VBUS voltage. + port: + description: connection to a USB Type C controller + $ref: /schemas/graph.yaml#/properties/port + usb3-2: type: object additionalProperties: false @@ -471,6 +500,10 @@ properties: description: A phandle to the regulator supplying the VBUS voltage. + port: + description: connection to a USB Type C controller + $ref: /schemas/graph.yaml#/properties/port + usb3-3: type: object additionalProperties: false @@ -504,6 +537,10 @@ properties: description: A phandle to the regulator supplying the VBUS voltage. + port: + description: connection to a USB Type C controller + $ref: /schemas/graph.yaml#/properties/port + additionalProperties: false required: From 6413bfc1f6aea376d953760f5dacc59cef481bdc Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 23 Feb 2026 15:32:58 +0100 Subject: [PATCH 151/193] dt-bindings: clock: tegra124-dfll: Convert to json-schema Convert the Tegra124 (and later) DFLL bindings from the free-form text format to json-schema. Co-developed-by: Rob Herring (Arm) Signed-off-by: Rob Herring (Arm) Reviewed-by: Rob Herring (Arm) Signed-off-by: Thierry Reding --- .../bindings/clock/nvidia,tegra124-dfll.txt | 155 ---------- .../bindings/clock/nvidia,tegra124-dfll.yaml | 290 ++++++++++++++++++ 2 files changed, 290 insertions(+), 155 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt create mode 100644 Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.yaml diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt deleted file mode 100644 index f7d347385b57..000000000000 --- a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt +++ /dev/null @@ -1,155 +0,0 @@ -NVIDIA Tegra124 DFLL FCPU clocksource - -This binding uses the common clock binding: -Documentation/devicetree/bindings/clock/clock-bindings.txt - -The DFLL IP block on Tegra is a root clocksource designed for clocking -the fast CPU cluster. It consists of a free-running voltage controlled -oscillator connected to the CPU voltage rail (VDD_CPU), and a closed loop -control module that will automatically adjust the VDD_CPU voltage by -communicating with an off-chip PMIC either via an I2C bus or via PWM signals. - -Required properties: -- compatible : should be one of: - - "nvidia,tegra124-dfll": for Tegra124 - - "nvidia,tegra210-dfll": for Tegra210 -- reg : Defines the following set of registers, in the order listed: - - registers for the DFLL control logic. - - registers for the I2C output logic. - - registers for the integrated I2C master controller. - - look-up table RAM for voltage register values. -- interrupts: Should contain the DFLL block interrupt. -- clocks: Must contain an entry for each entry in clock-names. - See clock-bindings.txt for details. -- clock-names: Must include the following entries: - - soc: Clock source for the DFLL control logic. - - ref: The closed loop reference clock - - i2c: Clock source for the integrated I2C master. -- resets: Must contain an entry for each entry in reset-names. - See ../reset/reset.txt for details. -- reset-names: Must include the following entries: - - dvco: Reset control for the DFLL DVCO. -- #clock-cells: Must be 0. -- clock-output-names: Name of the clock output. -- vdd-cpu-supply: Regulator for the CPU voltage rail that the DFLL - hardware will start controlling. The regulator will be queried for - the I2C register, control values and supported voltages. - -Required properties for the control loop parameters: -- nvidia,sample-rate: Sample rate of the DFLL control loop. -- nvidia,droop-ctrl: See the register CL_DVFS_DROOP_CTRL in the TRM. -- nvidia,force-mode: See the field DFLL_PARAMS_FORCE_MODE in the TRM. -- nvidia,cf: Numeric value, see the field DFLL_PARAMS_CF_PARAM in the TRM. -- nvidia,ci: Numeric value, see the field DFLL_PARAMS_CI_PARAM in the TRM. -- nvidia,cg: Numeric value, see the field DFLL_PARAMS_CG_PARAM in the TRM. - -Optional properties for the control loop parameters: -- nvidia,cg-scale: Boolean value, see the field DFLL_PARAMS_CG_SCALE in the TRM. - -Optional properties for mode selection: -- nvidia,pwm-to-pmic: Use PWM to control regulator rather then I2C. - -Required properties for I2C mode: -- nvidia,i2c-fs-rate: I2C transfer rate, if using full speed mode. - -Required properties for PWM mode: -- nvidia,pwm-period-nanoseconds: period of PWM square wave in nanoseconds. -- nvidia,pwm-tristate-microvolts: Regulator voltage in micro volts when PWM - control is disabled and the PWM output is tristated. Note that this voltage is - configured in hardware, typically via a resistor divider. -- nvidia,pwm-min-microvolts: Regulator voltage in micro volts when PWM control - is enabled and PWM output is low. Hence, this is the minimum output voltage - that the regulator supports when PWM control is enabled. -- nvidia,pwm-voltage-step-microvolts: Voltage increase in micro volts - corresponding to a 1/33th increase in duty cycle. Eg the voltage for 2/33th - duty cycle would be: nvidia,pwm-min-microvolts + - nvidia,pwm-voltage-step-microvolts * 2. -- pinctrl-0: I/O pad configuration when PWM control is enabled. -- pinctrl-1: I/O pad configuration when PWM control is disabled. -- pinctrl-names: must include the following entries: - - dvfs_pwm_enable: I/O pad configuration when PWM control is enabled. - - dvfs_pwm_disable: I/O pad configuration when PWM control is disabled. - -Example for I2C: - -clock@70110000 { - compatible = "nvidia,tegra124-dfll"; - reg = <0 0x70110000 0 0x100>, /* DFLL control */ - <0 0x70110000 0 0x100>, /* I2C output control */ - <0 0x70110100 0 0x100>, /* Integrated I2C controller */ - <0 0x70110200 0 0x100>; /* Look-up table RAM */ - interrupts = ; - clocks = <&tegra_car TEGRA124_CLK_DFLL_SOC>, - <&tegra_car TEGRA124_CLK_DFLL_REF>, - <&tegra_car TEGRA124_CLK_I2C5>; - clock-names = "soc", "ref", "i2c"; - resets = <&tegra_car TEGRA124_RST_DFLL_DVCO>; - reset-names = "dvco"; - #clock-cells = <0>; - clock-output-names = "dfllCPU_out"; - vdd-cpu-supply = <&vdd_cpu>; - - nvidia,sample-rate = <12500>; - nvidia,droop-ctrl = <0x00000f00>; - nvidia,force-mode = <1>; - nvidia,cf = <10>; - nvidia,ci = <0>; - nvidia,cg = <2>; - - nvidia,i2c-fs-rate = <400000>; -}; - -Example for PWM: - -clock@70110000 { - compatible = "nvidia,tegra124-dfll"; - reg = <0 0x70110000 0 0x100>, /* DFLL control */ - <0 0x70110000 0 0x100>, /* I2C output control */ - <0 0x70110100 0 0x100>, /* Integrated I2C controller */ - <0 0x70110200 0 0x100>; /* Look-up table RAM */ - interrupts = ; - clocks = <&tegra_car TEGRA210_CLK_DFLL_SOC>, - <&tegra_car TEGRA210_CLK_DFLL_REF>, - <&tegra_car TEGRA124_CLK_I2C5>;; - clock-names = "soc", "ref", "i2c"; - resets = <&tegra_car TEGRA124_RST_DFLL_DVCO>; - reset-names = "dvco"; - #clock-cells = <0>; - clock-output-names = "dfllCPU_out"; - - nvidia,sample-rate = <25000>; - nvidia,droop-ctrl = <0x00000f00>; - nvidia,force-mode = <1>; - nvidia,cf = <6>; - nvidia,ci = <0>; - nvidia,cg = <2>; - - nvidia,pwm-min-microvolts = <708000>; /* 708mV */ - nvidia,pwm-period-nanoseconds = <2500>; /* 2.5us */ - nvidia,pwm-to-pmic; - nvidia,pwm-tristate-microvolts = <1000000>; - nvidia,pwm-voltage-step-microvolts = <19200>; /* 19.2mV */ - - pinctrl-names = "dvfs_pwm_enable", "dvfs_pwm_disable"; - pinctrl-0 = <&dvfs_pwm_active_state>; - pinctrl-1 = <&dvfs_pwm_inactive_state>; -}; - -/* pinmux nodes added for completeness. Binding doc can be found in: - * Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.yaml - */ - -pinmux: pinmux@700008d4 { - dvfs_pwm_active_state: dvfs_pwm_active { - dvfs_pwm_pbb1 { - nvidia,pins = "dvfs_pwm_pbb1"; - nvidia,tristate = ; - }; - }; - dvfs_pwm_inactive_state: dvfs_pwm_inactive { - dvfs_pwm_pbb1 { - nvidia,pins = "dvfs_pwm_pbb1"; - nvidia,tristate = ; - }; - }; -}; diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.yaml b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.yaml new file mode 100644 index 000000000000..5d689e48c438 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.yaml @@ -0,0 +1,290 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/nvidia,tegra124-dfll.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra124 (and later) DFLL FCPU clocksource + +maintainers: + - Thierry Reding + - Jon Hunter + +description: + The DFLL IP block on Tegra is a root clocksource designed for clocking + the fast CPU cluster. It consists of a free-running voltage controlled + oscillator connected to the CPU voltage rail (VDD_CPU), and a closed + loop control module that will automatically adjust the VDD_CPU voltage + by communicating with an off-chip PMIC either via an I2C bus or via + PWM signals. + +properties: + compatible: + enum: + - nvidia,tegra124-dfll + - nvidia,tegra210-dfll + + reg: + items: + - description: DFLL control logic + - description: I2C output logic + - description: Integrated I2C controller + - description: Look-up table RAM for voltage register values + + interrupts: + maxItems: 1 + + "#clock-cells": + const: 0 + + clocks: + items: + - description: Clock source for the DFLL control logic + - description: Closed loop reference clock + - description: Clock source for the integrated I2C controller + + clock-names: + items: + - const: soc + - const: ref + - const: i2c + + clock-output-names: + description: Name of the clock output + items: + - const: dfllCPU_out + + resets: + minItems: 1 + maxItems: 2 + + reset-names: + minItems: 1 + items: + - const: dvco + - const: dfll + + vdd-cpu-supply: + description: Regulator for the CPU voltage rail that the DFLL + hardware will start controlling. The regulator will be queried for + the I2C register, control values and supported voltages. + + nvidia,sample-rate: + description: Sample rate of the DFLL control loop + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 12500 + maximum: 25000 + + nvidia,droop-ctrl: + description: Droop control parameter (CL_DVFS_DROOP_CTRL) in the TRM + $ref: /schemas/types.yaml#/definitions/uint32 + + nvidia,force-mode: + description: See the field DFLL_PARAMS_FORCE_MODE in the TRM + $ref: /schemas/types.yaml#/definitions/uint32 + oneOf: + - description: disabled + const: 0 + - description: fixed delay mode + const: 1 + - description: auto mode + const: 2 + + nvidia,cf: + description: Numeric value, see the field DFLL_PARAMS_CF_PARAM in the TRM + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 63 + + nvidia,ci: + description: Numeric value, see the field DFLL_PARAMS_CI_PARAM in the TRM + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 7 + + nvidia,cg: + description: Numeric value, see the field DFLL_PARAMS_CG_PARAM in the TRM + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + + # optional properties + nvidia,cg-scale: + description: Boolean value, see the field DFLL_PARAMS_CG_SCALE in the TRM + $ref: /schemas/types.yaml#/definitions/flag + + nvidia,pwm-to-pmic: + description: Use PWM to control regulator rather than I2C + $ref: /schemas/types.yaml#/definitions/flag + + nvidia,i2c-fs-rate: + description: I2C transfer rate, if using full speed mode + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [100000, 400000] + + # required properties for PWM mode + nvidia,pwm-period-nanoseconds: + description: Period of PWM square wave in nanoseconds + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1000 + maximum: 1000000000 + + nvidia,pwm-tristate-microvolts: + description: Regulator voltage in microvolts when PWM control is disabled + and the PWM output is tristated. Note that this voltage is configured in + hardware, typically via a resistor divider. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 3300000 + + nvidia,pwm-min-microvolts: + description: Regulator voltage in microvolts when PWM control is enabled + and PWM output is low. Hence, this is the minimum output voltage that + the regulator supports when PWM control is enabled. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 3300000 + + nvidia,pwm-voltage-step-microvolts: + description: | + Voltage increase in micro volts corresponding to a 1/33th increase + in duty cycle. For example, the voltage for 2/33th duty cycle would be: + + nvidia,pwm-min-microvolts + nvidia,pwm-voltage-step-microvolts * 2 + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 100000 + + pinctrl-0: + description: I/O pad configuration when PWM control is enabled + + pinctrl-1: + description: I/O pad configuration when PWM control is disabled + + pinctrl-names: + items: + - const: dvfs_pwm_enable + - const: dvfs_pwm_disable + +required: + - compatible + - reg + - interrupts + - "#clock-cells" + - clocks + - clock-names + - clock-output-names + - resets + - reset-names + - nvidia,sample-rate + - nvidia,droop-ctrl + - nvidia,force-mode + - nvidia,cf + - nvidia,ci + - nvidia,cg + +additionalProperties: false + +allOf: + - if: + properties: + compatible: + contains: + const: nvidia,tegra124-dfll + then: + properties: + resets: + maxItems: 1 + + reset-names: + maxItems: 1 + else: + properties: + resets: + minItems: 2 + + reset-names: + minItems: 2 + + - if: + required: + - nvidia,pwm-to-pmic + then: + required: + - nvidia,pwm-min-microvolts + - nvidia,pwm-period-nanoseconds + - nvidia,pwm-tristate-microvolts + - nvidia,pwm-voltage-step-microvolts + else: + required: + - vdd-cpu-supply + +examples: + - | + #include + #include + #include + + clock@70110000 { + compatible = "nvidia,tegra124-dfll"; + reg = <0x70110000 0x100>, /* DFLL control */ + <0x70110000 0x100>, /* I2C output control */ + <0x70110100 0x100>, /* Integrated I2C controller */ + <0x70110200 0x100>; /* Look-up table RAM */ + interrupts = ; + clocks = <&tegra_car TEGRA124_CLK_DFLL_SOC>, + <&tegra_car TEGRA124_CLK_DFLL_REF>, + <&tegra_car TEGRA124_CLK_I2C5>; + clock-names = "soc", "ref", "i2c"; + resets = <&tegra_car TEGRA124_RST_DFLL_DVCO>; + reset-names = "dvco"; + #clock-cells = <0>; + clock-output-names = "dfllCPU_out"; + vdd-cpu-supply = <&vdd_cpu>; + + nvidia,sample-rate = <12500>; + nvidia,droop-ctrl = <0x00000f00>; + nvidia,force-mode = <1>; + nvidia,cf = <10>; + nvidia,ci = <0>; + nvidia,cg = <2>; + + nvidia,i2c-fs-rate = <400000>; + }; + + - | + #include + #include + #include + + clock@70110000 { + compatible = "nvidia,tegra210-dfll"; + reg = <0x70110000 0x100>, /* DFLL control */ + <0x70110000 0x100>, /* I2C output control */ + <0x70110100 0x100>, /* Integrated I2C controller */ + <0x70110200 0x100>; /* Look-up table RAM */ + interrupts = ; + clocks = <&tegra_car TEGRA210_CLK_DFLL_SOC>, + <&tegra_car TEGRA210_CLK_DFLL_REF>, + <&tegra_car TEGRA210_CLK_I2C5>; + clock-names = "soc", "ref", "i2c"; + resets = <&tegra_car TEGRA210_RST_DFLL_DVCO>, + <&tegra_car 155>; + reset-names = "dvco", "dfll"; + #clock-cells = <0>; + clock-output-names = "dfllCPU_out"; + vdd-cpu-supply = <&vdd_cpu>; + + nvidia,sample-rate = <25000>; + nvidia,droop-ctrl = <0x00000f00>; + nvidia,force-mode = <1>; + nvidia,cf = <6>; + nvidia,ci = <0>; + nvidia,cg = <2>; + + nvidia,pwm-min-microvolts = <708000>; /* 708mV */ + nvidia,pwm-period-nanoseconds = <2500>; /* 2.5us */ + nvidia,pwm-to-pmic; + nvidia,pwm-tristate-microvolts = <1000000>; + nvidia,pwm-voltage-step-microvolts = <19200>; /* 19.2mV */ + }; From cafacd15e84d0b8163f2df92555a265e0b84e236 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 23 Feb 2026 15:32:59 +0100 Subject: [PATCH 152/193] dt-bindings: interrupt-controller: tegra: Fix reg entries Tegra210 takes exactly 6 "reg" property entries, as opposed to Tegra30 which supports only 5 entries. Reviewed-by: Rob Herring (Arm) Signed-off-by: Thierry Reding --- .../nvidia,tegra20-ictlr.yaml | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra20-ictlr.yaml b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra20-ictlr.yaml index 074a873880e5..d0c039d14ad2 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra20-ictlr.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra20-ictlr.yaml @@ -35,11 +35,12 @@ properties: - enum: - nvidia,tegra20-ictlr - nvidia,tegra30-ictlr + - nvidia,tegra210-ictlr reg: description: Each entry is a block of 32 interrupts minItems: 4 - maxItems: 5 + maxItems: 6 interrupt-controller: true @@ -64,10 +65,28 @@ allOf: properties: reg: maxItems: 4 - else: + + - if: + properties: + compatible: + contains: + const: nvidia,tegra30-ictlr + then: properties: reg: minItems: 5 + maxItems: 5 + + - if: + properties: + compatible: + contains: + const: nvidia,tegra210-ictlr + then: + properties: + reg: + minItems: 6 + maxItems: 6 examples: - | From 37420acce494ca69e30c0a98e868f357ae2509f5 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 23 Feb 2026 15:33:00 +0100 Subject: [PATCH 153/193] dt-bindings: arm: tegra: Add missing compatible strings The Nyan Blaze and Nyan Big, as well as Jetson Nano (P3450-0000), Darcy (P2894-0050-A08) and Pixel C (Smaug) were never mentioned. Add them. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Thierry Reding --- .../devicetree/bindings/arm/tegra.yaml | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/tegra.yaml b/Documentation/devicetree/bindings/arm/tegra.yaml index 50a31dba7bec..07e225a4d69b 100644 --- a/Documentation/devicetree/bindings/arm/tegra.yaml +++ b/Documentation/devicetree/bindings/arm/tegra.yaml @@ -131,6 +131,33 @@ properties: - const: toradex,apalis-tk1-v1.2 - const: toradex,apalis-tk1 - const: nvidia,tegra124 + - items: + - const: google,nyan-big-rev7 + - const: google,nyan-big-rev6 + - const: google,nyan-big-rev5 + - const: google,nyan-big-rev4 + - const: google,nyan-big-rev3 + - const: google,nyan-big-rev2 + - const: google,nyan-big-rev1 + - const: google,nyan-big-rev0 + - const: google,nyan-big + - const: google,nyan + - const: nvidia,tegra124 + - items: + - const: google,nyan-blaze-rev10 + - const: google,nyan-blaze-rev9 + - const: google,nyan-blaze-rev8 + - const: google,nyan-blaze-rev7 + - const: google,nyan-blaze-rev6 + - const: google,nyan-blaze-rev5 + - const: google,nyan-blaze-rev4 + - const: google,nyan-blaze-rev3 + - const: google,nyan-blaze-rev2 + - const: google,nyan-blaze-rev1 + - const: google,nyan-blaze-rev0 + - const: google,nyan-blaze + - const: google,nyan + - const: nvidia,tegra124 - items: - enum: - nvidia,norrin @@ -184,17 +211,35 @@ properties: - const: nvidia,tegra124 - items: - enum: - - nvidia,darcy - nvidia,p2371-0000 - nvidia,p2371-2180 - nvidia,p2571 - - nvidia,p2894-0050-a08 - - nvidia,p3450-0000 - const: nvidia,tegra210 - items: - const: nvidia,p3541-0000 - const: nvidia,p3450-0000 - const: nvidia,tegra210 + - description: NVIDIA Jetson Nano + items: + - const: nvidia,p3450-0000 + - const: nvidia,tegra210 + - description: NVIDIA Shield TV + items: + - const: nvidia,p2894-0050-a08 + - const: nvidia,darcy + - const: nvidia,tegra210 + - description: Google Pixel C + items: + - const: google,smaug-rev8 + - const: google,smaug-rev7 + - const: google,smaug-rev6 + - const: google,smaug-rev5 + - const: google,smaug-rev4 + - const: google,smaug-rev3 + - const: google,smaug-rev2 + - const: google,smaug-rev1 + - const: google,smaug + - const: nvidia,tegra210 - description: Jetson TX2 Developer Kit items: - const: nvidia,p2771-0000 From 99250f7553ea8e09b160ac290f5f22ac986e7c4a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 23 Feb 2026 15:33:01 +0100 Subject: [PATCH 154/193] dt-bindings: phy: tegra: Document Tegra210 USB PHY Add a compatible string for the USB PHY found on Tegra210 SoCs. Acked-by: Rob Herring (Arm) Signed-off-by: Thierry Reding --- .../devicetree/bindings/phy/nvidia,tegra20-usb-phy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/phy/nvidia,tegra20-usb-phy.yaml b/Documentation/devicetree/bindings/phy/nvidia,tegra20-usb-phy.yaml index d61585c96e31..a37e8322dc50 100644 --- a/Documentation/devicetree/bindings/phy/nvidia,tegra20-usb-phy.yaml +++ b/Documentation/devicetree/bindings/phy/nvidia,tegra20-usb-phy.yaml @@ -16,6 +16,7 @@ properties: oneOf: - items: - enum: + - nvidia,tegra210-usb-phy - nvidia,tegra124-usb-phy - nvidia,tegra114-usb-phy - enum: From 834e6bd48dd440b292d741138a7a87118ae9d95a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 23 Feb 2026 15:33:02 +0100 Subject: [PATCH 155/193] dt-bindings: memory: Add Tegra210 memory controller bindings Document the bindings for the memory controller found on Tegra210 SoCs. Reviewed-by: Rob Herring (Arm) Signed-off-by: Thierry Reding --- .../nvidia,tegra210-mc.yaml | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 Documentation/devicetree/bindings/memory-controllers/nvidia,tegra210-mc.yaml diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra210-mc.yaml b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra210-mc.yaml new file mode 100644 index 000000000000..268d5ff958f9 --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra210-mc.yaml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/memory-controllers/nvidia,tegra210-mc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra210 SoC Memory Controller + +maintainers: + - Thierry Reding + - Jon Hunter + +description: | + The NVIDIA Tegra210 SoC features a 64 bit memory controller that is split + into two 32 bit channels to support LPDDR3 and LPDDR4 with x16 subpartitions. + The MC handles memory requests for 34-bit virtual addresses from internal + clients and arbitrates among them to allocate memory bandwidth. + + Up to 8 GiB of physical memory can be supported. Security features such as + encryption of traffic to and from DRAM via general security apertures are + available for video and other secure applications. + +properties: + $nodename: + pattern: "^memory-controller@[0-9a-f]+$" + + compatible: + items: + - enum: + - nvidia,tegra210-mc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: module clock + + clock-names: + items: + - const: mc + + "#iommu-cells": + const: 1 + + "#reset-cells": + const: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - "#iommu-cells" + - "#reset-cells" + +additionalProperties: false + +examples: + - | + #include + #include + + memory-controller@70019000 { + compatible = "nvidia,tegra210-mc"; + reg = <0x70019000 0x1000>; + interrupts = ; + clocks = <&tegra_car TEGRA210_CLK_MC>; + clock-names = "mc"; + + #iommu-cells = <1>; + #reset-cells = <1>; + }; From ffff5e7275516f274fac53ab5496f26481b4b1b9 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 23 Feb 2026 15:33:03 +0100 Subject: [PATCH 156/193] dt-bindings: memory: tegra210: Mark EMC as cooling device The external memory controller found on Tegra210 can use throttling of the EMC frequency in order to reduce the memory chip temperature. Mark the memory controller as a cooling device to take advantage of this functionality. Reviewed-by: Rob Herring Signed-off-by: Thierry Reding --- .../bindings/memory-controllers/nvidia,tegra210-emc.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra210-emc.yaml b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra210-emc.yaml index 4e4fb4acd7f9..7a653a011f03 100644 --- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra210-emc.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra210-emc.yaml @@ -52,6 +52,9 @@ properties: Should contain freqs and voltages and opp-supported-hw property, which is a bitfield indicating SoC speedo ID mask. +allOf: + - $ref: /schemas/thermal/thermal-cooling-devices.yaml + required: - compatible - reg @@ -59,7 +62,7 @@ required: - clock-names - nvidia,memory-controller -additionalProperties: false +unevaluatedProperties: false examples: - | @@ -90,4 +93,5 @@ examples: operating-points-v2 = <&dvfs_opp_table>; #interconnect-cells = <0>; + #cooling-cells = <2>; }; From c65fe807b8469210b17461dd71b7bc0a1db37765 Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Wed, 25 Mar 2026 18:27:25 +0530 Subject: [PATCH 157/193] dt-bindings: arm: tegra: Add Tegra238 CBB compatible strings Add compatible strings for CBB v2.0 based fabrics (APE, AON, BPMP and CBB) on Tegra238. Signed-off-by: Sumit Gupta Acked-by: Krzysztof Kozlowski Signed-off-by: Thierry Reding --- .../devicetree/bindings/arm/tegra/nvidia,tegra234-cbb.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra234-cbb.yaml b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra234-cbb.yaml index fcdf03131323..e69ee6a48fcc 100644 --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra234-cbb.yaml +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra234-cbb.yaml @@ -48,6 +48,10 @@ properties: - nvidia,tegra234-dce-fabric - nvidia,tegra234-rce-fabric - nvidia,tegra234-sce-fabric + - nvidia,tegra238-ape-fabric + - nvidia,tegra238-aon-fabric + - nvidia,tegra238-bpmp-fabric + - nvidia,tegra238-cbb-fabric reg: maxItems: 1 From be09645037b43dffb2efe3c1b6c408ce0ed70c1c Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Mon, 23 Feb 2026 08:54:59 +0200 Subject: [PATCH 158/193] dt-bindings: display: tegra: Document Tegra20 HDMI port Tegra HDMI can be modeled using an OF graph. Reflect this in the bindings. Signed-off-by: Svyatoslav Ryhel Reviewed-by: Rob Herring (Arm) Signed-off-by: Thierry Reding --- .../bindings/display/tegra/nvidia,tegra20-hdmi.yaml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-hdmi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-hdmi.yaml index f77197e4869f..b4bf2662780b 100644 --- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-hdmi.yaml +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-hdmi.yaml @@ -82,6 +82,10 @@ properties: description: phandle of a display panel $ref: /schemas/types.yaml#/definitions/phandle + port: + description: HDMI output port for connection to HDMI connector or bridge + $ref: /schemas/graph.yaml#/properties/port + "#sound-dai-cells": const: 0 @@ -97,8 +101,13 @@ required: - reset-names - pll-supply - vdd-supply - - nvidia,ddc-i2c-bus - - nvidia,hpd-gpio + +anyOf: + - required: + - nvidia,ddc-i2c-bus + - nvidia,hpd-gpio + - required: + - port examples: - | From e68d494b8946e9060e60427f365107194f90ba0d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 26 Mar 2026 12:28:31 +0100 Subject: [PATCH 159/193] soc/tegra: bpmp: Use ENODEV instead of ENOTSUPP ENOTSUPP is not a SUSV4 error code and checkpatch will warn about it. It is also not very descriptive in the context of BPMP, so use the ENODEV error code instead. For the stub implementations this is a more accurate description of what the failure is. Signed-off-by: Thierry Reding --- include/soc/tegra/bpmp.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/include/soc/tegra/bpmp.h b/include/soc/tegra/bpmp.h index 822851ef4bf8..a33582590a3b 100644 --- a/include/soc/tegra/bpmp.h +++ b/include/soc/tegra/bpmp.h @@ -144,7 +144,7 @@ bool tegra_bpmp_mrq_is_supported(struct tegra_bpmp *bpmp, unsigned int mrq); #else static inline struct tegra_bpmp *tegra_bpmp_get(struct device *dev) { - return ERR_PTR(-ENOTSUPP); + return ERR_PTR(-ENODEV); } static inline struct tegra_bpmp *tegra_bpmp_get_with_id(struct device *dev, @@ -156,16 +156,19 @@ static inline struct tegra_bpmp *tegra_bpmp_get_with_id(struct device *dev, static inline void tegra_bpmp_put(struct tegra_bpmp *bpmp) { } + static inline int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp, struct tegra_bpmp_message *msg) { - return -ENOTSUPP; + return -ENODEV; } + static inline int tegra_bpmp_transfer(struct tegra_bpmp *bpmp, struct tegra_bpmp_message *msg) { - return -ENOTSUPP; + return -ENODEV; } + static inline void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code, const void *data, size_t size) @@ -177,8 +180,9 @@ static inline int tegra_bpmp_request_mrq(struct tegra_bpmp *bpmp, tegra_bpmp_mrq_handler_t handler, void *data) { - return -ENOTSUPP; + return -ENODEV; } + static inline void tegra_bpmp_free_mrq(struct tegra_bpmp *bpmp, unsigned int mrq, void *data) { From 8e2a2f5851d33f99a475c1dbd8eae74ef72c517c Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Mon, 26 Jan 2026 21:20:30 +0200 Subject: [PATCH 160/193] soc/tegra: pmc: Enable core domain support for Tegra114 Enable core domain support for Tegra114 since now it has power domains fully configured. Signed-off-by: Svyatoslav Ryhel Reviewed-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index a1a2966512d1..05ea52589342 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -3635,7 +3635,7 @@ static const u8 tegra114_cpu_powergates[] = { }; static const struct tegra_pmc_soc tegra114_pmc_soc = { - .supports_core_domain = false, + .supports_core_domain = true, .num_powergates = ARRAY_SIZE(tegra114_powergates), .powergates = tegra114_powergates, .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates), From 656275069fad4bd90b39d5fc163cc5757986900d Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Mon, 26 Jan 2026 21:02:06 +0200 Subject: [PATCH 161/193] soc/tegra: common: Add Tegra114 support to devm_tegra_core_dev_init_opp_table Determine the Tegra114 hardware version using the SoC Speedo ID bit macro, mirroring the approach already used for Tegra30 and Tegra124. Signed-off-by: Svyatoslav Ryhel Reviewed-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/soc/tegra/common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c index d82b7670abb7..0864eb0185b4 100644 --- a/drivers/soc/tegra/common.c +++ b/drivers/soc/tegra/common.c @@ -118,7 +118,8 @@ int devm_tegra_core_dev_init_opp_table(struct device *dev, hw_version = BIT(tegra_sku_info.soc_process_id); config.supported_hw = &hw_version; config.supported_hw_count = 1; - } else if (of_machine_is_compatible("nvidia,tegra30")) { + } else if (of_machine_is_compatible("nvidia,tegra30") || + of_machine_is_compatible("nvidia,tegra114")) { hw_version = BIT(tegra_sku_info.soc_speedo_id); config.supported_hw = &hw_version; config.supported_hw_count = 1; @@ -131,7 +132,7 @@ int devm_tegra_core_dev_init_opp_table(struct device *dev, } /* - * Tegra114+ doesn't support OPP yet, return early for non tegra20/30 + * Tegra124+ doesn't support OPP yet, return early for pre-Tegra124 * case. */ if (!config.supported_hw) From 21669619e4c17a5f097e0415bc64b1d400c54fcb Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 25 Mar 2026 19:25:51 +0000 Subject: [PATCH 162/193] soc/tegra: pmc: Add kerneldoc for reboot notifier Commit 48b7f802fb78 ("soc/tegra: pmc: Embed reboot notifier in PMC context") added the reboot_notifier structure to the PMC SoC structure but did not update the kerneldoc accordingly. Add this missing kerneldoc description to fix this. Fixes: 48b7f802fb78 ("soc/tegra: pmc: Embed reboot notifier in PMC context") Signed-off-by: Jon Hunter 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 05ea52589342..402e21c6edc8 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -437,6 +437,7 @@ struct tegra_pmc_soc { * @wake_sw_status_map: Bitmap to hold raw status of wakes without mask * @wake_cntrl_level_map: Bitmap to hold wake levels to be programmed in * cntrl register associated with each wake during system suspend. + * @reboot_notifier: PMC reboot notifier handler * @syscore: syscore suspend/resume callbacks */ struct tegra_pmc { From ec0e4da5d679f9da1cc198927951f70fdf28f001 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 25 Mar 2026 19:25:52 +0000 Subject: [PATCH 163/193] soc/tegra: pmc: Correct function names in kerneldoc Commit 70f752ebb08c ("soc/tegra: pmc: Add PMC contextual functions") added the functions devm_tegra_pmc_get() and tegra_pmc_io_pad_power_enable(), but the names of the functions in the associated kerneldoc is incorrect. Update the kerneldoc for these functions to correct their names. Fixes: 70f752ebb08c ("soc/tegra: pmc: Add PMC contextual functions") Signed-off-by: Jon Hunter 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 402e21c6edc8..1bcc06553bac 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -1005,7 +1005,7 @@ static struct tegra_pmc *tegra_pmc_get(struct device *dev) } /** - * tegra_pmc_get() - find the PMC for a given device + * devm_tegra_pmc_get() - find the PMC for a given device * @dev: device for which to find the PMC * * Returns a pointer to the PMC on success or an ERR_PTR()-encoded error code @@ -1747,7 +1747,7 @@ static void tegra_io_pad_unprepare(struct tegra_pmc *pmc) } /** - * tegra_io_pad_power_enable() - enable power to I/O pad + * tegra_pmc_io_pad_power_enable() - enable power to I/O pad * @pmc: power management controller * @id: Tegra I/O pad ID for which to enable power * From e6ad1988e56834d641ba4aa0d58970723c1c9c9b Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 25 Mar 2026 19:25:53 +0000 Subject: [PATCH 164/193] soc/tegra: pmc: Add kerneldoc for wake-up variables Commit e6d96073af68 ("soc/tegra: pmc: Fix unsafe generic_handle_irq() call") added the variables 'wake_work' and 'wake_status' to the 'tegra_pmc' structure but did not add the associated kerneldoc for these new variables. Add the kerneldoc for these variables. Fixes: e6d96073af68 ("soc/tegra: pmc: Fix unsafe generic_handle_irq() call") Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 1bcc06553bac..036c764de2e6 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -439,6 +439,8 @@ struct tegra_pmc_soc { * cntrl register associated with each wake during system suspend. * @reboot_notifier: PMC reboot notifier handler * @syscore: syscore suspend/resume callbacks + * @wake_work: IRQ work handler for processing wake-up events. + * @wake_status: Status of wake-up events. */ struct tegra_pmc { struct device *dev; From 8b3e944ee16ce9061b632ccab207e9a9dd540ad9 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 25 Mar 2026 19:25:54 +0000 Subject: [PATCH 165/193] soc/tegra: pmc: Remove unused AOWAKE definitions For Tegra264, the offsets for the AOWAKE registers have changed. Before adding support for the Tegra264 AOWAKE register offsets, remove the unused AOWAKE definitions. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 036c764de2e6..dbbf9d4b19b8 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -181,11 +181,8 @@ #define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3) #define WAKE_AOWAKE_CNTRL_SR_CAPTURE_EN (1 << 1) #define WAKE_AOWAKE_MASK_W(x) (0x180 + ((x) << 2)) -#define WAKE_AOWAKE_MASK_R(x) (0x300 + ((x) << 2)) #define WAKE_AOWAKE_STATUS_W(x) (0x30c + ((x) << 2)) #define WAKE_AOWAKE_STATUS_R(x) (0x48c + ((x) << 2)) -#define WAKE_AOWAKE_TIER0_ROUTING(x) (0x4b4 + ((x) << 2)) -#define WAKE_AOWAKE_TIER1_ROUTING(x) (0x4c0 + ((x) << 2)) #define WAKE_AOWAKE_TIER2_ROUTING(x) (0x4cc + ((x) << 2)) #define WAKE_AOWAKE_SW_STATUS_W_0 0x49c #define WAKE_AOWAKE_SW_STATUS(x) (0x4a0 + ((x) << 2)) From 5f87dac89270f7bf5c65eaa2dc884ba1fa2de4e2 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 25 Mar 2026 19:25:55 +0000 Subject: [PATCH 166/193] soc/tegra: pmc: Add support for SoC specific AOWAKE offsets For Tegra264, some of the AOWAKE registers have different register offsets. Prepare for adding the Tegra264 AOWAKE register by moving the offsets for the AOWAKE registers that are different for Tegra264 into the 'tegra_pmc_regs' structure and populate these offsets for the SoCs that support these registers. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 84 +++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 24 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index dbbf9d4b19b8..07678c53aa24 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -180,16 +180,18 @@ #define WAKE_AOWAKE_CNTRL(x) (0x000 + ((x) << 2)) #define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3) #define WAKE_AOWAKE_CNTRL_SR_CAPTURE_EN (1 << 1) -#define WAKE_AOWAKE_MASK_W(x) (0x180 + ((x) << 2)) -#define WAKE_AOWAKE_STATUS_W(x) (0x30c + ((x) << 2)) -#define WAKE_AOWAKE_STATUS_R(x) (0x48c + ((x) << 2)) -#define WAKE_AOWAKE_TIER2_ROUTING(x) (0x4cc + ((x) << 2)) -#define WAKE_AOWAKE_SW_STATUS_W_0 0x49c -#define WAKE_AOWAKE_SW_STATUS(x) (0x4a0 + ((x) << 2)) -#define WAKE_LATCH_SW 0x498 +#define WAKE_AOWAKE_MASK_W(_pmc, x) \ + ((_pmc)->soc->regs->aowake_mask_w + ((x) << 2)) +#define WAKE_AOWAKE_STATUS_W(_pmc, x) \ + ((_pmc)->soc->regs->aowake_status_w + ((x) << 2)) +#define WAKE_AOWAKE_STATUS_R(_pmc, x) \ + ((_pmc)->soc->regs->aowake_status_r + ((x) << 2)) +#define WAKE_AOWAKE_TIER2_ROUTING(_pmc, x) \ + ((_pmc)->soc->regs->aowake_tier2_routing + ((x) << 2)) +#define WAKE_AOWAKE_SW_STATUS(_pmc, x) \ + ((_pmc)->soc->regs->aowake_sw_status + ((x) << 2)) -#define WAKE_AOWAKE_CTRL 0x4f4 -#define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0) +#define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0) #define SW_WAKE_ID 83 /* wake83 */ @@ -302,6 +304,14 @@ struct tegra_pmc_regs { unsigned int rst_source_mask; unsigned int rst_level_shift; unsigned int rst_level_mask; + unsigned int aowake_mask_w; + unsigned int aowake_status_w; + unsigned int aowake_status_r; + unsigned int aowake_tier2_routing; + unsigned int aowake_sw_status_w; + unsigned int aowake_sw_status; + unsigned int aowake_latch_sw; + unsigned int aowake_ctrl; }; struct tegra_wake_event { @@ -2629,20 +2639,20 @@ static int tegra186_pmc_irq_set_wake(struct irq_data *data, unsigned int on) bit = data->hwirq % 32; /* clear wake status */ - writel(0x1, pmc->wake + WAKE_AOWAKE_STATUS_W(data->hwirq)); + writel(0x1, pmc->wake + WAKE_AOWAKE_STATUS_W(pmc, data->hwirq)); /* route wake to tier 2 */ - value = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(offset)); + value = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(pmc, offset)); if (!on) value &= ~(1 << bit); else value |= 1 << bit; - writel(value, pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(offset)); + writel(value, pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(pmc, offset)); /* enable wakeup event */ - writel(!!on, pmc->wake + WAKE_AOWAKE_MASK_W(data->hwirq)); + writel(!!on, pmc->wake + WAKE_AOWAKE_MASK_W(pmc, data->hwirq)); return 0; } @@ -3309,7 +3319,7 @@ static void wke_write_wake_levels(struct tegra_pmc *pmc) static void wke_clear_sw_wake_status(struct tegra_pmc *pmc) { - wke_32kwritel(pmc, 1, WAKE_AOWAKE_SW_STATUS_W_0); + wke_32kwritel(pmc, 1, pmc->soc->regs->aowake_sw_status_w); } static void wke_read_sw_wake_status(struct tegra_pmc *pmc) @@ -3322,7 +3332,7 @@ static void wke_read_sw_wake_status(struct tegra_pmc *pmc) wke_clear_sw_wake_status(pmc); - wke_32kwritel(pmc, 1, WAKE_LATCH_SW); + wke_32kwritel(pmc, 1, pmc->soc->regs->aowake_latch_sw); /* * WAKE_AOWAKE_SW_STATUS is edge triggered, so in order to @@ -3340,12 +3350,12 @@ static void wke_read_sw_wake_status(struct tegra_pmc *pmc) */ udelay(300); - wke_32kwritel(pmc, 0, WAKE_LATCH_SW); + wke_32kwritel(pmc, 0, pmc->soc->regs->aowake_latch_sw); bitmap_zero(pmc->wake_sw_status_map, pmc->soc->max_wake_events); for (i = 0; i < pmc->soc->max_wake_vectors; i++) { - status = readl(pmc->wake + WAKE_AOWAKE_SW_STATUS(i)); + status = readl(pmc->wake + WAKE_AOWAKE_SW_STATUS(pmc, i)); for_each_set_bit(wake, &status, 32) set_bit(wake + (i * 32), pmc->wake_sw_status_map); @@ -3359,11 +3369,12 @@ static void wke_clear_wake_status(struct tegra_pmc *pmc) u32 mask; for (i = 0; i < pmc->soc->max_wake_vectors; i++) { - mask = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(i)); - status = readl(pmc->wake + WAKE_AOWAKE_STATUS_R(i)) & mask; + mask = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(pmc, i)); + status = readl(pmc->wake + WAKE_AOWAKE_STATUS_R(pmc, i)) & mask; for_each_set_bit(wake, &status, 32) - wke_32kwritel(pmc, 0x1, WAKE_AOWAKE_STATUS_W((i * 32) + wake)); + wke_32kwritel(pmc, 0x1, WAKE_AOWAKE_STATUS_W(pmc, + (i * 32) + wake)); } } @@ -3374,8 +3385,9 @@ static void tegra186_pmc_wake_syscore_resume(void *data) u32 mask; for (i = 0; i < pmc->soc->max_wake_vectors; i++) { - mask = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(i)); - pmc->wake_status[i] = readl(pmc->wake + WAKE_AOWAKE_STATUS_R(i)) & mask; + mask = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(pmc, i)); + pmc->wake_status[i] = readl(pmc->wake + + WAKE_AOWAKE_STATUS_R(pmc, i)) & mask; } /* Schedule IRQ work to process wake IRQs (if any) */ @@ -4062,6 +4074,14 @@ static const struct tegra_pmc_regs tegra186_pmc_regs = { .rst_source_mask = 0x3c, .rst_level_shift = 0x0, .rst_level_mask = 0x3, + .aowake_mask_w = 0x180, + .aowake_status_w = 0x30c, + .aowake_status_r = 0x48c, + .aowake_tier2_routing = 0x4cc, + .aowake_sw_status_w = 0x49c, + .aowake_sw_status = 0x4a0, + .aowake_latch_sw = 0x498, + .aowake_ctrl = 0x4f4, }; static void tegra186_pmc_init(struct tegra_pmc *pmc) @@ -4094,14 +4114,14 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc, return; } - value = readl(wake + WAKE_AOWAKE_CTRL); + value = readl(wake + pmc->soc->regs->aowake_ctrl); if (invert) value |= WAKE_AOWAKE_CTRL_INTR_POLARITY; else value &= ~WAKE_AOWAKE_CTRL_INTR_POLARITY; - writel(value, wake + WAKE_AOWAKE_CTRL); + writel(value, wake + pmc->soc->regs->aowake_ctrl); iounmap(wake); } @@ -4281,6 +4301,14 @@ static const struct tegra_pmc_regs tegra194_pmc_regs = { .rst_source_mask = 0x7c, .rst_level_shift = 0x0, .rst_level_mask = 0x3, + .aowake_mask_w = 0x180, + .aowake_status_w = 0x30c, + .aowake_status_r = 0x48c, + .aowake_tier2_routing = 0x4cc, + .aowake_sw_status_w = 0x49c, + .aowake_sw_status = 0x4a0, + .aowake_latch_sw = 0x498, + .aowake_ctrl = 0x4f4, }; static const char * const tegra194_reset_sources[] = { @@ -4400,6 +4428,14 @@ static const struct tegra_pmc_regs tegra234_pmc_regs = { .rst_source_mask = 0xfc, .rst_level_shift = 0x0, .rst_level_mask = 0x3, + .aowake_mask_w = 0x180, + .aowake_status_w = 0x30c, + .aowake_status_r = 0x48c, + .aowake_tier2_routing = 0x4cc, + .aowake_sw_status_w = 0x49c, + .aowake_sw_status = 0x4a0, + .aowake_latch_sw = 0x498, + .aowake_ctrl = 0x4f4, }; static const char * const tegra234_reset_sources[] = { From bc8b07878cef6273aa1135630cad05227a4b223b Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 25 Mar 2026 19:25:56 +0000 Subject: [PATCH 167/193] soc/tegra: pmc: Add AOWAKE regs for Tegra264 Populate the AOWAKE register offsets for Tegra264. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 07678c53aa24..379bd622f8ff 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -4538,6 +4538,14 @@ static const struct tegra_pmc_regs tegra264_pmc_regs = { .rst_source_mask = 0x1fc, .rst_level_shift = 0x0, .rst_level_mask = 0x3, + .aowake_mask_w = 0x200, + .aowake_status_w = 0x410, + .aowake_status_r = 0x610, + .aowake_tier2_routing = 0x660, + .aowake_sw_status_w = 0x624, + .aowake_sw_status = 0x628, + .aowake_latch_sw = 0x620, + .aowake_ctrl = 0x68c, }; static const char * const tegra264_reset_sources[] = { From 91d5b17fd387d9822ef9fa64e8dd2c1d231c9aca Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 25 Mar 2026 19:25:57 +0000 Subject: [PATCH 168/193] soc/tegra: pmc: Add Tegra264 wake events Populate the various wake events for the Tegra264 device. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 379bd622f8ff..b4c85b65d8da 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -60,6 +60,7 @@ #include #include #include +#include #include #define PMC_CNTRL 0x0 @@ -4639,6 +4640,16 @@ static const char * const tegra264_reset_sources[] = { }; static const struct tegra_wake_event tegra264_wake_events[] = { + TEGRA_WAKE_IRQ("pmu", 0, 727), + TEGRA_WAKE_GPIO("power", 5, 1, TEGRA264_AON_GPIO(AA, 5)), + TEGRA_WAKE_IRQ("rtc", 65, 548), + TEGRA_WAKE_IRQ("usb3-port-0", 79, 965), + TEGRA_WAKE_IRQ("usb3-port-1", 80, 965), + TEGRA_WAKE_IRQ("usb3-port-3", 82, 965), + TEGRA_WAKE_IRQ("usb2-port-0", 83, 965), + TEGRA_WAKE_IRQ("usb2-port-1", 84, 965), + TEGRA_WAKE_IRQ("usb2-port-2", 85, 965), + TEGRA_WAKE_IRQ("usb2-port-3", 86, 965), }; static const struct tegra_pmc_soc tegra264_pmc_soc = { From edded7a9033a77c9b8a66176daa5e0b601e7c474 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 25 Mar 2026 19:25:58 +0000 Subject: [PATCH 169/193] soc/tegra: pmc: Refactor IO pad voltage control For Tegra devices, only a subset of IO pads can be configured for 1.8V or 3.3V. Therefore, in the 'tegra_io_pad_soc' structure for Tegra SoCs either all or most of the 'voltage' entries are set to UINT_MAX to indicate the IO pad voltage cannot be configured. So for the majority of IO pads this configuration is not applicable. However, refactoring the IO pad data to move this parameter into a separate structure does not make sense because the benefits are marginal. Support for the Tegra264 IO pads is currently missing and the control for configuring the voltage for the IO pads for Tegra264 has changed. Instead of having a single register that is used for setting the IO pad voltage for all IO pads, there is now a register associated with the specific IO pad. For Tegra264, there is now only one IO pad that can be configured for 1.8V or 3.3V which is the sdmmc1-hv. While we could make this work with by adding a new SoC flag, the implementation will be a bit cumbersome. Therefore, it now seems reasonable to refactor the IO pad code. Hence, introduce a new 'tegra_io_pad_vctrl' structure that contains the register offset and bit for enabling/disabling 3.3V mode and move the existing voltage control data for supported SoCs to this structure. This has an added benefit of simplifying the code in the functions tegra_io_pad_get_voltage and tegra_io_pad_set_voltage. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 471 ++++++++++++++++++++++------------------ 1 file changed, 261 insertions(+), 210 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index b4c85b65d8da..ac026e2560f9 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -294,10 +294,15 @@ struct tegra_io_pad_soc { unsigned int dpd; unsigned int request; unsigned int status; - unsigned int voltage; const char *name; }; +struct tegra_io_pad_vctrl { + enum tegra_io_pad id; + unsigned int offset; + unsigned int ena_3v3; +}; + struct tegra_pmc_regs { unsigned int scratch0; unsigned int rst_status; @@ -372,6 +377,8 @@ struct tegra_pmc_soc { const struct tegra_io_pad_soc *io_pads; unsigned int num_io_pads; + const struct tegra_io_pad_vctrl *io_pad_vctrls; + unsigned int num_io_pad_vctrls; const struct pinctrl_pin_desc *pin_descs; unsigned int num_pin_descs; @@ -1699,6 +1706,18 @@ tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id) return NULL; } +static const struct tegra_io_pad_vctrl * +tegra_io_pad_vctrl_find(struct tegra_pmc *pmc, enum tegra_io_pad id) +{ + unsigned int i; + + for (i = 0; i < pmc->soc->num_io_pad_vctrls; i++) + if (pmc->soc->io_pad_vctrls[i].id == id) + return &pmc->soc->io_pad_vctrls[i]; + + return NULL; +} + static int tegra_io_pad_prepare(struct tegra_pmc *pmc, const struct tegra_io_pad_soc *pad, unsigned long *request, @@ -1894,44 +1913,31 @@ static int tegra_io_pad_is_powered(struct tegra_pmc *pmc, enum tegra_io_pad id) static int tegra_io_pad_set_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id, int voltage) { - const struct tegra_io_pad_soc *pad; + const struct tegra_io_pad_vctrl *pad; u32 value; - pad = tegra_io_pad_find(pmc, id); + pad = tegra_io_pad_vctrl_find(pmc, id); if (!pad) return -ENOENT; - if (pad->voltage == UINT_MAX) - return -ENOTSUPP; - mutex_lock(&pmc->powergates_lock); - if (pmc->soc->has_impl_33v_pwr) { - value = tegra_pmc_readl(pmc, PMC_IMPL_E_33V_PWR); - - if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8) - value &= ~BIT(pad->voltage); - else - value |= BIT(pad->voltage); - - tegra_pmc_writel(pmc, value, PMC_IMPL_E_33V_PWR); - } else { - /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */ + if (!pmc->soc->has_impl_33v_pwr) { + /* write-enable PMC_PWR_DET_VALUE[pad->ena_3v3] */ value = tegra_pmc_readl(pmc, PMC_PWR_DET); - value |= BIT(pad->voltage); + value |= BIT(pad->ena_3v3); tegra_pmc_writel(pmc, value, PMC_PWR_DET); - - /* update I/O voltage */ - value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE); - - if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8) - value &= ~BIT(pad->voltage); - else - value |= BIT(pad->voltage); - - tegra_pmc_writel(pmc, value, PMC_PWR_DET_VALUE); } + value = tegra_pmc_readl(pmc, pad->offset); + + if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8) + value &= ~BIT(pad->ena_3v3); + else + value |= BIT(pad->ena_3v3); + + tegra_pmc_writel(pmc, value, pad->offset); + mutex_unlock(&pmc->powergates_lock); usleep_range(100, 250); @@ -1941,22 +1947,16 @@ static int tegra_io_pad_set_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id, static int tegra_io_pad_get_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id) { - const struct tegra_io_pad_soc *pad; + const struct tegra_io_pad_vctrl *pad; u32 value; - pad = tegra_io_pad_find(pmc, id); + pad = tegra_io_pad_vctrl_find(pmc, id); if (!pad) return -ENOENT; - if (pad->voltage == UINT_MAX) - return -ENOTSUPP; + value = tegra_pmc_readl(pmc, pad->offset); - if (pmc->soc->has_impl_33v_pwr) - value = tegra_pmc_readl(pmc, PMC_IMPL_E_33V_PWR); - else - value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE); - - if ((value & BIT(pad->voltage)) == 0) + if ((value & BIT(pad->ena_3v3)) == 0) return TEGRA_IO_PAD_VOLTAGE_1V8; return TEGRA_IO_PAD_VOLTAGE_3V3; @@ -3710,16 +3710,22 @@ static const u8 tegra124_cpu_powergates[] = { TEGRA_POWERGATE_CPU3, }; -#define TEGRA_IO_PAD(_id, _dpd, _request, _status, _voltage, _name) \ +#define TEGRA_IO_PAD(_id, _dpd, _request, _status, _name) \ ((struct tegra_io_pad_soc) { \ .id = (_id), \ .dpd = (_dpd), \ .request = (_request), \ .status = (_status), \ - .voltage = (_voltage), \ .name = (_name), \ }) +#define TEGRA_IO_PAD_VCTRL(_id, _offset, _ena_3v3) \ + ((struct tegra_io_pad_vctrl) { \ + .id = (_id), \ + .offset = (_offset), \ + .ena_3v3 = (_ena_3v3), \ + }) + #define TEGRA_IO_PIN_DESC(_id, _name) \ ((struct pinctrl_pin_desc) { \ .number = (_id), \ @@ -3727,36 +3733,36 @@ static const u8 tegra124_cpu_powergates[] = { }) static const struct tegra_io_pad_soc tegra124_io_pads[] = { - TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO, 17, 0x1b8, 0x1bc, UINT_MAX, "audio"), - TEGRA_IO_PAD(TEGRA_IO_PAD_BB, 15, 0x1b8, 0x1bc, UINT_MAX, "bb"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CAM, 4, 0x1c0, 0x1c4, UINT_MAX, "cam"), - TEGRA_IO_PAD(TEGRA_IO_PAD_COMP, 22, 0x1b8, 0x1bc, UINT_MAX, "comp"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x1b8, 0x1bc, UINT_MAX, "csia"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x1b8, 0x1bc, UINT_MAX, "csib"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 12, 0x1c0, 0x1c4, UINT_MAX, "csie"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DSI, 2, 0x1b8, 0x1bc, UINT_MAX, "dsi"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DSIB, 7, 0x1c0, 0x1c4, UINT_MAX, "dsib"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DSIC, 8, 0x1c0, 0x1c4, UINT_MAX, "dsic"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DSID, 9, 0x1c0, 0x1c4, UINT_MAX, "dsid"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI, 28, 0x1b8, 0x1bc, UINT_MAX, "hdmi"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HSIC, 19, 0x1b8, 0x1bc, UINT_MAX, "hsic"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HV, 6, 0x1c0, 0x1c4, UINT_MAX, "hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_LVDS, 25, 0x1c0, 0x1c4, UINT_MAX, "lvds"), - TEGRA_IO_PAD(TEGRA_IO_PAD_MIPI_BIAS, 3, 0x1b8, 0x1bc, UINT_MAX, "mipi-bias"), - TEGRA_IO_PAD(TEGRA_IO_PAD_NAND, 13, 0x1b8, 0x1bc, UINT_MAX, "nand"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_BIAS, 4, 0x1b8, 0x1bc, UINT_MAX, "pex-bias"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK1, 5, 0x1b8, 0x1bc, UINT_MAX, "pex-clk1"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK2, 6, 0x1b8, 0x1bc, UINT_MAX, "pex-clk2"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CNTRL, 0, 0x1c0, 0x1c4, UINT_MAX, "pex-cntrl"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1, 1, 0x1c0, 0x1c4, UINT_MAX, "sdmmc1"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3, 2, 0x1c0, 0x1c4, UINT_MAX, "sdmmc3"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC4, 3, 0x1c0, 0x1c4, UINT_MAX, "sdmmc4"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SYS_DDC, 26, 0x1c0, 0x1c4, UINT_MAX, "sys_ddc"), - TEGRA_IO_PAD(TEGRA_IO_PAD_UART, 14, 0x1b8, 0x1bc, UINT_MAX, "uart"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB0, 9, 0x1b8, 0x1bc, UINT_MAX, "usb0"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB1, 10, 0x1b8, 0x1bc, UINT_MAX, "usb1"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB2, 11, 0x1b8, 0x1bc, UINT_MAX, "usb2"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB_BIAS, 12, 0x1b8, 0x1bc, UINT_MAX, "usb_bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO, 17, 0x1b8, 0x1bc, "audio"), + TEGRA_IO_PAD(TEGRA_IO_PAD_BB, 15, 0x1b8, 0x1bc, "bb"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CAM, 4, 0x1c0, 0x1c4, "cam"), + TEGRA_IO_PAD(TEGRA_IO_PAD_COMP, 22, 0x1b8, 0x1bc, "comp"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x1b8, 0x1bc, "csia"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x1b8, 0x1bc, "csib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 12, 0x1c0, 0x1c4, "csie"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSI, 2, 0x1b8, 0x1bc, "dsi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSIB, 7, 0x1c0, 0x1c4, "dsib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSIC, 8, 0x1c0, 0x1c4, "dsic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSID, 9, 0x1c0, 0x1c4, "dsid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI, 28, 0x1b8, 0x1bc, "hdmi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HSIC, 19, 0x1b8, 0x1bc, "hsic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HV, 6, 0x1c0, 0x1c4, "hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_LVDS, 25, 0x1c0, 0x1c4, "lvds"), + TEGRA_IO_PAD(TEGRA_IO_PAD_MIPI_BIAS, 3, 0x1b8, 0x1bc, "mipi-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_NAND, 13, 0x1b8, 0x1bc, "nand"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_BIAS, 4, 0x1b8, 0x1bc, "pex-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK1, 5, 0x1b8, 0x1bc, "pex-clk1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK2, 6, 0x1b8, 0x1bc, "pex-clk2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CNTRL, 0, 0x1c0, 0x1c4, "pex-cntrl"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1, 1, 0x1c0, 0x1c4, "sdmmc1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3, 2, 0x1c0, 0x1c4, "sdmmc3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC4, 3, 0x1c0, 0x1c4, "sdmmc4"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SYS_DDC, 26, 0x1c0, 0x1c4, "sys_ddc"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UART, 14, 0x1b8, 0x1bc, "uart"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB0, 9, 0x1b8, 0x1bc, "usb0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB1, 10, 0x1b8, 0x1bc, "usb1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB2, 11, 0x1b8, 0x1bc, "usb2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB_BIAS, 12, 0x1b8, 0x1bc, "usb_bias"), }; static const struct pinctrl_pin_desc tegra124_pin_descs[] = { @@ -3857,46 +3863,60 @@ static const u8 tegra210_cpu_powergates[] = { }; static const struct tegra_io_pad_soc tegra210_io_pads[] = { - TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO, 17, 0x1b8, 0x1bc, 5, "audio"), - TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO_HV, 29, 0x1c0, 0x1c4, 18, "audio-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CAM, 4, 0x1c0, 0x1c4, 10, "cam"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x1b8, 0x1bc, UINT_MAX, "csia"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x1b8, 0x1bc, UINT_MAX, "csib"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 10, 0x1c0, 0x1c4, UINT_MAX, "csic"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 11, 0x1c0, 0x1c4, UINT_MAX, "csid"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 12, 0x1c0, 0x1c4, UINT_MAX, "csie"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 13, 0x1c0, 0x1c4, UINT_MAX, "csif"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DBG, 25, 0x1b8, 0x1bc, 19, "dbg"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DEBUG_NONAO, 26, 0x1b8, 0x1bc, UINT_MAX, "debug-nonao"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DMIC, 18, 0x1c0, 0x1c4, 20, "dmic"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DP, 19, 0x1c0, 0x1c4, UINT_MAX, "dp"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DSI, 2, 0x1b8, 0x1bc, UINT_MAX, "dsi"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DSIB, 7, 0x1c0, 0x1c4, UINT_MAX, "dsib"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DSIC, 8, 0x1c0, 0x1c4, UINT_MAX, "dsic"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DSID, 9, 0x1c0, 0x1c4, UINT_MAX, "dsid"), - TEGRA_IO_PAD(TEGRA_IO_PAD_EMMC, 3, 0x1c0, 0x1c4, UINT_MAX, "emmc"), - TEGRA_IO_PAD(TEGRA_IO_PAD_EMMC2, 5, 0x1c0, 0x1c4, UINT_MAX, "emmc2"), - TEGRA_IO_PAD(TEGRA_IO_PAD_GPIO, 27, 0x1b8, 0x1bc, 21, "gpio"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI, 28, 0x1b8, 0x1bc, UINT_MAX, "hdmi"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HSIC, 19, 0x1b8, 0x1bc, UINT_MAX, "hsic"), - TEGRA_IO_PAD(TEGRA_IO_PAD_LVDS, 25, 0x1c0, 0x1c4, UINT_MAX, "lvds"), - TEGRA_IO_PAD(TEGRA_IO_PAD_MIPI_BIAS, 3, 0x1b8, 0x1bc, UINT_MAX, "mipi-bias"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_BIAS, 4, 0x1b8, 0x1bc, UINT_MAX, "pex-bias"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK1, 5, 0x1b8, 0x1bc, UINT_MAX, "pex-clk1"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK2, 6, 0x1b8, 0x1bc, UINT_MAX, "pex-clk2"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CNTRL, UINT_MAX, UINT_MAX, UINT_MAX, 11, "pex-cntrl"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1, 1, 0x1c0, 0x1c4, 12, "sdmmc1"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3, 2, 0x1c0, 0x1c4, 13, "sdmmc3"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SPI, 14, 0x1c0, 0x1c4, 22, "spi"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SPI_HV, 15, 0x1c0, 0x1c4, 23, "spi-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_UART, 14, 0x1b8, 0x1bc, 2, "uart"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB0, 9, 0x1b8, 0x1bc, UINT_MAX, "usb0"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB1, 10, 0x1b8, 0x1bc, UINT_MAX, "usb1"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB2, 11, 0x1b8, 0x1bc, UINT_MAX, "usb2"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB3, 18, 0x1b8, 0x1bc, UINT_MAX, "usb3"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB_BIAS, 12, 0x1b8, 0x1bc, UINT_MAX, "usb-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO, 17, 0x1b8, 0x1bc, "audio"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO_HV, 29, 0x1c0, 0x1c4, "audio-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CAM, 4, 0x1c0, 0x1c4, "cam"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x1b8, 0x1bc, "csia"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x1b8, 0x1bc, "csib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 10, 0x1c0, 0x1c4, "csic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 11, 0x1c0, 0x1c4, "csid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 12, 0x1c0, 0x1c4, "csie"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 13, 0x1c0, 0x1c4, "csif"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DBG, 25, 0x1b8, 0x1bc, "dbg"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DEBUG_NONAO, 26, 0x1b8, 0x1bc, "debug-nonao"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DMIC, 18, 0x1c0, 0x1c4, "dmic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DP, 19, 0x1c0, 0x1c4, "dp"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSI, 2, 0x1b8, 0x1bc, "dsi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSIB, 7, 0x1c0, 0x1c4, "dsib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSIC, 8, 0x1c0, 0x1c4, "dsic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSID, 9, 0x1c0, 0x1c4, "dsid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EMMC, 3, 0x1c0, 0x1c4, "emmc"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EMMC2, 5, 0x1c0, 0x1c4, "emmc2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_GPIO, 27, 0x1b8, 0x1bc, "gpio"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI, 28, 0x1b8, 0x1bc, "hdmi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HSIC, 19, 0x1b8, 0x1bc, "hsic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_LVDS, 25, 0x1c0, 0x1c4, "lvds"), + TEGRA_IO_PAD(TEGRA_IO_PAD_MIPI_BIAS, 3, 0x1b8, 0x1bc, "mipi-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_BIAS, 4, 0x1b8, 0x1bc, "pex-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK1, 5, 0x1b8, 0x1bc, "pex-clk1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK2, 6, 0x1b8, 0x1bc, "pex-clk2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CNTRL, UINT_MAX, UINT_MAX, UINT_MAX, "pex-cntrl"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1, 1, 0x1c0, 0x1c4, "sdmmc1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3, 2, 0x1c0, 0x1c4, "sdmmc3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SPI, 14, 0x1c0, 0x1c4, "spi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SPI_HV, 15, 0x1c0, 0x1c4, "spi-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UART, 14, 0x1b8, 0x1bc, "uart"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB0, 9, 0x1b8, 0x1bc, "usb0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB1, 10, 0x1b8, 0x1bc, "usb1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB2, 11, 0x1b8, 0x1bc, "usb2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB3, 18, 0x1b8, 0x1bc, "usb3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB_BIAS, 12, 0x1b8, 0x1bc, "usb-bias"), }; +static const struct tegra_io_pad_vctrl tegra210_io_pad_vctrls[] = { + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_AUDIO, PMC_PWR_DET_VALUE, 5), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_AUDIO_HV, PMC_PWR_DET_VALUE, 18), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_CAM, PMC_PWR_DET_VALUE, 10), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_DBG, PMC_PWR_DET_VALUE, 19), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_DMIC, PMC_PWR_DET_VALUE, 20), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_GPIO, PMC_PWR_DET_VALUE, 21), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_PEX_CNTRL, PMC_PWR_DET_VALUE, 11), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_SDMMC1, PMC_PWR_DET_VALUE, 12), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_SDMMC3, PMC_PWR_DET_VALUE, 13), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_SPI, PMC_PWR_DET_VALUE, 22), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_SPI_HV, PMC_PWR_DET_VALUE, 23), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_UART, PMC_PWR_DET_VALUE, 2), +}; static const struct pinctrl_pin_desc tegra210_pin_descs[] = { TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AUDIO, "audio"), TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AUDIO_HV, "audio-hv"), @@ -3965,6 +3985,8 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = { .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, @@ -3987,44 +4009,53 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = { }; static const struct tegra_io_pad_soc tegra186_io_pads[] = { - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x74, 0x78, UINT_MAX, "csia"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x74, 0x78, UINT_MAX, "csib"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DSI, 2, 0x74, 0x78, UINT_MAX, "dsi"), - TEGRA_IO_PAD(TEGRA_IO_PAD_MIPI_BIAS, 3, 0x74, 0x78, UINT_MAX, "mipi-bias"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, 0x74, 0x78, UINT_MAX, "pex-clk-bias"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK3, 5, 0x74, 0x78, UINT_MAX, "pex-clk3"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK2, 6, 0x74, 0x78, UINT_MAX, "pex-clk2"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK1, 7, 0x74, 0x78, UINT_MAX, "pex-clk1"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB0, 9, 0x74, 0x78, UINT_MAX, "usb0"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB1, 10, 0x74, 0x78, UINT_MAX, "usb1"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB2, 11, 0x74, 0x78, UINT_MAX, "usb2"), - TEGRA_IO_PAD(TEGRA_IO_PAD_USB_BIAS, 12, 0x74, 0x78, UINT_MAX, "usb-bias"), - TEGRA_IO_PAD(TEGRA_IO_PAD_UART, 14, 0x74, 0x78, UINT_MAX, "uart"), - TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO, 17, 0x74, 0x78, UINT_MAX, "audio"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HSIC, 19, 0x74, 0x78, UINT_MAX, "hsic"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DBG, 25, 0x74, 0x78, UINT_MAX, "dbg"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP0, 28, 0x74, 0x78, UINT_MAX, "hdmi-dp0"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP1, 29, 0x74, 0x78, UINT_MAX, "hdmi-dp1"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CNTRL, 0, 0x7c, 0x80, UINT_MAX, "pex-cntrl"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC2_HV, 2, 0x7c, 0x80, 5, "sdmmc2-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC4, 4, 0x7c, 0x80, UINT_MAX, "sdmmc4"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CAM, 6, 0x7c, 0x80, UINT_MAX, "cam"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DSIB, 8, 0x7c, 0x80, UINT_MAX, "dsib"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DSIC, 9, 0x7c, 0x80, UINT_MAX, "dsic"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DSID, 10, 0x7c, 0x80, UINT_MAX, "dsid"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 11, 0x7c, 0x80, UINT_MAX, "csic"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 12, 0x7c, 0x80, UINT_MAX, "csid"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 13, 0x7c, 0x80, UINT_MAX, "csie"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 14, 0x7c, 0x80, UINT_MAX, "csif"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SPI, 15, 0x7c, 0x80, UINT_MAX, "spi"), - TEGRA_IO_PAD(TEGRA_IO_PAD_UFS, 17, 0x7c, 0x80, UINT_MAX, "ufs"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DMIC_HV, 20, 0x7c, 0x80, 2, "dmic-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_EDP, 21, 0x7c, 0x80, UINT_MAX, "edp"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1_HV, 23, 0x7c, 0x80, 4, "sdmmc1-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3_HV, 24, 0x7c, 0x80, 6, "sdmmc3-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CONN, 28, 0x7c, 0x80, UINT_MAX, "conn"), - TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO_HV, 29, 0x7c, 0x80, 1, "audio-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_AO_HV, UINT_MAX, UINT_MAX, UINT_MAX, 0, "ao-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x74, 0x78, "csia"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x74, 0x78, "csib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSI, 2, 0x74, 0x78, "dsi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_MIPI_BIAS, 3, 0x74, 0x78, "mipi-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, 0x74, 0x78, "pex-clk-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK3, 5, 0x74, 0x78, "pex-clk3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK2, 6, 0x74, 0x78, "pex-clk2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK1, 7, 0x74, 0x78, "pex-clk1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB0, 9, 0x74, 0x78, "usb0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB1, 10, 0x74, 0x78, "usb1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB2, 11, 0x74, 0x78, "usb2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB_BIAS, 12, 0x74, 0x78, "usb-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UART, 14, 0x74, 0x78, "uart"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO, 17, 0x74, 0x78, "audio"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HSIC, 19, 0x74, 0x78, "hsic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DBG, 25, 0x74, 0x78, "dbg"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP0, 28, 0x74, 0x78, "hdmi-dp0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP1, 29, 0x74, 0x78, "hdmi-dp1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CNTRL, 0, 0x7c, 0x80, "pex-cntrl"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC2_HV, 2, 0x7c, 0x80, "sdmmc2-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC4, 4, 0x7c, 0x80, "sdmmc4"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CAM, 6, 0x7c, 0x80, "cam"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSIB, 8, 0x7c, 0x80, "dsib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSIC, 9, 0x7c, 0x80, "dsic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSID, 10, 0x7c, 0x80, "dsid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 11, 0x7c, 0x80, "csic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 12, 0x7c, 0x80, "csid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 13, 0x7c, 0x80, "csie"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 14, 0x7c, 0x80, "csif"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SPI, 15, 0x7c, 0x80, "spi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UFS, 17, 0x7c, 0x80, "ufs"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DMIC_HV, 20, 0x7c, 0x80, "dmic-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EDP, 21, 0x7c, 0x80, "edp"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1_HV, 23, 0x7c, 0x80, "sdmmc1-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3_HV, 24, 0x7c, 0x80, "sdmmc3-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CONN, 28, 0x7c, 0x80, "conn"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO_HV, 29, 0x7c, 0x80, "audio-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AO_HV, UINT_MAX, UINT_MAX, UINT_MAX, "ao-hv"), +}; + +static const struct tegra_io_pad_vctrl tegra186_io_pad_vctrls[] = { + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_SDMMC2_HV, PMC_IMPL_E_33V_PWR, 5), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_DMIC_HV, PMC_IMPL_E_33V_PWR, 2), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_SDMMC1_HV, PMC_IMPL_E_33V_PWR, 4), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_SDMMC3_HV, PMC_IMPL_E_33V_PWR, 6), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_AUDIO_HV, PMC_IMPL_E_33V_PWR, 1), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_AO_HV, PMC_IMPL_E_33V_PWR, 0), }; static const struct pinctrl_pin_desc tegra186_pin_descs[] = { @@ -4168,6 +4199,8 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = { .maybe_tz_only = false, .num_io_pads = ARRAY_SIZE(tegra186_io_pads), .io_pads = tegra186_io_pads, + .num_io_pad_vctrls = ARRAY_SIZE(tegra186_io_pad_vctrls), + .io_pad_vctrls = tegra186_io_pad_vctrls, .num_pin_descs = ARRAY_SIZE(tegra186_pin_descs), .pin_descs = tegra186_pin_descs, .regs = &tegra186_pmc_regs, @@ -4192,55 +4225,62 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = { }; static const struct tegra_io_pad_soc tegra194_io_pads[] = { - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x74, 0x78, UINT_MAX, "csia"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x74, 0x78, UINT_MAX, "csib"), - TEGRA_IO_PAD(TEGRA_IO_PAD_MIPI_BIAS, 3, 0x74, 0x78, UINT_MAX, "mipi-bias"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, 0x74, 0x78, UINT_MAX, "pex-clk-bias"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK3, 5, 0x74, 0x78, UINT_MAX, "pex-clk3"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK2, 6, 0x74, 0x78, UINT_MAX, "pex-clk2"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK1, 7, 0x74, 0x78, UINT_MAX, "pex-clk1"), - TEGRA_IO_PAD(TEGRA_IO_PAD_EQOS, 8, 0x74, 0x78, UINT_MAX, "eqos"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK_2_BIAS, 9, 0x74, 0x78, UINT_MAX, "pex-clk-2-bias"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK_2, 10, 0x74, 0x78, UINT_MAX, "pex-clk-2"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DAP3, 11, 0x74, 0x78, UINT_MAX, "dap3"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DAP5, 12, 0x74, 0x78, UINT_MAX, "dap5"), - TEGRA_IO_PAD(TEGRA_IO_PAD_UART, 14, 0x74, 0x78, UINT_MAX, "uart"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PWR_CTL, 15, 0x74, 0x78, UINT_MAX, "pwr-ctl"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SOC_GPIO53, 16, 0x74, 0x78, UINT_MAX, "soc-gpio53"), - TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO, 17, 0x74, 0x78, UINT_MAX, "audio"), - TEGRA_IO_PAD(TEGRA_IO_PAD_GP_PWM2, 18, 0x74, 0x78, UINT_MAX, "gp-pwm2"), - TEGRA_IO_PAD(TEGRA_IO_PAD_GP_PWM3, 19, 0x74, 0x78, UINT_MAX, "gp-pwm3"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SOC_GPIO12, 20, 0x74, 0x78, UINT_MAX, "soc-gpio12"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SOC_GPIO13, 21, 0x74, 0x78, UINT_MAX, "soc-gpio13"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SOC_GPIO10, 22, 0x74, 0x78, UINT_MAX, "soc-gpio10"), - TEGRA_IO_PAD(TEGRA_IO_PAD_UART4, 23, 0x74, 0x78, UINT_MAX, "uart4"), - TEGRA_IO_PAD(TEGRA_IO_PAD_UART5, 24, 0x74, 0x78, UINT_MAX, "uart5"), - TEGRA_IO_PAD(TEGRA_IO_PAD_DBG, 25, 0x74, 0x78, UINT_MAX, "dbg"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP3, 26, 0x74, 0x78, UINT_MAX, "hdmi-dp3"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP2, 27, 0x74, 0x78, UINT_MAX, "hdmi-dp2"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP0, 28, 0x74, 0x78, UINT_MAX, "hdmi-dp0"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP1, 29, 0x74, 0x78, UINT_MAX, "hdmi-dp1"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CNTRL, 0, 0x7c, 0x80, UINT_MAX, "pex-cntrl"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CTL2, 1, 0x7c, 0x80, UINT_MAX, "pex-ctl2"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_L0_RST, 2, 0x7c, 0x80, UINT_MAX, "pex-l0-rst"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_L1_RST, 3, 0x7c, 0x80, UINT_MAX, "pex-l1-rst"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC4, 4, 0x7c, 0x80, UINT_MAX, "sdmmc4"), - TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_L5_RST, 5, 0x7c, 0x80, UINT_MAX, "pex-l5-rst"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CAM, 6, 0x7c, 0x80, UINT_MAX, "cam"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 11, 0x7c, 0x80, UINT_MAX, "csic"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 12, 0x7c, 0x80, UINT_MAX, "csid"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 13, 0x7c, 0x80, UINT_MAX, "csie"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 14, 0x7c, 0x80, UINT_MAX, "csif"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SPI, 15, 0x7c, 0x80, UINT_MAX, "spi"), - TEGRA_IO_PAD(TEGRA_IO_PAD_UFS, 17, 0x7c, 0x80, UINT_MAX, "ufs"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIG, 18, 0x7c, 0x80, UINT_MAX, "csig"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIH, 19, 0x7c, 0x80, UINT_MAX, "csih"), - TEGRA_IO_PAD(TEGRA_IO_PAD_EDP, 21, 0x7c, 0x80, UINT_MAX, "edp"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1_HV, 23, 0x7c, 0x80, 4, "sdmmc1-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3_HV, 24, 0x7c, 0x80, 6, "sdmmc3-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CONN, 28, 0x7c, 0x80, UINT_MAX, "conn"), - TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO_HV, 29, 0x7c, 0x80, 1, "audio-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_AO_HV, UINT_MAX, UINT_MAX, UINT_MAX, 0, "ao-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x74, 0x78, "csia"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x74, 0x78, "csib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_MIPI_BIAS, 3, 0x74, 0x78, "mipi-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, 0x74, 0x78, "pex-clk-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK3, 5, 0x74, 0x78, "pex-clk3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK2, 6, 0x74, 0x78, "pex-clk2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK1, 7, 0x74, 0x78, "pex-clk1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EQOS, 8, 0x74, 0x78, "eqos"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK_2_BIAS, 9, 0x74, 0x78, "pex-clk-2-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK_2, 10, 0x74, 0x78, "pex-clk-2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DAP3, 11, 0x74, 0x78, "dap3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DAP5, 12, 0x74, 0x78, "dap5"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UART, 14, 0x74, 0x78, "uart"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PWR_CTL, 15, 0x74, 0x78, "pwr-ctl"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SOC_GPIO53, 16, 0x74, 0x78, "soc-gpio53"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO, 17, 0x74, 0x78, "audio"), + TEGRA_IO_PAD(TEGRA_IO_PAD_GP_PWM2, 18, 0x74, 0x78, "gp-pwm2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_GP_PWM3, 19, 0x74, 0x78, "gp-pwm3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SOC_GPIO12, 20, 0x74, 0x78, "soc-gpio12"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SOC_GPIO13, 21, 0x74, 0x78, "soc-gpio13"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SOC_GPIO10, 22, 0x74, 0x78, "soc-gpio10"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UART4, 23, 0x74, 0x78, "uart4"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UART5, 24, 0x74, 0x78, "uart5"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DBG, 25, 0x74, 0x78, "dbg"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP3, 26, 0x74, 0x78, "hdmi-dp3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP2, 27, 0x74, 0x78, "hdmi-dp2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP0, 28, 0x74, 0x78, "hdmi-dp0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP1, 29, 0x74, 0x78, "hdmi-dp1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CNTRL, 0, 0x7c, 0x80, "pex-cntrl"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CTL2, 1, 0x7c, 0x80, "pex-ctl2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_L0_RST, 2, 0x7c, 0x80, "pex-l0-rst"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_L1_RST, 3, 0x7c, 0x80, "pex-l1-rst"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC4, 4, 0x7c, 0x80, "sdmmc4"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_L5_RST, 5, 0x7c, 0x80, "pex-l5-rst"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CAM, 6, 0x7c, 0x80, "cam"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 11, 0x7c, 0x80, "csic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 12, 0x7c, 0x80, "csid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 13, 0x7c, 0x80, "csie"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 14, 0x7c, 0x80, "csif"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SPI, 15, 0x7c, 0x80, "spi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UFS, 17, 0x7c, 0x80, "ufs"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIG, 18, 0x7c, 0x80, "csig"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIH, 19, 0x7c, 0x80, "csih"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EDP, 21, 0x7c, 0x80, "edp"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1_HV, 23, 0x7c, 0x80, "sdmmc1-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3_HV, 24, 0x7c, 0x80, "sdmmc3-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CONN, 28, 0x7c, 0x80, "conn"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO_HV, 29, 0x7c, 0x80, "audio-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AO_HV, UINT_MAX, UINT_MAX, UINT_MAX, "ao-hv"), +}; + +static const struct tegra_io_pad_vctrl tegra194_io_pad_vctrls[] = { + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_SDMMC1_HV, PMC_IMPL_E_33V_PWR, 4), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_SDMMC3_HV, PMC_IMPL_E_33V_PWR, 6), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_AUDIO_HV, PMC_IMPL_E_33V_PWR, 1), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_AO_HV, PMC_IMPL_E_33V_PWR, 0), }; static const struct pinctrl_pin_desc tegra194_pin_descs[] = { @@ -4363,6 +4403,8 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = { .maybe_tz_only = false, .num_io_pads = ARRAY_SIZE(tegra194_io_pads), .io_pads = tegra194_io_pads, + .num_io_pad_vctrls = ARRAY_SIZE(tegra194_io_pad_vctrls), + .io_pad_vctrls = tegra194_io_pad_vctrls, .num_pin_descs = ARRAY_SIZE(tegra194_pin_descs), .pin_descs = tegra194_pin_descs, .regs = &tegra194_pmc_regs, @@ -4387,21 +4429,28 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = { }; static const struct tegra_io_pad_soc tegra234_io_pads[] = { - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0xe0c0, 0xe0c4, UINT_MAX, "csia"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0xe0c0, 0xe0c4, UINT_MAX, "csib"), - TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP0, 0, 0xe0d0, 0xe0d4, UINT_MAX, "hdmi-dp0"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 2, 0xe0c0, 0xe0c4, UINT_MAX, "csic"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 3, 0xe0c0, 0xe0c4, UINT_MAX, "csid"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 4, 0xe0c0, 0xe0c4, UINT_MAX, "csie"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 5, 0xe0c0, 0xe0c4, UINT_MAX, "csif"), - TEGRA_IO_PAD(TEGRA_IO_PAD_UFS, 0, 0xe064, 0xe068, UINT_MAX, "ufs"), - TEGRA_IO_PAD(TEGRA_IO_PAD_EDP, 1, 0xe05c, 0xe060, UINT_MAX, "edp"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1_HV, 0, 0xe054, 0xe058, 4, "sdmmc1-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3_HV, UINT_MAX, UINT_MAX, UINT_MAX, 6, "sdmmc3-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO_HV, UINT_MAX, UINT_MAX, UINT_MAX, 1, "audio-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_AO_HV, UINT_MAX, UINT_MAX, UINT_MAX, 0, "ao-hv"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIG, 6, 0xe0c0, 0xe0c4, UINT_MAX, "csig"), - TEGRA_IO_PAD(TEGRA_IO_PAD_CSIH, 7, 0xe0c0, 0xe0c4, UINT_MAX, "csih"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0xe0c0, 0xe0c4, "csia"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0xe0c0, 0xe0c4, "csib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP0, 0, 0xe0d0, 0xe0d4, "hdmi-dp0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 2, 0xe0c0, 0xe0c4, "csic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 3, 0xe0c0, 0xe0c4, "csid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 4, 0xe0c0, 0xe0c4, "csie"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 5, 0xe0c0, 0xe0c4, "csif"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UFS, 0, 0xe064, 0xe068, "ufs"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EDP, 1, 0xe05c, 0xe060, "edp"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1_HV, 0, 0xe054, 0xe058, "sdmmc1-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3_HV, UINT_MAX, UINT_MAX, UINT_MAX, "sdmmc3-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO_HV, UINT_MAX, UINT_MAX, UINT_MAX, "audio-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AO_HV, UINT_MAX, UINT_MAX, UINT_MAX, "ao-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIG, 6, 0xe0c0, 0xe0c4, "csig"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIH, 7, 0xe0c0, 0xe0c4, "csih"), +}; + +static const struct tegra_io_pad_vctrl tegra234_io_pad_vctrls[] = { + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_SDMMC1_HV, PMC_IMPL_E_33V_PWR, 4), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_SDMMC3_HV, PMC_IMPL_E_33V_PWR, 6), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_AUDIO_HV, PMC_IMPL_E_33V_PWR, 1), + TEGRA_IO_PAD_VCTRL(TEGRA_IO_PAD_AO_HV, PMC_IMPL_E_33V_PWR, 0), }; static const struct pinctrl_pin_desc tegra234_pin_descs[] = { @@ -4510,6 +4559,8 @@ static const struct tegra_pmc_soc tegra234_pmc_soc = { .maybe_tz_only = false, .num_io_pads = ARRAY_SIZE(tegra234_io_pads), .io_pads = tegra234_io_pads, + .num_io_pad_vctrls = ARRAY_SIZE(tegra234_io_pad_vctrls), + .io_pad_vctrls = tegra234_io_pad_vctrls, .num_pin_descs = ARRAY_SIZE(tegra234_pin_descs), .pin_descs = tegra234_pin_descs, .regs = &tegra234_pmc_regs, From db3c16b2b90b0f56a94f9780f9dd10b50b648860 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 25 Mar 2026 19:25:59 +0000 Subject: [PATCH 170/193] soc/tegra: pmc: Rename has_impl_33v_pwr flag The flag 'has_impl_33v_pwr' is now only used to determine if we need to set the write-enable bit before we can set the bit to select if 3.3V IO is used or not. Therefore, rename the flag to 'has_io_pad_wren' to indicate that the SoC supports the write-enable register. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index ac026e2560f9..5502ed935c99 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -372,7 +372,7 @@ struct tegra_pmc_soc { bool has_tsense_reset; bool has_gpu_clamps; bool needs_mbist_war; - bool has_impl_33v_pwr; + bool has_io_pad_wren; bool maybe_tz_only; const struct tegra_io_pad_soc *io_pads; @@ -1922,7 +1922,7 @@ static int tegra_io_pad_set_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id, mutex_lock(&pmc->powergates_lock); - if (!pmc->soc->has_impl_33v_pwr) { + if (pmc->soc->has_io_pad_wren) { /* write-enable PMC_PWR_DET_VALUE[pad->ena_3v3] */ value = tegra_pmc_readl(pmc, PMC_PWR_DET); value |= BIT(pad->ena_3v3); @@ -3536,7 +3536,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = { .has_tsense_reset = false, .has_gpu_clamps = false, .needs_mbist_war = false, - .has_impl_33v_pwr = false, + .has_io_pad_wren = true, .maybe_tz_only = false, .num_io_pads = 0, .io_pads = NULL, @@ -3598,7 +3598,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = { .has_tsense_reset = true, .has_gpu_clamps = false, .needs_mbist_war = false, - .has_impl_33v_pwr = false, + .has_io_pad_wren = true, .maybe_tz_only = false, .num_io_pads = 0, .io_pads = NULL, @@ -3656,7 +3656,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = { .has_tsense_reset = true, .has_gpu_clamps = false, .needs_mbist_war = false, - .has_impl_33v_pwr = false, + .has_io_pad_wren = true, .maybe_tz_only = false, .num_io_pads = 0, .io_pads = NULL, @@ -3807,7 +3807,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = { .has_tsense_reset = true, .has_gpu_clamps = true, .needs_mbist_war = false, - .has_impl_33v_pwr = false, + .has_io_pad_wren = true, .maybe_tz_only = false, .num_io_pads = ARRAY_SIZE(tegra124_io_pads), .io_pads = tegra124_io_pads, @@ -3981,7 +3981,7 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = { .has_tsense_reset = true, .has_gpu_clamps = true, .needs_mbist_war = true, - .has_impl_33v_pwr = false, + .has_io_pad_wren = true, .maybe_tz_only = true, .num_io_pads = ARRAY_SIZE(tegra210_io_pads), .io_pads = tegra210_io_pads, @@ -4195,7 +4195,7 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = { .has_tsense_reset = false, .has_gpu_clamps = false, .needs_mbist_war = false, - .has_impl_33v_pwr = true, + .has_io_pad_wren = false, .maybe_tz_only = false, .num_io_pads = ARRAY_SIZE(tegra186_io_pads), .io_pads = tegra186_io_pads, @@ -4399,7 +4399,7 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = { .has_tsense_reset = false, .has_gpu_clamps = false, .needs_mbist_war = false, - .has_impl_33v_pwr = true, + .has_io_pad_wren = false, .maybe_tz_only = false, .num_io_pads = ARRAY_SIZE(tegra194_io_pads), .io_pads = tegra194_io_pads, @@ -4555,7 +4555,7 @@ static const struct tegra_pmc_soc tegra234_pmc_soc = { .has_tsense_reset = false, .has_gpu_clamps = false, .needs_mbist_war = false, - .has_impl_33v_pwr = true, + .has_io_pad_wren = false, .maybe_tz_only = false, .num_io_pads = ARRAY_SIZE(tegra234_io_pads), .io_pads = tegra234_io_pads, @@ -4704,7 +4704,7 @@ static const struct tegra_wake_event tegra264_wake_events[] = { }; static const struct tegra_pmc_soc tegra264_pmc_soc = { - .has_impl_33v_pwr = true, + .has_io_pad_wren = false, .regs = &tegra264_pmc_regs, .init = tegra186_pmc_init, .setup_irq_polarity = tegra186_pmc_setup_irq_polarity, From e8014b2c83f598e15f5ae48fb56ad9a8d1484965 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 25 Mar 2026 19:26:00 +0000 Subject: [PATCH 171/193] soc/tegra: pmc: Add IO pads for Tegra264 Populate the IO pads and pins for Tegra264. Tegra264 has internal 1.8V and 0.6V regulators that must be enabled when selecting the 1.8V mode for the sdmmc1-hv IO pad. To support this a new 'ena_1v8' member is added to the 'tegra_io_pad_vctrl' structure to populate the bits that need to be set to enable these internal regulators. Although this is enabling 1.8V (bit 1) and 0.6V (bit 2) regulators, it is simply called 'ena_1v8' because these are both enabled for 1.8V operation. Note that these internal regulators are disabled when not using 1.8V mode. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 66 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 5502ed935c99..2ee6539d796a 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -201,6 +201,9 @@ #define TEGRA_SMC_PMC_READ 0xaa #define TEGRA_SMC_PMC_WRITE 0xbb +/* Tegra264 and later */ +#define PMC_IMPL_SDMMC1_HV_PADCTL_0 0x41004 + struct pmc_clk { struct clk_hw hw; struct tegra_pmc *pmc; @@ -301,6 +304,7 @@ struct tegra_io_pad_vctrl { enum tegra_io_pad id; unsigned int offset; unsigned int ena_3v3; + unsigned int ena_1v8; }; struct tegra_pmc_regs { @@ -1931,11 +1935,18 @@ static int tegra_io_pad_set_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id, value = tegra_pmc_readl(pmc, pad->offset); - if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8) + if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8) { value &= ~BIT(pad->ena_3v3); - else + + if (pad->ena_1v8) + value |= pad->ena_1v8; + } else { value |= BIT(pad->ena_3v3); + if (pad->ena_1v8) + value &= ~pad->ena_1v8; + } + tegra_pmc_writel(pmc, value, pad->offset); mutex_unlock(&pmc->powergates_lock); @@ -3724,6 +3735,7 @@ static const u8 tegra124_cpu_powergates[] = { .id = (_id), \ .offset = (_offset), \ .ena_3v3 = (_ena_3v3), \ + .ena_1v8 = 0, \ }) #define TEGRA_IO_PIN_DESC(_id, _name) \ @@ -4583,6 +4595,50 @@ static const struct tegra_pmc_soc tegra234_pmc_soc = { .has_single_mmio_aperture = false, }; +#define TEGRA264_IO_PAD_VCTRL(_id, _offset, _ena_3v3, _ena_1v8) \ + ((struct tegra_io_pad_vctrl) { \ + .id = (_id), \ + .offset = (_offset), \ + .ena_3v3 = (_ena_3v3), \ + .ena_1v8 = (_ena_1v8), \ + }) + +static const struct tegra_io_pad_soc tegra264_io_pads[] = { + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x41020, 0x41024, "csia"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x41020, 0x41024, "csib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP0, 0, 0x41050, 0x41054, "hdmi-dp0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 2, 0x41020, 0x41024, "csic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 3, 0x41020, 0x41024, "csid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 4, 0x41020, 0x41024, "csie"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 5, 0x41020, 0x41024, "csif"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UFS, 4, 0x41040, 0x41044, "ufs0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EDP, 0, 0x41028, 0x4102c, "edp"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1, 0, 0x41090, 0x41094, "sdmmc1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1_HV, UINT_MAX, UINT_MAX, UINT_MAX, "sdmmc1-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIG, 6, 0x41020, 0x41024, "csig"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIH, 7, 0x41020, 0x41024, "csih"), +}; + +static const struct tegra_io_pad_vctrl tegra264_io_pad_vctrls[] = { + TEGRA264_IO_PAD_VCTRL(TEGRA_IO_PAD_SDMMC1_HV, PMC_IMPL_SDMMC1_HV_PADCTL_0, 0, 0x6), +}; + +static const struct pinctrl_pin_desc tegra264_pin_descs[] = { + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIA, "csia"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIB, "csib"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HDMI_DP0, "hdmi-dp0"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIC, "csic"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSID, "csid"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIE, "csie"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIF, "csif"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_UFS, "ufs0"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_EDP, "edp"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC1, "sdmmc1"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC1_HV, "sdmmc1-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIG, "csig"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIH, "csih"), +}; + static const struct tegra_pmc_regs tegra264_pmc_regs = { .scratch0 = 0x684, .rst_status = 0x4, @@ -4705,6 +4761,12 @@ static const struct tegra_wake_event tegra264_wake_events[] = { static const struct tegra_pmc_soc tegra264_pmc_soc = { .has_io_pad_wren = false, + .num_io_pads = ARRAY_SIZE(tegra264_io_pads), + .io_pads = tegra264_io_pads, + .num_io_pad_vctrls = ARRAY_SIZE(tegra264_io_pad_vctrls), + .io_pad_vctrls = tegra264_io_pad_vctrls, + .num_pin_descs = ARRAY_SIZE(tegra264_pin_descs), + .pin_descs = tegra264_pin_descs, .regs = &tegra264_pmc_regs, .init = tegra186_pmc_init, .setup_irq_polarity = tegra186_pmc_setup_irq_polarity, From bed2f5b4de6c6fd8f8928f6373ad92e8795c370f Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Sat, 21 Mar 2026 00:43:28 +0100 Subject: [PATCH 172/193] dt-bindings: arm: tegra: Document Jetson AGX Thor DevKit The Jetson AGX Thor Developer Kit uses the same module (P3834) as the P3971 reference platform but a slightly different carrier board (P4071). Acked-by: Rob Herring (Arm) Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/arm/tegra.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/tegra.yaml b/Documentation/devicetree/bindings/arm/tegra.yaml index 07e225a4d69b..033a63f6c068 100644 --- a/Documentation/devicetree/bindings/arm/tegra.yaml +++ b/Documentation/devicetree/bindings/arm/tegra.yaml @@ -313,5 +313,10 @@ properties: - const: nvidia,p3971-0089+p3834-0008 - const: nvidia,p3834-0008 - const: nvidia,tegra264 + - description: Jetson AGX Thor Developer Kit + items: + - const: nvidia,p4071-0000+p3834-0008 + - const: nvidia,p3834-0008 + - const: nvidia,tegra264 additionalProperties: true From 4b23febb6b11cd06183bed3d21b87ba7d6a8a1e0 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 22 Jan 2026 14:25:35 +0100 Subject: [PATCH 173/193] MAINTAINERS: Change email address for Thierry Reding Use the kernel.org email address as a level of indirection to enable transparent switching of providers if necessary. Signed-off-by: Thierry Reding --- MAINTAINERS | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 55af015174a5..0d89a5c7d555 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8650,7 +8650,7 @@ F: drivers/phy/mediatek/phy-mtk-hdmi* F: drivers/phy/mediatek/phy-mtk-mipi* DRM DRIVERS FOR NVIDIA TEGRA -M: Thierry Reding +M: Thierry Reding M: Mikko Perttunen L: dri-devel@lists.freedesktop.org L: linux-tegra@vger.kernel.org @@ -20248,7 +20248,7 @@ S: Maintained F: drivers/pci/controller/*mvebu* PCI DRIVER FOR NVIDIA TEGRA -M: Thierry Reding +M: Thierry Reding L: linux-tegra@vger.kernel.org L: linux-pci@vger.kernel.org S: Supported @@ -25951,7 +25951,7 @@ F: include/linux/tee_drv.h F: include/uapi/linux/tee.h TEGRA ARCHITECTURE SUPPORT -M: Thierry Reding +M: Thierry Reding M: Jonathan Hunter L: linux-tegra@vger.kernel.org S: Supported @@ -25983,7 +25983,7 @@ S: Supported F: drivers/i2c/busses/i2c-tegra.c TEGRA IOMMU DRIVERS -M: Thierry Reding +M: Thierry Reding R: Krishna Reddy L: linux-tegra@vger.kernel.org S: Supported @@ -26004,12 +26004,12 @@ F: Documentation/devicetree/bindings/mtd/nvidia,tegra20-nand.yaml F: drivers/mtd/nand/raw/tegra_nand.c TEGRA PWM DRIVER -M: Thierry Reding +M: Thierry Reding S: Supported F: drivers/pwm/pwm-tegra.c TEGRA QUAD SPI DRIVER -M: Thierry Reding +M: Thierry Reding M: Jonathan Hunter M: Sowjanya Komatineni L: linux-tegra@vger.kernel.org @@ -26027,7 +26027,7 @@ S: Supported F: drivers/spi/spi-tegra* TEGRA VIDEO DRIVER -M: Thierry Reding +M: Thierry Reding M: Jonathan Hunter M: Sowjanya Komatineni M: Luca Ceresoli From 24e7625df5ce065393249b78930781be593bc381 Mon Sep 17 00:00:00 2001 From: Alok Tiwari Date: Mon, 30 Mar 2026 02:51:11 -0700 Subject: [PATCH 174/193] soc: qcom: llcc: fix v1 SB syndrome register offset The llcc_v1_edac_reg_offset table uses 0x2304c for trp_ecc_sb_err_syn0, which is inconsistent with the surrounding TRP ECC registers (0x2034x) and with llcc_v2_1_edac_reg_offset, where trp_ecc_sb_err_syn0 is 0x2034c adjacent to trp_ecc_error_status0/1 at 0x20344/0x20348. Use 0x2034c for llcc v1 so the SB syndrome register follows the expected +0x4 progression from trp_ecc_error_status1. This fixes EDAC reading the wrong register for SB syndrome reporting. Fixes: c13d7d261e36 ("soc: qcom: llcc: Pass LLCC version based register offsets to EDAC driver") Signed-off-by: Alok Tiwari Reviewed-by: Manivannan Sadhasivam Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260330095118.2657362-1-alok.a.tiwari@oracle.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 68a3416692e0..0161ceec8842 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -4030,7 +4030,7 @@ static const struct llcc_slice_config x1e80100_data[] = { static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = { .trp_ecc_error_status0 = 0x20344, .trp_ecc_error_status1 = 0x20348, - .trp_ecc_sb_err_syn0 = 0x2304c, + .trp_ecc_sb_err_syn0 = 0x2034c, .trp_ecc_db_err_syn0 = 0x20370, .trp_ecc_error_cntr_clear = 0x20440, .trp_interrupt_0_status = 0x20480, From cd3c4670db3ffe997be9548c7a9db3952563cf14 Mon Sep 17 00:00:00 2001 From: Alok Tiwari Date: Sun, 29 Mar 2026 12:53:23 -0700 Subject: [PATCH 175/193] soc: qcom: aoss: compare against normalized cooling state qmp_cdev_set_cur_state() normalizes the requested state to a boolean (cdev_state = !!state). The existing early-return check compares qmp_cdev->state == state, which can be wrong if state is non-boolean (any non-zero value). Compare qmp_cdev->state against cdev_state instead, so the check matches the effective state and avoids redundant updates. Signed-off-by: Alok Tiwari Fixes: 05589b30b21a ("soc: qcom: Extend AOSS QMP driver to support resources that are used to wake up the SoC.") Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260329195333.1478090-1-alok.a.tiwari@oracle.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_aoss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index a543ab9bee6c..c255662b8fc3 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -355,7 +355,7 @@ static int qmp_cdev_set_cur_state(struct thermal_cooling_device *cdev, /* Normalize state */ cdev_state = !!state; - if (qmp_cdev->state == state) + if (qmp_cdev->state == cdev_state) return 0; ret = qmp_send(qmp_cdev->qmp, "{class: volt_flr, event:zero_temp, res:%s, value:%s}", From 79c9ede455820e179608f9d52584c74d19e13fb0 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Fri, 27 Mar 2026 16:22:33 +0200 Subject: [PATCH 176/193] soc: qcom: pd-mapper: Add support for Eliza Add support for the Qualcomm Eliza SoC to the protection domain mapper. It has the same exact protection domain configuration as SM8550 SoC, so reuse that. Signed-off-by: Abel Vesa Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260327-eliza-soc-pd-mapper-v1-1-17334d6ab82d@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_pd_mapper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index 003aa88fc372..bb99f003844b 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -578,6 +578,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,apq8064", .data = NULL, }, { .compatible = "qcom,apq8074", .data = NULL, }, { .compatible = "qcom,apq8084", .data = NULL, }, + { .compatible = "qcom,eliza", .data = sm8550_domains, }, { .compatible = "qcom,apq8096", .data = msm8996_domains, }, { .compatible = "qcom,glymur", .data = glymur_domains, }, { .compatible = "qcom,kaanapali", .data = kaanapali_domains, }, From 908061f0ad30aa08ce211c6a8f95d29102e570bd Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 26 Mar 2026 19:55:34 -0700 Subject: [PATCH 177/193] soc: qcom: wcnss: simplify allocation of req Get rid of automatic kfree and move allocation down to where it's used. Use kzalloc_flex as we're dealing with a flexible array member. Use struct_size to avoid some pointer math. Add __counted_by for extra runtime analysis. Move the counting variable assignment to right after allocation as required by __counted_by. Signed-off-by: Rosen Penev Link: https://lore.kernel.org/r/20260327025534.7864-1-rosenp@gmail.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/wcnss_ctrl.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/soc/qcom/wcnss_ctrl.c b/drivers/soc/qcom/wcnss_ctrl.c index 62b424e90d90..ffb31a049d4a 100644 --- a/drivers/soc/qcom/wcnss_ctrl.c +++ b/drivers/soc/qcom/wcnss_ctrl.c @@ -94,7 +94,7 @@ struct wcnss_download_nv_req { u16 seq; u16 last; u32 frag_size; - u8 fragment[]; + u8 fragment[] __counted_by(frag_size); } __packed; /** @@ -201,16 +201,12 @@ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc) { const struct firmware *fw; struct device *dev = wcnss->dev; + struct wcnss_download_nv_req *req; const char *nvbin = NVBIN_FILE; const void *data; ssize_t left; int ret; - struct wcnss_download_nv_req *req __free(kfree) = kzalloc(sizeof(*req) + NV_FRAGMENT_SIZE, - GFP_KERNEL); - if (!req) - return -ENOMEM; - ret = of_property_read_string(dev->of_node, "firmware-name", &nvbin); if (ret < 0 && ret != -EINVAL) return ret; @@ -224,11 +220,15 @@ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc) data = fw->data; left = fw->size; + req = kzalloc_flex(*req, fragment, NV_FRAGMENT_SIZE); + if (!req) + return -ENOMEM; + + req->frag_size = NV_FRAGMENT_SIZE; req->hdr.type = WCNSS_DOWNLOAD_NV_REQ; - req->hdr.len = sizeof(*req) + NV_FRAGMENT_SIZE; + req->hdr.len = struct_size(req, fragment, NV_FRAGMENT_SIZE); req->last = 0; - req->frag_size = NV_FRAGMENT_SIZE; req->seq = 0; do { @@ -264,6 +264,7 @@ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc) release_fw: release_firmware(fw); + kfree(req); return ret; } From 0ff62b7f1b355d4cc0568d73e5911683bdcfe1e7 Mon Sep 17 00:00:00 2001 From: Gopikrishna Garmidi Date: Sun, 22 Mar 2026 23:27:39 -0700 Subject: [PATCH 178/193] firmware: qcom: scm: Allow QSEECOM on Mahua CRD Add Mahua CRD board to the QSEECOM allowlist for enabling access to efivars and uefi bootloader. Signed-off-by: Gopikrishna Garmidi Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260322-mahua-qcom_scm-support-v1-1-00c50db332ee@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 d1082695ec38..a5a2c25f463b 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 = "microsoft,romulus15", }, { .compatible = "qcom,glymur-crd" }, { .compatible = "qcom,hamoa-iot-evk" }, + { .compatible = "qcom,mahua-crd" }, { .compatible = "qcom,purwa-iot-evk" }, { .compatible = "qcom,sc8180x-primus" }, { .compatible = "qcom,x1e001de-devkit" }, From a559a742c95c55ae3b347f2b57d26830c0cdd566 Mon Sep 17 00:00:00 2001 From: Lei wang Date: Sat, 21 Mar 2026 11:23:06 -0400 Subject: [PATCH 179/193] dt-bindings: arm: qcom,ids: Add SoC ID for SA8650P Add unique ID for Qualcomm SA8650P SoC. Signed-off-by: Lei wang Signed-off-by: Radu Rendec Reviewed-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260321152307.9131-2-rrendec@redhat.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 0316b85747d9..336f7bb7188a 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -261,6 +261,7 @@ #define QCOM_ID_SM8475 530 #define QCOM_ID_SM8475P 531 #define QCOM_ID_SA8255P 532 +#define QCOM_ID_SA8650P 533 #define QCOM_ID_SA8775P 534 #define QCOM_ID_QRU1000 539 #define QCOM_ID_SM8475_2 540 From f55fa3e3dcd8f766266fdf878994f0ec09459a7d Mon Sep 17 00:00:00 2001 From: Lei wang Date: Sat, 21 Mar 2026 11:23:07 -0400 Subject: [PATCH 180/193] soc: qcom: socinfo: Add SoC ID for SA8650P Add SoC ID table entry for Qualcomm SA8650P. Signed-off-by: Lei wang Signed-off-by: Radu Rendec Reviewed-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260321152307.9131-3-rrendec@redhat.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 802bf289626f..8ffd903ebddb 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -490,6 +490,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(SM8475) }, { qcom_board_id(SM8475P) }, { qcom_board_id(SA8255P) }, + { qcom_board_id(SA8650P) }, { qcom_board_id(SA8775P) }, { qcom_board_id(QRU1000) }, { qcom_board_id(SM8475_2) }, From 07b9712339e3ce1d183adef996c0f317adc9848d Mon Sep 17 00:00:00 2001 From: Hrishabh Rajput Date: Wed, 11 Mar 2026 11:16:30 +0530 Subject: [PATCH 181/193] firmware: qcom: scm: Register gunyah watchdog device To restrict Gunyah watchdog initialization to Qualcomm platforms running under the Gunyah Hypervisor, register the watchdog device in the QCOM SCM driver. When Gunyah is not present or Gunyah emulates MMIO-based watchdog, we expect Qualcomm watchdog or ARM SBSA watchdog device to be present in the devicetree. First, we make sure we're running under the Gunyah Hypervisor. Then we move to check if any of the above mentioned watchdog device nodes are present, if not then we proceed to register the SMC-based Gunyah watchdog device. Reviewed-by: Dmitry Baryshkov Tested-by: Shivendra Pratap Tested-by: Neil Armstrong Signed-off-by: Hrishabh Rajput Signed-off-by: Pavankumar Kondeti Tested-by: Mukesh Ojha Link: https://lore.kernel.org/r/20260311-gunyah_watchdog-v8-1-4c1c0689de22@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 53 ++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index a5a2c25f463b..9292af4a76d2 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2470,6 +2470,56 @@ int qcom_scm_qtee_callback_response(phys_addr_t buf, size_t buf_size, } EXPORT_SYMBOL(qcom_scm_qtee_callback_response); +static void qcom_scm_gunyah_wdt_free(void *data) +{ + struct platform_device *gunyah_wdt_dev = data; + + platform_device_unregister(gunyah_wdt_dev); +} + +static void qcom_scm_gunyah_wdt_init(struct qcom_scm *scm) +{ + struct platform_device *gunyah_wdt_dev; + struct device_node *np; + bool of_wdt_available; + int i; + static const uuid_t gunyah_uuid = UUID_INIT(0xc1d58fcd, 0xa453, 0x5fdb, + 0x92, 0x65, 0xce, 0x36, + 0x67, 0x3d, 0x5f, 0x14); + static const char * const of_wdt_compatible[] = { + "qcom,kpss-wdt", + "arm,sbsa-gwdt", + }; + + /* Bail out if we are not running under Gunyah */ + if (!IS_ENABLED(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) || + !arm_smccc_hypervisor_has_uuid(&gunyah_uuid)) + return; + + /* + * Gunyah emulates either of Qualcomm watchdog or ARM SBSA watchdog on + * newer platforms. Bail out if we find them in the devicetree. + */ + for (i = 0; i < ARRAY_SIZE(of_wdt_compatible); i++) { + np = of_find_compatible_node(NULL, NULL, of_wdt_compatible[i]); + of_wdt_available = of_device_is_available(np); + of_node_put(np); + if (of_wdt_available) + return; + } + + gunyah_wdt_dev = platform_device_register_simple("gunyah-wdt", -1, + NULL, 0); + if (IS_ERR(gunyah_wdt_dev)) { + dev_err(scm->dev, "Failed to register Gunyah watchdog device: %ld\n", + PTR_ERR(gunyah_wdt_dev)); + return; + } + + devm_add_action_or_reset(scm->dev, qcom_scm_gunyah_wdt_free, + gunyah_wdt_dev); +} + static void qcom_scm_qtee_free(void *data) { struct platform_device *qtee_dev = data; @@ -2814,6 +2864,9 @@ static int qcom_scm_probe(struct platform_device *pdev) /* Initialize the QTEE object interface. */ qcom_scm_qtee_init(scm); + /* Initialize the Gunyah watchdog platform device. */ + qcom_scm_gunyah_wdt_init(scm); + return 0; } From 68a66a44af6e196ca426d1250104d3018ed9e74b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 25 Jan 2026 13:30:03 +0200 Subject: [PATCH 182/193] soc: qcom: ubwc: add helper to get min_acc length MDSS and GPU drivers use different approaches to get min_acc length. Add helper function that can be used by all the drivers. The helper reflects our current best guess, it blindly copies the approach adopted by the MDSS drivers and it matches current values selected by the GPU driver. Reviewed-by: Bryan O'Donoghue Acked-by: Bjorn Andersson Reviewed-by: Konrad Dybcio Reviewed-by: Dikshita Agarwal Tested-by: Wangao Wang Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260125-iris-ubwc-v4-1-1ff30644ac81@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- include/linux/soc/qcom/ubwc.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/linux/soc/qcom/ubwc.h b/include/linux/soc/qcom/ubwc.h index f052e241736c..5bdeca18d54d 100644 --- a/include/linux/soc/qcom/ubwc.h +++ b/include/linux/soc/qcom/ubwc.h @@ -74,4 +74,14 @@ static inline bool qcom_ubwc_get_ubwc_mode(const struct qcom_ubwc_cfg_data *cfg) return ret; } +/* + * This is the best guess, based on the MDSS driver, which worked so far. + */ +static inline bool qcom_ubwc_min_acc_length_64b(const struct qcom_ubwc_cfg_data *cfg) +{ + return cfg->ubwc_enc_version == UBWC_1_0 && + (cfg->ubwc_dec_version == UBWC_2_0 || + cfg->ubwc_dec_version == UBWC_3_0); +} + #endif /* __QCOM_UBWC_H__ */ From b2571ef8d4ec9bb636889a9132090bcc3449792e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 25 Jan 2026 13:30:04 +0200 Subject: [PATCH 183/193] soc: qcom: ubwc: add helpers to get programmable values Currently the database stores macrotile_mode in the data. However it can be derived from the rest of the data: it should be used for UBWC encoding >= 3.0 except for several corner cases (SM8150 and SC8180X). The ubwc_bank_spread field seems to be based on the impreside data we had for the MDSS and DPU programming. In some cases UBWC engine inside the display controller doesn't need to program it, although bank spread is to be enabled. Bank swizzle is also currently stored as is, but it is almost standard (banks 1-3 for UBWC 1.0 and 2-3 for other versions), the only exception being Lemans (it uses only bank 3). Add helpers returning values from the config for now. They will be rewritten later, in a separate series, but having the helper now simplifies refacroring the code later. Tested-by: Wangao Wang Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260125-iris-ubwc-v4-2-1ff30644ac81@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- include/linux/soc/qcom/ubwc.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/linux/soc/qcom/ubwc.h b/include/linux/soc/qcom/ubwc.h index 5bdeca18d54d..f5d0e2341261 100644 --- a/include/linux/soc/qcom/ubwc.h +++ b/include/linux/soc/qcom/ubwc.h @@ -84,4 +84,19 @@ static inline bool qcom_ubwc_min_acc_length_64b(const struct qcom_ubwc_cfg_data cfg->ubwc_dec_version == UBWC_3_0); } +static inline bool qcom_ubwc_macrotile_mode(const struct qcom_ubwc_cfg_data *cfg) +{ + return cfg->macrotile_mode; +} + +static inline bool qcom_ubwc_bank_spread(const struct qcom_ubwc_cfg_data *cfg) +{ + return cfg->ubwc_bank_spread; +} + +static inline u32 qcom_ubwc_swizzle(const struct qcom_ubwc_cfg_data *cfg) +{ + return cfg->ubwc_swizzle; +} + #endif /* __QCOM_UBWC_H__ */ From e57b53f0f36ae0a3b13a101f135027c4aebc1bee Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 18 Mar 2026 11:04:33 +0000 Subject: [PATCH 184/193] gpio: mpfs: Add interrupt support Add support for interrupts to the PolarFire SoC GPIO driver. Each GPIO has an independent interrupt that is wired to an interrupt mux that sits between the controllers and the PLIC. The SoC has more GPIO lines than connections from the mux to the PLIC, so some GPIOs must share PLIC interrupts. The configuration is not static and is set at runtime, conventionally by the platform's firmware. CoreGPIO, the version intended for use in the FPGA fabric has two interrupt output ports, one is IO_NUM bits wide, as is used in the hardened cores, and the other is a single bit with all lines ORed together. Acked-by: Bartosz Golaszewski Reviewed-by: Linus Walleij Signed-off-by: Conor Dooley --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-mpfs.c | 122 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 120 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b45fb799e36c..1d1239323f61 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -572,6 +572,7 @@ config GPIO_PL061 config GPIO_POLARFIRE_SOC bool "Microchip FPGA GPIO support" select REGMAP_MMIO + select GPIOLIB_IRQCHIP help Say yes here to support the GPIO controllers on Microchip FPGAs. diff --git a/drivers/gpio/gpio-mpfs.c b/drivers/gpio/gpio-mpfs.c index 9468795b9634..1a4cf213c723 100644 --- a/drivers/gpio/gpio-mpfs.c +++ b/drivers/gpio/gpio-mpfs.c @@ -9,8 +9,9 @@ #include #include #include -#include +#include #include +#include #include #include #include @@ -18,7 +19,7 @@ #define MPFS_GPIO_CTRL(i) (0x4 * (i)) #define MPFS_MAX_NUM_GPIO 32 -#define MPFS_GPIO_EN_INT 3 +#define MPFS_GPIO_EN_INT BIT(3) #define MPFS_GPIO_EN_OUT_BUF BIT(2) #define MPFS_GPIO_EN_IN BIT(1) #define MPFS_GPIO_EN_OUT BIT(0) @@ -52,6 +53,7 @@ static const struct regmap_config mpfs_gpio_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, + .use_raw_spinlock = true, }; static int mpfs_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio_index) @@ -114,13 +116,98 @@ static int mpfs_gpio_set(struct gpio_chip *gc, unsigned int gpio_index, int valu return ret; } +static int mpfs_gpio_irq_set_type(struct irq_data *data, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + int gpio_index = irqd_to_hwirq(data) % 32; + u32 interrupt_type; + + switch (type) { + case IRQ_TYPE_EDGE_BOTH: + interrupt_type = MPFS_GPIO_TYPE_INT_EDGE_BOTH; + break; + case IRQ_TYPE_EDGE_FALLING: + interrupt_type = MPFS_GPIO_TYPE_INT_EDGE_NEG; + break; + case IRQ_TYPE_EDGE_RISING: + interrupt_type = MPFS_GPIO_TYPE_INT_EDGE_POS; + break; + case IRQ_TYPE_LEVEL_HIGH: + interrupt_type = MPFS_GPIO_TYPE_INT_LEVEL_HIGH; + break; + case IRQ_TYPE_LEVEL_LOW: + interrupt_type = MPFS_GPIO_TYPE_INT_LEVEL_LOW; + break; + } + + regmap_update_bits(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index), + MPFS_GPIO_TYPE_INT_MASK, interrupt_type); + + return 0; +} + +static void mpfs_gpio_irq_unmask(struct irq_data *data) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + int gpio_index = irqd_to_hwirq(data) % 32; + + gpiochip_enable_irq(gc, gpio_index); + mpfs_gpio_direction_input(gc, gpio_index); + regmap_update_bits(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index), + MPFS_GPIO_EN_INT, MPFS_GPIO_EN_INT); +} + +static void mpfs_gpio_irq_mask(struct irq_data *data) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + int gpio_index = irqd_to_hwirq(data) % 32; + + regmap_update_bits(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index), + MPFS_GPIO_EN_INT, 0); + gpiochip_disable_irq(gc, gpio_index); +} + +static const struct irq_chip mpfs_gpio_irqchip = { + .name = "MPFS GPIO", + .irq_set_type = mpfs_gpio_irq_set_type, + .irq_mask = mpfs_gpio_irq_mask, + .irq_unmask = mpfs_gpio_irq_unmask, + .flags = IRQCHIP_IMMUTABLE | IRQCHIP_MASK_ON_SUSPEND, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static void mpfs_gpio_irq_handler(struct irq_desc *desc) +{ + struct irq_chip *irqchip = irq_desc_get_chip(desc); + struct mpfs_gpio_chip *mpfs_gpio = irq_desc_get_handler_data(desc); + unsigned long status; + u32 val; + int i; + + chained_irq_enter(irqchip, desc); + + regmap_read(mpfs_gpio->regs, MPFS_IRQ_REG, &val); + status = val; + for_each_set_bit(i, &status, MPFS_MAX_NUM_GPIO) { + regmap_write(mpfs_gpio->regs, MPFS_IRQ_REG, BIT(i)); + generic_handle_domain_irq(mpfs_gpio->gc.irq.domain, i); + } + + chained_irq_exit(irqchip, desc); +} + static int mpfs_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; struct mpfs_gpio_chip *mpfs_gpio; + struct gpio_irq_chip *girq; struct clk *clk; void __iomem *base; - int ngpios; + int ngpios, nirqs, ret; mpfs_gpio = devm_kzalloc(dev, sizeof(*mpfs_gpio), GFP_KERNEL); if (!mpfs_gpio) @@ -157,6 +244,35 @@ static int mpfs_gpio_probe(struct platform_device *pdev) mpfs_gpio->gc.parent = dev; mpfs_gpio->gc.owner = THIS_MODULE; + nirqs = of_irq_count(node); + if (nirqs > MPFS_MAX_NUM_GPIO) + return -ENXIO; + + if (nirqs) { + girq = &mpfs_gpio->gc.irq; + + gpio_irq_chip_set_chip(girq, &mpfs_gpio_irqchip); + + girq->num_parents = nirqs; + girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, + sizeof(*girq->parents), GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + + for (int i = 0; i < nirqs; i++) { + ret = platform_get_irq(pdev, i); + if (ret < 0) + return ret; + + girq->parents[i] = ret; + girq->parent_handler_data = mpfs_gpio; + girq->parent_handler = mpfs_gpio_irq_handler; + } + + girq->handler = handle_level_irq; + girq->default_type = IRQ_TYPE_NONE; + } + return devm_gpiochip_add_data(dev, &mpfs_gpio->gc, mpfs_gpio); } From 5f3575cc73dc64dc0912d1f8ccf6d00c20aedd5b Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 18 Mar 2026 11:04:34 +0000 Subject: [PATCH 185/193] dt-bindings: soc: microchip: document PolarFire SoC's gpio interrupt mux On PolarFire SoC there are more GPIO interrupts than there are interrupt lines available on the PLIC, and a runtime configurable mux is used to decide which interrupts are assigned direct connections to the PLIC & which are relegated to sharing a line. Reviewed-by: Herve Codina Reviewed-by: Rob Herring (Arm) Reviewed-by: Linus Walleij Signed-off-by: Conor Dooley --- .../soc/microchip/microchip,mpfs-irqmux.yaml | 103 ++++++++++++++++++ .../microchip,mpfs-mss-top-sysreg.yaml | 4 + 2 files changed, 107 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-irqmux.yaml diff --git a/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-irqmux.yaml b/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-irqmux.yaml new file mode 100644 index 000000000000..51164772724f --- /dev/null +++ b/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-irqmux.yaml @@ -0,0 +1,103 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/microchip/microchip,mpfs-irqmux.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip Polarfire SoC GPIO Interrupt Mux + +maintainers: + - Conor Dooley + +description: | + There are 3 GPIO controllers on this SoC, of which: + - GPIO controller 0 has 14 GPIOs + - GPIO controller 1 has 24 GPIOs + - GPIO controller 2 has 32 GPIOs + + All GPIOs are capable of generating interrupts, for a total of 70. + There are only 41 IRQs available however, so a configurable mux is used to + ensure all GPIOs can be used for interrupt generation. + 38 of the 41 interrupts are in what the documentation calls "direct mode", + as they provide an exclusive connection from a GPIO to the PLIC. + Lines 18 to 23 on GPIO controller 1 are always in "direct mode". + The 3 remaining interrupts are used to mux the interrupts which do not have + a exclusive connection, one for each GPIO controller. + +properties: + compatible: + const: microchip,mpfs-irqmux + + reg: + maxItems: 1 + + "#address-cells": + const: 0 + + "#interrupt-cells": + const: 1 + + interrupt-map-mask: + items: + - const: 0x7f + + interrupt-map: + description: | + Specifies the mapping from GPIO interrupt lines to plic interrupts. + + The child interrupt number set in arrays items is computed using the + following formula: + gpio_bank * 32 + gpio_number + with: + - gpio_bank: The GPIO bank number + - 0 for GPIO0, + - 1 for GPIO1, + - 2 for GPIO2 + - gpio_number: Number of the gpio in the bank (0..31) + maxItems: 70 + +required: + - compatible + - reg + - "#address-cells" + - "#interrupt-cells" + - interrupt-map-mask + - interrupt-map + +additionalProperties: false + +examples: + - | + interrupt-controller@54 { + compatible = "microchip,mpfs-irqmux"; + reg = <0x54 0x4>; + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-map-mask = <0x7f>; + interrupt-map = <0 &plic 13>, <1 &plic 14>, <2 &plic 15>, + <3 &plic 16>, <4 &plic 17>, <5 &plic 18>, + <6 &plic 19>, <7 &plic 20>, <8 &plic 21>, + <9 &plic 22>, <10 &plic 23>, <11 &plic 24>, + <12 &plic 25>, <13 &plic 26>, + + <32 &plic 27>, <33 &plic 28>, <34 &plic 29>, + <35 &plic 30>, <36 &plic 31>, <37 &plic 32>, + <38 &plic 33>, <39 &plic 34>, <40 &plic 35>, + <41 &plic 36>, <42 &plic 37>, <43 &plic 38>, + <44 &plic 39>, <45 &plic 40>, <46 &plic 41>, + <47 &plic 42>, <48 &plic 43>, <49 &plic 44>, + <50 &plic 45>, <51 &plic 46>, <52 &plic 47>, + <53 &plic 48>, <54 &plic 49>, <55 &plic 50>, + + <64 &plic 53>, <65 &plic 53>, <66 &plic 53>, + <67 &plic 53>, <68 &plic 53>, <69 &plic 53>, + <70 &plic 53>, <71 &plic 53>, <72 &plic 53>, + <73 &plic 53>, <74 &plic 53>, <75 &plic 53>, + <76 &plic 53>, <77 &plic 53>, <78 &plic 53>, + <79 &plic 53>, <80 &plic 53>, <81 &plic 53>, + <82 &plic 53>, <83 &plic 53>, <84 &plic 53>, + <85 &plic 53>, <86 &plic 53>, <87 &plic 53>, + <88 &plic 53>, <89 &plic 53>, <90 &plic 53>, + <91 &plic 53>, <92 &plic 53>, <93 &plic 53>, + <94 &plic 53>, <95 &plic 53>; + }; diff --git a/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml b/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml index 2c1efcdf59b7..1e3725335b2c 100644 --- a/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml +++ b/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml @@ -44,6 +44,10 @@ properties: of PolarFire clock/reset IDs. const: 1 + interrupt-controller@54: + type: object + $ref: /schemas/soc/microchip/microchip,mpfs-irqmux.yaml + pinctrl@200: type: object $ref: /schemas/pinctrl/microchip,mpfs-pinctrl-iomux0.yaml From bd34cdd6d214f815570986ce55978fd7ddd8d8ac Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 18 Mar 2026 11:04:35 +0000 Subject: [PATCH 186/193] soc: microchip: add mpfs gpio interrupt mux driver On PolarFire SoC there are more GPIO interrupts than there are interrupt lines available on the PLIC, and a runtime configurable mux is used to decide which interrupts are assigned direct connections to the PLIC & which are relegated to sharing a line. Add a driver so that Linux can set the mux based on the interrupt mapping in the devicetree. Reviewed-by: Herve Codina Reviewed-by: Linus Walleij Reviewed-by: Bartosz Golaszewski Signed-off-by: Conor Dooley --- MAINTAINERS | 2 +- drivers/soc/microchip/Kconfig | 11 ++ drivers/soc/microchip/Makefile | 1 + drivers/soc/microchip/mpfs-irqmux.c | 181 ++++++++++++++++++++++++++++ 4 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/microchip/mpfs-irqmux.c diff --git a/MAINTAINERS b/MAINTAINERS index 55af015174a5..723c58756a5c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22734,7 +22734,7 @@ F: Documentation/devicetree/bindings/pinctrl/microchip,mpfs-pinctrl-mssio.yaml F: Documentation/devicetree/bindings/pinctrl/microchip,pic64gx-pinctrl-gpio2.yaml F: Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml F: Documentation/devicetree/bindings/riscv/microchip.yaml -F: Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-sys-controller.yaml +F: Documentation/devicetree/bindings/soc/microchip/microchip,mpfs*.yaml F: Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml F: Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml F: arch/riscv/boot/dts/microchip/ diff --git a/drivers/soc/microchip/Kconfig b/drivers/soc/microchip/Kconfig index bcf554602561..af7946741bce 100644 --- a/drivers/soc/microchip/Kconfig +++ b/drivers/soc/microchip/Kconfig @@ -1,3 +1,14 @@ +config POLARFIRE_SOC_IRQ_MUX + bool "Microchip PolarFire SoC's GPIO IRQ Mux" + depends on ARCH_MICROCHIP + select REGMAP + select REGMAP_MMIO + default y + help + Support for the interrupt mux on Polarfire SoC. It sits between + the GPIO controllers and the PLIC, as only 41 interrupts are shared + between 3 GPIO controllers with a total of 70 interrupts. + config POLARFIRE_SOC_SYS_CTRL tristate "Microchip PolarFire SoC (MPFS) system controller support" depends on POLARFIRE_SOC_MAILBOX diff --git a/drivers/soc/microchip/Makefile b/drivers/soc/microchip/Makefile index 1a3a1594b089..55775db45ee7 100644 --- a/drivers/soc/microchip/Makefile +++ b/drivers/soc/microchip/Makefile @@ -1,2 +1,3 @@ +obj-$(CONFIG_POLARFIRE_SOC_IRQ_MUX) += mpfs-irqmux.o obj-$(CONFIG_POLARFIRE_SOC_SYS_CTRL) += mpfs-sys-controller.o obj-$(CONFIG_POLARFIRE_SOC_SYSCONS) += mpfs-control-scb.o mpfs-mss-top-sysreg.o diff --git a/drivers/soc/microchip/mpfs-irqmux.c b/drivers/soc/microchip/mpfs-irqmux.c new file mode 100644 index 000000000000..ae15e913e780 --- /dev/null +++ b/drivers/soc/microchip/mpfs-irqmux.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Largely copied from rzn1_irqmux.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MPFS_IRQMUX_CR 0x54 +#define MPFS_IRQMUX_NUM_CHILDREN 96 +#define MPFS_IRQMUX_NUM_DIRECT 38 +#define MPFS_IRQMUX_DIRECT_START 13 +#define MPFS_IRQMUX_DIRECT_END 50 +#define MPFS_IRQMUX_NONDIRECT_END 53 + +static int mpfs_irqmux_is_direct_mode(struct device *dev, + const struct of_phandle_args *parent_args) +{ + if (parent_args->args_count != 1) { + dev_err(dev, "Invalid interrupt-map item\n"); + return -EINVAL; + } + + if (parent_args->args[0] < MPFS_IRQMUX_DIRECT_START || + parent_args->args[0] > MPFS_IRQMUX_NONDIRECT_END) { + dev_err(dev, "Invalid interrupt %u\n", parent_args->args[0]); + return -EINVAL; + } + + if (parent_args->args[0] > MPFS_IRQMUX_DIRECT_END) + return 0; + + return 1; +} + +static int mpfs_irqmux_probe(struct platform_device *pdev) +{ + DECLARE_BITMAP(child_done, MPFS_IRQMUX_NUM_CHILDREN) = {}; + DECLARE_BITMAP(parent_done, MPFS_IRQMUX_NUM_DIRECT) = {}; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct of_imap_parser imap_parser; + struct of_imap_item imap_item; + struct regmap *regmap; + int ret, direct_mode, line, controller, gpio, parent_line; + u32 tmp, val = 0, old; + + regmap = device_node_to_regmap(pdev->dev.parent->of_node); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to find syscon regmap\n"); + + /* We support only #interrupt-cells = <1> and #address-cells = <0> */ + ret = of_property_read_u32(np, "#interrupt-cells", &tmp); + if (ret) + return ret; + if (tmp != 1) + return -EINVAL; + + ret = of_property_read_u32(np, "#address-cells", &tmp); + if (ret) + return ret; + if (tmp != 0) + return -EINVAL; + + ret = of_imap_parser_init(&imap_parser, np, &imap_item); + if (ret) + return ret; + + for_each_of_imap_item(&imap_parser, &imap_item) { + + direct_mode = mpfs_irqmux_is_direct_mode(dev, &imap_item.parent_args); + if (direct_mode < 0) { + of_node_put(imap_item.parent_args.np); + return direct_mode; + } + + line = imap_item.child_imap[0]; + gpio = line % 32; + controller = line / 32; + + if (controller > 2) { + of_node_put(imap_item.parent_args.np); + dev_err(dev, "child interrupt number too large: %d\n", line); + return -EINVAL; + } + + if (test_and_set_bit(line, child_done)) { + of_node_put(imap_item.parent_args.np); + dev_err(dev, "mux child line %d already defined in interrupt-map\n", + line); + return -EINVAL; + } + + parent_line = imap_item.parent_args.args[0] - MPFS_IRQMUX_DIRECT_START; + if (direct_mode && test_and_set_bit(parent_line, parent_done)) { + of_node_put(imap_item.parent_args.np); + dev_err(dev, "mux parent line %d already defined in interrupt-map\n", + line); + return -EINVAL; + } + + /* + * There are 41 interrupts assigned to GPIOs, of which 38 are "direct". Since the + * mux has 32 bits only, 6 of these exclusive/"direct" interrupts remain. These + * are used by GPIO controller 1's lines 18 to 23. Nothing needs to be done + * for these interrupts. + */ + if (controller == 1 && gpio >= 18) + continue; + + /* + * The mux has a single register, where bits 0 to 13 mux between GPIO controller + * 1's 14 GPIOs and GPIO controller 2's first 14 GPIOs. The remaining bits mux + * between the first 18 GPIOs of controller 1 and the last 18 GPIOS of + * controller 2. If a bit in the mux's control register is set, the + * corresponding interrupt line for GPIO controller 0 or 1 will be put in + * "non-direct" mode. If cleared, the "fabric" controller's will. + * + * Register layout: + * GPIO 1 interrupt line 17 | mux bit 31 | GPIO 2 interrupt line 31 + * ... | ... | ... + * ... | ... | ... + * GPIO 1 interrupt line 0 | mux bit 14 | GPIO 2 interrupt line 14 + * GPIO 0 interrupt line 13 | mux bit 13 | GPIO 2 interrupt line 13 + * ... | ... | ... + * ... | ... | ... + * GPIO 0 interrupt line 0 | mux bit 0 | GPIO 2 interrupt line 0 + * + * As the binding mandates 70 items, one for each GPIO line, there's no need to + * handle anything for GPIO controller 2, since the bit will be set for the + * corresponding line in GPIO controller 0 or 1. + */ + if (controller == 2) + continue; + + /* + * If in direct mode, the bit is cleared, nothing needs to be done as val is zero + * initialised and that's the direct mode setting for GPIO controller 0 and 1. + */ + if (direct_mode) + continue; + + if (controller == 0) + val |= 1U << gpio; + else + val |= 1U << (gpio + 14); + } + + regmap_read(regmap, MPFS_IRQMUX_CR, &old); + regmap_write(regmap, MPFS_IRQMUX_CR, val); + + if (val != old) + dev_info(dev, "firmware mux setting of 0x%x overwritten to 0x%x\n", old, val); + + return 0; +} + +static const struct of_device_id mpfs_irqmux_of_match[] = { + { .compatible = "microchip,mpfs-irqmux", }, + { } +}; +MODULE_DEVICE_TABLE(of, mpfs_irqmux_of_match); + +static struct platform_driver mpfs_irqmux_driver = { + .probe = mpfs_irqmux_probe, + .driver = { + .name = "mpfs_irqmux", + .of_match_table = mpfs_irqmux_of_match, + }, +}; +module_platform_driver(mpfs_irqmux_driver); + +MODULE_AUTHOR("Conor Dooley "); +MODULE_DESCRIPTION("Polarfire SoC interrupt mux driver"); +MODULE_LICENSE("GPL"); From 6a1b6f7e56dc72ff8b4a83c728a2bed6d834e4cb Mon Sep 17 00:00:00 2001 From: Tommaso Merciai Date: Wed, 1 Apr 2026 17:16:08 +0200 Subject: [PATCH 187/193] dt-bindings: reset: renesas,rzv2h-usb2phy: Add '#mux-state-cells' property Add the '#mux-state-cells' property to support describing the USB VBUS_SEL multiplexer as a mux-controller in the Renesas RZ/V2H(P) USB2PHY binding. The mux-controller cannot be integrated into the parent USB2PHY node because the VBUS source selector is part of a separate hardware block, not the USB2PHY block itself. This is required to properly configure USB PHY power selection on RZ/V2H(P) and RZ/G3E SoCs. Acked-by: Krzysztof Kozlowski Signed-off-by: Tommaso Merciai Signed-off-by: Philipp Zabel --- .../bindings/reset/renesas,rzv2h-usb2phy-reset.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml b/Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml index c1b800a10b53..7ed0980b9ee1 100644 --- a/Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml +++ b/Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml @@ -37,6 +37,9 @@ properties: '#reset-cells': const: 0 + '#mux-state-cells': + const: 1 + required: - compatible - reg @@ -44,6 +47,7 @@ required: - resets - power-domains - '#reset-cells' + - '#mux-state-cells' additionalProperties: false @@ -58,4 +62,5 @@ examples: resets = <&cpg 0xaf>; power-domains = <&cpg>; #reset-cells = <0>; + #mux-state-cells = <1>; }; From 63be00249dd9f42a51fa164fa4eab920cb44f122 Mon Sep 17 00:00:00 2001 From: Tommaso Merciai Date: Wed, 1 Apr 2026 17:16:09 +0200 Subject: [PATCH 188/193] dt-bindings: reset: renesas,rzv2h-usb2phy: Document RZ/G3E USB2PHY reset Document USB2PHY reset controller bindings for RZ/G3E ("R9A09G047") SoC. The RZ/G3E USB2PHY reset controller is functionally identical to the one found on the RZ/V2H(P), so no driver changes are needed. The existing "renesas,r9a09g057-usb2phy-reset" will be used as a fallback compatible for this IP. Acked-by: Conor Dooley Signed-off-by: Tommaso Merciai Signed-off-by: Philipp Zabel --- .../bindings/reset/renesas,rzv2h-usb2phy-reset.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml b/Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml index 7ed0980b9ee1..66650ef8f772 100644 --- a/Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml +++ b/Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml @@ -17,7 +17,9 @@ properties: compatible: oneOf: - items: - - const: renesas,r9a09g056-usb2phy-reset # RZ/V2N + - enum: + - renesas,r9a09g047-usb2phy-reset # RZ/G3E + - renesas,r9a09g056-usb2phy-reset # RZ/V2N - const: renesas,r9a09g057-usb2phy-reset - const: renesas,r9a09g057-usb2phy-reset # RZ/V2H(P) From 890628c8d0f156a80a0aea02803d31fd8dd83fc0 Mon Sep 17 00:00:00 2001 From: Tommaso Merciai Date: Wed, 1 Apr 2026 17:16:10 +0200 Subject: [PATCH 189/193] reset: rzv2h-usb2phy: Convert to regmap API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace raw MMIO accesses (readl/writel) with regmap_read() and regmap_multi_reg_write() via devm_regmap_init_mmio(). Drop the manual spinlock as regmap provides internal locking. Replace the custom rzv2h_usb2phy_regval struct with the standard reg_sequence, and encode assert/deassert sequences as reg_sequence arrays rather than individual scalar fields in the of_data descriptor. Use the reg_sequence .delay_us field to encode the 11 µs post-assert delay, replacing the explicit usleep_range(11, 20) call in rzv2h_usbphy_reset_assert(). Select REGMAP_MMIO in Kconfig. Signed-off-by: Tommaso Merciai Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel --- drivers/reset/Kconfig | 1 + drivers/reset/reset-rzv2h-usb2phy.c | 108 ++++++++++++++-------------- 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index c73145749455..a2f56ea470c5 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -257,6 +257,7 @@ config RESET_RZG2L_USBPHY_CTRL config RESET_RZV2H_USB2PHY tristate "Renesas RZ/V2H(P) (and similar SoCs) USB2PHY Reset driver" depends on ARCH_RENESAS || COMPILE_TEST + select REGMAP_MMIO help Support for USB2PHY Port reset Control found on the RZ/V2H(P) SoC (and similar SoCs). diff --git a/drivers/reset/reset-rzv2h-usb2phy.c b/drivers/reset/reset-rzv2h-usb2phy.c index 5bdd39274612..c79bf72602e8 100644 --- a/drivers/reset/reset-rzv2h-usb2phy.c +++ b/drivers/reset/reset-rzv2h-usb2phy.c @@ -5,42 +5,35 @@ * Copyright (C) 2025 Renesas Electronics Corporation */ -#include #include #include #include #include #include #include +#include #include #include -struct rzv2h_usb2phy_regval { - u16 reg; - u16 val; -}; - struct rzv2h_usb2phy_reset_of_data { - const struct rzv2h_usb2phy_regval *init_vals; - unsigned int init_val_count; + const struct reg_sequence *init_seq; + unsigned int init_nseq; + + const struct reg_sequence *assert_seq; + unsigned int assert_nseq; + + const struct reg_sequence *deassert_seq; + unsigned int deassert_nseq; u16 reset_reg; - u16 reset_assert_val; - u16 reset_deassert_val; u16 reset_status_bits; - u16 reset_release_val; - - u16 reset2_reg; - u16 reset2_acquire_val; - u16 reset2_release_val; }; struct rzv2h_usb2phy_reset_priv { const struct rzv2h_usb2phy_reset_of_data *data; - void __iomem *base; + struct regmap *regmap; struct device *dev; struct reset_controller_dev rcdev; - spinlock_t lock; /* protects register accesses */ }; static inline struct rzv2h_usb2phy_reset_priv @@ -53,31 +46,18 @@ static int rzv2h_usbphy_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) { struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev); - const struct rzv2h_usb2phy_reset_of_data *data = priv->data; - scoped_guard(spinlock, &priv->lock) { - writel(data->reset2_acquire_val, priv->base + data->reset2_reg); - writel(data->reset_assert_val, priv->base + data->reset_reg); - } - - usleep_range(11, 20); - - return 0; + return regmap_multi_reg_write(priv->regmap, priv->data->assert_seq, + priv->data->assert_nseq); } static int rzv2h_usbphy_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) { struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev); - const struct rzv2h_usb2phy_reset_of_data *data = priv->data; - scoped_guard(spinlock, &priv->lock) { - writel(data->reset_deassert_val, priv->base + data->reset_reg); - writel(data->reset2_release_val, priv->base + data->reset2_reg); - writel(data->reset_release_val, priv->base + data->reset_reg); - } - - return 0; + return regmap_multi_reg_write(priv->regmap, priv->data->deassert_seq, + priv->data->deassert_nseq); } static int rzv2h_usbphy_reset_status(struct reset_controller_dev *rcdev, @@ -86,7 +66,7 @@ static int rzv2h_usbphy_reset_status(struct reset_controller_dev *rcdev, struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev); u32 reg; - reg = readl(priv->base + priv->data->reset_reg); + regmap_read(priv->regmap, priv->data->reset_reg, ®); return (reg & priv->data->reset_status_bits) == priv->data->reset_status_bits; } @@ -104,6 +84,13 @@ static int rzv2h_usb2phy_reset_of_xlate(struct reset_controller_dev *rcdev, return 0; } +static const struct regmap_config rzv2h_usb2phy_reset_regconf = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .can_sleep = true, +}; + static void rzv2h_usb2phy_reset_pm_runtime_put(void *data) { pm_runtime_put(data); @@ -115,6 +102,7 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev) struct rzv2h_usb2phy_reset_priv *priv; struct device *dev = &pdev->dev; struct reset_control *rstc; + void __iomem *base; int error; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -124,17 +112,19 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev) data = of_device_get_match_data(dev); priv->data = data; priv->dev = dev; - priv->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + priv->regmap = devm_regmap_init_mmio(dev, base, &rzv2h_usb2phy_reset_regconf); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); rstc = devm_reset_control_get_shared_deasserted(dev, NULL); if (IS_ERR(rstc)) return dev_err_probe(dev, PTR_ERR(rstc), "failed to get deasserted reset\n"); - spin_lock_init(&priv->lock); - error = devm_pm_runtime_enable(dev); if (error) return dev_err_probe(dev, error, "Failed to enable pm_runtime\n"); @@ -148,8 +138,9 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev) if (error) return dev_err_probe(dev, error, "unable to register cleanup action\n"); - for (unsigned int i = 0; i < data->init_val_count; i++) - writel(data->init_vals[i].val, priv->base + data->init_vals[i].reg); + error = regmap_multi_reg_write(priv->regmap, data->init_seq, data->init_nseq); + if (error) + return dev_err_probe(dev, error, "failed to initialize PHY registers\n"); priv->rcdev.ops = &rzv2h_usbphy_reset_ops; priv->rcdev.of_reset_n_cells = 0; @@ -169,23 +160,32 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev) * initialization values required to prepare the PHY to receive * assert and deassert requests. */ -static const struct rzv2h_usb2phy_regval rzv2h_init_vals[] = { - { .reg = 0xc10, .val = 0x67c }, - { .reg = 0xc14, .val = 0x1f }, - { .reg = 0x600, .val = 0x909 }, +static const struct reg_sequence rzv2h_init_seq[] = { + { .reg = 0xc10, .def = 0x67c }, + { .reg = 0xc14, .def = 0x01f }, + { .reg = 0x600, .def = 0x909 }, +}; + +static const struct reg_sequence rzv2h_assert_seq[] = { + { .reg = 0xb04, .def = 0x303 }, + { .reg = 0x000, .def = 0x206, .delay_us = 11 }, +}; + +static const struct reg_sequence rzv2h_deassert_seq[] = { + { .reg = 0x000, .def = 0x200 }, + { .reg = 0xb04, .def = 0x003 }, + { .reg = 0x000, .def = 0x000 }, }; static const struct rzv2h_usb2phy_reset_of_data rzv2h_reset_of_data = { - .init_vals = rzv2h_init_vals, - .init_val_count = ARRAY_SIZE(rzv2h_init_vals), + .init_seq = rzv2h_init_seq, + .init_nseq = ARRAY_SIZE(rzv2h_init_seq), + .assert_seq = rzv2h_assert_seq, + .assert_nseq = ARRAY_SIZE(rzv2h_assert_seq), + .deassert_seq = rzv2h_deassert_seq, + .deassert_nseq = ARRAY_SIZE(rzv2h_deassert_seq), .reset_reg = 0, - .reset_assert_val = 0x206, .reset_status_bits = BIT(2), - .reset_deassert_val = 0x200, - .reset_release_val = 0x0, - .reset2_reg = 0xb04, - .reset2_acquire_val = 0x303, - .reset2_release_val = 0x3, }; static const struct of_device_id rzv2h_usb2phy_reset_of_match[] = { From f62fcdf8ab826ffc811552e29a6dd8544281fd97 Mon Sep 17 00:00:00 2001 From: Tommaso Merciai Date: Wed, 1 Apr 2026 17:16:11 +0200 Subject: [PATCH 190/193] reset: rzv2h-usb2phy: Add support for VBUS mux controller registration The RZ/V2H USB2 PHY requires control of the VBUS selection line (VBENCTL) through a mux controller described in the device tree as "mux-controller". This change adds support for registering the rzv2h-usb-vbenctl auxiliary driver during probe. This enables proper management of USB2.0 VBUS source selection on platforms using the RZ/V2H SoC. Reviewed-by: Philipp Zabel Signed-off-by: Tommaso Merciai Signed-off-by: Philipp Zabel --- drivers/reset/Kconfig | 1 + drivers/reset/reset-rzv2h-usb2phy.c | 35 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index a2f56ea470c5..2fda1d9622f4 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -257,6 +257,7 @@ config RESET_RZG2L_USBPHY_CTRL config RESET_RZV2H_USB2PHY tristate "Renesas RZ/V2H(P) (and similar SoCs) USB2PHY Reset driver" depends on ARCH_RENESAS || COMPILE_TEST + select AUXILIARY_BUS select REGMAP_MMIO help Support for USB2PHY Port reset Control found on the RZ/V2H(P) SoC diff --git a/drivers/reset/reset-rzv2h-usb2phy.c b/drivers/reset/reset-rzv2h-usb2phy.c index c79bf72602e8..d96042e28cd5 100644 --- a/drivers/reset/reset-rzv2h-usb2phy.c +++ b/drivers/reset/reset-rzv2h-usb2phy.c @@ -5,7 +5,9 @@ * Copyright (C) 2025 Renesas Electronics Corporation */ +#include #include +#include #include #include #include @@ -15,6 +17,8 @@ #include #include +static DEFINE_IDA(auxiliary_ids); + struct rzv2h_usb2phy_reset_of_data { const struct reg_sequence *init_seq; unsigned int init_nseq; @@ -84,6 +88,33 @@ static int rzv2h_usb2phy_reset_of_xlate(struct reset_controller_dev *rcdev, return 0; } +static void rzv2h_usb2phy_reset_ida_free(void *data) +{ + struct auxiliary_device *adev = data; + + ida_free(&auxiliary_ids, adev->id); +} + +static int rzv2h_usb2phy_reset_mux_register(struct device *dev, + const char *mux_name) +{ + struct auxiliary_device *adev; + int id; + + id = ida_alloc(&auxiliary_ids, GFP_KERNEL); + if (id < 0) + return id; + + adev = __devm_auxiliary_device_create(dev, dev->driver->name, + mux_name, NULL, id); + if (!adev) { + ida_free(&auxiliary_ids, id); + return -ENOMEM; + } + + return devm_add_action_or_reset(dev, rzv2h_usb2phy_reset_ida_free, adev); +} + static const struct regmap_config rzv2h_usb2phy_reset_regconf = { .reg_bits = 32, .val_bits = 32, @@ -153,6 +184,10 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev) if (error) return dev_err_probe(dev, error, "could not register reset controller\n"); + error = rzv2h_usb2phy_reset_mux_register(dev, "vbenctl"); + if (error) + return dev_err_probe(dev, error, "could not register aux mux\n"); + return 0; } From a0ac82cbed1007afd89e30940fe2335b61666783 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Wed, 25 Mar 2026 14:22:04 +0800 Subject: [PATCH 191/193] clk: spear: fix resource leak in clk_register_vco_pll() Add a goto label in clk_register_vco_pll(), unregister vco_clk if tpll_clk is failed to be registered. Signed-off-by: Haoxiang Li Acked-by: Viresh Kumar Link: https://lore.kernel.org/r/20260325062204.169648-1-lihaoxiang@isrc.iscas.ac.cn Signed-off-by: Arnd Bergmann --- drivers/clk/spear/clk-vco-pll.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c index 601e123f5c4b..faba727e2f84 100644 --- a/drivers/clk/spear/clk-vco-pll.c +++ b/drivers/clk/spear/clk-vco-pll.c @@ -343,13 +343,15 @@ struct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name, tpll_clk = clk_register(NULL, &pll->hw); if (IS_ERR_OR_NULL(tpll_clk)) - goto free_pll; + goto unregister_clk; if (pll_clk) *pll_clk = tpll_clk; return vco_clk; +unregister_clk: + clk_unregister(vco_clk); free_pll: kfree(pll); free_vco: From a31ad9339eff4ce401dec816b01a94b4e3c47898 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 1 Apr 2026 21:31:27 -0500 Subject: [PATCH 192/193] firmware: qcom: scm: Allow QSEECOM on Lenovo IdeaCentre Mini X The Hamoa-based Lenovo IdeaCentre Mini X provides the same UEFI variable access through uefisecapp as other Hamoa devices, add it to the allowlist. Reviewed-by: Dmitry Baryshkov Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20260401-ideacentre-v2-3-5745fe2c764e@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 9292af4a76d2..9b06a69d3a6d 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2299,6 +2299,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "hp,omnibook-x14" }, { .compatible = "huawei,gaokun3" }, { .compatible = "lenovo,flex-5g" }, + { .compatible = "lenovo,ideacentre-mini-01q8x10" }, { .compatible = "lenovo,thinkbook-16" }, { .compatible = "lenovo,thinkpad-t14s" }, { .compatible = "lenovo,thinkpad-x13s", }, From 83210251fd70d5f96bcdc8911e15f7411a6b2463 Mon Sep 17 00:00:00 2001 From: Sebastian Ene Date: Thu, 2 Apr 2026 11:39:39 +0000 Subject: [PATCH 193/193] firmware: arm_ffa: Use the correct buffer size during RXTX_MAP Don't use the discovered buffer size from an FFA_FEATURES call directly since we can run on a system that has the PAGE_SIZE larger than the returned size which makes the alloc_pages_exact for the buffer to be rounded up. Fixes: 61824feae5c0 ("firmware: arm_ffa: Fetch the Rx/Tx buffer size using ffa_features()") Signed-off-by: Sebastian Ene Link: https://patch.msgid.link/20260402113939.930221-1-sebastianene@google.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index 12a625387d6e..83b8b47938b2 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -2078,7 +2078,7 @@ static int __init ffa_init(void) ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer), virt_to_phys(drv_info->rx_buffer), - rxtx_bufsz / FFA_PAGE_SIZE); + PAGE_ALIGN(rxtx_bufsz) / FFA_PAGE_SIZE); if (ret) { pr_err("failed to register FFA RxTx buffers\n"); goto free_pages;