From 1eeed9b4e31525fcaa3b16365aa32c5d0ecb5010 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Mon, 3 Mar 2025 13:08:31 -0800 Subject: [PATCH 001/113] FROMLIST: firmware: psci: Read and use vendor reset types SoC vendors have different types of resets and are controlled through various registers. For instance, Qualcomm chipsets can reboot to a "download mode" that allows a RAM dump to be collected. Another example is they also support writing a cookie that can be read by bootloader during next boot. PSCI offers a mechanism, SYSTEM_RESET2, for these vendor reset types to be implemented without requiring drivers for every register/cookie. Add support in PSCI to statically map reboot mode commands from userspace to a vendor reset and cookie value using the device tree. A separate initcall is needed to parse the devicetree, instead of using psci_dt_init because mm isn't sufficiently set up to allocate memory. Reboot mode framework is close but doesn't quite fit with the design and requirements for PSCI SYSTEM_RESET2. Some of these issues can be solved but doesn't seem reasonable in sum: 1. reboot mode registers against the reboot_notifier_list, which is too early to call SYSTEM_RESET2. PSCI would need to remember the reset type from the reboot-mode framework callback and use it psci_sys_reset. 2. reboot mode assumes only one cookie/parameter is described in the device tree. SYSTEM_RESET2 uses 2: one for the type and one for cookie. 3. psci cpuidle driver already registers a driver against the arm,psci-1.0 compatible. Refactoring would be needed to have both a cpuidle and reboot-mode driver. Link: https://lore.kernel.org/r/20250303-arm-psci-system_reset2-vendor-reboots-v9-2-b2cf4a20feda@oss.qualcomm.com Signed-off-by: Elliot Berman Reviewed-by: Florian Fainelli Tested-by: Florian Fainelli --- drivers/firmware/psci/psci.c | 105 +++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index a1ebbe9b73b13..6f8c47deaec02 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -80,6 +80,14 @@ static u32 psci_cpu_suspend_feature; static bool psci_system_reset2_supported; static bool psci_system_off2_hibernate_supported; +struct psci_reset_param { + const char *mode; + u32 reset_type; + u32 cookie; +}; +static struct psci_reset_param *psci_reset_params __ro_after_init; +static size_t num_psci_reset_params __ro_after_init; + static inline bool psci_has_ext_power_state(void) { return psci_cpu_suspend_feature & @@ -306,9 +314,39 @@ static int get_set_conduit_method(const struct device_node *np) return 0; } +static int psci_vendor_system_reset2(const char *cmd) +{ + unsigned long ret; + size_t i; + + for (i = 0; i < num_psci_reset_params; i++) { + if (!strcmp(psci_reset_params[i].mode, cmd)) { + ret = invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), + psci_reset_params[i].reset_type, + psci_reset_params[i].cookie, 0); + /* + * if vendor reset fails, log it and fall back to + * architecture reset types + */ + pr_err("failed to perform reset \"%s\": %ld\n", cmd, + (long)ret); + return 0; + } + } + + return -ENOENT; +} + static int psci_sys_reset(struct notifier_block *nb, unsigned long action, void *data) { + /* + * try to do the vendor system_reset2 + * If there wasn't a matching command, fall back to architectural resets + */ + if (data && !psci_vendor_system_reset2(data)) + return NOTIFY_DONE; + if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) && psci_system_reset2_supported) { /* @@ -795,6 +833,73 @@ static const struct of_device_id psci_of_match[] __initconst = { {}, }; +#define REBOOT_PREFIX "mode-" + +static int __init psci_init_system_reset2_modes(void) +{ + const size_t len = strlen(REBOOT_PREFIX); + struct psci_reset_param *param; + struct device_node *psci_np __free(device_node) = NULL; + struct device_node *np __free(device_node) = NULL; + struct property *prop; + size_t count = 0; + u32 magic[2]; + int num; + + if (!psci_system_reset2_supported) + return 0; + + psci_np = of_find_matching_node(NULL, psci_of_match); + if (!psci_np) + return 0; + + np = of_find_node_by_name(psci_np, "reset-types"); + if (!np) + return 0; + + for_each_property_of_node(np, prop) { + if (strncmp(prop->name, REBOOT_PREFIX, len)) + continue; + num = of_property_count_u32_elems(np, prop->name); + if (num != 1 && num != 2) + continue; + + count++; + } + + param = psci_reset_params = + kcalloc(count, sizeof(*psci_reset_params), GFP_KERNEL); + if (!psci_reset_params) + return -ENOMEM; + + for_each_property_of_node(np, prop) { + if (strncmp(prop->name, REBOOT_PREFIX, len)) + continue; + + num = of_property_read_variable_u32_array(np, prop->name, magic, + 1, ARRAY_SIZE(magic)); + if (num < 0) { + pr_warn("Failed to parse vendor reboot mode %s\n", + param->mode); + kfree_const(param->mode); + continue; + } + + param->mode = kstrdup_const(prop->name + len, GFP_KERNEL); + if (!param->mode) + continue; + + /* Force reset type to be in vendor space */ + param->reset_type = PSCI_1_1_RESET_TYPE_VENDOR_START | magic[0]; + param->cookie = num > 1 ? magic[1] : 0; + param++; + num_psci_reset_params++; + } + + return 0; +} +arch_initcall(psci_init_system_reset2_modes); + int __init psci_dt_init(void) { struct device_node *np; From 757e96fc3456bbaffd2755212d3c02886e90674f Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Mon, 3 Mar 2025 13:08:30 -0800 Subject: [PATCH 002/113] FROMLIST: dt-bindings: arm: Document reboot mode magic Add bindings to describe vendor-specific reboot modes. Values here correspond to valid parameters to vendor-specific reset types in PSCI SYSTEM_RESET2 call. Link: https://lore.kernel.org/r/20250303-arm-psci-system_reset2-vendor-reboots-v9-1-b2cf4a20feda@oss.qualcomm.com Reviewed-by: Rob Herring (Arm) Signed-off-by: Elliot Berman --- .../devicetree/bindings/arm/psci.yaml | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/psci.yaml b/Documentation/devicetree/bindings/arm/psci.yaml index 7360a2849b5bd..3ed573e5eb48f 100644 --- a/Documentation/devicetree/bindings/arm/psci.yaml +++ b/Documentation/devicetree/bindings/arm/psci.yaml @@ -98,6 +98,27 @@ properties: [1] Kernel documentation - ARM idle states bindings Documentation/devicetree/bindings/cpu/idle-states.yaml + reset-types: + type: object + $ref: /schemas/power/reset/reboot-mode.yaml# + unevaluatedProperties: false + properties: + # "mode-normal" is just SYSTEM_RESET + mode-normal: false + patternProperties: + "^mode-.*$": + minItems: 1 + maxItems: 2 + description: | + Describes a vendor-specific reset type. The string after "mode-" + maps a reboot mode to the parameters in the PSCI SYSTEM_RESET2 call. + + Parameters are named mode-xxx = , where xxx + is the name of the magic reboot mode, type is the lower 31 bits + of the reset_type, and, optionally, the cookie value. If the cookie + is not provided, it is defaulted to zero. + The 31st bit (vendor-resets) will be implicitly set by the driver. + patternProperties: "^power-domain-": $ref: /schemas/power/power-domain.yaml# @@ -137,6 +158,15 @@ allOf: required: - cpu_off - cpu_on + - if: + not: + properties: + compatible: + contains: + const: arm,psci-1.0 + then: + properties: + reset-types: false additionalProperties: false @@ -261,4 +291,17 @@ examples: domain-idle-states = <&cluster_ret>, <&cluster_pwrdn>; }; }; + + - |+ + + // Case 5: SYSTEM_RESET2 vendor resets + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + + reset-types { + mode-edl = <0>; + mode-bootloader = <1 2>; + }; + }; ... From a1b6bab311b8f820670dd875da618fa3cb96db5d Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Mon, 3 Mar 2025 13:08:32 -0800 Subject: [PATCH 003/113] FROMLSIT: arm64: dts: qcom: qcm6490-idp: Add PSCI SYSTEM_RESET2 types qcm6490-idp firmware supports vendor-defined SYSTEM_RESET2 types. Describe the reset types: "bootloader" will cause device to reboot and stop in the bootloader's fastboot mode. "edl" will cause device to reboot into "emergency download mode", which permits loading images via the Firehose protocol. Link: https://lore.kernel.org/r/20250303-arm-psci-system_reset2-vendor-reboots-v9-3-b2cf4a20feda@oss.qualcomm.com Co-developed-by: Shivendra Pratap Signed-off-by: Shivendra Pratap Reviewed-by: Konrad Dybcio Signed-off-by: Elliot Berman --- arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 7 +++++++ arch/arm64/boot/dts/qcom/sc7280.dtsi | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index 7a155ef6492e1..6de4b140ed10b 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -654,6 +654,13 @@ status = "okay"; }; +&psci { + reset-types { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; +}; + &qupv3_id_0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi index b1cc3bc1aec8b..8ac9ee12936f4 100644 --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi @@ -857,7 +857,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; From e2df32bfd1e925228ac299c2d15496ebee82109e Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Mon, 3 Mar 2025 13:08:33 -0800 Subject: [PATCH 004/113] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Add PSCI SYSTEM_RESET2 types qcs6490-rb3gen2 firmware supports vendor-defined SYSTEM_RESET2 types. Describe the reset types: "bootloader" will cause device to reboot and stop in the bootloader's fastboot mode. "edl" will cause device to reboot into "emergency download mode", which permits loading images via the Firehose protocol. Link: https://lore.kernel.org/r/20250303-arm-psci-system_reset2-vendor-reboots-v9-4-b2cf4a20feda@oss.qualcomm.com Reviewed-by: Konrad Dybcio Signed-off-by: Elliot Berman --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 5fbcd48f2e2d8..7c06fe496e800 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -966,6 +966,13 @@ status = "okay"; }; +&psci { + reset-types { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; +}; + &qup_uart7_cts { /* * Configure a bias-bus-hold on CTS to lower power From 09c3a47292488ba68863ef72b1f1953ad1621a94 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 27 May 2025 16:42:20 +0530 Subject: [PATCH 005/113] FROMLIST: arm64: dts: qcom: qcs6490-audioreach: Add gpr node Add GPR(Generic Pack router) node along with APM(Audio Process Manager) and PRM(Proxy resource Manager) audio services. Co-developed-by: Prasad Kumpatla Signed-off-by: Prasad Kumpatla Link: https://lore.kernel.org/linux-arm-msm/20250527111227.2318021-2-quic_pkumpatl@quicinc.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Mohammad Rafi Shaik --- .../boot/dts/qcom/qcs6490-audioreach.dtsi | 53 +++++++++++++++++++ arch/arm64/boot/dts/qcom/sc7280.dtsi | 2 +- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi diff --git a/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi new file mode 100644 index 0000000000000..29d4a6a2db260 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * qcs6490 device tree source for Audioreach Solution. + * This file will handle the common audio device tree nodes. + * + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include + +&remoteproc_adsp_glink { + /delete-node/ apr; + + gpr { + compatible = "qcom,gpr"; + qcom,glink-channels = "adsp_apps"; + qcom,domain = ; + qcom,intents = <512 20>; + #address-cells = <1>; + #size-cells = <0>; + + q6apm: service@1 { + compatible = "qcom,q6apm"; + reg = ; + #sound-dai-cells = <0>; + qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd"; + + q6apmdai: dais { + compatible = "qcom,q6apm-dais"; + iommus = <&apps_smmu 0x1801 0x0>; + }; + + q6apmbedai: bedais { + compatible = "qcom,q6apm-lpass-dais"; + #sound-dai-cells = <1>; + }; + }; + + q6prm: service@2 { + compatible = "qcom,q6prm"; + reg = ; + qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd"; + + q6prmcc: clock-controller { + compatible = "qcom,q6prm-lpass-clocks"; + #clock-cells = <2>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi index 8ac9ee12936f4..c65ee4e78916a 100644 --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi @@ -3814,7 +3814,7 @@ status = "disabled"; - glink-edge { + remoteproc_adsp_glink: glink-edge { interrupts-extended = <&ipcc IPCC_CLIENT_LPASS IPCC_MPROC_SIGNAL_GLINK_QMP IRQ_TYPE_EDGE_RISING>; From a78d9c3baf45273bffea926e825fc326e272b519 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 27 May 2025 16:42:21 +0530 Subject: [PATCH 006/113] FROMLIST: ASoC: dt-bindings: qcom: Manage clock settings for ADSP solution Manage clock settings for ADSP solution and document the clock properties on sc7280 lpass pincontrol node which is required for ADSP based solution. Co-developed-by: Prasad Kumpatla Signed-off-by: Prasad Kumpatla Link: https://lore.kernel.org/linux-arm-msm/20250527111227.2318021-3-quic_pkumpatl@quicinc.com/ Signed-off-by: Mohammad Rafi Shaik --- .../qcom,sc7280-lpass-lpi-pinctrl.yaml | 10 ++++++++ .../bindings/sound/qcom,lpass-va-macro.yaml | 12 +++++++--- .../bindings/sound/qcom,lpass-wsa-macro.yaml | 24 ++++++++++++++++--- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml index 08801cc4e476f..b1270124bfe38 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml @@ -20,6 +20,16 @@ properties: reg: maxItems: 2 + clocks: + items: + - description: LPASS Core voting clock + - description: LPASS Audio voting clock + + clock-names: + items: + - const: core + - const: audio + patternProperties: "-state$": oneOf: diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml index f41deaa6f4df5..92b97c2140606 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml @@ -78,10 +78,16 @@ allOf: then: properties: clocks: - maxItems: 1 + minItems: 1 + maxItems: 3 clock-names: - items: - - const: mclk + oneOf: + - items: # for ADSP based platforms + - const: mclk + - const: macro + - const: dcodec + - items: # for ADSP bypass based platforms + - const: mclk - if: properties: diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml index 9082e363c7094..6a999ed484e7b 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml @@ -35,11 +35,11 @@ properties: const: 0 clocks: - minItems: 4 + minItems: 3 maxItems: 6 clock-names: - minItems: 4 + minItems: 3 maxItems: 6 clock-output-names: @@ -59,12 +59,30 @@ required: allOf: - $ref: dai-common.yaml# - - if: properties: compatible: enum: - qcom,sc7280-lpass-wsa-macro + then: + properties: + clock-names: + oneOf: + - items: # for ADSP based platforms + - const: mclk + - const: npl + - const: macro + - const: dcodec + - const: fsgen + - items: # for ADSP bypass based platforms + - const: mclk + - const: npl + - const: fsgen + + - if: + properties: + compatible: + enum: - qcom,sm8250-lpass-wsa-macro - qcom,sm8450-lpass-wsa-macro - qcom,sc8280xp-lpass-wsa-macro From 5b9500acb93884485efdc468c62dbfc895ef616b Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 27 May 2025 16:42:22 +0530 Subject: [PATCH 007/113] FROMLIST: arm64: dts: qcom: sc7280: Add WSA SoundWire and LPASS support Add WSA LPASS macro Codec along with SoundWire controller. Co-developed-by: Prasad Kumpatla Signed-off-by: Prasad Kumpatla Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/linux-arm-msm/20250527111227.2318021-4-quic_pkumpatl@quicinc.com/ Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/boot/dts/qcom/sc7280.dtsi | 76 ++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi index c65ee4e78916a..685e9cd27d8f7 100644 --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi @@ -2636,6 +2636,66 @@ status = "disabled"; }; + lpass_wsa_macro: codec@3240000 { + compatible = "qcom,sc7280-lpass-wsa-macro"; + reg = <0x0 0x03240000 0x0 0x1000>; + + clocks = <&lpass_aon LPASS_AON_CC_TX_MCLK_CLK>, + <&lpass_aon LPASS_AON_CC_TX_MCLK_2X_CLK>, + <&lpass_va_macro>; + clock-names = "mclk", + "npl", + "fsgen"; + + pinctrl-0 = <&lpass_wsa_swr_clk>, <&lpass_wsa_swr_data>; + pinctrl-names = "default"; + + power-domains = <&lpass_hm LPASS_CORE_CC_LPASS_CORE_HM_GDSC>, + <&lpass_aon LPASS_AON_CC_LPASS_AUDIO_HM_GDSC>; + power-domain-names = "macro", "dcodec"; + + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + + status = "disabled"; + }; + + swr2: soundwire@3250000 { + compatible = "qcom,soundwire-v1.6.0"; + reg = <0x0 0x03250000 0x0 0x2000>; + + interrupts = ; + clocks = <&lpass_wsa_macro>; + clock-names = "iface"; + + resets = <&lpass_audiocc LPASS_AUDIO_SWR_WSA_CGCR>; + reset-names = "swr_audio_cgcr"; + + qcom,din-ports = <2>; + qcom,dout-ports = <6>; + + qcom,ports-sinterval-low = /bits/ 8 <0x07 0x1f 0x3f 0x07 + 0x1f 0x3f 0x0f 0x0f>; + qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x0c 0x06 0x12 0x0d 0x07 0x0a>; + qcom,ports-offset2 = /bits/ 8 <0xff 0x00 0x1f 0xff 0x00 0x1f 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0x01 0xff 0xff 0x01 + 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff>; + qcom,ports-lane-control = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff>; + + #address-cells = <2>; + #size-cells = <0>; + #sound-dai-cells = <1>; + + status = "disabled"; + }; + lpass_audiocc: clock-controller@3300000 { compatible = "qcom,sc7280-lpassaudiocc"; reg = <0 0x03300000 0 0x30000>, @@ -2839,6 +2899,22 @@ pins = "gpio1", "gpio2", "gpio14"; function = "swr_tx_data"; }; + + lpass_wsa_swr_clk: wsa-swr-clk-state { + pins = "gpio10"; + function = "wsa_swr_clk"; + drive-strength = <2>; + slew-rate = <1>; + bias-disable; + }; + + lpass_wsa_swr_data: wsa-swr-data-state { + pins = "gpio11"; + function = "wsa_swr_data"; + drive-strength = <2>; + slew-rate = <1>; + bias-bus-hold; + }; }; gpu: gpu@3d00000 { From 8587f2a21e611b23931d3affa928d5dcf17ce76c Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 27 May 2025 16:42:23 +0530 Subject: [PATCH 008/113] FROMLIST: arm64: dts: qcom: qcs6490-audioreach: Modify LPASS macros clock settings for audioreach Modify and enable WSA, VA, RX and TX lpass macros and lpass_tlmm clock settings. For audioreach solution mclk, npl and fsgen clocks are enabled through the q6prm clock driver. For qcs6490 RX drives clk from TX CORE which is mandated from DSP side, Unlike dedicated core clocks. Core TX clk is used for both RX and WSA as per DSP recommendations. Co-developed-by: Prasad Kumpatla Signed-off-by: Prasad Kumpatla Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/linux-arm-msm/20250527111227.2318021-5-quic_pkumpatl@quicinc.com/ Signed-off-by: Mohammad Rafi Shaik --- .../boot/dts/qcom/qcs6490-audioreach.dtsi | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi index 29d4a6a2db260..4111091f77b25 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi @@ -11,6 +11,69 @@ #include #include +&lpass_rx_macro { + /delete-property/ power-domains; + /delete-property/ power-domain-names; + clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&lpass_va_macro>; + clock-names = "mclk", + "npl", + "macro", + "dcodec", + "fsgen"; +}; + +&lpass_tlmm { + clocks = <&q6prmcc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "core", + "audio"; +}; + +&lpass_tx_macro { + /delete-property/ power-domains; + /delete-property/ power-domain-names; + clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&lpass_va_macro>; + clock-names = "mclk", + "npl", + "macro", + "dcodec", + "fsgen"; +}; + +&lpass_va_macro { + /delete-property/ power-domains; + /delete-property/ power-domain-names; + clocks = <&q6prmcc LPASS_CLK_ID_VA_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk", + "macro", + "dcodec"; +}; + +&lpass_wsa_macro { + /delete-property/ power-domains; + /delete-property/ power-domain-names; + clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&lpass_va_macro>; + clock-names = "mclk", + "npl", + "macro", + "dcodec", + "fsgen"; +}; + &remoteproc_adsp_glink { /delete-node/ apr; From 7639c222b10f6c098a561c7bc0e9a4d77d211253 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 27 May 2025 16:42:24 +0530 Subject: [PATCH 009/113] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Add WSA8830 speakers amplifier Add nodes for WSA8830 speakers amplifier on qcs6490-rb3gen2 board. Enable lpass_wsa and lpass_va macros along with pinctrl settings for audio. Co-developed-by: Prasad Kumpatla Signed-off-by: Prasad Kumpatla Link: https://lore.kernel.org/linux-arm-msm/20250527111227.2318021-6-quic_pkumpatl@quicinc.com/ Signed-off-by: Mohammad Rafi Shaik --- .../boot/dts/qcom/qcs6490-audioreach.dtsi | 18 ++++++++++ arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 35 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi index 4111091f77b25..542a39ca72bbe 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi @@ -11,6 +11,24 @@ #include #include +&lpass_dmic01_clk { + drive-strength = <8>; + bias-disable; +}; + +&lpass_dmic01_data { + bias-pull-down; +}; + +&lpass_dmic23_clk { + drive-strength = <8>; + bias-disable; +}; + +&lpass_dmic23_data { + bias-pull-down; +}; + &lpass_rx_macro { /delete-property/ power-domains; /delete-property/ power-domain-names; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 7c06fe496e800..86788da450e8f 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -19,6 +19,7 @@ #include "pm7325.dtsi" #include "pm8350c.dtsi" #include "pmk8350.dtsi" +#include "qcs6490-audioreach.dtsi" /delete-node/ &ipa_fw_mem; /delete-node/ &rmtfs_mem; @@ -765,6 +766,14 @@ }; }; +&lpass_va_macro { + status = "okay"; +}; + +&lpass_wsa_macro { + status = "okay"; +}; + &mdss { status = "okay"; }; @@ -1046,6 +1055,32 @@ status = "okay"; }; +&swr2 { + status = "okay"; + + left_spkr: speaker@0,1 { + compatible = "sdw10217020200"; + reg = <0 1>; + powerdown-gpios = <&tlmm 158 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrLeft"; + #thermal-sensor-cells = <0>; + vdd-supply = <&vreg_l18b_1p8>; + qcom,port-mapping = <1 2 3 7>; + }; + + right_spkr: speaker@0,2 { + compatible = "sdw10217020200"; + reg = <0 2>; + powerdown-gpios = <&tlmm 158 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrRight"; + #thermal-sensor-cells = <0>; + vdd-supply = <&vreg_l18b_1p8>; + qcom,port-mapping = <4 5 6 8>; + }; +}; + &tlmm { gpio-reserved-ranges = <32 2>, /* ADSP */ <48 4>; /* NFC */ From 24bba55b473600a52ceed08f76a2175606d4f6dc Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 27 May 2025 16:42:25 +0530 Subject: [PATCH 010/113] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Add sound card Add the sound card node with tested playback over WSA8835 speakers and digital on-board mics. Co-developed-by: Prasad Kumpatla Signed-off-by: Prasad Kumpatla Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/linux-arm-msm/20250527111227.2318021-7-quic_pkumpatl@quicinc.com/ Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 45 ++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 86788da450e8f..0da3525979c0b 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -1055,6 +1055,51 @@ status = "okay"; }; +&sound { + compatible = "qcom,qcs6490-rb3gen2-sndcard"; + model = "qcs6490-rb3gen2-snd-card"; + + audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT", + "SpkrRight IN", "WSA_SPK2 OUT", + "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb"; + + wsa-dai-link { + link-name = "WSA Playback"; + + codec { + sound-dai = <&left_spkr>, <&right_spkr>, + <&swr2 0>, <&lpass_wsa_macro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai WSA_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + va-dai-link { + link-name = "VA Capture"; + + codec { + sound-dai = <&lpass_va_macro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; +}; + &swr2 { status = "okay"; From 2ecf060874e953501c19ce20b0a316d981bbe6cf Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 27 May 2025 16:42:26 +0530 Subject: [PATCH 011/113] FROMLIST: arm64: dts: qcom: qcm6490-idp: Add WSA8830 speakers and WCD9370 headset codec Add nodes for WSA8830 speakers and WCD9370 headset codec on qcm6490-idp board. Enable lpass macros along with audio support pin controls. Co-developed-by: Prasad Kumpatla Signed-off-by: Prasad Kumpatla Link: https://lore.kernel.org/linux-arm-msm/20250527111227.2318021-8-quic_pkumpatl@quicinc.com/ Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 96 +++++++++++++++++++ .../boot/dts/qcom/qcs6490-audioreach.dtsi | 24 +++++ 2 files changed, 120 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index 6de4b140ed10b..f49a32e56135d 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -18,6 +18,7 @@ #include "pm7325.dtsi" #include "pm8350c.dtsi" #include "pmk8350.dtsi" +#include "qcs6490-audioreach.dtsi" /delete-node/ &ipa_fw_mem; /delete-node/ &rmtfs_mem; @@ -169,6 +170,30 @@ regulator-min-microvolt = <3700000>; regulator-max-microvolt = <3700000>; }; + + wcd9370: audio-codec-0 { + compatible = "qcom,wcd9370-codec"; + + pinctrl-0 = <&wcd_default>; + pinctrl-names = "default"; + + reset-gpios = <&tlmm 83 GPIO_ACTIVE_HIGH>; + + vdd-buck-supply = <&vreg_l17b_1p7>; + vdd-rxtx-supply = <&vreg_l18b_1p8>; + vdd-px-supply = <&vreg_l18b_1p8>; + vdd-mic-bias-supply = <&vreg_bob_3p296>; + + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + qcom,micbias4-microvolt = <1800000>; + + qcom,rx-device = <&wcd937x_rx>; + qcom,tx-device = <&wcd937x_tx>; + + #sound-dai-cells = <1>; + }; }; &apps_rsc { @@ -536,6 +561,22 @@ firmware-name = "qcom/qcm6490/a660_zap.mbn"; }; +&lpass_rx_macro { + status = "okay"; +}; + +&lpass_tx_macro { + status = "okay"; +}; + +&lpass_va_macro { + status = "okay"; +}; + +&lpass_wsa_macro { + status = "okay"; +}; + &mdss { status = "okay"; }; @@ -723,6 +764,54 @@ cd-gpios = <&tlmm 91 GPIO_ACTIVE_LOW>; }; +&swr0 { + status = "okay"; + + wcd937x_rx: codec@0,4 { + compatible = "sdw20217010a00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5>; + qcom,rx-channel-mapping = /bits/ 8 <1 2 1 1 2 1 1 2>; + }; +}; + +&swr1 { + status = "okay"; + + wcd937x_tx: codec@0,3 { + compatible = "sdw20217010a00"; + reg = <0 3>; + qcom,tx-port-mapping = <1 1 2 3>; + qcom,tx-channel-mapping = /bits/ 8 <1 2 1 1 2 3 3 4 1 2 3 4>; + }; +}; + +&swr2 { + status = "okay"; + + left_spkr: speaker@0,1 { + compatible = "sdw10217020200"; + reg = <0 1>; + powerdown-gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrLeft"; + #thermal-sensor-cells = <0>; + vdd-supply = <&vreg_l18b_1p8>; + qcom,port-mapping = <1 2 3 7>; + }; + + right_spkr: speaker@0,2 { + compatible = "sdw10217020200"; + reg = <0 2>; + powerdown-gpios = <&tlmm 62 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrRight"; + #thermal-sensor-cells = <0>; + vdd-supply = <&vreg_l18b_1p8>; + qcom,port-mapping = <4 5 6 8>; + }; +}; + &tlmm { gpio-reserved-ranges = <32 2>, /* ADSP */ <48 4>; /* NFC */ @@ -732,6 +821,13 @@ function = "gpio"; bias-pull-up; }; + + wcd_default: wcd-reset-n-active-state { + pins = "gpio83"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; }; &uart5 { diff --git a/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi index 542a39ca72bbe..2e75e7706fb4f 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-audioreach.dtsi @@ -29,6 +29,30 @@ bias-pull-down; }; +&lpass_rx_swr_clk { + drive-strength = <2>; + slew-rate = <1>; + bias-disable; +}; + +&lpass_rx_swr_data { + drive-strength = <2>; + slew-rate = <1>; + bias-bus-hold; +}; + +&lpass_tx_swr_clk { + drive-strength = <2>; + slew-rate = <1>; + bias-disable; +}; + +&lpass_tx_swr_data { + drive-strength = <2>; + slew-rate = <1>; + bias-bus-hold; +}; + &lpass_rx_macro { /delete-property/ power-domains; /delete-property/ power-domain-names; From e9c1cced62d4d2a64bdc5b56329d3741733d53d1 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 27 May 2025 16:42:27 +0530 Subject: [PATCH 012/113] FROMLIST: arm64: dts: qcom: qcm6490-idp: Add sound card Add the sound card node with tested playback over WSA8835 speakers, digital on-board mics along with wcd9370 headset playabck and record. Co-developed-by: Prasad Kumpatla Signed-off-by: Prasad Kumpatla Link: https://lore.kernel.org/linux-arm-msm/20250527111227.2318021-9-quic_pkumpatl@quicinc.com/ Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 84 ++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index f49a32e56135d..923f90ca38d75 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -764,6 +764,90 @@ cd-gpios = <&tlmm 91 GPIO_ACTIVE_LOW>; }; +&sound { + compatible = "qcom,qcm6490-idp-sndcard"; + model = "qcm6490-idp-snd-card"; + + audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT", + "SpkrRight IN", "WSA_SPK2 OUT", + "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2", + "TX DMIC0", "MIC BIAS1", + "TX DMIC1", "MIC BIAS2", + "TX DMIC2", "MIC BIAS3", + "TX SWR_ADC1", "ADC2_OUTPUT", + "VA DMIC0", "VA MIC BIAS3", + "VA DMIC1", "VA MIC BIAS3", + "VA DMIC2", "VA MIC BIAS1", + "VA DMIC3", "VA MIC BIAS1"; + + wsa-dai-link { + link-name = "WSA Playback"; + + codec { + sound-dai = <&left_spkr>, <&right_spkr>, + <&swr2 0>, <&lpass_wsa_macro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai WSA_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-playback-dai-link { + link-name = "WCD Playback"; + + codec { + sound-dai = <&wcd9370 0>, <&swr0 0>, <&lpass_rx_macro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-capture-dai-link { + link-name = "WCD Capture"; + + codec { + sound-dai = <&wcd9370 1>, <&swr1 0>, <&lpass_tx_macro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + va-dai-link { + link-name = "VA Capture"; + + codec { + sound-dai = <&lpass_va_macro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; +}; + &swr0 { status = "okay"; From 6fd9d89cdb524d3b61251b6eb46269131eb9bd3d Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:47 +0530 Subject: [PATCH 013/113] FROMLIST: media: iris: Skip destroying internal buffer if not dequeued Firmware might hold the DPB buffers for reference in case of sequence change, so skip destroying buffers for which QUEUED flag is not removed. Cc: stable@vger.kernel.org Fixes: 73702f45db81 ("media: iris: allocate, initialize and queue internal buffers") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-1-59b4ff7d331c@quicinc.com/ Reviewed-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- .../media/platform/qcom/iris/iris_buffer.c | 20 ++++++++++++++++++- .../media/platform/qcom/iris/iris_buffer.h | 3 ++- drivers/media/platform/qcom/iris/iris_vdec.c | 4 ++-- drivers/media/platform/qcom/iris/iris_vidc.c | 4 ++-- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index e5c5a564fcb81..981fedb000ed5 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -376,7 +376,7 @@ int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buf return 0; } -int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane) +static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool force) { const struct iris_platform_data *platform_data = inst->core->iris_platform_data; struct iris_buffer *buf, *next; @@ -396,6 +396,14 @@ int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane) for (i = 0; i < len; i++) { buffers = &inst->buffers[internal_buf_type[i]]; list_for_each_entry_safe(buf, next, &buffers->list, list) { + /* + * during stream on, skip destroying internal(DPB) buffer + * if firmware did not return it. + * during close, destroy all buffers irrespectively. + */ + if (!force && buf->attr & BUF_ATTR_QUEUED) + continue; + ret = iris_destroy_internal_buffer(inst, buf); if (ret) return ret; @@ -405,6 +413,16 @@ int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane) return 0; } +int iris_destroy_all_internal_buffers(struct iris_inst *inst, u32 plane) +{ + return iris_destroy_internal_buffers(inst, plane, true); +} + +int iris_destroy_dequeued_internal_buffers(struct iris_inst *inst, u32 plane) +{ + return iris_destroy_internal_buffers(inst, plane, false); +} + static int iris_release_internal_buffers(struct iris_inst *inst, enum iris_buffer_type buffer_type) { diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h index c36b6347b0770..00825ad2dc3a4 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_buffer.h @@ -106,7 +106,8 @@ void iris_get_internal_buffers(struct iris_inst *inst, u32 plane); int iris_create_internal_buffers(struct iris_inst *inst, u32 plane); int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane); int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer); -int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_destroy_all_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_destroy_dequeued_internal_buffers(struct iris_inst *inst, u32 plane); int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst); int iris_alloc_and_queue_input_int_bufs(struct iris_inst *inst); int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf); diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index 4143acedfc574..9c049b9671ccc 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -408,7 +408,7 @@ int iris_vdec_streamon_input(struct iris_inst *inst) iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - ret = iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); if (ret) return ret; @@ -496,7 +496,7 @@ int iris_vdec_streamon_output(struct iris_inst *inst) iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - ret = iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); if (ret) return ret; diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index ca0f4e310f77f..663f5602b5ad2 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -233,8 +233,8 @@ int iris_close(struct file *filp) iris_session_close(inst); iris_inst_change_state(inst, IRIS_INST_DEINIT); iris_v4l2_fh_deinit(inst); - iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); iris_remove_session(inst); mutex_unlock(&inst->lock); mutex_destroy(&inst->ctx_q_lock); From f29bf8b5787776831556ca8d42984361a93c53c6 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:48 +0530 Subject: [PATCH 014/113] FROMLIST: media: iris: Verify internal buffer release on close Validate all internal buffers queued to firmware are released back to driver on close. This helps ensure buffer lifecycle correctness and aids in debugging any resporce leaks. Cc: stable@vger.kernel.org Fixes: 73702f45db81 ("media: iris: allocate, initialize and queue internal buffers") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-2-59b4ff7d331c@quicinc.com/ Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_vidc.c | 29 ++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 663f5602b5ad2..a8144595cc78e 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -221,6 +221,33 @@ static void iris_session_close(struct iris_inst *inst) iris_wait_for_session_response(inst, false); } +static void iris_check_num_queued_internal_buffers(struct iris_inst *inst, u32 plane) +{ + const struct iris_platform_data *platform_data = inst->core->iris_platform_data; + struct iris_buffer *buf, *next; + struct iris_buffers *buffers; + const u32 *internal_buf_type; + u32 internal_buffer_count, i; + u32 count = 0; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + } + + for (i = 0; i < internal_buffer_count; i++) { + buffers = &inst->buffers[internal_buf_type[i]]; + list_for_each_entry_safe(buf, next, &buffers->list, list) + count++; + if (count) + dev_err(inst->core->dev, "%d buffer of type %d not released", + count, internal_buf_type[i]); + } +} + int iris_close(struct file *filp) { struct iris_inst *inst = iris_get_inst(filp, NULL); @@ -235,6 +262,8 @@ int iris_close(struct file *filp) iris_v4l2_fh_deinit(inst); iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + iris_check_num_queued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + iris_check_num_queued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); iris_remove_session(inst); mutex_unlock(&inst->lock); mutex_destroy(&inst->ctx_q_lock); From 31a6cff42dd01246d9519d134c2cd8e896fedd97 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:49 +0530 Subject: [PATCH 015/113] FROMLIST: media: iris: Update CAPTURE format info based on OUTPUT format Update the width, height and buffer size of CAPTURE based on the resolution set to OUTPUT via VIDIOC_S_FMT. This is required to set the updated capture resolution to firmware when S_FMT is called only for OUTPUT. Cc: stable@vger.kernel.org Fixes: b530b95de22c ("media: iris: implement s_fmt, g_fmt and try_fmt ioctls") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-3-59b4ff7d331c@quicinc.com/ Reviewed-by: Bryan O'Donoghue Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_vdec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index 9c049b9671ccc..d342f733feb99 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -171,6 +171,11 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f) output_fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; output_fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; + /* Update capture format based on new ip w/h */ + output_fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128); + output_fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32); + inst->buffers[BUF_OUTPUT].size = iris_get_buffer_size(inst, BUF_OUTPUT); + inst->crop.left = 0; inst->crop.top = 0; inst->crop.width = f->fmt.pix_mp.width; From 8d8bbd3a098f8927791c1b77b930dd06840377a6 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:50 +0530 Subject: [PATCH 016/113] FROMLIST: media: iris: Avoid updating frame size to firmware during reconfig During reconfig, the firmware sends the resolution aligned to 8 bytes. If the driver sends the same resolution back to the firmware the resolution will be aligned to 16 bytes not 8. The alignment mismatch would then subsequently cause the firmware to send another redundant sequence change event. Fix this by not setting the resolution property during reconfig. Cc: stable@vger.kernel.org Fixes: 3a19d7b9e08b ("media: iris: implement set properties to firmware during streamon") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-4-59b4ff7d331c@quicinc.com/ Reviewed-by: Bryan O'Donoghue Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- .../platform/qcom/iris/iris_hfi_gen1_command.c | 15 ++++++++------- drivers/media/platform/qcom/iris/iris_state.c | 2 +- drivers/media/platform/qcom/iris/iris_state.h | 1 + 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index 64f887d9a17d7..2a86c27443eaf 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -546,14 +546,15 @@ static int iris_hfi_gen1_set_resolution(struct iris_inst *inst) struct hfi_framesize fs; int ret; - fs.buffer_type = HFI_BUFFER_INPUT; - fs.width = inst->fmt_src->fmt.pix_mp.width; - fs.height = inst->fmt_src->fmt.pix_mp.height; - - ret = hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs)); - if (ret) - return ret; + if (!iris_drc_pending(inst)) { + fs.buffer_type = HFI_BUFFER_INPUT; + fs.width = inst->fmt_src->fmt.pix_mp.width; + fs.height = inst->fmt_src->fmt.pix_mp.height; + ret = hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs)); + if (ret) + return ret; + } fs.buffer_type = HFI_BUFFER_OUTPUT2; fs.width = inst->fmt_dst->fmt.pix_mp.width; fs.height = inst->fmt_dst->fmt.pix_mp.height; diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c index 5976e926c83d1..104e1687ad39d 100644 --- a/drivers/media/platform/qcom/iris/iris_state.c +++ b/drivers/media/platform/qcom/iris/iris_state.c @@ -245,7 +245,7 @@ int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane) return iris_inst_change_sub_state(inst, 0, set_sub_state); } -static inline bool iris_drc_pending(struct iris_inst *inst) +bool iris_drc_pending(struct iris_inst *inst) { return inst->sub_state & IRIS_INST_SUB_DRC && inst->sub_state & IRIS_INST_SUB_DRC_LAST; diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h index 78c61aac5e7e0..e718386dbe040 100644 --- a/drivers/media/platform/qcom/iris/iris_state.h +++ b/drivers/media/platform/qcom/iris/iris_state.h @@ -140,5 +140,6 @@ int iris_inst_sub_state_change_drain_last(struct iris_inst *inst); int iris_inst_sub_state_change_drc_last(struct iris_inst *inst); int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane); bool iris_allow_cmd(struct iris_inst *inst, u32 cmd); +bool iris_drc_pending(struct iris_inst *inst); #endif From b0e36e7d1a2a9d9ad092d5a7758d9bd117d6d3f8 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:51 +0530 Subject: [PATCH 017/113] FROMLIST: media: iris: Drop port check for session property response Currently, port check enforces that session property response must arrive only on the BITSTREAM port. However, firmware can send some responses on other port as well. Remove the strict port validation to correctly handle session property responses from the firmware. Cc: stable@vger.kernel.org Fixes: 3a19d7b9e08b ("media: iris: implement set properties to firmware during streamon") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-5-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index b75a01641d5d4..d1a2a497a7b2e 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -636,9 +636,6 @@ static int iris_hfi_gen2_handle_session_property(struct iris_inst *inst, { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - if (pkt->port != HFI_PORT_BITSTREAM) - return 0; - if (pkt->flags & HFI_FW_FLAGS_INFORMATION) return 0; From 4f568e56f734867c3093b67150e1d28825c1a6a6 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:52 +0530 Subject: [PATCH 018/113] FROMLIST: media: iris: Prevent HFI queue writes when core is in deinit state The current check only considers the core error state before allowing writes to the HFI queues. However, the core can also transition to the deinit state due to a system error triggered by the response thread. In such cases, writing to the HFI queues should not be allowed. Fix this by adding a check for the core deinit state, ensuring that writes are rejected when core is not in a valid state. Cc: stable@vger.kernel.org Fixes: fb583a214337 ("media: iris: introduce host firmware interface with necessary hooks") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-6-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Reviewed-by: Bryan O'Donoghue Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_hfi_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c index fac7df0c4d1ae..221dcd09e1e10 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c @@ -113,7 +113,7 @@ int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32 pkt_s { struct iris_iface_q_info *q_info = &core->command_queue; - if (core->state == IRIS_CORE_ERROR) + if (core->state == IRIS_CORE_ERROR || core->state == IRIS_CORE_DEINIT) return -EINVAL; if (!iris_hfi_queue_write(q_info, pkt, pkt_size)) { From 0c017aca19bfe89c3bec998f1f143b611a5cfdd7 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:53 +0530 Subject: [PATCH 019/113] FROMLIST: media: iris: Remove error check for non-zero v4l2 controls Remove the check for non-zero number of v4l2 controls as some SOCs might not expose any capability which requires v4l2 control. Cc: stable@vger.kernel.org Fixes: 33be1dde17e3 ("media: iris: implement iris v4l2_ctrl_ops") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-7-59b4ff7d331c@quicinc.com/ Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_ctrls.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c index b690578256d59..6a514af8108e9 100644 --- a/drivers/media/platform/qcom/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -84,8 +84,6 @@ int iris_ctrls_init(struct iris_inst *inst) if (iris_get_v4l2_id(cap[idx].cap_id)) num_ctrls++; } - if (!num_ctrls) - return -EINVAL; /* Adding 1 to num_ctrls to include V4L2_CID_MIN_BUFFERS_FOR_CAPTURE */ From 10b94e669cd523ea5f41d415f90f9d0bb7c9ffc6 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:54 +0530 Subject: [PATCH 020/113] FROMLIST: media: iris: Remove deprecated property setting to firmware HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER is deprecated and no longer supported on current firmware, remove setting the same to firmware. Cc: stable@vger.kernel.org Fixes: 79865252acb6 ("media: iris: enable video driver probe of SM8250 SoC") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-8-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_ctrls.c | 4 ---- drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c | 8 -------- drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h | 1 - drivers/media/platform/qcom/iris/iris_platform_common.h | 2 +- drivers/media/platform/qcom/iris/iris_platform_sm8250.c | 9 --------- 5 files changed, 1 insertion(+), 23 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c index 6a514af8108e9..915de101fcba4 100644 --- a/drivers/media/platform/qcom/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -17,8 +17,6 @@ static inline bool iris_valid_cap_id(enum platform_inst_fw_cap_type cap_id) static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id) { switch (id) { - case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: - return DEBLOCK; case V4L2_CID_MPEG_VIDEO_H264_PROFILE: return PROFILE; case V4L2_CID_MPEG_VIDEO_H264_LEVEL: @@ -34,8 +32,6 @@ static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id) return 0; switch (cap_id) { - case DEBLOCK: - return V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER; case PROFILE: return V4L2_CID_MPEG_VIDEO_H264_PROFILE; case LEVEL: diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index 2a86c27443eaf..ce855a20ce4bf 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -490,14 +490,6 @@ iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_pkt *p packet->shdr.hdr.size += sizeof(u32) + sizeof(*wm); break; } - case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER: { - struct hfi_enable *en = prop_data; - u32 *in = pdata; - - en->enable = *in; - packet->shdr.hdr.size += sizeof(u32) + sizeof(*en); - break; - } default: return -EINVAL; } diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h index 9f246816a2862..e178604855c13 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -65,7 +65,6 @@ #define HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS 0x202001 -#define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER 0x1200001 #define HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS 0x120300e #define HFI_PROPERTY_CONFIG_VDEC_ENTROPY 0x1204004 diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index ac76d9e1ef9c1..1dab276431c71 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -89,7 +89,7 @@ enum platform_inst_fw_cap_type { CODED_FRAMES, BIT_DEPTH, RAP_FRAME, - DEBLOCK, + TIER, INST_FW_CAP_MAX, }; diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c index 5c86fd7b7b6fd..543fa26615391 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c @@ -30,15 +30,6 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250[] = { .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE, .set = iris_set_stage, }, - { - .cap_id = DEBLOCK, - .min = 0, - .max = 1, - .step_or_mask = 1, - .value = 0, - .hfi_id = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER, - .set = iris_set_u32, - }, }; static struct platform_inst_caps platform_inst_cap_sm8250 = { From ee6f9e9ef8a9b5e965e8522c3d64f274dc168421 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:55 +0530 Subject: [PATCH 021/113] FROMLIST: media: iris: Fix missing function pointer initialization The function pointers responsible for setting firmware properties were never initialized in the instance capability structure, causing it to remain NULL. As a result, the firmware properties were not being set correctly. Fix this by properly assigning the function pointers from the core capability to the instance capability, ensuring that the properties are correctly applied to the firmware. Cc: stable@vger.kernel.org Fixes: 3a19d7b9e08b ("media: iris: implement set properties to firmware during streamon") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-9-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_ctrls.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c index 915de101fcba4..13f5cf0d0e8a4 100644 --- a/drivers/media/platform/qcom/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -157,6 +157,7 @@ void iris_session_init_caps(struct iris_core *core) core->inst_fw_caps[cap_id].value = caps[i].value; core->inst_fw_caps[cap_id].flags = caps[i].flags; core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id; + core->inst_fw_caps[cap_id].set = caps[i].set; } } From 0300feb1b49a508abb785f4e0f4dd3ce0c339d24 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:56 +0530 Subject: [PATCH 022/113] FROMLIST: media: iris: Fix NULL pointer dereference A warning reported by smatch indicated a possible null pointer dereference where one of the arguments to API "iris_hfi_gen2_handle_system_error" could sometimes be null. To fix this, add a check to validate that the argument passed is not null before accessing its members. Cc: stable@vger.kernel.org Fixes: fb583a214337 ("media: iris: introduce host firmware interface with necessary hooks") Reported-by: Dan Carpenter Closes: https://lore.kernel.org/linux-media/634cc9b8-f099-4b54-8556-d879fb2b5169@stanley.mountain/ Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-10-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index d1a2a497a7b2e..4488540d1d410 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -265,7 +265,8 @@ static int iris_hfi_gen2_handle_system_error(struct iris_core *core, { struct iris_inst *instance; - dev_err(core->dev, "received system error of type %#x\n", pkt->type); + if (pkt) + dev_err(core->dev, "received system error of type %#x\n", pkt->type); core->state = IRIS_CORE_ERROR; From 2a076db5c73236aa3263bb6e940940e45d6dc6da Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:57 +0530 Subject: [PATCH 023/113] FROMLIST: media: iris: Fix typo in depth variable Correct a typo from "dpeth" to "depth". Cc: stable@vger.kernel.org Fixes: 3a19d7b9e08b ("media: iris: implement set properties to firmware during streamon") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-11-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index a908b41e2868f..802fa62c26ebe 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -178,7 +178,7 @@ static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst) sizeof(u64)); } -static int iris_hfi_gen2_set_bit_dpeth(struct iris_inst *inst) +static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); @@ -378,7 +378,7 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p {HFI_PROP_BITSTREAM_RESOLUTION, iris_hfi_gen2_set_bitstream_resolution }, {HFI_PROP_CROP_OFFSETS, iris_hfi_gen2_set_crop_offsets }, {HFI_PROP_CODED_FRAMES, iris_hfi_gen2_set_coded_frames }, - {HFI_PROP_LUMA_CHROMA_BIT_DEPTH, iris_hfi_gen2_set_bit_dpeth }, + {HFI_PROP_LUMA_CHROMA_BIT_DEPTH, iris_hfi_gen2_set_bit_depth }, {HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT, iris_hfi_gen2_set_min_output_count }, {HFI_PROP_PIC_ORDER_CNT_TYPE, iris_hfi_gen2_set_picture_order_count }, {HFI_PROP_SIGNAL_COLOR_INFO, iris_hfi_gen2_set_colorspace }, From 0e1b74eae98b8d7d9c36ea42d4994dd7188d60fa Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:58 +0530 Subject: [PATCH 024/113] FROMLIST: media: iris: Track flush responses to prevent premature completion Currently, two types of flush commands are queued to the firmware, the first flush queued as part of sequence change, does not wait for a response, while the second flush queued as part of stop, expects a completion response before proceeding further. Due to timing issue, the flush response corresponding to the first command could arrive after the second flush is issued. This casuses the driver to incorrectly assume that the second flush has completed, leading to the premature signaling of flush_completion. To address this, introduce a counter to track the number of pending flush responses and signal flush completion only when all expected responses are received. Cc: stable@vger.kernel.org Fixes: 11712ce70f8e ("media: iris: implement vb2 streaming ops") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-12-59b4ff7d331c@quicinc.com/ Reviewed-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- .../platform/qcom/iris/iris_hfi_gen1_command.c | 4 +++- .../platform/qcom/iris/iris_hfi_gen1_response.c | 17 +++++++++++------ .../media/platform/qcom/iris/iris_instance.h | 2 ++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index ce855a20ce4bf..bd9d86220e611 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -208,8 +208,10 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane) flush_pkt.flush_type = flush_type; ret = iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); - if (!ret) + if (!ret) { + inst->flush_responses_pending++; ret = iris_wait_for_session_response(inst, true); + } } return ret; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index b72d503dd7401..271e144692231 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -207,7 +207,8 @@ static void iris_hfi_gen1_event_seq_changed(struct iris_inst *inst, flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; flush_pkt.shdr.session_id = inst->session_id; flush_pkt.flush_type = HFI_FLUSH_OUTPUT; - iris_hfi_queue_cmd_write(inst->core, &flush_pkt, flush_pkt.shdr.hdr.size); + if (!iris_hfi_queue_cmd_write(inst->core, &flush_pkt, flush_pkt.shdr.hdr.size)) + inst->flush_responses_pending++; } iris_vdec_src_change(inst); @@ -408,7 +409,9 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; flush_pkt.shdr.session_id = inst->session_id; flush_pkt.flush_type = HFI_FLUSH_OUTPUT; - iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); + if (!iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size)) + inst->flush_responses_pending++; + iris_inst_sub_state_change_drain_last(inst); return; @@ -558,7 +561,6 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response const struct iris_hfi_gen1_response_pkt_info *pkt_info; struct device *dev = core->dev; struct hfi_session_pkt *pkt; - struct completion *done; struct iris_inst *inst; bool found = false; u32 i; @@ -619,9 +621,12 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response if (shdr->error_type != HFI_ERR_NONE) iris_inst_change_state(inst, IRIS_INST_ERROR); - done = pkt_info->pkt == HFI_MSG_SESSION_FLUSH ? - &inst->flush_completion : &inst->completion; - complete(done); + if (pkt_info->pkt == HFI_MSG_SESSION_FLUSH) { + if (!(--inst->flush_responses_pending)) + complete(&inst->flush_completion); + } else { + complete(&inst->completion); + } } mutex_unlock(&inst->lock); diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h index caa3c65070061..06a7f1174ad55 100644 --- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -27,6 +27,7 @@ * @crop: structure of crop info * @completion: structure of signal completions * @flush_completion: structure of signal completions for flush cmd + * @flush_responses_pending: counter to track number of pending flush responses * @fw_caps: array of supported instance firmware capabilities * @buffers: array of different iris buffers * @fw_min_count: minimnum count of buffers needed by fw @@ -57,6 +58,7 @@ struct iris_inst { struct iris_hfi_rect_desc crop; struct completion completion; struct completion flush_completion; + u32 flush_responses_pending; struct platform_inst_fw_cap fw_caps[INST_FW_CAP_MAX]; struct iris_buffers buffers[BUF_TYPE_MAX]; u32 fw_min_count; From 7c2ba118b70f08db56e7d8fd3a35fc59dbee3fd2 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:08:59 +0530 Subject: [PATCH 025/113] FROMLIST: media: iris: Fix buffer preparation failure during resolution change When the resolution changes, the driver internally updates the width and height, but the client continue to queue buffers with the older resolution until the last flag is received. This results in a mismatch when the buffers are prepared, causing failure due to outdated size. Introduce a check to prevent size validation during buffer preparation if a resolution reconfiguration is in progress, to handle this. Cc: stable@vger.kernel.org Fixes: 17f2a485ca67 ("media: iris: implement vb2 ops for buf_queue and firmware response") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-13-59b4ff7d331c@quicinc.com/ Reviewed-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_vb2.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c index cdf11feb590b5..b3bde10eb6d2f 100644 --- a/drivers/media/platform/qcom/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/iris/iris_vb2.c @@ -259,13 +259,14 @@ int iris_vb2_buf_prepare(struct vb2_buffer *vb) return -EINVAL; } - if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && - vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_OUTPUT)) - return -EINVAL; - if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && - vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_INPUT)) - return -EINVAL; - + if (!(inst->sub_state & IRIS_INST_SUB_DRC)) { + if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && + vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_OUTPUT)) + return -EINVAL; + if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && + vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_INPUT)) + return -EINVAL; + } return 0; } From 1dee31fd23679005ac8f24341827d22da6e2b524 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:00 +0530 Subject: [PATCH 026/113] FROMLIST: media: iris: Send V4L2_BUF_FLAG_ERROR for capture buffers with 0 filled length Firmware sends capture buffers with 0 filled length which are not to be displayed and should be dropped by client. To achieve the same, add V4L2_BUF_FLAG_ERROR to such buffers by making sure: - These 0 length buffers are not returned as result of flush. - Its not a buffer with LAST flag enabled which will also have 0 filled length. Cc: stable@vger.kernel.org Fixes: d09100763bed ("media: iris: add support for drain sequence") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-14-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index 4488540d1d410..d2cede2fe1b5a 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -378,6 +378,11 @@ static int iris_hfi_gen2_handle_output_buffer(struct iris_inst *inst, buf->flags = iris_hfi_gen2_get_driver_buffer_flags(inst, hfi_buffer->flags); + if (!buf->data_size && inst->state == IRIS_INST_STREAMING && + !(hfi_buffer->flags & HFI_BUF_FW_FLAG_LAST)) { + buf->flags |= V4L2_BUF_FLAG_ERROR; + } + return 0; } From 10ff8bef6ae409439ad9d11a9b15e0c9d01ca8d7 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:01 +0530 Subject: [PATCH 027/113] FROMLIST: media: iris: Skip flush on first sequence change Add a condition to skip the flush operation during the first sequence change event. At this point, the capture queue is not streaming, making the flush unnecessary. Cc: stable@vger.kernel.org Fixes: 84e17adae3e3 ("media: iris: add support for dynamic resolution change") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-15-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index 271e144692231..aaad32a70b9ec 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -200,7 +200,7 @@ static void iris_hfi_gen1_event_seq_changed(struct iris_inst *inst, iris_hfi_gen1_read_changed_params(inst, pkt); - if (inst->state != IRIS_INST_ERROR) { + if (inst->state != IRIS_INST_ERROR && !(inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)) { reinit_completion(&inst->flush_completion); flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); From cc859b09c56dbe6ff06a203cbdfc9172baeb3f61 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:02 +0530 Subject: [PATCH 028/113] FROMLIST: media: iris: Remove unnecessary re-initialization of flush completion Currently, The flush completion signal is being re-initialized even though no response is expected during a sequence change. Simplify the code by removing re-initialization of flush completion signal as it is redundant. Cc: stable@vger.kernel.org Fixes: 84e17adae3e3 ("media: iris: add support for dynamic resolution change") Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-16-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index aaad32a70b9ec..c8c0aa23536b7 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -201,7 +201,6 @@ static void iris_hfi_gen1_event_seq_changed(struct iris_inst *inst, iris_hfi_gen1_read_changed_params(inst, pkt); if (inst->state != IRIS_INST_ERROR && !(inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)) { - reinit_completion(&inst->flush_completion); flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; From ef18b369c530530642378e9f043c13021cd26fec Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:03 +0530 Subject: [PATCH 029/113] FROMLIST: media: iris: Add handling for corrupt and drop frames Firmware attach DATACORRUPT/DROP buffer flags for the frames which needs to be dropped, handle it by setting VB2_BUF_STATE_ERROR for these buffers before calling buf_done. Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-17-59b4ff7d331c@quicinc.com/ Reviewed-by: Bryan O'Donoghue Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_buffer.c | 11 ++++++++--- .../media/platform/qcom/iris/iris_hfi_gen1_defines.h | 2 ++ .../media/platform/qcom/iris/iris_hfi_gen1_response.c | 6 ++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index 981fedb000ed5..018334512baed 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -611,10 +611,13 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf) vb2 = &vbuf->vb2_buf; - if (buf->flags & V4L2_BUF_FLAG_ERROR) + if (buf->flags & V4L2_BUF_FLAG_ERROR) { state = VB2_BUF_STATE_ERROR; - else - state = VB2_BUF_STATE_DONE; + vb2_set_plane_payload(vb2, 0, 0); + vb2->timestamp = 0; + v4l2_m2m_buf_done(vbuf, state); + return 0; + } vbuf->flags |= buf->flags; @@ -634,6 +637,8 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf) v4l2_m2m_mark_stopped(m2m_ctx); } } + + state = VB2_BUF_STATE_DONE; vb2->timestamp = buf->timestamp; v4l2_m2m_buf_done(vbuf, state); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h index e178604855c13..adffcead58ea7 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -116,6 +116,8 @@ #define HFI_FRAME_NOTCODED 0x7f002000 #define HFI_FRAME_YUV 0x7f004000 #define HFI_UNUSED_PICT 0x10000000 +#define HFI_BUFFERFLAG_DATACORRUPT 0x00000008 +#define HFI_BUFFERFLAG_DROP_FRAME 0x20000000 struct hfi_pkt_hdr { u32 size; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index c8c0aa23536b7..14d8bef62b606 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -483,6 +483,12 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) buf->attr |= BUF_ATTR_DEQUEUED; buf->attr |= BUF_ATTR_BUFFER_DONE; + if (hfi_flags & HFI_BUFFERFLAG_DATACORRUPT) + flags |= V4L2_BUF_FLAG_ERROR; + + if (hfi_flags & HFI_BUFFERFLAG_DROP_FRAME) + flags |= V4L2_BUF_FLAG_ERROR; + buf->flags |= flags; iris_vb2_buffer_done(inst, buf); From d8ee74956befb1fd47cb7eedb349824ce968a6c8 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:04 +0530 Subject: [PATCH 030/113] FROMLIST: media: iris: Add handling for no show frames Firmware sends the picture type as NO_SHOW for frames which are not supposed to be displayed, add handling for the same in driver to drop them. Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-18-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h | 1 + drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index 806f8bb7f505d..666061a612c30 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -113,6 +113,7 @@ enum hfi_picture_type { HFI_PICTURE_I = 0x00000008, HFI_PICTURE_CRA = 0x00000010, HFI_PICTURE_BLA = 0x00000020, + HFI_PICTURE_NOSHOW = 0x00000040, }; enum hfi_buffer_type { diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index d2cede2fe1b5a..b6d0ff860d786 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -91,7 +91,9 @@ static int iris_hfi_gen2_get_driver_buffer_flags(struct iris_inst *inst, u32 hfi struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); u32 driver_flags = 0; - if (inst_hfi_gen2->hfi_frame_info.picture_type & keyframe) + if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_NOSHOW) + driver_flags |= V4L2_BUF_FLAG_ERROR; + else if (inst_hfi_gen2->hfi_frame_info.picture_type & keyframe) driver_flags |= V4L2_BUF_FLAG_KEYFRAME; else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_P) driver_flags |= V4L2_BUF_FLAG_PFRAME; From c908282c4d4a627dc065645705b316197a627ef5 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:05 +0530 Subject: [PATCH 031/113] FROMLIST: media: iris: Improve last flag handling Improve the handling of the V4L2_BUF_FLAG_LAST flag in the driver: - Ensure that the last flag is not sent multiple times. - Attach the last flag to the first capture buffer returned during flush, triggered by a sequence change, addressing cases where the firmware does not set the last flag. Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-19-59b4ff7d331c@quicinc.com/ Reviewed-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_buffer.c | 1 + drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c | 7 ++++++- drivers/media/platform/qcom/iris/iris_instance.h | 2 ++ drivers/media/platform/qcom/iris/iris_vb2.c | 3 ++- drivers/media/platform/qcom/iris/iris_vdec.c | 2 ++ 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index 018334512baed..7dbac74b1a8de 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -636,6 +636,7 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf) v4l2_event_queue_fh(&inst->fh, &ev); v4l2_m2m_mark_stopped(m2m_ctx); } + inst->last_buffer_dequeued = true; } state = VB2_BUF_STATE_DONE; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index 14d8bef62b606..926acee1f48cc 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -457,7 +457,12 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) timestamp_us = timestamp_hi; timestamp_us = (timestamp_us << 32) | timestamp_lo; } else { - flags |= V4L2_BUF_FLAG_LAST; + if (pkt->stream_id == 1 && !inst->last_buffer_dequeued) { + if (iris_drc_pending(inst)) { + flags |= V4L2_BUF_FLAG_LAST; + inst->last_buffer_dequeued = true; + } + } } buf->timestamp = timestamp_us; diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h index 06a7f1174ad55..5ec6368b2af71 100644 --- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -43,6 +43,7 @@ * @sequence_out: a sequence counter for output queue * @tss: timestamp metadata * @metadata_idx: index for metadata buffer + * @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver */ struct iris_inst { @@ -74,6 +75,7 @@ struct iris_inst { u32 sequence_out; struct iris_ts_metadata tss[VIDEO_MAX_FRAME]; u32 metadata_idx; + bool last_buffer_dequeued; }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c index b3bde10eb6d2f..8b17c7c394879 100644 --- a/drivers/media/platform/qcom/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/iris/iris_vb2.c @@ -305,7 +305,7 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2) goto exit; } - if (V4L2_TYPE_IS_CAPTURE(vb2->vb2_queue->type)) { + if (!inst->last_buffer_dequeued && V4L2_TYPE_IS_CAPTURE(vb2->vb2_queue->type)) { if ((inst->sub_state & IRIS_INST_SUB_DRC && inst->sub_state & IRIS_INST_SUB_DRC_LAST) || (inst->sub_state & IRIS_INST_SUB_DRAIN && @@ -319,6 +319,7 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2) v4l2_event_queue_fh(&inst->fh, &eos); v4l2_m2m_mark_stopped(m2m_ctx); } + inst->last_buffer_dequeued = true; goto exit; } } diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index d342f733feb99..de4e3fe8ed5ac 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -487,6 +487,8 @@ static int iris_vdec_process_streamon_output(struct iris_inst *inst) if (ret) return ret; + inst->last_buffer_dequeued = false; + return iris_inst_change_sub_state(inst, clear_sub_state, 0); } From c5f359aeb376f4bd0646c435d7500f7518587a81 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:06 +0530 Subject: [PATCH 032/113] FROMLIST: media: iris: Remove redundant buffer count check in stream off Currently, the stream off process checks the count of buffers in v4l2_m2m_queues using v4l2_m2m_for_each_src_buf_safe and v4l2_m2m_for_each_dst_buf_safe APIs. If the count is non-zero, it returns an error. This check is redundant as the V4L2 framework already handles buffer management internally. Remove the unnecessary buffer count check in stream off, simplifying the process and relying on V4L2's internal mechanisms for buffer management. Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-20-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_vdec.c | 36 -------------------- 1 file changed, 36 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index de4e3fe8ed5ac..ce97c555192a9 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -244,35 +244,6 @@ void iris_vdec_src_change(struct iris_inst *inst) v4l2_event_queue_fh(&inst->fh, &event); } -static int iris_vdec_get_num_queued_buffers(struct iris_inst *inst, - enum iris_buffer_type type) -{ - struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; - struct v4l2_m2m_buffer *buffer, *n; - struct iris_buffer *buf; - u32 count = 0; - - switch (type) { - case BUF_INPUT: - v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { - buf = to_iris_buffer(&buffer->vb); - if (!(buf->attr & BUF_ATTR_QUEUED)) - continue; - count++; - } - return count; - case BUF_OUTPUT: - v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) { - buf = to_iris_buffer(&buffer->vb); - if (!(buf->attr & BUF_ATTR_QUEUED)) - continue; - count++; - } - return count; - default: - return count; - } -} static void iris_vdec_flush_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type type) @@ -321,7 +292,6 @@ int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane) { const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; enum iris_buffer_type buffer_type; - u32 count; int ret; switch (plane) { @@ -339,12 +309,6 @@ int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane) if (ret) goto error; - count = iris_vdec_get_num_queued_buffers(inst, buffer_type); - if (count) { - ret = -EINVAL; - goto error; - } - ret = iris_inst_state_change_streamoff(inst, plane); if (ret) goto error; From 868166412143d0a88e5fb4651c26c54d2c2e36e5 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:07 +0530 Subject: [PATCH 033/113] FROMLIST: media: iris: Add a comment to explain usage of MBPS Add a comment to explain usage of MBPS and define a macro for 8K resolution for better readability Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-21-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_platform_common.h | 2 ++ drivers/media/platform/qcom/iris/iris_platform_gen2.c | 4 ++-- drivers/media/platform/qcom/iris/iris_platform_sm8250.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 1dab276431c71..3e0ae87526a0c 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -21,6 +21,7 @@ struct iris_inst; #define DEFAULT_MAX_HOST_BUF_COUNT 64 #define DEFAULT_MAX_HOST_BURST_BUF_COUNT 256 #define DEFAULT_FPS 30 +#define NUM_MBS_8K ((8192 * 4352) / 256) enum stage_type { STAGE_1 = 1, @@ -172,6 +173,7 @@ struct iris_platform_data { struct ubwc_config_data *ubwc_config; u32 num_vpp_pipe; u32 max_session_count; + /* max number of macroblocks per frame supported */ u32 max_core_mbpf; const u32 *input_config_params; unsigned int input_config_params_size; diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c index 1e69ba15db0fd..deb7037e8e86f 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c @@ -248,7 +248,7 @@ struct iris_platform_data sm8550_data = { .ubwc_config = &ubwc_config_sm8550, .num_vpp_pipe = 4, .max_session_count = 16, - .max_core_mbpf = ((8192 * 4352) / 256) * 2, + .max_core_mbpf = NUM_MBS_8K * 2, .input_config_params = sm8550_vdec_input_config_params, .input_config_params_size = @@ -308,7 +308,7 @@ struct iris_platform_data sm8650_data = { .ubwc_config = &ubwc_config_sm8550, .num_vpp_pipe = 4, .max_session_count = 16, - .max_core_mbpf = ((8192 * 4352) / 256) * 2, + .max_core_mbpf = NUM_MBS_8K * 2, .input_config_params = sm8550_vdec_input_config_params, .input_config_params_size = diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c index 543fa26615391..8183e4e95fa4e 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c @@ -127,7 +127,7 @@ struct iris_platform_data sm8250_data = { .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, .num_vpp_pipe = 4, .max_session_count = 16, - .max_core_mbpf = (8192 * 4352) / 256, + .max_core_mbpf = NUM_MBS_8K, .input_config_params = sm8250_vdec_input_config_param_default, .input_config_params_size = From 5bec6099caf3817664cd55bceeb7883984d24550 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:08 +0530 Subject: [PATCH 034/113] FROMLIST: media: iris: Add HEVC and VP9 formats for decoder Extend the decoder driver's supported formats to include HEVC (H.265) and VP9. This change updates the format enumeration (VIDIOC_ENUM_FMT) and allows setting these formats via VIDIOC_S_FMT. Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-22-59b4ff7d331c@quicinc.com/ Reviewed-by: Bryan O'Donoghue Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- .../qcom/iris/iris_hfi_gen1_command.c | 15 +++- .../qcom/iris/iris_hfi_gen1_defines.h | 2 + .../qcom/iris/iris_hfi_gen2_command.c | 14 +++- .../qcom/iris/iris_hfi_gen2_defines.h | 3 + .../media/platform/qcom/iris/iris_instance.h | 2 + drivers/media/platform/qcom/iris/iris_vdec.c | 69 +++++++++++++++++-- drivers/media/platform/qcom/iris/iris_vdec.h | 11 +++ drivers/media/platform/qcom/iris/iris_vidc.c | 3 - 8 files changed, 108 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index bd9d86220e611..dbb1b1dab0970 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -88,16 +88,29 @@ static int iris_hfi_gen1_sys_pc_prep(struct iris_core *core) static int iris_hfi_gen1_session_open(struct iris_inst *inst) { struct hfi_session_open_pkt packet; + u32 codec = 0; int ret; if (inst->state != IRIS_INST_DEINIT) return -EALREADY; + switch (inst->codec) { + case V4L2_PIX_FMT_H264: + codec = HFI_VIDEO_CODEC_H264; + break; + case V4L2_PIX_FMT_HEVC: + codec = HFI_VIDEO_CODEC_HEVC; + break; + case V4L2_PIX_FMT_VP9: + codec = HFI_VIDEO_CODEC_VP9; + break; + } + packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt); packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT; packet.shdr.session_id = inst->session_id; packet.session_domain = HFI_SESSION_TYPE_DEC; - packet.session_codec = HFI_VIDEO_CODEC_H264; + packet.session_codec = codec; reinit_completion(&inst->completion); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h index adffcead58ea7..d4d119ca98b0c 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -13,6 +13,8 @@ #define HFI_SESSION_TYPE_DEC 2 #define HFI_VIDEO_CODEC_H264 0x00000002 +#define HFI_VIDEO_CODEC_HEVC 0x00002000 +#define HFI_VIDEO_CODEC_VP9 0x00004000 #define HFI_ERR_NONE 0x0 diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index 802fa62c26ebe..f23be23406586 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -416,7 +416,19 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 codec = HFI_CODEC_DECODE_AVC; + u32 codec = 0; + + switch (inst->codec) { + case V4L2_PIX_FMT_H264: + codec = HFI_CODEC_DECODE_AVC; + break; + case V4L2_PIX_FMT_HEVC: + codec = HFI_CODEC_DECODE_HEVC; + break; + case V4L2_PIX_FMT_VP9: + codec = HFI_CODEC_DECODE_VP9; + break; + } iris_hfi_gen2_packet_session_property(inst, HFI_PROP_CODEC, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index 666061a612c30..283d2f27e4c8e 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -104,6 +104,9 @@ enum hfi_color_format { enum hfi_codec_type { HFI_CODEC_DECODE_AVC = 1, HFI_CODEC_ENCODE_AVC = 2, + HFI_CODEC_DECODE_HEVC = 3, + HFI_CODEC_ENCODE_HEVC = 4, + HFI_CODEC_DECODE_VP9 = 5, }; enum hfi_picture_type { diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h index 5ec6368b2af71..0e1f5799b72d9 100644 --- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -43,6 +43,7 @@ * @sequence_out: a sequence counter for output queue * @tss: timestamp metadata * @metadata_idx: index for metadata buffer + * @codec: codec type * @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver */ @@ -75,6 +76,7 @@ struct iris_inst { u32 sequence_out; struct iris_ts_metadata tss[VIDEO_MAX_FRAME]; u32 metadata_idx; + u32 codec; bool last_buffer_dequeued; }; diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index ce97c555192a9..d670b51c5839d 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -32,6 +32,7 @@ int iris_vdec_inst_init(struct iris_inst *inst) f->fmt.pix_mp.width = DEFAULT_WIDTH; f->fmt.pix_mp.height = DEFAULT_HEIGHT; f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; + inst->codec = f->fmt.pix_mp.pixelformat; f->fmt.pix_mp.num_planes = 1; f->fmt.pix_mp.plane_fmt[0].bytesperline = 0; f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT); @@ -67,14 +68,67 @@ void iris_vdec_inst_deinit(struct iris_inst *inst) kfree(inst->fmt_src); } +static const struct iris_fmt iris_vdec_formats[] = { + [IRIS_FMT_H264] = { + .pixfmt = V4L2_PIX_FMT_H264, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + }, + [IRIS_FMT_HEVC] = { + .pixfmt = V4L2_PIX_FMT_HEVC, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + }, + [IRIS_FMT_VP9] = { + .pixfmt = V4L2_PIX_FMT_VP9, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + }, +}; + +static const struct iris_fmt * +find_format(struct iris_inst *inst, u32 pixfmt, u32 type) +{ + unsigned int size = ARRAY_SIZE(iris_vdec_formats); + const struct iris_fmt *fmt = iris_vdec_formats; + unsigned int i; + + for (i = 0; i < size; i++) { + if (fmt[i].pixfmt == pixfmt) + break; + } + + if (i == size || fmt[i].type != type) + return NULL; + + return &fmt[i]; +} + +static const struct iris_fmt * +find_format_by_index(struct iris_inst *inst, u32 index, u32 type) +{ + const struct iris_fmt *fmt = iris_vdec_formats; + unsigned int size = ARRAY_SIZE(iris_vdec_formats); + + if (index >= size || fmt[index].type != type) + return NULL; + + return &fmt[index]; +} + int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f) { + const struct iris_fmt *fmt; + switch (f->type) { case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - f->pixelformat = V4L2_PIX_FMT_H264; + fmt = find_format_by_index(inst, f->index, f->type); + if (!fmt) + return -EINVAL; + + f->pixelformat = fmt->pixfmt; f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_DYN_RESOLUTION; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (f->index) + return -EINVAL; f->pixelformat = V4L2_PIX_FMT_NV12; break; default: @@ -88,13 +142,15 @@ int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; + const struct iris_fmt *fmt; struct v4l2_format *f_inst; struct vb2_queue *src_q; memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); + fmt = find_format(inst, pixmp->pixelformat, f->type); switch (f->type) { case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264) { + if (!fmt) { f_inst = inst->fmt_src; f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; @@ -102,7 +158,7 @@ int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f) } break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) { + if (!fmt) { f_inst = inst->fmt_dst; f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; @@ -145,13 +201,14 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f) switch (f->type) { case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264) + if (!(find_format(inst, f->fmt.pix_mp.pixelformat, f->type))) return -EINVAL; fmt = inst->fmt_src; fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - - codec_align = DEFAULT_CODEC_ALIGNMENT; + fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; + inst->codec = fmt->fmt.pix_mp.pixelformat; + codec_align = inst->codec == V4L2_PIX_FMT_HEVC ? 32 : 16; fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, codec_align); fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, codec_align); fmt->fmt.pix_mp.num_planes = 1; diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h index b24932dc511a6..cd7aab66dc7c8 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.h +++ b/drivers/media/platform/qcom/iris/iris_vdec.h @@ -8,6 +8,17 @@ struct iris_inst; +enum iris_fmt_type { + IRIS_FMT_H264, + IRIS_FMT_HEVC, + IRIS_FMT_VP9, +}; + +struct iris_fmt { + u32 pixfmt; + u32 type; +}; + int iris_vdec_inst_init(struct iris_inst *inst); void iris_vdec_inst_deinit(struct iris_inst *inst); int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index a8144595cc78e..c417e8c31f806 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -278,9 +278,6 @@ static int iris_enum_fmt(struct file *filp, void *fh, struct v4l2_fmtdesc *f) { struct iris_inst *inst = iris_get_inst(filp, NULL); - if (f->index) - return -EINVAL; - return iris_vdec_enum_fmt(inst, f); } From d5780eaea136c594d0111027096a1eff1bd11cdb Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:09 +0530 Subject: [PATCH 035/113] FROMLIST: media: iris: Add platform capabilities for HEVC and VP9 decoders Add platform capabilities for HEVC and VP9 codecs in decoder driver with related hooks. Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-23-59b4ff7d331c@quicinc.com/ Reviewed-by: Bryan O'Donoghue Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_ctrls.c | 28 +++- .../qcom/iris/iris_hfi_gen2_command.c | 28 +++- .../qcom/iris/iris_hfi_gen2_defines.h | 1 + .../qcom/iris/iris_hfi_gen2_response.c | 34 ++++- .../platform/qcom/iris/iris_platform_common.h | 8 +- .../platform/qcom/iris/iris_platform_gen2.c | 80 ++++++++++- .../qcom/iris/iris_platform_qcs8300.h | 126 ++++++++++++++---- 7 files changed, 266 insertions(+), 39 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c index 13f5cf0d0e8a4..9136b723c0f2a 100644 --- a/drivers/media/platform/qcom/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -18,9 +18,19 @@ static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id) { switch (id) { case V4L2_CID_MPEG_VIDEO_H264_PROFILE: - return PROFILE; + return PROFILE_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: + return PROFILE_HEVC; + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: + return PROFILE_VP9; case V4L2_CID_MPEG_VIDEO_H264_LEVEL: - return LEVEL; + return LEVEL_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: + return LEVEL_HEVC; + case V4L2_CID_MPEG_VIDEO_VP9_LEVEL: + return LEVEL_VP9; + case V4L2_CID_MPEG_VIDEO_HEVC_TIER: + return TIER; default: return INST_FW_CAP_MAX; } @@ -32,10 +42,20 @@ static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id) return 0; switch (cap_id) { - case PROFILE: + case PROFILE_H264: return V4L2_CID_MPEG_VIDEO_H264_PROFILE; - case LEVEL: + case PROFILE_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_PROFILE; + case PROFILE_VP9: + return V4L2_CID_MPEG_VIDEO_VP9_PROFILE; + case LEVEL_H264: return V4L2_CID_MPEG_VIDEO_H264_LEVEL; + case LEVEL_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_LEVEL; + case LEVEL_VP9: + return V4L2_CID_MPEG_VIDEO_VP9_LEVEL; + case TIER: + return V4L2_CID_MPEG_VIDEO_HEVC_TIER; default: return 0; } diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index f23be23406586..8c91d336ff7e2 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -295,7 +295,19 @@ static int iris_hfi_gen2_set_profile(struct iris_inst *inst) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - u32 profile = inst->fw_caps[PROFILE].value; + u32 profile = 0; + + switch (inst->codec) { + case V4L2_PIX_FMT_HEVC: + profile = inst->fw_caps[PROFILE_HEVC].value; + break; + case V4L2_PIX_FMT_VP9: + profile = inst->fw_caps[PROFILE_VP9].value; + break; + case V4L2_PIX_FMT_H264: + profile = inst->fw_caps[PROFILE_H264].value; + break; + } inst_hfi_gen2->src_subcr_params.profile = profile; @@ -312,7 +324,19 @@ static int iris_hfi_gen2_set_level(struct iris_inst *inst) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - u32 level = inst->fw_caps[LEVEL].value; + u32 level = 0; + + switch (inst->codec) { + case V4L2_PIX_FMT_HEVC: + level = inst->fw_caps[LEVEL_HEVC].value; + break; + case V4L2_PIX_FMT_VP9: + level = inst->fw_caps[LEVEL_VP9].value; + break; + case V4L2_PIX_FMT_H264: + level = inst->fw_caps[LEVEL_H264].value; + break; + } inst_hfi_gen2->src_subcr_params.level = level; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index 283d2f27e4c8e..5f13dc11bea53 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -46,6 +46,7 @@ #define HFI_PROP_CROP_OFFSETS 0x03000105 #define HFI_PROP_PROFILE 0x03000107 #define HFI_PROP_LEVEL 0x03000108 +#define HFI_PROP_TIER 0x03000109 #define HFI_PROP_STAGE 0x0300010a #define HFI_PROP_PIPE 0x0300010b #define HFI_PROP_LUMA_CHROMA_BIT_DEPTH 0x0300010f diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index b6d0ff860d786..8e54962414aeb 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -571,8 +571,21 @@ static void iris_hfi_gen2_read_input_subcr_params(struct iris_inst *inst) inst->crop.width = pixmp_ip->width - ((subsc_params.crop_offsets[1] >> 16) & 0xFFFF) - inst->crop.left; - inst->fw_caps[PROFILE].value = subsc_params.profile; - inst->fw_caps[LEVEL].value = subsc_params.level; + switch (inst->codec) { + case V4L2_PIX_FMT_HEVC: + inst->fw_caps[PROFILE_HEVC].value = subsc_params.profile; + inst->fw_caps[LEVEL_HEVC].value = subsc_params.level; + break; + case V4L2_PIX_FMT_VP9: + inst->fw_caps[PROFILE_VP9].value = subsc_params.profile; + inst->fw_caps[LEVEL_VP9].value = subsc_params.level; + break; + case V4L2_PIX_FMT_H264: + inst->fw_caps[PROFILE_H264].value = subsc_params.profile; + inst->fw_caps[LEVEL_H264].value = subsc_params.level; + break; + } + inst->fw_caps[POC].value = subsc_params.pic_order_cnt; if (subsc_params.bit_depth != BIT_DEPTH_8 || @@ -796,8 +809,21 @@ static void iris_hfi_gen2_init_src_change_param(struct iris_inst *inst) full_range, video_format, video_signal_type_present_flag); - subsc_params->profile = inst->fw_caps[PROFILE].value; - subsc_params->level = inst->fw_caps[LEVEL].value; + switch (inst->codec) { + case V4L2_PIX_FMT_HEVC: + subsc_params->profile = inst->fw_caps[PROFILE_HEVC].value; + subsc_params->level = inst->fw_caps[LEVEL_HEVC].value; + break; + case V4L2_PIX_FMT_VP9: + subsc_params->profile = inst->fw_caps[PROFILE_VP9].value; + subsc_params->level = inst->fw_caps[LEVEL_VP9].value; + break; + case V4L2_PIX_FMT_H264: + subsc_params->profile = inst->fw_caps[PROFILE_H264].value; + subsc_params->level = inst->fw_caps[LEVEL_H264].value; + break; + } + subsc_params->pic_order_cnt = inst->fw_caps[POC].value; subsc_params->bit_depth = inst->fw_caps[BIT_DEPTH].value; if (inst->fw_caps[CODED_FRAMES].value == diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 3e0ae87526a0c..71d23214f224c 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -81,8 +81,12 @@ struct platform_inst_caps { }; enum platform_inst_fw_cap_type { - PROFILE = 1, - LEVEL, + PROFILE_H264 = 1, + PROFILE_HEVC, + PROFILE_VP9, + LEVEL_H264, + LEVEL_HEVC, + LEVEL_VP9, INPUT_BUF_HOST_MAX_COUNT, STAGE, PIPE, diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c index deb7037e8e86f..c2cded2876b74 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c @@ -17,7 +17,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = { { - .cap_id = PROFILE, + .cap_id = PROFILE_H264, .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | @@ -31,7 +31,29 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = { .set = iris_set_u32_enum, }, { - .cap_id = LEVEL, + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = PROFILE_VP9, + .min = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + .max = V4L2_MPEG_VIDEO_VP9_PROFILE_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_0) | + BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_2), + .value = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = LEVEL_H264, .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_2, .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | @@ -59,6 +81,60 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = { .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, .set = iris_set_u32_enum, }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = LEVEL_VP9, + .min = V4L2_MPEG_VIDEO_VP9_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_VP9_LEVEL_6_0, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_6_0), + .value = V4L2_MPEG_VIDEO_VP9_LEVEL_6_0, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = TIER, + .min = V4L2_MPEG_VIDEO_HEVC_TIER_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_TIER_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_TIER_HIGH), + .value = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH, + .hfi_id = HFI_PROP_TIER, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, { .cap_id = INPUT_BUF_HOST_MAX_COUNT, .min = DEFAULT_MAX_HOST_BUF_COUNT, diff --git a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h index f82355d72fcff..a8d66ed388a34 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h +++ b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h @@ -5,48 +5,124 @@ static struct platform_inst_fw_cap inst_fw_cap_qcs8300[] = { { - .cap_id = PROFILE, + .cap_id = PROFILE_H264, .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | - BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) | - BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | - BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | - BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH), + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH), .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, .hfi_id = HFI_PROP_PROFILE, .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, .set = iris_set_u32_enum, }, { - .cap_id = LEVEL, + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = PROFILE_VP9, + .min = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + .max = V4L2_MPEG_VIDEO_VP9_PROFILE_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_0) | + BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_2), + .value = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = LEVEL_H264, .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_2, .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_1) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_2), + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_2), .value = V4L2_MPEG_VIDEO_H264_LEVEL_6_1, .hfi_id = HFI_PROP_LEVEL, .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, .set = iris_set_u32_enum, }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = LEVEL_VP9, + .min = V4L2_MPEG_VIDEO_VP9_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_VP9_LEVEL_6_0, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_6_0), + .value = V4L2_MPEG_VIDEO_VP9_LEVEL_6_0, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = TIER, + .min = V4L2_MPEG_VIDEO_HEVC_TIER_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_TIER_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_TIER_HIGH), + .value = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH, + .hfi_id = HFI_PROP_TIER, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, { .cap_id = INPUT_BUF_HOST_MAX_COUNT, .min = DEFAULT_MAX_HOST_BUF_COUNT, From 0e737005aad7b4c9e3a3ddd56bbb2e639050811d Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:10 +0530 Subject: [PATCH 036/113] FROMLIST: media: iris: Set mandatory properties for HEVC and VP9 decoders. Subscribe and set mandatory properties to the firmware for HEVC and VP9 decoders. Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-24-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- .../platform/qcom/iris/iris_hfi_common.h | 1 + .../qcom/iris/iris_hfi_gen1_command.c | 4 +- .../qcom/iris/iris_hfi_gen2_command.c | 97 +++++++++++++-- .../qcom/iris/iris_hfi_gen2_response.c | 7 ++ .../platform/qcom/iris/iris_platform_common.h | 16 ++- .../platform/qcom/iris/iris_platform_gen2.c | 114 +++++++++++++++--- .../platform/qcom/iris/iris_platform_sm8250.c | 4 +- 7 files changed, 203 insertions(+), 40 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h index b2c541367fc61..9e6aadb837830 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -140,6 +140,7 @@ struct hfi_subscription_params { u32 color_info; u32 profile; u32 level; + u32 tier; }; u32 iris_hfi_get_v4l2_color_primaries(u32 hfi_primaries); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index dbb1b1dab0970..2e3f5a6b2ff11 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -776,8 +776,8 @@ static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 p iris_hfi_gen1_set_bufsize}, }; - config_params = core->iris_platform_data->input_config_params; - config_params_size = core->iris_platform_data->input_config_params_size; + config_params = core->iris_platform_data->input_config_params_default; + config_params_size = core->iris_platform_data->input_config_params_default_size; if (V4L2_TYPE_IS_OUTPUT(plane)) { for (i = 0; i < config_params_size; i++) { diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index 8c91d336ff7e2..7ca5ae13d62b9 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -391,11 +391,28 @@ static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst) sizeof(u64)); } +static int iris_hfi_gen2_set_tier(struct iris_inst *inst) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 tier = inst->fw_caps[TIER].value; + + inst_hfi_gen2->src_subcr_params.tier = tier; + + return iris_hfi_gen2_session_set_property(inst, + HFI_PROP_TIER, + HFI_HOST_FLAGS_NONE, + port, + HFI_PAYLOAD_U32_ENUM, + &tier, + sizeof(u32)); +} + static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 plane) { struct iris_core *core = inst->core; - u32 config_params_size, i, j; - const u32 *config_params; + u32 config_params_size = 0, i, j; + const u32 *config_params = NULL; int ret; static const struct iris_hfi_prop_type_handle prop_type_handle_arr[] = { @@ -410,11 +427,27 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p {HFI_PROP_LEVEL, iris_hfi_gen2_set_level }, {HFI_PROP_COLOR_FORMAT, iris_hfi_gen2_set_colorformat }, {HFI_PROP_LINEAR_STRIDE_SCANLINE, iris_hfi_gen2_set_linear_stride_scanline }, + {HFI_PROP_TIER, iris_hfi_gen2_set_tier }, }; if (V4L2_TYPE_IS_OUTPUT(plane)) { - config_params = core->iris_platform_data->input_config_params; - config_params_size = core->iris_platform_data->input_config_params_size; + switch (inst->codec) { + case V4L2_PIX_FMT_H264: + config_params = core->iris_platform_data->input_config_params_default; + config_params_size = + core->iris_platform_data->input_config_params_default_size; + break; + case V4L2_PIX_FMT_HEVC: + config_params = core->iris_platform_data->input_config_params_hevc; + config_params_size = + core->iris_platform_data->input_config_params_hevc_size; + break; + case V4L2_PIX_FMT_VP9: + config_params = core->iris_platform_data->input_config_params_vp9; + config_params_size = + core->iris_platform_data->input_config_params_vp9_size; + break; + } } else { config_params = core->iris_platform_data->output_config_params; config_params_size = core->iris_platform_data->output_config_params_size; @@ -584,8 +617,8 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan struct hfi_subscription_params subsc_params; u32 prop_type, payload_size, payload_type; struct iris_core *core = inst->core; - const u32 *change_param; - u32 change_param_size; + const u32 *change_param = NULL; + u32 change_param_size = 0; u32 payload[32] = {0}; u32 hfi_port = 0, i; int ret; @@ -596,8 +629,23 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan return 0; } - change_param = core->iris_platform_data->input_config_params; - change_param_size = core->iris_platform_data->input_config_params_size; + switch (inst->codec) { + case V4L2_PIX_FMT_H264: + change_param = core->iris_platform_data->input_config_params_default; + change_param_size = + core->iris_platform_data->input_config_params_default_size; + break; + case V4L2_PIX_FMT_HEVC: + change_param = core->iris_platform_data->input_config_params_hevc; + change_param_size = + core->iris_platform_data->input_config_params_hevc_size; + break; + case V4L2_PIX_FMT_VP9: + change_param = core->iris_platform_data->input_config_params_vp9; + change_param_size = + core->iris_platform_data->input_config_params_vp9_size; + break; + } payload[0] = HFI_MODE_PORT_SETTINGS_CHANGE; @@ -644,6 +692,11 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan payload_size = sizeof(u32); payload_type = HFI_PAYLOAD_U32; break; + case HFI_PROP_LUMA_CHROMA_BIT_DEPTH: + payload[0] = subsc_params.bit_depth; + payload_size = sizeof(u32); + payload_type = HFI_PAYLOAD_U32; + break; case HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT: payload[0] = subsc_params.fw_min_count; payload_size = sizeof(u32); @@ -669,6 +722,11 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan payload_size = sizeof(u32); payload_type = HFI_PAYLOAD_U32; break; + case HFI_PROP_TIER: + payload[0] = subsc_params.tier; + payload_size = sizeof(u32); + payload_type = HFI_PAYLOAD_U32; + break; default: prop_type = 0; ret = -EINVAL; @@ -695,8 +753,8 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan static int iris_hfi_gen2_subscribe_property(struct iris_inst *inst, u32 plane) { struct iris_core *core = inst->core; - u32 subscribe_prop_size, i; - const u32 *subcribe_prop; + u32 subscribe_prop_size = 0, i; + const u32 *subcribe_prop = NULL; u32 payload[32] = {0}; payload[0] = HFI_MODE_PROPERTY; @@ -705,8 +763,23 @@ static int iris_hfi_gen2_subscribe_property(struct iris_inst *inst, u32 plane) subscribe_prop_size = core->iris_platform_data->dec_input_prop_size; subcribe_prop = core->iris_platform_data->dec_input_prop; } else { - subscribe_prop_size = core->iris_platform_data->dec_output_prop_size; - subcribe_prop = core->iris_platform_data->dec_output_prop; + switch (inst->codec) { + case V4L2_PIX_FMT_H264: + subcribe_prop = core->iris_platform_data->dec_output_prop_avc; + subscribe_prop_size = + core->iris_platform_data->dec_output_prop_avc_size; + break; + case V4L2_PIX_FMT_HEVC: + subcribe_prop = core->iris_platform_data->dec_output_prop_hevc; + subscribe_prop_size = + core->iris_platform_data->dec_output_prop_hevc_size; + break; + case V4L2_PIX_FMT_VP9: + subcribe_prop = core->iris_platform_data->dec_output_prop_vp9; + subscribe_prop_size = + core->iris_platform_data->dec_output_prop_vp9_size; + break; + } } for (i = 0; i < subscribe_prop_size; i++) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index 8e54962414aeb..a8c30fc5c0d06 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -587,6 +587,7 @@ static void iris_hfi_gen2_read_input_subcr_params(struct iris_inst *inst) } inst->fw_caps[POC].value = subsc_params.pic_order_cnt; + inst->fw_caps[TIER].value = subsc_params.tier; if (subsc_params.bit_depth != BIT_DEPTH_8 || !(subsc_params.coded_frames & HFI_BITMASK_FRAME_MBS_ONLY_FLAG)) { @@ -668,6 +669,9 @@ static int iris_hfi_gen2_handle_session_property(struct iris_inst *inst, inst_hfi_gen2->src_subcr_params.crop_offsets[0] = pkt->payload[0]; inst_hfi_gen2->src_subcr_params.crop_offsets[1] = pkt->payload[1]; break; + case HFI_PROP_LUMA_CHROMA_BIT_DEPTH: + inst_hfi_gen2->src_subcr_params.bit_depth = pkt->payload[0]; + break; case HFI_PROP_CODED_FRAMES: inst_hfi_gen2->src_subcr_params.coded_frames = pkt->payload[0]; break; @@ -686,6 +690,9 @@ static int iris_hfi_gen2_handle_session_property(struct iris_inst *inst, case HFI_PROP_LEVEL: inst_hfi_gen2->src_subcr_params.level = pkt->payload[0]; break; + case HFI_PROP_TIER: + inst_hfi_gen2->src_subcr_params.tier = pkt->payload[0]; + break; case HFI_PROP_PICTURE_TYPE: inst_hfi_gen2->hfi_frame_info.picture_type = pkt->payload[0]; break; diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 71d23214f224c..adafdce8a856f 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -179,14 +179,22 @@ struct iris_platform_data { u32 max_session_count; /* max number of macroblocks per frame supported */ u32 max_core_mbpf; - const u32 *input_config_params; - unsigned int input_config_params_size; + const u32 *input_config_params_default; + unsigned int input_config_params_default_size; + const u32 *input_config_params_hevc; + unsigned int input_config_params_hevc_size; + const u32 *input_config_params_vp9; + unsigned int input_config_params_vp9_size; const u32 *output_config_params; unsigned int output_config_params_size; const u32 *dec_input_prop; unsigned int dec_input_prop_size; - const u32 *dec_output_prop; - unsigned int dec_output_prop_size; + const u32 *dec_output_prop_avc; + unsigned int dec_output_prop_avc_size; + const u32 *dec_output_prop_hevc; + unsigned int dec_output_prop_hevc_size; + const u32 *dec_output_prop_vp9; + unsigned int dec_output_prop_vp9_size; const u32 *dec_ip_int_buf_tbl; unsigned int dec_ip_int_buf_tbl_size; const u32 *dec_op_int_buf_tbl; diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c index c2cded2876b74..d3026b2bcb708 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c @@ -257,9 +257,10 @@ static struct tz_cp_config tz_cp_config_sm8550 = { .cp_nonpixel_size = 0x24800000, }; -static const u32 sm8550_vdec_input_config_params[] = { +static const u32 sm8550_vdec_input_config_params_default[] = { HFI_PROP_BITSTREAM_RESOLUTION, HFI_PROP_CROP_OFFSETS, + HFI_PROP_LUMA_CHROMA_BIT_DEPTH, HFI_PROP_CODED_FRAMES, HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT, HFI_PROP_PIC_ORDER_CNT_TYPE, @@ -268,6 +269,26 @@ static const u32 sm8550_vdec_input_config_params[] = { HFI_PROP_SIGNAL_COLOR_INFO, }; +static const u32 sm8550_vdec_input_config_param_hevc[] = { + HFI_PROP_BITSTREAM_RESOLUTION, + HFI_PROP_CROP_OFFSETS, + HFI_PROP_LUMA_CHROMA_BIT_DEPTH, + HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT, + HFI_PROP_PROFILE, + HFI_PROP_LEVEL, + HFI_PROP_TIER, + HFI_PROP_SIGNAL_COLOR_INFO, +}; + +static const u32 sm8550_vdec_input_config_param_vp9[] = { + HFI_PROP_BITSTREAM_RESOLUTION, + HFI_PROP_CROP_OFFSETS, + HFI_PROP_LUMA_CHROMA_BIT_DEPTH, + HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT, + HFI_PROP_PROFILE, + HFI_PROP_LEVEL, +}; + static const u32 sm8550_vdec_output_config_params[] = { HFI_PROP_COLOR_FORMAT, HFI_PROP_LINEAR_STRIDE_SCANLINE, @@ -277,11 +298,19 @@ static const u32 sm8550_vdec_subscribe_input_properties[] = { HFI_PROP_NO_OUTPUT, }; -static const u32 sm8550_vdec_subscribe_output_properties[] = { +static const u32 sm8550_vdec_subscribe_output_properties_avc[] = { HFI_PROP_PICTURE_TYPE, HFI_PROP_CABAC_SESSION, }; +static const u32 sm8550_vdec_subscribe_output_properties_hevc[] = { + HFI_PROP_PICTURE_TYPE, +}; + +static const u32 sm8550_vdec_subscribe_output_properties_vp9[] = { + HFI_PROP_PICTURE_TYPE, +}; + static const u32 sm8550_dec_ip_int_buf_tbl[] = { BUF_BIN, BUF_COMV, @@ -325,18 +354,33 @@ struct iris_platform_data sm8550_data = { .num_vpp_pipe = 4, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, - .input_config_params = - sm8550_vdec_input_config_params, - .input_config_params_size = - ARRAY_SIZE(sm8550_vdec_input_config_params), + .input_config_params_default = + sm8550_vdec_input_config_params_default, + .input_config_params_default_size = + ARRAY_SIZE(sm8550_vdec_input_config_params_default), + .input_config_params_hevc = + sm8550_vdec_input_config_param_hevc, + .input_config_params_hevc_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), + .input_config_params_vp9 = + sm8550_vdec_input_config_param_vp9, + .input_config_params_vp9_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), .output_config_params = sm8550_vdec_output_config_params, .output_config_params_size = ARRAY_SIZE(sm8550_vdec_output_config_params), .dec_input_prop = sm8550_vdec_subscribe_input_properties, .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), - .dec_output_prop = sm8550_vdec_subscribe_output_properties, - .dec_output_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_output_properties), + .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, + .dec_output_prop_avc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_avc), + .dec_output_prop_hevc = sm8550_vdec_subscribe_output_properties_hevc, + .dec_output_prop_hevc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_hevc), + .dec_output_prop_vp9 = sm8550_vdec_subscribe_output_properties_vp9, + .dec_output_prop_vp9_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_vp9), .dec_ip_int_buf_tbl = sm8550_dec_ip_int_buf_tbl, .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), @@ -385,18 +429,33 @@ struct iris_platform_data sm8650_data = { .num_vpp_pipe = 4, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, - .input_config_params = - sm8550_vdec_input_config_params, - .input_config_params_size = - ARRAY_SIZE(sm8550_vdec_input_config_params), + .input_config_params_default = + sm8550_vdec_input_config_params_default, + .input_config_params_default_size = + ARRAY_SIZE(sm8550_vdec_input_config_params_default), + .input_config_params_hevc = + sm8550_vdec_input_config_param_hevc, + .input_config_params_hevc_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), + .input_config_params_vp9 = + sm8550_vdec_input_config_param_vp9, + .input_config_params_vp9_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), .output_config_params = sm8550_vdec_output_config_params, .output_config_params_size = ARRAY_SIZE(sm8550_vdec_output_config_params), .dec_input_prop = sm8550_vdec_subscribe_input_properties, .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), - .dec_output_prop = sm8550_vdec_subscribe_output_properties, - .dec_output_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_output_properties), + .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, + .dec_output_prop_avc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_avc), + .dec_output_prop_hevc = sm8550_vdec_subscribe_output_properties_hevc, + .dec_output_prop_hevc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_hevc), + .dec_output_prop_vp9 = sm8550_vdec_subscribe_output_properties_vp9, + .dec_output_prop_vp9_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_vp9), .dec_ip_int_buf_tbl = sm8550_dec_ip_int_buf_tbl, .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), @@ -441,18 +500,33 @@ struct iris_platform_data qcs8300_data = { .num_vpp_pipe = 2, .max_session_count = 16, .max_core_mbpf = ((4096 * 2176) / 256) * 4, - .input_config_params = - sm8550_vdec_input_config_params, - .input_config_params_size = - ARRAY_SIZE(sm8550_vdec_input_config_params), + .input_config_params_default = + sm8550_vdec_input_config_params_default, + .input_config_params_default_size = + ARRAY_SIZE(sm8550_vdec_input_config_params_default), + .input_config_params_hevc = + sm8550_vdec_input_config_param_hevc, + .input_config_params_hevc_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), + .input_config_params_vp9 = + sm8550_vdec_input_config_param_vp9, + .input_config_params_vp9_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), .output_config_params = sm8550_vdec_output_config_params, .output_config_params_size = ARRAY_SIZE(sm8550_vdec_output_config_params), .dec_input_prop = sm8550_vdec_subscribe_input_properties, .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), - .dec_output_prop = sm8550_vdec_subscribe_output_properties, - .dec_output_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_output_properties), + .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, + .dec_output_prop_avc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_avc), + .dec_output_prop_hevc = sm8550_vdec_subscribe_output_properties_hevc, + .dec_output_prop_hevc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_hevc), + .dec_output_prop_vp9 = sm8550_vdec_subscribe_output_properties_vp9, + .dec_output_prop_vp9_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_vp9), .dec_ip_int_buf_tbl = sm8550_dec_ip_int_buf_tbl, .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c index 8183e4e95fa4e..8d0816a67ae0b 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c @@ -128,9 +128,9 @@ struct iris_platform_data sm8250_data = { .num_vpp_pipe = 4, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K, - .input_config_params = + .input_config_params_default = sm8250_vdec_input_config_param_default, - .input_config_params_size = + .input_config_params_default_size = ARRAY_SIZE(sm8250_vdec_input_config_param_default), .dec_ip_int_buf_tbl = sm8250_dec_ip_int_buf_tbl, From afa67f44bc5df83491e3b838fa47eceb11597f44 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:11 +0530 Subject: [PATCH 037/113] FROMLIST: media: iris: Add internal buffer calculation for HEVC and VP9 decoders Add internal buffer count and size calculations for HEVC and VP9 decoders. Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-25-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- .../media/platform/qcom/iris/iris_buffer.c | 3 + .../platform/qcom/iris/iris_vpu_buffer.c | 397 +++++++++++++++++- .../platform/qcom/iris/iris_vpu_buffer.h | 46 +- 3 files changed, 432 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index 7dbac74b1a8de..6425e4919e3b0 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -205,6 +205,9 @@ static u32 iris_bitstream_buffer_size(struct iris_inst *inst) if (num_mbs > NUM_MBS_4K) { div_factor = 4; base_res_mbs = caps->max_mbpf; + } else { + if (inst->codec == V4L2_PIX_FMT_VP9) + div_factor = 1; } /* diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index dce25e410d80b..13ee93356bcb0 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -31,6 +31,42 @@ static u32 hfi_buffer_bin_h264d(u32 frame_width, u32 frame_height, u32 num_vpp_p return size_h264d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes); } +static u32 size_h265d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 product = frame_width * frame_height; + u32 size_yuv, size_bin_hdr, size_bin_res; + + size_yuv = (product <= BIN_BUFFER_THRESHOLD) ? + ((BIN_BUFFER_THRESHOLD * 3) >> 1) : ((product * 3) >> 1); + size_bin_hdr = size_yuv * H265_CABAC_HDR_RATIO_HD_TOT; + size_bin_res = size_yuv * H265_CABAC_RES_RATIO_HD_TOT; + size_bin_hdr = ALIGN(size_bin_hdr / num_vpp_pipes, DMA_ALIGNMENT) * num_vpp_pipes; + size_bin_res = ALIGN(size_bin_res / num_vpp_pipes, DMA_ALIGNMENT) * num_vpp_pipes; + + return size_bin_hdr + size_bin_res; +} + +static u32 hfi_buffer_bin_vp9d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 _size_yuv = ALIGN(frame_width, 16) * ALIGN(frame_height, 16) * 3 / 2; + u32 _size = ALIGN(((max_t(u32, _size_yuv, ((BIN_BUFFER_THRESHOLD * 3) >> 1)) * + VPX_DECODER_FRAME_BIN_HDR_BUDGET / VPX_DECODER_FRAME_BIN_DENOMINATOR * + VPX_DECODER_FRAME_CONCURENCY_LVL) / num_vpp_pipes), DMA_ALIGNMENT) + + ALIGN(((max_t(u32, _size_yuv, ((BIN_BUFFER_THRESHOLD * 3) >> 1)) * + VPX_DECODER_FRAME_BIN_RES_BUDGET / VPX_DECODER_FRAME_BIN_DENOMINATOR * + VPX_DECODER_FRAME_CONCURENCY_LVL) / num_vpp_pipes), DMA_ALIGNMENT); + + return _size * num_vpp_pipes; +} + +static u32 hfi_buffer_bin_h265d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 n_aligned_w = ALIGN(frame_width, 16); + u32 n_aligned_h = ALIGN(frame_height, 16); + + return size_h265d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes); +} + static u32 hfi_buffer_comv_h264d(u32 frame_width, u32 frame_height, u32 _comv_bufcount) { u32 frame_height_in_mbs = DIV_ROUND_UP(frame_height, 16); @@ -55,6 +91,17 @@ static u32 hfi_buffer_comv_h264d(u32 frame_width, u32 frame_height, u32 _comv_bu return (size_colloc * (_comv_bufcount)) + 512; } +static u32 hfi_buffer_comv_h265d(u32 frame_width, u32 frame_height, u32 _comv_bufcount) +{ + u32 frame_height_in_mbs = (frame_height + 15) >> 4; + u32 frame_width_in_mbs = (frame_width + 15) >> 4; + u32 _size; + + _size = ALIGN(((frame_width_in_mbs * frame_height_in_mbs) << 8), 512); + + return (_size * (_comv_bufcount)) + 512; +} + static u32 size_h264d_bse_cmd_buf(u32 frame_height) { u32 height = ALIGN(frame_height, 32); @@ -63,6 +110,44 @@ static u32 size_h264d_bse_cmd_buf(u32 frame_height) SIZE_H264D_BSE_CMD_PER_BUF; } +static u32 size_h265d_bse_cmd_buf(u32 frame_width, u32 frame_height) +{ + u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * + (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS)) * + NUM_HW_PIC_BUF, DMA_ALIGNMENT); + _size = min_t(u32, _size, H265D_MAX_SLICE + 1); + _size = 2 * _size * SIZE_H265D_BSE_CMD_PER_BUF; + + return _size; +} + +static u32 hfi_buffer_persist_h265d(u32 rpu_enabled) +{ + return ALIGN((SIZE_SLIST_BUF_H265 * NUM_SLIST_BUF_H265 + + H265_NUM_FRM_INFO * H265_DISPLAY_BUF_SIZE + + H265_NUM_TILE * sizeof(u32) + + NUM_HW_PIC_BUF * SIZE_SEI_USERDATA + + rpu_enabled * NUM_HW_PIC_BUF * SIZE_DOLBY_RPU_METADATA), + DMA_ALIGNMENT); +} + +static inline +u32 hfi_iris3_vp9d_comv_size(void) +{ + return (((8192 + 63) >> 6) * ((4320 + 63) >> 6) * 8 * 8 * 2 * 8); +} + +static u32 hfi_buffer_persist_vp9d(void) +{ + return ALIGN(VP9_NUM_PROBABILITY_TABLE_BUF * VP9_PROB_TABLE_SIZE, DMA_ALIGNMENT) + + ALIGN(hfi_iris3_vp9d_comv_size(), DMA_ALIGNMENT) + + ALIGN(MAX_SUPERFRAME_HEADER_LEN, DMA_ALIGNMENT) + + ALIGN(VP9_UDC_HEADER_BUF_SIZE, DMA_ALIGNMENT) + + ALIGN(VP9_NUM_FRAME_INFO_BUF * CCE_TILE_OFFSET_SIZE, DMA_ALIGNMENT) + + ALIGN(VP9_NUM_FRAME_INFO_BUF * VP9_FRAME_INFO_BUF_SIZE, DMA_ALIGNMENT) + + HDR10_HIST_EXTRADATA_SIZE; +} + static u32 size_h264d_vpp_cmd_buf(u32 frame_height) { u32 size, height = ALIGN(frame_height, 32); @@ -83,17 +168,45 @@ static u32 hfi_buffer_persist_h264d(void) static u32 hfi_buffer_non_comv_h264d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) { - u32 size_bse, size_vpp, size; - - size_bse = size_h264d_bse_cmd_buf(frame_height); - size_vpp = size_h264d_vpp_cmd_buf(frame_height); - size = ALIGN(size_bse, DMA_ALIGNMENT) + + u32 size_bse = size_h264d_bse_cmd_buf(frame_height); + u32 size_vpp = size_h264d_vpp_cmd_buf(frame_height); + u32 size = ALIGN(size_bse, DMA_ALIGNMENT) + ALIGN(size_vpp, DMA_ALIGNMENT) + ALIGN(SIZE_HW_PIC(SIZE_H264D_HW_PIC_T), DMA_ALIGNMENT); return ALIGN(size, DMA_ALIGNMENT); } +static u32 size_h265d_vpp_cmd_buf(u32 frame_width, u32 frame_height) +{ + u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * + (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS)) * + NUM_HW_PIC_BUF, DMA_ALIGNMENT); + _size = min_t(u32, _size, H265D_MAX_SLICE + 1); + _size = ALIGN(_size, 4); + _size = 2 * _size * SIZE_H265D_VPP_CMD_PER_BUF; + if (_size > VPP_CMD_MAX_SIZE) + _size = VPP_CMD_MAX_SIZE; + + return _size; +} + +static u32 hfi_buffer_non_comv_h265d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 _size_bse = size_h265d_bse_cmd_buf(frame_width, frame_height); + u32 _size_vpp = size_h265d_vpp_cmd_buf(frame_width, frame_height); + u32 _size = ALIGN(_size_bse, DMA_ALIGNMENT) + + ALIGN(_size_vpp, DMA_ALIGNMENT) + + ALIGN(NUM_HW_PIC_BUF * 20 * 22 * 4, DMA_ALIGNMENT) + + ALIGN(2 * sizeof(u16) * + (ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * + (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS), DMA_ALIGNMENT) + + ALIGN(SIZE_HW_PIC(SIZE_H265D_HW_PIC_T), DMA_ALIGNMENT) + + HDR10_HIST_EXTRADATA_SIZE; + + return ALIGN(_size, DMA_ALIGNMENT); +} + static u32 size_vpss_lb(u32 frame_width, u32 frame_height) { u32 opb_lb_wr_llb_y_buffer_size, opb_lb_wr_llb_uv_buffer_size; @@ -119,6 +232,203 @@ static u32 size_vpss_lb(u32 frame_width, u32 frame_height) opb_lb_wr_llb_y_buffer_size; } +static inline +u32 size_h265d_lb_fe_top_data(u32 frame_width, u32 frame_height) +{ + return MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * + (ALIGN(frame_width, 64) + 8) * 2; +} + +static inline +u32 size_h265d_lb_fe_top_ctrl(u32 frame_width, u32 frame_height) +{ + return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * + (ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS); +} + +static inline +u32 size_h265d_lb_fe_left_ctrl(u32 frame_width, u32 frame_height) +{ + return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * + (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS); +} + +static inline +u32 size_h265d_lb_se_top_ctrl(u32 frame_width, u32 frame_height) +{ + return (LCU_MAX_SIZE_PELS / 8 * (128 / 8)) * ((frame_width + 15) >> 4); +} + +static inline +u32 size_h265d_lb_se_left_ctrl(u32 frame_width, u32 frame_height) +{ + return max_t(u32, ((frame_height + 16 - 1) / 8) * + MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE, + max_t(u32, ((frame_height + 32 - 1) / 8) * + MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE, + ((frame_height + 64 - 1) / 8) * + MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE)); +} + +static inline +u32 size_h265d_lb_pe_top_data(u32 frame_width, u32 frame_height) +{ + return MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE * + (ALIGN(frame_width, LCU_MIN_SIZE_PELS) / LCU_MIN_SIZE_PELS); +} + +static inline +u32 size_h265d_lb_vsp_top(u32 frame_width, u32 frame_height) +{ + return ((frame_width + 63) >> 6) * 128; +} + +static inline +u32 size_h265d_lb_vsp_left(u32 frame_width, u32 frame_height) +{ + return ((frame_height + 63) >> 6) * 128; +} + +static inline +u32 size_h265d_lb_recon_dma_metadata_wr(u32 frame_width, u32 frame_height) +{ + return size_h264d_lb_recon_dma_metadata_wr(frame_height); +} + +static inline +u32 size_h265d_qp(u32 frame_width, u32 frame_height) +{ + return size_h264d_qp(frame_width, frame_height); +} + +static inline +u32 hfi_buffer_line_h265d(u32 frame_width, u32 frame_height, bool is_opb, u32 num_vpp_pipes) +{ + u32 vpss_lb_size = 0, _size; + + _size = ALIGN(size_h265d_lb_fe_top_data(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_fe_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_fe_left_ctrl(frame_width, frame_height), + DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h265d_lb_se_left_ctrl(frame_width, frame_height), + DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h265d_lb_se_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_pe_top_data(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_vsp_top(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_vsp_left(frame_width, frame_height), + DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h265d_lb_recon_dma_metadata_wr(frame_width, frame_height), + DMA_ALIGNMENT) * 4 + + ALIGN(size_h265d_qp(frame_width, frame_height), DMA_ALIGNMENT); + if (is_opb) + vpss_lb_size = size_vpss_lb(frame_width, frame_height); + + return ALIGN((_size + vpss_lb_size), DMA_ALIGNMENT); +} + +static inline +u32 size_vpxd_lb_fe_left_ctrl(u32 frame_width, u32 frame_height) +{ + return max_t(u32, ((frame_height + 15) >> 4) * + MAX_FE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE, + max_t(u32, ((frame_height + 31) >> 5) * + MAX_FE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE, + ((frame_height + 63) >> 6) * + MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE)); +} + +static inline +u32 size_vpxd_lb_fe_top_ctrl(u32 frame_width, u32 frame_height) +{ + return ((ALIGN(frame_width, 64) + 8) * 10 * 2); +} + +static inline +u32 size_vpxd_lb_se_top_ctrl(u32 frame_width, u32 frame_height) +{ + return ((frame_width + 15) >> 4) * MAX_FE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE; +} + +static inline +u32 size_vpxd_lb_se_left_ctrl(u32 frame_width, u32 frame_height) +{ + return max_t(u32, ((frame_height + 15) >> 4) * + MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE, + max_t(u32, ((frame_height + 31) >> 5) * + MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE, + ((frame_height + 63) >> 6) * + MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE)); +} + +static inline +u32 size_vpxd_lb_recon_dma_metadata_wr(u32 frame_width, u32 frame_height) +{ + return ALIGN((ALIGN(frame_height, 8) / (4 / 2)) * 64, + BUFFER_ALIGNMENT_32_BYTES); +} + +static inline +u32 size_mp2d_lb_fe_top_data(u32 frame_width, u32 frame_height) +{ + return ((ALIGN(frame_width, 16) + 8) * 10 * 2); +} + +static inline +u32 size_vp9d_lb_fe_top_data(u32 frame_width, u32 frame_height) +{ + return (ALIGN(ALIGN(frame_width, 8), 64) + 8) * 10 * 2; +} + +static inline +u32 size_vp9d_lb_pe_top_data(u32 frame_width, u32 frame_height) +{ + return ((ALIGN(ALIGN(frame_width, 8), 64) >> 6) * 176); +} + +static inline +u32 size_vp9d_lb_vsp_top(u32 frame_width, u32 frame_height) +{ + return (((ALIGN(ALIGN(frame_width, 8), 64) >> 6) * 64 * 8) + 256); +} + +static inline +u32 size_vp9d_qp(u32 frame_width, u32 frame_height) +{ + return size_h264d_qp(frame_width, frame_height); +} + +static inline +u32 hfi_iris3_vp9d_lb_size(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + return ALIGN(size_vpxd_lb_fe_left_ctrl(frame_width, frame_height), DMA_ALIGNMENT) * + num_vpp_pipes + + ALIGN(size_vpxd_lb_se_left_ctrl(frame_width, frame_height), DMA_ALIGNMENT) * + num_vpp_pipes + + ALIGN(size_vp9d_lb_vsp_top(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_vpxd_lb_fe_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) + + 2 * ALIGN(size_vpxd_lb_recon_dma_metadata_wr(frame_width, frame_height), + DMA_ALIGNMENT) + + ALIGN(size_vpxd_lb_se_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_vp9d_lb_pe_top_data(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_vp9d_lb_fe_top_data(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_vp9d_qp(frame_width, frame_height), DMA_ALIGNMENT); +} + +static inline +u32 hfi_buffer_line_vp9d(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_min, bool is_opb, + u32 num_vpp_pipes) +{ + u32 vpss_lb_size = 0; + u32 _lb_size; + + _lb_size = hfi_iris3_vp9d_lb_size(frame_width, frame_height, num_vpp_pipes); + + if (is_opb) + vpss_lb_size = size_vpss_lb(frame_width, frame_height); + + return _lb_size + vpss_lb_size + 4096; +} + static u32 hfi_buffer_line_h264d(u32 frame_width, u32 frame_height, bool is_opb, u32 num_vpp_pipes) { @@ -148,7 +458,14 @@ static u32 iris_vpu_dec_bin_size(struct iris_inst *inst) u32 height = f->fmt.pix_mp.height; u32 width = f->fmt.pix_mp.width; - return hfi_buffer_bin_h264d(width, height, num_vpp_pipes); + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_bin_h264d(width, height, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_bin_h265d(width, height, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_VP9) + return hfi_buffer_bin_vp9d(width, height, num_vpp_pipes); + + return 0; } static u32 iris_vpu_dec_comv_size(struct iris_inst *inst) @@ -158,12 +475,24 @@ static u32 iris_vpu_dec_comv_size(struct iris_inst *inst) u32 height = f->fmt.pix_mp.height; u32 width = f->fmt.pix_mp.width; - return hfi_buffer_comv_h264d(width, height, num_comv); + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_comv_h264d(width, height, num_comv); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_comv_h265d(width, height, num_comv); + + return 0; } static u32 iris_vpu_dec_persist_size(struct iris_inst *inst) { - return hfi_buffer_persist_h264d(); + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_persist_h264d(); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_persist_h265d(0); + else if (inst->codec == V4L2_PIX_FMT_VP9) + return hfi_buffer_persist_vp9d(); + + return 0; } static u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) @@ -181,7 +510,12 @@ static u32 iris_vpu_dec_non_comv_size(struct iris_inst *inst) u32 height = f->fmt.pix_mp.height; u32 width = f->fmt.pix_mp.width; - return hfi_buffer_non_comv_h264d(width, height, num_vpp_pipes); + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_non_comv_h264d(width, height, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_non_comv_h265d(width, height, num_vpp_pipes); + + return 0; } static u32 iris_vpu_dec_line_size(struct iris_inst *inst) @@ -191,11 +525,20 @@ static u32 iris_vpu_dec_line_size(struct iris_inst *inst) u32 height = f->fmt.pix_mp.height; u32 width = f->fmt.pix_mp.width; bool is_opb = false; + u32 out_min_count = inst->buffers[BUF_OUTPUT].min_count; if (iris_split_mode_enabled(inst)) is_opb = true; - return hfi_buffer_line_h264d(width, height, is_opb, num_vpp_pipes); + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_line_h264d(width, height, is_opb, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_line_h265d(width, height, is_opb, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_VP9) + return hfi_buffer_line_vp9d(width, height, out_min_count, is_opb, + num_vpp_pipes); + + return 0; } static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst) @@ -205,6 +548,24 @@ static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst) iris_vpu_dec_line_size(inst); } +static int output_min_count(struct iris_inst *inst) +{ + int output_min_count = 4; + + /* fw_min_count > 0 indicates reconfig event has already arrived */ + if (inst->fw_min_count) { + if (iris_split_mode_enabled(inst) && inst->codec == V4L2_PIX_FMT_VP9) + return min_t(u32, 4, inst->fw_min_count); + else + return inst->fw_min_count; + } + + if (inst->codec == V4L2_PIX_FMT_VP9) + output_min_count = 9; + + return output_min_count; +} + struct iris_vpu_buf_type_handle { enum iris_buffer_type type; u32 (*handle)(struct iris_inst *inst); @@ -238,6 +599,19 @@ int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) return size; } +static u32 internal_buffer_count(struct iris_inst *inst, + enum iris_buffer_type buffer_type) +{ + if (buffer_type == BUF_BIN || buffer_type == BUF_LINE || + buffer_type == BUF_PERSIST) { + return 1; + } else if (buffer_type == BUF_COMV || buffer_type == BUF_NON_COMV) { + if (inst->codec == V4L2_PIX_FMT_H264 || inst->codec == V4L2_PIX_FMT_HEVC) + return 1; + } + return 0; +} + static inline int iris_vpu_dpb_count(struct iris_inst *inst) { if (iris_split_mode_enabled(inst)) { @@ -254,12 +628,13 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type case BUF_INPUT: return MIN_BUFFERS; case BUF_OUTPUT: - return inst->fw_min_count; + return output_min_count(inst); case BUF_BIN: case BUF_COMV: case BUF_NON_COMV: case BUF_LINE: case BUF_PERSIST: + return internal_buffer_count(inst, buffer_type); case BUF_SCRATCH_1: return 1; /* internal buffer count needed by firmware is 1 */ case BUF_DPB: diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h index 62af6ea6ba1fe..ee95fd20b794c 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -13,6 +13,10 @@ struct iris_inst; #define DMA_ALIGNMENT 256 #define NUM_HW_PIC_BUF 32 +#define LCU_MAX_SIZE_PELS 64 +#define LCU_MIN_SIZE_PELS 16 +#define HDR10_HIST_EXTRADATA_SIZE (4 * 1024) + #define SIZE_HW_PIC(size_per_buf) (NUM_HW_PIC_BUF * (size_per_buf)) #define MAX_TILE_COLUMNS 32 @@ -28,11 +32,47 @@ struct iris_inst; #define SIZE_SLIST_BUF_H264 512 #define H264_DISPLAY_BUF_SIZE 3328 #define H264_NUM_FRM_INFO 66 - -#define SIZE_SEI_USERDATA 4096 - +#define H265_NUM_TILE_COL 32 +#define H265_NUM_TILE_ROW 128 +#define H265_NUM_TILE (H265_NUM_TILE_ROW * H265_NUM_TILE_COL + 1) +#define SIZE_H265D_BSE_CMD_PER_BUF (16 * sizeof(u32)) + +#define NUM_SLIST_BUF_H265 (80 + 20) +#define SIZE_SLIST_BUF_H265 (BIT(10)) +#define H265_DISPLAY_BUF_SIZE (3072) +#define H265_NUM_FRM_INFO (48) + +#define VP9_NUM_FRAME_INFO_BUF 32 +#define VP9_NUM_PROBABILITY_TABLE_BUF (VP9_NUM_FRAME_INFO_BUF + 4) +#define VP9_PROB_TABLE_SIZE (3840) +#define VP9_FRAME_INFO_BUF_SIZE (6144) +#define BUFFER_ALIGNMENT_32_BYTES 32 +#define CCE_TILE_OFFSET_SIZE ALIGN(32 * 4 * 4, BUFFER_ALIGNMENT_32_BYTES) +#define MAX_SUPERFRAME_HEADER_LEN (34) +#define MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 64 +#define MAX_FE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE 64 +#define MAX_FE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE 64 +#define MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE (128 / 8) +#define MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE (128 / 8) +#define VP9_UDC_HEADER_BUF_SIZE (3 * 128) + +#define SIZE_SEI_USERDATA 4096 +#define SIZE_DOLBY_RPU_METADATA (41 * 1024) #define H264_CABAC_HDR_RATIO_HD_TOT 1 #define H264_CABAC_RES_RATIO_HD_TOT 3 +#define H265D_MAX_SLICE 1200 +#define SIZE_H265D_HW_PIC_T SIZE_H264D_HW_PIC_T +#define H265_CABAC_HDR_RATIO_HD_TOT 2 +#define H265_CABAC_RES_RATIO_HD_TOT 2 +#define SIZE_H265D_VPP_CMD_PER_BUF (256) + +#define VPX_DECODER_FRAME_CONCURENCY_LVL (2) +#define VPX_DECODER_FRAME_BIN_HDR_BUDGET 1 +#define VPX_DECODER_FRAME_BIN_RES_BUDGET 3 +#define VPX_DECODER_FRAME_BIN_DENOMINATOR 2 + +#define VPX_DECODER_FRAME_BIN_RES_BUDGET_RATIO (3 / 2) + #define SIZE_H264D_HW_PIC_T (BIT(11)) #define MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 64 From 8e7bd4865e2a6767264326990b942dc8c61bc40d Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 9 May 2025 14:09:12 +0530 Subject: [PATCH 038/113] FROMLIST: media: iris: Add codec specific check for VP9 decoder drain handling Add a codec specific for the VP9 decoder to ensure that a non-null buffer is sent to the firmware during drain. The firmware enforces a check for VP9 decoder that the number of buffers queued and dequeued on the output plane should match. When a null buffer is sent, the firmware does not return a response for it, leading to a count mismatch and an assertion failure from the firmware. Link: https://lore.kernel.org/linux-arm-msm/20250509-video-iris-hevc-vp9-v5-26-59b4ff7d331c@quicinc.com/ Acked-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-QRD Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Tested-by: Vikash Garodia # on sa8775p-ride Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c | 2 ++ drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index 2e3f5a6b2ff11..5fc30d54af4dc 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -401,6 +401,8 @@ static int iris_hfi_gen1_session_drain(struct iris_inst *inst, u32 plane) ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; ip_pkt.shdr.session_id = inst->session_id; ip_pkt.flags = HFI_BUFFERFLAG_EOS; + if (inst->codec == V4L2_PIX_FMT_VP9) + ip_pkt.packet_buffer = 0xdeadb000; return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size); } diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index 926acee1f48cc..8d1ce8a19a45e 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -348,6 +348,10 @@ static void iris_hfi_gen1_session_etb_done(struct iris_inst *inst, void *packet) struct iris_buffer *buf = NULL; bool found = false; + /* EOS buffer sent via drain won't be in v4l2 buffer list */ + if (pkt->packet_buffer == 0xdeadb000) + return; + v4l2_m2m_for_each_src_buf_safe(m2m_ctx, m2m_buffer, n) { buf = to_iris_buffer(&m2m_buffer->vb); if (buf->index == pkt->input_tag) { From 4c69f68087fbf2bd38f87e2340e51e0daa15393f Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 27 Mar 2024 20:49:08 +0100 Subject: [PATCH 039/113] FROMLIST: PCI: qcom: reshuffle reset logic in 2_7_0 .init At least on SC8280XP, if the PCIe reset is asserted, the corresponding AUX_CLK will be stuck at 'off'. This has not been an issue so far, since the reset is both left de-asserted by the previous boot stages and the driver only toggles it briefly in .init. As part of the upcoming suspend procedure however, the reset will be held asserted. Assert the reset (which may end up being a NOP in some cases) and de-assert it back *before* turning on the clocks in preparation for introducing RC powerdown and reinitialization. Link: https://lore.kernel.org/linux-pci/20240210-topic-8280_pcie-v2-0-1cef4b606883@linaro.org/ Signed-off-by: Konrad Dybcio Signed-off-by: Krishna Chaitanya Chundru --- drivers/pci/controller/dwc/pcie-qcom.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index dc98ae63362db..4c4295f5dbdd3 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -944,27 +944,27 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie) return ret; } - ret = clk_bulk_prepare_enable(res->num_clks, res->clks); - if (ret < 0) - goto err_disable_regulators; - + /* Assert the reset to hold the RC in a known state */ ret = reset_control_assert(res->rst); if (ret) { dev_err(dev, "reset assert failed (%d)\n", ret); - goto err_disable_clocks; + goto err_disable_regulators; } - usleep_range(1000, 1500); + /* GCC_PCIE_n_AUX_CLK won't come up if the reset is asserted */ ret = reset_control_deassert(res->rst); if (ret) { dev_err(dev, "reset deassert failed (%d)\n", ret); - goto err_disable_clocks; + goto err_disable_regulators; } - /* Wait for reset to complete, required on SM8450 */ usleep_range(1000, 1500); + ret = clk_bulk_prepare_enable(res->num_clks, res->clks); + if (ret < 0) + goto err_disable_regulators; + /* configure PCIe to RC mode */ writel(DEVICE_TYPE_RC, pcie->parf + PARF_DEVICE_TYPE); @@ -994,8 +994,6 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie) writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); return 0; -err_disable_clocks: - clk_bulk_disable_unprepare(res->num_clks, res->clks); err_disable_regulators: regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); From 1103f9c5c9aae402b9619402dbd7dcd1c3d14bc7 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 27 Mar 2024 20:49:09 +0100 Subject: [PATCH 040/113] FROMLIST: PCI: qcom: properly implement RC shutdown/power up Currently, we've only been minimizing the power draw while keeping the RC up at all times. This is suboptimal, as it draws a whole lot of power and prevents the SoC from power collapsing. Implement full shutdown and re-initialization to allow for powering off the controller. This is mainly intended for SC8280XP with a broken power rail setup, which requires a full RC shutdown/reinit in order to reach SoC-wide power collapse, but sleeping is generally better than not sleeping and less destructive suspend can be implemented later for platforms that support it. Link: https://lore.kernel.org/linux-pci/20240210-topic-8280_pcie-v2-0-1cef4b606883@linaro.org/ Co-developed-by: Bjorn Andersson Signed-off-by: Konrad Dybcio Signed-off-by: Krishna Chaitanya Chundru --- drivers/pci/controller/dwc/Kconfig | 1 + drivers/pci/controller/dwc/pcie-qcom.c | 189 ++++++++++++++++++------- 2 files changed, 135 insertions(+), 55 deletions(-) diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index d9f0386396edf..fee00158676ca 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -292,6 +292,7 @@ config PCIE_QCOM_COMMON config PCIE_QCOM bool "Qualcomm PCIe controller (host mode)" depends on OF && (ARCH_QCOM || COMPILE_TEST) + depends on QCOM_COMMAND_DB || QCOM_COMMAND_DB=n depends on PCI_MSI select PCIE_DW_HOST select CRC8 diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 4c4295f5dbdd3..76d90820855be 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -32,14 +32,19 @@ #include #include #include +#include #include "../../pci.h" #include "pcie-designware.h" #include "pcie-qcom-common.h" +#include +#include + /* PARF registers */ #define PARF_SYS_CTRL 0x00 #define PARF_PM_CTRL 0x20 +#define PARF_PM_STTS 0x24 #define PARF_PCS_DEEMPH 0x34 #define PARF_PCS_SWING 0x38 #define PARF_PHY_CTRL 0x40 @@ -70,6 +75,7 @@ /* ELBI registers */ #define ELBI_SYS_CTRL 0x04 +#define ELBI_SYS_CTRL_PME_TURNOFF_MSG BIT(4) /* DBI registers */ #define AXI_MSTR_RESP_COMP_CTRL0 0x818 @@ -94,7 +100,10 @@ #define L1_CLK_RMV_DIS BIT(1) /* PARF_PM_CTRL register fields */ -#define REQ_NOT_ENTR_L1 BIT(5) +#define REQ_NOT_ENTR_L1 BIT(5) /* "Prevent L0->L1" */ + +/* PARF_PM_STTS register fields */ +#define PM_ENTER_L23 BIT(5) /* PARF_PCS_DEEMPH register fields */ #define PCS_DEEMPH_TX_DEEMPH_GEN1(x) FIELD_PREP(GENMASK(21, 16), x) @@ -147,6 +156,7 @@ /* ELBI_SYS_CTRL register fields */ #define ELBI_SYS_CTRL_LT_ENABLE BIT(0) +#define ELBI_SYS_CTRL_PME_TURNOFF_MSG BIT(4) /* AXI_MSTR_RESP_COMP_CTRL0 register fields */ #define CFG_REMOTE_RD_REQ_BRIDGE_SIZE_2K 0x4 @@ -276,6 +286,7 @@ struct qcom_pcie { struct dentry *debugfs; bool suspended; bool use_pm_opp; + bool soc_is_rpmh; }; #define to_qcom_pcie(x) dev_get_drvdata((x)->dev) @@ -310,6 +321,24 @@ static int qcom_pcie_start_link(struct dw_pcie *pci) return 0; } +static int qcom_pcie_stop_link(struct dw_pcie *pci) +{ + struct qcom_pcie *pcie = to_qcom_pcie(pci); + u32 ret_l23, val; + + writel(ELBI_SYS_CTRL_PME_TURNOFF_MSG, pcie->elbi + ELBI_SYS_CTRL); + readl(pcie->elbi + ELBI_SYS_CTRL); + + ret_l23 = readl_poll_timeout(pcie->parf + PARF_PM_STTS, val, + val & PM_ENTER_L23, 10000, 100000); + if (ret_l23) { + dev_err(pci->dev, "Failed to enter L2/L3\n"); + return -ETIMEDOUT; + } + + return 0; +} + static void qcom_pcie_clear_aspm_l0s(struct dw_pcie *pci) { struct qcom_pcie *pcie = to_qcom_pcie(pci); @@ -1036,9 +1065,19 @@ static void qcom_pcie_host_post_init_2_7_0(struct qcom_pcie *pcie) static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0; + u32 val; + + /* Disable PCIe clocks and resets */ + val = readl(pcie->parf + PARF_PHY_CTRL); + val |= PHY_TEST_PWR_DOWN; + writel(val, pcie->parf + PARF_PHY_CTRL); + readl(pcie->parf + PARF_PHY_CTRL); clk_bulk_disable_unprepare(res->num_clks, res->clks); + reset_control_assert(res->rst); + usleep_range(2000, 2500); + regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); } @@ -1734,6 +1773,9 @@ static int qcom_pcie_probe(struct platform_device *pdev) pcie->parf + PARF_INT_ALL_MASK); } + /* If the soc features RPMh, cmd_db must have been prepared by now */ + pcie->soc_is_rpmh = !cmd_db_ready(); + qcom_pcie_icc_opp_update(pcie); if (pcie->mhi) @@ -1752,86 +1794,123 @@ static int qcom_pcie_probe(struct platform_device *pdev) return ret; } -static int qcom_pcie_suspend_noirq(struct device *dev) +static int qcom_pcie_resume_noirq(struct device *dev) { struct qcom_pcie *pcie = dev_get_drvdata(dev); - int ret = 0; + int ret; - /* - * Set minimum bandwidth required to keep data path functional during - * suspend. - */ - if (pcie->icc_mem) { - ret = icc_set_bw(pcie->icc_mem, 0, kBps_to_icc(1)); + if (pcie->soc_is_rpmh) { + /* + * Undo the tag change from qcom_pcie_suspend_noirq first in + * case RPMh spontaneously decides to power collapse the + * platform based on other inputs. + */ + icc_set_tag(pcie->icc_mem, QCOM_ICC_TAG_ALWAYS); + + /* Flush the tag change */ + ret = icc_enable(pcie->icc_mem); if (ret) { - dev_err(dev, - "Failed to set bandwidth for PCIe-MEM interconnect path: %d\n", - ret); + dev_err(pcie->pci->dev, "failed to icc_enable: %d", ret); return ret; } } - /* - * Turn OFF the resources only for controllers without active PCIe - * devices. For controllers with active devices, the resources are kept - * ON and the link is expected to be in L0/L1 (sub)states. - * - * Turning OFF the resources for controllers with active PCIe devices - * will trigger access violation during the end of the suspend cycle, - * as kernel tries to access the PCIe devices config space for masking - * MSIs. - * - * Also, it is not desirable to put the link into L2/L3 state as that - * implies VDD supply will be removed and the devices may go into - * powerdown state. This will affect the lifetime of the storage devices - * like NVMe. - */ - if (!dw_pcie_link_up(pcie->pci)) { - qcom_pcie_host_deinit(&pcie->pci->pp); - pcie->suspended = true; + /* Only check this now to make sure the icc tag has been set. */ + if (!pcie->suspended) + return 0; + + ret = icc_enable(pcie->icc_cpu); + if (ret) { + dev_err(dev, "Failed to enable CPU-PCIe interconnect path: %d\n", ret); + goto revert_icc_tag; } - /* - * Only disable CPU-PCIe interconnect path if the suspend is non-S2RAM. - * Because on some platforms, DBI access can happen very late during the - * S2RAM and a non-active CPU-PCIe interconnect path may lead to NoC - * error. - */ - if (pm_suspend_target_state != PM_SUSPEND_MEM) { - ret = icc_disable(pcie->icc_cpu); - if (ret) - dev_err(dev, "Failed to disable CPU-PCIe interconnect path: %d\n", ret); + ret = qcom_pcie_host_init(&pcie->pci->pp); + if (ret) + goto revert_icc_tag; + + dw_pcie_setup_rc(&pcie->pci->pp); + + ret = qcom_pcie_start_link(pcie->pci); + if (ret) + goto deinit_host; + + /* Ignore the retval, the devices may come up later. */ + dw_pcie_wait_for_link(pcie->pci); + + qcom_pcie_icc_opp_update(pcie); + + pcie->suspended = false; + + return 0; - if (pcie->use_pm_opp) - dev_pm_opp_set_opp(pcie->pci->dev, NULL); +deinit_host: + qcom_pcie_host_deinit(&pcie->pci->pp); +revert_icc_tag: + if (pcie->soc_is_rpmh) { + icc_set_tag(pcie->icc_mem, QCOM_ICC_TAG_WAKE); + + /* Ignore the retval, failing here would be tragic anyway.. */ + icc_enable(pcie->icc_mem); } + return ret; } -static int qcom_pcie_resume_noirq(struct device *dev) +static int qcom_pcie_suspend_noirq(struct device *dev) { struct qcom_pcie *pcie = dev_get_drvdata(dev); - int ret; + int ret = 0; + + if (pcie->suspended) + return 0; + + if (dw_pcie_link_up(pcie->pci)) { + ret = qcom_pcie_stop_link(pcie->pci); + if (ret) + return ret; + } + + qcom_pcie_host_deinit(&pcie->pci->pp); + + if (pcie->soc_is_rpmh) { + /* + * The PCIe RC may be covertly accessed by the secure firmware + * on sleep exit. Use the WAKE bucket to let RPMh pull the plug + * on PCIe in sleep, but guarantee it comes back up for resume. + */ + icc_set_tag(pcie->icc_mem, QCOM_ICC_TAG_WAKE); + + /* Flush the tag change */ + ret = icc_enable(pcie->icc_mem); + if (ret) { + dev_err(pcie->pci->dev, "failed to icc_enable %d\n", ret); - if (pm_suspend_target_state != PM_SUSPEND_MEM) { - ret = icc_enable(pcie->icc_cpu); + /* Revert everything and pray icc calls succeed */ + return qcom_pcie_resume_noirq(dev); + } + } else { + /* + * Set minimum bandwidth required to keep data path functional + * during suspend. + */ + ret = icc_set_bw(pcie->icc_mem, 0, kBps_to_icc(1)); if (ret) { - dev_err(dev, "Failed to enable CPU-PCIe interconnect path: %d\n", ret); + dev_err(dev, "Failed to set interconnect bandwidth: %d\n", ret); return ret; } } - if (pcie->suspended) { - ret = qcom_pcie_host_init(&pcie->pci->pp); - if (ret) - return ret; + pcie->suspended = true; - pcie->suspended = false; - } + ret = icc_disable(pcie->icc_cpu); + if (ret) + dev_err(dev, "Failed to disable CPU-PCIe interconnect path: %d\n", ret); - qcom_pcie_icc_opp_update(pcie); + if (pcie->use_pm_opp) + dev_pm_opp_set_opp(pcie->pci->dev, NULL); - return 0; + return ret; } static const struct of_device_id qcom_pcie_match[] = { From dd11b10685e12626359930e4d606a7fc25824014 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Thu, 29 May 2025 17:06:00 +0530 Subject: [PATCH 041/113] QCLINUX: defconfig: Introduce prune.config fragment Add prune.config fragment to disable support for non-Qualcomm architectures. This helps reduce boot image size and improves kernel build KPIs by trimming unnecessary configuration options. Signed-off-by: Komal Bajaj --- arch/arm64/configs/prune.config | 410 ++++++++++++++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 arch/arm64/configs/prune.config diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config new file mode 100644 index 0000000000000..01bb1243552ea --- /dev/null +++ b/arch/arm64/configs/prune.config @@ -0,0 +1,410 @@ +# CONFIG_ARCH_ACTIONS is not set +# CONFIG_ARCH_AIROHA is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_APPLE is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BCM2835 is not set +# CONFIG_ARCH_BCM_IPROC is not set +# CONFIG_ARCH_BCMBCA is not set +# CONFIG_ARCH_BRCMSTB is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_BLAIZE is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SPARX5 is not set +# CONFIG_ARCH_K3 is not set +# CONFIG_ARCH_LG1K is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_KEEMBAY is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_MESON is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_NXP is not set +# CONFIG_ARCH_MA35 is not set +# CONFIG_ARCH_NPCM is not set +# CONFIG_ARCH_REALTEK is not set +# CONFIG_ARCH_RENESAS is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_INTEL_SOCFPGA is not set +# CONFIG_ARCH_STM32 is not set +# CONFIG_ARCH_SYNQUACER is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_TESLA_FSD is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_THUNDER2 is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_VISCONTI is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZYNQMP is not set +# CONFIG_MOUSE_PS2 is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_VSOCKETS_DIAG is not set +# CONFIG_VSOCKETS_LOOPBACK is not set +# CONFIG_RODATA_FULL_DEFAULT_ENABLED is not set +# CONFIG_NET_DSA_TAG_OCELOT is not set +# CONFIG_NET_DSA_TAG_OCELOT_8021Q is not set +# CONFIG_BT_HCIBTUSB_MTK is not set +# CONFIG_BT_HCIUART_BCM is not set +# CONFIG_BT_HCIUART_MRVL is not set +# CONFIG_BT_MRVL is not set +# CONFIG_BT_MRVL_SDIO is not set +# CONFIG_PCIE_ALTERA is not set +# CONFIG_PCIE_ALTERA_MSI is not set +# CONFIG_PCI_HOST_THUNDER_PEM is not set +# CONFIG_PCI_HOST_THUNDER_ECAM is not set +# CONFIG_PCI_XGENE is not set +# CONFIG_PCI_MESON is not set +# CONFIG_PCI_HISI is not set +# CONFIG_PCIE_KIRIN is not set +# CONFIG_BRCMSTB_GISB_ARB is not set +# CONFIG_VEXPRESS_CONFIG is not set +# CONFIG_GNSS_MTK_SERIAL is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_NAND_DENALI_DT is not set +# CONFIG_MTD_NAND_BRCMNAND is not set +# CONFIG_MTD_NAND_BRCMNAND_BCMBCA is not set +# CONFIG_MTD_NAND_BRCMNAND_BRCMSTB is not set +# CONFIG_MTD_NAND_BRCMNAND_IPROC is not set +# CONFIG_B53_SRAB_DRIVER is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +# CONFIG_AMD_XGBE is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2X is not set +# CONFIG_SYSTEMPORT is not set +# CONFIG_MACB is not set +# CONFIG_THUNDER_NIC_PF is not set +# CONFIG_HIX5HD2_GMAC is not set +# CONFIG_HNS_DSAF is not set +# CONFIG_HNS_ENET is not set +# CONFIG_HNS3 is not set +# CONFIG_HNS3_HCLGE is not set +# CONFIG_HNS3_ENET is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_MVMDIO is not set +# CONFIG_SKY2 is not set +# CONFIG_MLX4_EN is not set +# CONFIG_MLX5_CORE is not set +# CONFIG_MLX5_CORE_EN is not set +# CONFIG_R8169 is not set +# CONFIG_SMC91X is not set +# CONFIG_SMSC911X is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM54140_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_ROCKCHIP_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_DP83TD510_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_CAN_FLEXCAN is not set +# CONFIG_CAN_MCP251XFD is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +# CONFIG_USB_LAN78XX is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_BRCMFMAC is not set +# CONFIG_MWIFIEX is not set +# CONFIG_MWIFIEX_SDIO is not set +# CONFIG_MWIFIEX_PCIE is not set +# CONFIG_MT7921E is not set +# CONFIG_WL18XX is not set +# CONFIG_WLCORE_SDIO is not set +# CONFIG_KEYBOARD_CROS_EC is not set +# CONFIG_KEYBOARD_MTK_PMIC is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_INPUT_TPS65219_PWRBUTTON is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_XILINX_PS_UART_CONSOLE is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_FSL_LPUART_CONSOLE is not set +# CONFIG_SERIAL_FSL_LINFLEXUART is not set +# CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE is not set +# CONFIG_TCG_TIS_SPI_CR50 is not set +# CONFIG_TCG_TIS_I2C_CR50 is not set +# CONFIG_TCG_TIS_I2C_INFINEON is not set +# CONFIG_I2C_CADENCE is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_CROS_EC_TUNNEL is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_DW_DMA is not set +# CONFIG_SPI_DW_MMIO is not set +# CONFIG_PINCTRL_MAX77620 is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_MB86S7X is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCA953X_IRQ is not set +# CONFIG_GPIO_BD9571MWV is not set +# CONFIG_GPIO_MAX77620 is not set +# CONFIG_POWER_RESET_BRCMSTB is not set +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_MT6360 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_BQ25980 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA3221 is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_ARM_SMC_WATCHDOG is not set +# CONFIG_PM8916_WATCHDOG is not set +# CONFIG_MFD_BD9571MWV is not set +# CONFIG_MFD_AXP20X_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_MFD_MAX77620 is not set +# CONFIG_MFD_MT6360 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_RK8XX_I2C is not set +# CONFIG_MFD_RK8XX_SPI is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_TPS65219 is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_ROHM_BD718XX is not set +# CONFIG_REGULATOR_AXP20X is not set +# CONFIG_REGULATOR_BD718XX is not set +# CONFIG_REGULATOR_BD9571MWV is not set +# CONFIG_REGULATOR_CROS_EC is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_HI6421V530 is not set +# CONFIG_REGULATOR_MAX77620 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MP8859 is not set +# CONFIG_REGULATOR_MT6315 is not set +# CONFIG_REGULATOR_MT6357 is not set +# CONFIG_REGULATOR_MT6358 is not set +# CONFIG_REGULATOR_MT6359 is not set +# CONFIG_REGULATOR_MT6360 is not set +# CONFIG_REGULATOR_MT6397 is not set +# CONFIG_REGULATOR_PCA9450 is not set +# CONFIG_REGULATOR_PF8X00 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_RK808 is not set +# CONFIG_REGULATOR_S2MPS11 is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS65219 is not set +# CONFIG_REGULATOR_RK808 is not set +# CONFIG_REGULATOR_S2MPS11 is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS65219 is not set +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +# CONFIG_VIDEO_IMX219 is not set +# CONFIG_VIDEO_IMX412 is not set +# CONFIG_VIDEO_OV5640 is not set +# CONFIG_VIDEO_OV5645 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_MALI_DISPLAY is not set +# CONFIG_DRM_KOMEDA is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set +# CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM67191 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7703 is not set +# CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA is not set +# CONFIG_DRM_PANEL_VISIONOX_VTDR6130 is not set +# CONFIG_DRM_LONTIUM_LT8912B is not set +# CONFIG_DRM_NWL_MIPI_DSI is not set +# CONFIG_DRM_PARADE_PS8640 is not set +# CONFIG_DRM_SAMSUNG_DSIM is not set +# CONFIG_DRM_SII902X is not set +# CONFIG_DRM_SIMPLE_BRIDGE is not set +# CONFIG_DRM_THINE_THC63LVD1024 is not set +# CONFIG_DRM_TOSHIBA_TC358768 is not set +# CONFIG_DRM_TI_TFP410 is not set +# CONFIG_DRM_TI_SN65DSI83 is not set +# CONFIG_DRM_TI_SN65DSI86 is not set +# CONFIG_DRM_I2C_ADV7511_AUDIO is not set +# CONFIG_DRM_CDNS_MHDP8546 is not set +# CONFIG_DRM_ETNAVIV is not set +# CONFIG_DRM_HISI_HIBMC is not set +# CONFIG_DRM_HISI_KIRIN is not set +# CONFIG_DRM_PL111 is not set +# CONFIG_DRM_LIMA is not set +# CONFIG_DRM_PANFROST is not set +# CONFIG_DRM_TIDSS is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_AUDMIX is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_FSL_MICFIL is not set +# CONFIG_SND_SOC_FSL_EASRC is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +# CONFIG_SND_SOC_AK4613 is not set +# CONFIG_SND_SOC_BT_SCO is not set +# CONFIG_SND_SOC_DA7213 is not set +# CONFIG_SND_SOC_DMIC is not set +# CONFIG_SND_SOC_ES7134 is not set +# CONFIG_SND_SOC_ES7241 is not set +# CONFIG_SND_SOC_ES8316 is not set +# CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_PCM3168A_I2C is not set +# CONFIG_SND_SOC_RT5640 is not set +# CONFIG_SND_SOC_RT5659 is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set +# CONFIG_SND_SOC_SIMPLE_MUX is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC32X4_I2C is not set +# CONFIG_SND_SOC_TLV320AIC3X_I2C is not set +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_SOC_WM8524 is not set +# CONFIG_SND_SOC_WM8904 is not set +# CONFIG_SND_SOC_WM8960 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_MT6358 is not set +# CONFIG_SND_SOC_NAU8822 is not set +# CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_CDNS3 is not set +# CONFIG_USB_CDNS3_GADGET is not set +# CONFIG_USB_CDNS3_HOST is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_CHIPIDEA_UDC is not set +# CONFIG_USB_CHIPIDEA_HOST is not set +# CONFIG_USB_ISP1760 is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_SNP_UDC_PLAT is not set +# CONFIG_USB_BDC_UDC is not set +# CONFIG_TYPEC_FUSB302 is not set +# CONFIG_UCSI_CCG is not set +# CONFIG_TYPEC_TPS6598X is not set +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +# CONFIG_MMC_SDHCI_OF_DWCMSHC is not set +# CONFIG_MMC_SDHCI_CADENCE is not set +# CONFIG_MMC_SDHCI_F_SDH30 is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_HI3798CV200 is not set +# CONFIG_MMC_DW_K3 is not set +# CONFIG_MMC_MTK is not set +# CONFIG_MMC_SDHCI_XENON is not set +# CONFIG_MMC_SDHCI_AM654 is not set +# CONFIG_LEDS_LM3692X is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX77686 is not set +# CONFIG_RTC_DRV_RK808 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF85363 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RV3028 is not set +# CONFIG_RTC_DRV_RV8803 is not set +# CONFIG_RTC_DRV_S5M is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_CROS_EC is not set +# CONFIG_RTC_DRV_MT6397 is not set +# CONFIG_BCM_SBA_RAID is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_MV_XOR_V2 is not set +# CONFIG_VIDEO_MAX96712 is not set +# CONFIG_CHROME_PLATFORMS is not set +# CONFIG_CROS_EC is not set +# CONFIG_CROS_EC_I2C is not set +# CONFIG_CROS_EC_RPMSG is not set +# CONFIG_CROS_EC_SPI is not set +# CONFIG_CROS_EC_CHARDEV is not set +# CONFIG_CLK_VEXPRESS_OSC is not set +# CONFIG_COMMON_CLK_RK808 is not set +# CONFIG_COMMON_CLK_CS2000_CP is not set +# CONFIG_COMMON_CLK_S2MPS11 is not set +# CONFIG_COMMON_CLK_XGENE is not set +# CONFIG_COMMON_CLK_RS9_PCIE is not set +# CONFIG_COMMON_CLK_VC5 is not set +# CONFIG_COMMON_CLK_BD718XX is not set +# CONFIG_SOC_TI is not set +# CONFIG_EXTCON_PTN5150 is not set +# CONFIG_EXTCON_USBC_CROS_EC is not set +# CONFIG_MAX9611 is not set +# CONFIG_TI_ADS1015 is not set +# CONFIG_TI_AM335X_ADC is not set +# CONFIG_IIO_CROS_EC_SENSORS_CORE is not set +# CONFIG_IIO_CROS_EC_SENSORS is not set +# CONFIG_IIO_ST_LSM6DSX is not set +# CONFIG_IIO_CROS_EC_LIGHT_PROX is not set +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_VCNL4000 is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set +# CONFIG_IIO_CROS_EC_BARO is not set +# CONFIG_MPL3115 is not set +# CONFIG_PWM_CROS_EC is not set +# CONFIG_PHY_CADENCE_TORRENT is not set +# CONFIG_PHY_CADENCE_SIERRA is not set +# CONFIG_CRYPTO_CRCT10DIF_ARM64_CE is not set +# CONFIG_CRYPTO_DEV_HISI_SEC2 is not set +# CONFIG_CRYPTO_DEV_HISI_ZIP is not set +# CONFIG_CRYPTO_DEV_HISI_HPRE is not set +# CONFIG_CRYPTO_DEV_HISI_TRNG is not set +# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set +# CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set +# CONFIG_DEVMEM is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set +# CONFIG_SECURITY_SELINUX_DEVELOP is not set +# CONFIG_SECURITY_SELINUX_AVC_STATS is not set +# CONFIG_AUDIT_GENERIC is not set +# CONFIG_EFI_DISABLE_RUNTIME is not set +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_CMDLINE_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET is not set +# CONFIG_VFIO_PLATFORM_AMDXGBE_RESET is not set +# CONFIG_VFIO_PLATFORM_BCMFLEXRM_RESET is not set +# CONFIG_FTRACE_RECORD_RECURSION is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_FUNCTION_GRAPH_RETVAL is not set +# CONFIG_FUNCTION_PROFILER is not set +# CONFIG_HID_BPF is not set +# CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set +# CONFIG_PSTORE_FTRACE is not set From bf38ae7d20c32742a0d9552772530276e8713259 Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Thu, 12 Jun 2025 14:11:53 +0530 Subject: [PATCH 042/113] FROMLIST: dt-bindings: qcom: se-common: Add QUP Peripheral-specific properties for I2C, SPI, and SERIAL bus Introduce a new YAML schema for QUP-supported peripherals. Define common properties used across QUP-supported peripherals. Add property `qcom,enable-gsi-dma` to configure the Serial Engine (SE) for QCOM GPI DMA mode. Reference the common schema YAML in the GENI I2C, SPI, and SERIAL YAML files. Link: https://lore.kernel.org/linux-i2c/20250503111029.3583807-2-quic_vdadhani@quicinc.com/ Reviewed-by: Krzysztof Kozlowski Co-developed-by: Mukesh Kumar Savaliya Signed-off-by: Mukesh Kumar Savaliya Signed-off-by: Viken Dadhaniya --- .../bindings/i2c/qcom,i2c-geni-qcom.yaml | 1 + .../serial/qcom,serial-geni-qcom.yaml | 1 + .../soc/qcom/qcom,se-common-props.yaml | 26 +++++++++++++++++++ .../bindings/spi/qcom,spi-geni-qcom.yaml | 1 + 4 files changed, 29 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,se-common-props.yaml diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml index 9f66a3bb1f80c..51534953a69cf 100644 --- a/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml +++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml @@ -75,6 +75,7 @@ required: allOf: - $ref: /schemas/i2c/i2c-controller.yaml# + - $ref: /schemas/soc/qcom/qcom,se-common-props.yaml# - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/serial/qcom,serial-geni-qcom.yaml b/Documentation/devicetree/bindings/serial/qcom,serial-geni-qcom.yaml index dd33794b3534e..ed7b3909d87df 100644 --- a/Documentation/devicetree/bindings/serial/qcom,serial-geni-qcom.yaml +++ b/Documentation/devicetree/bindings/serial/qcom,serial-geni-qcom.yaml @@ -12,6 +12,7 @@ maintainers: allOf: - $ref: /schemas/serial/serial.yaml# + - $ref: /schemas/soc/qcom/qcom,se-common-props.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,se-common-props.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,se-common-props.yaml new file mode 100644 index 0000000000000..044eea4bb960a --- /dev/null +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,se-common-props.yaml @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/qcom/qcom,se-common-props.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: QUP Peripheral-specific properties for I2C, SPI and SERIAL bus + +description: + The Generic Interface (GENI) based Qualcomm Universal Peripheral (QUP) is + a programmable module that supports a wide range of serial interfaces + such as UART, SPI, I2C, I3C, etc. This defines the common properties used + across QUP-supported peripherals. + +maintainers: + - Mukesh Kumar Savaliya + - Viken Dadhaniya + +properties: + qcom,enable-gsi-dma: + $ref: /schemas/types.yaml#/definitions/flag + description: + Configure the Serial Engine (SE) to transfer data in QCOM GPI DMA mode. + By default, FIFO mode (PIO/CPU DMA) will be selected. + +additionalProperties: true diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.yaml b/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.yaml index 2e20ca313ec1d..d12c5a060ed00 100644 --- a/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.yaml +++ b/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.yaml @@ -25,6 +25,7 @@ description: allOf: - $ref: /schemas/spi/spi-controller.yaml# + - $ref: /schemas/soc/qcom/qcom,se-common-props.yaml# properties: compatible: From 32c7d585e880fdca4bf4566ed6edd0f652f57dbf Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Thu, 12 Jun 2025 12:39:08 +0530 Subject: [PATCH 043/113] FROMLIST: soc: qcom: geni-se: Add support to load QUP SE Firmware via Linux subsystem In Qualcomm SoCs, firmware loading for Serial Engines (SE) within the QUP hardware has traditionally been managed by TrustZone (TZ). This restriction poses a significant challenge for developers, as it limits their ability to enable various protocols on any of the SEs from the Linux side, reducing flexibility. Load the firmware to QUP SE based on the 'firmware-name' property specified in devicetree at bootup time. Link: https://lore.kernel.org/linux-i2c/20250503111029.3583807-3-quic_vdadhani@quicinc.com/ Co-developed-by: Mukesh Kumar Savaliya Signed-off-by: Mukesh Kumar Savaliya Signed-off-by: Viken Dadhaniya --- drivers/soc/qcom/qcom-geni-se.c | 404 +++++++++++++++++++++++++-- include/linux/soc/qcom/geni-se.h | 31 +- include/linux/soc/qcom/qup-fw-load.h | 89 ++++++ 3 files changed, 502 insertions(+), 22 deletions(-) create mode 100644 include/linux/soc/qcom/qup-fw-load.h diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 4cb959106efa9..ad9595275a9ec 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -1,11 +1,15 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ /* Disable MMIO tracing to prevent excessive logging of unwanted MMIO traces */ #define __DISABLE_TRACE_MMIO__ #include #include +#include #include #include #include @@ -15,6 +19,7 @@ #include #include #include +#include /** * DOC: Overview @@ -80,9 +85,9 @@ * common to all the serial engines and are independent of serial interfaces. */ -#define MAX_CLK_PERF_LEVEL 32 -#define MAX_CLKS 2 - +#define MAX_CLK_PERF_LEVEL 32 +#define MAX_CLKS 2 +#define MAX_PROTOCOL 6 /** * struct geni_wrapper - Data structure to represent the QUP Wrapper Core * @dev: Device pointer of the QUP wrapper core @@ -110,28 +115,23 @@ struct geni_se_desc { static const char * const icc_path_names[] = {"qup-core", "qup-config", "qup-memory"}; +static const char * const protocol_name[MAX_PROTOCOL] = { "None", "SPI", "UART", + "I2C", "I3C", "SPI SLAVE"}; + #define QUP_HW_VER_REG 0x4 /* Common SE registers */ -#define GENI_INIT_CFG_REVISION 0x0 -#define GENI_S_INIT_CFG_REVISION 0x4 -#define GENI_OUTPUT_CTRL 0x24 -#define GENI_CGC_CTRL 0x28 #define GENI_CLK_CTRL_RO 0x60 -#define GENI_FW_S_REVISION_RO 0x6c #define SE_GENI_BYTE_GRAN 0x254 #define SE_GENI_TX_PACKING_CFG0 0x260 #define SE_GENI_TX_PACKING_CFG1 0x264 #define SE_GENI_RX_PACKING_CFG0 0x284 #define SE_GENI_RX_PACKING_CFG1 0x288 -#define SE_GENI_M_GP_LENGTH 0x910 -#define SE_GENI_S_GP_LENGTH 0x914 #define SE_DMA_TX_PTR_L 0xc30 #define SE_DMA_TX_PTR_H 0xc34 #define SE_DMA_TX_ATTR 0xc38 #define SE_DMA_TX_LEN 0xc3c #define SE_DMA_TX_IRQ_EN 0xc48 -#define SE_DMA_TX_IRQ_EN_SET 0xc4c #define SE_DMA_TX_IRQ_EN_CLR 0xc50 #define SE_DMA_TX_LEN_IN 0xc54 #define SE_DMA_TX_MAX_BURST 0xc5c @@ -140,9 +140,7 @@ static const char * const icc_path_names[] = {"qup-core", "qup-config", #define SE_DMA_RX_ATTR 0xd38 #define SE_DMA_RX_LEN 0xd3c #define SE_DMA_RX_IRQ_EN 0xd48 -#define SE_DMA_RX_IRQ_EN_SET 0xd4c #define SE_DMA_RX_IRQ_EN_CLR 0xd50 -#define SE_DMA_RX_LEN_IN 0xd54 #define SE_DMA_RX_MAX_BURST 0xd5c #define SE_DMA_RX_FLUSH 0xd60 #define SE_GSI_EVENT_EN 0xe18 @@ -179,7 +177,7 @@ static const char * const icc_path_names[] = {"qup-core", "qup-config", /* SE_DMA_GENERAL_CFG */ #define DMA_RX_CLK_CGC_ON BIT(0) #define DMA_TX_CLK_CGC_ON BIT(1) -#define DMA_AHB_SLV_CFG_ON BIT(2) +#define DMA_AHB_SLV_CLK_CGC_ON BIT(2) #define AHB_SEC_SLV_CLK_CGC_ON BIT(3) #define DUMMY_RX_NON_BUFFERABLE BIT(4) #define RX_DMA_ZERO_PADDING_EN BIT(5) @@ -220,12 +218,12 @@ static void geni_se_io_init(void __iomem *base) { u32 val; - val = readl_relaxed(base + GENI_CGC_CTRL); + val = readl_relaxed(base + SE_GENI_CGC_CTRL); val |= DEFAULT_CGC_EN; - writel_relaxed(val, base + GENI_CGC_CTRL); + writel_relaxed(val, base + SE_GENI_CGC_CTRL); val = readl_relaxed(base + SE_DMA_GENERAL_CFG); - val |= AHB_SEC_SLV_CLK_CGC_ON | DMA_AHB_SLV_CFG_ON; + val |= AHB_SEC_SLV_CLK_CGC_ON | DMA_AHB_SLV_CLK_CGC_ON; val |= DMA_TX_CLK_CGC_ON | DMA_RX_CLK_CGC_ON; writel_relaxed(val, base + SE_DMA_GENERAL_CFG); @@ -891,6 +889,376 @@ int geni_icc_disable(struct geni_se *se) } EXPORT_SYMBOL_GPL(geni_icc_disable); +/** + * geni_read_elf() - Read an ELF file. + * @se: Pointer to the SE resources structure. + * @fw: Pointer to the firmware buffer. + * @pelfseg: Pointer to the SE-specific ELF header. + * + * Read the ELF file and output a pointer to the header data, which + * contains the firmware data and any other details. + * + * Return: 0 if successful, otherwise return an error value. + */ +static int geni_read_elf(struct geni_se *se, const struct firmware *fw, struct elf_se_hdr **pelfseg) +{ + const struct elf32_hdr *ehdr; + struct elf32_phdr *phdrs, *phdr; + const struct elf_se_hdr *elfseg; + const u8 *addr; + int i; + + if (!fw || fw->size < sizeof(struct elf32_hdr)) + return -EINVAL; + + ehdr = (struct elf32_hdr *)fw->data; + phdrs = (struct elf32_phdr *)(ehdr + 1); + + if (ehdr->e_phnum < 2) + return -EINVAL; + + for (i = 0; i < ehdr->e_phnum; i++) { + phdr = &phdrs[i]; + + if (fw->size < phdr->p_offset + phdr->p_filesz) + return -EINVAL; + + if (phdr->p_type != PT_LOAD || !phdr->p_memsz) + continue; + + if (MI_PBT_PAGE_MODE_VALUE(phdr->p_flags) != MI_PBT_NON_PAGED_SEGMENT || + MI_PBT_SEGMENT_TYPE_VALUE(phdr->p_flags) == MI_PBT_HASH_SEGMENT || + MI_PBT_ACCESS_TYPE_VALUE(phdr->p_flags) == MI_PBT_NOTUSED_SEGMENT || + MI_PBT_ACCESS_TYPE_VALUE(phdr->p_flags) == MI_PBT_SHARED_SEGMENT) + continue; + + if (phdr->p_filesz < sizeof(struct elf_se_hdr)) + continue; + + addr = fw->data + phdr->p_offset; + elfseg = (const struct elf_se_hdr *)addr; + + if (elfseg->magic != MAGIC_NUM_SE || elfseg->version != 1) + continue; + + if (phdr->p_filesz < elfseg->fw_offset + elfseg->fw_size_in_items * sizeof(u32) || + phdr->p_filesz < elfseg->cfg_idx_offset + elfseg->cfg_items_size * sizeof(u8) || + phdr->p_filesz < elfseg->cfg_val_offset + elfseg->cfg_items_size * sizeof(u32)) + continue; + + if (elfseg->serial_protocol != se->protocol) + continue; + + *pelfseg = (struct elf_se_hdr *)addr; + return 0; + } + return -EINVAL; +} + +/** + * geni_configure_xfer_mode() - Set the transfer mode. + * @se: Pointer to a structure representing SE-related resources. + * + * Set the transfer mode to either FIFO or DMA according to the mode specified by the protocol + * driver. + * + * Return: 0 if successful, otherwise return an error value. + */ +static int geni_configure_xfer_mode(struct geni_se *se) +{ + /* Configure SE FIFO, DMA or GSI mode. */ + switch (se->mode) { + case GENI_GPI_DMA: + geni_setbits32(se->base + SE_GENI_DMA_MODE_EN, GENI_DMA_MODE_EN); + writel_relaxed(0x0, se->base + SE_IRQ_EN); + writel_relaxed(DMA_RX_EVENT_EN | DMA_TX_EVENT_EN | + GENI_M_EVENT_EN | GENI_S_EVENT_EN, + se->base + SE_GSI_EVENT_EN); + break; + + case GENI_SE_FIFO: + geni_clrbits32(se->base + SE_GENI_DMA_MODE_EN, GENI_DMA_MODE_EN); + writel_relaxed(DMA_RX_IRQ_EN | DMA_TX_IRQ_EN | GENI_M_IRQ_EN | GENI_S_IRQ_EN, + se->base + SE_IRQ_EN); + writel_relaxed(0x0, se->base + SE_GSI_EVENT_EN); + break; + + case GENI_SE_DMA: + geni_setbits32(se->base + SE_GENI_DMA_MODE_EN, GENI_DMA_MODE_EN); + writel_relaxed(DMA_RX_IRQ_EN | DMA_TX_IRQ_EN | GENI_M_IRQ_EN | GENI_S_IRQ_EN, + se->base + SE_IRQ_EN); + writel_relaxed(0x0, se->base + SE_GSI_EVENT_EN); + break; + + default: + dev_err(se->dev, "Invalid geni-se transfer mode: %d\n", se->mode); + return -EINVAL; + } + return 0; +} + +/** + * geni_enable_interrupts() - Enable interrupts. + * @se: Pointer to a structure representing SE-related resources. + * + * Enable the required interrupts during the firmware load process. + * + */ +static void geni_enable_interrupts(struct geni_se *se) +{ + u32 reg_value; + + /* Enable required interrupts. */ + writel_relaxed(M_COMMON_GENI_M_IRQ_EN, se->base + SE_GENI_M_IRQ_EN); + + reg_value = S_CMD_OVERRUN_EN | S_ILLEGAL_CMD_EN | + S_CMD_CANCEL_EN | S_CMD_ABORT_EN | + S_GP_IRQ_0_EN | S_GP_IRQ_1_EN | + S_GP_IRQ_2_EN | S_GP_IRQ_3_EN | + S_RX_FIFO_WR_ERR_EN | S_RX_FIFO_RD_ERR_EN; + writel_relaxed(reg_value, se->base + SE_GENI_S_IRQ_ENABLE); + + /* DMA mode configuration. */ + reg_value = RESET_DONE_EN | SBE_EN | DMA_DONE_EN; + writel_relaxed(reg_value, se->base + SE_DMA_TX_IRQ_EN_SET); + reg_value = FLUSH_DONE_EN | RESET_DONE_EN | SBE_EN | DMA_DONE_EN; + writel_relaxed(reg_value, se->base + SE_DMA_RX_IRQ_EN_SET); +} + +/** + * geni_write_fw_revision() - Write the firmware revision. + * @se: Pointer to a structure representing SE-related resources. + * @serial_protocol: serial protocol type. + * @fw_version: QUP firmware version. + * + * Write the firmware revision and protocol into the respective register. + * + * Return: None. + */ +static void geni_write_fw_revision(struct geni_se *se, u16 serial_protocol, u16 fw_version) +{ + u32 reg_value; + + reg_value = FIELD_PREP(FW_REV_PROTOCOL_MSK, serial_protocol); + reg_value |= FIELD_PREP(FW_REV_VERSION_MSK, fw_version); + + writel_relaxed(reg_value, se->base + SE_GENI_FW_REVISION); + writel_relaxed(reg_value, se->base + SE_S_FW_REVISION); +} + +/** + * geni_load_se_fw() - Load Serial Engine specific firmware. + * @se: Pointer to a structure representing SE-related resources. + * @fw: Pointer to the firmware structure. + * + * Load the protocol firmware into the IRAM of the Serial Engine. + * + * Return: 0 if successful, otherwise return an error value. + */ +static int geni_load_se_fw(struct geni_se *se, const struct firmware *fw) +{ + const u32 *fw_data, *cfg_val_arr; + const u8 *cfg_idx_arr; + u32 i, reg_value, ramn_cnt; + int ret; + struct elf_se_hdr *hdr; + + ret = geni_read_elf(se, fw, &hdr); + if (ret) { + dev_err(se->dev, "ELF parsing failed ret: %d\n", ret); + return ret; + } + + ramn_cnt = hdr->fw_size_in_items; + if (hdr->fw_size_in_items % 2 != 0) + ramn_cnt++; + + if (ramn_cnt >= MAX_GENI_CFG_RAMn_CNT) + return -EINVAL; + + ret = geni_icc_set_bw(se); + if (ret) + return ret; + + ret = geni_icc_enable(se); + if (ret) + return ret; + + ret = geni_se_resources_on(se); + if (ret) + goto err; + + ramn_cnt = hdr->fw_size_in_items; + if (hdr->fw_size_in_items % 2 != 0) + ramn_cnt++; + + if (ramn_cnt >= MAX_GENI_CFG_RAMn_CNT) + goto err_resource; + + fw_data = (const u32 *)((u8 *)hdr + hdr->fw_offset); + cfg_idx_arr = (const u8 *)hdr + hdr->cfg_idx_offset; + cfg_val_arr = (const u32 *)((u8 *)hdr + hdr->cfg_val_offset); + + /* Disable high priority interrupt until current low priority interrupts are handled. */ + geni_setbits32(se->wrapper->base + QUPV3_COMMON_CFG, FAST_SWITCH_TO_HIGH_DISABLE); + + /* Set AHB_M_CLK_CGC_ON to indicate hardware controls se-wrapper cgc clock. */ + geni_setbits32(se->wrapper->base + QUPV3_SE_AHB_M_CFG, AHB_M_CLK_CGC_ON); + + /* Let hardware to control common cgc. */ + geni_setbits32(se->wrapper->base + QUPV3_COMMON_CGC_CTRL, COMMON_CSR_SLV_CLK_CGC_ON); + + /* Allows to drive corresponding data according to hardware value. */ + writel_relaxed(0x0, se->base + GENI_OUTPUT_CTRL); + + /* Set SCLK and HCLK to program RAM */ + geni_setbits32(se->base + SE_GENI_CGC_CTRL, PROG_RAM_SCLK_OFF | PROG_RAM_HCLK_OFF); + writel_relaxed(0x0, se->base + SE_GENI_CLK_CTRL); + geni_clrbits32(se->base + SE_GENI_CGC_CTRL, PROG_RAM_SCLK_OFF | PROG_RAM_HCLK_OFF); + + /* Enable required clocks for DMA CSR, TX and RX. */ + reg_value = AHB_SEC_SLV_CLK_CGC_ON | DMA_AHB_SLV_CLK_CGC_ON | + DMA_TX_CLK_CGC_ON | DMA_RX_CLK_CGC_ON; + geni_setbits32(se->base + SE_DMA_GENERAL_CFG, reg_value); + + /* Let hardware control CGC by default. */ + writel_relaxed(DEFAULT_CGC_EN, se->base + SE_GENI_CGC_CTRL); + + /* Set version of the configuration register part of firmware. */ + writel_relaxed(hdr->cfg_version, se->base + SE_GENI_INIT_CFG_REVISION); + writel_relaxed(hdr->cfg_version, se->base + SE_GENI_S_INIT_CFG_REVISION); + + /* Configure GENI primitive table. */ + for (i = 0; i < hdr->cfg_items_size; i++) + writel_relaxed(cfg_val_arr[i], + se->base + SE_GENI_CFG_REG0 + (cfg_idx_arr[i] * sizeof(u32))); + + /* Configure condition for assertion of RX_RFR_WATERMARK condition. */ + reg_value = geni_se_get_rx_fifo_depth(se); + writel_relaxed(reg_value - 2, se->base + SE_GENI_RX_RFR_WATERMARK_REG); + + /* Let hardware control CGC */ + geni_setbits32(se->base + GENI_OUTPUT_CTRL, DEFAULT_IO_OUTPUT_CTRL_MSK); + + ret = geni_configure_xfer_mode(se); + if (ret) + goto err_resource; + + geni_enable_interrupts(se); + + geni_write_fw_revision(se, hdr->serial_protocol, hdr->fw_version); + + ramn_cnt = hdr->fw_size_in_items; + if (hdr->fw_size_in_items % 2 != 0) + ramn_cnt++; + + if (ramn_cnt >= MAX_GENI_CFG_RAMn_CNT) + goto err_resource; + + /* Program RAM address space. */ + memcpy_toio(se->base + SE_GENI_CFG_RAMN, fw_data, ramn_cnt * sizeof(u32)); + + /* Put default values on GENI's output pads. */ + writel_relaxed(0x1, se->base + GENI_FORCE_DEFAULT_REG); + + /* High to low SCLK and HCLK to finish RAM. */ + geni_setbits32(se->base + SE_GENI_CGC_CTRL, PROG_RAM_SCLK_OFF | PROG_RAM_HCLK_OFF); + geni_setbits32(se->base + SE_GENI_CLK_CTRL, SER_CLK_SEL); + geni_clrbits32(se->base + SE_GENI_CGC_CTRL, PROG_RAM_SCLK_OFF | PROG_RAM_HCLK_OFF); + + /* Serial engine DMA interface is enabled. */ + geni_setbits32(se->base + SE_DMA_IF_EN, DMA_IF_EN); + + /* Enable or disable FIFO interface of the serial engine. */ + if (se->mode == GENI_SE_FIFO) + geni_clrbits32(se->base + SE_FIFO_IF_DISABLE, FIFO_IF_DISABLE); + else + geni_setbits32(se->base + SE_FIFO_IF_DISABLE, FIFO_IF_DISABLE); + +err_resource: + geni_se_resources_off(se); +err: + geni_icc_disable(se); + return ret; +} + +/** + * qup_fw_load() - Initiate firmware load. + * @se: Pointer to a structure representing SE-related resources. + * @fw_name: Name of the firmware. + * + * Load the firmware into a specific SE. Read the associated ELF file, + * copy the data into a buffer in kernel space using the request_firmware API, write the + * data into the SE's IRAM register, and then free the buffers. Handle firmware loading + * and parsing for a specific protocol. + * + * Return: 0 if successful, otherwise return an error value. + */ +static int qup_fw_load(struct geni_se *se, const char *fw_name) +{ + int ret; + const struct firmware *fw; + struct device *dev = se->dev; + + ret = request_firmware(&fw, fw_name, dev); + if (ret) { + dev_err(dev, "request_firmware failed for %d: %d\n", se->protocol, ret); + return ret; + } + + ret = geni_load_se_fw(se, fw); + + release_firmware(fw); + + return ret; +} + +/** + * geni_load_se_firmware() - Initiate firmware loading. + * @se: Serial engine details. + * @protocol: Protocol (SPI, I2C, or UART) for which the firmware is to be loaded. + * + * If the device tree properties are configured to load QUP firmware and the firmware + * is not already loaded, start the firmware loading process. If the device tree properties + * are not defined, skip loading the firmware, assuming it is already loaded by TZ. + * + * Return: 0 if successful, otherwise return an error value. + */ +int geni_load_se_firmware(struct geni_se *se, enum geni_se_protocol_type protocol) +{ + const char *fw_name; + int ret; + + if (protocol >= MAX_PROTOCOL) { + dev_err(se->dev, "Invalid geni-se protocol: %d", protocol); + return -EINVAL; + } + + ret = device_property_read_string(se->wrapper->dev, "firmware-name", &fw_name); + if (ret) + return -EINVAL; + + se->protocol = protocol; + + if (of_property_read_bool(se->dev->of_node, "qcom,enable-gsi-dma")) + se->mode = GENI_GPI_DMA; + else + se->mode = GENI_SE_FIFO; + + /* GSI mode is not supported by the UART driver; therefore, setting FIFO mode */ + if (protocol == GENI_SE_UART) + se->mode = GENI_SE_FIFO; + + ret = qup_fw_load(se, fw_name); + if (ret) + return ret; + + dev_dbg(se->dev, "Firmware load for %s protocol is successful for xfer mode %d\n", + protocol_name[se->protocol], se->mode); + return 0; +} +EXPORT_SYMBOL_GPL(geni_load_se_firmware); + static int geni_se_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; diff --git a/include/linux/soc/qcom/geni-se.h b/include/linux/soc/qcom/geni-se.h index 2996a3c28ef3e..c6c01c3cf8193 100644 --- a/include/linux/soc/qcom/geni-se.h +++ b/include/linux/soc/qcom/geni-se.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2023-2025 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _LINUX_QCOM_GENI_SE @@ -36,6 +37,7 @@ enum geni_se_protocol_type { GENI_SE_I2C, GENI_SE_I3C, GENI_SE_SPI_SLAVE, + GENI_SE_INVALID_PROTO = 255, }; struct geni_wrapper; @@ -61,6 +63,8 @@ struct geni_icc_path { * @num_clk_levels: Number of valid clock levels in clk_perf_tbl * @clk_perf_tbl: Table of clock frequency input to serial engine clock * @icc_paths: Array of ICC paths for SE + * @mode: Transfer mode se fifo, dma or gsi. + * @protocol: Protocol spi or i2c or serial. */ struct geni_se { void __iomem *base; @@ -70,24 +74,32 @@ struct geni_se { unsigned int num_clk_levels; unsigned long *clk_perf_tbl; struct geni_icc_path icc_paths[3]; + enum geni_se_xfer_mode mode; + enum geni_se_protocol_type protocol; }; /* Common SE registers */ +#define SE_GENI_INIT_CFG_REVISION 0x0 +#define SE_GENI_S_INIT_CFG_REVISION 0x4 #define GENI_FORCE_DEFAULT_REG 0x20 #define GENI_OUTPUT_CTRL 0x24 +#define SE_GENI_CGC_CTRL 0x28 #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_FW_REVISION_RO 0x68 +#define SE_GENI_S_FW_REVISION_RO 0x6c #define SE_GENI_CLK_SEL 0x7c #define SE_GENI_CFG_SEQ_START 0x84 +#define SE_GENI_CFG_REG0 0x100 #define SE_GENI_DMA_MODE_EN 0x258 #define SE_GENI_M_CMD0 0x600 #define SE_GENI_M_CMD_CTRL_REG 0x604 #define SE_GENI_M_IRQ_STATUS 0x610 #define SE_GENI_M_IRQ_EN 0x614 #define SE_GENI_M_IRQ_CLEAR 0x618 +#define SE_GENI_S_IRQ_ENABLE 0x644 #define SE_GENI_M_IRQ_EN_SET 0x61c #define SE_GENI_M_IRQ_EN_CLEAR 0x620 #define SE_GENI_S_CMD0 0x630 @@ -109,13 +121,22 @@ struct geni_se { #define SE_GENI_S_GP_LENGTH 0x914 #define SE_DMA_TX_IRQ_STAT 0xc40 #define SE_DMA_TX_IRQ_CLR 0xc44 +#define SE_DMA_TX_IRQ_EN_SET 0xc4c #define SE_DMA_TX_FSM_RST 0xc58 #define SE_DMA_RX_IRQ_STAT 0xd40 #define SE_DMA_RX_IRQ_CLR 0xd44 +#define SE_DMA_RX_IRQ_EN_SET 0xd4c #define SE_DMA_RX_LEN_IN 0xd54 #define SE_DMA_RX_FSM_RST 0xd58 #define SE_HW_PARAM_0 0xe24 #define SE_HW_PARAM_1 0xe28 +#define SE_DMA_GENERAL_CFG 0xe30 +#define SE_GENI_FW_REVISION 0x1000 +#define SE_S_FW_REVISION 0x1004 +#define SE_GENI_CFG_RAMN 0x1010 +#define SE_GENI_CLK_CTRL 0x2000 +#define SE_DMA_IF_EN 0x2004 +#define SE_FIFO_IF_DISABLE 0x2008 /* GENI_FORCE_DEFAULT_REG fields */ #define FORCE_DEFAULT BIT(0) @@ -137,7 +158,7 @@ struct geni_se { /* GENI_FW_REVISION_RO fields */ #define FW_REV_PROTOCOL_MSK GENMASK(15, 8) -#define FW_REV_PROTOCOL_SHFT 8 +#define FW_REV_VERSION_MSK GENMASK(7, 0) /* GENI_CLK_SEL fields */ #define CLK_SEL_MSK GENMASK(2, 0) @@ -325,9 +346,9 @@ static inline u32 geni_se_read_proto(struct geni_se *se) { u32 val; - val = readl_relaxed(se->base + GENI_FW_REVISION_RO); + val = readl_relaxed(se->base + SE_GENI_FW_REVISION_RO); - return (val & FW_REV_PROTOCOL_MSK) >> FW_REV_PROTOCOL_SHFT; + return FIELD_GET(FW_REV_PROTOCOL_MSK, val); } /** @@ -531,5 +552,7 @@ void geni_icc_set_tag(struct geni_se *se, u32 tag); int geni_icc_enable(struct geni_se *se); int geni_icc_disable(struct geni_se *se); + +int geni_load_se_firmware(struct geni_se *se, enum geni_se_protocol_type protocol); #endif #endif diff --git a/include/linux/soc/qcom/qup-fw-load.h b/include/linux/soc/qcom/qup-fw-load.h new file mode 100644 index 0000000000000..08d8a22ae5141 --- /dev/null +++ b/include/linux/soc/qcom/qup-fw-load.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ +#ifndef _LINUX_QCOM_QUP_FW_LOAD +#define _LINUX_QCOM_QUP_FW_LOAD + +#include + +/*Magic numbers*/ +#define MAGIC_NUM_SE 0x57464553 + +#define MAX_GENI_CFG_RAMn_CNT 455 + +#define MI_PBT_NON_PAGED_SEGMENT 0x0 +#define MI_PBT_HASH_SEGMENT 0x2 +#define MI_PBT_NOTUSED_SEGMENT 0x3 +#define MI_PBT_SHARED_SEGMENT 0x4 + +#define MI_PBT_FLAG_PAGE_MODE BIT(20) +#define MI_PBT_FLAG_SEGMENT_TYPE GENMASK(26, 24) +#define MI_PBT_FLAG_ACCESS_TYPE GENMASK(23, 21) + +#define MI_PBT_PAGE_MODE_VALUE(x) FIELD_GET(MI_PBT_FLAG_PAGE_MODE, x) + +#define MI_PBT_SEGMENT_TYPE_VALUE(x) FIELD_GET(MI_PBT_FLAG_SEGMENT_TYPE, x) + +#define MI_PBT_ACCESS_TYPE_VALUE(x) FIELD_GET(MI_PBT_FLAG_ACCESS_TYPE, x) + +#define M_COMMON_GENI_M_IRQ_EN (GENMASK(6, 1) | \ + M_IO_DATA_DEASSERT_EN | \ + M_IO_DATA_ASSERT_EN | M_RX_FIFO_RD_ERR_EN | \ + M_RX_FIFO_WR_ERR_EN | M_TX_FIFO_RD_ERR_EN | \ + M_TX_FIFO_WR_ERR_EN) + +/* DMA_TX/RX_IRQ_EN fields */ +#define DMA_DONE_EN BIT(0) +#define SBE_EN BIT(2) +#define RESET_DONE_EN BIT(3) +#define FLUSH_DONE_EN BIT(4) + +/* GENI_CLK_CTRL fields */ +#define SER_CLK_SEL BIT(0) + +/* GENI_DMA_IF_EN fields */ +#define DMA_IF_EN BIT(0) + +#define QUPV3_COMMON_CFG 0x120 +#define FAST_SWITCH_TO_HIGH_DISABLE BIT(0) + +#define QUPV3_SE_AHB_M_CFG 0x118 +#define AHB_M_CLK_CGC_ON BIT(0) + +#define QUPV3_COMMON_CGC_CTRL 0x21C +#define COMMON_CSR_SLV_CLK_CGC_ON BIT(0) + +/* access ports */ +#define geni_setbits32(_addr, _v) writel_relaxed(readl_relaxed(_addr) | (_v), _addr) +#define geni_clrbits32(_addr, _v) writel_relaxed(readl_relaxed(_addr) & ~(_v), _addr) + +/** + * struct elf_se_hdr - firmware configurations + * + * @magic: set to 'SEFW' + * @version: A 32-bit value indicating the structure’s version number + * @core_version: QUPV3_HW_VERSION + * @serial_protocol: Programmed into GENI_FW_REVISION + * @fw_version: Programmed into GENI_FW_REVISION + * @cfg_version: Programmed into GENI_INIT_CFG_REVISION + * @fw_size_in_items: Number of (uint32_t) GENI_FW_RAM words + * @fw_offset: Byte offset of GENI_FW_RAM array + * @cfg_items_size: Number of GENI_FW_CFG index/value pairs + * @cfg_idx_offset: Byte offset of GENI_FW_CFG index array + * @cfg_val_offset: Byte offset of GENI_FW_CFG values array + */ +struct elf_se_hdr { + u32 magic; + u32 version; + u32 core_version; + u16 serial_protocol; + u16 fw_version; + u16 cfg_version; + u16 fw_size_in_items; + u16 fw_offset; + u16 cfg_items_size; + u16 cfg_idx_offset; + u16 cfg_val_offset; +}; +#endif /* _LINUX_QCOM_QUP_FW_LOAD */ From c91a56731d827b795c0e6f1e86f98bee89e65761 Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Mon, 14 Oct 2024 16:32:25 +0530 Subject: [PATCH 044/113] FROMLIST: i2c: qcom-geni: Load i2c qup Firmware from linux side Add provision to load firmware of Serial engine for I2C protocol from Linux Execution Environment on running on APPS processor. Link: https://lore.kernel.org/linux-i2c/20250503111029.3583807-4-quic_vdadhani@quicinc.com/ Co-developed-by: Mukesh Kumar Savaliya Signed-off-by: Mukesh Kumar Savaliya Signed-off-by: Viken Dadhaniya --- drivers/i2c/busses/i2c-qcom-geni.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 515a784c951ca..57a99cbaf4a55 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -871,7 +871,13 @@ static int geni_i2c_probe(struct platform_device *pdev) goto err_clk; } proto = geni_se_read_proto(&gi2c->se); - if (proto != GENI_SE_I2C) { + if (proto == GENI_SE_INVALID_PROTO) { + ret = geni_load_se_firmware(&gi2c->se, GENI_SE_I2C); + if (ret) { + dev_err_probe(dev, ret, "i2c firmware load failed ret: %d\n", ret); + goto err_resources; + } + } else if (proto != GENI_SE_I2C) { ret = dev_err_probe(dev, -ENXIO, "Invalid proto %d\n", proto); goto err_resources; } From 0389bab6d9e634c3dbcab2684270b4fbdea20ab2 Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Mon, 14 Oct 2024 16:35:57 +0530 Subject: [PATCH 045/113] FROMLIST: spi: geni-qcom: Load spi qup Firmware from linux side Add provision to load firmware of Serial engine for SPI protocol from Linux Execution Environment on running on APPS processor. Link: https://lore.kernel.org/linux-i2c/20250503111029.3583807-5-quic_vdadhani@quicinc.com/ Co-developed-by: Mukesh Kumar Savaliya Signed-off-by: Mukesh Kumar Savaliya Signed-off-by: Viken Dadhaniya --- drivers/spi/spi-geni-qcom.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 768d7482102ad..a0d8d3425c6c6 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -671,6 +671,12 @@ static int spi_geni_init(struct spi_geni_master *mas) goto out_pm; } spi_slv_setup(mas); + } else if (proto == GENI_SE_INVALID_PROTO) { + ret = geni_load_se_firmware(se, GENI_SE_SPI); + if (ret) { + dev_err(mas->dev, "spi master firmware load failed ret: %d\n", ret); + goto out_pm; + } } else if (proto != GENI_SE_SPI) { dev_err(mas->dev, "Invalid proto %d\n", proto); goto out_pm; From ed0f1f841818b59155935b6047ac1f5b3b5a1e57 Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Mon, 14 Oct 2024 16:43:36 +0530 Subject: [PATCH 046/113] FROMLIST: serial: qcom-geni: Load UART qup Firmware from linux side Add provision to load firmware of Serial engine for UART protocol from Linux Execution Environment on running on APPS processor. Link: https://lore.kernel.org/linux-i2c/20250503111029.3583807-6-quic_vdadhani@quicinc.com/ Co-developed-by: Mukesh Kumar Savaliya Signed-off-by: Mukesh Kumar Savaliya Signed-off-by: Viken Dadhaniya --- drivers/tty/serial/qcom_geni_serial.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index a80ce7aaf309d..ae66c5f673a6d 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -1145,7 +1145,13 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) int ret; proto = geni_se_read_proto(&port->se); - if (proto != GENI_SE_UART) { + if (proto == GENI_SE_INVALID_PROTO) { + ret = geni_load_se_firmware(&port->se, GENI_SE_UART); + if (ret) { + dev_err(uport->dev, "UART firmware load failed ret: %d\n", ret); + return ret; + } + } else if (proto != GENI_SE_UART) { dev_err(uport->dev, "Invalid FW loaded, proto: %d\n", proto); return -ENXIO; } From adf3d0ae30d0e39e7db861824b705b7f7a3040bc Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Fri, 1 Dec 2023 16:36:31 +0530 Subject: [PATCH 047/113] FROMLIST: rpmsg: glink: smem: validate index before fifo read write Fifo head and tail index can be modified with wrong values from untrusted remote procs. Glink smem is not validating these index before using to read or write fifo. This can result in out of bound memory access if head and tail have incorrect values. Add check for validation of head and tail index. This check will put index within fifo boundaries, so that no invalid memory access is made. Further this may result in certain packet drops unless glink finds a valid packet header in fifo again and recovers. Crash signature and calltrace with wrong head and tail values: Internal error: Oops: 96000007 [#1] PREEMPT SMP pc : __memcpy_fromio+0x34/0xb4 lr : glink_smem_rx_peak+0x68/0x94 __memcpy_fromio+0x34/0xb4 glink_smem_rx_peak+0x68/0x94 qcom_glink_native_intr+0x90/0x888 Link: https://lore.kernel.org/r/20231201110631.669085-1-quic_deesin@quicinc.com Signed-off-by: Deepak Kumar Singh --- drivers/rpmsg/qcom_glink_smem.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index 7a982c60a8ddc..9eba0aaae916a 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -86,9 +86,14 @@ static size_t glink_smem_rx_avail(struct qcom_glink_pipe *np) tail = le32_to_cpu(*pipe->tail); if (head < tail) - return pipe->native.length - tail + head; + len = pipe->native.length - tail + head; else - return head - tail; + len = head - tail; + + if (WARN_ON_ONCE(len > pipe->native.length)) + len = 0; + + return len; } static void glink_smem_rx_peek(struct qcom_glink_pipe *np, @@ -99,6 +104,10 @@ static void glink_smem_rx_peek(struct qcom_glink_pipe *np, u32 tail; tail = le32_to_cpu(*pipe->tail); + + if (WARN_ON_ONCE(tail > pipe->native.length)) + return; + tail += offset; if (tail >= pipe->native.length) tail -= pipe->native.length; @@ -121,7 +130,7 @@ static void glink_smem_rx_advance(struct qcom_glink_pipe *np, tail += count; if (tail >= pipe->native.length) - tail -= pipe->native.length; + tail %= pipe->native.length; *pipe->tail = cpu_to_le32(tail); } @@ -146,6 +155,9 @@ static size_t glink_smem_tx_avail(struct qcom_glink_pipe *np) else avail -= FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE; + if (WARN_ON_ONCE(avail > pipe->native.length)) + avail = 0; + return avail; } @@ -155,6 +167,9 @@ static unsigned int glink_smem_tx_write_one(struct glink_smem_pipe *pipe, { size_t len; + if (WARN_ON_ONCE(head > pipe->native.length)) + return head; + len = min_t(size_t, count, pipe->native.length - head); if (len) memcpy(pipe->fifo + head, data, len); From 7479b77ed6e1cc7e7ff10812605b47cd10cba6c3 Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Tue, 13 May 2025 09:58:21 +0530 Subject: [PATCH 048/113] FROMLIST: misc: fastrpc: Add NULL check to fastrpc_buf_free to prevent crash The fastrpc_buf_free function currently does not handle the case where the input buffer pointer (buf) is NULL. This can lead to a null pointer dereference, causing a crash or undefined behavior when the function attempts to access members of the buf structure. Add a NULL check to ensure safe handling of NULL pointers and prevent potential crashes. Link: https://lore.kernel.org/all/20250513042825.2147985-2-ekansh.gupta@oss.qualcomm.com/ Fixes: c68cfb718c8f9 ("misc: fastrpc: Add support for context Invoke method") Cc: stable@kernel.org Signed-off-by: Ekansh Gupta --- drivers/misc/fastrpc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 378923594f024..af8b5dafbcfa4 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -394,6 +394,9 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd, static void fastrpc_buf_free(struct fastrpc_buf *buf) { + if (!buf) + return; + dma_free_coherent(buf->dev, buf->size, buf->virt, FASTRPC_PHYS(buf->phys)); kfree(buf); From 12ea1591ee84bee4bb703c52b32aa5522e7711bc Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Tue, 13 May 2025 09:58:22 +0530 Subject: [PATCH 049/113] FROMLIST: misc: fastrpc: Move all remote heap allocations to a new list Remote heap allocations are not organized in a maintainable manner, leading to potential issues with memory management. As the remote heap allocations are maintained in fl mmaps list, the allocations will go away if the audio daemon process is killed but there are chances that audio PD might still be using the memory. Move all remote heap allocations to a dedicated list where the entries are cleaned only for user requests and subsystem shutdown. Link: https://lore.kernel.org/all/20250513042825.2147985-3-ekansh.gupta@oss.qualcomm.com/ Fixes: 0871561055e66 ("misc: fastrpc: Add support for audiopd") Cc: stable@kernel.org Signed-off-by: Ekansh Gupta --- drivers/misc/fastrpc.c | 93 ++++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 21 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index af8b5dafbcfa4..b61e39da4fcb7 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -273,10 +273,12 @@ struct fastrpc_channel_ctx { struct kref refcount; /* Flag if dsp attributes are cached */ bool valid_attributes; + /* Flag if audio PD init mem was allocated */ + bool audio_init_mem; u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES]; struct fastrpc_device *secure_fdevice; struct fastrpc_device *fdevice; - struct fastrpc_buf *remote_heap; + struct list_head rhmaps; struct list_head invoke_interrupted_mmaps; bool secure; bool unsigned_support; @@ -1237,12 +1239,47 @@ static bool is_session_rejected(struct fastrpc_user *fl, bool unsigned_pd_reques return false; } +static void fastrpc_cleanup_rhmaps(struct fastrpc_channel_ctx *cctx) +{ + struct fastrpc_buf *buf, *b; + struct list_head temp_list; + int err; + unsigned long flags; + + INIT_LIST_HEAD(&temp_list); + + spin_lock_irqsave(&cctx->lock, flags); + list_splice_init(&cctx->rhmaps, &temp_list); + spin_unlock_irqrestore(&cctx->lock, flags); + + list_for_each_entry_safe(buf, b, &temp_list, node) { + if (cctx->vmcount) { + u64 src_perms = 0; + struct qcom_scm_vmperm dst_perms; + u32 i; + + for (i = 0; i < cctx->vmcount; i++) + src_perms |= BIT(cctx->vmperms[i].vmid); + + dst_perms.vmid = QCOM_SCM_VMID_HLOS; + dst_perms.perm = QCOM_SCM_PERM_RWX; + err = qcom_scm_assign_mem(buf->phys, (u64)buf->size, + &src_perms, &dst_perms, 1); + if (err) + continue; + } + fastrpc_buf_free(buf); + } +} + static int fastrpc_init_create_static_process(struct fastrpc_user *fl, char __user *argp) { struct fastrpc_init_create_static init; struct fastrpc_invoke_args *args; struct fastrpc_phy_page pages[1]; + struct fastrpc_buf *buf = NULL; + u64 phys = 0, size = 0; char *name; int err; bool scm_done = false; @@ -1252,6 +1289,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, u32 pageslen; } inbuf; u32 sc; + unsigned long flags; args = kcalloc(FASTRPC_CREATE_STATIC_PROCESS_NARGS, sizeof(*args), GFP_KERNEL); if (!args) @@ -1273,26 +1311,30 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, goto err; } - if (!fl->cctx->remote_heap) { + if (!fl->cctx->audio_init_mem) { err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen, - &fl->cctx->remote_heap); + &buf); if (err) goto err_name; + phys = buf->phys; + size = buf->size; /* Map if we have any heap VMIDs associated with this ADSP Static Process. */ if (fl->cctx->vmcount) { u64 src_perms = BIT(QCOM_SCM_VMID_HLOS); - err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys, - (u64)fl->cctx->remote_heap->size, - &src_perms, - fl->cctx->vmperms, fl->cctx->vmcount); + err = qcom_scm_assign_mem(phys, size, &src_perms, + fl->cctx->vmperms, fl->cctx->vmcount); if (err) { dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n", - fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err); + phys, size, err); goto err_map; } scm_done = true; + spin_lock_irqsave(&fl->cctx->lock, flags); + list_add_tail(&buf->node, &fl->cctx->rhmaps); + spin_unlock_irqrestore(&fl->cctx->lock, flags); + fl->cctx->audio_init_mem = true; } } @@ -1309,8 +1351,8 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, args[1].length = inbuf.namelen; args[1].fd = -1; - pages[0].addr = fl->cctx->remote_heap->phys; - pages[0].size = fl->cctx->remote_heap->size; + pages[0].addr = phys; + pages[0].size = size; args[2].ptr = (u64)(uintptr_t) pages; args[2].length = sizeof(*pages); @@ -1328,6 +1370,11 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, return 0; err_invoke: + if (buf) { + spin_lock_irqsave(&fl->cctx->lock, flags); + list_del(&buf->node); + spin_unlock_irqrestore(&fl->cctx->lock, flags); + } if (fl->cctx->vmcount && scm_done) { u64 src_perms = 0; struct qcom_scm_vmperm dst_perms; @@ -1338,15 +1385,15 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, dst_perms.vmid = QCOM_SCM_VMID_HLOS; dst_perms.perm = QCOM_SCM_PERM_RWX; - err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys, - (u64)fl->cctx->remote_heap->size, - &src_perms, &dst_perms, 1); + err = qcom_scm_assign_mem(phys, size, &src_perms, + &dst_perms, 1); if (err) dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n", - fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err); + phys, size, err); } err_map: - fastrpc_buf_free(fl->cctx->remote_heap); + fl->cctx->audio_init_mem = false; + fastrpc_buf_free(buf); err_name: kfree(name); err: @@ -1869,6 +1916,7 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) struct device *dev = fl->sctx->dev; int err; u32 sc; + unsigned long flags; if (copy_from_user(&req, argp, sizeof(req))) return -EFAULT; @@ -1937,12 +1985,15 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) buf->phys, buf->size, err); goto err_assign; } + spin_lock_irqsave(&fl->cctx->lock, flags); + list_add_tail(&buf->node, &fl->cctx->rhmaps); + spin_unlock_irqrestore(&fl->cctx->lock, flags); + } else { + spin_lock(&fl->lock); + list_add_tail(&buf->node, &fl->mmaps); + spin_unlock(&fl->lock); } - spin_lock(&fl->lock); - list_add_tail(&buf->node, &fl->mmaps); - spin_unlock(&fl->lock); - if (copy_to_user((void __user *)argp, &req, sizeof(req))) { err = -EFAULT; goto err_assign; @@ -2362,6 +2413,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) rdev->dma_mask = &data->dma_mask; dma_set_mask_and_coherent(rdev, DMA_BIT_MASK(32)); INIT_LIST_HEAD(&data->users); + INIT_LIST_HEAD(&data->rhmaps); INIT_LIST_HEAD(&data->invoke_interrupted_mmaps); spin_lock_init(&data->lock); idr_init(&data->ctx_idr); @@ -2420,8 +2472,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node) list_del(&buf->node); - if (cctx->remote_heap) - fastrpc_buf_free(cctx->remote_heap); + fastrpc_cleanup_rhmaps(cctx); of_platform_depopulate(&rpdev->dev); From 419cf1f9e4086867893f6324a19986af871bff77 Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Tue, 13 May 2025 09:58:23 +0530 Subject: [PATCH 050/113] FROMLIST: misc: fastrpc: Fix initial memory allocation for Audio PD memory pool The initially allocated memory is not properly included in the pool, leading to potential issues with memory management. Set the number of pages to one to ensure that the initially allocated memory is correctly added to the Audio PD memory pool. Link: https://lore.kernel.org/all/20250513042825.2147985-4-ekansh.gupta@oss.qualcomm.com/ Fixes: 0871561055e66 ("misc: fastrpc: Add support for audiopd") Cc: stable@kernel.org Signed-off-by: Ekansh Gupta --- drivers/misc/fastrpc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index b61e39da4fcb7..8dcb676511b05 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1311,6 +1311,9 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, goto err; } + inbuf.client_id = fl->client_id; + inbuf.namelen = init.namelen; + inbuf.pageslen = 0; if (!fl->cctx->audio_init_mem) { err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen, &buf); @@ -1335,12 +1338,10 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, list_add_tail(&buf->node, &fl->cctx->rhmaps); spin_unlock_irqrestore(&fl->cctx->lock, flags); fl->cctx->audio_init_mem = true; + inbuf.pageslen = 1; } } - inbuf.client_id = fl->client_id; - inbuf.namelen = init.namelen; - inbuf.pageslen = 0; fl->pd = USER_PD; args[0].ptr = (u64)(uintptr_t)&inbuf; From 4006038b028526f96f533ab17c49997316cc6f91 Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Tue, 13 May 2025 09:58:24 +0530 Subject: [PATCH 051/113] FROMLIST: misc: fastrpc: Remove buffer from list prior to unmap operation fastrpc_req_munmap_impl() is called to unmap any buffer. The buffer is getting removed from the list after it is unmapped from DSP. This can create potential race conditions if any other thread removes the entry from list while unmap operation is ongoing. Remove the entry before calling unmap operation. Link: https://lore.kernel.org/all/20250513042825.2147985-5-ekansh.gupta@oss.qualcomm.com/ Fixes: 2419e55e532de ("misc: fastrpc: add mmap/unmap support") Cc: stable@kernel.org Signed-off-by: Ekansh Gupta --- drivers/misc/fastrpc.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 8dcb676511b05..28911bb965a03 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1868,9 +1868,6 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf * &args[0]); if (!err) { dev_dbg(dev, "unmmap\tpt 0x%09lx OK\n", buf->raddr); - spin_lock(&fl->lock); - list_del(&buf->node); - spin_unlock(&fl->lock); fastrpc_buf_free(buf); } else { dev_err(dev, "unmmap\tpt 0x%09lx ERROR\n", buf->raddr); @@ -1884,13 +1881,15 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) struct fastrpc_buf *buf = NULL, *iter, *b; struct fastrpc_req_munmap req; struct device *dev = fl->sctx->dev; + int err; if (copy_from_user(&req, argp, sizeof(req))) return -EFAULT; spin_lock(&fl->lock); list_for_each_entry_safe(iter, b, &fl->mmaps, node) { - if ((iter->raddr == req.vaddrout) && (iter->size == req.size)) { + if (iter->raddr == req.vaddrout && iter->size == req.size) { + list_del(&iter->node); buf = iter; break; } @@ -1903,7 +1902,14 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) return -EINVAL; } - return fastrpc_req_munmap_impl(fl, buf); + err = fastrpc_req_munmap_impl(fl, buf); + if (err) { + spin_lock(&fl->lock); + list_add_tail(&buf->node, &fl->mmaps); + spin_unlock(&fl->lock); + } + + return err; } static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) @@ -1997,14 +2003,23 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) if (copy_to_user((void __user *)argp, &req, sizeof(req))) { err = -EFAULT; - goto err_assign; + goto err_copy; } dev_dbg(dev, "mmap\t\tpt 0x%09lx OK [len 0x%08llx]\n", buf->raddr, buf->size); return 0; - +err_copy: + if (req.flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + spin_lock_irqsave(&fl->cctx->lock, flags); + list_del(&buf->node); + spin_unlock_irqrestore(&fl->cctx->lock, flags); + } else { + spin_lock(&fl->lock); + list_del(&buf->node); + spin_unlock(&fl->lock); + } err_assign: fastrpc_req_munmap_impl(fl, buf); From 5a94c05e12cbc5cecb3a039d67c51bd8aff0ecec Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Tue, 13 May 2025 09:58:25 +0530 Subject: [PATCH 052/113] FROMLIST: misc: fastrpc: Add missing unmapping user-requested remote heap User request for remote heap allocation is supported using ioctl interface but support for unmap is missing. This could result in memory leak issues. Add unmap user request support for remote heap. Link: https://lore.kernel.org/all/20250513042825.2147985-6-ekansh.gupta@oss.qualcomm.com/ Fixes: 532ad70c6d449 ("misc: fastrpc: Add mmap request assigning for static PD pool") Cc: stable@kernel.org Signed-off-by: Ekansh Gupta --- drivers/misc/fastrpc.c | 62 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 28911bb965a03..4e4c157f29170 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -197,6 +197,8 @@ struct fastrpc_buf { struct dma_buf *dmabuf; struct device *dev; void *virt; + /* Type of buffer */ + u32 flag; u64 phys; u64 size; /* Lock for dma buf attachments */ @@ -1867,8 +1869,26 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf * err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc, &args[0]); if (!err) { - dev_dbg(dev, "unmmap\tpt 0x%09lx OK\n", buf->raddr); + if (buf->flag == ADSP_MMAP_REMOTE_HEAP_ADDR && fl->cctx->vmcount) { + u64 src_perms = 0; + struct qcom_scm_vmperm dst_perms; + u32 i; + + for (i = 0; i < fl->cctx->vmcount; i++) + src_perms |= BIT(fl->cctx->vmperms[i].vmid); + + dst_perms.vmid = QCOM_SCM_VMID_HLOS; + dst_perms.perm = QCOM_SCM_PERM_RWX; + err = qcom_scm_assign_mem(buf->phys, (u64)buf->size, + &src_perms, &dst_perms, 1); + if (err) { + dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n", + buf->phys, buf->size, err); + return err; + } + } fastrpc_buf_free(buf); + dev_dbg(dev, "unmmap\tpt 0x%09lx OK\n", buf->raddr); } else { dev_err(dev, "unmmap\tpt 0x%09lx ERROR\n", buf->raddr); } @@ -1882,6 +1902,7 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) struct fastrpc_req_munmap req; struct device *dev = fl->sctx->dev; int err; + unsigned long flags; if (copy_from_user(&req, argp, sizeof(req))) return -EFAULT; @@ -1896,20 +1917,38 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) } spin_unlock(&fl->lock); - if (!buf) { - dev_err(dev, "mmap\t\tpt 0x%09llx [len 0x%08llx] not in list\n", - req.vaddrout, req.size); - return -EINVAL; + if (buf) { + err = fastrpc_req_munmap_impl(fl, buf); + if (err) { + spin_lock(&fl->lock); + list_add_tail(&buf->node, &fl->mmaps); + spin_unlock(&fl->lock); + } + return err; } - err = fastrpc_req_munmap_impl(fl, buf); - if (err) { - spin_lock(&fl->lock); - list_add_tail(&buf->node, &fl->mmaps); - spin_unlock(&fl->lock); + spin_lock_irqsave(&fl->cctx->lock, flags); + list_for_each_entry_safe(iter, b, &fl->cctx->rhmaps, node) { + if (iter->raddr == req.vaddrout && iter->size == req.size) { + list_del(&iter->node); + buf = iter; + break; + } } + spin_unlock_irqrestore(&fl->cctx->lock, flags); + if (buf) { + err = fastrpc_req_munmap_impl(fl, buf); + if (err) { + spin_lock_irqsave(&fl->cctx->lock, flags); + list_add_tail(&buf->node, &fl->cctx->rhmaps); + spin_unlock_irqrestore(&fl->cctx->lock, flags); + } + return err; + } + dev_err(dev, "mmap\t\tpt 0x%09llx [len 0x%08llx] not in list\n", + req.vaddrout, req.size); - return err; + return -EINVAL; } static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) @@ -1977,6 +2016,7 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) /* update the buffer to be able to deallocate the memory on the DSP */ buf->raddr = (uintptr_t) rsp_msg.vaddr; + buf->flag = req.flags; /* let the client know the address to use */ req.vaddrout = rsp_msg.vaddr; From af64cb8991de1c62361cf9f27a09c39786a6d08a Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Mon, 3 Mar 2025 13:08:34 -0800 Subject: [PATCH 053/113] FROMLIST: arm64: dts: qcom: sa8775p-ride: Add PSCI SYSTEM_RESET2 types sa8775p-ride firmware supports vendor-defined SYSTEM_RESET2 types. Describe the reset types: "bootloader" will cause device to reboot and stop in the bootloader's fastboot mode. "edl" will cause device to reboot into "emergency download mode", which permits loading images via the Firehose protocol. Link: https://lore.kernel.org/r/20250303-arm-psci-system_reset2-vendor-reboots-v9-5-b2cf4a20feda@oss.qualcomm.com Co-developed-by: Shivendra Pratap Signed-off-by: Shivendra Pratap Reviewed-by: Konrad Dybcio Signed-off-by: Elliot Berman --- arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi | 7 +++++++ arch/arm64/boot/dts/qcom/sa8775p.dtsi | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi index 3ae416ab66e8b..aea13e45a1e23 100644 --- a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi @@ -651,6 +651,13 @@ "GNSS_BOOT_MODE"; }; +&psci { + reset-types { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; +}; + &qupv3_id_1 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi index 45f536633f644..9efecf2f88a90 100644 --- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi @@ -409,7 +409,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; From b92981178cf7e5dadbe8a850823651cb25136ce7 Mon Sep 17 00:00:00 2001 From: Wasim Nazir Date: Thu, 12 Jun 2025 21:24:32 +0530 Subject: [PATCH 054/113] FROMLIST: dt-bindings: arm: qcom: Add bindings for QCS9075 SOC based board QCS9075 is compatible Industrial-IOT grade variant of SA8775p SOC. Unlike QCS9100, it doesn't have safety monitoring feature of Safety-Island(SAIL) subsystem, which affects thermal management. qcs9075-iq-9075-evk board is based on QCS9075 SOC. Link: https://lore.kernel.org/r/20250612155437.146925-2-quic_wasimn@quicinc.com Acked-by: Rob Herring (Arm) Acked-by: Krzysztof Kozlowski Signed-off-by: Wasim Nazir --- Documentation/devicetree/bindings/arm/qcom.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index 56f78f0f3803f..3b2c60af12cd0 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -58,6 +58,7 @@ description: | qcs8550 qcm2290 qcm6490 + qcs9075 qcs9100 qdu1000 qrb2210 @@ -961,6 +962,12 @@ properties: - qcom,sa8775p-ride-r3 - const: qcom,sa8775p + - items: + - enum: + - qcom,qcs9075-iq-9075-evk + - const: qcom,qcs9075 + - const: qcom,sa8775p + - items: - enum: - qcom,qcs9100-ride From c8ab3ca2154012f70236369528d8ab439b0d15be Mon Sep 17 00:00:00 2001 From: Wasim Nazir Date: Thu, 12 Jun 2025 21:24:33 +0530 Subject: [PATCH 055/113] FROMLIST: arm64: dts: qcom: Add qcs9075 IoT SOC devicetree QCS9075 is an IoT variant of SA8775P SOC, most notably without safety monitoring feature of Safety Island(SAIL) subsystem. Add a new device tree file for the QCS9075 IoT SOC, which inherits changes from the SA8775P SOC. Update the memory map to reflect the differences between the two SOCs. As part of the memory-map updates, introduce new carveouts for gunyah_md and pil dtb, and adjust the size and base address of the PIL carveout to accomodate the changes. Increase the size of the video/camera PIL carveout without breaking any features. Reduce the size of the trusted apps carveout to meet IoT requirements. Remove audio_mdf_mem, tz_ffi_mem, and their corresponding scm references, as they are not required for IoT parts. Link: https://lore.kernel.org/r/20250612155437.146925-3-quic_wasimn@quicinc.com Co-developed-by: Pratyush Brahma Signed-off-by: Pratyush Brahma Co-developed-by: Prakash Gupta Signed-off-by: Prakash Gupta Signed-off-by: Wasim Nazir --- arch/arm64/boot/dts/qcom/qcs9075.dtsi | 116 ++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs9075.dtsi diff --git a/arch/arm64/boot/dts/qcom/qcs9075.dtsi b/arch/arm64/boot/dts/qcom/qcs9075.dtsi new file mode 100644 index 0000000000000..f3b1c5788367a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs9075.dtsi @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "sa8775p.dtsi" + +/delete-node/ &pil_camera_mem; +/delete-node/ &pil_adsp_mem; +/delete-node/ &pil_gdsp0_mem; +/delete-node/ &pil_gdsp1_mem; +/delete-node/ &pil_cdsp0_mem; +/delete-node/ &pil_gpu_mem; +/delete-node/ &pil_cdsp1_mem; +/delete-node/ &pil_cvp_mem; +/delete-node/ &pil_video_mem; +/delete-node/ &audio_mdf_mem; +/delete-node/ &trusted_apps_mem; +/delete-node/ &hyptz_reserved_mem; +/delete-node/ &tz_ffi_mem; + +/ { + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gunyah_md_mem: gunyah-md@91a80000 { + reg = <0x0 0x91a80000 0x0 0x80000>; + no-map; + }; + + pil_camera_mem: pil-camera@95200000 { + reg = <0x0 0x95200000 0x0 0x700000>; + no-map; + }; + + pil_adsp_mem: pil-adsp@95900000 { + reg = <0x0 0x95900000 0x0 0x1e00000>; + no-map; + }; + + q6_adsp_dtb_mem: q6-adsp-dtb@97700000 { + reg = <0x0 0x97700000 0x0 0x80000>; + no-map; + }; + + q6_gdsp0_dtb_mem: q6-gdsp0-dtb@97780000 { + reg = <0x0 0x97780000 0x0 0x80000>; + no-map; + }; + + pil_gdsp0_mem: pil-gdsp0@97800000 { + reg = <0x0 0x97800000 0x0 0x1e00000>; + no-map; + }; + + pil_gdsp1_mem: pil-gdsp1@99600000 { + reg = <0x0 0x99600000 0x0 0x1e00000>; + no-map; + }; + + q6_gdsp1_dtb_mem: q6-gdsp1-dtb@9b400000 { + reg = <0x0 0x9b400000 0x0 0x80000>; + no-map; + }; + + q6_cdsp0_dtb_mem: q6-cdsp0-dtb@9b480000 { + reg = <0x0 0x9b480000 0x0 0x80000>; + no-map; + }; + + pil_cdsp0_mem: pil-cdsp0@9b500000 { + reg = <0x0 0x9b500000 0x0 0x1e00000>; + no-map; + }; + + pil_gpu_mem: pil-gpu@9d300000 { + reg = <0x0 0x9d300000 0x0 0x2000>; + no-map; + }; + + q6_cdsp1_dtb_mem: q6-cdsp1-dtb@9d380000 { + reg = <0x0 0x9d380000 0x0 0x80000>; + no-map; + }; + + pil_cdsp1_mem: pil-cdsp1@9d400000 { + reg = <0x0 0x9d400000 0x0 0x1e00000>; + no-map; + }; + + pil_cvp_mem: pil-cvp@9f200000 { + reg = <0x0 0x9f200000 0x0 0x700000>; + no-map; + }; + + pil_video_mem: pil-video@9f900000 { + reg = <0x0 0x9f900000 0x0 0x1000000>; + no-map; + }; + + trusted_apps_mem: trusted-apps@d1900000 { + reg = <0x0 0xd1900000 0x0 0x1c00000>; + no-map; + }; + }; + + firmware { + scm { + /delete-property/ memory-region; + }; + }; +}; From a9098fc761d7c52bde6233edfc2d753cccad96c3 Mon Sep 17 00:00:00 2001 From: Wasim Nazir Date: Thu, 12 Jun 2025 21:24:34 +0530 Subject: [PATCH 056/113] FROMLIST: arm64: dts: qcom: Add support for qcs9075 IQ-9075-EVK Add initial device tree support for IQ-9075-EVK board, based on Qualcomm's QCS9075 SOC. Implement basic features like uart/ufs to enable boot to shell. Link: https://lore.kernel.org/r/20250612155437.146925-4-quic_wasimn@quicinc.com Co-developed-by: Rakesh Kota Signed-off-by: Rakesh Kota Co-developed-by: Sayali Lokhande Signed-off-by: Sayali Lokhande Reviewed-by: Konrad Dybcio Signed-off-by: Wasim Nazir --- arch/arm64/boot/dts/qcom/Makefile | 1 + .../boot/dts/qcom/qcs9075-iq-9075-evk.dts | 290 ++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs9075-iq-9075-evk.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 669b888b27a1d..77501a13d91e0 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -124,6 +124,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs8550-aim300-aiot.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs9075-iq-9075-evk.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3.dtb dtb-$(CONFIG_ARCH_QCOM) += qdu1000-idp.dtb diff --git a/arch/arm64/boot/dts/qcom/qcs9075-iq-9075-evk.dts b/arch/arm64/boot/dts/qcom/qcs9075-iq-9075-evk.dts new file mode 100644 index 0000000000000..ab161180d1d5a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs9075-iq-9075-evk.dts @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2024-2025, Qualcomm Innovation Center, Inc. All rights reserved. + */ +/dts-v1/; + +#include +#include + +#include "qcs9075.dtsi" +#include "sa8775p-pmics.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. IQ 9075 EVK"; + compatible = "qcom,qcs9075-iq-9075-evk", "qcom,qcs9075", "qcom,sa8775p"; + + aliases { + serial0 = &uart10; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pmm8654au-rpmh-regulators"; + qcom,pmic-id = "a"; + + vreg_s4a: smps4 { + regulator-name = "vreg_s4a"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1816000>; + regulator-initial-mode = ; + }; + + vreg_s5a: smps5 { + regulator-name = "vreg_s5a"; + regulator-min-microvolt = <1850000>; + regulator-max-microvolt = <1996000>; + regulator-initial-mode = ; + }; + + vreg_s9a: smps9 { + regulator-name = "vreg_s9a"; + regulator-min-microvolt = <535000>; + regulator-max-microvolt = <1120000>; + regulator-initial-mode = ; + }; + + vreg_l4a: ldo4 { + regulator-name = "vreg_l4a"; + regulator-min-microvolt = <788000>; + regulator-max-microvolt = <1050000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l5a: ldo5 { + regulator-name = "vreg_l5a"; + regulator-min-microvolt = <870000>; + regulator-max-microvolt = <950000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l6a: ldo6 { + regulator-name = "vreg_l6a"; + regulator-min-microvolt = <870000>; + regulator-max-microvolt = <970000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7a: ldo7 { + regulator-name = "vreg_l7a"; + regulator-min-microvolt = <720000>; + regulator-max-microvolt = <950000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8a: ldo8 { + regulator-name = "vreg_l8a"; + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <3300000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l9a: ldo9 { + regulator-name = "vreg_l9a"; + regulator-min-microvolt = <2970000>; + regulator-max-microvolt = <3544000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + regulators-1 { + compatible = "qcom,pmm8654au-rpmh-regulators"; + qcom,pmic-id = "c"; + + vreg_l1c: ldo1 { + regulator-name = "vreg_l1c"; + regulator-min-microvolt = <1140000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2c: ldo2 { + regulator-name = "vreg_l2c"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1100000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l3c: ldo3 { + regulator-name = "vreg_l3c"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1300000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4c: ldo4 { + regulator-name = "vreg_l4c"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l5c: ldo5 { + regulator-name = "vreg_l5c"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1300000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l6c: ldo6 { + regulator-name = "vreg_l6c"; + regulator-min-microvolt = <1620000>; + regulator-max-microvolt = <1980000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7c: ldo7 { + regulator-name = "vreg_l7c"; + regulator-min-microvolt = <1620000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8c: ldo8 { + regulator-name = "vreg_l8c"; + regulator-min-microvolt = <2400000>; + regulator-max-microvolt = <3300000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l9c: ldo9 { + regulator-name = "vreg_l9c"; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2700000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + regulators-2 { + compatible = "qcom,pmm8654au-rpmh-regulators"; + qcom,pmic-id = "e"; + + vreg_s4e: smps4 { + regulator-name = "vreg_s4e"; + regulator-min-microvolt = <970000>; + regulator-max-microvolt = <1520000>; + regulator-initial-mode = ; + }; + + vreg_s7e: smps7 { + regulator-name = "vreg_s7e"; + regulator-min-microvolt = <1010000>; + regulator-max-microvolt = <1170000>; + regulator-initial-mode = ; + }; + + vreg_s9e: smps9 { + regulator-name = "vreg_s9e"; + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <570000>; + regulator-initial-mode = ; + }; + + vreg_l6e: ldo6 { + regulator-name = "vreg_l6e"; + regulator-min-microvolt = <1280000>; + regulator-max-microvolt = <1450000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8e: ldo8 { + regulator-name = "vreg_l8e"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1950000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; +}; + +&qupv3_id_1 { + status = "okay"; +}; + +&sleep_clk { + clock-frequency = <32768>; +}; + +&uart10 { + compatible = "qcom,geni-debug-uart"; + pinctrl-0 = <&qup_uart10_default>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&ufs_mem_hc { + reset-gpios = <&tlmm 149 GPIO_ACTIVE_LOW>; + vcc-supply = <&vreg_l8a>; + vcc-max-microamp = <1100000>; + vccq-supply = <&vreg_l4c>; + vccq-max-microamp = <1200000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l4a>; + vdda-pll-supply = <&vreg_l1c>; + + status = "okay"; +}; + +&xo_board_clk { + clock-frequency = <38400000>; +}; From d53874cdcf27e2e6f613228d81c28464df62970a Mon Sep 17 00:00:00 2001 From: Tingguo Cheng Date: Thu, 29 May 2025 11:47:08 +0800 Subject: [PATCH 057/113] FROMLIST: arm64: dts: qcom: sa8775p: pmic: enable rtc Add RTC node, the RTC is controlled by PMIC device via spmi bus. Link: https://lore.kernel.org/r/20250529-add-rtc-for-sa8775p-v2-1-f06fd212c0e5@oss.qualcomm.com Reviewed-by: Dmitry Baryshkov Signed-off-by: Tingguo Cheng --- arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi b/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi index 1369c3d43f866..9e0d05c1b39ce 100644 --- a/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi @@ -132,6 +132,13 @@ }; }; + pmm8654au_0_rtc: rtc@6100 { + compatible = "qcom,pmk8350-rtc"; + reg = <0x6100>, <0x6200>; + reg-names = "rtc", "alarm"; + interrupts = <0x0 0x62 0x1 IRQ_TYPE_EDGE_RISING>; + }; + pmm8654au_0_gpios: gpio@8800 { compatible = "qcom,pmm8654au-gpio", "qcom,spmi-gpio"; reg = <0x8800>; From 6cc4b79328197a405e8e46bdbffc7ecd1d511f15 Mon Sep 17 00:00:00 2001 From: Raviteja Laggyshetty Date: Tue, 15 Apr 2025 09:53:42 +0000 Subject: [PATCH 058/113] FROMGIT: arm64: dts: qcom: sa8775p: add EPSS l3 interconnect provider Add Epoch Subsystem (EPSS) L3 interconnect provider node on SA8775P SoCs. L3 instances on this SoC are same as SM8250 and SC7280 SoCs. These SoCs use EPSS_L3_PERF register instead of REG_L3_VOTE register for programming the perf level. This is taken care in the data associated with the target specific compatible. Since, the HW is same in the all SoCs with EPSS support, using the same generic compatible for all. Link: https://lore.kernel.org/r/20250415095343.32125-7-quic_rlaggysh@quicinc.com Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Raviteja Laggyshetty --- arch/arm64/boot/dts/qcom/sa8775p.dtsi | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi index 9efecf2f88a90..accc8ac728f20 100644 --- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -5548,6 +5549,15 @@ }; }; + epss_l3_cl0: interconnect@18590000 { + compatible = "qcom,sa8775p-epss-l3", + "qcom,epss-l3"; + reg = <0x0 0x18590000 0x0 0x1000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GCC_GPLL0>; + clock-names = "xo", "alternate"; + #interconnect-cells = <1>; + }; + cpufreq_hw: cpufreq@18591000 { compatible = "qcom,sa8775p-cpufreq-epss", "qcom,cpufreq-epss"; @@ -5565,6 +5575,15 @@ #freq-domain-cells = <1>; }; + epss_l3_cl1: interconnect@18592000 { + compatible = "qcom,sa8775p-epss-l3", + "qcom,epss-l3"; + reg = <0x0 0x18592000 0x0 0x1000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GCC_GPLL0>; + clock-names = "xo", "alternate"; + #interconnect-cells = <1>; + }; + remoteproc_gpdsp0: remoteproc@20c00000 { compatible = "qcom,sa8775p-gpdsp0-pas"; reg = <0x0 0x20c00000 0x0 0x10000>; From 31667be7ef83c26a6aad5fa41ac63900c6796db5 Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Tue, 15 Apr 2025 09:53:43 +0000 Subject: [PATCH 059/113] FROMGIT: arm64: dts: qcom: sa8775p: Add CPU OPP tables to scale DDR/L3 Add OPP tables required to scale DDR and L3 per freq-domain on SA8775P platform. If a single OPP table is used for both CPU domains, then _allocate_opp_table() won't be invoked for CPU4 but instead CPU4 will be added as device under the CPU0 OPP table. Due to this, dev_pm_opp_of_find_icc_paths() won't be invoked for CPU4 device and hence CPU4 won't be able to independently scale it's interconnects. Both CPU0 and CPU4 devices will scale the same ICC path which can lead to one device overwriting the BW vote placed by other device. Hence CPU0 and CPU4 require separate OPP tables to allow independent scaling of DDR and L3 frequencies for each CPU domain, with the final DDR and L3 frequencies being an aggregate of both. Link: https://lore.kernel.org/r/20250415095343.32125-8-quic_rlaggysh@quicinc.com Co-developed-by: Shivnandan Kumar Signed-off-by: Shivnandan Kumar Signed-off-by: Raviteja Laggyshetty Signed-off-by: Jagadeesh Kona Reviewed-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/sa8775p.dtsi | 210 ++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi index accc8ac728f20..889652303de51 100644 --- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi @@ -52,6 +52,11 @@ next-level-cache = <&l2_0>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&epss_l3_cl0 MASTER_EPSS_L3_APPS + &epss_l3_cl0 SLAVE_EPSS_L3_SHARED>; l2_0: l2-cache { compatible = "cache"; cache-level = <2>; @@ -76,6 +81,11 @@ next-level-cache = <&l2_1>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&epss_l3_cl0 MASTER_EPSS_L3_APPS + &epss_l3_cl0 SLAVE_EPSS_L3_SHARED>; l2_1: l2-cache { compatible = "cache"; cache-level = <2>; @@ -95,6 +105,11 @@ next-level-cache = <&l2_2>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&epss_l3_cl0 MASTER_EPSS_L3_APPS + &epss_l3_cl0 SLAVE_EPSS_L3_SHARED>; l2_2: l2-cache { compatible = "cache"; cache-level = <2>; @@ -114,6 +129,11 @@ next-level-cache = <&l2_3>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&epss_l3_cl0 MASTER_EPSS_L3_APPS + &epss_l3_cl0 SLAVE_EPSS_L3_SHARED>; l2_3: l2-cache { compatible = "cache"; cache-level = <2>; @@ -133,6 +153,11 @@ next-level-cache = <&l2_4>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + operating-points-v2 = <&cpu4_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&epss_l3_cl1 MASTER_EPSS_L3_APPS + &epss_l3_cl1 SLAVE_EPSS_L3_SHARED>; l2_4: l2-cache { compatible = "cache"; cache-level = <2>; @@ -158,6 +183,11 @@ next-level-cache = <&l2_5>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + operating-points-v2 = <&cpu4_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&epss_l3_cl1 MASTER_EPSS_L3_APPS + &epss_l3_cl1 SLAVE_EPSS_L3_SHARED>; l2_5: l2-cache { compatible = "cache"; cache-level = <2>; @@ -177,6 +207,11 @@ next-level-cache = <&l2_6>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + operating-points-v2 = <&cpu4_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&epss_l3_cl1 MASTER_EPSS_L3_APPS + &epss_l3_cl1 SLAVE_EPSS_L3_SHARED>; l2_6: l2-cache { compatible = "cache"; cache-level = <2>; @@ -196,6 +231,11 @@ next-level-cache = <&l2_7>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + operating-points-v2 = <&cpu4_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&epss_l3_cl1 MASTER_EPSS_L3_APPS + &epss_l3_cl1 SLAVE_EPSS_L3_SHARED>; l2_7: l2-cache { compatible = "cache"; cache-level = <2>; @@ -285,6 +325,176 @@ }; }; + cpu0_opp_table: opp-table-cpu0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-1267200000 { + opp-hz = /bits/ 64 <1267200000>; + opp-peak-kBps = <(1555200 * 4) (921600 * 32)>; + }; + + opp-1363200000 { + opp-hz = /bits/ 64 <1363200000>; + opp-peak-kBps = <(1555200 * 4) (921600 * 32)>; + }; + + opp-1459200000 { + opp-hz = /bits/ 64 <1459200000>; + opp-peak-kBps = <(1555200 * 4) (921600 * 32)>; + }; + + opp-1536000000 { + opp-hz = /bits/ 64 <1536000000>; + opp-peak-kBps = <(1555200 * 4) (921600 * 32)>; + }; + + opp-1632000000 { + opp-hz = /bits/ 64 <1632000000>; + opp-peak-kBps = <(1708800 * 4) (1228800 * 32)>; + }; + + opp-1708800000 { + opp-hz = /bits/ 64 <1708800000>; + opp-peak-kBps = <(1708800 * 4) (1228800 * 32)>; + }; + + opp-1785600000 { + opp-hz = /bits/ 64 <1785600000>; + opp-peak-kBps = <(1708800 * 4) (1228800 * 32)>; + }; + + opp-1862400000 { + opp-hz = /bits/ 64 <1862400000>; + opp-peak-kBps = <(1708800 * 4) (1228800 * 32)>; + }; + + opp-1939200000 { + opp-hz = /bits/ 64 <1939200000>; + opp-peak-kBps = <(1708800 * 4) (1228800 * 32)>; + }; + + opp-2016000000 { + opp-hz = /bits/ 64 <2016000000>; + opp-peak-kBps = <(1708800 * 4) (1228800 * 32)>; + }; + + opp-2112000000 { + opp-hz = /bits/ 64 <2112000000>; + opp-peak-kBps = <(2092800 * 4) (1555200 * 32)>; + }; + + opp-2188800000 { + opp-hz = /bits/ 64 <2188800000>; + opp-peak-kBps = <(2092800 * 4) (1555200 * 32)>; + }; + + opp-2265600000 { + opp-hz = /bits/ 64 <2265600000>; + opp-peak-kBps = <(2092800 * 4) (1555200 * 32)>; + }; + + opp-2361600000 { + opp-hz = /bits/ 64 <2361600000>; + opp-peak-kBps = <(3196800 * 4) (1612800 * 32)>; + }; + + opp-2457600000 { + opp-hz = /bits/ 64 <2457600000>; + opp-peak-kBps = <(3196800 * 4) (1612800 * 32)>; + }; + + opp-2553600000 { + opp-hz = /bits/ 64 <2553600000>; + opp-peak-kBps = <(3196800 * 4) (1708800 * 32)>; + }; + }; + + cpu4_opp_table: opp-table-cpu4 { + compatible = "operating-points-v2"; + opp-shared; + + opp-1267200000 { + opp-hz = /bits/ 64 <1267200000>; + opp-peak-kBps = <(1555200 * 4) (921600 * 32)>; + }; + + opp-1363200000 { + opp-hz = /bits/ 64 <1363200000>; + opp-peak-kBps = <(1555200 * 4) (921600 * 32)>; + }; + + opp-1459200000 { + opp-hz = /bits/ 64 <1459200000>; + opp-peak-kBps = <(1555200 * 4) (921600 * 32)>; + }; + + opp-1536000000 { + opp-hz = /bits/ 64 <1536000000>; + opp-peak-kBps = <(1555200 * 4) (921600 * 32)>; + }; + + opp-1632000000 { + opp-hz = /bits/ 64 <1632000000>; + opp-peak-kBps = <(1708800 * 4) (1228800 * 32)>; + }; + + opp-1708800000 { + opp-hz = /bits/ 64 <1708800000>; + opp-peak-kBps = <(1708800 * 4) (1228800 * 32)>; + }; + + opp-1785600000 { + opp-hz = /bits/ 64 <1785600000>; + opp-peak-kBps = <(1708800 * 4) (1228800 * 32)>; + }; + + opp-1862400000 { + opp-hz = /bits/ 64 <1862400000>; + opp-peak-kBps = <(1708800 * 4) (1228800 * 32)>; + }; + + opp-1939200000 { + opp-hz = /bits/ 64 <1939200000>; + opp-peak-kBps = <(1708800 * 4) (1228800 * 32)>; + }; + + opp-2016000000 { + opp-hz = /bits/ 64 <2016000000>; + opp-peak-kBps = <(1708800 * 4) (1228800 * 32)>; + }; + + opp-2112000000 { + opp-hz = /bits/ 64 <2112000000>; + opp-peak-kBps = <(2092800 * 4) (1555200 * 32)>; + }; + + opp-2188800000 { + opp-hz = /bits/ 64 <2188800000>; + opp-peak-kBps = <(2092800 * 4) (1555200 * 32)>; + }; + + opp-2265600000 { + opp-hz = /bits/ 64 <2265600000>; + opp-peak-kBps = <(2092800 * 4) (1555200 * 32)>; + }; + + opp-2361600000 { + opp-hz = /bits/ 64 <2361600000>; + opp-peak-kBps = <(3196800 * 4) (1612800 * 32)>; + }; + + opp-2457600000 { + opp-hz = /bits/ 64 <2457600000>; + opp-peak-kBps = <(3196800 * 4) (1612800 * 32)>; + }; + + opp-2553600000 { + opp-hz = /bits/ 64 <2553600000>; + opp-peak-kBps = <(3196800 * 4) (1708800 * 32)>; + }; + }; + dummy-sink { compatible = "arm,coresight-dummy-sink"; From 7c42242f76761d3fd7ecbe99a1a8036908906093 Mon Sep 17 00:00:00 2001 From: Ryan Eatmon Date: Sat, 24 May 2025 21:25:37 +0530 Subject: [PATCH 060/113] FROMLIST: drivers: gpu: drm: msm: registers: improve reproducibility The files generated by gen_header.py capture the source path to the input files and the date. While that can be informative, it varies based on where and when the kernel was built as the full path is captured. Since all of the files that this tool is run on is under the drivers directory, this modifies the application to strip all of the path before drivers. Additionally it prints instead of the date. Link: https://lore.kernel.org/dri-devel/20250524-binrep-v2-1-09040177218e@oss.qualcomm.com/ Signed-off-by: Ryan Eatmon Signed-off-by: Bruce Ashfield Signed-off-by: Viswanath Kraleti --- drivers/gpu/drm/msm/registers/gen_header.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/registers/gen_header.py b/drivers/gpu/drm/msm/registers/gen_header.py index 3926485bb197b..a409404627c71 100644 --- a/drivers/gpu/drm/msm/registers/gen_header.py +++ b/drivers/gpu/drm/msm/registers/gen_header.py @@ -11,6 +11,7 @@ import argparse import time import datetime +import re class Error(Exception): def __init__(self, message): @@ -877,13 +878,14 @@ def dump_c(args, guard, func): """) maxlen = 0 for filepath in p.xml_files: - maxlen = max(maxlen, len(filepath)) + new_filepath = re.sub("^.+drivers","drivers",filepath) + maxlen = max(maxlen, len(new_filepath)) for filepath in p.xml_files: - pad = " " * (maxlen - len(filepath)) + pad = " " * (maxlen - len(new_filepath)) filesize = str(os.path.getsize(filepath)) filesize = " " * (7 - len(filesize)) + filesize filetime = time.ctime(os.path.getmtime(filepath)) - print("- " + filepath + pad + " (" + filesize + " bytes, from " + filetime + ")") + print("- " + new_filepath + pad + " (" + filesize + " bytes, from )") if p.copyright_year: current_year = str(datetime.date.today().year) print() From cdf3c88048e245dc1119a442ad267c6a5d3da4c9 Mon Sep 17 00:00:00 2001 From: Yijie Yang Date: Tue, 21 Jan 2025 15:54:55 +0800 Subject: [PATCH 061/113] FROMLIST: arm64: dts: qcom: qcs615: add ethernet node Add an ethernet controller node for QCS615 SoC to enable ethernet functionality. Link: https://lore.kernel.org/r/20250121-dts_qcs615-v3-3-fa4496950d8a@quicinc.com Signed-off-by: Yijie Yang Reviewed-by: Konrad Dybcio Reviewed-by: Konrad Dybcio --- arch/arm64/boot/dts/qcom/qcs615.dtsi | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs615.dtsi b/arch/arm64/boot/dts/qcom/qcs615.dtsi index bb8b6c3ebd03f..0890354363937 100644 --- a/arch/arm64/boot/dts/qcom/qcs615.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs615.dtsi @@ -438,6 +438,40 @@ #address-cells = <2>; #size-cells = <2>; + ethernet: ethernet@20000 { + compatible = "qcom,qcs615-ethqos", "qcom,qcs404-ethqos"; + reg = <0x0 0x00020000 0x0 0x10000>, + <0x0 0x00036000 0x0 0x100>; + reg-names = "stmmaceth", + "rgmii"; + + clocks = <&gcc GCC_EMAC_AXI_CLK>, + <&gcc GCC_EMAC_SLV_AHB_CLK>, + <&gcc GCC_EMAC_PTP_CLK>, + <&gcc GCC_EMAC_RGMII_CLK>; + clock-names = "stmmaceth", + "pclk", + "ptp_ref", + "rgmii"; + + interrupts = , + ; + interrupt-names = "macirq", + "eth_lpi"; + + power-domains = <&gcc EMAC_GDSC>; + resets = <&gcc GCC_EMAC_BCR>; + + iommus = <&apps_smmu 0x1c0 0x0>; + + snps,tso; + snps,pbl = <32>; + rx-fifo-depth = <16384>; + tx-fifo-depth = <20480>; + + status = "disabled"; + }; + gcc: clock-controller@100000 { compatible = "qcom,qcs615-gcc"; reg = <0 0x00100000 0 0x1f0000>; From 8e5db1876d3ac65b607263241e9ccd5e98b18db8 Mon Sep 17 00:00:00 2001 From: Yijie Yang Date: Tue, 21 Jan 2025 15:54:56 +0800 Subject: [PATCH 062/113] FROMLIST: arm64: dts: qcom: qcs615-ride: Enable ethernet node Enable the ethernet node, add the phy node and pinctrl for ethernet. This change is necessary to support ethernet functionality on this board. Link: https://lore.kernel.org/r/20250121-dts_qcs615-v3-4-fa4496950d8a@quicinc.com Signed-off-by: Yijie Yang Reviewed-by: Konrad Dybcio --- arch/arm64/boot/dts/qcom/qcs615-ride.dts | 104 +++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride.dts b/arch/arm64/boot/dts/qcom/qcs615-ride.dts index 2b5aa3c668676..2d201b5d09a79 100644 --- a/arch/arm64/boot/dts/qcom/qcs615-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs615-ride.dts @@ -211,6 +211,59 @@ }; }; +ðernet { + pinctrl-0 = <ðernet_defaults>; + pinctrl-names = "default"; + + phy-handle = <&rgmii_phy>; + phy-mode = "rgmii-id"; + + snps,mtl-rx-config = <&mtl_rx_setup>; + snps,mtl-tx-config = <&mtl_tx_setup>; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rgmii_phy: phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x7>; + + interrupts-extended = <&tlmm 121 IRQ_TYPE_EDGE_FALLING>; + device_type = "ethernet-phy"; + reset-gpios = <&tlmm 104 GPIO_ACTIVE_LOW>; + reset-assert-us = <11000>; + reset-deassert-us = <70000>; + }; + }; + + mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <1>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + }; + + mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <1>; + snps,tx-sched-wrr; + + queue0 { + snps,weight = <0x10>; + snps,dcb-algorithm; + snps,priority = <0x0>; + }; + }; +}; + &gcc { clocks = <&rpmhcc RPMH_CXO_CLK>, <&rpmhcc RPMH_CXO_CLK_A>, @@ -278,6 +331,57 @@ status = "okay"; }; +&tlmm { + ethernet_defaults: ethernet-defaults-state { + mdc-pins { + pins = "gpio113"; + function = "rgmii"; + bias-pull-up; + }; + + mdio-pins { + pins = "gpio114"; + function = "rgmii"; + bias-pull-up; + }; + + rgmii-rx-pins { + pins = "gpio81", "gpio82", "gpio83", "gpio102", "gpio103", "gpio112"; + function = "rgmii"; + bias-disable; + drive-strength = <2>; + }; + + rgmii-tx-pins { + pins = "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + + phy-intr-pins { + pins = "gpio121"; + function = "gpio"; + bias-disable; + drive-strength = <8>; + }; + + phy-reset-pins { + pins = "gpio104"; + function = "gpio"; + bias-pull-up; + drive-strength = <16>; + }; + + pps-pins { + pins = "gpio91"; + function = "rgmii"; + bias-disable; + drive-strength = <8>; + }; + }; +}; + &uart0 { status = "okay"; }; From 7d116167b701fa87ad54b557fd7daf00fd981e76 Mon Sep 17 00:00:00 2001 From: Yijie Yang Date: Wed, 25 Dec 2024 18:04:47 +0800 Subject: [PATCH 063/113] FROMLIST: arm64: dts: qcom: qcs615-ride: Enable RX programmable swap on qcs615-ride The timing of sampling at the RX side for qcs615-ride needs adjustment. It varies from board to board. Link: https://lore.kernel.org/r/20241225-support_10m100m-v1-3-4b52ef48b488@quicinc.com Signed-off-by: Yijie Yang --- arch/arm64/boot/dts/qcom/qcs615-ride.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride.dts b/arch/arm64/boot/dts/qcom/qcs615-ride.dts index 2d201b5d09a79..5cea3ce870962 100644 --- a/arch/arm64/boot/dts/qcom/qcs615-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs615-ride.dts @@ -217,6 +217,7 @@ phy-handle = <&rgmii_phy>; phy-mode = "rgmii-id"; + qcom,rx-prog-swap; snps,mtl-rx-config = <&mtl_rx_setup>; snps,mtl-tx-config = <&mtl_tx_setup>; From ac4c56fadf4594f7fa0d9da83250ca042158ae17 Mon Sep 17 00:00:00 2001 From: Lijuan Gao Date: Mon, 26 May 2025 13:21:47 +0800 Subject: [PATCH 064/113] FROMLIST: dt-bindings: remoteproc: qcom,sm8150-pas: Document QCS615 remoteproc Document the components used to boot the ADSP and CDSP on the Qualcomm QCS615 SoC. Use fallback to indicate the compatibility of the remoteproc on the QCS615 with that on the SM8150. Link: https://lore.kernel.org/r/20250526-add_qcs615_remoteproc_support-v4-1-06a7d8bed0b5@quicinc.com Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lijuan Gao --- .../bindings/remoteproc/qcom,sm8150-pas.yaml | 65 +++++++++++-------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml index 5dcc2a32c0800..a8cddf7e2fe1a 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml @@ -15,17 +15,26 @@ description: properties: compatible: - enum: - - qcom,sc8180x-adsp-pas - - qcom,sc8180x-cdsp-pas - - qcom,sc8180x-slpi-pas - - qcom,sm8150-adsp-pas - - qcom,sm8150-cdsp-pas - - qcom,sm8150-mpss-pas - - qcom,sm8150-slpi-pas - - qcom,sm8250-adsp-pas - - qcom,sm8250-cdsp-pas - - qcom,sm8250-slpi-pas + oneOf: + - items: + - enum: + - qcom,qcs615-adsp-pas + - const: qcom,sm8150-adsp-pas + - items: + - enum: + - qcom,qcs615-cdsp-pas + - const: qcom,sm8150-cdsp-pas + - enum: + - qcom,sc8180x-adsp-pas + - qcom,sc8180x-cdsp-pas + - qcom,sc8180x-slpi-pas + - qcom,sm8150-adsp-pas + - qcom,sm8150-cdsp-pas + - qcom,sm8150-mpss-pas + - qcom,sm8150-slpi-pas + - qcom,sm8250-adsp-pas + - qcom,sm8250-cdsp-pas + - qcom,sm8250-slpi-pas reg: maxItems: 1 @@ -62,16 +71,17 @@ allOf: - if: properties: compatible: - enum: - - qcom,sc8180x-adsp-pas - - qcom,sc8180x-cdsp-pas - - qcom,sc8180x-slpi-pas - - qcom,sm8150-adsp-pas - - qcom,sm8150-cdsp-pas - - qcom,sm8150-slpi-pas - - qcom,sm8250-adsp-pas - - qcom,sm8250-cdsp-pas - - qcom,sm8250-slpi-pas + contains: + enum: + - qcom,sc8180x-adsp-pas + - qcom,sc8180x-cdsp-pas + - qcom,sc8180x-slpi-pas + - qcom,sm8150-adsp-pas + - qcom,sm8150-cdsp-pas + - qcom,sm8150-slpi-pas + - qcom,sm8250-adsp-pas + - qcom,sm8250-cdsp-pas + - qcom,sm8250-slpi-pas then: properties: interrupts: @@ -88,12 +98,13 @@ allOf: - if: properties: compatible: - enum: - - qcom,sc8180x-adsp-pas - - qcom,sc8180x-cdsp-pas - - qcom,sm8150-adsp-pas - - qcom,sm8150-cdsp-pas - - qcom,sm8250-cdsp-pas + contains: + enum: + - qcom,sc8180x-adsp-pas + - qcom,sc8180x-cdsp-pas + - qcom,sm8150-adsp-pas + - qcom,sm8150-cdsp-pas + - qcom,sm8250-cdsp-pas then: properties: power-domains: From 427fa76d77aca44d40b3a5eeee0493975cc42722 Mon Sep 17 00:00:00 2001 From: Lijuan Gao Date: Mon, 26 May 2025 13:21:48 +0800 Subject: [PATCH 065/113] FROMGIT: dt-bindings: soc: qcom: add qcom,qcs615-imem compatible Document qcom,qcs615-imem compatible. It has a child node for debugging purposes. Link: https://lore.kernel.org/r/20250526-add_qcs615_remoteproc_support-v4-2-06a7d8bed0b5@quicinc.com Acked-by: Krzysztof Kozlowski Signed-off-by: Lijuan Gao --- Documentation/devicetree/bindings/sram/qcom,imem.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sram/qcom,imem.yaml b/Documentation/devicetree/bindings/sram/qcom,imem.yaml index 2711f90d9664b..dc3b5a69b9254 100644 --- a/Documentation/devicetree/bindings/sram/qcom,imem.yaml +++ b/Documentation/devicetree/bindings/sram/qcom,imem.yaml @@ -22,6 +22,7 @@ properties: - qcom,msm8974-imem - qcom,msm8976-imem - qcom,qcs404-imem + - qcom,qcs615-imem - qcom,qcs8300-imem - qcom,qdu1000-imem - qcom,sa8775p-imem From 1d0ec7318dcb4bc62490e561c71408250759716e Mon Sep 17 00:00:00 2001 From: Kyle Deng Date: Mon, 26 May 2025 13:21:49 +0800 Subject: [PATCH 066/113] FROMGIT: arm64: dts: qcom: qcs615: Add mproc node for SEMP2P The Shared Memory Point to Point (SMP2P) protocol facilitates communication of a single 32-bit value between two processors. Add these two nodes for remoteproc enablement on QCS615 SoC. Link: https://lore.kernel.org/r/20250526-add_qcs615_remoteproc_support-v4-3-06a7d8bed0b5@quicinc.com Signed-off-by: Kyle Deng Reviewed-by: Konrad Dybcio Signed-off-by: Lijuan Gao --- arch/arm64/boot/dts/qcom/qcs615.dtsi | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs615.dtsi b/arch/arm64/boot/dts/qcom/qcs615.dtsi index 0890354363937..40efdc21e0140 100644 --- a/arch/arm64/boot/dts/qcom/qcs615.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs615.dtsi @@ -332,6 +332,50 @@ qcom,bcm-voters = <&apps_bcm_voter>; }; + smp2p-adsp { + compatible = "qcom,smp2p"; + qcom,smem = <443>, <429>; + interrupts = ; + /* On this platform, bit 26 (normally SLPI) is repurposed for ADSP */ + mboxes = <&apss_shared 26>; + + qcom,local-pid = <0>; + qcom,remote-pid = <2>; + + adsp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + adsp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-cdsp { + compatible = "qcom,smp2p"; + qcom,smem = <94>, <432>; + interrupts = ; + mboxes = <&apss_shared 6>; + + qcom,local-pid = <0>; + qcom,remote-pid = <5>; + + cdsp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + cdsp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + + }; + qup_opp_table: opp-table-qup { compatible = "operating-points-v2"; opp-shared; From f0e0250719b8e8049f39ef1ede64670baf678d15 Mon Sep 17 00:00:00 2001 From: Lijuan Gao Date: Mon, 26 May 2025 13:21:50 +0800 Subject: [PATCH 067/113] FROMGIT: arm64: dts: qcom: qcs615: Add IMEM and PIL info region Add a simple-mfd representing IMEM on QCS615 and define the PIL relocation info region as its child. The PIL region in IMEM is used to communicate load addresses of remoteproc to post mortem debug tools, so that these tools can collect ramdumps. Link: https://lore.kernel.org/r/20250526-add_qcs615_remoteproc_support-v4-4-06a7d8bed0b5@quicinc.com Reviewed-by: Konrad Dybcio Signed-off-by: Lijuan Gao --- arch/arm64/boot/dts/qcom/qcs615.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs615.dtsi b/arch/arm64/boot/dts/qcom/qcs615.dtsi index 40efdc21e0140..5a7b72ac09097 100644 --- a/arch/arm64/boot/dts/qcom/qcs615.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs615.dtsi @@ -3323,6 +3323,20 @@ reg = <0x0 0x0c3f0000 0x0 0x400>; }; + sram@14680000 { + compatible = "qcom,qcs615-imem", "syscon", "simple-mfd"; + reg = <0x0 0x14680000 0x0 0x2c000>; + ranges = <0 0 0x14680000 0x2c000>; + + #address-cells = <1>; + #size-cells = <1>; + + pil-reloc@2a94c { + compatible = "qcom,pil-reloc-info"; + reg = <0x2a94c 0xc8>; + }; + }; + apps_smmu: iommu@15000000 { compatible = "qcom,qcs615-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0x0 0x15000000 0x0 0x80000>; From 5976433ef16ebc8e33cedfafd5895637a1e21a76 Mon Sep 17 00:00:00 2001 From: Lijuan Gao Date: Mon, 26 May 2025 13:21:51 +0800 Subject: [PATCH 068/113] FROMGIT: arm64: dts: qcom: qcs615: add ADSP and CDSP nodes Add nodes for remoteprocs: ADSP and CDSP for QCS615 SoC to enable proper remoteproc functionality. Link: https://lore.kernel.org/r/20250526-add_qcs615_remoteproc_support-v4-5-06a7d8bed0b5@quicinc.com Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Lijuan Gao --- arch/arm64/boot/dts/qcom/qcs615.dtsi | 86 ++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs615.dtsi b/arch/arm64/boot/dts/qcom/qcs615.dtsi index 5a7b72ac09097..f5ec2ec62b727 100644 --- a/arch/arm64/boot/dts/qcom/qcs615.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs615.dtsi @@ -473,6 +473,16 @@ no-map; hwlocks = <&tcsr_mutex 3>; }; + + rproc_cdsp_mem: rproc-cdsp@93b00000 { + reg = <0x0 0x93b00000 0x0 0x1e00000>; + no-map; + }; + + rproc_adsp_mem: rproc-adsp@95900000 { + reg = <0x0 0x95900000 0x0 0x1e00000>; + no-map; + }; }; soc: soc@0 { @@ -3151,6 +3161,44 @@ clock-names = "apb_pclk"; }; + remoteproc_cdsp: remoteproc@8300000 { + compatible = "qcom,qcs615-cdsp-pas", "qcom,sm8150-cdsp-pas"; + reg = <0x0 0x08300000 0x0 0x4040>; + + interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd RPMHPD_CX>; + power-domain-names = "cx"; + + memory-region = <&rproc_cdsp_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&cdsp_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts = ; + mboxes = <&apss_shared 4>; + label = "cdsp"; + qcom,remote-pid = <5>; + }; + }; + pmu@90b6300 { compatible = "qcom,qcs615-cpu-bwmon", "qcom,sdm845-bwmon"; reg = <0x0 0x090b6300 0x0 0x600>; @@ -3784,6 +3832,44 @@ maximum-speed = "high-speed"; }; }; + + remoteproc_adsp: remoteproc@62400000 { + compatible = "qcom,qcs615-adsp-pas", "qcom,sm8150-adsp-pas"; + reg = <0x0 0x62400000 0x0 0x4040>; + + interrupts-extended = <&intc GIC_SPI 162 IRQ_TYPE_EDGE_RISING>, + <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&adsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&adsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&adsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd RPMHPD_CX>; + power-domain-names = "cx"; + + memory-region = <&rproc_adsp_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&adsp_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink_edge: glink-edge { + interrupts = ; + mboxes = <&apss_shared 24>; + label = "lpass"; + qcom,remote-pid = <2>; + }; + }; }; arch_timer: timer { From 1db28a992b53a11c4e1d31c708833cfb89623463 Mon Sep 17 00:00:00 2001 From: Lijuan Gao Date: Mon, 26 May 2025 13:21:52 +0800 Subject: [PATCH 069/113] FROMGIT: arm64: dts: qcom: qcs615-ride: enable remoteprocs Enable all remoteproc nodes on the qcs615-ride board and point to the appropriate firmware files to allow proper functioning of the remote processors. Link: https://lore.kernel.org/r/20250526-add_qcs615_remoteproc_support-v4-6-06a7d8bed0b5@quicinc.com Reviewed-by: Konrad Dybcio Signed-off-by: Lijuan Gao --- arch/arm64/boot/dts/qcom/qcs615-ride.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride.dts b/arch/arm64/boot/dts/qcom/qcs615-ride.dts index 5cea3ce870962..c613a028b8585 100644 --- a/arch/arm64/boot/dts/qcom/qcs615-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs615-ride.dts @@ -294,6 +294,18 @@ status = "okay"; }; +&remoteproc_adsp { + firmware-name = "qcom/qcs615/adsp.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/qcs615/cdsp.mbn"; + + status = "okay"; +}; + &rpmhcc { clocks = <&xo_board_clk>; }; From 479236a0a9deabefd5fe7c6e2414174439ba902f Mon Sep 17 00:00:00 2001 From: Krishna chaitanya chundru Date: Wed, 2 Jul 2025 18:35:48 +0800 Subject: [PATCH 070/113] FORMLIST: arm64: dts: qcom: qcs615: enable pcie Add configurations in devicetree for PCIe0, including registers, clocks, interrupts and phy setting sequence. Add PCIe lane equalization preset properties for 8 GT/s. Signed-off-by: Krishna chaitanya chundru Signed-off-by: Ziyue Zhang Reviewed-by: Konrad Dybcio Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/all/20250702103549.712039-3-ziyue.zhang@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/qcs615.dtsi | 138 +++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs615.dtsi b/arch/arm64/boot/dts/qcom/qcs615.dtsi index f5ec2ec62b727..dbc839363775c 100644 --- a/arch/arm64/boot/dts/qcom/qcs615.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs615.dtsi @@ -1100,6 +1100,144 @@ qcom,bcm-voters = <&apps_bcm_voter>; }; + pcie: pcie@1c08000 { + device_type = "pci"; + compatible = "qcom,pcie-qcs615", "qcom,pcie-sm8150"; + reg = <0x0 0x01c08000 0x0 0x3000>, + <0x0 0x40000000 0x0 0xf1d>, + <0x0 0x40000f20 0x0 0xa8>, + <0x0 0x40001000 0x0 0x1000>, + <0x0 0x40100000 0x0 0x100000>, + <0x0 0x01c0b000 0x0 0x1000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x01000000 0x0 0x00000000 0x0 0x40200000 0x0 0x100000>, + <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>; + bus-range = <0x00 0xff>; + + dma-coherent; + + linux,pci-domain = <0>; + num-lanes = <1>; + + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-names = "msi0", + "msi1", + "msi2", + "msi3", + "msi4", + "msi5", + "msi6", + "msi7", + "global"; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>; + + clocks = <&gcc GCC_PCIE_0_PIPE_CLK>, + <&gcc GCC_PCIE_0_AUX_CLK>, + <&gcc GCC_PCIE_0_CFG_AHB_CLK>, + <&gcc GCC_PCIE_0_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_0_SLV_AXI_CLK>, + <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>; + clock-names = "pipe", + "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a"; + assigned-clocks = <&gcc GCC_PCIE_0_AUX_CLK>; + assigned-clock-rates = <19200000>; + + interconnects = <&aggre1_noc MASTER_PCIE QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_PCIE_0 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "pcie-mem", "cpu-pcie"; + + iommu-map = <0x0 &apps_smmu 0x400 0x1>, + <0x100 &apps_smmu 0x401 0x1>; + + resets = <&gcc GCC_PCIE_0_BCR>; + reset-names = "pci"; + + power-domains = <&gcc PCIE_0_GDSC>; + + phys = <&pcie_phy>; + phy-names = "pciephy"; + + max-link-speed = <2>; + + operating-points-v2 = <&pcie_opp_table>; + + status = "disabled"; + + pcie_opp_table: opp-table { + compatible = "operating-points-v2"; + + /* GEN 1 x1 */ + opp-2500000 { + opp-hz = /bits/ 64 <2500000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <250000 1>; + }; + + /* GEN 2 x1 */ + opp-5000000 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <500000 1>; + }; + }; + }; + + pcie_phy: phy@1c0e000 { + compatible = "qcom,qcs615-qmp-gen3x1-pcie-phy"; + reg = <0x0 0x01c0e000 0x0 0x1000>; + + clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>, + <&gcc GCC_PCIE_0_CFG_AHB_CLK>, + <&gcc GCC_PCIE_0_CLKREF_CLK>, + <&gcc GCC_PCIE0_PHY_REFGEN_CLK>, + <&gcc GCC_PCIE_0_PIPE_CLK>; + clock-names = "aux", + "cfg_ahb", + "ref", + "refgen", + "pipe"; + + resets = <&gcc GCC_PCIE_0_PHY_BCR>; + reset-names = "phy"; + + assigned-clocks = <&gcc GCC_PCIE0_PHY_REFGEN_CLK>; + assigned-clock-rates = <100000000>; + + #clock-cells = <0>; + clock-output-names = "pcie_0_pipe_clk"; + + #phy-cells = <0>; + + status = "disabled"; + }; + ufs_mem_hc: ufshc@1d84000 { compatible = "qcom,qcs615-ufshc", "qcom,ufshc", "jedec,ufs-2.0"; reg = <0x0 0x01d84000 0x0 0x3000>, From 7593857604f2c674328e1103ec354fee642295b0 Mon Sep 17 00:00:00 2001 From: Krishna chaitanya chundru Date: Wed, 2 Jul 2025 18:35:49 +0800 Subject: [PATCH 071/113] FORMLIST: arm64: dts: qcom: qcs615-ride: Enable PCIe interface Add platform configurations in devicetree for PCIe, board related gpios, PMIC regulators, etc. Reviewed-by: Konrad Dybcio Signed-off-by: Krishna chaitanya chundru Signed-off-by: Ziyue Zhang Link: https://lore.kernel.org/all/20250702103549.712039-4-ziyue.zhang@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/qcs615-ride.dts | 42 ++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride.dts b/arch/arm64/boot/dts/qcom/qcs615-ride.dts index c613a028b8585..379c8dfcac20b 100644 --- a/arch/arm64/boot/dts/qcom/qcs615-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs615-ride.dts @@ -271,6 +271,23 @@ <&sleep_clk>; }; +&pcie { + perst-gpios = <&tlmm 101 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 100 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&pcie_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie_phy { + vdda-phy-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l12a>; + + status = "okay"; +}; + &pm8150_gpios { usb2_en: usb2-en-state { pins = "gpio10"; @@ -310,6 +327,31 @@ clocks = <&xo_board_clk>; }; +&tlmm { + pcie_default_state: pcie-default-state { + clkreq-pins { + pins = "gpio90"; + function = "pcie_clk_req"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio101"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + wake-pins { + pins = "gpio100"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; +}; + &sdhc_1 { pinctrl-0 = <&sdc1_state_on>; pinctrl-1 = <&sdc1_state_off>; From 6d00161ad18ef52f1e8a794471581fa932c088d1 Mon Sep 17 00:00:00 2001 From: Ziyue Zhang Date: Fri, 14 Mar 2025 18:13:02 +0800 Subject: [PATCH 072/113] FROMLIST: PCI: qcom: Add QCS615 PCIe support Add the compatible and the driver data for QCS615 PCIe controller. There is only one controller instance found on this platform, out of which is Gen3 with speeds of up to 8.0GT/s. The version of the controller is 1.38.0 for all instances, but they are compatible with 1.9.0 config. Link: https://lore.kernel.org/all/20250507031559.4085159-6-quic_ziyuzhan@quicinc.com/ Signed-off-by: Krishna chaitanya chundru Signed-off-by: Ziyue Zhang --- drivers/pci/controller/dwc/pcie-qcom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 76d90820855be..c80f0ab2ea77c 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -1939,6 +1939,7 @@ static const struct of_device_id qcom_pcie_match[] = { { .compatible = "qcom,pcie-sm8450-pcie1", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-sm8550", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-x1e80100", .data = &cfg_sc8280xp }, + { .compatible = "qcom,qcs615-pcie", .data = &cfg_1_9_0 }, { } }; From ac2552ead6681898e7709596b63ab3dc131a717d Mon Sep 17 00:00:00 2001 From: Ziyue Zhang Date: Mon, 26 May 2025 17:27:00 +0800 Subject: [PATCH 073/113] BACKPORT: dt-bindings: PCI: qcom,pcie-sm8150: document qcs615 Add compatible for qcs615 platform, with sm8150 as the fallback. Signed-off-by: Ziyue Zhang Link: https://lore.kernel.org/all/20250527072036.3599076-3-quic_ziyuzhan@quicinc.com/ --- .../devicetree/bindings/pci/qcom,pcie-sm8150.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8150.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8150.yaml index 9d569644fda90..67c6b38d19ba9 100644 --- a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8150.yaml +++ b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8150.yaml @@ -16,7 +16,12 @@ description: properties: compatible: - const: qcom,pcie-sm8150 + oneOf: + - const: qcom,pcie-sm8150 + - items: + - enum: + - qcom,pcie-qcs615 + - const: qcom,pcie-sm8150 reg: minItems: 5 From 5f69f87640a5ae09d2a607174e852e58cd8e25d0 Mon Sep 17 00:00:00 2001 From: Ziyue Zhang Date: Thu, 26 Jun 2025 17:28:47 +0800 Subject: [PATCH 074/113] FORMLIST: dt-bindings: PCI: qcom,pcie-sa8775p: document link_down reset Each PCIe controller on sa8775p includes 'link_down'reset on hardware, document it. Signed-off-by: Ziyue Zhang Link: https://lore.kernel.org/all/20250625090048.624399-3-quic_ziyuzhan@quicinc.com/ --- .../devicetree/bindings/pci/qcom,pcie-sa8775p.yaml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml index efde49d1bef85..976e74ede930a 100644 --- a/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml +++ b/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml @@ -59,11 +59,14 @@ properties: - const: msi7 resets: - maxItems: 1 + items: + - description: PCIe controller reset + - description: PCIe link down reset reset-names: items: - - const: pci + - const: pci # PCIe core reset + - const: link_down # PCIe link down reset required: - interconnects @@ -157,8 +160,10 @@ examples: power-domains = <&gcc PCIE_0_GDSC>; - resets = <&gcc GCC_PCIE_0_BCR>; - reset-names = "pci"; + resets = <&gcc GCC_PCIE_0_BCR>, + <&gcc GCC_PCIE_0_LINK_DOWN_BCR>; + reset-names = "pci", + "link_down"; perst-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; wake-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; From efaefa5626fb7b437ef595badae9ef46e8f076b5 Mon Sep 17 00:00:00 2001 From: Ziyue Zhang Date: Tue, 27 May 2025 14:35:11 +0800 Subject: [PATCH 075/113] BACKPORT: dt-bindings: PCI: qcom,pcie-sa8775p: document qcs8300 Add compatible for qcs8300 platform, with sa8775p as the fallback. Signed-off-by: Ziyue Zhang Link: https://lore.kernel.org/all/20250529035635.4162149-3-quic_ziyuzhan@quicinc.com/ --- .../devicetree/bindings/pci/qcom,pcie-sa8775p.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml index 976e74ede930a..90df0e56c0683 100644 --- a/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml +++ b/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml @@ -16,7 +16,12 @@ description: properties: compatible: - const: qcom,pcie-sa8775p + oneOf: + - const: qcom,pcie-sa8775p + - items: + - enum: + - qcom,pcie-qcs8300 + - const: qcom,pcie-sa8775p reg: minItems: 6 From 6de06e000f183745dc2f3c91b8ea0df8cbf077fc Mon Sep 17 00:00:00 2001 From: Ziyue Zhang Date: Thu, 29 May 2025 11:54:13 +0800 Subject: [PATCH 076/113] FORMLIST: dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Update sa8775p pcie phy bindings The gcc_aux_clk is required by the PCIe controller but not by the PCIe PHY. In PCIe PHY, the source of aux_clk used in low-power mode should be gcc_phy_aux_clk. Hence, remove gcc_aux_clk and replace it with gcc_phy_aux_clk. Removed the phy_aux clock from the PCIe PHY binding as it is no longer used by any instance. Signed-off-by: Ziyue Zhang Link: https://lore.kernel.org/all/20250625090048.624399-2-quic_ziyuzhan@quicinc.com/ --- .../bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml index 2c6c9296e4c0d..57b16444eb0e2 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml @@ -54,7 +54,7 @@ properties: clocks: minItems: 5 - maxItems: 7 + maxItems: 6 clock-names: minItems: 5 @@ -65,7 +65,6 @@ properties: - enum: [rchng, refgen] - const: pipe - const: pipediv2 - - const: phy_aux power-domains: maxItems: 1 @@ -176,6 +175,8 @@ allOf: contains: enum: - qcom,qcs615-qmp-gen3x1-pcie-phy + - qcom,sa8775p-qmp-gen4x2-pcie-phy + - qcom,sa8775p-qmp-gen4x4-pcie-phy - qcom,sc8280xp-qmp-gen3x1-pcie-phy - qcom,sc8280xp-qmp-gen3x2-pcie-phy - qcom,sc8280xp-qmp-gen3x4-pcie-phy @@ -197,8 +198,6 @@ allOf: contains: enum: - qcom,qcs8300-qmp-gen4x2-pcie-phy - - qcom,sa8775p-qmp-gen4x2-pcie-phy - - qcom,sa8775p-qmp-gen4x4-pcie-phy then: properties: clocks: From 5159ecf66111209bb6561b6897edb53ada242ca1 Mon Sep 17 00:00:00 2001 From: Ziyue Zhang Date: Tue, 27 May 2025 14:21:30 +0800 Subject: [PATCH 077/113] FORMLIST: dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Update pcie phy bindings for qcs8300 The gcc_aux_clk is not required by the PCIe PHY on qcs8300 and is not specified in the device tree node. Hence, move the qcs8300 phy compatibility entry into the list of PHYs that require six clocks. As no compatible need the entry which require seven clocks, delete it. Signed-off-by: Ziyue Zhang Acked-by: Rob Herring (Arm) Link: https://lore.kernel.org/all/20250625092539.762075-2-quic_ziyuzhan@quicinc.com/ --- .../bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml index 57b16444eb0e2..10c03831f9e75 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml @@ -175,6 +175,7 @@ allOf: contains: enum: - qcom,qcs615-qmp-gen3x1-pcie-phy + - qcom,qcs8300-qmp-gen4x2-pcie-phy - qcom,sa8775p-qmp-gen4x2-pcie-phy - qcom,sa8775p-qmp-gen4x4-pcie-phy - qcom,sc8280xp-qmp-gen3x1-pcie-phy @@ -192,19 +193,6 @@ allOf: clock-names: minItems: 6 - - if: - properties: - compatible: - contains: - enum: - - qcom,qcs8300-qmp-gen4x2-pcie-phy - then: - properties: - clocks: - minItems: 7 - clock-names: - minItems: 7 - - if: properties: compatible: From eb43f6ad1104f4714b1747d7f68708fae0eb05ce Mon Sep 17 00:00:00 2001 From: Renjiang Han Date: Thu, 12 Jun 2025 07:53:51 +0530 Subject: [PATCH 078/113] FROMLIST: media: venus: pm_helpers: use opp-table for the frequency Some platforms (such as qcs615 and sc7180) use the same core but have different frequency tables. Using the opp-table allows us to separate the core description from the frequency data and supports the use of fallback compatibles. Link: https://lore.kernel.org/linux-arm-msm/20250612-use_freq_with_opp_table-v2-1-42b03648fba8@quicinc.com/ Reviewed-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue Signed-off-by: Renjiang Han Signed-off-by: Wangao Wang --- .../media/platform/qcom/venus/pm_helpers.c | 58 +++++++++++-------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c index 409aa9bd0b5d0..8dd5a9b0d060c 100644 --- a/drivers/media/platform/qcom/venus/pm_helpers.c +++ b/drivers/media/platform/qcom/venus/pm_helpers.c @@ -41,16 +41,14 @@ static int core_clks_get(struct venus_core *core) static int core_clks_enable(struct venus_core *core) { const struct venus_resources *res = core->res; - const struct freq_tbl *freq_tbl = core->res->freq_tbl; - unsigned int freq_tbl_size = core->res->freq_tbl_size; - unsigned long freq; + struct device *dev = core->dev; + unsigned long freq = 0; + struct dev_pm_opp *opp; unsigned int i; int ret; - if (!freq_tbl) - return -EINVAL; - - freq = freq_tbl[freq_tbl_size - 1].freq; + opp = dev_pm_opp_find_freq_ceil(dev, &freq); + dev_pm_opp_put(opp); for (i = 0; i < res->clks_num; i++) { if (IS_V6(core)) { @@ -636,7 +634,9 @@ static int decide_core(struct venus_inst *inst) u32 min_coreid, min_load, cur_inst_load; u32 min_lp_coreid, min_lp_load, cur_inst_lp_load; struct hfi_videocores_usage_type cu; - unsigned long max_freq; + unsigned long max_freq = ULONG_MAX; + struct device *dev = core->dev; + struct dev_pm_opp *opp; int ret = 0; if (legacy_binding) { @@ -659,7 +659,8 @@ static int decide_core(struct venus_inst *inst) cur_inst_lp_load *= inst->clk_data.low_power_freq; /*TODO : divide this inst->load by work_route */ - max_freq = core->res->freq_tbl[0].freq; + opp = dev_pm_opp_find_freq_floor(dev, &max_freq); + dev_pm_opp_put(opp); min_loaded_core(inst, &min_coreid, &min_load, false); min_loaded_core(inst, &min_lp_coreid, &min_lp_load, true); @@ -949,7 +950,10 @@ static int core_resets_get(struct venus_core *core) static int core_get_v4(struct venus_core *core) { struct device *dev = core->dev; + const struct freq_tbl *freq_tbl = core->res->freq_tbl; + unsigned int num_rows = core->res->freq_tbl_size; const struct venus_resources *res = core->res; + unsigned int i; int ret; ret = core_clks_get(core); @@ -986,9 +990,17 @@ static int core_get_v4(struct venus_core *core) if (core->res->opp_pmdomain) { ret = devm_pm_opp_of_add_table(dev); - if (ret && ret != -ENODEV) { - dev_err(dev, "invalid OPP table in device tree\n"); - return ret; + if (ret) { + if (ret == -ENODEV) { + for (i = 0; i < num_rows; i++) { + ret = dev_pm_opp_add(dev, freq_tbl[i].freq, 0); + if (ret) + return ret; + } + } else { + dev_err(dev, "invalid OPP table in device tree\n"); + return ret; + } } } @@ -1078,11 +1090,11 @@ static unsigned long calculate_inst_freq(struct venus_inst *inst, static int load_scale_v4(struct venus_inst *inst) { struct venus_core *core = inst->core; - const struct freq_tbl *table = core->res->freq_tbl; - unsigned int num_rows = core->res->freq_tbl_size; struct device *dev = core->dev; unsigned long freq = 0, freq_core1 = 0, freq_core2 = 0; + unsigned long max_freq = ULONG_MAX; unsigned long filled_len = 0; + struct dev_pm_opp *opp; int i, ret = 0; for (i = 0; i < inst->num_input_bufs; i++) @@ -1108,20 +1120,18 @@ static int load_scale_v4(struct venus_inst *inst) freq = max(freq_core1, freq_core2); - if (freq > table[0].freq) { - dev_dbg(dev, VDBGL "requested clock rate: %lu scaling clock rate : %lu\n", - freq, table[0].freq); + opp = dev_pm_opp_find_freq_floor(dev, &max_freq); + dev_pm_opp_put(opp); - freq = table[0].freq; + if (freq > max_freq) { + dev_dbg(dev, VDBGL "requested clock rate: %lu scaling clock rate : %lu\n", + freq, max_freq); + freq = max_freq; goto set_freq; } - for (i = num_rows - 1 ; i >= 0; i--) { - if (freq <= table[i].freq) { - freq = table[i].freq; - break; - } - } + opp = dev_pm_opp_find_freq_ceil(dev, &freq); + dev_pm_opp_put(opp); set_freq: From 52c8aeeb27e92b1c3ee42ed475ab8756b86fa33a Mon Sep 17 00:00:00 2001 From: Mao Jinlong Date: Tue, 26 Sep 2023 07:54:33 -0700 Subject: [PATCH 079/113] FROMLIST: stm: class: Add MIPI OST protocol support Add MIPI OST(Open System Trace) protocol support for stm to format the traces. OST over STP packet consists of Header/Payload/End. In header, there will be STARTSIMPLE/VERSION/ENTITY/PROTOCOL. STARTSIMPLE is used to signal the beginning of a simplified OST base protocol packet.The Entity ID field is a one byte unsigned number that identifies the source. FLAG packet is used for END token. Link: https://lore.kernel.org/linux-arm-msm/20230419141328.37472-1-quic_jinlmao@quicinc.com/ Signed-off-by: Tingwei Zhang Signed-off-by: Yuanfang Zhang Signed-off-by: Mao Jinlong --- drivers/hwtracing/stm/Kconfig | 14 ++++++ drivers/hwtracing/stm/Makefile | 2 + drivers/hwtracing/stm/p_ost.c | 92 ++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 drivers/hwtracing/stm/p_ost.c diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig index eda6b11d40a1f..a26318f9d847e 100644 --- a/drivers/hwtracing/stm/Kconfig +++ b/drivers/hwtracing/stm/Kconfig @@ -48,6 +48,20 @@ config STM_DUMMY If you don't know what this is, say N. +config STM_PROTO_OST + tristate "MIPI OST STM framing protocol driver" + default CONFIG_STM + help + This is an implementation of MIPI OST protocol to be used + over the STP transport. In addition to the data payload, it + also carries additional metadata for entity, better + means of trace source identification, etc. + + The receiving side must be able to decode this protocol in + addition to the MIPI STP, in order to extract the data. + + If you don't know what this is, say N. + config STM_SOURCE_CONSOLE tristate "Kernel console over STM devices" help diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile index 1692fcd292779..715fc721891e2 100644 --- a/drivers/hwtracing/stm/Makefile +++ b/drivers/hwtracing/stm/Makefile @@ -5,9 +5,11 @@ stm_core-y := core.o policy.o obj-$(CONFIG_STM_PROTO_BASIC) += stm_p_basic.o obj-$(CONFIG_STM_PROTO_SYS_T) += stm_p_sys-t.o +obj-$(CONFIG_STM_PROTO_OST) += stm_p_ost.o stm_p_basic-y := p_basic.o stm_p_sys-t-y := p_sys-t.o +stm_p_ost-y := p_ost.o obj-$(CONFIG_STM_DUMMY) += dummy_stm.o diff --git a/drivers/hwtracing/stm/p_ost.c b/drivers/hwtracing/stm/p_ost.c new file mode 100644 index 0000000000000..b80b9f7701f20 --- /dev/null +++ b/drivers/hwtracing/stm/p_ost.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + * + * MIPI OST framing protocol for STM devices. + */ + +#include +#include +#include +#include +#include +#include +#include "stm.h" + +#define OST_TOKEN_STARTSIMPLE (0x10) +#define OST_VERSION_MIPI1 (0x10 << 8) +#define OST_ENTITY_FTRACE (0x01 << 16) +#define OST_CONTROL_PROTOCOL (0x0 << 24) + +#define DATA_HEADER (OST_TOKEN_STARTSIMPLE | OST_VERSION_MIPI1 | \ + OST_ENTITY_FTRACE | OST_CONTROL_PROTOCOL) + +#define STM_MAKE_VERSION(ma, mi) ((ma << 8) | mi) +#define STM_HEADER_MAGIC (0x5953) + +static ssize_t notrace ost_write(struct stm_data *data, + struct stm_output *output, unsigned int chan, + const char *buf, size_t count, + struct stm_source_data *source) +{ + unsigned int c = output->channel + chan; + unsigned int m = output->master; + const unsigned char nil = 0; + u32 header = DATA_HEADER; + u8 trc_hdr[24]; + ssize_t sz; + + /* + * STP framing rules for OST frames: + * * the first packet of the OST frame is marked; + * * the last packet is a FLAG. + */ + /* Message layout: HEADER / DATA / TAIL */ + /* HEADER */ + + sz = data->packet(data, m, c, STP_PACKET_DATA, STP_PACKET_MARKED, + 4, (u8 *)&header); + if (sz <= 0) + return sz; + *(uint16_t *)(trc_hdr) = STM_MAKE_VERSION(0, 3); + *(uint16_t *)(trc_hdr + 2) = STM_HEADER_MAGIC; + *(uint32_t *)(trc_hdr + 4) = raw_smp_processor_id(); + *(uint64_t *)(trc_hdr + 8) = sched_clock(); + *(uint64_t *)(trc_hdr + 16) = task_tgid_nr(get_current()); + sz = stm_data_write(data, m, c, false, trc_hdr, sizeof(trc_hdr)); + if (sz <= 0) + return sz; + + /* DATA */ + sz = stm_data_write(data, m, c, false, buf, count); + + /* TAIL */ + if (sz > 0) + data->packet(data, m, c, STP_PACKET_FLAG, + STP_PACKET_TIMESTAMPED, 0, &nil); + + return sz; +} + +static const struct stm_protocol_driver ost_pdrv = { + .owner = THIS_MODULE, + .name = "p_ost", + .write = ost_write, +}; + +static int ost_stm_init(void) +{ + return stm_register_protocol(&ost_pdrv); +} + +static void ost_stm_exit(void) +{ + stm_unregister_protocol(&ost_pdrv); +} + +module_init(ost_stm_init); +module_exit(ost_stm_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MIPI Open System Trace STM framing protocol driver"); From fffc6a13be8c1bba34598c1ab8d15157fd4a00fb Mon Sep 17 00:00:00 2001 From: Mao Jinlong Date: Wed, 26 Feb 2025 04:19:25 -0800 Subject: [PATCH 080/113] FROMLIST: dt-bindings: arm: Add label in the coresight components Current name of coresight component's folder consists of prefix of the device and the id in the device list. When run 'ls' command, we can get the register address of the device. Take CTI for example, if we want to set the config for modem CTI, but we can't know which CTI is modem CTI from all current information. cti_sys0 -> ../../../devices/platform/soc@0/138f0000.cti/cti_sys0 cti_sys1 -> ../../../devices/platform/soc@0/13900000.cti/cti_sys1 Add label to show hardware context information of each coresight device. There will be a sysfs node label in each device folder. cat /sys/bus/coresight/devices/cti_sys0/label Link: https://lore.kernel.org/all/20250703130453.4265-2-quic_jinlmao@quicinc.com/ Signed-off-by: Mao Jinlong Reviewed-by: Krzysztof Kozlowski Reviewed-by: Mike Leach --- .../devicetree/bindings/arm/arm,coresight-cti.yaml | 6 ++++++ .../devicetree/bindings/arm/arm,coresight-dummy-sink.yaml | 6 ++++++ .../devicetree/bindings/arm/arm,coresight-dummy-source.yaml | 6 ++++++ .../bindings/arm/arm,coresight-dynamic-funnel.yaml | 6 ++++++ .../bindings/arm/arm,coresight-dynamic-replicator.yaml | 6 ++++++ .../bindings/arm/arm,coresight-static-funnel.yaml | 6 ++++++ .../bindings/arm/arm,coresight-static-replicator.yaml | 6 ++++++ .../devicetree/bindings/arm/arm,coresight-tmc.yaml | 6 ++++++ .../devicetree/bindings/arm/qcom,coresight-tpda.yaml | 6 ++++++ .../devicetree/bindings/arm/qcom,coresight-tpdm.yaml | 6 ++++++ 10 files changed, 60 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml index 2d5545a2b49c6..5ca6d3d313a3d 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml @@ -98,6 +98,12 @@ properties: power-domains: maxItems: 1 + label: + $ref: /schemas/types.yaml#/definitions/string + description: + Define the label which can describe what kind of HW or system the + coresight device belongs to. + arm,cti-ctm-id: $ref: /schemas/types.yaml#/definitions/uint32 description: diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-dummy-sink.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-dummy-sink.yaml index 08b89b62c505b..bc82cd1f3595d 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-dummy-sink.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-dummy-sink.yaml @@ -39,6 +39,12 @@ properties: enum: - arm,coresight-dummy-sink + label: + $ref: /schemas/types.yaml#/definitions/string + description: + Define the label which can describe what kind of HW or system the + coresight device belongs to. + in-ports: $ref: /schemas/graph.yaml#/properties/ports diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-dummy-source.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-dummy-source.yaml index 742dc4e25d3bb..3010055d5ad6f 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-dummy-source.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-dummy-source.yaml @@ -38,6 +38,12 @@ properties: enum: - arm,coresight-dummy-source + label: + $ref: /schemas/types.yaml#/definitions/string + description: + Define the label which can describe what kind of HW or system the + coresight device belongs to. + arm,static-trace-id: description: If dummy source needs static id support, use this to set trace id. $ref: /schemas/types.yaml#/definitions/uint32 diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml index 44a1041cb0fc9..30776610d4b4b 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml @@ -57,6 +57,12 @@ properties: power-domains: maxItems: 1 + label: + $ref: /schemas/types.yaml#/definitions/string + description: + Define the label which can describe what kind of HW or system the + coresight device belongs to. + in-ports: $ref: /schemas/graph.yaml#/properties/ports diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-replicator.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-replicator.yaml index 03792e9bd97a0..178a3861ee29e 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-replicator.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-replicator.yaml @@ -54,6 +54,12 @@ properties: - const: apb_pclk - const: atclk + label: + $ref: /schemas/types.yaml#/definitions/string + description: + Define the label which can describe what kind of HW or system the + coresight device belongs to. + power-domains: maxItems: 1 diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-static-funnel.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-static-funnel.yaml index cc8c3baa79b45..39b291909cc41 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-static-funnel.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-static-funnel.yaml @@ -30,6 +30,12 @@ properties: power-domains: maxItems: 1 + label: + $ref: /schemas/types.yaml#/definitions/string + description: + Define the label which can describe what kind of HW or system the + coresight device belongs to. + in-ports: $ref: /schemas/graph.yaml#/properties/ports diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml index 0c1017affbad2..a3e8a105b2aec 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml @@ -43,6 +43,12 @@ properties: - const: dbg_trc - const: dbg_apb + label: + $ref: /schemas/types.yaml#/definitions/string + description: + Define the label which can describe what kind of HW or system the + coresight device belongs to. + in-ports: $ref: /schemas/graph.yaml#/properties/ports additionalProperties: false diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml index 4787d7c6bac2a..6a37ebaf474b2 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml @@ -55,6 +55,12 @@ properties: - const: apb_pclk - const: atclk + label: + $ref: /schemas/types.yaml#/definitions/string + description: + Define the label which can describe what kind of HW or system the + coresight device belongs to. + iommus: maxItems: 1 diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tpda.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tpda.yaml index 5ed40f21b8eb5..f42ecb4e85399 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-tpda.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tpda.yaml @@ -64,6 +64,12 @@ properties: items: - const: apb_pclk + label: + $ref: /schemas/types.yaml#/definitions/string + description: + Define the label which can describe what kind of HW or system the + coresight device belongs to. + in-ports: description: | Input connections from TPDM to TPDA diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml index 07d21a3617f5b..5e758476ad7f4 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml @@ -76,6 +76,12 @@ properties: minimum: 0 maximum: 32 + label: + $ref: /schemas/types.yaml#/definitions/string + description: + Define the label which can describe what kind of HW or system the + coresight device belongs to. + clocks: maxItems: 1 From 83e843ba2b9791eedd8d23b6a31742a21617cb01 Mon Sep 17 00:00:00 2001 From: Mao Jinlong Date: Wed, 26 Feb 2025 04:19:26 -0800 Subject: [PATCH 081/113] FROMLIST: coresight: Add label sysfs node support For some coresight components like CTI and TPDM, there could be numerous of them. From the node name, we can only get the type and register address of the component. We can't identify the HW or the system the component belongs to. Add label sysfs node support for showing the intuitive name of the device. Link: https://lore.kernel.org/all/20250703130453.4265-3-quic_jinlmao@quicinc.com/ Signed-off-by: Mao Jinlong Reviewed-by: Mike Leach --- .../testing/sysfs-bus-coresight-devices-cti | 6 ++++ .../sysfs-bus-coresight-devices-funnel | 6 ++++ .../testing/sysfs-bus-coresight-devices-tpdm | 6 ++++ drivers/hwtracing/coresight/coresight-sysfs.c | 32 +++++++++++++++++++ 4 files changed, 50 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti index a97b70f588da8..b013de5a7afc0 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti @@ -239,3 +239,9 @@ Date: March 2020 KernelVersion: 5.7 Contact: Mike Leach or Mathieu Poirier Description: (Write) Clear all channel / trigger programming. + +What: /sys/bus/coresight/devices//label +Date: Feb 2025 +KernelVersion 6.15 +Contact: Mao Jinlong +Description: (Read) Show hardware context information of device. diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-funnel b/Documentation/ABI/testing/sysfs-bus-coresight-devices-funnel index d75acda5e1b38..d9780489aa123 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-funnel +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-funnel @@ -10,3 +10,9 @@ Date: November 2014 KernelVersion: 3.19 Contact: Mathieu Poirier Description: (RW) Defines input port priority order. + +What: /sys/bus/coresight/devices/.funnel/label +Date: Feb 2025 +KernelVersion 6.15 +Contact: Mao Jinlong +Description: (Read) Show hardware context information of device. diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index a341b08ae70bf..29f04eebdf226 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -272,3 +272,9 @@ KernelVersion 6.15 Contact: Jinlong Mao (QUIC) , Tao Zhang (QUIC) Description: (RW) Set/Get the enablement of the individual lane. + +What: /sys/bus/coresight/devices//label +Date: Feb 2025 +KernelVersion 6.15 +Contact: Mao Jinlong +Description: (Read) Show hardware context information of device. diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c index feadaf065b531..e3d21c49814d1 100644 --- a/drivers/hwtracing/coresight/coresight-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-sysfs.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "coresight-priv.h" #include "coresight-trace-id.h" @@ -371,18 +372,47 @@ static ssize_t enable_source_store(struct device *dev, } static DEVICE_ATTR_RW(enable_source); +static ssize_t label_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + const char *str; + int ret = 0; + + ret = fwnode_property_read_string(dev_fwnode(dev), "label", &str); + if (ret == 0) + return scnprintf(buf, PAGE_SIZE, "%s\n", str); + else + return ret; +} +static DEVICE_ATTR_RO(label); + static struct attribute *coresight_sink_attrs[] = { &dev_attr_enable_sink.attr, + &dev_attr_label.attr, NULL, }; ATTRIBUTE_GROUPS(coresight_sink); static struct attribute *coresight_source_attrs[] = { &dev_attr_enable_source.attr, + &dev_attr_label.attr, NULL, }; ATTRIBUTE_GROUPS(coresight_source); +static struct attribute *coresight_link_attrs[] = { + &dev_attr_label.attr, + NULL, +}; +ATTRIBUTE_GROUPS(coresight_link); + +static struct attribute *coresight_helper_attrs[] = { + &dev_attr_label.attr, + NULL, +}; +ATTRIBUTE_GROUPS(coresight_helper); + const struct device_type coresight_dev_type[] = { [CORESIGHT_DEV_TYPE_SINK] = { .name = "sink", @@ -390,6 +420,7 @@ const struct device_type coresight_dev_type[] = { }, [CORESIGHT_DEV_TYPE_LINK] = { .name = "link", + .groups = coresight_link_groups, }, [CORESIGHT_DEV_TYPE_LINKSINK] = { .name = "linksink", @@ -401,6 +432,7 @@ const struct device_type coresight_dev_type[] = { }, [CORESIGHT_DEV_TYPE_HELPER] = { .name = "helper", + .groups = coresight_helper_groups, } }; /* Ensure the enum matches the names and groups */ From 1d8f8a8c0745842926c299a3347845103d1a411f Mon Sep 17 00:00:00 2001 From: Mao Jinlong Date: Thu, 24 Apr 2025 04:58:50 -0700 Subject: [PATCH 082/113] FROMLIST: dt-bindings: arm: Add CoreSight QMI component description Add new coresight-qmi.yaml file describing the bindings required to define qmi node in the device trees. Link: https://lore.kernel.org/all/20250424115854.2328190-2-quic_jinlmao@quicinc.com/ Signed-off-by: Mao Jinlong --- .../bindings/arm/qcom,coresight-qmi.yaml | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/qcom,coresight-qmi.yaml diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-qmi.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-qmi.yaml new file mode 100644 index 0000000000000..601c865fe4d73 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-qmi.yaml @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/qcom,coresight-qmi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm coresight QMI(Qualcomm Messaging Interface) component + +description: | + Qualcomm Messaging Interface (QMI) is an interface that clients can + use to send, and receive, messages from a remote entity. The coresight + QMI component is to configure QMI instance ids and service ids for different + remote subsystem connections. Coresight QMI driver uses the ids to init + the qmi connections. Other coresight drivers call the send qmi request + function when connection is established. + +maintainers: + - Mao Jinlong + +properties: + compatible: + enum: + - qcom,coresight-qmi + +patternProperties: + '^conns(-[0-9]+)?$': + type: object + description: + QMI instance id and service id for different remote subsystem connections. + + properties: + qmi-id: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Instance id for the remote subsystem connection. + + service-id: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Service id for the remote subsystem connection. + + additionalProperties: false + + required: + - qmi-id + - service-id + +required: + - compatible + +additionalProperties: false + +examples: + # Minimum coresight qmi definition. + - | + coresight-qmi { + compatible = "qcom,coresight-qmi"; + + conns-0 { + qmi-id = <0xd>; + service-id = <0x33>; + }; + }; + +... From 6be487afef8378e52b55a2eb5904ea29c47e2c94 Mon Sep 17 00:00:00 2001 From: Mao Jinlong Date: Thu, 24 Apr 2025 04:58:51 -0700 Subject: [PATCH 083/113] FROMLIST: coresight: Add coresight QMI driver Coresight QMI driver uses QMI(Qualcomm Messaging Interface) interfaces to communicate with remote subsystems. Driver gets the instance id and service id from device tree node and init the QMI connections to remote subsystems. Send request function is for other coresight drivers to communicate with remote subsystems. Link: https://lore.kernel.org/all/20250424115854.2328190-3-quic_jinlmao@quicinc.com/ Signed-off-by: Mao Jinlong --- drivers/hwtracing/coresight/Kconfig | 11 ++ drivers/hwtracing/coresight/Makefile | 1 + drivers/hwtracing/coresight/coresight-qmi.c | 209 ++++++++++++++++++++ drivers/hwtracing/coresight/coresight-qmi.h | 107 ++++++++++ 4 files changed, 328 insertions(+) create mode 100644 drivers/hwtracing/coresight/coresight-qmi.c create mode 100644 drivers/hwtracing/coresight/coresight-qmi.h diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index f064e3d172b3d..cecae35b0e59d 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -268,4 +268,15 @@ config CORESIGHT_KUNIT_TESTS Enable Coresight unit tests. Only useful for development and not intended for production. +config CORESIGHT_QMI + tristate "CORESIGHT QMI support" + select QCOM_QMI_HELPERS + help + Enables support for sending command to subsystem via QMI. This is + primarily used for sending QMI message to subsystems for remote trace + sources. + + To compile this driver as a module, choose M here: the module will be + called coresight-qmi. + endif diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index 4e7cc3c5bf994..d4b1c74d183fb 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_CORESIGHT_TPDA) += coresight-tpda.o coresight-cti-y := coresight-cti-core.o coresight-cti-platform.o \ coresight-cti-sysfs.o obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o +obj-$(CONFIG_CORESIGHT_QMI) += coresight-qmi.o obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o coresight-ctcu-y := coresight-ctcu-core.o diff --git a/drivers/hwtracing/coresight/coresight-qmi.c b/drivers/hwtracing/coresight/coresight-qmi.c new file mode 100644 index 0000000000000..d93b606e71084 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-qmi.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include +#include + +#include "coresight-qmi.h" +static LIST_HEAD(qmi_data); + +static int service_coresight_qmi_new_server(struct qmi_handle *qmi, + struct qmi_service *svc) +{ + struct qmi_data *data = container_of(qmi, + struct qmi_data, handle); + + data->s_addr.sq_family = AF_QIPCRTR; + data->s_addr.sq_node = svc->node; + data->s_addr.sq_port = svc->port; + data->service_connected = true; + pr_debug("Connection established between QMI handle and %d service\n", + data->qmi_id); + + return 0; +} + +static void service_coresight_qmi_del_server(struct qmi_handle *qmi, + struct qmi_service *svc) +{ + struct qmi_data *data = container_of(qmi, + struct qmi_data, handle); + data->service_connected = false; + pr_debug("Connection disconnected between QMI handle and %d service\n", + data->qmi_id); +} + +static struct qmi_ops server_ops = { + .new_server = service_coresight_qmi_new_server, + .del_server = service_coresight_qmi_del_server, +}; + +static int coresight_qmi_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = pdev->dev.of_node; + struct device_node *child_node; + int ret; + + /** + * Get the instance id and service id of the QMI service connection + * from DT node. Creates QMI handle and register new lookup for each + * QMI connection. + */ + for_each_available_child_of_node(node, child_node) { + struct qmi_data *data; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = of_property_read_u32(child_node, "qmi-id", &data->qmi_id); + if (ret) + return ret; + + ret = of_property_read_u32(child_node, "service-id", &data->service_id); + if (ret) + return ret; + + ret = qmi_handle_init(&data->handle, + CORESIGHT_QMI_MAX_MSG_LEN, + &server_ops, NULL); + if (ret < 0) { + dev_err(dev, "qmi client init failed ret:%d\n", ret); + return ret; + } + + qmi_add_lookup(&data->handle, + data->service_id, + CORESIGHT_QMI_VERSION, + data->qmi_id); + + list_add(&data->node, &qmi_data); + } + + return 0; +} + +/** + * coresight_get_qmi_data() - Get the qmi data struct from qmi_data + * @id: instance id to get the qmi data + * + * Return: qmi data struct on success, NULL on failure. + */ +static struct qmi_data *coresight_get_qmi_data(int id) +{ + struct qmi_data *data; + + list_for_each_entry(data, &qmi_data, node) { + if (data->qmi_id == id) + return data; + } + + return NULL; +} + +/** + * coresight_send_qmi_request() - Send a QMI message to remote subsystem + * @instance_id: QMI Instance id of the remote subsystem + * @msg_id: message id of the request + * @resp_ei: description of how to decode a matching response + * @req_ei: description of how to encode a matching request + * @resp: pointer to the object to decode the response info + * @req: pointer to the object to encode the request info + * @len: max length of the QMI message + * + * Return: 0 on success, negative errno on failure. + */ +int coresight_send_qmi_request(int instance_id, int msg_id, struct qmi_elem_info *resp_ei, + struct qmi_elem_info *req_ei, void *resp, void *req, int len) +{ + struct qmi_txn txn; + int ret; + struct qmi_data *data; + + data = coresight_get_qmi_data(instance_id); + if (!data) { + pr_err("No QMI data for QMI service!\n"); + ret = -EINVAL; + return ret; + } + + if (!data->service_connected) { + pr_err("QMI service not connected!\n"); + ret = -EINVAL; + return ret; + } + + ret = qmi_txn_init(&data->handle, &txn, + resp_ei, + resp); + + if (ret < 0) { + pr_err("QMI tx init failed , ret:%d\n", ret); + return ret; + } + + ret = qmi_send_request(&data->handle, &data->s_addr, + &txn, msg_id, + len, + req_ei, + req); + + if (ret < 0) { + pr_err("QMI send ACK failed, ret:%d\n", ret); + qmi_txn_cancel(&txn); + return ret; + } + + ret = qmi_txn_wait(&txn, msecs_to_jiffies(TIMEOUT_MS)); + if (ret < 0) { + pr_err("QMI qmi txn wait failed, ret:%d\n", ret); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(coresight_send_qmi_request); + +static void coresight_qmi_remove(struct platform_device *pdev) +{ + struct qmi_data *data; + + list_for_each_entry(data, &qmi_data, node) { + qmi_handle_release(&data->handle); + } +} + +static const struct of_device_id coresight_qmi_match[] = { + {.compatible = "qcom,coresight-qmi"}, + {} +}; + +static struct platform_driver coresight_qmi_driver = { + .probe = coresight_qmi_probe, + .remove = coresight_qmi_remove, + .driver = { + .name = "coresight-qmi", + .of_match_table = coresight_qmi_match, + }, +}; + +static int __init coresight_qmi_init(void) +{ + return platform_driver_register(&coresight_qmi_driver); +} +module_init(coresight_qmi_init); + +static void __exit coresight_qmi_exit(void) +{ + platform_driver_unregister(&coresight_qmi_driver); +} +module_exit(coresight_qmi_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("CoreSight QMI driver"); diff --git a/drivers/hwtracing/coresight/coresight-qmi.h b/drivers/hwtracing/coresight/coresight-qmi.h new file mode 100644 index 0000000000000..1d57e46177b8c --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-qmi.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ +#ifndef _CORESIGHT_QMI_H +#define _CORESIGHT_QMI_H + +#include + +#define CORESIGHT_QMI_VERSION (1) + +#define CORESIGHT_QMI_SET_ETM_REQ_V01 (0x002C) +#define CORESIGHT_QMI_SET_ETM_RESP_V01 (0x002C) + +#define CORESIGHT_QMI_MAX_MSG_LEN (50) + +#define TIMEOUT_MS (10000) + +/* Qmi data for the QMI connection */ +struct qmi_data { + u32 qmi_id; + u32 service_id; + struct list_head node; + struct qmi_handle handle; + bool service_connected; + struct sockaddr_qrtr s_addr; +}; + +/** + * QMI service IDs + * + * CORESIGHT_QMI_QDSSC_SVC_ID for remote etm + * CORESIGHT_QMI_QDCP_SVC_ID for STM/TPDM/CTI + */ +enum coresight_qmi_service_id { + CORESIGHT_QMI_QDSSC_SVC_ID = 0x33, + CORESIGHT_QMI_QDCP_SVC_ID = 0xff, +}; + +enum coresight_qmi_instance_id { + CORESIGHT_QMI_INSTANCE_MODEM_V01 = 2, + CORESIGHT_QMI_INSTANCE_WLAN_V01 = 3, + CORESIGHT_QMI_INSTANCE_AOP_V01 = 4, + CORESIGHT_QMI_INSTANCE_ADSP_V01 = 5, + CORESIGHT_QMI_INSTANCE_VENUS_V01 = 6, + CORESIGHT_QMI_INSTANCE_GNSS_V01 = 7, + CORESIGHT_QMI_INSTANCE_SENSOR_V01 = 8, + CORESIGHT_QMI_INSTANCE_AUDIO_V01 = 9, + CORESIGHT_QMI_INSTANCE_VPU_V01 = 10, + CORESIGHT_QMI_INSTANCE_MODEM2_V01 = 11, + CORESIGHT_QMI_INSTANCE_SENSOR2_V01 = 12, + CORESIGHT_QMI_INSTANCE_CDSP_V01 = 13, + CORESIGHT_QMI_INSTANCE_NPU_V01 = 14, + CORESIGHT_QMI_INSTANCE_CDSP_USER_V01 = 15, + CORESIGHT_QMI_INSTANCE_CDSP1_V01 = 16, + CORESIGHT_QMI_INSTANCE_GPDSP0_V01 = 17, + CORESIGHT_QMI_INSTANCE_GPDSP1_V01 = 18, + CORESIGHT_QMI_INSTANCE_TBD_V01 = 19, + CORESIGHT_QMI_INSTANCE_GPDSP0_AUDI0_V01 = 20, + CORESIGHT_QMI_INSTANCE_GPDSP1_AUDI0_V01 = 21, + CORESIGHT_QMI_INSTANCE_MODEM_OEM_V01 = 22, + CORESIGHT_QMI_INSTANCE_ADSP1_V01 = 23, + CORESIGHT_QMI_INSTANCE_ADSP1_AUDIO_V01 = 24, + CORESIGHT_QMI_INSTANCE_ADSP2_V01 = 25, + CORESIGHT_QMI_INSTANCE_ADSP2_AUDIO_V01 = 26, + CORESIGHT_QMI_INSTANCE_CDSP2_V01 = 27, + CORESIGHT_QMI_INSTANCE_CDSP3_V01 = 28, + CORESIGHT_QMI_INSTANCE_SOCCP_V01 = 29, + CORESIGHT_QMI_INSTANCE_QECP_V01 = 30, +}; + +enum coresight_etm_state_enum_type_v01 { + /* To force a 32 bit signed enum. Do not change or use */ + CORESIGHT_ETM_STATE_ENUM_TYPE_MIN_ENUM_VAL_V01 = INT_MIN, + CORESIGHT_ETM_STATE_DISABLED_V01 = 0, + CORESIGHT_ETM_STATE_ENABLED_V01 = 1, + CORESIGHT_ETM_STATE_ENUM_TYPE_MAX_ENUM_VAL_01 = INT_MAX, +}; + +/** + * Set remote etm request message + * + * @state enable/disable state + */ +struct coresight_set_etm_req_msg_v01 { + enum coresight_etm_state_enum_type_v01 state; +}; + +/** + * Set remote etm response message + */ +struct coresight_set_etm_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#if IS_ENABLED(CONFIG_CORESIGHT_QMI) +extern int coresight_send_qmi_request(int instance_id, int msg_id, + struct qmi_elem_info *resp_ei, + struct qmi_elem_info *req_ei, void *resp, void *req, int len); +#else + +static inline int coresight_send_qmi_request(int instance_id, int msg_id, + struct qmi_elem_info *resp_ei, + struct qmi_elem_info *req_ei, void *resp, void *req, int len) {return NULL; } +#endif + +#endif From 660db94596b8e348a33c38bad4167df26c073252 Mon Sep 17 00:00:00 2001 From: Mao Jinlong Date: Thu, 24 Apr 2025 04:58:52 -0700 Subject: [PATCH 084/113] FROMLIST: dt-bindings: arm: Add qcom,qmi-id for remote etm qcom,qmi-id is required for remote etm driver to find the remote subsystem connection. It is the instance id used by qmi API to communicate with remote processor. Link: https://lore.kernel.org/all/20250424115854.2328190-4-quic_jinlmao@quicinc.com/ Signed-off-by: Mao Jinlong --- .../bindings/arm/qcom,coresight-remote-etm.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-remote-etm.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-remote-etm.yaml index 4fd5752978cd0..947fe33738a3f 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-remote-etm.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-remote-etm.yaml @@ -20,6 +20,13 @@ properties: compatible: const: qcom,coresight-remote-etm + qcom,qmi-id: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + This id is used by qmi API to communicate with remote processor for + enabling and disabling remote etm. Each processor has its unique instance + id. + out-ports: $ref: /schemas/graph.yaml#/properties/ports additionalProperties: false @@ -32,6 +39,7 @@ properties: required: - compatible - out-ports + - qcom,qmi-id additionalProperties: false @@ -40,6 +48,8 @@ examples: etm { compatible = "qcom,coresight-remote-etm"; + qcom,qmi-id = <2>; + out-ports { port { modem_etm0_out_funnel_modem: endpoint { From 6005719ed7eea00e5ff96e97a7e8927af0a2362e Mon Sep 17 00:00:00 2001 From: Mao Jinlong Date: Thu, 24 Apr 2025 04:58:53 -0700 Subject: [PATCH 085/113] FROMLIST: coresight: Add remote etm support The system on chip (SoC) consists of main APSS(Applications processor subsytem) and additional processors like modem, lpass. Coresight remote etm(Embedded Trace Macrocell) driver is for enabling and disabling the etm trace of remote processors. It uses QMI interface to communicate with remote processors' software and uses coresight framework to configure the connection from remote etm source to TMC sinks. Link: https://lore.kernel.org/all/20250424115854.2328190-5-quic_jinlmao@quicinc.com/ Signed-off-by: Mao Jinlong --- drivers/hwtracing/coresight/Kconfig | 12 + drivers/hwtracing/coresight/Makefile | 1 + .../coresight/coresight-remote-etm.c | 252 ++++++++++++++++++ 3 files changed, 265 insertions(+) create mode 100644 drivers/hwtracing/coresight/coresight-remote-etm.c diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index cecae35b0e59d..7a282c6c72b72 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -279,4 +279,16 @@ config CORESIGHT_QMI To compile this driver as a module, choose M here: the module will be called coresight-qmi. +config CORESIGHT_REMOTE_ETM + tristate "Remote processor ETM trace support" + depends on QCOM_QMI_HELPERS + help + Enables support for ETM trace collection on remote processor using + CoreSight framework. Enabling this will allow turning on ETM + tracing on remote processor via sysfs by configuring the required + CoreSight components. + + To compile this driver as a module, choose M here: the module will be + called coresight-remote-etm. + endif diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index d4b1c74d183fb..60bfe6ff0ecb9 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -53,6 +53,7 @@ coresight-cti-y := coresight-cti-core.o coresight-cti-platform.o \ coresight-cti-sysfs.o obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o obj-$(CONFIG_CORESIGHT_QMI) += coresight-qmi.o +obj-$(CONFIG_CORESIGHT_REMOTE_ETM) += coresight-remote-etm.o obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o coresight-ctcu-y := coresight-ctcu-core.o diff --git a/drivers/hwtracing/coresight/coresight-remote-etm.c b/drivers/hwtracing/coresight/coresight-remote-etm.c new file mode 100644 index 0000000000000..6b24dc70847a3 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-remote-etm.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "coresight-qmi.h" + +#define CORESIGHT_QMI_SET_ETM_REQ_MAX_LEN (7) + +DEFINE_CORESIGHT_DEVLIST(remote_etm_devs, "remote-etm"); + +/** + * struct remote_etm_drvdata - specifics associated to remote etm device + * @dev: the device entity associated to this component + * @csdev: component vitals needed by the framework + * @mutex: lock for seting etm + * @inst_id: the instance id of the remote connection + */ +struct remote_etm_drvdata { + struct device *dev; + struct coresight_device *csdev; + struct mutex mutex; + u32 inst_id; +}; + +/* + * Element info to descrbe the coresight_set_etm_req_msg_v01 struct + * which is used to encode the request. + */ +static struct qmi_elem_info coresight_set_etm_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(enum coresight_etm_state_enum_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct coresight_set_etm_req_msg_v01, + state), + .ei_array = NULL, + }, + { + .data_type = QMI_EOTI, + .elem_len = 0, + .elem_size = 0, + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = 0, + .ei_array = NULL, + }, +}; + +/* + * Element info to describe the coresight_set_etm_resp_msg_v01 struct + * which is used to decode the response. + */ +static struct qmi_elem_info coresight_set_etm_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct coresight_set_etm_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .elem_len = 0, + .elem_size = 0, + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = 0, + .ei_array = NULL, + }, +}; + +static int remote_etm_enable(struct coresight_device *csdev, + struct perf_event *event, enum cs_mode mode, + __maybe_unused struct coresight_path *path) +{ + struct remote_etm_drvdata *drvdata = + dev_get_drvdata(csdev->dev.parent); + struct coresight_set_etm_req_msg_v01 req; + struct coresight_set_etm_resp_msg_v01 resp = { { 0, 0 } }; + int ret = 0; + + mutex_lock(&drvdata->mutex); + + if (mode != CS_MODE_SYSFS) { + ret = -EINVAL; + goto err; + } + + if (!coresight_take_mode(csdev, mode)) { + ret = -EBUSY; + goto err; + } + + req.state = CORESIGHT_ETM_STATE_ENABLED_V01; + + ret = coresight_send_qmi_request(drvdata->inst_id, CORESIGHT_QMI_SET_ETM_REQ_V01, + coresight_set_etm_resp_msg_v01_ei, + coresight_set_etm_req_msg_v01_ei, + &resp, &req, CORESIGHT_QMI_SET_ETM_REQ_MAX_LEN); + + if (ret) + goto err; + + if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { + dev_err(drvdata->dev, "QMI request failed 0x%x\n", resp.resp.error); + ret = -EINVAL; + goto err; + } + + mutex_unlock(&drvdata->mutex); + return 0; +err: + coresight_set_mode(csdev, CS_MODE_DISABLED); + mutex_unlock(&drvdata->mutex); + return ret; + +} + +static void remote_etm_disable(struct coresight_device *csdev, + struct perf_event *event) +{ + struct remote_etm_drvdata *drvdata = + dev_get_drvdata(csdev->dev.parent); + struct coresight_set_etm_req_msg_v01 req; + struct coresight_set_etm_resp_msg_v01 resp = { { 0, 0 } }; + int ret = 0; + + mutex_lock(&drvdata->mutex); + + req.state = CORESIGHT_ETM_STATE_DISABLED_V01; + + ret = coresight_send_qmi_request(drvdata->inst_id, CORESIGHT_QMI_SET_ETM_REQ_V01, + coresight_set_etm_resp_msg_v01_ei, + coresight_set_etm_req_msg_v01_ei, + &resp, &req, CORESIGHT_QMI_SET_ETM_REQ_MAX_LEN); + if (ret) + dev_err(drvdata->dev, "Send qmi request failed %d\n", ret); + + if (resp.resp.result != QMI_RESULT_SUCCESS_V01) + dev_err(drvdata->dev, "QMI request failed %d\n", resp.resp.error); + + coresight_set_mode(csdev, CS_MODE_DISABLED); + mutex_unlock(&drvdata->mutex); +} + +static const struct coresight_ops_source remote_etm_source_ops = { + .enable = remote_etm_enable, + .disable = remote_etm_disable, +}; + +static const struct coresight_ops remote_cs_ops = { + .source_ops = &remote_etm_source_ops, +}; + +static int remote_etm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct coresight_platform_data *pdata; + struct remote_etm_drvdata *drvdata; + struct coresight_desc desc = {0 }; + int ret; + + desc.name = coresight_alloc_device_name(&remote_etm_devs, dev); + if (!desc.name) + return -ENOMEM; + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + pdev->dev.platform_data = pdata; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + drvdata->dev = dev; + platform_set_drvdata(pdev, drvdata); + + ret = of_property_read_u32(dev->of_node, "qcom,qmi-id", + &drvdata->inst_id); + if (ret) + return ret; + + mutex_init(&drvdata->mutex); + + desc.type = CORESIGHT_DEV_TYPE_SOURCE; + desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS; + desc.ops = &remote_cs_ops; + desc.pdata = pdev->dev.platform_data; + desc.dev = &pdev->dev; + drvdata->csdev = coresight_register(&desc); + if (IS_ERR(drvdata->csdev)) { + ret = PTR_ERR(drvdata->csdev); + goto err; + } + + dev_dbg(dev, "Remote ETM initialized\n"); + + return 0; + +err: + return ret; +} + +static void remote_etm_remove(struct platform_device *pdev) +{ + struct remote_etm_drvdata *drvdata = platform_get_drvdata(pdev); + + coresight_unregister(drvdata->csdev); +} + +static const struct of_device_id remote_etm_match[] = { + {.compatible = "qcom,coresight-remote-etm"}, + {} +}; + +static struct platform_driver remote_etm_driver = { + .probe = remote_etm_probe, + .remove = remote_etm_remove, + .driver = { + .name = "coresight-remote-etm", + .of_match_table = remote_etm_match, + }, +}; + +static int __init remote_etm_init(void) +{ + return platform_driver_register(&remote_etm_driver); +} +module_init(remote_etm_init); + +static void __exit remote_etm_exit(void) +{ + platform_driver_unregister(&remote_etm_driver); +} +module_exit(remote_etm_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("CoreSight Remote ETM driver"); From c5ea8f623fd27c6b2d576f9f5f9622b337e48556 Mon Sep 17 00:00:00 2001 From: Mao Jinlong Date: Thu, 24 Apr 2025 04:58:54 -0700 Subject: [PATCH 086/113] FROMLIST: arm64: dts: qcom: msm8996: Add coresight qmi node coresight qmi nodes is to init the qmi connection to remote subsystem. qcom,qmi-id is used by remote etm driver to get the remote subsystem connection and send the request. Link: https://lore.kernel.org/all/20250424115854.2328190-6-quic_jinlmao@quicinc.com/ Signed-off-by: Mao Jinlong --- arch/arm64/boot/dts/qcom/msm8996.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index ede851fbf6284..26fab7626c394 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -40,6 +40,15 @@ }; }; + coresight-qmi { + compatible = "qcom,coresight-qmi"; + + conns-0 { + qmi-id = <0x2>; + service-id = <0x33>; + }; + }; + cpus { #address-cells = <2>; #size-cells = <0>; @@ -448,6 +457,8 @@ etm { compatible = "qcom,coresight-remote-etm"; + qcom,qmi-id = <0x2>; + out-ports { port { modem_etm_out_funnel_in2: endpoint { From 0dd733952362bec2cc89583ad1610902b73ad2fb Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Wed, 23 Apr 2025 14:34:18 +0800 Subject: [PATCH 087/113] FROMLIST: dt-bindings: arm: Add support for Coresight TGU trace The Trigger Generation Unit (TGU) is designed to detect patterns or sequences within a specific region of the System on Chip (SoC). Once configured and activated, it monitors sense inputs and can detect a pre-programmed state or sequence across clock cycles, subsequently producing a trigger. TGU configuration space offset table x-------------------------x | | | | | | Step configuration | | space layout | coresight management | x-------------x | registers | |---> | | | | | | reserve | | | | | | |-------------------------| | |-------------| | | | | priority[3] | | step[7] |<-- | |-------------| |-------------------------| | | | priority[2] | | | | | |-------------| | ... | |Steps region | | priority[1] | | | | | |-------------| |-------------------------| | | | priority[0] | | |<-- | |-------------| | step[0] |--------------------> | | |-------------------------| | condition | | | | | | control and status | x-------------x | space | | | x-------------------------x |Timer/Counter| | | x-------------x TGU Configuration in Hardware The TGU provides a step region for user configuration, similar to a flow chart. Each step region consists of three register clusters: 1.Priority Region: Sets the required signals with priority. 2.Condition Region: Defines specific requirements (e.g., signal A reaches three times) and the subsequent action once the requirement is met. 3.Timer/Counter (Optional): Provides timing or counting functionality. Add a new coresight-tgu.yaml file to describe the bindings required to define the TGU in the device trees. Link: https://lore.kernel.org/all/20250423-tgu_patch-v5-1-3b52c105cc63@quicinc.com/ Signed-off-by: Songwei Chai --- .../bindings/arm/qcom,coresight-tgu.yaml | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml new file mode 100644 index 0000000000000..3576d38711261 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +# Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/qcom,coresight-tgu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Trigger Generation Unit - TGU + +description: | + The Trigger Generation Unit (TGU) is a Data Engine which can be utilized + to sense a plurality of signals and create a trigger into the CTI or + generate interrupts to processors. The TGU is like the trigger circuit + of a Logic Analyzer. The corresponding trigger logic can be realized by + configuring the conditions for each step after sensing the signal. + Once setup and enabled, it will observe sense inputs and based upon + the activity of those inputs, even over clock cycles, may detect a + preprogrammed state/sequence and then produce a trigger or interrupt. + + The primary use case of the TGU is to detect patterns or sequences on a + given set of signals within some region to indentify the issue in time + once there is abnormal behavior in the subsystem. + +maintainers: + - Mao Jinlong + - Sam Chai + +# Need a custom select here or 'arm,primecell' will match on lots of nodes +select: + properties: + compatible: + contains: + enum: + - qcom,coresight-tgu + required: + - compatible + +properties: + compatible: + items: + - const: qcom,coresight-tgu + - const: arm,primecell + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: apb_pclk + + in-ports: + $ref: /schemas/graph.yaml#/properties/ports + additionalProperties: false + + properties: + port: + description: + The port mechanism here ensures the relationship between TGU and + TPDM, as TPDM is one of the inputs for TGU. It will allow TGU to + function as TPDM's helper and enable TGU when the connected + TPDM is enabled. + $ref: /schemas/graph.yaml#/properties/port + +required: + - compatible + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + tgu@10b0e000 { + compatible = "qcom,coresight-tgu", "arm,primecell"; + reg = <0x10b0e000 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + tgu_in_tpdm_swao: endpoint{ + remote-endpoint = <&tpdm_swao_out_tgu>; + }; + }; + }; + }; +... From 4bba4b98e4fd7649cd7d976cf7fcf382aa16a7fd Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Wed, 23 Apr 2025 14:34:19 +0800 Subject: [PATCH 088/113] FROMLIST: coresight: Add coresight TGU driver Add driver to support Coresight device TGU (Trigger Generation Unit). TGU is a Data Engine which can be utilized to sense a plurality of signals and create a trigger into the CTI or generate interrupts to processors. Add probe/enable/disable functions for tgu. Link: https://lore.kernel.org/all/20250423-tgu_patch-v5-2-3b52c105cc63@quicinc.com/ Signed-off-by: Songwei Chai --- .../testing/sysfs-bus-coresight-devices-tgu | 9 + drivers/hwtracing/coresight/Kconfig | 11 + drivers/hwtracing/coresight/Makefile | 1 + drivers/hwtracing/coresight/coresight-tgu.c | 213 ++++++++++++++++++ drivers/hwtracing/coresight/coresight-tgu.h | 37 +++ 5 files changed, 271 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu create mode 100644 drivers/hwtracing/coresight/coresight-tgu.c create mode 100644 drivers/hwtracing/coresight/coresight-tgu.h diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu new file mode 100644 index 0000000000000..741bc9fd9df50 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu @@ -0,0 +1,9 @@ +What: /sys/bus/coresight/devices//enable_tgu +Date: February 2025 +KernelVersion 6.15 +Contact: Jinlong Mao (QUIC) , Sam Chai (QUIC) +Description: + (RW) Set/Get the enable/disable status of TGU + Accepts only one of the 2 values - 0 or 1. + 0 : disable TGU. + 1 : enable TGU. diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index 7a282c6c72b72..02ef739f5fef7 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -291,4 +291,15 @@ config CORESIGHT_REMOTE_ETM To compile this driver as a module, choose M here: the module will be called coresight-remote-etm. +config CORESIGHT_TGU + tristate "CoreSight Trigger Generation Unit driver" + help + This driver provides support for Trigger Generation Unit that is + used to detect patterns or sequences on a given set of signals. + TGU is used to monitor a particular bus within a given region to + detect illegal transaction sequences or slave responses. It is also + used to monitor a data stream to detect protocol violations and to + provide a trigger point for centering data around a specific event + within the trace data buffer. + endif diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index 60bfe6ff0ecb9..e2e5c309e9a9b 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o obj-$(CONFIG_CORESIGHT_QMI) += coresight-qmi.o obj-$(CONFIG_CORESIGHT_REMOTE_ETM) += coresight-remote-etm.o obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o +obj-$(CONFIG_CORESIGHT_TGU) += coresight-tgu.o obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o coresight-ctcu-y := coresight-ctcu-core.o obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o diff --git a/drivers/hwtracing/coresight/coresight-tgu.c b/drivers/hwtracing/coresight/coresight-tgu.c new file mode 100644 index 0000000000000..a1a02602f7b36 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-tgu.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "coresight-priv.h" +#include "coresight-tgu.h" + +DEFINE_CORESIGHT_DEVLIST(tgu_devs, "tgu"); + +static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) +{ + CS_UNLOCK(drvdata->base); + /* Enable TGU to program the triggers */ + tgu_writel(drvdata, 1, TGU_CONTROL); + CS_LOCK(drvdata->base); +} + +static int tgu_enable(struct coresight_device *csdev, enum cs_mode mode, + void *data) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + spin_lock(&drvdata->spinlock); + + if (drvdata->enable) { + spin_unlock(&drvdata->spinlock); + return -EBUSY; + } + tgu_write_all_hw_regs(drvdata); + drvdata->enable = true; + + spin_unlock(&drvdata->spinlock); + return 0; +} + +static int tgu_disable(struct coresight_device *csdev, void *data) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + spin_lock(&drvdata->spinlock); + if (drvdata->enable) { + CS_UNLOCK(drvdata->base); + tgu_writel(drvdata, 0, TGU_CONTROL); + CS_LOCK(drvdata->base); + + drvdata->enable = false; + } + spin_unlock(&drvdata->spinlock); + return 0; +} + +static ssize_t enable_tgu_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + bool enabled; + + struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent); + + spin_lock(&drvdata->spinlock); + enabled = drvdata->enable; + spin_unlock(&drvdata->spinlock); + + return sysfs_emit(buf, "%d\n", enabled); +} + +/* enable_tgu_store - Configure Trace and Gating Unit (TGU) triggers. */ +static ssize_t enable_tgu_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + int ret = 0; + unsigned long val; + struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent); + + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; + + if (val) { + ret = pm_runtime_resume_and_get(dev->parent); + if (ret) + return ret; + ret = tgu_enable(drvdata->csdev, CS_MODE_SYSFS, NULL); + if (ret) + pm_runtime_put(dev->parent); + } else { + ret = tgu_disable(drvdata->csdev, NULL); + pm_runtime_put(dev->parent); + } + + if (ret) + return ret; + return size; +} +static DEVICE_ATTR_RW(enable_tgu); + +static const struct coresight_ops_helper tgu_helper_ops = { + .enable = tgu_enable, + .disable = tgu_disable, +}; + +static const struct coresight_ops tgu_ops = { + .helper_ops = &tgu_helper_ops, +}; + +static struct attribute *tgu_common_attrs[] = { + &dev_attr_enable_tgu.attr, + NULL, +}; + +static const struct attribute_group tgu_common_grp = { + .attrs = tgu_common_attrs, + { NULL }, +}; + +static const struct attribute_group *tgu_attr_groups[] = { + &tgu_common_grp, + NULL, +}; + +static int tgu_probe(struct amba_device *adev, const struct amba_id *id) +{ + int ret = 0; + struct device *dev = &adev->dev; + struct coresight_desc desc = { 0 }; + struct coresight_platform_data *pdata; + struct tgu_drvdata *drvdata; + + desc.name = coresight_alloc_device_name(&tgu_devs, dev); + if (!desc.name) + return -ENOMEM; + + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + + adev->dev.platform_data = pdata; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + drvdata->dev = &adev->dev; + dev_set_drvdata(dev, drvdata); + + drvdata->base = devm_ioremap_resource(dev, &adev->res); + if (!drvdata->base) + return -ENOMEM; + + spin_lock_init(&drvdata->spinlock); + + drvdata->enable = false; + desc.type = CORESIGHT_DEV_TYPE_HELPER; + desc.pdata = adev->dev.platform_data; + desc.dev = &adev->dev; + desc.ops = &tgu_ops; + desc.groups = tgu_attr_groups; + + drvdata->csdev = coresight_register(&desc); + if (IS_ERR(drvdata->csdev)) { + ret = PTR_ERR(drvdata->csdev); + goto err; + } + + pm_runtime_put(&adev->dev); + return 0; +err: + pm_runtime_put(&adev->dev); + return ret; +} + +static void tgu_remove(struct amba_device *adev) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(&adev->dev); + + coresight_unregister(drvdata->csdev); +} + +static const struct amba_id tgu_ids[] = { + { + .id = 0x000f0e00, + .mask = 0x000fffff, + .data = "TGU", + }, + { 0, 0, NULL }, +}; + +MODULE_DEVICE_TABLE(amba, tgu_ids); + +static struct amba_driver tgu_driver = { + .drv = { + .name = "coresight-tgu", + .suppress_bind_attrs = true, + }, + .probe = tgu_probe, + .remove = tgu_remove, + .id_table = tgu_ids, +}; + +module_amba_driver(tgu_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("CoreSight TGU driver"); diff --git a/drivers/hwtracing/coresight/coresight-tgu.h b/drivers/hwtracing/coresight/coresight-tgu.h new file mode 100644 index 0000000000000..6c849a2f78faf --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-tgu.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _CORESIGHT_TGU_H +#define _CORESIGHT_TGU_H + +/* Register addresses */ +#define TGU_CONTROL 0x0000 + +/* Register read/write */ +#define tgu_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off) +#define tgu_readl(drvdata, off) __raw_readl(drvdata->base + off) + +/** + * struct tgu_drvdata - Data structure for a TGU (Trigger Generator Unit) + * @base: Memory-mapped base address of the TGU device + * @dev: Pointer to the associated device structure + * @csdev: Pointer to the associated coresight device + * @spinlock: Spinlock for handling concurrent access + * @enable: Flag indicating whether the TGU device is enabled + * + * This structure defines the data associated with a TGU device, + * including its base address, device pointers, clock, spinlock for + * synchronization, trigger data pointers, maximum limits for various + * trigger-related parameters, and enable status. + */ +struct tgu_drvdata { + void __iomem *base; + struct device *dev; + struct coresight_device *csdev; + spinlock_t spinlock; + bool enable; +}; + +#endif From 0734514315adbb079eef76483be15000a0ea60e4 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Wed, 23 Apr 2025 14:34:20 +0800 Subject: [PATCH 089/113] FROMLIST: coresight-tgu: Add signal priority support Like circuit of a Logic analyzer, in TGU, the requirement could be configured in each step and the trigger will be created once the requirements are met. Add priority functionality here to sort the signals into different priorities. The signal which is wanted could be configured in each step's priority node, the larger number means the higher priority and the signal with higher priority will be sensed more preferentially. Link: https://lore.kernel.org/all/20250423-tgu_patch-v5-3-3b52c105cc63@quicinc.com/ Signed-off-by: Songwei Chai --- .../testing/sysfs-bus-coresight-devices-tgu | 7 + drivers/hwtracing/coresight/coresight-tgu.c | 163 ++++++++++++++++++ drivers/hwtracing/coresight/coresight-tgu.h | 112 ++++++++++++ 3 files changed, 282 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu index 741bc9fd9df50..5843409768838 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu @@ -7,3 +7,10 @@ Description: Accepts only one of the 2 values - 0 or 1. 0 : disable TGU. 1 : enable TGU. + +What: /sys/bus/coresight/devices//step[0:7]_priority[0:3]/reg[0:17] +Date: February 2025 +KernelVersion 6.15 +Contact: Jinlong Mao (QUIC) , Sam Chai (QUIC) +Description: + (RW) Set/Get the sensed signal with specific step and priority for TGU. diff --git a/drivers/hwtracing/coresight/coresight-tgu.c b/drivers/hwtracing/coresight/coresight-tgu.c index a1a02602f7b36..6dbfd4c604b1f 100644 --- a/drivers/hwtracing/coresight/coresight-tgu.c +++ b/drivers/hwtracing/coresight/coresight-tgu.c @@ -17,14 +17,128 @@ DEFINE_CORESIGHT_DEVLIST(tgu_devs, "tgu"); +static int calculate_array_location(struct tgu_drvdata *drvdata, + int step_index, int operation_index, + int reg_index) +{ + int ret; + + ret = operation_index * (drvdata->max_step) * + (drvdata->max_reg) + + step_index * (drvdata->max_reg) + reg_index; + + return ret; +} + +static ssize_t tgu_dataset_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct tgu_attribute *tgu_attr = + container_of(attr, struct tgu_attribute, attr); + + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->priority[ + calculate_array_location( + drvdata, tgu_attr->step_index, + tgu_attr->operation_index, + tgu_attr->reg_num)]); +} + +static ssize_t tgu_dataset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + unsigned long val; + + struct tgu_drvdata *tgu_drvdata = dev_get_drvdata(dev->parent); + struct tgu_attribute *tgu_attr = + container_of(attr, struct tgu_attribute, attr); + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + guard(spinlock)(&tgu_drvdata->spinlock); + tgu_drvdata->value_table->priority[calculate_array_location( + tgu_drvdata, tgu_attr->step_index, tgu_attr->operation_index, + tgu_attr->reg_num)] = val; + + return size; +} + +static umode_t tgu_node_visible(struct kobject *kobject, + struct attribute *attr, + int n) +{ + struct device *dev = kobj_to_dev(kobject); + struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent); + int ret = SYSFS_GROUP_INVISIBLE; + + struct device_attribute *dev_attr = + container_of(attr, struct device_attribute, attr); + struct tgu_attribute *tgu_attr = + container_of(dev_attr, struct tgu_attribute, attr); + + if (tgu_attr->step_index < drvdata->max_step) { + ret = (tgu_attr->reg_num < drvdata->max_reg) ? + attr->mode : + 0; + } + return ret; +} + static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) { + int i, j, k; + CS_UNLOCK(drvdata->base); + + for (i = 0; i < drvdata->max_step; i++) { + for (j = 0; j < MAX_PRIORITY; j++) { + for (k = 0; k < drvdata->max_reg; k++) { + tgu_writel(drvdata, + drvdata->value_table->priority + [calculate_array_location( + drvdata, i, j, k)], + PRIORITY_REG_STEP(i, j, k)); + } + } + } + /* Enable TGU to program the triggers */ tgu_writel(drvdata, 1, TGU_CONTROL); CS_LOCK(drvdata->base); } +static void tgu_set_reg_number(struct tgu_drvdata *drvdata) +{ + int num_sense_input; + int num_reg; + u32 devid; + + devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID); + + num_sense_input = TGU_DEVID_SENSE_INPUT(devid); + if (((num_sense_input * NUMBER_BITS_EACH_SIGNAL) % LENGTH_REGISTER) == 0) + num_reg = (num_sense_input * NUMBER_BITS_EACH_SIGNAL) / LENGTH_REGISTER; + else + num_reg = ((num_sense_input * NUMBER_BITS_EACH_SIGNAL) / LENGTH_REGISTER) + 1; + drvdata->max_reg = num_reg; +} + +static void tgu_set_steps(struct tgu_drvdata *drvdata) +{ + int num_steps; + u32 devid; + + devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID); + + num_steps = TGU_DEVID_STEPS(devid); + + drvdata->max_step = num_steps; +} + static int tgu_enable(struct coresight_device *csdev, enum cs_mode mode, void *data) { @@ -125,6 +239,38 @@ static const struct attribute_group tgu_common_grp = { static const struct attribute_group *tgu_attr_groups[] = { &tgu_common_grp, + PRIORITY_ATTRIBUTE_GROUP_INIT(0, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(0, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(0, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(0, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(1, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(1, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(1, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(1, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(2, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(2, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(2, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(2, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(3, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(3, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(3, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(3, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(4, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(4, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(4, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(4, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(5, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(5, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(5, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(5, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(6, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(6, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(6, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(6, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(7, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(7, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(7, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(7, 3), NULL, }; @@ -159,6 +305,23 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) spin_lock_init(&drvdata->spinlock); + tgu_set_reg_number(drvdata); + tgu_set_steps(drvdata); + + drvdata->value_table = + devm_kzalloc(dev, sizeof(*drvdata->value_table), GFP_KERNEL); + if (!drvdata->value_table) + return -ENOMEM; + + drvdata->value_table->priority = devm_kzalloc( + dev, + MAX_PRIORITY * drvdata->max_reg * drvdata->max_step * + sizeof(*(drvdata->value_table->priority)), + GFP_KERNEL); + + if (!drvdata->value_table->priority) + return -ENOMEM; + drvdata->enable = false; desc.type = CORESIGHT_DEV_TYPE_HELPER; desc.pdata = adev->dev.platform_data; diff --git a/drivers/hwtracing/coresight/coresight-tgu.h b/drivers/hwtracing/coresight/coresight-tgu.h index 6c849a2f78faf..f07ead5053658 100644 --- a/drivers/hwtracing/coresight/coresight-tgu.h +++ b/drivers/hwtracing/coresight/coresight-tgu.h @@ -13,6 +13,112 @@ #define tgu_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off) #define tgu_readl(drvdata, off) __raw_readl(drvdata->base + off) +#define TGU_DEVID_SENSE_INPUT(devid_val) ((int) BMVAL(devid_val, 10, 17)) +#define TGU_DEVID_STEPS(devid_val) ((int)BMVAL(devid_val, 3, 6)) +#define NUMBER_BITS_EACH_SIGNAL 4 +#define LENGTH_REGISTER 32 + +/* + * TGU configuration space Step configuration + * offset table space layout + * x-------------------------x$ x-------------x$ + * | |$ | |$ + * | | | reserve |$ + * | | | |$ + * |coresight management | |-------------|base+n*0x1D8+0x1F4$ + * | registe | |---> |prioroty[3] |$ + * | | | |-------------|base+n*0x1D8+0x194$ + * | | | |prioroty[2] |$ + * |-------------------------| | |-------------|base+n*0x1D8+0x134$ + * | | | |prioroty[1] |$ + * | step[7] | | |-------------|base+n*0x1D8+0xD4$ + * |-------------------------|->base+0x40+7*0x1D8 | |prioroty[0] |$ + * | | | |-------------|base+n*0x1D8+0x74$ + * | ... | | | condition |$ + * | | | | select |$ + * |-------------------------|->base+0x40+1*0x1D8 | |-------------|base+n*0x1D8+0x60$ + * | | | | condition |$ + * | step[0] |--------------------> | decode |$ + * |-------------------------|-> base+0x40 |-------------|base+n*0x1D8+0x50$ + * | | | |$ + * | Control and status space| |Timer/Counter|$ + * | space | | |$ + * x-------------------------x->base x-------------x base+n*0x1D8+0x40$ + * + */ +#define STEP_OFFSET 0x1D8 +#define PRIORITY_START_OFFSET 0x0074 +#define PRIORITY_OFFSET 0x60 +#define REG_OFFSET 0x4 + +/* Calculate compare step addresses */ +#define PRIORITY_REG_STEP(step, priority, reg)\ + (PRIORITY_START_OFFSET + PRIORITY_OFFSET * priority +\ + REG_OFFSET * reg + STEP_OFFSET * step) + +#define tgu_dataset_rw(name, step_index, type, reg_num) \ + (&((struct tgu_attribute[]){ { \ + __ATTR(name, 0644, tgu_dataset_show, tgu_dataset_store), \ + step_index, \ + type, \ + reg_num, \ + } })[0].attr.attr) + +#define STEP_PRIORITY(step_index, reg_num, priority) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_PRIORITY##priority, \ + reg_num) + +#define STEP_PRIORITY_LIST(step_index, priority) \ + {STEP_PRIORITY(step_index, 0, priority), \ + STEP_PRIORITY(step_index, 1, priority), \ + STEP_PRIORITY(step_index, 2, priority), \ + STEP_PRIORITY(step_index, 3, priority), \ + STEP_PRIORITY(step_index, 4, priority), \ + STEP_PRIORITY(step_index, 5, priority), \ + STEP_PRIORITY(step_index, 6, priority), \ + STEP_PRIORITY(step_index, 7, priority), \ + STEP_PRIORITY(step_index, 8, priority), \ + STEP_PRIORITY(step_index, 9, priority), \ + STEP_PRIORITY(step_index, 10, priority), \ + STEP_PRIORITY(step_index, 11, priority), \ + STEP_PRIORITY(step_index, 12, priority), \ + STEP_PRIORITY(step_index, 13, priority), \ + STEP_PRIORITY(step_index, 14, priority), \ + STEP_PRIORITY(step_index, 15, priority), \ + STEP_PRIORITY(step_index, 16, priority), \ + STEP_PRIORITY(step_index, 17, priority), \ + NULL \ + } + +#define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_priority" #priority \ + }) + +enum operation_index { + TGU_PRIORITY0, + TGU_PRIORITY1, + TGU_PRIORITY2, + TGU_PRIORITY3 + +}; + +/* Maximum priority that TGU supports */ +#define MAX_PRIORITY 4 + +struct tgu_attribute { + struct device_attribute attr; + u32 step_index; + enum operation_index operation_index; + u32 reg_num; +}; + +struct value_table { + unsigned int *priority; +}; + /** * struct tgu_drvdata - Data structure for a TGU (Trigger Generator Unit) * @base: Memory-mapped base address of the TGU device @@ -20,6 +126,9 @@ * @csdev: Pointer to the associated coresight device * @spinlock: Spinlock for handling concurrent access * @enable: Flag indicating whether the TGU device is enabled + * @value_table: Store given value based on relevant parameters. + * @max_reg: Maximum number of registers + * @max_step: Maximum step size * * This structure defines the data associated with a TGU device, * including its base address, device pointers, clock, spinlock for @@ -32,6 +141,9 @@ struct tgu_drvdata { struct coresight_device *csdev; spinlock_t spinlock; bool enable; + struct value_table *value_table; + int max_reg; + int max_step; }; #endif From b970f3fe4855708e8899b78b9060bac6e9e10402 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Wed, 23 Apr 2025 14:34:21 +0800 Subject: [PATCH 090/113] FROMLIST: coresight-tgu: Add TGU decode support Decoding is when all the potential pieces for creating a trigger are brought together for a given step. Example - there may be a counter keeping track of some occurrences and a priority-group that is being used to detect a pattern on the sense inputs. These 2 inputs to condition_decode must be programmed, for a given step, to establish the condition for the trigger, or movement to another steps. Link: https://lore.kernel.org/all/20250423-tgu_patch-v5-4-3b52c105cc63@quicinc.com/ Signed-off-by: Songwei Chai --- .../testing/sysfs-bus-coresight-devices-tgu | 7 + drivers/hwtracing/coresight/coresight-tgu.c | 186 +++++++++++++++--- drivers/hwtracing/coresight/coresight-tgu.h | 29 ++- 3 files changed, 196 insertions(+), 26 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu index 5843409768838..50967ca039d88 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu @@ -14,3 +14,10 @@ KernelVersion 6.15 Contact: Jinlong Mao (QUIC) , Sam Chai (QUIC) Description: (RW) Set/Get the sensed signal with specific step and priority for TGU. + +What: /sys/bus/coresight/devices//step[0:7]_condition_decode/reg[0:3] +Date: February 2025 +KernelVersion 6.15 +Contact: Jinlong Mao (QUIC) , Sam Chai (QUIC) +Description: + (RW) Set/Get the decode mode with specific step for TGU. \ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tgu.c b/drivers/hwtracing/coresight/coresight-tgu.c index 6dbfd4c604b1f..8dbe8ab30174d 100644 --- a/drivers/hwtracing/coresight/coresight-tgu.c +++ b/drivers/hwtracing/coresight/coresight-tgu.c @@ -21,13 +21,35 @@ static int calculate_array_location(struct tgu_drvdata *drvdata, int step_index, int operation_index, int reg_index) { - int ret; + int ret = -EINVAL; + + switch (operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + ret = operation_index * (drvdata->max_step) * + (drvdata->max_reg) + + step_index * (drvdata->max_reg) + reg_index; + break; + case TGU_CONDITION_DECODE: + ret = step_index * (drvdata->max_condition_decode) + + reg_index; + break; + default: + break; + } + return ret; +} - ret = operation_index * (drvdata->max_step) * - (drvdata->max_reg) + - step_index * (drvdata->max_reg) + reg_index; +static int check_array_location(struct tgu_drvdata *drvdata, int step, + int ops, int reg) +{ + int result = calculate_array_location(drvdata, step, ops, reg); - return ret; + if (result == -EINVAL) + dev_err(&drvdata->csdev->dev, "%s - Fail\n", __func__); + return result; } static ssize_t tgu_dataset_show(struct device *dev, @@ -36,13 +58,33 @@ static ssize_t tgu_dataset_show(struct device *dev, struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent); struct tgu_attribute *tgu_attr = container_of(attr, struct tgu_attribute, attr); + int ret = 0; + + ret = check_array_location(drvdata, tgu_attr->step_index, + tgu_attr->operation_index, tgu_attr->reg_num); + if (ret == -EINVAL) + return ret; - return sysfs_emit(buf, "0x%x\n", - drvdata->value_table->priority[ - calculate_array_location( - drvdata, tgu_attr->step_index, - tgu_attr->operation_index, - tgu_attr->reg_num)]); + switch (tgu_attr->operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->priority[calculate_array_location( + drvdata, tgu_attr->step_index, + tgu_attr->operation_index, + tgu_attr->reg_num)]); + case TGU_CONDITION_DECODE: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->condition_decode[calculate_array_location( + drvdata, tgu_attr->step_index, + tgu_attr->operation_index, + tgu_attr->reg_num)]); + default: + break; + } + return -EINVAL; } static ssize_t tgu_dataset_store(struct device *dev, @@ -51,20 +93,44 @@ static ssize_t tgu_dataset_store(struct device *dev, size_t size) { unsigned long val; + int ret = -EINVAL; struct tgu_drvdata *tgu_drvdata = dev_get_drvdata(dev->parent); struct tgu_attribute *tgu_attr = container_of(attr, struct tgu_attribute, attr); if (kstrtoul(buf, 0, &val)) - return -EINVAL; + return ret; - guard(spinlock)(&tgu_drvdata->spinlock); - tgu_drvdata->value_table->priority[calculate_array_location( - tgu_drvdata, tgu_attr->step_index, tgu_attr->operation_index, - tgu_attr->reg_num)] = val; + ret = check_array_location(tgu_drvdata, tgu_attr->step_index, + tgu_attr->operation_index, tgu_attr->reg_num); - return size; + if (ret == -EINVAL) + return ret; + + guard(spinlock)(&tgu_drvdata->spinlock); + switch (tgu_attr->operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + tgu_drvdata->value_table->priority[calculate_array_location( + tgu_drvdata, tgu_attr->step_index, + tgu_attr->operation_index, + tgu_attr->reg_num)] = val; + ret = size; + break; + case TGU_CONDITION_DECODE: + tgu_drvdata->value_table->condition_decode[calculate_array_location( + tgu_drvdata, tgu_attr->step_index, + tgu_attr->operation_index, + tgu_attr->reg_num)] = val; + ret = size; + break; + default: + break; + } + return ret; } static umode_t tgu_node_visible(struct kobject *kobject, @@ -81,34 +147,70 @@ static umode_t tgu_node_visible(struct kobject *kobject, container_of(dev_attr, struct tgu_attribute, attr); if (tgu_attr->step_index < drvdata->max_step) { - ret = (tgu_attr->reg_num < drvdata->max_reg) ? - attr->mode : - 0; + switch (tgu_attr->operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + ret = (tgu_attr->reg_num < drvdata->max_reg) ? + attr->mode : + 0; + break; + case TGU_CONDITION_DECODE: + ret = (tgu_attr->reg_num < + drvdata->max_condition_decode) ? + attr->mode : + 0; + break; + default: + break; + } } return ret; } -static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) +static ssize_t tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) { - int i, j, k; + int i, j, k, ret; CS_UNLOCK(drvdata->base); for (i = 0; i < drvdata->max_step; i++) { for (j = 0; j < MAX_PRIORITY; j++) { for (k = 0; k < drvdata->max_reg; k++) { + + ret = check_array_location(drvdata, i, j, k); + if (ret == -EINVAL) + goto exit; + tgu_writel(drvdata, drvdata->value_table->priority [calculate_array_location( - drvdata, i, j, k)], + drvdata, i, j, k)], PRIORITY_REG_STEP(i, j, k)); } } } + for (i = 0; i < drvdata->max_step; i++) { + for (j = 0; j < drvdata->max_condition_decode; j++) { + ret = check_array_location(drvdata, i, TGU_CONDITION_DECODE, j); + if (ret == -EINVAL) + goto exit; + + tgu_writel(drvdata, + drvdata->value_table->condition_decode + [calculate_array_location( + drvdata, i, + TGU_CONDITION_DECODE, j)], + CONDITION_DECODE_STEP(i, j)); + } + } /* Enable TGU to program the triggers */ tgu_writel(drvdata, 1, TGU_CONTROL); +exit: CS_LOCK(drvdata->base); + return ret >= 0 ? 0 : ret; } static void tgu_set_reg_number(struct tgu_drvdata *drvdata) @@ -139,9 +241,21 @@ static void tgu_set_steps(struct tgu_drvdata *drvdata) drvdata->max_step = num_steps; } +static void tgu_set_conditions(struct tgu_drvdata *drvdata) +{ + int num_conditions; + u32 devid; + + devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID); + + num_conditions = TGU_DEVID_CONDITIONS(devid); + drvdata->max_condition_decode = num_conditions; +} + static int tgu_enable(struct coresight_device *csdev, enum cs_mode mode, void *data) { + int ret = 0; struct tgu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); spin_lock(&drvdata->spinlock); @@ -150,11 +264,15 @@ static int tgu_enable(struct coresight_device *csdev, enum cs_mode mode, spin_unlock(&drvdata->spinlock); return -EBUSY; } - tgu_write_all_hw_regs(drvdata); + ret = tgu_write_all_hw_regs(drvdata); + + if (ret == -EINVAL) + goto exit; drvdata->enable = true; +exit: spin_unlock(&drvdata->spinlock); - return 0; + return ret; } static int tgu_disable(struct coresight_device *csdev, void *data) @@ -271,6 +389,14 @@ static const struct attribute_group *tgu_attr_groups[] = { PRIORITY_ATTRIBUTE_GROUP_INIT(7, 1), PRIORITY_ATTRIBUTE_GROUP_INIT(7, 2), PRIORITY_ATTRIBUTE_GROUP_INIT(7, 3), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(0), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(1), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(2), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(3), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(4), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(5), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(6), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(7), NULL, }; @@ -307,6 +433,7 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) tgu_set_reg_number(drvdata); tgu_set_steps(drvdata); + tgu_set_conditions(drvdata); drvdata->value_table = devm_kzalloc(dev, sizeof(*drvdata->value_table), GFP_KERNEL); @@ -322,6 +449,15 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) if (!drvdata->value_table->priority) return -ENOMEM; + drvdata->value_table->condition_decode = devm_kzalloc( + dev, + drvdata->max_condition_decode * drvdata->max_step * + sizeof(*(drvdata->value_table->condition_decode)), + GFP_KERNEL); + + if (!drvdata->value_table->condition_decode) + return -ENOMEM; + drvdata->enable = false; desc.type = CORESIGHT_DEV_TYPE_HELPER; desc.pdata = adev->dev.platform_data; diff --git a/drivers/hwtracing/coresight/coresight-tgu.h b/drivers/hwtracing/coresight/coresight-tgu.h index f07ead5053658..691da393ffa30 100644 --- a/drivers/hwtracing/coresight/coresight-tgu.h +++ b/drivers/hwtracing/coresight/coresight-tgu.h @@ -15,6 +15,7 @@ #define TGU_DEVID_SENSE_INPUT(devid_val) ((int) BMVAL(devid_val, 10, 17)) #define TGU_DEVID_STEPS(devid_val) ((int)BMVAL(devid_val, 3, 6)) +#define TGU_DEVID_CONDITIONS(devid_val) ((int)BMVAL(devid_val, 0, 2)) #define NUMBER_BITS_EACH_SIGNAL 4 #define LENGTH_REGISTER 32 @@ -48,6 +49,7 @@ */ #define STEP_OFFSET 0x1D8 #define PRIORITY_START_OFFSET 0x0074 +#define CONDITION_DECODE_OFFSET 0x0050 #define PRIORITY_OFFSET 0x60 #define REG_OFFSET 0x4 @@ -56,6 +58,9 @@ (PRIORITY_START_OFFSET + PRIORITY_OFFSET * priority +\ REG_OFFSET * reg + STEP_OFFSET * step) +#define CONDITION_DECODE_STEP(step, decode) \ + (CONDITION_DECODE_OFFSET + REG_OFFSET * decode + STEP_OFFSET * step) + #define tgu_dataset_rw(name, step_index, type, reg_num) \ (&((struct tgu_attribute[]){ { \ __ATTR(name, 0644, tgu_dataset_show, tgu_dataset_store), \ @@ -68,6 +73,9 @@ tgu_dataset_rw(reg##reg_num, step_index, TGU_PRIORITY##priority, \ reg_num) +#define STEP_DECODE(step_index, reg_num) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_DECODE, reg_num) + #define STEP_PRIORITY_LIST(step_index, priority) \ {STEP_PRIORITY(step_index, 0, priority), \ STEP_PRIORITY(step_index, 1, priority), \ @@ -90,6 +98,14 @@ NULL \ } +#define STEP_DECODE_LIST(n) \ + {STEP_DECODE(n, 0), \ + STEP_DECODE(n, 1), \ + STEP_DECODE(n, 2), \ + STEP_DECODE(n, 3), \ + NULL \ + } + #define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\ (&(const struct attribute_group){\ .attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\ @@ -97,11 +113,19 @@ .name = "step" #step "_priority" #priority \ }) +#define CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(step)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_DECODE_LIST(step),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_condition_decode" \ + }) + enum operation_index { TGU_PRIORITY0, TGU_PRIORITY1, TGU_PRIORITY2, - TGU_PRIORITY3 + TGU_PRIORITY3, + TGU_CONDITION_DECODE }; @@ -117,6 +141,7 @@ struct tgu_attribute { struct value_table { unsigned int *priority; + unsigned int *condition_decode; }; /** @@ -129,6 +154,7 @@ struct value_table { * @value_table: Store given value based on relevant parameters. * @max_reg: Maximum number of registers * @max_step: Maximum step size + * @max_condition_decode: Maximum number of condition_decode * * This structure defines the data associated with a TGU device, * including its base address, device pointers, clock, spinlock for @@ -144,6 +170,7 @@ struct tgu_drvdata { struct value_table *value_table; int max_reg; int max_step; + int max_condition_decode; }; #endif From c75a233be8db5ee9d3b42cf89e2a466363abef29 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Wed, 23 Apr 2025 14:34:22 +0800 Subject: [PATCH 091/113] FROMLIST: coresight-tgu: add support to configure next action Add "select" node for each step to determine if another step is taken, trigger(s) are generated, counters/timers incremented/decremented, etc. Link: https://lore.kernel.org/all/20250423-tgu_patch-v5-5-3b52c105cc63@quicinc.com/ Signed-off-by: Songwei Chai --- .../testing/sysfs-bus-coresight-devices-tgu | 9 ++- drivers/hwtracing/coresight/coresight-tgu.c | 59 +++++++++++++++++++ drivers/hwtracing/coresight/coresight-tgu.h | 30 +++++++++- 3 files changed, 95 insertions(+), 3 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu index 50967ca039d88..5e82fc91f8f70 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu @@ -20,4 +20,11 @@ Date: February 2025 KernelVersion 6.15 Contact: Jinlong Mao (QUIC) , Sam Chai (QUIC) Description: - (RW) Set/Get the decode mode with specific step for TGU. \ No newline at end of file + (RW) Set/Get the decode mode with specific step for TGU. + +What: /sys/bus/coresight/devices//step[0:7]_condition_select/reg[0:3] +Date: February 2025 +KernelVersion 6.15 +Contact: Jinlong Mao (QUIC) , Sam Chai (QUIC) +Description: + (RW) Set/Get the next action with specific step for TGU. \ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tgu.c b/drivers/hwtracing/coresight/coresight-tgu.c index 8dbe8ab30174d..41f648b9e0ee5 100644 --- a/drivers/hwtracing/coresight/coresight-tgu.c +++ b/drivers/hwtracing/coresight/coresight-tgu.c @@ -36,6 +36,9 @@ static int calculate_array_location(struct tgu_drvdata *drvdata, ret = step_index * (drvdata->max_condition_decode) + reg_index; break; + case TGU_CONDITION_SELECT: + ret = step_index * (drvdata->max_condition_select) + reg_index; + break; default: break; } @@ -81,6 +84,12 @@ static ssize_t tgu_dataset_show(struct device *dev, drvdata, tgu_attr->step_index, tgu_attr->operation_index, tgu_attr->reg_num)]); + case TGU_CONDITION_SELECT: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->condition_select[calculate_array_location( + drvdata, tgu_attr->step_index, + tgu_attr->operation_index, + tgu_attr->reg_num)]); default: break; } @@ -127,6 +136,13 @@ static ssize_t tgu_dataset_store(struct device *dev, tgu_attr->reg_num)] = val; ret = size; break; + case TGU_CONDITION_SELECT: + tgu_drvdata->value_table->condition_select[calculate_array_location( + tgu_drvdata, tgu_attr->step_index, + tgu_attr->operation_index, + tgu_attr->reg_num)] = val; + ret = size; + break; default: break; } @@ -162,6 +178,16 @@ static umode_t tgu_node_visible(struct kobject *kobject, attr->mode : 0; break; + case TGU_CONDITION_SELECT: + /* 'default' register is at the end of 'select' region */ + if (tgu_attr->reg_num == + drvdata->max_condition_select - 1) + attr->name = "default"; + ret = (tgu_attr->reg_num < + drvdata->max_condition_select) ? + attr->mode : + 0; + break; default: break; } @@ -206,6 +232,20 @@ static ssize_t tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) CONDITION_DECODE_STEP(i, j)); } } + + for (i = 0; i < drvdata->max_step; i++) { + for (j = 0; j < drvdata->max_condition_select; j++) { + ret = check_array_location(drvdata, i, TGU_CONDITION_SELECT, j); + if (ret == -EINVAL) + goto exit; + + tgu_writel(drvdata, + drvdata->value_table->condition_select + [calculate_array_location(drvdata, i, + TGU_CONDITION_SELECT, j)], + CONDITION_SELECT_STEP(i, j)); + } + } /* Enable TGU to program the triggers */ tgu_writel(drvdata, 1, TGU_CONTROL); exit: @@ -250,6 +290,8 @@ static void tgu_set_conditions(struct tgu_drvdata *drvdata) num_conditions = TGU_DEVID_CONDITIONS(devid); drvdata->max_condition_decode = num_conditions; + /* select region has an additional 'default' register */ + drvdata->max_condition_select = num_conditions + 1; } static int tgu_enable(struct coresight_device *csdev, enum cs_mode mode, @@ -397,6 +439,14 @@ static const struct attribute_group *tgu_attr_groups[] = { CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(5), CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(6), CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(7), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(0), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(1), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(2), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(3), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(4), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(5), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(6), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(7), NULL, }; @@ -458,6 +508,15 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) if (!drvdata->value_table->condition_decode) return -ENOMEM; + drvdata->value_table->condition_select = devm_kzalloc( + dev, + drvdata->max_condition_select * drvdata->max_step * + sizeof(*(drvdata->value_table->condition_select)), + GFP_KERNEL); + + if (!drvdata->value_table->condition_select) + return -ENOMEM; + drvdata->enable = false; desc.type = CORESIGHT_DEV_TYPE_HELPER; desc.pdata = adev->dev.platform_data; diff --git a/drivers/hwtracing/coresight/coresight-tgu.h b/drivers/hwtracing/coresight/coresight-tgu.h index 691da393ffa30..214ee67d19474 100644 --- a/drivers/hwtracing/coresight/coresight-tgu.h +++ b/drivers/hwtracing/coresight/coresight-tgu.h @@ -50,6 +50,7 @@ #define STEP_OFFSET 0x1D8 #define PRIORITY_START_OFFSET 0x0074 #define CONDITION_DECODE_OFFSET 0x0050 +#define CONDITION_SELECT_OFFSET 0x0060 #define PRIORITY_OFFSET 0x60 #define REG_OFFSET 0x4 @@ -61,6 +62,9 @@ #define CONDITION_DECODE_STEP(step, decode) \ (CONDITION_DECODE_OFFSET + REG_OFFSET * decode + STEP_OFFSET * step) +#define CONDITION_SELECT_STEP(step, select) \ + (CONDITION_SELECT_OFFSET + REG_OFFSET * select + STEP_OFFSET * step) + #define tgu_dataset_rw(name, step_index, type, reg_num) \ (&((struct tgu_attribute[]){ { \ __ATTR(name, 0644, tgu_dataset_show, tgu_dataset_store), \ @@ -76,6 +80,9 @@ #define STEP_DECODE(step_index, reg_num) \ tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_DECODE, reg_num) +#define STEP_SELECT(step_index, reg_num) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_SELECT, reg_num) + #define STEP_PRIORITY_LIST(step_index, priority) \ {STEP_PRIORITY(step_index, 0, priority), \ STEP_PRIORITY(step_index, 1, priority), \ @@ -106,6 +113,15 @@ NULL \ } +#define STEP_SELECT_LIST(n) \ + {STEP_SELECT(n, 0), \ + STEP_SELECT(n, 1), \ + STEP_SELECT(n, 2), \ + STEP_SELECT(n, 3), \ + STEP_SELECT(n, 4), \ + NULL \ + } + #define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\ (&(const struct attribute_group){\ .attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\ @@ -120,13 +136,20 @@ .name = "step" #step "_condition_decode" \ }) +#define CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(step)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_SELECT_LIST(step),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_condition_select" \ + }) + enum operation_index { TGU_PRIORITY0, TGU_PRIORITY1, TGU_PRIORITY2, TGU_PRIORITY3, - TGU_CONDITION_DECODE - + TGU_CONDITION_DECODE, + TGU_CONDITION_SELECT }; /* Maximum priority that TGU supports */ @@ -142,6 +165,7 @@ struct tgu_attribute { struct value_table { unsigned int *priority; unsigned int *condition_decode; + unsigned int *condition_select; }; /** @@ -155,6 +179,7 @@ struct value_table { * @max_reg: Maximum number of registers * @max_step: Maximum step size * @max_condition_decode: Maximum number of condition_decode + * @max_condition_select: Maximum number of condition_select * * This structure defines the data associated with a TGU device, * including its base address, device pointers, clock, spinlock for @@ -171,6 +196,7 @@ struct tgu_drvdata { int max_reg; int max_step; int max_condition_decode; + int max_condition_select; }; #endif From a81b743effe3fedea3b7003696877697eea21eb4 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Wed, 23 Apr 2025 14:34:23 +0800 Subject: [PATCH 092/113] FROMLIST: coresight-tgu: add timer/counter functionality for TGU Add counter and timer node for each step which could be programed if they are to be utilized in trigger event/sequence. Link: https://lore.kernel.org/all/20250423-tgu_patch-v5-6-3b52c105cc63@quicinc.com/ Signed-off-by: Songwei Chai --- .../testing/sysfs-bus-coresight-devices-tgu | 16 ++- drivers/hwtracing/coresight/coresight-tgu.c | 134 ++++++++++++++++++ drivers/hwtracing/coresight/coresight-tgu.h | 57 +++++++- 3 files changed, 204 insertions(+), 3 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu index 5e82fc91f8f70..2843cecead55f 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu @@ -27,4 +27,18 @@ Date: February 2025 KernelVersion 6.15 Contact: Jinlong Mao (QUIC) , Sam Chai (QUIC) Description: - (RW) Set/Get the next action with specific step for TGU. \ No newline at end of file + (RW) Set/Get the next action with specific step for TGU. + +What: /sys/bus/coresight/devices//step[0:7]_timer/reg[0:1] +Date: February 2025 +KernelVersion 6.15 +Contact: Jinlong Mao (QUIC) , Sam Chai (QUIC) +Description: + (RW) Set/Get the timer value with specific step for TGU. + +What: /sys/bus/coresight/devices//step[0:7]_counter/reg[0:1] +Date: February 2025 +KernelVersion 6.15 +Contact: Jinlong Mao (QUIC) , Sam Chai (QUIC) +Description: + (RW) Set/Get the counter value with specific step for TGU. diff --git a/drivers/hwtracing/coresight/coresight-tgu.c b/drivers/hwtracing/coresight/coresight-tgu.c index 41f648b9e0ee5..4a58f2cb8d8ca 100644 --- a/drivers/hwtracing/coresight/coresight-tgu.c +++ b/drivers/hwtracing/coresight/coresight-tgu.c @@ -39,6 +39,12 @@ static int calculate_array_location(struct tgu_drvdata *drvdata, case TGU_CONDITION_SELECT: ret = step_index * (drvdata->max_condition_select) + reg_index; break; + case TGU_COUNTER: + ret = step_index * (drvdata->max_counter) + reg_index; + break; + case TGU_TIMER: + ret = step_index * (drvdata->max_timer) + reg_index; + break; default: break; } @@ -90,6 +96,16 @@ static ssize_t tgu_dataset_show(struct device *dev, drvdata, tgu_attr->step_index, tgu_attr->operation_index, tgu_attr->reg_num)]); + case TGU_TIMER: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->timer[calculate_array_location( + drvdata, tgu_attr->step_index, tgu_attr->operation_index, + tgu_attr->reg_num)]); + case TGU_COUNTER: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->counter[calculate_array_location( + drvdata, tgu_attr->step_index, tgu_attr->operation_index, + tgu_attr->reg_num)]); default: break; } @@ -143,6 +159,18 @@ static ssize_t tgu_dataset_store(struct device *dev, tgu_attr->reg_num)] = val; ret = size; break; + case TGU_TIMER: + tgu_drvdata->value_table->timer[calculate_array_location( + tgu_drvdata, tgu_attr->step_index, tgu_attr->operation_index, + tgu_attr->reg_num)] = val; + ret = size; + break; + case TGU_COUNTER: + tgu_drvdata->value_table->counter[calculate_array_location( + tgu_drvdata, tgu_attr->step_index, tgu_attr->operation_index, + tgu_attr->reg_num)] = val; + ret = size; + break; default: break; } @@ -188,6 +216,24 @@ static umode_t tgu_node_visible(struct kobject *kobject, attr->mode : 0; break; + case TGU_COUNTER: + if (drvdata->max_counter == 0) + ret = SYSFS_GROUP_INVISIBLE; + else + ret = (tgu_attr->reg_num < + drvdata->max_counter) ? + attr->mode : + 0; + break; + case TGU_TIMER: + if (drvdata->max_timer == 0) + ret = SYSFS_GROUP_INVISIBLE; + else + ret = (tgu_attr->reg_num < + drvdata->max_timer) ? + attr->mode : + 0; + break; default: break; } @@ -246,6 +292,34 @@ static ssize_t tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) CONDITION_SELECT_STEP(i, j)); } } + + for (i = 0; i < drvdata->max_step; i++) { + for (j = 0; j < drvdata->max_timer; j++) { + ret = check_array_location(drvdata, i, TGU_TIMER, j); + if (ret == -EINVAL) + goto exit; + + tgu_writel(drvdata, + drvdata->value_table->timer + [calculate_array_location(drvdata, i, + TGU_TIMER, j)], + TIMER_COMPARE_STEP(i, j)); + } + } + + for (i = 0; i < drvdata->max_step; i++) { + for (j = 0; j < drvdata->max_counter; j++) { + ret = check_array_location(drvdata, i, TGU_COUNTER, j); + if (ret == -EINVAL) + goto exit; + + tgu_writel(drvdata, + drvdata->value_table->counter + [calculate_array_location(drvdata, i, + TGU_COUNTER, j)], + COUNTER_COMPARE_STEP(i, j)); + } + } /* Enable TGU to program the triggers */ tgu_writel(drvdata, 1, TGU_CONTROL); exit: @@ -294,6 +368,31 @@ static void tgu_set_conditions(struct tgu_drvdata *drvdata) drvdata->max_condition_select = num_conditions + 1; } +static void tgu_set_timer_counter(struct tgu_drvdata *drvdata) +{ + int num_timers, num_counters; + u32 devid2; + + devid2 = readl_relaxed(drvdata->base + CORESIGHT_DEVID2); + + if (TGU_DEVID2_TIMER0(devid2) && TGU_DEVID2_TIMER1(devid2)) + num_timers = 2; + else if (TGU_DEVID2_TIMER0(devid2) || TGU_DEVID2_TIMER1(devid2)) + num_timers = 1; + else + num_timers = 0; + + if (TGU_DEVID2_COUNTER0(devid2) && TGU_DEVID2_COUNTER1(devid2)) + num_counters = 2; + else if (TGU_DEVID2_COUNTER0(devid2) || TGU_DEVID2_COUNTER1(devid2)) + num_counters = 1; + else + num_counters = 0; + + drvdata->max_timer = num_timers; + drvdata->max_counter = num_counters; +} + static int tgu_enable(struct coresight_device *csdev, enum cs_mode mode, void *data) { @@ -447,6 +546,22 @@ static const struct attribute_group *tgu_attr_groups[] = { CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(5), CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(6), CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(7), + TIMER_ATTRIBUTE_GROUP_INIT(0), + TIMER_ATTRIBUTE_GROUP_INIT(1), + TIMER_ATTRIBUTE_GROUP_INIT(2), + TIMER_ATTRIBUTE_GROUP_INIT(3), + TIMER_ATTRIBUTE_GROUP_INIT(4), + TIMER_ATTRIBUTE_GROUP_INIT(5), + TIMER_ATTRIBUTE_GROUP_INIT(6), + TIMER_ATTRIBUTE_GROUP_INIT(7), + COUNTER_ATTRIBUTE_GROUP_INIT(0), + COUNTER_ATTRIBUTE_GROUP_INIT(1), + COUNTER_ATTRIBUTE_GROUP_INIT(2), + COUNTER_ATTRIBUTE_GROUP_INIT(3), + COUNTER_ATTRIBUTE_GROUP_INIT(4), + COUNTER_ATTRIBUTE_GROUP_INIT(5), + COUNTER_ATTRIBUTE_GROUP_INIT(6), + COUNTER_ATTRIBUTE_GROUP_INIT(7), NULL, }; @@ -484,6 +599,7 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) tgu_set_reg_number(drvdata); tgu_set_steps(drvdata); tgu_set_conditions(drvdata); + tgu_set_timer_counter(drvdata); drvdata->value_table = devm_kzalloc(dev, sizeof(*drvdata->value_table), GFP_KERNEL); @@ -517,6 +633,24 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) if (!drvdata->value_table->condition_select) return -ENOMEM; + drvdata->value_table->timer = devm_kzalloc( + dev, + drvdata->max_step * drvdata->max_timer * + sizeof(*(drvdata->value_table->timer)), + GFP_KERNEL); + + if (!drvdata->value_table->timer) + return -ENOMEM; + + drvdata->value_table->counter = devm_kzalloc( + dev, + drvdata->max_step * drvdata->max_counter * + sizeof(*(drvdata->value_table->counter)), + GFP_KERNEL); + + if (!drvdata->value_table->counter) + return -ENOMEM; + drvdata->enable = false; desc.type = CORESIGHT_DEV_TYPE_HELPER; desc.pdata = adev->dev.platform_data; diff --git a/drivers/hwtracing/coresight/coresight-tgu.h b/drivers/hwtracing/coresight/coresight-tgu.h index 214ee67d19474..be9c87ec7e3ce 100644 --- a/drivers/hwtracing/coresight/coresight-tgu.h +++ b/drivers/hwtracing/coresight/coresight-tgu.h @@ -8,7 +8,7 @@ /* Register addresses */ #define TGU_CONTROL 0x0000 - +#define CORESIGHT_DEVID2 0xfc0 /* Register read/write */ #define tgu_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off) #define tgu_readl(drvdata, off) __raw_readl(drvdata->base + off) @@ -16,6 +16,11 @@ #define TGU_DEVID_SENSE_INPUT(devid_val) ((int) BMVAL(devid_val, 10, 17)) #define TGU_DEVID_STEPS(devid_val) ((int)BMVAL(devid_val, 3, 6)) #define TGU_DEVID_CONDITIONS(devid_val) ((int)BMVAL(devid_val, 0, 2)) +#define TGU_DEVID2_TIMER0(devid_val) ((int)BMVAL(devid_val, 18, 23)) +#define TGU_DEVID2_TIMER1(devid_val) ((int)BMVAL(devid_val, 13, 17)) +#define TGU_DEVID2_COUNTER0(devid_val) ((int)BMVAL(devid_val, 6, 11)) +#define TGU_DEVID2_COUNTER1(devid_val) ((int)BMVAL(devid_val, 0, 5)) + #define NUMBER_BITS_EACH_SIGNAL 4 #define LENGTH_REGISTER 32 @@ -51,6 +56,8 @@ #define PRIORITY_START_OFFSET 0x0074 #define CONDITION_DECODE_OFFSET 0x0050 #define CONDITION_SELECT_OFFSET 0x0060 +#define TIMER_START_OFFSET 0x0040 +#define COUNTER_START_OFFSET 0x0048 #define PRIORITY_OFFSET 0x60 #define REG_OFFSET 0x4 @@ -62,6 +69,12 @@ #define CONDITION_DECODE_STEP(step, decode) \ (CONDITION_DECODE_OFFSET + REG_OFFSET * decode + STEP_OFFSET * step) +#define TIMER_COMPARE_STEP(step, timer) \ + (TIMER_START_OFFSET + REG_OFFSET * timer + STEP_OFFSET * step) + +#define COUNTER_COMPARE_STEP(step, counter) \ + (COUNTER_START_OFFSET + REG_OFFSET * counter + STEP_OFFSET * step) + #define CONDITION_SELECT_STEP(step, select) \ (CONDITION_SELECT_OFFSET + REG_OFFSET * select + STEP_OFFSET * step) @@ -83,6 +96,12 @@ #define STEP_SELECT(step_index, reg_num) \ tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_SELECT, reg_num) +#define STEP_TIMER(step_index, reg_num) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_TIMER, reg_num) + +#define STEP_COUNTER(step_index, reg_num) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_COUNTER, reg_num) + #define STEP_PRIORITY_LIST(step_index, priority) \ {STEP_PRIORITY(step_index, 0, priority), \ STEP_PRIORITY(step_index, 1, priority), \ @@ -122,6 +141,18 @@ NULL \ } +#define STEP_TIMER_LIST(n) \ + {STEP_TIMER(n, 0), \ + STEP_TIMER(n, 1), \ + NULL \ + } + +#define STEP_COUNTER_LIST(n) \ + {STEP_COUNTER(n, 0), \ + STEP_COUNTER(n, 1), \ + NULL \ + } + #define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\ (&(const struct attribute_group){\ .attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\ @@ -143,13 +174,29 @@ .name = "step" #step "_condition_select" \ }) +#define TIMER_ATTRIBUTE_GROUP_INIT(step)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_TIMER_LIST(step),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_timer" \ + }) + +#define COUNTER_ATTRIBUTE_GROUP_INIT(step)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_COUNTER_LIST(step),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_counter" \ + }) + enum operation_index { TGU_PRIORITY0, TGU_PRIORITY1, TGU_PRIORITY2, TGU_PRIORITY3, TGU_CONDITION_DECODE, - TGU_CONDITION_SELECT + TGU_CONDITION_SELECT, + TGU_TIMER, + TGU_COUNTER }; /* Maximum priority that TGU supports */ @@ -166,6 +213,8 @@ struct value_table { unsigned int *priority; unsigned int *condition_decode; unsigned int *condition_select; + unsigned int *timer; + unsigned int *counter; }; /** @@ -180,6 +229,8 @@ struct value_table { * @max_step: Maximum step size * @max_condition_decode: Maximum number of condition_decode * @max_condition_select: Maximum number of condition_select + * @max_timer: Maximum number of timers + * @max_counter: Maximum number of counters * * This structure defines the data associated with a TGU device, * including its base address, device pointers, clock, spinlock for @@ -197,6 +248,8 @@ struct tgu_drvdata { int max_step; int max_condition_decode; int max_condition_select; + int max_timer; + int max_counter; }; #endif From 4fea1a93f8a8c3d12b2ac693c445a1175b65a64a Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Wed, 23 Apr 2025 14:34:24 +0800 Subject: [PATCH 093/113] FROMLIST: coresight-tgu: add reset node to initialize Add reset node to initialize the value of priority/condition_decode/condition_select/timer/counter nodes Link: https://lore.kernel.org/all/20250423-tgu_patch-v5-7-3b52c105cc63@quicinc.com/ Signed-off-by: Songwei Chai --- .../testing/sysfs-bus-coresight-devices-tgu | 7 ++ drivers/hwtracing/coresight/coresight-tgu.c | 75 +++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu index 2843cecead55f..117e648d28535 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu @@ -42,3 +42,10 @@ KernelVersion 6.15 Contact: Jinlong Mao (QUIC) , Sam Chai (QUIC) Description: (RW) Set/Get the counter value with specific step for TGU. + +What: /sys/bus/coresight/devices//reset_tgu +Date: February 2025 +KernelVersion 6.15 +Contact: Jinlong Mao (QUIC) , Sam Chai (QUIC) +Description: + (Write) Write 1 to reset the dataset for TGU. diff --git a/drivers/hwtracing/coresight/coresight-tgu.c b/drivers/hwtracing/coresight/coresight-tgu.c index 4a58f2cb8d8ca..b44c876e7cc7e 100644 --- a/drivers/hwtracing/coresight/coresight-tgu.c +++ b/drivers/hwtracing/coresight/coresight-tgu.c @@ -477,6 +477,80 @@ static ssize_t enable_tgu_store(struct device *dev, } static DEVICE_ATTR_RW(enable_tgu); +/* reset_tgu_store - Reset Trace and Gating Unit (TGU) configuration. */ +static ssize_t reset_tgu_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + unsigned long value; + struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent); + int i, j, ret; + + if (kstrtoul(buf, 0, &value) || value == 0) + return -EINVAL; + + if (!drvdata->enable) { + ret = pm_runtime_get_sync(drvdata->dev); + if (ret < 0) { + pm_runtime_put(drvdata->dev); + return ret; + } + } + + spin_lock(&drvdata->spinlock); + CS_UNLOCK(drvdata->base); + + tgu_writel(drvdata, 0, TGU_CONTROL); + + if (drvdata->value_table->priority) + memset(drvdata->value_table->priority, 0, + MAX_PRIORITY * drvdata->max_step * + drvdata->max_reg * sizeof(unsigned int)); + + if (drvdata->value_table->condition_decode) + memset(drvdata->value_table->condition_decode, 0, + drvdata->max_condition_decode * drvdata->max_step * + sizeof(unsigned int)); + + /* Initialize all condition registers to NOT(value=0x1000000) */ + for (i = 0; i < drvdata->max_step; i++) { + for (j = 0; j < drvdata->max_condition_decode; j++) { + drvdata->value_table + ->condition_decode[calculate_array_location( + drvdata, i, TGU_CONDITION_DECODE, j)] = + 0x1000000; + } + } + + if (drvdata->value_table->condition_select) + memset(drvdata->value_table->condition_select, 0, + drvdata->max_condition_select * drvdata->max_step * + sizeof(unsigned int)); + + if (drvdata->value_table->timer) + memset(drvdata->value_table->timer, 0, + (drvdata->max_step) * + (drvdata->max_timer) * + sizeof(unsigned int)); + + if (drvdata->value_table->counter) + memset(drvdata->value_table->counter, 0, + (drvdata->max_step) * + (drvdata->max_counter) * + sizeof(unsigned int)); + + dev_dbg(dev, "Coresight-TGU reset complete\n"); + + CS_LOCK(drvdata->base); + + drvdata->enable = false; + spin_unlock(&drvdata->spinlock); + pm_runtime_put(drvdata->dev); + + return size; +} +static DEVICE_ATTR_WO(reset_tgu); + static const struct coresight_ops_helper tgu_helper_ops = { .enable = tgu_enable, .disable = tgu_disable, @@ -488,6 +562,7 @@ static const struct coresight_ops tgu_ops = { static struct attribute *tgu_common_attrs[] = { &dev_attr_enable_tgu.attr, + &dev_attr_reset_tgu.attr, NULL, }; From 6be6a1eb7a53d93b8d7d12a29ec6aca0f9bf6753 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 12 Apr 2025 07:19:58 +0530 Subject: [PATCH 094/113] FROMLIST: arm64: defconfig: Enable TC9563 PWRCTL driver Enable TC9563 PCIe switch pwrctl driver by default. This is needed to power the PCIe switch which is present in Qualcomm RB3gen2 platform. Without this the switch will not powered up and we can't use the endpoints connected to the switch. Link: https://lore.kernel.org/lkml/20250412-qps615_v4_1-v5-0-5b6a06132fec@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 897fc686e6a91..e068b3beee793 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -245,6 +245,7 @@ CONFIG_PCIE_LAYERSCAPE_GEN4=y CONFIG_PCI_ENDPOINT=y CONFIG_PCI_ENDPOINT_CONFIGFS=y CONFIG_PCI_EPF_TEST=m +CONFIG_PCI_PWRCTRL_TC9563=m CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_FW_LOADER_USER_HELPER=y From 304deb2772fe44d886968f85ef704ef230bfd1e5 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 12 Apr 2025 07:19:51 +0530 Subject: [PATCH 095/113] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Add TC9563 PCIe switch node Add a node for the TC9563 PCIe switch, which has three downstream ports. Two embedded Ethernet devices are present on one of the downstream ports. As all these ports are present in the node represent the downstream ports and embedded endpoints. Power to the TC9563 is supplied through two LDO regulators, controlled by two GPIOs, which are added as fixed regulators. Configure the TC9563 through I2C. Link: https://lore.kernel.org/lkml/20250412-qps615_v4_1-v5-0-5b6a06132fec@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru Reviewed-by: Bjorn Andersson Acked-by: Manivannan Sadhasivam Reviewed-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 129 +++++++++++++++++++ arch/arm64/boot/dts/qcom/sc7280.dtsi | 2 +- 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 0da3525979c0b..ee8c6fe968f5e 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -318,6 +318,31 @@ }; }; }; + + vdd_ntn_0p9: regulator-vdd-ntn-0p9 { + compatible = "regulator-fixed"; + regulator-name = "VDD_NTN_0P9"; + gpio = <&pm8350c_gpios 2 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <899400>; + regulator-max-microvolt = <899400>; + enable-active-high; + pinctrl-0 = <&ntn_0p9_en>; + pinctrl-names = "default"; + regulator-enable-ramp-delay = <4300>; + }; + + vdd_ntn_1p8: regulator-vdd-ntn-1p8 { + compatible = "regulator-fixed"; + regulator-name = "VDD_NTN_1P8"; + gpio = <&pm8350c_gpios 3 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + pinctrl-0 = <&ntn_1p8_en>; + pinctrl-names = "default"; + regulator-enable-ramp-delay = <10000>; + }; + }; &apps_rsc { @@ -843,6 +868,78 @@ status = "okay"; }; +&pcie1_port0 { + pcie@0,0 { + compatible = "pci1179,0623"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x2 0xff>; + + vddc-supply = <&vdd_ntn_0p9>; + vdd18-supply = <&vdd_ntn_1p8>; + vdd09-supply = <&vdd_ntn_0p9>; + vddio1-supply = <&vdd_ntn_1p8>; + vddio2-supply = <&vdd_ntn_1p8>; + vddio18-supply = <&vdd_ntn_1p8>; + + i2c-parent = <&i2c0 0x77>; + + reset-gpios = <&pm8350c_gpios 1 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&tc9563_rsex_n>; + pinctrl-names = "default"; + + pcie@1,0 { + reg = <0x20800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x3 0xff>; + }; + + pcie@2,0 { + reg = <0x21000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x4 0xff>; + }; + + pcie@3,0 { + reg = <0x21800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x5 0xff>; + + pci@0,0 { + reg = <0x50000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + + pci@0,1 { + reg = <0x50100 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + }; + }; +}; + &pm7325_gpios { kypd_vol_up_n: kypd-vol-up-n-state { pins = "gpio6"; @@ -1126,6 +1223,38 @@ }; }; +&pm8350c_gpios { + ntn_0p9_en: ntn-0p9-en-state { + pins = "gpio2"; + function = "normal"; + + bias-disable; + input-disable; + output-enable; + power-source = <0>; + }; + + ntn_1p8_en: ntn-1p8-en-state { + pins = "gpio3"; + function = "normal"; + + bias-disable; + input-disable; + output-enable; + power-source = <0>; + }; + + tc9563_rsex_n: tc9563-resx-state { + pins = "gpio1"; + function = "normal"; + + bias-disable; + input-disable; + output-enable; + power-source = <0>; + }; +}; + &tlmm { gpio-reserved-ranges = <32 2>, /* ADSP */ <48 4>; /* NFC */ diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi index 685e9cd27d8f7..5092bb6c90db3 100644 --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi @@ -2286,7 +2286,7 @@ status = "disabled"; - pcie@0 { + pcie1_port0: pcie@0 { device_type = "pci"; reg = <0x0 0x0 0x0 0x0 0x0>; bus-range = <0x01 0xff>; From 385de97108c404de7d80c5470c46938529af8326 Mon Sep 17 00:00:00 2001 From: "Yu Zhang(Yuriy)" Date: Fri, 4 Jul 2025 14:31:32 +0800 Subject: [PATCH 096/113] FORMLIST: arm64: dts: qcom: qcs615: add a PCIe port for WLAN Add an original PCIe port for WLAN. This port will be referenced and supplemented by specific WLAN devices. Signed-off-by: Yu Zhang(Yuriy) Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/all/20250704-615-v3-1-6c384e0470f2@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/qcs615.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs615.dtsi b/arch/arm64/boot/dts/qcom/qcs615.dtsi index dbc839363775c..ec63ed2d1869e 100644 --- a/arch/arm64/boot/dts/qcom/qcs615.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs615.dtsi @@ -1207,6 +1207,15 @@ opp-peak-kBps = <500000 1>; }; }; + + pcie_port0: pcie@0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + bus-range = <0x01 0xff>; + }; }; pcie_phy: phy@1c0e000 { From 0302dddc7f2aadd87f0477b00d1e31d8d75ee69c Mon Sep 17 00:00:00 2001 From: "Yu Zhang(Yuriy)" Date: Fri, 4 Jul 2025 15:07:05 +0800 Subject: [PATCH 097/113] FROMLIST: arm64: dts: qcom: qcs615-ride: add WiFi/BT nodes Add a node for the PMU module of the WCN6855 present on the qcs615 ride board. Assign its LDO power outputs to the existing WiFi/BT module. Signed-off-by: Yu Zhang(Yuriy) Link: https://lore.kernel.org/all/20250704-615-v3-2-6c384e0470f2@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/qcs615-ride.dts | 136 +++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride.dts b/arch/arm64/boot/dts/qcom/qcs615-ride.dts index 379c8dfcac20b..8a6bf819eb80e 100644 --- a/arch/arm64/boot/dts/qcom/qcs615-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs615-ride.dts @@ -18,6 +18,7 @@ mmc0 = &sdhc_1; mmc1 = &sdhc_2; serial0 = &uart0; + serial1 = &uart7; }; chosen { @@ -47,6 +48,86 @@ enable-active-high; regulator-always-on; }; + + vreg_conn_1p8: vreg_conn_1p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_conn_1p8"; + startup-delay-us = <4000>; + enable-active-high; + gpio = <&pm8150_gpios 1 GPIO_ACTIVE_HIGH>; + }; + + vreg_conn_pa: vreg_conn_pa { + compatible = "regulator-fixed"; + regulator-name = "vreg_conn_pa"; + startup-delay-us = <4000>; + enable-active-high; + gpio = <&pm8150_gpios 6 GPIO_ACTIVE_HIGH>; + }; + + wcn6855-pmu { + compatible = "qcom,wcn6855-pmu"; + + pinctrl-0 = <&bt_en_state>, <&wlan_en_state>; + pinctrl-names = "default"; + + bt-enable-gpios = <&tlmm 85 GPIO_ACTIVE_HIGH>; + wlan-enable-gpios = <&tlmm 98 GPIO_ACTIVE_HIGH>; + + vddio-supply = <&vreg_conn_pa>; + vddaon-supply = <&vreg_s5a>; + vddpmu-supply = <&vreg_conn_1p8>; + vddpmumx-supply = <&vreg_conn_1p8>; + vddpmucx-supply = <&vreg_conn_pa>; + vddrfa0p95-supply = <&vreg_s5a>; + vddrfa1p3-supply = <&vreg_s6a>; + vddrfa1p9-supply = <&vreg_l15a>; + vddpcie1p3-supply = <&vreg_s6a>; + vddpcie1p9-supply = <&vreg_l15a>; + + regulators { + vreg_pmu_rfa_cmn: ldo0 { + regulator-name = "vreg_pmu_rfa_cmn"; + }; + + vreg_pmu_aon_0p59: ldo1 { + regulator-name = "vreg_pmu_aon_0p59"; + }; + + vreg_pmu_wlcx_0p8: ldo2 { + regulator-name = "vreg_pmu_wlcx_0p8"; + }; + + vreg_pmu_wlmx_0p85: ldo3 { + regulator-name = "vreg_pmu_wlmx_0p85"; + }; + + vreg_pmu_btcmx_0p85: ldo4 { + regulator-name = "vreg_pmu_btcmx_0p85"; + }; + + vreg_pmu_rfa_0p8: ldo5 { + regulator-name = "vreg_pmu_rfa_0p8"; + }; + + vreg_pmu_rfa_1p2: ldo6 { + regulator-name = "vreg_pmu_rfa_1p2"; + }; + + vreg_pmu_rfa_1p7: ldo7 { + regulator-name = "vreg_pmu_rfa_1p7"; + }; + + vreg_pmu_pcie_0p9: ldo8 { + regulator-name = "vreg_pmu_pcie_0p9"; + }; + + vreg_pmu_pcie_1p8: ldo9 { + regulator-name = "vreg_pmu_pcie_1p8"; + }; + }; + }; + }; &apps_rsc { @@ -288,6 +369,25 @@ status = "okay"; }; +&pcie_port0 { + wifi@0 { + compatible = "pci17cb,1103"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + + qcom,calibration-variant = "QC_QCS615_Ride"; + + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>; + vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>; + }; +}; + &pm8150_gpios { usb2_en: usb2-en-state { pins = "gpio10"; @@ -311,6 +411,10 @@ status = "okay"; }; +&qupv3_id_1 { + status = "okay"; +}; + &remoteproc_adsp { firmware-name = "qcom/qcs615/adsp.mbn"; @@ -328,6 +432,13 @@ }; &tlmm { + bt_en_state: bt-en-state { + pins = "gpio85"; + function = "gpio"; + bias-pull-down; + output-low; + }; + pcie_default_state: pcie-default-state { clkreq-pins { pins = "gpio90"; @@ -350,6 +461,13 @@ bias-pull-up; }; }; + + wlan_en_state: wlan-en-state { + pins = "gpio98"; + function = "gpio"; + bias-pull-down; + output-low; + }; }; &sdhc_1 { @@ -441,6 +559,24 @@ status = "okay"; }; +&uart7 { + status = "okay"; + + bluetooth { + compatible = "qcom,wcn6855-bt"; + firmware-name = "QCA6698/hpnv21", "QCA6698/hpbtfw21.tlv"; + + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>; + }; +}; + &usb_1_hsphy { vdd-supply = <&vreg_l5a>; vdda-pll-supply = <&vreg_l12a>; From 6faf7f6b6c6f52f3ae190eaa47de58798c8644fc Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Wed, 13 Mar 2024 10:56:39 +0530 Subject: [PATCH 098/113] FROMLIST: i2c: i2c-qcom-geni: Parse Error correctly in i2c GSI mode I2C driver currently reports "DMA txn failed" error even though it's NACK OR BUS_PROTO OR ARB_LOST. Detect NACK error when no device ACKs on the bus instead of generic transfer failure which doesn't give any specific clue. Make Changes inside i2c driver callback handler function i2c_gpi_cb_result() to parse these errors and make sure GSI driver stores the error status during error interrupt. Co-developed-by: Viken Dadhaniya Signed-off-by: Viken Dadhaniya Signed-off-by: Mukesh Kumar Savaliya Reviewed-by: Dmitry Baryshkov --- drivers/dma/qcom/gpi.c | 12 +++++++++++- drivers/i2c/busses/i2c-qcom-geni.c | 20 ++++++++++++++++---- include/linux/dma/qcom-gpi-dma.h | 10 ++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index b1f0001cc99c7..41741b69a7b1d 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -1072,7 +1072,17 @@ static void gpi_process_xfer_compl_event(struct gchan *gchan, dev_dbg(gpii->gpi_dev->dev, "Residue %d\n", result.residue); dma_cookie_complete(&vd->tx); - dmaengine_desc_get_callback_invoke(&vd->tx, &result); + if (gchan->protocol == QCOM_GPI_I2C) { + struct dmaengine_desc_callback cb; + struct gpi_i2c_result *i2c; + + dmaengine_desc_get_callback(&vd->tx, &cb); + i2c = cb.callback_param; + i2c->status = compl_event->status; + dmaengine_desc_callback_invoke(&cb, &result); + } else { + dmaengine_desc_get_callback_invoke(&vd->tx, &result); + } gpi_free_desc: spin_lock_irqsave(&gchan->vc.lock, flags); diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 57a99cbaf4a55..517f3d58376c0 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -2,6 +2,7 @@ // Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. #include +#include #include #include #include @@ -67,6 +68,7 @@ enum geni_i2c_err_code { GENI_TIMEOUT, }; +#define I2C_DMA_TX_IRQ_MASK GENMASK(12, 5) #define DM_I2C_CB_ERR ((BIT(NACK) | BIT(BUS_PROTO) | BIT(ARB_LOST)) \ << 5) @@ -100,6 +102,7 @@ struct geni_i2c_dev { struct dma_chan *rx_c; bool gpi_mode; bool abort_done; + struct gpi_i2c_result i2c_result; }; struct geni_i2c_desc { @@ -499,9 +502,18 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, static void i2c_gpi_cb_result(void *cb, const struct dmaengine_result *result) { - struct geni_i2c_dev *gi2c = cb; - - if (result->result != DMA_TRANS_NOERROR) { + struct gpi_i2c_result *i2c_res = cb; + struct geni_i2c_dev *gi2c = container_of(i2c_res, struct geni_i2c_dev, i2c_result); + u32 status; + + status = FIELD_GET(I2C_DMA_TX_IRQ_MASK, i2c_res->status); + if (status == BIT(NACK)) { + geni_i2c_err(gi2c, NACK); + } else if (status == BIT(BUS_PROTO)) { + geni_i2c_err(gi2c, BUS_PROTO); + } else if (status == BIT(ARB_LOST)) { + geni_i2c_err(gi2c, ARB_LOST); + } else if (result->result != DMA_TRANS_NOERROR) { dev_err(gi2c->se.dev, "DMA txn failed:%d\n", result->result); gi2c->err = -EIO; } else if (result->residue) { @@ -583,7 +595,7 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, } desc->callback_result = i2c_gpi_cb_result; - desc->callback_param = gi2c; + desc->callback_param = &gi2c->i2c_result; dmaengine_submit(desc); *buf = dma_buf; diff --git a/include/linux/dma/qcom-gpi-dma.h b/include/linux/dma/qcom-gpi-dma.h index 6680dd1a43c68..f585c6a35e51c 100644 --- a/include/linux/dma/qcom-gpi-dma.h +++ b/include/linux/dma/qcom-gpi-dma.h @@ -80,4 +80,14 @@ struct gpi_i2c_config { bool multi_msg; }; +/** + * struct gpi_i2c_result - i2c transfer status result in GSI mode + * + * @status: store txfer status value as part of callback + * + */ +struct gpi_i2c_result { + u32 status; +}; + #endif /* QCOM_GPI_DMA_H */ From affa0c7a3883184a21bf14ec268abfc9f656eb13 Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Tue, 8 Jul 2025 15:19:06 +0800 Subject: [PATCH 099/113] FROMLIST: net: bluetooth: add callback to exe l2cap when read_security uncompleted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the DUT receives a remote L2CAP Connection Request during the Read Encryption Key Size procedure, if it fails to complete reading the Encryption Key Size while processing the request, it will respond with a Connection Response – Refused (security block), resulting in the disconnection of the remote device. Use HCI_CONN_ENC_KEY_READY to determine whether l2cap_connect_request is pending. When l2cap_connect occurs before the read_enc_key_size event, it will be pending because HCI_CONN_ENC_KEY_READY has not yet been set. The connection request will be processed once the read_enc_key_size event completes. Signed-off-by: Shuai Zhang --- include/net/bluetooth/hci_core.h | 3 +++ include/net/bluetooth/l2cap.h | 9 +++++++++ net/bluetooth/hci_event.c | 15 +++++++++++++++ net/bluetooth/l2cap_core.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 2b261e74e2c4c..76d1e808cf6d8 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -763,6 +763,8 @@ struct hci_conn { struct bt_codec codec; + struct l2cap_pending_connect *pending_connect; + void (*connect_cfm_cb) (struct hci_conn *conn, u8 status); void (*security_cfm_cb) (struct hci_conn *conn, u8 status); void (*disconn_cfm_cb) (struct hci_conn *conn, u8 reason); @@ -966,6 +968,7 @@ enum { HCI_CONN_CREATE_PA_SYNC, HCI_CONN_PA_SYNC, HCI_CONN_PA_SYNC_FAILED, + HCI_CONN_ENC_KEY_READY, }; static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 4bb0eaedda180..dc209c7d1ba31 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -679,6 +679,13 @@ struct l2cap_user { void (*remove) (struct l2cap_conn *conn, struct l2cap_user *user); }; +struct l2cap_pending_connect { + struct l2cap_conn *conn; + struct l2cap_cmd_hdr cmd; + u8 data[sizeof(struct l2cap_conn_req)]; + u8 rsp_code; +}; + #define L2CAP_INFO_CL_MTU_REQ_SENT 0x01 #define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04 #define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08 @@ -977,4 +984,6 @@ void l2cap_conn_put(struct l2cap_conn *conn); int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user); void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user); +void l2cap_process_pending_connect(struct l2cap_conn *conn, + struct l2cap_cmd_hdr *cmd, u8 *data, u8 rsp_code); #endif /* __L2CAP_H */ diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 66052d6aaa1d5..be3b11d1c8168 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "hci_debugfs.h" #include "hci_codec.h" @@ -766,10 +767,22 @@ static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data, /* Update the key encryption size with the connection one */ if (key_enc_size && *key_enc_size != conn->enc_key_size) *key_enc_size = conn->enc_key_size; + set_bit(HCI_CONN_ENC_KEY_READY, &conn->flags); } hci_encrypt_cfm(conn, status); + /*Defer l2cap_connect here if it's triggered before key size is read.*/ + if (conn->pending_connect) { + struct l2cap_pending_connect *pc = conn->pending_connect; + + conn->pending_connect = NULL; + + bt_dev_dbg(hdev, "Defer l2cap_connect"); + l2cap_process_pending_connect(pc->conn, &pc->cmd, pc->data, pc->rsp_code); + + kfree(pc); + } done: hci_dev_unlock(hdev); @@ -3590,6 +3603,8 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data, if (!conn) goto unlock; + clear_bit(HCI_CONN_ENC_KEY_READY, &conn->flags); + if (!ev->status) { if (ev->encrypt) { /* Encryption implies authentication */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a5bde5db58efc..0eba3ee25685b 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -3975,6 +3975,30 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, struct l2cap_chan *chan = NULL, *pchan = NULL; int result, status = L2CAP_CS_NO_INFO; + /* If encryption is requested, but the key size is not ready yet, + * we need to wait for the key size to be ready before we can + * proceed with the connection. We do this by deferring the + * connection request until the key size is ready. This is done + * by storing the connection request in the hcon->pending_connect + * field. The connection request will be retried when the key size + * is ready. + */ + if (test_bit(HCI_CONN_ENCRYPT, &conn->hcon->flags) && + !test_bit(HCI_CONN_ENC_KEY_READY, &conn->hcon->flags)) { + struct l2cap_pending_connect *pc; + + pc = kzalloc(sizeof(*pc), GFP_KERNEL); + if (!pc) + return; + pc->conn = conn; + memcpy(&pc->cmd, cmd, sizeof(*cmd)); + memcpy(pc->data, data, sizeof(struct l2cap_conn_req)); + pc->rsp_code = rsp_code; + BT_DBG("store request and retried when keysize is ready"); + conn->hcon->pending_connect = pc; + return; + } + u16 dcid = 0, scid = __le16_to_cpu(req->scid); __le16 psm = req->psm; @@ -4098,6 +4122,12 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, l2cap_chan_put(pchan); } +void l2cap_process_pending_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, + u8 *data, u8 rsp_code) +{ + l2cap_connect(conn, cmd, data, rsp_code); +} + static int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) { From 7692b77d5df75f98c38e08e17032ede9f8c29da7 Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Tue, 8 Jul 2025 14:55:00 +0800 Subject: [PATCH 100/113] FROMLIST: driver: bluetooth: hci_qca: fix ssr fail when BT_EN is consistently pulled up by hardware If BT_EN is consistently pulled up by hardware, the QCA_SSR_TRIGGERED and QCA_IBS_DISABLED bits cannot be cleared by qca_setup during SSR. This leads to a failure to send commands due to the error state. To address this, clear QCA_SSR_TRIGGERED and QCA_IBS_DISABLED bits after the coredump collection is complete. Also, add a delay to wait for controller to complete SSR. Signed-off-by: Shuai Zhang --- drivers/bluetooth/hci_qca.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 5fe5879881f59..8ed56f09fba13 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1653,6 +1653,23 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code) } clear_bit(QCA_HW_ERROR_EVENT, &qca->flags); + + /* + * If the SoC always enables the bt_en pin via hardware and the driver + * cannot control the bt_en pin of the SoC chip, then during SSR, + * the QCA_SSR_TRIGGERED and QCA_IBS_DISABLED bits cannot be cleared. + * This leads to a reset command timeout failure. + * + * To address this, clear QCA_SSR_TRIGGERED and QCA_IBS_DISABLED bits + * after the coredump collection is complete. + * Also, add msleep delay to wait for controller to complete SSR. + */ + if (!test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks)) { + clear_bit(QCA_SSR_TRIGGERED, &qca->flags); + clear_bit(QCA_IBS_DISABLED, &qca->flags); + qca->tx_ibs_state = HCI_IBS_TX_AWAKE; + msleep(50); + } } static void qca_reset(struct hci_dev *hdev) From 27ab39b196ea0d814a0178be9070517f8252b956 Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Tue, 8 Jul 2025 14:59:40 +0800 Subject: [PATCH 101/113] FROMLIST: driver: bluetooth: hci_qca: Multiple triggers of SSR only generate one coredump file Multiple triggers of SSR only first generate coredump file, duo to memcoredump_flag no clear. add clear coredump flag when ssr completed. Signed-off-by: Shuai Zhang --- drivers/bluetooth/hci_qca.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 8ed56f09fba13..d47b904e1231d 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1668,6 +1668,7 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code) clear_bit(QCA_SSR_TRIGGERED, &qca->flags); clear_bit(QCA_IBS_DISABLED, &qca->flags); qca->tx_ibs_state = HCI_IBS_TX_AWAKE; + qca->memdump_state = QCA_MEMDUMP_IDLE; msleep(50); } } From 73b0b7d84bd468e0f5ad5c492e69dd848a1f9a57 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Mon, 21 Apr 2025 20:16:56 +0530 Subject: [PATCH 102/113] FROMGIT: arm64: dts: qcom: sa8775p: add support for video node Video node enables video on Qualcomm SA8775P platform. Link: https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git/commit/?h=for-next&id=7bc95052c64f45c24affbb7636489dc9a1c2a982 Reviewed-by: Bryan O'Donoghue Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Vikash Garodia Signed-off-by: Dikshita Agarwal --- arch/arm64/boot/dts/qcom/sa8775p.dtsi | 71 +++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi index 889652303de51..80699f77454e5 100644 --- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -4260,6 +4261,76 @@ interrupts = ; }; + iris: video-codec@aa00000 { + compatible = "qcom,sa8775p-iris", "qcom,sm8550-iris"; + + reg = <0x0 0x0aa00000 0x0 0xf0000>; + interrupts = ; + + power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, + <&videocc VIDEO_CC_MVS0_GDSC>, + <&rpmhpd SA8775P_MX>, + <&rpmhpd SA8775P_MMCX>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx"; + operating-points-v2 = <&iris_opp_table>; + + clocks = <&gcc GCC_VIDEO_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>; + clock-names = "iface", + "core", + "vcodec0_core"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_VENUS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_VIDEO_P0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + memory-region = <&pil_video_mem>; + + resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; + reset-names = "bus"; + + iommus = <&apps_smmu 0x0880 0x0400>, + <&apps_smmu 0x0887 0x0400>; + dma-coherent; + + status = "disabled"; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-366000000 { + opp-hz = /bits/ 64 <366000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_nom>; + }; + + opp-533000000 { + opp-hz = /bits/ 64 <533000000>; + required-opps = <&rpmhpd_opp_turbo>, + <&rpmhpd_opp_turbo>; + }; + + opp-560000000 { + opp-hz = /bits/ 64 <560000000>; + required-opps = <&rpmhpd_opp_turbo_l1>, + <&rpmhpd_opp_turbo_l1>; + }; + }; + }; + videocc: clock-controller@abf0000 { compatible = "qcom,sa8775p-videocc"; reg = <0x0 0x0abf0000 0x0 0x10000>; From 8c4261ae92a4082bff7599af0ab487be01dbf022 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Mon, 21 Apr 2025 20:16:57 +0530 Subject: [PATCH 103/113] FROMGIT: arm64: dts: qcom: sa8775p-ride: enable video Enable video nodes on the sa8775p-ride board and point to the appropriate firmware files. Link: https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git/commit/?h=for-next&id=d33ad6600453fbcf6a9275864ad120079bd540da Reviewed-by: Dmitry Baryshkov Signed-off-by: Vikash Garodia Signed-off-by: Dikshita Agarwal --- arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi index aea13e45a1e23..0d0eb2f150797 100644 --- a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi @@ -516,6 +516,12 @@ status = "okay"; }; +&iris { + firmware-name = "qcom/vpu/vpu30_p4_s6.mbn"; + + status = "okay"; +}; + &mdss0 { status = "okay"; }; From cbd343c58f93e90e4d9d0eef5ad626720af37533 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Wed, 9 Jul 2025 15:11:57 +0800 Subject: [PATCH 104/113] FROMLIST: arm64: dts: qcom: qcs8300: add display dt nodes for MDSS, DPU, DisplayPort and eDP PHY Add devicetree changes to enable MDSS display-subsystem, display-controller(DPU), DisplayPort controller and eDP PHY for Qualcomm QCS8300 platform. Link:https://lore.kernel.org/all/20241226-dts_qcs8300-v2-1-ec8d4fb65cba@quicinc.com/ Signed-off-by: Yongxing Mou --- arch/arm64/boot/dts/qcom/qcs8300.dtsi | 204 +++++++++++++++++++++++++- 1 file changed, 203 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs8300.dtsi b/arch/arm64/boot/dts/qcom/qcs8300.dtsi index 009f9658a4fa8..60cd4742de62b 100644 --- a/arch/arm64/boot/dts/qcom/qcs8300.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs8300.dtsi @@ -4237,6 +4237,206 @@ #power-domain-cells = <1>; }; + mdss: display-subsystem@ae00000 { + compatible = "qcom,qcs8300-mdss"; + reg = <0x0 0x0ae00000 0x0 0x1000>; + reg-names = "mdss"; + + interconnects = <&mmss_noc MASTER_MDP0 QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_MDP1 QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "mdp0-mem", + "mdp1-mem", + "cpu-cfg"; + + resets = <&dispcc MDSS_DISP_CC_MDSS_CORE_BCR>; + + power-domains = <&dispcc MDSS_DISP_CC_MDSS_CORE_GDSC>; + + clocks = <&dispcc MDSS_DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc MDSS_DISP_CC_MDSS_MDP_CLK>; + + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + iommus = <&apps_smmu 0x1000 0x402>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + mdss_mdp: display-controller@ae01000 { + compatible = "qcom,qcs8300-dpu", "qcom,sa8775p-dpu"; + reg = <0x0 0x0ae01000 0x0 0x8f000>, + <0x0 0x0aeb0000 0x0 0x2008>; + reg-names = "mdp", "vbif"; + + clocks = <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc MDSS_DISP_CC_MDSS_AHB_CLK>, + <&dispcc MDSS_DISP_CC_MDSS_MDP_LUT_CLK>, + <&dispcc MDSS_DISP_CC_MDSS_MDP_CLK>, + <&dispcc MDSS_DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "bus", + "iface", + "lut", + "core", + "vsync"; + + assigned-clocks = <&dispcc MDSS_DISP_CC_MDSS_VSYNC_CLK>; + assigned-clock-rates = <19200000>; + + operating-points-v2 = <&mdp_opp_table>; + power-domains = <&rpmhpd RPMHPD_MMCX>; + + interrupt-parent = <&mdss>; + interrupts = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + dpu_intf0_out: endpoint { + remote-endpoint = <&mdss_dp0_in>; + }; + }; + }; + + mdp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-375000000 { + opp-hz = /bits/ 64 <375000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-575000000 { + opp-hz = /bits/ 64 <575000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + required-opps = <&rpmhpd_opp_turbo_l1>; + }; + }; + }; + + mdss_dp0_phy: phy@aec2a00 { + compatible = "qcom,qcs8300-edp-phy", "qcom,sa8775p-edp-phy"; + + reg = <0x0 0x0aec2a00 0x0 0x19c>, + <0x0 0x0aec2200 0x0 0xec>, + <0x0 0x0aec2600 0x0 0xec>, + <0x0 0x0aec2000 0x0 0x1c8>; + + clocks = <&dispcc MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK>, + <&dispcc MDSS_DISP_CC_MDSS_AHB_CLK>; + clock-names = "aux", + "cfg_ahb"; + + power-domains = <&rpmhpd RPMHPD_MMCX>; + + #clock-cells = <1>; + #phy-cells = <0>; + + status = "disabled"; + }; + + mdss_dp0: displayport-controller@af54000 { + compatible = "qcom,qcs8300-dp", "qcom,sm8650-dp"; + + reg = <0x0 0x0af54000 0x0 0x200>, + <0x0 0x0af54200 0x0 0x200>, + <0x0 0x0af55000 0x0 0xc00>, + <0x0 0x0af56000 0x0 0x400>; + + interrupt-parent = <&mdss>; + interrupts = <12>; + + clocks = <&dispcc MDSS_DISP_CC_MDSS_AHB_CLK>, + <&dispcc MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK>, + <&dispcc MDSS_DISP_CC_MDSS_DPTX0_LINK_CLK>, + <&dispcc MDSS_DISP_CC_MDSS_DPTX0_LINK_INTF_CLK>, + <&dispcc MDSS_DISP_CC_MDSS_DPTX0_PIXEL0_CLK>; + clock-names = "core_iface", + "core_aux", + "ctrl_link", + "ctrl_link_iface", + "stream_pixel"; + assigned-clocks = <&dispcc MDSS_DISP_CC_MDSS_DPTX0_LINK_CLK_SRC>, + <&dispcc MDSS_DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC>; + assigned-clock-parents = <&mdss_dp0_phy 0>, + <&mdss_dp0_phy 1>; + phys = <&mdss_dp0_phy>; + phy-names = "dp"; + + operating-points-v2 = <&dp_opp_table>; + power-domains = <&rpmhpd RPMHPD_MMCX>; + + #sound-dai-cells = <0>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + mdss_dp0_in: endpoint { + remote-endpoint = <&dpu_intf0_out>; + }; + }; + + port@1 { + reg = <1>; + + mdss_dp0_out: endpoint { }; + }; + }; + + dp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-270000000 { + opp-hz = /bits/ 64 <270000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-810000000 { + opp-hz = /bits/ 64 <810000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + }; + dispcc: clock-controller@af00000 { compatible = "qcom,sa8775p-dispcc0"; reg = <0x0 0x0af00000 0x0 0x20000>; @@ -4244,7 +4444,9 @@ <&rpmhcc RPMH_CXO_CLK>, <&rpmhcc RPMH_CXO_CLK_A>, <&sleep_clk>, - <0>, <0>, <0>, <0>, + <&mdss_dp0_phy 0>, + <&mdss_dp0_phy 1>, + <0>, <0>, <0>, <0>, <0>, <0>; power-domains = <&rpmhpd RPMHPD_MMCX>; #clock-cells = <1>; From 6ebe22bd381a322f63b204cca5888f3838ee9690 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Wed, 9 Jul 2025 15:14:13 +0800 Subject: [PATCH 105/113] FROMLIST: arm64: dts: qcom: qcs8300-ride: Enable Display Port Enable DPTX0 along with their corresponding PHYs for qcs8300-ride platform. Link:https://lore.kernel.org/all/20241226-dts_qcs8300-v2-2-ec8d4fb65cba@quicinc.com/ Signed-off-by: Yongxing Mou --- arch/arm64/boot/dts/qcom/qcs8300-ride.dts | 44 +++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts index 3ff8f398cad31..e268bb55916c4 100644 --- a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts @@ -32,6 +32,18 @@ enable-active-high; regulator-always-on; }; + + dp0-connector { + compatible = "dp-connector"; + label = "DP0"; + type = "full-size"; + + port { + dp0_connector_in: endpoint { + remote-endpoint = <&mdss_dp0_out>; + }; + }; + }; }; &apps_rsc { @@ -304,6 +316,30 @@ }; }; +&mdss { + status = "okay"; +}; + +&mdss_dp0 { + pinctrl-0 = <&dp_hot_plug_det>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&mdss_dp0_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + remote-endpoint = <&dp0_connector_in>; +}; + +&mdss_dp0_phy { + vdda-phy-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l4a>; + + status = "okay"; +}; + &qupv3_id_0 { status = "okay"; }; @@ -346,6 +382,14 @@ }; }; +&tlmm { + dp_hot_plug_det: dp-hot-plug-det-state { + pins = "gpio94"; + function = "edp0_hot"; + bias-disable; + }; +}; + &uart7 { status = "okay"; }; From 05a8da5f51c13eadcac1a876ae69bf4f5f8385cd Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 12 Apr 2025 07:19:50 +0530 Subject: [PATCH 106/113] FROMLIST: dt-bindings: PCI: Add binding for Toshiba TC9563 PCIe switch Add a device tree binding for the Toshiba TC9563 PCIe switch, which provides an Ethernet MAC integrated to the 3rd downstream port and two downstream PCIe ports. Link: https://lore.kernel.org/lkml/20250412-qps615_v4_1-v5-0-5b6a06132fec@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru Reviewed-by: Rob Herring (Arm) --- .../bindings/pci/toshiba,tc9563.yaml | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml diff --git a/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml b/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml new file mode 100644 index 0000000000000..82c902b67852d --- /dev/null +++ b/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml @@ -0,0 +1,178 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pci/toshiba,tc9563.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Toshiba TC9563 PCIe switch + +maintainers: + - Krishna chaitanya chundru + +description: | + Toshiba TC9563 PCIe switch has one upstream and three downstream ports. + The 3rd downstream port has integrated endpoint device of Ethernet MAC. + Other two downstream ports are supposed to connect to external device. + + The TC9563 PCIe switch can be configured through I2C interface before + PCIe link is established to change FTS, ASPM related entry delays, + tx amplitude etc for better power efficiency and functionality. + +properties: + compatible: + enum: + - pci1179,0623 + + reg: + maxItems: 1 + + reset-gpios: + maxItems: 1 + description: + GPIO controlling the RESX# pin. + + vdd18-supply: true + + vdd09-supply: true + + vddc-supply: true + + vddio1-supply: true + + vddio2-supply: true + + vddio18-supply: true + + i2c-parent: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + A phandle to the parent I2C node and the slave address of the device + used to do configure tc9563 to change FTS, tx amplitude etc. + items: + - description: Phandle to the I2C controller node + - description: I2C slave address + +patternProperties: + "^pcie@[1-3],0$": + description: + child nodes describing the internal downstream ports + the tc9563 switch. + type: object + allOf: + - $ref: "#/$defs/tc9563-node" + - $ref: /schemas/pci/pci-pci-bridge.yaml# + unevaluatedProperties: false + +$defs: + tc9563-node: + type: object + + properties: + toshiba,tx-amplitude-microvolt: + description: + Change Tx Margin setting for low power consumption. + + toshiba,no-dfe-support: + type: boolean + description: + Disable DFE (Decision Feedback Equalizer), which mitigates + intersymbol interference and some reflections caused by impedance mismatches. + +required: + - reset-gpios + - vdd18-supply + - vdd09-supply + - vddc-supply + - vddio1-supply + - vddio2-supply + - vddio18-supply + - i2c-parent + +allOf: + - $ref: "#/$defs/tc9563-node" + - $ref: /schemas/pci/pci-bus-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + + pcie { + #address-cells = <3>; + #size-cells = <2>; + + pcie@0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + + #address-cells = <3>; + #size-cells = <2>; + ranges; + bus-range = <0x01 0xff>; + + pcie@0,0 { + compatible = "pci1179,0623"; + + reg = <0x10000 0x0 0x0 0x0 0x0>; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + ranges; + bus-range = <0x02 0xff>; + + i2c-parent = <&qup_i2c 0x77>; + + vdd18-supply = <&vdd>; + vdd09-supply = <&vdd>; + vddc-supply = <&vdd>; + vddio1-supply = <&vdd>; + vddio2-supply = <&vdd>; + vddio18-supply = <&vdd>; + + reset-gpios = <&gpio 1 GPIO_ACTIVE_LOW>; + + pcie@1,0 { + compatible = "pciclass,0604"; + reg = <0x20800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x03 0xff>; + + toshiba,no-dfe-support; + }; + + pcie@2,0 { + compatible = "pciclass,0604"; + reg = <0x21000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x04 0xff>; + }; + + pcie@3,0 { + compatible = "pciclass,0604"; + reg = <0x21800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x05 0xff>; + + toshiba,tx-amplitude-microvolt = <10>; + + ethernet@0,0 { + reg = <0x50000 0x0 0x0 0x0 0x0>; + }; + + ethernet@0,1 { + reg = <0x50100 0x0 0x0 0x0 0x0>; + }; + }; + }; + }; + }; From 28ce8356c477aa05ecc661a390242e3d0884489d Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 12 Apr 2025 07:19:52 +0530 Subject: [PATCH 107/113] FROMLIST: PCI: Add new start_link() & stop_link function ops First controller driver probes, enables link training and scans the bus. When the PCI bridge is found, its child DT nodes will be scanned and pwrctrl devices will be created if needed. By the time pwrctrl driver probe gets called link training is already enabled by controller driver. Certain devices like TC956x which uses PCI pwrctl framework needs to configure the device before PCI link is up. As the controller driver already enables link training as part of its probe, the moment device is powered on, controller and device participates in the link training and link can come up immediately and maynot have time to configure the device. So we need to stop the link training by using stop_link() and enable them back after device is configured by using start_link(). Link: https://lore.kernel.org/lkml/20250412-qps615_v4_1-v5-0-5b6a06132fec@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru --- include/linux/pci.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/pci.h b/include/linux/pci.h index 05e68f35f3923..36f350987361f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -807,6 +807,8 @@ struct pci_ops { void __iomem *(*map_bus)(struct pci_bus *bus, unsigned int devfn, int where); int (*read)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val); int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val); + int (*start_link)(struct pci_bus *bus); + void (*stop_link)(struct pci_bus *bus); }; /* From e17291cdb4f9b44c8e5ea8fac090aba26f304f87 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 12 Apr 2025 07:19:53 +0530 Subject: [PATCH 108/113] FROMLIST: PCI: dwc: Add host_start_link() & host_start_link() hooks for dwc glue drivers Add host_start_link() and host_stop_link() functions to dwc glue drivers to register with start_link() and stop_link() of pci ops, allowing for better control over the link initialization and shutdown process. Link: https://lore.kernel.org/lkml/20250412-qps615_v4_1-v5-0-5b6a06132fec@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru --- drivers/pci/controller/dwc/pcie-designware.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index ce9e18554e426..3d58dc5bce90a 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -484,6 +484,8 @@ struct dw_pcie_ops { enum dw_pcie_ltssm (*get_ltssm)(struct dw_pcie *pcie); int (*start_link)(struct dw_pcie *pcie); void (*stop_link)(struct dw_pcie *pcie); + int (*host_start_link)(struct dw_pcie *pcie); + void (*host_stop_link)(struct dw_pcie *pcie); }; struct debugfs_info { @@ -743,6 +745,20 @@ static inline void dw_pcie_stop_link(struct dw_pcie *pci) pci->ops->stop_link(pci); } +static inline int dw_pcie_host_start_link(struct dw_pcie *pci) +{ + if (pci->ops && pci->ops->host_start_link) + return pci->ops->host_start_link(pci); + + return 0; +} + +static inline void dw_pcie_host_stop_link(struct dw_pcie *pci) +{ + if (pci->ops && pci->ops->host_stop_link) + pci->ops->host_stop_link(pci); +} + static inline enum dw_pcie_ltssm dw_pcie_get_ltssm(struct dw_pcie *pci) { u32 val; From df237d90e8af548fb607916ed162bb4b0a3d4c42 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 12 Apr 2025 07:19:54 +0530 Subject: [PATCH 109/113] FROMLIST: PCI: dwc: Implement .start_link(), .stop_link() hooks Implement stop_link() and start_link() function op for dwc drivers. Link: https://lore.kernel.org/lkml/20250412-qps615_v4_1-v5-0-5b6a06132fec@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru --- .../pci/controller/dwc/pcie-designware-host.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 906277f9ffaf7..1acf1812d2ae7 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -727,10 +727,28 @@ void __iomem *dw_pcie_own_conf_map_bus(struct pci_bus *bus, unsigned int devfn, } EXPORT_SYMBOL_GPL(dw_pcie_own_conf_map_bus); +static int dw_pcie_op_start_link(struct pci_bus *bus) +{ + struct dw_pcie_rp *pp = bus->sysdata; + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + + return dw_pcie_host_start_link(pci); +} + +static void dw_pcie_op_stop_link(struct pci_bus *bus) +{ + struct dw_pcie_rp *pp = bus->sysdata; + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + + dw_pcie_host_stop_link(pci); +} + static struct pci_ops dw_pcie_ops = { .map_bus = dw_pcie_own_conf_map_bus, .read = pci_generic_config_read, .write = pci_generic_config_write, + .start_link = dw_pcie_op_start_link, + .stop_link = dw_pcie_op_stop_link, }; static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp) From 69d8388d0bfc98aa2784a6d14f6ae2be45fd9d95 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 12 Apr 2025 07:19:55 +0530 Subject: [PATCH 110/113] FROMLIST: PCI: qcom: Add support for host_stop_link() & host_start_link() Add support for host_stop_link() and host_start_link() for switches like TC956x, which require configuration before the PCIe link is established. Assert PERST# and disable LTSSM bit to prevent the PCIe controller from participating in link training during host_stop_link(). De-assert PERST# and enable LTSSM bit during host_start_link(). Introduce ltssm_disable function op to stop link training. For the switches like TC956x, which needs to configure it before the PCIe link is established. Link: https://lore.kernel.org/lkml/20250412-qps615_v4_1-v5-0-5b6a06132fec@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru --- drivers/pci/controller/dwc/pcie-qcom.c | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index c789e3f856550..f5b473fb050aa 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -247,6 +247,7 @@ struct qcom_pcie_ops { void (*host_post_init)(struct qcom_pcie *pcie); void (*deinit)(struct qcom_pcie *pcie); void (*ltssm_enable)(struct qcom_pcie *pcie); + void (*ltssm_disable)(struct qcom_pcie *pcie); int (*config_sid)(struct qcom_pcie *pcie); }; @@ -618,6 +619,37 @@ static int qcom_pcie_post_init_1_0_0(struct qcom_pcie *pcie) return 0; } +static int qcom_pcie_host_start_link(struct dw_pcie *pci) +{ + struct qcom_pcie *pcie = to_qcom_pcie(pci); + + qcom_ep_reset_deassert(pcie); + + if (pcie->cfg->ops->ltssm_enable) + pcie->cfg->ops->ltssm_enable(pcie); + + return 0; +} + +static void qcom_pcie_host_stop_link(struct dw_pcie *pci) +{ + struct qcom_pcie *pcie = to_qcom_pcie(pci); + + qcom_ep_reset_assert(pcie); + + if (pcie->cfg->ops->ltssm_disable) + pcie->cfg->ops->ltssm_disable(pcie); +} + +static void qcom_pcie_2_3_2_ltssm_disable(struct qcom_pcie *pcie) +{ + u32 val; + + val = readl(pcie->parf + PARF_LTSSM); + val &= ~LTSSM_EN; + writel(val, pcie->parf + PARF_LTSSM); +} + static void qcom_pcie_2_3_2_ltssm_enable(struct qcom_pcie *pcie) { u32 val; @@ -1362,6 +1394,7 @@ static const struct qcom_pcie_ops ops_1_9_0 = { .host_post_init = qcom_pcie_host_post_init_2_7_0, .deinit = qcom_pcie_deinit_2_7_0, .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable, + .ltssm_disable = qcom_pcie_2_3_2_ltssm_disable, .config_sid = qcom_pcie_config_sid_1_9_0, }; @@ -1429,6 +1462,8 @@ static const struct qcom_pcie_cfg cfg_sc8280xp = { static const struct dw_pcie_ops dw_pcie_ops = { .link_up = qcom_pcie_link_up, .start_link = qcom_pcie_start_link, + .host_start_link = qcom_pcie_host_start_link, + .host_stop_link = qcom_pcie_host_stop_link, }; static int qcom_pcie_icc_init(struct qcom_pcie *pcie) From 2c9bc88c94a941307ba8e78376290453c30e0474 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 12 Apr 2025 07:19:56 +0530 Subject: [PATCH 111/113] FROMLIST: PCI: PCI: Add pcie_link_is_active() to determine if the PCIe link is active Introduce a common API to check if the PCIe link is active, replacing duplicate code in multiple locations. Link: https://lore.kernel.org/lkml/20250412-qps615_v4_1-v5-0-5b6a06132fec@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru Reviewed-by: Lukas Wunner --- drivers/pci/hotplug/pciehp_ctrl.c | 7 ++++--- drivers/pci/hotplug/pciehp_hpc.c | 31 ++----------------------------- drivers/pci/pci.c | 26 +++++++++++++++++++++++--- include/linux/pci.h | 4 ++++ 4 files changed, 33 insertions(+), 35 deletions(-) diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index bcc938d4420f3..1d760525b5887 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -230,7 +230,8 @@ void pciehp_handle_disable_request(struct controller *ctrl) void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events) { - int present, link_active; + bool link_active; + int present; /* * If the slot is on and presence or link has changed, turn it off. @@ -260,8 +261,8 @@ void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events) /* Turn the slot on if it's occupied or link is up */ mutex_lock(&ctrl->state_lock); present = pciehp_card_present(ctrl); - link_active = pciehp_check_link_active(ctrl); - if (present <= 0 && link_active <= 0) { + link_active = pcie_link_is_active(ctrl->pcie->port); + if (present <= 0 && !link_active) { if (ctrl->state == BLINKINGON_STATE) { ctrl->state = OFF_STATE; cancel_delayed_work(&ctrl->button_work); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 91d2d92717d98..36d6188ced646 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -221,33 +221,6 @@ static void pcie_write_cmd_nowait(struct controller *ctrl, u16 cmd, u16 mask) pcie_do_write_cmd(ctrl, cmd, mask, false); } -/** - * pciehp_check_link_active() - Is the link active - * @ctrl: PCIe hotplug controller - * - * Check whether the downstream link is currently active. Note it is - * possible that the card is removed immediately after this so the - * caller may need to take it into account. - * - * If the hotplug controller itself is not available anymore returns - * %-ENODEV. - */ -int pciehp_check_link_active(struct controller *ctrl) -{ - struct pci_dev *pdev = ctrl_dev(ctrl); - u16 lnk_status; - int ret; - - ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); - if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status)) - return -ENODEV; - - ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); - ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status); - - return ret; -} - static bool pci_bus_check_dev(struct pci_bus *bus, int devfn) { u32 l; @@ -467,7 +440,7 @@ int pciehp_card_present_or_link_active(struct controller *ctrl) if (ret) return ret; - return pciehp_check_link_active(ctrl); + return pcie_link_is_active(ctrl_dev(ctrl)); } int pciehp_query_power_fault(struct controller *ctrl) @@ -921,7 +894,7 @@ int pciehp_slot_reset(struct pcie_device *dev) pcie_capability_write_word(dev->port, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_DLLSC); - if (!pciehp_check_link_active(ctrl)) + if (!pcie_link_is_active(ctrl_dev(ctrl))) pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC); return 0; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9e42090fb1089..6096c3d06655d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4909,7 +4909,6 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) return 0; if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) { - u16 status; pci_dbg(dev, "waiting %d ms for downstream link\n", delay); msleep(delay); @@ -4925,8 +4924,7 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) if (!dev->link_active_reporting) return -ENOTTY; - pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &status); - if (!(status & PCI_EXP_LNKSTA_DLLLA)) + if (!pcie_link_is_active(dev)) return -ENOTTY; return pci_dev_wait(child, reset_type, @@ -6231,6 +6229,28 @@ void pcie_print_link_status(struct pci_dev *dev) } EXPORT_SYMBOL(pcie_print_link_status); +/** + * pcie_link_is_active() - Checks if the link is active or not + * @pdev: PCI device to query + * + * Check whether the link is active or not. + * + * Return: true if link is active. + */ +bool pcie_link_is_active(struct pci_dev *pdev) +{ + u16 lnk_status; + int ret; + + ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); + if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status)) + return false; + + pci_dbg(pdev, "lnk_status = %x\n", lnk_status); + return !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); +} +EXPORT_SYMBOL(pcie_link_is_active); + /** * pci_select_bars - Make BAR mask from the type of resource * @dev: the PCI device for which BAR mask is made diff --git a/include/linux/pci.h b/include/linux/pci.h index 36f350987361f..3919115a374f3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1995,6 +1995,7 @@ pci_release_mem_regions(struct pci_dev *pdev) pci_select_bars(pdev, IORESOURCE_MEM)); } +bool pcie_link_is_active(struct pci_dev *dev); #else /* CONFIG_PCI is not enabled */ static inline void pci_set_flags(int flags) { } @@ -2143,6 +2144,9 @@ pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, { return -ENOSPC; } + +static inline bool pcie_link_is_active(struct pci_dev *dev) +{ return false; } #endif /* CONFIG_PCI */ /* Include architecture-dependent settings and functions */ From c387c06e97b117087e11f3ccc43ec75233a15e29 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 12 Apr 2025 07:19:57 +0530 Subject: [PATCH 112/113] FROMLIST: PCI: pwrctrl: Add power control driver for tc9563 TC9563 is a PCIe switch which has one upstream and three downstream ports. To one of the downstream ports ethernet MAC is connected as endpoint device. Other two downstream ports are supposed to connect to external device. One Host can connect to TC9563 by upstream port. TC9563 switch needs to be configured after powering on and before PCIe link was up. The PCIe controller driver already enables link training at the host side even before this driver probe happens, due to this when driver enables power to the switch it participates in the link training and PCIe link may come up before configuring the switch through i2c. Once the link is up the configuration done through i2c will not have any affect.To prevent the host from participating in link training, disable link training on the host side to ensure the link does not come up before the switch is configured via I2C. Based up on dt property and type of the port, tc9563 is configured through i2c. Link: https://lore.kernel.org/lkml/20250412-qps615_v4_1-v5-0-5b6a06132fec@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru Reviewed-by: Bjorn Andersson Reviewed-by: Bartosz Golaszewski --- drivers/pci/pwrctrl/Kconfig | 10 + drivers/pci/pwrctrl/Makefile | 2 + drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c | 628 +++++++++++++++++++++++ 3 files changed, 640 insertions(+) create mode 100644 drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c diff --git a/drivers/pci/pwrctrl/Kconfig b/drivers/pci/pwrctrl/Kconfig index 6956c18548114..acc78acaede86 100644 --- a/drivers/pci/pwrctrl/Kconfig +++ b/drivers/pci/pwrctrl/Kconfig @@ -31,3 +31,13 @@ config HAVE_PWRCTL config PCI_PWRCTL_PWRSEQ tristate select PCI_PWRCTRL_PWRSEQ + +config PCI_PWRCTRL_TC9563 + tristate "PCI Power Control driver for TC9563 PCIe switch" + select PCI_PWRCTRL + help + Say Y here to enable the PCI Power Control driver of TC9563 PCIe + switch. + + This driver enables power and configures the TC9563 PCIe switch + through i2c. diff --git a/drivers/pci/pwrctrl/Makefile b/drivers/pci/pwrctrl/Makefile index a4e5808d7850c..13b02282106c2 100644 --- a/drivers/pci/pwrctrl/Makefile +++ b/drivers/pci/pwrctrl/Makefile @@ -7,3 +7,5 @@ obj-$(CONFIG_PCI_PWRCTRL_PWRSEQ) += pci-pwrctrl-pwrseq.o obj-$(CONFIG_PCI_PWRCTRL_SLOT) += pci-pwrctrl-slot.o pci-pwrctrl-slot-y := slot.o + +obj-$(CONFIG_PCI_PWRCTRL_TC9563) += pci-pwrctrl-tc9563.o diff --git a/drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c b/drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c new file mode 100644 index 0000000000000..547c764a6f405 --- /dev/null +++ b/drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c @@ -0,0 +1,628 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../pci.h" + +#define TC9563_GPIO_CONFIG 0x801208 +#define TC9563_RESET_GPIO 0x801210 + +#define TC9563_BUS_CONTROL 0x801014 + +#define TC9563_PORT_L0S_DELAY 0x82496c +#define TC9563_PORT_L1_DELAY 0x824970 + +#define TC9563_EMBEDDED_ETH_DELAY 0x8200d8 +#define TC9563_ETH_L1_DELAY_MASK GENMASK(27, 18) +#define TC9563_ETH_L1_DELAY_VALUE(x) FIELD_PREP(TC9563_ETH_L1_DELAY_MASK, x) +#define TC9563_ETH_L0S_DELAY_MASK GENMASK(17, 13) +#define TC9563_ETH_L0S_DELAY_VALUE(x) FIELD_PREP(TC9563_ETH_L0S_DELAY_MASK, x) + +#define TC9563_NFTS_2_5_GT 0x824978 +#define TC9563_NFTS_5_GT 0x82497c + +#define TC9563_PORT_LANE_ACCESS_ENABLE 0x828000 + +#define TC9563_PHY_RATE_CHANGE_OVERRIDE 0x828040 +#define TC9563_PHY_RATE_CHANGE 0x828050 + +#define TC9563_TX_MARGIN 0x828234 + +#define TC9563_DFE_ENABLE 0x828a04 +#define TC9563_DFE_EQ0_MODE 0x828a08 +#define TC9563_DFE_EQ1_MODE 0x828a0c +#define TC9563_DFE_EQ2_MODE 0x828a14 +#define TC9563_DFE_PD_MASK 0x828254 + +#define TC9563_PORT_SELECT 0x82c02c +#define TC9563_PORT_ACCESS_ENABLE 0x82c030 + +#define TC9563_POWER_CONTROL 0x82b09c +#define TC9563_POWER_CONTROL_OVREN 0x82b2c8 + +#define TC9563_GPIO_MASK 0xfffffff3 + +#define TC9563_TX_MARGIN_MIN_VAL 400000 + +struct tc9563_pwrctrl_reg_setting { + unsigned int offset; + unsigned int val; +}; + +enum tc9563_pwrctrl_ports { + TC9563_USP, + TC9563_DSP1, + TC9563_DSP2, + TC9563_DSP3, + TC9563_ETHERNET, + TC9563_MAX +}; + +struct tc9563_pwrctrl_cfg { + u32 l0s_delay; + u32 l1_delay; + u32 tx_amp; + u8 nfts[2]; /* GEN1 & GEN2 */ + bool disable_dfe; + bool disable_port; +}; + +#define TC9563_PWRCTL_MAX_SUPPLY 6 + +struct tc9563_pwrctrl_ctx { + struct regulator_bulk_data supplies[TC9563_PWRCTL_MAX_SUPPLY]; + struct tc9563_pwrctrl_cfg cfg[TC9563_MAX]; + struct gpio_desc *reset_gpio; + struct i2c_adapter *adapter; + struct i2c_client *client; + struct pci_pwrctrl pwrctrl; +}; + +/* + * downstream port power off sequence, hardcoding the address + * as we don't know register names for these register offsets. + */ +static const struct tc9563_pwrctrl_reg_setting common_pwroff_seq[] = { + {0x82900c, 0x1}, + {0x829010, 0x1}, + {0x829018, 0x0}, + {0x829020, 0x1}, + {0x82902c, 0x1}, + {0x829030, 0x1}, + {0x82903c, 0x1}, + {0x829058, 0x0}, + {0x82905c, 0x1}, + {0x829060, 0x1}, + {0x8290cc, 0x1}, + {0x8290d0, 0x1}, + {0x8290d8, 0x1}, + {0x8290e0, 0x1}, + {0x8290e8, 0x1}, + {0x8290ec, 0x1}, + {0x8290f4, 0x1}, + {0x82910c, 0x1}, + {0x829110, 0x1}, + {0x829114, 0x1}, +}; + +static const struct tc9563_pwrctrl_reg_setting dsp1_pwroff_seq[] = { + {TC9563_PORT_ACCESS_ENABLE, 0x2}, + {TC9563_PORT_LANE_ACCESS_ENABLE, 0x3}, + {TC9563_POWER_CONTROL, 0x014f4804}, + {TC9563_POWER_CONTROL_OVREN, 0x1}, + {TC9563_PORT_ACCESS_ENABLE, 0x4}, +}; + +static const struct tc9563_pwrctrl_reg_setting dsp2_pwroff_seq[] = { + {TC9563_PORT_ACCESS_ENABLE, 0x8}, + {TC9563_PORT_LANE_ACCESS_ENABLE, 0x1}, + {TC9563_POWER_CONTROL, 0x014f4804}, + {TC9563_POWER_CONTROL_OVREN, 0x1}, + {TC9563_PORT_ACCESS_ENABLE, 0x8}, +}; + +/* + * Since all transfers are initiated by the probe, no locks are necessary, + * as there are no concurrent calls. + */ +static int tc9563_pwrctrl_i2c_write(struct i2c_client *client, + u32 reg_addr, u32 reg_val) +{ + struct i2c_msg msg; + u8 msg_buf[7]; + int ret; + + msg.addr = client->addr; + msg.len = 7; + msg.flags = 0; + + /* Big Endian for reg addr */ + put_unaligned_be24(reg_addr, &msg_buf[0]); + + /* Little Endian for reg val */ + put_unaligned_le32(reg_val, &msg_buf[3]); + + msg.buf = msg_buf; + ret = i2c_transfer(client->adapter, &msg, 1); + return ret == 1 ? 0 : ret; +} + +static int tc9563_pwrctrl_i2c_read(struct i2c_client *client, + u32 reg_addr, u32 *reg_val) +{ + struct i2c_msg msg[2]; + u8 wr_data[3]; + u32 rd_data; + int ret; + + msg[0].addr = client->addr; + msg[0].len = 3; + msg[0].flags = 0; + + /* Big Endian for reg addr */ + put_unaligned_be24(reg_addr, &wr_data[0]); + + msg[0].buf = wr_data; + + msg[1].addr = client->addr; + msg[1].len = 4; + msg[1].flags = I2C_M_RD; + + msg[1].buf = (u8 *)&rd_data; + + ret = i2c_transfer(client->adapter, &msg[0], 2); + if (ret == 2) { + *reg_val = get_unaligned_le32(&rd_data); + return 0; + } + + /* If only one message successfully completed, return -EIO */ + return ret == 1 ? -EIO : ret; +} + +static int tc9563_pwrctrl_i2c_bulk_write(struct i2c_client *client, + const struct tc9563_pwrctrl_reg_setting *seq, int len) +{ + int ret, i; + + for (i = 0; i < len; i++) { + ret = tc9563_pwrctrl_i2c_write(client, seq[i].offset, seq[i].val); + if (ret) + return ret; + } + + return 0; +} + +static int tc9563_pwrctrl_disable_port(struct tc9563_pwrctrl_ctx *ctx, + enum tc9563_pwrctrl_ports port) +{ + struct tc9563_pwrctrl_cfg *cfg = &ctx->cfg[port]; + const struct tc9563_pwrctrl_reg_setting *seq; + int ret, len; + + if (!cfg->disable_port) + return 0; + + if (port == TC9563_DSP1) { + seq = dsp1_pwroff_seq; + len = ARRAY_SIZE(dsp1_pwroff_seq); + } else { + seq = dsp2_pwroff_seq; + len = ARRAY_SIZE(dsp2_pwroff_seq); + } + + ret = tc9563_pwrctrl_i2c_bulk_write(ctx->client, seq, len); + if (ret) + return ret; + + return tc9563_pwrctrl_i2c_bulk_write(ctx->client, + common_pwroff_seq, ARRAY_SIZE(common_pwroff_seq)); +} + +static int tc9563_pwrctrl_set_l0s_l1_entry_delay(struct tc9563_pwrctrl_ctx *ctx, + enum tc9563_pwrctrl_ports port, bool is_l1, u32 ns) +{ + u32 rd_val, units; + int ret; + + if (ns < 256) + return 0; + + /* convert to units of 256ns */ + units = ns / 256; + + if (port == TC9563_ETHERNET) { + ret = tc9563_pwrctrl_i2c_read(ctx->client, TC9563_EMBEDDED_ETH_DELAY, &rd_val); + if (ret) + return ret; + + if (is_l1) + rd_val = u32_replace_bits(rd_val, units, TC9563_ETH_L1_DELAY_MASK); + else + rd_val = u32_replace_bits(rd_val, units, TC9563_ETH_L0S_DELAY_MASK); + + return tc9563_pwrctrl_i2c_write(ctx->client, TC9563_EMBEDDED_ETH_DELAY, rd_val); + } + + ret = tc9563_pwrctrl_i2c_write(ctx->client, TC9563_PORT_SELECT, BIT(port)); + if (ret) + return ret; + + return tc9563_pwrctrl_i2c_write(ctx->client, + is_l1 ? TC9563_PORT_L1_DELAY : TC9563_PORT_L0S_DELAY, units); +} + +static int tc9563_pwrctrl_set_tx_amplitude(struct tc9563_pwrctrl_ctx *ctx, + enum tc9563_pwrctrl_ports port, u32 amp) +{ + int port_access; + + if (amp < TC9563_TX_MARGIN_MIN_VAL) + return 0; + + /* txmargin = (Amp(uV) - 400000) / 3125 */ + amp = (amp - TC9563_TX_MARGIN_MIN_VAL) / 3125; + + switch (port) { + case TC9563_USP: + port_access = 0x1; + break; + case TC9563_DSP1: + port_access = 0x2; + break; + case TC9563_DSP2: + port_access = 0x8; + break; + default: + return -EINVAL; + }; + + struct tc9563_pwrctrl_reg_setting tx_amp_seq[] = { + {TC9563_PORT_ACCESS_ENABLE, port_access}, + {TC9563_PORT_LANE_ACCESS_ENABLE, 0x3}, + {TC9563_TX_MARGIN, amp}, + }; + + return tc9563_pwrctrl_i2c_bulk_write(ctx->client, tx_amp_seq, ARRAY_SIZE(tx_amp_seq)); +} + +static int tc9563_pwrctrl_disable_dfe(struct tc9563_pwrctrl_ctx *ctx, + enum tc9563_pwrctrl_ports port) +{ + struct tc9563_pwrctrl_cfg *cfg = &ctx->cfg[port]; + int port_access, lane_access = 0x3; + u32 phy_rate = 0x21; + + if (!cfg->disable_dfe) + return 0; + + switch (port) { + case TC9563_USP: + phy_rate = 0x1; + port_access = 0x1; + break; + case TC9563_DSP1: + port_access = 0x2; + break; + case TC9563_DSP2: + port_access = 0x8; + lane_access = 0x1; + break; + default: + return -EINVAL; + }; + + struct tc9563_pwrctrl_reg_setting disable_dfe_seq[] = { + {TC9563_PORT_ACCESS_ENABLE, port_access}, + {TC9563_PORT_LANE_ACCESS_ENABLE, lane_access}, + {TC9563_DFE_ENABLE, 0x0}, + {TC9563_DFE_EQ0_MODE, 0x411}, + {TC9563_DFE_EQ1_MODE, 0x11}, + {TC9563_DFE_EQ2_MODE, 0x11}, + {TC9563_DFE_PD_MASK, 0x7}, + {TC9563_PHY_RATE_CHANGE_OVERRIDE, 0x10}, + {TC9563_PHY_RATE_CHANGE, phy_rate}, + {TC9563_PHY_RATE_CHANGE, 0x0}, + {TC9563_PHY_RATE_CHANGE_OVERRIDE, 0x0}, + }; + + return tc9563_pwrctrl_i2c_bulk_write(ctx->client, + disable_dfe_seq, ARRAY_SIZE(disable_dfe_seq)); +} + +static int tc9563_pwrctrl_set_nfts(struct tc9563_pwrctrl_ctx *ctx, + enum tc9563_pwrctrl_ports port, u8 *nfts) +{ + struct tc9563_pwrctrl_reg_setting nfts_seq[] = { + {TC9563_NFTS_2_5_GT, nfts[0]}, + {TC9563_NFTS_5_GT, nfts[1]}, + }; + int ret; + + if (!nfts[0]) + return 0; + + ret = tc9563_pwrctrl_i2c_write(ctx->client, TC9563_PORT_SELECT, BIT(port)); + if (ret) + return ret; + + return tc9563_pwrctrl_i2c_bulk_write(ctx->client, nfts_seq, ARRAY_SIZE(nfts_seq)); +} + +static int tc9563_pwrctrl_assert_deassert_reset(struct tc9563_pwrctrl_ctx *ctx, bool deassert) +{ + int ret, val; + + ret = tc9563_pwrctrl_i2c_write(ctx->client, TC9563_GPIO_CONFIG, TC9563_GPIO_MASK); + if (ret) + return ret; + + val = deassert ? 0xc : 0; + + return tc9563_pwrctrl_i2c_write(ctx->client, TC9563_RESET_GPIO, val); +} + +static int tc9563_pwrctrl_parse_device_dt(struct tc9563_pwrctrl_ctx *ctx, struct device_node *node, + enum tc9563_pwrctrl_ports port) +{ + struct tc9563_pwrctrl_cfg *cfg; + int ret; + + cfg = &ctx->cfg[port]; + + /* Disable port if the status of the port is disabled. */ + if (!of_device_is_available(node)) { + cfg->disable_port = true; + return 0; + }; + + ret = of_property_read_u32(node, "aspm-l0s-entry-delay-ns", &cfg->l0s_delay); + if (ret && ret != -EINVAL) + return ret; + + ret = of_property_read_u32(node, "aspm-l1-entry-delay-ns", &cfg->l1_delay); + if (ret && ret != -EINVAL) + return ret; + + ret = of_property_read_u32(node, "qcom,tx-amplitude-microvolt", &cfg->tx_amp); + if (ret && ret != -EINVAL) + return ret; + + ret = of_property_read_u8_array(node, "nfts", cfg->nfts, 2); + if (ret && ret != -EINVAL) + return ret; + + cfg->disable_dfe = of_property_read_bool(node, "qcom,no-dfe-support"); + + return 0; +} + +static void tc9563_pwrctrl_power_off(struct tc9563_pwrctrl_ctx *ctx) +{ + gpiod_set_value(ctx->reset_gpio, 1); + + regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); +} + +static int tc9563_pwrctrl_bring_up(struct tc9563_pwrctrl_ctx *ctx) +{ + struct tc9563_pwrctrl_cfg *cfg; + int ret, i; + + ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); + if (ret < 0) + return dev_err_probe(ctx->pwrctrl.dev, ret, "cannot enable regulators\n"); + + gpiod_set_value(ctx->reset_gpio, 0); + + /* wait for the internal osc frequency to stablise */ + usleep_range(10000, 10500); + + ret = tc9563_pwrctrl_assert_deassert_reset(ctx, false); + if (ret) + goto power_off; + + for (i = 0; i < TC9563_MAX; i++) { + cfg = &ctx->cfg[i]; + ret = tc9563_pwrctrl_disable_port(ctx, i); + if (ret) { + dev_err(ctx->pwrctrl.dev, "Disabling port failed\n"); + goto power_off; + } + + ret = tc9563_pwrctrl_set_l0s_l1_entry_delay(ctx, i, false, cfg->l0s_delay); + if (ret) { + dev_err(ctx->pwrctrl.dev, "Setting L0s entry delay failed\n"); + goto power_off; + } + + ret = tc9563_pwrctrl_set_l0s_l1_entry_delay(ctx, i, true, cfg->l1_delay); + if (ret) { + dev_err(ctx->pwrctrl.dev, "Setting L1 entry delay failed\n"); + goto power_off; + } + + ret = tc9563_pwrctrl_set_tx_amplitude(ctx, i, cfg->tx_amp); + if (ret) { + dev_err(ctx->pwrctrl.dev, "Setting Tx amplitube failed\n"); + goto power_off; + } + + ret = tc9563_pwrctrl_set_nfts(ctx, i, cfg->nfts); + if (ret) { + dev_err(ctx->pwrctrl.dev, "Setting nfts failed\n"); + goto power_off; + } + + ret = tc9563_pwrctrl_disable_dfe(ctx, i); + if (ret) { + dev_err(ctx->pwrctrl.dev, "Disabling DFE failed\n"); + goto power_off; + } + } + + ret = tc9563_pwrctrl_assert_deassert_reset(ctx, true); + if (!ret) + return 0; + +power_off: + tc9563_pwrctrl_power_off(ctx); + return ret; +} + +static int tc9563_pwrctrl_probe(struct platform_device *pdev) +{ + struct pci_host_bridge *bridge = to_pci_host_bridge(pdev->dev.parent); + struct pci_dev *pci_dev = to_pci_dev(pdev->dev.parent); + struct pci_bus *bus = bridge->bus; + struct device *dev = &pdev->dev; + enum tc9563_pwrctrl_ports port; + struct tc9563_pwrctrl_ctx *ctx; + struct device_node *i2c_node; + int ret, addr; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ret = of_property_read_u32_index(pdev->dev.of_node, "i2c-parent", 1, &addr); + if (ret) + return dev_err_probe(dev, ret, "Failed to read i2c-parent property\n"); + + i2c_node = of_parse_phandle(dev->of_node, "i2c-parent", 0); + ctx->adapter = of_find_i2c_adapter_by_node(i2c_node); + of_node_put(i2c_node); + if (!ctx->adapter) + return dev_err_probe(dev, -EPROBE_DEFER, "Failed to find I2C adapter\n"); + + ctx->client = i2c_new_dummy_device(ctx->adapter, addr); + if (IS_ERR(ctx->client)) { + dev_err(dev, "Failed to create I2C client\n"); + i2c_put_adapter(ctx->adapter); + return PTR_ERR(ctx->client); + } + + ctx->supplies[0].supply = "vddc"; + ctx->supplies[1].supply = "vdd18"; + ctx->supplies[2].supply = "vdd09"; + ctx->supplies[3].supply = "vddio1"; + ctx->supplies[4].supply = "vddio2"; + ctx->supplies[5].supply = "vddio18"; + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), ctx->supplies); + if (ret) { + dev_err_probe(dev, ret, + "failed to get supply regulator\n"); + goto remove_i2c; + } + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ctx->reset_gpio)) { + ret = dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "failed to get reset GPIO\n"); + goto remove_i2c; + } + + pci_pwrctrl_init(&ctx->pwrctrl, dev); + + port = TC9563_USP; + ret = tc9563_pwrctrl_parse_device_dt(ctx, pdev->dev.of_node, port); + if (ret) { + dev_err(dev, "failed to parse device tree properties: %d\n", ret); + goto remove_i2c; + } + + /* + * Downstream ports are always children of the upstream port. + * The first node represents DSP1, the second node represents DSP2, and so on. + */ + for_each_child_of_node_scoped(pdev->dev.of_node, child) { + ret = tc9563_pwrctrl_parse_device_dt(ctx, child, port++); + if (ret) + break; + /* Embedded ethernet device are under DSP3 */ + if (port == TC9563_DSP3) + for_each_child_of_node_scoped(child, child1) { + ret = tc9563_pwrctrl_parse_device_dt(ctx, child1, port++); + if (ret) + break; + } + } + if (ret) { + dev_err(dev, "failed to parse device tree properties: %d\n", ret); + goto remove_i2c; + } + + if (!pcie_link_is_active(pci_dev) && bridge->ops->stop_link) + bridge->ops->stop_link(bus); + + ret = tc9563_pwrctrl_bring_up(ctx); + if (ret) + goto remove_i2c; + + if (!pcie_link_is_active(pci_dev) && bridge->ops->start_link) { + ret = bridge->ops->start_link(bus); + if (ret) + goto power_off; + } + + ret = devm_pci_pwrctrl_device_set_ready(dev, &ctx->pwrctrl); + if (ret) + goto power_off; + + platform_set_drvdata(pdev, ctx); + + return 0; + +power_off: + tc9563_pwrctrl_power_off(ctx); +remove_i2c: + i2c_unregister_device(ctx->client); + i2c_put_adapter(ctx->adapter); + return ret; +} + +static void tc9563_pwrctrl_remove(struct platform_device *pdev) +{ + struct tc9563_pwrctrl_ctx *ctx = platform_get_drvdata(pdev); + + tc9563_pwrctrl_power_off(ctx); + i2c_unregister_device(ctx->client); + i2c_put_adapter(ctx->adapter); +} + +static const struct of_device_id tc9563_pwrctrl_of_match[] = { + { .compatible = "pci1179,0623"}, + { } +}; +MODULE_DEVICE_TABLE(of, tc9563_pwrctrl_of_match); + +static struct platform_driver tc9563_pwrctrl_driver = { + .driver = { + .name = "pwrctrl-tc9563", + .of_match_table = tc9563_pwrctrl_of_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + .probe = tc9563_pwrctrl_probe, + .remove = tc9563_pwrctrl_remove, +}; +module_platform_driver(tc9563_pwrctrl_driver); + +MODULE_AUTHOR("Krishna chaitanya chundru "); +MODULE_DESCRIPTION("TC956x power control driver"); +MODULE_LICENSE("GPL"); From 1d878590b501e2c046c790f808a7ec6b0dccec9d Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 11 Jul 2025 07:51:05 +0530 Subject: [PATCH 113/113] Add qcom-next log files for 20250711 Adding merge log file and topic_SHA1 file Signed-off-by: Salendarsingh Gaud --- qcom-next/merge.log | 442 +++++++++++++++++++++++++++++++++++++++++++ qcom-next/topic_SHA1 | 17 ++ 2 files changed, 459 insertions(+) create mode 100644 qcom-next/merge.log create mode 100644 qcom-next/topic_SHA1 diff --git a/qcom-next/merge.log b/qcom-next/merge.log new file mode 100644 index 0000000000000..61c7e521e8f32 --- /dev/null +++ b/qcom-next/merge.log @@ -0,0 +1,442 @@ +Verified existence of local and remote repos: Success +/local/mnt/workspace/automerge/actions-runner/_work/kernel-automation/kernel-automation/kernel-topics /local/mnt/workspace/automerge/actions-runner/_work/kernel-automation/kernel-automation/kernel-topics +Reuse-Recorded-Resolution: Disabled +Local tree is clean +Removing old remotes ... +The remote origin https://github.com/qualcomm-linux/kernel-topics.git is no longer tracked. +Delete it [Y/n]? Done, removed 1 old remote(s). +Adding new remotes... +Adding remote baseline git@github.com:qualcomm-linux/kernel.git qcom-next-staging +Updating baseline +Adding remote tech/bsp/clk git@github.com:qualcomm-linux/kernel-topics.git tech/bsp/clk +Updating tech/bsp/clk +Adding remote tech/bsp/interconnect git@github.com:qualcomm-linux/kernel-topics.git tech/bsp/interconnect +Updating tech/bsp/interconnect +Adding remote tech/mem/secure-buffer git@github.com:qualcomm-linux/kernel-topics.git tech/mem/secure-buffer +Updating tech/mem/secure-buffer +Adding remote tech/security/firmware-smc git@github.com:qualcomm-linux/kernel-topics.git tech/security/firmware-smc +Updating tech/security/firmware-smc +Adding remote tech/bsp/soc-infra git@github.com:qualcomm-linux/kernel-topics.git tech/bsp/soc-infra +Updating tech/bsp/soc-infra +Adding remote tech/debug/soc git@github.com:qualcomm-linux/kernel-topics.git tech/debug/soc +Updating tech/debug/soc +Adding remote tech/bsp/pinctrl git@github.com:qualcomm-linux/kernel-topics.git tech/bsp/pinctrl +Updating tech/bsp/pinctrl +Adding remote tech/bsp/remoteproc git@github.com:qualcomm-linux/kernel-topics.git tech/bsp/remoteproc +Updating tech/bsp/remoteproc +Adding remote tech/bus/peripherals git@github.com:qualcomm-linux/kernel-topics.git tech/bus/peripherals +Updating tech/bus/peripherals +Adding remote tech/bus/pci/all git@github.com:qualcomm-linux/kernel-topics.git tech/bus/pci/all +Updating tech/bus/pci/all +Adding remote tech/bus/pci/mhi git@github.com:qualcomm-linux/kernel-topics.git tech/bus/pci/mhi +Updating tech/bus/pci/mhi +Adding remote tech/bus/pci/phy git@github.com:qualcomm-linux/kernel-topics.git tech/bus/pci/phy +Updating tech/bus/pci/phy +Adding remote tech/bus/pci/pwrctl git@github.com:qualcomm-linux/kernel-topics.git tech/bus/pci/pwrctl +Updating tech/bus/pci/pwrctl +Adding remote tech/bus/usb/dwc git@github.com:qualcomm-linux/kernel-topics.git tech/bus/usb/dwc +Updating tech/bus/usb/dwc +Adding remote tech/bus/usb/gadget git@github.com:qualcomm-linux/kernel-topics.git tech/bus/usb/gadget +Updating tech/bus/usb/gadget +Adding remote tech/bus/usb/phy git@github.com:qualcomm-linux/kernel-topics.git tech/bus/usb/phy +Updating tech/bus/usb/phy +Adding remote tech/debug/eud git@github.com:qualcomm-linux/kernel-topics.git tech/debug/eud +Updating tech/debug/eud +Adding remote tech/debug/hwtracing git@github.com:qualcomm-linux/kernel-topics.git tech/debug/hwtracing +Updating tech/debug/hwtracing +Adding remote tech/debug/rdbg git@github.com:qualcomm-linux/kernel-topics.git tech/debug/rdbg +Updating tech/debug/rdbg +Adding remote tech/pmic/backlight git@github.com:qualcomm-linux/kernel-topics.git tech/pmic/backlight +Updating tech/pmic/backlight +Adding remote tech/pmic/mfd git@github.com:qualcomm-linux/kernel-topics.git tech/pmic/mfd +Updating tech/pmic/mfd +Adding remote tech/pmic/misc git@github.com:qualcomm-linux/kernel-topics.git tech/pmic/misc +Updating tech/pmic/misc +Adding remote tech/pmic/regulator git@github.com:qualcomm-linux/kernel-topics.git tech/pmic/regulator +Updating tech/pmic/regulator +Adding remote tech/pmic/supply git@github.com:qualcomm-linux/kernel-topics.git tech/pmic/supply +Updating tech/pmic/supply +Adding remote tech/mem/dma-buf git@github.com:qualcomm-linux/kernel-topics.git tech/mem/dma-buf +Updating tech/mem/dma-buf +Adding remote tech/mem/iommu git@github.com:qualcomm-linux/kernel-topics.git tech/mem/iommu +Updating tech/mem/iommu +Adding remote tech/mm/audio/all git@github.com:qualcomm-linux/kernel-topics.git tech/mm/audio/all +Updating tech/mm/audio/all +Adding remote tech/mm/audio/soundwire git@github.com:qualcomm-linux/kernel-topics.git tech/mm/audio/soundwire +Updating tech/mm/audio/soundwire +Adding remote tech/mm/camss git@github.com:qualcomm-linux/kernel-topics.git tech/mm/camss +Updating tech/mm/camss +Adding remote tech/mm/drm git@github.com:qualcomm-linux/kernel-topics.git tech/mm/drm +Updating tech/mm/drm +Adding remote tech/mm/fastrpc git@github.com:qualcomm-linux/kernel-topics.git tech/mm/fastrpc +Updating tech/mm/fastrpc +Adding remote tech/mm/phy git@github.com:qualcomm-linux/kernel-topics.git tech/mm/phy +Updating tech/mm/phy +Adding remote tech/mm/video git@github.com:qualcomm-linux/kernel-topics.git tech/mm/video +Updating tech/mm/video +Adding remote tech/mproc/rpmsg git@github.com:qualcomm-linux/kernel-topics.git tech/mproc/rpmsg +Updating tech/mproc/rpmsg +Adding remote tech/mproc/qmi git@github.com:qualcomm-linux/kernel-topics.git tech/mproc/qmi +Updating tech/mproc/qmi +Adding remote tech/net/ath git@github.com:qualcomm-linux/kernel-topics.git tech/net/ath +Updating tech/net/ath +Adding remote tech/net/eth git@github.com:qualcomm-linux/kernel-topics.git tech/net/eth +Updating tech/net/eth +Adding remote tech/net/rmnet git@github.com:qualcomm-linux/kernel-topics.git tech/net/rmnet +Updating tech/net/rmnet +Adding remote tech/net/qrtr git@github.com:qualcomm-linux/kernel-topics.git tech/net/qrtr +Updating tech/net/qrtr +Adding remote tech/net/phy git@github.com:qualcomm-linux/kernel-topics.git tech/net/phy +Updating tech/net/phy +Adding remote tech/net/bluetooth git@github.com:qualcomm-linux/kernel-topics.git tech/net/bluetooth +Updating tech/net/bluetooth +Adding remote tech/pm/opp git@github.com:qualcomm-linux/kernel-topics.git tech/pm/opp +Updating tech/pm/opp +Adding remote tech/pm/pmdomain git@github.com:qualcomm-linux/kernel-topics.git tech/pm/pmdomain +Updating tech/pm/pmdomain +Adding remote tech/pm/power git@github.com:qualcomm-linux/kernel-topics.git tech/pm/power +Updating tech/pm/power +Adding remote tech/pm/thermal git@github.com:qualcomm-linux/kernel-topics.git tech/pm/thermal +Updating tech/pm/thermal +Adding remote tech/security/crypto git@github.com:qualcomm-linux/kernel-topics.git tech/security/crypto +Updating tech/security/crypto +Adding remote tech/security/fscrypt git@github.com:qualcomm-linux/kernel-topics.git tech/security/fscrypt +Updating tech/security/fscrypt +Adding remote tech/security/ice git@github.com:qualcomm-linux/kernel-topics.git tech/security/ice +Updating tech/security/ice +Adding remote tech/storage/nvmem git@github.com:qualcomm-linux/kernel-topics.git tech/storage/nvmem +Updating tech/storage/nvmem +Adding remote tech/storage/phy git@github.com:qualcomm-linux/kernel-topics.git tech/storage/phy +Updating tech/storage/phy +Adding remote tech/storage/all git@github.com:qualcomm-linux/kernel-topics.git tech/storage/all +Updating tech/storage/all +Adding remote tech/virt/gunyah git@github.com:qualcomm-linux/kernel-topics.git tech/virt/gunyah +Updating tech/virt/gunyah +Adding remote tech/all/workaround git@github.com:qualcomm-linux/kernel-topics.git tech/all/workaround +Updating tech/all/workaround +Adding remote tech/all/dt/qcs6490 git@github.com:qualcomm-linux/kernel-topics.git tech/all/dt/qcs6490 +Updating tech/all/dt/qcs6490 +Adding remote tech/all/dt/qcs9100 git@github.com:qualcomm-linux/kernel-topics.git tech/all/dt/qcs9100 +Updating tech/all/dt/qcs9100 +Adding remote tech/all/dt/qcs8300 git@github.com:qualcomm-linux/kernel-topics.git tech/all/dt/qcs8300 +Updating tech/all/dt/qcs8300 +Adding remote tech/all/dt/qcs615 git@github.com:qualcomm-linux/kernel-topics.git tech/all/dt/qcs615 +Updating tech/all/dt/qcs615 +Adding remote tech/all/dt/hamoa git@github.com:qualcomm-linux/kernel-topics.git tech/all/dt/hamoa +Updating tech/all/dt/hamoa +Adding remote tech/all/config git@github.com:qualcomm-linux/kernel-topics.git tech/all/config +Updating tech/all/config +Adding remote tech/mm/gpu git@github.com:qualcomm-linux/kernel-topics.git tech/mm/gpu +Updating tech/mm/gpu +Done, added 61 new remote(s). +Updating the remotes ... +Updating tech/bsp/clk +tech/bsp/clk has changed. +Updating tech/bsp/interconnect +tech/bsp/interconnect has changed. +Updating tech/mem/secure-buffer +tech/mem/secure-buffer has changed. +Updating tech/security/firmware-smc +tech/security/firmware-smc has changed. +Updating tech/bsp/soc-infra +tech/bsp/soc-infra has changed. +Updating tech/debug/soc +tech/debug/soc has changed. +Updating tech/bsp/pinctrl +tech/bsp/pinctrl has changed. +Updating tech/bsp/remoteproc +tech/bsp/remoteproc has changed. +Updating tech/bus/peripherals +tech/bus/peripherals has changed. +Updating tech/bus/pci/all +tech/bus/pci/all has changed. +Updating tech/bus/pci/mhi +tech/bus/pci/mhi has changed. +Updating tech/bus/pci/phy +tech/bus/pci/phy has changed. +Updating tech/bus/pci/pwrctl +tech/bus/pci/pwrctl has changed. +Updating tech/bus/usb/dwc +tech/bus/usb/dwc has changed. +Updating tech/bus/usb/gadget +tech/bus/usb/gadget has changed. +Updating tech/bus/usb/phy +tech/bus/usb/phy has changed. +Updating tech/debug/eud +tech/debug/eud has changed. +Updating tech/debug/hwtracing +tech/debug/hwtracing has changed. +Updating tech/debug/rdbg +tech/debug/rdbg has changed. +Updating tech/pmic/backlight +tech/pmic/backlight has changed. +Updating tech/pmic/mfd +tech/pmic/mfd has changed. +Updating tech/pmic/misc +tech/pmic/misc has changed. +Updating tech/pmic/regulator +tech/pmic/regulator has changed. +Updating tech/pmic/supply +tech/pmic/supply has changed. +Updating tech/mem/dma-buf +tech/mem/dma-buf has changed. +Updating tech/mem/iommu +tech/mem/iommu has changed. +Updating tech/mm/audio/all +tech/mm/audio/all has changed. +Updating tech/mm/audio/soundwire +tech/mm/audio/soundwire has changed. +Updating tech/mm/camss +tech/mm/camss has changed. +Updating tech/mm/drm +tech/mm/drm has changed. +Updating tech/mm/fastrpc +tech/mm/fastrpc has changed. +Updating tech/mm/phy +tech/mm/phy has changed. +Updating tech/mm/video +tech/mm/video has changed. +Updating tech/mproc/rpmsg +tech/mproc/rpmsg has changed. +Updating tech/mproc/qmi +tech/mproc/qmi has changed. +Updating tech/net/ath +tech/net/ath has changed. +Updating tech/net/eth +tech/net/eth has changed. +Updating tech/net/rmnet +tech/net/rmnet has changed. +Updating tech/net/qrtr +tech/net/qrtr has changed. +Updating tech/net/phy +tech/net/phy has changed. +Updating tech/net/bluetooth +tech/net/bluetooth has changed. +Updating tech/pm/opp +tech/pm/opp has changed. +Updating tech/pm/pmdomain +tech/pm/pmdomain has changed. +Updating tech/pm/power +tech/pm/power has changed. +Updating tech/pm/thermal +tech/pm/thermal has changed. +Updating tech/security/crypto +tech/security/crypto has changed. +Updating tech/security/fscrypt +tech/security/fscrypt has changed. +Updating tech/security/ice +tech/security/ice has changed. +Updating tech/storage/nvmem +tech/storage/nvmem has changed. +Updating tech/storage/phy +tech/storage/phy has changed. +Updating tech/storage/all +tech/storage/all has changed. +Updating tech/virt/gunyah +tech/virt/gunyah has changed. +Updating tech/all/workaround +tech/all/workaround has changed. +Updating tech/all/dt/qcs6490 +tech/all/dt/qcs6490 has changed. +Updating tech/all/dt/qcs9100 +tech/all/dt/qcs9100 has changed. +Updating tech/all/dt/qcs8300 +tech/all/dt/qcs8300 has changed. +Updating tech/all/dt/qcs615 +tech/all/dt/qcs615 has changed. +Updating tech/all/dt/hamoa +tech/all/dt/hamoa has changed. +Updating tech/all/config +tech/all/config has changed. +Updating tech/mm/gpu +tech/mm/gpu has changed. +Done, updated 60 remote(s). +Updating baseline ... +Fetching baseline +X11 forwarding request failed on channel 0 +latest tag/id is a0731d77c2b4e56b1bdb1ae15a45cd356739d1f3 +Done, updated baseline. +Latest tag is a0731d77c2b4e56b1bdb1ae15a45cd356739d1f3 +Create a new integration branch based on a0731d77c2b4e56b1bdb1ae15a45cd356739d1f3 +Merging topic branches... +------------------------------------------ + ** Merging topic branch: tech/bsp/clk/tech/bsp/clk +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bsp/interconnect/tech/bsp/interconnect +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mem/secure-buffer/tech/mem/secure-buffer +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/security/firmware-smc/tech/security/firmware-smc +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bsp/soc-infra/tech/bsp/soc-infra +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/debug/soc/tech/debug/soc +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bsp/pinctrl/tech/bsp/pinctrl +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bsp/remoteproc/tech/bsp/remoteproc +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bus/peripherals/tech/bus/peripherals +Merge successful : tech/bus/peripherals : 6faf7f6b6c6f52f3ae190eaa47de58798c8644fc : 6 +------------------------------------------ + ** Merging topic branch: tech/bus/pci/all/tech/bus/pci/all +Merge successful : tech/bus/pci/all : 5159ecf66111209bb6561b6897edb53ada242ca1 : 8 +------------------------------------------ + ** Merging topic branch: tech/bus/pci/mhi/tech/bus/pci/mhi +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bus/pci/phy/tech/bus/pci/phy +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bus/pci/pwrctl/tech/bus/pci/pwrctl +Merge successful : tech/bus/pci/pwrctl : c387c06e97b117087e11f3ccc43ec75233a15e29 : 7 +------------------------------------------ + ** Merging topic branch: tech/bus/usb/dwc/tech/bus/usb/dwc +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bus/usb/gadget/tech/bus/usb/gadget +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bus/usb/phy/tech/bus/usb/phy +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/debug/eud/tech/debug/eud +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/debug/hwtracing/tech/debug/hwtracing +Merge successful : tech/debug/hwtracing : 4fea1a93f8a8c3d12b2ac693c445a1175b65a64a : 15 +------------------------------------------ + ** Merging topic branch: tech/debug/rdbg/tech/debug/rdbg +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/backlight/tech/pmic/backlight +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/mfd/tech/pmic/mfd +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/misc/tech/pmic/misc +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/regulator/tech/pmic/regulator +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/supply/tech/pmic/supply +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mem/dma-buf/tech/mem/dma-buf +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mem/iommu/tech/mem/iommu +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mm/audio/all/tech/mm/audio/all +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mm/audio/soundwire/tech/mm/audio/soundwire +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mm/camss/tech/mm/camss +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mm/drm/tech/mm/drm +Merge successful : tech/mm/drm : 7c42242f76761d3fd7ecbe99a1a8036908906093 : 1 +------------------------------------------ + ** Merging topic branch: tech/mm/fastrpc/tech/mm/fastrpc +Merge successful : tech/mm/fastrpc : 5a94c05e12cbc5cecb3a039d67c51bd8aff0ecec : 5 +------------------------------------------ + ** Merging topic branch: tech/mm/phy/tech/mm/phy +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mm/video/tech/mm/video +Merge successful : tech/mm/video : eb43f6ad1104f4714b1747d7f68708fae0eb05ce : 27 +------------------------------------------ + ** Merging topic branch: tech/mproc/rpmsg/tech/mproc/rpmsg +Merge successful : tech/mproc/rpmsg : adf3d0ae30d0e39e7db861824b705b7f7a3040bc : 1 +------------------------------------------ + ** Merging topic branch: tech/mproc/qmi/tech/mproc/qmi +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/ath/tech/net/ath +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/eth/tech/net/eth +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/rmnet/tech/net/rmnet +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/qrtr/tech/net/qrtr +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/phy/tech/net/phy +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/bluetooth/tech/net/bluetooth +Merge successful : tech/net/bluetooth : 27ab39b196ea0d814a0178be9070517f8252b956 : 3 +------------------------------------------ + ** Merging topic branch: tech/pm/opp/tech/pm/opp +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pm/pmdomain/tech/pm/pmdomain +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pm/power/tech/pm/power +Merge successful : tech/pm/power : 1eeed9b4e31525fcaa3b16365aa32c5d0ecb5010 : 1 +------------------------------------------ + ** Merging topic branch: tech/pm/thermal/tech/pm/thermal +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/security/crypto/tech/security/crypto +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/security/fscrypt/tech/security/fscrypt +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/security/ice/tech/security/ice +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/storage/nvmem/tech/storage/nvmem +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/storage/phy/tech/storage/phy +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/storage/all/tech/storage/all +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/virt/gunyah/tech/virt/gunyah +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/all/workaround/tech/all/workaround +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs6490/tech/all/dt/qcs6490 +Merge successful : tech/all/dt/qcs6490 : 304deb2772fe44d886968f85ef704ef230bfd1e5 : 12 +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs9100/tech/all/dt/qcs9100 +Merge successful : tech/all/dt/qcs9100 : 8c4261ae92a4082bff7599af0ab487be01dbf022 : 9 +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs8300/tech/all/dt/qcs8300 +Merge successful : tech/all/dt/qcs8300 : 6ebe22bd381a322f63b204cca5888f3838ee9690 : 2 +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs615/tech/all/dt/qcs615 +Merge successful : tech/all/dt/qcs615 : 0302dddc7f2aadd87f0477b00d1e31d8d75ee69c : 13 +------------------------------------------ + ** Merging topic branch: tech/all/dt/hamoa/tech/all/dt/hamoa +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/all/config/tech/all/config +Merge successful : tech/all/config : 6be6a1eb7a53d93b8d7d12a29ec6aca0f9bf6753 : 2 +------------------------------------------ + ** Merging topic branch: tech/mm/gpu/tech/mm/gpu +Nothing to merge: Already up to date. +Done, merged 15 topic(s). diff --git a/qcom-next/topic_SHA1 b/qcom-next/topic_SHA1 new file mode 100644 index 0000000000000..facaf4ea61fe8 --- /dev/null +++ b/qcom-next/topic_SHA1 @@ -0,0 +1,17 @@ +Name SHA Commits +------------------------------------------------------------------------------------ +tech/bus/peripherals 6faf7f6b6c6f52f3ae190eaa47de58798c8644fc 6 +tech/bus/pci/all 5159ecf66111209bb6561b6897edb53ada242ca1 8 +tech/bus/pci/pwrctl c387c06e97b117087e11f3ccc43ec75233a15e29 7 +tech/debug/hwtracing 4fea1a93f8a8c3d12b2ac693c445a1175b65a64a 15 +tech/mm/drm 7c42242f76761d3fd7ecbe99a1a8036908906093 1 +tech/mm/fastrpc 5a94c05e12cbc5cecb3a039d67c51bd8aff0ecec 5 +tech/mm/video eb43f6ad1104f4714b1747d7f68708fae0eb05ce 27 +tech/mproc/rpmsg adf3d0ae30d0e39e7db861824b705b7f7a3040bc 1 +tech/net/bluetooth 27ab39b196ea0d814a0178be9070517f8252b956 3 +tech/pm/power 1eeed9b4e31525fcaa3b16365aa32c5d0ecb5010 1 +tech/all/dt/qcs6490 304deb2772fe44d886968f85ef704ef230bfd1e5 12 +tech/all/dt/qcs9100 8c4261ae92a4082bff7599af0ab487be01dbf022 9 +tech/all/dt/qcs8300 6ebe22bd381a322f63b204cca5888f3838ee9690 2 +tech/all/dt/qcs615 0302dddc7f2aadd87f0477b00d1e31d8d75ee69c 13 +tech/all/config 6be6a1eb7a53d93b8d7d12a29ec6aca0f9bf6753 2