From b07d8b37de7fde5c5abd158a137ee7b90e86f4e8 Mon Sep 17 00:00:00 2001 From: Kyle Deng Date: Fri, 18 Oct 2024 15:34:16 +0800 Subject: [PATCH 01/58] dt-bindings: soc: qcom,aoss-qmp: Document the qcs615 Document the Always-On Subsystem Qualcomm Message Protocol(AOSS_QMP) on the Qualcomm qcs615 platform. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kyle Deng Link: https://lore.kernel.org/r/20241018073417.2338864-3-quic_chunkaid@quicinc.com [bjorn: Fixed subject prefix] Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml index e63f800c6caae..41fbbe059d80c 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml @@ -25,6 +25,7 @@ properties: compatible: items: - enum: + - qcom,qcs615-aoss-qmp - qcom,qcs8300-aoss-qmp - qcom,qdu1000-aoss-qmp - qcom,sa8255p-aoss-qmp From 0124b9bebd64fbe718a661841b74616bdfb4e25d Mon Sep 17 00:00:00 2001 From: Qingqing Zhou Date: Tue, 5 Nov 2024 08:51:05 +0530 Subject: [PATCH 02/58] dt-bindings: firmware: qcom,scm: document QCS615 SCM Add the compatible for Qualcomm QCS615 SCM. Acked-by: Krzysztof Kozlowski Signed-off-by: Qingqing Zhou Link: https://lore.kernel.org/r/20241105032107.9552-2-quic_qqzhou@quicinc.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 2ee0300000078..66cc68babea09 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -42,6 +42,7 @@ properties: - qcom,scm-msm8996 - qcom,scm-msm8998 - qcom,scm-qcm2290 + - qcom,scm-qcs615 - qcom,scm-qcs8300 - qcom,scm-qdu1000 - qcom,scm-sa8255p From e501bfde65581aad673e1022fdaf4e8ab928f9f2 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Tue, 3 Dec 2024 19:35:44 +0000 Subject: [PATCH 03/58] firmware: arm_scmi: Allow transport properties for multiple instances Default SCMI transport properties values can be overridden with devicetree provided descriptors; in order to support multiple SCMI instances, make the properties-update happen on a per-instance copy of the original transport descriptor. Signed-off-by: Cristian Marussi Message-Id: <20241203193544.3895173-1-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 4 ++-- drivers/firmware/arm_scmi/driver.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 48b12f81141dd..10ea7962323e4 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -442,7 +442,7 @@ struct scmi_transport_core_operations { */ struct scmi_transport { struct device *supplier; - struct scmi_desc *desc; + struct scmi_desc desc; struct scmi_transport_core_operations **core_ops; }; @@ -468,7 +468,7 @@ static int __tag##_probe(struct platform_device *pdev) \ device_set_of_node_from_dev(&spdev->dev, dev); \ \ strans.supplier = dev; \ - strans.desc = &(__desc); \ + memcpy(&strans.desc, &(__desc), sizeof(strans.desc)); \ strans.core_ops = &(__core_ops); \ \ ret = platform_device_add_data(spdev, &strans, sizeof(strans)); \ diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 1b5fb2c4ce868..eeed1689b2080 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -3028,7 +3028,7 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev) int ret; trans = dev_get_platdata(dev); - if (!trans || !trans->desc || !trans->supplier || !trans->core_ops) + if (!trans || !trans->supplier || !trans->core_ops) return NULL; if (!device_link_add(dev, trans->supplier, DL_FLAG_AUTOREMOVE_CONSUMER)) { @@ -3043,33 +3043,33 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev) dev_info(dev, "Using %s\n", dev_driver_string(trans->supplier)); ret = of_property_read_u32(dev->of_node, "arm,max-rx-timeout-ms", - &trans->desc->max_rx_timeout_ms); + &trans->desc.max_rx_timeout_ms); if (ret && ret != -EINVAL) dev_err(dev, "Malformed arm,max-rx-timeout-ms DT property.\n"); ret = of_property_read_u32(dev->of_node, "arm,max-msg-size", - &trans->desc->max_msg_size); + &trans->desc.max_msg_size); if (ret && ret != -EINVAL) dev_err(dev, "Malformed arm,max-msg-size DT property.\n"); ret = of_property_read_u32(dev->of_node, "arm,max-msg", - &trans->desc->max_msg); + &trans->desc.max_msg); if (ret && ret != -EINVAL) dev_err(dev, "Malformed arm,max-msg DT property.\n"); 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, - trans->desc->max_msg); + trans->desc.max_rx_timeout_ms, trans->desc.max_msg_size, + trans->desc.max_msg); /* System wide atomic threshold for atomic ops .. if any */ if (!of_property_read_u32(dev->of_node, "atomic-threshold-us", - &trans->desc->atomic_threshold)) + &trans->desc.atomic_threshold)) dev_info(dev, "SCMI System wide atomic threshold set to %u us\n", - trans->desc->atomic_threshold); + trans->desc.atomic_threshold); - return trans->desc; + return &trans->desc; } static int scmi_probe(struct platform_device *pdev) From 0b4dc35529f87d99fca91b259d50f54613bf9ec0 Mon Sep 17 00:00:00 2001 From: "alice.guo" Date: Mon, 18 Nov 2024 10:17:16 +0800 Subject: [PATCH 04/58] soc: imx: Add SoC device register for i.MX9 i.MX9 SoCs have SoC ID, SoC revision number and chip unique identifier which are provided by the corresponding ARM trusted firmware API. This patch intends to use SMC call to obtain these information and then register i.MX9 SoC as a device. Signed-off-by: Alice Guo Tested-by: Alexander Stein Reviewed-by: Stefan Wahren Signed-off-by: Shawn Guo --- drivers/soc/imx/Makefile | 2 +- drivers/soc/imx/soc-imx9.c | 128 +++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/imx/soc-imx9.c diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile index 3ad321ca608a6..ca6a5fa1618fc 100644 --- a/drivers/soc/imx/Makefile +++ b/drivers/soc/imx/Makefile @@ -3,4 +3,4 @@ ifeq ($(CONFIG_ARM),y) obj-$(CONFIG_ARCH_MXC) += soc-imx.o endif obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o -obj-$(CONFIG_SOC_IMX9) += imx93-src.o +obj-$(CONFIG_SOC_IMX9) += imx93-src.o soc-imx9.o diff --git a/drivers/soc/imx/soc-imx9.c b/drivers/soc/imx/soc-imx9.c new file mode 100644 index 0000000000000..b46d22cf0212c --- /dev/null +++ b/drivers/soc/imx/soc-imx9.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include +#include + +#define IMX_SIP_GET_SOC_INFO 0xc2000006 +#define SOC_ID(x) (((x) & 0xFFFF) >> 8) +#define SOC_REV_MAJOR(x) ((((x) >> 28) & 0xF) - 0x9) +#define SOC_REV_MINOR(x) (((x) >> 24) & 0xF) + +static int imx9_soc_probe(struct platform_device *pdev) +{ + struct soc_device_attribute *attr; + struct arm_smccc_res res; + struct soc_device *sdev; + u32 soc_id, rev_major, rev_minor; + u64 uid127_64, uid63_0; + int err; + + attr = kzalloc(sizeof(*attr), GFP_KERNEL); + if (!attr) + return -ENOMEM; + + err = of_property_read_string(of_root, "model", &attr->machine); + if (err) { + pr_err("%s: missing model property: %d\n", __func__, err); + goto attr; + } + + attr->family = kasprintf(GFP_KERNEL, "Freescale i.MX"); + + /* + * Retrieve the soc id, rev & uid info: + * res.a1[31:16]: soc revision; + * res.a1[15:0]: soc id; + * res.a2: uid[127:64]; + * res.a3: uid[63:0]; + */ + arm_smccc_smc(IMX_SIP_GET_SOC_INFO, 0, 0, 0, 0, 0, 0, 0, &res); + if (res.a0 != SMCCC_RET_SUCCESS) { + pr_err("%s: SMC failed: 0x%lx\n", __func__, res.a0); + err = -EINVAL; + goto family; + } + + soc_id = SOC_ID(res.a1); + rev_major = SOC_REV_MAJOR(res.a1); + rev_minor = SOC_REV_MINOR(res.a1); + + attr->soc_id = kasprintf(GFP_KERNEL, "i.MX%2x", soc_id); + attr->revision = kasprintf(GFP_KERNEL, "%d.%d", rev_major, rev_minor); + + uid127_64 = res.a2; + uid63_0 = res.a3; + attr->serial_number = kasprintf(GFP_KERNEL, "%016llx%016llx", uid127_64, uid63_0); + + sdev = soc_device_register(attr); + if (IS_ERR(sdev)) { + err = PTR_ERR(sdev); + pr_err("%s failed to register SoC as a device: %d\n", __func__, err); + goto serial_number; + } + + return 0; + +serial_number: + kfree(attr->serial_number); + kfree(attr->revision); + kfree(attr->soc_id); +family: + kfree(attr->family); +attr: + kfree(attr); + return err; +} + +static __maybe_unused const struct of_device_id imx9_soc_match[] = { + { .compatible = "fsl,imx93", }, + { .compatible = "fsl,imx95", }, + { } +}; + +#define IMX_SOC_DRIVER "imx9-soc" + +static struct platform_driver imx9_soc_driver = { + .probe = imx9_soc_probe, + .driver = { + .name = IMX_SOC_DRIVER, + }, +}; + +static int __init imx9_soc_init(void) +{ + int ret; + struct platform_device *pdev; + + /* No match means it is not an i.MX 9 series SoC, do nothing. */ + if (!of_match_node(imx9_soc_match, of_root)) + return 0; + + ret = platform_driver_register(&imx9_soc_driver); + if (ret) { + pr_err("failed to register imx9_soc platform driver: %d\n", ret); + return ret; + } + + pdev = platform_device_register_simple(IMX_SOC_DRIVER, -1, NULL, 0); + if (IS_ERR(pdev)) { + pr_err("failed to register imx9_soc platform device: %ld\n", PTR_ERR(pdev)); + platform_driver_unregister(&imx9_soc_driver); + return PTR_ERR(pdev); + } + + return 0; +} +device_initcall(imx9_soc_init); + +MODULE_AUTHOR("NXP"); +MODULE_DESCRIPTION("NXP i.MX9 SoC"); +MODULE_LICENSE("GPL"); From 1ec0fa90070c9468d22b3c3ea5f4bd6c27810907 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Wed, 4 Dec 2024 10:43:11 +0100 Subject: [PATCH 05/58] memory: ti-aemif: Store timings parameter in number of cycles - 1 The CS configuration register expects timings to be expressed in 'number of cycles - 1' but they are stored in ns in the struct aemif_cs_data. So at init, the timings currently set are converted to ns by aemif_get_hw_params(), updated with values from the device-tree properties, and then converted back to 'number of cycles - 1' before being applied. Store the timings directly in 'number of cycles - 1' instead of nanoseconds. Perform the conversion from nanosecond during the device-tree parsing. Remove aemif_cycles_to_nsec() as it isn't used anymore. Signed-off-by: Bastien Curutchet Reviewed-by: Miquel Raynal Link: https://lore.kernel.org/r/20241204094319.1050826-2-bastien.curutchet@bootlin.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/ti-aemif.c | 135 ++++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 56 deletions(-) diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c index d54dc3cfff73c..f23a549b219b7 100644 --- a/drivers/memory/ti-aemif.c +++ b/drivers/memory/ti-aemif.c @@ -82,26 +82,26 @@ /** * struct aemif_cs_data: structure to hold cs parameters * @cs: chip-select number - * @wstrobe: write strobe width, ns - * @rstrobe: read strobe width, ns - * @wsetup: write setup width, ns - * @whold: write hold width, ns - * @rsetup: read setup width, ns - * @rhold: read hold width, ns - * @ta: minimum turn around time, ns + * @wstrobe: write strobe width, number of cycles - 1 + * @rstrobe: read strobe width, number of cycles - 1 + * @wsetup: write setup width, number of cycles - 1 + * @whold: write hold width, number of cycles - 1 + * @rsetup: read setup width, number of cycles - 1 + * @rhold: read hold width, number of cycles - 1 + * @ta: minimum turn around time, number of cycles - 1 * @enable_ss: enable/disable select strobe mode * @enable_ew: enable/disable extended wait mode * @asize: width of the asynchronous device's data bus */ struct aemif_cs_data { u8 cs; - u16 wstrobe; - u16 rstrobe; - u8 wsetup; - u8 whold; - u8 rsetup; - u8 rhold; - u8 ta; + u32 wstrobe; + u32 rstrobe; + u32 wsetup; + u32 whold; + u32 rsetup; + u32 rhold; + u32 ta; u8 enable_ss; u8 enable_ew; u8 asize; @@ -175,26 +175,18 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum) struct aemif_device *aemif = platform_get_drvdata(pdev); struct aemif_cs_data *data = &aemif->cs_data[csnum]; int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup; - unsigned long clk_rate = aemif->clk_rate; unsigned offset; u32 set, val; offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; - ta = aemif_calc_rate(pdev, data->ta, clk_rate, TA_MAX); - rhold = aemif_calc_rate(pdev, data->rhold, clk_rate, RHOLD_MAX); - rstrobe = aemif_calc_rate(pdev, data->rstrobe, clk_rate, RSTROBE_MAX); - rsetup = aemif_calc_rate(pdev, data->rsetup, clk_rate, RSETUP_MAX); - whold = aemif_calc_rate(pdev, data->whold, clk_rate, WHOLD_MAX); - wstrobe = aemif_calc_rate(pdev, data->wstrobe, clk_rate, WSTROBE_MAX); - wsetup = aemif_calc_rate(pdev, data->wsetup, clk_rate, WSETUP_MAX); - - if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 || - whold < 0 || wstrobe < 0 || wsetup < 0) { - dev_err(&pdev->dev, "%s: cannot get suitable timings\n", - __func__); - return -EINVAL; - } + ta = data->ta; + rhold = data->rhold; + rstrobe = data->rstrobe; + rsetup = data->rsetup; + whold = data->whold; + wstrobe = data->wstrobe; + wsetup = data->wsetup; set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) | WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup); @@ -213,11 +205,6 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum) return 0; } -static inline int aemif_cycles_to_nsec(int val, unsigned long clk_rate) -{ - return ((val + 1) * NSEC_PER_MSEC) / clk_rate; -} - /** * aemif_get_hw_params - function to read hw register values * @pdev: platform device to read for @@ -231,19 +218,18 @@ static void aemif_get_hw_params(struct platform_device *pdev, int csnum) { struct aemif_device *aemif = platform_get_drvdata(pdev); struct aemif_cs_data *data = &aemif->cs_data[csnum]; - unsigned long clk_rate = aemif->clk_rate; u32 val, offset; offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; val = readl(aemif->base + offset); - data->ta = aemif_cycles_to_nsec(TA_VAL(val), clk_rate); - data->rhold = aemif_cycles_to_nsec(RHOLD_VAL(val), clk_rate); - data->rstrobe = aemif_cycles_to_nsec(RSTROBE_VAL(val), clk_rate); - data->rsetup = aemif_cycles_to_nsec(RSETUP_VAL(val), clk_rate); - data->whold = aemif_cycles_to_nsec(WHOLD_VAL(val), clk_rate); - data->wstrobe = aemif_cycles_to_nsec(WSTROBE_VAL(val), clk_rate); - data->wsetup = aemif_cycles_to_nsec(WSETUP_VAL(val), clk_rate); + data->ta = TA_VAL(val); + data->rhold = RHOLD_VAL(val); + data->rstrobe = RSTROBE_VAL(val); + data->rsetup = RSETUP_VAL(val); + data->whold = WHOLD_VAL(val); + data->wstrobe = WSTROBE_VAL(val); + data->wsetup = WSETUP_VAL(val); data->enable_ew = EW_VAL(val); data->enable_ss = SSTROBE_VAL(val); data->asize = val & ASIZE_MAX; @@ -261,7 +247,9 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, struct device_node *np) { struct aemif_device *aemif = platform_get_drvdata(pdev); + unsigned long clk_rate = aemif->clk_rate; struct aemif_cs_data *data; + int ret; u32 cs; u32 val; @@ -287,26 +275,61 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, aemif_get_hw_params(pdev, aemif->num_cs++); /* override the values from device node */ - if (!of_property_read_u32(np, "ti,cs-min-turnaround-ns", &val)) - data->ta = val; + if (!of_property_read_u32(np, "ti,cs-min-turnaround-ns", &val)) { + ret = aemif_calc_rate(pdev, val, clk_rate, TA_MAX); + if (ret < 0) + return ret; - if (!of_property_read_u32(np, "ti,cs-read-hold-ns", &val)) - data->rhold = val; + data->ta = ret; + } - if (!of_property_read_u32(np, "ti,cs-read-strobe-ns", &val)) - data->rstrobe = val; + if (!of_property_read_u32(np, "ti,cs-read-hold-ns", &val)) { + ret = aemif_calc_rate(pdev, val, clk_rate, RHOLD_MAX); + if (ret < 0) + return ret; - if (!of_property_read_u32(np, "ti,cs-read-setup-ns", &val)) - data->rsetup = val; + data->rhold = ret; + } - if (!of_property_read_u32(np, "ti,cs-write-hold-ns", &val)) - data->whold = val; + if (!of_property_read_u32(np, "ti,cs-read-strobe-ns", &val)) { + ret = aemif_calc_rate(pdev, val, clk_rate, RSTROBE_MAX); + if (ret < 0) + return ret; - if (!of_property_read_u32(np, "ti,cs-write-strobe-ns", &val)) - data->wstrobe = val; + data->rstrobe = ret; + } - if (!of_property_read_u32(np, "ti,cs-write-setup-ns", &val)) - data->wsetup = val; + if (!of_property_read_u32(np, "ti,cs-read-setup-ns", &val)) { + ret = aemif_calc_rate(pdev, val, clk_rate, RSETUP_MAX); + if (ret < 0) + return ret; + + data->rsetup = ret; + } + + if (!of_property_read_u32(np, "ti,cs-write-hold-ns", &val)) { + ret = aemif_calc_rate(pdev, val, clk_rate, WHOLD_MAX); + if (ret < 0) + return ret; + + data->whold = ret; + } + + if (!of_property_read_u32(np, "ti,cs-write-strobe-ns", &val)) { + ret = aemif_calc_rate(pdev, val, clk_rate, WSTROBE_MAX); + if (ret < 0) + return ret; + + data->wstrobe = ret; + } + + if (!of_property_read_u32(np, "ti,cs-write-setup-ns", &val)) { + ret = aemif_calc_rate(pdev, val, clk_rate, WSETUP_MAX); + if (ret < 0) + return ret; + + data->wsetup = ret; + } if (!of_property_read_u32(np, "ti,cs-bus-width", &val)) if (val == 16) From b3d57e179607106d5b08a635c49b338c409357d4 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Wed, 4 Dec 2024 10:43:12 +0100 Subject: [PATCH 06/58] memory: ti-aemif: Remove unnecessary local variables CS timings are copied to local variables that are then used as is, without any modifications. Remove these unneeded local variables and deal directly with the timings stored in the struct aemif_cs_data. Signed-off-by: Bastien Curutchet Reviewed-by: Miquel Raynal Link: https://lore.kernel.org/r/20241204094319.1050826-3-bastien.curutchet@bootlin.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/ti-aemif.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c index f23a549b219b7..a0e1a6b53256b 100644 --- a/drivers/memory/ti-aemif.c +++ b/drivers/memory/ti-aemif.c @@ -174,22 +174,14 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum) { struct aemif_device *aemif = platform_get_drvdata(pdev); struct aemif_cs_data *data = &aemif->cs_data[csnum]; - int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup; unsigned offset; u32 set, val; offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; - ta = data->ta; - rhold = data->rhold; - rstrobe = data->rstrobe; - rsetup = data->rsetup; - whold = data->whold; - wstrobe = data->wstrobe; - wsetup = data->wsetup; - - set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) | - WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup); + set = TA(data->ta) | + RHOLD(data->rhold) | RSTROBE(data->rstrobe) | RSETUP(data->rsetup) | + WHOLD(data->whold) | WSTROBE(data->wstrobe) | WSETUP(data->wsetup); set |= (data->asize & ACR_ASIZE_MASK); if (data->enable_ew) From 30b4da67655469bf8d4b8ba7c001096a1e10c7bf Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Wed, 4 Dec 2024 10:43:13 +0100 Subject: [PATCH 07/58] memory: ti-aemif: Wrap CS timings into a struct CS timings are store in the struct aemif_cs_data along with other CS parameters. It isn't convenient for exposing CS timings to other drivers without also exposing the other parameters. Wrap the CS timings in a new struct aemif_cs_timings to simplify their export in upcoming patches. Signed-off-by: Bastien Curutchet Reviewed-by: Miquel Raynal Link: https://lore.kernel.org/r/20241204094319.1050826-4-bastien.curutchet@bootlin.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/ti-aemif.c | 57 ++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c index a0e1a6b53256b..1d1b30112af5e 100644 --- a/drivers/memory/ti-aemif.c +++ b/drivers/memory/ti-aemif.c @@ -80,8 +80,7 @@ ASIZE_MAX) /** - * struct aemif_cs_data: structure to hold cs parameters - * @cs: chip-select number + * struct aemif_cs_timings: structure to hold CS timings * @wstrobe: write strobe width, number of cycles - 1 * @rstrobe: read strobe width, number of cycles - 1 * @wsetup: write setup width, number of cycles - 1 @@ -89,12 +88,8 @@ * @rsetup: read setup width, number of cycles - 1 * @rhold: read hold width, number of cycles - 1 * @ta: minimum turn around time, number of cycles - 1 - * @enable_ss: enable/disable select strobe mode - * @enable_ew: enable/disable extended wait mode - * @asize: width of the asynchronous device's data bus */ -struct aemif_cs_data { - u8 cs; +struct aemif_cs_timings { u32 wstrobe; u32 rstrobe; u32 wsetup; @@ -102,6 +97,19 @@ struct aemif_cs_data { u32 rsetup; u32 rhold; u32 ta; +}; + +/** + * struct aemif_cs_data: structure to hold CS parameters + * @timings: timings configuration + * @cs: chip-select number + * @enable_ss: enable/disable select strobe mode + * @enable_ew: enable/disable extended wait mode + * @asize: width of the asynchronous device's data bus + */ +struct aemif_cs_data { + struct aemif_cs_timings timings; + u8 cs; u8 enable_ss; u8 enable_ew; u8 asize; @@ -179,9 +187,10 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum) offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; - set = TA(data->ta) | - RHOLD(data->rhold) | RSTROBE(data->rstrobe) | RSETUP(data->rsetup) | - WHOLD(data->whold) | WSTROBE(data->wstrobe) | WSETUP(data->wsetup); + set = TA(data->timings.ta) | + RHOLD(data->timings.rhold) | RSTROBE(data->timings.rstrobe) | + RSETUP(data->timings.rsetup) | WHOLD(data->timings.whold) | + WSTROBE(data->timings.wstrobe) | WSETUP(data->timings.wsetup); set |= (data->asize & ACR_ASIZE_MASK); if (data->enable_ew) @@ -215,13 +224,13 @@ static void aemif_get_hw_params(struct platform_device *pdev, int csnum) offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; val = readl(aemif->base + offset); - data->ta = TA_VAL(val); - data->rhold = RHOLD_VAL(val); - data->rstrobe = RSTROBE_VAL(val); - data->rsetup = RSETUP_VAL(val); - data->whold = WHOLD_VAL(val); - data->wstrobe = WSTROBE_VAL(val); - data->wsetup = WSETUP_VAL(val); + data->timings.ta = TA_VAL(val); + data->timings.rhold = RHOLD_VAL(val); + data->timings.rstrobe = RSTROBE_VAL(val); + data->timings.rsetup = RSETUP_VAL(val); + data->timings.whold = WHOLD_VAL(val); + data->timings.wstrobe = WSTROBE_VAL(val); + data->timings.wsetup = WSETUP_VAL(val); data->enable_ew = EW_VAL(val); data->enable_ss = SSTROBE_VAL(val); data->asize = val & ASIZE_MAX; @@ -272,7 +281,7 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, if (ret < 0) return ret; - data->ta = ret; + data->timings.ta = ret; } if (!of_property_read_u32(np, "ti,cs-read-hold-ns", &val)) { @@ -280,7 +289,7 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, if (ret < 0) return ret; - data->rhold = ret; + data->timings.rhold = ret; } if (!of_property_read_u32(np, "ti,cs-read-strobe-ns", &val)) { @@ -288,7 +297,7 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, if (ret < 0) return ret; - data->rstrobe = ret; + data->timings.rstrobe = ret; } if (!of_property_read_u32(np, "ti,cs-read-setup-ns", &val)) { @@ -296,7 +305,7 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, if (ret < 0) return ret; - data->rsetup = ret; + data->timings.rsetup = ret; } if (!of_property_read_u32(np, "ti,cs-write-hold-ns", &val)) { @@ -304,7 +313,7 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, if (ret < 0) return ret; - data->whold = ret; + data->timings.whold = ret; } if (!of_property_read_u32(np, "ti,cs-write-strobe-ns", &val)) { @@ -312,7 +321,7 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, if (ret < 0) return ret; - data->wstrobe = ret; + data->timings.wstrobe = ret; } if (!of_property_read_u32(np, "ti,cs-write-setup-ns", &val)) { @@ -320,7 +329,7 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, if (ret < 0) return ret; - data->wsetup = ret; + data->timings.wsetup = ret; } if (!of_property_read_u32(np, "ti,cs-bus-width", &val)) From 2c7b585d19cc1a7185a3a0b58cb643d28fd19cc1 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Wed, 4 Dec 2024 10:43:14 +0100 Subject: [PATCH 08/58] memory: ti-aemif: Create aemif_check_cs_timings() aemif_calc_rate() checks the validity of a new computed timing against a 'max' value given as input. This isn't convenient if we want to check the CS timing configuration somewhere else in the code. Wrap the verification of all the chip select's timing configuration into a single function to ease its exportation in upcoming patches. Remove the validity check from aemif_calc_rate(). Also remove the no longer used 'max' input and change the return type to u32. Remove the check of the aemif_calc_rate()'s return value during device-tree parsing as aemif_calc_rate() can't fail anymore. Signed-off-by: Bastien Curutchet Reviewed-by: Miquel Raynal Link: https://lore.kernel.org/r/20241204094319.1050826-5-bastien.curutchet@bootlin.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/ti-aemif.c | 111 ++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 60 deletions(-) diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c index 1d1b30112af5e..ec770a2668e7f 100644 --- a/drivers/memory/ti-aemif.c +++ b/drivers/memory/ti-aemif.c @@ -133,18 +133,48 @@ struct aemif_device { struct aemif_cs_data cs_data[NUM_CS]; }; +/** + * aemif_check_cs_timings() - Check the validity of a CS timing configuration. + * @timings: timings configuration + * + * @return: 0 if the timing configuration is valid, negative error number otherwise. + */ +static int aemif_check_cs_timings(struct aemif_cs_timings *timings) +{ + if (timings->ta > TA_MAX) + return -EINVAL; + + if (timings->rhold > RHOLD_MAX) + return -EINVAL; + + if (timings->rstrobe > RSTROBE_MAX) + return -EINVAL; + + if (timings->rsetup > RSETUP_MAX) + return -EINVAL; + + if (timings->whold > WHOLD_MAX) + return -EINVAL; + + if (timings->wstrobe > WSTROBE_MAX) + return -EINVAL; + + if (timings->wsetup > WSETUP_MAX) + return -EINVAL; + + return 0; +} + /** * aemif_calc_rate - calculate timing data. * @pdev: platform device to calculate for * @wanted: The cycle time needed in nanoseconds. * @clk: The input clock rate in kHz. - * @max: The maximum divider value that can be programmed. * - * On success, returns the calculated timing value minus 1 for easy - * programming into AEMIF timing registers, else negative errno. + * @return: the calculated timing value minus 1 for easy + * programming into AEMIF timing registers. */ -static int aemif_calc_rate(struct platform_device *pdev, int wanted, - unsigned long clk, int max) +static u32 aemif_calc_rate(struct platform_device *pdev, int wanted, unsigned long clk) { int result; @@ -157,10 +187,6 @@ static int aemif_calc_rate(struct platform_device *pdev, int wanted, if (result < 0) result = 0; - /* ... But configuring tighter timings is not an option. */ - else if (result > max) - result = -EINVAL; - return result; } @@ -250,7 +276,6 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, struct aemif_device *aemif = platform_get_drvdata(pdev); unsigned long clk_rate = aemif->clk_rate; struct aemif_cs_data *data; - int ret; u32 cs; u32 val; @@ -276,68 +301,34 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, aemif_get_hw_params(pdev, aemif->num_cs++); /* override the values from device node */ - if (!of_property_read_u32(np, "ti,cs-min-turnaround-ns", &val)) { - ret = aemif_calc_rate(pdev, val, clk_rate, TA_MAX); - if (ret < 0) - return ret; - - data->timings.ta = ret; - } + if (!of_property_read_u32(np, "ti,cs-min-turnaround-ns", &val)) + data->timings.ta = aemif_calc_rate(pdev, val, clk_rate); - if (!of_property_read_u32(np, "ti,cs-read-hold-ns", &val)) { - ret = aemif_calc_rate(pdev, val, clk_rate, RHOLD_MAX); - if (ret < 0) - return ret; - - data->timings.rhold = ret; - } + if (!of_property_read_u32(np, "ti,cs-read-hold-ns", &val)) + data->timings.rhold = aemif_calc_rate(pdev, val, clk_rate); - if (!of_property_read_u32(np, "ti,cs-read-strobe-ns", &val)) { - ret = aemif_calc_rate(pdev, val, clk_rate, RSTROBE_MAX); - if (ret < 0) - return ret; + if (!of_property_read_u32(np, "ti,cs-read-strobe-ns", &val)) + data->timings.rstrobe = aemif_calc_rate(pdev, val, clk_rate); - data->timings.rstrobe = ret; - } + if (!of_property_read_u32(np, "ti,cs-read-setup-ns", &val)) + data->timings.rsetup = aemif_calc_rate(pdev, val, clk_rate); - if (!of_property_read_u32(np, "ti,cs-read-setup-ns", &val)) { - ret = aemif_calc_rate(pdev, val, clk_rate, RSETUP_MAX); - if (ret < 0) - return ret; + if (!of_property_read_u32(np, "ti,cs-write-hold-ns", &val)) + data->timings.whold = aemif_calc_rate(pdev, val, clk_rate); - data->timings.rsetup = ret; - } + if (!of_property_read_u32(np, "ti,cs-write-strobe-ns", &val)) + data->timings.wstrobe = aemif_calc_rate(pdev, val, clk_rate); - if (!of_property_read_u32(np, "ti,cs-write-hold-ns", &val)) { - ret = aemif_calc_rate(pdev, val, clk_rate, WHOLD_MAX); - if (ret < 0) - return ret; - - data->timings.whold = ret; - } - - if (!of_property_read_u32(np, "ti,cs-write-strobe-ns", &val)) { - ret = aemif_calc_rate(pdev, val, clk_rate, WSTROBE_MAX); - if (ret < 0) - return ret; - - data->timings.wstrobe = ret; - } - - if (!of_property_read_u32(np, "ti,cs-write-setup-ns", &val)) { - ret = aemif_calc_rate(pdev, val, clk_rate, WSETUP_MAX); - if (ret < 0) - return ret; - - data->timings.wsetup = ret; - } + if (!of_property_read_u32(np, "ti,cs-write-setup-ns", &val)) + data->timings.wsetup = aemif_calc_rate(pdev, val, clk_rate); if (!of_property_read_u32(np, "ti,cs-bus-width", &val)) if (val == 16) data->asize = 1; data->enable_ew = of_property_read_bool(np, "ti,cs-extended-wait-mode"); data->enable_ss = of_property_read_bool(np, "ti,cs-select-strobe-mode"); - return 0; + + return aemif_check_cs_timings(&data->timings); } static const struct of_device_id aemif_of_match[] = { From a6d60e3376065752137ec23d103f7d039c363e41 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Wed, 4 Dec 2024 10:43:15 +0100 Subject: [PATCH 09/58] memory: ti-aemif: Create aemif_set_cs_timings() Create an aemif_set_cs_timings() function to isolate the setting of a chip select timing configuration and ease its exportation. Signed-off-by: Bastien Curutchet Reviewed-by: Miquel Raynal Link: https://lore.kernel.org/r/20241204094319.1050826-6-bastien.curutchet@bootlin.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/ti-aemif.c | 65 +++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c index ec770a2668e7f..83fb308a831b1 100644 --- a/drivers/memory/ti-aemif.c +++ b/drivers/memory/ti-aemif.c @@ -69,15 +69,15 @@ #define ACR_SSTROBE_MASK BIT(31) #define ASIZE_16BIT 1 -#define CONFIG_MASK (TA(TA_MAX) | \ - RHOLD(RHOLD_MAX) | \ - RSTROBE(RSTROBE_MAX) | \ - RSETUP(RSETUP_MAX) | \ - WHOLD(WHOLD_MAX) | \ - WSTROBE(WSTROBE_MAX) | \ - WSETUP(WSETUP_MAX) | \ - EW(EW_MAX) | SSTROBE(SSTROBE_MAX) | \ - ASIZE_MAX) +#define TIMINGS_MASK (TA(TA_MAX) | \ + RHOLD(RHOLD_MAX) | \ + RSTROBE(RSTROBE_MAX) | \ + RSETUP(RSETUP_MAX) | \ + WHOLD(WHOLD_MAX) | \ + WSTROBE(WSTROBE_MAX) | \ + WSETUP(WSETUP_MAX)) + +#define CONFIG_MASK (EW(EW_MAX) | SSTROBE(SSTROBE_MAX) | ASIZE_MAX) /** * struct aemif_cs_timings: structure to hold CS timings @@ -165,6 +165,44 @@ static int aemif_check_cs_timings(struct aemif_cs_timings *timings) return 0; } +/** + * aemif_set_cs_timings() - Set the timing configuration of a given chip select. + * @aemif: aemif device to configure + * @cs: index of the chip select to configure + * @timings: timings configuration to set + * + * @return: 0 on success, else negative errno. + */ +static int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, struct aemif_cs_timings *timings) +{ + unsigned int offset; + u32 val, set; + int ret; + + if (!timings || !aemif) + return -EINVAL; + + if (cs > aemif->num_cs) + return -EINVAL; + + ret = aemif_check_cs_timings(timings); + if (ret) + return ret; + + set = TA(timings->ta) | RHOLD(timings->rhold) | RSTROBE(timings->rstrobe) | + RSETUP(timings->rsetup) | WHOLD(timings->whold) | + WSTROBE(timings->wstrobe) | WSETUP(timings->wsetup); + + offset = A1CR_OFFSET + cs * 4; + + val = readl(aemif->base + offset); + val &= ~TIMINGS_MASK; + val |= set; + writel(val, aemif->base + offset); + + return 0; +} + /** * aemif_calc_rate - calculate timing data. * @pdev: platform device to calculate for @@ -213,12 +251,7 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum) offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; - set = TA(data->timings.ta) | - RHOLD(data->timings.rhold) | RSTROBE(data->timings.rstrobe) | - RSETUP(data->timings.rsetup) | WHOLD(data->timings.whold) | - WSTROBE(data->timings.wstrobe) | WSETUP(data->timings.wsetup); - - set |= (data->asize & ACR_ASIZE_MASK); + set = (data->asize & ACR_ASIZE_MASK); if (data->enable_ew) set |= ACR_EW_MASK; if (data->enable_ss) @@ -229,7 +262,7 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum) val |= set; writel(val, aemif->base + offset); - return 0; + return aemif_set_cs_timings(aemif, data->cs - aemif->cs_offset, &data->timings); } /** From df8e78607d4795806b59564ba7a3e2e125d119fc Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Wed, 4 Dec 2024 10:43:16 +0100 Subject: [PATCH 10/58] memory: ti-aemif: Export aemif_*_cs_timings() Export the aemif_set_cs_timing() and aemif_check_cs_timing() symbols so they can be used by other drivers Add a mutex to protect the CS configuration register from concurrent accesses between the AEMIF and its 'children'. Signed-off-by: Bastien Curutchet Reviewed-by: Miquel Raynal Link: https://lore.kernel.org/r/20241204094319.1050826-7-bastien.curutchet@bootlin.com [krzysztof: wrap aemif_set_cs_timings() at 80-char] Signed-off-by: Krzysztof Kozlowski --- drivers/memory/ti-aemif.c | 36 +++++++++++++-------------------- include/linux/memory/ti-aemif.h | 32 +++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 22 deletions(-) create mode 100644 include/linux/memory/ti-aemif.h diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c index 83fb308a831b1..c8b83c9edbd58 100644 --- a/drivers/memory/ti-aemif.c +++ b/drivers/memory/ti-aemif.c @@ -13,7 +13,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -79,26 +81,6 @@ #define CONFIG_MASK (EW(EW_MAX) | SSTROBE(SSTROBE_MAX) | ASIZE_MAX) -/** - * struct aemif_cs_timings: structure to hold CS timings - * @wstrobe: write strobe width, number of cycles - 1 - * @rstrobe: read strobe width, number of cycles - 1 - * @wsetup: write setup width, number of cycles - 1 - * @whold: write hold width, number of cycles - 1 - * @rsetup: read setup width, number of cycles - 1 - * @rhold: read hold width, number of cycles - 1 - * @ta: minimum turn around time, number of cycles - 1 - */ -struct aemif_cs_timings { - u32 wstrobe; - u32 rstrobe; - u32 wsetup; - u32 whold; - u32 rsetup; - u32 rhold; - u32 ta; -}; - /** * struct aemif_cs_data: structure to hold CS parameters * @timings: timings configuration @@ -123,6 +105,7 @@ struct aemif_cs_data { * @num_cs: number of assigned chip-selects * @cs_offset: start number of cs nodes * @cs_data: array of chip-select settings + * @config_cs_lock: lock used to access CS configuration */ struct aemif_device { void __iomem *base; @@ -131,6 +114,7 @@ struct aemif_device { u8 num_cs; int cs_offset; struct aemif_cs_data cs_data[NUM_CS]; + struct mutex config_cs_lock; }; /** @@ -139,7 +123,7 @@ struct aemif_device { * * @return: 0 if the timing configuration is valid, negative error number otherwise. */ -static int aemif_check_cs_timings(struct aemif_cs_timings *timings) +int aemif_check_cs_timings(struct aemif_cs_timings *timings) { if (timings->ta > TA_MAX) return -EINVAL; @@ -164,6 +148,7 @@ static int aemif_check_cs_timings(struct aemif_cs_timings *timings) return 0; } +EXPORT_SYMBOL_GPL(aemif_check_cs_timings); /** * aemif_set_cs_timings() - Set the timing configuration of a given chip select. @@ -173,7 +158,8 @@ static int aemif_check_cs_timings(struct aemif_cs_timings *timings) * * @return: 0 on success, else negative errno. */ -static int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, struct aemif_cs_timings *timings) +int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, + struct aemif_cs_timings *timings) { unsigned int offset; u32 val, set; @@ -195,13 +181,16 @@ static int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, struct aemif_ offset = A1CR_OFFSET + cs * 4; + mutex_lock(&aemif->config_cs_lock); val = readl(aemif->base + offset); val &= ~TIMINGS_MASK; val |= set; writel(val, aemif->base + offset); + mutex_unlock(&aemif->config_cs_lock); return 0; } +EXPORT_SYMBOL_GPL(aemif_set_cs_timings); /** * aemif_calc_rate - calculate timing data. @@ -257,10 +246,12 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum) if (data->enable_ss) set |= ACR_SSTROBE_MASK; + mutex_lock(&aemif->config_cs_lock); val = readl(aemif->base + offset); val &= ~CONFIG_MASK; val |= set; writel(val, aemif->base + offset); + mutex_unlock(&aemif->config_cs_lock); return aemif_set_cs_timings(aemif, data->cs - aemif->cs_offset, &data->timings); } @@ -399,6 +390,7 @@ static int aemif_probe(struct platform_device *pdev) if (IS_ERR(aemif->base)) return PTR_ERR(aemif->base); + mutex_init(&aemif->config_cs_lock); if (np) { /* * For every controller device node, there is a cs device node diff --git a/include/linux/memory/ti-aemif.h b/include/linux/memory/ti-aemif.h new file mode 100644 index 0000000000000..da94a9d985e74 --- /dev/null +++ b/include/linux/memory/ti-aemif.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __MEMORY_TI_AEMIF_H +#define __MEMORY_TI_AEMIF_H + +/** + * struct aemif_cs_timings: structure to hold CS timing configuration + * values are expressed in number of clock cycles - 1 + * @ta: minimum turn around time + * @rhold: read hold width + * @rstrobe: read strobe width + * @rsetup: read setup width + * @whold: write hold width + * @wstrobe: write strobe width + * @wsetup: write setup width + */ +struct aemif_cs_timings { + u32 ta; + u32 rhold; + u32 rstrobe; + u32 rsetup; + u32 whold; + u32 wstrobe; + u32 wsetup; +}; + +struct aemif_device; + +int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, struct aemif_cs_timings *timings); +int aemif_check_cs_timings(struct aemif_cs_timings *timings); + +#endif // __MEMORY_TI_AEMIF_H From 54cf6e786caa29e125f34a3cf33bc7cfa3aa74da Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 9 Dec 2024 16:49:55 +0000 Subject: [PATCH 11/58] firmware: arm_scmi: Support vendor protocol modules autoloading SCMI vendor protocols namespace is shared amongst all vendors so that there can be multiple implementation for the same protocol ID by different vendors, exposing completely different functionalities and used by distinct SCMI vendor drivers. For these reasons, at runtime, when some driver asks for a protocol, the proper implementation to use is chosen based on the SCMI vendor/subvendor/ impl_version data as advertised by the platform SCMI server and gathered from the SCMI core during stack initialization: this enables proper runtime selection of vendor protocols even when many different protocols from different vendors are built into the same image via a common defconfig. This same selection mechanism works similarly well even when all the vendor protocols are compiled as loadable modules, as long as all such required protocol modules have been previously loaded by some other means. Add support for the automatic loading of vendor protocol modules, based on protocol/vendor IDs, when an SCMI driver attempts to use such a protocol. Reported-by: Johan Hovold Closes: https://lore.kernel.org/lkml/ZytnRc94iKUfMYH0@hovoldconsulting.com/ Signed-off-by: Cristian Marussi Message-Id: <20241209164957.1801886-2-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 56 ++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index eeed1689b2080..60050da54bf24 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,8 @@ #define CREATE_TRACE_POINTS #include +#define SCMI_VENDOR_MODULE_ALIAS_FMT "scmi-protocol-0x%02x-%s" + static DEFINE_IDA(scmi_id); static DEFINE_XARRAY(scmi_protocols); @@ -275,6 +278,44 @@ scmi_vendor_protocol_lookup(int protocol_id, char *vendor_id, return proto; } +static const struct scmi_protocol * +scmi_vendor_protocol_get(int protocol_id, struct scmi_revision_info *version) +{ + const struct scmi_protocol *proto; + + proto = scmi_vendor_protocol_lookup(protocol_id, version->vendor_id, + version->sub_vendor_id, + version->impl_ver); + if (!proto) { + int ret; + + pr_debug("Looking for '" SCMI_VENDOR_MODULE_ALIAS_FMT "'\n", + protocol_id, version->vendor_id); + + /* Note that vendor_id is mandatory for vendor protocols */ + ret = request_module(SCMI_VENDOR_MODULE_ALIAS_FMT, + protocol_id, version->vendor_id); + if (ret) { + pr_warn("Problem loading module for protocol 0x%x\n", + protocol_id); + return NULL; + } + + /* Lookup again, once modules loaded */ + proto = scmi_vendor_protocol_lookup(protocol_id, + version->vendor_id, + version->sub_vendor_id, + version->impl_ver); + } + + if (proto) + pr_info("Loaded SCMI Vendor Protocol 0x%x - %s %s %X\n", + protocol_id, proto->vendor_id ?: "", + proto->sub_vendor_id ?: "", proto->impl_ver); + + return proto; +} + static const struct scmi_protocol * scmi_protocol_get(int protocol_id, struct scmi_revision_info *version) { @@ -283,10 +324,8 @@ scmi_protocol_get(int protocol_id, struct scmi_revision_info *version) if (protocol_id < SCMI_PROTOCOL_VENDOR_BASE) proto = xa_load(&scmi_protocols, protocol_id); else - proto = scmi_vendor_protocol_lookup(protocol_id, - version->vendor_id, - version->sub_vendor_id, - version->impl_ver); + proto = scmi_vendor_protocol_get(protocol_id, version); + if (!proto || !try_module_get(proto->owner)) { pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id); return NULL; @@ -294,11 +333,6 @@ scmi_protocol_get(int protocol_id, struct scmi_revision_info *version) pr_debug("Found SCMI Protocol 0x%x\n", protocol_id); - if (protocol_id >= SCMI_PROTOCOL_VENDOR_BASE) - pr_info("Loaded SCMI Vendor Protocol 0x%x - %s %s %X\n", - protocol_id, proto->vendor_id ?: "", - proto->sub_vendor_id ?: "", proto->impl_ver); - return proto; } @@ -366,7 +400,9 @@ int scmi_protocol_register(const struct scmi_protocol *proto) return ret; } - pr_debug("Registered SCMI Protocol 0x%x\n", proto->id); + pr_debug("Registered SCMI Protocol 0x%x - %s %s 0x%08X\n", + proto->id, proto->vendor_id, proto->sub_vendor_id, + proto->impl_ver); return 0; } From d4cc8912cbff4990940b33cc61a9b09ddaee9704 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 9 Dec 2024 16:49:56 +0000 Subject: [PATCH 12/58] firmware: arm_scmi: Add module aliases to i.MX vendor protocols Using the pattern 'scmi-protocol-0x-' as MODULE_ALIAS allows the SCMI core to autoload this protocol, if built as a module, when its protocol operations are requested by an SCMI driver. Cc: Peng Fan Acked-by: Peng Fan Signed-off-by: Cristian Marussi Message-Id: <20241209164957.1801886-3-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/vendors/imx/imx-sm-bbm.c | 5 +++-- drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c | 5 +++-- include/linux/scmi_imx_protocol.h | 9 +++++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-bbm.c b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-bbm.c index 17799eacf06c3..aa176c1a5eefe 100644 --- a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-bbm.c +++ b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-bbm.c @@ -374,10 +374,11 @@ static const struct scmi_protocol scmi_imx_bbm = { .ops = &scmi_imx_bbm_proto_ops, .events = &scmi_imx_bbm_protocol_events, .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, - .vendor_id = "NXP", - .sub_vendor_id = "IMX", + .vendor_id = SCMI_IMX_VENDOR, + .sub_vendor_id = SCMI_IMX_SUBVENDOR, }; module_scmi_protocol(scmi_imx_bbm); +MODULE_ALIAS("scmi-protocol-" __stringify(SCMI_PROTOCOL_IMX_BBM) "-" SCMI_IMX_VENDOR); MODULE_DESCRIPTION("i.MX SCMI BBM driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c index a86ab9b35953f..83b69fc4fba5b 100644 --- a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c +++ b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c @@ -309,10 +309,11 @@ static const struct scmi_protocol scmi_imx_misc = { .ops = &scmi_imx_misc_proto_ops, .events = &scmi_imx_misc_protocol_events, .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, - .vendor_id = "NXP", - .sub_vendor_id = "IMX", + .vendor_id = SCMI_IMX_VENDOR, + .sub_vendor_id = SCMI_IMX_SUBVENDOR, }; module_scmi_protocol(scmi_imx_misc); +MODULE_ALIAS("scmi-protocol-" __stringify(SCMI_PROTOCOL_IMX_MISC) "-" SCMI_IMX_VENDOR); MODULE_DESCRIPTION("i.MX SCMI MISC driver"); MODULE_LICENSE("GPL"); diff --git a/include/linux/scmi_imx_protocol.h b/include/linux/scmi_imx_protocol.h index 066216f1357aa..53b356a264142 100644 --- a/include/linux/scmi_imx_protocol.h +++ b/include/linux/scmi_imx_protocol.h @@ -13,10 +13,11 @@ #include #include -enum scmi_nxp_protocol { - SCMI_PROTOCOL_IMX_BBM = 0x81, - SCMI_PROTOCOL_IMX_MISC = 0x84, -}; +#define SCMI_PROTOCOL_IMX_BBM 0x81 +#define SCMI_PROTOCOL_IMX_MISC 0x84 + +#define SCMI_IMX_VENDOR "NXP" +#define SCMI_IMX_SUBVENDOR "IMX" struct scmi_imx_bbm_proto_ops { int (*rtc_time_set)(const struct scmi_protocol_handle *ph, u32 id, From 3f3f0e53e9ae906844e8309fa433b48372f905e1 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 9 Dec 2024 16:49:57 +0000 Subject: [PATCH 13/58] firmware: arm_scmi: Add aliases to transport modules SCMI transports when built as loadable modules should be loaded by the subsystem they plug into, based on the related subsystem specific aliases. Add, where missing, the MODULE_DEVICE_TABLE() directives needed to generate the aliases required to enable autoloading for SCMI transports. Signed-off-by: Cristian Marussi Message-Id: <20241209164957.1801886-4-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/transports/mailbox.c | 1 + drivers/firmware/arm_scmi/transports/smc.c | 1 + drivers/firmware/arm_scmi/transports/virtio.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/firmware/arm_scmi/transports/mailbox.c b/drivers/firmware/arm_scmi/transports/mailbox.c index b66df29814566..bd041c99b92bd 100644 --- a/drivers/firmware/arm_scmi/transports/mailbox.c +++ b/drivers/firmware/arm_scmi/transports/mailbox.c @@ -378,6 +378,7 @@ static const struct of_device_id scmi_of_match[] = { { .compatible = "arm,scmi" }, { /* Sentinel */ }, }; +MODULE_DEVICE_TABLE(of, scmi_of_match); DEFINE_SCMI_TRANSPORT_DRIVER(scmi_mailbox, scmi_mailbox_driver, scmi_mailbox_desc, scmi_of_match, core); diff --git a/drivers/firmware/arm_scmi/transports/smc.c b/drivers/firmware/arm_scmi/transports/smc.c index f632a62cfb3ec..21abb571e4f2f 100644 --- a/drivers/firmware/arm_scmi/transports/smc.c +++ b/drivers/firmware/arm_scmi/transports/smc.c @@ -301,6 +301,7 @@ static const struct of_device_id scmi_of_match[] = { { .compatible = "qcom,scmi-smc" }, { /* Sentinel */ }, }; +MODULE_DEVICE_TABLE(of, scmi_of_match); DEFINE_SCMI_TRANSPORT_DRIVER(scmi_smc, scmi_smc_driver, scmi_smc_desc, scmi_of_match, core); diff --git a/drivers/firmware/arm_scmi/transports/virtio.c b/drivers/firmware/arm_scmi/transports/virtio.c index 41aea33776a9b..cb934db9b2b4a 100644 --- a/drivers/firmware/arm_scmi/transports/virtio.c +++ b/drivers/firmware/arm_scmi/transports/virtio.c @@ -921,6 +921,7 @@ static const struct virtio_device_id id_table[] = { { VIRTIO_ID_SCMI, VIRTIO_DEV_ANY_ID }, { 0 } }; +MODULE_DEVICE_TABLE(virtio, id_table); static struct virtio_driver virtio_scmi_driver = { .driver.name = "scmi-virtio", From e9f826b0459f1376b9c8beba019b84f9878419c6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 22 Aug 2024 18:48:15 +0200 Subject: [PATCH 14/58] soc: qcom: pmic_glink: simplify locking with guard() Simplify error handling over locks with guard(). In few places this elimiates error gotos and local variables. Switch to guard() everywhere (except when jumps would go over scoped guard) for consistency, even if it does not bring benefit in such places. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240822164815.230167-2-krzysztof.kozlowski@linaro.org [bjorn: Rebased ontop of v6.13-rc1] Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pmic_glink.c | 70 +++++++++++++++-------------------- 1 file changed, 29 insertions(+), 41 deletions(-) diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index caf3f63d940e3..052c292eeda61 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -4,6 +4,7 @@ * Copyright (c) 2022, Linaro Ltd */ #include +#include #include #include #include @@ -100,15 +101,13 @@ void pmic_glink_client_register(struct pmic_glink_client *client) struct pmic_glink *pg = client->pg; unsigned long flags; - mutex_lock(&pg->state_lock); + guard(mutex)(&pg->state_lock); spin_lock_irqsave(&pg->client_lock, flags); list_add(&client->node, &pg->clients); client->pdr_notify(client->priv, pg->client_state); spin_unlock_irqrestore(&pg->client_lock, flags); - mutex_unlock(&pg->state_lock); - } EXPORT_SYMBOL_GPL(pmic_glink_client_register); @@ -119,26 +118,25 @@ int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len) unsigned long start; int ret; - mutex_lock(&pg->state_lock); + guard(mutex)(&pg->state_lock); if (!pg->ept) { - ret = -ECONNRESET; - } else { - start = jiffies; - for (;;) { - ret = rpmsg_send(pg->ept, data, len); - if (ret != -EAGAIN) - break; - - if (timeout_reached) { - ret = -ETIMEDOUT; - break; - } - - usleep_range(1000, 5000); - timeout_reached = time_after(jiffies, start + PMIC_GLINK_SEND_TIMEOUT); + return -ECONNRESET; + } + + start = jiffies; + for (;;) { + ret = rpmsg_send(pg->ept, data, len); + if (ret != -EAGAIN) + break; + + if (timeout_reached) { + ret = -ETIMEDOUT; + break; } + + usleep_range(1000, 5000); + timeout_reached = time_after(jiffies, start + PMIC_GLINK_SEND_TIMEOUT); } - mutex_unlock(&pg->state_lock); return ret; } @@ -227,51 +225,42 @@ static void pmic_glink_pdr_callback(int state, char *svc_path, void *priv) { struct pmic_glink *pg = priv; - mutex_lock(&pg->state_lock); + guard(mutex)(&pg->state_lock); pg->pdr_state = state; pmic_glink_state_notify_clients(pg); - mutex_unlock(&pg->state_lock); } static int pmic_glink_rpmsg_probe(struct rpmsg_device *rpdev) { struct pmic_glink *pg = __pmic_glink; - int ret = 0; - mutex_lock(&__pmic_glink_lock); - if (!pg) { - ret = dev_err_probe(&rpdev->dev, -ENODEV, "no pmic_glink device to attach to\n"); - goto out_unlock; - } + guard(mutex)(&__pmic_glink_lock); + pg = __pmic_glink; + if (!pg) + return dev_err_probe(&rpdev->dev, -ENODEV, "no pmic_glink device to attach to\n"); dev_set_drvdata(&rpdev->dev, pg); - mutex_lock(&pg->state_lock); + guard(mutex)(&pg->state_lock); pg->ept = rpdev->ept; pmic_glink_state_notify_clients(pg); - mutex_unlock(&pg->state_lock); -out_unlock: - mutex_unlock(&__pmic_glink_lock); - return ret; + return 0; } static void pmic_glink_rpmsg_remove(struct rpmsg_device *rpdev) { struct pmic_glink *pg; - mutex_lock(&__pmic_glink_lock); + guard(mutex)(&__pmic_glink_lock); pg = __pmic_glink; if (!pg) - goto out_unlock; + return; - mutex_lock(&pg->state_lock); + guard(mutex)(&pg->state_lock); pg->ept = NULL; pmic_glink_state_notify_clients(pg); - mutex_unlock(&pg->state_lock); -out_unlock: - mutex_unlock(&__pmic_glink_lock); } static const struct rpmsg_device_id pmic_glink_rpmsg_id_match[] = { @@ -378,9 +367,8 @@ static void pmic_glink_remove(struct platform_device *pdev) if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) pmic_glink_del_aux_device(pg, &pg->ucsi_aux); - mutex_lock(&__pmic_glink_lock); + guard(mutex)(&__pmic_glink_lock); __pmic_glink = NULL; - mutex_unlock(&__pmic_glink_lock); } static const unsigned long pmic_glink_sc8280xp_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | From 12e0bd600e3c2f33f9db0e3b91f6b8d8d95b7dbe Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 3 Dec 2024 10:49:32 +0000 Subject: [PATCH 15/58] soc: renesas: Add RZ/G3E (R9A09G047) config option Add a configuration option for the RZ/G3E SoC. Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/20241203105005.103927-6-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 9f7fe02310b9a..6d2e135eed89b 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -345,6 +345,11 @@ config ARCH_R9A09G011 help This enables support for the Renesas RZ/V2M SoC. +config ARCH_R9A09G047 + bool "ARM64 Platform support for RZ/G3E" + help + This enables support for the Renesas RZ/G3E SoC variants. + config ARCH_R9A09G057 bool "ARM64 Platform support for RZ/V2H(P)" select RENESAS_RZV2H_ICU From 5119e6b44f8ada5f5cea19935a7f005fee062aef Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Wed, 11 Dec 2024 21:42:27 +0000 Subject: [PATCH 16/58] memory: omap-gpmc: deadcode a pair of functions gpmc_get_client_irq() last use was removed by commit ac28e47ccc3f ("ARM: OMAP2+: Remove legacy gpmc-nand.c") gpmc_ticks_to_ns() last use was removed by commit 2514830b8b8c ("ARM: OMAP2+: Remove gpmc-onenand") Remove them. gpmc_clk_ticks_to_ns() is now only used in some DEBUG code; move inside the ifdef to avoid unused warnings. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Roger Quadros Acked-by: Kevin Hilman Link: https://lore.kernel.org/r/20241211214227.107980-1-linux@treblig.org Signed-off-by: Krzysztof Kozlowski --- drivers/memory/omap-gpmc.c | 33 +++++++-------------------------- include/linux/omap-gpmc.h | 4 ---- 2 files changed, 7 insertions(+), 30 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index c8a0d82f9c27d..1bab3f88c1f02 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -358,17 +358,6 @@ static unsigned int gpmc_ps_to_ticks(unsigned int time_ps) return (time_ps + tick_ps - 1) / tick_ps; } -static unsigned int gpmc_clk_ticks_to_ns(unsigned int ticks, int cs, - enum gpmc_clk_domain cd) -{ - return ticks * gpmc_get_clk_period(cs, cd) / 1000; -} - -unsigned int gpmc_ticks_to_ns(unsigned int ticks) -{ - return gpmc_clk_ticks_to_ns(ticks, /* any CS */ 0, GPMC_CD_FCLK); -} - static unsigned int gpmc_ticks_to_ps(unsigned int ticks) { return ticks * gpmc_get_fclk_period(); @@ -415,6 +404,13 @@ static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) } #ifdef CONFIG_OMAP_GPMC_DEBUG + +static unsigned int gpmc_clk_ticks_to_ns(unsigned int ticks, int cs, + enum gpmc_clk_domain cd) +{ + return ticks * gpmc_get_clk_period(cs, cd) / 1000; +} + /** * get_gpmc_timing_reg - read a timing parameter and print DTS settings for it. * @cs: Chip Select Region @@ -1295,21 +1291,6 @@ int gpmc_omap_onenand_set_timings(struct device *dev, int cs, int freq, } EXPORT_SYMBOL_GPL(gpmc_omap_onenand_set_timings); -int gpmc_get_client_irq(unsigned int irq_config) -{ - if (!gpmc_irq_domain) { - pr_warn("%s called before GPMC IRQ domain available\n", - __func__); - return 0; - } - - /* we restrict this to NAND IRQs only */ - if (irq_config >= GPMC_NR_NAND_IRQS) - return 0; - - return irq_create_mapping(gpmc_irq_domain, irq_config); -} - static int gpmc_irq_endis(unsigned long hwirq, bool endis) { u32 regval; diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h index c9e3843d2dd56..263b915df1fb1 100644 --- a/include/linux/omap-gpmc.h +++ b/include/linux/omap-gpmc.h @@ -66,10 +66,6 @@ extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t, struct device_node; -extern int gpmc_get_client_irq(unsigned irq_config); - -extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); - extern void gpmc_cs_write_reg(int cs, int idx, u32 val); extern int gpmc_calc_divider(unsigned int sync_clk); extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t, From 1ff7d092dce0b2273dce4b8d33fa5856679dd25b Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Fri, 29 Nov 2024 12:46:48 +0100 Subject: [PATCH 17/58] optee: fix format string for printing optee build_id There has been a recent change in OP-TEE to print 8 and 16 character commit id for 32bit and 64bit architecture respectively. In case if commit id is starting with 0 like 04d1c612ec7beaede073b8c it is printing revision as below removing leading 0 "optee: revision 4.4 (4d1c612ec7beaed)" Signed-off-by: Sahil Malhotra Reviewed-by: Jerome Forissier Reviewed-by: Sumit Garg Link: https://lore.kernel.org/r/20241129114648.3048941-1-sahil.malhotra@nxp.com Signed-off-by: Jens Wiklander --- drivers/tee/optee/smc_abi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index 3e33cf2af73bb..f0c3ac1103bb5 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -1272,8 +1272,9 @@ static void optee_msg_get_os_revision(optee_invoke_fn *invoke_fn) &res.smccc); if (res.result.build_id) - pr_info("revision %lu.%lu (%08lx)", res.result.major, - res.result.minor, res.result.build_id); + pr_info("revision %lu.%lu (%0*lx)", res.result.major, + res.result.minor, (int)sizeof(res.result.build_id) * 2, + res.result.build_id); else pr_info("revision %lu.%lu", res.result.major, res.result.minor); } From 653bd35b8849dd47536edc8c893718e7142548c7 Mon Sep 17 00:00:00 2001 From: Lijuan Gao Date: Wed, 18 Dec 2024 18:39:38 +0800 Subject: [PATCH 18/58] dt-bindings: interconnect: qcom-bwmon: Document QCS615 bwmon compatibles Document QCS615 BWMONs, which includes one BWMONv4 instance for CPU to LLCC path bandwidth monitoring and one BWMONv5 instance for LLCC to DDR path bandwidth monitoring. Signed-off-by: Lijuan Gao Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241218-add_bwmon_support_for_qcs615-v1-1-680d798a19e5@quicinc.com Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml index 251410aabf38b..ff24b5ee2c661 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml @@ -26,6 +26,7 @@ properties: - items: - enum: - qcom,qcm2290-cpu-bwmon + - qcom,qcs615-cpu-bwmon - qcom,qcs8300-cpu-bwmon - qcom,sa8775p-cpu-bwmon - qcom,sc7180-cpu-bwmon @@ -41,6 +42,7 @@ properties: - const: qcom,sdm845-bwmon # BWMON v4, unified register space - items: - enum: + - qcom,qcs615-llcc-bwmon - qcom,qcs8300-llcc-bwmon - qcom,sa8775p-llcc-bwmon - qcom,sc7180-llcc-bwmon From b9784e5cde1f9fb83661a70e580e381ae1264d12 Mon Sep 17 00:00:00 2001 From: Joe Hattori Date: Tue, 17 Dec 2024 18:14:34 +0900 Subject: [PATCH 19/58] memory: tegra20-emc: fix an OF node reference bug in tegra_emc_find_node_by_ram_code() As of_find_node_by_name() release the reference of the argument device node, tegra_emc_find_node_by_ram_code() releases some device nodes while still in use, resulting in possible UAFs. According to the bindings and the in-tree DTS files, the "emc-tables" node is always device's child node with the property "nvidia,use-ram-code", and the "lpddr2" node is a child of the "emc-tables" node. Thus utilize the for_each_child_of_node() macro and of_get_child_by_name() instead of of_find_node_by_name() to simplify the code. This bug was found by an experimental verification tool that I am developing. Fixes: 96e5da7c8424 ("memory: tegra: Introduce Tegra20 EMC driver") Signed-off-by: Joe Hattori Link: https://lore.kernel.org/r/20241217091434.1993597-1-joe@pf.is.s.u-tokyo.ac.jp Link: https://lore.kernel.org/r/20241218024415.2494267-3-joe@pf.is.s.u-tokyo.ac.jp [krzysztof: applied v1, adjust the commit msg to incorporate v2 parts] Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra20-emc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c index 7193f848d17e6..9b7d30a21a5bd 100644 --- a/drivers/memory/tegra/tegra20-emc.c +++ b/drivers/memory/tegra/tegra20-emc.c @@ -474,14 +474,15 @@ tegra_emc_find_node_by_ram_code(struct tegra_emc *emc) ram_code = tegra_read_ram_code(); - for (np = of_find_node_by_name(dev->of_node, "emc-tables"); np; - np = of_find_node_by_name(np, "emc-tables")) { + for_each_child_of_node(dev->of_node, np) { + if (!of_node_name_eq(np, "emc-tables")) + continue; err = of_property_read_u32(np, "nvidia,ram-code", &value); if (err || value != ram_code) { struct device_node *lpddr2_np; bool cfg_mismatches = false; - lpddr2_np = of_find_node_by_name(np, "lpddr2"); + lpddr2_np = of_get_child_by_name(np, "lpddr2"); if (lpddr2_np) { const struct lpddr2_info *info; @@ -518,7 +519,6 @@ tegra_emc_find_node_by_ram_code(struct tegra_emc *emc) } if (cfg_mismatches) { - of_node_put(np); continue; } } From e7282bf8a0e9bb8a4cb1be406674ff7bb7b264f2 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 21 Dec 2024 13:36:02 +0100 Subject: [PATCH 20/58] soc: qcom: pd-mapper: Add X1P42100 X1P42100 is a cousin of X1E80100, and hence can make use of the latter's configuration. Do so. Signed-off-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20241221-topic-x1p4_soc-v1-3-55347831d73c@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 6e30f08761aa4..50aa54996901f 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -561,6 +561,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,sm8550", .data = sm8550_domains, }, { .compatible = "qcom,sm8650", .data = sm8550_domains, }, { .compatible = "qcom,x1e80100", .data = x1e80100_domains, }, + { .compatible = "qcom,x1p42100", .data = x1e80100_domains, }, {}, }; From 6994c655e1252049007973fd641e6a26f94c420b Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 21 Dec 2024 13:36:03 +0100 Subject: [PATCH 21/58] firmware: qcom: scm: Allow QSEECOM on X1P42100 CRD Add this board to the list to allow e.g. efivars access. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20241221-topic-x1p4_soc-v1-4-55347831d73c@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 72bf87ddcd969..4ef219684a2dc 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -1780,6 +1780,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "qcom,x1e001de-devkit" }, { .compatible = "qcom,x1e80100-crd" }, { .compatible = "qcom,x1e80100-qcp" }, + { .compatible = "qcom,x1p42100-crd" }, { } }; From 35d8bc131de0f0f280f0db42499512d79f05f456 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Thu, 19 Dec 2024 19:53:29 +0100 Subject: [PATCH 22/58] soc: qcom: llcc: Enable LLCC_WRCACHE at boot on X1 The Last Level Cache is split into many slices, each one of which can be toggled on or off. Only certain slices are recommended to be turned on unconditionally, in order to reach optimal performance/latency/power levels. Enable WRCACHE on X1 at boot, in accordance with internal recommendations. No significant performance difference is expected. Fixes: b3cf69a43502 ("soc: qcom: llcc: Add configuration data for X1E80100") Cc: stable@vger.kernel.org Reviewed-by: Rajendra Nayak Signed-off-by: Konrad Dybcio Reviewed-by: Johan Hovold Tested-by: Johan Hovold Link: https://lore.kernel.org/r/20241219-topic-llcc_x1e_wrcache-v3-1-b9848d9c3d63@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 32c3bc887cefb..1560db00a0124 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -3004,6 +3004,7 @@ static const struct llcc_slice_config x1e80100_data[] = { .fixed_size = true, .bonus_ways = 0xfff, .cache_mode = 0, + .activate_on_init = true, }, { .usecase_id = LLCC_CAMEXP0, .slice_id = 4, From 70096b4990848229d0784c5e51dc3c7c072f1111 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 22 Aug 2024 18:48:51 +0200 Subject: [PATCH 23/58] soc: qcom: smem_state: fix missing of_node_put in error path If of_parse_phandle_with_args() succeeds, the OF node reference should be dropped, regardless of number of phandle arguments. Cc: stable@vger.kernel.org Fixes: 9460ae2ff308 ("soc: qcom: Introduce common SMEM state machine code") Signed-off-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240822164853.231087-2-krzysztof.kozlowski@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem_state.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/smem_state.c b/drivers/soc/qcom/smem_state.c index d9bfac6c54fb8..cc5be8019b6a3 100644 --- a/drivers/soc/qcom/smem_state.c +++ b/drivers/soc/qcom/smem_state.c @@ -112,7 +112,8 @@ struct qcom_smem_state *qcom_smem_state_get(struct device *dev, if (args.args_count != 1) { dev_err(dev, "invalid #qcom,smem-state-cells\n"); - return ERR_PTR(-EINVAL); + state = ERR_PTR(-EINVAL); + goto put; } state = of_node_to_state(args.np); From 9b01fc6bb1fca6ab2b7edb04b55bf106cf489118 Mon Sep 17 00:00:00 2001 From: Maud Spierings Date: Sat, 16 Nov 2024 14:44:39 +0100 Subject: [PATCH 24/58] firmware: qcom: scm: Allow QSEECOM on the asus vivobook s15 Add the asus vivobook s15 to the compatible list to allow access to efivars Signed-off-by: Maud Spierings Link: https://lore.kernel.org/r/20241116-add_asus_qcom_scm-v1-1-5aa2b0fb52bd@hotmail.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 4ef219684a2dc..11be6840cc6ad 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -1768,6 +1768,7 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_send); + any potential issues with this, only allow validated machines for now. */ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { + { .compatible = "asus,vivobook-s15" }, { .compatible = "dell,xps13-9345" }, { .compatible = "lenovo,flex-5g" }, { .compatible = "lenovo,thinkpad-t14s" }, From 2705bce5b4c45e2a0a354ec4df937d2803241cd8 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Fri, 29 Nov 2024 16:24:46 +0200 Subject: [PATCH 25/58] soc: qcom: Rework BCM_TCS_CMD macro Reworked BCM_TCS_CMD macro in order to fix warnings from sparse: drivers/clk/qcom/clk-rpmh.c:270:28: warning: restricted __le32 degrades to integer drivers/clk/qcom/clk-rpmh.c:270:28: warning: restricted __le32 degrades to integer While at it, used u32_encode_bits which made the code easier to follow and removed unnecessary shift definitions. The use of cpu_to_le32 was wrong and thus removed. Signed-off-by: Eugen Hristev Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20241129142446.407443-1-eugen.hristev@linaro.org Signed-off-by: Bjorn Andersson --- include/soc/qcom/tcs.h | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/include/soc/qcom/tcs.h b/include/soc/qcom/tcs.h index 3acca067c72b1..cff67ce25488e 100644 --- a/include/soc/qcom/tcs.h +++ b/include/soc/qcom/tcs.h @@ -6,6 +6,9 @@ #ifndef __SOC_QCOM_TCS_H__ #define __SOC_QCOM_TCS_H__ +#include +#include + #define MAX_RPMH_PAYLOAD 16 /** @@ -60,22 +63,17 @@ struct tcs_request { struct tcs_cmd *cmds; }; -#define BCM_TCS_CMD_COMMIT_SHFT 30 -#define BCM_TCS_CMD_COMMIT_MASK 0x40000000 -#define BCM_TCS_CMD_VALID_SHFT 29 -#define BCM_TCS_CMD_VALID_MASK 0x20000000 -#define BCM_TCS_CMD_VOTE_X_SHFT 14 -#define BCM_TCS_CMD_VOTE_MASK 0x3fff -#define BCM_TCS_CMD_VOTE_Y_SHFT 0 -#define BCM_TCS_CMD_VOTE_Y_MASK 0xfffc000 +#define BCM_TCS_CMD_COMMIT_MASK BIT(30) +#define BCM_TCS_CMD_VALID_MASK BIT(29) +#define BCM_TCS_CMD_VOTE_MASK GENMASK(13, 0) +#define BCM_TCS_CMD_VOTE_Y_MASK GENMASK(13, 0) +#define BCM_TCS_CMD_VOTE_X_MASK GENMASK(27, 14) /* Construct a Bus Clock Manager (BCM) specific TCS command */ #define BCM_TCS_CMD(commit, valid, vote_x, vote_y) \ - (((commit) << BCM_TCS_CMD_COMMIT_SHFT) | \ - ((valid) << BCM_TCS_CMD_VALID_SHFT) | \ - ((cpu_to_le32(vote_x) & \ - BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_X_SHFT) | \ - ((cpu_to_le32(vote_y) & \ - BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_Y_SHFT)) + (u32_encode_bits(commit, BCM_TCS_CMD_COMMIT_MASK) | \ + u32_encode_bits(valid, BCM_TCS_CMD_VALID_MASK) | \ + u32_encode_bits(vote_x, BCM_TCS_CMD_VOTE_X_MASK) | \ + u32_encode_bits(vote_y, BCM_TCS_CMD_VOTE_Y_MASK)) #endif /* __SOC_QCOM_TCS_H__ */ From 95fee3009461f4a65247db677f445fbd67776019 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 22 Aug 2024 18:48:50 +0200 Subject: [PATCH 26/58] soc: qcom: pmic_glink_altmode: simplify locking with guard() Simplify error handling (less gotos) over locks with guard(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240822164853.231087-1-krzysztof.kozlowski@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pmic_glink_altmode.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index 463b1c5288318..bd06ce1618041 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -5,6 +5,7 @@ */ #include #include +#include #include #include #include @@ -114,7 +115,7 @@ static int pmic_glink_altmode_request(struct pmic_glink_altmode *altmode, u32 cm * The USBC_CMD_WRITE_REQ ack doesn't identify the request, so wait for * one ack at a time. */ - mutex_lock(&altmode->lock); + guard(mutex)(&altmode->lock); req.hdr.owner = cpu_to_le32(altmode->owner_id); req.hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP); @@ -125,18 +126,16 @@ static int pmic_glink_altmode_request(struct pmic_glink_altmode *altmode, u32 cm ret = pmic_glink_send(altmode->client, &req, sizeof(req)); if (ret) { dev_err(altmode->dev, "failed to send altmode request: %#x (%d)\n", cmd, ret); - goto out_unlock; + return ret; } left = wait_for_completion_timeout(&altmode->pan_ack, 5 * HZ); if (!left) { dev_err(altmode->dev, "timeout waiting for altmode request ack for: %#x\n", cmd); - ret = -ETIMEDOUT; + return -ETIMEDOUT; } -out_unlock: - mutex_unlock(&altmode->lock); - return ret; + return 0; } static void pmic_glink_altmode_enable_dp(struct pmic_glink_altmode *altmode, From a9020afe40e8752c6db905e895e9002a83255e7b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 2 Dec 2024 10:49:02 +0100 Subject: [PATCH 27/58] soc: qcom: rmtfs: allow building the module with COMPILE_TEST=y Make it possible to build the module when COMPILE_TEST is enabled for better build coverage. Reviewed-by: Dmitry Baryshkov Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20241202094903.18388-1-brgl@bgdev.pl Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 74b9121240f89..58e63cf0036ba 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -139,7 +139,7 @@ config QCOM_RAMP_CTRL config QCOM_RMTFS_MEM tristate "Qualcomm Remote Filesystem memory driver" - depends on ARCH_QCOM + depends on ARCH_QCOM || COMPILE_TEST select QCOM_SCM help The Qualcomm remote filesystem memory driver is used for allocating From eb9fc0f32f9b4e8b7984c276c1ed6f61d39ef630 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 2 Dec 2024 10:49:03 +0100 Subject: [PATCH 28/58] soc: qcom: rmtfs: constify rmtfs_class The rmtfs class object is never modified and can be made constant. Reviewed-by: Dmitry Baryshkov Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20241202094903.18388-2-brgl@bgdev.pl Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rmtfs_mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c index 33603b8fd8f38..1b32469f27896 100644 --- a/drivers/soc/qcom/rmtfs_mem.c +++ b/drivers/soc/qcom/rmtfs_mem.c @@ -125,7 +125,7 @@ static int qcom_rmtfs_mem_release(struct inode *inode, struct file *filp) return 0; } -static struct class rmtfs_class = { +static const struct class rmtfs_class = { .name = "rmtfs", }; From 7d467c1b62d0b432df837da24dc023104a184b83 Mon Sep 17 00:00:00 2001 From: Jens Glathe Date: Mon, 2 Dec 2024 20:41:30 +0100 Subject: [PATCH 29/58] firmware: qcom: scm: Allow QSEECOM for HP Omnibook X14 add "hp,omnibook-x14" as compatible device for QSEECOM This is required to get access to efivars and uefi boot loader support. Signed-off-by: Jens Glathe Link: https://lore.kernel.org/r/20241202-hp-omnibook-x14-v3-2-0fcd96483723@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 11be6840cc6ad..83a13ca33c8b7 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -1770,6 +1770,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 = "dell,xps13-9345" }, + { .compatible = "hp,omnibook-x14" }, { .compatible = "lenovo,flex-5g" }, { .compatible = "lenovo,thinkpad-t14s" }, { .compatible = "lenovo,thinkpad-x13s", }, From 96ac79829ccd7e86ef87eb2d27736608665f5dfd Mon Sep 17 00:00:00 2001 From: Jens Glathe Date: Mon, 2 Dec 2024 20:59:46 +0100 Subject: [PATCH 30/58] firmware: qcom: scm: Allow QSEECOM for Windows Dev Kit 2023 add "microsoft,blackrock" as compatible device for QSEECOM This is required to get access to efivars and uefi boot loader support. Signed-off-by: Jens Glathe Link: https://lore.kernel.org/r/20241202-jg-blackrock-for-upstream-v9-2-385bb46ca122@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 83a13ca33c8b7..03124da4bac9a 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -1776,6 +1776,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "lenovo,thinkpad-x13s", }, { .compatible = "lenovo,yoga-slim7x" }, { .compatible = "microsoft,arcata", }, + { .compatible = "microsoft,blackrock" }, { .compatible = "microsoft,romulus13", }, { .compatible = "microsoft,romulus15", }, { .compatible = "qcom,sc8180x-primus" }, From f900709e38f40440daf0d878b70adfa358ccf115 Mon Sep 17 00:00:00 2001 From: Pengyu Luo Date: Sat, 21 Dec 2024 00:05:29 +0800 Subject: [PATCH 31/58] firmware: qcom: scm: Allow QSEECOM on Huawei Matebook E Go (sc8280xp) Add the SC8280XP-based Huawei Matebook E Go (sc8280xp) to the allowlist. Signed-off-by: Pengyu Luo Link: https://lore.kernel.org/r/20241220160530.444864-3-mitltlatltl@gmail.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 03124da4bac9a..e736b4b46ea49 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -1771,6 +1771,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "asus,vivobook-s15" }, { .compatible = "dell,xps13-9345" }, { .compatible = "hp,omnibook-x14" }, + { .compatible = "huawei,gaokun3" }, { .compatible = "lenovo,flex-5g" }, { .compatible = "lenovo,thinkpad-t14s" }, { .compatible = "lenovo,thinkpad-x13s", }, From 31bd1f4517b651e132fae7cbb5f63b190015da94 Mon Sep 17 00:00:00 2001 From: MD Danish Anwar Date: Fri, 20 Dec 2024 15:35:08 +0530 Subject: [PATCH 32/58] MAINTAINERS: Add entry for linux/pruss_driver.h include/linux/pruss_driver.h is an orphan file. Add entry for this in the MAINTAINERS file. Signed-off-by: MD Danish Anwar Link: https://lore.kernel.org/r/20241220100508.1554309-3-danishanwar@ti.com Signed-off-by: Nishanth Menon --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1e930c7a58b13..2d808a99f7b43 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23539,6 +23539,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git F: Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml F: drivers/pmdomain/ti/omap_prm.c F: drivers/soc/ti/* +F: include/linux/pruss_driver.h TI LM49xxx FAMILY ASoC CODEC DRIVERS M: M R Swami Reddy From 7ece8b3ca3a6424b220e2a83bd4d625bf5bcb8c8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 3 Jan 2025 09:25:49 +0100 Subject: [PATCH 33/58] dt-bindings: samsung: exynos-usi: Restrict possible samsung,mode values "samsung,mode" property defines the desired mode of the serial engine (e.g. I2C or SPI) and only few values are allowed/used by Linux driver. Cc: Ivaylo Ivanov Reviewed-by: Tudor Ambarus Reviewed-by: Sam Protsenko Acked-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250103082549.19419-1-krzysztof.kozlowski@linaro.org Signed-off-by: Krzysztof Kozlowski --- Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml b/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml index f80fcbc3128bf..5b046932fbc3f 100644 --- a/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml +++ b/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml @@ -64,6 +64,7 @@ properties: samsung,mode: $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] description: Selects USI function (which serial protocol to use). Refer to for valid USI mode values. From 38405d3825d883b9e6ae680c14b530f79709533e Mon Sep 17 00:00:00 2001 From: Ivaylo Ivanov Date: Sat, 4 Jan 2025 18:29:13 +0200 Subject: [PATCH 34/58] dt-bindings: soc: samsung: exynos-sysreg: add sysreg compatibles for exynos8895 Exynos8895 has four different SYSREG controllers, add dedicated compatibles for them to the documentation. They also require clocks. Signed-off-by: Ivaylo Ivanov Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250104162915.332005-2-ivo.ivanov.ivanov1@gmail.com Signed-off-by: Krzysztof Kozlowski --- .../bindings/soc/samsung/samsung,exynos-sysreg.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/samsung/samsung,exynos-sysreg.yaml b/Documentation/devicetree/bindings/soc/samsung/samsung,exynos-sysreg.yaml index 3ca220582897f..a75aef2406293 100644 --- a/Documentation/devicetree/bindings/soc/samsung/samsung,exynos-sysreg.yaml +++ b/Documentation/devicetree/bindings/soc/samsung/samsung,exynos-sysreg.yaml @@ -21,6 +21,10 @@ properties: - samsung,exynos3-sysreg - samsung,exynos4-sysreg - samsung,exynos5-sysreg + - samsung,exynos8895-fsys0-sysreg + - samsung,exynos8895-fsys1-sysreg + - samsung,exynos8895-peric0-sysreg + - samsung,exynos8895-peric1-sysreg - samsung,exynosautov920-peric0-sysreg - samsung,exynosautov920-peric1-sysreg - tesla,fsd-cam-sysreg @@ -79,6 +83,10 @@ allOf: - samsung,exynos850-cmgp-sysreg - samsung,exynos850-peri-sysreg - samsung,exynos850-sysreg + - samsung,exynos8895-fsys0-sysreg + - samsung,exynos8895-fsys1-sysreg + - samsung,exynos8895-peric0-sysreg + - samsung,exynos8895-peric1-sysreg then: required: - clocks From eca836dfd8386b32f1aae60f8e323218ac6a0b75 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 4 Jan 2025 14:56:05 +0100 Subject: [PATCH 35/58] soc: samsung: exynos-pmu: Fix uninitialized ret in tensor_set_bits_atomic() If tensor_set_bits_atomic() is called with a mask of 0 the function will just iterate over its bit, not perform any updates and return stack value of 'ret'. Also reported by smatch: drivers/soc/samsung/exynos-pmu.c:129 tensor_set_bits_atomic() error: uninitialized symbol 'ret'. Fixes: 0b7c6075022c ("soc: samsung: exynos-pmu: Add regmap support for SoCs that protect PMU regs") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250104135605.109209-1-krzysztof.kozlowski@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/soc/samsung/exynos-pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c index d8c53cec7f37a..dd5256e5aae1a 100644 --- a/drivers/soc/samsung/exynos-pmu.c +++ b/drivers/soc/samsung/exynos-pmu.c @@ -126,7 +126,7 @@ static int tensor_set_bits_atomic(void *ctx, unsigned int offset, u32 val, if (ret) return ret; } - return ret; + return 0; } static bool tensor_is_atomic(unsigned int reg) From 22cf4fae6660b6e1a583a41cbf84e3046ca9ccd0 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 30 Dec 2024 20:59:35 +0100 Subject: [PATCH 36/58] soc: qcom: socinfo: Avoid out of bounds read of serial number On MSM8916 devices, the serial number exposed in sysfs is constant and does not change across individual devices. It's always: db410c:/sys/devices/soc0$ cat serial_number 2644893864 The firmware used on MSM8916 exposes SOCINFO_VERSION(0, 8), which does not have support for the serial_num field in the socinfo struct. There is an existing check to avoid exposing the serial number in that case, but it's not correct: When checking the item_size returned by SMEM, we need to make sure the *end* of the serial_num is within bounds, instead of comparing with the *start* offset. The serial_number currently exposed on MSM8916 devices is just an out of bounds read of whatever comes after the socinfo struct in SMEM. Fix this by changing offsetof() to offsetofend(), so that the size of the field is also taken into account. Cc: stable@vger.kernel.org Fixes: efb448d0a3fc ("soc: qcom: Add socinfo driver") Signed-off-by: Stephan Gerhold Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20241230-qcom-socinfo-serialno-oob-v1-1-9b7a890da3da@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 62fadfe44a09f..d49c55979bb30 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -796,7 +796,7 @@ static int qcom_socinfo_probe(struct platform_device *pdev) if (!qs->attr.soc_id || !qs->attr.revision) return -ENOMEM; - if (offsetof(struct socinfo, serial_num) <= item_size) { + if (offsetofend(struct socinfo, serial_num) <= item_size) { qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u", le32_to_cpu(info->serial_num)); From cee3947b1aed42f71f99ce4e5d1410ee8670621a Mon Sep 17 00:00:00 2001 From: Wasim Nazir Date: Sun, 29 Dec 2024 20:53:27 +0530 Subject: [PATCH 37/58] dt-bindings: arm: qcom,ids: add SoC ID for QCS9075 Add the unique ID for Qualcomm QCS9075 SoC. This value is used to differentiate the SoC across qcom targets. Acked-by: Rob Herring (Arm) Signed-off-by: Wasim Nazir Link: https://lore.kernel.org/r/20241229152332.3068172-2-quic_wasimn@quicinc.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 e850dc3a1ad32..1b3e0176dcb7c 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -284,6 +284,7 @@ #define QCOM_ID_QCS9100 667 #define QCOM_ID_QCS8300 674 #define QCOM_ID_QCS8275 675 +#define QCOM_ID_QCS9075 676 #define QCOM_ID_QCS615 680 /* From 7b115b623545650407e3f262ee9cdd8a778a9fdf Mon Sep 17 00:00:00 2001 From: Wasim Nazir Date: Sun, 29 Dec 2024 20:53:28 +0530 Subject: [PATCH 38/58] soc: qcom: socinfo: add QCS9075 SoC ID Update soc_id table for the Qualcomm QCS9075 SoC to represent qcs9075 machine. Reviewed-by: Dmitry Baryshkov Signed-off-by: Wasim Nazir Link: https://lore.kernel.org/r/20241229152332.3068172-3-quic_wasimn@quicinc.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 d49c55979bb30..18d7f1be90937 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -451,6 +451,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QCS9100) }, { qcom_board_id(QCS8300) }, { qcom_board_id(QCS8275) }, + { qcom_board_id(QCS9075) }, { qcom_board_id(QCS615) }, }; From 0a744cceebd0480cb39587b3b1339d66a9d14063 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 9 Dec 2024 15:27:54 +0100 Subject: [PATCH 39/58] firmware: qcom: scm: Fix missing read barrier in qcom_scm_is_available() Commit 2e4955167ec5 ("firmware: qcom: scm: Fix __scm and waitq completion variable initialization") introduced a write barrier in probe function to store global '__scm' variable. It also claimed that it added a read barrier, because as we all known barriers are paired (see memory-barriers.txt: "Note that write barriers should normally be paired with read or address-dependency barriers"), however it did not really add it. The offending commit used READ_ONCE() to access '__scm' global which is not a barrier. The barrier is needed so the store to '__scm' will be properly visible. This is most likely not fatal in current driver design, because missing read barrier would mean qcom_scm_is_available() callers will access old value, NULL. Driver does not support unbinding and does not correctly handle probe failures, thus there is no risk of stale or old pointer in '__scm' variable. However for code correctness, readability and to be sure that we did not mess up something in this tricky topic of SMP barriers, add a read barrier for accessing '__scm'. Change also comment from useless/obvious what does barrier do, to what is expected: which other parts of the code are involved here. Fixes: 2e4955167ec5 ("firmware: qcom: scm: Fix __scm and waitq completion variable initialization") Cc: stable@vger.kernel.org Reviewed-by: Bartosz Golaszewski Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241209-qcom-scm-missing-barriers-and-all-sort-of-srap-v2-1-9061013c8d92@linaro.org Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index e736b4b46ea49..cde60566c7934 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -1872,7 +1872,8 @@ static int qcom_scm_qseecom_init(struct qcom_scm *scm) */ bool qcom_scm_is_available(void) { - return !!READ_ONCE(__scm); + /* Paired with smp_store_release() in qcom_scm_probe */ + return !!smp_load_acquire(&__scm); } EXPORT_SYMBOL_GPL(qcom_scm_is_available); @@ -2029,7 +2030,7 @@ static int qcom_scm_probe(struct platform_device *pdev) if (ret) return ret; - /* Let all above stores be available after this */ + /* Paired with smp_load_acquire() in qcom_scm_is_available(). */ smp_store_release(&__scm, scm); irq = platform_get_irq_optional(pdev, 0); From b628510397b5cafa1f5d3e848a28affd1c635302 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 9 Dec 2024 15:27:55 +0100 Subject: [PATCH 40/58] firmware: qcom: scm: Fix missing read barrier in qcom_scm_get_tzmem_pool() Commit 2e4955167ec5 ("firmware: qcom: scm: Fix __scm and waitq completion variable initialization") introduced a write barrier in probe function to store global '__scm' variable. We all known barriers are paired (see memory-barriers.txt: "Note that write barriers should normally be paired with read or address-dependency barriers"), therefore accessing it from concurrent contexts requires read barrier. Previous commit added such barrier in qcom_scm_is_available(), so let's use that directly. Lack of this read barrier can result in fetching stale '__scm' variable value, NULL, and dereferencing it. Note that barrier in qcom_scm_is_available() satisfies here the control dependency. Fixes: ca61d6836e6f ("firmware: qcom: scm: fix a NULL-pointer dereference") Fixes: 449d0d84bcd8 ("firmware: qcom: scm: smc: switch to using the SCM allocator") Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241209-qcom-scm-missing-barriers-and-all-sort-of-srap-v2-2-9061013c8d92@linaro.org Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index cde60566c7934..4a1c05a7bf20a 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -217,7 +217,10 @@ static DEFINE_SPINLOCK(scm_query_lock); struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void) { - return __scm ? __scm->mempool : NULL; + if (!qcom_scm_is_available()) + return NULL; + + return __scm->mempool; } static enum qcom_scm_convention __get_convention(void) From 1e76b546e6fca7eb568161f408133904ca6bcf4f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 9 Dec 2024 15:27:57 +0100 Subject: [PATCH 41/58] firmware: qcom: scm: Cleanup global '__scm' on probe failures If SCM driver fails the probe, it should not leave global '__scm' variable assigned, because external users of this driver will assume the probe finished successfully. For example TZMEM parts ('__scm->mempool') are initialized later in the probe, but users of it (__scm_smc_call()) rely on the '__scm' variable. This fixes theoretical NULL pointer exception, triggered via introducing probe deferral in SCM driver with call trace: qcom_tzmem_alloc+0x70/0x1ac (P) qcom_tzmem_alloc+0x64/0x1ac (L) qcom_scm_assign_mem+0x78/0x194 qcom_rmtfs_mem_probe+0x2d4/0x38c platform_probe+0x68/0xc8 Fixes: 40289e35ca52 ("firmware: qcom: scm: enable the TZ mem allocator") Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241209-qcom-scm-missing-barriers-and-all-sort-of-srap-v2-4-9061013c8d92@linaro.org Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 42 ++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 4a1c05a7bf20a..2380775508ac6 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2038,13 +2038,17 @@ static int qcom_scm_probe(struct platform_device *pdev) irq = platform_get_irq_optional(pdev, 0); if (irq < 0) { - if (irq != -ENXIO) - return irq; + if (irq != -ENXIO) { + ret = irq; + goto err; + } } else { ret = devm_request_threaded_irq(__scm->dev, irq, NULL, qcom_scm_irq_handler, IRQF_ONESHOT, "qcom-scm", __scm); - if (ret < 0) - return dev_err_probe(scm->dev, ret, "Failed to request qcom-scm irq\n"); + if (ret < 0) { + dev_err_probe(scm->dev, ret, "Failed to request qcom-scm irq\n"); + goto err; + } } __get_convention(); @@ -2063,14 +2067,18 @@ static int qcom_scm_probe(struct platform_device *pdev) qcom_scm_disable_sdi(); ret = of_reserved_mem_device_init(__scm->dev); - if (ret && ret != -ENODEV) - return dev_err_probe(__scm->dev, ret, - "Failed to setup the reserved memory region for TZ mem\n"); + if (ret && ret != -ENODEV) { + dev_err_probe(__scm->dev, ret, + "Failed to setup the reserved memory region for TZ mem\n"); + goto err; + } ret = qcom_tzmem_enable(__scm->dev); - if (ret) - return dev_err_probe(__scm->dev, ret, - "Failed to enable the TrustZone memory allocator\n"); + if (ret) { + dev_err_probe(__scm->dev, ret, + "Failed to enable the TrustZone memory allocator\n"); + goto err; + } memset(&pool_config, 0, sizeof(pool_config)); pool_config.initial_size = 0; @@ -2078,9 +2086,11 @@ static int qcom_scm_probe(struct platform_device *pdev) pool_config.max_size = SZ_256K; __scm->mempool = devm_qcom_tzmem_pool_new(__scm->dev, &pool_config); - if (IS_ERR(__scm->mempool)) - return dev_err_probe(__scm->dev, PTR_ERR(__scm->mempool), - "Failed to create the SCM memory pool\n"); + if (IS_ERR(__scm->mempool)) { + dev_err_probe(__scm->dev, PTR_ERR(__scm->mempool), + "Failed to create the SCM memory pool\n"); + goto err; + } /* * Initialize the QSEECOM interface. @@ -2096,6 +2106,12 @@ static int qcom_scm_probe(struct platform_device *pdev) WARN(ret < 0, "failed to initialize qseecom: %d\n", ret); return 0; + +err: + /* Paired with smp_load_acquire() in qcom_scm_is_available(). */ + smp_store_release(&__scm, NULL); + + return ret; } static void qcom_scm_shutdown(struct platform_device *pdev) From 94f48ecf0a538019ca2025e0b0da391f8e7cc58c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 9 Dec 2024 15:27:58 +0100 Subject: [PATCH 42/58] firmware: qcom: scm: smc: Handle missing SCM device Commit ca61d6836e6f ("firmware: qcom: scm: fix a NULL-pointer dereference") makes it explicit that qcom_scm_get_tzmem_pool() can return NULL, therefore its users should handle this. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20241209-qcom-scm-missing-barriers-and-all-sort-of-srap-v2-5-9061013c8d92@linaro.org Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm-smc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/firmware/qcom/qcom_scm-smc.c b/drivers/firmware/qcom/qcom_scm-smc.c index 2b4c2826f5725..3f10b23ec941b 100644 --- a/drivers/firmware/qcom/qcom_scm-smc.c +++ b/drivers/firmware/qcom/qcom_scm-smc.c @@ -173,6 +173,9 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc, smc.args[i + SCM_SMC_FIRST_REG_IDX] = desc->args[i]; if (unlikely(arglen > SCM_SMC_N_REG_ARGS)) { + if (!mempool) + return -EINVAL; + args_virt = qcom_tzmem_alloc(mempool, SCM_SMC_N_EXT_ARGS * sizeof(u64), flag); From a4332f6c791e1d70bf025ac51afa968607b9812b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 9 Dec 2024 15:27:59 +0100 Subject: [PATCH 43/58] firmware: qcom: scm: smc: Narrow 'mempool' variable scope Only part of the __scm_smc_call() function uses 'mempool' variable, so narrow the scope to make it more readable. Reviewed-by: Bartosz Golaszewski Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241209-qcom-scm-missing-barriers-and-all-sort-of-srap-v2-6-9061013c8d92@linaro.org Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm-smc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/qcom_scm-smc.c b/drivers/firmware/qcom/qcom_scm-smc.c index 3f10b23ec941b..574930729ddd7 100644 --- a/drivers/firmware/qcom/qcom_scm-smc.c +++ b/drivers/firmware/qcom/qcom_scm-smc.c @@ -152,7 +152,6 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc, enum qcom_scm_convention qcom_convention, struct qcom_scm_res *res, bool atomic) { - struct qcom_tzmem_pool *mempool = qcom_scm_get_tzmem_pool(); int arglen = desc->arginfo & 0xf; int i, ret; void *args_virt __free(qcom_tzmem) = NULL; @@ -173,6 +172,8 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc, smc.args[i + SCM_SMC_FIRST_REG_IDX] = desc->args[i]; if (unlikely(arglen > SCM_SMC_N_REG_ARGS)) { + struct qcom_tzmem_pool *mempool = qcom_scm_get_tzmem_pool(); + if (!mempool) return -EINVAL; From c0eb059a4575ed57f265d9883a5203799c19982c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 4 Jan 2025 15:20:11 +0100 Subject: [PATCH 44/58] soc: mediatek: mtk-devapc: Fix leaking IO map on error paths Error paths of mtk_devapc_probe() should unmap the memory. Reported by Smatch: drivers/soc/mediatek/mtk-devapc.c:292 mtk_devapc_probe() warn: 'ctx->infra_base' from of_iomap() not released on lines: 277,281,286. Fixes: 0890beb22618 ("soc: mediatek: add mt6779 devapc driver") Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250104142012.115974-1-krzysztof.kozlowski@linaro.org Signed-off-by: AngeloGioacchino Del Regno --- drivers/soc/mediatek/mtk-devapc.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c index 2a1adcb87d4e4..500847b41b160 100644 --- a/drivers/soc/mediatek/mtk-devapc.c +++ b/drivers/soc/mediatek/mtk-devapc.c @@ -273,23 +273,31 @@ static int mtk_devapc_probe(struct platform_device *pdev) return -EINVAL; devapc_irq = irq_of_parse_and_map(node, 0); - if (!devapc_irq) - return -EINVAL; + if (!devapc_irq) { + ret = -EINVAL; + goto err; + } ctx->infra_clk = devm_clk_get_enabled(&pdev->dev, "devapc-infra-clock"); - if (IS_ERR(ctx->infra_clk)) - return -EINVAL; + if (IS_ERR(ctx->infra_clk)) { + ret = -EINVAL; + goto err; + } ret = devm_request_irq(&pdev->dev, devapc_irq, devapc_violation_irq, IRQF_TRIGGER_NONE, "devapc", ctx); if (ret) - return ret; + goto err; platform_set_drvdata(pdev, ctx); start_devapc(ctx); return 0; + +err: + iounmap(ctx->infra_base); + return ret; } static void mtk_devapc_remove(struct platform_device *pdev) From c9c0036c1990da8d2dd33563e327e05a775fcf10 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 4 Jan 2025 15:20:12 +0100 Subject: [PATCH 45/58] soc: mediatek: mtk-devapc: Fix leaking IO map on driver remove Driver removal should fully clean up - unmap the memory. Fixes: 0890beb22618 ("soc: mediatek: add mt6779 devapc driver") Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250104142012.115974-2-krzysztof.kozlowski@linaro.org Signed-off-by: AngeloGioacchino Del Regno --- drivers/soc/mediatek/mtk-devapc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c index 500847b41b160..f54c966138b5b 100644 --- a/drivers/soc/mediatek/mtk-devapc.c +++ b/drivers/soc/mediatek/mtk-devapc.c @@ -305,6 +305,7 @@ static void mtk_devapc_remove(struct platform_device *pdev) struct mtk_devapc_context *ctx = platform_get_drvdata(pdev); stop_devapc(ctx); + iounmap(ctx->infra_base); } static struct platform_driver mtk_devapc_driver = { From f35a4397bec51509aa08c109041428958621d5f5 Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Thu, 21 Nov 2024 10:49:33 +0530 Subject: [PATCH 46/58] dt-bindings: cache: qcom,llcc: Add IPQ5424 compatible Document the Last Level Cache Controller on IPQ5424. The 'broadcast' register space is present only in chipsets that have multiple instances of LLCC IP. Since IPQ5424 has only one instance, both the LLCC and LLCC_BROADCAST points to the same register space. Hence, allow only '1' reg & reg-names entry for IPQ5424. Reviewed-by: Rob Herring (Arm) Signed-off-by: Varadarajan Narayanan Link: https://lore.kernel.org/r/20241121051935.1055222-2-quic_varada@quicinc.com Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/cache/qcom,llcc.yaml | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml index 03b1941eaa33d..e5effbb4a606b 100644 --- a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml +++ b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml @@ -20,6 +20,7 @@ description: | properties: compatible: enum: + - qcom,ipq5424-llcc - qcom,qcs615-llcc - qcom,qcs8300-llcc - qcom,qdu1000-llcc @@ -42,11 +43,11 @@ properties: - qcom,x1e80100-llcc reg: - minItems: 2 + minItems: 1 maxItems: 10 reg-names: - minItems: 2 + minItems: 1 maxItems: 10 interrupts: @@ -66,6 +67,21 @@ required: - reg-names allOf: + - if: + properties: + compatible: + contains: + enum: + - qcom,ipq5424-llcc + then: + properties: + reg: + items: + - description: LLCC0 base register region + reg-names: + items: + - const: llcc0_base + - if: properties: compatible: From c88c323b610a6048b87c5d9fff69659678f69924 Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Thu, 21 Nov 2024 10:49:34 +0530 Subject: [PATCH 47/58] soc: qcom: llcc: Update configuration data for IPQ5424 The 'broadcast' register space is present only in chipsets that have multiple instances of LLCC IP. Since IPQ5424 has only one instance, both the LLCC and LLCC_BROADCAST points to the same register space. Signed-off-by: Varadarajan Narayanan Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20241121051935.1055222-3-quic_varada@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 57 ++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 1560db00a0124..56823b6a2facc 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -142,6 +142,7 @@ struct qcom_llcc_config { bool skip_llcc_cfg; bool no_edac; bool irq_configured; + bool no_broadcast_register; }; struct qcom_sct_config { @@ -154,6 +155,38 @@ enum llcc_reg_offset { LLCC_COMMON_STATUS0, }; +static const struct llcc_slice_config ipq5424_data[] = { + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 768, + .priority = 1, + .bonus_ways = 0xFFFF, + .retain_on_pc = true, + .activate_on_init = true, + .write_scid_cacheable_en = true, + .stale_en = true, + .stale_cap_en = true, + .alloc_oneway_en = true, + .ovcap_en = true, + .ovcap_prio = true, + .vict_prio = true, + }, + { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 256, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xF000, + .retain_on_pc = true, + .activate_on_init = true, + .write_scid_cacheable_en = true, + .stale_en = true, + .stale_cap_en = true, + }, +}; + static const struct llcc_slice_config sa8775p_data[] = { { .usecase_id = LLCC_CPUSS, @@ -3186,6 +3219,16 @@ static const struct qcom_llcc_config qdu1000_cfg[] = { }, }; +static const struct qcom_llcc_config ipq5424_cfg[] = { + { + .sct_data = ipq5424_data, + .size = ARRAY_SIZE(ipq5424_data), + .reg_offset = llcc_v2_1_reg_offset, + .edac_reg_offset = &llcc_v2_1_edac_reg_offset, + .no_broadcast_register = true, + }, +}; + static const struct qcom_llcc_config sa8775p_cfg[] = { { .sct_data = sa8775p_data, @@ -3361,6 +3404,11 @@ static const struct qcom_sct_config qdu1000_cfgs = { .num_config = ARRAY_SIZE(qdu1000_cfg), }; +static const struct qcom_sct_config ipq5424_cfgs = { + .llcc_config = ipq5424_cfg, + .num_config = ARRAY_SIZE(ipq5424_cfg), +}; + static const struct qcom_sct_config sa8775p_cfgs = { .llcc_config = sa8775p_cfg, .num_config = ARRAY_SIZE(sa8775p_cfg), @@ -3958,8 +4006,12 @@ static int qcom_llcc_probe(struct platform_device *pdev) drv_data->bcast_regmap = qcom_llcc_init_mmio(pdev, i, "llcc_broadcast_base"); if (IS_ERR(drv_data->bcast_regmap)) { - ret = PTR_ERR(drv_data->bcast_regmap); - goto err; + if (cfg->no_broadcast_register) { + drv_data->bcast_regmap = regmap; + } else { + ret = PTR_ERR(drv_data->bcast_regmap); + goto err; + } } /* Extract version of the IP */ @@ -4030,6 +4082,7 @@ static int qcom_llcc_probe(struct platform_device *pdev) } static const struct of_device_id qcom_llcc_of_match[] = { + { .compatible = "qcom,ipq5424-llcc", .data = &ipq5424_cfgs}, { .compatible = "qcom,qcs615-llcc", .data = &qcs615_cfgs}, { .compatible = "qcom,qcs8300-llcc", .data = &qcs8300_cfgs}, { .compatible = "qcom,qdu1000-llcc", .data = &qdu1000_cfgs}, From 6cf5e9a6d260c117dc1dbcb0bf781ddb4ad5393a Mon Sep 17 00:00:00 2001 From: Manikanta Mylavarapu Date: Wed, 4 Dec 2024 19:06:26 +0530 Subject: [PATCH 48/58] dt-bindings: firmware: qcom,scm: Document ipq5424 SCM Document the scm compatible for ipq5424 SoC. Signed-off-by: Manikanta Mylavarapu Acked-by: Conor Dooley Link: https://lore.kernel.org/r/20241204133627.1341760-2-quic_mmanikan@quicinc.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 66cc68babea09..8cdaac8011ba4 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -26,6 +26,7 @@ properties: - qcom,scm-ipq4019 - qcom,scm-ipq5018 - qcom,scm-ipq5332 + - qcom,scm-ipq5424 - qcom,scm-ipq6018 - qcom,scm-ipq806x - qcom,scm-ipq8074 From 8e6854efd4738d3c9e6fdfeff8df726d454d4c7d Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Fri, 20 Dec 2024 09:39:44 +0100 Subject: [PATCH 49/58] soc: qcom: pd_mapper: Add SM7225 compatible The Qualcomm SM7225 is practically identical to SM6350, so add an entry using that data. Signed-off-by: Luca Weiss Link: https://lore.kernel.org/r/20241220-pd-mapper-sm7225-v1-1-68f85a87288d@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 50aa54996901f..154ca5beb4716 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -553,6 +553,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,sm4250", .data = sm6115_domains, }, { .compatible = "qcom,sm6115", .data = sm6115_domains, }, { .compatible = "qcom,sm6350", .data = sm6350_domains, }, + { .compatible = "qcom,sm7225", .data = sm6350_domains, }, { .compatible = "qcom,sm7325", .data = sc7280_domains, }, { .compatible = "qcom,sm8150", .data = sm8150_domains, }, { .compatible = "qcom,sm8250", .data = sm8250_domains, }, From 1d45a1cd9f3ae849db868e07e5fee5e5b37eff55 Mon Sep 17 00:00:00 2001 From: Gaurav Kashyap Date: Thu, 12 Dec 2024 20:19:51 -0800 Subject: [PATCH 50/58] firmware: qcom: scm: add calls for wrapped key support Add helper functions for the SCM calls required to support hardware-wrapped inline storage encryption keys. These SCM calls manage wrapped keys via Qualcomm's Hardware Key Manager (HWKM), which can only be accessed from TrustZone. QCOM_SCM_ES_GENERATE_ICE_KEY and QCOM_SCM_ES_IMPORT_ICE_KEY create a new long-term wrapped key, with the former making the hardware generate the key and the latter importing a raw key. QCOM_SCM_ES_PREPARE_ICE_KEY converts the key to ephemerally-wrapped form so that it can be used for inline storage encryption. These are planned to be wired up to new ioctls via the blk-crypto framework; see the proposed documentation for the hardware-wrapped keys feature for more information. Similarly there's also QCOM_SCM_ES_DERIVE_SW_SECRET which derives a "software secret" from an ephemerally-wrapped key and will be wired up to the corresponding operation in the blk_crypto_profile. These will all be used by the ICE driver in drivers/soc/qcom/ice.c. [EB: merged related patches, fixed error handling, fixed naming, fixed docs for size parameters, fixed qcom_scm_has_wrapped_key_support(), improved comments, improved commit message.] Signed-off-by: Gaurav Kashyap Signed-off-by: Bartosz Golaszewski Signed-off-by: Eric Biggers Link: https://lore.kernel.org/r/20241213041958.202565-9-ebiggers@kernel.org Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 214 +++++++++++++++++++++++++ drivers/firmware/qcom/qcom_scm.h | 4 + include/linux/firmware/qcom/qcom_scm.h | 8 + 3 files changed, 226 insertions(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 2380775508ac6..f0569bb9411f7 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -1282,6 +1282,220 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size, } EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key); +bool qcom_scm_has_wrapped_key_support(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES, + QCOM_SCM_ES_DERIVE_SW_SECRET) && + __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES, + QCOM_SCM_ES_GENERATE_ICE_KEY) && + __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES, + QCOM_SCM_ES_PREPARE_ICE_KEY) && + __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES, + QCOM_SCM_ES_IMPORT_ICE_KEY); +} +EXPORT_SYMBOL_GPL(qcom_scm_has_wrapped_key_support); + +/** + * qcom_scm_derive_sw_secret() - Derive software secret from wrapped key + * @eph_key: an ephemerally-wrapped key + * @eph_key_size: size of @eph_key in bytes + * @sw_secret: output buffer for the software secret + * @sw_secret_size: size of the software secret to derive in bytes + * + * Derive a software secret from an ephemerally-wrapped key for software crypto + * operations. This is done by calling into the secure execution environment, + * which then calls into the hardware to unwrap and derive the secret. + * + * For more information on sw_secret, see the "Hardware-wrapped keys" section of + * Documentation/block/inline-encryption.rst. + * + * Return: 0 on success; -errno on failure. + */ +int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size, + u8 *sw_secret, size_t sw_secret_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_DERIVE_SW_SECRET, + .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL, + QCOM_SCM_RW, QCOM_SCM_VAL), + .owner = ARM_SMCCC_OWNER_SIP, + }; + int ret; + + void *eph_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, + eph_key_size, + GFP_KERNEL); + if (!eph_key_buf) + return -ENOMEM; + + void *sw_secret_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, + sw_secret_size, + GFP_KERNEL); + if (!sw_secret_buf) + return -ENOMEM; + + memcpy(eph_key_buf, eph_key, eph_key_size); + desc.args[0] = qcom_tzmem_to_phys(eph_key_buf); + desc.args[1] = eph_key_size; + desc.args[2] = qcom_tzmem_to_phys(sw_secret_buf); + desc.args[3] = sw_secret_size; + + ret = qcom_scm_call(__scm->dev, &desc, NULL); + if (!ret) + memcpy(sw_secret, sw_secret_buf, sw_secret_size); + + memzero_explicit(eph_key_buf, eph_key_size); + memzero_explicit(sw_secret_buf, sw_secret_size); + return ret; +} +EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret); + +/** + * qcom_scm_generate_ice_key() - Generate a wrapped key for storage encryption + * @lt_key: output buffer for the long-term wrapped key + * @lt_key_size: size of @lt_key in bytes. Must be the exact wrapped key size + * used by the SoC. + * + * Generate a key using the built-in HW module in the SoC. The resulting key is + * returned wrapped with the platform-specific Key Encryption Key. + * + * Return: 0 on success; -errno on failure. + */ +int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_GENERATE_ICE_KEY, + .arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL), + .owner = ARM_SMCCC_OWNER_SIP, + }; + int ret; + + void *lt_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, + lt_key_size, + GFP_KERNEL); + if (!lt_key_buf) + return -ENOMEM; + + desc.args[0] = qcom_tzmem_to_phys(lt_key_buf); + desc.args[1] = lt_key_size; + + ret = qcom_scm_call(__scm->dev, &desc, NULL); + if (!ret) + memcpy(lt_key, lt_key_buf, lt_key_size); + + memzero_explicit(lt_key_buf, lt_key_size); + return ret; +} +EXPORT_SYMBOL_GPL(qcom_scm_generate_ice_key); + +/** + * qcom_scm_prepare_ice_key() - Re-wrap a key with the per-boot ephemeral key + * @lt_key: a long-term wrapped key + * @lt_key_size: size of @lt_key in bytes + * @eph_key: output buffer for the ephemerally-wrapped key + * @eph_key_size: size of @eph_key in bytes. Must be the exact wrapped key size + * used by the SoC. + * + * Given a long-term wrapped key, re-wrap it with the per-boot ephemeral key for + * added protection. The resulting key will only be valid for the current boot. + * + * Return: 0 on success; -errno on failure. + */ +int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size, + u8 *eph_key, size_t eph_key_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_PREPARE_ICE_KEY, + .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO, QCOM_SCM_VAL, + QCOM_SCM_RW, QCOM_SCM_VAL), + .owner = ARM_SMCCC_OWNER_SIP, + }; + int ret; + + void *lt_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, + lt_key_size, + GFP_KERNEL); + if (!lt_key_buf) + return -ENOMEM; + + void *eph_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, + eph_key_size, + GFP_KERNEL); + if (!eph_key_buf) + return -ENOMEM; + + memcpy(lt_key_buf, lt_key, lt_key_size); + desc.args[0] = qcom_tzmem_to_phys(lt_key_buf); + desc.args[1] = lt_key_size; + desc.args[2] = qcom_tzmem_to_phys(eph_key_buf); + desc.args[3] = eph_key_size; + + ret = qcom_scm_call(__scm->dev, &desc, NULL); + if (!ret) + memcpy(eph_key, eph_key_buf, eph_key_size); + + memzero_explicit(lt_key_buf, lt_key_size); + memzero_explicit(eph_key_buf, eph_key_size); + return ret; +} +EXPORT_SYMBOL_GPL(qcom_scm_prepare_ice_key); + +/** + * qcom_scm_import_ice_key() - Import key for storage encryption + * @raw_key: the raw key to import + * @raw_key_size: size of @raw_key in bytes + * @lt_key: output buffer for the long-term wrapped key + * @lt_key_size: size of @lt_key in bytes. Must be the exact wrapped key size + * used by the SoC. + * + * Import a raw key and return a long-term wrapped key. Uses the SoC's HWKM to + * wrap the raw key using the platform-specific Key Encryption Key. + * + * Return: 0 on success; -errno on failure. + */ +int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size, + u8 *lt_key, size_t lt_key_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_IMPORT_ICE_KEY, + .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO, QCOM_SCM_VAL, + QCOM_SCM_RW, QCOM_SCM_VAL), + .owner = ARM_SMCCC_OWNER_SIP, + }; + int ret; + + void *raw_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, + raw_key_size, + GFP_KERNEL); + if (!raw_key_buf) + return -ENOMEM; + + void *lt_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, + lt_key_size, + GFP_KERNEL); + if (!lt_key_buf) + return -ENOMEM; + + memcpy(raw_key_buf, raw_key, raw_key_size); + desc.args[0] = qcom_tzmem_to_phys(raw_key_buf); + desc.args[1] = raw_key_size; + desc.args[2] = qcom_tzmem_to_phys(lt_key_buf); + desc.args[3] = lt_key_size; + + ret = qcom_scm_call(__scm->dev, &desc, NULL); + if (!ret) + memcpy(lt_key, lt_key_buf, lt_key_size); + + memzero_explicit(raw_key_buf, raw_key_size); + memzero_explicit(lt_key_buf, lt_key_size); + return ret; +} +EXPORT_SYMBOL_GPL(qcom_scm_import_ice_key); + /** * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. * diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h index e36b2f67607fc..097369d38b84e 100644 --- a/drivers/firmware/qcom/qcom_scm.h +++ b/drivers/firmware/qcom/qcom_scm.h @@ -128,6 +128,10 @@ struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void); #define QCOM_SCM_SVC_ES 0x10 /* Enterprise Security */ #define QCOM_SCM_ES_INVALIDATE_ICE_KEY 0x03 #define QCOM_SCM_ES_CONFIG_SET_ICE_KEY 0x04 +#define QCOM_SCM_ES_DERIVE_SW_SECRET 0x07 +#define QCOM_SCM_ES_GENERATE_ICE_KEY 0x08 +#define QCOM_SCM_ES_PREPARE_ICE_KEY 0x09 +#define QCOM_SCM_ES_IMPORT_ICE_KEY 0x0a #define QCOM_SCM_SVC_HDCP 0x11 #define QCOM_SCM_HDCP_INVOKE 0x01 diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h index 4621aec0328c2..983e1591bbba7 100644 --- a/include/linux/firmware/qcom/qcom_scm.h +++ b/include/linux/firmware/qcom/qcom_scm.h @@ -105,6 +105,14 @@ bool qcom_scm_ice_available(void); int qcom_scm_ice_invalidate_key(u32 index); int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size, enum qcom_scm_ice_cipher cipher, u32 data_unit_size); +bool qcom_scm_has_wrapped_key_support(void); +int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size, + u8 *sw_secret, size_t sw_secret_size); +int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size); +int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size, + u8 *eph_key, size_t eph_key_size); +int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size, + u8 *lt_key, size_t lt_key_size); bool qcom_scm_hdcp_available(void); int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); From 74d4d7c64d89aaf3e08aa06a6967dbc540b72c06 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 4 Jan 2025 15:19:58 +0100 Subject: [PATCH 51/58] soc/tegra: cbb: Drop unnecessary debugfs error handling Kernel coding style expects all drivers to ignore debugfs errors. Partially because it is purely for debugging, not for important user interfaces. Simplify the code by dropping unnecessary probe failuring and error message on debugfs failures, which also fixes incorrect usage IS_ERR_OR_NULL() and Smatch warning: drivers/soc/tegra/cbb/tegra-cbb.c:80 tegra_cbb_err_debugfs_init() warn: passing zero to 'PTR_ERR' Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250104141958.115911-1-krzysztof.kozlowski@linaro.org Signed-off-by: Thierry Reding --- drivers/soc/tegra/cbb/tegra-cbb.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/soc/tegra/cbb/tegra-cbb.c b/drivers/soc/tegra/cbb/tegra-cbb.c index 84ab46c9d9f53..6215c6a84fbe1 100644 --- a/drivers/soc/tegra/cbb/tegra-cbb.c +++ b/drivers/soc/tegra/cbb/tegra-cbb.c @@ -69,19 +69,12 @@ static int tegra_cbb_err_show(struct seq_file *file, void *data) } DEFINE_SHOW_ATTRIBUTE(tegra_cbb_err); -static int tegra_cbb_err_debugfs_init(struct tegra_cbb *cbb) +static void tegra_cbb_err_debugfs_init(struct tegra_cbb *cbb) { static struct dentry *root; - if (!root) { + if (!root) root = debugfs_create_file("tegra_cbb_err", 0444, NULL, cbb, &tegra_cbb_err_fops); - if (IS_ERR_OR_NULL(root)) { - pr_err("%s(): could not create debugfs node\n", __func__); - return PTR_ERR(root); - } - } - - return 0; } void tegra_cbb_stall_enable(struct tegra_cbb *cbb) @@ -148,13 +141,8 @@ int tegra_cbb_register(struct tegra_cbb *cbb) { int ret; - if (IS_ENABLED(CONFIG_DEBUG_FS)) { - ret = tegra_cbb_err_debugfs_init(cbb); - if (ret) { - dev_err(cbb->dev, "failed to create debugfs\n"); - return ret; - } - } + if (IS_ENABLED(CONFIG_DEBUG_FS)) + tegra_cbb_err_debugfs_init(cbb); /* register interrupt handler for errors due to different initiators */ ret = cbb->ops->interrupt_enable(cbb); From c475b68155942cc2142aca02f3fc19f6e730f17e Mon Sep 17 00:00:00 2001 From: liujing Date: Mon, 9 Dec 2024 13:51:48 +0800 Subject: [PATCH 52/58] soc/tegra: Fix spelling error in tegra234_lookup_slave_timeout() Fix spelling error in tegra234_lookup_slave_timeout(). Signed-off-by: liujing Link: https://lore.kernel.org/r/20241209055148.3749-1-liujing@cmss.chinamobile.com Signed-off-by: Thierry Reding --- drivers/soc/tegra/cbb/tegra234-cbb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c index 5cf0e8c341644..c74629af9bb5d 100644 --- a/drivers/soc/tegra/cbb/tegra234-cbb.c +++ b/drivers/soc/tegra/cbb/tegra234-cbb.c @@ -277,7 +277,7 @@ static void tegra234_lookup_slave_timeout(struct seq_file *file, struct tegra234 * which timed out. * a) Get block number from the index of set bit in * _SN_AXI2APB_<>_BLOCK_TMO_STATUS_0 register. - * b) Get address of register repective to block number i.e. + * b) Get address of register respective to block number i.e. * _SN_AXI2APB_<>_BLOCK_TMO_0. * c) Read the register in above step to get client_id which * timed out as per the set bits. From 836b341cc8dab680acc06a7883bfeea89680b689 Mon Sep 17 00:00:00 2001 From: Kartik Rajput Date: Wed, 27 Nov 2024 11:40:53 +0530 Subject: [PATCH 53/58] soc/tegra: fuse: Update Tegra234 nvmem keepout list Various Nvidia userspace applications and tests access following fuse via Fuse nvmem interface: * odmid * odminfo * boot_security_info * public_key_hash * reserved_odm0 * reserved_odm1 * reserved_odm2 * reserved_odm3 * reserved_odm4 * reserved_odm5 * reserved_odm6 * reserved_odm7 * odm_lock * pk_h1 * pk_h2 * revoke_pk_h0 * revoke_pk_h1 * security_mode * system_fw_field_ratchet0 * system_fw_field_ratchet1 * system_fw_field_ratchet2 * system_fw_field_ratchet3 * optin_enable Update tegra234_fuse_keepouts list to allow reading these fuse from nvmem sysfs interface. Signed-off-by: Kartik Rajput Link: https://lore.kernel.org/r/20241127061053.16775-1-kkartik@nvidia.com Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/fuse-tegra30.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index eb14e5ff5a0aa..e24ab5f7d2bf1 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c @@ -647,15 +647,20 @@ static const struct nvmem_cell_lookup tegra234_fuse_lookups[] = { }; static const struct nvmem_keepout tegra234_fuse_keepouts[] = { - { .start = 0x01c, .end = 0x0c8 }, - { .start = 0x12c, .end = 0x184 }, + { .start = 0x01c, .end = 0x064 }, + { .start = 0x084, .end = 0x0a0 }, + { .start = 0x0a4, .end = 0x0c8 }, + { .start = 0x12c, .end = 0x164 }, + { .start = 0x16c, .end = 0x184 }, { .start = 0x190, .end = 0x198 }, { .start = 0x1a0, .end = 0x204 }, - { .start = 0x21c, .end = 0x250 }, - { .start = 0x25c, .end = 0x2f0 }, + { .start = 0x21c, .end = 0x2f0 }, { .start = 0x310, .end = 0x3d8 }, - { .start = 0x400, .end = 0x4f0 }, - { .start = 0x4f8, .end = 0x7e8 }, + { .start = 0x400, .end = 0x420 }, + { .start = 0x444, .end = 0x490 }, + { .start = 0x4bc, .end = 0x4f0 }, + { .start = 0x4f8, .end = 0x54c }, + { .start = 0x57c, .end = 0x7e8 }, { .start = 0x8d0, .end = 0x8d8 }, { .start = 0xacc, .end = 0xf00 } }; From 0d602fcfb9d2fb9d6340bc4e82047df41c7aa214 Mon Sep 17 00:00:00 2001 From: Jan Dakinevich Date: Wed, 13 Nov 2024 02:00:55 +0300 Subject: [PATCH 54/58] dt-bindings: reset: add bindings for A1 SoC audio reset controller This reset controller is part of audio clock controller and handled by auxiliary reset driver. Introduced defines supposed to be used together with upcoming device tree nodes for audio clock controller fo A1 SoC. Signed-off-by: Jan Dakinevich Acked-by: Conor Dooley Link: https://lore.kernel.org/r/20241112230056.1406222-2-jan.dakinevich@salutedevices.com Signed-off-by: Philipp Zabel --- .../reset/amlogic,meson-a1-audio-reset.h | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 include/dt-bindings/reset/amlogic,meson-a1-audio-reset.h diff --git a/include/dt-bindings/reset/amlogic,meson-a1-audio-reset.h b/include/dt-bindings/reset/amlogic,meson-a1-audio-reset.h new file mode 100644 index 0000000000000..7693552f1507a --- /dev/null +++ b/include/dt-bindings/reset/amlogic,meson-a1-audio-reset.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ +/* + * Copyright (c) 2024, SaluteDevices. All Rights Reserved. + * + * Author: Jan Dakinevich + */ + +#ifndef _DT_BINDINGS_AMLOGIC_MESON_A1_AUDIO_RESET_H +#define _DT_BINDINGS_AMLOGIC_MESON_A1_AUDIO_RESET_H + +#define AUD_RESET_DDRARB 0 +#define AUD_RESET_TDMIN_A 1 +#define AUD_RESET_TDMIN_B 2 +#define AUD_RESET_TDMIN_LB 3 +#define AUD_RESET_LOOPBACK 4 +#define AUD_RESET_TDMOUT_A 5 +#define AUD_RESET_TDMOUT_B 6 +#define AUD_RESET_FRDDR_A 7 +#define AUD_RESET_FRDDR_B 8 +#define AUD_RESET_TODDR_A 9 +#define AUD_RESET_TODDR_B 10 +#define AUD_RESET_SPDIFIN 11 +#define AUD_RESET_RESAMPLE 12 +#define AUD_RESET_EQDRC 13 +#define AUD_RESET_LOCKER 14 +#define AUD_RESET_TOACODEC 30 +#define AUD_RESET_CLKTREE 31 + +#define AUD_VAD_RESET_DDRARB 0 +#define AUD_VAD_RESET_PDM 1 +#define AUD_VAD_RESET_TDMIN_VAD 2 +#define AUD_VAD_RESET_TODDR_VAD 3 +#define AUD_VAD_RESET_TOVAD 4 +#define AUD_VAD_RESET_CLKTREE 5 + +#endif /* _DT_BINDINGS_AMLOGIC_MESON_A1_AUDIO_RESET_H */ From 64de6a3fed96bad801e8ecd70140a4fc1304bdde Mon Sep 17 00:00:00 2001 From: Jan Dakinevich Date: Wed, 13 Nov 2024 02:00:56 +0300 Subject: [PATCH 55/58] reset: amlogic: add support for A1 SoC in auxiliary reset driver Add support for the reset controller present in the audio clock controller of A1 SoC families, using the auxiliary bus. Signed-off-by: Jan Dakinevich Link: https://lore.kernel.org/r/20241112230056.1406222-3-jan.dakinevich@salutedevices.com Signed-off-by: Philipp Zabel --- drivers/reset/amlogic/reset-meson-aux.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/reset/amlogic/reset-meson-aux.c b/drivers/reset/amlogic/reset-meson-aux.c index dd8453001db9c..4b422ae5fcd20 100644 --- a/drivers/reset/amlogic/reset-meson-aux.c +++ b/drivers/reset/amlogic/reset-meson-aux.c @@ -26,6 +26,18 @@ struct meson_reset_adev { #define to_meson_reset_adev(_adev) \ container_of((_adev), struct meson_reset_adev, adev) +static const struct meson_reset_param meson_a1_audio_param = { + .reset_ops = &meson_reset_toggle_ops, + .reset_num = 32, + .level_offset = 0x28, +}; + +static const struct meson_reset_param meson_a1_audio_vad_param = { + .reset_ops = &meson_reset_toggle_ops, + .reset_num = 6, + .level_offset = 0x8, +}; + static const struct meson_reset_param meson_g12a_audio_param = { .reset_ops = &meson_reset_toggle_ops, .reset_num = 26, @@ -40,6 +52,12 @@ static const struct meson_reset_param meson_sm1_audio_param = { static const struct auxiliary_device_id meson_reset_aux_ids[] = { { + .name = "a1-audio-clkc.rst-a1", + .driver_data = (kernel_ulong_t)&meson_a1_audio_param, + }, { + .name = "a1-audio-clkc.rst-a1-vad", + .driver_data = (kernel_ulong_t)&meson_a1_audio_vad_param, + }, { .name = "axg-audio-clkc.rst-g12a", .driver_data = (kernel_ulong_t)&meson_g12a_audio_param, }, { From ccfba09ceecc3ac1f264e680120cef01aed6e75e Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 9 Dec 2024 17:04:34 +0100 Subject: [PATCH 56/58] reset: amlogic: aux: get regmap through parent device Get regmap directly from the parent device registering the auxiliary reset driver, instead of using device data attached to the auxiliary device. This simplifies the registration a bit. Suggested-by: Stephen Boyd Signed-off-by: Jerome Brunet Acked-by: Arnd Bergmann Link: https://lore.kernel.org/r/20241209-meson-rst-aux-rework-v1-1-d2afb69cc72e@baylibre.com Signed-off-by: Philipp Zabel --- drivers/reset/amlogic/reset-meson-aux.c | 36 +++++++++---------------- 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/drivers/reset/amlogic/reset-meson-aux.c b/drivers/reset/amlogic/reset-meson-aux.c index 4b422ae5fcd20..0fc1788eb7a83 100644 --- a/drivers/reset/amlogic/reset-meson-aux.c +++ b/drivers/reset/amlogic/reset-meson-aux.c @@ -18,14 +18,6 @@ static DEFINE_IDA(meson_rst_aux_ida); -struct meson_reset_adev { - struct auxiliary_device adev; - struct regmap *map; -}; - -#define to_meson_reset_adev(_adev) \ - container_of((_adev), struct meson_reset_adev, adev) - static const struct meson_reset_param meson_a1_audio_param = { .reset_ops = &meson_reset_toggle_ops, .reset_num = 32, @@ -72,10 +64,13 @@ static int meson_reset_aux_probe(struct auxiliary_device *adev, { const struct meson_reset_param *param = (const struct meson_reset_param *)(id->driver_data); - struct meson_reset_adev *raux = - to_meson_reset_adev(adev); + struct regmap *map; + + map = dev_get_regmap(adev->dev.parent, NULL); + if (!map) + return -EINVAL; - return meson_reset_controller_register(&adev->dev, raux->map, param); + return meson_reset_controller_register(&adev->dev, map, param); } static struct auxiliary_driver meson_reset_aux_driver = { @@ -87,11 +82,9 @@ module_auxiliary_driver(meson_reset_aux_driver); static void meson_rst_aux_release(struct device *dev) { struct auxiliary_device *adev = to_auxiliary_dev(dev); - struct meson_reset_adev *raux = - to_meson_reset_adev(adev); ida_free(&meson_rst_aux_ida, adev->id); - kfree(raux); + kfree(adev); } static void meson_rst_aux_unregister_adev(void *_adev) @@ -103,24 +96,19 @@ static void meson_rst_aux_unregister_adev(void *_adev) } int devm_meson_rst_aux_register(struct device *dev, - struct regmap *map, const char *adev_name) { - struct meson_reset_adev *raux; struct auxiliary_device *adev; int ret; - raux = kzalloc(sizeof(*raux), GFP_KERNEL); - if (!raux) + adev = kzalloc(sizeof(*adev), GFP_KERNEL); + if (!adev) return -ENOMEM; ret = ida_alloc(&meson_rst_aux_ida, GFP_KERNEL); if (ret < 0) - goto raux_free; - - raux->map = map; + goto adev_free; - adev = &raux->adev; adev->id = ret; adev->name = adev_name; adev->dev.parent = dev; @@ -142,8 +130,8 @@ int devm_meson_rst_aux_register(struct device *dev, ida_free: ida_free(&meson_rst_aux_ida, adev->id); -raux_free: - kfree(raux); +adev_free: + kfree(adev); return ret; } EXPORT_SYMBOL_GPL(devm_meson_rst_aux_register); From 72bb8275a3b0784a817e0371c49c0110d68bb7fb Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 9 Dec 2024 17:04:35 +0100 Subject: [PATCH 57/58] reset: amlogic: aux: drop aux registration helper Having the aux registration helper along with the registered driver is not great dependency wise. It does not allow the registering driver to be properly decoupled from the registered auxiliary driver. Drop the registration helper from the amlogic auxiliary reset driver. This will be handled in the registering clock driver to start with while a more generic solution is worked on. Suggested-by: Arnd Bergmann Signed-off-by: Jerome Brunet Acked-by: Arnd Bergmann Link: https://lore.kernel.org/r/20241209-meson-rst-aux-rework-v1-2-d2afb69cc72e@baylibre.com Signed-off-by: Philipp Zabel --- drivers/reset/amlogic/reset-meson-aux.c | 61 ------------------------- include/soc/amlogic/reset-meson-aux.h | 23 ---------- 2 files changed, 84 deletions(-) delete mode 100644 include/soc/amlogic/reset-meson-aux.h diff --git a/drivers/reset/amlogic/reset-meson-aux.c b/drivers/reset/amlogic/reset-meson-aux.c index 0fc1788eb7a83..1a2024afa056e 100644 --- a/drivers/reset/amlogic/reset-meson-aux.c +++ b/drivers/reset/amlogic/reset-meson-aux.c @@ -11,12 +11,8 @@ #include #include #include -#include #include "reset-meson.h" -#include - -static DEFINE_IDA(meson_rst_aux_ida); static const struct meson_reset_param meson_a1_audio_param = { .reset_ops = &meson_reset_toggle_ops, @@ -79,63 +75,6 @@ static struct auxiliary_driver meson_reset_aux_driver = { }; module_auxiliary_driver(meson_reset_aux_driver); -static void meson_rst_aux_release(struct device *dev) -{ - struct auxiliary_device *adev = to_auxiliary_dev(dev); - - ida_free(&meson_rst_aux_ida, adev->id); - kfree(adev); -} - -static void meson_rst_aux_unregister_adev(void *_adev) -{ - struct auxiliary_device *adev = _adev; - - auxiliary_device_delete(adev); - auxiliary_device_uninit(adev); -} - -int devm_meson_rst_aux_register(struct device *dev, - const char *adev_name) -{ - struct auxiliary_device *adev; - int ret; - - adev = kzalloc(sizeof(*adev), GFP_KERNEL); - if (!adev) - return -ENOMEM; - - ret = ida_alloc(&meson_rst_aux_ida, GFP_KERNEL); - if (ret < 0) - goto adev_free; - - adev->id = ret; - adev->name = adev_name; - adev->dev.parent = dev; - adev->dev.release = meson_rst_aux_release; - device_set_of_node_from_dev(&adev->dev, dev); - - ret = auxiliary_device_init(adev); - if (ret) - goto ida_free; - - ret = __auxiliary_device_add(adev, dev->driver->name); - if (ret) { - auxiliary_device_uninit(adev); - return ret; - } - - return devm_add_action_or_reset(dev, meson_rst_aux_unregister_adev, - adev); - -ida_free: - ida_free(&meson_rst_aux_ida, adev->id); -adev_free: - kfree(adev); - return ret; -} -EXPORT_SYMBOL_GPL(devm_meson_rst_aux_register); - MODULE_DESCRIPTION("Amlogic Meson Reset Auxiliary driver"); MODULE_AUTHOR("Jerome Brunet "); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/include/soc/amlogic/reset-meson-aux.h b/include/soc/amlogic/reset-meson-aux.h deleted file mode 100644 index d8a15d48c9849..0000000000000 --- a/include/soc/amlogic/reset-meson-aux.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __SOC_RESET_MESON_AUX_H -#define __SOC_RESET_MESON_AUX_H - -#include - -struct device; -struct regmap; - -#if IS_ENABLED(CONFIG_RESET_MESON_AUX) -int devm_meson_rst_aux_register(struct device *dev, - struct regmap *map, - const char *adev_name); -#else -static inline int devm_meson_rst_aux_register(struct device *dev, - struct regmap *map, - const char *adev_name) -{ - return 0; -} -#endif - -#endif /* __SOC_RESET_MESON_AUX_H */ From c7345869aa382b1e22691d51cbbd218d7f488a55 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Tue, 23 Jan 2024 10:44:41 -0600 Subject: [PATCH 58/58] drivers/soc/litex: Use devm_register_restart_handler() Use device life-cycle managed register function to simplify probe error path and eliminate need for explicit remove function. Signed-off-by: Andrew Davis Reviewed-by: Gabriel Somlo Link: https://lore.kernel.org/all/20240123164443.394642-3-afd@ti.com Signed-off-by: Gabriel Somlo --- drivers/soc/litex/litex_soc_ctrl.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/soc/litex/litex_soc_ctrl.c b/drivers/soc/litex/litex_soc_ctrl.c index d08bfc8ef7be7..104a5f9bfd268 100644 --- a/drivers/soc/litex/litex_soc_ctrl.c +++ b/drivers/soc/litex/litex_soc_ctrl.c @@ -69,14 +69,11 @@ static int litex_check_csr_access(void __iomem *reg_addr) struct litex_soc_ctrl_device { void __iomem *base; - struct notifier_block reset_nb; }; -static int litex_reset_handler(struct notifier_block *this, unsigned long mode, - void *cmd) +static int litex_reset_handler(struct sys_off_data *data) { - struct litex_soc_ctrl_device *soc_ctrl_dev = - container_of(this, struct litex_soc_ctrl_device, reset_nb); + struct litex_soc_ctrl_device *soc_ctrl_dev = data->cb_data; litex_write32(soc_ctrl_dev->base + RESET_REG_OFF, RESET_REG_VALUE); return NOTIFY_DONE; @@ -105,11 +102,9 @@ static int litex_soc_ctrl_probe(struct platform_device *pdev) if (error) return error; - platform_set_drvdata(pdev, soc_ctrl_dev); - - soc_ctrl_dev->reset_nb.notifier_call = litex_reset_handler; - soc_ctrl_dev->reset_nb.priority = 128; - error = register_restart_handler(&soc_ctrl_dev->reset_nb); + error = devm_register_restart_handler(&pdev->dev, + litex_reset_handler, + soc_ctrl_dev); if (error) { dev_warn(&pdev->dev, "cannot register restart handler: %d\n", error); @@ -118,20 +113,12 @@ static int litex_soc_ctrl_probe(struct platform_device *pdev) return 0; } -static void litex_soc_ctrl_remove(struct platform_device *pdev) -{ - struct litex_soc_ctrl_device *soc_ctrl_dev = platform_get_drvdata(pdev); - - unregister_restart_handler(&soc_ctrl_dev->reset_nb); -} - static struct platform_driver litex_soc_ctrl_driver = { .driver = { .name = "litex-soc-controller", .of_match_table = litex_soc_ctrl_of_match, }, .probe = litex_soc_ctrl_probe, - .remove = litex_soc_ctrl_remove, }; module_platform_driver(litex_soc_ctrl_driver);