From 6bc45428635d693ebe3341a331dd8475748f4796 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 21 Feb 2021 19:14:31 -0800 Subject: [PATCH 01/20] firmware: qcom_scm: Mark string array const Mark the qcom_scm_convention_names[] array const as it isn't changed. Cc: Elliot Berman Fixes: 9a434cee773a ("firmware: qcom_scm: Dynamically support SMCCC and legacy conventions") Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20210222031431.3831189-1-swboyd@chromium.org Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom_scm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 47ea2bd42b10..33db4a65c2b2 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -71,7 +71,7 @@ static struct qcom_scm_wb_entry qcom_scm_wb[] = { { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 }, }; -static const char *qcom_scm_convention_names[] = { +static const char * const qcom_scm_convention_names[] = { [SMC_CONVENTION_UNKNOWN] = "unknown", [SMC_CONVENTION_ARM_32] = "smc arm 32", [SMC_CONVENTION_ARM_64] = "smc arm 64", From d775dab9a4a8f1279b65a80a445753a569338319 Mon Sep 17 00:00:00 2001 From: Junlin Yang Date: Thu, 11 Mar 2021 09:32:35 +0800 Subject: [PATCH 02/20] firmware: qcom_scm: remove a duplicative condition Fixes coccicheck warnings: ./drivers/firmware/qcom_scm.c:324:20-22: WARNING !A || A && B is equivalent to !A || B Signed-off-by: Junlin Yang Link: https://lore.kernel.org/r/20210311013235.1458-1-angkery@163.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom_scm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 33db4a65c2b2..76bfa7ac2818 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -331,7 +331,7 @@ int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) .owner = ARM_SMCCC_OWNER_SIP, }; - if (!cpus || (cpus && cpumask_empty(cpus))) + if (!cpus || cpumask_empty(cpus)) return -EINVAL; for_each_cpu(cpu, cpus) { From e9ad5da25002772436c968309d6dbeaf31c91404 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 9 Jul 2021 10:41:40 -0700 Subject: [PATCH 03/20] dt-bindings: soc: qcom: aoss: Add SC8180X and generic compatible Add a generic compatible for all versions of the AOSS QMP to the binding, in order to allow a single implementation for them and then add a specific compatible for the Qualcomm SC8180x platform. Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210709174142.1274554-2-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt index 783dc81b0f26..3747032311a4 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt @@ -18,10 +18,13 @@ power-domains. Definition: must be one of: "qcom,sc7180-aoss-qmp" "qcom,sc7280-aoss-qmp" + "qcom,sc8180x-aoss-qmp" "qcom,sdm845-aoss-qmp" "qcom,sm8150-aoss-qmp" "qcom,sm8250-aoss-qmp" "qcom,sm8350-aoss-qmp" + and: + "qcom,aoss-qmp" - reg: Usage: required @@ -70,7 +73,7 @@ The following example represents the AOSS side-channel message RAM and the mechanism exposing the power-domains, as found in SDM845. aoss_qmp: qmp@c300000 { - compatible = "qcom,sdm845-aoss-qmp"; + compatible = "qcom,sdm845-aoss-qmp", "qcom,aoss-qmp"; reg = <0x0c300000 0x100000>; interrupts = ; mboxes = <&apss_shared 0>; From 44dadfbcd992829515c80ff7d1bbab73cd321a3f Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 9 Jul 2021 10:41:41 -0700 Subject: [PATCH 04/20] dt-bindings: soc: qcom: aoss: Convert to YAML Convert to YAML in order to allow validation. Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210709174142.1274554-3-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- .../bindings/soc/qcom/qcom,aoss-qmp.txt | 90 -------------- .../bindings/soc/qcom/qcom,aoss-qmp.yaml | 114 ++++++++++++++++++ 2 files changed, 114 insertions(+), 90 deletions(-) delete mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt deleted file mode 100644 index 3747032311a4..000000000000 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt +++ /dev/null @@ -1,90 +0,0 @@ -Qualcomm Always-On Subsystem side channel binding - -This binding describes the hardware component responsible for side channel -requests to the always-on subsystem (AOSS), used for certain power management -requests that is not handled by the standard RPMh interface. Each client in the -SoC has it's own block of message RAM and IRQ for communication with the AOSS. -The protocol used to communicate in the message RAM is known as Qualcomm -Messaging Protocol (QMP) - -The AOSS side channel exposes control over a set of resources, used to control -a set of debug related clocks and to affect the low power state of resources -related to the secondary subsystems. These resources are exposed as a set of -power-domains. - -- compatible: - Usage: required - Value type: - Definition: must be one of: - "qcom,sc7180-aoss-qmp" - "qcom,sc7280-aoss-qmp" - "qcom,sc8180x-aoss-qmp" - "qcom,sdm845-aoss-qmp" - "qcom,sm8150-aoss-qmp" - "qcom,sm8250-aoss-qmp" - "qcom,sm8350-aoss-qmp" - and: - "qcom,aoss-qmp" - -- reg: - Usage: required - Value type: - Definition: the base address and size of the message RAM for this - client's communication with the AOSS - -- interrupts: - Usage: required - Value type: - Definition: should specify the AOSS message IRQ for this client - -- mboxes: - Usage: required - Value type: - Definition: reference to the mailbox representing the outgoing doorbell - in APCS for this client, as described in mailbox/mailbox.txt - -- #clock-cells: - Usage: optional - Value type: - Definition: must be 0 - The single clock represents the QDSS clock. - -- #power-domain-cells: - Usage: optional - Value type: - Definition: must be 1 - The provided power-domains are: - CDSP state (0), LPASS state (1), modem state (2), SLPI - state (3), SPSS state (4) and Venus state (5). - -= SUBNODES -The AOSS side channel also provides the controls for three cooling devices, -these are expressed as subnodes of the QMP node. The name of the node is used -to identify the resource and must therefor be "cx", "mx" or "ebi". - -- #cooling-cells: - Usage: optional - Value type: - Definition: must be 2 - -= EXAMPLE - -The following example represents the AOSS side-channel message RAM and the -mechanism exposing the power-domains, as found in SDM845. - - aoss_qmp: qmp@c300000 { - compatible = "qcom,sdm845-aoss-qmp", "qcom,aoss-qmp"; - reg = <0x0c300000 0x100000>; - interrupts = ; - mboxes = <&apss_shared 0>; - - #power-domain-cells = <1>; - - cx_cdev: cx { - #cooling-cells = <2>; - }; - - mx_cdev: mx { - #cooling-cells = <2>; - }; - }; diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml new file mode 100644 index 000000000000..93e4b737ee1b --- /dev/null +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml @@ -0,0 +1,114 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/qcom/qcom,aoss-qmp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Always-On Subsystem side channel binding + +maintainers: + - Bjorn Andersson + +description: + This binding describes the hardware component responsible for side channel + requests to the always-on subsystem (AOSS), used for certain power management + requests that is not handled by the standard RPMh interface. Each client in the + SoC has it's own block of message RAM and IRQ for communication with the AOSS. + The protocol used to communicate in the message RAM is known as Qualcomm + Messaging Protocol (QMP) + + The AOSS side channel exposes control over a set of resources, used to control + a set of debug related clocks and to affect the low power state of resources + related to the secondary subsystems. These resources are exposed as a set of + power-domains. + +properties: + compatible: + items: + - enum: + - qcom,sc7180-aoss-qmp + - qcom,sc7280-aoss-qmp + - qcom,sc8180x-aoss-qmp + - qcom,sdm845-aoss-qmp + - qcom,sm8150-aoss-qmp + - qcom,sm8250-aoss-qmp + - qcom,sm8350-aoss-qmp + - const: qcom,aoss-qmp + + reg: + maxItems: 1 + description: + The base address and size of the message RAM for this client's + communication with the AOSS + + interrupts: + maxItems: 1 + description: + Should specify the AOSS message IRQ for this client + + mboxes: + maxItems: 1 + description: + Reference to the mailbox representing the outgoing doorbell in APCS for + this client, as described in mailbox/mailbox.txt + + "#clock-cells": + const: 0 + description: + The single clock represents the QDSS clock. + + "#power-domain-cells": + const: 1 + description: | + The provided power-domains are: + CDSP state (0), LPASS state (1), modem state (2), SLPI + state (3), SPSS state (4) and Venus state (5). + +required: + - compatible + - reg + - interrupts + - mboxes + - "#clock-cells" + +additionalProperties: false + +patternProperties: + "^(cx|mx|ebi)$": + type: object + description: + The AOSS side channel also provides the controls for three cooling devices, + these are expressed as subnodes of the QMP node. The name of the node is + used to identify the resource and must therefor be "cx", "mx" or "ebi". + + properties: + "#cooling-cells": + const: 2 + + required: + - "#cooling-cells" + + additionalProperties: false + +examples: + - | + #include + + aoss_qmp: qmp@c300000 { + compatible = "qcom,sdm845-aoss-qmp", "qcom,aoss-qmp"; + reg = <0x0c300000 0x100000>; + interrupts = ; + mboxes = <&apss_shared 0>; + + #clock-cells = <0>; + #power-domain-cells = <1>; + + cx_cdev: cx { + #cooling-cells = <2>; + }; + + mx_cdev: mx { + #cooling-cells = <2>; + }; + }; +... From d63486dd8e0bf843949c184843137e03bca5b8b4 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 9 Jul 2021 10:41:42 -0700 Subject: [PATCH 05/20] soc: qcom: aoss: Add generic compatible It seems we don't need platform specific implementation for the AOSS QMP, so let's introduce a generic compatible to avoid having to update the driver for each platform. Reviewed-by: Sibi Sankar Tested-by: Sibi Sankar Link: https://lore.kernel.org/r/20210709174142.1274554-4-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_aoss.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 934fcc4d2b05..92a1af70a649 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -602,6 +602,7 @@ static const struct of_device_id qmp_dt_match[] = { { .compatible = "qcom,sm8150-aoss-qmp", }, { .compatible = "qcom,sm8250-aoss-qmp", }, { .compatible = "qcom,sm8350-aoss-qmp", }, + { .compatible = "qcom,aoss-qmp", }, {} }; MODULE_DEVICE_TABLE(of, qmp_dt_match); From d43b3a989bc8c06fd4bbb69a7500d180db2d68e8 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 2 Jul 2021 17:54:15 -0700 Subject: [PATCH 06/20] soc: qcom: rpmhpd: Use corner in power_off rpmhpd_aggregate_corner() takes a corner as parameter, but in rpmhpd_power_off() the code requests the level of the first corner instead. In all (known) current cases the first corner has level 0, so this change should be a nop, but in case that there's a power domain with a non-zero lowest level this makes sure that rpmhpd_power_off() actually requests the lowest level - which is the closest to "power off" we can get. While touching the code, also skip the unnecessary zero-initialization of "ret". Fixes: 279b7e8a62cc ("soc: qcom: rpmhpd: Add RPMh power domain driver") Reviewed-by: Rajendra Nayak Reviewed-by: Stephen Boyd Reviewed-by: Sibi Sankar Tested-by: Sibi Sankar Link: https://lore.kernel.org/r/20210703005416.2668319-2-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmhpd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c index 2daa17ba54a3..fa209b479ab3 100644 --- a/drivers/soc/qcom/rpmhpd.c +++ b/drivers/soc/qcom/rpmhpd.c @@ -403,12 +403,11 @@ static int rpmhpd_power_on(struct generic_pm_domain *domain) static int rpmhpd_power_off(struct generic_pm_domain *domain) { struct rpmhpd *pd = domain_to_rpmhpd(domain); - int ret = 0; + int ret; mutex_lock(&rpmhpd_lock); - ret = rpmhpd_aggregate_corner(pd, pd->level[0]); - + ret = rpmhpd_aggregate_corner(pd, 0); if (!ret) pd->enabled = false; From 0d361b0ac1ad99ecbe401a4eacdeb844dcdf86a2 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 27 Jun 2021 20:01:50 -0700 Subject: [PATCH 07/20] soc: qcom: socinfo: Don't print anything if nothing found Let's skip printing anything if there's nothing to see. This makes it so the file length is 0 instead of 1, for the newline, and helps scripts figure out if there's anything to see in these files. Cc: Sai Prakash Ranjan Cc: Douglas Anderson Cc: Dmitry Baryshkov Reviewed-by: Douglas Anderson Reviewed-by: Sai Prakash Ranjan Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20210628030150.2627905-1-swboyd@chromium.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index b2f049faa3df..9faf48302f4b 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -417,8 +417,8 @@ QCOM_OPEN(chip_id, qcom_show_chip_id); static int show_image_##type(struct seq_file *seq, void *p) \ { \ struct smem_image_version *image_version = seq->private; \ - seq_puts(seq, image_version->type); \ - seq_putc(seq, '\n'); \ + if (image_version->type[0] != '\0') \ + seq_printf(seq, "%s\n", image_version->type); \ return 0; \ } \ static int open_image_##type(struct inode *inode, struct file *file) \ From b42000e4b8741bf6591fcbbbefff6aa745f8eb29 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Wed, 7 Jul 2021 04:53:20 +0000 Subject: [PATCH 08/20] firmware: qcom_scm: Allow qcom_scm driver to be loadable as a permenent module Allow the qcom_scm driver to be loadable as a permenent module. This still uses the "depends on QCOM_SCM || !QCOM_SCM" bit to ensure that drivers that call into the qcom_scm driver are also built as modules. While not ideal in some cases its the only safe way I can find to avoid build errors without having those drivers select QCOM_SCM and have to force it on (as QCOM_SCM=n can be valid for those drivers). Reviving this now that Saravana's fw_devlink defaults to on, which should avoid loading troubles seen before. Acked-by: Kalle Valo Acked-by: Greg Kroah-Hartman Acked-by: Will Deacon Reviewed-by: Bjorn Andersson Signed-off-by: John Stultz Link: https://lore.kernel.org/r/20210707045320.529186-1-john.stultz@linaro.org Signed-off-by: Bjorn Andersson --- drivers/firmware/Kconfig | 2 +- drivers/firmware/Makefile | 3 ++- drivers/firmware/qcom_scm.c | 4 ++++ drivers/iommu/Kconfig | 2 ++ drivers/net/wireless/ath/ath10k/Kconfig | 1 + 5 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 1db738d5b301..aadb720c229b 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -235,7 +235,7 @@ config INTEL_STRATIX10_RSU Say Y here if you want Intel RSU support. config QCOM_SCM - bool + tristate "Qcom SCM driver" depends on ARM || ARM64 depends on HAVE_ARM_SMCCC select RESET_CONTROLLER diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 546ac8e7f6d0..3c2af2e98def 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -17,7 +17,8 @@ obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o -obj-$(CONFIG_QCOM_SCM) += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o +obj-$(CONFIG_QCOM_SCM) += qcom-scm.o +qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 76bfa7ac2818..ced1964faf42 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -1299,6 +1299,7 @@ static const struct of_device_id qcom_scm_dt_match[] = { { .compatible = "qcom,scm" }, {} }; +MODULE_DEVICE_TABLE(of, qcom_scm_dt_match); static struct platform_driver qcom_scm_driver = { .driver = { @@ -1315,3 +1316,6 @@ static int __init qcom_scm_init(void) return platform_driver_register(&qcom_scm_driver); } subsys_initcall(qcom_scm_init); + +MODULE_DESCRIPTION("Qualcomm Technologies, Inc. SCM driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 07b7c25cbed8..f61516c17589 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -253,6 +253,7 @@ config SPAPR_TCE_IOMMU config ARM_SMMU tristate "ARM Ltd. System MMU (SMMU) Support" depends on ARM64 || ARM || (COMPILE_TEST && !GENERIC_ATOMIC64) + depends on QCOM_SCM || !QCOM_SCM #if QCOM_SCM=m this can't be =y select IOMMU_API select IOMMU_IO_PGTABLE_LPAE select ARM_DMA_USE_IOMMU if ARM @@ -382,6 +383,7 @@ config QCOM_IOMMU # Note: iommu drivers cannot (yet?) be built as modules bool "Qualcomm IOMMU Support" depends on ARCH_QCOM || (COMPILE_TEST && !GENERIC_ATOMIC64) + depends on QCOM_SCM=y select IOMMU_API select IOMMU_IO_PGTABLE_LPAE select ARM_DMA_USE_IOMMU diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index 40f91bc8514d..741289e385d5 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -44,6 +44,7 @@ config ATH10K_SNOC tristate "Qualcomm ath10k SNOC support" depends on ATH10K depends on ARCH_QCOM || COMPILE_TEST + depends on QCOM_SCM || !QCOM_SCM #if QCOM_SCM=m this can't be =y select QCOM_QMI_HELPERS help This module adds support for integrated WCN3990 chip connected From a89f355e469dcda129c2522be4fdba00c1c74c83 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 29 Jun 2021 21:02:49 +0530 Subject: [PATCH 09/20] soc: qcom: aoss: Fix the out of bound usage of cooling_devs In "qmp_cooling_devices_register", the count value is initially QMP_NUM_COOLING_RESOURCES, which is 2. Based on the initial count value, the memory for cooling_devs is allocated. Then while calling the "qmp_cooling_device_add" function, count value is post-incremented for each child node. This makes the out of bound access to the cooling_dev array. Fix it by passing the QMP_NUM_COOLING_RESOURCES definition to devm_kzalloc() and initializing the count to 0. While at it, let's also free the memory allocated to cooling_dev if no cooling device is found in DT and during unroll phase. Cc: stable@vger.kernel.org # 5.4 Fixes: 05589b30b21a ("soc: qcom: Extend AOSS QMP driver to support resources that are used to wake up the SoC.") Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20210629153249.73428-1-manivannan.sadhasivam@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_aoss.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 92a1af70a649..536c3e4114fb 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -476,12 +476,12 @@ static int qmp_cooling_device_add(struct qmp *qmp, static int qmp_cooling_devices_register(struct qmp *qmp) { struct device_node *np, *child; - int count = QMP_NUM_COOLING_RESOURCES; + int count = 0; int ret; np = qmp->dev->of_node; - qmp->cooling_devs = devm_kcalloc(qmp->dev, count, + qmp->cooling_devs = devm_kcalloc(qmp->dev, QMP_NUM_COOLING_RESOURCES, sizeof(*qmp->cooling_devs), GFP_KERNEL); @@ -497,12 +497,16 @@ static int qmp_cooling_devices_register(struct qmp *qmp) goto unroll; } + if (!count) + devm_kfree(qmp->dev, qmp->cooling_devs); + return 0; unroll: while (--count >= 0) thermal_cooling_device_unregister (qmp->cooling_devs[count].cdev); + devm_kfree(qmp->dev, qmp->cooling_devs); return ret; } From d3625d94490e4c2d95febe3eafcc11e606eabb0c Mon Sep 17 00:00:00 2001 From: Iskren Chernev Date: Sun, 27 Jun 2021 21:59:23 +0300 Subject: [PATCH 10/20] dt-bindings: soc: qcom: smd-rpm: Add SM6115 compatible Add the dt-binding for the rpm on the Qualcomm SM4250/6115 SoC platform. Signed-off-by: Iskren Chernev Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210627185927.695411-2-iskren.chernev@gmail.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml index d511f01fcac6..cc3fe5ed7421 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml @@ -39,6 +39,7 @@ properties: - qcom,rpm-msm8996 - qcom,rpm-msm8998 - qcom,rpm-sdm660 + - qcom,rpm-sm6115 - qcom,rpm-sm6125 - qcom,rpm-qcs404 From 49a22c4a7136d257d80b9863093a8e66eeb06baa Mon Sep 17 00:00:00 2001 From: Iskren Chernev Date: Sun, 27 Jun 2021 21:59:26 +0300 Subject: [PATCH 11/20] dt-bindings: power: rpmpd: Add SM6115 to rpmpd binding Add compatible and constants for the power domains exposed by the RPM in the Qualcomm SM4250/6115 platforms. Signed-off-by: Iskren Chernev Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210627185927.695411-5-iskren.chernev@gmail.com Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/power/qcom,rpmpd.yaml | 1 + include/dt-bindings/power/qcom-rpmpd.h | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml index 4807b560f00d..239f37881cae 100644 --- a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml @@ -30,6 +30,7 @@ properties: - qcom,sc8180x-rpmhpd - qcom,sdm845-rpmhpd - qcom,sdx55-rpmhpd + - qcom,sm6115-rpmpd - qcom,sm8150-rpmhpd - qcom,sm8250-rpmhpd - qcom,sm8350-rpmhpd diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h index 8b5708bb9671..4533dbbf9937 100644 --- a/include/dt-bindings/power/qcom-rpmpd.h +++ b/include/dt-bindings/power/qcom-rpmpd.h @@ -192,6 +192,16 @@ #define SDM660_SSCMX 8 #define SDM660_SSCMX_VFL 9 +/* SM6115 Power Domains */ +#define SM6115_VDDCX 0 +#define SM6115_VDDCX_AO 1 +#define SM6115_VDDCX_VFL 2 +#define SM6115_VDDMX 3 +#define SM6115_VDDMX_AO 4 +#define SM6115_VDDMX_VFL 5 +#define SM6115_VDD_LPI_CX 6 +#define SM6115_VDD_LPI_MX 7 + /* RPM SMD Power Domain performance levels */ #define RPM_SMD_LEVEL_RETENTION 16 #define RPM_SMD_LEVEL_RETENTION_PLUS 32 From 18785c94ab6357338cf4aa872aabacbcc7178e83 Mon Sep 17 00:00:00 2001 From: Iskren Chernev Date: Sun, 27 Jun 2021 21:59:27 +0300 Subject: [PATCH 12/20] drivers: soc: qcom: rpmpd: Add SM6115 RPM Power Domains The SM4250/6115 have 4 rpm power domains, ported from downstream DT. Signed-off-by: Iskren Chernev Link: https://lore.kernel.org/r/20210627185927.695411-6-iskren.chernev@gmail.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmpd.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index 0b532a892d60..dbf494e92574 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -346,6 +346,33 @@ static const struct rpmpd_desc sdm660_desc = { .max_state = RPM_SMD_LEVEL_TURBO, }; +/* sm4250/6115 RPM Power domains */ +DEFINE_RPMPD_PAIR(sm6115, vddcx, vddcx_ao, RWCX, LEVEL, 0); +DEFINE_RPMPD_VFL(sm6115, vddcx_vfl, RWCX, 0); + +DEFINE_RPMPD_PAIR(sm6115, vddmx, vddmx_ao, RWMX, LEVEL, 0); +DEFINE_RPMPD_VFL(sm6115, vddmx_vfl, RWMX, 0); + +DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_cx, RWLC, 0); +DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_mx, RWLM, 0); + +static struct rpmpd *sm6115_rpmpds[] = { + [SM6115_VDDCX] = &sm6115_vddcx, + [SM6115_VDDCX_AO] = &sm6115_vddcx_ao, + [SM6115_VDDCX_VFL] = &sm6115_vddcx_vfl, + [SM6115_VDDMX] = &sm6115_vddmx, + [SM6115_VDDMX_AO] = &sm6115_vddmx_ao, + [SM6115_VDDMX_VFL] = &sm6115_vddmx_vfl, + [SM6115_VDD_LPI_CX] = &sm6115_vdd_lpi_cx, + [SM6115_VDD_LPI_MX] = &sm6115_vdd_lpi_mx, +}; + +static const struct rpmpd_desc sm6115_desc = { + .rpmpds = sm6115_rpmpds, + .num_pds = ARRAY_SIZE(sm6115_rpmpds), + .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, +}; + static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc }, { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc }, @@ -356,6 +383,7 @@ static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc }, { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc }, { .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc }, + { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc }, { } }; MODULE_DEVICE_TABLE(of, rpmpd_match_table); From 6feba6a62c577e98bd9214b73c17860166ac8b91 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Fri, 21 May 2021 13:44:53 -0700 Subject: [PATCH 13/20] PM: AVS: qcom-cpr: Use nvmem_cell_read_variable_le_u32() Let's delete the private function cpr_read_efuse() since it does the basically the same thing as the new API call nvmem_cell_read_variable_le_u32(). Differences between the new API call and the old private function: * less error printing (I assume this is OK). * will give an error if the value doesn't fit in 32-bits (the old code would have truncated silently). Reviewed-by: Bjorn Andersson Acked-by: Niklas Cassel Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20210521134437.v2.1.Id1c70158722750aec0673d60c12e46a9c66bbfed@changeid Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/cpr.c | 43 +++++------------------------------------- 1 file changed, 5 insertions(+), 38 deletions(-) diff --git a/drivers/soc/qcom/cpr.c b/drivers/soc/qcom/cpr.c index b24cc77d1889..4ce8e816154f 100644 --- a/drivers/soc/qcom/cpr.c +++ b/drivers/soc/qcom/cpr.c @@ -801,38 +801,6 @@ unlock: return ret; } -static int cpr_read_efuse(struct device *dev, const char *cname, u32 *data) -{ - struct nvmem_cell *cell; - ssize_t len; - char *ret; - int i; - - *data = 0; - - cell = nvmem_cell_get(dev, cname); - if (IS_ERR(cell)) { - if (PTR_ERR(cell) != -EPROBE_DEFER) - dev_err(dev, "undefined cell %s\n", cname); - return PTR_ERR(cell); - } - - ret = nvmem_cell_read(cell, &len); - nvmem_cell_put(cell); - if (IS_ERR(ret)) { - dev_err(dev, "can't read cell %s\n", cname); - return PTR_ERR(ret); - } - - for (i = 0; i < len; i++) - *data |= ret[i] << (8 * i); - - kfree(ret); - dev_dbg(dev, "efuse read(%s) = %x, bytes %zd\n", cname, *data, len); - - return 0; -} - static int cpr_populate_ring_osc_idx(struct cpr_drv *drv) { @@ -843,8 +811,7 @@ cpr_populate_ring_osc_idx(struct cpr_drv *drv) int ret; for (; fuse < end; fuse++, fuses++) { - ret = cpr_read_efuse(drv->dev, fuses->ring_osc, - &data); + ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->ring_osc, &data); if (ret) return ret; fuse->ring_osc_idx = data; @@ -863,7 +830,7 @@ static int cpr_read_fuse_uV(const struct cpr_desc *desc, u32 bits = 0; int ret; - ret = cpr_read_efuse(drv->dev, init_v_efuse, &bits); + ret = nvmem_cell_read_variable_le_u32(drv->dev, init_v_efuse, &bits); if (ret) return ret; @@ -932,7 +899,7 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv) } /* Populate target quotient by scaling */ - ret = cpr_read_efuse(drv->dev, fuses->quotient, &fuse->quot); + ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->quotient, &fuse->quot); if (ret) return ret; @@ -1001,7 +968,7 @@ static int cpr_calculate_scaling(const char *quot_offset, prev_fuse = fuse - 1; if (quot_offset) { - ret = cpr_read_efuse(drv->dev, quot_offset, "_diff); + ret = nvmem_cell_read_variable_le_u32(drv->dev, quot_offset, "_diff); if (ret) return ret; @@ -1701,7 +1668,7 @@ static int cpr_probe(struct platform_device *pdev) * initialized after attaching to the power domain, * since it depends on the CPU's OPP table. */ - ret = cpr_read_efuse(dev, "cpr_fuse_revision", &cpr_rev); + ret = nvmem_cell_read_variable_le_u32(dev, "cpr_fuse_revision", &cpr_rev); if (ret) return ret; From cb531cab62a19e97d8de0a2c9935daed93ec3736 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 25 Jun 2021 10:52:09 +0530 Subject: [PATCH 14/20] soc: qcom: geni: move GENI_IF_DISABLE_RO to common header GENI_IF_DISABLE_RO is used by geni spi driver as well to check the status if GENI, so move this to common header qcom-geni-se.h Reviewed-by: Bjorn Andersson Signed-off-by: Vinod Koul Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/20210625052213.32260-2-vkoul@kernel.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 1 - include/linux/qcom-geni-se.h | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 5bdfb1565c14..fe666ea0c487 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -104,7 +104,6 @@ static const char * const icc_path_names[] = {"qup-core", "qup-config", #define GENI_OUTPUT_CTRL 0x24 #define GENI_CGC_CTRL 0x28 #define GENI_CLK_CTRL_RO 0x60 -#define GENI_IF_DISABLE_RO 0x64 #define GENI_FW_S_REVISION_RO 0x6c #define SE_GENI_BYTE_GRAN 0x254 #define SE_GENI_TX_PACKING_CFG0 0x260 diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h index 7c811eebcaab..5114e2144b17 100644 --- a/include/linux/qcom-geni-se.h +++ b/include/linux/qcom-geni-se.h @@ -63,6 +63,7 @@ struct geni_se { #define SE_GENI_STATUS 0x40 #define GENI_SER_M_CLK_CFG 0x48 #define GENI_SER_S_CLK_CFG 0x4c +#define GENI_IF_DISABLE_RO 0x64 #define GENI_FW_REVISION_RO 0x68 #define SE_GENI_CLK_SEL 0x7c #define SE_GENI_DMA_MODE_EN 0x258 @@ -105,6 +106,9 @@ struct geni_se { #define CLK_DIV_MSK GENMASK(15, 4) #define CLK_DIV_SHFT 4 +/* GENI_IF_DISABLE_RO fields */ +#define FIFO_IF_DISABLE (BIT(0)) + /* GENI_FW_REVISION_RO fields */ #define FW_REV_PROTOCOL_MSK GENMASK(15, 8) #define FW_REV_PROTOCOL_SHFT 8 From 0fa8266294754978da34d7ea785d621f51d939f2 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 25 Jun 2021 10:52:10 +0530 Subject: [PATCH 15/20] soc: qcom: geni: Add support for gpi dma GPI DMA is one of the DMA modes supported on geni, this adds support to enable that mode Also do better documentation of the enum geni_se_xfer_mode. Signed-off-by: Vinod Koul Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/20210625052213.32260-3-vkoul@kernel.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 29 ++++++++++++++++++++++++++++- include/linux/qcom-geni-se.h | 15 ++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index fe666ea0c487..7d649d2cf31e 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -321,6 +321,30 @@ static void geni_se_select_dma_mode(struct geni_se *se) writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); } +static void geni_se_select_gpi_mode(struct geni_se *se) +{ + u32 val; + + geni_se_irq_clear(se); + + writel(0, se->base + SE_IRQ_EN); + + val = readl(se->base + SE_GENI_S_IRQ_EN); + val &= ~S_CMD_DONE_EN; + writel(val, se->base + SE_GENI_S_IRQ_EN); + + val = readl(se->base + SE_GENI_M_IRQ_EN); + val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN | + M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); + writel(val, se->base + SE_GENI_M_IRQ_EN); + + writel(GENI_DMA_MODE_EN, se->base + SE_GENI_DMA_MODE_EN); + + val = readl(se->base + SE_GSI_EVENT_EN); + val |= (DMA_RX_EVENT_EN | DMA_TX_EVENT_EN | GENI_M_EVENT_EN | GENI_S_EVENT_EN); + writel(val, se->base + SE_GSI_EVENT_EN); +} + /** * geni_se_select_mode() - Select the serial engine transfer mode * @se: Pointer to the concerned serial engine. @@ -328,7 +352,7 @@ static void geni_se_select_dma_mode(struct geni_se *se) */ void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode) { - WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA); + WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA && mode != GENI_GPI_DMA); switch (mode) { case GENI_SE_FIFO: @@ -337,6 +361,9 @@ void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode) case GENI_SE_DMA: geni_se_select_dma_mode(se); break; + case GENI_GPI_DMA: + geni_se_select_gpi_mode(se); + break; case GENI_SE_INVALID: default: break; diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h index 5114e2144b17..f5672785c0c4 100644 --- a/include/linux/qcom-geni-se.h +++ b/include/linux/qcom-geni-se.h @@ -8,11 +8,24 @@ #include -/* Transfer mode supported by GENI Serial Engines */ +/** + * enum geni_se_xfer_mode: Transfer modes supported by Serial Engines + * + * @GENI_SE_INVALID: Invalid mode + * @GENI_SE_FIFO: FIFO mode. Data is transferred with SE FIFO + * by programmed IO method + * @GENI_SE_DMA: Serial Engine DMA mode. Data is transferred + * with SE by DMAengine internal to SE + * @GENI_GPI_DMA: GPI DMA mode. Data is transferred using a DMAengine + * configured by a firmware residing on a GSI engine. This DMA name is + * interchangeably used as GSI or GPI which seem to imply the same DMAengine + */ + enum geni_se_xfer_mode { GENI_SE_INVALID, GENI_SE_FIFO, GENI_SE_DMA, + GENI_GPI_DMA, }; /* Protocols supported by GENI Serial Engines */ From 593cb55b4cdd18a2946efd67c29ec4c6081dea8f Mon Sep 17 00:00:00 2001 From: Iskren Chernev Date: Sat, 31 Jul 2021 19:48:27 +0300 Subject: [PATCH 16/20] soc: qcom: smd-rpm: Add SM6115 compatible Add a compatible for SM6115 Signed-off-by: Iskren Chernev Link: https://lore.kernel.org/r/20210731164827.2756798-3-iskren.chernev@gmail.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smd-rpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c index bc0be1d4be5f..dfdd4f20f5fd 100644 --- a/drivers/soc/qcom/smd-rpm.c +++ b/drivers/soc/qcom/smd-rpm.c @@ -242,6 +242,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = { { .compatible = "qcom,rpm-msm8996" }, { .compatible = "qcom,rpm-msm8998" }, { .compatible = "qcom,rpm-sdm660" }, + { .compatible = "qcom,rpm-sm6115" }, { .compatible = "qcom,rpm-sm6125" }, { .compatible = "qcom,rpm-qcs404" }, {} From a95fc720844154acc79064c222335165fe7cb136 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Thu, 8 Apr 2021 16:21:14 +0000 Subject: [PATCH 17/20] dt-bindings: qcom: geni-se: document iommus Document the iommus property for QCOM Geni SE. Signed-off-by: Caleb Connolly Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210408161953.26298-4-caleb@connolly.tech Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml index 4663c2bcad50..a776cd37c297 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml @@ -51,6 +51,9 @@ properties: interconnect-names: const: qup-core + iommus: + maxItems: 1 + required: - compatible - reg From ad68c620b7b296aab9cbe61802e329c04fde8385 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 15 Mar 2021 09:44:55 -0500 Subject: [PATCH 18/20] soc: qcom: mdt_loader: be more informative on errors In __qcom_mdt_load() there are cases where an error occurs that cause a message to be printed. In some of those cases the errno value can be helpful to understand exactly what caused the problem. Print the errno (as well as the firmware file name) where it is helpful, and in a few cases reword the error message. Consistently use the private fw_name for the file name. Signed-off-by: Alex Elder Link: https://lore.kernel.org/r/20210315144455.1770492-1-elder@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/mdt_loader.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index eba7f76f9d61..bda170d7b4a2 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -166,6 +166,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, metadata = qcom_mdt_read_metadata(fw, &metadata_len); if (IS_ERR(metadata)) { ret = PTR_ERR(metadata); + dev_err(dev, "error %d reading firmware %s metadata\n", + ret, fw_name); goto out; } @@ -173,7 +175,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, kfree(metadata); if (ret) { - dev_err(dev, "invalid firmware metadata\n"); + /* Invalid firmware metadata */ + dev_err(dev, "error %d initializing firmware %s\n", + ret, fw_name); goto out; } } @@ -199,7 +203,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); if (ret) { - dev_err(dev, "unable to setup relocation\n"); + /* Unable to set up relocation */ + dev_err(dev, "error %d setting up firmware %s\n", + ret, fw_name); goto out; } } @@ -243,9 +249,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, if (phdr->p_filesz && phdr->p_offset < fw->size) { /* Firmware is large enough to be non-split */ if (phdr->p_offset + phdr->p_filesz > fw->size) { - dev_err(dev, - "failed to load segment %d from truncated file %s\n", - i, firmware); + dev_err(dev, "file %s segment %d would be truncated\n", + fw_name, i); ret = -EINVAL; break; } @@ -257,7 +262,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, ret = request_firmware_into_buf(&seg_fw, fw_name, dev, ptr, phdr->p_filesz); if (ret) { - dev_err(dev, "failed to load %s\n", fw_name); + dev_err(dev, "error %d loading %s\n", + ret, fw_name); break; } From c73a6852b42c8c80cc46590dbbcfa6c448fdbc63 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 12 Jul 2021 15:57:02 +0200 Subject: [PATCH 19/20] soc: qcom: smsm: Implement support for get_irqchip_state At the moment there is no way for drivers to get the current state of the interrupt signal reported by a remote processor. The irqchip API has generic functionality for this, using irq_get_irqchip_state(). Implement support for getting the IRQCHIP_STATE_LINE_LEVEL by reading the remote state and checking the bit for the specified IRQ. Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20210712135703.324748-1-stephan@gerhold.net Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smsm.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c index 1d3d5e3ec2b0..a48f9db98836 100644 --- a/drivers/soc/qcom/smsm.c +++ b/drivers/soc/qcom/smsm.c @@ -299,11 +299,28 @@ static int smsm_set_irq_type(struct irq_data *irqd, unsigned int type) return 0; } +static int smsm_get_irqchip_state(struct irq_data *irqd, + enum irqchip_irq_state which, bool *state) +{ + struct smsm_entry *entry = irq_data_get_irq_chip_data(irqd); + irq_hw_number_t irq = irqd_to_hwirq(irqd); + u32 val; + + if (which != IRQCHIP_STATE_LINE_LEVEL) + return -EINVAL; + + val = readl(entry->remote_state); + *state = !!(val & BIT(irq)); + + return 0; +} + static struct irq_chip smsm_irq_chip = { .name = "smsm", .irq_mask = smsm_mask_irq, .irq_unmask = smsm_unmask_irq, .irq_set_type = smsm_set_irq_type, + .irq_get_irqchip_state = smsm_get_irqchip_state, }; /** From e3d4571955050736bbf3eda0a9538a09d9fcfce8 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 12 Jul 2021 15:57:03 +0200 Subject: [PATCH 20/20] soc: qcom: smsm: Fix missed interrupts if state changes while masked The SMSM driver detects interrupt edges by tracking the last state it has seen (and has triggered the interrupt handler for). This works fine, but only if the interrupt does not change state while masked. For example, if an interrupt is unmasked while the state is HIGH, the stored last_value for that interrupt might still be LOW. Then, when the remote processor triggers smsm_intr() we assume that nothing has changed, even though the state might have changed from HIGH to LOW. Attempt to fix this by checking the current remote state before unmasking an IRQ. Use atomic operations to avoid the interrupt handler from interfering with the unmask function. This fixes modem crashes in some edge cases with the BAM-DMUX driver. Specifically, the BAM-DMUX interrupt handler is not called for the HIGH -> LOW smsm state transition if the BAM-DMUX driver is loaded (and therefore unmasks the interrupt) after the modem was already started: qcom-q6v5-mss 4080000.remoteproc: fatal error received: a2_task.c:3188: Assert FALSE failed: A2 DL PER deadlock timer expired waiting for Apps ACK Fixes: c97c4090ff72 ("soc: qcom: smsm: Add driver for Qualcomm SMSM") Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20210712135703.324748-2-stephan@gerhold.net Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smsm.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c index a48f9db98836..ef15d014c03a 100644 --- a/drivers/soc/qcom/smsm.c +++ b/drivers/soc/qcom/smsm.c @@ -109,7 +109,7 @@ struct smsm_entry { DECLARE_BITMAP(irq_enabled, 32); DECLARE_BITMAP(irq_rising, 32); DECLARE_BITMAP(irq_falling, 32); - u32 last_value; + unsigned long last_value; u32 *remote_state; u32 *subscription; @@ -204,8 +204,7 @@ static irqreturn_t smsm_intr(int irq, void *data) u32 val; val = readl(entry->remote_state); - changed = val ^ entry->last_value; - entry->last_value = val; + changed = val ^ xchg(&entry->last_value, val); for_each_set_bit(i, entry->irq_enabled, 32) { if (!(changed & BIT(i))) @@ -264,6 +263,12 @@ static void smsm_unmask_irq(struct irq_data *irqd) struct qcom_smsm *smsm = entry->smsm; u32 val; + /* Make sure our last cached state is up-to-date */ + if (readl(entry->remote_state) & BIT(irq)) + set_bit(irq, &entry->last_value); + else + clear_bit(irq, &entry->last_value); + set_bit(irq, entry->irq_enabled); if (entry->subscription) {